@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.
- package/content/index.ts +26 -0
- package/dist/util/index.js +6 -0
- package/dist/util/index.mjs +6 -1
- package/docs/_registry/index.ts +426 -0
- package/docs/_registry/layout/docs-min.tsx +197 -0
- package/docs/_registry/layout/page-min.tsx +128 -0
- package/docs/components/accordion.tsx +118 -0
- package/docs/components/banner.tsx +144 -0
- package/docs/components/callout.tsx +112 -0
- package/docs/components/card.tsx +52 -0
- package/docs/components/codeblock.tsx +258 -0
- package/docs/components/dialog/search-algolia.tsx +132 -0
- package/docs/components/dialog/search-default.tsx +131 -0
- package/docs/components/dialog/search-orama.tsx +143 -0
- package/docs/components/dialog/search.tsx +529 -0
- package/docs/components/dynamic-codeblock.tsx +129 -0
- package/docs/components/files.tsx +81 -0
- package/docs/components/github-info.tsx +107 -0
- package/docs/components/heading.tsx +33 -0
- package/docs/components/image-zoom.css +77 -0
- package/docs/components/image-zoom.tsx +58 -0
- package/docs/components/index.ts +7 -0
- package/docs/components/inline-toc.tsx +48 -0
- package/docs/components/sidebar/base.tsx +451 -0
- package/docs/components/sidebar/link-item.tsx +65 -0
- package/docs/components/sidebar/page-tree.tsx +113 -0
- package/docs/components/sidebar/tabs/dropdown.tsx +109 -0
- package/docs/components/sidebar/tabs/index.tsx +89 -0
- package/docs/components/steps.tsx +9 -0
- package/docs/components/tabs.tsx +203 -0
- package/docs/components/toc/clerk.tsx +173 -0
- package/docs/components/toc/default.tsx +57 -0
- package/docs/components/toc/index.tsx +136 -0
- package/docs/components/type-table.tsx +174 -0
- package/docs/components/ui/accordion.tsx +88 -0
- package/docs/components/ui/button.tsx +28 -0
- package/docs/components/ui/collapsible.tsx +42 -0
- package/docs/components/ui/navigation-menu.tsx +83 -0
- package/docs/components/ui/popover.tsx +32 -0
- package/docs/components/ui/scroll-area.tsx +59 -0
- package/docs/components/ui/tabs.tsx +145 -0
- package/docs/contexts/i18n.tsx +56 -0
- package/docs/contexts/search.tsx +165 -0
- package/docs/contexts/tree.tsx +65 -0
- package/docs/css/black.css +39 -0
- package/docs/css/catppuccin.css +49 -0
- package/docs/css/colors/index.css +51 -0
- package/docs/css/dusk.css +47 -0
- package/docs/css/layouts/docs.css +1 -0
- package/docs/css/layouts/home.css +1 -0
- package/docs/css/layouts/notebook.css +1 -0
- package/docs/css/neutral.css +7 -0
- package/docs/css/ocean.css +48 -0
- package/docs/css/preset.css +305 -0
- package/docs/css/purple.css +39 -0
- package/docs/css/shadcn.css +36 -0
- package/docs/css/shiki.css +90 -0
- package/docs/css/solar.css +75 -0
- package/docs/css/style.css +9 -0
- package/docs/css/vitepress.css +77 -0
- package/docs/i18n.tsx +30 -0
- package/docs/icons.tsx +354 -0
- package/docs/layouts/docs/client.tsx +129 -0
- package/docs/layouts/docs/index.tsx +321 -0
- package/docs/layouts/docs/page/client.tsx +376 -0
- package/docs/layouts/docs/page/index.tsx +251 -0
- package/docs/layouts/docs/sidebar.tsx +265 -0
- package/docs/layouts/home/client.tsx +375 -0
- package/docs/layouts/home/index.tsx +51 -0
- package/docs/layouts/home/navbar.tsx +55 -0
- package/docs/layouts/notebook/client.tsx +281 -0
- package/docs/layouts/notebook/index.tsx +461 -0
- package/docs/layouts/notebook/page/client.tsx +375 -0
- package/docs/layouts/notebook/page/index.tsx +251 -0
- package/docs/layouts/notebook/sidebar.tsx +248 -0
- package/docs/layouts/shared/index.tsx +89 -0
- package/docs/layouts/shared/language-toggle.tsx +66 -0
- package/docs/layouts/shared/link-item.tsx +119 -0
- package/docs/layouts/shared/search-toggle.tsx +78 -0
- package/docs/layouts/shared/theme-toggle.tsx +86 -0
- package/docs/mdx.server.tsx +37 -0
- package/docs/mdx.tsx +97 -0
- package/docs/og.tsx +101 -0
- package/docs/page.tsx +85 -0
- package/docs/provider/base.tsx +173 -0
- package/docs/provider/next.tsx +23 -0
- package/docs/provider/react-router.tsx +23 -0
- package/docs/provider/tanstack.tsx +23 -0
- package/docs/provider/waku.tsx +23 -0
- package/docs/source.ts +3 -0
- package/docs/theme/typography/LICENSE +21 -0
- package/docs/theme/typography/index.ts +201 -0
- package/docs/theme/typography/styles.ts +449 -0
- package/docs/utils/cn.ts +1 -0
- package/docs/utils/is-active.ts +23 -0
- package/docs/utils/merge-refs.ts +15 -0
- package/docs/utils/use-copy-button.ts +39 -0
- package/docs/utils/use-footer-items.ts +27 -0
- package/docs/utils/use-is-scroll-top.ts +21 -0
- 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
|
+
}
|