@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,281 @@
1
+ 'use client';
2
+ import { cn } from '@/utils/cn';
3
+ import {
4
+ type ComponentProps,
5
+ createContext,
6
+ Fragment,
7
+ type HTMLAttributes,
8
+ type PointerEvent,
9
+ type ReactNode,
10
+ use,
11
+ useMemo,
12
+ useRef,
13
+ useState,
14
+ } from 'react';
15
+ import { useSidebar } from '@/components/sidebar/base';
16
+ import { ChevronDown } from '@icons';
17
+ import Link from '@hanzo/docs-core/link';
18
+ import { usePathname } from '@hanzo/docs-core/framework';
19
+ import { isTabActive } from '@/utils/is-active';
20
+ import { useIsScrollTop } from '@/utils/use-is-scroll-top';
21
+ import {
22
+ LinkItem,
23
+ type LinkItemType,
24
+ type MenuItemType,
25
+ } from '../shared/link-item';
26
+ import {
27
+ Popover,
28
+ PopoverContent,
29
+ PopoverTrigger,
30
+ } from '@/components/ui/popover';
31
+ import type { SidebarTabWithProps } from '@/components/sidebar/tabs/dropdown';
32
+
33
+ export const LayoutContext = createContext<
34
+ | (LayoutInfo & {
35
+ isNavTransparent: boolean;
36
+ })
37
+ | null
38
+ >(null);
39
+
40
+ export interface LayoutInfo {
41
+ tabMode: 'sidebar' | 'navbar';
42
+ navMode: 'top' | 'auto';
43
+ }
44
+
45
+ export function LayoutContextProvider({
46
+ navTransparentMode = 'none',
47
+ navMode,
48
+ tabMode,
49
+ children,
50
+ }: LayoutInfo & {
51
+ navTransparentMode?: 'always' | 'top' | 'none';
52
+ children: ReactNode;
53
+ }) {
54
+ const isTop =
55
+ useIsScrollTop({ enabled: navTransparentMode === 'top' }) ?? true;
56
+ const isNavTransparent =
57
+ navTransparentMode === 'top' ? isTop : navTransparentMode === 'always';
58
+
59
+ return (
60
+ <LayoutContext
61
+ value={useMemo(
62
+ () => ({
63
+ isNavTransparent,
64
+ navMode,
65
+ tabMode,
66
+ }),
67
+ [isNavTransparent, navMode, tabMode],
68
+ )}
69
+ >
70
+ {children}
71
+ </LayoutContext>
72
+ );
73
+ }
74
+
75
+ export function LayoutHeader(props: ComponentProps<'header'>) {
76
+ const { open } = useSidebar();
77
+ const { isNavTransparent } = use(LayoutContext)!;
78
+
79
+ return (
80
+ <header data-transparent={isNavTransparent && !open} {...props}>
81
+ {props.children}
82
+ </header>
83
+ );
84
+ }
85
+
86
+ export function LayoutBody({
87
+ className,
88
+ style,
89
+ children,
90
+ ...props
91
+ }: ComponentProps<'div'>) {
92
+ const { navMode } = use(LayoutContext)!;
93
+ const { collapsed } = useSidebar();
94
+ const pageCol =
95
+ 'calc(var(--fd-layout-width,97rem) - var(--fd-sidebar-col) - var(--fd-toc-width))';
96
+
97
+ return (
98
+ <div
99
+ id="nd-notebook-layout"
100
+ className={cn(
101
+ 'grid overflow-x-clip min-h-(--fd-docs-height) transition-[grid-template-columns] auto-cols-auto auto-rows-auto [--fd-docs-height:100dvh] [--fd-header-height:0px] [--fd-toc-popover-height:0px] [--fd-sidebar-width:0px] [--fd-toc-width:0px]',
102
+ className,
103
+ )}
104
+ style={
105
+ {
106
+ gridTemplate:
107
+ navMode === 'top'
108
+ ? `". header header header ."
109
+ "sidebar sidebar toc-popover toc-popover ."
110
+ "sidebar sidebar main toc ." 1fr / minmax(min-content, 1fr) var(--fd-sidebar-col) minmax(0, ${pageCol}) var(--fd-toc-width) minmax(min-content, 1fr)`
111
+ : `"sidebar sidebar header header ."
112
+ "sidebar sidebar toc-popover toc-popover ."
113
+ "sidebar sidebar main toc ." 1fr / minmax(min-content, 1fr) var(--fd-sidebar-col) minmax(0, ${pageCol}) var(--fd-toc-width) minmax(min-content, 1fr)`,
114
+ '--fd-docs-row-1': 'var(--fd-banner-height, 0px)',
115
+ '--fd-docs-row-2':
116
+ 'calc(var(--fd-docs-row-1) + var(--fd-header-height))',
117
+ '--fd-docs-row-3':
118
+ 'calc(var(--fd-docs-row-2) + var(--fd-toc-popover-height))',
119
+ '--fd-sidebar-col': collapsed ? '0px' : 'var(--fd-sidebar-width)',
120
+ ...style,
121
+ } as object
122
+ }
123
+ {...props}
124
+ >
125
+ {children}
126
+ </div>
127
+ );
128
+ }
129
+
130
+ export function LayoutHeaderTabs({
131
+ options,
132
+ className,
133
+ ...props
134
+ }: ComponentProps<'div'> & {
135
+ options: SidebarTabWithProps[];
136
+ }) {
137
+ const pathname = usePathname();
138
+ const selectedIdx = useMemo(() => {
139
+ return options.findLastIndex((option) => isTabActive(option, pathname));
140
+ }, [options, pathname]);
141
+
142
+ return (
143
+ <div className={cn('flex flex-row items-end gap-6', className)} {...props}>
144
+ {options.map((option, i) => {
145
+ const {
146
+ title,
147
+ url,
148
+ unlisted,
149
+ props: { className, ...rest } = {},
150
+ } = option;
151
+ const isSelected = selectedIdx === i;
152
+
153
+ return (
154
+ <Link
155
+ key={i}
156
+ href={url}
157
+ className={cn(
158
+ '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',
159
+ unlisted && !isSelected && 'hidden',
160
+ isSelected && 'border-fd-primary text-fd-primary',
161
+ className,
162
+ )}
163
+ {...rest}
164
+ >
165
+ {title}
166
+ </Link>
167
+ );
168
+ })}
169
+ </div>
170
+ );
171
+ }
172
+
173
+ export function NavbarLinkItem({
174
+ item,
175
+ className,
176
+ ...props
177
+ }: { item: LinkItemType } & HTMLAttributes<HTMLElement>) {
178
+ if (item.type === 'custom') return item.children;
179
+
180
+ if (item.type === 'menu') {
181
+ return <NavbarLinkItemMenu item={item} className={className} {...props} />;
182
+ }
183
+
184
+ return (
185
+ <LinkItem
186
+ item={item}
187
+ className={cn(
188
+ 'text-sm text-fd-muted-foreground transition-colors hover:text-fd-accent-foreground data-[active=true]:text-fd-primary',
189
+ className,
190
+ )}
191
+ {...props}
192
+ >
193
+ {item.text}
194
+ </LinkItem>
195
+ );
196
+ }
197
+
198
+ function NavbarLinkItemMenu({
199
+ item,
200
+ hoverDelay = 50,
201
+ className,
202
+ ...props
203
+ }: { item: MenuItemType; hoverDelay?: number } & HTMLAttributes<HTMLElement>) {
204
+ const [open, setOpen] = useState(false);
205
+ const timeoutRef = useRef<number>(null);
206
+ const freezeUntil = useRef<number>(null);
207
+
208
+ const delaySetOpen = (value: boolean) => {
209
+ if (timeoutRef.current) {
210
+ clearTimeout(timeoutRef.current);
211
+ timeoutRef.current = null;
212
+ }
213
+
214
+ timeoutRef.current = window.setTimeout(() => {
215
+ setOpen(value);
216
+ freezeUntil.current = Date.now() + 300;
217
+ }, hoverDelay);
218
+ };
219
+ const onPointerEnter = (e: PointerEvent) => {
220
+ if (e.pointerType === 'touch') return;
221
+ delaySetOpen(true);
222
+ };
223
+ const onPointerLeave = (e: PointerEvent) => {
224
+ if (e.pointerType === 'touch') return;
225
+ delaySetOpen(false);
226
+ };
227
+ function isTouchDevice() {
228
+ return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
229
+ }
230
+
231
+ return (
232
+ <Popover
233
+ open={open}
234
+ onOpenChange={(value) => {
235
+ if (freezeUntil.current === null || Date.now() >= freezeUntil.current)
236
+ setOpen(value);
237
+ }}
238
+ >
239
+ <PopoverTrigger
240
+ className={cn(
241
+ 'inline-flex items-center gap-1.5 p-1 text-sm text-fd-muted-foreground transition-colors has-data-[active=true]:text-fd-primary data-[state=open]:text-fd-accent-foreground focus-visible:outline-none',
242
+ className,
243
+ )}
244
+ onPointerEnter={onPointerEnter}
245
+ onPointerLeave={onPointerLeave}
246
+ {...props}
247
+ >
248
+ {item.url ? (
249
+ <LinkItem item={item as { url: string }}>{item.text}</LinkItem>
250
+ ) : (
251
+ item.text
252
+ )}
253
+ <ChevronDown className="size-3" />
254
+ </PopoverTrigger>
255
+ <PopoverContent
256
+ className="flex flex-col p-1 text-fd-muted-foreground text-start"
257
+ onPointerEnter={onPointerEnter}
258
+ onPointerLeave={onPointerLeave}
259
+ >
260
+ {item.items.map((child, i) => {
261
+ if (child.type === 'custom')
262
+ return <Fragment key={i}>{child.children}</Fragment>;
263
+
264
+ return (
265
+ <LinkItem
266
+ key={i}
267
+ item={child}
268
+ className="inline-flex items-center gap-2 rounded-md p-2 transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground data-[active=true]:text-fd-primary [&_svg]:size-4"
269
+ onClick={() => {
270
+ if (isTouchDevice()) setOpen(false);
271
+ }}
272
+ >
273
+ {child.icon}
274
+ {child.text}
275
+ </LinkItem>
276
+ );
277
+ })}
278
+ </PopoverContent>
279
+ </Popover>
280
+ );
281
+ }