@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
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export async function copyToClipboard(text: string) {
|
|
2
|
+
try {
|
|
3
|
+
await navigator.clipboard.writeText(text);
|
|
4
|
+
} catch {
|
|
5
|
+
// Fallback for browsers where the Clipboard API is not supported
|
|
6
|
+
const textarea = document.createElement('textarea');
|
|
7
|
+
textarea.style.position = 'fixed';
|
|
8
|
+
textarea.style.top = '-9999px';
|
|
9
|
+
textarea.style.left = '-9999px';
|
|
10
|
+
textarea.innerText = text;
|
|
11
|
+
document.body.appendChild(textarea);
|
|
12
|
+
textarea.focus();
|
|
13
|
+
textarea.select();
|
|
14
|
+
document.execCommand('copy');
|
|
15
|
+
textarea.remove();
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createRoot } from 'react-dom/client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a shadow root with the specified styles and returns a React root in it.
|
|
5
|
+
* @param {string} tagName - Node name to be applied to the shadow root.
|
|
6
|
+
* @param {string} styles - CSS styles to be applied to the shadow root.
|
|
7
|
+
* @returns {ReactRoot} - React root rendered inside the shadow root.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export function createShadowRoot(tagName: string, styles: string) {
|
|
11
|
+
const container = document.createElement(tagName);
|
|
12
|
+
const shadow = container.attachShadow({ mode: 'open' });
|
|
13
|
+
|
|
14
|
+
// Create a new CSS style sheet and apply the specified styles and apply the style sheet to the shadow root
|
|
15
|
+
const globalStyleSheet = new CSSStyleSheet();
|
|
16
|
+
globalStyleSheet.replaceSync(styles);
|
|
17
|
+
shadow.adoptedStyleSheets = [globalStyleSheet];
|
|
18
|
+
|
|
19
|
+
const html = document.querySelector('html') as HTMLHtmlElement;
|
|
20
|
+
html.prepend(container);
|
|
21
|
+
return createRoot(shadow);
|
|
22
|
+
}
|
package/util/date.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { FormattedMessage } from '@hanzo_network/hanzo-node-state/v2/queries/getChatConversation/types';
|
|
2
|
+
|
|
3
|
+
export type ChatConversationMessage = {
|
|
4
|
+
hash: string;
|
|
5
|
+
parentHash: string;
|
|
6
|
+
inboxId: string;
|
|
7
|
+
scheduledTime: string | undefined;
|
|
8
|
+
content: string;
|
|
9
|
+
isLocal: boolean;
|
|
10
|
+
sender: {
|
|
11
|
+
avatar: string;
|
|
12
|
+
};
|
|
13
|
+
fileInbox?: {
|
|
14
|
+
id: string;
|
|
15
|
+
files: {
|
|
16
|
+
name: string;
|
|
17
|
+
preview?: string;
|
|
18
|
+
}[];
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
export type GetChatConversationOutput = ChatConversationMessage[];
|
|
22
|
+
|
|
23
|
+
export const formatDateToUSLocaleString = (date: Date | undefined) => {
|
|
24
|
+
if (!date) return '-';
|
|
25
|
+
return new Date(date).toLocaleDateString('en-US', {
|
|
26
|
+
year: 'numeric',
|
|
27
|
+
month: 'numeric',
|
|
28
|
+
day: 'numeric',
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
export const formatDateToLocaleStringWithTime = (date: Date | undefined) => {
|
|
32
|
+
if (!date) return '-';
|
|
33
|
+
return new Date(date).toLocaleDateString('en-US', {
|
|
34
|
+
year: 'numeric',
|
|
35
|
+
month: 'numeric',
|
|
36
|
+
day: 'numeric',
|
|
37
|
+
hour: 'numeric',
|
|
38
|
+
minute: 'numeric',
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const getRelativeDateLabel = (date: Date): string => {
|
|
43
|
+
const today = new Date();
|
|
44
|
+
const yesterday = new Date();
|
|
45
|
+
yesterday.setDate(today.getDate() - 1);
|
|
46
|
+
if (date.toDateString() === today.toDateString()) {
|
|
47
|
+
return 'today';
|
|
48
|
+
} else if (date.toDateString() === yesterday.toDateString()) {
|
|
49
|
+
return 'yesterday';
|
|
50
|
+
} else {
|
|
51
|
+
return date.toDateString();
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const groupMessagesByDate = (messages: FormattedMessage[]) => {
|
|
56
|
+
const groupedMessages: Record<string, FormattedMessage[]> = {};
|
|
57
|
+
for (const message of messages) {
|
|
58
|
+
const date = new Date(message.createdAt ?? '').toDateString();
|
|
59
|
+
if (!groupedMessages[date]) {
|
|
60
|
+
groupedMessages[date] = [];
|
|
61
|
+
}
|
|
62
|
+
groupedMessages[date].push(message);
|
|
63
|
+
}
|
|
64
|
+
return groupedMessages;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const formatDateToMonthAndDay = (date: Date): string => {
|
|
68
|
+
const today = new Date();
|
|
69
|
+
if (
|
|
70
|
+
date.getDate() === today.getDate() &&
|
|
71
|
+
date.getMonth() === today.getMonth() &&
|
|
72
|
+
date.getFullYear() === today.getFullYear()
|
|
73
|
+
) {
|
|
74
|
+
return date.toLocaleTimeString('en-US', {
|
|
75
|
+
hour: 'numeric',
|
|
76
|
+
minute: 'numeric',
|
|
77
|
+
hour12: true,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
const month = date.getMonth() + 1;
|
|
81
|
+
const day = date.getDate();
|
|
82
|
+
return `${month}/${day}`;
|
|
83
|
+
};
|
package/util/debounce.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const debounce = (func: Function, delay: number) => {
|
|
2
|
+
let timeoutId: NodeJS.Timeout | null = null;
|
|
3
|
+
return (...args: any[]) => {
|
|
4
|
+
if (timeoutId) {
|
|
5
|
+
clearTimeout(timeoutId);
|
|
6
|
+
}
|
|
7
|
+
timeoutId = setTimeout(() => {
|
|
8
|
+
func(...args);
|
|
9
|
+
}, delay);
|
|
10
|
+
};
|
|
11
|
+
};
|
package/util/file.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const getFileName = (fileName: string): string => {
|
|
2
|
+
const nameParts = fileName.split('.');
|
|
3
|
+
return nameParts.slice(0, -1).join('.');
|
|
4
|
+
};
|
|
5
|
+
export const getFileExt = (fileName: string): string => {
|
|
6
|
+
const nameParts = fileName.split('.');
|
|
7
|
+
return nameParts.pop() || '';
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const isFileTypeImageOrPdf = (file: File): boolean => {
|
|
11
|
+
if (!file) return false;
|
|
12
|
+
return (
|
|
13
|
+
file?.type.startsWith('image/') || file?.type.startsWith('application/pdf')
|
|
14
|
+
);
|
|
15
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { HanzoToolHeader } from '@hanzo_network/hanzo-message-ts/api/tools/types';
|
|
2
|
+
|
|
3
|
+
export const formatText = (text: string) => {
|
|
4
|
+
const camelToSpaces = text.replace(/([a-z])([A-Z])/g, '$1 $2');
|
|
5
|
+
const snakeToSpaces = camelToSpaces.replace(/_/g, ' ');
|
|
6
|
+
return snakeToSpaces
|
|
7
|
+
.split(' ')
|
|
8
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
9
|
+
.join(' ');
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const formatCamelCaseText = (text: string) => {
|
|
13
|
+
const words = text.split(/(?=[A-Z])/);
|
|
14
|
+
|
|
15
|
+
const formattedWords = words.map((word) => {
|
|
16
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const result = formattedWords.join(' ');
|
|
20
|
+
|
|
21
|
+
return result.charAt(0).toUpperCase() + result.slice(1);
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const getVersionFromTool = (toolRouterKey: HanzoToolHeader) => {
|
|
25
|
+
if (toolRouterKey.version) {
|
|
26
|
+
return toolRouterKey.version;
|
|
27
|
+
}
|
|
28
|
+
const parts = toolRouterKey.name.split(':::');
|
|
29
|
+
if (parts.length === 4) {
|
|
30
|
+
return parts[3];
|
|
31
|
+
}
|
|
32
|
+
return 'latest';
|
|
33
|
+
};
|
package/util/index.ts
CHANGED
|
@@ -1,78 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export const cn = (...inputs: ClassValue[]) => (
|
|
12
|
-
twMerge(clsx(inputs))
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
export const markdown = (s: string, options?: any): JSX.Element => (
|
|
16
|
-
mdCompiler(s, {
|
|
17
|
-
wrapper: null,
|
|
18
|
-
...options
|
|
19
|
-
})
|
|
20
|
-
)
|
|
21
|
-
|
|
22
|
-
export const round = (num: number): string => (
|
|
23
|
-
num
|
|
24
|
-
.toFixed(7)
|
|
25
|
-
.replace(/(\.[0-9]+?)0+$/, '$1')
|
|
26
|
-
.replace(/\.0$/, '')
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
export const pxToRem = (px: number, base: number): string => (`${round(px / base)}rem`)
|
|
30
|
-
|
|
31
|
-
export const pxToEm = (px: number, base: number): string => (`${round(px / base)}em`)
|
|
32
|
-
|
|
33
|
-
export const hexToRgb = (hex: string): string => {
|
|
34
|
-
hex = hex.replace('#', '')
|
|
35
|
-
hex = hex.length === 3 ? hex.replace(/./g, '$&$&') : hex
|
|
36
|
-
const r = parseInt(hex.substring(0, 2), 16)
|
|
37
|
-
const g = parseInt(hex.substring(2, 4), 16)
|
|
38
|
-
const b = parseInt(hex.substring(4, 6), 16)
|
|
39
|
-
return `${r} ${g} ${b}`
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
export const asNum = (n: number | `${number}`): number => (
|
|
44
|
-
(typeof n === 'number') ? n : parseInt(n, 10)
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
// https://stackoverflow.com/questions/3971841/how-to-resize-images-proportionally-keeping-the-aspect-ratio
|
|
48
|
-
export const constrain = (d: Dimensions, c: Dimensions): Dimensions => {
|
|
49
|
-
|
|
50
|
-
const ratio = Math.min(c.w / d.w, c.h / d.h)
|
|
51
|
-
return {
|
|
52
|
-
w: Math.round(d.w * ratio),
|
|
53
|
-
h: Math.round(d.h * ratio)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const containsToken = (s: string | undefined, toFind: string): boolean => (s ? s.split(' ').includes(toFind) : false)
|
|
58
|
-
|
|
59
|
-
export const ldMerge = (
|
|
60
|
-
result: any,
|
|
61
|
-
...sources: any[]
|
|
62
|
-
): any => (_merge(result, ...sources))
|
|
63
|
-
|
|
64
|
-
export const capitalize = (str: string): string => (
|
|
65
|
-
str.charAt(0).toUpperCase() + str.slice(1)
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
export { default as spreadToTransform } from './spread-to-transform'
|
|
69
|
-
export { default as formatToMaxChar } from './format-to-max-char'
|
|
70
|
-
export {
|
|
71
|
-
default as formatAndAbbreviateAsCurrency,
|
|
72
|
-
type FormatThreshold,
|
|
73
|
-
type QuantityAbbrSymbol
|
|
74
|
-
} from './format-and-abbreviate-as-currency'
|
|
75
|
-
|
|
76
|
-
// Must be imported from 'use client', so can't include this...
|
|
77
|
-
// export * from './step-animation'
|
|
78
|
-
|
|
1
|
+
export * from './date';
|
|
2
|
+
export * from './file';
|
|
3
|
+
export * from './create-shadow-root';
|
|
4
|
+
export * from './timing';
|
|
5
|
+
export * from './blob';
|
|
6
|
+
export * from './copy-to-clipboard';
|
|
7
|
+
export * from './format-text';
|
|
8
|
+
export * from './toasts';
|
|
9
|
+
export * from './debounce';
|
package/util/timing.ts
ADDED
package/util/toasts.tsx
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { toast } from 'sonner';
|
|
2
|
+
|
|
3
|
+
export const submitRegistrationNoCodeNonPristineError = () => {
|
|
4
|
+
return toast.error(
|
|
5
|
+
<div>
|
|
6
|
+
Your Hanzo Node is currently locked by existing keys, please restore your
|
|
7
|
+
connection or reset your Hanzo Node Storage
|
|
8
|
+
</div>,
|
|
9
|
+
{ position: 'bottom-center' },
|
|
10
|
+
);
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const submitRegistrationNoCodeError = () => {
|
|
14
|
+
return toast.error(<div>Error connecting to your Hanzo Node</div>, {
|
|
15
|
+
position: 'bottom-center',
|
|
16
|
+
});
|
|
17
|
+
};
|
package/utils.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type ClassValue, clsx } from "clsx";
|
|
2
|
+
import { twMerge } from "tailwind-merge";
|
|
3
|
+
|
|
4
|
+
export function cn(...inputs: ClassValue[]) {
|
|
5
|
+
return twMerge(clsx(inputs));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// Re-export from src/utils for backward compatibility
|
|
9
|
+
export * from './src/utils';
|