@hanzo/ui 4.7.0 → 4.8.3
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/assets/ai-icons.tsx +207 -0
- package/assets/crypto.tsx +33 -0
- package/assets/file-type-icon.tsx +66 -0
- package/assets/file.tsx +45 -0
- package/assets/general.tsx +2318 -0
- package/assets/hanzo-logo.svg +9 -0
- package/assets/hanzo-logo.tsx +17 -0
- package/assets/index.ts +122 -0
- package/assets/index.tsx +4 -0
- package/assets/llm-provider.tsx +1094 -0
- package/blocks/auth/index.ts +6 -0
- package/blocks/auth/login-2fa.tsx +165 -0
- package/blocks/auth/login-basic.tsx +94 -0
- package/blocks/auth/login-social.tsx +148 -0
- package/blocks/auth/magic-link.tsx +129 -0
- package/blocks/auth/password-reset.tsx +97 -0
- package/blocks/auth/signup.tsx +157 -0
- package/blocks/components/accordian-block.tsx +48 -0
- package/blocks/components/block-component-props.ts +11 -0
- package/blocks/components/bullet-cards-block.tsx +46 -0
- package/blocks/components/card-block/index.tsx +171 -0
- package/blocks/components/card-block/link-out-button.tsx +20 -0
- package/blocks/components/card-block/util.ts +28 -0
- package/blocks/components/carte-blanche-block/index.tsx +127 -0
- package/blocks/components/carte-blanche-block/variant-content-left.tsx +49 -0
- package/blocks/components/content.tsx +70 -0
- package/blocks/components/cta-block.tsx +115 -0
- package/blocks/components/enh-heading-block.tsx +204 -0
- package/blocks/components/grid-block/grid-block-mutator.ts +12 -0
- package/blocks/components/grid-block/index.tsx +83 -0
- package/blocks/components/grid-block/mutator-registry.ts +10 -0
- package/blocks/components/grid-block/table-borders.mutator.ts +47 -0
- package/blocks/components/group-block.tsx +83 -0
- package/blocks/components/heading-block.tsx +88 -0
- package/blocks/components/image-block.tsx +111 -0
- package/blocks/components/index.ts +30 -0
- package/blocks/components/screenful-block/content.tsx +123 -0
- package/blocks/components/screenful-block/index.tsx +107 -0
- package/blocks/components/screenful-block/poster-background.tsx +34 -0
- package/blocks/components/screenful-block/video-background.tsx +45 -0
- package/blocks/components/space-block.tsx +66 -0
- package/blocks/components/video-block.tsx +138 -0
- package/blocks/data-display/activity-feed.tsx +242 -0
- package/blocks/data-display/data-table.tsx +235 -0
- package/blocks/data-display/stats-grid.tsx +194 -0
- package/blocks/def/accordian-block.ts +14 -0
- package/blocks/def/block.ts +7 -0
- package/blocks/def/bullet-cards-block.ts +22 -0
- package/blocks/def/card-block.ts +22 -0
- package/blocks/def/carte-blanche-block.ts +21 -0
- package/blocks/def/cta-block.ts +19 -0
- package/blocks/def/element-block.ts +11 -0
- package/blocks/def/enh-heading-block.ts +44 -0
- package/blocks/def/grid-block.ts +16 -0
- package/blocks/def/group-block.ts +11 -0
- package/blocks/def/heading-block.ts +15 -0
- package/blocks/def/image-block.ts +31 -0
- package/blocks/def/index.ts +35 -0
- package/blocks/def/screenful-block.ts +54 -0
- package/blocks/def/space-block.ts +64 -0
- package/blocks/def/video-block.ts +9 -0
- package/blocks/ecommerce/checkout.tsx +242 -0
- package/blocks/ecommerce/index.ts +7 -0
- package/blocks/ecommerce/product-detail.tsx +257 -0
- package/blocks/ecommerce/product-grid.tsx +148 -0
- package/blocks/ecommerce/shopping-cart.tsx +181 -0
- package/blocks/index.ts +2 -0
- package/blocks/marketing/cta-section.tsx +207 -0
- package/blocks/marketing/faq.tsx +159 -0
- package/blocks/marketing/features-grid.tsx +156 -0
- package/blocks/marketing/hero-section.tsx +192 -0
- package/blocks/marketing/index.ts +6 -0
- package/blocks/marketing/pricing-table.tsx +121 -0
- package/blocks/marketing/testimonials.tsx +196 -0
- package/components/index.ts +9 -0
- package/dist/index.js +1408 -1514
- package/dist/index.mjs +1364 -1472
- package/dist/lib/utils.js +1 -0
- package/dist/lib/utils.mjs +1 -0
- package/dist/src/utils.js +1 -0
- package/dist/src/utils.mjs +1 -0
- package/dist/tailwind/index.js +4 -1
- package/dist/tailwind/index.mjs +4 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.mjs +2 -0
- package/dist/util/format-text.js +52 -0
- package/dist/util/format-text.mjs +33 -0
- package/dist/util/index.js +385 -0
- package/dist/util/index.mjs +364 -0
- package/frameworks/core/index.ts +6 -0
- package/frameworks/core/utils/index.ts +64 -0
- package/frameworks/react/components/button.tsx +26 -0
- package/frameworks/react/components/index.ts +5 -0
- package/frameworks/react/hooks/index.ts +5 -0
- package/frameworks/react/index.ts +9 -0
- package/frameworks/react/package.json +8 -0
- package/frameworks/react/utils/index.ts +2 -0
- package/frameworks/react-native/index.ts +9 -0
- package/frameworks/react-native/package.json +8 -0
- package/frameworks/registry.json +371 -0
- package/frameworks/setup.sh +69 -0
- package/frameworks/svelte/index.ts +9 -0
- package/frameworks/svelte/package.json +8 -0
- package/frameworks/tracker.json +1854 -0
- package/frameworks/vue/index.ts +9 -0
- package/frameworks/vue/package.json +8 -0
- package/helpers/file.ts +33 -0
- package/helpers/memoization.ts +40 -0
- package/package.json +49 -11
- package/primitives/accordion.tsx +74 -0
- package/primitives/action-button.tsx +42 -0
- package/primitives/alert-dialog.tsx +185 -0
- package/primitives/alert.tsx +74 -0
- package/primitives/apply-typography.tsx +55 -0
- package/primitives/aspect-ratio.tsx +5 -0
- package/primitives/avatar.tsx +57 -0
- package/primitives/background-beams.tsx +142 -0
- package/primitives/badge.tsx +45 -0
- package/primitives/breadcrumb.tsx +130 -0
- package/primitives/breakpoint-indicator.tsx +19 -0
- package/primitives/button.tsx +72 -0
- package/primitives/calendar.tsx +72 -0
- package/primitives/card.tsx +97 -0
- package/primitives/carousel.tsx +238 -0
- package/primitives/chat/chat-input-area.tsx +88 -0
- package/primitives/chat/chat-input.tsx +71 -0
- package/primitives/chat/files-preview.tsx +331 -0
- package/primitives/chat/index.ts +6 -0
- package/primitives/chat/json-form.tsx +8 -0
- package/primitives/chat/message-list.tsx +308 -0
- package/primitives/chat/message.tsx +569 -0
- package/primitives/chat/sqlite-preview.tsx +215 -0
- package/primitives/checkbox.tsx +32 -0
- package/primitives/collapsible.tsx +9 -0
- package/primitives/combobox.tsx +239 -0
- package/primitives/command.tsx +151 -0
- package/primitives/context-menu.tsx +206 -0
- package/primitives/copy-to-clipboard-icon.tsx +60 -0
- package/primitives/dialog-video-controller.tsx +38 -0
- package/primitives/dialog.tsx +128 -0
- package/primitives/dot-pattern.tsx +57 -0
- package/primitives/dots-loader.tsx +13 -0
- package/primitives/drawer.tsx +113 -0
- package/primitives/dropdown-menu.tsx +199 -0
- package/primitives/error-message.tsx +19 -0
- package/primitives/file-uploader.tsx +202 -0
- package/primitives/form.tsx +185 -0
- package/primitives/hover-card.tsx +28 -0
- package/primitives/icons/github.tsx +14 -0
- package/primitives/icons/index.ts +18 -0
- package/primitives/icons/youtube-logo.tsx +59 -0
- package/primitives/index-common.ts +304 -0
- package/primitives/index-next.ts +4 -0
- package/primitives/input-otp.tsx +65 -0
- package/primitives/input.tsx +128 -0
- package/primitives/label.tsx +21 -0
- package/primitives/list-adaptor.ts +12 -0
- package/primitives/list-box.tsx +74 -0
- package/primitives/loading-spinner.tsx +33 -0
- package/primitives/markdown-preview.tsx +612 -0
- package/primitives/mermaid.tsx +191 -0
- package/primitives/navigation-menu.tsx +147 -0
- package/primitives/next/image.tsx +91 -0
- package/primitives/next/index.ts +7 -0
- package/primitives/next/inline-icon.tsx +36 -0
- package/primitives/next/link-element.tsx +109 -0
- package/primitives/next/mdx-link.tsx +22 -0
- package/primitives/next/media-stack.tsx +52 -0
- package/primitives/next/nav-items.tsx +45 -0
- package/primitives/next/youtube-embed.tsx +83 -0
- package/primitives/pagination.tsx +117 -0
- package/primitives/popover.tsx +34 -0
- package/primitives/pretty-json-print.tsx +28 -0
- package/primitives/progress.tsx +27 -0
- package/primitives/prompt-textarea.tsx +72 -0
- package/primitives/qr-code.tsx +112 -0
- package/primitives/radio-group.tsx +42 -0
- package/primitives/resizable.tsx +47 -0
- package/primitives/scroll-area.tsx +57 -0
- package/primitives/search-input.tsx +66 -0
- package/primitives/select.tsx +122 -0
- package/primitives/separator.tsx +26 -0
- package/primitives/sheet.tsx +139 -0
- package/primitives/skeleton.tsx +18 -0
- package/primitives/slider.tsx +63 -0
- package/primitives/sonner.tsx +35 -0
- package/primitives/step-indicator.tsx +69 -0
- package/primitives/stepper.tsx +272 -0
- package/primitives/switch.tsx +27 -0
- package/primitives/table.tsx +105 -0
- package/primitives/tabs.tsx +50 -0
- package/primitives/text-area.tsx +26 -0
- package/primitives/text-link.tsx +25 -0
- package/primitives/textarea.tsx +64 -0
- package/primitives/textfield.tsx +78 -0
- package/primitives/toast.tsx +30 -0
- package/primitives/toggle-group.tsx +63 -0
- package/primitives/toggle.tsx +44 -0
- package/primitives/tooltip.tsx +47 -0
- package/primitives/video-player.tsx +23 -0
- package/src/button.ts +1 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/use-click-away.ts +31 -0
- package/src/hooks/use-combined-refs.ts +22 -0
- package/src/hooks/use-copy-clipboard.ts +30 -0
- package/src/hooks/use-debounce.ts +17 -0
- package/src/hooks/use-fill-ids.ts +25 -0
- package/src/hooks/use-map.ts +26 -0
- package/src/hooks/use-measure.ts +42 -0
- package/src/hooks/use-reverse-video-playback.ts +43 -0
- package/src/hooks/use-scroll-restoration.ts +50 -0
- package/src/index-lean.ts +87 -0
- package/src/index.ts +54 -0
- package/src/mcp/README.md +141 -0
- package/src/mcp/enhanced-server.ts +1208 -0
- package/src/mcp/index.ts +518 -0
- package/src/mcp/package.json +10 -0
- package/src/registry/api.ts +164 -0
- package/src/registry/index.ts +60 -0
- package/src/registry/package.json +10 -0
- package/src/utils.ts +19 -0
- package/tailwind/colors.tailwind.js +53 -0
- package/tailwind/fontFamily.tailwind.ts +7 -0
- package/tailwind/fontSize.tailwind.ts +13 -0
- package/tailwind/index.ts +7 -0
- package/tailwind/safelist.tailwind.js +26 -0
- package/tailwind/screens.tailwind.js +8 -0
- package/tailwind/spacing.tailwind.js +65 -0
- package/tailwind/tailwind.config.hanzo-preset.d.ts +5 -0
- package/tailwind/tailwind.config.hanzo-preset.js +915 -0
- package/tailwind/tw-font-desc.ts +15 -0
- package/tailwind/typo-plugin/get-plugin-styles.js +679 -0
- package/tailwind/typo-plugin/index.d.ts +9 -0
- package/tailwind/typo-plugin/index.js +141 -0
- package/tailwind/typo-plugin/utils.js +60 -0
- package/tailwind/typography-test.mdx +35 -0
- package/tailwind/z-index.tailwind.js +71 -0
- package/types/animation-def.ts +3 -0
- package/types/breakpoints.ts +11 -0
- package/types/bullet-item.ts +10 -0
- package/types/button-def.ts +39 -0
- package/types/dimensions.ts +8 -0
- package/types/grid-def.ts +56 -0
- package/types/image-def.ts +32 -0
- package/types/index.ts +30 -0
- package/types/link-def.ts +56 -0
- package/types/media-stack-def.ts +31 -0
- package/types/t-shirt-size.ts +5 -0
- package/types/tshirt-dimensions.ts +20 -0
- package/types/video-def.ts +25 -0
- package/util/blob.ts +33 -0
- package/util/copy-to-clipboard.ts +17 -0
- package/util/create-shadow-root.ts +22 -0
- package/util/date.ts +84 -0
- package/util/debounce.ts +11 -0
- package/util/file.ts +15 -0
- package/util/format-and-abbreviate-as-currency.ts +125 -0
- package/util/format-text.ts +34 -0
- package/util/format-to-max-char.ts +68 -0
- package/util/index-client.ts +3 -0
- package/util/index.ts +112 -0
- package/util/number-abbreviate.ts +49 -0
- package/util/specifier.ts +43 -0
- package/util/spread-to-transform.ts +25 -0
- package/util/step-animation.ts +90 -0
- package/util/timing.ts +3 -0
- package/util/toasts.tsx +17 -0
- package/util/two-way-map.ts +19 -0
- package/dist/index.d.mts +0 -16
- package/dist/index.d.ts +0 -16
- package/dist/lib/utils.d.mts +0 -2
- package/dist/lib/utils.d.ts +0 -2
- package/dist/src/utils.d.mts +0 -7
- package/dist/src/utils.d.ts +0 -7
- package/dist/tailwind/index.d.mts +0 -2
- package/dist/tailwind/index.d.ts +0 -2
- package/dist/types/index.d.mts +0 -12
- package/dist/types/index.d.ts +0 -12
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
2
|
+
import { VariantProps } from 'class-variance-authority';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../src/utils';
|
|
6
|
+
import { toggleVariants } from './toggle';
|
|
7
|
+
|
|
8
|
+
const ToggleGroupContext = React.createContext<
|
|
9
|
+
VariantProps<typeof toggleVariants>
|
|
10
|
+
>({
|
|
11
|
+
size: 'default',
|
|
12
|
+
variant: 'default',
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const ToggleGroup = ({
|
|
16
|
+
className,
|
|
17
|
+
variant,
|
|
18
|
+
size,
|
|
19
|
+
children,
|
|
20
|
+
...props
|
|
21
|
+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> &
|
|
22
|
+
VariantProps<typeof toggleVariants>) => (
|
|
23
|
+
<ToggleGroupPrimitive.Root
|
|
24
|
+
className={cn('flex items-center justify-center gap-1', className)}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
<ToggleGroupContext.Provider value={{ variant, size }}>
|
|
28
|
+
{children}
|
|
29
|
+
</ToggleGroupContext.Provider>
|
|
30
|
+
</ToggleGroupPrimitive.Root>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
34
|
+
|
|
35
|
+
const ToggleGroupItem = ({
|
|
36
|
+
className,
|
|
37
|
+
children,
|
|
38
|
+
variant,
|
|
39
|
+
size,
|
|
40
|
+
...props
|
|
41
|
+
}: React.ComponentProps<typeof ToggleGroupPrimitive.Item> &
|
|
42
|
+
VariantProps<typeof toggleVariants>) => {
|
|
43
|
+
const context = React.useContext(ToggleGroupContext);
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<ToggleGroupPrimitive.Item
|
|
47
|
+
className={cn(
|
|
48
|
+
toggleVariants({
|
|
49
|
+
variant: context.variant || variant,
|
|
50
|
+
size: context.size || size,
|
|
51
|
+
}),
|
|
52
|
+
className,
|
|
53
|
+
)}
|
|
54
|
+
{...props}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</ToggleGroupPrimitive.Item>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
62
|
+
|
|
63
|
+
export { ToggleGroup, ToggleGroupItem };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
2
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
|
|
5
|
+
import { cn } from '../src/utils';
|
|
6
|
+
|
|
7
|
+
const toggleVariants = cva(
|
|
8
|
+
'ring-offset-background hover:bg-muted hover:text-text-secondary focus-visible:ring-ring data-[state=on]:bg-bg-quaternary inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50 data-[state=on]:text-white',
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: 'bg-bg-tertiary',
|
|
13
|
+
outline:
|
|
14
|
+
'border-divider hover:bg-bg-tertiary border bg-transparent hover:text-white',
|
|
15
|
+
},
|
|
16
|
+
size: {
|
|
17
|
+
default: 'h-10 px-3',
|
|
18
|
+
sm: 'h-9 px-2.5',
|
|
19
|
+
lg: 'h-11 px-5',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: {
|
|
23
|
+
variant: 'default',
|
|
24
|
+
size: 'default',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
const Toggle = ({
|
|
30
|
+
className,
|
|
31
|
+
variant,
|
|
32
|
+
size,
|
|
33
|
+
...props
|
|
34
|
+
}: React.ComponentProps<typeof TogglePrimitive.Root> &
|
|
35
|
+
VariantProps<typeof toggleVariants>) => (
|
|
36
|
+
<TogglePrimitive.Root
|
|
37
|
+
className={cn(toggleVariants({ variant, size, className }))}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
43
|
+
|
|
44
|
+
export { Toggle, toggleVariants };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { cn } from '../src/utils';
|
|
5
|
+
|
|
6
|
+
const TooltipProvider = TooltipPrimitive.Provider;
|
|
7
|
+
|
|
8
|
+
const Tooltip = TooltipPrimitive.Root;
|
|
9
|
+
|
|
10
|
+
const TooltipTrigger = TooltipPrimitive.Trigger;
|
|
11
|
+
|
|
12
|
+
const TooltipPortal = TooltipPrimitive.Portal;
|
|
13
|
+
const TooltipArrow = TooltipPrimitive.TooltipArrow;
|
|
14
|
+
|
|
15
|
+
const TooltipContent = ({
|
|
16
|
+
className,
|
|
17
|
+
sideOffset = 4,
|
|
18
|
+
showArrow = true,
|
|
19
|
+
...props
|
|
20
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content> & {
|
|
21
|
+
showArrow?: boolean;
|
|
22
|
+
}) => (
|
|
23
|
+
<TooltipPrimitive.Content
|
|
24
|
+
className={cn(
|
|
25
|
+
'border-divider bg-bg-dark animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-w-[280px] rounded-lg border px-3 py-1.5 text-xs text-white',
|
|
26
|
+
className,
|
|
27
|
+
)}
|
|
28
|
+
sideOffset={sideOffset}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{props.children}
|
|
32
|
+
|
|
33
|
+
{showArrow && (
|
|
34
|
+
<TooltipPrimitive.Arrow className="fill-bg-dark -my-px drop-shadow-[0_1px_0_#313336]" />
|
|
35
|
+
)}
|
|
36
|
+
</TooltipPrimitive.Content>
|
|
37
|
+
);
|
|
38
|
+
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
Tooltip,
|
|
42
|
+
TooltipTrigger,
|
|
43
|
+
TooltipContent,
|
|
44
|
+
TooltipProvider,
|
|
45
|
+
TooltipPortal,
|
|
46
|
+
TooltipArrow,
|
|
47
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
interface VideoProps extends React.ComponentPropsWithoutRef<"video"> {
|
|
5
|
+
sources: string[]
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const VideoPlayer = React.forwardRef<HTMLVideoElement, VideoProps>(
|
|
9
|
+
({
|
|
10
|
+
sources,
|
|
11
|
+
...rest
|
|
12
|
+
}, ref) => {
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<video ref={ref} {...rest} >
|
|
16
|
+
{sources.map((source, index) => (
|
|
17
|
+
<source key={index} src={source} />
|
|
18
|
+
))}
|
|
19
|
+
</video>
|
|
20
|
+
)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export default VideoPlayer
|
package/src/button.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../../app/registry/new-york/ui/button'
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export function useClickAway<T extends Element>(
|
|
4
|
+
cb: (e: Event) => void,
|
|
5
|
+
): React.RefObject<T | null> {
|
|
6
|
+
const ref = React.useRef<T | null>(null);
|
|
7
|
+
const refCb = React.useRef(cb);
|
|
8
|
+
|
|
9
|
+
React.useLayoutEffect(() => {
|
|
10
|
+
refCb.current = cb;
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
React.useEffect(() => {
|
|
14
|
+
const handler = (e: Event) => {
|
|
15
|
+
const element = ref.current;
|
|
16
|
+
if (element && !element.contains(e.target as Node)) {
|
|
17
|
+
refCb.current(e);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
document.addEventListener('mousedown', handler);
|
|
22
|
+
document.addEventListener('touchstart', handler);
|
|
23
|
+
|
|
24
|
+
return () => {
|
|
25
|
+
document.removeEventListener('mousedown', handler);
|
|
26
|
+
document.removeEventListener('touchstart', handler);
|
|
27
|
+
};
|
|
28
|
+
}, []);
|
|
29
|
+
|
|
30
|
+
return ref;
|
|
31
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
function useCombinedRefs<T>(
|
|
5
|
+
...refs: React.ForwardedRef<T>[]
|
|
6
|
+
): React.RefObject<T | null> {
|
|
7
|
+
const targetRef = useRef<T>(null);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
refs.forEach((ref) => {
|
|
10
|
+
if (!ref) return;
|
|
11
|
+
|
|
12
|
+
if (typeof ref === 'function') {
|
|
13
|
+
ref(targetRef.current);
|
|
14
|
+
} else {
|
|
15
|
+
ref.current = targetRef.current;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
}, [refs]);
|
|
19
|
+
return targetRef;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { useCombinedRefs };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { copyToClipboard } from '../../util/copy-to-clipboard';
|
|
3
|
+
|
|
4
|
+
type UseCopyClipboardProps = {
|
|
5
|
+
string?: string;
|
|
6
|
+
onCopyClipboard?: () => void;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export const useCopyClipboard = ({
|
|
10
|
+
string,
|
|
11
|
+
onCopyClipboard,
|
|
12
|
+
}: UseCopyClipboardProps) => {
|
|
13
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
14
|
+
|
|
15
|
+
let timeout: ReturnType<typeof setTimeout>;
|
|
16
|
+
const onCopy = async () => {
|
|
17
|
+
if (!string) return;
|
|
18
|
+
const string_ = string.trim();
|
|
19
|
+
if (onCopyClipboard && typeof onCopyClipboard === 'function') {
|
|
20
|
+
onCopyClipboard();
|
|
21
|
+
} else {
|
|
22
|
+
await copyToClipboard(string_);
|
|
23
|
+
}
|
|
24
|
+
setIsCopied(true);
|
|
25
|
+
clearTimeout(timeout);
|
|
26
|
+
timeout = setTimeout(() => setIsCopied(false), 1000);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return { isCopied, onCopy };
|
|
30
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export function useDebounce(value: string, delay = 500) {
|
|
4
|
+
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
5
|
+
|
|
6
|
+
React.useEffect(() => {
|
|
7
|
+
const handler: NodeJS.Timeout = setTimeout(() => {
|
|
8
|
+
setDebouncedValue(value);
|
|
9
|
+
}, delay);
|
|
10
|
+
|
|
11
|
+
return () => {
|
|
12
|
+
clearTimeout(handler);
|
|
13
|
+
};
|
|
14
|
+
}, [value, delay]);
|
|
15
|
+
|
|
16
|
+
return debouncedValue;
|
|
17
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useFillId = (namespace: string) => {
|
|
4
|
+
const id = `lobe-icons-${namespace.toLowerCase()}-fill`;
|
|
5
|
+
return useMemo(
|
|
6
|
+
() => ({
|
|
7
|
+
fill: `url(#${id})`,
|
|
8
|
+
id,
|
|
9
|
+
}),
|
|
10
|
+
[namespace],
|
|
11
|
+
);
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export const useFillIds = (namespace: string, length: number) => {
|
|
15
|
+
return useMemo(() => {
|
|
16
|
+
const ids = Array.from({ length }, (_, i) => {
|
|
17
|
+
const id = `lobe-icons-${namespace.toLowerCase()}-fill-${i}`;
|
|
18
|
+
return {
|
|
19
|
+
fill: `url(#${id})`,
|
|
20
|
+
id,
|
|
21
|
+
};
|
|
22
|
+
});
|
|
23
|
+
return ids;
|
|
24
|
+
}, [namespace]);
|
|
25
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export function useMap<Key, Value>(initialState: [Key, Value][] = []) {
|
|
4
|
+
const mapRef = React.useRef(new Map<Key, Value>(initialState));
|
|
5
|
+
const [, reRender] = React.useReducer((x) => x + 1, 0);
|
|
6
|
+
|
|
7
|
+
mapRef.current.set = (...args) => {
|
|
8
|
+
Map.prototype.set.apply(mapRef.current, args);
|
|
9
|
+
reRender();
|
|
10
|
+
return mapRef.current;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
mapRef.current.clear = (...args) => {
|
|
14
|
+
Map.prototype.clear.apply(mapRef.current, args);
|
|
15
|
+
reRender();
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
mapRef.current.delete = (...args) => {
|
|
19
|
+
const res = Map.prototype.delete.apply(mapRef.current, args);
|
|
20
|
+
reRender();
|
|
21
|
+
|
|
22
|
+
return res;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return mapRef.current;
|
|
26
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export function useMeasure<T extends Element>(): [
|
|
4
|
+
React.RefCallback<T>,
|
|
5
|
+
{
|
|
6
|
+
width: number | null;
|
|
7
|
+
height: number | null;
|
|
8
|
+
},
|
|
9
|
+
] {
|
|
10
|
+
const [dimensions, setDimensions] = React.useState<{
|
|
11
|
+
width: number | null;
|
|
12
|
+
height: number | null;
|
|
13
|
+
}>({
|
|
14
|
+
width: null,
|
|
15
|
+
height: null,
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const previousObserver = React.useRef<ResizeObserver | null>(null);
|
|
19
|
+
|
|
20
|
+
const customRef = React.useCallback((node: T) => {
|
|
21
|
+
if (previousObserver.current) {
|
|
22
|
+
previousObserver.current.disconnect();
|
|
23
|
+
previousObserver.current = null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (node?.nodeType === Node.ELEMENT_NODE) {
|
|
27
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
28
|
+
if (entry && entry.borderBoxSize) {
|
|
29
|
+
const { inlineSize: width, blockSize: height } =
|
|
30
|
+
entry.borderBoxSize[0];
|
|
31
|
+
|
|
32
|
+
setDimensions({ width, height });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
observer.observe(node);
|
|
37
|
+
previousObserver.current = observer;
|
|
38
|
+
}
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
return [customRef, dimensions];
|
|
42
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useReverseVideoPlayback = () => {
|
|
4
|
+
const videoRef = useRef<HTMLVideoElement>(null);
|
|
5
|
+
|
|
6
|
+
const [isReversing, setIsReversing] = useState(false);
|
|
7
|
+
const playReverse = () => {
|
|
8
|
+
if (!videoRef.current) return;
|
|
9
|
+
const video = videoRef.current;
|
|
10
|
+
const reversePlayback = () => {
|
|
11
|
+
if (video.currentTime <= 0) {
|
|
12
|
+
setIsReversing(false);
|
|
13
|
+
void video.play();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
video.currentTime -= 0.023;
|
|
17
|
+
requestAnimationFrame(reversePlayback);
|
|
18
|
+
};
|
|
19
|
+
reversePlayback();
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
const videoElement = videoRef.current;
|
|
24
|
+
if (videoElement) {
|
|
25
|
+
const handleVideoEnd = () => {
|
|
26
|
+
if (isReversing) {
|
|
27
|
+
setIsReversing(false);
|
|
28
|
+
videoElement.currentTime = 0;
|
|
29
|
+
void videoElement.play();
|
|
30
|
+
} else {
|
|
31
|
+
setIsReversing(true);
|
|
32
|
+
playReverse();
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
videoElement.addEventListener('ended', handleVideoEnd);
|
|
37
|
+
return () => {
|
|
38
|
+
videoElement.removeEventListener('ended', handleVideoEnd);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}, [isReversing]);
|
|
42
|
+
return videoRef;
|
|
43
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
export const useScrollRestoration = ({
|
|
4
|
+
key,
|
|
5
|
+
containerRef,
|
|
6
|
+
scrollTopStateRef,
|
|
7
|
+
}: {
|
|
8
|
+
key: string;
|
|
9
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
10
|
+
scrollTopStateRef: React.RefObject<{ [key: string]: number } | null>;
|
|
11
|
+
}): void => {
|
|
12
|
+
const saveScroll = React.useCallback(() => {
|
|
13
|
+
if (scrollTopStateRef.current) {
|
|
14
|
+
scrollTopStateRef.current[`${key}-scrollTop`] =
|
|
15
|
+
containerRef?.current?.scrollTop ?? 0;
|
|
16
|
+
}
|
|
17
|
+
}, [containerRef, scrollTopStateRef, key]);
|
|
18
|
+
|
|
19
|
+
const restoreScroll = React.useCallback(() => {
|
|
20
|
+
if (containerRef.current) {
|
|
21
|
+
containerRef.current.scrollTo({
|
|
22
|
+
top: scrollTopStateRef?.current?.[`${key}-scrollTop`] ?? 0,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
}, [containerRef, key, scrollTopStateRef]);
|
|
26
|
+
|
|
27
|
+
React.useLayoutEffect(() => {
|
|
28
|
+
return () => {
|
|
29
|
+
saveScroll();
|
|
30
|
+
};
|
|
31
|
+
}, [saveScroll]);
|
|
32
|
+
|
|
33
|
+
React.useEffect(() => {
|
|
34
|
+
// Small delay to ensure content is rendered
|
|
35
|
+
const timeoutId = setTimeout(restoreScroll, 100);
|
|
36
|
+
return () => clearTimeout(timeoutId);
|
|
37
|
+
}, [restoreScroll]);
|
|
38
|
+
|
|
39
|
+
React.useEffect(() => {
|
|
40
|
+
restoreScroll();
|
|
41
|
+
}, [restoreScroll]);
|
|
42
|
+
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
const element = containerRef?.current;
|
|
45
|
+
element?.addEventListener('scroll', saveScroll);
|
|
46
|
+
return () => {
|
|
47
|
+
element?.removeEventListener('scroll', saveScroll);
|
|
48
|
+
};
|
|
49
|
+
}, [containerRef, saveScroll]);
|
|
50
|
+
};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hanzo/ui - Lean Build (Minimal Bundle)
|
|
3
|
+
*
|
|
4
|
+
* This is a lightweight version that excludes heavy dependencies.
|
|
5
|
+
* Heavy components can be imported separately when needed:
|
|
6
|
+
*
|
|
7
|
+
* - Syntax highlighting: import from '@hanzo/ui/components/syntax-highlighter'
|
|
8
|
+
* - Markdown: import from '@hanzo/ui/components/markdown'
|
|
9
|
+
* - Math rendering: import from '@hanzo/ui/components/katex'
|
|
10
|
+
* - Animations: import from 'framer-motion' directly
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
// Core utilities - must be imported first
|
|
14
|
+
export { cn } from './utils'
|
|
15
|
+
export * from './utils'
|
|
16
|
+
|
|
17
|
+
// Hooks (lightweight)
|
|
18
|
+
export * from './hooks'
|
|
19
|
+
|
|
20
|
+
// Only export the core Radix primitives used in the desktop app
|
|
21
|
+
// Button
|
|
22
|
+
export { Button, buttonVariants } from '../primitives/button'
|
|
23
|
+
export type { ButtonProps } from '../primitives/button'
|
|
24
|
+
|
|
25
|
+
// Form components
|
|
26
|
+
export * from '../primitives/form'
|
|
27
|
+
export * from '../primitives/input'
|
|
28
|
+
export * from '../primitives/label'
|
|
29
|
+
export * from '../primitives/textarea'
|
|
30
|
+
export * from '../primitives/checkbox'
|
|
31
|
+
export * from '../primitives/radio-group'
|
|
32
|
+
export * from '../primitives/select'
|
|
33
|
+
export * from '../primitives/switch'
|
|
34
|
+
|
|
35
|
+
// Layout
|
|
36
|
+
export * from '../primitives/card'
|
|
37
|
+
export * from '../primitives/separator'
|
|
38
|
+
export * from '../primitives/scroll-area'
|
|
39
|
+
export * from '../primitives/tabs'
|
|
40
|
+
export * from '../primitives/accordion'
|
|
41
|
+
|
|
42
|
+
// Feedback
|
|
43
|
+
export * from '../primitives/alert'
|
|
44
|
+
export * from '../primitives/alert-dialog'
|
|
45
|
+
export * from '../primitives/dialog'
|
|
46
|
+
export * from '../primitives/toast'
|
|
47
|
+
export * from '../primitives/progress'
|
|
48
|
+
export * from '../primitives/skeleton'
|
|
49
|
+
export * from '../primitives/badge'
|
|
50
|
+
|
|
51
|
+
// Navigation
|
|
52
|
+
export * from '../primitives/dropdown-menu'
|
|
53
|
+
export * from '../primitives/command'
|
|
54
|
+
export * from '../primitives/breadcrumb'
|
|
55
|
+
export * from '../primitives/sheet'
|
|
56
|
+
|
|
57
|
+
// Data display
|
|
58
|
+
export * from '../primitives/table'
|
|
59
|
+
export * from '../primitives/avatar'
|
|
60
|
+
export * from '../primitives/hover-card'
|
|
61
|
+
export * from '../primitives/popover'
|
|
62
|
+
export * from '../primitives/tooltip'
|
|
63
|
+
|
|
64
|
+
// Other essentials
|
|
65
|
+
export * from '../primitives/collapsible'
|
|
66
|
+
export * from '../primitives/context-menu'
|
|
67
|
+
export * from '../primitives/resizable'
|
|
68
|
+
export * from '../primitives/slider'
|
|
69
|
+
export * from '../primitives/toggle'
|
|
70
|
+
export * from '../primitives/toggle-group'
|
|
71
|
+
|
|
72
|
+
// Re-export assets (icons are lightweight)
|
|
73
|
+
export * from '../assets'
|
|
74
|
+
|
|
75
|
+
// Re-export utilities
|
|
76
|
+
export * from '../util'
|
|
77
|
+
export * from '../util/index-client'
|
|
78
|
+
|
|
79
|
+
// Types
|
|
80
|
+
export * from '../types'
|
|
81
|
+
|
|
82
|
+
// NOTE: Heavy components excluded from lean build:
|
|
83
|
+
// - MarkdownText (react-markdown + plugins)
|
|
84
|
+
// - SyntaxHighlighter (react-syntax-highlighter)
|
|
85
|
+
// - KatexRender (katex)
|
|
86
|
+
// - Animated components (framer-motion)
|
|
87
|
+
// - MediaStack, Mapbox, Spline3D, PlotlyChart
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @hanzo/ui - Complete UI Library
|
|
3
|
+
*
|
|
4
|
+
* This file exports all components, utilities, hooks, and blocks from the @hanzo/ui library.
|
|
5
|
+
* Components are organized by category and support tree-shaking.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Core utilities - must be imported first
|
|
9
|
+
export { cn } from './utils'
|
|
10
|
+
export * from './utils'
|
|
11
|
+
|
|
12
|
+
// Registry exports for tooling
|
|
13
|
+
export * from './registry'
|
|
14
|
+
|
|
15
|
+
// MCP (Model Context Protocol) support
|
|
16
|
+
export * from './mcp'
|
|
17
|
+
|
|
18
|
+
// Hooks
|
|
19
|
+
export * from './hooks'
|
|
20
|
+
|
|
21
|
+
// Re-export all primitives
|
|
22
|
+
export * from '../primitives/index-next'
|
|
23
|
+
export * from '../primitives/index-common'
|
|
24
|
+
|
|
25
|
+
// Re-export assets
|
|
26
|
+
export * from '../assets'
|
|
27
|
+
|
|
28
|
+
// Re-export blocks
|
|
29
|
+
export * from '../blocks'
|
|
30
|
+
|
|
31
|
+
// Re-export components (if different from primitives)
|
|
32
|
+
export * from '../components'
|
|
33
|
+
|
|
34
|
+
// Re-export types
|
|
35
|
+
export * from '../types'
|
|
36
|
+
|
|
37
|
+
// Re-export utilities
|
|
38
|
+
export * from '../util'
|
|
39
|
+
export * from '../util/index-client'
|
|
40
|
+
|
|
41
|
+
// Re-export tailwind configuration helpers
|
|
42
|
+
export * from '../tailwind'
|
|
43
|
+
|
|
44
|
+
// Theme provider for brand support
|
|
45
|
+
export { ThemeProvider } from '../style/theme-provider'
|
|
46
|
+
|
|
47
|
+
// Framework-specific exports
|
|
48
|
+
export * as React from '../frameworks/react'
|
|
49
|
+
export * as Vue from '../frameworks/vue'
|
|
50
|
+
export * as Svelte from '../frameworks/svelte'
|
|
51
|
+
export * as ReactNative from '../frameworks/react-native'
|
|
52
|
+
|
|
53
|
+
// Export version
|
|
54
|
+
export const VERSION = '4.8.0'
|