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:
Shahed Nasser authored and GitHub committed 2024-08-15 12:13:13 +03:00
1 parent 4cb28531e5
commit b4f3b8a79d
157 files changed
+4944 -1874

No files matched your search

+1 -1
View File
@@ -15,7 +15,7 @@ const ReferencePage = async () => {
</h1> </h1>
<DividedLayout <DividedLayout
mainContent={ mainContent={
<Section> <Section checkActiveOnScroll={true}>
<h1 className="!text-h2 hidden lg:block"> <h1 className="!text-h2 hidden lg:block">
Medusa V2 Admin API Reference Medusa V2 Admin API Reference
</h1> </h1>
+5 -2
View File
@@ -1,5 +1,4 @@
import "./globals.css" import "./globals.css"
import Navbar from "@/components/Navbar"
import Providers from "../providers" import Providers from "../providers"
import { WideLayout } from "docs-ui" import { WideLayout } from "docs-ui"
import { Inter, Roboto_Mono } from "next/font/google" import { Inter, Roboto_Mono } from "next/font/google"
@@ -29,8 +28,12 @@ export default function RootLayout({
return ( return (
<WideLayout <WideLayout
ProvidersComponent={Providers} ProvidersComponent={Providers}
NavbarComponent={Navbar} sidebarProps={{
expandItems: false,
}}
bodyClassName={clsx(inter.variable, robotoMono.variable)} bodyClassName={clsx(inter.variable, robotoMono.variable)}
showToc={false}
showBanner={false}
> >
{children} {children}
</WideLayout> </WideLayout>
+1 -1
View File
@@ -15,7 +15,7 @@ const ReferencePage = async () => {
</h1> </h1>
<DividedLayout <DividedLayout
mainContent={ mainContent={
<Section> <Section checkActiveOnScroll={true}>
<h1 className="!text-h2 hidden lg:block"> <h1 className="!text-h2 hidden lg:block">
Medusa V2 Store API Reference Medusa V2 Store API Reference
</h1> </h1>
@@ -1,73 +1,47 @@
"use client" "use client"
import { InView } from "react-intersection-observer" import { useScrollController, useSidebar } from "docs-ui"
import { isElmWindow, useScrollController, useSidebar } from "docs-ui" import { useEffect, useMemo, useRef, useState } from "react"
import checkElementInViewport from "../../../utils/check-element-in-viewport"
import { useEffect, useMemo } from "react"
import getSectionId from "../../../utils/get-section-id" import getSectionId from "../../../utils/get-section-id"
type H2Props = { type H2Props = React.HTMLAttributes<HTMLHeadingElement>
addToSidebar?: boolean
} & React.HTMLAttributes<HTMLHeadingElement>
const H2 = ({ addToSidebar = true, children, ...props }: H2Props) => { const H2 = ({ children, ...props }: H2Props) => {
const { activePath, setActivePath, addItems } = useSidebar() const headingRef = useRef<HTMLHeadingElement>(null)
const { getScrolledTop, scrollableElement } = useScrollController() const { activePath, addItems } = useSidebar()
const { scrollableElement, scrollToElement } = useScrollController()
const [scrolledFirstTime, setScrolledFirstTime] = useState(false)
const handleViewChange = ( const id = useMemo(() => getSectionId([children as string]), [children])
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])
useEffect(() => { useEffect(() => {
if (id === (activePath || location.hash.replace("#", ""))) { if (!scrollableElement || !headingRef.current || scrolledFirstTime) {
const elm = document.getElementById(id) return
elm?.scrollIntoView()
} }
if (id === (activePath || location.hash.replace("#", ""))) {
scrollToElement(
(headingRef.current.offsetParent as HTMLElement) || headingRef.current
)
}
setScrolledFirstTime(scrolledFirstTime)
}, [scrollableElement, headingRef, id])
useEffect(() => {
addItems([ addItems([
{ {
type: "link",
path: `${id}`, path: `${id}`,
title: children as string, title: children as string,
loaded: true, loaded: true,
}, },
]) ])
}, []) }, [id])
const root = useMemo(() => {
return isElmWindow(scrollableElement) ? document.body : scrollableElement
}, [scrollableElement])
return ( return (
<InView <h2 {...props} id={id} ref={headingRef}>
as="h2"
threshold={0.4}
skip={!addToSidebar}
initialInView={false}
{...props}
onChange={handleViewChange}
id={id}
root={root}
>
{children} {children}
</InView> </h2>
) )
} }
@@ -14,9 +14,7 @@ const getCustomComponents = (scope?: ScopeType): MDXComponents => {
...UiMDXComponents, ...UiMDXComponents,
Security: () => <Security specs={scope?.specs} />, Security: () => <Security specs={scope?.specs} />,
a: Link, a: Link,
h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => ( h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => <H2 {...props} />,
<H2 addToSidebar={scope?.addToSidebar} {...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" "use client"
import clsx from "clsx" import clsx from "clsx"
import { useActiveOnScroll, useSidebar } from "docs-ui"
import { useEffect, useRef } from "react" import { useEffect, useRef } from "react"
export type SectionProps = { export type SectionProps = {
addToSidebar?: boolean checkActiveOnScroll?: boolean
} & React.AllHTMLAttributes<HTMLDivElement> } & React.AllHTMLAttributes<HTMLDivElement>
const Section = ({ children, className }: SectionProps) => { const Section = ({
children,
className,
checkActiveOnScroll = false,
}: SectionProps) => {
const sectionRef = useRef<HTMLDivElement>(null) const sectionRef = useRef<HTMLDivElement>(null)
const { activeItemId } = useActiveOnScroll({
rootElm: sectionRef.current || undefined,
enable: checkActiveOnScroll,
useDefaultIfNoActive: false,
})
const { setActivePath } = useSidebar()
useEffect(() => { useEffect(() => {
if ("scrollRestoration" in history) { if ("scrollRestoration" in history) {
@@ -17,6 +28,13 @@ const Section = ({ children, className }: SectionProps) => {
} }
}, []) }, [])
useEffect(() => {
if (activeItemId.length) {
history.pushState({}, "", `#${activeItemId}`)
setActivePath(activeItemId)
}
}, [activeItemId])
return ( return (
<div <div
ref={sectionRef} ref={sectionRef}
@@ -13,6 +13,7 @@ import TagsOperationDescriptionSection from "./DescriptionSection"
import DividedLayout from "@/layouts/Divided" import DividedLayout from "@/layouts/Divided"
import { useLoading } from "@/providers/loading" import { useLoading } from "@/providers/loading"
import SectionDivider from "../../Section/Divider" import SectionDivider from "../../Section/Divider"
import checkElementInViewport from "../../../utils/check-element-in-viewport"
const TagOperationCodeSection = dynamic<TagOperationCodeSectionProps>( const TagOperationCodeSection = dynamic<TagOperationCodeSectionProps>(
async () => import("./CodeSection") async () => import("./CodeSection")
@@ -40,7 +41,7 @@ const TagOperation = ({
) )
const nodeRef = useRef<Element | null>(null) const nodeRef = useRef<Element | null>(null)
const { loading, removeLoading } = useLoading() const { loading, removeLoading } = useLoading()
const { scrollableElement } = useScrollController() const { scrollableElement, scrollToTop } = useScrollController()
const root = useMemo(() => { const root = useMemo(() => {
return isElmWindow(scrollableElement) ? document.body : scrollableElement return isElmWindow(scrollableElement) ? document.body : scrollableElement
}, [scrollableElement]) }, [scrollableElement])
@@ -75,24 +76,28 @@ const TagOperation = ({
[ref] [ref]
) )
useEffect(() => { const scrollIntoView = useCallback(() => {
const enableShow = () => { if (nodeRef.current && !checkElementInViewport(nodeRef.current, 10)) {
setShow(true) const elm = nodeRef.current as HTMLElement
scrollToTop(
elm.offsetTop + (elm.offsetParent as HTMLElement)?.offsetTop,
0
)
} }
setShow(true)
}, [scrollToTop, nodeRef])
useEffect(() => {
if (nodeRef && nodeRef.current) { if (nodeRef && nodeRef.current) {
removeLoading() removeLoading()
const currentHash = location.hash.replace("#", "") const currentHash = location.hash.replace("#", "")
if (currentHash === path) { if (currentHash === path) {
setTimeout(() => { setTimeout(scrollIntoView, 100)
nodeRef.current?.scrollIntoView()
enableShow()
}, 100)
} else if (currentHash.split("_")[0] === path.split("_")[0]) { } else if (currentHash.split("_")[0] === path.split("_")[0]) {
enableShow() setShow(true)
} }
} }
}, [nodeRef, path]) }, [nodeRef, path, scrollIntoView])
return ( return (
<div <div
@@ -14,7 +14,7 @@ import { useBaseSpecs } from "@/providers/base-specs"
import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items" import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items"
import { useLoading } from "@/providers/loading" import { useLoading } from "@/providers/loading"
import DividedLoading from "@/components/DividedLoading" import DividedLoading from "@/components/DividedLoading"
import { SidebarItemSections, SidebarItemType } from "types" import { SidebarItemSections, SidebarItem, SidebarItemCategory } from "types"
import basePathUrl from "../../../utils/base-path-url" import basePathUrl from "../../../utils/base-path-url"
const TagOperation = dynamic<TagOperationProps>( const TagOperation = dynamic<TagOperationProps>(
@@ -56,16 +56,17 @@ const TagPaths = ({ tag, className }: TagPathsProps) => {
useEffect(() => { useEffect(() => {
if (paths) { if (paths) {
const parentItem = findItemInSection( const parentItem = findItemInSection(
items[SidebarItemSections.BOTTOM], items[SidebarItemSections.DEFAULT],
{ path: tagSlugName }, { title: tag.name },
false false
) ) as SidebarItemCategory
const pathItems: SidebarItemType[] = getTagChildSidebarItems(paths) const pathItems: SidebarItem[] = getTagChildSidebarItems(paths)
if ((parentItem?.children?.length || 0) < pathItems.length) { if ((parentItem?.children?.length || 0) < pathItems.length) {
addItems(pathItems, { addItems(pathItems, {
section: SidebarItemSections.BOTTOM, section: SidebarItemSections.DEFAULT,
parent: { parent: {
path: tagSlugName, title: tag.name,
path: "",
changeLoaded: true, changeLoaded: true,
}, },
}) })
@@ -40,7 +40,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
}, },
}) })
const { scrollableElement } = useScrollController() const { scrollableElement, scrollToElement } = useScrollController()
const root = useMemo(() => { const root = useMemo(() => {
return isElmWindow(scrollableElement) ? document.body : scrollableElement return isElmWindow(scrollableElement) ? document.body : scrollableElement
}, [scrollableElement]) }, [scrollableElement])
@@ -49,6 +49,7 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
addItems( addItems(
[ [
{ {
type: "link",
path: schemaSlug, path: schemaSlug,
title: `${formattedName} Object`, title: `${formattedName} Object`,
additionalElms: <Badge variant="neutral">Schema</Badge>, additionalElms: <Badge variant="neutral">Schema</Badge>,
@@ -56,8 +57,9 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
}, },
], ],
{ {
section: SidebarItemSections.BOTTOM, section: SidebarItemSections.DEFAULT,
parent: { parent: {
title: tagName,
path: tagSlugName, path: tagSlugName,
changeLoaded: true, changeLoaded: true,
}, },
@@ -69,12 +71,12 @@ const TagSectionSchema = ({ schema, tagName }: TagSectionSchemaProps) => {
useEffect(() => { useEffect(() => {
if (schemaSlug === (activePath || location.hash.replace("#", ""))) { if (schemaSlug === (activePath || location.hash.replace("#", ""))) {
const elm = document.getElementById(schemaSlug) const elm = document.getElementById(schemaSlug) as HTMLElement
elm?.scrollIntoView({ if (!checkElementInViewport(elm, 40)) {
block: "center", scrollToElement(elm)
})
} }
}, []) }
}, [activePath, schemaSlug])
const handleViewChange = ( const handleViewChange = (
inView: boolean, inView: boolean,
@@ -26,6 +26,7 @@ import { SchemaObject, TagObject } from "@/types/openapi"
import useSWR from "swr" import useSWR from "swr"
import { TagSectionSchemaProps } from "./Schema" import { TagSectionSchemaProps } from "./Schema"
import basePathUrl from "../../../utils/base-path-url" import basePathUrl from "../../../utils/base-path-url"
import checkElementInViewport from "../../../utils/check-element-in-viewport"
export type TagSectionProps = { export type TagSectionProps = {
tag: TagObject tag: TagObject
@@ -52,7 +53,7 @@ const TagSection = ({ tag }: TagSectionProps) => {
const slugTagName = useMemo(() => getSectionId([tag.name]), [tag]) const slugTagName = useMemo(() => getSectionId([tag.name]), [tag])
const { area } = useArea() const { area } = useArea()
const pathname = usePathname() const pathname = usePathname()
const { scrollableElement } = useScrollController() const { scrollableElement, scrollToElement } = useScrollController()
const { data } = useSWR<{ const { data } = useSWR<{
schema: SchemaObject schema: SchemaObject
}>( }>(
@@ -96,8 +97,10 @@ const TagSection = ({ tag }: TagSectionProps) => {
if (activePath && activePath.includes(slugTagName)) { if (activePath && activePath.includes(slugTagName)) {
const tagName = activePath.split("_") const tagName = activePath.split("_")
if (tagName.length === 1 && tagName[0] === slugTagName) { if (tagName.length === 1 && tagName[0] === slugTagName) {
const elm = document.getElementById(tagName[0]) as Element const elm = document.getElementById(tagName[0])
elm?.scrollIntoView() if (elm && !checkElementInViewport(elm, 10)) {
scrollToElement(elm)
}
} else if (tagName.length > 1 && tagName[0] === slugTagName) { } else if (tagName.length > 1 && tagName[0] === slugTagName) {
setLoadPaths(true) setLoadPaths(true)
} }
@@ -11,7 +11,7 @@ import { swrFetcher, useSidebar } from "docs-ui"
import getSectionId from "@/utils/get-section-id" import getSectionId from "@/utils/get-section-id"
import { ExpandedDocument } from "@/types/openapi" import { ExpandedDocument } from "@/types/openapi"
import getTagChildSidebarItems from "@/utils/get-tag-child-sidebar-items" 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" import basePathUrl from "../../utils/base-path-url"
const TagSection = dynamic<TagSectionProps>( const TagSection = dynamic<TagSectionProps>(
@@ -31,7 +31,7 @@ const Tags = () => {
const [loadData, setLoadData] = useState<boolean>(false) const [loadData, setLoadData] = useState<boolean>(false)
const [expand, setExpand] = useState<string>("") const [expand, setExpand] = useState<string>("")
const { baseSpecs, setBaseSpecs } = useBaseSpecs() const { baseSpecs, setBaseSpecs } = useBaseSpecs()
const { addItems } = useSidebar() const { addItems, setActivePath } = useSidebar()
const { area, prevArea } = useArea() const { area, prevArea } = useArea()
const { data } = useSWR<ExpandedDocument>( const { data } = useSWR<ExpandedDocument>(
@@ -65,30 +65,42 @@ const Tags = () => {
if (baseSpecs) { if (baseSpecs) {
if (prevArea !== area) { if (prevArea !== area) {
setBaseSpecs(null) setBaseSpecs(null)
setLoadData(true)
return return
} }
addItems( const itemsToAdd: SidebarItem[] = [
baseSpecs.tags?.map((tag) => { {
type: "separator",
},
]
if (baseSpecs.tags) {
baseSpecs.tags.forEach((tag) => {
const tagPathName = getSectionId([tag.name.toLowerCase()]) const tagPathName = getSectionId([tag.name.toLowerCase()])
const childItems = const childItems =
baseSpecs.expandedTags && baseSpecs.expandedTags &&
Object.hasOwn(baseSpecs.expandedTags, tagPathName) Object.hasOwn(baseSpecs.expandedTags, tagPathName)
? getTagChildSidebarItems(baseSpecs.expandedTags[tagPathName]) ? getTagChildSidebarItems(baseSpecs.expandedTags[tagPathName])
: [] : []
return { itemsToAdd.push({
path: tagPathName, type: "category",
title: tag.name, title: tag.name,
children: childItems, children: childItems,
loaded: childItems.length > 0, loaded: childItems.length > 0,
onOpen: () => {
history.pushState({}, "", `#${tagPathName}`)
setActivePath(tagPathName)
},
})
})
} }
}) || [],
{ addItems(itemsToAdd, {
section: SidebarItemSections.BOTTOM, section: SidebarItemSections.DEFAULT,
})
} }
) }, [baseSpecs, prevArea, area])
}
}, [baseSpecs, addItems])
return ( return (
<> <>
+2 -2
View File
@@ -8,14 +8,14 @@ export const config: DocsConfig = {
basePath: process.env.NEXT_PUBLIC_BASE_PATH, basePath: process.env.NEXT_PUBLIC_BASE_PATH,
// sidebar is auto generated // sidebar is auto generated
sidebar: { sidebar: {
top: [ default: [
{ {
type: "link",
title: "Introduction", title: "Introduction",
path: "", path: "",
loaded: true, loaded: true,
}, },
], ],
bottom: [],
mobile: getMobileSidebarItems({ mobile: getMobileSidebarItems({
baseUrl, baseUrl,
version: "v2", version: "v2",
@@ -13,6 +13,7 @@ import BaseSpecsProvider from "./base-specs"
import SidebarProvider from "./sidebar" import SidebarProvider from "./sidebar"
import SearchProvider from "./search" import SearchProvider from "./search"
import { config } from "../config" import { config } from "../config"
import { MainNavProvider } from "./main-nav"
type ProvidersProps = { type ProvidersProps = {
children?: React.ReactNode children?: React.ReactNode
@@ -28,9 +29,11 @@ const Providers = ({ children }: ProvidersProps) => {
<BaseSpecsProvider> <BaseSpecsProvider>
<ScrollControllerProvider scrollableSelector="#main"> <ScrollControllerProvider scrollableSelector="#main">
<SidebarProvider> <SidebarProvider>
<MainNavProvider>
<SearchProvider> <SearchProvider>
<MobileProvider>{children}</MobileProvider> <MobileProvider>{children}</MobileProvider>
</SearchProvider> </SearchProvider>
</MainNavProvider>
</SidebarProvider> </SidebarProvider>
</ScrollControllerProvider> </ScrollControllerProvider>
</BaseSpecsProvider> </BaseSpecsProvider>
@@ -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 { createContext, useEffect } from "react"
import { capitalize, useSidebar } from "docs-ui" import { capitalize, useSidebar } from "docs-ui"
import { useArea } from "./area" import { useArea } from "./area"
import { SidebarItemLink } from "types"
const PageTitleContext = createContext(null) const PageTitleContext = createContext(null)
@@ -25,7 +26,9 @@ const PageTitleProvider = ({ children }: PageTitleProviderProps) => {
document.title = `${activeItem?.title} - ${titleSuffix}` document.title = `${activeItem?.title} - ${titleSuffix}`
} else { } else {
// find the child that matches the active path // 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) { if (item) {
document.title = `${item.title} - ${titleSuffix}` document.title = `${item.title} - ${titleSuffix}`
} }
+5 -4
View File
@@ -1,4 +1,5 @@
"use client" "use client"
import { import {
SidebarProvider as UiSidebarProvider, SidebarProvider as UiSidebarProvider,
usePageLoading, usePageLoading,
@@ -6,8 +7,8 @@ import {
useScrollController, useScrollController,
} from "docs-ui" } from "docs-ui"
import { config } from "../config" import { config } from "../config"
import { usePathname } from "next/navigation"
import { useCallback } from "react" import { useCallback } from "react"
import { usePathname } from "next/navigation"
type SidebarProviderProps = { type SidebarProviderProps = {
children?: React.ReactNode children?: React.ReactNode
@@ -17,11 +18,11 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
const { isLoading, setIsLoading } = usePageLoading() const { isLoading, setIsLoading } = usePageLoading()
const { scrollableElement } = useScrollController() const { scrollableElement } = useScrollController()
const pathname = usePathname() const pathname = usePathname()
const prevPathname = usePrevious(pathname) const prevPathName = usePrevious(pathname)
const resetOnCondition = useCallback( const resetOnCondition = useCallback(
() => prevPathname !== undefined && prevPathname !== pathname, () => prevPathName !== undefined && pathname !== prevPathName,
[pathname, prevPathname] [pathname, prevPathName]
) )
return ( return (
@@ -1,5 +1,5 @@
import { getLinkWithBasePath } from "docs-ui" 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) return getLinkWithBasePath(path, process.env.NEXT_PUBLIC_BASE_PATH)
} }
@@ -4,7 +4,7 @@ export default function checkElementInViewport(
height?: number height?: number
) { ) {
const rect = element.getBoundingClientRect() const rect = element.getBoundingClientRect()
const windowHeight = const windowHeight: number | undefined =
height || window.innerHeight || document.documentElement.clientHeight height || window.innerHeight || document.documentElement.clientHeight
return !( return !(
@@ -1,4 +1,4 @@
import type { SidebarItemType } from "types" import type { SidebarItem } from "types"
import type { Operation, PathsObject } from "@/types/openapi" import type { Operation, PathsObject } from "@/types/openapi"
import type { OpenAPIV3 } from "openapi-types" import type { OpenAPIV3 } from "openapi-types"
import dynamic from "next/dynamic" import dynamic from "next/dynamic"
@@ -11,13 +11,14 @@ const MethodLabel = dynamic<MethodLabelProps>(
export default function getTagChildSidebarItems( export default function getTagChildSidebarItems(
paths: PathsObject paths: PathsObject
): SidebarItemType[] { ): SidebarItem[] {
const items: SidebarItemType[] = [] const items: SidebarItem[] = []
Object.entries(paths).forEach(([, operations]) => { Object.entries(paths).forEach(([, operations]) => {
Object.entries(operations).map(([method, operation]) => { Object.entries(operations).map(([method, operation]) => {
const definedOperation = operation as Operation const definedOperation = operation as Operation
const definedMethod = method as OpenAPIV3.HttpMethods const definedMethod = method as OpenAPIV3.HttpMethods
items.push({ items.push({
type: "link",
path: getSectionId([ path: getSectionId([
...(definedOperation.tags || []), ...(definedOperation.tags || []),
definedOperation.operationId, definedOperation.operationId,
+1 -5
View File
@@ -1,10 +1,8 @@
import type { Metadata } from "next" import type { Metadata } from "next"
import { Inter, Roboto_Mono } from "next/font/google" import { Inter, Roboto_Mono } from "next/font/google"
import Navbar from "@/components/Navbar"
import Providers from "@/providers" import Providers from "@/providers"
import "./globals.css" import "./globals.css"
import { Bannerv2, TightLayout } from "docs-ui" import { TightLayout } from "docs-ui"
import { config } from "@/config" import { config } from "@/config"
import clsx from "clsx" import clsx from "clsx"
import Feedback from "@/components/Feedback" import Feedback from "@/components/Feedback"
@@ -40,10 +38,8 @@ export default function RootLayout({
return ( return (
<TightLayout <TightLayout
ProvidersComponent={Providers} ProvidersComponent={Providers}
NavbarComponent={Navbar}
sidebarProps={{ sidebarProps={{
expandItems: true, expandItems: true,
banner: <Bannerv2 />,
}} }}
showPagination={true} showPagination={true}
bodyClassName={clsx(inter.variable, robotoMono.variable)} bodyClassName={clsx(inter.variable, robotoMono.variable)}
-39
View File
@@ -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
+7 -5
View File
@@ -1,17 +1,20 @@
import { Badge, getMobileSidebarItems } from "docs-ui" import { Badge, getMobileSidebarItems } from "docs-ui"
import type { SidebarConfig, SidebarItemType } from "@/types" import type { SidebarConfig, SidebarItem } from "@/types"
import { sidebar } from "../sidebar.mjs" import { sidebar } from "../sidebar.mjs"
const soonBadge = <Badge variant="blue">Soon</Badge> const soonBadge = <Badge variant="blue">Soon</Badge>
const normalizeSidebarItems = (items: SidebarItemType[]) => const normalizeSidebarItems = (items: SidebarItem[]) =>
items.map((item) => { items.map((item) => {
if (item.type === "separator") {
return item
}
if (item.isSoon) { if (item.isSoon) {
item.additionalElms = soonBadge item.additionalElms = soonBadge
} }
if (item.children) { if (item.children) {
item.children = normalizeSidebarItems(item.children as SidebarItemType[]) item.children = normalizeSidebarItems(item.children as SidebarItem[])
} }
return item return item
@@ -19,8 +22,7 @@ const normalizeSidebarItems = (items: SidebarItemType[]) =>
export const sidebarConfig = (baseUrl: string): SidebarConfig => { export const sidebarConfig = (baseUrl: string): SidebarConfig => {
return { return {
top: normalizeSidebarItems(sidebar), default: normalizeSidebarItems(sidebar),
bottom: [],
mobile: getMobileSidebarItems({ mobile: getMobileSidebarItems({
baseUrl, baseUrl,
version: "v2", version: "v2",
+3
View File
@@ -16,6 +16,7 @@ import {
import SidebarProvider from "./sidebar" import SidebarProvider from "./sidebar"
import SearchProvider from "./search" import SearchProvider from "./search"
import { config } from "../config" import { config } from "../config"
import { MainNavProvider } from "./main-nav"
type ProvidersProps = { type ProvidersProps = {
children?: React.ReactNode children?: React.ReactNode
@@ -33,6 +34,7 @@ const Providers = ({ children }: ProvidersProps) => {
<ScrollControllerProvider scrollableSelector="#main"> <ScrollControllerProvider scrollableSelector="#main">
<SidebarProvider> <SidebarProvider>
<PaginationProvider> <PaginationProvider>
<MainNavProvider>
<SearchProvider> <SearchProvider>
<HooksLoader <HooksLoader
options={{ options={{
@@ -43,6 +45,7 @@ const Providers = ({ children }: ProvidersProps) => {
{children} {children}
</HooksLoader> </HooksLoader>
</SearchProvider> </SearchProvider>
</MainNavProvider>
</PaginationProvider> </PaginationProvider>
</SidebarProvider> </SidebarProvider>
</ScrollControllerProvider> </ScrollControllerProvider>
+46
View 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 -1
View File
@@ -1,4 +1,5 @@
"use client" "use client"
import { import {
SidebarProvider as UiSidebarProvider, SidebarProvider as UiSidebarProvider,
useScrollController, useScrollController,
@@ -20,7 +21,6 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
initialItems={config.sidebar} initialItems={config.sidebar}
staticSidebarItems={true} staticSidebarItems={true}
disableActiveTransition={true} disableActiveTransition={true}
noTitleStyling={true}
> >
{children} {children}
</UiSidebarProvider> </UiSidebarProvider>
+75 -3
View File
@@ -1,183 +1,226 @@
import numberSidebarItems from "./utils/number-sidebar-items.mjs" import numberSidebarItems from "./utils/number-sidebar-items.mjs"
import { sidebarAttachHrefCommonOptions } from "./utils/sidebar-attach-common-options.mjs" import { sidebarAttachHrefCommonOptions } from "./utils/sidebar-attach-common-options.mjs"
/** @type {import('@/types').SidebarItemType[]} */ /** @type {import('@/types').SidebarItem[]} */
export const sidebar = sidebarAttachHrefCommonOptions( export const sidebar = numberSidebarItems(
numberSidebarItems([ sidebarAttachHrefCommonOptions([
{ {
type: "link",
path: "/", path: "/",
title: "Introduction", title: "Introduction",
}, },
{ {
type: "link",
path: "/first-customizations", path: "/first-customizations",
title: "Your First Customizations", title: "Your First Customizations",
}, },
{ {
type: "link",
path: "/basics", path: "/basics",
title: "The Basics", title: "The Basics",
children: [ children: [
{ {
type: "link",
path: "/basics/project-directories-files", path: "/basics/project-directories-files",
title: "Project Directories and Files", title: "Project Directories and Files",
}, },
{ {
type: "link",
path: "/basics/medusa-container", path: "/basics/medusa-container",
title: "Medusa Container", title: "Medusa Container",
}, },
{ {
type: "link",
path: "/basics/api-routes", path: "/basics/api-routes",
title: "API Routes", title: "API Routes",
}, },
{ {
type: "link",
path: "/basics/modules-and-services", path: "/basics/modules-and-services",
title: "Modules and Services", title: "Modules and Services",
}, },
{ {
type: "link",
path: "/basics/commerce-modules", path: "/basics/commerce-modules",
title: "Commerce Modules", title: "Commerce Modules",
}, },
{ {
type: "link",
path: "/basics/modules-directory-structure", path: "/basics/modules-directory-structure",
title: "Modules Directory Structure", title: "Modules Directory Structure",
}, },
{ {
type: "link",
path: "/basics/data-models", path: "/basics/data-models",
title: "Data Models", title: "Data Models",
}, },
{ {
type: "link",
path: "/basics/loaders", path: "/basics/loaders",
title: "Loaders", title: "Loaders",
}, },
{ {
type: "link",
path: "/basics/events-and-subscribers", path: "/basics/events-and-subscribers",
title: "Events and Subscribers", title: "Events and Subscribers",
}, },
{ {
type: "link",
path: "/basics/scheduled-jobs", path: "/basics/scheduled-jobs",
title: "Scheduled Jobs", title: "Scheduled Jobs",
}, },
{ {
type: "link",
path: "/basics/workflows", path: "/basics/workflows",
title: "Workflows", title: "Workflows",
}, },
{ {
type: "link",
path: "/basics/admin-customizations", path: "/basics/admin-customizations",
title: "Admin Customizations", title: "Admin Customizations",
}, },
], ],
}, },
{ {
type: "link",
path: "/advanced-development", path: "/advanced-development",
title: "Advanced Development", title: "Advanced Development",
children: [ children: [
{ {
type: "sub-category",
title: "API Routes", title: "API Routes",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/api-routes/http-methods", path: "/advanced-development/api-routes/http-methods",
title: "HTTP Methods", title: "HTTP Methods",
}, },
{ {
type: "link",
path: "/advanced-development/api-routes/parameters", path: "/advanced-development/api-routes/parameters",
title: "Parameters", title: "Parameters",
}, },
{ {
type: "link",
path: "/advanced-development/api-routes/middlewares", path: "/advanced-development/api-routes/middlewares",
title: "Middlewares", title: "Middlewares",
}, },
{ {
type: "link",
path: "/advanced-development/api-routes/protected-routes", path: "/advanced-development/api-routes/protected-routes",
title: "Protected Routes", title: "Protected Routes",
}, },
{ {
type: "link",
path: "/advanced-development/api-routes/cors", path: "/advanced-development/api-routes/cors",
title: "Handling CORS", title: "Handling CORS",
}, },
], ],
}, },
{ {
type: "sub-category",
title: "Modules", title: "Modules",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/modules/container", path: "/advanced-development/modules/container",
title: "Module's Container", title: "Module's Container",
}, },
{ {
type: "link",
path: "/advanced-development/modules/service-factory", path: "/advanced-development/modules/service-factory",
title: "Service Factory", title: "Service Factory",
}, },
{ {
type: "link",
path: "/advanced-development/modules/isolation", path: "/advanced-development/modules/isolation",
title: "Module Isolation", title: "Module Isolation",
}, },
{ {
type: "link",
path: "/advanced-development/modules/module-links", path: "/advanced-development/modules/module-links",
title: "Module Links", title: "Module Links",
}, },
{ {
type: "link",
path: "/advanced-development/modules/module-link-directions", path: "/advanced-development/modules/module-link-directions",
title: "Module Link Direction", title: "Module Link Direction",
}, },
{ {
type: "link",
path: "/advanced-development/modules/remote-link", path: "/advanced-development/modules/remote-link",
title: "Remote Link", title: "Remote Link",
}, },
{ {
type: "link",
path: "/advanced-development/modules/remote-query", path: "/advanced-development/modules/remote-query",
title: "Remote Query", title: "Remote Query",
}, },
{ {
type: "link",
path: "/advanced-development/modules/options", path: "/advanced-development/modules/options",
title: "Module Options", title: "Module Options",
}, },
], ],
}, },
{ {
type: "link",
path: "/advanced-development/data-models", path: "/advanced-development/data-models",
title: "Data Models", title: "Data Models",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/data-models/property-types", path: "/advanced-development/data-models/property-types",
title: "Property Types", title: "Property Types",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/primary-key", path: "/advanced-development/data-models/primary-key",
title: "Primary Key", title: "Primary Key",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/default-properties", path: "/advanced-development/data-models/default-properties",
title: "Default Properties", title: "Default Properties",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/configure-properties", path: "/advanced-development/data-models/configure-properties",
title: "Configure Properties", title: "Configure Properties",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/relationships", path: "/advanced-development/data-models/relationships",
title: "Relationships", title: "Relationships",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/manage-relationships", path: "/advanced-development/data-models/manage-relationships",
title: "Manage Relationships", title: "Manage Relationships",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/index", path: "/advanced-development/data-models/index",
title: "Index", title: "Index",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/searchable-property", path: "/advanced-development/data-models/searchable-property",
title: "Searchable Property", title: "Searchable Property",
}, },
{ {
type: "link",
path: "/advanced-development/data-models/write-migration", path: "/advanced-development/data-models/write-migration",
title: "Write Migration", title: "Write Migration",
}, },
], ],
}, },
{ {
type: "sub-category",
title: "Events and Subscribers", title: "Events and Subscribers",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/events-and-subscribers/data-payload", path: "/advanced-development/events-and-subscribers/data-payload",
title: "Events Data Payload", title: "Events Data Payload",
}, },
@@ -188,84 +231,104 @@ export const sidebar = sidebarAttachHrefCommonOptions(
], ],
}, },
{ {
type: "sub-category",
title: "Scheduled Jobs", title: "Scheduled Jobs",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/scheduled-jobs/execution-number", path: "/advanced-development/scheduled-jobs/execution-number",
title: "Execution Number", title: "Execution Number",
}, },
], ],
}, },
{ {
type: "sub-category",
title: "Workflows", title: "Workflows",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/workflows/constructor-constraints", path: "/advanced-development/workflows/constructor-constraints",
title: "Workflow Constraints", title: "Workflow Constraints",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/conditions", path: "/advanced-development/workflows/conditions",
title: "Conditions in Workflows", title: "Conditions in Workflows",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/compensation-function", path: "/advanced-development/workflows/compensation-function",
title: "Compensation Function", title: "Compensation Function",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/workflow-hooks", path: "/advanced-development/workflows/workflow-hooks",
title: "Workflow Hooks", title: "Workflow Hooks",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/add-workflow-hook", path: "/advanced-development/workflows/add-workflow-hook",
title: "Expose a Hook", title: "Expose a Hook",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/access-workflow-errors", path: "/advanced-development/workflows/access-workflow-errors",
title: "Access Workflow Errors", title: "Access Workflow Errors",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/retry-failed-steps", path: "/advanced-development/workflows/retry-failed-steps",
title: "Retry Failed Steps", title: "Retry Failed Steps",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/parallel-steps", path: "/advanced-development/workflows/parallel-steps",
title: "Run Steps in Parallel", title: "Run Steps in Parallel",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/workflow-timeout", path: "/advanced-development/workflows/workflow-timeout",
title: "Workflow Timeout", title: "Workflow Timeout",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/long-running-workflow", path: "/advanced-development/workflows/long-running-workflow",
title: "Long-Running Workflow", title: "Long-Running Workflow",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/execute-another-workflow", path: "/advanced-development/workflows/execute-another-workflow",
title: "Execute Another Workflow", title: "Execute Another Workflow",
}, },
{ {
type: "link",
path: "/advanced-development/workflows/advanced-example", path: "/advanced-development/workflows/advanced-example",
title: "Example: Advanced Workflow", title: "Example: Advanced Workflow",
}, },
], ],
}, },
{ {
type: "link",
path: "/advanced-development/custom-cli-scripts", path: "/advanced-development/custom-cli-scripts",
title: "Custom CLI Scripts", title: "Custom CLI Scripts",
}, },
{ {
type: "link",
path: "/advanced-development/admin", path: "/advanced-development/admin",
title: "Admin Development", title: "Admin Development",
children: [ children: [
{ {
type: "link",
path: "/advanced-development/admin/widgets", path: "/advanced-development/admin/widgets",
title: "Admin Widgets", title: "Admin Widgets",
}, },
{ {
type: "link",
path: "/advanced-development/admin/ui-routes", path: "/advanced-development/admin/ui-routes",
title: "Admin UI Routes", title: "Admin UI Routes",
}, },
{ {
type: "link",
path: "/advanced-development/admin/tips", path: "/advanced-development/admin/tips",
title: "Tips", title: "Tips",
}, },
@@ -274,42 +337,51 @@ export const sidebar = sidebarAttachHrefCommonOptions(
], ],
}, },
{ {
type: "link",
path: "/storefront-development", path: "/storefront-development",
title: "Storefront Development", title: "Storefront Development",
children: [ children: [
{ {
type: "link",
path: "/storefront-development/nextjs-starter", path: "/storefront-development/nextjs-starter",
title: "Next.js Starter", title: "Next.js Starter",
}, },
], ],
}, },
{ {
type: "link",
path: "/architectural-modules", path: "/architectural-modules",
title: "Architectural Modules", title: "Architectural Modules",
}, },
{ {
type: "link",
path: "/debugging-and-testing", path: "/debugging-and-testing",
title: "Debugging and Testing", title: "Debugging and Testing",
children: [ children: [
{ {
type: "link",
path: "/debugging-and-testing/logging", path: "/debugging-and-testing/logging",
title: "Logging", title: "Logging",
}, },
{ {
type: "link",
path: "/debugging-and-testing/tools", path: "/debugging-and-testing/tools",
title: "Tools", title: "Tools",
}, },
], ],
}, },
{ {
type: "link",
path: "/deployment", path: "/deployment",
title: "Deployment", title: "Deployment",
}, },
{ {
type: "link",
path: "/more-resources", path: "/more-resources",
title: "More Resources", title: "More Resources",
}, },
{ {
type: "link",
path: "/cheatsheet", path: "/cheatsheet",
title: "Cheat Sheet", title: "Cheat Sheet",
}, },
+3 -6
View File
@@ -1,11 +1,8 @@
import { import { SidebarSectionItems, SidebarItem as SidebarItemType } from "types"
SidebarSectionItemsType,
SidebarItemType as UiSidebarItemType,
} from "docs-ui"
export declare type SidebarItemType = UiSidebarItemType & { export declare type SidebarItem = SidebarItemType & {
isSoon: boolean isSoon: boolean
number?: string number?: string
} }
export declare type SidebarConfig = SidebarSectionItemsType export declare type SidebarConfig = SidebarSectionItems
+34 -3
View File
@@ -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 * @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]) { export default function numberSidebarItems(sidebarItems, numbering = [1]) {
// TODO generate chapter titles
if (!numbering.length) { if (!numbering.length) {
numbering.push(1) numbering.push(1)
} }
const isTopItems = numbering.length === 1
/** @type {import("@/types").SidebarItem[]} */
const numberedItems = []
/** @type {import("@/types").SidebarItem | undefined} */
let parentItem
sidebarItems.forEach((item) => { 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 // append current number to the item's title
item.number = `${numbering.join(".")}.` item.number = `${numbering.join(".")}.`
item.title = `${item.number} ${item.title.trim()}` 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]) item.children = numberSidebarItems(item.children, [...numbering, 1])
} }
;(parentItem?.children || numberedItems).push(item)
numbering[numbering.length - 1]++ 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 = { const commonOptions = {
loaded: true, loaded: true,
isPathHref: true, isPathHref: true,
@@ -6,13 +6,26 @@ const commonOptions = {
/** /**
* *
* @param {import("../providers").SidebarItemType[]} sidebar * @param {import("@/types").SidebarItem[]} sidebar
* @returns {import("../providers").SidebarItemType[]} * @param {boolean} nested
* @returns {import("@/types").SidebarItem[]}
*/ */
export function sidebarAttachHrefCommonOptions(sidebar) { export function sidebarAttachHrefCommonOptions(sidebar, nested = false) {
return sidebar.map((item) => ({ return sidebar.map((item) => {
if (item.type === "separator") {
return item
}
const updatedItem = {
...commonOptions, ...commonOptions,
...item, ...item,
children: sidebarAttachHrefCommonOptions(item.children || []), children: sidebarAttachHrefCommonOptions(item.children || [], true),
})) }
if (updatedItem.type !== "category" && !nested) {
updatedItem.childrenSameLevel = true
}
return updatedItem
})
} }
+1 -6
View File
@@ -1,10 +1,8 @@
import type { Metadata } from "next" import type { Metadata } from "next"
import { Inter, Roboto_Mono } from "next/font/google" import { Inter, Roboto_Mono } from "next/font/google"
import Navbar from "@/components/Navbar"
import Providers from "@/providers" import Providers from "@/providers"
import "./globals.css" import "./globals.css"
import { Bannerv2, Breadcrumbs, TightLayout } from "docs-ui" import { Breadcrumbs, TightLayout } from "docs-ui"
import { config } from "@/config" import { config } from "@/config"
import clsx from "clsx" import clsx from "clsx"
import { Feedback } from "@/components/Feedback" import { Feedback } from "@/components/Feedback"
@@ -41,14 +39,11 @@ export default function RootLayout({
return ( return (
<TightLayout <TightLayout
ProvidersComponent={Providers} ProvidersComponent={Providers}
NavbarComponent={Navbar}
sidebarProps={{ sidebarProps={{
expandItems: true, expandItems: true,
banner: <Bannerv2 />,
}} }}
bodyClassName={clsx(inter.variable, robotoMono.variable)} bodyClassName={clsx(inter.variable, robotoMono.variable)}
> >
<Breadcrumbs />
{children} {children}
<Feedback className="my-2" /> <Feedback className="my-2" />
<EditButton /> <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. 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
+2 -3
View File
@@ -1,4 +1,4 @@
import { DocsConfig } from "types" import { DocsConfig, SidebarItem } from "types"
import { getMobileSidebarItems } from "docs-ui" import { getMobileSidebarItems } from "docs-ui"
import { generatedSidebar } from "../generated/sidebar.mjs" import { generatedSidebar } from "../generated/sidebar.mjs"
@@ -9,8 +9,7 @@ export const config: DocsConfig = {
baseUrl, baseUrl,
basePath: process.env.NEXT_PUBLIC_BASE_PATH, basePath: process.env.NEXT_PUBLIC_BASE_PATH,
sidebar: { sidebar: {
top: generatedSidebar, default: generatedSidebar as SidebarItem[],
bottom: [],
mobile: getMobileSidebarItems({ mobile: getMobileSidebarItems({
baseUrl, baseUrl,
version: "v2", version: "v2",
File diff suppressed because it is too large. Load diff
+3
View File
@@ -16,6 +16,7 @@ import {
import SidebarProvider from "./sidebar" import SidebarProvider from "./sidebar"
import SearchProvider from "./search" import SearchProvider from "./search"
import { config } from "../config" import { config } from "../config"
import { MainNavProvider } from "./main-nav"
type ProvidersProps = { type ProvidersProps = {
children?: React.ReactNode children?: React.ReactNode
@@ -35,6 +36,7 @@ const Providers = ({ children }: ProvidersProps) => {
<ScrollControllerProvider scrollableSelector="#main"> <ScrollControllerProvider scrollableSelector="#main">
<SidebarProvider> <SidebarProvider>
<PaginationProvider> <PaginationProvider>
<MainNavProvider>
<SearchProvider> <SearchProvider>
<HooksLoader <HooksLoader
options={{ options={{
@@ -45,6 +47,7 @@ const Providers = ({ children }: ProvidersProps) => {
{children} {children}
</HooksLoader> </HooksLoader>
</SearchProvider> </SearchProvider>
</MainNavProvider>
</PaginationProvider> </PaginationProvider>
</SidebarProvider> </SidebarProvider>
</ScrollControllerProvider> </ScrollControllerProvider>
+46
View 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
View File
@@ -20,7 +20,6 @@ const SidebarProvider = ({ children }: SidebarProviderProps) => {
initialItems={config.sidebar} initialItems={config.sidebar}
staticSidebarItems={true} staticSidebarItems={true}
disableActiveTransition={true} disableActiveTransition={true}
noTitleStyling={true}
> >
{children} {children}
</UiSidebarProvider> </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 = { const commonOptions = {
loaded: true, loaded: true,
isPathHref: true, isPathHref: true,
@@ -6,13 +6,19 @@ const commonOptions = {
/** /**
* *
* @param {import("types").SidebarItemType[]} sidebar * @param {import("types").RawSidebarItem[]} sidebar
* @returns {import("types").SidebarItemType[]} * @returns {import("types").RawSidebarItem[]}
*/ */
export function sidebarAttachHrefCommonOptions(sidebar) { export function sidebarAttachHrefCommonOptions(sidebar) {
return sidebar.map((item) => ({ return sidebar.map((item) => {
if (item.type === "separator") {
return item
}
return {
...commonOptions, ...commonOptions,
...item, ...item,
children: sidebarAttachHrefCommonOptions(item.children || []), children: sidebarAttachHrefCommonOptions(item.children || []),
})) }
})
} }
+2 -1
View File
@@ -1,5 +1,6 @@
import { defineDocumentType, makeSource } from "contentlayer/source-files" import { defineDocumentType, makeSource } from "contentlayer/source-files"
import { rehypeComponent } from "./src/lib/rehype-component" import { rehypeComponent } from "./src/lib/rehype-component"
import rehypeSlug from "rehype-slug"
export const Doc = defineDocumentType(() => ({ export const Doc = defineDocumentType(() => ({
name: "Doc", name: "Doc",
@@ -26,6 +27,6 @@ export default makeSource({
contentDirPath: "./src/content", contentDirPath: "./src/content",
documentTypes: [Doc], documentTypes: [Doc],
mdx: { mdx: {
rehypePlugins: [rehypeComponent], rehypePlugins: [[rehypeComponent], [rehypeSlug]],
}, },
}) })
+1
View File
@@ -37,6 +37,7 @@
"react": "18.2.0", "react": "18.2.0",
"react-day-picker": "^8.10.0", "react-day-picker": "^8.10.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"rehype-slug": "^6.0.0",
"remark": "^14.0.3", "remark": "^14.0.3",
"tailwind": "*", "tailwind": "*",
"tailwindcss": "3.3.3", "tailwindcss": "3.3.3",
+7 -6
View File
@@ -2,7 +2,7 @@ import { MetadataRoute } from "next"
import { docsConfig } from "@/config/docs" import { docsConfig } from "@/config/docs"
import { absoluteUrl } from "@/lib/absolute-url" import { absoluteUrl } from "@/lib/absolute-url"
import { SidebarItemType } from "types" import { SidebarItem } from "types"
export default function sitemap(): MetadataRoute.Sitemap { export default function sitemap(): MetadataRoute.Sitemap {
const now = new Date() const now = new Date()
@@ -12,14 +12,16 @@ export default function sitemap(): MetadataRoute.Sitemap {
lastModified?: string | Date lastModified?: string | Date
}> = [] }> = []
function pushItems(newItems: SidebarItemType[]) { function pushItems(newItems: SidebarItem[]) {
newItems.forEach((item) => { newItems.forEach((item) => {
if (item.path) { if (item.type !== "link") {
return
}
items.push({ items.push({
url: absoluteUrl(item.path), url: absoluteUrl(item.path),
lastModified: now, lastModified: now,
}) })
}
if (item.children) { if (item.children) {
pushItems(item.children) pushItems(item.children)
@@ -27,8 +29,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
}) })
} }
pushItems(docsConfig.sidebar.top) pushItems(docsConfig.sidebar.default)
pushItems(docsConfig.sidebar.bottom)
return items return items
} }
+1 -2
View File
@@ -1,6 +1,5 @@
import type { Metadata } from "next" import type { Metadata } from "next"
import { Navbar } from "@/components/navbar"
import { Providers } from "@/providers" import { Providers } from "@/providers"
import { siteConfig } from "@/config/site" import { siteConfig } from "@/config/site"
@@ -36,11 +35,11 @@ export default function RootLayout({
return ( return (
<TightLayout <TightLayout
ProvidersComponent={Providers} ProvidersComponent={Providers}
NavbarComponent={Navbar}
sidebarProps={{ sidebarProps={{
expandItems: true, expandItems: true,
}} }}
bodyClassName={clsx(inter.variable, robotoMono.variable)} bodyClassName={clsx(inter.variable, robotoMono.variable)}
showBanner={false}
> >
{children} {children}
</TightLayout> </TightLayout>
-25
View File
@@ -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 }
+106 -27
View File
@@ -1,281 +1,360 @@
import { ArrowUpRightOnBox } from "@medusajs/icons" import { getMobileSidebarItems } from "docs-ui"
import { NavbarItem, getMobileSidebarItems, getNavbarItems } from "docs-ui" import { SidebarSectionItems } from "types"
import { SidebarSectionItemsType } from "types"
import { siteConfig } from "./site" import { siteConfig } from "./site"
type DocsConfig = { type DocsConfig = {
mainNav: NavbarItem[] sidebar: SidebarSectionItems
sidebar: SidebarSectionItemsType
} }
export const docsConfig: DocsConfig = { export const docsConfig: DocsConfig = {
mainNav: getNavbarItems({
basePath: siteConfig.baseUrl,
activePath: process.env.NEXT_PUBLIC_BASE_PATH || "/ui",
version: "v1",
}),
sidebar: { sidebar: {
top: [ default: [
{
title: "Getting Started",
children: [
{ {
type: "link",
title: "Introduction", title: "Introduction",
path: "/", path: "/",
loaded: true, loaded: true,
isPathHref: true, isPathHref: true,
}, },
], {
type: "separator",
}, },
{ {
type: "category",
title: "Installation", title: "Installation",
loaded: true,
children: [ children: [
{ {
type: "link",
title: "Medusa Admin Extension", title: "Medusa Admin Extension",
path: "/installation/medusa-admin-extension", path: "/installation/medusa-admin-extension",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Standalone Project", title: "Standalone Project",
path: "/installation/standalone-project", path: "/installation/standalone-project",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Upgrade Guides", title: "Upgrade Guides",
path: `${process.env.NEXT_PUBLIC_DOCS_URL}/upgrade-guides/medusa-ui`, path: `${process.env.NEXT_PUBLIC_DOCS_URL}/upgrade-guides/medusa-ui`,
isPathHref: true, isPathHref: true,
additionalElms: <ArrowUpRightOnBox />, loaded: true,
linkProps: {
target: "_blank",
rel: "noreferrer",
},
}, },
], ],
}, },
],
bottom: [
{ {
type: "category",
title: "Colors", title: "Colors",
loaded: true,
children: [ children: [
{ {
type: "link",
title: "Overview", title: "Overview",
path: "/colors/overview", path: "/colors/overview",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
], ],
}, },
{ {
type: "link",
title: "Icons", title: "Icons",
children: [
{
title: "Overview",
path: "/icons/overview", path: "/icons/overview",
isPathHref: true, isPathHref: true,
}, loaded: true,
],
}, },
{ {
type: "separator",
},
{
type: "category",
title: "Components", title: "Components",
loaded: true,
children: [ children: [
{ {
type: "link",
title: "Alert", title: "Alert",
path: "/components/alert", path: "/components/alert",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Avatar", title: "Avatar",
path: "/components/avatar", path: "/components/avatar",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Badge", title: "Badge",
path: "/components/badge", path: "/components/badge",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Button", title: "Button",
path: "/components/button", path: "/components/button",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Calendar", title: "Calendar",
path: "/components/calendar", path: "/components/calendar",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Checkbox", title: "Checkbox",
path: "/components/checkbox", path: "/components/checkbox",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Code Block", title: "Code Block",
path: "/components/code-block", path: "/components/code-block",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Command", title: "Command",
path: "/components/command", path: "/components/command",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Command Bar", title: "Command Bar",
path: "/components/command-bar", path: "/components/command-bar",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Container", title: "Container",
path: "/components/container", path: "/components/container",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Copy", title: "Copy",
path: "/components/copy", path: "/components/copy",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Currency Input", title: "Currency Input",
path: "/components/currency-input", path: "/components/currency-input",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Date Picker", title: "Date Picker",
path: "/components/date-picker", path: "/components/date-picker",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Drawer", title: "Drawer",
path: "/components/drawer", path: "/components/drawer",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Dropdown Menu", title: "Dropdown Menu",
path: "/components/dropdown-menu", path: "/components/dropdown-menu",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Focus Modal", title: "Focus Modal",
path: "/components/focus-modal", path: "/components/focus-modal",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Heading", title: "Heading",
path: "/components/heading", path: "/components/heading",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Icon Badge", title: "Icon Badge",
path: "/components/icon-badge", path: "/components/icon-badge",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Icon Button", title: "Icon Button",
path: "/components/icon-button", path: "/components/icon-button",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Input", title: "Input",
path: "/components/input", path: "/components/input",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Kbd", title: "Kbd",
path: "/components/kbd", path: "/components/kbd",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Label", title: "Label",
path: "/components/label", path: "/components/label",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Progress Accordion", title: "Progress Accordion",
path: "/components/progress-accordion", path: "/components/progress-accordion",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Progress Tabs", title: "Progress Tabs",
path: "/components/progress-tabs", path: "/components/progress-tabs",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Prompt", title: "Prompt",
path: "/components/prompt", path: "/components/prompt",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Radio Group", title: "Radio Group",
path: "/components/radio-group", path: "/components/radio-group",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Select", title: "Select",
path: "/components/select", path: "/components/select",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Status Badge", title: "Status Badge",
path: "/components/status-badge", path: "/components/status-badge",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Switch", title: "Switch",
path: "/components/switch", path: "/components/switch",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Table", title: "Table",
path: "/components/table", path: "/components/table",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Tabs", title: "Tabs",
path: "/components/tabs", path: "/components/tabs",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Text", title: "Text",
path: "/components/text", path: "/components/text",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Textarea", title: "Textarea",
path: "/components/textarea", path: "/components/textarea",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Toast", title: "Toast",
path: "/components/toast", path: "/components/toast",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "Tooltip", title: "Tooltip",
path: "/components/tooltip", path: "/components/tooltip",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
], ],
}, },
{ {
type: "category",
title: "Hooks", title: "Hooks",
loaded: true,
children: [ children: [
{ {
type: "link",
title: "usePrompt", title: "usePrompt",
path: "/hooks/use-prompt", path: "/hooks/use-prompt",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
{ {
type: "link",
title: "useToggleState", title: "useToggleState",
path: "/hooks/use-toggle-state", path: "/hooks/use-toggle-state",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
], ],
}, },
{ {
type: "category",
title: "Utils", title: "Utils",
loaded: true,
children: [ children: [
{ {
type: "link",
title: "clx", title: "clx",
path: "/utils/clx", path: "/utils/clx",
isPathHref: true, isPathHref: true,
loaded: true,
}, },
], ],
}, },
+1 -2
View File
@@ -16,8 +16,7 @@ export const siteConfig: SiteConfig = {
description: "Primitives for building Medusa applications.", description: "Primitives for building Medusa applications.",
// sidebar is defined in docs.tsx // sidebar is defined in docs.tsx
sidebar: { sidebar: {
top: [], default: [],
bottom: [],
mobile: [], mobile: [],
}, },
} }
+3
View File
@@ -11,6 +11,7 @@ import {
import SearchProvider from "./search" import SearchProvider from "./search"
import SidebarProvider from "./sidebar" import SidebarProvider from "./sidebar"
import { siteConfig } from "../config/site" import { siteConfig } from "../config/site"
import { MainNavProvider } from "./main-nav"
type ProvidersProps = { type ProvidersProps = {
children: React.ReactNode children: React.ReactNode
@@ -25,7 +26,9 @@ const Providers = ({ children }: ProvidersProps) => {
<ModalProvider> <ModalProvider>
<ScrollControllerProvider scrollableSelector="#main"> <ScrollControllerProvider scrollableSelector="#main">
<SidebarProvider> <SidebarProvider>
<MainNavProvider>
<SearchProvider>{children}</SearchProvider> <SearchProvider>{children}</SearchProvider>
</MainNavProvider>
</SidebarProvider> </SidebarProvider>
</ScrollControllerProvider> </ScrollControllerProvider>
</ModalProvider> </ModalProvider>
+42
View 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>
)
}
+1
View File
@@ -10,6 +10,7 @@ type SidebarProviderProps = {
const SidebarProvider = ({ children }: SidebarProviderProps) => { const SidebarProvider = ({ children }: SidebarProviderProps) => {
const { scrollableElement } = useScrollController() const { scrollableElement } = useScrollController()
return ( return (
<UiSidebarProvider <UiSidebarProvider
initialItems={docsConfig.sidebar} initialItems={docsConfig.sidebar}
-3
View File
@@ -1,7 +1,5 @@
import type { Metadata } from "next" import type { Metadata } from "next"
import { Inter, Roboto_Mono } from "next/font/google" import { Inter, Roboto_Mono } from "next/font/google"
import Navbar from "@/components/Navbar"
import Providers from "@/providers" import Providers from "@/providers"
import "../css/globals.css" import "../css/globals.css"
import { TightLayout } from "docs-ui" import { TightLayout } from "docs-ui"
@@ -40,7 +38,6 @@ export default function RootLayout({
return ( return (
<TightLayout <TightLayout
ProvidersComponent={Providers} ProvidersComponent={Providers}
NavbarComponent={Navbar}
sidebarProps={{ sidebarProps={{
expandItems: true, 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
+2 -3
View File
@@ -1,4 +1,4 @@
import { DocsConfig } from "types" import { DocsConfig, SidebarItem } from "types"
import { getMobileSidebarItems } from "docs-ui" import { getMobileSidebarItems } from "docs-ui"
import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs" import { generatedSidebar as sidebar } from "@/generated/sidebar.mjs"
@@ -9,8 +9,7 @@ export const config: DocsConfig = {
baseUrl, baseUrl,
basePath: process.env.NEXT_PUBLIC_BASE_PATH, basePath: process.env.NEXT_PUBLIC_BASE_PATH,
sidebar: { sidebar: {
top: sidebar, default: sidebar as SidebarItem[],
bottom: [],
mobile: getMobileSidebarItems({ mobile: getMobileSidebarItems({
baseUrl, baseUrl,
version: "v2", version: "v2",
+61
View File
@@ -2,13 +2,18 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/", "path": "/",
"title": "Introduction", "title": "Introduction",
"children": [] "children": []
}, },
{
"type": "separator"
},
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"title": "Tips", "title": "Tips",
"hasTitleStyling": true, "hasTitleStyling": true,
"autogenerate_path": "/tips", "autogenerate_path": "/tips",
@@ -16,6 +21,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/tips/bulk-editor", "path": "/tips/bulk-editor",
"title": "Bulk Editor", "title": "Bulk Editor",
"children": [] "children": []
@@ -23,6 +29,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/tips/languages", "path": "/tips/languages",
"title": "Admin Languages", "title": "Admin Languages",
"children": [] "children": []
@@ -30,6 +37,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/tips/lists", "path": "/tips/lists",
"title": "Lists", "title": "Lists",
"children": [] "children": []
@@ -39,6 +47,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/orders", "path": "/orders",
"title": "Orders", "title": "Orders",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -47,6 +56,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/manage", "path": "/orders/manage",
"title": "Manage Details", "title": "Manage Details",
"children": [] "children": []
@@ -54,6 +64,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/payments", "path": "/orders/payments",
"title": "Manage Payments", "title": "Manage Payments",
"children": [] "children": []
@@ -61,6 +72,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/fulfillments", "path": "/orders/fulfillments",
"title": "Manage Fulfillments", "title": "Manage Fulfillments",
"children": [] "children": []
@@ -68,6 +80,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/edit", "path": "/orders/edit",
"title": "Edit an Order’s Items", "title": "Edit an Order’s Items",
"children": [] "children": []
@@ -75,6 +88,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/drafts", "path": "/orders/drafts",
"title": "Manage Draft Orders", "title": "Manage Draft Orders",
"children": [] "children": []
@@ -82,6 +96,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/returns", "path": "/orders/returns",
"title": "Manage Returns", "title": "Manage Returns",
"children": [] "children": []
@@ -89,6 +104,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/exchange", "path": "/orders/exchange",
"title": "Manage Exchanges", "title": "Manage Exchanges",
"children": [] "children": []
@@ -96,6 +112,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/claims", "path": "/orders/claims",
"title": "Manage Order's Claims", "title": "Manage Order's Claims",
"children": [] "children": []
@@ -103,6 +120,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/orders/export", "path": "/orders/export",
"title": "Export Orders", "title": "Export Orders",
"children": [] "children": []
@@ -112,6 +130,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/products", "path": "/products",
"title": "Products", "title": "Products",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -120,6 +139,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/manage", "path": "/products/manage",
"title": "Manage Products", "title": "Manage Products",
"children": [] "children": []
@@ -127,6 +147,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/collections", "path": "/products/collections",
"title": "Manage Product Collections", "title": "Manage Product Collections",
"children": [] "children": []
@@ -134,6 +155,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/categories", "path": "/products/categories",
"title": "Manage Product Categories", "title": "Manage Product Categories",
"children": [] "children": []
@@ -141,12 +163,14 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/gift-cards", "path": "/products/gift-cards",
"title": "Gift Cards", "title": "Gift Cards",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/gift-cards/product-gift-card", "path": "/products/gift-cards/product-gift-card",
"title": "Manage a Product Gift Card", "title": "Manage a Product Gift Card",
"children": [], "children": [],
@@ -155,6 +179,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/gift-cards/customer-gift-card", "path": "/products/gift-cards/customer-gift-card",
"title": "Manage a Customer Gift Card", "title": "Manage a Customer Gift Card",
"children": [], "children": [],
@@ -165,6 +190,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/import", "path": "/products/import",
"title": "Import Products", "title": "Import Products",
"children": [] "children": []
@@ -172,6 +198,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/products/export", "path": "/products/export",
"title": "Export Products", "title": "Export Products",
"children": [] "children": []
@@ -181,6 +208,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/inventory", "path": "/inventory",
"title": "Inventory", "title": "Inventory",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -189,6 +217,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/inventory/inventory", "path": "/inventory/inventory",
"title": "Manage Inventory", "title": "Manage Inventory",
"children": [] "children": []
@@ -196,6 +225,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/inventory/reservations", "path": "/inventory/reservations",
"title": "Manage Reservations", "title": "Manage Reservations",
"children": [] "children": []
@@ -205,6 +235,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/customers", "path": "/customers",
"title": "Customers", "title": "Customers",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -213,6 +244,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/customers/manage", "path": "/customers/manage",
"title": "Manage Customers", "title": "Manage Customers",
"children": [] "children": []
@@ -220,6 +252,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/customers/groups", "path": "/customers/groups",
"title": "Manage Customer Groups", "title": "Manage Customer Groups",
"children": [] "children": []
@@ -229,6 +262,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/discounts", "path": "/discounts",
"title": "Discounts", "title": "Discounts",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -237,6 +271,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/discounts/create", "path": "/discounts/create",
"title": "Create a Discount", "title": "Create a Discount",
"children": [] "children": []
@@ -244,6 +279,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/discounts/manage", "path": "/discounts/manage",
"title": "Manage Discounts", "title": "Manage Discounts",
"children": [] "children": []
@@ -253,6 +289,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/pricing", "path": "/pricing",
"title": "Pricing", "title": "Pricing",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -261,6 +298,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/pricing/create", "path": "/pricing/create",
"title": "Create a Price List", "title": "Create a Price List",
"children": [] "children": []
@@ -268,6 +306,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/pricing/manage", "path": "/pricing/manage",
"title": "Manage Price Lists", "title": "Manage Price Lists",
"children": [] "children": []
@@ -277,6 +316,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "category",
"path": "/settings", "path": "/settings",
"title": "Settings", "title": "Settings",
"hasTitleStyling": true, "hasTitleStyling": true,
@@ -285,6 +325,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/profile", "path": "/settings/profile",
"title": "Profile", "title": "Profile",
"children": [] "children": []
@@ -292,6 +333,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/store", "path": "/settings/store",
"title": "Store", "title": "Store",
"children": [] "children": []
@@ -299,12 +341,14 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/users", "path": "/settings/users",
"title": "Users", "title": "Users",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/users/invites", "path": "/settings/users/invites",
"title": "Manage Invites", "title": "Manage Invites",
"children": [], "children": [],
@@ -315,12 +359,14 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/regions", "path": "/settings/regions",
"title": "Regions", "title": "Regions",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/regions/manage", "path": "/settings/regions/manage",
"title": "Manage Regions", "title": "Manage Regions",
"children": [], "children": [],
@@ -329,6 +375,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/regions/countries", "path": "/settings/regions/countries",
"title": "Manage Countries", "title": "Manage Countries",
"children": [], "children": [],
@@ -337,6 +384,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/regions/providers", "path": "/settings/regions/providers",
"title": "Manage Providers", "title": "Manage Providers",
"children": [], "children": [],
@@ -345,6 +393,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/regions/shipping-options", "path": "/settings/regions/shipping-options",
"title": "Manage Shipping Options", "title": "Manage Shipping Options",
"children": [], "children": [],
@@ -355,6 +404,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/return-reasons", "path": "/settings/return-reasons",
"title": "Return Reasons", "title": "Return Reasons",
"children": [] "children": []
@@ -362,12 +412,14 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/taxes", "path": "/settings/taxes",
"title": "Taxes", "title": "Taxes",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/taxes/manage", "path": "/settings/taxes/manage",
"title": "Manage Taxes", "title": "Manage Taxes",
"children": [], "children": [],
@@ -376,6 +428,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/taxes/tax-rates", "path": "/settings/taxes/tax-rates",
"title": "Manage Tax Rates", "title": "Manage Tax Rates",
"children": [], "children": [],
@@ -386,6 +439,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/locations", "path": "/settings/locations",
"title": "Locations", "title": "Locations",
"children": [] "children": []
@@ -393,12 +447,14 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/sales-channels", "path": "/settings/sales-channels",
"title": "Sales Channels", "title": "Sales Channels",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/sales-channels/manage", "path": "/settings/sales-channels/manage",
"title": "Manage Sales Channels", "title": "Manage Sales Channels",
"children": [], "children": [],
@@ -407,6 +463,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/sales-channels/products", "path": "/settings/sales-channels/products",
"title": "Manage Products", "title": "Manage Products",
"children": [], "children": [],
@@ -417,18 +474,21 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/developer", "path": "/settings/developer",
"title": "Developer", "title": "Developer",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/developer/api-key-management", "path": "/settings/developer/api-key-management",
"title": "API Key Management", "title": "API Key Management",
"children": [ "children": [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/developer/api-key-management/sales-channels", "path": "/settings/developer/api-key-management/sales-channels",
"title": "Manage Sales Channels", "title": "Manage Sales Channels",
"children": [], "children": [],
@@ -440,6 +500,7 @@ export const generatedSidebar = [
{ {
"loaded": true, "loaded": true,
"isPathHref": true, "isPathHref": true,
"type": "link",
"path": "/settings/developer/executions", "path": "/settings/developer/executions",
"title": "Executions", "title": "Executions",
"children": [], "children": [],
+3
View File
@@ -15,6 +15,7 @@ import {
import SidebarProvider from "./sidebar" import SidebarProvider from "./sidebar"
import SearchProvider from "./search" import SearchProvider from "./search"
import { config } from "../config" import { config } from "../config"
import { MainNavProvider } from "./main-nav"
type ProvidersProps = { type ProvidersProps = {
children?: React.ReactNode children?: React.ReactNode
@@ -32,6 +33,7 @@ const Providers = ({ children }: ProvidersProps) => {
<ScrollControllerProvider scrollableSelector="#main"> <ScrollControllerProvider scrollableSelector="#main">
<SidebarProvider> <SidebarProvider>
<PaginationProvider> <PaginationProvider>
<MainNavProvider>
<SearchProvider> <SearchProvider>
<HooksLoader <HooksLoader
options={{ options={{
@@ -41,6 +43,7 @@ const Providers = ({ children }: ProvidersProps) => {
{children} {children}
</HooksLoader> </HooksLoader>
</SearchProvider> </SearchProvider>
</MainNavProvider>
</PaginationProvider> </PaginationProvider>
</SidebarProvider> </SidebarProvider>
</ScrollControllerProvider> </ScrollControllerProvider>
@@ -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} initialItems={config.sidebar}
staticSidebarItems={true} staticSidebarItems={true}
disableActiveTransition={true} disableActiveTransition={true}
noTitleStyling={true}
> >
{children} {children}
</UiSidebarProvider> </UiSidebarProvider>
+12
View File
@@ -5,51 +5,63 @@ import { sidebarAttachHrefCommonOptions } from "build-scripts"
/** @type {import('types').RawSidebarItemType[]} */ /** @type {import('types').RawSidebarItemType[]} */
export const sidebar = sidebarAttachHrefCommonOptions([ export const sidebar = sidebarAttachHrefCommonOptions([
{ {
type: "link",
path: "/", path: "/",
title: "Introduction", title: "Introduction",
}, },
{ {
type: "separator",
},
{
type: "category",
title: "Tips", title: "Tips",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/tips", autogenerate_path: "/tips",
}, },
{ {
type: "category",
path: "/orders", path: "/orders",
title: "Orders", title: "Orders",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/orders", autogenerate_path: "/orders",
}, },
{ {
type: "category",
path: "/products", path: "/products",
title: "Products", title: "Products",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/products", autogenerate_path: "/products",
}, },
{ {
type: "category",
path: "/inventory", path: "/inventory",
title: "Inventory", title: "Inventory",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/inventory", autogenerate_path: "/inventory",
}, },
{ {
type: "category",
path: "/customers", path: "/customers",
title: "Customers", title: "Customers",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/customers", autogenerate_path: "/customers",
}, },
{ {
type: "category",
path: "/discounts", path: "/discounts",
title: "Discounts", title: "Discounts",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/discounts", autogenerate_path: "/discounts",
}, },
{ {
type: "category",
path: "/pricing", path: "/pricing",
title: "Pricing", title: "Pricing",
hasTitleStyling: true, hasTitleStyling: true,
autogenerate_path: "/pricing", autogenerate_path: "/pricing",
}, },
{ {
type: "category",
path: "/settings", path: "/settings",
title: "Settings", title: "Settings",
hasTitleStyling: true, 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 { existsSync, mkdirSync, readdirSync, statSync } from "fs"
import path from "path" import path from "path"
import { getSidebarItemLink, sidebarAttachHrefCommonOptions } from "./index.js" import { getSidebarItemLink, sidebarAttachHrefCommonOptions } from "./index.js"
import getCoreFlowsRefSidebarChildren from "./utils/get-core-flows-ref-sidebar-children.js" import getCoreFlowsRefSidebarChildren from "./utils/get-core-flows-ref-sidebar-children.js"
export type ItemsToAdd = RawSidebarItemType & { export type ItemsToAdd = SidebarItem & {
sidebar_position?: number sidebar_position?: number
} }
@@ -37,19 +37,17 @@ async function getSidebarItems(
true true
) )
if (nested && newItems.length > 1) { if (nested && newItems.length > 1) {
items.push( items.push({
...sidebarAttachHrefCommonOptions([ type: "sub-category",
{
title: title:
fileBasename.charAt(0).toUpperCase() + fileBasename.charAt(0).toUpperCase() + fileBasename.substring(1),
fileBasename.substring(1),
hasTitleStyling: true,
children: newItems, children: newItems,
}, loaded: true,
]) })
)
} else { } else {
items.push(...sidebarAttachHrefCommonOptions(newItems)) items.push(
...(sidebarAttachHrefCommonOptions(newItems) as ItemsToAdd[])
)
} }
continue continue
} }
@@ -69,7 +67,11 @@ async function getSidebarItems(
mainPageIndex = items.length - 1 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. // push all other items to be children of that page.
const mainPageChildren = [ const mainPageChildren = [
...items.splice(0, mainPageIndex), ...items.splice(0, mainPageIndex),
@@ -84,9 +86,19 @@ async function getSidebarItems(
return items return items
} }
async function checkItem( async function checkItem(item: RawSidebarItem): Promise<RawSidebarItem> {
item: RawSidebarItemType if (!item.type) {
): Promise<RawSidebarItemType> { 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) { if (item.autogenerate_path) {
item.children = (await getSidebarItems(item.autogenerate_path)).map( item.children = (await getSidebarItems(item.autogenerate_path)).map(
(child) => { (child) => {
@@ -109,7 +121,7 @@ async function checkItem(
return item return item
} }
export async function generateSidebar(sidebar: RawSidebarItemType[]) { export async function generateSidebar(sidebar: RawSidebarItem[]) {
const path = await import("path") const path = await import("path")
const { writeFileSync } = await import("fs") const { writeFileSync } = await import("fs")
@@ -14,6 +14,19 @@ export default async function getCoreFlowsRefSidebarChildren(): Promise<
const sidebarItems: ItemsToAdd[] = [] const sidebarItems: ItemsToAdd[] = []
sidebarItems.push(
{
type: "link",
title: "Overview",
path: "/medusa-workflows-reference",
loaded: true,
isPathHref: true,
},
{
type: "separator",
}
)
for (const directory of directories) { for (const directory of directories) {
if ( if (
!directory.isDirectory() || !directory.isDirectory() ||
@@ -66,21 +79,28 @@ export default async function getCoreFlowsRefSidebarChildren(): Promise<
if (workflowItems.length || stepItems.length) { if (workflowItems.length || stepItems.length) {
const item: ItemsToAdd = { const item: ItemsToAdd = {
type: "category",
title: directory.name.replaceAll("_", " "), title: directory.name.replaceAll("_", " "),
children: [], children: [],
loaded: true,
initialOpen: false,
} }
if (workflowItems.length) { if (workflowItems.length) {
item.children!.push({ item.children!.push({
type: "sub-category",
title: "Workflows", title: "Workflows",
children: workflowItems, children: workflowItems,
loaded: true,
}) })
} }
if (stepItems.length) { if (stepItems.length) {
item.children!.push({ item.children!.push({
type: "sub-category",
title: "Steps", title: "Steps",
children: stepItems, children: stepItems,
loaded: true,
}) })
} }
@@ -3,6 +3,7 @@ import { ItemsToAdd, sidebarAttachHrefCommonOptions } from "../index.js"
import { readFileSync } from "fs" import { readFileSync } from "fs"
import findMetadataTitle from "./find-metadata-title.js" import findMetadataTitle from "./find-metadata-title.js"
import findPageHeading from "./find-page-heading.js" import findPageHeading from "./find-page-heading.js"
import { InteractiveSidebarItem } from "types"
export async function getSidebarItemLink({ export async function getSidebarItemLink({
filePath, filePath,
@@ -24,6 +25,7 @@ export async function getSidebarItemLink({
const newItem = sidebarAttachHrefCommonOptions([ const newItem = sidebarAttachHrefCommonOptions([
{ {
type: "link",
path: path:
frontmatter.slug || frontmatter.slug ||
filePath.replace(basePath, "").replace(`/${fileBasename}`, ""), filePath.replace(basePath, "").replace(`/${fileBasename}`, ""),
@@ -33,7 +35,7 @@ export async function getSidebarItemLink({
findPageHeading(fileContent) || findPageHeading(fileContent) ||
"", "",
}, },
])[0] ])[0] as InteractiveSidebarItem
return { return {
...newItem, ...newItem,
@@ -1,16 +1,22 @@
import { RawSidebarItemType } from "types" import { RawSidebarItem } from "types"
const commonOptions: Partial<RawSidebarItemType> = { const commonOptions: Partial<RawSidebarItem> = {
loaded: true, loaded: true,
isPathHref: true, isPathHref: true,
} }
export function sidebarAttachHrefCommonOptions( export function sidebarAttachHrefCommonOptions(
sidebar: RawSidebarItemType[] sidebar: RawSidebarItem[]
): RawSidebarItemType[] { ): RawSidebarItem[] {
return sidebar.map((item) => ({ return sidebar.map((item) => {
if (item.type === "separator") {
return item
}
return {
...commonOptions, ...commonOptions,
...item, ...item,
children: sidebarAttachHrefCommonOptions(item.children || []), children: sidebarAttachHrefCommonOptions(item.children || []),
})) }
})
} }
+2 -1
View File
@@ -78,6 +78,7 @@
"react-medium-image-zoom": "^5.1.10", "react-medium-image-zoom": "^5.1.10",
"react-tooltip": "^5.21.3", "react-tooltip": "^5.21.3",
"react-transition-group": "^4.4.5", "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" "use client"
import { Card, Link } from "../.."
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 ( return (
<Card> <div
This documentation is for Medusa v2, which isn&apos;t ready for className={clsx(
production. "bg-medusa-bg-base hidden gap-docs_0.5 z-20",
<br /> "justify-between items-start rounded-docs_DEFAULT",
<br /> "p-docs_0.75 shadow-elevation-card-rest dark:shadow-elevation-card-rest-dark",
For production-use, refer to{" "} show && "lg:flex",
<Link href="https://docs.medusajs.com">this documentation</Link> instead. className
</Card> )}
>
<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 React from "react"
import { Bordered } from "@/components/Bordered"
import clsx from "clsx" import clsx from "clsx"
import { IconProps } from "@medusajs/icons/dist/types" import { IconProps } from "@medusajs/icons/dist/types"
@@ -15,16 +14,15 @@ export type BorderedIconProps = {
export const BorderedIcon = ({ export const BorderedIcon = ({
icon = "", icon = "",
IconComponent = null, IconComponent = null,
wrapperClassName,
iconWrapperClassName, iconWrapperClassName,
iconClassName, iconClassName,
iconColorClassName = "", iconColorClassName = "",
}: BorderedIconProps) => { }: BorderedIconProps) => {
return ( return (
<Bordered wrapperClassName={wrapperClassName}>
<span <span
className={clsx( className={clsx(
"rounded-docs_xs p-docs_0.125 bg-medusa-bg-component inline-flex items-center justify-center", "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 iconWrapperClassName
)} )}
> >
@@ -38,7 +36,7 @@ export const BorderedIcon = ({
{IconComponent && ( {IconComponent && (
<IconComponent <IconComponent
className={clsx( className={clsx(
"text-medusa-fg-subtle", "text-medusa-fg-subtle rounded-docs_sm",
iconClassName, iconClassName,
"bordered-icon", "bordered-icon",
iconColorClassName iconColorClassName
@@ -46,6 +44,5 @@ export const BorderedIcon = ({
/> />
)} )}
</span> </span>
</Bordered>
) )
} }
@@ -17,8 +17,13 @@ export const Breadcrumbs = () => {
tempBreadcrumbItems = getBreadcrumbsOfItem(item.previousSidebar) 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( tempBreadcrumbItems.set(
item.parentItem?.path || item.top[0].path || "/", parentPath || firstItemPath || "/",
item.parentItem?.childSidebarTitle || item.parentItem?.title || "" item.parentItem?.childSidebarTitle || item.parentItem?.title || ""
) )
@@ -2,7 +2,8 @@
import React, { useMemo } from "react" import React, { useMemo } from "react"
import { Card, CardList, MDXComponents, useSidebar } from "../.." import { Card, CardList, MDXComponents, useSidebar } from "../.."
import { SidebarItemType } from "types" import { InteractiveSidebarItem, SidebarItem, SidebarItemLink } from "types"
import slugify from "slugify"
type ChildDocsProps = { type ChildDocsProps = {
onlyTopLevel?: boolean onlyTopLevel?: boolean
@@ -30,16 +31,19 @@ export const ChildDocs = ({
: "all" : "all"
}, [showItems, hideItems]) }, [showItems, hideItems])
const filterCondition = (item: SidebarItemType): boolean => { const filterCondition = (item: SidebarItem): boolean => {
if (item.type === "separator") {
return false
}
switch (filterType) { switch (filterType) {
case "hide": case "hide":
return ( return (
(!item.path || !hideItems.includes(item.path)) && (item.type !== "link" || !hideItems.includes(item.path)) &&
!hideItems.includes(item.title) !hideItems.includes(item.title)
) )
case "show": case "show":
return ( return (
(item.path !== undefined && showItems!.includes(item.path)) || (item.type === "link" && showItems!.includes(item.path)) ||
showItems!.includes(item.title) showItems!.includes(item.title)
) )
case "all": case "all":
@@ -47,12 +51,16 @@ export const ChildDocs = ({
} }
} }
const filterItems = (items: SidebarItemType[]): SidebarItemType[] => { const filterItems = (items: SidebarItem[]): SidebarItem[] => {
return items return items
.filter(filterCondition) .filter(filterCondition)
.map((item) => Object.assign({}, item)) .map((item) => Object.assign({}, item))
.map((item) => { .map((item) => {
if (item.children && filterType === "hide") { if (
item.type !== "separator" &&
item.children &&
filterType === "hide"
) {
item.children = filterItems(item.children) item.children = filterItems(item.children)
} }
@@ -67,8 +75,7 @@ export const ChildDocs = ({
? Object.assign({}, currentItems) ? Object.assign({}, currentItems)
: undefined : undefined
: { : {
top: [...(getActiveItem()?.children || [])], default: [...(getActiveItem()?.children || [])],
bottom: [],
} }
if (filterType === "all" || !targetItems) { if (filterType === "all" || !targetItems) {
return targetItems return targetItems
@@ -76,25 +83,34 @@ export const ChildDocs = ({
return { return {
...targetItems, ...targetItems,
top: filterItems(targetItems.top), default: filterItems(targetItems.default),
bottom: filterItems(targetItems.bottom),
} }
}, [currentItems, type, getActiveItem, filterItems]) }, [currentItems, type, getActiveItem, filterItems])
const filterNonInteractiveItems = (
items: SidebarItem[] | undefined
): InteractiveSidebarItem[] => {
return (
(items?.filter(
(item) => item.type !== "separator"
) as InteractiveSidebarItem[]) || []
)
}
const getChildrenForLevel = ( const getChildrenForLevel = (
item: SidebarItemType, item: InteractiveSidebarItem,
currentLevel = 1 currentLevel = 1
): SidebarItemType[] | undefined => { ): InteractiveSidebarItem[] | undefined => {
if (currentLevel === childLevel) { if (currentLevel === childLevel) {
return item.children return filterNonInteractiveItems(item.children)
} }
if (!item.children) { if (!item.children) {
return return
} }
const childrenResult: SidebarItemType[] = [] const childrenResult: InteractiveSidebarItem[] = []
item.children.forEach((child) => { filterNonInteractiveItems(item.children).forEach((child) => {
const childChildren = getChildrenForLevel(child, currentLevel + 1) const childChildren = getChildrenForLevel(child, currentLevel + 1)
if (!childChildren) { if (!childChildren) {
@@ -107,20 +123,34 @@ export const ChildDocs = ({
return childrenResult return childrenResult
} }
const getTopLevelElms = (items?: SidebarItemType[]) => ( const getTopLevelElms = (items?: SidebarItem[]) => {
return (
<CardList <CardList
items={ items={
items?.map((childItem) => ({ 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, title: childItem.title,
href: childItem.path, href,
showLinkIcon: false, showLinkIcon: false,
})) || [] }
}) || []
} }
/> />
) )
}
const getAllLevelsElms = (items?: SidebarItemType[]) => const getAllLevelsElms = (items?: SidebarItem[]) =>
items?.map((item, key) => { filterNonInteractiveItems(items).map((item, key) => {
const itemChildren = getChildrenForLevel(item) const itemChildren = getChildrenForLevel(item)
const HeadingComponent = itemChildren?.length const HeadingComponent = itemChildren?.length
? MDXComponents["h2"] ? MDXComponents["h2"]
@@ -130,12 +160,16 @@ export const ChildDocs = ({
<React.Fragment key={key}> <React.Fragment key={key}>
{HeadingComponent && ( {HeadingComponent && (
<> <>
{!hideTitle && <HeadingComponent>{item.title}</HeadingComponent>} {!hideTitle && (
<HeadingComponent id={slugify(item.title)}>
{item.title}
</HeadingComponent>
)}
<CardList <CardList
items={ items={
itemChildren?.map((childItem) => ({ itemChildren?.map((childItem) => ({
title: childItem.title, title: childItem.title,
href: childItem.path, href: childItem.type === "link" ? childItem.path : "",
showLinkIcon: false, showLinkIcon: false,
})) || [] })) || []
} }
@@ -143,20 +177,19 @@ export const ChildDocs = ({
</> </>
)} )}
{!HeadingComponent && ( {!HeadingComponent && (
<Card title={item.title} href={item.path} showLinkIcon={false} /> <Card
title={item.title}
href={item.type === "link" ? item.path : ""}
showLinkIcon={false}
/>
)} )}
</React.Fragment> </React.Fragment>
) )
}) })
const getElms = (items?: SidebarItemType[]) => { const getElms = (items?: SidebarItem[]) => {
return onlyTopLevel ? getTopLevelElms(items) : getAllLevelsElms(items) return onlyTopLevel ? getTopLevelElms(items) : getAllLevelsElms(items)
} }
return ( return <>{getElms(filteredItems?.default)}</>
<>
{getElms(filteredItems?.top)}
{getElms(filteredItems?.bottom)}
</>
)
} }
@@ -1,39 +1,23 @@
"use client" "use client"
import React, { useCallback, useEffect, useRef, useState } from "react" import React, { useEffect, useRef, useState } from "react"
import { Button } from "@/components" import { Button } from "@/components"
import clsx from "clsx" import clsx from "clsx"
import { CSSTransition } from "react-transition-group" import { CSSTransition } from "react-transition-group"
import { HelpButtonActions } from "./Actions" import { HelpButtonActions } from "./Actions"
import { useIsBrowser } from "../.." import { useClickOutside } from "../.."
export const HelpButton = () => { export const HelpButton = () => {
const [showText, setShowText] = useState(false) const [showText, setShowText] = useState(false)
const [showHelp, setShowHelp] = useState(false) const [showHelp, setShowHelp] = useState(false)
const ref = useRef<HTMLDivElement>(null) const ref = useRef<HTMLDivElement>(null)
const isBrowser = useIsBrowser() useClickOutside({
elmRef: ref,
const onClickOutside = useCallback( onClickOutside: () => {
(e: MouseEvent) => {
if (!ref.current?.contains(e.target as Node)) {
setShowHelp(false) setShowHelp(false)
setShowText(false) setShowText(false)
}
}, },
[ref.current] })
)
useEffect(() => {
if (!isBrowser) {
return
}
window.document.addEventListener("click", onClickOutside)
return () => {
window.document.removeEventListener("click", onClickOutside)
}
}, [isBrowser])
useEffect(() => { useEffect(() => {
if (showHelp) { if (showHelp) {
@@ -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>
)
}
@@ -0,0 +1,60 @@
import { IconProps } from "@medusajs/icons/dist/types"
import React from "react"
export const MedusaIcon = (props: IconProps) => {
return (
<svg
width="21"
height="20"
viewBox="0 0 21 20"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<rect
x="0.5"
width="20"
height="20"
rx="4"
fill="url(#pattern0_10130_17928)"
/>
<rect
x="0.5"
width="20"
height="20"
rx="4"
fill="url(#pattern1_10130_17928)"
/>
<defs>
<pattern
id="pattern0_10130_17928"
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use xlinkHref="#image0_10130_17928" transform="scale(0.0025)" />
</pattern>
<pattern
id="pattern1_10130_17928"
patternContentUnits="objectBoundingBox"
width="1"
height="1"
>
<use xlinkHref="#image1_10130_17928" transform="scale(0.00121212)" />
</pattern>
<image
id="image0_10130_17928"
width="400"
height="400"
xlinkHref="data:image/png;base64,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 truncated
/>
<image
id="image1_10130_17928"
width="825"
height="825"
xlinkHref="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAzkAAAM5CAYAAAAkEv8ZAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUACf0ISURBVHgBbL1LsuNIlmxrBpAn7ifySjaqcRvZqGY1a2bpM3szeiJvBJkhFVkfPwTscRt0qSkYRZEIdz+HBAGz/dGt+2P9X//1X//8/f39/2zb1o7jGP/1X//Vv76+2r7v7T//8z/bn/70pzbGaP/4xz/a//pf/6v13uffH49H++WXX9rr9Wr/9m//1uoz9ff/8T/+hz9b76n/3tdsdf3zPOef9ar31c/rVe9/f/f8fL2fV33vz58//e/6vvr+uk79V9eo99ffua+6Vn2uvqf++4//+I/xfD57/f79u/H+nv7+d/28/e///b/nfdZ//+f//J/5XfW+uma9930/ve6p7q0+k/dXf77XreWrflafr++tP+s76u/1uVqf932N9797fd97Lcf7vntdm7Wpe681qXWuP+sa9Sx8F2tXf7Le78+N+n091/v+59/ff/ZaK+6HtazPcM9ct151P/X9eu553fp+/l3/8b31Pu6t/l17wBrVf7/++mt9/1zn+o56f30v61Pvrc/++7//+3hft9fn65541nrVv+vnrEl9rtay9qQ28n2/cx2RAe3zfG+tXf37fX2vW/287qF+Xp99/33eG2tR1/jtt9/mvbM2tSa15/Wq52IN6ud1r3W9z/Ut+WEPkUtevL++870G89n57voce1vXq/+0hnUP8znrXuqz9V50rP5dP6/vQ4fqPmrvS9ZqD1jHerF36GV9hvsvHX7/bLzf33le7qv2jPur56g14F65juRuvhdZ+fxcfX/dM3JQ34NO86r3p+zVv5EPbEXqFfvPvdTv0Nf6d60DNq22qXSa72Vdcu3qc9KTUXrEz+q/33//fX7mf/7P/znvibWoz2MfsDv1Pu6jZFEyM22RdKB0ddqCskPYwvodcocM1/chY3wP61jXkV2aelHy/37flBn2guvWfWGzWf96P/tR31f/TtlPWa77qHvg88g/9hb7Xmv3/p65YejEp50r+a73YHfQ4fQZ/I69ee/11Pv376b+1Gd4L7YG24huYBfqGshDiS56g+xgz7DVstFzTerf6ET9vN6DDPBMdT3sVz1zfVd9rj7PdyBztT51D+gY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 Line truncated
/>
</defs>
</svg>
)
}
@@ -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( className={clsx(
"rounded-docs_xs border-solid border border-medusa-border-base", "rounded-docs_xs border-solid border border-medusa-border-base",
"inline-flex items-center justify-center", "inline-flex items-center justify-center",
"py-0 px-[6px]", "py-0 px-docs_0.25",
"bg-medusa-bg-field", "bg-medusa-bg-field",
"text-medusa-tag-neutral-text", "text-medusa-fg-subtle",
"text-compact-x-small-plus font-base shadow-none", "text-compact-x-small-plus font-base shadow-none",
className 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>
)
}
@@ -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>
)
}
@@ -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]" />
}
@@ -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>
)
}
@@ -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} {...props}
className={clsx( className={clsx(
"fixed top-0 left-0 flex h-screen w-screen items-center justify-center", "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", "hidden open:flex border-0 p-0",
className 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>
)
}
Loaded 100 of 157 files, more files were not shown because too many files have changed in this diff. Show more