@ciridae/ui 0.2.5 → 0.3.2

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.
Files changed (150) hide show
  1. package/dist/components/ui/app-shell-page.js +1 -1
  2. package/dist/components/ui/app-shell.js +1 -1
  3. package/dist/components/ui/button-group.js +1 -1
  4. package/dist/components/ui/card.js +1 -1
  5. package/dist/components/ui/ciridae-ui-provider.d.ts +8 -0
  6. package/dist/components/ui/ciridae-ui-provider.js +14 -0
  7. package/dist/components/ui/color-theme.d.ts +1 -0
  8. package/dist/components/ui/color-theme.js +1 -0
  9. package/dist/components/ui/combobox.js +2 -2
  10. package/dist/components/ui/command.js +1 -1
  11. package/dist/components/ui/context-menu.js +2 -2
  12. package/dist/components/ui/data-table-grid.js +1 -1
  13. package/dist/components/ui/data-table.js +1 -1
  14. package/dist/components/ui/dropdown-menu.js +2 -2
  15. package/dist/components/ui/input-group.js +1 -1
  16. package/dist/components/ui/item.d.ts +1 -1
  17. package/dist/components/ui/menubar.js +2 -2
  18. package/dist/components/ui/page-header.js +1 -1
  19. package/dist/components/ui/registry-docs-api.js +1 -1
  20. package/dist/components/ui/registry-docs-showcase.js +1 -1
  21. package/dist/components/ui/select.js +1 -1
  22. package/dist/components/ui/sidebar/group.js +2 -2
  23. package/dist/components/ui/sidebar/menu.js +3 -3
  24. package/dist/components/ui/sidebar-account-menu-theme.js +2 -2
  25. package/dist/components/ui/sidebar-account-menu.js +3 -3
  26. package/dist/styled-system/styles.css +393 -61
  27. package/dist/styles.css +2 -0
  28. package/package.json +7 -260
  29. package/dist/components/agentic/agent-card.d.ts +0 -28
  30. package/dist/components/agentic/agent-card.js +0 -27
  31. package/dist/components/agentic/agent-composer.d.ts +0 -44
  32. package/dist/components/agentic/agent-composer.js +0 -104
  33. package/dist/components/agentic/agent-context.d.ts +0 -28
  34. package/dist/components/agentic/agent-context.js +0 -102
  35. package/dist/components/agentic/agent-plan.d.ts +0 -27
  36. package/dist/components/agentic/agent-plan.js +0 -43
  37. package/dist/components/agentic/agent-queue.d.ts +0 -46
  38. package/dist/components/agentic/agent-queue.js +0 -53
  39. package/dist/components/agentic/agent-task.d.ts +0 -16
  40. package/dist/components/agentic/agent-task.js +0 -20
  41. package/dist/components/agentic/approval-request.d.ts +0 -24
  42. package/dist/components/agentic/approval-request.js +0 -57
  43. package/dist/components/agentic/artifact.d.ts +0 -24
  44. package/dist/components/agentic/artifact.js +0 -72
  45. package/dist/components/agentic/attachments.d.ts +0 -124
  46. package/dist/components/agentic/attachments.js +0 -595
  47. package/dist/components/agentic/audio-player.d.ts +0 -16
  48. package/dist/components/agentic/audio-player.js +0 -21
  49. package/dist/components/agentic/canvas.d.ts +0 -10
  50. package/dist/components/agentic/canvas.js +0 -22
  51. package/dist/components/agentic/clipboard.d.ts +0 -2
  52. package/dist/components/agentic/clipboard.js +0 -12
  53. package/dist/components/agentic/code-block.d.ts +0 -43
  54. package/dist/components/agentic/code-block.js +0 -92
  55. package/dist/components/agentic/commit.d.ts +0 -57
  56. package/dist/components/agentic/commit.js +0 -85
  57. package/dist/components/agentic/connection.d.ts +0 -3
  58. package/dist/components/agentic/connection.js +0 -8
  59. package/dist/components/agentic/controls.d.ts +0 -6
  60. package/dist/components/agentic/controls.js +0 -7
  61. package/dist/components/agentic/conversation.d.ts +0 -25
  62. package/dist/components/agentic/conversation.js +0 -56
  63. package/dist/components/agentic/edge.d.ts +0 -8
  64. package/dist/components/agentic/edge.js +0 -65
  65. package/dist/components/agentic/effort-selector.d.ts +0 -43
  66. package/dist/components/agentic/effort-selector.js +0 -47
  67. package/dist/components/agentic/environment-variables.d.ts +0 -32
  68. package/dist/components/agentic/environment-variables.js +0 -66
  69. package/dist/components/agentic/file-tree.d.ts +0 -24
  70. package/dist/components/agentic/file-tree.js +0 -56
  71. package/dist/components/agentic/image.d.ts +0 -9
  72. package/dist/components/agentic/image.js +0 -11
  73. package/dist/components/agentic/inline-citation.d.ts +0 -40
  74. package/dist/components/agentic/inline-citation.js +0 -111
  75. package/dist/components/agentic/jsx-preview.d.ts +0 -19
  76. package/dist/components/agentic/jsx-preview.js +0 -34
  77. package/dist/components/agentic/message-branch.d.ts +0 -20
  78. package/dist/components/agentic/message-branch.js +0 -83
  79. package/dist/components/agentic/message-response.css +0 -265
  80. package/dist/components/agentic/message-response.css.d.ts +0 -2
  81. package/dist/components/agentic/message.d.ts +0 -27
  82. package/dist/components/agentic/message.js +0 -57
  83. package/dist/components/agentic/mic-selector.d.ts +0 -58
  84. package/dist/components/agentic/mic-selector.js +0 -173
  85. package/dist/components/agentic/model-selector.d.ts +0 -39
  86. package/dist/components/agentic/model-selector.js +0 -47
  87. package/dist/components/agentic/node.d.ts +0 -26
  88. package/dist/components/agentic/node.js +0 -29
  89. package/dist/components/agentic/open-in-chat.d.ts +0 -9
  90. package/dist/components/agentic/open-in-chat.js +0 -8
  91. package/dist/components/agentic/package-info.d.ts +0 -30
  92. package/dist/components/agentic/package-info.js +0 -44
  93. package/dist/components/agentic/panel.d.ts +0 -6
  94. package/dist/components/agentic/panel.js +0 -7
  95. package/dist/components/agentic/persona.d.ts +0 -16
  96. package/dist/components/agentic/persona.js +0 -116
  97. package/dist/components/agentic/prompt-input-action-menu.d.ts +0 -16
  98. package/dist/components/agentic/prompt-input-action-menu.js +0 -22
  99. package/dist/components/agentic/prompt-input-command.d.ts +0 -18
  100. package/dist/components/agentic/prompt-input-command.js +0 -25
  101. package/dist/components/agentic/prompt-input-hover-card.d.ts +0 -10
  102. package/dist/components/agentic/prompt-input-hover-card.js +0 -13
  103. package/dist/components/agentic/prompt-input-select.d.ts +0 -14
  104. package/dist/components/agentic/prompt-input-select.js +0 -19
  105. package/dist/components/agentic/prompt-input-tabs.d.ts +0 -17
  106. package/dist/components/agentic/prompt-input-tabs.js +0 -45
  107. package/dist/components/agentic/prompt-input.d.ts +0 -79
  108. package/dist/components/agentic/prompt-input.js +0 -206
  109. package/dist/components/agentic/reasoning.d.ts +0 -21
  110. package/dist/components/agentic/reasoning.js +0 -106
  111. package/dist/components/agentic/run-checkpoint.d.ts +0 -13
  112. package/dist/components/agentic/run-checkpoint.js +0 -19
  113. package/dist/components/agentic/run-trace.d.ts +0 -30
  114. package/dist/components/agentic/run-trace.js +0 -56
  115. package/dist/components/agentic/sandbox.d.ts +0 -24
  116. package/dist/components/agentic/sandbox.js +0 -33
  117. package/dist/components/agentic/schema-display.d.ts +0 -39
  118. package/dist/components/agentic/schema-display.js +0 -56
  119. package/dist/components/agentic/shimmer.d.ts +0 -11
  120. package/dist/components/agentic/shimmer.js +0 -16
  121. package/dist/components/agentic/snippet.d.ts +0 -18
  122. package/dist/components/agentic/snippet.js +0 -35
  123. package/dist/components/agentic/sources.d.ts +0 -16
  124. package/dist/components/agentic/sources.js +0 -17
  125. package/dist/components/agentic/speech-input.d.ts +0 -24
  126. package/dist/components/agentic/speech-input.js +0 -30
  127. package/dist/components/agentic/stack-trace.d.ts +0 -27
  128. package/dist/components/agentic/stack-trace.js +0 -76
  129. package/dist/components/agentic/suggestion.d.ts +0 -12
  130. package/dist/components/agentic/suggestion.js +0 -15
  131. package/dist/components/agentic/terminal.d.ts +0 -24
  132. package/dist/components/agentic/terminal.js +0 -47
  133. package/dist/components/agentic/test-results.d.ts +0 -51
  134. package/dist/components/agentic/test-results.js +0 -83
  135. package/dist/components/agentic/theme.d.ts +0 -5
  136. package/dist/components/agentic/theme.js +0 -31
  137. package/dist/components/agentic/tool.d.ts +0 -25
  138. package/dist/components/agentic/tool.js +0 -73
  139. package/dist/components/agentic/toolbar.d.ts +0 -6
  140. package/dist/components/agentic/toolbar.js +0 -7
  141. package/dist/components/agentic/transcription.d.ts +0 -20
  142. package/dist/components/agentic/transcription.js +0 -32
  143. package/dist/components/agentic/types.d.ts +0 -172
  144. package/dist/components/agentic/types.js +0 -1
  145. package/dist/components/agentic/use-controllable-state.d.ts +0 -6
  146. package/dist/components/agentic/use-controllable-state.js +0 -13
  147. package/dist/components/agentic/voice-selector.d.ts +0 -69
  148. package/dist/components/agentic/voice-selector.js +0 -122
  149. package/dist/components/agentic/web-preview.d.ts +0 -25
  150. package/dist/components/agentic/web-preview.js +0 -33
@@ -1,595 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- /* eslint-disable complexity, max-lines, max-lines-per-function, react-refresh/only-export-components */
3
- import { CameraIcon, CheckIcon, CircleAlertIcon, FileTextIcon, GlobeIcon, ImageIcon, Music2Icon, PaperclipIcon, VideoIcon, XIcon, } from "lucide-react";
4
- import * as React from "react";
5
- import { Button } from "@ciridae/ui/button";
6
- import { DropdownMenuItem } from "@ciridae/ui/dropdown-menu";
7
- import { HoverCard, HoverCardContent, HoverCardTrigger } from "@ciridae/ui/hover-card";
8
- import { Spinner } from "@ciridae/ui/spinner";
9
- import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@ciridae/ui/tooltip";
10
- import { cn } from "@ciridae/ui/utils";
11
- const mediaCategoryIcons = {
12
- audio: Music2Icon,
13
- document: FileTextIcon,
14
- image: ImageIcon,
15
- source: GlobeIcon,
16
- unknown: PaperclipIcon,
17
- video: VideoIcon,
18
- };
19
- const AttachmentControllerContext = React.createContext(null);
20
- const AttachmentsContext = React.createContext(null);
21
- const AttachmentItemContext = React.createContext(null);
22
- function AttachmentProvider({ accept, attachments, children, defaultAttachments = [], maxAttachmentSizeMb = 10, maxAttachments = 4, multiple = true, onAttachmentError, onAttachmentsChange, onCaptureScreenshot, }) {
23
- const fileInputRef = React.useRef(null);
24
- const isControlled = attachments !== undefined;
25
- const isControlledRef = React.useRef(isControlled);
26
- const [localAttachments, setLocalAttachments] = React.useState(defaultAttachments);
27
- const files = attachments ?? localAttachments;
28
- const filesRef = React.useRef(files);
29
- const ownedObjectUrlsRef = React.useRef(new Set());
30
- const [error, setError] = React.useState();
31
- const [screenshotStatus, setScreenshotStatus] = React.useState(() => getInitialScreenshotStatus(onCaptureScreenshot));
32
- React.useEffect(() => {
33
- const previous = filesRef.current;
34
- if (previous !== files) {
35
- if (isControlled)
36
- revokeRemovedObjectUrls(previous, files, ownedObjectUrlsRef.current);
37
- filesRef.current = files;
38
- }
39
- }, [files, isControlled]);
40
- React.useEffect(() => {
41
- setScreenshotStatus(getInitialScreenshotStatus(onCaptureScreenshot));
42
- }, [onCaptureScreenshot]);
43
- React.useEffect(() => {
44
- isControlledRef.current = isControlled;
45
- }, [isControlled]);
46
- React.useEffect(() => () => {
47
- if (isControlledRef.current)
48
- revokeOwnedObjectUrls(ownedObjectUrlsRef.current);
49
- else
50
- revokeObjectUrls(filesRef.current);
51
- }, []);
52
- const updateAttachments = React.useCallback((updater) => {
53
- const previous = filesRef.current;
54
- const next = updater(previous);
55
- filesRef.current = next;
56
- if (isControlled) {
57
- revokeRemovedObjectUrls(previous, next, ownedObjectUrlsRef.current);
58
- }
59
- else {
60
- revokeRemovedObjectUrls(previous, next);
61
- setLocalAttachments(next);
62
- }
63
- onAttachmentsChange?.(next);
64
- }, [isControlled, onAttachmentsChange]);
65
- const reportError = React.useCallback((nextError) => {
66
- setError(nextError);
67
- onAttachmentError?.(nextError);
68
- }, [onAttachmentError]);
69
- const add = React.useCallback((fileList, options) => {
70
- const incoming = Array.from(fileList);
71
- if (incoming.length === 0)
72
- return;
73
- const validationError = getAttachmentError({
74
- accept,
75
- currentCount: filesRef.current.length,
76
- files: incoming,
77
- maxAttachmentSizeMb,
78
- maxAttachments,
79
- });
80
- if (validationError) {
81
- reportError(validationError);
82
- return;
83
- }
84
- const nextAttachments = incoming.map((file) => {
85
- const attachment = fileToAttachment(file, options?.kind ?? "file");
86
- if (attachment.url?.startsWith("blob:"))
87
- ownedObjectUrlsRef.current.add(attachment.url);
88
- return attachment;
89
- });
90
- setError(undefined);
91
- updateAttachments((current) => [...current, ...nextAttachments]);
92
- if (fileInputRef.current)
93
- fileInputRef.current.value = "";
94
- }, [accept, maxAttachmentSizeMb, maxAttachments, reportError, updateAttachments]);
95
- const remove = React.useCallback((id) => {
96
- updateAttachments((current) => current.filter((attachment) => attachment.id !== id));
97
- }, [updateAttachments]);
98
- const clear = React.useCallback(() => {
99
- updateAttachments(() => []);
100
- }, [updateAttachments]);
101
- const openFileDialog = React.useCallback(() => {
102
- fileInputRef.current?.click();
103
- }, []);
104
- const takeScreenshot = React.useCallback(async () => {
105
- setScreenshotStatus("capturing");
106
- try {
107
- const screenshot = onCaptureScreenshot
108
- ? await onCaptureScreenshot()
109
- : await captureBrowserScreenshot();
110
- if (screenshot)
111
- add([screenshot], { kind: "screenshot" });
112
- setScreenshotStatus(isScreenshotSupported() || onCaptureScreenshot ? "idle" : "unavailable");
113
- }
114
- catch (screenshotError) {
115
- if (isIgnoredScreenshotError(screenshotError)) {
116
- setScreenshotStatus("idle");
117
- return;
118
- }
119
- setScreenshotStatus("error");
120
- }
121
- }, [add, onCaptureScreenshot]);
122
- const contextValue = React.useMemo(() => ({
123
- accept,
124
- add,
125
- clear,
126
- error,
127
- files,
128
- maxAttachmentSizeMb,
129
- maxAttachments,
130
- openFileDialog,
131
- remove,
132
- screenshotStatus,
133
- takeScreenshot,
134
- }), [
135
- accept,
136
- add,
137
- clear,
138
- error,
139
- files,
140
- maxAttachmentSizeMb,
141
- maxAttachments,
142
- openFileDialog,
143
- remove,
144
- screenshotStatus,
145
- takeScreenshot,
146
- ]);
147
- return (_jsxs(AttachmentControllerContext.Provider, { value: contextValue, children: [_jsx("input", { "aria-hidden": "true", accept: accept, className: "hidden", multiple: multiple, onChange: (event) => {
148
- if (event.currentTarget.files)
149
- add(event.currentTarget.files);
150
- event.currentTarget.value = "";
151
- }, ref: fileInputRef, tabIndex: -1, type: "file" }), children] }));
152
- }
153
- function useAttachments() {
154
- const context = React.useContext(AttachmentControllerContext);
155
- if (!context) {
156
- throw new Error("useAttachments must be used within AttachmentProvider.");
157
- }
158
- return context;
159
- }
160
- function useOptionalAttachments() {
161
- return React.useContext(AttachmentControllerContext);
162
- }
163
- function useAttachmentsContext() {
164
- return React.useContext(AttachmentsContext) ?? { variant: "grid" };
165
- }
166
- function useAttachmentContext() {
167
- const context = React.useContext(AttachmentItemContext);
168
- if (!context) {
169
- throw new Error("Attachment components must be used within Attachment.");
170
- }
171
- return context;
172
- }
173
- function Attachments({ variant = "grid", className, children, ...props }) {
174
- const controller = useOptionalAttachments();
175
- const shouldRenderFiles = !children && controller && controller.files.length > 0;
176
- const contextValue = React.useMemo(() => ({ variant }), [variant]);
177
- if (!children && controller && controller.files.length === 0)
178
- return null;
179
- return (_jsx(AttachmentsContext.Provider, { value: contextValue, children: _jsx("div", { "data-slot": "attachments", "data-variant": variant, className: cn("flex min-w-0 items-start", variant === "grid" && "ml-auto w-fit flex-wrap gap-2", variant === "inline" && "flex-wrap gap-1.5", variant === "list" && "w-full flex-col gap-2", className), ...props, children: shouldRenderFiles
180
- ? controller.files.map((attachment) => (_jsxs(Attachment, { data: attachment, onRemove: () => controller.remove(attachment.id), children: [_jsx(AttachmentPreview, {}), _jsx(AttachmentInfo, { showMediaType: variant === "list" }), _jsx(AttachmentStatus, { status: attachment.status }), _jsx(AttachmentRemove, {})] }, attachment.id)))
181
- : children }) }));
182
- }
183
- function AttachmentList({ variant = "inline", ...props }) {
184
- return _jsx(Attachments, { variant: variant, ...props });
185
- }
186
- function Attachment({ attachment, children, className, data, onRemove, ...props }) {
187
- const { variant } = useAttachmentsContext();
188
- const controller = useOptionalAttachments();
189
- const resolvedData = data ?? attachment;
190
- const contextValue = React.useMemo(() => {
191
- if (!resolvedData)
192
- return null;
193
- const resolvedOnRemove = onRemove ??
194
- (resolvedData.id && controller ? () => controller.remove(resolvedData.id) : undefined);
195
- return {
196
- data: resolvedData,
197
- mediaCategory: getMediaCategory(resolvedData),
198
- onRemove: resolvedOnRemove,
199
- variant,
200
- };
201
- }, [controller, onRemove, resolvedData, variant]);
202
- if (!contextValue)
203
- return null;
204
- return (_jsx(AttachmentItemContext.Provider, { value: contextValue, children: _jsx("div", { "data-kind": contextValue.data.kind, "data-slot": "attachment", "data-status": contextValue.data.status, "data-variant": variant, className: cn("group/attachment relative min-w-0 text-sm text-foreground", variant === "grid" && "size-24 overflow-hidden rounded-lg border bg-muted/40", variant === "inline" && [
205
- "flex h-8 max-w-full cursor-pointer select-none items-center gap-1.5 rounded-md border bg-background px-1.5",
206
- "font-medium transition-colors hover:bg-accent hover:text-accent-foreground",
207
- ], variant === "list" && [
208
- "flex w-full items-center gap-3 rounded-lg border bg-background p-3 transition-colors",
209
- "hover:bg-accent/50",
210
- ], "data-[status=error]:border-destructive/40 data-[status=error]:bg-destructive/5", className), ...props, children: children ?? (_jsxs(_Fragment, { children: [_jsx(AttachmentPreview, {}), _jsx(AttachmentInfo, { showMediaType: variant === "list" }), _jsx(AttachmentStatus, { status: contextValue.data.status }), _jsx(AttachmentRemove, {})] })) }) }));
211
- }
212
- function AttachmentPreview({ fallbackIcon, className, ...props }) {
213
- const { data, mediaCategory, variant } = useAttachmentContext();
214
- const Icon = mediaCategoryIcons[mediaCategory];
215
- const iconClassName = variant === "inline" ? "size-3" : "size-4";
216
- return (_jsx("div", { "data-slot": "attachment-preview", className: cn("flex shrink-0 items-center justify-center overflow-hidden", variant === "grid" && "size-full bg-muted", variant === "inline" && "size-5 rounded bg-muted/60", variant === "list" && "size-12 rounded-md bg-muted/60", className), ...props, children: renderAttachmentPreview(data, mediaCategory, variant) ?? fallbackIcon ?? (_jsx(Icon, { className: cn(iconClassName, "text-muted-foreground") })) }));
217
- }
218
- function AttachmentInfo({ showMediaType = false, className, ...props }) {
219
- const { data, variant } = useAttachmentContext();
220
- if (variant === "grid")
221
- return null;
222
- return (_jsxs("div", { "data-slot": "attachment-info", className: cn("grid min-w-0 flex-1 gap-0.5", className), ...props, children: [_jsx("span", { className: "block min-w-0 truncate text-xs leading-none font-medium", children: getAttachmentLabel(data) }), showMediaType || data.error ? (_jsx("span", { className: "block min-w-0 truncate text-[0.6875rem] leading-none text-muted-foreground", children: data.error ?? getAttachmentMeta(data) })) : null] }));
223
- }
224
- function AttachmentName({ className, children, ...props }) {
225
- const context = React.useContext(AttachmentItemContext);
226
- return (_jsx("span", { "data-slot": "attachment-name", className: cn("min-w-0 truncate text-xs leading-none font-medium", className), ...props, children: children ?? (context ? getAttachmentLabel(context.data) : undefined) }));
227
- }
228
- function AttachmentMeta({ attachment, children, className, data, ...props }) {
229
- const context = React.useContext(AttachmentItemContext);
230
- const resolvedData = data ?? attachment ?? context?.data;
231
- return (_jsx("span", { "data-slot": "attachment-meta", className: cn("min-w-0 truncate text-[0.6875rem] leading-none text-muted-foreground", className), ...props, children: children ?? getAttachmentMeta(resolvedData) }));
232
- }
233
- function AttachmentRemove({ attachmentId, children, className, label = "Remove", onClick, size, type = "button", variant: buttonVariant = "ghost", ...props }) {
234
- const controller = useOptionalAttachments();
235
- const item = React.useContext(AttachmentItemContext);
236
- const resolvedAttachmentId = attachmentId ?? item?.data.id;
237
- const attachmentVariant = item?.variant ?? "inline";
238
- if (!item?.onRemove && !resolvedAttachmentId && !onClick)
239
- return null;
240
- return (_jsxs(Button, { "aria-label": label, "data-slot": "attachment-remove", onClick: (event) => {
241
- event.stopPropagation();
242
- onClick?.(event);
243
- if (event.defaultPrevented)
244
- return;
245
- if (item?.onRemove) {
246
- item.onRemove();
247
- return;
248
- }
249
- if (resolvedAttachmentId)
250
- controller?.remove(resolvedAttachmentId);
251
- }, size: size ?? getAttachmentRemoveSize(attachmentVariant), type: type, variant: buttonVariant, className: cn(attachmentVariant === "grid" && [
252
- "absolute top-2 right-2 size-6 rounded-full bg-background/90 p-0 opacity-0 shadow-sm transition-opacity",
253
- "group-hover/attachment:opacity-100 group-focus-within/attachment:opacity-100",
254
- "hover:bg-background [&>svg]:size-3",
255
- ], attachmentVariant === "inline" && [
256
- "absolute right-1.5 size-3.5 rounded p-0 opacity-0 transition-opacity",
257
- "group-hover/attachment:opacity-100 group-focus-within/attachment:opacity-100",
258
- "[&>svg]:size-2.5",
259
- ], attachmentVariant === "list" && "size-8 shrink-0 rounded p-0 [&>svg]:size-4", className), ...props, children: [children ?? _jsx(XIcon, {}), _jsx("span", { className: "sr-only", children: label })] }));
260
- }
261
- function AttachmentHoverCard({ closeDelay = 0, openDelay = 0, ...props }) {
262
- return _jsx(HoverCard, { closeDelay: closeDelay, openDelay: openDelay, ...props });
263
- }
264
- function AttachmentHoverCardTrigger(props) {
265
- return _jsx(HoverCardTrigger, { ...props });
266
- }
267
- function AttachmentHoverCardContent({ align = "start", className, ...props }) {
268
- return _jsx(HoverCardContent, { align: align, className: cn("w-auto p-2", className), ...props });
269
- }
270
- function AttachmentEmpty({ className, children, ...props }) {
271
- return (_jsx("div", { "data-slot": "attachment-empty", className: cn("flex items-center justify-center rounded-lg border border-dashed p-4 text-sm text-muted-foreground", className), ...props, children: children ?? "No attachments" }));
272
- }
273
- function AttachmentActionAddFiles({ children, className, label = "Add attachments", onClick, renderAs = "button", size = "icon-sm", tooltip = "Add attachments", type = "button", variant = "ghost", ...props }) {
274
- const attachments = useOptionalAttachments();
275
- const handleAction = React.useCallback(() => {
276
- attachments?.openFileDialog();
277
- }, [attachments]);
278
- if (renderAs === "menu-item") {
279
- return (_jsxs(DropdownMenuItem, { "data-slot": "attachment-action-add-files", onSelect: (event) => {
280
- event.preventDefault();
281
- handleAction();
282
- }, className: cn("gap-2", className), children: [children ?? _jsx(PaperclipIcon, {}), label] }));
283
- }
284
- const button = (_jsx(Button, { "aria-label": label, "data-slot": "attachment-action-add-files", onClick: (event) => {
285
- onClick?.(event);
286
- if (event.defaultPrevented)
287
- return;
288
- handleAction();
289
- }, size: size, type: type, variant: variant, className: cn("shrink-0 text-muted-foreground", className), ...props, children: children ?? _jsx(PaperclipIcon, {}) }));
290
- return withOptionalTooltip(button, tooltip);
291
- }
292
- function AttachmentActionAddScreenshot({ children, className, disabled, label, onClick, renderAs = "button", size = "icon-sm", status, tooltip, type = "button", variant = "ghost", ...props }) {
293
- const attachments = useOptionalAttachments();
294
- const resolvedStatus = status ?? attachments?.screenshotStatus ?? "idle";
295
- const resolvedLabel = label ?? getScreenshotLabel(resolvedStatus);
296
- const handleAction = React.useCallback(() => {
297
- void attachments?.takeScreenshot();
298
- }, [attachments]);
299
- if (renderAs === "menu-item") {
300
- return (_jsxs(DropdownMenuItem, { "data-slot": "attachment-action-add-screenshot", "data-status": resolvedStatus, disabled: disabled ?? resolvedStatus === "unavailable", onSelect: (event) => {
301
- event.preventDefault();
302
- handleAction();
303
- }, className: cn("gap-2", className), children: [children ?? _jsx(CameraIcon, {}), resolvedLabel] }));
304
- }
305
- const button = (_jsx(Button, { "aria-label": resolvedLabel, "data-slot": "attachment-action-add-screenshot", "data-status": resolvedStatus, disabled: disabled ?? resolvedStatus === "unavailable", loading: resolvedStatus === "capturing", loadingLabel: "Capturing screenshot", onClick: (event) => {
306
- onClick?.(event);
307
- if (event.defaultPrevented)
308
- return;
309
- handleAction();
310
- }, size: size, type: type, variant: variant, className: cn("shrink-0 text-muted-foreground", className), ...props, children: children ?? _jsx(CameraIcon, {}) }));
311
- return withOptionalTooltip(button, tooltip ?? resolvedLabel);
312
- }
313
- function useAttachmentDropTarget({ global, ref, }) {
314
- const { add } = useAttachments();
315
- React.useEffect(() => {
316
- const target = global ? document : ref.current;
317
- if (!target)
318
- return;
319
- const handleDragOver = (event) => {
320
- if (!(event instanceof DragEvent))
321
- return;
322
- if (event.dataTransfer?.types.includes("Files"))
323
- event.preventDefault();
324
- };
325
- const handleDrop = (event) => {
326
- if (!(event instanceof DragEvent))
327
- return;
328
- if (!event.dataTransfer?.types.includes("Files"))
329
- return;
330
- event.preventDefault();
331
- if (event.dataTransfer.files.length > 0)
332
- add(event.dataTransfer.files);
333
- };
334
- target.addEventListener("dragover", handleDragOver);
335
- target.addEventListener("drop", handleDrop);
336
- return () => {
337
- target.removeEventListener("dragover", handleDragOver);
338
- target.removeEventListener("drop", handleDrop);
339
- };
340
- }, [add, global, ref]);
341
- }
342
- async function prepareAttachmentsForSubmit(attachments) {
343
- return await Promise.all(attachments.map(attachmentToSubmitAttachment));
344
- }
345
- function fileToAttachment(file, kind = "file") {
346
- return {
347
- file,
348
- filename: file.name,
349
- id: createAttachmentId(),
350
- kind,
351
- mediaType: file.type,
352
- name: file.name,
353
- size: file.size,
354
- status: "complete",
355
- type: "file",
356
- url: URL.createObjectURL(file),
357
- };
358
- }
359
- function getMediaCategory(data) {
360
- if (data.type === "source-document" || data.kind === "source")
361
- return "source";
362
- const mediaType = data.mediaType ?? "";
363
- if (mediaType.startsWith("image/"))
364
- return "image";
365
- if (mediaType.startsWith("video/"))
366
- return "video";
367
- if (mediaType.startsWith("audio/"))
368
- return "audio";
369
- if (mediaType.startsWith("application/") || mediaType.startsWith("text/"))
370
- return "document";
371
- return "unknown";
372
- }
373
- function getAttachmentLabel(data) {
374
- if (data.type === "source-document" || data.kind === "source") {
375
- return data.title || data.filename || data.name || "Source";
376
- }
377
- const category = getMediaCategory(data);
378
- return data.filename || data.name || (category === "image" ? "Image" : "Attachment");
379
- }
380
- function renderAttachmentPreview(data, mediaCategory, variant) {
381
- if (mediaCategory === "image" && data.url) {
382
- return (_jsx("img", { alt: getAttachmentLabel(data), className: cn("size-full object-cover", variant !== "grid" && "rounded"), height: variant === "grid" ? 96 : 20, src: data.url, width: variant === "grid" ? 96 : 20 }));
383
- }
384
- if (mediaCategory === "video" && data.url) {
385
- return _jsx("video", { className: "size-full object-cover", muted: true, src: data.url });
386
- }
387
- return null;
388
- }
389
- function AttachmentStatus({ status }) {
390
- const item = React.useContext(AttachmentItemContext);
391
- const hoverClassName = item?.variant === "inline"
392
- ? "transition-opacity group-hover/attachment:opacity-0 group-focus-within/attachment:opacity-0"
393
- : undefined;
394
- if (status === "uploading")
395
- return (_jsx(Spinner, { "data-slot": "attachment-status", className: cn("size-3.5 shrink-0 text-muted-foreground", hoverClassName) }));
396
- if (status === "complete")
397
- return (_jsx(CheckIcon, { "data-slot": "attachment-status", className: cn("size-3.5 shrink-0 text-muted-foreground", hoverClassName) }));
398
- if (status === "error")
399
- return (_jsx(CircleAlertIcon, { "data-slot": "attachment-status", className: cn("size-3.5 shrink-0 text-destructive", hoverClassName) }));
400
- return null;
401
- }
402
- async function attachmentToSubmitAttachment(attachment) {
403
- if (!attachment.url?.startsWith("blob:"))
404
- return attachment;
405
- const dataUrl = await convertBlobUrlToDataUrl(attachment.url);
406
- return {
407
- ...attachment,
408
- url: dataUrl ?? attachment.url,
409
- };
410
- }
411
- async function convertBlobUrlToDataUrl(url) {
412
- try {
413
- const response = await fetch(url);
414
- const blob = await response.blob();
415
- return await new Promise((resolve) => {
416
- const reader = new FileReader();
417
- reader.onloadend = () => {
418
- const result = reader.result;
419
- resolve(typeof result === "string" ? result : null);
420
- };
421
- reader.onerror = () => resolve(null);
422
- reader.readAsDataURL(blob);
423
- });
424
- }
425
- catch {
426
- return null;
427
- }
428
- }
429
- function getAttachmentError({ accept, currentCount, files, maxAttachmentSizeMb, maxAttachments, }) {
430
- if (currentCount + files.length > maxAttachments) {
431
- return { code: "max_attachments", message: `Attach up to ${maxAttachments} files.` };
432
- }
433
- const oversizedFile = files.find((file) => file.size > maxAttachmentSizeMb * 1024 * 1024);
434
- if (oversizedFile) {
435
- return {
436
- code: "max_attachment_size",
437
- message: `${oversizedFile.name} is larger than ${maxAttachmentSizeMb} MB.`,
438
- };
439
- }
440
- const unsupportedFile = files.find((file) => !isAcceptedFile(file, accept));
441
- if (unsupportedFile) {
442
- return { code: "accept", message: `${unsupportedFile.name} is not an accepted file type.` };
443
- }
444
- return undefined;
445
- }
446
- function isAcceptedFile(file, accept) {
447
- if (!accept)
448
- return true;
449
- const rules = accept
450
- .split(",")
451
- .map((rule) => rule.trim().toLowerCase())
452
- .filter(Boolean);
453
- const fileName = file.name.toLowerCase();
454
- const fileType = file.type.toLowerCase();
455
- return rules.some((rule) => {
456
- if (rule === "*/*")
457
- return true;
458
- if (rule.startsWith("."))
459
- return fileName.endsWith(rule);
460
- if (rule.endsWith("/*"))
461
- return fileType.startsWith(rule.slice(0, -1));
462
- return fileType === rule;
463
- });
464
- }
465
- async function captureBrowserScreenshot() {
466
- if (!isScreenshotSupported())
467
- return null;
468
- let stream = null;
469
- const video = document.createElement("video");
470
- video.muted = true;
471
- video.playsInline = true;
472
- try {
473
- stream = await navigator.mediaDevices.getDisplayMedia({ audio: false, video: true });
474
- video.srcObject = stream;
475
- await new Promise((resolve, reject) => {
476
- video.onloadedmetadata = () => resolve();
477
- video.onerror = () => reject(new Error("Failed to load screen stream."));
478
- });
479
- await video.play();
480
- if (!video.videoWidth || !video.videoHeight)
481
- return null;
482
- const canvas = document.createElement("canvas");
483
- canvas.width = video.videoWidth;
484
- canvas.height = video.videoHeight;
485
- const context = canvas.getContext("2d");
486
- if (!context)
487
- return null;
488
- context.drawImage(video, 0, 0, canvas.width, canvas.height);
489
- const blob = await new Promise((resolve) => {
490
- canvas.toBlob(resolve, "image/png");
491
- });
492
- if (!blob)
493
- return null;
494
- return new File([blob], `screenshot-${getScreenshotTimestamp()}.png`, {
495
- lastModified: Date.now(),
496
- type: "image/png",
497
- });
498
- }
499
- finally {
500
- if (stream) {
501
- for (const track of stream.getTracks())
502
- track.stop();
503
- }
504
- video.pause();
505
- video.srcObject = null;
506
- }
507
- }
508
- function isScreenshotSupported() {
509
- return typeof navigator !== "undefined" && !!navigator.mediaDevices?.getDisplayMedia;
510
- }
511
- function getInitialScreenshotStatus(onCaptureScreenshot) {
512
- return onCaptureScreenshot || isScreenshotSupported() ? "idle" : "unavailable";
513
- }
514
- function isIgnoredScreenshotError(error) {
515
- return (error instanceof DOMException &&
516
- (error.name === "NotAllowedError" || error.name === "AbortError"));
517
- }
518
- function revokeRemovedObjectUrls(previousAttachments, nextAttachments, ownedUrls) {
519
- const nextUrls = new Set(nextAttachments.map((attachment) => attachment.url).filter(Boolean));
520
- const removedAttachments = previousAttachments.filter((attachment) => attachment.url &&
521
- !nextUrls.has(attachment.url) &&
522
- (!ownedUrls || ownedUrls.has(attachment.url)));
523
- revokeObjectUrls(removedAttachments);
524
- if (ownedUrls) {
525
- for (const attachment of removedAttachments) {
526
- if (attachment.url)
527
- ownedUrls.delete(attachment.url);
528
- }
529
- }
530
- }
531
- function revokeObjectUrls(attachments) {
532
- for (const attachment of attachments) {
533
- if (attachment.url?.startsWith("blob:"))
534
- URL.revokeObjectURL(attachment.url);
535
- }
536
- }
537
- function revokeOwnedObjectUrls(ownedUrls) {
538
- for (const url of ownedUrls) {
539
- URL.revokeObjectURL(url);
540
- }
541
- ownedUrls.clear();
542
- }
543
- function getAttachmentMeta(attachment) {
544
- if (!attachment)
545
- return null;
546
- if (attachment.error)
547
- return attachment.error;
548
- const parts = [getMediaLabel(attachment), formatFileSize(attachment.size)].filter(Boolean);
549
- return parts.join(" · ");
550
- }
551
- function getMediaLabel(attachment) {
552
- if (attachment.kind === "screenshot")
553
- return "Screenshot";
554
- if (attachment.kind === "source" || attachment.type === "source-document")
555
- return "Source";
556
- if (!attachment.mediaType)
557
- return "File";
558
- const mediaTypeParts = attachment.mediaType.split("/");
559
- return mediaTypeParts[mediaTypeParts.length - 1]?.toUpperCase() ?? "File";
560
- }
561
- function formatFileSize(size) {
562
- if (size === undefined)
563
- return undefined;
564
- if (size < 1024)
565
- return `${size} B`;
566
- if (size < 1024 * 1024)
567
- return `${Math.round(size / 1024)} KB`;
568
- return `${(size / 1024 / 1024).toFixed(1)} MB`;
569
- }
570
- function getAttachmentRemoveSize(variant) {
571
- if (variant === "list")
572
- return "icon-sm";
573
- return "icon-xs";
574
- }
575
- function getScreenshotLabel(status) {
576
- if (status === "capturing")
577
- return "Capturing screenshot";
578
- if (status === "unavailable")
579
- return "Screenshot unavailable";
580
- if (status === "error")
581
- return "Screenshot failed";
582
- return "Add screenshot";
583
- }
584
- function getScreenshotTimestamp() {
585
- return new Date().toISOString().replace(/[:.]/g, "-").replace("T", "_").replace("Z", "");
586
- }
587
- function createAttachmentId() {
588
- return globalThis.crypto?.randomUUID?.() ?? `attachment-${Date.now()}-${Math.random()}`;
589
- }
590
- function withOptionalTooltip(button, tooltip) {
591
- if (!tooltip)
592
- return button;
593
- return (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: button }), _jsx(TooltipContent, { children: tooltip })] }) }));
594
- }
595
- export { Attachment, AttachmentActionAddFiles, AttachmentActionAddScreenshot, AttachmentEmpty, AttachmentHoverCard, AttachmentHoverCardContent, AttachmentHoverCardTrigger, AttachmentInfo, AttachmentList, AttachmentMeta, AttachmentName, AttachmentPreview, AttachmentProvider, AttachmentRemove, Attachments, captureBrowserScreenshot, fileToAttachment, getAttachmentLabel, getMediaCategory, prepareAttachmentsForSubmit, useAttachmentContext, useAttachmentDropTarget, useAttachments, useAttachmentsContext, useOptionalAttachments, };
@@ -1,16 +0,0 @@
1
- import type * as React from "react";
2
- import type { AgenticAudioSource, AgenticPreviewState } from "@ciridae/ui/types";
3
- type AudioPlayerProps = React.ComponentProps<"div"> & AgenticAudioSource & {
4
- state?: AgenticPreviewState;
5
- };
6
- type AudioPlayerHeaderProps = React.ComponentProps<"div">;
7
- type AudioPlayerTitleProps = React.ComponentProps<"p">;
8
- type AudioPlayerDescriptionProps = React.ComponentProps<"p">;
9
- type AudioPlayerContentProps = React.ComponentProps<"div">;
10
- declare function AudioPlayer({ className, description, duration, src, state, title, ...props }: AudioPlayerProps): React.JSX.Element;
11
- declare function AudioPlayerHeader({ className, ...props }: AudioPlayerHeaderProps): React.JSX.Element;
12
- declare function AudioPlayerTitle({ className, ...props }: AudioPlayerTitleProps): React.JSX.Element;
13
- declare function AudioPlayerDescription({ className, ...props }: AudioPlayerDescriptionProps): React.JSX.Element;
14
- declare function AudioPlayerContent({ className, ...props }: AudioPlayerContentProps): React.JSX.Element;
15
- export { AudioPlayer, AudioPlayerContent, AudioPlayerDescription, AudioPlayerHeader, AudioPlayerTitle, };
16
- export type { AudioPlayerContentProps, AudioPlayerDescriptionProps, AudioPlayerHeaderProps, AudioPlayerProps, AudioPlayerTitleProps, };
@@ -1,21 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { HeadphonesIcon, PlayIcon } from "lucide-react";
3
- import { Badge } from "@ciridae/ui/badge";
4
- import { Card } from "@ciridae/ui/card";
5
- import { cn } from "@ciridae/ui/utils";
6
- function AudioPlayer({ className, description, duration, src, state = src ? "ready" : "idle", title = "Audio response", ...props }) {
7
- return (_jsxs(Card, { "data-slot": "audio-player", "data-state": state, className: cn("grid w-full min-w-0 gap-3 rounded-lg border bg-card p-3", className), ...props, children: [_jsxs(AudioPlayerHeader, { children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [_jsx("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-muted-foreground", children: _jsx(HeadphonesIcon, { "aria-hidden": "true", className: "size-4" }) }), _jsxs("div", { className: "min-w-0", children: [_jsx(AudioPlayerTitle, { children: title }), description ? _jsx(AudioPlayerDescription, { children: description }) : null] })] }), duration ? _jsx(Badge, { variant: "outline", children: duration }) : null] }), _jsx(AudioPlayerContent, { children: src ? (_jsx("audio", { className: "h-9 w-full", controls: true, preload: "metadata", src: src, children: _jsx("track", { kind: "captions" }) })) : (_jsxs("div", { className: "flex h-9 items-center gap-2 rounded-md bg-muted/40 px-3 text-sm text-muted-foreground", children: [_jsx(PlayIcon, { "aria-hidden": "true", className: "size-4" }), "No audio source"] })) })] }));
8
- }
9
- function AudioPlayerHeader({ className, ...props }) {
10
- return (_jsx("div", { "data-slot": "audio-player-header", className: cn("flex min-w-0 items-start justify-between gap-3", className), ...props }));
11
- }
12
- function AudioPlayerTitle({ className, ...props }) {
13
- return (_jsx("p", { "data-slot": "audio-player-title", className: cn("truncate text-sm font-medium", className), ...props }));
14
- }
15
- function AudioPlayerDescription({ className, ...props }) {
16
- return (_jsx("p", { "data-slot": "audio-player-description", className: cn("truncate text-xs text-muted-foreground", className), ...props }));
17
- }
18
- function AudioPlayerContent({ className, ...props }) {
19
- return _jsx("div", { "data-slot": "audio-player-content", className: cn("min-w-0", className), ...props });
20
- }
21
- export { AudioPlayer, AudioPlayerContent, AudioPlayerDescription, AudioPlayerHeader, AudioPlayerTitle, };
@@ -1,10 +0,0 @@
1
- import { type ReactNode } from "react";
2
- import { type Edge as FlowEdge, type Node as FlowNode, type ReactFlowProps } from "@xyflow/react";
3
- import "@xyflow/react/dist/style.css";
4
- type CanvasProps<NodeType extends FlowNode = FlowNode, EdgeType extends FlowEdge = FlowEdge> = ReactFlowProps<NodeType, EdgeType> & {
5
- children?: ReactNode;
6
- showBackground?: boolean;
7
- };
8
- declare function Canvas<NodeType extends FlowNode = FlowNode, EdgeType extends FlowEdge = FlowEdge>({ children, className, colorMode, deleteKeyCode, defaultMarkerColor, fitView, maxZoom, minZoom, proOptions, showBackground, style, ...props }: CanvasProps<NodeType, EdgeType>): import("react").JSX.Element;
9
- export { Canvas };
10
- export type { CanvasProps };
@@ -1,22 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { Background, BackgroundVariant, ReactFlow, } from "@xyflow/react";
3
- import "@xyflow/react/dist/style.css";
4
- import { useAgenticTheme } from "@ciridae/ui/theme";
5
- import { cn } from "@ciridae/ui/utils";
6
- const defaultDeleteKeyCode = ["Backspace", "Delete"];
7
- const workflowEdgeColor = "color-mix(in oklch, var(--foreground) 72%, transparent)";
8
- const workflowEdgeColorVariable = "var(--agentic-workflow-edge-color)";
9
- function Canvas({ children, className, colorMode, deleteKeyCode = defaultDeleteKeyCode, defaultMarkerColor, fitView = true, maxZoom = 1.5, minZoom = 0.35, proOptions = { hideAttribution: true }, showBackground = true, style, ...props }) {
10
- const resolvedColorMode = useCanvasColorMode(colorMode);
11
- const canvasStyle = {
12
- "--agentic-workflow-edge-color": workflowEdgeColor,
13
- ...style,
14
- };
15
- const markerColor = defaultMarkerColor === undefined ? workflowEdgeColorVariable : defaultMarkerColor;
16
- return (_jsxs(ReactFlow, { colorMode: resolvedColorMode, deleteKeyCode: deleteKeyCode, defaultMarkerColor: markerColor, fitView: fitView, maxZoom: maxZoom, minZoom: minZoom, proOptions: proOptions, style: canvasStyle, "data-slot": "canvas", className: cn("w-full min-w-0 min-h-80 rounded-lg border bg-background text-foreground", "[&_.react-flow__pane]:cursor-grab [&_.react-flow__pane.react-flow__pane-dragging]:cursor-grabbing", className), ...props, children: [showBackground ? (_jsx(Background, { className: "text-border opacity-80", color: "currentColor", gap: 24, size: 1, variant: BackgroundVariant.Dots })) : null, children] }));
17
- }
18
- function useCanvasColorMode(colorMode) {
19
- const documentTheme = useAgenticTheme();
20
- return colorMode ?? documentTheme;
21
- }
22
- export { Canvas };