@hanzo/ui 5.3.26 → 5.3.29

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 (100) hide show
  1. package/content/index.ts +26 -0
  2. package/dist/util/index.js +6 -0
  3. package/dist/util/index.mjs +6 -1
  4. package/docs/_registry/index.ts +426 -0
  5. package/docs/_registry/layout/docs-min.tsx +197 -0
  6. package/docs/_registry/layout/page-min.tsx +128 -0
  7. package/docs/components/accordion.tsx +118 -0
  8. package/docs/components/banner.tsx +144 -0
  9. package/docs/components/callout.tsx +112 -0
  10. package/docs/components/card.tsx +52 -0
  11. package/docs/components/codeblock.tsx +258 -0
  12. package/docs/components/dialog/search-algolia.tsx +132 -0
  13. package/docs/components/dialog/search-default.tsx +131 -0
  14. package/docs/components/dialog/search-orama.tsx +143 -0
  15. package/docs/components/dialog/search.tsx +529 -0
  16. package/docs/components/dynamic-codeblock.tsx +129 -0
  17. package/docs/components/files.tsx +81 -0
  18. package/docs/components/github-info.tsx +107 -0
  19. package/docs/components/heading.tsx +33 -0
  20. package/docs/components/image-zoom.css +77 -0
  21. package/docs/components/image-zoom.tsx +58 -0
  22. package/docs/components/index.ts +7 -0
  23. package/docs/components/inline-toc.tsx +48 -0
  24. package/docs/components/sidebar/base.tsx +451 -0
  25. package/docs/components/sidebar/link-item.tsx +65 -0
  26. package/docs/components/sidebar/page-tree.tsx +113 -0
  27. package/docs/components/sidebar/tabs/dropdown.tsx +109 -0
  28. package/docs/components/sidebar/tabs/index.tsx +89 -0
  29. package/docs/components/steps.tsx +9 -0
  30. package/docs/components/tabs.tsx +203 -0
  31. package/docs/components/toc/clerk.tsx +173 -0
  32. package/docs/components/toc/default.tsx +57 -0
  33. package/docs/components/toc/index.tsx +136 -0
  34. package/docs/components/type-table.tsx +174 -0
  35. package/docs/components/ui/accordion.tsx +88 -0
  36. package/docs/components/ui/button.tsx +28 -0
  37. package/docs/components/ui/collapsible.tsx +42 -0
  38. package/docs/components/ui/navigation-menu.tsx +83 -0
  39. package/docs/components/ui/popover.tsx +32 -0
  40. package/docs/components/ui/scroll-area.tsx +59 -0
  41. package/docs/components/ui/tabs.tsx +145 -0
  42. package/docs/contexts/i18n.tsx +56 -0
  43. package/docs/contexts/search.tsx +165 -0
  44. package/docs/contexts/tree.tsx +65 -0
  45. package/docs/css/black.css +39 -0
  46. package/docs/css/catppuccin.css +49 -0
  47. package/docs/css/colors/index.css +51 -0
  48. package/docs/css/dusk.css +47 -0
  49. package/docs/css/layouts/docs.css +1 -0
  50. package/docs/css/layouts/home.css +1 -0
  51. package/docs/css/layouts/notebook.css +1 -0
  52. package/docs/css/neutral.css +7 -0
  53. package/docs/css/ocean.css +48 -0
  54. package/docs/css/preset.css +305 -0
  55. package/docs/css/purple.css +39 -0
  56. package/docs/css/shadcn.css +36 -0
  57. package/docs/css/shiki.css +90 -0
  58. package/docs/css/solar.css +75 -0
  59. package/docs/css/style.css +9 -0
  60. package/docs/css/vitepress.css +77 -0
  61. package/docs/i18n.tsx +30 -0
  62. package/docs/icons.tsx +354 -0
  63. package/docs/layouts/docs/client.tsx +129 -0
  64. package/docs/layouts/docs/index.tsx +321 -0
  65. package/docs/layouts/docs/page/client.tsx +376 -0
  66. package/docs/layouts/docs/page/index.tsx +251 -0
  67. package/docs/layouts/docs/sidebar.tsx +265 -0
  68. package/docs/layouts/home/client.tsx +375 -0
  69. package/docs/layouts/home/index.tsx +51 -0
  70. package/docs/layouts/home/navbar.tsx +55 -0
  71. package/docs/layouts/notebook/client.tsx +281 -0
  72. package/docs/layouts/notebook/index.tsx +461 -0
  73. package/docs/layouts/notebook/page/client.tsx +375 -0
  74. package/docs/layouts/notebook/page/index.tsx +251 -0
  75. package/docs/layouts/notebook/sidebar.tsx +248 -0
  76. package/docs/layouts/shared/index.tsx +89 -0
  77. package/docs/layouts/shared/language-toggle.tsx +66 -0
  78. package/docs/layouts/shared/link-item.tsx +119 -0
  79. package/docs/layouts/shared/search-toggle.tsx +78 -0
  80. package/docs/layouts/shared/theme-toggle.tsx +86 -0
  81. package/docs/mdx.server.tsx +37 -0
  82. package/docs/mdx.tsx +97 -0
  83. package/docs/og.tsx +101 -0
  84. package/docs/page.tsx +85 -0
  85. package/docs/provider/base.tsx +173 -0
  86. package/docs/provider/next.tsx +23 -0
  87. package/docs/provider/react-router.tsx +23 -0
  88. package/docs/provider/tanstack.tsx +23 -0
  89. package/docs/provider/waku.tsx +23 -0
  90. package/docs/source.ts +3 -0
  91. package/docs/theme/typography/LICENSE +21 -0
  92. package/docs/theme/typography/index.ts +201 -0
  93. package/docs/theme/typography/styles.ts +449 -0
  94. package/docs/utils/cn.ts +1 -0
  95. package/docs/utils/is-active.ts +23 -0
  96. package/docs/utils/merge-refs.ts +15 -0
  97. package/docs/utils/use-copy-button.ts +39 -0
  98. package/docs/utils/use-footer-items.ts +27 -0
  99. package/docs/utils/use-is-scroll-top.ts +21 -0
  100. package/package.json +4 -2
@@ -0,0 +1,461 @@
1
+ import {
2
+ type ComponentProps,
3
+ type FC,
4
+ type HTMLAttributes,
5
+ type ReactNode,
6
+ useMemo,
7
+ } from 'react';
8
+ import { type BaseLayoutProps, resolveLinkItems } from '@/layouts/shared';
9
+ import {
10
+ Sidebar,
11
+ SidebarCollapseTrigger,
12
+ SidebarContent,
13
+ SidebarDrawer,
14
+ SidebarLinkItem,
15
+ SidebarPageTree,
16
+ SidebarTrigger,
17
+ SidebarViewport,
18
+ } from './sidebar';
19
+ import { TreeContextProvider } from '@/contexts/tree';
20
+ import { cn } from '@/utils/cn';
21
+ import { buttonVariants } from '@/components/ui/button';
22
+ import { Languages, Sidebar as SidebarIcon, X } from '@icons';
23
+ import { LanguageToggle } from '@/layouts/shared/language-toggle';
24
+ import { ThemeToggle } from '@/layouts/shared/theme-toggle';
25
+ import type * as PageTree from '@hanzo/docs-core/page-tree';
26
+ import {
27
+ LayoutBody,
28
+ LayoutContextProvider,
29
+ LayoutHeader,
30
+ LayoutHeaderTabs,
31
+ NavbarLinkItem,
32
+ } from '@/layouts/notebook/client';
33
+ import Link from '@hanzo/docs-core/link';
34
+ import {
35
+ LargeSearchToggle,
36
+ SearchToggle,
37
+ } from '@/layouts/shared/search-toggle';
38
+ import { LinkItem, type LinkItemType } from '@/layouts/shared/link-item';
39
+ import type { SidebarPageTreeComponents } from '@/components/sidebar/page-tree';
40
+ import {
41
+ getSidebarTabs,
42
+ type GetSidebarTabsOptions,
43
+ } from '@/components/sidebar/tabs';
44
+ import {
45
+ SidebarTabsDropdown,
46
+ type SidebarTabWithProps,
47
+ } from '@/components/sidebar/tabs/dropdown';
48
+
49
+ export interface DocsLayoutProps extends BaseLayoutProps {
50
+ tree: PageTree.Root;
51
+ tabMode?: 'sidebar' | 'navbar';
52
+
53
+ nav?: BaseLayoutProps['nav'] & {
54
+ mode?: 'top' | 'auto';
55
+ };
56
+
57
+ sidebar?: SidebarOptions;
58
+
59
+ containerProps?: HTMLAttributes<HTMLDivElement>;
60
+ }
61
+
62
+ interface SidebarOptions
63
+ extends
64
+ ComponentProps<'aside'>,
65
+ Pick<ComponentProps<typeof Sidebar>, 'defaultOpenLevel' | 'prefetch'> {
66
+ components?: Partial<SidebarPageTreeComponents>;
67
+
68
+ /**
69
+ * Root Toggle options
70
+ */
71
+ tabs?: SidebarTabWithProps[] | GetSidebarTabsOptions | false;
72
+
73
+ banner?: ReactNode | FC<ComponentProps<'div'>>;
74
+ footer?: ReactNode | FC<ComponentProps<'div'>>;
75
+
76
+ /**
77
+ * Support collapsing the sidebar on desktop mode
78
+ *
79
+ * @defaultValue true
80
+ */
81
+ collapsible?: boolean;
82
+ }
83
+
84
+ export function DocsLayout(props: DocsLayoutProps) {
85
+ const {
86
+ tabMode = 'sidebar',
87
+ nav = {},
88
+ sidebar: {
89
+ tabs: tabOptions,
90
+ defaultOpenLevel,
91
+ prefetch,
92
+ ...sidebarProps
93
+ } = {},
94
+ i18n = false,
95
+ themeSwitch = {},
96
+ tree,
97
+ } = props;
98
+
99
+ const navMode = nav.mode ?? 'auto';
100
+ const links = resolveLinkItems(props);
101
+ const tabs = useMemo(() => {
102
+ if (Array.isArray(tabOptions)) {
103
+ return tabOptions;
104
+ }
105
+
106
+ if (typeof tabOptions === 'object') {
107
+ return getSidebarTabs(tree, tabOptions);
108
+ }
109
+
110
+ if (tabOptions !== false) {
111
+ return getSidebarTabs(tree);
112
+ }
113
+
114
+ return [];
115
+ }, [tabOptions, tree]);
116
+
117
+ function sidebar() {
118
+ const {
119
+ banner,
120
+ footer,
121
+ components,
122
+ collapsible = true,
123
+ ...rest
124
+ } = sidebarProps;
125
+
126
+ const iconLinks = links.filter((item) => item.type === 'icon');
127
+ const Header =
128
+ typeof banner === 'function'
129
+ ? banner
130
+ : ({ className, ...props }: ComponentProps<'div'>) => (
131
+ <div
132
+ className={cn(
133
+ 'flex flex-col gap-3 p-4 pb-2 empty:hidden',
134
+ className,
135
+ )}
136
+ {...props}
137
+ >
138
+ {props.children}
139
+ {banner}
140
+ </div>
141
+ );
142
+ const Footer =
143
+ typeof footer === 'function'
144
+ ? footer
145
+ : ({ className, ...props }: ComponentProps<'div'>) => (
146
+ <div
147
+ className={cn(
148
+ 'hidden flex-row text-fd-muted-foreground items-center border-t p-4 pt-2',
149
+ iconLinks.length > 0 && 'max-lg:flex',
150
+ className,
151
+ )}
152
+ {...props}
153
+ >
154
+ {props.children}
155
+ {footer}
156
+ </div>
157
+ );
158
+ const viewport = (
159
+ <SidebarViewport>
160
+ {links
161
+ .filter((item) => item.type !== 'icon')
162
+ .map((item, i, arr) => (
163
+ <SidebarLinkItem
164
+ key={i}
165
+ item={item}
166
+ className={cn('lg:hidden', i === arr.length - 1 && 'mb-4')}
167
+ />
168
+ ))}
169
+
170
+ <SidebarPageTree {...components} />
171
+ </SidebarViewport>
172
+ );
173
+
174
+ return (
175
+ <>
176
+ <SidebarContent {...rest}>
177
+ <Header>
178
+ {navMode === 'auto' && (
179
+ <div className="flex justify-between">
180
+ <Link
181
+ href={nav.url ?? '/'}
182
+ className="inline-flex items-center gap-2.5 font-medium"
183
+ >
184
+ {nav.title}
185
+ </Link>
186
+ {collapsible && (
187
+ <SidebarCollapseTrigger
188
+ className={cn(
189
+ buttonVariants({
190
+ color: 'ghost',
191
+ size: 'icon-sm',
192
+ className: 'mt-px mb-auto text-fd-muted-foreground',
193
+ }),
194
+ )}
195
+ >
196
+ <SidebarIcon />
197
+ </SidebarCollapseTrigger>
198
+ )}
199
+ </div>
200
+ )}
201
+ {nav.children}
202
+ {tabs.length > 0 && (
203
+ <SidebarTabsDropdown
204
+ options={tabs}
205
+ className={cn(tabMode === 'navbar' && 'lg:hidden')}
206
+ />
207
+ )}
208
+ </Header>
209
+ {viewport}
210
+ <Footer>
211
+ {iconLinks.map((item, i) => (
212
+ <LinkItem
213
+ key={i}
214
+ item={item}
215
+ className={cn(
216
+ buttonVariants({
217
+ size: 'icon-sm',
218
+ color: 'ghost',
219
+ className: 'lg:hidden',
220
+ }),
221
+ )}
222
+ aria-label={item.label}
223
+ >
224
+ {item.icon}
225
+ </LinkItem>
226
+ ))}
227
+ </Footer>
228
+ </SidebarContent>
229
+ <SidebarDrawer {...rest}>
230
+ <Header>
231
+ <SidebarTrigger
232
+ className={cn(
233
+ buttonVariants({
234
+ size: 'icon-sm',
235
+ color: 'ghost',
236
+ className: 'ms-auto text-fd-muted-foreground',
237
+ }),
238
+ )}
239
+ >
240
+ <X />
241
+ </SidebarTrigger>
242
+ {tabs.length > 0 && <SidebarTabsDropdown options={tabs} />}
243
+ </Header>
244
+ {viewport}
245
+ <Footer
246
+ className={cn(
247
+ 'hidden flex-row items-center justify-end',
248
+ (i18n || themeSwitch.enabled !== false) && 'flex',
249
+ iconLinks.length > 0 && 'max-lg:flex',
250
+ )}
251
+ >
252
+ {iconLinks.map((item, i) => (
253
+ <LinkItem
254
+ key={i}
255
+ item={item}
256
+ className={cn(
257
+ buttonVariants({
258
+ size: 'icon-sm',
259
+ color: 'ghost',
260
+ }),
261
+ 'text-fd-muted-foreground lg:hidden',
262
+ i === iconLinks.length - 1 && 'me-auto',
263
+ )}
264
+ aria-label={item.label}
265
+ >
266
+ {item.icon}
267
+ </LinkItem>
268
+ ))}
269
+ {i18n && (
270
+ <LanguageToggle>
271
+ <Languages className="size-4.5 text-fd-muted-foreground" />
272
+ </LanguageToggle>
273
+ )}
274
+ {themeSwitch.enabled !== false &&
275
+ (themeSwitch.component ?? (
276
+ <ThemeToggle mode={themeSwitch.mode ?? 'light-dark-system'} />
277
+ ))}
278
+ </Footer>
279
+ </SidebarDrawer>
280
+ </>
281
+ );
282
+ }
283
+
284
+ return (
285
+ <TreeContextProvider tree={tree}>
286
+ <LayoutContextProvider
287
+ navMode={nav.mode ?? 'auto'}
288
+ tabMode={tabMode}
289
+ navTransparentMode={nav.transparentMode}
290
+ >
291
+ <Sidebar defaultOpenLevel={defaultOpenLevel} prefetch={prefetch}>
292
+ <LayoutBody {...props.containerProps}>
293
+ {sidebar()}
294
+ <DocsNavbar {...props} links={links} tabs={tabs} />
295
+ {props.children}
296
+ </LayoutBody>
297
+ </Sidebar>
298
+ </LayoutContextProvider>
299
+ </TreeContextProvider>
300
+ );
301
+ }
302
+
303
+ function DocsNavbar({
304
+ links,
305
+ tabs,
306
+ tabMode = 'sidebar',
307
+ sidebar: { collapsible: sidebarCollapsible = true } = {},
308
+ searchToggle = {},
309
+ themeSwitch = {},
310
+ nav = {},
311
+ i18n,
312
+ }: DocsLayoutProps & {
313
+ links: LinkItemType[];
314
+ tabs: SidebarTabWithProps[];
315
+ }) {
316
+ const navMode = nav.mode ?? 'auto';
317
+ const showLayoutTabs = tabMode === 'navbar' && tabs.length > 0;
318
+
319
+ return (
320
+ <LayoutHeader
321
+ id="nd-subnav"
322
+ className={cn(
323
+ 'sticky [grid-area:header] flex flex-col top-(--fd-docs-row-1) z-10 backdrop-blur-sm transition-colors data-[transparent=false]:bg-fd-background/80 layout:[--fd-header-height:--spacing(14)]',
324
+ showLayoutTabs && 'lg:layout:[--fd-header-height:--spacing(24)]',
325
+ )}
326
+ >
327
+ <div
328
+ data-header-body=""
329
+ className="flex border-b px-4 gap-2 h-14 md:px-6"
330
+ >
331
+ <div
332
+ className={cn(
333
+ 'items-center',
334
+ navMode === 'top' && 'flex flex-1',
335
+ navMode === 'auto' &&
336
+ 'hidden has-data-[collapsed=true]:md:flex max-md:flex',
337
+ )}
338
+ >
339
+ {sidebarCollapsible && navMode === 'auto' && (
340
+ <SidebarCollapseTrigger
341
+ className={cn(
342
+ buttonVariants({
343
+ color: 'ghost',
344
+ size: 'icon-sm',
345
+ }),
346
+ 'text-fd-muted-foreground data-[collapsed=false]:hidden max-md:hidden',
347
+ )}
348
+ >
349
+ <SidebarIcon />
350
+ </SidebarCollapseTrigger>
351
+ )}
352
+ <Link
353
+ href={nav.url ?? '/'}
354
+ className={cn(
355
+ 'inline-flex items-center gap-2.5 font-semibold',
356
+ navMode === 'auto' && 'md:hidden',
357
+ )}
358
+ >
359
+ {nav.title}
360
+ </Link>
361
+ </div>
362
+ {searchToggle.enabled !== false &&
363
+ (searchToggle.components?.lg ? (
364
+ <div
365
+ className={cn(
366
+ 'w-full my-auto max-md:hidden',
367
+ navMode === 'top' ? 'rounded-xl max-w-sm' : 'max-w-[240px]',
368
+ )}
369
+ >
370
+ {searchToggle.components.lg}
371
+ </div>
372
+ ) : (
373
+ <LargeSearchToggle
374
+ hideIfDisabled
375
+ className={cn(
376
+ 'w-full my-auto max-md:hidden',
377
+ navMode === 'top'
378
+ ? 'rounded-xl max-w-sm ps-2.5'
379
+ : 'max-w-[240px]',
380
+ )}
381
+ />
382
+ ))}
383
+ <div className="flex flex-1 items-center justify-end md:gap-2">
384
+ <div className="flex items-center gap-6 empty:hidden max-lg:hidden">
385
+ {links
386
+ .filter((item) => item.type !== 'icon')
387
+ .map((item, i) => (
388
+ <NavbarLinkItem key={i} item={item} />
389
+ ))}
390
+ </div>
391
+ {nav.children}
392
+ {links
393
+ .filter((item) => item.type === 'icon')
394
+ .map((item, i) => (
395
+ <LinkItem
396
+ key={i}
397
+ item={item}
398
+ className={cn(
399
+ buttonVariants({ size: 'icon-sm', color: 'ghost' }),
400
+ 'text-fd-muted-foreground max-lg:hidden',
401
+ )}
402
+ aria-label={item.label}
403
+ >
404
+ {item.icon}
405
+ </LinkItem>
406
+ ))}
407
+
408
+ <div className="flex items-center md:hidden">
409
+ {searchToggle.enabled !== false &&
410
+ (searchToggle.components?.sm ?? (
411
+ <SearchToggle hideIfDisabled className="p-2" />
412
+ ))}
413
+ <SidebarTrigger
414
+ className={cn(
415
+ buttonVariants({
416
+ color: 'ghost',
417
+ size: 'icon-sm',
418
+ className: 'p-2 -me-1.5',
419
+ }),
420
+ )}
421
+ >
422
+ <SidebarIcon />
423
+ </SidebarTrigger>
424
+ </div>
425
+
426
+ <div className="flex items-center gap-2 max-md:hidden">
427
+ {i18n && (
428
+ <LanguageToggle>
429
+ <Languages className="size-4.5 text-fd-muted-foreground" />
430
+ </LanguageToggle>
431
+ )}
432
+ {themeSwitch.enabled !== false &&
433
+ (themeSwitch.component ?? (
434
+ <ThemeToggle mode={themeSwitch.mode ?? 'light-dark-system'} />
435
+ ))}
436
+ {sidebarCollapsible && navMode === 'top' && (
437
+ <SidebarCollapseTrigger
438
+ className={cn(
439
+ buttonVariants({
440
+ color: 'secondary',
441
+ size: 'icon-sm',
442
+ }),
443
+ 'text-fd-muted-foreground rounded-full -me-1.5',
444
+ )}
445
+ >
446
+ <SidebarIcon />
447
+ </SidebarCollapseTrigger>
448
+ )}
449
+ </div>
450
+ </div>
451
+ </div>
452
+ {showLayoutTabs && (
453
+ <LayoutHeaderTabs
454
+ data-header-tabs=""
455
+ className="overflow-x-auto border-b px-6 h-10 max-lg:hidden"
456
+ options={tabs}
457
+ />
458
+ )}
459
+ </LayoutHeader>
460
+ );
461
+ }