@zvk/ui 0.1.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/LICENSE.md +26 -0
- package/README.md +31 -0
- package/dist/components/accordion/accordion.d.ts +43 -0
- package/dist/components/accordion/accordion.js +207 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +2 -0
- package/dist/components/alert/alert.d.ts +24 -0
- package/dist/components/alert/alert.js +17 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/alert-dialog/alert-dialog.d.ts +46 -0
- package/dist/components/alert-dialog/alert-dialog.js +112 -0
- package/dist/components/alert-dialog/index.d.ts +2 -0
- package/dist/components/alert-dialog/index.js +2 -0
- package/dist/components/avatar/avatar.d.ts +14 -0
- package/dist/components/avatar/avatar.js +22 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +2 -0
- package/dist/components/badge/badge.d.ts +11 -0
- package/dist/components/badge/badge.js +6 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +24 -0
- package/dist/components/breadcrumbs/breadcrumbs.js +18 -0
- package/dist/components/breadcrumbs/index.d.ts +2 -0
- package/dist/components/breadcrumbs/index.js +1 -0
- package/dist/components/button/button.d.ts +13 -0
- package/dist/components/button/button.js +8 -0
- package/dist/components/button/index.d.ts +2 -0
- package/dist/components/button/index.js +1 -0
- package/dist/components/card/card.d.ts +31 -0
- package/dist/components/card/card.js +28 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/checkbox/checkbox.d.ts +11 -0
- package/dist/components/checkbox/checkbox.js +30 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +2 -0
- package/dist/components/code-block/code-block.d.ts +10 -0
- package/dist/components/code-block/code-block.js +16 -0
- package/dist/components/code-block/index.d.ts +2 -0
- package/dist/components/code-block/index.js +1 -0
- package/dist/components/collapsible/collapsible.d.ts +23 -0
- package/dist/components/collapsible/collapsible.js +52 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +2 -0
- package/dist/components/combobox/combobox.d.ts +20 -0
- package/dist/components/combobox/combobox.js +121 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +2 -0
- package/dist/components/command/command-dialog.d.ts +2 -0
- package/dist/components/command/command-dialog.js +1 -0
- package/dist/components/command/command-filter.d.ts +7 -0
- package/dist/components/command/command-filter.js +14 -0
- package/dist/components/command/command.d.ts +55 -0
- package/dist/components/command/command.js +200 -0
- package/dist/components/command/index.d.ts +2 -0
- package/dist/components/command/index.js +2 -0
- package/dist/components/context-menu/context-menu.d.ts +34 -0
- package/dist/components/context-menu/context-menu.js +154 -0
- package/dist/components/context-menu/index.d.ts +2 -0
- package/dist/components/context-menu/index.js +2 -0
- package/dist/components/conversation/conversation.d.ts +60 -0
- package/dist/components/conversation/conversation.js +49 -0
- package/dist/components/conversation/index.d.ts +2 -0
- package/dist/components/conversation/index.js +1 -0
- package/dist/components/copy-button/copy-button.d.ts +23 -0
- package/dist/components/copy-button/copy-button.js +50 -0
- package/dist/components/copy-button/index.d.ts +2 -0
- package/dist/components/copy-button/index.js +2 -0
- package/dist/components/dialog/dialog.d.ts +62 -0
- package/dist/components/dialog/dialog.js +141 -0
- package/dist/components/dialog/index.d.ts +2 -0
- package/dist/components/dialog/index.js +2 -0
- package/dist/components/dropdown-menu/dropdown-menu.d.ts +43 -0
- package/dist/components/dropdown-menu/dropdown-menu.js +286 -0
- package/dist/components/dropdown-menu/index.d.ts +2 -0
- package/dist/components/dropdown-menu/index.js +2 -0
- package/dist/components/empty-state/empty-state.d.ts +13 -0
- package/dist/components/empty-state/empty-state.js +34 -0
- package/dist/components/empty-state/index.d.ts +2 -0
- package/dist/components/empty-state/index.js +1 -0
- package/dist/components/error-boundary/error-boundary.d.ts +29 -0
- package/dist/components/error-boundary/error-boundary.js +43 -0
- package/dist/components/error-boundary/index.d.ts +2 -0
- package/dist/components/error-boundary/index.js +2 -0
- package/dist/components/field/field.d.ts +23 -0
- package/dist/components/field/field.js +20 -0
- package/dist/components/field/index.d.ts +2 -0
- package/dist/components/field/index.js +1 -0
- package/dist/components/file-upload-input/file-upload-input.d.ts +13 -0
- package/dist/components/file-upload-input/file-upload-input.js +41 -0
- package/dist/components/file-upload-input/index.d.ts +2 -0
- package/dist/components/file-upload-input/index.js +2 -0
- package/dist/components/form/form.d.ts +30 -0
- package/dist/components/form/form.js +88 -0
- package/dist/components/form/index.d.ts +2 -0
- package/dist/components/form/index.js +2 -0
- package/dist/components/icon-button/icon-button.d.ts +10 -0
- package/dist/components/icon-button/icon-button.js +8 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/icon-button/index.js +1 -0
- package/dist/components/index.d.ts +102 -0
- package/dist/components/index.js +51 -0
- package/dist/components/input/index.d.ts +2 -0
- package/dist/components/input/index.js +1 -0
- package/dist/components/input/input.d.ts +11 -0
- package/dist/components/input/input.js +27 -0
- package/dist/components/label/index.d.ts +2 -0
- package/dist/components/label/index.js +1 -0
- package/dist/components/label/label.d.ts +9 -0
- package/dist/components/label/label.js +6 -0
- package/dist/components/menubar/index.d.ts +2 -0
- package/dist/components/menubar/index.js +2 -0
- package/dist/components/menubar/menubar.d.ts +39 -0
- package/dist/components/menubar/menubar.js +214 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/pagination/pagination.d.ts +21 -0
- package/dist/components/pagination/pagination.js +92 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +2 -0
- package/dist/components/popover/popover.d.ts +28 -0
- package/dist/components/popover/popover.js +164 -0
- package/dist/components/progress/index.d.ts +2 -0
- package/dist/components/progress/index.js +1 -0
- package/dist/components/progress/progress.d.ts +24 -0
- package/dist/components/progress/progress.js +29 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +2 -0
- package/dist/components/radio-group/radio-group.d.ts +42 -0
- package/dist/components/radio-group/radio-group.js +69 -0
- package/dist/components/responsive-container/index.d.ts +2 -0
- package/dist/components/responsive-container/index.js +1 -0
- package/dist/components/responsive-container/responsive-container.d.ts +10 -0
- package/dist/components/responsive-container/responsive-container.js +6 -0
- package/dist/components/scroll-area/index.d.ts +2 -0
- package/dist/components/scroll-area/index.js +2 -0
- package/dist/components/scroll-area/scroll-area.d.ts +21 -0
- package/dist/components/scroll-area/scroll-area.js +23 -0
- package/dist/components/sectioned-sidebar-nav/index.d.ts +2 -0
- package/dist/components/sectioned-sidebar-nav/index.js +1 -0
- package/dist/components/sectioned-sidebar-nav/sectioned-sidebar-nav.d.ts +39 -0
- package/dist/components/sectioned-sidebar-nav/sectioned-sidebar-nav.js +37 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +2 -0
- package/dist/components/select/select.d.ts +46 -0
- package/dist/components/select/select.js +239 -0
- package/dist/components/separator/index.d.ts +2 -0
- package/dist/components/separator/index.js +1 -0
- package/dist/components/separator/separator.d.ts +8 -0
- package/dist/components/separator/separator.js +6 -0
- package/dist/components/sheet/index.d.ts +2 -0
- package/dist/components/sheet/index.js +2 -0
- package/dist/components/sheet/sheet.d.ts +49 -0
- package/dist/components/sheet/sheet.js +116 -0
- package/dist/components/sidebar-shell/index.d.ts +2 -0
- package/dist/components/sidebar-shell/index.js +1 -0
- package/dist/components/sidebar-shell/sidebar-shell.d.ts +35 -0
- package/dist/components/sidebar-shell/sidebar-shell.js +28 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/skeleton/skeleton.d.ts +10 -0
- package/dist/components/skeleton/skeleton.js +16 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +2 -0
- package/dist/components/slider/slider.d.ts +12 -0
- package/dist/components/slider/slider.js +30 -0
- package/dist/components/spinner/index.d.ts +2 -0
- package/dist/components/spinner/index.js +1 -0
- package/dist/components/spinner/spinner.d.ts +10 -0
- package/dist/components/spinner/spinner.js +7 -0
- package/dist/components/stat/index.d.ts +2 -0
- package/dist/components/stat/index.js +1 -0
- package/dist/components/stat/stat.d.ts +13 -0
- package/dist/components/stat/stat.js +8 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +2 -0
- package/dist/components/switch/switch.d.ts +11 -0
- package/dist/components/switch/switch.js +27 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/table/table.d.ts +45 -0
- package/dist/components/table/table.js +36 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +2 -0
- package/dist/components/tabs/tabs.d.ts +34 -0
- package/dist/components/tabs/tabs.js +233 -0
- package/dist/components/tabs-with-sidebar/index.d.ts +2 -0
- package/dist/components/tabs-with-sidebar/index.js +2 -0
- package/dist/components/tabs-with-sidebar/tabs-with-sidebar.d.ts +21 -0
- package/dist/components/tabs-with-sidebar/tabs-with-sidebar.js +18 -0
- package/dist/components/textarea/index.d.ts +2 -0
- package/dist/components/textarea/index.js +2 -0
- package/dist/components/textarea/textarea.d.ts +11 -0
- package/dist/components/textarea/textarea.js +28 -0
- package/dist/components/toast/index.d.ts +2 -0
- package/dist/components/toast/index.js +1 -0
- package/dist/components/toast/toast.d.ts +33 -0
- package/dist/components/toast/toast.js +27 -0
- package/dist/components/toggle/index.d.ts +2 -0
- package/dist/components/toggle/index.js +2 -0
- package/dist/components/toggle/toggle.d.ts +12 -0
- package/dist/components/toggle/toggle.js +18 -0
- package/dist/components/toggle-group/index.d.ts +2 -0
- package/dist/components/toggle-group/index.js +2 -0
- package/dist/components/toggle-group/toggle-group.d.ts +28 -0
- package/dist/components/toggle-group/toggle-group.js +67 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +2 -0
- package/dist/components/tooltip/tooltip.d.ts +10 -0
- package/dist/components/tooltip/tooltip.js +100 -0
- package/dist/hooks/index.d.ts +7 -0
- package/dist/hooks/index.js +5 -0
- package/dist/hooks/use-composed-refs.d.ts +3 -0
- package/dist/hooks/use-composed-refs.js +18 -0
- package/dist/hooks/use-controllable-state.d.ts +7 -0
- package/dist/hooks/use-controllable-state.js +30 -0
- package/dist/hooks/use-disclosure.d.ts +13 -0
- package/dist/hooks/use-disclosure.js +20 -0
- package/dist/hooks/use-event.d.ts +1 -0
- package/dist/hooks/use-event.js +11 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/internal/collection/collection.d.ts +18 -0
- package/dist/internal/collection/collection.js +54 -0
- package/dist/internal/collection/index.d.ts +2 -0
- package/dist/internal/collection/index.js +1 -0
- package/dist/internal/dismissable-layer/dismissable-layer.d.ts +13 -0
- package/dist/internal/dismissable-layer/dismissable-layer.js +73 -0
- package/dist/internal/dismissable-layer/index.d.ts +2 -0
- package/dist/internal/dismissable-layer/index.js +1 -0
- package/dist/internal/floating/auto-update.d.ts +9 -0
- package/dist/internal/floating/auto-update.js +48 -0
- package/dist/internal/floating/compute-position.d.ts +2 -0
- package/dist/internal/floating/compute-position.js +96 -0
- package/dist/internal/floating/detect-overflow.d.ts +13 -0
- package/dist/internal/floating/detect-overflow.js +13 -0
- package/dist/internal/floating/floating-types.d.ts +42 -0
- package/dist/internal/floating/floating-types.js +1 -0
- package/dist/internal/floating/index.d.ts +27 -0
- package/dist/internal/floating/index.js +5 -0
- package/dist/internal/floating/middleware.d.ts +11 -0
- package/dist/internal/floating/middleware.js +42 -0
- package/dist/internal/floating/use-floating-position.d.ts +2 -0
- package/dist/internal/floating/use-floating-position.js +113 -0
- package/dist/internal/focus/focus-scope.d.ts +10 -0
- package/dist/internal/focus/focus-scope.js +68 -0
- package/dist/internal/focus/focus-utils.d.ts +9 -0
- package/dist/internal/focus/focus-utils.js +94 -0
- package/dist/internal/focus/index.d.ts +3 -0
- package/dist/internal/focus/index.js +2 -0
- package/dist/internal/overlay-stack/index.d.ts +1 -0
- package/dist/internal/overlay-stack/index.js +1 -0
- package/dist/internal/overlay-stack/overlay-stack.d.ts +12 -0
- package/dist/internal/overlay-stack/overlay-stack.js +41 -0
- package/dist/internal/portal/index.d.ts +2 -0
- package/dist/internal/portal/index.js +1 -0
- package/dist/internal/portal/portal.d.ts +7 -0
- package/dist/internal/portal/portal.js +19 -0
- package/dist/internal/scroll-lock/index.d.ts +1 -0
- package/dist/internal/scroll-lock/index.js +1 -0
- package/dist/internal/scroll-lock/scroll-lock.d.ts +4 -0
- package/dist/internal/scroll-lock/scroll-lock.js +69 -0
- package/dist/styles.css +3852 -0
- package/dist/tokens/index.d.ts +2 -0
- package/dist/tokens/index.js +1 -0
- package/dist/tokens/token-types.d.ts +23 -0
- package/dist/tokens/token-types.js +1 -0
- package/dist/tokens/tokens.d.ts +139 -0
- package/dist/tokens/tokens.js +139 -0
- package/dist/utils/cn.d.ts +2 -0
- package/dist/utils/cn.js +3 -0
- package/dist/utils/compose-event-handlers.d.ts +6 -0
- package/dist/utils/compose-event-handlers.js +8 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +2 -0
- package/package.json +282 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Dialog } from "../dialog/index.js";
|
|
5
|
+
import { composeEventHandlers } from "../../utils/compose-event-handlers.js";
|
|
6
|
+
import { cn } from "../../utils/cn.js";
|
|
7
|
+
import { useControllableState } from "../../hooks/use-controllable-state.js";
|
|
8
|
+
import { createCollection } from "../../internal/collection/index.js";
|
|
9
|
+
import { commandItemMatches } from "./command-filter.js";
|
|
10
|
+
const CommandContext = React.createContext(null);
|
|
11
|
+
function useCommandContext(calledBy) {
|
|
12
|
+
const context = React.useContext(CommandContext);
|
|
13
|
+
if (context === null) {
|
|
14
|
+
throw new Error(`"${calledBy}" must be used inside a <Command />`);
|
|
15
|
+
}
|
|
16
|
+
return context;
|
|
17
|
+
}
|
|
18
|
+
function textFromNode(node) {
|
|
19
|
+
if (typeof node === "string" || typeof node === "number") {
|
|
20
|
+
return String(node);
|
|
21
|
+
}
|
|
22
|
+
if (Array.isArray(node)) {
|
|
23
|
+
return node.map(textFromNode).join("");
|
|
24
|
+
}
|
|
25
|
+
return "";
|
|
26
|
+
}
|
|
27
|
+
function CommandRoot({ children, className, defaultValue = "", onItemSelect, onValueChange, ref, value, ...props }) {
|
|
28
|
+
const [query, setQuery] = useControllableState({
|
|
29
|
+
...(value !== undefined ? { value } : {}),
|
|
30
|
+
defaultValue,
|
|
31
|
+
...(onValueChange ? { onChange: onValueChange } : {})
|
|
32
|
+
});
|
|
33
|
+
const inputId = React.useId();
|
|
34
|
+
const listId = `${inputId}-list`;
|
|
35
|
+
const collectionRef = React.useRef(createCollection());
|
|
36
|
+
const [activeId, setActiveId] = React.useState();
|
|
37
|
+
const [version, setVersion] = React.useState(0);
|
|
38
|
+
const bumpVersion = React.useCallback(() => setVersion((current) => current + 1), []);
|
|
39
|
+
const visibleEnabledItems = React.useCallback(() => {
|
|
40
|
+
return collectionRef.current.items().filter((item) => item.data.visible && item.data.disabled !== true);
|
|
41
|
+
}, []);
|
|
42
|
+
const moveActive = React.useCallback((direction) => {
|
|
43
|
+
const visible = visibleEnabledItems();
|
|
44
|
+
if (visible.length === 0) {
|
|
45
|
+
setActiveId(undefined);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (direction === "first") {
|
|
49
|
+
setActiveId(visible[0]?.id);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (direction === "last") {
|
|
53
|
+
setActiveId(visible.at(-1)?.id);
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
const currentIndex = activeId === undefined ? -1 : visible.findIndex((item) => item.id === activeId);
|
|
57
|
+
const nextIndex = direction === "next" ? currentIndex + 1 : currentIndex - 1;
|
|
58
|
+
const wrapped = ((nextIndex % visible.length) + visible.length) % visible.length;
|
|
59
|
+
setActiveId(visible[wrapped]?.id);
|
|
60
|
+
}, [activeId, visibleEnabledItems]);
|
|
61
|
+
const selectItem = React.useCallback((id) => {
|
|
62
|
+
const item = collectionRef.current.items().find((record) => record.id === id)?.data;
|
|
63
|
+
if (!item || item.disabled === true || !item.visible) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
item.onSelect?.(item.value);
|
|
67
|
+
onItemSelect?.(item.value);
|
|
68
|
+
}, [onItemSelect]);
|
|
69
|
+
const selectActive = React.useCallback(() => {
|
|
70
|
+
if (activeId !== undefined) {
|
|
71
|
+
selectItem(activeId);
|
|
72
|
+
}
|
|
73
|
+
}, [activeId, selectItem]);
|
|
74
|
+
const registerItem = React.useCallback((id, item) => {
|
|
75
|
+
collectionRef.current.register(id, item);
|
|
76
|
+
bumpVersion();
|
|
77
|
+
}, [bumpVersion]);
|
|
78
|
+
const unregisterItem = React.useCallback((id) => {
|
|
79
|
+
collectionRef.current.unregister(id);
|
|
80
|
+
bumpVersion();
|
|
81
|
+
}, [bumpVersion]);
|
|
82
|
+
React.useLayoutEffect(() => {
|
|
83
|
+
const visible = visibleEnabledItems();
|
|
84
|
+
if (visible.length === 0 && activeId !== undefined) {
|
|
85
|
+
setActiveId(undefined);
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (activeId !== undefined && !visible.some((item) => item.id === activeId)) {
|
|
89
|
+
setActiveId(visible[0]?.id);
|
|
90
|
+
}
|
|
91
|
+
}, [activeId, query, version, visibleEnabledItems]);
|
|
92
|
+
const empty = collectionRef.current.items().some((item) => !item.data.visible) &&
|
|
93
|
+
!collectionRef.current.items().some((item) => item.data.visible);
|
|
94
|
+
return (_jsx(CommandContext.Provider, { value: {
|
|
95
|
+
activeId,
|
|
96
|
+
empty,
|
|
97
|
+
getItem: (id) => collectionRef.current.items().find((item) => item.id === id)?.data,
|
|
98
|
+
inputId,
|
|
99
|
+
listId,
|
|
100
|
+
moveActive,
|
|
101
|
+
query,
|
|
102
|
+
registerItem,
|
|
103
|
+
selectActive,
|
|
104
|
+
selectItem,
|
|
105
|
+
setQuery,
|
|
106
|
+
unregisterItem
|
|
107
|
+
}, children: _jsx("div", { ...props, ref: ref, className: cn("liano-command", className), children: children }) }));
|
|
108
|
+
}
|
|
109
|
+
function CommandInput({ className, onKeyDown, placeholder, ref, ...props }) {
|
|
110
|
+
const { activeId, inputId, listId, moveActive, query, selectActive, setQuery } = useCommandContext("Command.Input");
|
|
111
|
+
return (_jsx("input", { ...props, ref: ref, id: props.id ?? inputId, role: "searchbox", "aria-activedescendant": activeId, "aria-controls": listId, "aria-autocomplete": "list", className: cn("liano-command__input", className), onChange: (event) => setQuery(event.currentTarget.value), onKeyDown: composeEventHandlers(onKeyDown, (event) => {
|
|
112
|
+
if (event.key === "ArrowDown") {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
moveActive("next");
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
if (event.key === "ArrowUp") {
|
|
118
|
+
event.preventDefault();
|
|
119
|
+
moveActive("previous");
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (event.key === "Home") {
|
|
123
|
+
event.preventDefault();
|
|
124
|
+
moveActive("first");
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (event.key === "End") {
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
moveActive("last");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (event.key === "Enter") {
|
|
133
|
+
event.preventDefault();
|
|
134
|
+
selectActive();
|
|
135
|
+
}
|
|
136
|
+
}), placeholder: placeholder, value: query }));
|
|
137
|
+
}
|
|
138
|
+
function CommandList({ className, ref, ...props }) {
|
|
139
|
+
const { listId } = useCommandContext("Command.List");
|
|
140
|
+
return _jsx("div", { ...props, ref: ref, id: props.id ?? listId, role: "listbox", className: cn("liano-command__list", className) });
|
|
141
|
+
}
|
|
142
|
+
function CommandEmpty({ className, ref, ...props }) {
|
|
143
|
+
const { empty } = useCommandContext("Command.Empty");
|
|
144
|
+
if (!empty) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return _jsx("div", { ...props, ref: ref, className: cn("liano-command__empty", className) });
|
|
148
|
+
}
|
|
149
|
+
function CommandGroup({ children, className, heading, ref, ...props }) {
|
|
150
|
+
const headingId = React.useId();
|
|
151
|
+
return (_jsxs("div", { ...props, ref: ref, role: "group", "aria-labelledby": heading ? headingId : undefined, className: cn("liano-command__group", className), children: [heading ? _jsx("div", { id: headingId, className: "liano-command__group-heading", children: heading }) : null, children] }));
|
|
152
|
+
}
|
|
153
|
+
function CommandItem({ children, className, disabled, keywords, onClick, onSelect, ref, value, ...props }) {
|
|
154
|
+
const context = useCommandContext("Command.Item");
|
|
155
|
+
const { activeId, query, registerItem, selectItem, unregisterItem } = context;
|
|
156
|
+
const generatedId = React.useId();
|
|
157
|
+
const id = props.id ?? generatedId;
|
|
158
|
+
const label = textFromNode(children) || value;
|
|
159
|
+
const visible = commandItemMatches({ label, value, keywords }, query);
|
|
160
|
+
const isActive = activeId === id;
|
|
161
|
+
React.useLayoutEffect(() => {
|
|
162
|
+
registerItem(id, {
|
|
163
|
+
disabled,
|
|
164
|
+
keywords,
|
|
165
|
+
label,
|
|
166
|
+
onSelect,
|
|
167
|
+
value,
|
|
168
|
+
visible
|
|
169
|
+
});
|
|
170
|
+
return () => unregisterItem(id);
|
|
171
|
+
}, [disabled, id, keywords, label, onSelect, registerItem, unregisterItem, value, visible]);
|
|
172
|
+
if (!visible) {
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
175
|
+
return (_jsx("div", { ...props, ref: ref, id: id, role: "option", "aria-disabled": disabled ? "true" : undefined, "aria-selected": isActive ? "true" : "false", className: cn("liano-command__item", className), "data-disabled": disabled ? "true" : undefined, "data-highlighted": isActive ? "true" : undefined, onClick: composeEventHandlers(onClick, () => {
|
|
176
|
+
if (!disabled) {
|
|
177
|
+
selectItem(id);
|
|
178
|
+
}
|
|
179
|
+
}), children: children }));
|
|
180
|
+
}
|
|
181
|
+
function CommandSeparator({ className, ref, ...props }) {
|
|
182
|
+
return _jsx("div", { ...props, ref: ref, role: "separator", "aria-hidden": "true", className: cn("liano-command__separator", className) });
|
|
183
|
+
}
|
|
184
|
+
export function CommandDialog({ children, className, closeOnSelect = false, commandLabel = "Command menu", onOpenChange, ...props }) {
|
|
185
|
+
const handleItemSelect = React.useCallback(() => {
|
|
186
|
+
if (closeOnSelect) {
|
|
187
|
+
onOpenChange?.(false);
|
|
188
|
+
}
|
|
189
|
+
}, [closeOnSelect, onOpenChange]);
|
|
190
|
+
return (_jsx(Dialog, { ...props, ...(onOpenChange ? { onOpenChange } : {}), children: _jsxs(Dialog.Content, { className: cn("liano-command-dialog", className), children: [_jsx(Dialog.Title, { className: "liano-command-dialog__title", children: commandLabel }), _jsx(Command, { onItemSelect: handleItemSelect, children: children })] }) }));
|
|
191
|
+
}
|
|
192
|
+
export const Command = Object.assign(CommandRoot, {
|
|
193
|
+
Dialog: CommandDialog,
|
|
194
|
+
Empty: CommandEmpty,
|
|
195
|
+
Group: CommandGroup,
|
|
196
|
+
Input: CommandInput,
|
|
197
|
+
Item: CommandItem,
|
|
198
|
+
List: CommandList,
|
|
199
|
+
Separator: CommandSeparator
|
|
200
|
+
});
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface ContextMenuProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
defaultOpen?: boolean;
|
|
4
|
+
onOpenChange?: (open: boolean) => void;
|
|
5
|
+
open?: boolean;
|
|
6
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
7
|
+
}
|
|
8
|
+
export interface ContextMenuTriggerProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
9
|
+
ref?: React.Ref<HTMLSpanElement>;
|
|
10
|
+
}
|
|
11
|
+
export interface ContextMenuContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
12
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
13
|
+
}
|
|
14
|
+
export interface ContextMenuItemProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
15
|
+
onSelect?: (event: React.SyntheticEvent<HTMLElement>) => void;
|
|
16
|
+
tone?: "default" | "danger";
|
|
17
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
18
|
+
}
|
|
19
|
+
export interface ContextMenuSeparatorProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
20
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
21
|
+
}
|
|
22
|
+
declare function ContextMenuRoot({ children, className, defaultOpen, onOpenChange, open: openProp, ref, ...props }: ContextMenuProps): React.JSX.Element;
|
|
23
|
+
declare function ContextMenuTrigger({ children, className, onContextMenu, onKeyDown, ref, ...props }: ContextMenuTriggerProps): React.JSX.Element;
|
|
24
|
+
declare function ContextMenuContent({ children, className, onKeyDown, ref, style, ...props }: ContextMenuContentProps): React.JSX.Element | null;
|
|
25
|
+
declare function ContextMenuItem({ children, className, disabled, onClick, onKeyDown, onSelect, ref, tone, type, ...props }: ContextMenuItemProps): React.JSX.Element;
|
|
26
|
+
declare function ContextMenuSeparator({ className, ref, ...props }: ContextMenuSeparatorProps): React.JSX.Element;
|
|
27
|
+
type ContextMenuComponent = typeof ContextMenuRoot & {
|
|
28
|
+
Content: typeof ContextMenuContent;
|
|
29
|
+
Item: typeof ContextMenuItem;
|
|
30
|
+
Separator: typeof ContextMenuSeparator;
|
|
31
|
+
Trigger: typeof ContextMenuTrigger;
|
|
32
|
+
};
|
|
33
|
+
export declare const ContextMenu: ContextMenuComponent;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { composeEventHandlers } from "../../utils/compose-event-handlers.js";
|
|
5
|
+
import { cn } from "../../utils/cn.js";
|
|
6
|
+
import { useControllableState } from "../../hooks/use-controllable-state.js";
|
|
7
|
+
import { createCollection } from "../../internal/collection/index.js";
|
|
8
|
+
import { DismissableLayer } from "../../internal/dismissable-layer/index.js";
|
|
9
|
+
import { Portal } from "../../internal/portal/index.js";
|
|
10
|
+
const ContextMenuContext = React.createContext(null);
|
|
11
|
+
function useContextMenuContext(calledBy) {
|
|
12
|
+
const context = React.useContext(ContextMenuContext);
|
|
13
|
+
if (context === null) {
|
|
14
|
+
throw new Error(`"${calledBy}" must be used inside a <ContextMenu />`);
|
|
15
|
+
}
|
|
16
|
+
return context;
|
|
17
|
+
}
|
|
18
|
+
function ContextMenuRoot({ children, className, defaultOpen = false, onOpenChange, open: openProp, ref, ...props }) {
|
|
19
|
+
const [open, setOpen] = useControllableState({
|
|
20
|
+
...(openProp !== undefined ? { value: openProp } : {}),
|
|
21
|
+
defaultValue: defaultOpen,
|
|
22
|
+
...(onOpenChange ? { onChange: onOpenChange } : {})
|
|
23
|
+
});
|
|
24
|
+
const [point, setPoint] = React.useState({ x: 0, y: 0 });
|
|
25
|
+
const collectionRef = React.useRef(createCollection());
|
|
26
|
+
const restoreFocusRef = React.useRef(null);
|
|
27
|
+
const contentId = React.useId();
|
|
28
|
+
const close = React.useCallback(() => {
|
|
29
|
+
setOpen(false);
|
|
30
|
+
}, [setOpen]);
|
|
31
|
+
const openAt = React.useCallback((nextPoint, restoreFocusTo) => {
|
|
32
|
+
restoreFocusRef.current = restoreFocusTo;
|
|
33
|
+
setPoint(nextPoint);
|
|
34
|
+
setOpen(true);
|
|
35
|
+
}, [setOpen]);
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
if (open) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
restoreFocusRef.current?.focus();
|
|
41
|
+
}, [open]);
|
|
42
|
+
const registerItem = React.useCallback((id, item) => {
|
|
43
|
+
collectionRef.current.register(id, item);
|
|
44
|
+
}, []);
|
|
45
|
+
const unregisterItem = React.useCallback((id) => {
|
|
46
|
+
collectionRef.current.unregister(id);
|
|
47
|
+
}, []);
|
|
48
|
+
const getItems = React.useCallback(() => collectionRef.current.items(), []);
|
|
49
|
+
const contextValue = React.useMemo(() => ({
|
|
50
|
+
close,
|
|
51
|
+
contentId,
|
|
52
|
+
getItems,
|
|
53
|
+
open,
|
|
54
|
+
openAt,
|
|
55
|
+
point,
|
|
56
|
+
registerItem,
|
|
57
|
+
unregisterItem
|
|
58
|
+
}), [close, contentId, getItems, open, openAt, point, registerItem, unregisterItem]);
|
|
59
|
+
return (_jsx(ContextMenuContext.Provider, { value: contextValue, children: _jsx("div", { ...props, ref: ref, className: cn("liano-context-menu", className), "data-state": open ? "open" : "closed", children: children }) }));
|
|
60
|
+
}
|
|
61
|
+
function ContextMenuTrigger({ children, className, onContextMenu, onKeyDown, ref, ...props }) {
|
|
62
|
+
const { contentId, open, openAt } = useContextMenuContext("ContextMenu.Trigger");
|
|
63
|
+
return (_jsx("span", { ...props, ref: ref, "aria-controls": contentId, "aria-expanded": open ? "true" : "false", className: cn("liano-context-menu__trigger", className), "data-state": open ? "open" : "closed", onContextMenu: composeEventHandlers(onContextMenu, (event) => {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
openAt({ x: event.clientX, y: event.clientY }, document.activeElement instanceof HTMLElement ? document.activeElement : event.currentTarget);
|
|
66
|
+
}), onKeyDown: composeEventHandlers(onKeyDown, (event) => {
|
|
67
|
+
if ((event.shiftKey && event.key === "F10") || event.key === "ContextMenu") {
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
const target = document.activeElement instanceof HTMLElement ? document.activeElement : event.currentTarget;
|
|
70
|
+
const rect = target.getBoundingClientRect();
|
|
71
|
+
openAt({ x: rect.left, y: rect.bottom }, target);
|
|
72
|
+
}
|
|
73
|
+
}), children: children }));
|
|
74
|
+
}
|
|
75
|
+
function focusItem(items, index) {
|
|
76
|
+
const enabled = items.filter((item) => item.data.disabled !== true && item.data.ref !== null);
|
|
77
|
+
if (enabled.length === 0) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
const wrapped = ((index % enabled.length) + enabled.length) % enabled.length;
|
|
81
|
+
enabled[wrapped]?.data.ref?.focus();
|
|
82
|
+
}
|
|
83
|
+
function currentIndex(items) {
|
|
84
|
+
const enabled = items.filter((item) => item.data.disabled !== true && item.data.ref !== null);
|
|
85
|
+
return enabled.findIndex((item) => item.data.ref === document.activeElement);
|
|
86
|
+
}
|
|
87
|
+
function ContextMenuContent({ children, className, onKeyDown, ref, style, ...props }) {
|
|
88
|
+
const { close, contentId, getItems, open, point } = useContextMenuContext("ContextMenu.Content");
|
|
89
|
+
React.useLayoutEffect(() => {
|
|
90
|
+
if (!open) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
queueMicrotask(() => focusItem(getItems(), 0));
|
|
94
|
+
}, [getItems, open]);
|
|
95
|
+
if (!open) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return (_jsx(Portal, { children: _jsx(DismissableLayer, { open: open, onDismiss: close, children: _jsx("div", { ...props, ref: ref, id: contentId, role: "menu", className: cn("liano-context-menu__content", className), style: { ...style, left: `${point.x}px`, top: `${point.y}px` }, onKeyDown: composeEventHandlers(onKeyDown, (event) => {
|
|
99
|
+
const items = getItems();
|
|
100
|
+
const index = currentIndex(items);
|
|
101
|
+
if (event.key === "ArrowDown") {
|
|
102
|
+
event.preventDefault();
|
|
103
|
+
focusItem(items, index + 1);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (event.key === "ArrowUp") {
|
|
107
|
+
event.preventDefault();
|
|
108
|
+
focusItem(items, index - 1);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (event.key === "Escape") {
|
|
112
|
+
close();
|
|
113
|
+
}
|
|
114
|
+
}), children: children }) }) }));
|
|
115
|
+
}
|
|
116
|
+
function ContextMenuItem({ children, className, disabled, onClick, onKeyDown, onSelect, ref, tone = "default", type = "button", ...props }) {
|
|
117
|
+
const { close, registerItem, unregisterItem } = useContextMenuContext("ContextMenu.Item");
|
|
118
|
+
const itemId = React.useId();
|
|
119
|
+
const itemRef = React.useRef(null);
|
|
120
|
+
React.useLayoutEffect(() => {
|
|
121
|
+
registerItem(itemId, { disabled, ref: itemRef.current });
|
|
122
|
+
return () => unregisterItem(itemId);
|
|
123
|
+
}, [disabled, itemId, registerItem, unregisterItem]);
|
|
124
|
+
const select = (event) => {
|
|
125
|
+
if (disabled) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
onSelect?.(event);
|
|
129
|
+
close();
|
|
130
|
+
};
|
|
131
|
+
return (_jsx("button", { ...props, ref: (node) => {
|
|
132
|
+
itemRef.current = node;
|
|
133
|
+
if (typeof ref === "function") {
|
|
134
|
+
ref(node);
|
|
135
|
+
}
|
|
136
|
+
else if (ref) {
|
|
137
|
+
ref.current = node;
|
|
138
|
+
}
|
|
139
|
+
}, type: type, role: "menuitem", disabled: disabled, "aria-disabled": disabled ? "true" : undefined, className: cn("liano-context-menu__item", className), "data-disabled": disabled ? "true" : undefined, "data-tone": tone, onClick: composeEventHandlers(onClick, select), onKeyDown: composeEventHandlers(onKeyDown, (event) => {
|
|
140
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
select(event);
|
|
143
|
+
}
|
|
144
|
+
}), children: children }));
|
|
145
|
+
}
|
|
146
|
+
function ContextMenuSeparator({ className, ref, ...props }) {
|
|
147
|
+
return _jsx("div", { ...props, ref: ref, role: "separator", "aria-hidden": "true", className: cn("liano-context-menu__separator", className) });
|
|
148
|
+
}
|
|
149
|
+
export const ContextMenu = Object.assign(ContextMenuRoot, {
|
|
150
|
+
Content: ContextMenuContent,
|
|
151
|
+
Item: ContextMenuItem,
|
|
152
|
+
Separator: ContextMenuSeparator,
|
|
153
|
+
Trigger: ContextMenuTrigger
|
|
154
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type ConversationMessageRole = "user" | "assistant" | "system";
|
|
3
|
+
export type ConversationToolStatus = "pending" | "running" | "success" | "error";
|
|
4
|
+
export interface ConversationProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
6
|
+
}
|
|
7
|
+
export interface ConversationListProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
8
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
9
|
+
}
|
|
10
|
+
export interface ConversationMessageProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
11
|
+
role: ConversationMessageRole;
|
|
12
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
13
|
+
}
|
|
14
|
+
export interface ConversationSlotProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
15
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
16
|
+
}
|
|
17
|
+
export interface ConversationReasoningProps extends Omit<React.DetailsHTMLAttributes<HTMLDetailsElement>, "title"> {
|
|
18
|
+
title?: React.ReactNode;
|
|
19
|
+
ref?: React.Ref<HTMLDetailsElement>;
|
|
20
|
+
}
|
|
21
|
+
export interface ConversationToolProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "title"> {
|
|
22
|
+
status?: ConversationToolStatus;
|
|
23
|
+
title?: React.ReactNode;
|
|
24
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
25
|
+
}
|
|
26
|
+
export interface ConversationPromptInputProps extends React.FormHTMLAttributes<HTMLFormElement> {
|
|
27
|
+
ref?: React.Ref<HTMLFormElement>;
|
|
28
|
+
}
|
|
29
|
+
export interface ConversationPromptInputTextareaProps extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
30
|
+
ref?: React.Ref<HTMLTextAreaElement>;
|
|
31
|
+
}
|
|
32
|
+
export interface ConversationPromptInputSubmitProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "disabled"> {
|
|
33
|
+
loading?: boolean;
|
|
34
|
+
disabled?: boolean;
|
|
35
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
36
|
+
}
|
|
37
|
+
declare function ConversationRoot({ className, ref, ...props }: ConversationProps): React.JSX.Element;
|
|
38
|
+
declare function ConversationList({ className, ref, ...props }: ConversationListProps): React.JSX.Element;
|
|
39
|
+
declare function ConversationMessage({ className, ref, role, ...props }: ConversationMessageProps): React.JSX.Element;
|
|
40
|
+
declare function ConversationMessageAvatar({ className, ref, ...props }: ConversationSlotProps): React.JSX.Element;
|
|
41
|
+
declare function ConversationMessageContent({ className, ref, ...props }: ConversationSlotProps): React.JSX.Element;
|
|
42
|
+
declare function ConversationResponse({ className, ref, ...props }: ConversationSlotProps): React.JSX.Element;
|
|
43
|
+
declare function ConversationReasoning({ children, className, ref, title, ...props }: ConversationReasoningProps): React.JSX.Element;
|
|
44
|
+
declare function ConversationTool({ children, className, ref, status, title, ...props }: ConversationToolProps): React.JSX.Element;
|
|
45
|
+
declare function ConversationPromptInput({ className, ref, ...props }: ConversationPromptInputProps): React.JSX.Element;
|
|
46
|
+
declare function ConversationPromptInputTextarea({ className, ref, rows, ...props }: ConversationPromptInputTextareaProps): React.JSX.Element;
|
|
47
|
+
declare function ConversationPromptInputSubmit({ className, disabled, loading, ref, type, ...props }: ConversationPromptInputSubmitProps): React.JSX.Element;
|
|
48
|
+
export declare const Conversation: typeof ConversationRoot & {
|
|
49
|
+
List: typeof ConversationList;
|
|
50
|
+
Message: typeof ConversationMessage;
|
|
51
|
+
MessageAvatar: typeof ConversationMessageAvatar;
|
|
52
|
+
MessageContent: typeof ConversationMessageContent;
|
|
53
|
+
Response: typeof ConversationResponse;
|
|
54
|
+
Reasoning: typeof ConversationReasoning;
|
|
55
|
+
Tool: typeof ConversationTool;
|
|
56
|
+
PromptInput: typeof ConversationPromptInput;
|
|
57
|
+
PromptInputTextarea: typeof ConversationPromptInputTextarea;
|
|
58
|
+
PromptInputSubmit: typeof ConversationPromptInputSubmit;
|
|
59
|
+
};
|
|
60
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../utils/cn.js";
|
|
4
|
+
function ConversationRoot({ className, ref, ...props }) {
|
|
5
|
+
return _jsx("div", { ...props, ref: ref, className: cn("liano-conversation", className) });
|
|
6
|
+
}
|
|
7
|
+
function ConversationList({ className, ref, ...props }) {
|
|
8
|
+
return (_jsx("div", { ...props, ref: ref, "aria-label": props["aria-label"] ?? "Conversation", className: cn("liano-conversation__list", className), role: "log" }));
|
|
9
|
+
}
|
|
10
|
+
function ConversationMessage({ className, ref, role, ...props }) {
|
|
11
|
+
return (_jsx("div", { ...props, ref: ref, className: cn("liano-conversation__message", className), "data-role": role }));
|
|
12
|
+
}
|
|
13
|
+
function ConversationMessageAvatar({ className, ref, ...props }) {
|
|
14
|
+
return _jsx("div", { ...props, ref: ref, className: cn("liano-conversation__message-avatar", className) });
|
|
15
|
+
}
|
|
16
|
+
function ConversationMessageContent({ className, ref, ...props }) {
|
|
17
|
+
return _jsx("div", { ...props, ref: ref, className: cn("liano-conversation__message-content", className) });
|
|
18
|
+
}
|
|
19
|
+
function ConversationResponse({ className, ref, ...props }) {
|
|
20
|
+
return _jsx("div", { ...props, ref: ref, className: cn("liano-conversation__response", className) });
|
|
21
|
+
}
|
|
22
|
+
function ConversationReasoning({ children, className, ref, title = "Reasoning", ...props }) {
|
|
23
|
+
return (_jsxs("details", { ...props, ref: ref, className: cn("liano-conversation__reasoning", className), children: [_jsx("summary", { className: "liano-conversation__reasoning-summary", children: title }), _jsx("div", { className: "liano-conversation__reasoning-content", children: children })] }));
|
|
24
|
+
}
|
|
25
|
+
function ConversationTool({ children, className, ref, status = "pending", title, ...props }) {
|
|
26
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("liano-conversation__tool", className), "data-status": status, children: [title ? _jsx("div", { className: "liano-conversation__tool-title", children: title }) : null, children ? _jsx("div", { className: "liano-conversation__tool-content", children: children }) : null] }));
|
|
27
|
+
}
|
|
28
|
+
function ConversationPromptInput({ className, ref, ...props }) {
|
|
29
|
+
return _jsx("form", { ...props, ref: ref, className: cn("liano-conversation__prompt-input", className) });
|
|
30
|
+
}
|
|
31
|
+
function ConversationPromptInputTextarea({ className, ref, rows = 3, ...props }) {
|
|
32
|
+
return (_jsx("textarea", { ...props, ref: ref, className: cn("liano-conversation__prompt-textarea", className), rows: rows }));
|
|
33
|
+
}
|
|
34
|
+
function ConversationPromptInputSubmit({ className, disabled, loading = false, ref, type = "submit", ...props }) {
|
|
35
|
+
const isDisabled = disabled || loading;
|
|
36
|
+
return (_jsx("button", { ...props, ref: ref, "aria-busy": loading ? true : undefined, className: cn("liano-conversation__prompt-submit", className), "data-disabled": isDisabled ? "true" : undefined, "data-loading": loading ? "true" : undefined, disabled: isDisabled, type: type }));
|
|
37
|
+
}
|
|
38
|
+
export const Conversation = Object.assign(ConversationRoot, {
|
|
39
|
+
List: ConversationList,
|
|
40
|
+
Message: ConversationMessage,
|
|
41
|
+
MessageAvatar: ConversationMessageAvatar,
|
|
42
|
+
MessageContent: ConversationMessageContent,
|
|
43
|
+
Response: ConversationResponse,
|
|
44
|
+
Reasoning: ConversationReasoning,
|
|
45
|
+
Tool: ConversationTool,
|
|
46
|
+
PromptInput: ConversationPromptInput,
|
|
47
|
+
PromptInputTextarea: ConversationPromptInputTextarea,
|
|
48
|
+
PromptInputSubmit: ConversationPromptInputSubmit
|
|
49
|
+
});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { Conversation } from "./conversation.js";
|
|
2
|
+
export type { ConversationListProps, ConversationMessageProps, ConversationMessageRole, ConversationPromptInputProps, ConversationPromptInputSubmitProps, ConversationPromptInputTextareaProps, ConversationProps, ConversationReasoningProps, ConversationSlotProps, ConversationToolProps, ConversationToolStatus } from "./conversation.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Conversation } from "./conversation.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export type CopyStatus = "idle" | "copied" | "error";
|
|
3
|
+
export type CopyButtonSize = "sm" | "md";
|
|
4
|
+
export interface CopyButtonProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children" | "onCopy"> {
|
|
5
|
+
value: string;
|
|
6
|
+
copiedLabel?: React.ReactNode;
|
|
7
|
+
idleLabel?: React.ReactNode;
|
|
8
|
+
errorLabel?: React.ReactNode;
|
|
9
|
+
resetDelay?: number;
|
|
10
|
+
onCopy?: (value: string) => void;
|
|
11
|
+
onCopyError?: (error: unknown) => void;
|
|
12
|
+
size?: CopyButtonSize;
|
|
13
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
14
|
+
}
|
|
15
|
+
export interface CopyableTextProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
16
|
+
value: string;
|
|
17
|
+
label?: React.ReactNode;
|
|
18
|
+
truncate?: boolean;
|
|
19
|
+
copyLabel?: React.ReactNode;
|
|
20
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
21
|
+
}
|
|
22
|
+
export declare function CopyButton({ className, copiedLabel, disabled, errorLabel, idleLabel, onClick, onCopy, onCopyError, ref, resetDelay, size, type, value, ...props }: CopyButtonProps): React.JSX.Element;
|
|
23
|
+
export declare function CopyableText({ className, copyLabel, label, ref, truncate, value, ...props }: CopyableTextProps): React.JSX.Element;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "../../utils/cn.js";
|
|
5
|
+
function getClipboard() {
|
|
6
|
+
return typeof navigator === "undefined" ? undefined : navigator.clipboard;
|
|
7
|
+
}
|
|
8
|
+
export function CopyButton({ className, copiedLabel = "Copied", disabled, errorLabel = "Copy failed", idleLabel = "Copy", onClick, onCopy, onCopyError, ref, resetDelay = 2000, size = "sm", type = "button", value, ...props }) {
|
|
9
|
+
const [status, setStatus] = React.useState("idle");
|
|
10
|
+
const resetTimer = React.useRef(undefined);
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
return () => {
|
|
13
|
+
if (resetTimer.current !== undefined) {
|
|
14
|
+
clearTimeout(resetTimer.current);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
}, []);
|
|
18
|
+
const scheduleReset = React.useCallback(() => {
|
|
19
|
+
if (resetTimer.current !== undefined) {
|
|
20
|
+
clearTimeout(resetTimer.current);
|
|
21
|
+
}
|
|
22
|
+
resetTimer.current = setTimeout(() => setStatus("idle"), resetDelay);
|
|
23
|
+
}, [resetDelay]);
|
|
24
|
+
async function handleClick(event) {
|
|
25
|
+
onClick?.(event);
|
|
26
|
+
if (event.defaultPrevented || disabled) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const clipboard = getClipboard();
|
|
31
|
+
if (!clipboard?.writeText) {
|
|
32
|
+
throw new Error("Clipboard API is unavailable.");
|
|
33
|
+
}
|
|
34
|
+
await clipboard.writeText(value);
|
|
35
|
+
setStatus("copied");
|
|
36
|
+
onCopy?.(value);
|
|
37
|
+
scheduleReset();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
setStatus("error");
|
|
41
|
+
onCopyError?.(error);
|
|
42
|
+
scheduleReset();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const label = status === "copied" ? copiedLabel : status === "error" ? errorLabel : idleLabel;
|
|
46
|
+
return (_jsx("button", { ...props, ref: ref, className: cn("liano-copy-button", className), "data-size": size, "data-status": status, disabled: disabled, onClick: handleClick, type: type, children: label }));
|
|
47
|
+
}
|
|
48
|
+
export function CopyableText({ className, copyLabel, label, ref, truncate, value, ...props }) {
|
|
49
|
+
return (_jsxs("div", { ...props, ref: ref, className: cn("liano-copyable-text", className), children: [label ? _jsx("span", { className: "liano-copyable-text__label", children: label }) : null, _jsx("code", { className: "liano-copyable-text__value", "data-truncate": truncate ? "true" : undefined, children: value }), _jsx(CopyButton, { idleLabel: copyLabel ?? "Copy", value: value })] }));
|
|
50
|
+
}
|