boltdocs 2.5.5 → 2.6.0

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.
Files changed (166) hide show
  1. package/bin/boltdocs.js +2 -2
  2. package/dist/client/index.cjs +6 -0
  3. package/dist/client/index.d.cts +1560 -0
  4. package/dist/client/index.d.ts +1219 -922
  5. package/dist/client/index.js +6 -1
  6. package/dist/client/theme/neutral.css +428 -0
  7. package/dist/node/cli-entry.cjs +8 -0
  8. package/dist/node/cli-entry.d.cts +2 -0
  9. package/dist/node/cli-entry.d.mts +2 -1
  10. package/dist/node/cli-entry.mjs +7 -5
  11. package/dist/node/index.cjs +6 -0
  12. package/dist/node/index.d.cts +519 -0
  13. package/dist/node/index.d.mts +374 -422
  14. package/dist/node/index.mjs +6 -1
  15. package/dist/node-BgvNl2Ay.mjs +89 -0
  16. package/dist/node-vkbb0MK7.cjs +89 -0
  17. package/dist/package-CR0HF9x3.mjs +6 -0
  18. package/dist/package-Dgmsc_l5.cjs +6 -0
  19. package/dist/search-dialog-3lvKsbVG.js +6 -0
  20. package/dist/search-dialog-DMK5OpgH.cjs +6 -0
  21. package/dist/use-search-C9bxCqfF.js +6 -0
  22. package/dist/use-search-DcfZSunO.cjs +6 -0
  23. package/package.json +26 -25
  24. package/src/client/app/config-context.tsx +38 -5
  25. package/src/client/app/doc-page.tsx +34 -0
  26. package/src/client/app/mdx-component.tsx +2 -3
  27. package/src/client/app/mdx-components-context.tsx +27 -2
  28. package/src/client/app/routes-context.tsx +34 -0
  29. package/src/client/app/scroll-handler.tsx +7 -4
  30. package/src/client/app/theme-context.tsx +71 -67
  31. package/src/client/components/default-layout.tsx +34 -33
  32. package/src/client/components/docs-layout.tsx +1 -2
  33. package/src/client/components/icons-dev.tsx +36 -5
  34. package/src/client/components/mdx/admonition.tsx +11 -27
  35. package/src/client/components/mdx/badge.tsx +1 -1
  36. package/src/client/components/mdx/button.tsx +3 -3
  37. package/src/client/components/mdx/card.tsx +1 -1
  38. package/src/client/components/mdx/code-block.tsx +90 -80
  39. package/src/client/components/mdx/component-preview.tsx +1 -5
  40. package/src/client/components/mdx/component-props.tsx +1 -1
  41. package/src/client/components/mdx/field.tsx +4 -5
  42. package/src/client/components/mdx/file-tree.tsx +6 -3
  43. package/src/client/components/mdx/hooks/use-code-block.ts +2 -2
  44. package/src/client/components/mdx/image.tsx +1 -1
  45. package/src/client/components/mdx/link.tsx +2 -2
  46. package/src/client/components/mdx/list.tsx +1 -1
  47. package/src/client/components/mdx/table.tsx +1 -1
  48. package/src/client/components/mdx/tabs.tsx +1 -1
  49. package/src/client/components/primitives/breadcrumbs.tsx +1 -7
  50. package/src/client/components/primitives/button-group.tsx +1 -1
  51. package/src/client/components/primitives/button.tsx +1 -1
  52. package/src/client/components/primitives/code-block.tsx +113 -0
  53. package/src/client/components/primitives/link.tsx +23 -41
  54. package/src/client/components/primitives/menu.tsx +5 -6
  55. package/src/client/components/primitives/navbar.tsx +6 -18
  56. package/src/client/components/primitives/navigation-menu.tsx +4 -4
  57. package/src/client/components/primitives/on-this-page.tsx +6 -10
  58. package/src/client/components/primitives/page-nav.tsx +4 -9
  59. package/src/client/components/primitives/popover.tsx +1 -1
  60. package/src/client/components/primitives/search-dialog.tsx +3 -6
  61. package/src/client/components/primitives/sidebar.tsx +80 -22
  62. package/src/client/components/primitives/skeleton.tsx +1 -1
  63. package/src/client/components/primitives/tabs.tsx +4 -11
  64. package/src/client/components/primitives/tooltip.tsx +3 -3
  65. package/src/client/components/ui-base/breadcrumbs.tsx +4 -6
  66. package/src/client/components/ui-base/copy-markdown.tsx +2 -7
  67. package/src/client/components/ui-base/github-stars.tsx +2 -2
  68. package/src/client/components/ui-base/head.tsx +58 -51
  69. package/src/client/components/ui-base/loading.tsx +2 -2
  70. package/src/client/components/ui-base/navbar.tsx +12 -14
  71. package/src/client/components/ui-base/not-found.tsx +1 -1
  72. package/src/client/components/ui-base/on-this-page.tsx +6 -6
  73. package/src/client/components/ui-base/page-nav.tsx +4 -8
  74. package/src/client/components/ui-base/search-dialog.tsx +10 -8
  75. package/src/client/components/ui-base/sidebar.tsx +76 -23
  76. package/src/client/components/ui-base/tabs.tsx +9 -8
  77. package/src/client/components/ui-base/theme-toggle.tsx +2 -2
  78. package/src/client/hooks/use-i18n.ts +3 -3
  79. package/src/client/hooks/use-localized-to.ts +1 -1
  80. package/src/client/hooks/use-navbar.ts +8 -6
  81. package/src/client/hooks/use-routes.ts +19 -11
  82. package/src/client/hooks/use-search.ts +1 -1
  83. package/src/client/hooks/use-sidebar.ts +48 -2
  84. package/src/client/hooks/use-tabs.ts +6 -2
  85. package/src/client/hooks/use-version.ts +3 -3
  86. package/src/client/index.ts +22 -22
  87. package/src/client/ssg/boltdocs-shell.tsx +127 -0
  88. package/src/client/ssg/create-routes.tsx +179 -0
  89. package/src/client/ssg/index.ts +3 -0
  90. package/src/client/ssg/mdx-page.tsx +37 -0
  91. package/src/client/store/boltdocs-context.tsx +66 -0
  92. package/src/client/theme/neutral.css +90 -50
  93. package/src/client/types.ts +5 -33
  94. package/src/client/utils/react-to-text.ts +34 -0
  95. package/CHANGELOG.md +0 -98
  96. package/dist/cache-3FOEPC2P.mjs +0 -1
  97. package/dist/chunk-5B5NKOW6.mjs +0 -77
  98. package/dist/chunk-J2PTDWZM.mjs +0 -1
  99. package/dist/chunk-TP5KMRD3.mjs +0 -1
  100. package/dist/chunk-Y4RE5KI7.mjs +0 -1
  101. package/dist/client/index.d.mts +0 -1263
  102. package/dist/client/index.mjs +0 -1
  103. package/dist/client/ssr.d.mts +0 -78
  104. package/dist/client/ssr.d.ts +0 -78
  105. package/dist/client/ssr.js +0 -1
  106. package/dist/client/ssr.mjs +0 -1
  107. package/dist/node/cli-entry.d.ts +0 -1
  108. package/dist/node/cli-entry.js +0 -82
  109. package/dist/node/index.d.ts +0 -567
  110. package/dist/node/index.js +0 -77
  111. package/dist/package-QFIAETHR.mjs +0 -1
  112. package/dist/search-dialog-O6VLVSOA.mjs +0 -1
  113. package/src/client/app/index.tsx +0 -345
  114. package/src/client/app/mdx-page.tsx +0 -15
  115. package/src/client/app/preload.tsx +0 -66
  116. package/src/client/app/router.tsx +0 -30
  117. package/src/client/integrations/codesandbox.ts +0 -179
  118. package/src/client/integrations/index.ts +0 -1
  119. package/src/client/ssr.tsx +0 -65
  120. package/src/client/store/use-boltdocs-store.ts +0 -44
  121. package/src/node/cache.ts +0 -408
  122. package/src/node/cli/build.ts +0 -53
  123. package/src/node/cli/dev.ts +0 -22
  124. package/src/node/cli/doctor.ts +0 -243
  125. package/src/node/cli/index.ts +0 -9
  126. package/src/node/cli/ui.ts +0 -54
  127. package/src/node/cli-entry.ts +0 -24
  128. package/src/node/config.ts +0 -382
  129. package/src/node/errors.ts +0 -44
  130. package/src/node/index.ts +0 -84
  131. package/src/node/mdx/cache.ts +0 -12
  132. package/src/node/mdx/highlighter.ts +0 -47
  133. package/src/node/mdx/index.ts +0 -122
  134. package/src/node/mdx/rehype-shiki.ts +0 -62
  135. package/src/node/mdx/remark-code-meta.ts +0 -35
  136. package/src/node/mdx/remark-shiki.ts +0 -61
  137. package/src/node/plugin/entry.ts +0 -87
  138. package/src/node/plugin/html.ts +0 -99
  139. package/src/node/plugin/index.ts +0 -478
  140. package/src/node/plugin/types.ts +0 -9
  141. package/src/node/plugins/index.ts +0 -17
  142. package/src/node/plugins/plugin-errors.ts +0 -62
  143. package/src/node/plugins/plugin-lifecycle.ts +0 -117
  144. package/src/node/plugins/plugin-sandbox.ts +0 -59
  145. package/src/node/plugins/plugin-store.ts +0 -54
  146. package/src/node/plugins/plugin-types.ts +0 -107
  147. package/src/node/plugins/plugin-validator.ts +0 -105
  148. package/src/node/routes/cache.ts +0 -28
  149. package/src/node/routes/index.ts +0 -293
  150. package/src/node/routes/parser.ts +0 -262
  151. package/src/node/routes/sorter.ts +0 -42
  152. package/src/node/routes/types.ts +0 -61
  153. package/src/node/schema/config.ts +0 -195
  154. package/src/node/schema/frontmatter.ts +0 -17
  155. package/src/node/search/index.ts +0 -55
  156. package/src/node/security/constants/index.ts +0 -10
  157. package/src/node/security/csp.ts +0 -31
  158. package/src/node/security/headers.ts +0 -27
  159. package/src/node/ssg/index.ts +0 -205
  160. package/src/node/ssg/meta.ts +0 -33
  161. package/src/node/ssg/options.ts +0 -15
  162. package/src/node/ssg/robots.ts +0 -53
  163. package/src/node/ssg/sitemap.ts +0 -55
  164. package/src/node/utils.ts +0 -349
  165. package/tsconfig.json +0 -26
  166. package/tsup.config.ts +0 -56
@@ -1,12 +1,11 @@
1
- import React from 'react'
2
1
  import {
3
2
  Link as RACLink,
4
3
  type LinkProps as RACLinkProps,
5
4
  } from 'react-aria-components'
6
5
  import { useLocation } from 'react-router-dom'
7
- import { useLocalizedTo } from '@hooks/use-localized-to'
8
- import { usePreload } from '@client/app/preload'
9
- import { cn } from '@client/utils/cn'
6
+ import { useLocalizedTo } from '../../hooks/use-localized-to'
7
+ import { cn } from '../../utils/cn'
8
+ import { forwardRef } from 'react'
10
9
 
11
10
  export interface LinkProps extends RACLinkProps {
12
11
  /** Should prefetch the page on hover? Default 'hover' */
@@ -20,46 +19,29 @@ export interface LinkProps extends RACLinkProps {
20
19
  * It uses the global navigation configuration from BoltdocsRouterProvider
21
20
  * to handle seamless client-side transitions.
22
21
  */
23
- export const Link = React.forwardRef<HTMLAnchorElement, LinkProps>(
24
- (props, ref) => {
25
- const { href, prefetch = 'hover', onMouseEnter, onFocus, ...rest } = props
22
+ export const Link = forwardRef<HTMLAnchorElement, LinkProps>((props, ref) => {
23
+ const { href, prefetch = 'hover', onMouseEnter, onFocus, ...rest } = props
26
24
 
27
- const localizedHref = useLocalizedTo(href ?? '')
28
- const { preload } = usePreload()
25
+ const localizedHref = useLocalizedTo(href ?? '')
29
26
 
30
- const handleMouseEnter = (e: React.MouseEvent<HTMLAnchorElement>) => {
31
- onMouseEnter?.(e)
32
- if (
33
- prefetch === 'hover' &&
34
- typeof localizedHref === 'string' &&
35
- localizedHref.startsWith('/')
36
- ) {
37
- preload(localizedHref)
38
- }
39
- }
27
+ const handleMouseEnter = (e: React.MouseEvent<HTMLAnchorElement>) => {
28
+ onMouseEnter?.(e)
29
+ }
40
30
 
41
- const handleFocus = (e: React.FocusEvent) => {
42
- onFocus?.(e as any)
43
- if (
44
- prefetch === 'hover' &&
45
- typeof localizedHref === 'string' &&
46
- localizedHref.startsWith('/')
47
- ) {
48
- preload(localizedHref)
49
- }
50
- }
31
+ const handleFocus = (e: React.FocusEvent) => {
32
+ onFocus?.(e as any)
33
+ }
51
34
 
52
- return (
53
- <RACLink
54
- {...rest}
55
- ref={ref}
56
- href={localizedHref as string}
57
- onMouseEnter={handleMouseEnter}
58
- onFocus={handleFocus as any}
59
- />
60
- )
61
- },
62
- )
35
+ return (
36
+ <RACLink
37
+ {...rest}
38
+ ref={ref}
39
+ href={localizedHref as string}
40
+ onMouseEnter={handleMouseEnter}
41
+ onFocus={handleFocus as any}
42
+ />
43
+ )
44
+ })
63
45
  Link.displayName = 'Link'
64
46
 
65
47
  /**
@@ -90,7 +72,7 @@ export interface NavLinkProps
90
72
  * It combines the Link primitive with path matching logic to determine
91
73
  * if the link is currently active based on the browser's location.
92
74
  */
93
- export const NavLink = React.forwardRef<HTMLAnchorElement, NavLinkProps>(
75
+ export const NavLink = forwardRef<HTMLAnchorElement, NavLinkProps>(
94
76
  (props, ref) => {
95
77
  const { href, end = false, className, children, ...rest } = props
96
78
  const location = useLocation()
@@ -1,11 +1,10 @@
1
1
  'use client'
2
2
 
3
3
  import { Check, ChevronRight, Dot } from 'lucide-react'
4
- import React from 'react'
5
4
  import * as RAC from 'react-aria-components'
5
+ import { Children } from 'react'
6
6
  import { Popover, type PopoverProps } from './popover'
7
- import { cn } from '@client/utils/cn'
8
-
7
+ import { cn } from '../../utils/cn'
9
8
  /**
10
9
  * MenuTrigger wraps a trigger (usually a Button) and a Menu.
11
10
  */
@@ -15,7 +14,7 @@ export interface MenuTriggerProps extends RAC.MenuTriggerProps {
15
14
 
16
15
  function MenuTrigger(props: MenuTriggerProps) {
17
16
  const [trigger, menu] = (
18
- React.Children.toArray(props.children) as React.ReactElement[]
17
+ Children.toArray(props.children) as React.ReactElement[]
19
18
  ).slice(0, 2)
20
19
  return (
21
20
  <RAC.MenuTrigger {...props}>
@@ -32,7 +31,7 @@ function MenuTrigger(props: MenuTriggerProps) {
32
31
  */
33
32
  function SubmenuTrigger(props: RAC.SubmenuTriggerProps) {
34
33
  const [trigger, menu] = (
35
- React.Children.toArray(props.children) as React.ReactElement[]
34
+ Children.toArray(props.children) as React.ReactElement[]
36
35
  ).slice(0, 2)
37
36
  return (
38
37
  <RAC.SubmenuTrigger {...props}>
@@ -159,4 +158,4 @@ Menu.Item = MenuItem
159
158
  Menu.Trigger = MenuTrigger
160
159
  Menu.SubTrigger = SubmenuTrigger
161
160
  Menu.Section = MenuSection
162
- Menu.Separator = MenuSeparator
161
+ Menu.Separator = MenuSeparator
@@ -2,9 +2,9 @@ import { type ReactNode, useState, useEffect } from 'react'
2
2
  import { Separator, ToggleButton, Link, cn } from './index'
3
3
  import { Button as ButtonRAC } from 'react-aria-components'
4
4
  import { Search, Sun, Moon, ExternalLink } from 'lucide-react'
5
- import * as IconsSocials from '@components/icons-dev'
5
+ import * as IconsSocials from '../icons-dev'
6
6
  import type { ComponentBase } from './types'
7
- import type { BoltdocsSocialLink } from '@node/config'
7
+ import type { BoltdocsSocialLink } from '../../../shared/types'
8
8
 
9
9
  export interface NavbarLinkProps extends Omit<ComponentBase, 'children'> {
10
10
  label: ReactNode
@@ -35,11 +35,7 @@ export interface NavbarSocialsProps extends ComponentBase {
35
35
  link: string
36
36
  }
37
37
 
38
- export const Navbar = ({
39
- children,
40
- className,
41
- ...props
42
- }: ComponentBase) => {
38
+ export const Navbar = ({ children, className, ...props }: ComponentBase) => {
43
39
  return (
44
40
  <header
45
41
  className={cn(
@@ -226,11 +222,7 @@ const NavbarSearchTrigger = ({
226
222
  )
227
223
  }
228
224
 
229
- const NavbarTheme = ({
230
- className,
231
- theme,
232
- onThemeChange,
233
- }: NavbarThemeProps) => {
225
+ const NavbarTheme = ({ className, theme, onThemeChange }: NavbarThemeProps) => {
234
226
  return (
235
227
  <ToggleButton
236
228
  isSelected={theme === 'dark'}
@@ -255,11 +247,7 @@ const Icon = ({ name }: { name: BoltdocsSocialLink['icon'] }) => {
255
247
  if (name === 'bluesky') return <IconsSocials.Bluesky />
256
248
  }
257
249
 
258
- const NavbarSocials = ({
259
- icon,
260
- link,
261
- className,
262
- }: NavbarSocialsProps) => {
250
+ const NavbarSocials = ({ icon, link, className }: NavbarSocialsProps) => {
263
251
  return (
264
252
  <Link
265
253
  href={link}
@@ -300,4 +288,4 @@ Navbar.Socials = NavbarSocials
300
288
  Navbar.Split = NavbarSplit
301
289
  Navbar.Content = NavbarContent
302
290
 
303
- export default Navbar
291
+ export default Navbar
@@ -1,6 +1,6 @@
1
1
  import * as RAC from 'react-aria-components'
2
2
  import { ChevronDown } from 'lucide-react'
3
- import { cn } from '@client/utils/cn'
3
+ import { cn } from '../../utils/cn'
4
4
  import type { ComponentBase, CompoundComponent } from './types'
5
5
 
6
6
  export interface NavigationMenuItemProps extends ComponentBase {
@@ -13,8 +13,8 @@ export interface NavigationMenuLinkProps
13
13
  label: string
14
14
  description?: string
15
15
  children?:
16
- | React.ReactNode
17
- | ((opts: RAC.MenuItemRenderProps) => React.ReactNode)
16
+ | React.ReactNode
17
+ | ((opts: RAC.MenuItemRenderProps) => React.ReactNode)
18
18
  }
19
19
 
20
20
  export type NavigationMenuComponent = CompoundComponent<
@@ -111,4 +111,4 @@ const NavigationMenuLink = ({
111
111
  NavigationMenu.Root = NavigationMenu
112
112
  NavigationMenu.List = NavigationMenuList
113
113
  NavigationMenu.Item = NavigationMenuItem
114
- NavigationMenu.Link = NavigationMenuLink
114
+ NavigationMenu.Link = NavigationMenuLink
@@ -1,4 +1,4 @@
1
- import React, {
1
+ import {
2
2
  createContext,
3
3
  use,
4
4
  useEffect,
@@ -10,8 +10,8 @@ import React, {
10
10
  type RefObject,
11
11
  } from 'react'
12
12
  import scrollIntoView from 'scroll-into-view-if-needed'
13
- import { cn } from '@client/utils/cn'
14
- import { useOnChange } from '@client/utils/use-on-change'
13
+ import { cn } from '../../utils/cn'
14
+ import { useOnChange } from '../../utils/use-on-change'
15
15
  import type { ComponentBase } from './types'
16
16
  import { getItemId, Observer } from './helpers/observer'
17
17
 
@@ -165,15 +165,11 @@ export const OnThisPage = ({ children, className }: ComponentBase) => {
165
165
  )
166
166
  }
167
167
 
168
- const OnThisPageHeader = ({
169
- children,
170
- className,
171
- ...props
172
- }: ComponentBase) => {
168
+ const OnThisPageHeader = ({ children, className, ...props }: ComponentBase) => {
173
169
  return (
174
170
  <div
175
171
  className={cn(
176
- 'mb-4 text-xs font-bold uppercase tracking-wider text-text-main',
172
+ 'mb-4 text-xs font-bold text-text-main',
177
173
  className,
178
174
  )}
179
175
  {...props}
@@ -302,4 +298,4 @@ OnThisPage.Content = OnThisPageContent
302
298
  OnThisPage.List = OnThisPageList
303
299
  OnThisPage.Item = OnThisPageItem
304
300
  OnThisPage.Link = OnThisPageLink
305
- OnThisPage.Indicator = OnThisPageIndicator
301
+ OnThisPage.Indicator = OnThisPageIndicator
@@ -1,6 +1,6 @@
1
1
  import * as RAC from 'react-aria-components'
2
2
  import { ChevronLeft, ChevronRight } from 'lucide-react'
3
- import { cn } from '@client/utils/cn'
3
+ import { cn } from '../../utils/cn'
4
4
  import type { ComponentBase } from './types'
5
5
 
6
6
  export interface PageNavProps extends ComponentBase {
@@ -21,12 +21,7 @@ export const PageNav = ({ children, className }: ComponentBase) => {
21
21
  )
22
22
  }
23
23
 
24
- const PageNavLink = ({
25
- children,
26
- to,
27
- direction,
28
- className,
29
- }: PageNavProps) => {
24
+ const PageNavLink = ({ children, to, direction, className }: PageNavProps) => {
30
25
  const isNext = direction === 'next'
31
26
  return (
32
27
  <RAC.Link
@@ -54,7 +49,7 @@ const PageNavTitle = ({ children, className }: ComponentBase) => {
54
49
  return (
55
50
  <span
56
51
  className={cn(
57
- 'text-xs font-medium uppercase tracking-wider text-text-muted',
52
+ 'text-xs font-medium uppercase text-text-muted',
58
53
  className,
59
54
  )}
60
55
  >
@@ -81,4 +76,4 @@ PageNav.Root = PageNav
81
76
  PageNav.Link = PageNavLink
82
77
  PageNav.Title = PageNavTitle
83
78
  PageNav.Description = PageNavDescription
84
- PageNav.Icon = PageNavIcon
79
+ PageNav.Icon = PageNavIcon
@@ -1,7 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import * as RAC from 'react-aria-components'
4
- import { cn } from '@client/utils/cn'
4
+ import { cn } from '../../utils/cn'
5
5
 
6
6
  export interface PopoverProps extends Omit<RAC.PopoverProps, 'children'> {
7
7
  children: React.ReactNode
@@ -1,6 +1,6 @@
1
1
  import * as RAC from 'react-aria-components'
2
2
  import { Search, Hash, FileText, CornerDownLeft } from 'lucide-react'
3
- import { cn } from '@client/utils/cn'
3
+ import { cn } from '../../utils/cn'
4
4
  import type { ComponentBase } from './types'
5
5
 
6
6
  export interface SearchDialogProps extends ComponentBase {
@@ -153,10 +153,7 @@ const SearchDialogItemIcon = ({
153
153
  )
154
154
  }
155
155
 
156
- const SearchDialogItemTitle = ({
157
- children,
158
- className,
159
- }: ComponentBase) => {
156
+ const SearchDialogItemTitle = ({ children, className }: ComponentBase) => {
160
157
  return (
161
158
  <span
162
159
  className={cn('block font-medium truncate flex-1 text-sm', className)}
@@ -187,4 +184,4 @@ SearchDialog.Item = Object.assign(SearchDialogItemRoot, {
187
184
  Icon: SearchDialogItemIcon,
188
185
  Title: SearchDialogItemTitle,
189
186
  Bio: SearchDialogItemBio,
190
- })
187
+ })
@@ -1,15 +1,19 @@
1
1
  import { Link } from './link'
2
2
  import * as RAC from 'react-aria-components'
3
3
  import { ChevronRight } from 'lucide-react'
4
- import { cn } from '@client/utils/cn'
4
+ import { cn } from '../../utils/cn'
5
5
  import type { ComponentBase } from './types'
6
- import type { ComponentRoute } from '@client/types'
6
+ import type { ComponentRoute } from '../../types'
7
7
 
8
8
  export interface SidebarGroupProps extends ComponentBase {
9
9
  title?: string
10
10
  icon?: React.ElementType
11
+ }
12
+
13
+ export interface SidebarSubGroupProps extends SidebarLinkProps {
11
14
  isOpen?: boolean
12
15
  onToggle?: () => void
16
+ children?: React.ReactNode
13
17
  }
14
18
 
15
19
  export interface SidebarLinkProps extends ComponentBase {
@@ -73,35 +77,24 @@ const SidebarGroup = ({
73
77
  children,
74
78
  title,
75
79
  icon: Icon,
76
- isOpen = true,
77
- onToggle,
78
80
  className,
79
81
  }: SidebarGroupProps) => {
80
82
  return (
81
83
  <div className={cn('space-y-1', className)}>
82
84
  {title && (
83
- <RAC.Button
84
- onPress={onToggle}
85
+ <div
85
86
  className={cn(
86
- 'flex w-full items-center justify-between px-2 py-1.5 text-xs font-bold uppercase tracking-wider outline-none cursor-pointer',
87
- 'text-text-muted hover:text-text-main transition-colors',
88
- 'focus-visible:ring-2 focus-visible:ring-primary-500/30 rounded-md',
87
+ 'flex w-full items-center justify-between px-2 py-1.5 text-sm font-semibold',
88
+ 'text-text-main',
89
89
  )}
90
90
  >
91
91
  <div className="flex items-center gap-2">
92
92
  {Icon && <Icon size={14} />}
93
93
  {title}
94
94
  </div>
95
- <ChevronRight
96
- size={14}
97
- className={cn(
98
- 'transition-transform duration-200',
99
- isOpen && 'rotate-90',
100
- )}
101
- />
102
- </RAC.Button>
95
+ </div>
103
96
  )}
104
- {isOpen && <div className="space-y-0.5">{children}</div>}
97
+ {children && <div className="space-y-0.5">{children}</div>}
105
98
  </div>
106
99
  )
107
100
  }
@@ -125,9 +118,10 @@ const SidebarLink = ({
125
118
  'group flex items-center gap-2.5 rounded-lg px-2.5 py-2 text-sm outline-none',
126
119
  'transition-all duration-200 ease-in-out',
127
120
  'focus-visible:ring-2 focus-visible:ring-primary-500/30',
128
- active
129
- ? 'bg-primary-500/10 text-primary-500 font-medium'
130
- : 'text-text-muted hover:bg-bg-surface hover:text-text-main hover:translate-x-1',
121
+ {
122
+ 'bg-primary-500/10 text-primary-500 font-medium': active,
123
+ 'text-text-muted hover:bg-bg-muted hover:text-text-main': !active,
124
+ },
131
125
  className,
132
126
  )}
133
127
  >
@@ -147,7 +141,71 @@ const SidebarLink = ({
147
141
  )
148
142
  }
149
143
 
144
+ const SidebarSubGroup = ({
145
+ label,
146
+ href,
147
+ active,
148
+ icon: Icon,
149
+ badge,
150
+ className,
151
+ isOpen = false,
152
+ onToggle,
153
+ children,
154
+ }: SidebarSubGroupProps) => {
155
+ return (
156
+ <div className="space-y-0.5">
157
+ <div className="flex items-center w-full">
158
+ <Link
159
+ href={href}
160
+ className={cn(
161
+ 'group flex flex-1 items-center gap-2.5 rounded-lg px-2.5 py-2 text-sm outline-none',
162
+ 'transition-all duration-200 ease-in-out',
163
+ 'focus-visible:ring-2 focus-visible:ring-primary-500/30',
164
+ active
165
+ ? 'bg-primary-500/10 text-primary-500 font-medium'
166
+ : 'text-text-muted hover:bg-bg-surface hover:text-text-main hover:translate-x-1',
167
+ className,
168
+ )}
169
+ >
170
+ {Icon && (
171
+ <Icon
172
+ size={16}
173
+ className={cn(
174
+ active
175
+ ? 'text-primary-500'
176
+ : 'text-text-muted group-hover:text-text-main',
177
+ )}
178
+ />
179
+ )}
180
+ <span className="truncate">{label}</span>
181
+ {badge && <Badge badge={badge} />}
182
+ </Link>
183
+ {children && (
184
+ <RAC.Button
185
+ onPress={onToggle}
186
+ className="flex items-center justify-center p-1.5 ml-1 rounded-md text-text-muted hover:bg-bg-surface hover:text-text-main transition-colors outline-none focus-visible:ring-2 focus-visible:ring-primary-500/30 cursor-pointer"
187
+ >
188
+ <ChevronRight
189
+ size={16}
190
+ className={cn(
191
+ 'transition-transform duration-200',
192
+ isOpen && 'rotate-90',
193
+ )}
194
+ />
195
+ </RAC.Button>
196
+ )}
197
+ </div>
198
+ {isOpen && children && (
199
+ <div className="pl-4 ml-[7px] border-l border-border-subtle/50 space-y-0.5 mt-0.5">
200
+ {children}
201
+ </div>
202
+ )}
203
+ </div>
204
+ )
205
+ }
206
+
150
207
  Sidebar.Root = Sidebar
151
208
  Sidebar.Group = SidebarGroup
209
+ Sidebar.SubGroup = SidebarSubGroup
152
210
  Sidebar.GroupItem = SidebarGroupItem
153
- Sidebar.Link = SidebarLink
211
+ Sidebar.Link = SidebarLink
@@ -1,4 +1,4 @@
1
- import { cn } from '@client/utils/cn'
1
+ import { cn } from '../../utils/cn'
2
2
 
3
3
  interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
4
4
  variant?: 'rect' | 'circle'
@@ -1,4 +1,4 @@
1
- import { cn } from '@client/utils/cn'
1
+ import { cn } from '../../utils/cn'
2
2
  import type { ComponentBase } from './types'
3
3
 
4
4
  export interface TabsItemProps extends ComponentBase {
@@ -13,11 +13,7 @@ export interface TabsIndicatorProps extends ComponentBase {
13
13
  style?: React.CSSProperties
14
14
  }
15
15
 
16
- export const Tabs = ({
17
- children,
18
- className = '',
19
- ...props
20
- }: ComponentBase) => {
16
+ export const Tabs = ({ children, className = '', ...props }: ComponentBase) => {
21
17
  return (
22
18
  <div className={cn('w-full', className)} {...props}>
23
19
  {children}
@@ -66,10 +62,7 @@ const TabsContent = ({ children, className = '' }: ComponentBase) => {
66
62
  return <div className={cn('p-4 outline-none', className)}>{children}</div>
67
63
  }
68
64
 
69
- const TabsIndicator = ({
70
- className = '',
71
- style,
72
- }: TabsIndicatorProps) => {
65
+ const TabsIndicator = ({ className = '', style }: TabsIndicatorProps) => {
73
66
  return (
74
67
  <div
75
68
  className={cn(
@@ -85,4 +78,4 @@ Tabs.Root = Tabs
85
78
  Tabs.List = TabsList
86
79
  Tabs.Item = TabsItem
87
80
  Tabs.Content = TabsContent
88
- Tabs.Indicator = TabsIndicator
81
+ Tabs.Indicator = TabsIndicator
@@ -1,6 +1,6 @@
1
1
  import type { ReactNode } from 'react'
2
2
  import * as RAC from 'react-aria-components'
3
- import { cn } from '@client/utils/cn'
3
+ import { cn } from '../../utils/cn'
4
4
 
5
5
  export interface TooltipProps extends Omit<RAC.TooltipProps, 'children'> {
6
6
  /** The content to show inside the tooltip */
@@ -14,7 +14,7 @@ export interface TooltipProps extends Omit<RAC.TooltipProps, 'children'> {
14
14
  }
15
15
 
16
16
  // Fixed type for TooltipContentProps to match RAC's internal expectations
17
- export interface TooltipContentProps extends RAC.TooltipProps { }
17
+ export interface TooltipContentProps extends RAC.TooltipProps {}
18
18
 
19
19
  /**
20
20
  * Modern, accessible Tooltip component built with React Aria Components.
@@ -78,4 +78,4 @@ export const Tooltip = ({
78
78
  }
79
79
 
80
80
  Tooltip.Root = Tooltip
81
- Tooltip.Content = TooltipContent
81
+ Tooltip.Content = TooltipContent
@@ -1,10 +1,8 @@
1
- import { useBreadcrumbs } from '@hooks/use-breadcrumbs'
1
+ import { useBreadcrumbs } from '../../hooks/use-breadcrumbs'
2
2
  import { Home } from 'lucide-react'
3
- import {
4
- Breadcrumbs as BreadcrumbsRoot,
5
- } from '@components/primitives/breadcrumbs'
6
- import { cn } from '@client/utils/cn'
7
- import { useConfig } from '@client/app/config-context'
3
+ import { Breadcrumbs as BreadcrumbsRoot } from '../primitives/breadcrumbs'
4
+ import { cn } from '../../utils/cn'
5
+ import { useConfig } from '../../app/config-context'
8
6
 
9
7
  export function Breadcrumbs() {
10
8
  const { crumbs, activeRoute } = useBreadcrumbs()
@@ -1,13 +1,8 @@
1
1
  import { useState } from 'react'
2
2
  import { Copy, Check, ExternalLink, ChevronDown } from 'lucide-react'
3
- import {
4
- Button,
5
- ButtonGroup,
6
- Menu,
7
- cn,
8
- } from '@client/components/primitives'
3
+ import { Button, ButtonGroup, Menu, cn } from '../../components/primitives'
9
4
 
10
- import type { ComponentRoute } from '@client/types'
5
+ import type { ComponentRoute } from '../../types'
11
6
 
12
7
  export interface CopyMarkdownProps {
13
8
  content?: string
@@ -1,6 +1,6 @@
1
1
  import { useEffect, useState } from 'react'
2
- import { getStarsRepo } from '@client/utils/github'
3
- import { Github } from '@components/icons-dev'
2
+ import { getStarsRepo } from '../../utils/github'
3
+ import { Github } from '../icons-dev'
4
4
 
5
5
  export function GithubStars({ repo }: { repo: string }) {
6
6
  const [stars, setStars] = useState<string | null>(null)