@fumadocs/base-ui 16.15.4 → 16.15.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- @source inline("!footer !isSelected !showItem *:col-start-1 *:max-w-[1285px] *:max-w-[900px] *:my-auto *:pointer-events-auto *:row-start-1 *:w-(--fd-sidebar-width) --fd-docs-height --fd-docs-row-1 --fd-docs-row-2 --fd-docs-row-3 --fd-header-height --fd-layout-width --fd-sidebar-col --fd-sidebar-width --fd-toc-popover-height --fd-toc-width -me-1.5 -ms-1.5 -mx-1 -translate-x-(--fd-sidebar-width) -translate-y-full [&_svg]:shrink-0 [--fd-docs-height:100dvh] [--fd-header-height:0px] [--fd-sidebar-width:0px] [--fd-toc-popover-height:0px] [--fd-toc-width:0px] [grid-area:header] [grid-area:main] [grid-area:sidebar] [grid-area:toc-popover] [grid-area:toc] after aria-valuemax aria-valuemin aria-valuenow article attribute auto-cols-auto auto-rows-auto available backdrop-blur-sm before before:absolute before:bg-fd-border before:content-[''] before:inset-y-1 before:start-2.5 before:w-px bg-fd-background/80 border-b-2 border-e border-fd-primary breadcrumb breadcrumbEnabled circleProps circumference clerk click collapseTrigger collapsing containerProps createLinkItemRenderer data-[active=true]:before:absolute data-[active=true]:before:bg-fd-primary data-[active=true]:before:content-[''] data-[active=true]:before:inset-y-2.5 data-[active=true]:before:start-2.5 data-[active=true]:before:w-px data-[active=true]:bg-fd-primary/10 data-[active=true]:hover:transition-colors data-[collapsed=false]:hidden data-[column-changed=true]:transition-[grid-template-columns] data-[state=closed]:animate-fd-fade-out data-[state=closed]:animate-fd-sidebar-out data-[state=open]:animate-fd-fade-in data-[state=open]:animate-fd-sidebar-in data-[transparent=false]:bg-fd-background/80 data-column-changed data-full data-header-body data-header-tabs data-hovered data-layout-content data-layout-main data-sidebar-collapsed data-sidebar-placeholder data-toc-popover data-toc-popover-content data-toc-popover-trigger data-transparent defaultSlots delaySetOpen desktop duration-250 edit end-0 flex-row-reverse font-semibold footer footerEnabled footerList freezeUntil fumadocs-core/breadcrumb gap-2.5 gap-6 getBreadcrumbItemsFromPath grid-cols-1 gridTemplate h-(--fd-toc-popover-height) h-10 h-14 h-[calc(var(--fd-docs-height)-var(--fd-docs-row-1))] h-[calc(var(--fd-docs-height)-var(--fd-docs-row-2))] h-[calc(var(--fd-docs-height)-var(--fd-docs-row-3))] has-data-[active=true]:text-fd-primary has-data-[collapsed=true]:md:flex hideIfDisabled hover:bg-fd-accent/50 hover:opacity-80 hover:text-fd-accent-foreground/80 hover:transition-none hoverDelay iconLinks including information inset-y-2 instant isCollapseChanged isLayoutTabActive isNavTransparent isSelected isTop items-end justify-end layout-level layout:[--fd-header-height:--spacing(14)] lg:hidden lg:layout:[--fd-header-height:--spacing(24)] linkItems max max-h-[50vh] max-lg:flex max-lg:hidden max-md:flex max-md:hidden max-w-[240px] max-w-[380px] max-w-sm max-xl:hidden max-xl:layout:[--fd-toc-popover-height:--spacing(10)] maxTouchPoints mb-4 mb-8 mb-auto md:gap-2 md:layout:[--fd-sidebar-width:268px] md:pt-8 md:px-6 min min-h-(--fd-docs-height) ms-px mt-px mx-0.5 navEnabled navMode navTransparentMode navbar nd-notebook-layout nd-page nd-subnav nd-toc nd-toc-placeholder no normalizedValue onClickItem onClickOutside ontouchstart pageCol pagination pb-1.5 pe-4 pointer-events-none popover previousCollapsed progress progressbar provided ps-2.5 pt-0.5 pt-12 pt-2 px-6 py-6 radius resolvedTabs restSvgProps rotate-180 rtl:-translate-x-2 rtl:translate-x-full selectedIdx setDate setPreviousCollapsed showItem showLayoutTabs sidebarCollapsible sidebarProps single size-4.5 start-0 stroke-current/25 strokeDasharray strokeDashoffset tabMode tableOfContent tableOfContentPopover text-[1.75em] text-end text-fd-foreground timeoutRef timezone toc-popover toc-title tocEnabled tocPopover tocPopoverEnabled tocPopoverProps tocProps top-(--fd-docs-row-1) top-(--fd-docs-row-2) top-(--fd-docs-row-3) transition-[opacity,translate,color] transition-[opacity,translate] transition-[width,inset-block,translate,background-color] translate-x-2 translate-y-full transparentMode typography under unlisted updated useBaseSlots useDocsPage useFooterItems useIsScrollTop useNotebookLayout w-(--fd-sidebar-width) w-(--fd-toc-width) w-4 w-[85%] xl:hidden xl:layout:[--fd-toc-width:268px] xl:pt-14 xl:px-8 z-10 z-20");
1
+ @source inline("!footer !isSelected !showItem *:col-start-1 *:max-w-[1285px] *:max-w-[900px] *:my-auto *:pointer-events-auto *:row-start-1 *:w-(--fd-sidebar-width) --fd-docs-height --fd-docs-row-1 --fd-docs-row-2 --fd-docs-row-3 --fd-header-height --fd-layout-width --fd-sidebar-col --fd-sidebar-width --fd-toc-popover-height --fd-toc-width -me-1.5 -ms-1.5 -mx-1 -translate-x-(--fd-sidebar-width) -translate-y-full [&_svg]:shrink-0 [--fd-docs-height:100dvh] [--fd-header-height:0px] [--fd-sidebar-width:0px] [--fd-toc-popover-height:0px] [--fd-toc-width:0px] [grid-area:header] [grid-area:main] [grid-area:sidebar] [grid-area:toc-popover] [grid-area:toc] after aria-valuemax aria-valuemin aria-valuenow article attribute auto-cols-auto auto-rows-auto available backdrop-blur-sm before before:absolute before:bg-fd-border before:content-[''] before:inset-y-1 before:start-2.5 before:w-px bg-fd-background/80 border-b-2 border-e border-fd-primary breadcrumb breadcrumbEnabled circleProps circumference clerk click collapseTrigger collapsing containerProps createLinkItemRenderer data-[active=true]:before:absolute data-[active=true]:before:bg-fd-primary data-[active=true]:before:content-[''] data-[active=true]:before:inset-y-2.5 data-[active=true]:before:start-2.5 data-[active=true]:before:w-px data-[active=true]:bg-fd-primary/10 data-[active=true]:hover:transition-colors data-[collapsed=false]:hidden data-[column-changed=true]:transition-[grid-template-columns] data-[state=closed]:animate-fd-fade-out data-[state=closed]:animate-fd-sidebar-out data-[state=open]:animate-fd-fade-in data-[state=open]:animate-fd-sidebar-in data-[transparent=false]:bg-fd-background/80 data-column-changed data-full data-header-body data-header-tabs data-hovered data-layout-content data-layout-main data-sidebar-collapsed data-sidebar-placeholder data-toc-popover data-toc-popover-content data-toc-popover-trigger data-transparent defaultSlots delaySetOpen desktop duration-250 edit end-0 flex-row-reverse font-semibold footer footerEnabled footerList freezeUntil fumadocs-core/breadcrumb gap-2.5 gap-6 getBreadcrumbItemsFromPath grid-cols-1 gridTemplate h-(--fd-toc-popover-height) h-10 h-14 h-[calc(var(--fd-docs-height)-var(--fd-docs-row-1))] h-[calc(var(--fd-docs-height)-var(--fd-docs-row-2))] h-[calc(var(--fd-docs-height)-var(--fd-docs-row-3))] has-data-[active=true]:text-fd-primary has-data-[collapsed=true]:md:flex hideIfDisabled hover:bg-fd-accent/50 hover:opacity-80 hover:text-fd-accent-foreground/80 hover:transition-none hoverDelay iconLinks including information inset-y-2 instant isCollapseChanged isLayoutTabActive isNavTransparent isSelected isTop items-end justify-end layout-level layout:[--fd-header-height:--spacing(14)] lg:hidden lg:layout:[--fd-header-height:--spacing(24)] linkItems max max-h-[50vh] max-lg:flex max-lg:hidden max-md:flex max-md:hidden max-w-[240px] max-w-[380px] max-w-sm max-xl:hidden max-xl:layout:[--fd-toc-popover-height:--spacing(10)] maxTouchPoints mb-4 mb-8 mb-auto md:gap-2 md:layout:[--fd-sidebar-width:268px] md:pt-8 md:px-6 min min-h-(--fd-docs-height) ms-px mt-px mx-0.5 navEnabled navMode navTransparentMode navbar nd-notebook-layout nd-page nd-subnav nd-toc nd-toc-placeholder no normalizedValue onClickItem onClickOutside ontouchstart pageCol pagination pb-1.5 pe-4 pointer-events-none popover previousCollapsed progress progressbar provided ps-2.5 pt-0.5 pt-12 pt-2 px-6 py-6 radius resolvedTabs restSvgProps rotate-180 rtl:-translate-x-2 rtl:translate-x-full selectedIdx setDate setPreviousCollapsed showItem showLayoutTabs sidebarCollapsible sidebarProps single size-4.5 start-0 stroke-current/25 strokeDasharray strokeDashoffset tabMode tableOfContent tableOfContentPopover text-[1.75em] text-end text-fd-foreground timeoutRef timezone toc-popover toc-title tocEnabled tocPopover tocPopoverEnabled tocPopoverProps tocProps top-(--fd-docs-row-1) top-(--fd-docs-row-2) top-(--fd-docs-row-3) transition-[opacity,translate,color] transition-[opacity,translate] transition-[width,inset-block,translate,background-color] translate-x-2 translate-y-full transparentMode typedTabs typography under unlisted updated useBaseSlots useDocsPage useFooterItems useIsScrollTop useNotebookLayout w-(--fd-sidebar-width) w-(--fd-toc-width) w-4 w-[85%] xl:hidden xl:layout:[--fd-toc-width:268px] xl:pt-14 xl:px-8 z-10 z-20");
@@ -1 +1 @@
1
- @source inline("!collapsed !isActive !items !nested !open !title *:border-b *:data-[empty=true]:border-b-0 *:flex *:flex-col *:has-[+:last-child[data-empty=true]]:border-b-0 *:last:border-b-0 *:rounded-full --accordion-panel-height --anchor-width --available-height --callout-color --collapsible-panel-height --color-fd- --color-fd-muted --fd-animated-height --fd-banner-height --offset-distance --opacity --padding-right --shiki-dark-bg --shiki-light-bg --spacing --track-bottom --track-top --transform-origin -mb-px -me-0.5 -me-2 -mx-px -rotate-90 -top-1.5 -translate-x-1/2 -translate-y-1/2 -z-1 @container @defaultValue @deprecated @fuma-translate/react @keyframes @max-lg:col-span-full @max-xl:hidden @param @ts-expect-error @typescript-eslint/no-namespace [&>figure:only-child]:-m-4 [&>figure:only-child]:border-none [&[hidden]:not([hidden='until-found'])]:hidden [&_svg]:size-3.5 [&_svg]:size-4 [&_svg]:size-4.5 [&_svg]:size-5 [&_svg]:size-full [&_svg]:text-fd-muted-foreground [offset-distance:var(--offset-distance,0)] [scrollbar-width:none] a abcdefghijklmnopqrstuvwxyz234567 about absolute accordion action actions active add addEventListener advanced algoliaClient align alignItems alignmentBaseline all allowClear allowCopy allowDangerousHtml allows alphabet always an anchor and animate-pulse animation another application/json areaRef aria-controls aria-describedby aria-expanded aria-label aria-selected as aside ask assume assumes async at auto await backdrop-blur-lg backdrop-blur-xs background background-position backgroundColor backgroundImage backgroundSize backward banner basePath baseProps baseSlots baseUrl based behaviour belongs bg-(--callout-color)/50 bg-(--shiki-light-bg) bg-fd-accent bg-fd-background bg-fd-border bg-fd-card bg-fd-muted bg-fd-overlay bg-fd-popover bg-fd-popover/60 bg-fd-primary bg-fd-primary/10 bg-fd-secondary bg-fd-secondary/50 bg-transparent bind bitsLeft black block blocks boolean border border-b border-l border-none border-s border-t border-transparent borderBottom bottom bottom-0 bottom-1.5 bound boundary buffer bundle button buttonVariants by cache cached can case center central change changeLayout checked child children chooseLanguage class-variance-authority className clear client client-side clientHeight clientWidth clipPath clone close closeOnRedirect closed cn code col-span-full collapsed collapsible collection color colors column com compact compat compatibility component components composedRef computed config const container containerRef containing content contents context controlled/uncontrolled copy core counterSet createContext createMarkdownRenderer createRelativeLink css ctx current currentColor custom customize cva cx cy d dangerouslySetInnerHTML dark dark:bg-(--shiki-dark-bg) dashed data data-[active=true]:text-fd-primary data-[active]:border-fd-primary data-[active]:text-fd-primary data-[inactive]:hidden data-[popup-open]:bg-fd-accent data-[popup-open]:text-fd-accent-foreground data-accordion-value data-active data-card data-checked data-checked:text-fd-accent-foreground data-closed:animate-fd-dialog-out data-closed:animate-fd-fade-out data-closed:animate-fd-popover-out data-collapsed data-empty data-ending-style:h-0 data-ending-style:opacity-0 data-fd-search-dialog-input data-icon data-line-numbers data-line-numbers-start data-open:animate-fd-dialog-in data-open:animate-fd-fade-in data-open:animate-fd-popover-in data-open:bg-fd-accent data-open:text-fd-accent-foreground data-search data-search-full data-starting-style:h-0 data-starting-style:opacity-0 data-state data-theme-toggle date debounced declare default defaultColor defaultFormatter defaultIndex defaultItems defaultMdxComponents defaultOpen defaultOpenLevel defaultShikiFactory defaultTransform defaultUrl defaultValue defineI18nUI defined delay delayMs depends deprecated depth description detect dialog dialogHandle dir disabled disabled:opacity-50 disabled:pointer-events-none display displayName displayed distance div divide-fd-border divide-x divide-y documented dominantBaseline don drawer duration-100 duration-200 duration-400 ease-out element else empty empty:hidden empty:mb-0 enabled encoded endIdx endpoint env environment equal error escape eslint-disable-next-line event export extends external extraProps false fd-moving-banner fd-scroll-container fd-search-dialog-content fd-step fd-steps fetch fetchClient fetchOptions field fieldVariants figure file fill fill-(--callout-color) fill-fd-muted fill-fd-muted-foreground fill-fd-primary fill-fd-primary-foreground filter filters finally first:mt-0 fixed flex flex-1 flex-col flex-row flex-wrap flexDirection flushSync focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fd-ring focus-visible:ring-inset folder folders font-medium font-mono fontSize fontWeight for forks formatter formatterOptions found fragment free from full fumadocs fumadocs-core/framework fumadocs-core/highlight fumadocs-core/i18n fumadocs-core/link fumadocs-core/page-tree fumadocs-core/search fumadocs-core/source fumadocs-core/toc function gap gap-0.5 gap-1 gap-1.5 gap-2 gap-3 gap-3.5 gap-4 gap-y-4 generated ghost github-dark github-light githubUrl global globalKey grid grid-cols-2 grid-cols-[1fr_3fr] group group-data-[open]:rotate-180 group-data-active:bg-fd-primary group-data-open:rotate-180 group-data-panel-open:rotate-90 group-hover/heading:opacity-100 group/heading groupListeners guides h h-(--accordion-panel-height) h-(--collapsible-panel-height) h-(--fd-animated-height) h-1.5 h-9.5 h-[calc(100%+--spacing(1.5))] h-full h-px h1 h2 h3 h4 h5 h6 handle handleThemeChange has-focus-visible:bg-fd-accent hash hashchange hast have header headers heading height hidden highlight highlighter hints horizontal hover:bg-fd-accent hover:bg-fd-accent/80 hover:bg-fd-primary/80 hover:text-fd-accent-foreground hovered hovering href html i i18n i18nProvider icon icon-sm icon-xs iconClass id idea idx if if-needed ignore img import in inPre inTab index infinite info initialFocus inline inline-flex input inputType inset-0 inset-e-2 inset-s-0 inset-s-3 inset-s-6 inset-x-2 inset-y-0 inside instanceof instead integration interface intersect invisible is isActive isFirst isLast isLoading isUp it item itemLineLengths itemVariants items items-center js justify-between justify-center keepBackground keepMounted key keydown keys l l0 l1 l2 label lang language languageSelect languages last:rounded-b-xl layer layout leading-none leaving left-0 left-1/2 length let level light light-dark light-dark-system line line-through linear link links list listener listeners localRef locale localeTranslations locales lower ltr lucide lucide-book lucide-book-icon lucide-react made main make mapped margin marginTop mark markdownUrl marked mask-[linear-gradient(to_bottom,transparent,white_12px,white_calc(100%-12px),transparent)] mask-[linear-gradient(to_bottom,transparent,white_16px,white_calc(100%-16px),transparent)] mask-[linear-gradient(to_bottom,white,white_30px,transparent_80px)] maskComposite maskImage max-h-(--available-height) max-h-20 max-h-[460px] max-h-[600px] max-md:bg-fd-secondary max-md:border max-md:p-1.5 max-md:rounded-md max-w-[1400px] max-w-[98vw] max-w-full max-w-screen-sm max-width maximumFractionDigits mb-1 mb-1.5 mb-2 md:hidden md:mb-auto md:size-5 md:top-[calc(50%-250px)] mdComponents mdRenderer mdx/types.js me-1 me-2 me-auto menu menuItems mergeRefs message middle min-h-0 min-w-0 min-w-[240px] min-w-fit min-w-full mode module mounted mouse ms-2 ms-auto mt-1 mt-6 must mx-auto my-0 my-0! my-0.5 my-4 my-6 my-auto n name namespace nav navItems navTitle navigate navigation nd-copy-ignore nd-sidebar nd-sidebar-mobile nearest needed nested nested-url never new newTheme next next-themes next/og node nodes none noopener noreferrer normal normalize not not-last:mb-2 not-prose notation note now null number numbers object observer of offsetPath offsetTop on onAnimationEnd onChange onClick onCopy onKey onOpenChange onOpenChangeCallback onPointerEnter onPointerLeave onPointerMove onPrint onSearchChange onSearchChangeCallback onSelect onSelectCallback onTagChange onTagChangeCallback onValueChange once only opacity-(--opacity,0) opacity-0 open openFromHash option optional options or oramaCloudClient order orientation origin-(--transform-origin) origin-center original other out outline outline-none output overflow-auto overflow-hidden overflow-x-auto overflow-x-clip overflow-y-auto override overscroll-contain own owner p p-0.5 p-1 p-1.5 p-2 p-3 p-4 padding paddingBottom paddingInlineStart page pageUrl panel panels parameters params parentId pass passed path pathname paths pb-0 pb-2 pe-2 performing persist persistent placeholder placeholder:text-fd-muted-foreground please pointerType points populated positions possible powered pre pre-rendering prefetch prev preventScroll previous previousRef primary primaryColor primaryTextColor promise promises prompt prop props prose prose-no-margin provide provider ps-1 ps-2 ps-4 ps-8 pt-0 pure px px-0.5 px-1 px-1.5 px-2 px-2.5 px-3 px-4 px-px py-0.5 py-1 py-1.5 py-12 py-2 py-2.5 py-3 py-3.5 q query querySelector questions rainbow rainbowColors raw re-create react react-dom react-hooks/rules-of-hooks react-medium-image-zoom ref referenced region registering rehype-raw rehypeCustomElements rehypePlugins rehypeRaw rel relative remarkRehypeOptions remove removeEventListener render renderHighlights renderMarkdown repo repository required resolve resolved resolvedTheme response rest result results return revalidate right-2 role root rootRef round rounded-2xl rounded-[inherit] rounded-full rounded-lg rounded-md rounded-sm rounded-xl router row rtl:-scale-x-100 rtl:rotate-180 rtl:rotate-90 s scroll scroll-into-view-if-needed scroll-m-20 scroll-m-24 scroll-m-28 scroll-m-4 scrollIntoView scrollMode search searchOptions searchToggle searchToggleEnabled searchTrigger secondary see select-none selected separate separator server set setActive setCollapsed setHidden setHover setLoading setMounted setOpen setSvg setTag setValue shadow-2xl shadow-lg shadow-md shadow-sm shiki shikiOptions shortcuts show showAlgolia showOrama shrink-0 side sideOffset sidebar signature simple since site size size-1 size-3 size-3.5 size-4 size-5 size-6.5 size-9 size-full sizes slots sm solid some source space span specific src stars startIdx state static stay sticky still str string stroke stroke-fd-foreground/10 stroke-fd-primary strokeLinecap strokeLinejoin strokeWidth strong style styles success supported supposed sure svg switch switcher system t tab tabIndex table tabs tabsRef tag tagName tags target text text-(--callout-color) text-[0.8125rem] text-[0.9375rem] text-center text-fd-accent-foreground text-fd-card text-fd-card-foreground text-fd-foreground/80 text-fd-muted-foreground text-fd-muted-foreground/50 text-fd-popover-foreground text-fd-popover-foreground/80 text-fd-primary text-fd-primary-foreground text-fd-primary/50 text-fd-secondary-foreground text-lg text-nowrap text-sm text-start text-xs text/plain textAnchor textContent that the their theme themeAriaLabels themeSwitch themeSwitchEnabled themes then this throw thumbBox tier timerRef tip title to toc tocInfo toolbar top top-0 top-1/2 top-2 top-2.5 top-4 touch transform transition-[clip-path] transition-[height,opacity] transition-[height] transition-[opacity,offset-distance] transition-all transition-colors transition-opacity transition-transform translationKeys translations translations/keys.json transparent tree trigger true truncate try type typeof types unchanged undefined underline underlying understand unified unist-util-visit unknown unnecessarily updateAnchor updates upperX url urls us usage use useCopyButton useDocsSearch useI18n useId useIsDocsLayout useItems useMediaQuery useMemo useOnChange usePathname useProps useRef useRouter useSearchContext useSidebar useState useTOCItems useTheme useTranslations useTreePath useful users using usually v v17 value valueToIdMap values variables variant variants vertical viewBox viewRef viewport viewportProps visit vite void w w-(--anchor-width) w-0 w-0.5 w-1.5 w-1/4 w-[calc(100%-1rem)] w-fit w-full w-max w-px want warn warning what when where which while white whitespace-nowrap whitespaces width will window with work wrap wrap-anywhere wrapElement wrapInSuspense wrapped x x1 x2 xmlns y y1 y2 you your z-2 z-40 z-50 zoom zoomImg zoomMargin");
1
+ @source inline("!collapsed !isActive !items !nested !open !title *:border-b *:data-[empty=true]:border-b-0 *:flex *:flex-col *:has-[+:last-child[data-empty=true]]:border-b-0 *:last:border-b-0 *:rounded-full --accordion-panel-height --anchor-width --available-height --callout-color --collapsible-panel-height --color-fd- --color-fd-muted --fd-animated-height --fd-banner-height --offset-distance --opacity --padding-right --shiki-dark-bg --shiki-light-bg --spacing --track-bottom --track-top --transform-origin -mb-px -me-0.5 -me-2 -mx-px -rotate-90 -top-1.5 -translate-x-1/2 -translate-y-1/2 -z-1 @container @defaultValue @deprecated @fuma-translate/react @keyframes @max-lg:col-span-full @max-xl:hidden @param @ts-expect-error @typescript-eslint/no-namespace [&>figure:only-child]:-m-4 [&>figure:only-child]:border-none [&[hidden]:not([hidden='until-found'])]:hidden [&_svg]:size-3.5 [&_svg]:size-4 [&_svg]:size-4.5 [&_svg]:size-5 [&_svg]:size-full [&_svg]:text-fd-muted-foreground [offset-distance:var(--offset-distance,0)] [scrollbar-width:none] a abcdefghijklmnopqrstuvwxyz234567 about absolute accordion action actions active add addEventListener advanced algoliaClient align alignItems alignmentBaseline all allowClear allowCopy allowDangerousHtml allows alphabet always an anchor and animate-pulse animation another application/json areaRef aria-controls aria-describedby aria-expanded aria-label aria-selected as aside ask assume assumes async at auto await backdrop-blur-lg backdrop-blur-xs background background-position backgroundColor backgroundImage backgroundSize backward banner basePath baseProps baseSlots baseUrl based behaviour belongs between bg-(--callout-color)/50 bg-(--shiki-light-bg) bg-fd-accent bg-fd-background bg-fd-border bg-fd-card bg-fd-muted bg-fd-overlay bg-fd-popover bg-fd-popover/60 bg-fd-primary bg-fd-primary/10 bg-fd-secondary bg-fd-secondary/50 bg-transparent bind bitsLeft black block blocks boolean border border-b border-l border-none border-s border-t border-transparent borderBottom bottom bottom-0 bottom-1.5 bound boundary buffer bundle button buttonVariants by cache cached can case center central change changeLayout checked child children chooseLanguage class-variance-authority className clear client client-side clientHeight clientWidth clipPath clone close closeOnRedirect closed cn code col-span-full collapsed collapsible collection color colors column com compact compat compatibility component components composedRef computed config const container containerRef containing content contents context controlled/uncontrolled copy core counterSet createContext createMarkdownRenderer createRelativeLink css ctx current currentColor custom customize cva cx cy d dangerouslySetInnerHTML dark dark:bg-(--shiki-dark-bg) dashed data data-[active=true]:text-fd-primary data-[active]:border-fd-primary data-[active]:text-fd-primary data-[inactive]:hidden data-[popup-open]:bg-fd-accent data-[popup-open]:text-fd-accent-foreground data-accordion-value data-active data-card data-checked data-checked:text-fd-accent-foreground data-closed:animate-fd-dialog-out data-closed:animate-fd-fade-out data-closed:animate-fd-popover-out data-collapsed data-empty data-ending-style:h-0 data-ending-style:opacity-0 data-fd-search-dialog-input data-icon data-line-numbers data-line-numbers-start data-open:animate-fd-dialog-in data-open:animate-fd-fade-in data-open:animate-fd-popover-in data-search data-search-full data-starting-style:h-0 data-starting-style:opacity-0 data-state data-theme-toggle date debounced declare default defaultColor defaultFormatter defaultIndex defaultItems defaultMdxComponents defaultOpen defaultOpenLevel defaultShikiFactory defaultTransform defaultUrl defaultValue defineI18nUI defined delay delayMs depends deprecated depth description detect dialog dialogHandle dir disabled disabled:opacity-50 disabled:pointer-events-none display displayName displayed distance div divide-fd-border divide-x divide-y documented dominantBaseline don drawer dropdown duration-100 duration-200 duration-400 each ease-out element else empty empty:hidden empty:mb-0 enabled encoded endIdx endpoint env environment equal error escape eslint-disable-next-line event export extends external extraProps false fd-moving-banner fd-scroll-container fd-search-dialog-content fd-step fd-steps fetch fetchClient fetchOptions field fieldVariants figure file fill fill-(--callout-color) fill-fd-muted fill-fd-muted-foreground fill-fd-primary fill-fd-primary-foreground filter filters finally first:mt-0 fixed flex flex-1 flex-col flex-row flex-wrap flexDirection flushSync focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fd-ring focus-visible:ring-inset folder folders font-medium font-mono fontSize fontWeight for forks formatter formatterOptions found fragment free from full fumadocs fumadocs-core/framework fumadocs-core/highlight fumadocs-core/i18n fumadocs-core/link fumadocs-core/page-tree fumadocs-core/search fumadocs-core/source fumadocs-core/toc function gap gap-0.5 gap-1 gap-1.5 gap-2 gap-3 gap-3.5 gap-4 gap-y-4 generated ghost github-dark github-light githubUrl given global globalKey grid grid-cols-2 grid-cols-[1fr_3fr] group group-data-[open]:rotate-180 group-data-active:bg-fd-primary group-data-open:rotate-180 group-data-panel-open:rotate-90 group-hover/heading:opacity-100 group/heading groupListeners groups guides h h-(--accordion-panel-height) h-(--collapsible-panel-height) h-(--fd-animated-height) h-1.5 h-9.5 h-[calc(100%+--spacing(1.5))] h-full h-px h1 h2 h3 h4 h5 h6 handle handleThemeChange has-focus-visible:bg-fd-accent hash hashchange hast have header headers heading height hidden highlight highlighter hints horizontal hover:bg-fd-accent hover:bg-fd-accent/80 hover:bg-fd-primary/80 hover:text-fd-accent-foreground hovered hovering href html i i18n i18nProvider icon icon-sm icon-xs iconClass id idea idx if if-needed ignore img import in inPre inTab index infinite info initialFocus inline inline-flex input inputType inset-0 inset-e-2 inset-s-0 inset-s-3 inset-s-6 inset-x-2 inset-y-0 inside instanceof instead integration interface intersect invisible is isActive isComposing isFirst isLast isLoading isUp it item itemLineLengths itemVariants items items-center js justify-between justify-center keepBackground keepMounted key keyCode keydown keys l l0 l1 l2 label lang language languageSelect languages last:rounded-b-xl layer layout leading-none leaving left-0 left-1/2 length let letting level light light-dark light-dark-system line line-through linear link links list listener listeners localRef locale localeTranslations locales lower ltr lucide lucide-book lucide-book-icon lucide-react made main make mapped margin marginTop mark markdownUrl marked mask-[linear-gradient(to_bottom,transparent,white_12px,white_calc(100%-12px),transparent)] mask-[linear-gradient(to_bottom,transparent,white_16px,white_calc(100%-16px),transparent)] mask-[linear-gradient(to_bottom,white,white_30px,transparent_80px)] maskComposite maskImage max-h-(--available-height) max-h-20 max-h-[460px] max-h-[600px] max-md:bg-fd-secondary max-md:border max-md:p-1.5 max-md:rounded-md max-w-[1400px] max-w-[98vw] max-w-full max-w-screen-sm max-width maximumFractionDigits mb-1 mb-1.5 mb-2 md:hidden md:mb-auto md:size-5 md:top-[calc(50%-250px)] mdComponents mdRenderer mdx/types.js me-1 me-2 me-auto menu menuItems mergeRefs message middle min-h-0 min-w-0 min-w-[240px] min-w-fit min-w-full mode module mounted mouse ms-2 ms-auto mt-1 mt-6 must mx-auto my-0 my-0! my-0.5 my-4 my-6 my-auto n name namespace nav navItems navTitle navigate navigation nd-copy-ignore nd-sidebar nd-sidebar-mobile nearest needed nested nested-url never new newTheme next next-themes next/og node nodes none noopener noreferrer normal normalize not not-last:mb-2 not-prose notation note now null number numbers object observer of offsetPath offsetTop on onAnimationEnd onChange onClick onCopy onKey onOpenChange onOpenChangeCallback onPointerEnter onPointerLeave onPointerMove onPrint onSearchChange onSearchChangeCallback onSelect onSelectCallback onTagChange onTagChangeCallback onValueChange once one only opacity-(--opacity,0) opacity-0 open openFromHash option optional options or oramaCloudClient order orientation origin-(--transform-origin) origin-center original other out outline outline-none output overflow-auto overflow-hidden overflow-x-auto overflow-x-clip overflow-y-auto override overscroll-contain own owner p p-0.5 p-1 p-1.5 p-2 p-3 p-4 padding paddingBottom paddingInlineStart page pageUrl panel panels parameters params parentId pass passed path pathname paths pb-0 pb-2 pe-2 per performing persist persistent placeholder placeholder:text-fd-muted-foreground please pointerType points populated positions possible powered pre pre-rendering prefetch prev preventScroll previous previousRef primary primaryColor primaryTextColor promise promises prompt prop props prose prose-no-margin provide provider ps-1 ps-2 ps-4 ps-8 pt-0 pure px px-0.5 px-1 px-1.5 px-2 px-2.5 px-3 px-4 px-px py-0.5 py-1 py-1.5 py-12 py-2 py-2.5 py-3 py-3.5 q query querySelector questions rainbow rainbowColors raw re-create react react-dom react-hooks/rules-of-hooks react-medium-image-zoom ref referenced region registering rehype-raw rehypeCustomElements rehypePlugins rehypeRaw rel relative remarkRehypeOptions remove removeEventListener render renderHighlights renderMarkdown repo repository required resolve resolved resolvedTheme response rest result results return revalidate right-2 role root rootRef round rounded-2xl rounded-[inherit] rounded-full rounded-lg rounded-md rounded-sm rounded-xl router row rtl:-scale-x-100 rtl:rotate-180 rtl:rotate-90 s same scroll scroll-into-view-if-needed scroll-m-20 scroll-m-24 scroll-m-28 scroll-m-4 scrollIntoView scrollMode search searchOptions searchToggle searchToggleEnabled searchTrigger secondary see select-none selected separate separator server set setActive setCollapsed setHidden setHover setLoading setMounted setOpen setSvg setTag setValue shadow-2xl shadow-lg shadow-md shadow-sm shiki shikiOptions shortcuts show showAlgolia showOrama shrink-0 side sideOffset sidebar signature simple since site size size-1 size-3 size-3.5 size-4 size-5 size-6.5 size-9 size-full sizes slots sm solid some source space span specific src stars startIdx state static stay sticky still str string stroke stroke-fd-foreground/10 stroke-fd-primary strokeLinecap strokeLinejoin strokeWidth strong style styles success supported supposed sure svg switch switcher system t tab tabIndex table tabs tabsRef tag tagName tags target text text-(--callout-color) text-[0.8125rem] text-[0.9375rem] text-center text-fd-accent-foreground text-fd-card text-fd-card-foreground text-fd-foreground/80 text-fd-muted-foreground text-fd-muted-foreground/50 text-fd-popover-foreground text-fd-popover-foreground/80 text-fd-primary text-fd-primary-foreground text-fd-primary/50 text-fd-secondary-foreground text-lg text-nowrap text-sm text-start text-xs text/plain textAnchor textContent that the their theme themeAriaLabels themeSwitch themeSwitchEnabled themes then this throw thumbBox tier timerRef tip title to toc tocInfo toolbar top top-0 top-1/2 top-2 top-2.5 top-4 touch transform transition-[clip-path] transition-[height,opacity] transition-[height] transition-[opacity,offset-distance] transition-all transition-colors transition-opacity transition-transform translationKeys translations translations/keys.json transparent tree trigger true truncate try type typeof types unchanged undefined underline underlying understand unified unist-util-visit unknown unnecessarily updateAnchor updates upperX url urls us usage use useCopyButton useDocsSearch useI18n useId useIsDocsLayout useItems useMediaQuery useMemo useOnChange usePathname useProps useRef useRouter useSearchContext useSidebar useState useTOCItems useTheme useTranslations useTreePath useful users using usually v v17 value valueToIdMap values variables variant variants vertical viewBox viewRef viewport viewportProps visit vite void w w-(--anchor-width) w-0 w-0.5 w-1.5 w-1/4 w-[calc(100%-1rem)] w-fit w-full w-max w-px want warn warning what when where which while white whitespace-nowrap whitespaces width will window with work wrap wrap-anywhere wrapElement wrapInSuspense wrapped x x1 x2 xmlns y y1 y2 you your z-2 z-40 z-50 zoom zoomImg zoomMargin");
@@ -215,7 +215,7 @@ function SearchDialogList({ items = null, Empty = () => /* @__PURE__ */ jsx("div
215
215
  const { onSelect } = useSearch();
216
216
  const [active, setActive] = useState(() => items && items.length > 0 ? items[0].id : null);
217
217
  const onKey = useEffectEvent((e) => {
218
- if (!items || e.isComposing) return;
218
+ if (!items || e.isComposing || e.keyCode === 229) return;
219
219
  if (e.key === "ArrowDown" || e.key == "ArrowUp") {
220
220
  let idx = items.findIndex((item) => item.id === active);
221
221
  if (idx === -1) idx = 0;
@@ -2,9 +2,13 @@ import { LayoutTab } from "../../../layouts/shared/index.js";
2
2
  import { ComponentProps, ReactNode } from "react";
3
3
  //#region src/components/sidebar/tabs/dropdown.d.ts
4
4
  type SidebarTabWithProps = LayoutTab;
5
+ /**
6
+ * Renders the given tabs as a dropdown per tabs group, one for each root folder on the
7
+ * current page's path, letting users switch between root folders of the same type.
8
+ */
5
9
  declare function SidebarTabsDropdown({ options, placeholder, ...props }: {
6
10
  placeholder?: ReactNode;
7
- options: SidebarTabWithProps[];
8
- } & ComponentProps<'button'>): import("react").JSX.Element;
11
+ options: LayoutTab[];
12
+ } & ComponentProps<'button'>): import("react").JSX.Element[];
9
13
  //#endregion
10
14
  export { SidebarTabWithProps, SidebarTabsDropdown };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../../../utils/cn.js";
3
- import { useTreePath } from "../../../contexts/tree.js";
3
+ import { useTabsGroups, useTreePath } from "../../../contexts/tree.js";
4
4
  import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.js";
5
5
  import { isLayoutTabActive } from "../../../layouts/shared/index.js";
6
6
  import { useSidebar } from "../base.js";
@@ -10,7 +10,18 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
10
  import { Check, ChevronsUpDown } from "lucide-react";
11
11
  import { useMemo, useState } from "react";
12
12
  //#region src/components/sidebar/tabs/dropdown.tsx
13
+ /**
14
+ * Renders the given tabs as a dropdown per tabs group, one for each root folder on the
15
+ * current page's path, letting users switch between root folders of the same type.
16
+ */
13
17
  function SidebarTabsDropdown({ options, placeholder, ...props }) {
18
+ return useTabsGroups(options).map((group, i) => /* @__PURE__ */ jsx(Dropdown, {
19
+ options: group.options,
20
+ placeholder,
21
+ ...props
22
+ }, i));
23
+ }
24
+ function Dropdown({ options, placeholder, ...props }) {
14
25
  const [open, setOpen] = useState(false);
15
26
  const { closeOnRedirect } = useSidebar();
16
27
  const pathname = usePathname();
@@ -41,7 +52,7 @@ function SidebarTabsDropdown({ options, placeholder, ...props }) {
41
52
  onOpenChange: setOpen,
42
53
  children: [item && /* @__PURE__ */ jsxs(PopoverTrigger, {
43
54
  ...props,
44
- className: cn("flex items-center gap-2 rounded-lg p-2 border bg-fd-secondary/50 text-start text-fd-secondary-foreground transition-colors hover:bg-fd-accent data-open:bg-fd-accent data-open:text-fd-accent-foreground", props.className),
55
+ className: cn("flex items-center gap-2 rounded-lg p-2 border bg-fd-secondary/50 text-start text-fd-secondary-foreground transition-colors hover:bg-fd-accent data-[popup-open]:bg-fd-accent data-[popup-open]:text-fd-accent-foreground", props.className),
45
56
  children: [item, /* @__PURE__ */ jsx(ChevronsUpDown, { className: "shrink-0 ms-auto size-4 text-fd-muted-foreground" })]
46
57
  }), /* @__PURE__ */ jsx(PopoverContent, {
47
58
  className: "flex flex-col gap-1 w-(--anchor-width) p-1 fd-scroll-container",
@@ -3,7 +3,7 @@ import { VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
4
  variant?: "primary" | "outline" | "ghost" | "secondary" | null | undefined;
5
5
  color?: "primary" | "outline" | "ghost" | "secondary" | null | undefined;
6
- size?: "sm" | "icon" | "icon-sm" | "icon-xs" | null | undefined;
6
+ size?: "icon" | "sm" | "icon-sm" | "icon-xs" | null | undefined;
7
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
8
  type ButtonProps = VariantProps<typeof buttonVariants>;
9
9
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { LayoutTab } from "../layouts/shared/index.js";
1
2
  import { ReactNode } from "react";
2
3
  import * as PageTree from "fumadocs-core/page-tree";
3
4
  //#region src/contexts/tree.d.ts
@@ -12,5 +13,17 @@ declare function TreeContextProvider({ tree: rawTree, children }: {
12
13
  }): import("react").JSX.Element;
13
14
  declare function useTreePath(): PageTree.Node[];
14
15
  declare function useTreeContext(): TreeContextType;
16
+ interface TabsGroup {
17
+ /** the root folder on the current page's path, undefined for tabs not bound to the page tree */
18
+ active?: PageTree.Folder;
19
+ options: LayoutTab[];
20
+ }
21
+ /**
22
+ * Group tabs by the root folders on the current page's path (outermost first): each tab is
23
+ * matched to its root folder, linking to the projection of current page when possible.
24
+ *
25
+ * Tabs not bound to the page tree are appended to the group of `root: true` folders.
26
+ */
27
+ declare function useTabsGroups(tabs: LayoutTab[]): TabsGroup[];
15
28
  //#endregion
16
- export { TreeContextProvider, useTreeContext, useTreePath };
29
+ export { TabsGroup, TreeContextProvider, useTabsGroups, useTreeContext, useTreePath };
@@ -2,6 +2,7 @@
2
2
  import { usePathname } from "fumadocs-core/framework";
3
3
  import { jsx } from "react/jsx-runtime";
4
4
  import { createContext, use, useMemo, useRef } from "react";
5
+ import * as PageTree from "fumadocs-core/page-tree";
5
6
  import { searchPath } from "fumadocs-core/breadcrumb";
6
7
  //#region src/contexts/tree.tsx
7
8
  const TreeContext = createContext(null);
@@ -34,5 +35,57 @@ function useTreeContext() {
34
35
  if (!ctx) throw new Error("You must wrap this component under <DocsLayout />");
35
36
  return ctx;
36
37
  }
38
+ /**
39
+ * Group tabs by the root folders on the current page's path (outermost first): each tab is
40
+ * matched to its root folder, linking to the projection of current page when possible.
41
+ *
42
+ * Tabs not bound to the page tree are appended to the group of `root: true` folders.
43
+ */
44
+ function useTabsGroups(tabs) {
45
+ const { full: tree } = useTreeContext();
46
+ const path = use(PathContext);
47
+ return useMemo(() => {
48
+ const out = [];
49
+ const last = path[path.length - 1];
50
+ const page = last?.type === "page" ? last : void 0;
51
+ let scope = tree.fallback && !tree.children.includes(path[0]) ? tree.fallback : tree;
52
+ for (const node of path) {
53
+ if (node.type !== "folder" || !node.root) continue;
54
+ const group = {
55
+ active: node,
56
+ options: []
57
+ };
58
+ collectTabs(scope, node, page, tabs, group.options);
59
+ if (group.options.length > 0) out.push(group);
60
+ scope = node;
61
+ }
62
+ const custom = tabs.filter((tab) => !tab.$folder);
63
+ if (custom.length > 0) {
64
+ const group = out.findLast((group) => group.active?.root === true);
65
+ if (group) group.options.push(...custom);
66
+ else out.push({ options: custom });
67
+ }
68
+ return out;
69
+ }, [
70
+ tabs,
71
+ tree,
72
+ path
73
+ ]);
74
+ }
75
+ /** collect the tabs of root folders with the same type as `active` within a scope */
76
+ function collectTabs(scope, active, page, tabs, out) {
77
+ for (const node of scope.children) {
78
+ if (node.type !== "folder") continue;
79
+ if (node.root === active.root) {
80
+ const tab = tabs.find((tab) => tab.$folder && (tab.$folder === node || tab.$folder.$id === node.$id));
81
+ if (!tab) continue;
82
+ const projection = page && PageTree.findProjection(active, node, page);
83
+ out.push(projection ? {
84
+ ...tab,
85
+ url: projection.url
86
+ } : tab);
87
+ } else if (!node.root) collectTabs(node, active, page, tabs, out);
88
+ }
89
+ }
37
90
  //#endregion
38
- export { TreeContextProvider, useTreeContext, useTreePath };
91
+ export { TreeContextProvider, useTabsGroups, useTreeContext, useTreePath };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../../utils/cn.js";
3
- import { TreeContextProvider, useTreePath } from "../../contexts/tree.js";
3
+ import { TreeContextProvider, useTabsGroups, useTreePath } from "../../contexts/tree.js";
4
4
  import { baseSlots } from "../shared/client.js";
5
5
  import { isLayoutTabActive, useLinkItems } from "../shared/index.js";
6
6
  import { useIsScrollTop } from "../../utils/use-is-scroll-top.js";
@@ -73,20 +73,22 @@ function LayoutBody(props) {
73
73
  })
74
74
  });
75
75
  }
76
- function LayoutTabs({ tabs, ...props }) {
76
+ function LayoutTabs({ tabs: allTabs, ...props }) {
77
77
  const pathname = usePathname();
78
78
  const path = useTreePath();
79
+ const group = useTabsGroups(allTabs).findLast((group) => typeof group.active?.root !== "string");
79
80
  const selected = useMemo(() => {
80
- return tabs.findLast((option) => isLayoutTabActive(option, path, pathname));
81
+ return group?.options.findLast((option) => isLayoutTabActive(option, path, pathname));
81
82
  }, [
82
- tabs,
83
+ group,
83
84
  path,
84
85
  pathname
85
86
  ]);
87
+ if (!group) return;
86
88
  return /* @__PURE__ */ jsx("div", {
87
89
  ...props,
88
90
  className: cn("flex flex-row items-end gap-6 overflow-auto [grid-area:main]", props.className),
89
- children: tabs.map((tab, i) => /* @__PURE__ */ jsx(Link, {
91
+ children: group.options.map((tab, i) => /* @__PURE__ */ jsx(Link, {
90
92
  href: tab.url,
91
93
  className: cn("inline-flex border-b-2 border-transparent transition-colors items-center pb-1.5 font-medium gap-2 text-fd-muted-foreground text-sm text-nowrap hover:text-fd-accent-foreground", tab.unlisted && selected !== tab && "hidden", selected === tab && "border-fd-primary text-fd-primary"),
92
94
  children: tab.title
@@ -2,21 +2,18 @@
2
2
  import { cn } from "../../../utils/cn.js";
3
3
  import { buttonVariants } from "../../../components/ui/button.js";
4
4
  import { mergeRefs } from "../../../utils/merge-refs.js";
5
- import { useTreePath } from "../../../contexts/tree.js";
6
- import { Popover, PopoverContent, PopoverTrigger } from "../../../components/ui/popover.js";
7
5
  import { SearchTrigger } from "../../shared/slots/search-trigger.js";
8
6
  import { LinkItem } from "../../shared/client.js";
9
- import { isLayoutTabActive } from "../../shared/index.js";
7
+ import "../../shared/index.js";
10
8
  import { SidebarCollapseTrigger as SidebarCollapseTrigger$1, SidebarContent as SidebarContent$1, SidebarDrawerContent, SidebarDrawerOverlay, SidebarFolder as SidebarFolder$1, SidebarFolderContent as SidebarFolderContent$1, SidebarFolderLink as SidebarFolderLink$1, SidebarFolderTrigger as SidebarFolderTrigger$1, SidebarItem as SidebarItem$1, SidebarProvider as SidebarProvider$1, SidebarSeparator as SidebarSeparator$1, SidebarTrigger as SidebarTrigger$1, SidebarViewport, base_exports, useFolder, useFolderDepth } from "../../../components/sidebar/base.js";
11
9
  import { createPageTreeRenderer } from "../../../components/sidebar/page-tree.js";
12
10
  import { createLinkItemRenderer } from "../../../components/sidebar/link-item.js";
11
+ import { SidebarTabsDropdown } from "../../../components/sidebar/tabs/dropdown.js";
13
12
  import { useDocsLayout } from "../client.js";
14
- import Link from "fumadocs-core/link";
15
- import { usePathname } from "fumadocs-core/framework";
16
13
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
- import { Check, ChevronDown, ChevronsUpDown, Languages, SidebarIcon } from "lucide-react";
14
+ import { ChevronDown, Languages, SidebarIcon } from "lucide-react";
18
15
  import { cva } from "class-variance-authority";
19
- import { useMemo, useRef, useState } from "react";
16
+ import { useRef } from "react";
20
17
  //#region src/layouts/docs/slots/sidebar.tsx
21
18
  const itemVariants = cva("relative flex flex-row items-center gap-2 rounded-lg p-2 text-start text-fd-muted-foreground wrap-anywhere [&_svg]:size-4 [&_svg]:shrink-0", { variants: {
22
19
  variant: {
@@ -61,7 +58,7 @@ function Sidebar({ footer, banner, collapsible = true, components, ...rest }) {
61
58
  ]
62
59
  }),
63
60
  slots.searchTrigger && /* @__PURE__ */ jsx(slots.searchTrigger.full, { hideIfDisabled: true }),
64
- tabs.length > 0 && tabMode === "auto" && /* @__PURE__ */ jsx(SidebarTabsDropdown, { tabs }),
61
+ tabs.length > 0 && /* @__PURE__ */ jsx(SidebarTabsDropdown, { options: tabMode === "auto" ? tabs : tabs.filter((tab) => typeof tab.$folder?.root === "string") }),
65
62
  banner
66
63
  ]
67
64
  }),
@@ -126,7 +123,7 @@ function Sidebar({ footer, banner, collapsible = true, components, ...rest }) {
126
123
  })
127
124
  ]
128
125
  }),
129
- tabs.length > 0 && /* @__PURE__ */ jsx(SidebarTabsDropdown, { tabs }),
126
+ tabs.length > 0 && /* @__PURE__ */ jsx(SidebarTabsDropdown, { options: tabs }),
130
127
  banner
131
128
  ]
132
129
  }),
@@ -249,68 +246,6 @@ function SidebarFolderContent({ className, children, ...props }) {
249
246
  children
250
247
  });
251
248
  }
252
- function SidebarTabsDropdown({ tabs, placeholder, ...props }) {
253
- const [open, setOpen] = useState(false);
254
- const { closeOnRedirect } = useSidebar();
255
- const pathname = usePathname();
256
- const path = useTreePath();
257
- const selected = useMemo(() => {
258
- return tabs.findLast((item) => isLayoutTabActive(item, path, pathname));
259
- }, [
260
- tabs,
261
- path,
262
- pathname
263
- ]);
264
- const onClick = () => {
265
- closeOnRedirect.current = false;
266
- setOpen(false);
267
- };
268
- const item = selected ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
269
- className: "size-9 shrink-0 empty:hidden md:size-5",
270
- children: selected.icon
271
- }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
272
- className: "text-sm font-medium",
273
- children: selected.title
274
- }), /* @__PURE__ */ jsx("p", {
275
- className: "text-sm text-fd-muted-foreground empty:hidden md:hidden",
276
- children: selected.description
277
- })] })] }) : placeholder;
278
- return /* @__PURE__ */ jsxs(Popover, {
279
- open,
280
- onOpenChange: setOpen,
281
- children: [item && /* @__PURE__ */ jsxs(PopoverTrigger, {
282
- ...props,
283
- className: cn("flex items-center gap-2 rounded-lg p-2 border bg-fd-secondary/50 text-start text-fd-secondary-foreground transition-colors hover:bg-fd-accent data-[popup-open]:bg-fd-accent data-[popup-open]:text-fd-accent-foreground", props.className),
284
- children: [item, /* @__PURE__ */ jsx(ChevronsUpDown, { className: "shrink-0 ms-auto size-4 text-fd-muted-foreground" })]
285
- }), /* @__PURE__ */ jsx(PopoverContent, {
286
- className: "flex flex-col gap-1 w-(--anchor-width) p-1 fd-scroll-container",
287
- children: tabs.map((item) => {
288
- const isActive = selected && item.url === selected.url;
289
- if (!isActive && item.unlisted) return;
290
- return /* @__PURE__ */ jsxs(Link, {
291
- href: item.url,
292
- onClick,
293
- ...item.props,
294
- className: cn("flex items-center gap-2 rounded-lg p-1.5 hover:bg-fd-accent hover:text-fd-accent-foreground", item.props?.className),
295
- children: [
296
- /* @__PURE__ */ jsx("div", {
297
- className: "shrink-0 size-9 md:mb-auto md:size-5 empty:hidden",
298
- children: item.icon
299
- }),
300
- /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
301
- className: "text-sm font-medium leading-none",
302
- children: item.title
303
- }), /* @__PURE__ */ jsx("p", {
304
- className: "text-[0.8125rem] text-fd-muted-foreground mt-1 empty:hidden",
305
- children: item.description
306
- })] }),
307
- /* @__PURE__ */ jsx(Check, { className: cn("shrink-0 ms-auto size-3.5 text-fd-primary", !isActive && "invisible") })
308
- ]
309
- }, item.url);
310
- })
311
- })]
312
- });
313
- }
314
249
  function getItemOffset(depth) {
315
250
  return `calc(${2 + 3 * depth} * var(--spacing))`;
316
251
  }
@@ -3,8 +3,8 @@ import { BaseLayoutProps, GetLayoutTabsOptions, LayoutTab, LinkItemType } from "
3
3
  import { TabDropdownProps } from "./slots/tab-dropdown.js";
4
4
  import { SidebarProps, SidebarProviderProps } from "./slots/sidebar.js";
5
5
  import { ComponentProps, FC, ReactNode } from "react";
6
- import { motion } from "motion/react";
7
6
  import * as PageTree from "fumadocs-core/page-tree";
7
+ import { motion } from "motion/react";
8
8
  //#region src/layouts/flux/index.d.ts
9
9
  interface DocsSlots extends BaseSlots {
10
10
  container: FC<ComponentProps<'div'>>;
@@ -5,6 +5,6 @@ interface TabDropdownProps extends ComponentProps<'button'> {
5
5
  placeholder?: ReactNode;
6
6
  tabs: LayoutTab[];
7
7
  }
8
- declare function TabDropdown({ tabs, placeholder, className, ...props }: TabDropdownProps): import("react").JSX.Element;
8
+ declare function TabDropdown({ tabs: allTabs, placeholder, className, ...props }: TabDropdownProps): import("react").JSX.Element | undefined;
9
9
  //#endregion
10
10
  export { TabDropdown, TabDropdownProps };
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import { cn } from "../../../utils/cn.js";
3
- import { useTreePath } from "../../../contexts/tree.js";
3
+ import { useTabsGroups, useTreePath } from "../../../contexts/tree.js";
4
4
  import { Popover, PopoverContent, PopoverTrigger } from "../../../components/ui/popover.js";
5
5
  import { isLayoutTabActive } from "../../shared/index.js";
6
6
  import Link from "fumadocs-core/link";
@@ -10,17 +10,19 @@ import { Check, ChevronsUpDown } from "lucide-react";
10
10
  import { useMemo, useState } from "react";
11
11
  import { AnimatePresence, motion } from "motion/react";
12
12
  //#region src/layouts/flux/slots/tab-dropdown.tsx
13
- function TabDropdown({ tabs, placeholder, className, ...props }) {
13
+ function TabDropdown({ tabs: allTabs, placeholder, className, ...props }) {
14
14
  const [open, setOpen] = useState(false);
15
15
  const pathname = usePathname();
16
16
  const path = useTreePath();
17
+ const tabs = useTabsGroups(allTabs).findLast((group) => typeof group.active?.root !== "string")?.options;
17
18
  const selectedIdx = useMemo(() => {
18
- return tabs.findLastIndex((item) => isLayoutTabActive(item, path, pathname));
19
+ return tabs?.findLastIndex((item) => isLayoutTabActive(item, path, pathname)) ?? -1;
19
20
  }, [
20
21
  tabs,
21
22
  path,
22
23
  pathname
23
24
  ]);
25
+ if (!tabs) return;
24
26
  const selected = selectedIdx !== -1 ? tabs[selectedIdx] : void 0;
25
27
  const onClick = () => {
26
28
  setOpen(false);
@@ -1,5 +1,5 @@
1
1
  import { cn } from "../../utils/cn.js";
2
- import { useTreePath } from "../../contexts/tree.js";
2
+ import { useTabsGroups, useTreePath } from "../../contexts/tree.js";
3
3
  import { Popover, PopoverContent, PopoverTrigger } from "../../components/ui/popover.js";
4
4
  import { isLayoutTabActive } from "../shared/index.js";
5
5
  import Link from "fumadocs-core/link";
@@ -9,12 +9,14 @@ import { ChevronsUpDown } from "lucide-react";
9
9
  import { useState } from "react";
10
10
  import { useTranslations } from "@fuma-translate/react";
11
11
  //#region src/layouts/glass/layout-tabs.tsx
12
- function LayoutTabsDropdown({ tabs, className, size = "default", ...props }) {
12
+ function LayoutTabsDropdown({ tabs: allTabs, className, size = "default", ...props }) {
13
13
  const path = useTreePath();
14
14
  const pathname = usePathname();
15
15
  const t = useTranslations();
16
+ const tabs = useTabsGroups(allTabs).findLast((group) => typeof group.active?.root !== "string")?.options ?? [];
16
17
  const selected = tabs.findLast((t) => isLayoutTabActive(t, path, pathname));
17
18
  const [open, setOpen] = useState(false);
19
+ if (tabs.length === 0) return;
18
20
  return /* @__PURE__ */ jsxs(Popover, {
19
21
  open,
20
22
  onOpenChange: setOpen,
@@ -1,7 +1,7 @@
1
1
  import { ComponentProps } from "react";
2
2
  //#region src/layouts/home/slots/header.d.ts
3
3
  declare const navItemVariants: (props?: ({
4
- variant?: "icon" | "button" | "main" | null | undefined;
4
+ variant?: "icon" | "main" | "button" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  declare function Header(props: ComponentProps<'header'>): import("react").JSX.Element;
7
7
  //#endregion
@@ -1,10 +1,11 @@
1
1
  "use client";
2
2
  import { cn } from "../../../utils/cn.js";
3
3
  import { buttonVariants } from "../../../components/ui/button.js";
4
- import { useTreePath } from "../../../contexts/tree.js";
4
+ import { useTabsGroups, useTreePath } from "../../../contexts/tree.js";
5
5
  import { Popover, PopoverContent, PopoverTrigger } from "../../../components/ui/popover.js";
6
6
  import { LinkItem } from "../../shared/client.js";
7
7
  import { isLayoutTabActive } from "../../shared/index.js";
8
+ import { SidebarTabsDropdown } from "../../../components/sidebar/tabs/dropdown.js";
8
9
  import { useNotebookLayout } from "../client.js";
9
10
  import Link from "fumadocs-core/link";
10
11
  import { usePathname } from "fumadocs-core/framework";
@@ -17,7 +18,8 @@ function Header(props) {
17
18
  const { open } = slots.sidebar?.useSidebar?.() ?? {};
18
19
  const navMode = nav?.mode ?? "auto";
19
20
  const sidebarCollapsible = sidebar.collapsible ?? true;
20
- const showLayoutTabs = tabMode === "navbar" && tabs.length > 0;
21
+ const groups = useTabsGroups(tabs);
22
+ const showLayoutTabs = tabMode === "navbar" && groups.length > 0;
21
23
  if (nav?.component) return nav.component;
22
24
  return /* @__PURE__ */ jsxs("header", {
23
25
  id: "nd-subnav",
@@ -100,20 +102,27 @@ function Header(props) {
100
102
  })]
101
103
  });
102
104
  }
103
- function LayoutHeaderTabs({ tabs, className, ...props }) {
105
+ function LayoutHeaderTabs({ tabs: allTabs, className, ...props }) {
104
106
  const pathname = usePathname();
105
107
  const path = useTreePath();
108
+ const tabs = useTabsGroups(allTabs).findLast((group) => typeof group.active?.root !== "string")?.options;
109
+ const typedTabs = useMemo(() => {
110
+ return allTabs.filter((tab) => typeof tab.$folder?.root === "string");
111
+ }, [allTabs]);
106
112
  const selectedIdx = useMemo(() => {
107
- return tabs.findLastIndex((option) => isLayoutTabActive(option, path, pathname));
113
+ return tabs?.findLastIndex((option) => isLayoutTabActive(option, path, pathname)) ?? -1;
108
114
  }, [
109
115
  tabs,
110
116
  path,
111
117
  pathname
112
118
  ]);
113
- return /* @__PURE__ */ jsx("div", {
119
+ return /* @__PURE__ */ jsxs("div", {
114
120
  className: cn("flex flex-row items-end gap-6", className),
115
121
  ...props,
116
- children: tabs.map((option, i) => {
122
+ children: [typedTabs.length > 0 && /* @__PURE__ */ jsx(SidebarTabsDropdown, {
123
+ options: typedTabs,
124
+ className: "my-auto p-1"
125
+ }), tabs?.map((option, i) => {
117
126
  const { title, url, unlisted, props: { className, ...rest } = {} } = option;
118
127
  const isSelected = selectedIdx === i;
119
128
  return /* @__PURE__ */ jsx(Link, {
@@ -122,7 +131,7 @@ function LayoutHeaderTabs({ tabs, className, ...props }) {
122
131
  ...rest,
123
132
  children: title
124
133
  }, i);
125
- })
134
+ })]
126
135
  });
127
136
  }
128
137
  function NavbarLinkItem({ item, className, ...props }) {
@@ -1,6 +1,6 @@
1
1
  import { SidebarProviderProps as SidebarProviderProps$1, useSidebar as useSidebar$1 } from "../../../components/sidebar/base.js";
2
- import { LayoutTab } from "../../shared/index.js";
3
2
  import { SidebarPageTreeComponents } from "../../../components/sidebar/page-tree.js";
3
+ import { SidebarTabsDropdown } from "../../../components/sidebar/tabs/dropdown.js";
4
4
  import { ComponentProps, FC, ReactNode } from "react";
5
5
  //#region src/layouts/notebook/slots/sidebar.d.ts
6
6
  interface SidebarProps extends ComponentProps<'aside'> {
@@ -20,9 +20,5 @@ declare function SidebarProvider(props: SidebarProviderProps): import("react").J
20
20
  declare function SidebarTrigger(props: ComponentProps<'button'>): import("react").JSX.Element;
21
21
  declare function SidebarCollapseTrigger(props: ComponentProps<'button'>): import("react").JSX.Element;
22
22
  declare function Sidebar({ banner, footer, components, collapsible, ...rest }: SidebarProps): import("react").JSX.Element;
23
- declare function SidebarTabsDropdown({ options, placeholder, ...props }: {
24
- placeholder?: ReactNode;
25
- options: LayoutTab[];
26
- } & ComponentProps<'button'>): import("react").JSX.Element;
27
23
  //#endregion
28
24
  export { Sidebar, SidebarCollapseTrigger, SidebarProps, SidebarProvider, SidebarProviderProps, SidebarTabsDropdown, SidebarTrigger, useSidebar };
@@ -2,20 +2,17 @@
2
2
  import { cn } from "../../../utils/cn.js";
3
3
  import { buttonVariants } from "../../../components/ui/button.js";
4
4
  import { mergeRefs } from "../../../utils/merge-refs.js";
5
- import { useTreePath } from "../../../contexts/tree.js";
6
- import { Popover, PopoverContent, PopoverTrigger } from "../../../components/ui/popover.js";
7
5
  import { LinkItem } from "../../shared/client.js";
8
- import { isLayoutTabActive } from "../../shared/index.js";
6
+ import "../../shared/index.js";
9
7
  import { SidebarCollapseTrigger as SidebarCollapseTrigger$1, SidebarContent as SidebarContent$1, SidebarDrawerContent, SidebarDrawerOverlay, SidebarFolder as SidebarFolder$1, SidebarFolderContent as SidebarFolderContent$1, SidebarFolderLink as SidebarFolderLink$1, SidebarFolderTrigger as SidebarFolderTrigger$1, SidebarItem as SidebarItem$1, SidebarProvider as SidebarProvider$1, SidebarSeparator as SidebarSeparator$1, SidebarTrigger as SidebarTrigger$1, SidebarViewport, base_exports, useFolder, useFolderDepth } from "../../../components/sidebar/base.js";
10
8
  import { createPageTreeRenderer } from "../../../components/sidebar/page-tree.js";
11
9
  import { createLinkItemRenderer } from "../../../components/sidebar/link-item.js";
10
+ import { SidebarTabsDropdown } from "../../../components/sidebar/tabs/dropdown.js";
12
11
  import { useNotebookLayout } from "../client.js";
13
- import Link from "fumadocs-core/link";
14
- import { usePathname } from "fumadocs-core/framework";
15
12
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
16
- import { Check, ChevronsUpDown, Languages, SidebarIcon, X } from "lucide-react";
13
+ import { Languages, SidebarIcon, X } from "lucide-react";
17
14
  import { cva } from "class-variance-authority";
18
- import { createElement, useMemo, useRef, useState } from "react";
15
+ import { createElement, useRef } from "react";
19
16
  //#region src/layouts/notebook/slots/sidebar.tsx
20
17
  const itemVariants = cva("relative flex flex-row items-center gap-2 rounded-lg p-2 text-start text-fd-muted-foreground wrap-anywhere [&_svg]:size-4 [&_svg]:shrink-0", { variants: {
21
18
  variant: {
@@ -239,67 +236,5 @@ function Sidebar({ banner, footer, components, collapsible = true, ...rest }) {
239
236
  ]
240
237
  })] });
241
238
  }
242
- function SidebarTabsDropdown({ options, placeholder, ...props }) {
243
- const [open, setOpen] = useState(false);
244
- const { closeOnRedirect } = useSidebar();
245
- const pathname = usePathname();
246
- const path = useTreePath();
247
- const selected = useMemo(() => {
248
- return options.findLast((item) => isLayoutTabActive(item, path, pathname));
249
- }, [
250
- options,
251
- path,
252
- pathname
253
- ]);
254
- const onClick = () => {
255
- closeOnRedirect.current = false;
256
- setOpen(false);
257
- };
258
- const item = selected ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("div", {
259
- className: "size-9 shrink-0 empty:hidden md:size-5",
260
- children: selected.icon
261
- }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
262
- className: "text-sm font-medium",
263
- children: selected.title
264
- }), /* @__PURE__ */ jsx("p", {
265
- className: "text-sm text-fd-muted-foreground empty:hidden md:hidden",
266
- children: selected.description
267
- })] })] }) : placeholder;
268
- return /* @__PURE__ */ jsxs(Popover, {
269
- open,
270
- onOpenChange: setOpen,
271
- children: [item && /* @__PURE__ */ jsxs(PopoverTrigger, {
272
- ...props,
273
- className: cn("flex items-center gap-2 rounded-lg p-2 border bg-fd-secondary/50 text-start text-fd-secondary-foreground transition-colors hover:bg-fd-accent data-[popup-open]:bg-fd-accent data-[popup-open]:text-fd-accent-foreground", props.className),
274
- children: [item, /* @__PURE__ */ jsx(ChevronsUpDown, { className: "shrink-0 ms-auto size-4 text-fd-muted-foreground" })]
275
- }), /* @__PURE__ */ jsx(PopoverContent, {
276
- className: "flex flex-col gap-1 w-(--anchor-width) p-1 fd-scroll-container",
277
- children: options.map((item) => {
278
- const isActive = selected && item.url === selected.url;
279
- if (!isActive && item.unlisted) return;
280
- return /* @__PURE__ */ jsxs(Link, {
281
- href: item.url,
282
- onClick,
283
- ...item.props,
284
- className: cn("flex items-center gap-2 rounded-lg p-1.5 hover:bg-fd-accent hover:text-fd-accent-foreground", item.props?.className),
285
- children: [
286
- /* @__PURE__ */ jsx("div", {
287
- className: "shrink-0 size-9 md:mb-auto md:size-5 empty:hidden",
288
- children: item.icon
289
- }),
290
- /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("p", {
291
- className: "text-sm font-medium leading-none",
292
- children: item.title
293
- }), /* @__PURE__ */ jsx("p", {
294
- className: "text-[0.8125rem] text-fd-muted-foreground mt-1 empty:hidden",
295
- children: item.description
296
- })] }),
297
- /* @__PURE__ */ jsx(Check, { className: cn("shrink-0 ms-auto size-3.5 text-fd-primary", !isActive && "invisible") })
298
- ]
299
- }, item.url);
300
- })
301
- })]
302
- });
303
- }
304
239
  //#endregion
305
240
  export { Sidebar, SidebarCollapseTrigger, SidebarProvider, SidebarTabsDropdown, SidebarTrigger, useSidebar };
@@ -2,8 +2,8 @@ import { FullSearchTriggerProps, SearchTriggerProps } from "./slots/search-trigg
2
2
  import { ThemeSwitchProps } from "./slots/theme-switch.js";
3
3
  import { BaseSlots, BaseSlotsProps, LinkItem, baseSlots } from "./client.js";
4
4
  import { ComponentProps, FC, ReactNode } from "react";
5
- import { I18nConfig } from "fumadocs-core/i18n";
6
5
  import * as PageTree from "fumadocs-core/page-tree";
6
+ import { I18nConfig } from "fumadocs-core/i18n";
7
7
  //#region src/layouts/shared/index.d.ts
8
8
  interface NavOptions {
9
9
  enabled?: boolean;
@@ -27,7 +27,7 @@ function isTypingTarget(target) {
27
27
  function ThemeHotKey({ hotKey }) {
28
28
  const { setTheme, resolvedTheme } = useTheme$1();
29
29
  const onKeyDown = useEffectEvent((e) => {
30
- if (e.defaultPrevented || e.isComposing) return;
30
+ if (e.defaultPrevented || e.isComposing || e.keyCode === 229) return;
31
31
  if (isTypingTarget(e.target)) return;
32
32
  if (!(typeof hotKey === "string" ? !e.metaKey && !e.ctrlKey && !e.altKey && e.key.toLowerCase() === hotKey.toLowerCase() : hotKey(e))) return;
33
33
  e.preventDefault();
package/dist/style.css CHANGED
@@ -2456,12 +2456,6 @@
2456
2456
  .data-open\:animate-fd-popover-in[data-open] {
2457
2457
  animation: var(--animate-fd-popover-in);
2458
2458
  }
2459
- .data-open\:bg-fd-accent[data-open] {
2460
- background-color: var(--color-fd-accent);
2461
- }
2462
- .data-open\:text-fd-accent-foreground[data-open] {
2463
- color: var(--color-fd-accent-foreground);
2464
- }
2465
2459
  .data-popup-open\:bg-fd-accent[data-popup-open] {
2466
2460
  background-color: var(--color-fd-accent);
2467
2461
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fumadocs/base-ui",
3
- "version": "16.15.4",
3
+ "version": "16.15.5",
4
4
  "description": "The Base UI version of Fumadocs UI",
5
5
  "keywords": [
6
6
  "Docs",
@@ -154,9 +154,9 @@
154
154
  "tailwindcss": "^4.3.3",
155
155
  "tsdown": "0.22.14",
156
156
  "unified": "^11.0.5",
157
- "@fumadocs/cli": "1.4.1",
157
+ "fumadocs-core": "16.15.5",
158
158
  "tsconfig": "0.0.0",
159
- "fumadocs-core": "16.15.4"
159
+ "@fumadocs/cli": "1.5.0"
160
160
  },
161
161
  "peerDependencies": {
162
162
  "@types/mdx": "*",
@@ -165,7 +165,7 @@
165
165
  "react": "^19.2.0",
166
166
  "react-dom": "^19.2.0",
167
167
  "takumi-js": "*",
168
- "fumadocs-core": "16.15.4"
168
+ "fumadocs-core": "16.15.5"
169
169
  },
170
170
  "peerDependenciesMeta": {
171
171
  "next": {