docs: redesign sidebar (#8408)
* initial changes * redesign the sidebar + nav drawer * changes to sidebar items * finish up sidebar redesign * support new sidebar in resources * general fixes * integrate in ui * support api reference * refactor * integrate in user guide * docs: fix build errors * fix user guide build * more refactoring * added banner * added bottom logo + icon * fix up sidebar * fix up paddings * fix shadow bottom * docs: add table of content (#8445) * add toc types * implement toc functionality * finished toc redesign * redesigned table of content * mobile fixes * truncate text in toc * mobile fixes * merge fixes * implement redesign * add hide sidebar * add menu action item * finish up hide sidebar design * implement redesign in resources * integrate in api reference * integrate changes in ui * fixes to api reference scrolling * fix build error * fix build errors * fixes * fixes to sidebar * general fixes * fix active category not closing * fix long titles
This commit is contained in:
@@ -15,7 +15,7 @@ const ReferencePage = async () => {
|
||||
</h1>
|
||||
<DividedLayout
|
||||
mainContent={
|
||||
<Section>
|
||||
<Section checkActiveOnScroll={true}>
|
||||
<h1 className="!text-h2 hidden lg:block">
|
||||
Medusa V2 Admin API Reference
|
||||
</h1>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import "./globals.css"
|
||||
import Navbar from "@/components/Navbar"
|
||||
import Providers from "../providers"
|
||||
import { WideLayout } from "docs-ui"
|
||||
import { Inter, Roboto_Mono } from "next/font/google"
|
||||
@@ -29,8 +28,12 @@ export default function RootLayout({
|
||||
return (
|
||||
<WideLayout
|
||||
ProvidersComponent={Providers}
|
||||
NavbarComponent={Navbar}
|
||||
sidebarProps={{
|
||||
expandItems: false,
|
||||
}}
|
||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||
showToc={false}
|
||||
showBanner={false}
|
||||
>
|
||||
{children}
|
||||
</WideLayout>
|
||||
|
||||
@@ -15,7 +15,7 @@ const ReferencePage = async () => {
|
||||
</h1>
|
||||
<DividedLayout
|
||||
mainContent={
|
||||
<Section>
|
||||
<Section checkActiveOnScroll={true}>
|
||||
<h1 className="!text-h2 hidden lg:block">
|
||||
Medusa V2 Store API Reference
|
||||
</h1>
|
||||
|
||||
@@ -1,73 +1,47 @@
|
||||
"use client"
|
||||
|
||||
import { InView } from "react-intersection-observer"
|
||||
import { isElmWindow, useScrollController, useSidebar } from "docs-ui"
|
||||
import checkElementInViewport from "../../../utils/check-element-in-viewport"
|
||||
import { useEffect, useMemo } from "react"
|
||||
import { useScrollController, useSidebar } from "docs-ui"
|
||||
import { useEffect, useMemo, useRef, useState } from "react"
|
||||
import getSectionId from "../../../utils/get-section-id"
|
||||
|
||||
type H2Props = {
|
||||
addToSidebar?: boolean
|
||||
} & React.HTMLAttributes<HTMLHeadingElement>
|
||||
type H2Props = React.HTMLAttributes<HTMLHeadingElement>
|
||||
|
||||
const H2 = ({ addToSidebar = true, children, ...props }: H2Props) => {
|
||||
const { activePath, setActivePath, addItems } = useSidebar()
|
||||
const { getScrolledTop, scrollableElement } = useScrollController()
|
||||
const H2 = ({ children, ...props }: H2Props) => {
|
||||
const headingRef = useRef<HTMLHeadingElement>(null)
|
||||
const { activePath, addItems } = useSidebar()
|
||||
const { scrollableElement, scrollToElement } = useScrollController()
|
||||
const [scrolledFirstTime, setScrolledFirstTime] = useState(false)
|
||||
|
||||
const handleViewChange = (
|
||||
inView: boolean,
|
||||
entry: IntersectionObserverEntry
|
||||
) => {
|
||||
if (!addToSidebar) {
|
||||
return
|
||||
}
|
||||
const heading = entry.target
|
||||
if (
|
||||
(inView ||
|
||||
checkElementInViewport(heading.parentElement || heading, 40)) &&
|
||||
getScrolledTop() !== 0 &&
|
||||
activePath !== heading.id
|
||||
) {
|
||||
// can't use next router as it doesn't support
|
||||
// changing url without scrolling
|
||||
history.pushState({}, "", `#${heading.id}`)
|
||||
setActivePath(heading.id)
|
||||
}
|
||||
}
|
||||
const id = getSectionId([children as string])
|
||||
const id = useMemo(() => getSectionId([children as string]), [children])
|
||||
|
||||
useEffect(() => {
|
||||
if (id === (activePath || location.hash.replace("#", ""))) {
|
||||
const elm = document.getElementById(id)
|
||||
elm?.scrollIntoView()
|
||||
if (!scrollableElement || !headingRef.current || scrolledFirstTime) {
|
||||
return
|
||||
}
|
||||
|
||||
if (id === (activePath || location.hash.replace("#", ""))) {
|
||||
scrollToElement(
|
||||
(headingRef.current.offsetParent as HTMLElement) || headingRef.current
|
||||
)
|
||||
}
|
||||
setScrolledFirstTime(scrolledFirstTime)
|
||||
}, [scrollableElement, headingRef, id])
|
||||
|
||||
useEffect(() => {
|
||||
addItems([
|
||||
{
|
||||
type: "link",
|
||||
path: `${id}`,
|
||||
title: children as string,
|
||||
loaded: true,
|
||||
},
|
||||
])
|
||||
}, [])
|
||||
|
||||
const root = useMemo(() => {
|
||||
return isElmWindow(scrollableElement) ? document.body : scrollableElement
|
||||
}, [scrollableElement])
|
||||
}, [id])
|
||||
|
||||
return (
|
||||
<InView
|
||||
as="h2"
|
||||
threshold={0.4}
|
||||
skip={!addToSidebar}
|
||||
initialInView={false}
|
||||
{...props}
|
||||
onChange={handleViewChange}
|
||||
id={id}
|
||||
root={root}
|
||||
>
|
||||
<h2 {...props} id={id} ref={headingRef}>
|
||||
{children}
|
||||
</InView>
|
||||
</h2>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,7 @@ const getCustomComponents = (scope?: ScopeType): MDXComponents => {
|
||||
...UiMDXComponents,
|
||||
Security: () => <Security specs={scope?.specs} />,
|
||||
a: Link,
|
||||
h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => (
|
||||
<H2 addToSidebar={scope?.addToSidebar} {...props} />
|
||||
),
|
||||
h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => <H2 {...props} />,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Button, useModal, usePageLoading } from "docs-ui"
|
||||
import DetailedFeedback from "../../DetailedFeedback"
|
||||
|
||||
const FeedbackModal = () => {
|
||||
const { setModalProps } = useModal()
|
||||
const { isLoading } = usePageLoading()
|
||||
|
||||
const openModal = () => {
|
||||
if (isLoading) {
|
||||
return
|
||||
}
|
||||
setModalProps({
|
||||
title: "Send your Feedback",
|
||||
children: <DetailedFeedback />,
|
||||
contentClassName: "lg:!min-h-auto !p-0",
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Button onClick={openModal} variant="secondary">
|
||||
Feedback
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export default FeedbackModal
|
||||
@@ -1,50 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
Navbar as UiNavbar,
|
||||
getNavbarItems,
|
||||
usePageLoading,
|
||||
useSidebar,
|
||||
} from "docs-ui"
|
||||
import FeedbackModal from "./FeedbackModal"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../../config"
|
||||
import { usePathname } from "next/navigation"
|
||||
import VersionSwitcher from "../VersionSwitcher"
|
||||
import basePathUrl from "../../utils/base-path-url"
|
||||
|
||||
const Navbar = () => {
|
||||
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
||||
const pathname = usePathname()
|
||||
const { isLoading } = usePageLoading()
|
||||
|
||||
const navbarItems = useMemo(
|
||||
() =>
|
||||
getNavbarItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(pathname),
|
||||
version: "v2",
|
||||
}),
|
||||
[pathname]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiNavbar
|
||||
logo={{
|
||||
light: basePathUrl("/images/logo-icon.png"),
|
||||
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||
}}
|
||||
items={navbarItems}
|
||||
mobileMenuButton={{
|
||||
setMobileSidebarOpen,
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
additionalActionsBefore={<VersionSwitcher />}
|
||||
additionalActionsAfter={<FeedbackModal />}
|
||||
showSearchOpener
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Navbar
|
||||
@@ -1,14 +1,25 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import { useActiveOnScroll, useSidebar } from "docs-ui"
|
||||
import { useEffect, useRef } from "react"
|
||||
|
||||
export type SectionProps = {
|
||||
addToSidebar?: boolean
|
||||
checkActiveOnScroll?: boolean
|
||||
} & React.AllHTMLAttributes<HTMLDivElement>
|
||||
|
||||
const Section = ({ children, className }: SectionProps) => {
|
||||
const Section = ({
|
||||
children,
|
||||
className,
|
||||
checkActiveOnScroll = false,
|
||||
}: SectionProps) => {
|
||||
const sectionRef = useRef<HTMLDivElement>(null)
|
||||
const { activeItemId } = useActiveOnScroll({
|
||||
rootElm: sectionRef.current || undefined,
|
||||
enable: checkActiveOnScroll,
|
||||
useDefaultIfNoActive: false,
|
||||
})
|
||||
const { setActivePath } = useSidebar()
|
||||
|
||||
useEffect(() => {
|
||||
if ("scrollRestoration" in history) {
|
||||
@@ -17,6 +28,13 @@ const Section = ({ children, className }: SectionProps) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (activeItemId.length) {
|
||||
history.pushState({}, "", `#${activeItemId}`)
|
||||
setActivePath(activeItemId)
|
||||
}
|
||||
}, [activeItemId])
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={sectionRef}
|
||||
|
||||
@@ -13,6 +13,7 @@ import TagsOperationDescriptionSection from "./DescriptionSection"
|
||||
import DividedLayout from "@/layouts/Divided"
|
||||
import { useLoading } from "@/providers/loading"
|
||||
import SectionDivider from "../../Section/Divider"
|
||||
import checkElementInViewport from "../../../utils/check-element-in-viewport"
|
||||
|
||||
const TagOperationCodeSection = dynamic<TagOperationCodeSectionProps>(
|
||||
async () => import("./CodeSection")
|
||||
@@ -40,7 +41,7 @@ const TagOperation = ({
|
||||
)
|
||||
const nodeRef = useRef<Element | null>(null)
|
||||
const { loading, removeLoading } = useLoading()
|
||||
const { scrollableElement } = useScrollController()
|
||||
const { scrollableElement, scrollToTop } = useScrollController()
|
||||
const root = useMemo(() => {
|
||||
return isElmWindow(scrollableElement) ? document.body : scrollableElement
|
||||
}, [scrollableElement])
|
||||
@@ -75,24 +76,28 @@ const TagOperation = ({
|
||||
[ref]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const enableShow = () => {
|
||||
setShow(true)
|
||||
const scrollIntoView = useCallback(() => {
|
||||
if (nodeRef.current && !checkElementInViewport(nodeRef.current, 10)) {
|
||||
const elm = nodeRef.current as HTMLElement
|
||||
scrollToTop(
|
||||
elm.offsetTop + (elm.offsetParent as HTMLElement)?.offsetTop,
|
||||
0
|
||||
)
|
||||
}
|
||||
setShow(true)
|
||||
}, [scrollToTop, nodeRef])
|
||||
|
||||
useEffect(() => {
|
||||
if (nodeRef && nodeRef.current) {
|
||||
removeLoading()
|
||||
const currentHash = location.hash.replace("#", "")
|
||||
if (currentHash === path) {
|
||||
setTimeout(() => {
|
||||
nodeRef.current?.scrollIntoView()
|
||||
enableShow()
|
||||
}, 100)
|
||||
setTimeout(scrollIntoView, 100)
|
||||
} else if (currentHash.split("_")[0] === path.split("_")[0]) {
|
||||
enableShow()
|
||||
setShow(true)
|
||||
}
|
||||
}
|
||||
}, [nodeRef, path])
|
||||
}, [nodeRef, path, scrollIntoView])
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -14,7 +14,7 @@ import { useBaseSpecs } from "@/providers/base-specs"
|
||||
import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items"
|
||||
import { useLoading } from "@/providers/loading"
|
||||
import DividedLoading from "@/components/DividedLoading"
|
||||
import { SidebarItemSections, SidebarItemType } from "types"
|
||||
import { SidebarItemSections, SidebarItem, SidebarItemCategory } from "types"
|
||||
import basePathUrl from "../../../utils/base-path-url"
|
||||
|
||||
const TagOperation = dynamic<TagOperationProps>(
|
||||
@@ -56,16 +56,17 @@ const TagPaths = ({ tag, className }: TagPathsProps) => {
|
||||
useEffect(() => {
|
||||
if (paths) {
|
||||
const parentItem = findItemInSection(
|
||||
items[SidebarItemSections.BOTTOM],
|
||||
{ path: tagSlugName },
|
||||
items[SidebarItemSections.DEFAULT],
|
||||
{ title: tag.name },
|
||||
false
|
||||
)
|
||||
const pathItems: SidebarItemType[] = getTagChildSidebarItems(paths)
|
||||
) as SidebarItemCategory
|
||||
const pathItems: SidebarItem[] = getTagChildSidebarItems(paths)
|
||||
if ((parentItem?.children?.length || 0) < pathItems.length) {
|
||||
addItems(pathItems, {
|
||||
section: SidebarItemSections.BOTTOM,
|
||||
section: SidebarItemSections.DEFAULT,
|
||||
parent: {
|
||||
path: tagSlugName,
|
||||
title: tag.name,
|
||||
path: "",
|
||||
changeLoaded: true,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -40,7 +40,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
|
||||
},
|
||||
})
|
||||
|
||||
const { scrollableElement } = useScrollController()
|
||||
const { scrollableElement, scrollToElement } = useScrollController()
|
||||
const root = useMemo(() => {
|
||||
return isElmWindow(scrollableElement) ? document.body : scrollableElement
|
||||
}, [scrollableElement])
|
||||
@@ -49,6 +49,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
|
||||
addItems(
|
||||
[
|
||||
{
|
||||
type: "link",
|
||||
path: schemaSlug,
|
||||
title: `${formattedName} Object`,
|
||||
additionalElms: <Badge variant="neutral">Schema</Badge>,
|
||||
@@ -56,8 +57,9 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
|
||||
},
|
||||
],
|
||||
{
|
||||
section: SidebarItemSections.BOTTOM,
|
||||
section: SidebarItemSections.DEFAULT,
|
||||
parent: {
|
||||
title: tagName,
|
||||
path: tagSlugName,
|
||||
changeLoaded: true,
|
||||
},
|
||||
@@ -69,12 +71,12 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
if (schemaSlug === (activePath || location.hash.replace("#", ""))) {
|
||||
const elm = document.getElementById(schemaSlug)
|
||||
elm?.scrollIntoView({
|
||||
block: "center",
|
||||
})
|
||||
const elm = document.getElementById(schemaSlug) as HTMLElement
|
||||
if (!checkElementInViewport(elm, 40)) {
|
||||
scrollToElement(elm)
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
}, [activePath, schemaSlug])
|
||||
|
||||
const handleViewChange = (
|
||||
inView: boolean,
|
||||
|
||||
@@ -26,6 +26,7 @@ import { SchemaObject, TagObject } from "@/types/openapi"
|
||||
import useSWR from "swr"
|
||||
import { TagSectionSchemaProps } from "./Schema"
|
||||
import basePathUrl from "../../../utils/base-path-url"
|
||||
import checkElementInViewport from "../../../utils/check-element-in-viewport"
|
||||
|
||||
export type TagSectionProps = {
|
||||
tag: TagObject
|
||||
@@ -52,7 +53,7 @@ const TagSection = ({ tag }: TagSectionProps) => {
|
||||
const slugTagName = useMemo(() => getSectionId([tag.name]), [tag])
|
||||
const { area } = useArea()
|
||||
const pathname = usePathname()
|
||||
const { scrollableElement } = useScrollController()
|
||||
const { scrollableElement, scrollToElement } = useScrollController()
|
||||
const { data } = useSWR<{
|
||||
schema: SchemaObject
|
||||
}>(
|
||||
@@ -96,8 +97,10 @@ const TagSection = ({ tag }: TagSectionProps) => {
|
||||
if (activePath && activePath.includes(slugTagName)) {
|
||||
const tagName = activePath.split("_")
|
||||
if (tagName.length === 1 && tagName[0] === slugTagName) {
|
||||
const elm = document.getElementById(tagName[0]) as Element
|
||||
elm?.scrollIntoView()
|
||||
const elm = document.getElementById(tagName[0])
|
||||
if (elm && !checkElementInViewport(elm, 10)) {
|
||||
scrollToElement(elm)
|
||||
}
|
||||
} else if (tagName.length > 1 && tagName[0] === slugTagName) {
|
||||
setLoadPaths(true)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ import { swrFetcher, useSidebar } from "docs-ui"
|
||||
import getSectionId from "@/utils/get-section-id"
|
||||
import { ExpandedDocument } from "@/types/openapi"
|
||||
import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items"
|
||||
import { SidebarItemSections } from "types"
|
||||
import { SidebarItem, SidebarItemSections } from "types"
|
||||
import basePathUrl from "../../utils/base-path-url"
|
||||
|
||||
const TagSection = dynamic<TagSectionProps>(
|
||||
@@ -31,7 +31,7 @@ const Tags = () => {
|
||||
const [loadData, setLoadData] = useState<boolean>(false)
|
||||
const [expand, setExpand] = useState<string>("")
|
||||
const { baseSpecs, setBaseSpecs } = useBaseSpecs()
|
||||
const { addItems } = useSidebar()
|
||||
const { addItems, setActivePath } = useSidebar()
|
||||
const { area, prevArea } = useArea()
|
||||
|
||||
const { data } = useSWR<ExpandedDocument>(
|
||||
@@ -65,30 +65,42 @@ const Tags = () => {
|
||||
if (baseSpecs) {
|
||||
if (prevArea !== area) {
|
||||
setBaseSpecs(null)
|
||||
setLoadData(true)
|
||||
return
|
||||
}
|
||||
|
||||
addItems(
|
||||
baseSpecs.tags?.map((tag) => {
|
||||
const itemsToAdd: SidebarItem[] = [
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
]
|
||||
|
||||
if (baseSpecs.tags) {
|
||||
baseSpecs.tags.forEach((tag) => {
|
||||
const tagPathName = getSectionId([tag.name.toLowerCase()])
|
||||
const childItems =
|
||||
baseSpecs.expandedTags &&
|
||||
Object.hasOwn(baseSpecs.expandedTags, tagPathName)
|
||||
? getTagChildSidebarItems(baseSpecs.expandedTags[tagPathName])
|
||||
: []
|
||||
return {
|
||||
path: tagPathName,
|
||||
itemsToAdd.push({
|
||||
type: "category",
|
||||
title: tag.name,
|
||||
children: childItems,
|
||||
loaded: childItems.length > 0,
|
||||
}
|
||||
}) || [],
|
||||
{
|
||||
section: SidebarItemSections.BOTTOM,
|
||||
}
|
||||
)
|
||||
onOpen: () => {
|
||||
history.pushState({}, "", `#${tagPathName}`)
|
||||
setActivePath(tagPathName)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
addItems(itemsToAdd, {
|
||||
section: SidebarItemSections.DEFAULT,
|
||||
})
|
||||
}
|
||||
}, [baseSpecs, addItems])
|
||||
}, [baseSpecs, prevArea, area])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -8,14 +8,14 @@ export const config: DocsConfig = {
|
||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||
// sidebar is auto generated
|
||||
sidebar: {
|
||||
top: [
|
||||
default: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Introduction",
|
||||
path: "",
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
bottom: [],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
|
||||
@@ -13,6 +13,7 @@ import BaseSpecsProvider from "./base-specs"
|
||||
import SidebarProvider from "./sidebar"
|
||||
import SearchProvider from "./search"
|
||||
import { config } from "../config"
|
||||
import { MainNavProvider } from "./main-nav"
|
||||
|
||||
type ProvidersProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -28,9 +29,11 @@ const Providers = ({ children }: ProvidersProps) => {
|
||||
<BaseSpecsProvider>
|
||||
<ScrollControllerProvider scrollableSelector="#main">
|
||||
<SidebarProvider>
|
||||
<SearchProvider>
|
||||
<MobileProvider>{children}</MobileProvider>
|
||||
</SearchProvider>
|
||||
<MainNavProvider>
|
||||
<SearchProvider>
|
||||
<MobileProvider>{children}</MobileProvider>
|
||||
</SearchProvider>
|
||||
</MainNavProvider>
|
||||
</SidebarProvider>
|
||||
</ScrollControllerProvider>
|
||||
</BaseSpecsProvider>
|
||||
|
||||
48
www/apps/api-reference/providers/main-nav.tsx
Normal file
48
www/apps/api-reference/providers/main-nav.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
formatReportLink,
|
||||
getNavDropdownItems,
|
||||
MainNavProvider as UiMainNavProvider,
|
||||
useIsBrowser,
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { usePathname } from "next/navigation"
|
||||
import basePathUrl from "../utils/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
const isBrowser = useIsBrowser()
|
||||
const pathname = usePathname()
|
||||
const navigationDropdownItems = useMemo(
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(pathname),
|
||||
version: "v2",
|
||||
}),
|
||||
[pathname]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
() =>
|
||||
formatReportLink(
|
||||
config.titleSuffix || "",
|
||||
isBrowser ? document.title : ""
|
||||
),
|
||||
[isBrowser]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiMainNavProvider
|
||||
navItems={navigationDropdownItems}
|
||||
reportIssueLink={reportLink}
|
||||
>
|
||||
{children}
|
||||
</UiMainNavProvider>
|
||||
)
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
import { createContext, useEffect } from "react"
|
||||
import { capitalize, useSidebar } from "docs-ui"
|
||||
import { useArea } from "./area"
|
||||
import { SidebarItemLink } from "types"
|
||||
|
||||
const PageTitleContext = createContext(null)
|
||||
|
||||
@@ -25,7 +26,9 @@ const PageTitleProvider = ({ children }: PageTitleProviderProps) => {
|
||||
document.title = `${activeItem?.title} - ${titleSuffix}`
|
||||
} else {
|
||||
// find the child that matches the active path
|
||||
const item = activeItem?.children?.find((i) => i.path === activePath)
|
||||
const item = activeItem?.children?.find(
|
||||
(i) => i.type === "link" && i.path === activePath
|
||||
) as SidebarItemLink
|
||||
if (item) {
|
||||
document.title = `${item.title} - ${titleSuffix}`
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
SidebarProvider as UiSidebarProvider,
|
||||
usePageLoading,
|
||||
@@ -6,8 +7,8 @@ import {
|
||||
useScrollController,
|
||||
} from "docs-ui"
|
||||
import { config } from "../config"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { useCallback } from "react"
|
||||
import { usePathname } from "next/navigation"
|
||||
|
||||
type SidebarProviderProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -17,11 +18,11 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
|
||||
const { isLoading, setIsLoading } = usePageLoading()
|
||||
const { scrollableElement } = useScrollController()
|
||||
const pathname = usePathname()
|
||||
const prevPathname = usePrevious(pathname)
|
||||
const prevPathName = usePrevious(pathname)
|
||||
|
||||
const resetOnCondition = useCallback(
|
||||
() => prevPathname !== undefined && prevPathname !== pathname,
|
||||
[pathname, prevPathname]
|
||||
() => prevPathName !== undefined && pathname !== prevPathName,
|
||||
[pathname, prevPathName]
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getLinkWithBasePath } from "docs-ui"
|
||||
|
||||
export default function basePathUrl(path: string) {
|
||||
export default function basePathUrl(path = "") {
|
||||
return getLinkWithBasePath(path, process.env.NEXT_PUBLIC_BASE_PATH)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ export default function checkElementInViewport(
|
||||
height?: number
|
||||
) {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const windowHeight =
|
||||
const windowHeight: number | undefined =
|
||||
height || window.innerHeight || document.documentElement.clientHeight
|
||||
|
||||
return !(
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { SidebarItemType } from "types"
|
||||
import type { SidebarItem } from "types"
|
||||
import type { Operation, PathsObject } from "@/types/openapi"
|
||||
import type { OpenAPIV3 } from "openapi-types"
|
||||
import dynamic from "next/dynamic"
|
||||
@@ -11,13 +11,14 @@ const MethodLabel = dynamic<MethodLabelProps>(
|
||||
|
||||
export default function getTagChildSidebarItems(
|
||||
paths: PathsObject
|
||||
): SidebarItemType[] {
|
||||
const items: SidebarItemType[] = []
|
||||
): SidebarItem[] {
|
||||
const items: SidebarItem[] = []
|
||||
Object.entries(paths).forEach(([, operations]) => {
|
||||
Object.entries(operations).map(([method, operation]) => {
|
||||
const definedOperation = operation as Operation
|
||||
const definedMethod = method as OpenAPIV3.HttpMethods
|
||||
items.push({
|
||||
type: "link",
|
||||
path: getSectionId([
|
||||
...(definedOperation.tags || []),
|
||||
definedOperation.operationId,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Metadata } from "next"
|
||||
import { Inter, Roboto_Mono } from "next/font/google"
|
||||
|
||||
import Navbar from "@/components/Navbar"
|
||||
import Providers from "@/providers"
|
||||
import "./globals.css"
|
||||
import { Bannerv2, TightLayout } from "docs-ui"
|
||||
import { TightLayout } from "docs-ui"
|
||||
import { config } from "@/config"
|
||||
import clsx from "clsx"
|
||||
import Feedback from "@/components/Feedback"
|
||||
@@ -40,10 +38,8 @@ export default function RootLayout({
|
||||
return (
|
||||
<TightLayout
|
||||
ProvidersComponent={Providers}
|
||||
NavbarComponent={Navbar}
|
||||
sidebarProps={{
|
||||
expandItems: true,
|
||||
banner: <Bannerv2 />,
|
||||
}}
|
||||
showPagination={true}
|
||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Navbar as UiNavbar, getNavbarItems } from "docs-ui"
|
||||
import { useSidebar } from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../../config"
|
||||
import { basePathUrl } from "../../utils/base-path-url"
|
||||
|
||||
const Navbar = () => {
|
||||
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
||||
|
||||
const navbarItems = useMemo(
|
||||
() =>
|
||||
getNavbarItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiNavbar
|
||||
logo={{
|
||||
light: basePathUrl("/images/logo-icon.png"),
|
||||
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||
}}
|
||||
items={navbarItems}
|
||||
mobileMenuButton={{
|
||||
setMobileSidebarOpen,
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
isLoading={false}
|
||||
showSearchOpener
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Navbar
|
||||
@@ -1,17 +1,20 @@
|
||||
import { Badge, getMobileSidebarItems } from "docs-ui"
|
||||
import type { SidebarConfig, SidebarItemType } from "@/types"
|
||||
import type { SidebarConfig, SidebarItem } from "@/types"
|
||||
import { sidebar } from "../sidebar.mjs"
|
||||
|
||||
const soonBadge = <Badge variant="blue">Soon</Badge>
|
||||
|
||||
const normalizeSidebarItems = (items: SidebarItemType[]) =>
|
||||
const normalizeSidebarItems = (items: SidebarItem[]) =>
|
||||
items.map((item) => {
|
||||
if (item.type === "separator") {
|
||||
return item
|
||||
}
|
||||
if (item.isSoon) {
|
||||
item.additionalElms = soonBadge
|
||||
}
|
||||
|
||||
if (item.children) {
|
||||
item.children = normalizeSidebarItems(item.children as SidebarItemType[])
|
||||
item.children = normalizeSidebarItems(item.children as SidebarItem[])
|
||||
}
|
||||
|
||||
return item
|
||||
@@ -19,8 +22,7 @@ const normalizeSidebarItems = (items: SidebarItemType[]) =>
|
||||
|
||||
export const sidebarConfig = (baseUrl: string): SidebarConfig => {
|
||||
return {
|
||||
top: normalizeSidebarItems(sidebar),
|
||||
bottom: [],
|
||||
default: normalizeSidebarItems(sidebar),
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import SidebarProvider from "./sidebar"
|
||||
import SearchProvider from "./search"
|
||||
import { config } from "../config"
|
||||
import { MainNavProvider } from "./main-nav"
|
||||
|
||||
type ProvidersProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -33,16 +34,18 @@ const Providers = ({ children }: ProvidersProps) => {
|
||||
<ScrollControllerProvider scrollableSelector="#main">
|
||||
<SidebarProvider>
|
||||
<PaginationProvider>
|
||||
<SearchProvider>
|
||||
<HooksLoader
|
||||
options={{
|
||||
pageScrollManager: true,
|
||||
currentLearningPath: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</HooksLoader>
|
||||
</SearchProvider>
|
||||
<MainNavProvider>
|
||||
<SearchProvider>
|
||||
<HooksLoader
|
||||
options={{
|
||||
pageScrollManager: true,
|
||||
currentLearningPath: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</HooksLoader>
|
||||
</SearchProvider>
|
||||
</MainNavProvider>
|
||||
</PaginationProvider>
|
||||
</SidebarProvider>
|
||||
</ScrollControllerProvider>
|
||||
|
||||
46
www/apps/book/providers/main-nav.tsx
Normal file
46
www/apps/book/providers/main-nav.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
formatReportLink,
|
||||
getNavDropdownItems,
|
||||
MainNavProvider as UiMainNavProvider,
|
||||
useIsBrowser,
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { basePathUrl } from "../utils/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
const isBrowser = useIsBrowser()
|
||||
const navigationDropdownItems = useMemo(
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
() =>
|
||||
formatReportLink(
|
||||
config.titleSuffix || "",
|
||||
isBrowser ? document.title : ""
|
||||
),
|
||||
[isBrowser]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiMainNavProvider
|
||||
navItems={navigationDropdownItems}
|
||||
reportIssueLink={reportLink}
|
||||
>
|
||||
{children}
|
||||
</UiMainNavProvider>
|
||||
)
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
SidebarProvider as UiSidebarProvider,
|
||||
useScrollController,
|
||||
@@ -20,7 +21,6 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
|
||||
initialItems={config.sidebar}
|
||||
staticSidebarItems={true}
|
||||
disableActiveTransition={true}
|
||||
noTitleStyling={true}
|
||||
>
|
||||
{children}
|
||||
</UiSidebarProvider>
|
||||
|
||||
@@ -1,183 +1,226 @@
|
||||
import numberSidebarItems from "./utils/number-sidebar-items.mjs"
|
||||
import { sidebarAttachHrefCommonOptions } from "./utils/sidebar-attach-common-options.mjs"
|
||||
|
||||
/** @type {import('@/types').SidebarItemType[]} */
|
||||
export const sidebar = sidebarAttachHrefCommonOptions(
|
||||
numberSidebarItems([
|
||||
/** @type {import('@/types').SidebarItem[]} */
|
||||
export const sidebar = numberSidebarItems(
|
||||
sidebarAttachHrefCommonOptions([
|
||||
{
|
||||
type: "link",
|
||||
path: "/",
|
||||
title: "Introduction",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/first-customizations",
|
||||
title: "Your First Customizations",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics",
|
||||
title: "The Basics",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/project-directories-files",
|
||||
title: "Project Directories and Files",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/medusa-container",
|
||||
title: "Medusa Container",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/api-routes",
|
||||
title: "API Routes",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/modules-and-services",
|
||||
title: "Modules and Services",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/commerce-modules",
|
||||
title: "Commerce Modules",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/modules-directory-structure",
|
||||
title: "Modules Directory Structure",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/data-models",
|
||||
title: "Data Models",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/loaders",
|
||||
title: "Loaders",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/events-and-subscribers",
|
||||
title: "Events and Subscribers",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/scheduled-jobs",
|
||||
title: "Scheduled Jobs",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/workflows",
|
||||
title: "Workflows",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/basics/admin-customizations",
|
||||
title: "Admin Customizations",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development",
|
||||
title: "Advanced Development",
|
||||
children: [
|
||||
{
|
||||
type: "sub-category",
|
||||
title: "API Routes",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/api-routes/http-methods",
|
||||
title: "HTTP Methods",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/api-routes/parameters",
|
||||
title: "Parameters",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/api-routes/middlewares",
|
||||
title: "Middlewares",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/api-routes/protected-routes",
|
||||
title: "Protected Routes",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/api-routes/cors",
|
||||
title: "Handling CORS",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "sub-category",
|
||||
title: "Modules",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/container",
|
||||
title: "Module's Container",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/service-factory",
|
||||
title: "Service Factory",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/isolation",
|
||||
title: "Module Isolation",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/module-links",
|
||||
title: "Module Links",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/module-link-directions",
|
||||
title: "Module Link Direction",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/remote-link",
|
||||
title: "Remote Link",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/remote-query",
|
||||
title: "Remote Query",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/modules/options",
|
||||
title: "Module Options",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models",
|
||||
title: "Data Models",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/property-types",
|
||||
title: "Property Types",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/primary-key",
|
||||
title: "Primary Key",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/default-properties",
|
||||
title: "Default Properties",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/configure-properties",
|
||||
title: "Configure Properties",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/relationships",
|
||||
title: "Relationships",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/manage-relationships",
|
||||
title: "Manage Relationships",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/index",
|
||||
title: "Index",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/searchable-property",
|
||||
title: "Searchable Property",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/data-models/write-migration",
|
||||
title: "Write Migration",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "sub-category",
|
||||
title: "Events and Subscribers",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/events-and-subscribers/data-payload",
|
||||
title: "Events Data Payload",
|
||||
},
|
||||
@@ -188,84 +231,104 @@ export const sidebar = sidebarAttachHrefCommonOptions(
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "sub-category",
|
||||
title: "Scheduled Jobs",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/scheduled-jobs/execution-number",
|
||||
title: "Execution Number",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "sub-category",
|
||||
title: "Workflows",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/constructor-constraints",
|
||||
title: "Workflow Constraints",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/conditions",
|
||||
title: "Conditions in Workflows",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/compensation-function",
|
||||
title: "Compensation Function",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/workflow-hooks",
|
||||
title: "Workflow Hooks",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/add-workflow-hook",
|
||||
title: "Expose a Hook",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/access-workflow-errors",
|
||||
title: "Access Workflow Errors",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/retry-failed-steps",
|
||||
title: "Retry Failed Steps",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/parallel-steps",
|
||||
title: "Run Steps in Parallel",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/workflow-timeout",
|
||||
title: "Workflow Timeout",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/long-running-workflow",
|
||||
title: "Long-Running Workflow",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/execute-another-workflow",
|
||||
title: "Execute Another Workflow",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/workflows/advanced-example",
|
||||
title: "Example: Advanced Workflow",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/custom-cli-scripts",
|
||||
title: "Custom CLI Scripts",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/admin",
|
||||
title: "Admin Development",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/admin/widgets",
|
||||
title: "Admin Widgets",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/admin/ui-routes",
|
||||
title: "Admin UI Routes",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/advanced-development/admin/tips",
|
||||
title: "Tips",
|
||||
},
|
||||
@@ -274,42 +337,51 @@ export const sidebar = sidebarAttachHrefCommonOptions(
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/storefront-development",
|
||||
title: "Storefront Development",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/storefront-development/nextjs-starter",
|
||||
title: "Next.js Starter",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/architectural-modules",
|
||||
title: "Architectural Modules",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/debugging-and-testing",
|
||||
title: "Debugging and Testing",
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
path: "/debugging-and-testing/logging",
|
||||
title: "Logging",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/debugging-and-testing/tools",
|
||||
title: "Tools",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/deployment",
|
||||
title: "Deployment",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/more-resources",
|
||||
title: "More Resources",
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
path: "/cheatsheet",
|
||||
title: "Cheat Sheet",
|
||||
},
|
||||
|
||||
9
www/apps/book/types/index.d.ts
vendored
9
www/apps/book/types/index.d.ts
vendored
@@ -1,11 +1,8 @@
|
||||
import {
|
||||
SidebarSectionItemsType,
|
||||
SidebarItemType as UiSidebarItemType,
|
||||
} from "docs-ui"
|
||||
import { SidebarSectionItems, SidebarItem as SidebarItemType } from "types"
|
||||
|
||||
export declare type SidebarItemType = UiSidebarItemType & {
|
||||
export declare type SidebarItem = SidebarItemType & {
|
||||
isSoon: boolean
|
||||
number?: string
|
||||
}
|
||||
|
||||
export declare type SidebarConfig = SidebarSectionItemsType
|
||||
export declare type SidebarConfig = SidebarSectionItems
|
||||
|
||||
@@ -1,14 +1,34 @@
|
||||
/**
|
||||
*
|
||||
* @param {import("@/types").SidebarItemType[]} sidebarItems - The items to add numbers to their titles
|
||||
* @param {import("@/types").SidebarItem[]} sidebarItems - The items to add numbers to their titles
|
||||
* @param {number[]} numbering - The current numbering level
|
||||
* @returns {import("@/types").SidebarItemType[]} The modified sidebar items
|
||||
* @returns {import("@/types").SidebarItem[]} The modified sidebar items
|
||||
*/
|
||||
export default function numberSidebarItems(sidebarItems, numbering = [1]) {
|
||||
// TODO generate chapter titles
|
||||
if (!numbering.length) {
|
||||
numbering.push(1)
|
||||
}
|
||||
const isTopItems = numbering.length === 1
|
||||
/** @type {import("@/types").SidebarItem[]} */
|
||||
const numberedItems = []
|
||||
/** @type {import("@/types").SidebarItem | undefined} */
|
||||
let parentItem
|
||||
sidebarItems.forEach((item) => {
|
||||
if (item.type === "separator") {
|
||||
;(parentItem?.children || numberedItems).push(item)
|
||||
}
|
||||
if (isTopItems) {
|
||||
// Add chapter category
|
||||
numberedItems.push({
|
||||
type: "category",
|
||||
title: `Chapter ${padNumber(numbering[0])}`,
|
||||
children: [],
|
||||
loaded: true,
|
||||
})
|
||||
|
||||
parentItem = numberedItems[numberedItems.length - 1]
|
||||
}
|
||||
// append current number to the item's title
|
||||
item.number = `${numbering.join(".")}.`
|
||||
item.title = `${item.number} ${item.title.trim()}`
|
||||
@@ -17,8 +37,19 @@ export default function numberSidebarItems(sidebarItems, numbering = [1]) {
|
||||
item.children = numberSidebarItems(item.children, [...numbering, 1])
|
||||
}
|
||||
|
||||
;(parentItem?.children || numberedItems).push(item)
|
||||
|
||||
numbering[numbering.length - 1]++
|
||||
})
|
||||
|
||||
return sidebarItems
|
||||
return numberedItems
|
||||
}
|
||||
|
||||
function padNumber(number) {
|
||||
number = number.toString()
|
||||
if (number.length < 2) {
|
||||
number = `0` + number
|
||||
}
|
||||
|
||||
return number
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/** @type {Partial<import("../providers").SidebarItemType>} */
|
||||
/** @type {Partial<import("@/types").SidebarItem[]>} */
|
||||
const commonOptions = {
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
@@ -6,13 +6,26 @@ const commonOptions = {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("../providers").SidebarItemType[]} sidebar
|
||||
* @returns {import("../providers").SidebarItemType[]}
|
||||
* @param {import("@/types").SidebarItem[]} sidebar
|
||||
* @param {boolean} nested
|
||||
* @returns {import("@/types").SidebarItem[]}
|
||||
*/
|
||||
export function sidebarAttachHrefCommonOptions(sidebar) {
|
||||
return sidebar.map((item) => ({
|
||||
...commonOptions,
|
||||
...item,
|
||||
children: sidebarAttachHrefCommonOptions(item.children || []),
|
||||
}))
|
||||
export function sidebarAttachHrefCommonOptions(sidebar, nested = false) {
|
||||
return sidebar.map((item) => {
|
||||
if (item.type === "separator") {
|
||||
return item
|
||||
}
|
||||
|
||||
const updatedItem = {
|
||||
...commonOptions,
|
||||
...item,
|
||||
children: sidebarAttachHrefCommonOptions(item.children || [], true),
|
||||
}
|
||||
|
||||
if (updatedItem.type !== "category" && !nested) {
|
||||
updatedItem.childrenSameLevel = true
|
||||
}
|
||||
|
||||
return updatedItem
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import type { Metadata } from "next"
|
||||
import { Inter, Roboto_Mono } from "next/font/google"
|
||||
|
||||
import Navbar from "@/components/Navbar"
|
||||
import Providers from "@/providers"
|
||||
import "./globals.css"
|
||||
import { Bannerv2, Breadcrumbs, TightLayout } from "docs-ui"
|
||||
import { Breadcrumbs, TightLayout } from "docs-ui"
|
||||
import { config } from "@/config"
|
||||
import clsx from "clsx"
|
||||
import { Feedback } from "@/components/Feedback"
|
||||
@@ -41,14 +39,11 @@ export default function RootLayout({
|
||||
return (
|
||||
<TightLayout
|
||||
ProvidersComponent={Providers}
|
||||
NavbarComponent={Navbar}
|
||||
sidebarProps={{
|
||||
expandItems: true,
|
||||
banner: <Bannerv2 />,
|
||||
}}
|
||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||
>
|
||||
<Breadcrumbs />
|
||||
{children}
|
||||
<Feedback className="my-2" />
|
||||
<EditButton />
|
||||
|
||||
@@ -10,4 +10,4 @@ This section of the documentation provides a reference to the workflows created
|
||||
|
||||
You can use these workflows in your customizations as well. They're available in the `@medusajs/core-flows` package.
|
||||
|
||||
<ChildDocs childLevel={2} />
|
||||
<ChildDocs childLevel={2} hideItems={["Overview"]} />
|
||||
@@ -1,38 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Navbar as UiNavbar, getNavbarItems } from "docs-ui"
|
||||
import { useSidebar } from "docs-ui"
|
||||
import { basePathUrl } from "../../utils/base-path-url"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../../config"
|
||||
|
||||
const Navbar = () => {
|
||||
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
||||
const navbarItems = useMemo(
|
||||
() =>
|
||||
getNavbarItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(""),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiNavbar
|
||||
logo={{
|
||||
light: basePathUrl("/images/logo-icon.png"),
|
||||
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||
}}
|
||||
items={navbarItems}
|
||||
mobileMenuButton={{
|
||||
setMobileSidebarOpen,
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
isLoading={false}
|
||||
showSearchOpener
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Navbar
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DocsConfig } from "types"
|
||||
import { DocsConfig, SidebarItem } from "types"
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
import { generatedSidebar } from "../generated/sidebar.mjs"
|
||||
|
||||
@@ -9,8 +9,7 @@ export const config: DocsConfig = {
|
||||
baseUrl,
|
||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||
sidebar: {
|
||||
top: generatedSidebar,
|
||||
bottom: [],
|
||||
default: generatedSidebar as SidebarItem[],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -16,6 +16,7 @@ import {
|
||||
import SidebarProvider from "./sidebar"
|
||||
import SearchProvider from "./search"
|
||||
import { config } from "../config"
|
||||
import { MainNavProvider } from "./main-nav"
|
||||
|
||||
type ProvidersProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -35,16 +36,18 @@ const Providers = ({ children }: ProvidersProps) => {
|
||||
<ScrollControllerProvider scrollableSelector="#main">
|
||||
<SidebarProvider>
|
||||
<PaginationProvider>
|
||||
<SearchProvider>
|
||||
<HooksLoader
|
||||
options={{
|
||||
pageScrollManager: true,
|
||||
currentLearningPath: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</HooksLoader>
|
||||
</SearchProvider>
|
||||
<MainNavProvider>
|
||||
<SearchProvider>
|
||||
<HooksLoader
|
||||
options={{
|
||||
pageScrollManager: true,
|
||||
currentLearningPath: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</HooksLoader>
|
||||
</SearchProvider>
|
||||
</MainNavProvider>
|
||||
</PaginationProvider>
|
||||
</SidebarProvider>
|
||||
</ScrollControllerProvider>
|
||||
|
||||
46
www/apps/resources/providers/main-nav.tsx
Normal file
46
www/apps/resources/providers/main-nav.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
formatReportLink,
|
||||
getNavDropdownItems,
|
||||
MainNavProvider as UiMainNavProvider,
|
||||
useIsBrowser,
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { basePathUrl } from "../utils/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
const isBrowser = useIsBrowser()
|
||||
const navigationDropdownItems = useMemo(
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
() =>
|
||||
formatReportLink(
|
||||
config.titleSuffix || "",
|
||||
isBrowser ? document.title : ""
|
||||
),
|
||||
[isBrowser]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiMainNavProvider
|
||||
navItems={navigationDropdownItems}
|
||||
reportIssueLink={reportLink}
|
||||
>
|
||||
{children}
|
||||
</UiMainNavProvider>
|
||||
)
|
||||
}
|
||||
@@ -20,7 +20,6 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
|
||||
initialItems={config.sidebar}
|
||||
staticSidebarItems={true}
|
||||
disableActiveTransition={true}
|
||||
noTitleStyling={true}
|
||||
>
|
||||
{children}
|
||||
</UiSidebarProvider>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
||||
/** @type {Partial<import("../types").SidebarItemType>} */
|
||||
/** @type {Partial<import("../types").RawSidebarItem>} */
|
||||
const commonOptions = {
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
@@ -6,13 +6,19 @@ const commonOptions = {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {import("types").SidebarItemType[]} sidebar
|
||||
* @returns {import("types").SidebarItemType[]}
|
||||
* @param {import("types").RawSidebarItem[]} sidebar
|
||||
* @returns {import("types").RawSidebarItem[]}
|
||||
*/
|
||||
export function sidebarAttachHrefCommonOptions(sidebar) {
|
||||
return sidebar.map((item) => ({
|
||||
...commonOptions,
|
||||
...item,
|
||||
children: sidebarAttachHrefCommonOptions(item.children || []),
|
||||
}))
|
||||
return sidebar.map((item) => {
|
||||
if (item.type === "separator") {
|
||||
return item
|
||||
}
|
||||
|
||||
return {
|
||||
...commonOptions,
|
||||
...item,
|
||||
children: sidebarAttachHrefCommonOptions(item.children || []),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineDocumentType, makeSource } from "contentlayer/source-files"
|
||||
import { rehypeComponent } from "./src/lib/rehype-component"
|
||||
import rehypeSlug from "rehype-slug"
|
||||
|
||||
export const Doc = defineDocumentType(() => ({
|
||||
name: "Doc",
|
||||
@@ -26,6 +27,6 @@ export default makeSource({
|
||||
contentDirPath: "./src/content",
|
||||
documentTypes: [Doc],
|
||||
mdx: {
|
||||
rehypePlugins: [rehypeComponent],
|
||||
rehypePlugins: [[rehypeComponent], [rehypeSlug]],
|
||||
},
|
||||
})
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
"react": "18.2.0",
|
||||
"react-day-picker": "^8.10.0",
|
||||
"react-dom": "18.2.0",
|
||||
"rehype-slug": "^6.0.0",
|
||||
"remark": "^14.0.3",
|
||||
"tailwind": "*",
|
||||
"tailwindcss": "3.3.3",
|
||||
|
||||
@@ -2,7 +2,7 @@ import { MetadataRoute } from "next"
|
||||
|
||||
import { docsConfig } from "@/config/docs"
|
||||
import { absoluteUrl } from "@/lib/absolute-url"
|
||||
import { SidebarItemType } from "types"
|
||||
import { SidebarItem } from "types"
|
||||
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
const now = new Date()
|
||||
@@ -12,23 +12,24 @@ export default function sitemap(): MetadataRoute.Sitemap {
|
||||
lastModified?: string | Date
|
||||
}> = []
|
||||
|
||||
function pushItems(newItems: SidebarItemType[]) {
|
||||
function pushItems(newItems: SidebarItem[]) {
|
||||
newItems.forEach((item) => {
|
||||
if (item.path) {
|
||||
items.push({
|
||||
url: absoluteUrl(item.path),
|
||||
lastModified: now,
|
||||
})
|
||||
if (item.type !== "link") {
|
||||
return
|
||||
}
|
||||
|
||||
items.push({
|
||||
url: absoluteUrl(item.path),
|
||||
lastModified: now,
|
||||
})
|
||||
|
||||
if (item.children) {
|
||||
pushItems(item.children)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pushItems(docsConfig.sidebar.top)
|
||||
pushItems(docsConfig.sidebar.bottom)
|
||||
pushItems(docsConfig.sidebar.default)
|
||||
|
||||
return items
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { Metadata } from "next"
|
||||
|
||||
import { Navbar } from "@/components/navbar"
|
||||
import { Providers } from "@/providers"
|
||||
|
||||
import { siteConfig } from "@/config/site"
|
||||
@@ -36,11 +35,11 @@ export default function RootLayout({
|
||||
return (
|
||||
<TightLayout
|
||||
ProvidersComponent={Providers}
|
||||
NavbarComponent={Navbar}
|
||||
sidebarProps={{
|
||||
expandItems: true,
|
||||
}}
|
||||
bodyClassName={clsx(inter.variable, robotoMono.variable)}
|
||||
showBanner={false}
|
||||
>
|
||||
{children}
|
||||
</TightLayout>
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { docsConfig } from "@/config/docs"
|
||||
import { basePathUrl } from "@/lib/base-path-url"
|
||||
import { Navbar as UiNavbar, useSidebar } from "docs-ui"
|
||||
|
||||
const Navbar = () => {
|
||||
const { mobileSidebarOpen, setMobileSidebarOpen } = useSidebar()
|
||||
|
||||
return (
|
||||
<UiNavbar
|
||||
logo={{
|
||||
light: basePathUrl("/images/logo-icon.png"),
|
||||
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||
}}
|
||||
items={docsConfig.mainNav}
|
||||
mobileMenuButton={{
|
||||
setMobileSidebarOpen,
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Navbar }
|
||||
@@ -1,281 +1,360 @@
|
||||
import { ArrowUpRightOnBox } from "@medusajs/icons"
|
||||
import { NavbarItem, getMobileSidebarItems, getNavbarItems } from "docs-ui"
|
||||
import { SidebarSectionItemsType } from "types"
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
import { SidebarSectionItems } from "types"
|
||||
import { siteConfig } from "./site"
|
||||
|
||||
type DocsConfig = {
|
||||
mainNav: NavbarItem[]
|
||||
sidebar: SidebarSectionItemsType
|
||||
sidebar: SidebarSectionItems
|
||||
}
|
||||
|
||||
export const docsConfig: DocsConfig = {
|
||||
mainNav: getNavbarItems({
|
||||
basePath: siteConfig.baseUrl,
|
||||
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/ui",
|
||||
version: "v1",
|
||||
}),
|
||||
sidebar: {
|
||||
top: [
|
||||
default: [
|
||||
{
|
||||
title: "Getting Started",
|
||||
children: [
|
||||
{
|
||||
title: "Introduction",
|
||||
path: "/",
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
type: "link",
|
||||
title: "Introduction",
|
||||
path: "/",
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
title: "Installation",
|
||||
loaded: true,
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Medusa Admin Extension",
|
||||
path: "/installation/medusa-admin-extension",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Standalone Project",
|
||||
path: "/installation/standalone-project",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Upgrade Guides",
|
||||
path: `${process.env.NEXT_PUBLIC_DOCS_URL}/upgrade-guides/medusa-ui`,
|
||||
isPathHref: true,
|
||||
additionalElms: <ArrowUpRightOnBox />,
|
||||
linkProps: {
|
||||
target: "_blank",
|
||||
rel: "noreferrer",
|
||||
},
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
bottom: [
|
||||
{
|
||||
type: "category",
|
||||
title: "Colors",
|
||||
loaded: true,
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Overview",
|
||||
path: "/colors/overview",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Icons",
|
||||
children: [
|
||||
{
|
||||
title: "Overview",
|
||||
path: "/icons/overview",
|
||||
isPathHref: true,
|
||||
},
|
||||
],
|
||||
path: "/icons/overview",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
title: "Components",
|
||||
loaded: true,
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "Alert",
|
||||
path: "/components/alert",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Avatar",
|
||||
path: "/components/avatar",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Badge",
|
||||
path: "/components/badge",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Button",
|
||||
path: "/components/button",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Calendar",
|
||||
path: "/components/calendar",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Checkbox",
|
||||
path: "/components/checkbox",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Code Block",
|
||||
path: "/components/code-block",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Command",
|
||||
path: "/components/command",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Command Bar",
|
||||
path: "/components/command-bar",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Container",
|
||||
path: "/components/container",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Copy",
|
||||
path: "/components/copy",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Currency Input",
|
||||
path: "/components/currency-input",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Date Picker",
|
||||
path: "/components/date-picker",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Drawer",
|
||||
path: "/components/drawer",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Dropdown Menu",
|
||||
path: "/components/dropdown-menu",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Focus Modal",
|
||||
path: "/components/focus-modal",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Heading",
|
||||
path: "/components/heading",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Icon Badge",
|
||||
path: "/components/icon-badge",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Icon Button",
|
||||
path: "/components/icon-button",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Input",
|
||||
path: "/components/input",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Kbd",
|
||||
path: "/components/kbd",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Label",
|
||||
path: "/components/label",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Progress Accordion",
|
||||
path: "/components/progress-accordion",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Progress Tabs",
|
||||
path: "/components/progress-tabs",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Prompt",
|
||||
path: "/components/prompt",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Radio Group",
|
||||
path: "/components/radio-group",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Select",
|
||||
path: "/components/select",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Status Badge",
|
||||
path: "/components/status-badge",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Switch",
|
||||
path: "/components/switch",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Table",
|
||||
path: "/components/table",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Tabs",
|
||||
path: "/components/tabs",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Text",
|
||||
path: "/components/text",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Textarea",
|
||||
path: "/components/textarea",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Toast",
|
||||
path: "/components/toast",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "Tooltip",
|
||||
path: "/components/tooltip",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
title: "Hooks",
|
||||
loaded: true,
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "usePrompt",
|
||||
path: "/hooks/use-prompt",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
{
|
||||
type: "link",
|
||||
title: "useToggleState",
|
||||
path: "/hooks/use-toggle-state",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
title: "Utils",
|
||||
loaded: true,
|
||||
children: [
|
||||
{
|
||||
type: "link",
|
||||
title: "clx",
|
||||
path: "/utils/clx",
|
||||
isPathHref: true,
|
||||
loaded: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -16,8 +16,7 @@ export const siteConfig: SiteConfig = {
|
||||
description: "Primitives for building Medusa applications.",
|
||||
// sidebar is defined in docs.tsx
|
||||
sidebar: {
|
||||
top: [],
|
||||
bottom: [],
|
||||
default: [],
|
||||
mobile: [],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
import SearchProvider from "./search"
|
||||
import SidebarProvider from "./sidebar"
|
||||
import { siteConfig } from "../config/site"
|
||||
import { MainNavProvider } from "./main-nav"
|
||||
|
||||
type ProvidersProps = {
|
||||
children: React.ReactNode
|
||||
@@ -25,7 +26,9 @@ const Providers = ({ children }: ProvidersProps) => {
|
||||
<ModalProvider>
|
||||
<ScrollControllerProvider scrollableSelector="#main">
|
||||
<SidebarProvider>
|
||||
<SearchProvider>{children}</SearchProvider>
|
||||
<MainNavProvider>
|
||||
<SearchProvider>{children}</SearchProvider>
|
||||
</MainNavProvider>
|
||||
</SidebarProvider>
|
||||
</ScrollControllerProvider>
|
||||
</ModalProvider>
|
||||
|
||||
42
www/apps/ui/src/providers/main-nav.tsx
Normal file
42
www/apps/ui/src/providers/main-nav.tsx
Normal file
@@ -0,0 +1,42 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
formatReportLink,
|
||||
getNavDropdownItems,
|
||||
MainNavProvider as UiMainNavProvider,
|
||||
useIsBrowser,
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { siteConfig } from "../config/site"
|
||||
import { basePathUrl } from "../lib/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
const isBrowser = useIsBrowser()
|
||||
const navigationDropdownItems = useMemo(
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: siteConfig.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v1",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
() => formatReportLink("UI Docs", isBrowser ? document.title : "", "ui"),
|
||||
[isBrowser]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiMainNavProvider
|
||||
navItems={navigationDropdownItems}
|
||||
reportIssueLink={reportLink}
|
||||
>
|
||||
{children}
|
||||
</UiMainNavProvider>
|
||||
)
|
||||
}
|
||||
@@ -10,6 +10,7 @@ type SidebarProviderProps = {
|
||||
|
||||
const SidebarProvider = ({ children }: SidebarProviderProps) => {
|
||||
const { scrollableElement } = useScrollController()
|
||||
|
||||
return (
|
||||
<UiSidebarProvider
|
||||
initialItems={docsConfig.sidebar}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import type { Metadata } from "next"
|
||||
import { Inter, Roboto_Mono } from "next/font/google"
|
||||
|
||||
import Navbar from "@/components/Navbar"
|
||||
import Providers from "@/providers"
|
||||
import "../css/globals.css"
|
||||
import { TightLayout } from "docs-ui"
|
||||
@@ -40,7 +38,6 @@ export default function RootLayout({
|
||||
return (
|
||||
<TightLayout
|
||||
ProvidersComponent={Providers}
|
||||
NavbarComponent={Navbar}
|
||||
sidebarProps={{
|
||||
expandItems: true,
|
||||
}}
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import { Navbar as UiNavbar, getNavbarItems } from "docs-ui"
|
||||
import { useSidebar } from "docs-ui"
|
||||
import { basePathUrl } from "../../utils/base-path-url"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../../config"
|
||||
|
||||
const Navbar = () => {
|
||||
const { setMobileSidebarOpen, mobileSidebarOpen } = useSidebar()
|
||||
|
||||
const navbarItems = useMemo(
|
||||
() =>
|
||||
getNavbarItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/user-guide",
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiNavbar
|
||||
logo={{
|
||||
light: basePathUrl("/images/logo-icon.png"),
|
||||
dark: basePathUrl("/images/logo-icon-dark.png"),
|
||||
}}
|
||||
items={navbarItems}
|
||||
mobileMenuButton={{
|
||||
setMobileSidebarOpen,
|
||||
mobileSidebarOpen,
|
||||
}}
|
||||
isLoading={false}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default Navbar
|
||||
@@ -1,4 +1,4 @@
|
||||
import { DocsConfig } from "types"
|
||||
import { DocsConfig, SidebarItem } from "types"
|
||||
import { getMobileSidebarItems } from "docs-ui"
|
||||
import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs"
|
||||
|
||||
@@ -9,8 +9,7 @@ export const config: DocsConfig = {
|
||||
baseUrl,
|
||||
basePath: process.env.NEXT_PUBLIC_BASE_PATH,
|
||||
sidebar: {
|
||||
top: sidebar,
|
||||
bottom: [],
|
||||
default: sidebar as SidebarItem[],
|
||||
mobile: getMobileSidebarItems({
|
||||
baseUrl,
|
||||
version: "v2",
|
||||
|
||||
@@ -2,13 +2,18 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/",
|
||||
"title": "Introduction",
|
||||
"children": []
|
||||
},
|
||||
{
|
||||
"type": "separator"
|
||||
},
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"title": "Tips",
|
||||
"hasTitleStyling": true,
|
||||
"autogenerate_path": "/tips",
|
||||
@@ -16,6 +21,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/tips/bulk-editor",
|
||||
"title": "Bulk Editor",
|
||||
"children": []
|
||||
@@ -23,6 +29,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/tips/languages",
|
||||
"title": "Admin Languages",
|
||||
"children": []
|
||||
@@ -30,6 +37,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/tips/lists",
|
||||
"title": "Lists",
|
||||
"children": []
|
||||
@@ -39,6 +47,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/orders",
|
||||
"title": "Orders",
|
||||
"hasTitleStyling": true,
|
||||
@@ -47,6 +56,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/manage",
|
||||
"title": "Manage Details",
|
||||
"children": []
|
||||
@@ -54,6 +64,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/payments",
|
||||
"title": "Manage Payments",
|
||||
"children": []
|
||||
@@ -61,6 +72,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/fulfillments",
|
||||
"title": "Manage Fulfillments",
|
||||
"children": []
|
||||
@@ -68,6 +80,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/edit",
|
||||
"title": "Edit an Order’s Items",
|
||||
"children": []
|
||||
@@ -75,6 +88,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/drafts",
|
||||
"title": "Manage Draft Orders",
|
||||
"children": []
|
||||
@@ -82,6 +96,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/returns",
|
||||
"title": "Manage Returns",
|
||||
"children": []
|
||||
@@ -89,6 +104,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/exchange",
|
||||
"title": "Manage Exchanges",
|
||||
"children": []
|
||||
@@ -96,6 +112,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/claims",
|
||||
"title": "Manage Order's Claims",
|
||||
"children": []
|
||||
@@ -103,6 +120,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/orders/export",
|
||||
"title": "Export Orders",
|
||||
"children": []
|
||||
@@ -112,6 +130,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/products",
|
||||
"title": "Products",
|
||||
"hasTitleStyling": true,
|
||||
@@ -120,6 +139,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/manage",
|
||||
"title": "Manage Products",
|
||||
"children": []
|
||||
@@ -127,6 +147,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/collections",
|
||||
"title": "Manage Product Collections",
|
||||
"children": []
|
||||
@@ -134,6 +155,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/categories",
|
||||
"title": "Manage Product Categories",
|
||||
"children": []
|
||||
@@ -141,12 +163,14 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/gift-cards",
|
||||
"title": "Gift Cards",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/gift-cards/product-gift-card",
|
||||
"title": "Manage a Product Gift Card",
|
||||
"children": [],
|
||||
@@ -155,6 +179,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/gift-cards/customer-gift-card",
|
||||
"title": "Manage a Customer Gift Card",
|
||||
"children": [],
|
||||
@@ -165,6 +190,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/import",
|
||||
"title": "Import Products",
|
||||
"children": []
|
||||
@@ -172,6 +198,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/products/export",
|
||||
"title": "Export Products",
|
||||
"children": []
|
||||
@@ -181,6 +208,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/inventory",
|
||||
"title": "Inventory",
|
||||
"hasTitleStyling": true,
|
||||
@@ -189,6 +217,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/inventory/inventory",
|
||||
"title": "Manage Inventory",
|
||||
"children": []
|
||||
@@ -196,6 +225,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/inventory/reservations",
|
||||
"title": "Manage Reservations",
|
||||
"children": []
|
||||
@@ -205,6 +235,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/customers",
|
||||
"title": "Customers",
|
||||
"hasTitleStyling": true,
|
||||
@@ -213,6 +244,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/customers/manage",
|
||||
"title": "Manage Customers",
|
||||
"children": []
|
||||
@@ -220,6 +252,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/customers/groups",
|
||||
"title": "Manage Customer Groups",
|
||||
"children": []
|
||||
@@ -229,6 +262,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/discounts",
|
||||
"title": "Discounts",
|
||||
"hasTitleStyling": true,
|
||||
@@ -237,6 +271,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/discounts/create",
|
||||
"title": "Create a Discount",
|
||||
"children": []
|
||||
@@ -244,6 +279,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/discounts/manage",
|
||||
"title": "Manage Discounts",
|
||||
"children": []
|
||||
@@ -253,6 +289,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/pricing",
|
||||
"title": "Pricing",
|
||||
"hasTitleStyling": true,
|
||||
@@ -261,6 +298,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/pricing/create",
|
||||
"title": "Create a Price List",
|
||||
"children": []
|
||||
@@ -268,6 +306,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/pricing/manage",
|
||||
"title": "Manage Price Lists",
|
||||
"children": []
|
||||
@@ -277,6 +316,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "category",
|
||||
"path": "/settings",
|
||||
"title": "Settings",
|
||||
"hasTitleStyling": true,
|
||||
@@ -285,6 +325,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/profile",
|
||||
"title": "Profile",
|
||||
"children": []
|
||||
@@ -292,6 +333,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/store",
|
||||
"title": "Store",
|
||||
"children": []
|
||||
@@ -299,12 +341,14 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/users",
|
||||
"title": "Users",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/users/invites",
|
||||
"title": "Manage Invites",
|
||||
"children": [],
|
||||
@@ -315,12 +359,14 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/regions",
|
||||
"title": "Regions",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/regions/manage",
|
||||
"title": "Manage Regions",
|
||||
"children": [],
|
||||
@@ -329,6 +375,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/regions/countries",
|
||||
"title": "Manage Countries",
|
||||
"children": [],
|
||||
@@ -337,6 +384,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/regions/providers",
|
||||
"title": "Manage Providers",
|
||||
"children": [],
|
||||
@@ -345,6 +393,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/regions/shipping-options",
|
||||
"title": "Manage Shipping Options",
|
||||
"children": [],
|
||||
@@ -355,6 +404,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/return-reasons",
|
||||
"title": "Return Reasons",
|
||||
"children": []
|
||||
@@ -362,12 +412,14 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/taxes",
|
||||
"title": "Taxes",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/taxes/manage",
|
||||
"title": "Manage Taxes",
|
||||
"children": [],
|
||||
@@ -376,6 +428,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/taxes/tax-rates",
|
||||
"title": "Manage Tax Rates",
|
||||
"children": [],
|
||||
@@ -386,6 +439,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/locations",
|
||||
"title": "Locations",
|
||||
"children": []
|
||||
@@ -393,12 +447,14 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/sales-channels",
|
||||
"title": "Sales Channels",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/sales-channels/manage",
|
||||
"title": "Manage Sales Channels",
|
||||
"children": [],
|
||||
@@ -407,6 +463,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/sales-channels/products",
|
||||
"title": "Manage Products",
|
||||
"children": [],
|
||||
@@ -417,18 +474,21 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/developer",
|
||||
"title": "Developer",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/developer/api-key-management",
|
||||
"title": "API Key Management",
|
||||
"children": [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/developer/api-key-management/sales-channels",
|
||||
"title": "Manage Sales Channels",
|
||||
"children": [],
|
||||
@@ -440,6 +500,7 @@ export const generatedSidebar = [
|
||||
{
|
||||
"loaded": true,
|
||||
"isPathHref": true,
|
||||
"type": "link",
|
||||
"path": "/settings/developer/executions",
|
||||
"title": "Executions",
|
||||
"children": [],
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
import SidebarProvider from "./sidebar"
|
||||
import SearchProvider from "./search"
|
||||
import { config } from "../config"
|
||||
import { MainNavProvider } from "./main-nav"
|
||||
|
||||
type ProvidersProps = {
|
||||
children?: React.ReactNode
|
||||
@@ -32,15 +33,17 @@ const Providers = ({ children }: ProvidersProps) => {
|
||||
<ScrollControllerProvider scrollableSelector="#main">
|
||||
<SidebarProvider>
|
||||
<PaginationProvider>
|
||||
<SearchProvider>
|
||||
<HooksLoader
|
||||
options={{
|
||||
pageScrollManager: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</HooksLoader>
|
||||
</SearchProvider>
|
||||
<MainNavProvider>
|
||||
<SearchProvider>
|
||||
<HooksLoader
|
||||
options={{
|
||||
pageScrollManager: true,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</HooksLoader>
|
||||
</SearchProvider>
|
||||
</MainNavProvider>
|
||||
</PaginationProvider>
|
||||
</SidebarProvider>
|
||||
</ScrollControllerProvider>
|
||||
|
||||
46
www/apps/user-guide/providers/main-nav.tsx
Normal file
46
www/apps/user-guide/providers/main-nav.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
formatReportLink,
|
||||
getNavDropdownItems,
|
||||
MainNavProvider as UiMainNavProvider,
|
||||
useIsBrowser,
|
||||
} from "docs-ui"
|
||||
import { useMemo } from "react"
|
||||
import { config } from "../config"
|
||||
import { basePathUrl } from "../utils/base-path-url"
|
||||
|
||||
type MainNavProviderProps = {
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
export const MainNavProvider = ({ children }: MainNavProviderProps) => {
|
||||
const isBrowser = useIsBrowser()
|
||||
const navigationDropdownItems = useMemo(
|
||||
() =>
|
||||
getNavDropdownItems({
|
||||
basePath: config.baseUrl,
|
||||
activePath: basePathUrl(),
|
||||
version: "v2",
|
||||
}),
|
||||
[]
|
||||
)
|
||||
|
||||
const reportLink = useMemo(
|
||||
() =>
|
||||
formatReportLink(
|
||||
config.titleSuffix || "",
|
||||
isBrowser ? document.title : ""
|
||||
),
|
||||
[isBrowser]
|
||||
)
|
||||
|
||||
return (
|
||||
<UiMainNavProvider
|
||||
navItems={navigationDropdownItems}
|
||||
reportIssueLink={reportLink}
|
||||
>
|
||||
{children}
|
||||
</UiMainNavProvider>
|
||||
)
|
||||
}
|
||||
@@ -20,7 +20,6 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
|
||||
initialItems={config.sidebar}
|
||||
staticSidebarItems={true}
|
||||
disableActiveTransition={true}
|
||||
noTitleStyling={true}
|
||||
>
|
||||
{children}
|
||||
</UiSidebarProvider>
|
||||
|
||||
@@ -5,51 +5,63 @@ import { sidebarAttachHrefCommonOptions } from "build-scripts"
|
||||
/** @type {import('types').RawSidebarItemType[]} */
|
||||
export const sidebar = sidebarAttachHrefCommonOptions([
|
||||
{
|
||||
type: "link",
|
||||
path: "/",
|
||||
title: "Introduction",
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
title: "Tips",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/tips",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/orders",
|
||||
title: "Orders",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/orders",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/products",
|
||||
title: "Products",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/products",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/inventory",
|
||||
title: "Inventory",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/inventory",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/customers",
|
||||
title: "Customers",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/customers",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/discounts",
|
||||
title: "Discounts",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/discounts",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/pricing",
|
||||
title: "Pricing",
|
||||
hasTitleStyling: true,
|
||||
autogenerate_path: "/pricing",
|
||||
},
|
||||
{
|
||||
type: "category",
|
||||
path: "/settings",
|
||||
title: "Settings",
|
||||
hasTitleStyling: true,
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import type { RawSidebarItemType } from "types"
|
||||
import type { RawSidebarItem, SidebarItem } from "types"
|
||||
import { existsSync, mkdirSync, readdirSync, statSync } from "fs"
|
||||
import path from "path"
|
||||
import { getSidebarItemLink, sidebarAttachHrefCommonOptions } from "./index.js"
|
||||
import getCoreFlowsRefSidebarChildren from "./utils/get-core-flows-ref-sidebar-children.js"
|
||||
|
||||
export type ItemsToAdd = RawSidebarItemType & {
|
||||
export type ItemsToAdd = SidebarItem & {
|
||||
sidebar_position?: number
|
||||
}
|
||||
|
||||
@@ -37,19 +37,17 @@ async function getSidebarItems(
|
||||
true
|
||||
)
|
||||
if (nested && newItems.length > 1) {
|
||||
items.push(
|
||||
...sidebarAttachHrefCommonOptions([
|
||||
{
|
||||
title:
|
||||
fileBasename.charAt(0).toUpperCase() +
|
||||
fileBasename.substring(1),
|
||||
hasTitleStyling: true,
|
||||
children: newItems,
|
||||
},
|
||||
])
|
||||
)
|
||||
items.push({
|
||||
type: "sub-category",
|
||||
title:
|
||||
fileBasename.charAt(0).toUpperCase() + fileBasename.substring(1),
|
||||
children: newItems,
|
||||
loaded: true,
|
||||
})
|
||||
} else {
|
||||
items.push(...sidebarAttachHrefCommonOptions(newItems))
|
||||
items.push(
|
||||
...(sidebarAttachHrefCommonOptions(newItems) as ItemsToAdd[])
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -69,7 +67,11 @@ async function getSidebarItems(
|
||||
mainPageIndex = items.length - 1
|
||||
}
|
||||
|
||||
if (mainPageIndex !== -1 && items.length > 1) {
|
||||
if (
|
||||
mainPageIndex !== -1 &&
|
||||
items.length > 1 &&
|
||||
items[0].type !== "separator"
|
||||
) {
|
||||
// push all other items to be children of that page.
|
||||
const mainPageChildren = [
|
||||
...items.splice(0, mainPageIndex),
|
||||
@@ -84,9 +86,19 @@ async function getSidebarItems(
|
||||
return items
|
||||
}
|
||||
|
||||
async function checkItem(
|
||||
item: RawSidebarItemType
|
||||
): Promise<RawSidebarItemType> {
|
||||
async function checkItem(item: RawSidebarItem): Promise<RawSidebarItem> {
|
||||
if (!item.type) {
|
||||
throw new Error(
|
||||
`ERROR: The following item doesn't have a type: ${JSON.stringify(
|
||||
item,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
)
|
||||
}
|
||||
if (item.type === "separator") {
|
||||
return item
|
||||
}
|
||||
if (item.autogenerate_path) {
|
||||
item.children = (await getSidebarItems(item.autogenerate_path)).map(
|
||||
(child) => {
|
||||
@@ -109,7 +121,7 @@ async function checkItem(
|
||||
return item
|
||||
}
|
||||
|
||||
export async function generateSidebar(sidebar: RawSidebarItemType[]) {
|
||||
export async function generateSidebar(sidebar: RawSidebarItem[]) {
|
||||
const path = await import("path")
|
||||
const { writeFileSync } = await import("fs")
|
||||
|
||||
|
||||
@@ -14,6 +14,19 @@ export default async function getCoreFlowsRefSidebarChildren(): Promise<
|
||||
|
||||
const sidebarItems: ItemsToAdd[] = []
|
||||
|
||||
sidebarItems.push(
|
||||
{
|
||||
type: "link",
|
||||
title: "Overview",
|
||||
path: "/medusa-workflows-reference",
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
}
|
||||
)
|
||||
|
||||
for (const directory of directories) {
|
||||
if (
|
||||
!directory.isDirectory() ||
|
||||
@@ -66,21 +79,28 @@ export default async function getCoreFlowsRefSidebarChildren(): Promise<
|
||||
|
||||
if (workflowItems.length || stepItems.length) {
|
||||
const item: ItemsToAdd = {
|
||||
type: "category",
|
||||
title: directory.name.replaceAll("_", " "),
|
||||
children: [],
|
||||
loaded: true,
|
||||
initialOpen: false,
|
||||
}
|
||||
|
||||
if (workflowItems.length) {
|
||||
item.children!.push({
|
||||
type: "sub-category",
|
||||
title: "Workflows",
|
||||
children: workflowItems,
|
||||
loaded: true,
|
||||
})
|
||||
}
|
||||
|
||||
if (stepItems.length) {
|
||||
item.children!.push({
|
||||
type: "sub-category",
|
||||
title: "Steps",
|
||||
children: stepItems,
|
||||
loaded: true,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ItemsToAdd, sidebarAttachHrefCommonOptions } from "../index.js"
|
||||
import { readFileSync } from "fs"
|
||||
import findMetadataTitle from "./find-metadata-title.js"
|
||||
import findPageHeading from "./find-page-heading.js"
|
||||
import { InteractiveSidebarItem } from "types"
|
||||
|
||||
export async function getSidebarItemLink({
|
||||
filePath,
|
||||
@@ -24,6 +25,7 @@ export async function getSidebarItemLink({
|
||||
|
||||
const newItem = sidebarAttachHrefCommonOptions([
|
||||
{
|
||||
type: "link",
|
||||
path:
|
||||
frontmatter.slug ||
|
||||
filePath.replace(basePath, "").replace(`/${fileBasename}`, ""),
|
||||
@@ -33,7 +35,7 @@ export async function getSidebarItemLink({
|
||||
findPageHeading(fileContent) ||
|
||||
"",
|
||||
},
|
||||
])[0]
|
||||
])[0] as InteractiveSidebarItem
|
||||
|
||||
return {
|
||||
...newItem,
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
import { RawSidebarItemType } from "types"
|
||||
import { RawSidebarItem } from "types"
|
||||
|
||||
const commonOptions: Partial<RawSidebarItemType> = {
|
||||
const commonOptions: Partial<RawSidebarItem> = {
|
||||
loaded: true,
|
||||
isPathHref: true,
|
||||
}
|
||||
|
||||
export function sidebarAttachHrefCommonOptions(
|
||||
sidebar: RawSidebarItemType[]
|
||||
): RawSidebarItemType[] {
|
||||
return sidebar.map((item) => ({
|
||||
...commonOptions,
|
||||
...item,
|
||||
children: sidebarAttachHrefCommonOptions(item.children || []),
|
||||
}))
|
||||
sidebar: RawSidebarItem[]
|
||||
): RawSidebarItem[] {
|
||||
return sidebar.map((item) => {
|
||||
if (item.type === "separator") {
|
||||
return item
|
||||
}
|
||||
|
||||
return {
|
||||
...commonOptions,
|
||||
...item,
|
||||
children: sidebarAttachHrefCommonOptions(item.children || []),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
"react-medium-image-zoom": "^5.1.10",
|
||||
"react-tooltip": "^5.21.3",
|
||||
"react-transition-group": "^4.4.5",
|
||||
"react-uuid": "^2.0.0"
|
||||
"react-uuid": "^2.0.0",
|
||||
"slugify": "^1.6.6"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,65 @@
|
||||
import React from "react"
|
||||
import { Card, Link } from "../.."
|
||||
"use client"
|
||||
|
||||
import React, { useEffect, useState } from "react"
|
||||
import { Button, useIsBrowser } from "../.."
|
||||
import { ExclamationCircleSolid, XMark } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
|
||||
const LOCAL_STORAGE_KEY = "banner-v2"
|
||||
|
||||
export type Bannerv2Props = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const Bannerv2 = ({ className }: Bannerv2Props) => {
|
||||
const [show, setShow] = useState(false)
|
||||
const isBrowser = useIsBrowser()
|
||||
|
||||
useEffect(() => {
|
||||
if (!isBrowser) {
|
||||
return
|
||||
}
|
||||
|
||||
const localStorageValue = localStorage.getItem(LOCAL_STORAGE_KEY)
|
||||
if (!localStorageValue) {
|
||||
setShow(true)
|
||||
}
|
||||
}, [isBrowser])
|
||||
|
||||
const handleClose = () => {
|
||||
setShow(false)
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY, "true")
|
||||
}
|
||||
|
||||
export const Bannerv2 = () => {
|
||||
return (
|
||||
<Card>
|
||||
This documentation is for Medusa v2, which isn't ready for
|
||||
production.
|
||||
<br />
|
||||
<br />
|
||||
For production-use, refer to{" "}
|
||||
<Link href="https://docs.medusajs.com">this documentation</Link> instead.
|
||||
</Card>
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-medusa-bg-base hidden gap-docs_0.5 z-20",
|
||||
"justify-between items-start rounded-docs_DEFAULT",
|
||||
"p-docs_0.75 shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
|
||||
show && "lg:flex",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<span className="p-[2.5px]">
|
||||
<ExclamationCircleSolid className="text-medusa-tag-orange-icon" />
|
||||
</span>
|
||||
<div className="flex flex-col gap-docs_0.125 flex-1">
|
||||
<span className="text-compact-small-plus text-medusa-fg-base">
|
||||
Medusa v2 and Docs under development
|
||||
</span>
|
||||
<span className="text-compact-small text-medusa-fg-subtle">
|
||||
We are actively working on building and improving. Some sections may
|
||||
be incomplete or subject to change. Thank you for your patience.
|
||||
</span>
|
||||
</div>
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className="text-medusa-fg-muted"
|
||||
onClick={handleClose}
|
||||
>
|
||||
<XMark />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import React from "react"
|
||||
import { Bordered } from "@/components/Bordered"
|
||||
import clsx from "clsx"
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
|
||||
@@ -15,37 +14,35 @@ export type BorderedIconProps = {
|
||||
export const BorderedIcon = ({
|
||||
icon = "",
|
||||
IconComponent = null,
|
||||
wrapperClassName,
|
||||
iconWrapperClassName,
|
||||
iconClassName,
|
||||
iconColorClassName = "",
|
||||
}: BorderedIconProps) => {
|
||||
return (
|
||||
<Bordered wrapperClassName={wrapperClassName}>
|
||||
<span
|
||||
className={clsx(
|
||||
"rounded-docs_xs p-docs_0.125 bg-medusa-bg-component inline-flex items-center justify-center",
|
||||
iconWrapperClassName
|
||||
)}
|
||||
>
|
||||
{!IconComponent && (
|
||||
<img
|
||||
src={icon || ""}
|
||||
className={clsx(iconClassName, "bordered-icon")}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
{IconComponent && (
|
||||
<IconComponent
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle",
|
||||
iconClassName,
|
||||
"bordered-icon",
|
||||
iconColorClassName
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
</Bordered>
|
||||
<span
|
||||
className={clsx(
|
||||
"rounded-docs_sm p-docs_0.125 bg-medusa-bg-base inline-flex items-center justify-center",
|
||||
"shadow-border-base dark:shadow-border-base-dark",
|
||||
iconWrapperClassName
|
||||
)}
|
||||
>
|
||||
{!IconComponent && (
|
||||
<img
|
||||
src={icon || ""}
|
||||
className={clsx(iconClassName, "bordered-icon")}
|
||||
alt=""
|
||||
/>
|
||||
)}
|
||||
{IconComponent && (
|
||||
<IconComponent
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle rounded-docs_sm",
|
||||
iconClassName,
|
||||
"bordered-icon",
|
||||
iconColorClassName
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -17,8 +17,13 @@ export const Breadcrumbs = () => {
|
||||
tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar)
|
||||
}
|
||||
|
||||
const parentPath =
|
||||
item.parentItem?.type === "link" ? item.parentItem.path : undefined
|
||||
const firstItemPath =
|
||||
item.default[0].type === "link" ? item.default[0].path : undefined
|
||||
|
||||
tempBreadcrumbItems.set(
|
||||
item.parentItem?.path || item.top[0].path || "/",
|
||||
parentPath || firstItemPath || "/",
|
||||
item.parentItem?.childSidebarTitle || item.parentItem?.title || ""
|
||||
)
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
import React, { useMemo } from "react"
|
||||
import { Card, CardList, MDXComponents, useSidebar } from "../.."
|
||||
import { SidebarItemType } from "types"
|
||||
import { InteractiveSidebarItem, SidebarItem, SidebarItemLink } from "types"
|
||||
import slugify from "slugify"
|
||||
|
||||
type ChildDocsProps = {
|
||||
onlyTopLevel?: boolean
|
||||
@@ -30,16 +31,19 @@ export const ChildDocs = ({
|
||||
: "all"
|
||||
}, [showItems, hideItems])
|
||||
|
||||
const filterCondition = (item: SidebarItemType): boolean => {
|
||||
const filterCondition = (item: SidebarItem): boolean => {
|
||||
if (item.type === "separator") {
|
||||
return false
|
||||
}
|
||||
switch (filterType) {
|
||||
case "hide":
|
||||
return (
|
||||
(!item.path || !hideItems.includes(item.path)) &&
|
||||
(item.type !== "link" || !hideItems.includes(item.path)) &&
|
||||
!hideItems.includes(item.title)
|
||||
)
|
||||
case "show":
|
||||
return (
|
||||
(item.path !== undefined && showItems!.includes(item.path)) ||
|
||||
(item.type === "link" && showItems!.includes(item.path)) ||
|
||||
showItems!.includes(item.title)
|
||||
)
|
||||
case "all":
|
||||
@@ -47,12 +51,16 @@ export const ChildDocs = ({
|
||||
}
|
||||
}
|
||||
|
||||
const filterItems = (items: SidebarItemType[]): SidebarItemType[] => {
|
||||
const filterItems = (items: SidebarItem[]): SidebarItem[] => {
|
||||
return items
|
||||
.filter(filterCondition)
|
||||
.map((item) => Object.assign({}, item))
|
||||
.map((item) => {
|
||||
if (item.children && filterType === "hide") {
|
||||
if (
|
||||
item.type !== "separator" &&
|
||||
item.children &&
|
||||
filterType === "hide"
|
||||
) {
|
||||
item.children = filterItems(item.children)
|
||||
}
|
||||
|
||||
@@ -67,8 +75,7 @@ export const ChildDocs = ({
|
||||
? Object.assign({}, currentItems)
|
||||
: undefined
|
||||
: {
|
||||
top: [...(getActiveItem()?.children || [])],
|
||||
bottom: [],
|
||||
default: [...(getActiveItem()?.children || [])],
|
||||
}
|
||||
if (filterType === "all" || !targetItems) {
|
||||
return targetItems
|
||||
@@ -76,25 +83,34 @@ export const ChildDocs = ({
|
||||
|
||||
return {
|
||||
...targetItems,
|
||||
top: filterItems(targetItems.top),
|
||||
bottom: filterItems(targetItems.bottom),
|
||||
default: filterItems(targetItems.default),
|
||||
}
|
||||
}, [currentItems, type, getActiveItem, filterItems])
|
||||
|
||||
const filterNonInteractiveItems = (
|
||||
items: SidebarItem[] | undefined
|
||||
): InteractiveSidebarItem[] => {
|
||||
return (
|
||||
(items?.filter(
|
||||
(item) => item.type !== "separator"
|
||||
) as InteractiveSidebarItem[]) || []
|
||||
)
|
||||
}
|
||||
|
||||
const getChildrenForLevel = (
|
||||
item: SidebarItemType,
|
||||
item: InteractiveSidebarItem,
|
||||
currentLevel = 1
|
||||
): SidebarItemType[] | undefined => {
|
||||
): InteractiveSidebarItem[] | undefined => {
|
||||
if (currentLevel === childLevel) {
|
||||
return item.children
|
||||
return filterNonInteractiveItems(item.children)
|
||||
}
|
||||
if (!item.children) {
|
||||
return
|
||||
}
|
||||
|
||||
const childrenResult: SidebarItemType[] = []
|
||||
const childrenResult: InteractiveSidebarItem[] = []
|
||||
|
||||
item.children.forEach((child) => {
|
||||
filterNonInteractiveItems(item.children).forEach((child) => {
|
||||
const childChildren = getChildrenForLevel(child, currentLevel + 1)
|
||||
|
||||
if (!childChildren) {
|
||||
@@ -107,20 +123,34 @@ export const ChildDocs = ({
|
||||
return childrenResult
|
||||
}
|
||||
|
||||
const getTopLevelElms = (items?: SidebarItemType[]) => (
|
||||
<CardList
|
||||
items={
|
||||
items?.map((childItem) => ({
|
||||
title: childItem.title,
|
||||
href: childItem.path,
|
||||
showLinkIcon: false,
|
||||
})) || []
|
||||
}
|
||||
/>
|
||||
)
|
||||
const getTopLevelElms = (items?: SidebarItem[]) => {
|
||||
return (
|
||||
<CardList
|
||||
items={
|
||||
filterNonInteractiveItems(items).map((childItem) => {
|
||||
const href =
|
||||
childItem.type === "link"
|
||||
? childItem.path
|
||||
: childItem.children?.length
|
||||
? (
|
||||
childItem.children.find(
|
||||
(item) => item.type === "link"
|
||||
) as SidebarItemLink
|
||||
)?.path
|
||||
: "#"
|
||||
return {
|
||||
title: childItem.title,
|
||||
href,
|
||||
showLinkIcon: false,
|
||||
}
|
||||
}) || []
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const getAllLevelsElms = (items?: SidebarItemType[]) =>
|
||||
items?.map((item, key) => {
|
||||
const getAllLevelsElms = (items?: SidebarItem[]) =>
|
||||
filterNonInteractiveItems(items).map((item, key) => {
|
||||
const itemChildren = getChildrenForLevel(item)
|
||||
const HeadingComponent = itemChildren?.length
|
||||
? MDXComponents["h2"]
|
||||
@@ -130,12 +160,16 @@ export const ChildDocs = ({
|
||||
<React.Fragment key={key}>
|
||||
{HeadingComponent && (
|
||||
<>
|
||||
{!hideTitle && <HeadingComponent>{item.title}</HeadingComponent>}
|
||||
{!hideTitle && (
|
||||
<HeadingComponent id={slugify(item.title)}>
|
||||
{item.title}
|
||||
</HeadingComponent>
|
||||
)}
|
||||
<CardList
|
||||
items={
|
||||
itemChildren?.map((childItem) => ({
|
||||
title: childItem.title,
|
||||
href: childItem.path,
|
||||
href: childItem.type === "link" ? childItem.path : "",
|
||||
showLinkIcon: false,
|
||||
})) || []
|
||||
}
|
||||
@@ -143,20 +177,19 @@ export const ChildDocs = ({
|
||||
</>
|
||||
)}
|
||||
{!HeadingComponent && (
|
||||
<Card title={item.title} href={item.path} showLinkIcon={false} />
|
||||
<Card
|
||||
title={item.title}
|
||||
href={item.type === "link" ? item.path : ""}
|
||||
showLinkIcon={false}
|
||||
/>
|
||||
)}
|
||||
</React.Fragment>
|
||||
)
|
||||
})
|
||||
|
||||
const getElms = (items?: SidebarItemType[]) => {
|
||||
const getElms = (items?: SidebarItem[]) => {
|
||||
return onlyTopLevel ? getTopLevelElms(items) : getAllLevelsElms(items)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{getElms(filteredItems?.top)}
|
||||
{getElms(filteredItems?.bottom)}
|
||||
</>
|
||||
)
|
||||
return <>{getElms(filteredItems?.default)}</>
|
||||
}
|
||||
|
||||
@@ -1,39 +1,23 @@
|
||||
"use client"
|
||||
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react"
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
import { Button } from "@/components"
|
||||
import clsx from "clsx"
|
||||
import { CSSTransition } from "react-transition-group"
|
||||
import { HelpButtonActions } from "./Actions"
|
||||
import { useIsBrowser } from "../.."
|
||||
import { useClickOutside } from "../.."
|
||||
|
||||
export const HelpButton = () => {
|
||||
const [showText, setShowText] = useState(false)
|
||||
const [showHelp, setShowHelp] = useState(false)
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const isBrowser = useIsBrowser()
|
||||
|
||||
const onClickOutside = useCallback(
|
||||
(e: MouseEvent) => {
|
||||
if (!ref.current?.contains(e.target as Node)) {
|
||||
setShowHelp(false)
|
||||
setShowText(false)
|
||||
}
|
||||
useClickOutside({
|
||||
elmRef: ref,
|
||||
onClickOutside: () => {
|
||||
setShowHelp(false)
|
||||
setShowText(false)
|
||||
},
|
||||
[ref.current]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!isBrowser) {
|
||||
return
|
||||
}
|
||||
|
||||
window.document.addEventListener("click", onClickOutside)
|
||||
|
||||
return () => {
|
||||
window.document.removeEventListener("click", onClickOutside)
|
||||
}
|
||||
}, [isBrowser])
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
if (showHelp) {
|
||||
|
||||
23
www/packages/docs-ui/src/components/Icons/House/index.tsx
Normal file
23
www/packages/docs-ui/src/components/Icons/House/index.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from "react"
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
|
||||
export const HouseIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="15"
|
||||
height="16"
|
||||
viewBox="0 0 15 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
d="M12.7044 5.5112L8.03778 1.96454C7.71956 1.72276 7.27956 1.72276 6.96222 1.96454L2.29556 5.5112C2.07422 5.6792 1.94444 5.94143 1.94444 6.21965V12.6676C1.94444 13.6499 2.74 14.4454 3.72222 14.4454H5.94444V10.8899C5.94444 10.3992 6.34267 10.001 6.83333 10.001H8.16667C8.65733 10.001 9.05556 10.3992 9.05556 10.8899V14.4454H11.2778C12.26 14.4454 13.0556 13.6499 13.0556 12.6676V6.21876C13.0556 5.94054 12.9258 5.68009 12.7044 5.5112Z"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,33 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownAdminIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect width="20" height="20" className="fill-medusa-tag-green-icon" />
|
||||
<g clipPath="url(#clip0_9988_95571)">
|
||||
<path
|
||||
d="M13.25 4.5H6.75C5.233 4.5 4 5.733 4 7.25V12.75C4 14.267 5.233 15.5 6.75 15.5H13.25C14.767 15.5 16 14.267 16 12.75V7.25C16 5.733 14.767 4.5 13.25 4.5ZM6.5 8C5.948 8 5.5 7.552 5.5 7C5.5 6.448 5.948 6 6.5 6C7.052 6 7.5 6.448 7.5 7C7.5 7.552 7.052 8 6.5 8ZM9.5 8C8.948 8 8.5 7.552 8.5 7C8.5 6.448 8.948 6 9.5 6C10.052 6 10.5 6.448 10.5 7C10.5 7.552 10.052 8 9.5 8Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9988_95571">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownDocIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect
|
||||
width="20"
|
||||
height="20"
|
||||
className="fill-medusa-fg-base dark:fill-medusa-bg-base"
|
||||
/>
|
||||
<g clipPath="url(#clip0_9988_95547)">
|
||||
<path
|
||||
d="M14.25 16H7.25C6.009 16 5 14.991 5 13.75C5 13.336 5.336 13 5.75 13C6.164 13 6.5 13.336 6.5 13.75C6.5 14.164 6.836 14.5 7.25 14.5H14.25C14.664 14.5 15 14.836 15 15.25C15 15.664 14.664 16 14.25 16Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
<path
|
||||
d="M12.75 4H7.25C6.009 4 5 5.009 5 6.25V13.75C5 14.164 5.336 14.5 5.75 14.5C6.164 14.5 6.5 14.164 6.5 13.75C6.5 13.336 6.836 13 7.25 13H14.25C14.664 13 15 12.664 15 12.25V6.25C15 5.009 13.991 4 12.75 4ZM11.25 9H8.75C8.336 9 8 8.664 8 8.25C8 7.836 8.336 7.5 8.75 7.5H11.25C11.664 7.5 12 7.836 12 8.25C12 8.664 11.664 9 11.25 9Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9988_95547">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownDocV1Icon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect width="20" height="20" className="fill-medusa-fg-subtle" />
|
||||
<g clipPath="url(#clip0_10088_101562)">
|
||||
<path
|
||||
d="M8 4.02405C6.687 4.14505 5.646 5.18605 5.525 6.50005H4.75C4.336 6.50005 4 6.83605 4 7.25005C4 7.66405 4.336 8.00005 4.75 8.00005H5.5V9.25005H4.75C4.336 9.25005 4 9.58605 4 10C4 10.414 4.336 10.75 4.75 10.75H5.5V12H4.75C4.336 12 4 12.336 4 12.75C4 13.164 4.336 13.5 4.75 13.5H5.525C5.646 14.814 6.687 15.855 8 15.976V4.02405Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
<path
|
||||
d="M12.25 4H9.5V16H12.25C13.767 16 15 14.767 15 13.25V6.75C15 5.233 13.767 4 12.25 4Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_10088_101562">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownResourcesIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect width="20" height="20" className="fill-medusa-tag-orange-icon" />
|
||||
<g clipPath="url(#clip0_9988_95555)">
|
||||
<path
|
||||
d="M15.25 12C14.836 12 14.5 11.664 14.5 11.25V8.75C14.5 8.061 13.939 7.5 13.25 7.5H10.614C10.386 7.5 10.172 7.397 10.029 7.219L9.425 6.467C9.187 6.17 8.831 6 8.45 6H6.749C6.06 6 5.499 6.561 5.499 7.25V11.25C5.499 11.664 5.163 12 4.749 12C4.335 12 3.999 11.664 3.999 11.25V7.25C4 5.733 5.233 4.5 6.75 4.5H8.451C9.289 4.5 10.07 4.875 10.596 5.528L10.974 6H13.25C14.767 6 16 7.233 16 8.75V11.25C16 11.664 15.664 12 15.25 12Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
<path
|
||||
d="M13.25 8.5H6.75C5.23122 8.5 4 9.73122 4 11.25V12.75C4 14.2688 5.23122 15.5 6.75 15.5H13.25C14.7688 15.5 16 14.2688 16 12.75V11.25C16 9.73122 14.7688 8.5 13.25 8.5Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9988_95555">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownStoreIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect width="20" height="20" className="fill-medusa-tag-purple-icon" />
|
||||
<g clipPath="url(#clip0_9988_95563)">
|
||||
<path
|
||||
d="M15.25 8.548C15.122 8.548 14.993 8.515 14.874 8.446L10 5.617L5.126 8.446C4.77 8.654 4.309 8.532 4.101 8.174C3.893 7.816 4.015 7.357 4.373 7.149L9.624 4.102C9.856 3.966 10.145 3.966 10.377 4.102L15.627 7.15C15.985 7.358 16.107 7.817 15.899 8.175C15.76 8.415 15.508 8.548 15.25 8.548Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
<path
|
||||
d="M10 7.35195L5 10.254V13.75C5 14.715 5.785 15.5 6.75 15.5H9.25V13.25C9.25 12.836 9.586 12.5 10 12.5C10.414 12.5 10.75 12.836 10.75 13.25V15.5H13.25C14.215 15.5 15 14.715 15 13.75V10.254L10 7.35195Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9988_95563">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownUiIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width={props.width || 20}
|
||||
height={props.height || 20}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect width="20" height="20" className="fill-medusa-tag-blue-icon" />
|
||||
<g clipPath="url(#clip0_9988_95578)">
|
||||
<path
|
||||
d="M14.18 10.472L9.28899 8.685C8.82599 8.518 8.32399 8.627 7.97699 8.975C7.62799 9.323 7.51699 9.826 7.68599 10.288L9.47199 15.178C9.65599 15.679 10.114 16 10.645 16C10.654 16 10.664 16 10.672 16C11.215 15.989 11.672 15.648 11.836 15.132L12.394 13.394L14.131 12.838C14.648 12.673 14.988 12.216 15 11.673C15.011 11.131 14.689 10.658 14.18 10.472Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
<path
|
||||
d="M6.13499 11.894C6.05799 11.894 5.97999 11.882 5.90299 11.857C4.76499 11.487 4.00099 10.439 4.00099 9.25V7.75C3.99999 6.234 5.23299 5 6.74999 5H13.25C14.767 5 16 6.234 16 7.75V9.052C16 9.466 15.664 9.802 15.25 9.802C14.836 9.802 14.5 9.466 14.5 9.052V7.75C14.5 7.061 13.939 6.5 13.25 6.5H6.74999C6.06099 6.5 5.49999 7.061 5.49999 7.75V9.25C5.49999 9.788 5.84899 10.262 6.36699 10.43C6.76099 10.558 6.97599 10.981 6.84699 11.375C6.74399 11.692 6.45099 11.893 6.13399 11.893L6.13499 11.894Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_9988_95578">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const NavigationDropdownUserIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<rect width="20" height="20" className="fill-medusa-tag-red-icon" />
|
||||
<g clipPath="url(#clip0_10088_101526)">
|
||||
<path
|
||||
d="M10 8.99097C11.3807 8.99097 12.5 7.87168 12.5 6.49097C12.5 5.11025 11.3807 3.99097 10 3.99097C8.61929 3.99097 7.5 5.11025 7.5 6.49097C7.5 7.87168 8.61929 8.99097 10 8.99097Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
<path
|
||||
d="M14.533 12.639C13.601 11.011 11.864 10 10 10C8.136 10 6.398 11.011 5.467 12.639C5.218 13.073 5.162 13.593 5.313 14.067C5.463 14.539 5.809 14.93 6.26 15.139C7.501 15.713 8.75 16 10 16C11.25 16 12.499 15.713 13.74 15.139C14.191 14.93 14.536 14.539 14.687 14.067C14.838 13.593 14.782 13.073 14.533 12.64V12.639Z"
|
||||
className="fill-medusa-fg-on-color"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_10088_101526">
|
||||
<rect
|
||||
width="12"
|
||||
height="12"
|
||||
className="fill-medusa-fg-on-color"
|
||||
transform="translate(4 4)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
import React from "react"
|
||||
|
||||
export const SidebarLeftIcon = (props: IconProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
{...props}
|
||||
>
|
||||
<g clipPath="url(#clip0_10002_37978)">
|
||||
<path
|
||||
d="M12.6668 2.25H3.33344C2.3516 2.25 1.55566 3.0738 1.55566 4.09V11.91C1.55566 12.9262 2.3516 13.75 3.33344 13.75H12.6668C13.6486 13.75 14.4446 12.9262 14.4446 11.91V4.09C14.4446 3.0738 13.6486 2.25 12.6668 2.25Z"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M4.3999 5V11"
|
||||
stroke="currentColor"
|
||||
strokeWidth="1.5"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_10002_37978">
|
||||
<rect
|
||||
width="15"
|
||||
height="15"
|
||||
fill="none"
|
||||
transform="translate(0.5 0.5)"
|
||||
/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -9,9 +9,9 @@ export const Kbd = ({ children, className, ...props }: KbdProps) => {
|
||||
className={clsx(
|
||||
"rounded-docs_xs border-solid border border-medusa-border-base",
|
||||
"inline-flex items-center justify-center",
|
||||
"py-0 px-[6px]",
|
||||
"py-0 px-docs_0.25",
|
||||
"bg-medusa-bg-field",
|
||||
"text-medusa-tag-neutral-text",
|
||||
"text-medusa-fg-subtle",
|
||||
"text-compact-x-small-plus font-base shadow-none",
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
"use client"
|
||||
|
||||
import React, { useMemo } from "react"
|
||||
import { CurrentItemsState, useSidebar } from "../../.."
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import { SidebarItemLink } from "types"
|
||||
|
||||
export const MainNavBreadcrumbs = () => {
|
||||
const { currentItems, getActiveItem } = useSidebar()
|
||||
|
||||
const getLinkPath = (item?: SidebarItemLink): string | undefined => {
|
||||
if (!item) {
|
||||
return
|
||||
}
|
||||
return item.isPathHref ? item.path : `#${item.path}`
|
||||
}
|
||||
|
||||
const getBreadcrumbsOfItem = (
|
||||
item: CurrentItemsState
|
||||
): Map<string, string> => {
|
||||
let tempBreadcrumbItems: Map<string, string> = new Map()
|
||||
if (item.previousSidebar) {
|
||||
tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar)
|
||||
}
|
||||
|
||||
const parentPath =
|
||||
item.parentItem?.type === "link"
|
||||
? getLinkPath(item.parentItem)
|
||||
: undefined
|
||||
const firstItemPath =
|
||||
item.default[0].type === "link" ? getLinkPath(item.default[0]) : undefined
|
||||
|
||||
tempBreadcrumbItems.set(
|
||||
parentPath || firstItemPath || "/",
|
||||
item.parentItem?.childSidebarTitle || item.parentItem?.title || ""
|
||||
)
|
||||
|
||||
return tempBreadcrumbItems
|
||||
}
|
||||
|
||||
const breadcrumbItems = useMemo(() => {
|
||||
const tempBreadcrumbItems: Map<string, string> = new Map()
|
||||
if (currentItems) {
|
||||
getBreadcrumbsOfItem(currentItems).forEach((value, key) =>
|
||||
tempBreadcrumbItems.set(key, value)
|
||||
)
|
||||
}
|
||||
|
||||
const activeItem = getActiveItem()
|
||||
if (activeItem) {
|
||||
tempBreadcrumbItems.set(
|
||||
getLinkPath(activeItem) || "/",
|
||||
activeItem?.title || ""
|
||||
)
|
||||
}
|
||||
|
||||
return tempBreadcrumbItems
|
||||
}, [currentItems, getActiveItem])
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex items-center",
|
||||
"text-medusa-fg-muted text-compact-small"
|
||||
)}
|
||||
>
|
||||
{Array.from(breadcrumbItems).map(([link, title]) => (
|
||||
<React.Fragment key={link}>
|
||||
<span>/</span>
|
||||
<Link
|
||||
href={link}
|
||||
className={clsx(
|
||||
"hover:text-medusa-fg-base transition-colors",
|
||||
"px-docs_0.5 py-docs_0.25"
|
||||
)}
|
||||
>
|
||||
{title}
|
||||
</Link>
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { useColorMode } from "../../../providers"
|
||||
import { Button } from "../../.."
|
||||
import { Moon, Sun } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
|
||||
export const MainNavColorMode = () => {
|
||||
const { colorMode, toggleColorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className={clsx("!p-[6.5px] text-medusa-fg-muted")}
|
||||
onClick={toggleColorMode}
|
||||
>
|
||||
{colorMode === "light" && <Sun />}
|
||||
{colorMode === "dark" && <Moon />}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
|
||||
export const MainNavDivider = () => {
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
"h-docs_0.75 w-px block bg-medusa-border-base",
|
||||
"mx-docs_0.5"
|
||||
)}
|
||||
></span>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from "react"
|
||||
import { BorderedIcon } from "@/components"
|
||||
import { IconProps } from "@medusajs/icons/dist/types"
|
||||
|
||||
export type MainNavigationDropdownIconProps = {
|
||||
icon: React.FC<IconProps>
|
||||
inDropdown?: boolean
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownIcon = ({
|
||||
icon,
|
||||
inDropdown = false,
|
||||
}: MainNavigationDropdownIconProps) => {
|
||||
return (
|
||||
<BorderedIcon
|
||||
IconComponent={icon}
|
||||
iconClassName={inDropdown ? "w-docs_1 h-docs_1" : ""}
|
||||
iconWrapperClassName="rounded-docs_xs"
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import Link from "next/link"
|
||||
import clsx from "clsx"
|
||||
import { EllipseMiniSolid } from "@medusajs/icons"
|
||||
import { MainNavigationDropdownIcon } from "../../Icon"
|
||||
import { SidebarSeparator } from "../../../../Sidebar/Separator"
|
||||
|
||||
export type MainNavigationDropdownMenuItemProps = {
|
||||
item: NavigationDropdownItem
|
||||
onSelect: () => void
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownMenuItem = ({
|
||||
item,
|
||||
onSelect,
|
||||
}: MainNavigationDropdownMenuItemProps) => {
|
||||
switch (item.type) {
|
||||
case "divider":
|
||||
return <SidebarSeparator className="my-docs_0.25" />
|
||||
case "link":
|
||||
return (
|
||||
<Link
|
||||
href={item.path}
|
||||
className={clsx(
|
||||
"hover:bg-medusa-bg-component-hover",
|
||||
"block rounded-docs_xs"
|
||||
)}
|
||||
prefetch={false}
|
||||
onClick={onSelect}
|
||||
>
|
||||
<li
|
||||
className={clsx(
|
||||
"px-docs_0.5 py-docs_0.25",
|
||||
"rounded-docs_xs text-medusa-fg-base",
|
||||
"flex gap-docs_0.5 justify-start items-center"
|
||||
)}
|
||||
>
|
||||
<span className={clsx(!item.isActive && "invisible")}>
|
||||
<EllipseMiniSolid />
|
||||
</span>
|
||||
<MainNavigationDropdownIcon icon={item.icon} inDropdown={true} />
|
||||
<span className="whitespace-nowrap">{item.title}</span>
|
||||
</li>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import { MainNavigationDropdownMenuItem } from "./Item"
|
||||
|
||||
export type MainNavigationDropdownMenuProps = {
|
||||
items: NavigationDropdownItem[]
|
||||
open: boolean
|
||||
onSelect: () => void
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownMenu = ({
|
||||
items,
|
||||
open,
|
||||
onSelect,
|
||||
}: MainNavigationDropdownMenuProps) => {
|
||||
return (
|
||||
<ul
|
||||
className={clsx(
|
||||
"absolute top-[calc(100%+4px)] p-docs_0.25 z-50 lg:-left-docs_0.25",
|
||||
"bg-medusa-bg-component rounded shadow-elevation-flyout",
|
||||
!open && "hidden"
|
||||
)}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<MainNavigationDropdownMenuItem
|
||||
item={item}
|
||||
key={index}
|
||||
onSelect={onSelect}
|
||||
/>
|
||||
))}
|
||||
</ul>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { NavigationDropdownItem } from "types"
|
||||
import { TrianglesMini } from "@medusajs/icons"
|
||||
import clsx from "clsx"
|
||||
import { MainNavigationDropdownIcon } from "../Icon"
|
||||
|
||||
export type MainNavigationDropdownSelectedProps = {
|
||||
item: NavigationDropdownItem
|
||||
onClick: () => void
|
||||
}
|
||||
|
||||
export const MainNavigationDropdownSelected = ({
|
||||
item,
|
||||
onClick,
|
||||
}: MainNavigationDropdownSelectedProps) => {
|
||||
if (item.type === "divider") {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex justify-between items-center",
|
||||
"cursor-pointer rounded-docs_sm hover:bg-medusa-bg-hover"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={onClick}
|
||||
>
|
||||
<MainNavigationDropdownIcon icon={item.icon} />
|
||||
<div className="flex gap-[6px] py-docs_0.25 px-docs_0.5 items-center">
|
||||
<span className="text-medusa-fg-base whitespace-nowrap flex-1">
|
||||
{item.title}
|
||||
</span>
|
||||
<TrianglesMini className="text-medusa-fg-muted" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React, { useMemo, useRef, useState } from "react"
|
||||
import { MainNavigationDropdownSelected } from "./Selected"
|
||||
import { MainNavigationDropdownMenu } from "./Menu"
|
||||
import { useClickOutside, useMainNav } from "../../.."
|
||||
|
||||
export const MainNavigationDropdown = () => {
|
||||
const { navItems: items } = useMainNav()
|
||||
const navigationRef = useRef<HTMLDivElement>(null)
|
||||
const [menuOpen, setMenuOpen] = useState(false)
|
||||
useClickOutside({
|
||||
elmRef: navigationRef,
|
||||
onClickOutside: () => {
|
||||
setMenuOpen(false)
|
||||
},
|
||||
})
|
||||
|
||||
const selectedItem = useMemo(() => {
|
||||
const activeItem = items.find(
|
||||
(item) => item.type === "link" && item.isActive
|
||||
)
|
||||
|
||||
if (!activeItem) {
|
||||
return items.length ? items[0] : undefined
|
||||
}
|
||||
|
||||
return activeItem
|
||||
}, [items])
|
||||
return (
|
||||
<div className={clsx("relative z-50")} ref={navigationRef}>
|
||||
{selectedItem && (
|
||||
<MainNavigationDropdownSelected
|
||||
item={selectedItem}
|
||||
onClick={() => setMenuOpen((prev) => !prev)}
|
||||
/>
|
||||
)}
|
||||
<MainNavigationDropdownMenu
|
||||
items={items}
|
||||
open={menuOpen}
|
||||
onSelect={() => setMenuOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { Button, useSidebar } from "../../.."
|
||||
import clsx from "clsx"
|
||||
import { SidebarLeft } from "@medusajs/icons"
|
||||
|
||||
export const MainNavSidebarOpener = () => {
|
||||
const { desktopSidebarOpen, setDesktopSidebarOpen } = useSidebar()
|
||||
|
||||
if (desktopSidebarOpen) {
|
||||
return <></>
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
className={clsx("!p-[6.5px] text-medusa-fg-muted", "mr-docs_0.5")}
|
||||
onClick={() => setDesktopSidebarOpen(true)}
|
||||
>
|
||||
<SidebarLeft />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
38
www/packages/docs-ui/src/components/MainNav/index.tsx
Normal file
38
www/packages/docs-ui/src/components/MainNav/index.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { MainNavigationDropdown } from "./NavigationDropdown"
|
||||
import { MainNavBreadcrumbs } from "./Breadcrumb"
|
||||
import { SearchModalOpener, useMainNav } from "../.."
|
||||
import { MainNavColorMode } from "./ColorMode"
|
||||
import Link from "next/link"
|
||||
import { MainNavDivider } from "./Divider"
|
||||
import { MainNavSidebarOpener } from "./SidebarOpener"
|
||||
|
||||
export const MainNav = () => {
|
||||
const { reportIssueLink } = useMainNav()
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"hidden sm:flex justify-between items-center",
|
||||
"px-docs_1 py-docs_0.75 w-full z-20",
|
||||
"sticky top-0 bg-medusa-bg-base"
|
||||
)}
|
||||
>
|
||||
<div className="flex items-center gap-docs_0.25">
|
||||
<MainNavSidebarOpener />
|
||||
<MainNavigationDropdown />
|
||||
<MainNavBreadcrumbs />
|
||||
</div>
|
||||
<div className="flex items-center gap-docs_0.25">
|
||||
<Link href={reportIssueLink} className="text-medusa-fg-muted">
|
||||
Report Issue
|
||||
</Link>
|
||||
<MainNavDivider />
|
||||
<MainNavColorMode />
|
||||
<SearchModalOpener />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
32
www/packages/docs-ui/src/components/Menu/Action/index.tsx
Normal file
32
www/packages/docs-ui/src/components/Menu/Action/index.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { MenuItemAction } from "types"
|
||||
|
||||
export type MenuActionProps = {
|
||||
item: MenuItemAction
|
||||
}
|
||||
|
||||
export const MenuAction = ({ item }: MenuActionProps) => {
|
||||
return (
|
||||
<span
|
||||
className={clsx(
|
||||
"flex py-docs_0.25 px-docs_0.5",
|
||||
"gap-docs_0.5 rounded-docs_xs",
|
||||
"hover:bg-medusa-bg-component-hover",
|
||||
"text-medusa-fg-base cursor-pointer"
|
||||
)}
|
||||
tabIndex={-1}
|
||||
onClick={item.action}
|
||||
>
|
||||
<span className="text-medusa-fg-subtle">{item.icon}</span>
|
||||
<span className="text-compact-small flex-1">{item.title}</span>
|
||||
{item.shortcut && (
|
||||
<span className="text-medusa-fg-subtle text-compact-small">
|
||||
{item.shortcut}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
|
||||
export const MenuDivider = () => {
|
||||
return <hr className="bg-medusa-border-menu-top mt-[3px] mb-[3px]" />
|
||||
}
|
||||
27
www/packages/docs-ui/src/components/Menu/Item/index.tsx
Normal file
27
www/packages/docs-ui/src/components/Menu/Item/index.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import Link from "next/link"
|
||||
import React from "react"
|
||||
import { MenuItemLink } from "types"
|
||||
|
||||
export type MenuItemProps = {
|
||||
item: MenuItemLink
|
||||
}
|
||||
|
||||
export const MenuItem = ({ item }: MenuItemProps) => {
|
||||
return (
|
||||
<Link
|
||||
className={clsx(
|
||||
"flex py-docs_0.25 px-docs_0.5",
|
||||
"gap-docs_0.5 rounded-docs_xs",
|
||||
"hover:bg-medusa-bg-component-hover",
|
||||
"text-medusa-fg-base"
|
||||
)}
|
||||
href={item.link}
|
||||
>
|
||||
<span className="text-medusa-fg-subtle">{item.icon}</span>
|
||||
<span className="text-compact-small">{item.title}</span>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
31
www/packages/docs-ui/src/components/Menu/index.tsx
Normal file
31
www/packages/docs-ui/src/components/Menu/index.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { MenuItem as MenuItemType } from "types"
|
||||
import { MenuItem } from "./Item"
|
||||
import { MenuDivider } from "./Divider"
|
||||
import { MenuAction } from "./Action"
|
||||
|
||||
export type MenuProps = {
|
||||
items: MenuItemType[]
|
||||
className?: string
|
||||
}
|
||||
|
||||
export const Menu = ({ items, className }: MenuProps) => {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"bg-medusa-bg-component p-docs_0.25 rounded-docs_DEFAULT",
|
||||
"shadow-elevation-flyout dark:shadow-elevation-flyout-dark",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{items.map((item, index) => (
|
||||
<React.Fragment key={index}>
|
||||
{item.type === "link" && <MenuItem item={item} />}
|
||||
{item.type === "action" && <MenuAction item={item} />}
|
||||
{item.type === "divider" && <MenuDivider />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
"use client"
|
||||
|
||||
import clsx from "clsx"
|
||||
import React from "react"
|
||||
import { SidebarLeftIcon } from "../Icons/SidebarLeft"
|
||||
import { Button, SearchModalOpener, useSidebar } from "../.."
|
||||
import { MainNavigationDropdown } from "../MainNav/NavigationDropdown"
|
||||
|
||||
export const MobileNavigation = () => {
|
||||
const { setMobileSidebarOpen } = useSidebar()
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"sm:hidden bg-medusa-bg-base",
|
||||
"sticky top-0 w-full z-50 h-min",
|
||||
"px-docs_0.75 py-docs_0.5",
|
||||
"flex justify-between items-center",
|
||||
"border-b border-medusa-border-base"
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
variant="transparent-clear"
|
||||
onClick={() => setMobileSidebarOpen(true)}
|
||||
>
|
||||
<SidebarLeftIcon />
|
||||
</Button>
|
||||
<MainNavigationDropdown />
|
||||
<SearchModalOpener />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -88,7 +88,7 @@ export const Modal = ({
|
||||
{...props}
|
||||
className={clsx(
|
||||
"fixed top-0 left-0 flex h-screen w-screen items-center justify-center",
|
||||
"bg-medusa-bg-overlay",
|
||||
"bg-medusa-bg-overlay z-50",
|
||||
"hidden open:flex border-0 p-0",
|
||||
className
|
||||
)}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { NavbarIconButton, NavbarIconButtonProps } from "../IconButton"
|
||||
import { useColorMode } from "@/providers"
|
||||
import { Moon, Sun } from "@medusajs/icons"
|
||||
|
||||
export type NavbarColorModeToggleProps = {
|
||||
buttonProps?: NavbarIconButtonProps
|
||||
}
|
||||
|
||||
export const NavbarColorModeToggle = ({
|
||||
buttonProps,
|
||||
}: NavbarColorModeToggleProps) => {
|
||||
const { colorMode, toggleColorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<NavbarIconButton {...buttonProps} onClick={() => toggleColorMode()}>
|
||||
{colorMode === "light" && <Sun className="text-medusa-fg-muted" />}
|
||||
{colorMode === "dark" && <Moon className="text-medusa-fg-muted" />}
|
||||
</NavbarIconButton>
|
||||
)
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
import React from "react"
|
||||
import clsx from "clsx"
|
||||
import { Button, ButtonProps } from "@/components"
|
||||
|
||||
export type NavbarIconButtonProps = ButtonProps
|
||||
|
||||
export const NavbarIconButton = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}: NavbarIconButtonProps) => {
|
||||
return (
|
||||
<Button
|
||||
className={clsx(
|
||||
"[&>svg]:h-[22px] [&>svg]:w-[22px] btn-secondary-icon",
|
||||
className
|
||||
)}
|
||||
variant="secondary"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import clsx from "clsx"
|
||||
import { Badge, BadgeProps, Link, LinkProps } from "@/components"
|
||||
|
||||
export type NavbarLinkProps = {
|
||||
href: string
|
||||
label: string
|
||||
className?: string
|
||||
activeValuePattern?: RegExp
|
||||
isActive?: boolean
|
||||
badge?: BadgeProps
|
||||
} & LinkProps
|
||||
|
||||
export const NavbarLink = ({
|
||||
href,
|
||||
label,
|
||||
className,
|
||||
isActive,
|
||||
badge,
|
||||
}: NavbarLinkProps) => {
|
||||
return (
|
||||
<Link
|
||||
href={href}
|
||||
className={clsx(
|
||||
isActive && "!text-medusa-fg-base",
|
||||
!isActive && "!text-medusa-fg-subtle",
|
||||
"text-compact-small-plus inline-block",
|
||||
"hover:!text-medusa-fg-base",
|
||||
className
|
||||
)}
|
||||
>
|
||||
{label}
|
||||
{badge && (
|
||||
<Badge {...badge} className={clsx(badge.className, "ml-docs_0.5")} />
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import { useColorMode } from "@/providers"
|
||||
import Link from "next/link"
|
||||
import clsx from "clsx"
|
||||
import Image from "next/image"
|
||||
|
||||
export type NavbarLogoProps = {
|
||||
light: string
|
||||
dark?: string
|
||||
className?: string
|
||||
imageClassName?: string
|
||||
}
|
||||
|
||||
export const NavbarLogo = ({
|
||||
light,
|
||||
dark,
|
||||
className,
|
||||
imageClassName,
|
||||
}: NavbarLogoProps) => {
|
||||
const { colorMode } = useColorMode()
|
||||
|
||||
return (
|
||||
<Link href={`/`} className={clsx("flex-1", className)}>
|
||||
<Image
|
||||
src={colorMode === "light" ? light : dark || light}
|
||||
alt="Medusa Logo"
|
||||
height={20}
|
||||
width={20}
|
||||
className={clsx("align-middle", imageClassName)}
|
||||
/>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user