@hanzo/ui 4.5.4 → 4.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.
- package/README-MCP.md +3 -3
- package/README.md +229 -0
- 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 +15 -0
- package/assets/index.ts +8 -0
- package/assets/index.tsx +4 -0
- package/assets/llm-provider.tsx +1094 -0
- package/bin/create-registry.js +1 -1
- package/bin/test-mcp.sh +1 -1
- package/bin/update-registry.js +2 -2
- package/blocks/components/content.tsx +1 -1
- package/blocks/components/grid-block/index.tsx +1 -1
- package/blocks/components/screenful-block/content.tsx +1 -1
- package/blocks/components/screenful-block/poster-background.tsx +1 -1
- package/components/index.ts +56 -0
- package/dist/button.d.ts +1 -0
- package/dist/button.js +1 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.js +7 -0
- package/dist/hooks/use-click-away.d.ts +2 -0
- package/dist/hooks/use-click-away.js +23 -0
- package/dist/hooks/use-combined-refs.d.ts +3 -0
- package/dist/hooks/use-combined-refs.js +18 -0
- package/dist/hooks/use-copy-clipboard.d.ts +9 -0
- package/dist/hooks/use-copy-clipboard.js +21 -0
- package/dist/hooks/use-debounce.d.ts +1 -0
- package/dist/hooks/use-debounce.js +13 -0
- package/dist/hooks/use-fill-ids.d.ts +8 -0
- package/dist/hooks/use-fill-ids.js +20 -0
- package/dist/hooks/use-map.d.ts +1 -0
- package/dist/hooks/use-map.js +20 -0
- package/dist/hooks/use-measure.d.ts +8 -0
- package/dist/hooks/use-measure.js +25 -0
- package/dist/hooks/use-reverse-video-playback.d.ts +1 -0
- package/dist/hooks/use-reverse-video-playback.js +41 -0
- package/dist/hooks/use-scroll-restoration.d.ts +8 -0
- package/dist/hooks/use-scroll-restoration.js +36 -0
- package/dist/mcp/enhanced-server.js +2 -2
- package/dist/registry/api.d.ts +1 -1
- package/dist/registry/api.js +3 -3
- package/dist/registry/index.d.ts +48 -48
- package/dist/registry/index.js +3 -3
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +1 -0
- package/helpers/file.ts +33 -0
- package/helpers/memoization.ts +40 -0
- package/package.json +27 -6
- package/primitives/accordion.tsx +53 -45
- package/primitives/alert-dialog.tsx +185 -0
- package/primitives/alert.tsx +74 -0
- package/primitives/apply-typography.tsx +1 -1
- package/primitives/avatar.tsx +37 -29
- package/primitives/background-beams.tsx +142 -0
- package/primitives/badge.tsx +27 -19
- package/primitives/breadcrumb.tsx +77 -62
- package/primitives/button.tsx +69 -72
- package/primitives/card.tsx +73 -59
- package/primitives/chat/chat-input-area.tsx +87 -0
- package/primitives/chat/chat-input.tsx +71 -0
- package/primitives/chat/files-preview.tsx +330 -0
- package/primitives/chat/index.ts +6 -0
- package/primitives/chat/json-form.tsx +8 -0
- package/primitives/chat/message-list.tsx +307 -0
- package/primitives/chat/message.tsx +569 -0
- package/primitives/chat/sqlite-preview.tsx +215 -0
- package/primitives/checkbox.tsx +18 -19
- package/primitives/collapsible.tsx +9 -0
- package/primitives/command.tsx +75 -83
- package/primitives/context-menu.tsx +115 -109
- package/primitives/copy-to-clipboard-icon.tsx +60 -0
- package/primitives/dialog-video-controller.tsx +1 -1
- package/primitives/dialog.tsx +111 -145
- package/primitives/dot-pattern.tsx +57 -0
- package/primitives/dots-loader.tsx +13 -0
- package/primitives/drawer.tsx +59 -87
- package/primitives/dropdown-menu.tsx +199 -0
- package/primitives/error-message.tsx +19 -0
- package/primitives/file-uploader.tsx +200 -0
- package/primitives/form.tsx +92 -87
- package/primitives/hover-card.tsx +28 -0
- package/primitives/icons/github.tsx +1 -1
- package/primitives/icons/youtube-logo.tsx +1 -1
- package/primitives/index-common.ts +121 -42
- package/primitives/index-next.ts +3 -1
- package/primitives/input.tsx +115 -20
- package/primitives/label.tsx +15 -23
- package/primitives/loading-spinner.tsx +1 -1
- package/primitives/markdown-preview.tsx +609 -0
- package/primitives/mermaid.tsx +196 -0
- package/primitives/next/link-element.tsx +1 -1
- package/primitives/next/mdx-link.tsx +1 -1
- package/primitives/pagination.tsx +117 -0
- package/primitives/popover.tsx +20 -25
- package/primitives/pretty-json-print.tsx +28 -0
- package/primitives/progress.tsx +14 -15
- package/primitives/prompt-textarea.tsx +72 -0
- package/primitives/qr-code.tsx +112 -0
- package/primitives/radio-group.tsx +25 -39
- package/primitives/resizable.tsx +47 -0
- package/primitives/scroll-area.tsx +35 -25
- package/primitives/search-input.tsx +66 -0
- package/primitives/select.tsx +62 -109
- package/primitives/separator.tsx +22 -26
- package/primitives/sheet.tsx +78 -117
- package/primitives/skeleton.tsx +13 -16
- package/primitives/slider.tsx +50 -60
- package/primitives/stepper.tsx +272 -0
- package/primitives/switch.tsx +14 -23
- package/primitives/table.tsx +65 -77
- package/primitives/tabs.tsx +29 -39
- package/primitives/text-link.tsx +25 -0
- package/primitives/textarea.tsx +61 -0
- package/primitives/textfield.tsx +75 -0
- package/primitives/toast.tsx +30 -0
- package/primitives/toggle-group.tsx +33 -33
- package/primitives/toggle.tsx +22 -51
- package/primitives/tooltip.tsx +37 -38
- package/registry.json +1 -1
- 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/mcp/README.md +1 -1
- package/src/mcp/enhanced-server.ts +2 -2
- package/src/registry/api.ts +3 -3
- package/src/registry/index.ts +3 -3
- package/src/utils.ts +1 -0
- package/style/theme-provider.tsx +1 -1
- package/test-imports.mjs +19 -0
- package/types/animation-def.ts +1 -1
- package/types/button-def.ts +1 -1
- package/types/index.ts +1 -1
- package/util/blob.ts +28 -0
- package/util/copy-to-clipboard.ts +17 -0
- package/util/create-shadow-root.ts +22 -0
- package/util/date.ts +83 -0
- package/util/debounce.ts +11 -0
- package/util/file.ts +15 -0
- package/util/format-and-abbreviate-as-currency.ts +1 -1
- package/util/format-text.ts +33 -0
- package/util/index.ts +9 -78
- package/util/timing.ts +3 -0
- package/util/toasts.tsx +17 -0
- package/utils.ts +9 -0
package/bin/create-registry.js
CHANGED
|
@@ -16,7 +16,7 @@ const REGISTRY_STYLES = ['default', 'new-york'];
|
|
|
16
16
|
|
|
17
17
|
// Registry schema
|
|
18
18
|
const registrySchema = {
|
|
19
|
-
"$schema": "https://ui.
|
|
19
|
+
"$schema": "https://ui.hanzo.com/schema/registry.json",
|
|
20
20
|
"name": "hanzo",
|
|
21
21
|
"homepage": "https://ui.hanzo.ai",
|
|
22
22
|
"items": []
|
package/bin/test-mcp.sh
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# Test script for verifying the Hanzo UI MCP functionality
|
|
4
4
|
|
|
5
5
|
# Set a test registry URL
|
|
6
|
-
export REGISTRY_URL="https://ui.
|
|
6
|
+
export REGISTRY_URL="https://ui.hanzo.com/registry/registry.json"
|
|
7
7
|
|
|
8
8
|
echo "Testing Hanzo UI MCP Server"
|
|
9
9
|
echo "============================"
|
package/bin/update-registry.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* This script updates the registry.json file based on components
|
|
5
|
-
* found in the registry directory. It's similar to the approach used by
|
|
5
|
+
* found in the registry directory. It's similar to the approach used by hanzo/ui.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
@@ -17,7 +17,7 @@ const REGISTRY_STYLES = ['default', 'new-york']; // Add other styles as needed
|
|
|
17
17
|
|
|
18
18
|
// Schema for registry.json
|
|
19
19
|
const registrySchema = {
|
|
20
|
-
"$schema": "https://ui.
|
|
20
|
+
"$schema": "https://ui.hanzo.com/schema/registry.json",
|
|
21
21
|
"name": "hanzo",
|
|
22
22
|
"homepage": "https://ui.hanzo.ai",
|
|
23
23
|
"items": []
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Auto-generated component exports
|
|
2
|
+
// This file provides a central import point for all UI components
|
|
3
|
+
// Usage: import { Button, Card, cn } from '@hanzo/ui/components'
|
|
4
|
+
|
|
5
|
+
// Export commonly used utilities
|
|
6
|
+
export { cn } from '../../../app/lib/utils'
|
|
7
|
+
|
|
8
|
+
export * from '../../../app/registry/new-york/ui/accordion'
|
|
9
|
+
export * from '../../../app/registry/new-york/ui/alert-dialog'
|
|
10
|
+
export * from '../../../app/registry/new-york/ui/alert'
|
|
11
|
+
export * from '../../../app/registry/new-york/ui/aspect-ratio'
|
|
12
|
+
export * from '../../../app/registry/new-york/ui/avatar'
|
|
13
|
+
export * from '../../../app/registry/new-york/ui/badge'
|
|
14
|
+
export * from '../../../app/registry/new-york/ui/breadcrumb'
|
|
15
|
+
export * from '../../../app/registry/new-york/ui/button'
|
|
16
|
+
export * from '../../../app/registry/new-york/ui/calendar'
|
|
17
|
+
export * from '../../../app/registry/new-york/ui/card'
|
|
18
|
+
export * from '../../../app/registry/new-york/ui/carousel'
|
|
19
|
+
export * from '../../../app/registry/new-york/ui/chart'
|
|
20
|
+
export * from '../../../app/registry/new-york/ui/checkbox'
|
|
21
|
+
export * from '../../../app/registry/new-york/ui/collapsible'
|
|
22
|
+
export * from '../../../app/registry/new-york/ui/command'
|
|
23
|
+
export * from '../../../app/registry/new-york/ui/context-menu'
|
|
24
|
+
export * from '../../../app/registry/new-york/ui/dialog'
|
|
25
|
+
export * from '../../../app/registry/new-york/ui/drawer'
|
|
26
|
+
export * from '../../../app/registry/new-york/ui/dropdown-menu'
|
|
27
|
+
export * from '../../../app/registry/new-york/ui/form'
|
|
28
|
+
export * from '../../../app/registry/new-york/ui/hover-card'
|
|
29
|
+
export * from '../../../app/registry/new-york/ui/input-otp'
|
|
30
|
+
export * from '../../../app/registry/new-york/ui/input'
|
|
31
|
+
export * from '../../../app/registry/new-york/ui/label'
|
|
32
|
+
export * from '../../../app/registry/new-york/ui/menubar'
|
|
33
|
+
export * from '../../../app/registry/new-york/ui/navigation-menu'
|
|
34
|
+
export * from '../../../app/registry/new-york/ui/pagination'
|
|
35
|
+
export * from '../../../app/registry/new-york/ui/popover'
|
|
36
|
+
export * from '../../../app/registry/new-york/ui/progress'
|
|
37
|
+
export * from '../../../app/registry/new-york/ui/radio-group'
|
|
38
|
+
export * from '../../../app/registry/new-york/ui/resizable'
|
|
39
|
+
export * from '../../../app/registry/new-york/ui/scroll-area'
|
|
40
|
+
export * from '../../../app/registry/new-york/ui/select'
|
|
41
|
+
export * from '../../../app/registry/new-york/ui/separator'
|
|
42
|
+
export * from '../../../app/registry/new-york/ui/sheet'
|
|
43
|
+
export * from '../../../app/registry/new-york/ui/sidebar'
|
|
44
|
+
export * from '../../../app/registry/new-york/ui/skeleton'
|
|
45
|
+
export * from '../../../app/registry/new-york/ui/slider'
|
|
46
|
+
export * from '../../../app/registry/new-york/ui/sonner'
|
|
47
|
+
export * from '../../../app/registry/new-york/ui/switch'
|
|
48
|
+
export * from '../../../app/registry/new-york/ui/table'
|
|
49
|
+
export * from '../../../app/registry/new-york/ui/tabs'
|
|
50
|
+
export * from '../../../app/registry/new-york/ui/textarea'
|
|
51
|
+
export * from '../../../app/registry/new-york/ui/toast'
|
|
52
|
+
export * from '../../../app/registry/new-york/ui/toaster'
|
|
53
|
+
export * from '../../../app/registry/new-york/ui/toggle-group'
|
|
54
|
+
export * from '../../../app/registry/new-york/ui/toggle'
|
|
55
|
+
export * from '../../../app/registry/new-york/ui/tooltip'
|
|
56
|
+
export * from '../../../app/registry/new-york/ui/use-toast'
|
package/dist/button.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../../app/registry/new-york/ui/button';
|
package/dist/button.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from '../../../app/registry/new-york/ui/button';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function useClickAway(cb) {
|
|
3
|
+
const ref = React.useRef(null);
|
|
4
|
+
const refCb = React.useRef(cb);
|
|
5
|
+
React.useLayoutEffect(() => {
|
|
6
|
+
refCb.current = cb;
|
|
7
|
+
});
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const handler = (e) => {
|
|
10
|
+
const element = ref.current;
|
|
11
|
+
if (element && !element.contains(e.target)) {
|
|
12
|
+
refCb.current(e);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
document.addEventListener('mousedown', handler);
|
|
16
|
+
document.addEventListener('touchstart', handler);
|
|
17
|
+
return () => {
|
|
18
|
+
document.removeEventListener('mousedown', handler);
|
|
19
|
+
document.removeEventListener('touchstart', handler);
|
|
20
|
+
};
|
|
21
|
+
}, []);
|
|
22
|
+
return ref;
|
|
23
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
function useCombinedRefs(...refs) {
|
|
3
|
+
const targetRef = useRef(null);
|
|
4
|
+
useEffect(() => {
|
|
5
|
+
refs.forEach((ref) => {
|
|
6
|
+
if (!ref)
|
|
7
|
+
return;
|
|
8
|
+
if (typeof ref === 'function') {
|
|
9
|
+
ref(targetRef.current);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
ref.current = targetRef.current;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}, [refs]);
|
|
16
|
+
return targetRef;
|
|
17
|
+
}
|
|
18
|
+
export { useCombinedRefs };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import { copyToClipboard } from '../helpers';
|
|
3
|
+
export const useCopyClipboard = ({ string, onCopyClipboard, }) => {
|
|
4
|
+
const [isCopied, setIsCopied] = useState(false);
|
|
5
|
+
let timeout;
|
|
6
|
+
const onCopy = async () => {
|
|
7
|
+
if (!string)
|
|
8
|
+
return;
|
|
9
|
+
const string_ = string.trim();
|
|
10
|
+
if (onCopyClipboard && typeof onCopyClipboard === 'function') {
|
|
11
|
+
onCopyClipboard();
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
await copyToClipboard(string_);
|
|
15
|
+
}
|
|
16
|
+
setIsCopied(true);
|
|
17
|
+
clearTimeout(timeout);
|
|
18
|
+
timeout = setTimeout(() => setIsCopied(false), 1000);
|
|
19
|
+
};
|
|
20
|
+
return { isCopied, onCopy };
|
|
21
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useDebounce(value: string, delay?: number): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function useDebounce(value, delay = 500) {
|
|
3
|
+
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
4
|
+
React.useEffect(() => {
|
|
5
|
+
const handler = setTimeout(() => {
|
|
6
|
+
setDebouncedValue(value);
|
|
7
|
+
}, delay);
|
|
8
|
+
return () => {
|
|
9
|
+
clearTimeout(handler);
|
|
10
|
+
};
|
|
11
|
+
}, [value, delay]);
|
|
12
|
+
return debouncedValue;
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
export const useFillId = (namespace) => {
|
|
3
|
+
const id = `lobe-icons-${namespace.toLowerCase()}-fill`;
|
|
4
|
+
return useMemo(() => ({
|
|
5
|
+
fill: `url(#${id})`,
|
|
6
|
+
id,
|
|
7
|
+
}), [namespace]);
|
|
8
|
+
};
|
|
9
|
+
export const useFillIds = (namespace, length) => {
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
const ids = Array.from({ length }, (_, i) => {
|
|
12
|
+
const id = `lobe-icons-${namespace.toLowerCase()}-fill-${i}`;
|
|
13
|
+
return {
|
|
14
|
+
fill: `url(#${id})`,
|
|
15
|
+
id,
|
|
16
|
+
};
|
|
17
|
+
});
|
|
18
|
+
return ids;
|
|
19
|
+
}, [namespace]);
|
|
20
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function useMap<Key, Value>(initialState?: [Key, Value][]): Map<Key, Value>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function useMap(initialState = []) {
|
|
3
|
+
const mapRef = React.useRef(new Map(initialState));
|
|
4
|
+
const [, reRender] = React.useReducer((x) => x + 1, 0);
|
|
5
|
+
mapRef.current.set = (...args) => {
|
|
6
|
+
Map.prototype.set.apply(mapRef.current, args);
|
|
7
|
+
reRender();
|
|
8
|
+
return mapRef.current;
|
|
9
|
+
};
|
|
10
|
+
mapRef.current.clear = (...args) => {
|
|
11
|
+
Map.prototype.clear.apply(mapRef.current, args);
|
|
12
|
+
reRender();
|
|
13
|
+
};
|
|
14
|
+
mapRef.current.delete = (...args) => {
|
|
15
|
+
const res = Map.prototype.delete.apply(mapRef.current, args);
|
|
16
|
+
reRender();
|
|
17
|
+
return res;
|
|
18
|
+
};
|
|
19
|
+
return mapRef.current;
|
|
20
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export function useMeasure() {
|
|
3
|
+
const [dimensions, setDimensions] = React.useState({
|
|
4
|
+
width: null,
|
|
5
|
+
height: null,
|
|
6
|
+
});
|
|
7
|
+
const previousObserver = React.useRef(null);
|
|
8
|
+
const customRef = React.useCallback((node) => {
|
|
9
|
+
if (previousObserver.current) {
|
|
10
|
+
previousObserver.current.disconnect();
|
|
11
|
+
previousObserver.current = null;
|
|
12
|
+
}
|
|
13
|
+
if (node?.nodeType === Node.ELEMENT_NODE) {
|
|
14
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
15
|
+
if (entry && entry.borderBoxSize) {
|
|
16
|
+
const { inlineSize: width, blockSize: height } = entry.borderBoxSize[0];
|
|
17
|
+
setDimensions({ width, height });
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
observer.observe(node);
|
|
21
|
+
previousObserver.current = observer;
|
|
22
|
+
}
|
|
23
|
+
}, []);
|
|
24
|
+
return [customRef, dimensions];
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useReverseVideoPlayback: () => import("react").RefObject<HTMLVideoElement>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
|
2
|
+
export const useReverseVideoPlayback = () => {
|
|
3
|
+
const videoRef = useRef(null);
|
|
4
|
+
const [isReversing, setIsReversing] = useState(false);
|
|
5
|
+
const playReverse = () => {
|
|
6
|
+
if (!videoRef.current)
|
|
7
|
+
return;
|
|
8
|
+
const video = videoRef.current;
|
|
9
|
+
const reversePlayback = () => {
|
|
10
|
+
if (video.currentTime <= 0) {
|
|
11
|
+
setIsReversing(false);
|
|
12
|
+
void video.play();
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
video.currentTime -= 0.023;
|
|
16
|
+
requestAnimationFrame(reversePlayback);
|
|
17
|
+
};
|
|
18
|
+
reversePlayback();
|
|
19
|
+
};
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const videoElement = videoRef.current;
|
|
22
|
+
if (videoElement) {
|
|
23
|
+
const handleVideoEnd = () => {
|
|
24
|
+
if (isReversing) {
|
|
25
|
+
setIsReversing(false);
|
|
26
|
+
videoElement.currentTime = 0;
|
|
27
|
+
void videoElement.play();
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
setIsReversing(true);
|
|
31
|
+
playReverse();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
videoElement.addEventListener('ended', handleVideoEnd);
|
|
35
|
+
return () => {
|
|
36
|
+
videoElement.removeEventListener('ended', handleVideoEnd);
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}, [isReversing]);
|
|
40
|
+
return videoRef;
|
|
41
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export declare const useScrollRestoration: ({ key, containerRef, scrollTopStateRef, }: {
|
|
3
|
+
key: string;
|
|
4
|
+
containerRef: React.RefObject<HTMLElement | null>;
|
|
5
|
+
scrollTopStateRef: React.RefObject<{
|
|
6
|
+
[key: string]: number;
|
|
7
|
+
} | null>;
|
|
8
|
+
}) => void;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const useScrollRestoration = ({ key, containerRef, scrollTopStateRef, }) => {
|
|
3
|
+
const saveScroll = React.useCallback(() => {
|
|
4
|
+
if (scrollTopStateRef.current) {
|
|
5
|
+
scrollTopStateRef.current[`${key}-scrollTop`] =
|
|
6
|
+
containerRef?.current?.scrollTop ?? 0;
|
|
7
|
+
}
|
|
8
|
+
}, [containerRef, scrollTopStateRef, key]);
|
|
9
|
+
const restoreScroll = React.useCallback(() => {
|
|
10
|
+
if (containerRef.current) {
|
|
11
|
+
containerRef.current.scrollTo({
|
|
12
|
+
top: scrollTopStateRef?.current?.[`${key}-scrollTop`] ?? 0,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}, [containerRef, key, scrollTopStateRef]);
|
|
16
|
+
React.useLayoutEffect(() => {
|
|
17
|
+
return () => {
|
|
18
|
+
saveScroll();
|
|
19
|
+
};
|
|
20
|
+
}, [saveScroll]);
|
|
21
|
+
React.useEffect(() => {
|
|
22
|
+
// Small delay to ensure content is rendered
|
|
23
|
+
const timeoutId = setTimeout(restoreScroll, 100);
|
|
24
|
+
return () => clearTimeout(timeoutId);
|
|
25
|
+
}, [restoreScroll]);
|
|
26
|
+
React.useEffect(() => {
|
|
27
|
+
restoreScroll();
|
|
28
|
+
}, [restoreScroll]);
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
const element = containerRef?.current;
|
|
31
|
+
element?.addEventListener('scroll', saveScroll);
|
|
32
|
+
return () => {
|
|
33
|
+
element?.removeEventListener('scroll', saveScroll);
|
|
34
|
+
};
|
|
35
|
+
}, [containerRef, saveScroll]);
|
|
36
|
+
};
|
|
@@ -303,7 +303,7 @@ module.exports = {
|
|
|
303
303
|
### 3. Add the cn() utility
|
|
304
304
|
Create \`lib/utils.ts\`:
|
|
305
305
|
\`\`\`typescript
|
|
306
|
-
import {
|
|
306
|
+
import { ClassValue, clsx } from "clsx"
|
|
307
307
|
import { twMerge } from "tailwind-merge"
|
|
308
308
|
|
|
309
309
|
export function cn(...inputs: ClassValue[]) {
|
|
@@ -1056,7 +1056,7 @@ Add to your \`globals.css\`:
|
|
|
1056
1056
|
Create \`lib/utils.ts\`:
|
|
1057
1057
|
|
|
1058
1058
|
\`\`\`typescript
|
|
1059
|
-
import {
|
|
1059
|
+
import { ClassValue, clsx } from "clsx"
|
|
1060
1060
|
import { twMerge } from "tailwind-merge"
|
|
1061
1061
|
|
|
1062
1062
|
export function cn(...inputs: ClassValue[]) {
|
package/dist/registry/api.d.ts
CHANGED
package/dist/registry/api.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { registryItemSchema } from "
|
|
1
|
+
import { registryItemSchema } from "./schemas";
|
|
2
2
|
const registryCache = new Map();
|
|
3
3
|
/**
|
|
4
4
|
* Gets the full registry URL based on the registry name or URL provided
|
|
@@ -10,8 +10,8 @@ export function getRegistryUrl(registry) {
|
|
|
10
10
|
if (registry.startsWith("http")) {
|
|
11
11
|
return registry;
|
|
12
12
|
}
|
|
13
|
-
// Default to Hanzo registry if REGISTRY_BASE_URL is defined, otherwise use
|
|
14
|
-
const baseUrl = process.env.REGISTRY_BASE_URL || "https://ui.
|
|
13
|
+
// Default to Hanzo registry if REGISTRY_BASE_URL is defined, otherwise use hanzo
|
|
14
|
+
const baseUrl = process.env.REGISTRY_BASE_URL || "https://ui.hanzo.com/registry";
|
|
15
15
|
// Check if registry is a path to a JSON file
|
|
16
16
|
if (registry.endsWith(".json")) {
|
|
17
17
|
return `${baseUrl}/${registry}`;
|