@arbidocs/react 0.3.184 → 0.4.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/dist/chunk-3CLGHHME.js +3882 -0
- package/dist/chunk-3CLGHHME.js.map +1 -0
- package/dist/chunk-6ALMBER7.js +176 -0
- package/dist/chunk-6ALMBER7.js.map +1 -0
- package/dist/chunk-BXP6S34V.cjs +284 -0
- package/dist/chunk-BXP6S34V.cjs.map +1 -0
- package/dist/chunk-EJ2BMHYK.js +272 -0
- package/dist/chunk-EJ2BMHYK.js.map +1 -0
- package/dist/chunk-OU2QLIKS.cjs +4060 -0
- package/dist/chunk-OU2QLIKS.cjs.map +1 -0
- package/dist/chunk-RZQACYNQ.cjs +218 -0
- package/dist/chunk-RZQACYNQ.cjs.map +1 -0
- package/dist/index-CcbVSNSP.d.cts +116 -0
- package/dist/index-CcbVSNSP.d.ts +116 -0
- package/dist/index.cjs +955 -2796
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -901
- package/dist/index.d.ts +13 -901
- package/dist/index.js +312 -2303
- package/dist/index.js.map +1 -1
- package/dist/shell/index.cjs +29 -0
- package/dist/shell/index.cjs.map +1 -0
- package/dist/shell/index.d.cts +4 -0
- package/dist/shell/index.d.ts +4 -0
- package/dist/shell/index.js +4 -0
- package/dist/shell/index.js.map +1 -0
- package/dist/ui/index.cjs +288 -147
- package/dist/ui/index.d.cts +878 -3
- package/dist/ui/index.d.ts +878 -3
- package/dist/ui/index.js +2 -1
- package/dist/viewers/index.cjs +327 -76
- package/dist/viewers/index.cjs.map +1 -1
- package/dist/viewers/index.d.cts +90 -4
- package/dist/viewers/index.d.ts +90 -4
- package/dist/viewers/index.js +316 -78
- package/dist/viewers/index.js.map +1 -1
- package/package.json +12 -3
- package/dist/chunk-FIPS3VPH.cjs +0 -1975
- package/dist/chunk-FIPS3VPH.cjs.map +0 -1
- package/dist/chunk-I256BUCX.js +0 -1819
- package/dist/chunk-I256BUCX.js.map +0 -1
|
@@ -0,0 +1,3882 @@
|
|
|
1
|
+
import { cn, getCollisionPadding, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator } from './chunk-6ALMBER7.js';
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import * as React2 from 'react';
|
|
4
|
+
import React2__default, { createContext, forwardRef, memo, useMemo, useContext, useState, useRef, useEffect, useCallback, useId, Fragment as Fragment$1 } from 'react';
|
|
5
|
+
import Markdown from 'react-markdown';
|
|
6
|
+
import remarkGfm from 'remark-gfm';
|
|
7
|
+
import rehypeRaw from 'rehype-raw';
|
|
8
|
+
import { Circle, Check, X, ChevronDown, ChevronUp, Search, MessageCircleMore, Loader2, Square, Mic, MoreVertical, Copy, MessageSquareLock, Info, FileQuestion, BookOpen, Upload, LogOut, LayoutGrid, Bell, MessageSquare, CircleUserRound, Wrench, CreditCard, ClipboardList, UserPlus, UserStar, Settings2, Users, User, NotebookPen, NotebookText, StickyNote, FolderPlus, Hash, EyeOff, Eye, CaptionsOff, FolderOpen, MessageSquareMore, MessageSquarePlus, MessageSquareText, MessageSquareOff, MessagesSquare, Columns3Cog, SquarePlus, SquareM, ChevronsDown, Bot, Calendar, Folder, List, SquareCheckBig, ChevronsUpDown, Minus, Plus, AlertTriangle, FileX, SkipForward, XCircle, CheckCircle } from 'lucide-react';
|
|
9
|
+
import { createPortal } from 'react-dom';
|
|
10
|
+
import * as AvatarPrimitive from '@radix-ui/react-avatar';
|
|
11
|
+
import { cva } from 'class-variance-authority';
|
|
12
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
13
|
+
import * as HoverCardPrimitive from '@radix-ui/react-hover-card';
|
|
14
|
+
import * as SeparatorPrimitive from '@radix-ui/react-separator';
|
|
15
|
+
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
16
|
+
import * as ProgressPrimitive from '@radix-ui/react-progress';
|
|
17
|
+
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
18
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
19
|
+
import * as SwitchPrimitives from '@radix-ui/react-switch';
|
|
20
|
+
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
21
|
+
import * as SliderPrimitive from '@radix-ui/react-slider';
|
|
22
|
+
import * as TogglePrimitive from '@radix-ui/react-toggle';
|
|
23
|
+
import * as ToggleGroupPrimitive from '@radix-ui/react-toggle-group';
|
|
24
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
25
|
+
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
26
|
+
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
27
|
+
import { Command as Command$1 } from 'cmdk';
|
|
28
|
+
|
|
29
|
+
var markdownBaseComponents = {
|
|
30
|
+
h1: ({ children, ...props }) => /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold", "data-testid": "markdown-heading-1", ...props, children }),
|
|
31
|
+
h2: ({ children, ...props }) => /* @__PURE__ */ jsx("h2", { className: "font-semibold text-base", "data-testid": "markdown-heading-2", ...props, children }),
|
|
32
|
+
h3: ({ children, ...props }) => /* @__PURE__ */ jsx("h3", { className: "font-semibold text-base", "data-testid": "markdown-heading-3", ...props, children }),
|
|
33
|
+
h4: ({ children, ...props }) => /* @__PURE__ */ jsx("h4", { className: "font-semibold text-base", ...props, children }),
|
|
34
|
+
h5: ({ children, ...props }) => /* @__PURE__ */ jsx("h5", { className: "font-medium", ...props, children }),
|
|
35
|
+
strong: ({ children, ...props }) => /* @__PURE__ */ jsx("strong", { className: "font-semibold", ...props, children }),
|
|
36
|
+
blockquote: ({ children, ...props }) => /* @__PURE__ */ jsx("blockquote", { className: "border-l-2 border-primary pl-4", ...props, children }),
|
|
37
|
+
ol: ({ children, ...props }) => /* @__PURE__ */ jsx("ol", { className: "list-decimal space-y-2 pl-6", "data-testid": "markdown-ordered-list", ...props, children }),
|
|
38
|
+
ul: ({ children, ...props }) => /* @__PURE__ */ jsx("ul", { className: "list-none space-y-2 pl-6", "data-testid": "markdown-unordered-list", ...props, children }),
|
|
39
|
+
li: ({ children, ...props }) => /* @__PURE__ */ jsx("li", { className: "my-1.5", ...props, children }),
|
|
40
|
+
table: ({ children, ...props }) => /* @__PURE__ */ jsx("table", { "data-testid": "markdown-table", ...props, children }),
|
|
41
|
+
th: ({ children, ...props }) => /* @__PURE__ */ jsx("th", { ...props, children }),
|
|
42
|
+
td: ({ children, ...props }) => /* @__PURE__ */ jsx("td", { ...props, children }),
|
|
43
|
+
tr: ({ children, ...props }) => /* @__PURE__ */ jsx("tr", { ...props, children }),
|
|
44
|
+
p: ({ children, ...props }) => /* @__PURE__ */ jsx("p", { className: "whitespace-pre-wrap", ...props, children }),
|
|
45
|
+
hr: (props) => /* @__PURE__ */ jsx("hr", { className: "border-foreground/20", ...props }),
|
|
46
|
+
sup: ({ children, ...props }) => /* @__PURE__ */ jsx("sup", { className: "text-xs", ...props, children }),
|
|
47
|
+
sub: ({ children, ...props }) => /* @__PURE__ */ jsx("sub", { className: "text-xs", ...props, children }),
|
|
48
|
+
div: ({ children, className, ...props }) => /* @__PURE__ */ jsx("div", { className, ...props, children }),
|
|
49
|
+
br: (props) => /* @__PURE__ */ jsx("br", { ...props }),
|
|
50
|
+
kbd: ({ children, ...props }) => /* @__PURE__ */ jsx(
|
|
51
|
+
"kbd",
|
|
52
|
+
{
|
|
53
|
+
className: "px-1.5 py-0.5 text-xs font-mono bg-muted border border-border rounded",
|
|
54
|
+
...props,
|
|
55
|
+
children
|
|
56
|
+
}
|
|
57
|
+
),
|
|
58
|
+
abbr: ({ children, title, ...props }) => /* @__PURE__ */ jsx("abbr", { title, className: "underline decoration-dotted cursor-help", ...props, children }),
|
|
59
|
+
cite: ({ children, ...props }) => /* @__PURE__ */ jsx("cite", { className: "italic", ...props, children })
|
|
60
|
+
};
|
|
61
|
+
var MarkdownStreamingContext = createContext(false);
|
|
62
|
+
|
|
63
|
+
// src/ai/split-markdown-blocks.ts
|
|
64
|
+
var LIST_ITEM_RE = /^\s*([-*+]|\d+[.)])\s/;
|
|
65
|
+
var BLOCKQUOTE_RE = /^\s*>/;
|
|
66
|
+
function splitMarkdownBlocks(content) {
|
|
67
|
+
if (!content) return [];
|
|
68
|
+
const blocks = [];
|
|
69
|
+
let start = 0;
|
|
70
|
+
let inFence = false;
|
|
71
|
+
let i = 0;
|
|
72
|
+
while (i < content.length) {
|
|
73
|
+
if (content.startsWith("```", i)) {
|
|
74
|
+
inFence = !inFence;
|
|
75
|
+
i += 3;
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (!inFence && content[i] === "\n" && content[i + 1] === "\n") {
|
|
79
|
+
const before = content.slice(start, i);
|
|
80
|
+
const lastLine = before.slice(before.lastIndexOf("\n") + 1);
|
|
81
|
+
const afterStart = i + 2;
|
|
82
|
+
const nextNewline = content.indexOf("\n", afterStart);
|
|
83
|
+
const nextLine = content.slice(afterStart, nextNewline === -1 ? void 0 : nextNewline);
|
|
84
|
+
const bothListItems = LIST_ITEM_RE.test(lastLine) && LIST_ITEM_RE.test(nextLine);
|
|
85
|
+
const bothBlockquotes = BLOCKQUOTE_RE.test(lastLine) && BLOCKQUOTE_RE.test(nextLine);
|
|
86
|
+
if (bothListItems || bothBlockquotes) {
|
|
87
|
+
i += 2;
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
blocks.push(content.slice(start, afterStart));
|
|
91
|
+
start = afterStart;
|
|
92
|
+
i = afterStart;
|
|
93
|
+
continue;
|
|
94
|
+
}
|
|
95
|
+
i++;
|
|
96
|
+
}
|
|
97
|
+
if (start < content.length) blocks.push(content.slice(start));
|
|
98
|
+
return blocks;
|
|
99
|
+
}
|
|
100
|
+
function CodeBlock({ language, code }) {
|
|
101
|
+
const [copied, setCopied] = useState(false);
|
|
102
|
+
const handleCopy = async () => {
|
|
103
|
+
try {
|
|
104
|
+
await navigator.clipboard.writeText(code);
|
|
105
|
+
setCopied(true);
|
|
106
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
107
|
+
} catch {
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
return /* @__PURE__ */ jsxs(
|
|
111
|
+
"div",
|
|
112
|
+
{
|
|
113
|
+
className: "code-block relative my-3 overflow-hidden rounded-md border border-border bg-muted",
|
|
114
|
+
"data-testid": "markdown-code-block",
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b border-border px-3 py-1.5", children: [
|
|
117
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs text-muted-foreground", children: language || "code" }),
|
|
118
|
+
/* @__PURE__ */ jsxs(
|
|
119
|
+
"button",
|
|
120
|
+
{
|
|
121
|
+
type: "button",
|
|
122
|
+
onClick: handleCopy,
|
|
123
|
+
className: "flex items-center gap-1 text-xs text-muted-foreground transition-colors hover:text-foreground",
|
|
124
|
+
title: copied ? "Copied!" : "Copy code",
|
|
125
|
+
children: [
|
|
126
|
+
copied ? /* @__PURE__ */ jsx(Check, { size: 12 }) : /* @__PURE__ */ jsx(Copy, { size: 12 }),
|
|
127
|
+
/* @__PURE__ */ jsx("span", { children: copied ? "Copied" : "Copy" })
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsx("pre", { className: "overflow-x-auto p-3 text-sm leading-relaxed", children: /* @__PURE__ */ jsx("code", { className: cn("font-mono text-foreground", language && `language-${language}`), children: code }) })
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
var defaultComponents = {
|
|
138
|
+
...markdownBaseComponents,
|
|
139
|
+
a: ({ href, children, ...props }) => {
|
|
140
|
+
const isInternal = !href || href.startsWith("#") || href.startsWith("cite:");
|
|
141
|
+
return /* @__PURE__ */ jsx(
|
|
142
|
+
"a",
|
|
143
|
+
{
|
|
144
|
+
className: "text-primary underline underline-offset-2",
|
|
145
|
+
href,
|
|
146
|
+
...isInternal ? {} : { target: "_blank", rel: "noopener noreferrer" },
|
|
147
|
+
...props,
|
|
148
|
+
children
|
|
149
|
+
}
|
|
150
|
+
);
|
|
151
|
+
},
|
|
152
|
+
em: ({ children, ...props }) => /* @__PURE__ */ jsx("em", { className: "italic", ...props, children }),
|
|
153
|
+
code: function MarkdownCode({
|
|
154
|
+
className,
|
|
155
|
+
children,
|
|
156
|
+
...props
|
|
157
|
+
}) {
|
|
158
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
159
|
+
if (!match) {
|
|
160
|
+
return /* @__PURE__ */ jsx(
|
|
161
|
+
"code",
|
|
162
|
+
{
|
|
163
|
+
className: "rounded bg-muted px-1 py-0.5 font-mono text-[0.9em]",
|
|
164
|
+
"data-testid": "markdown-inline-code",
|
|
165
|
+
...props,
|
|
166
|
+
children
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
return /* @__PURE__ */ jsx(CodeBlock, { language: match[1], code: String(children).replace(/\n$/, "") });
|
|
171
|
+
},
|
|
172
|
+
// The CodeBlock renders its own <pre>; unwrap react-markdown's wrapper so we
|
|
173
|
+
// don't nest <pre><pre>.
|
|
174
|
+
pre: ({ children }) => /* @__PURE__ */ jsx(Fragment, { children }),
|
|
175
|
+
blockquote: ({ children, ...props }) => /* @__PURE__ */ jsx("blockquote", { className: "border-l-2 border-border pl-4 italic text-muted-foreground", ...props, children }),
|
|
176
|
+
table: ({ children, ...props }) => /* @__PURE__ */ jsx("div", { className: "my-3 overflow-x-auto rounded-lg border border-border", children: /* @__PURE__ */ jsx("table", { "data-testid": "markdown-table", className: "w-full border-collapse text-sm", ...props, children }) }),
|
|
177
|
+
thead: ({ children, ...props }) => /* @__PURE__ */ jsx("thead", { className: "bg-muted", ...props, children }),
|
|
178
|
+
th: ({ children, ...props }) => /* @__PURE__ */ jsx(
|
|
179
|
+
"th",
|
|
180
|
+
{
|
|
181
|
+
className: "border-b border-border px-3 py-2 text-left font-semibold text-foreground",
|
|
182
|
+
...props,
|
|
183
|
+
children
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
td: ({ children, ...props }) => /* @__PURE__ */ jsx("td", { className: "border-b border-border px-3 py-2 align-top", ...props, children }),
|
|
187
|
+
// General emphasis marks (GFM `~~strikethrough~~` → <del>, raw <ins>/<mark>).
|
|
188
|
+
del: ({ children, ...props }) => /* @__PURE__ */ jsx("del", { className: "text-muted-foreground line-through", ...props, children }),
|
|
189
|
+
ins: ({ children, ...props }) => /* @__PURE__ */ jsx("ins", { className: "underline decoration-primary/60", ...props, children }),
|
|
190
|
+
mark: ({ children, ...props }) => /* @__PURE__ */ jsx("mark", { className: "rounded bg-primary/15 px-0.5 text-foreground", ...props, children })
|
|
191
|
+
};
|
|
192
|
+
var remarkPlugins = [remarkGfm];
|
|
193
|
+
var rehypePlugins = [rehypeRaw];
|
|
194
|
+
var MemoizedBlock = React2__default.memo(function MarkdownBlock({
|
|
195
|
+
content,
|
|
196
|
+
components
|
|
197
|
+
}) {
|
|
198
|
+
return /* @__PURE__ */ jsx(Markdown, { remarkPlugins, rehypePlugins, components, children: content });
|
|
199
|
+
});
|
|
200
|
+
var MarkdownErrorBoundary = class extends React2__default.Component {
|
|
201
|
+
state = { hasError: false };
|
|
202
|
+
static getDerivedStateFromError() {
|
|
203
|
+
return { hasError: true };
|
|
204
|
+
}
|
|
205
|
+
render() {
|
|
206
|
+
return this.state.hasError ? this.props.fallback : this.props.children;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
function MarkdownRendererComponent({
|
|
210
|
+
children,
|
|
211
|
+
components: customComponents,
|
|
212
|
+
isStreaming = false,
|
|
213
|
+
className,
|
|
214
|
+
testId = "markdown-renderer"
|
|
215
|
+
}) {
|
|
216
|
+
const components = useMemo(
|
|
217
|
+
() => customComponents ? { ...defaultComponents, ...customComponents } : defaultComponents,
|
|
218
|
+
[customComponents]
|
|
219
|
+
);
|
|
220
|
+
const blocks = useMemo(() => splitMarkdownBlocks(children), [children]);
|
|
221
|
+
return /* @__PURE__ */ jsx(
|
|
222
|
+
MarkdownErrorBoundary,
|
|
223
|
+
{
|
|
224
|
+
fallback: /* @__PURE__ */ jsx("div", { className: cn("whitespace-pre-wrap break-words text-foreground", className), children }),
|
|
225
|
+
children: /* @__PURE__ */ jsx(MarkdownStreamingContext.Provider, { value: isStreaming, children: /* @__PURE__ */ jsx(
|
|
226
|
+
"div",
|
|
227
|
+
{
|
|
228
|
+
className: cn(
|
|
229
|
+
"markdown-content space-y-3 break-words leading-relaxed text-foreground",
|
|
230
|
+
className
|
|
231
|
+
),
|
|
232
|
+
"data-testid": testId,
|
|
233
|
+
children: blocks.map((block, index) => /* @__PURE__ */ jsx(MemoizedBlock, { content: block, components }, index))
|
|
234
|
+
}
|
|
235
|
+
) })
|
|
236
|
+
}
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
var MarkdownRenderer = React2__default.memo(MarkdownRendererComponent);
|
|
240
|
+
var TooltipContext = React2.createContext(null);
|
|
241
|
+
var DEFAULT_DELAY = 300;
|
|
242
|
+
var TooltipConfigContext = React2.createContext({
|
|
243
|
+
delayDuration: DEFAULT_DELAY
|
|
244
|
+
});
|
|
245
|
+
var TooltipProvider = ({ children, delayDuration = DEFAULT_DELAY }) => {
|
|
246
|
+
const value = React2.useMemo(() => ({ delayDuration }), [delayDuration]);
|
|
247
|
+
return /* @__PURE__ */ jsx(TooltipConfigContext.Provider, { value, children });
|
|
248
|
+
};
|
|
249
|
+
function Tooltip({ children, delayDuration }) {
|
|
250
|
+
const config = React2.useContext(TooltipConfigContext);
|
|
251
|
+
const delay = delayDuration ?? config.delayDuration;
|
|
252
|
+
const [open, setOpen] = React2.useState(false);
|
|
253
|
+
const triggerRef = React2.useRef(null);
|
|
254
|
+
const timer = React2.useRef(null);
|
|
255
|
+
const contentId = React2.useId();
|
|
256
|
+
const clearTimer = () => {
|
|
257
|
+
if (timer.current) {
|
|
258
|
+
clearTimeout(timer.current);
|
|
259
|
+
timer.current = null;
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
const suppressed = React2.useRef(false);
|
|
263
|
+
const show = React2.useCallback(() => {
|
|
264
|
+
clearTimer();
|
|
265
|
+
if (suppressed.current) return;
|
|
266
|
+
timer.current = setTimeout(() => setOpen(true), delay);
|
|
267
|
+
}, [delay]);
|
|
268
|
+
const hide = React2.useCallback(() => {
|
|
269
|
+
clearTimer();
|
|
270
|
+
setOpen(false);
|
|
271
|
+
}, []);
|
|
272
|
+
const suppress = React2.useCallback(() => {
|
|
273
|
+
suppressed.current = true;
|
|
274
|
+
clearTimer();
|
|
275
|
+
setOpen(false);
|
|
276
|
+
}, []);
|
|
277
|
+
const release = React2.useCallback(() => {
|
|
278
|
+
suppressed.current = false;
|
|
279
|
+
}, []);
|
|
280
|
+
const setTrigger = React2.useCallback((el) => {
|
|
281
|
+
triggerRef.current = el;
|
|
282
|
+
}, []);
|
|
283
|
+
React2.useEffect(() => () => clearTimer(), []);
|
|
284
|
+
const value = React2.useMemo(
|
|
285
|
+
() => ({ open, show, hide, suppress, release, setTrigger, triggerRef, contentId }),
|
|
286
|
+
[open, show, hide, suppress, release, setTrigger, contentId]
|
|
287
|
+
);
|
|
288
|
+
return /* @__PURE__ */ jsx(TooltipContext.Provider, { value, children });
|
|
289
|
+
}
|
|
290
|
+
function isKeyboardFocus(target) {
|
|
291
|
+
try {
|
|
292
|
+
return target.matches(":focus-visible");
|
|
293
|
+
} catch {
|
|
294
|
+
return true;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
function showsOwnText(el) {
|
|
298
|
+
if (!el) return false;
|
|
299
|
+
const walker = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
|
|
300
|
+
let visible = "";
|
|
301
|
+
for (let node = walker.nextNode(); node; node = walker.nextNode()) {
|
|
302
|
+
if (node.parentElement?.closest(".sr-only")) continue;
|
|
303
|
+
visible += node.textContent ?? "";
|
|
304
|
+
}
|
|
305
|
+
return /\p{L}{2,}/u.test(visible);
|
|
306
|
+
}
|
|
307
|
+
function TooltipTrigger({ asChild, children, ...props }) {
|
|
308
|
+
const ctx = React2.useContext(TooltipContext);
|
|
309
|
+
if (!ctx) return /* @__PURE__ */ jsx(Fragment, { children });
|
|
310
|
+
const triggerHandlers = {
|
|
311
|
+
onPointerEnter: (e) => {
|
|
312
|
+
props.onPointerEnter?.(e);
|
|
313
|
+
if (e.pointerType === "touch") return;
|
|
314
|
+
if (showsOwnText(e.currentTarget)) return;
|
|
315
|
+
ctx.show();
|
|
316
|
+
},
|
|
317
|
+
onPointerLeave: (e) => {
|
|
318
|
+
props.onPointerLeave?.(e);
|
|
319
|
+
ctx.release();
|
|
320
|
+
ctx.hide();
|
|
321
|
+
},
|
|
322
|
+
onPointerDown: (e) => {
|
|
323
|
+
props.onPointerDown?.(e);
|
|
324
|
+
(asChild && React2.isValidElement(children) ? children.props.onPointerDown : void 0)?.(e);
|
|
325
|
+
ctx.suppress();
|
|
326
|
+
},
|
|
327
|
+
onFocus: (e) => {
|
|
328
|
+
props.onFocus?.(e);
|
|
329
|
+
if (isKeyboardFocus(e.target) && !showsOwnText(e.currentTarget)) ctx.show();
|
|
330
|
+
},
|
|
331
|
+
onBlur: (e) => {
|
|
332
|
+
props.onBlur?.(e);
|
|
333
|
+
ctx.hide();
|
|
334
|
+
},
|
|
335
|
+
"aria-describedby": ctx.open ? ctx.contentId : void 0,
|
|
336
|
+
"data-state": ctx.open ? "open" : "closed"
|
|
337
|
+
};
|
|
338
|
+
if (asChild && React2.isValidElement(children)) {
|
|
339
|
+
const child = children;
|
|
340
|
+
return React2.cloneElement(child, {
|
|
341
|
+
...props,
|
|
342
|
+
...triggerHandlers,
|
|
343
|
+
ref: ctx.setTrigger
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
return /* @__PURE__ */ jsx(
|
|
347
|
+
"button",
|
|
348
|
+
{
|
|
349
|
+
type: "button",
|
|
350
|
+
...props,
|
|
351
|
+
...triggerHandlers,
|
|
352
|
+
ref: ctx.setTrigger,
|
|
353
|
+
children
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
var TRANSFORM_BY_SIDE = {
|
|
358
|
+
top: "translate(-50%, -100%)",
|
|
359
|
+
bottom: "translate(-50%, 0)",
|
|
360
|
+
left: "translate(-100%, -50%)",
|
|
361
|
+
right: "translate(0, -50%)"
|
|
362
|
+
};
|
|
363
|
+
var TooltipContent = React2.forwardRef(
|
|
364
|
+
({ className, side = "top", sideOffset = 4, collisionPadding = 8, style, ...props }, ref) => {
|
|
365
|
+
const ctx = React2.useContext(TooltipContext);
|
|
366
|
+
const innerRef = React2.useRef(null);
|
|
367
|
+
const [coords, setCoords] = React2.useState(null);
|
|
368
|
+
React2.useLayoutEffect(() => {
|
|
369
|
+
if (!ctx?.open || !ctx.triggerRef.current) {
|
|
370
|
+
setCoords(null);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
const r = ctx.triggerRef.current.getBoundingClientRect();
|
|
374
|
+
const c = innerRef.current?.getBoundingClientRect();
|
|
375
|
+
const ch = c?.height ?? 0;
|
|
376
|
+
const cw = c?.width ?? 0;
|
|
377
|
+
const vh = window.innerHeight;
|
|
378
|
+
const vw = window.innerWidth;
|
|
379
|
+
let s = side;
|
|
380
|
+
if (s === "top" && r.top - sideOffset - ch < 0) s = "bottom";
|
|
381
|
+
else if (s === "bottom" && r.bottom + sideOffset + ch > vh) s = "top";
|
|
382
|
+
else if (s === "left" && r.left - sideOffset - cw < 0) s = "right";
|
|
383
|
+
else if (s === "right" && r.right + sideOffset + cw > vw) s = "left";
|
|
384
|
+
const PAD = collisionPadding;
|
|
385
|
+
const clamp = (value, half, max) => Math.min(Math.max(value, PAD + half), Math.max(PAD + half, max - PAD - half));
|
|
386
|
+
const rawTop = s === "top" ? r.top - sideOffset : s === "bottom" ? r.bottom + sideOffset : r.top + r.height / 2;
|
|
387
|
+
const rawLeft = s === "left" ? r.left - sideOffset : s === "right" ? r.right + sideOffset : r.left + r.width / 2;
|
|
388
|
+
setCoords({
|
|
389
|
+
top: s === "left" || s === "right" ? clamp(rawTop, ch / 2, vh) : rawTop,
|
|
390
|
+
left: s === "top" || s === "bottom" ? clamp(rawLeft, cw / 2, vw) : rawLeft,
|
|
391
|
+
transform: TRANSFORM_BY_SIDE[s]
|
|
392
|
+
});
|
|
393
|
+
}, [ctx?.open, side, sideOffset, collisionPadding, ctx?.triggerRef]);
|
|
394
|
+
if (!ctx?.open) return null;
|
|
395
|
+
const setRefs = (node) => {
|
|
396
|
+
innerRef.current = node;
|
|
397
|
+
if (typeof ref === "function") ref(node);
|
|
398
|
+
else if (ref) ref.current = node;
|
|
399
|
+
};
|
|
400
|
+
return createPortal(
|
|
401
|
+
/* @__PURE__ */ jsx(
|
|
402
|
+
"div",
|
|
403
|
+
{
|
|
404
|
+
ref: setRefs,
|
|
405
|
+
id: ctx.contentId,
|
|
406
|
+
role: "tooltip",
|
|
407
|
+
className: cn(
|
|
408
|
+
// The kit owns the tooltip's look: semantic tokens only, so it is
|
|
409
|
+
// legible in every app without one of them defining a global class.
|
|
410
|
+
// The `tooltip-content` hook is kept last-but-one so a host stylesheet
|
|
411
|
+
// can still restyle every tooltip in one place (the ARBI app does, with
|
|
412
|
+
// `!important` rules that win over these defaults).
|
|
413
|
+
"pointer-events-none w-max max-w-[300px] break-words rounded-md border border-border bg-popover px-3 py-2 text-sm font-normal text-popover-foreground shadow-lg",
|
|
414
|
+
"tooltip-content",
|
|
415
|
+
className
|
|
416
|
+
),
|
|
417
|
+
style: {
|
|
418
|
+
position: "fixed",
|
|
419
|
+
top: coords?.top ?? -9999,
|
|
420
|
+
left: coords?.left ?? -9999,
|
|
421
|
+
transform: coords?.transform ?? TRANSFORM_BY_SIDE[side],
|
|
422
|
+
opacity: coords ? void 0 : 0,
|
|
423
|
+
zIndex: 9999,
|
|
424
|
+
...style
|
|
425
|
+
},
|
|
426
|
+
...props
|
|
427
|
+
}
|
|
428
|
+
),
|
|
429
|
+
document.body
|
|
430
|
+
);
|
|
431
|
+
}
|
|
432
|
+
);
|
|
433
|
+
TooltipContent.displayName = "TooltipContent";
|
|
434
|
+
function IconToggle({
|
|
435
|
+
icon: Icon2,
|
|
436
|
+
isActive,
|
|
437
|
+
onToggle,
|
|
438
|
+
colors,
|
|
439
|
+
fillWhenActive = false,
|
|
440
|
+
disabled = false,
|
|
441
|
+
disabledTooltip,
|
|
442
|
+
showLabel = false,
|
|
443
|
+
label,
|
|
444
|
+
tooltipActive,
|
|
445
|
+
tooltipInactive,
|
|
446
|
+
tooltipMixed,
|
|
447
|
+
isMixed = false,
|
|
448
|
+
showTooltip = true,
|
|
449
|
+
"data-testid": dataTestId
|
|
450
|
+
}) {
|
|
451
|
+
const handleClick = (e) => {
|
|
452
|
+
e.stopPropagation();
|
|
453
|
+
onToggle(!isActive);
|
|
454
|
+
};
|
|
455
|
+
const { bg: bgColorClass } = colors;
|
|
456
|
+
const tooltipText = disabled ? disabledTooltip : isMixed ? tooltipMixed : isActive ? tooltipActive : tooltipInactive;
|
|
457
|
+
const { text: textColorClass } = colors;
|
|
458
|
+
const button = /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2", children: /* @__PURE__ */ jsxs(
|
|
459
|
+
"button",
|
|
460
|
+
{
|
|
461
|
+
type: "button",
|
|
462
|
+
onClick: handleClick,
|
|
463
|
+
disabled,
|
|
464
|
+
"data-testid": dataTestId,
|
|
465
|
+
"aria-pressed": isMixed ? "mixed" : isActive,
|
|
466
|
+
className: `
|
|
467
|
+
group/toggle relative inline-flex items-center h-4 w-8 rounded-full
|
|
468
|
+
pointer-coarse:after:absolute pointer-coarse:after:left-1/2 pointer-coarse:after:top-1/2 pointer-coarse:after:size-11 pointer-coarse:after:-translate-x-1/2 pointer-coarse:after:-translate-y-1/2 pointer-coarse:after:content-['']
|
|
469
|
+
transition-colors cursor-pointer
|
|
470
|
+
disabled:opacity-50 disabled:cursor-not-allowed
|
|
471
|
+
${isActive ? bgColorClass : isMixed ? "bg-gray-400" : "bg-muted"}
|
|
472
|
+
`,
|
|
473
|
+
children: [
|
|
474
|
+
isActive && !disabled && /* @__PURE__ */ jsx("div", { className: "absolute left-0 w-4 h-4 flex items-center justify-center", children: /* @__PURE__ */ jsx(Minus, { className: "w-2.5 h-2.5 text-white/70 hidden group-hover/toggle:block" }) }),
|
|
475
|
+
!isActive && !disabled && /* @__PURE__ */ jsx("div", { className: "absolute right-0 w-4 h-4 flex items-center justify-center", children: /* @__PURE__ */ jsx(Plus, { className: "w-2.5 h-2.5 text-muted-foreground hidden group-hover/toggle:block" }) }),
|
|
476
|
+
/* @__PURE__ */ jsx(
|
|
477
|
+
"div",
|
|
478
|
+
{
|
|
479
|
+
className: `
|
|
480
|
+
absolute h-4 w-4 rounded-full bg-white shadow-sm
|
|
481
|
+
flex items-center justify-center
|
|
482
|
+
transition-transform duration-200
|
|
483
|
+
${isActive ? "translate-x-4" : "translate-x-0"}
|
|
484
|
+
`,
|
|
485
|
+
children: /* @__PURE__ */ jsx(
|
|
486
|
+
Icon2,
|
|
487
|
+
{
|
|
488
|
+
className: `w-2.5 h-2.5 ${isActive ? textColorClass : "text-muted-foreground"} ${isActive && fillWhenActive ? "fill-current" : ""}`
|
|
489
|
+
}
|
|
490
|
+
)
|
|
491
|
+
}
|
|
492
|
+
)
|
|
493
|
+
]
|
|
494
|
+
}
|
|
495
|
+
) });
|
|
496
|
+
return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-2", children: [
|
|
497
|
+
showLabel && label && /* @__PURE__ */ jsx("span", { className: "font-semibold text-sm text-primary", children: label }),
|
|
498
|
+
tooltipText && showTooltip ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
499
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, onFocusCapture: (e) => e.stopPropagation(), children: button }),
|
|
500
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: tooltipText }) })
|
|
501
|
+
] }) : button
|
|
502
|
+
] });
|
|
503
|
+
}
|
|
504
|
+
var DictateContext = createContext(null);
|
|
505
|
+
function DictateProvider({
|
|
506
|
+
transcribe,
|
|
507
|
+
onError,
|
|
508
|
+
children
|
|
509
|
+
}) {
|
|
510
|
+
return /* @__PURE__ */ jsx(DictateContext.Provider, { value: { transcribe, onError }, children });
|
|
511
|
+
}
|
|
512
|
+
function useDictateContext() {
|
|
513
|
+
return useContext(DictateContext);
|
|
514
|
+
}
|
|
515
|
+
var Avatar = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
516
|
+
AvatarPrimitive.Root,
|
|
517
|
+
{
|
|
518
|
+
ref,
|
|
519
|
+
className: cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className),
|
|
520
|
+
...props
|
|
521
|
+
}
|
|
522
|
+
));
|
|
523
|
+
Avatar.displayName = AvatarPrimitive.Root.displayName;
|
|
524
|
+
var AvatarImage = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
525
|
+
AvatarPrimitive.Image,
|
|
526
|
+
{
|
|
527
|
+
ref,
|
|
528
|
+
className: cn("aspect-square h-full w-full object-cover", className),
|
|
529
|
+
...props
|
|
530
|
+
}
|
|
531
|
+
));
|
|
532
|
+
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
|
|
533
|
+
var AvatarFallback = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
534
|
+
AvatarPrimitive.Fallback,
|
|
535
|
+
{
|
|
536
|
+
ref,
|
|
537
|
+
className: cn(
|
|
538
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted",
|
|
539
|
+
className
|
|
540
|
+
),
|
|
541
|
+
...props
|
|
542
|
+
}
|
|
543
|
+
));
|
|
544
|
+
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
|
|
545
|
+
var badgeVariants = cva(
|
|
546
|
+
"inline-flex items-center rounded-md border px-2.5 py-0.5 text-sm font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
547
|
+
{
|
|
548
|
+
variants: {
|
|
549
|
+
variant: {
|
|
550
|
+
default: "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80",
|
|
551
|
+
accent: "border-transparent bg-ai-accent-soft text-ai-accent",
|
|
552
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
553
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80",
|
|
554
|
+
outline: "text-foreground"
|
|
555
|
+
}
|
|
556
|
+
},
|
|
557
|
+
defaultVariants: {
|
|
558
|
+
variant: "default"
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
);
|
|
562
|
+
function Badge({ className, variant, ...props }) {
|
|
563
|
+
return /* @__PURE__ */ jsx("div", { className: cn(badgeVariants({ variant }), className), ...props });
|
|
564
|
+
}
|
|
565
|
+
var buttonVariants = cva(
|
|
566
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
567
|
+
{
|
|
568
|
+
variants: {
|
|
569
|
+
// One filled primary per view; everything else is tonal, hairline or ghost. No
|
|
570
|
+
// static shadows: separation is tone, and shadows are reserved for floating layers.
|
|
571
|
+
variant: {
|
|
572
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
573
|
+
accent: "bg-ai-accent text-ai-accent-foreground hover:bg-ai-accent/90",
|
|
574
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
575
|
+
outline: "border border-border bg-background hover:bg-muted",
|
|
576
|
+
secondary: "bg-muted text-foreground hover:bg-muted/70",
|
|
577
|
+
ghost: "hover:bg-muted",
|
|
578
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
579
|
+
},
|
|
580
|
+
// Touch screens get a 44px target (coarse pointers only), mouse keeps the compact 36px.
|
|
581
|
+
// `!` so the floor also wins over a caller's compact `h-7` or a container's
|
|
582
|
+
// `[&_button]:h-7` rule: a compact toolbar on a phone must still be tappable.
|
|
583
|
+
size: {
|
|
584
|
+
default: "h-9 px-4 py-2 pointer-coarse:h-11!",
|
|
585
|
+
sm: "h-8 rounded-md px-3 pointer-coarse:h-11! pointer-coarse:min-w-11",
|
|
586
|
+
lg: "h-10 rounded-md px-8 pointer-coarse:h-12!",
|
|
587
|
+
icon: "h-9 w-9 pointer-coarse:h-11! pointer-coarse:w-11!"
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
defaultVariants: {
|
|
591
|
+
variant: "default",
|
|
592
|
+
size: "default"
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
);
|
|
596
|
+
var Button = React2.forwardRef(
|
|
597
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
598
|
+
const Comp = asChild ? Slot : "button";
|
|
599
|
+
return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
|
|
600
|
+
}
|
|
601
|
+
);
|
|
602
|
+
Button.displayName = "Button";
|
|
603
|
+
var HoverCard = HoverCardPrimitive.Root;
|
|
604
|
+
var HoverCardTrigger = HoverCardPrimitive.Trigger;
|
|
605
|
+
var HoverCardContent = React2.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(HoverCardPrimitive.Portal, { children: /* @__PURE__ */ jsx(
|
|
606
|
+
HoverCardPrimitive.Content,
|
|
607
|
+
{
|
|
608
|
+
ref,
|
|
609
|
+
align,
|
|
610
|
+
sideOffset,
|
|
611
|
+
collisionPadding: getCollisionPadding(),
|
|
612
|
+
className: cn(
|
|
613
|
+
"z-50 w-64 max-w-[calc(100vw-1rem)] rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
|
|
614
|
+
className
|
|
615
|
+
),
|
|
616
|
+
...props
|
|
617
|
+
}
|
|
618
|
+
) }));
|
|
619
|
+
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName;
|
|
620
|
+
var cardVariants = cva("rounded-lg bg-card text-card-foreground", {
|
|
621
|
+
variants: {
|
|
622
|
+
variant: {
|
|
623
|
+
flat: "",
|
|
624
|
+
outline: "border",
|
|
625
|
+
elevated: "border shadow-sm"
|
|
626
|
+
}
|
|
627
|
+
},
|
|
628
|
+
defaultVariants: {
|
|
629
|
+
variant: "flat"
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
var Card = React2.forwardRef(
|
|
633
|
+
({ className, variant, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
634
|
+
"div",
|
|
635
|
+
{
|
|
636
|
+
ref,
|
|
637
|
+
"data-slot": "card",
|
|
638
|
+
className: cn(cardVariants({ variant }), className),
|
|
639
|
+
...props
|
|
640
|
+
}
|
|
641
|
+
)
|
|
642
|
+
);
|
|
643
|
+
Card.displayName = "Card";
|
|
644
|
+
var CardHeader = React2.forwardRef(
|
|
645
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
646
|
+
"div",
|
|
647
|
+
{
|
|
648
|
+
ref,
|
|
649
|
+
"data-slot": "card-header",
|
|
650
|
+
className: cn("flex flex-col space-y-1.5 p-6", className),
|
|
651
|
+
...props
|
|
652
|
+
}
|
|
653
|
+
)
|
|
654
|
+
);
|
|
655
|
+
CardHeader.displayName = "CardHeader";
|
|
656
|
+
var CardTitle = React2.forwardRef(
|
|
657
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
658
|
+
"div",
|
|
659
|
+
{
|
|
660
|
+
ref,
|
|
661
|
+
"data-slot": "card-title",
|
|
662
|
+
className: cn("font-semibold leading-none tracking-tight", className),
|
|
663
|
+
...props
|
|
664
|
+
}
|
|
665
|
+
)
|
|
666
|
+
);
|
|
667
|
+
CardTitle.displayName = "CardTitle";
|
|
668
|
+
var CardDescription = React2.forwardRef(
|
|
669
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
670
|
+
"div",
|
|
671
|
+
{
|
|
672
|
+
ref,
|
|
673
|
+
"data-slot": "card-description",
|
|
674
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
675
|
+
...props
|
|
676
|
+
}
|
|
677
|
+
)
|
|
678
|
+
);
|
|
679
|
+
CardDescription.displayName = "CardDescription";
|
|
680
|
+
var CardContent = React2.forwardRef(
|
|
681
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, "data-slot": "card-content", className: cn("p-6 pt-0", className), ...props })
|
|
682
|
+
);
|
|
683
|
+
CardContent.displayName = "CardContent";
|
|
684
|
+
var CardFooter = React2.forwardRef(
|
|
685
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
686
|
+
"div",
|
|
687
|
+
{
|
|
688
|
+
ref,
|
|
689
|
+
"data-slot": "card-footer",
|
|
690
|
+
className: cn("flex items-center p-6 pt-0", className),
|
|
691
|
+
...props
|
|
692
|
+
}
|
|
693
|
+
)
|
|
694
|
+
);
|
|
695
|
+
CardFooter.displayName = "CardFooter";
|
|
696
|
+
|
|
697
|
+
// src/documents/media-error.ts
|
|
698
|
+
function classifyMediaError(err, kind) {
|
|
699
|
+
const label = kind === "camera" ? "Camera" : "Microphone";
|
|
700
|
+
const name = err instanceof DOMException ? err.name : void 0;
|
|
701
|
+
if (name === "NotAllowedError" || name === "SecurityError") {
|
|
702
|
+
return `${label} access is blocked. Allow ${kind} permission in your browser settings to use this feature.`;
|
|
703
|
+
}
|
|
704
|
+
if (name === "NotFoundError" || name === "DevicesNotFoundError") {
|
|
705
|
+
return `No ${kind} found on this device.`;
|
|
706
|
+
}
|
|
707
|
+
if (!navigator.mediaDevices?.getUserMedia) {
|
|
708
|
+
return `${kind === "camera" ? "Camera" : "Voice"} input is not supported in this browser.`;
|
|
709
|
+
}
|
|
710
|
+
return `Could not access the ${kind}. Please try again.`;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// src/documents/useAudioRecorder.ts
|
|
714
|
+
var LEVEL_UPDATE_INTERVAL_MS = 50;
|
|
715
|
+
function useAudioRecorder() {
|
|
716
|
+
const [state, setState] = useState("idle");
|
|
717
|
+
const [level, setLevel] = useState(0);
|
|
718
|
+
const [elapsedMs, setElapsedMs] = useState(0);
|
|
719
|
+
const [blob, setBlob] = useState(null);
|
|
720
|
+
const [mimeType, setMimeType] = useState(null);
|
|
721
|
+
const [error, setError] = useState(null);
|
|
722
|
+
const mediaRecorderRef = useRef(null);
|
|
723
|
+
const chunksRef = useRef([]);
|
|
724
|
+
const streamRef = useRef(null);
|
|
725
|
+
const stateRef = useRef("idle");
|
|
726
|
+
stateRef.current = state;
|
|
727
|
+
const segmentStartRef = useRef(0);
|
|
728
|
+
const accumulatedMsRef = useRef(0);
|
|
729
|
+
const audioContextRef = useRef(null);
|
|
730
|
+
const analyserRef = useRef(null);
|
|
731
|
+
const levelRafRef = useRef(null);
|
|
732
|
+
const stopMeter = useCallback(() => {
|
|
733
|
+
if (levelRafRef.current !== null) cancelAnimationFrame(levelRafRef.current);
|
|
734
|
+
levelRafRef.current = null;
|
|
735
|
+
analyserRef.current = null;
|
|
736
|
+
void audioContextRef.current?.close().catch(() => {
|
|
737
|
+
});
|
|
738
|
+
audioContextRef.current = null;
|
|
739
|
+
}, []);
|
|
740
|
+
const startMeter = useCallback((stream) => {
|
|
741
|
+
const audioContext = new AudioContext();
|
|
742
|
+
const source = audioContext.createMediaStreamSource(stream);
|
|
743
|
+
const analyser = audioContext.createAnalyser();
|
|
744
|
+
analyser.fftSize = 256;
|
|
745
|
+
source.connect(analyser);
|
|
746
|
+
audioContextRef.current = audioContext;
|
|
747
|
+
analyserRef.current = analyser;
|
|
748
|
+
const data = new Uint8Array(analyser.frequencyBinCount);
|
|
749
|
+
let lastUpdate = 0;
|
|
750
|
+
const tick = (t) => {
|
|
751
|
+
const active = analyserRef.current;
|
|
752
|
+
if (!active) return;
|
|
753
|
+
if (t - lastUpdate >= LEVEL_UPDATE_INTERVAL_MS) {
|
|
754
|
+
lastUpdate = t;
|
|
755
|
+
active.getByteTimeDomainData(data);
|
|
756
|
+
let sumSquares = 0;
|
|
757
|
+
for (let i = 0; i < data.length; i++) {
|
|
758
|
+
const centered = (data[i] - 128) / 128;
|
|
759
|
+
sumSquares += centered * centered;
|
|
760
|
+
}
|
|
761
|
+
const rms = Math.sqrt(sumSquares / data.length);
|
|
762
|
+
setLevel(Math.sqrt(Math.min(1, rms * 8)));
|
|
763
|
+
setElapsedMs(accumulatedMsRef.current + (t - segmentStartRef.current));
|
|
764
|
+
}
|
|
765
|
+
levelRafRef.current = requestAnimationFrame(tick);
|
|
766
|
+
};
|
|
767
|
+
levelRafRef.current = requestAnimationFrame(tick);
|
|
768
|
+
}, []);
|
|
769
|
+
const stopTracks = useCallback(() => {
|
|
770
|
+
streamRef.current?.getTracks().forEach((t) => t.stop());
|
|
771
|
+
streamRef.current = null;
|
|
772
|
+
}, []);
|
|
773
|
+
useEffect(
|
|
774
|
+
() => () => {
|
|
775
|
+
stopTracks();
|
|
776
|
+
stopMeter();
|
|
777
|
+
},
|
|
778
|
+
[stopTracks, stopMeter]
|
|
779
|
+
);
|
|
780
|
+
const start = useCallback(async () => {
|
|
781
|
+
if (stateRef.current === "recording" || stateRef.current === "paused") return;
|
|
782
|
+
setError(null);
|
|
783
|
+
try {
|
|
784
|
+
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
785
|
+
streamRef.current = stream;
|
|
786
|
+
const mt = MediaRecorder.isTypeSupported("audio/webm") ? "audio/webm" : "audio/mp4";
|
|
787
|
+
const recorder = new MediaRecorder(stream, { mimeType: mt });
|
|
788
|
+
chunksRef.current = [];
|
|
789
|
+
recorder.ondataavailable = (e) => {
|
|
790
|
+
if (e.data.size > 0) chunksRef.current.push(e.data);
|
|
791
|
+
};
|
|
792
|
+
mediaRecorderRef.current = recorder;
|
|
793
|
+
setMimeType(mt);
|
|
794
|
+
setBlob(null);
|
|
795
|
+
accumulatedMsRef.current = 0;
|
|
796
|
+
segmentStartRef.current = performance.now();
|
|
797
|
+
recorder.start();
|
|
798
|
+
setState("recording");
|
|
799
|
+
startMeter(stream);
|
|
800
|
+
} catch (err) {
|
|
801
|
+
stopTracks();
|
|
802
|
+
setError(classifyMediaError(err, "microphone"));
|
|
803
|
+
}
|
|
804
|
+
}, [startMeter, stopTracks]);
|
|
805
|
+
const pause = useCallback(() => {
|
|
806
|
+
const recorder = mediaRecorderRef.current;
|
|
807
|
+
if (!recorder || recorder.state !== "recording") return;
|
|
808
|
+
recorder.pause();
|
|
809
|
+
accumulatedMsRef.current += performance.now() - segmentStartRef.current;
|
|
810
|
+
stopMeter();
|
|
811
|
+
setLevel(0);
|
|
812
|
+
setState("paused");
|
|
813
|
+
}, [stopMeter]);
|
|
814
|
+
const resume = useCallback(() => {
|
|
815
|
+
const recorder = mediaRecorderRef.current;
|
|
816
|
+
if (!recorder || recorder.state !== "paused") return;
|
|
817
|
+
recorder.resume();
|
|
818
|
+
segmentStartRef.current = performance.now();
|
|
819
|
+
setState("recording");
|
|
820
|
+
if (streamRef.current) startMeter(streamRef.current);
|
|
821
|
+
}, [startMeter]);
|
|
822
|
+
const stop = useCallback(() => {
|
|
823
|
+
const recorder = mediaRecorderRef.current;
|
|
824
|
+
if (!recorder || recorder.state === "inactive") return;
|
|
825
|
+
const finalElapsed = recorder.state === "paused" ? accumulatedMsRef.current : accumulatedMsRef.current + (performance.now() - segmentStartRef.current);
|
|
826
|
+
stopMeter();
|
|
827
|
+
recorder.onstop = () => {
|
|
828
|
+
stopTracks();
|
|
829
|
+
const finalBlob = chunksRef.current.length ? new Blob(chunksRef.current, { type: recorder.mimeType }) : null;
|
|
830
|
+
setBlob(finalBlob);
|
|
831
|
+
setElapsedMs(finalElapsed);
|
|
832
|
+
setLevel(0);
|
|
833
|
+
setState("stopped");
|
|
834
|
+
};
|
|
835
|
+
recorder.stop();
|
|
836
|
+
}, [stopMeter, stopTracks]);
|
|
837
|
+
const reset = useCallback(() => {
|
|
838
|
+
setState("idle");
|
|
839
|
+
setBlob(null);
|
|
840
|
+
setElapsedMs(0);
|
|
841
|
+
setLevel(0);
|
|
842
|
+
setMimeType(null);
|
|
843
|
+
setError(null);
|
|
844
|
+
}, []);
|
|
845
|
+
return { state, level, elapsedMs, blob, mimeType, error, start, pause, resume, stop, reset };
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// src/documents/format-elapsed.ts
|
|
849
|
+
function formatElapsed(ms) {
|
|
850
|
+
const totalSeconds = Math.max(0, Math.floor(ms / 1e3));
|
|
851
|
+
const minutes = Math.floor(totalSeconds / 60);
|
|
852
|
+
const seconds = totalSeconds % 60;
|
|
853
|
+
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
|
|
854
|
+
}
|
|
855
|
+
var BAR_WEIGHTS = [
|
|
856
|
+
0.25,
|
|
857
|
+
0.32,
|
|
858
|
+
0.48,
|
|
859
|
+
0.62,
|
|
860
|
+
0.82,
|
|
861
|
+
0.56,
|
|
862
|
+
0.92,
|
|
863
|
+
0.72,
|
|
864
|
+
1,
|
|
865
|
+
0.86,
|
|
866
|
+
0.62,
|
|
867
|
+
0.96,
|
|
868
|
+
0.76,
|
|
869
|
+
0.5,
|
|
870
|
+
0.84,
|
|
871
|
+
0.66,
|
|
872
|
+
0.42,
|
|
873
|
+
0.56,
|
|
874
|
+
0.36,
|
|
875
|
+
0.28,
|
|
876
|
+
0.22
|
|
877
|
+
];
|
|
878
|
+
var MIN_BAR_PX = 3;
|
|
879
|
+
var MAX_BAR_PX = 40;
|
|
880
|
+
function MicWaveformIndicator({
|
|
881
|
+
level,
|
|
882
|
+
elapsedMs,
|
|
883
|
+
paused = false
|
|
884
|
+
}) {
|
|
885
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", "data-testid": "mic-waveform-indicator", children: [
|
|
886
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
887
|
+
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
888
|
+
!paused && /* @__PURE__ */ jsx("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-red-500 opacity-75" }),
|
|
889
|
+
/* @__PURE__ */ jsx(
|
|
890
|
+
"span",
|
|
891
|
+
{
|
|
892
|
+
className: `relative inline-flex h-2 w-2 rounded-full ${paused ? "bg-muted-foreground" : "bg-red-500"}`
|
|
893
|
+
}
|
|
894
|
+
)
|
|
895
|
+
] }),
|
|
896
|
+
/* @__PURE__ */ jsx(
|
|
897
|
+
"span",
|
|
898
|
+
{
|
|
899
|
+
className: `text-xs font-semibold uppercase tracking-wide ${paused ? "text-muted-foreground" : "text-red-500"}`,
|
|
900
|
+
children: paused ? "Paused" : "Rec"
|
|
901
|
+
}
|
|
902
|
+
),
|
|
903
|
+
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs tabular-nums text-muted-foreground", children: formatElapsed(elapsedMs) })
|
|
904
|
+
] }),
|
|
905
|
+
/* @__PURE__ */ jsx("div", { className: "flex h-10 items-end gap-[3px]", "data-testid": "mic-waveform-indicator-bars", children: BAR_WEIGHTS.map((weight, i) => /* @__PURE__ */ jsx(
|
|
906
|
+
"span",
|
|
907
|
+
{
|
|
908
|
+
className: "w-1 rounded-full bg-secondary transition-[height] duration-75 ease-out",
|
|
909
|
+
style: {
|
|
910
|
+
height: Math.min(MAX_BAR_PX, Math.max(MIN_BAR_PX, level * weight * MAX_BAR_PX))
|
|
911
|
+
}
|
|
912
|
+
},
|
|
913
|
+
i
|
|
914
|
+
)) })
|
|
915
|
+
] });
|
|
916
|
+
}
|
|
917
|
+
function MicRecordingOverlay({
|
|
918
|
+
level,
|
|
919
|
+
elapsedMs,
|
|
920
|
+
paused,
|
|
921
|
+
caption = "Keep button pressed while speaking"
|
|
922
|
+
}) {
|
|
923
|
+
if (typeof document === "undefined") return null;
|
|
924
|
+
return createPortal(
|
|
925
|
+
/* @__PURE__ */ jsx(
|
|
926
|
+
"div",
|
|
927
|
+
{
|
|
928
|
+
"aria-hidden": true,
|
|
929
|
+
className: "pointer-events-none fixed inset-0 z-[2147483647] flex items-center justify-center",
|
|
930
|
+
"data-testid": "mic-recording-overlay",
|
|
931
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex w-72 flex-col items-center gap-3 rounded-2xl bg-background/95 px-6 py-5 shadow-2xl ring-1 ring-border backdrop-blur-sm", children: [
|
|
932
|
+
/* @__PURE__ */ jsx(MicWaveformIndicator, { level, elapsedMs, paused }),
|
|
933
|
+
/* @__PURE__ */ jsx("p", { className: "text-center text-sm font-medium text-muted-foreground", children: caption })
|
|
934
|
+
] })
|
|
935
|
+
}
|
|
936
|
+
),
|
|
937
|
+
document.body
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
var HOLD_THRESHOLD_MS = 350;
|
|
941
|
+
function InlineMicButton({
|
|
942
|
+
focused,
|
|
943
|
+
onTranscript,
|
|
944
|
+
onError,
|
|
945
|
+
transcribe,
|
|
946
|
+
className
|
|
947
|
+
}) {
|
|
948
|
+
const recorder = useAudioRecorder();
|
|
949
|
+
const [isTranscribing, setIsTranscribing] = useState(false);
|
|
950
|
+
const [latched, setLatched] = useState(false);
|
|
951
|
+
const pressedAtRef = useRef(0);
|
|
952
|
+
useEffect(() => {
|
|
953
|
+
if (recorder.error) onError?.(recorder.error);
|
|
954
|
+
}, [recorder.error]);
|
|
955
|
+
useEffect(() => {
|
|
956
|
+
if (recorder.state !== "stopped" || !recorder.blob) return;
|
|
957
|
+
const blob = recorder.blob;
|
|
958
|
+
setIsTranscribing(true);
|
|
959
|
+
transcribe(blob).then((text) => {
|
|
960
|
+
if (text.trim()) onTranscript(text.trim());
|
|
961
|
+
}).catch((err) => {
|
|
962
|
+
onError?.(err instanceof Error ? err.message : "Could not transcribe audio.");
|
|
963
|
+
}).finally(() => {
|
|
964
|
+
setIsTranscribing(false);
|
|
965
|
+
setLatched(false);
|
|
966
|
+
recorder.reset();
|
|
967
|
+
});
|
|
968
|
+
}, [recorder.state, recorder.blob]);
|
|
969
|
+
const isRecording = recorder.state === "recording";
|
|
970
|
+
const isBusy = isTranscribing;
|
|
971
|
+
if (!focused && !isRecording && !isBusy) return null;
|
|
972
|
+
const handlePointerDown = (e) => {
|
|
973
|
+
e.preventDefault();
|
|
974
|
+
if (isRecording) return;
|
|
975
|
+
pressedAtRef.current = Date.now();
|
|
976
|
+
void recorder.start();
|
|
977
|
+
};
|
|
978
|
+
const handlePointerUp = () => {
|
|
979
|
+
if (!isRecording) return;
|
|
980
|
+
if (latched) {
|
|
981
|
+
recorder.stop();
|
|
982
|
+
setLatched(false);
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
const held = Date.now() - pressedAtRef.current;
|
|
986
|
+
if (held >= HOLD_THRESHOLD_MS) {
|
|
987
|
+
recorder.stop();
|
|
988
|
+
} else {
|
|
989
|
+
setLatched(true);
|
|
990
|
+
}
|
|
991
|
+
};
|
|
992
|
+
const handlePointerLeave = () => {
|
|
993
|
+
if (isRecording && !latched) recorder.stop();
|
|
994
|
+
};
|
|
995
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
996
|
+
/* @__PURE__ */ jsx(
|
|
997
|
+
"button",
|
|
998
|
+
{
|
|
999
|
+
type: "button",
|
|
1000
|
+
onPointerDown: handlePointerDown,
|
|
1001
|
+
onPointerUp: handlePointerUp,
|
|
1002
|
+
onPointerLeave: handlePointerLeave,
|
|
1003
|
+
onPointerCancel: handlePointerLeave,
|
|
1004
|
+
disabled: isBusy,
|
|
1005
|
+
title: isRecording ? "Release to stop, or tap again if hands-free" : "Hold, or tap to dictate",
|
|
1006
|
+
"data-testid": "inline-mic-button",
|
|
1007
|
+
className: `inline-flex items-center justify-center rounded-full transition-colors disabled:pointer-events-none ${isRecording ? "h-7 w-7 bg-red-500 text-white shadow-sm hover:bg-red-600" : isBusy ? "h-6 w-6 text-muted-foreground" : "h-6 w-6 text-muted-foreground/50 hover:bg-muted hover:text-muted-foreground"} ${className ?? ""}`,
|
|
1008
|
+
children: isBusy ? /* @__PURE__ */ jsx(Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : isRecording ? /* @__PURE__ */ jsx(Square, { className: "h-3 w-3 fill-current" }) : /* @__PURE__ */ jsx(Mic, { className: "h-3.5 w-3.5" })
|
|
1009
|
+
}
|
|
1010
|
+
),
|
|
1011
|
+
isRecording && /* @__PURE__ */ jsx(
|
|
1012
|
+
MicRecordingOverlay,
|
|
1013
|
+
{
|
|
1014
|
+
level: recorder.level,
|
|
1015
|
+
elapsedMs: recorder.elapsedMs,
|
|
1016
|
+
caption: latched ? "Tap the mic again to stop" : "Release to stop, or keep holding"
|
|
1017
|
+
}
|
|
1018
|
+
)
|
|
1019
|
+
] });
|
|
1020
|
+
}
|
|
1021
|
+
var Input = React2.forwardRef(
|
|
1022
|
+
({ className, type, dictate, onFocus, onBlur, ...props }, forwardedRef) => {
|
|
1023
|
+
const dictateCtx = useDictateContext();
|
|
1024
|
+
const [focused, setFocused] = React2.useState(false);
|
|
1025
|
+
const innerRef = React2.useRef(null);
|
|
1026
|
+
React2.useImperativeHandle(forwardedRef, () => innerRef.current);
|
|
1027
|
+
const showDictate = dictate && !!dictateCtx && !props.disabled && !props.readOnly;
|
|
1028
|
+
const input = /* @__PURE__ */ jsx(
|
|
1029
|
+
"input",
|
|
1030
|
+
{
|
|
1031
|
+
type,
|
|
1032
|
+
"data-slot": "input",
|
|
1033
|
+
className: cn(
|
|
1034
|
+
"flex h-9 pointer-coarse:h-11 w-full rounded-md border border-input bg-background px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground/60 focus-visible:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
1035
|
+
showDictate && "pr-9",
|
|
1036
|
+
className
|
|
1037
|
+
),
|
|
1038
|
+
ref: innerRef,
|
|
1039
|
+
onFocus: (e) => {
|
|
1040
|
+
setFocused(true);
|
|
1041
|
+
onFocus?.(e);
|
|
1042
|
+
},
|
|
1043
|
+
onBlur: (e) => {
|
|
1044
|
+
setFocused(false);
|
|
1045
|
+
onBlur?.(e);
|
|
1046
|
+
},
|
|
1047
|
+
...props
|
|
1048
|
+
}
|
|
1049
|
+
);
|
|
1050
|
+
if (!showDictate) return input;
|
|
1051
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
|
|
1052
|
+
input,
|
|
1053
|
+
/* @__PURE__ */ jsx(
|
|
1054
|
+
InlineMicButton,
|
|
1055
|
+
{
|
|
1056
|
+
focused,
|
|
1057
|
+
transcribe: dictateCtx.transcribe,
|
|
1058
|
+
onError: dictateCtx.onError,
|
|
1059
|
+
className: "absolute right-1.5 top-1/2 -translate-y-1/2",
|
|
1060
|
+
onTranscript: (text) => {
|
|
1061
|
+
const el = innerRef.current;
|
|
1062
|
+
if (!el) return;
|
|
1063
|
+
const next = el.value ? `${el.value} ${text}` : text;
|
|
1064
|
+
const setter = Object.getOwnPropertyDescriptor(
|
|
1065
|
+
window.HTMLInputElement.prototype,
|
|
1066
|
+
"value"
|
|
1067
|
+
)?.set;
|
|
1068
|
+
setter?.call(el, next);
|
|
1069
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
)
|
|
1073
|
+
] });
|
|
1074
|
+
}
|
|
1075
|
+
);
|
|
1076
|
+
Input.displayName = "Input";
|
|
1077
|
+
var Label = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1078
|
+
"label",
|
|
1079
|
+
{
|
|
1080
|
+
ref,
|
|
1081
|
+
className: `text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 ${className || ""}`,
|
|
1082
|
+
...props
|
|
1083
|
+
}
|
|
1084
|
+
));
|
|
1085
|
+
Label.displayName = "Label";
|
|
1086
|
+
var Separator = React2.forwardRef(({ className, orientation = "horizontal", decorative = true, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1087
|
+
SeparatorPrimitive.Root,
|
|
1088
|
+
{
|
|
1089
|
+
ref,
|
|
1090
|
+
decorative,
|
|
1091
|
+
orientation,
|
|
1092
|
+
className: cn(
|
|
1093
|
+
"shrink-0 bg-border",
|
|
1094
|
+
orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
|
|
1095
|
+
className
|
|
1096
|
+
),
|
|
1097
|
+
...props
|
|
1098
|
+
}
|
|
1099
|
+
));
|
|
1100
|
+
Separator.displayName = SeparatorPrimitive.Root.displayName;
|
|
1101
|
+
var Textarea = React2.forwardRef(
|
|
1102
|
+
({ className, dictate, onFocus, onBlur, ...props }, forwardedRef) => {
|
|
1103
|
+
const dictateCtx = useDictateContext();
|
|
1104
|
+
const [focused, setFocused] = React2.useState(false);
|
|
1105
|
+
const innerRef = React2.useRef(null);
|
|
1106
|
+
React2.useImperativeHandle(forwardedRef, () => innerRef.current);
|
|
1107
|
+
const showDictate = dictate && !!dictateCtx && !props.disabled && !props.readOnly;
|
|
1108
|
+
const textarea = /* @__PURE__ */ jsx(
|
|
1109
|
+
"textarea",
|
|
1110
|
+
{
|
|
1111
|
+
className: cn(
|
|
1112
|
+
"flex min-h-[60px] w-full rounded-md border border-input bg-background px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground/60 focus-visible:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
1113
|
+
showDictate && "pr-9",
|
|
1114
|
+
className
|
|
1115
|
+
),
|
|
1116
|
+
ref: innerRef,
|
|
1117
|
+
onFocus: (e) => {
|
|
1118
|
+
setFocused(true);
|
|
1119
|
+
onFocus?.(e);
|
|
1120
|
+
},
|
|
1121
|
+
onBlur: (e) => {
|
|
1122
|
+
setFocused(false);
|
|
1123
|
+
onBlur?.(e);
|
|
1124
|
+
},
|
|
1125
|
+
...props
|
|
1126
|
+
}
|
|
1127
|
+
);
|
|
1128
|
+
if (!showDictate) return textarea;
|
|
1129
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
|
|
1130
|
+
textarea,
|
|
1131
|
+
/* @__PURE__ */ jsx(
|
|
1132
|
+
InlineMicButton,
|
|
1133
|
+
{
|
|
1134
|
+
focused,
|
|
1135
|
+
transcribe: dictateCtx.transcribe,
|
|
1136
|
+
onError: dictateCtx.onError,
|
|
1137
|
+
className: "absolute right-1.5 top-1.5",
|
|
1138
|
+
onTranscript: (text) => {
|
|
1139
|
+
const el = innerRef.current;
|
|
1140
|
+
if (!el) return;
|
|
1141
|
+
const next = el.value ? `${el.value} ${text}` : text;
|
|
1142
|
+
const setter = Object.getOwnPropertyDescriptor(
|
|
1143
|
+
window.HTMLTextAreaElement.prototype,
|
|
1144
|
+
"value"
|
|
1145
|
+
)?.set;
|
|
1146
|
+
setter?.call(el, next);
|
|
1147
|
+
el.dispatchEvent(new Event("input", { bubbles: true }));
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
)
|
|
1151
|
+
] });
|
|
1152
|
+
}
|
|
1153
|
+
);
|
|
1154
|
+
Textarea.displayName = "Textarea";
|
|
1155
|
+
var Collapsible = CollapsiblePrimitive.Root;
|
|
1156
|
+
var CollapsibleTrigger2 = CollapsiblePrimitive.CollapsibleTrigger;
|
|
1157
|
+
var CollapsibleContent2 = CollapsiblePrimitive.CollapsibleContent;
|
|
1158
|
+
var Progress = React2.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1159
|
+
ProgressPrimitive.Root,
|
|
1160
|
+
{
|
|
1161
|
+
ref,
|
|
1162
|
+
className: cn("relative h-2 w-full overflow-hidden rounded-full bg-primary/20", className),
|
|
1163
|
+
...props,
|
|
1164
|
+
children: /* @__PURE__ */ jsx(
|
|
1165
|
+
ProgressPrimitive.Indicator,
|
|
1166
|
+
{
|
|
1167
|
+
className: "h-full w-full flex-1 bg-primary transition-all",
|
|
1168
|
+
style: { transform: `translateX(-${100 - (value || 0)}%)` }
|
|
1169
|
+
}
|
|
1170
|
+
)
|
|
1171
|
+
}
|
|
1172
|
+
));
|
|
1173
|
+
Progress.displayName = ProgressPrimitive.Root.displayName;
|
|
1174
|
+
var RadioGroup = React2.forwardRef(({ className, ...props }, ref) => {
|
|
1175
|
+
return /* @__PURE__ */ jsx(RadioGroupPrimitive.Root, { className: cn("grid gap-2", className), ...props, ref });
|
|
1176
|
+
});
|
|
1177
|
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
1178
|
+
var RadioGroupItem = React2.forwardRef(({ className, ...props }, ref) => {
|
|
1179
|
+
return /* @__PURE__ */ jsx(
|
|
1180
|
+
RadioGroupPrimitive.Item,
|
|
1181
|
+
{
|
|
1182
|
+
ref,
|
|
1183
|
+
className: cn(
|
|
1184
|
+
"relative aspect-square h-4 w-4 rounded-full border border-primary text-primary after:absolute after:left-1/2 after:top-1/2 after:hidden after:size-11 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] pointer-coarse:after:block focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
|
|
1185
|
+
className
|
|
1186
|
+
),
|
|
1187
|
+
...props,
|
|
1188
|
+
children: /* @__PURE__ */ jsx(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx(Circle, { className: "h-2.5 w-2.5 fill-current text-current" }) })
|
|
1189
|
+
}
|
|
1190
|
+
);
|
|
1191
|
+
});
|
|
1192
|
+
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
1193
|
+
var Checkbox = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1194
|
+
CheckboxPrimitive.Root,
|
|
1195
|
+
{
|
|
1196
|
+
ref,
|
|
1197
|
+
className: cn(
|
|
1198
|
+
"peer relative h-4 w-4 shrink-0 rounded-sm border border-muted-foreground/50 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground after:absolute after:left-1/2 after:top-1/2 after:hidden after:size-11 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] pointer-coarse:after:block",
|
|
1199
|
+
className
|
|
1200
|
+
),
|
|
1201
|
+
...props,
|
|
1202
|
+
children: /* @__PURE__ */ jsx(CheckboxPrimitive.Indicator, { className: cn("flex items-center justify-center text-current"), children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) })
|
|
1203
|
+
}
|
|
1204
|
+
));
|
|
1205
|
+
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
1206
|
+
var Switch = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1207
|
+
SwitchPrimitives.Root,
|
|
1208
|
+
{
|
|
1209
|
+
className: cn(
|
|
1210
|
+
"peer relative inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-muted-foreground/45 after:absolute after:left-1/2 after:top-1/2 after:hidden after:size-11 after:-translate-x-1/2 after:-translate-y-1/2 after:content-[''] pointer-coarse:after:block",
|
|
1211
|
+
className
|
|
1212
|
+
),
|
|
1213
|
+
...props,
|
|
1214
|
+
ref,
|
|
1215
|
+
children: /* @__PURE__ */ jsx(
|
|
1216
|
+
SwitchPrimitives.Thumb,
|
|
1217
|
+
{
|
|
1218
|
+
className: cn(
|
|
1219
|
+
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
|
|
1220
|
+
)
|
|
1221
|
+
}
|
|
1222
|
+
)
|
|
1223
|
+
}
|
|
1224
|
+
));
|
|
1225
|
+
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
1226
|
+
var Tabs = TabsPrimitive.Root;
|
|
1227
|
+
var TabsList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1228
|
+
TabsPrimitive.List,
|
|
1229
|
+
{
|
|
1230
|
+
ref,
|
|
1231
|
+
className: cn(
|
|
1232
|
+
"inline-flex h-9 pointer-coarse:h-auto items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
|
1233
|
+
className
|
|
1234
|
+
),
|
|
1235
|
+
...props
|
|
1236
|
+
}
|
|
1237
|
+
));
|
|
1238
|
+
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
1239
|
+
var TabsTrigger = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1240
|
+
TabsPrimitive.Trigger,
|
|
1241
|
+
{
|
|
1242
|
+
ref,
|
|
1243
|
+
className: cn(
|
|
1244
|
+
"inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm pointer-coarse:min-h-11 font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow",
|
|
1245
|
+
className
|
|
1246
|
+
),
|
|
1247
|
+
...props
|
|
1248
|
+
}
|
|
1249
|
+
));
|
|
1250
|
+
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
1251
|
+
var TabsContent = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1252
|
+
TabsPrimitive.Content,
|
|
1253
|
+
{
|
|
1254
|
+
ref,
|
|
1255
|
+
className: cn(
|
|
1256
|
+
"mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
|
|
1257
|
+
className
|
|
1258
|
+
),
|
|
1259
|
+
...props
|
|
1260
|
+
}
|
|
1261
|
+
));
|
|
1262
|
+
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
1263
|
+
var Table = React2.forwardRef(
|
|
1264
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { className: "relative w-full overflow-auto", children: /* @__PURE__ */ jsx("table", { ref, className: cn("w-full caption-bottom text-sm", className), ...props }) })
|
|
1265
|
+
);
|
|
1266
|
+
Table.displayName = "Table";
|
|
1267
|
+
var TableHeader = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
|
|
1268
|
+
TableHeader.displayName = "TableHeader";
|
|
1269
|
+
var TableBody = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("tbody", { ref, className: cn("[&_tr:last-child]:border-0", className), ...props }));
|
|
1270
|
+
TableBody.displayName = "TableBody";
|
|
1271
|
+
var TableFooter = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1272
|
+
"tfoot",
|
|
1273
|
+
{
|
|
1274
|
+
ref,
|
|
1275
|
+
className: cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className),
|
|
1276
|
+
...props
|
|
1277
|
+
}
|
|
1278
|
+
));
|
|
1279
|
+
TableFooter.displayName = "TableFooter";
|
|
1280
|
+
var TableRow = React2.forwardRef(
|
|
1281
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1282
|
+
"tr",
|
|
1283
|
+
{
|
|
1284
|
+
ref,
|
|
1285
|
+
className: cn(
|
|
1286
|
+
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
|
1287
|
+
className
|
|
1288
|
+
),
|
|
1289
|
+
...props
|
|
1290
|
+
}
|
|
1291
|
+
)
|
|
1292
|
+
);
|
|
1293
|
+
TableRow.displayName = "TableRow";
|
|
1294
|
+
var TableHead = React2.forwardRef(
|
|
1295
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1296
|
+
"th",
|
|
1297
|
+
{
|
|
1298
|
+
ref,
|
|
1299
|
+
className: cn(
|
|
1300
|
+
"h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
1301
|
+
className
|
|
1302
|
+
),
|
|
1303
|
+
...props
|
|
1304
|
+
}
|
|
1305
|
+
)
|
|
1306
|
+
);
|
|
1307
|
+
TableHead.displayName = "TableHead";
|
|
1308
|
+
var TableCell = React2.forwardRef(
|
|
1309
|
+
({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1310
|
+
"td",
|
|
1311
|
+
{
|
|
1312
|
+
ref,
|
|
1313
|
+
className: cn(
|
|
1314
|
+
"p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
1315
|
+
className
|
|
1316
|
+
),
|
|
1317
|
+
...props
|
|
1318
|
+
}
|
|
1319
|
+
)
|
|
1320
|
+
);
|
|
1321
|
+
TableCell.displayName = "TableCell";
|
|
1322
|
+
var TableCaption = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("caption", { ref, className: cn("mt-4 text-sm text-muted-foreground", className), ...props }));
|
|
1323
|
+
TableCaption.displayName = "TableCaption";
|
|
1324
|
+
var Slider = React2.forwardRef(
|
|
1325
|
+
({ className, rangeClassName, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1326
|
+
SliderPrimitive.Root,
|
|
1327
|
+
{
|
|
1328
|
+
ref,
|
|
1329
|
+
className: cn("relative flex w-full touch-none select-none items-center", className),
|
|
1330
|
+
...props,
|
|
1331
|
+
children: [
|
|
1332
|
+
/* @__PURE__ */ jsx(SliderPrimitive.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20", children: /* @__PURE__ */ jsx(SliderPrimitive.Range, { className: cn("absolute h-full bg-primary", rangeClassName) }) }),
|
|
1333
|
+
/* @__PURE__ */ jsx(SliderPrimitive.Thumb, { className: "block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" })
|
|
1334
|
+
]
|
|
1335
|
+
}
|
|
1336
|
+
)
|
|
1337
|
+
);
|
|
1338
|
+
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
1339
|
+
var toggleVariants = cva(
|
|
1340
|
+
"inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
1341
|
+
{
|
|
1342
|
+
variants: {
|
|
1343
|
+
variant: {
|
|
1344
|
+
default: "bg-transparent",
|
|
1345
|
+
outline: "border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground"
|
|
1346
|
+
},
|
|
1347
|
+
size: {
|
|
1348
|
+
default: "h-9 px-2 min-w-9 pointer-coarse:h-11 pointer-coarse:min-w-11",
|
|
1349
|
+
sm: "h-8 px-1.5 min-w-8 pointer-coarse:h-11 pointer-coarse:min-w-11",
|
|
1350
|
+
lg: "h-10 px-2.5 min-w-10 pointer-coarse:h-11 pointer-coarse:min-w-11"
|
|
1351
|
+
}
|
|
1352
|
+
},
|
|
1353
|
+
defaultVariants: {
|
|
1354
|
+
variant: "default",
|
|
1355
|
+
size: "default"
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
);
|
|
1359
|
+
var Toggle = React2.forwardRef(({ className, variant, size, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1360
|
+
TogglePrimitive.Root,
|
|
1361
|
+
{
|
|
1362
|
+
ref,
|
|
1363
|
+
className: cn(toggleVariants({ variant, size, className })),
|
|
1364
|
+
...props
|
|
1365
|
+
}
|
|
1366
|
+
));
|
|
1367
|
+
Toggle.displayName = TogglePrimitive.Root.displayName;
|
|
1368
|
+
var ToggleGroupContext = React2.createContext({
|
|
1369
|
+
size: "default",
|
|
1370
|
+
variant: "default"
|
|
1371
|
+
});
|
|
1372
|
+
var ToggleGroup = React2.forwardRef(({ className, variant, size, children, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1373
|
+
ToggleGroupPrimitive.Root,
|
|
1374
|
+
{
|
|
1375
|
+
ref,
|
|
1376
|
+
className: cn("flex items-center justify-center gap-1", className),
|
|
1377
|
+
...props,
|
|
1378
|
+
children: /* @__PURE__ */ jsx(ToggleGroupContext.Provider, { value: { variant, size }, children })
|
|
1379
|
+
}
|
|
1380
|
+
));
|
|
1381
|
+
ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName;
|
|
1382
|
+
var ToggleGroupItem = React2.forwardRef(({ className, children, variant, size, ...props }, ref) => {
|
|
1383
|
+
const context = React2.useContext(ToggleGroupContext);
|
|
1384
|
+
return /* @__PURE__ */ jsx(
|
|
1385
|
+
ToggleGroupPrimitive.Item,
|
|
1386
|
+
{
|
|
1387
|
+
ref,
|
|
1388
|
+
className: cn(
|
|
1389
|
+
toggleVariants({
|
|
1390
|
+
variant: context.variant || variant,
|
|
1391
|
+
size: context.size || size
|
|
1392
|
+
}),
|
|
1393
|
+
className
|
|
1394
|
+
),
|
|
1395
|
+
...props,
|
|
1396
|
+
children
|
|
1397
|
+
}
|
|
1398
|
+
);
|
|
1399
|
+
});
|
|
1400
|
+
ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName;
|
|
1401
|
+
|
|
1402
|
+
// src/lib/toast-interaction.ts
|
|
1403
|
+
function isToastInteraction(event) {
|
|
1404
|
+
const original = event.detail?.originalEvent;
|
|
1405
|
+
const target = original?.target ?? event.target;
|
|
1406
|
+
return target instanceof Element && target.closest("[data-sonner-toaster]") !== null;
|
|
1407
|
+
}
|
|
1408
|
+
var Dialog = DialogPrimitive.Root;
|
|
1409
|
+
var DialogTrigger = DialogPrimitive.Trigger;
|
|
1410
|
+
var DialogPortal = DialogPrimitive.Portal;
|
|
1411
|
+
var DialogClose = DialogPrimitive.Close;
|
|
1412
|
+
var DialogOverlay = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1413
|
+
DialogPrimitive.Overlay,
|
|
1414
|
+
{
|
|
1415
|
+
ref,
|
|
1416
|
+
className: cn(
|
|
1417
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
1418
|
+
className
|
|
1419
|
+
),
|
|
1420
|
+
...props
|
|
1421
|
+
}
|
|
1422
|
+
));
|
|
1423
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
1424
|
+
var PHONE_PRESENTATION = {
|
|
1425
|
+
center: "",
|
|
1426
|
+
sheet: "max-sm:top-auto max-sm:bottom-0 max-sm:left-0 max-sm:w-full max-sm:max-w-full max-sm:border-x-0 max-sm:border-b-0 max-sm:translate-x-0 max-sm:translate-y-0 max-sm:rounded-b-none max-sm:rounded-t-xl max-sm:pb-[max(1.5rem,env(safe-area-inset-bottom))] max-sm:max-h-[calc(100dvh-env(safe-area-inset-top,0px)-2.5rem)] max-sm:data-[state=open]:slide-in-from-bottom-10 max-sm:data-[state=open]:zoom-in-100 max-sm:data-[state=closed]:zoom-out-100",
|
|
1427
|
+
full: "max-sm:top-auto max-sm:bottom-0 max-sm:left-0 max-sm:border-x-0 max-sm:border-b-0 max-sm:h-[calc(100dvh-env(safe-area-inset-top,0px)-1rem)] max-sm:w-full max-sm:max-w-full max-sm:translate-x-0 max-sm:translate-y-0 max-sm:rounded-b-none max-sm:rounded-t-xl max-sm:pb-[max(1.5rem,env(safe-area-inset-bottom))] max-sm:max-h-none max-sm:data-[state=open]:slide-in-from-bottom-10 max-sm:data-[state=open]:zoom-in-100 max-sm:data-[state=closed]:zoom-out-100"
|
|
1428
|
+
};
|
|
1429
|
+
var DialogContent = React2.forwardRef(
|
|
1430
|
+
({ className, children, hideCloseButton, presentation = "center", onInteractOutside, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
1431
|
+
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
1432
|
+
/* @__PURE__ */ jsxs(
|
|
1433
|
+
DialogPrimitive.Content,
|
|
1434
|
+
{
|
|
1435
|
+
ref,
|
|
1436
|
+
"data-slot": "dialog-content",
|
|
1437
|
+
"data-presentation": presentation,
|
|
1438
|
+
onInteractOutside: (event) => {
|
|
1439
|
+
if (isToastInteraction(event)) event.preventDefault();
|
|
1440
|
+
onInteractOutside?.(event);
|
|
1441
|
+
},
|
|
1442
|
+
className: cn(
|
|
1443
|
+
// Always inside the viewport: width and height are capped by the DYNAMIC viewport (mobile
|
|
1444
|
+
// browser chrome) and the notch / home-indicator insets; the content scrolls inside.
|
|
1445
|
+
"fixed left-[50%] top-[50%] z-50 grid w-[calc(100%-2rem-env(safe-area-inset-left,0px)-env(safe-area-inset-right,0px))] max-w-lg max-h-[calc(min(100dvh,100svh,100vh)-2rem-env(safe-area-inset-top,0px)-env(safe-area-inset-bottom,0px))] translate-x-[-50%] translate-y-[-50%] will-change-transform grid-cols-[minmax(0,1fr)] gap-4 overflow-x-hidden overflow-y-auto overscroll-contain border bg-background p-6 shadow-xl duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 rounded-md",
|
|
1446
|
+
PHONE_PRESENTATION[presentation],
|
|
1447
|
+
className
|
|
1448
|
+
),
|
|
1449
|
+
...props,
|
|
1450
|
+
children: [
|
|
1451
|
+
children,
|
|
1452
|
+
!hideCloseButton && /* @__PURE__ */ jsxs(
|
|
1453
|
+
DialogPrimitive.Close,
|
|
1454
|
+
{
|
|
1455
|
+
className: "fixed right-4 top-4 z-20 inline-flex items-center justify-center rounded-sm pointer-coarse:right-2 pointer-coarse:top-2 pointer-coarse:size-11 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",
|
|
1456
|
+
"data-testid": "dialog-close-button",
|
|
1457
|
+
children: [
|
|
1458
|
+
/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
|
|
1459
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close dialog" })
|
|
1460
|
+
]
|
|
1461
|
+
}
|
|
1462
|
+
)
|
|
1463
|
+
]
|
|
1464
|
+
}
|
|
1465
|
+
)
|
|
1466
|
+
] })
|
|
1467
|
+
);
|
|
1468
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
1469
|
+
var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 flex-col space-y-1.5 pr-8 text-left", className), ...props });
|
|
1470
|
+
DialogHeader.displayName = "DialogHeader";
|
|
1471
|
+
var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ jsx(
|
|
1472
|
+
"div",
|
|
1473
|
+
{
|
|
1474
|
+
className: cn(
|
|
1475
|
+
// Sticks to the bottom of a scrolling dialog so the actions stay reachable.
|
|
1476
|
+
"sticky bottom-0 z-10 -mx-6 -mb-6 flex flex-col-reverse gap-2 bg-background px-6 pb-6 pt-3 sm:flex-row sm:justify-end",
|
|
1477
|
+
className
|
|
1478
|
+
),
|
|
1479
|
+
...props
|
|
1480
|
+
}
|
|
1481
|
+
);
|
|
1482
|
+
DialogFooter.displayName = "DialogFooter";
|
|
1483
|
+
var DialogTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1484
|
+
DialogPrimitive.Title,
|
|
1485
|
+
{
|
|
1486
|
+
ref,
|
|
1487
|
+
className: cn("break-words text-lg font-semibold leading-tight tracking-tight", className),
|
|
1488
|
+
...props
|
|
1489
|
+
}
|
|
1490
|
+
));
|
|
1491
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
1492
|
+
var DialogDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1493
|
+
DialogPrimitive.Description,
|
|
1494
|
+
{
|
|
1495
|
+
ref,
|
|
1496
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
1497
|
+
...props
|
|
1498
|
+
}
|
|
1499
|
+
));
|
|
1500
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
1501
|
+
var Popover = PopoverPrimitive.Root;
|
|
1502
|
+
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
1503
|
+
var PopoverAnchor = PopoverPrimitive.Anchor;
|
|
1504
|
+
var PopoverContent = React2.forwardRef(({ className, align = "center", sideOffset = 4, container, ...props }, ref) => /* @__PURE__ */ jsx(PopoverPrimitive.Portal, { container: container ?? void 0, children: /* @__PURE__ */ jsx(
|
|
1505
|
+
PopoverPrimitive.Content,
|
|
1506
|
+
{
|
|
1507
|
+
ref,
|
|
1508
|
+
align,
|
|
1509
|
+
sideOffset,
|
|
1510
|
+
collisionPadding: getCollisionPadding(),
|
|
1511
|
+
className: cn(
|
|
1512
|
+
"z-50 w-72 max-w-[calc(100vw-1rem)] max-h-[var(--radix-popover-content-available-height)] overflow-y-auto overscroll-contain rounded-md border bg-popover p-4 text-popover-foreground shadow-lg outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-popover-content-transform-origin]",
|
|
1513
|
+
className
|
|
1514
|
+
),
|
|
1515
|
+
...props
|
|
1516
|
+
}
|
|
1517
|
+
) }));
|
|
1518
|
+
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
1519
|
+
var FINE_OPEN_DELAY = 350;
|
|
1520
|
+
var FINE_CLOSE_DELAY = 180;
|
|
1521
|
+
function isFocusVisible(el) {
|
|
1522
|
+
try {
|
|
1523
|
+
return el.matches(":focus-visible");
|
|
1524
|
+
} catch {
|
|
1525
|
+
return true;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
function isCoarse(pointerType) {
|
|
1529
|
+
if (pointerType === "touch" || pointerType === "pen") return true;
|
|
1530
|
+
if (pointerType === "mouse") return false;
|
|
1531
|
+
return typeof window !== "undefined" && !!window.matchMedia?.("(pointer: coarse)").matches;
|
|
1532
|
+
}
|
|
1533
|
+
function MarkMenu({
|
|
1534
|
+
as = "span",
|
|
1535
|
+
href,
|
|
1536
|
+
items,
|
|
1537
|
+
preview,
|
|
1538
|
+
menuLabel,
|
|
1539
|
+
shouldClickRunPrimary = true,
|
|
1540
|
+
openDelay = FINE_OPEN_DELAY,
|
|
1541
|
+
closeDelay = FINE_CLOSE_DELAY,
|
|
1542
|
+
testId,
|
|
1543
|
+
menuTestId,
|
|
1544
|
+
triggerRef: externalRef,
|
|
1545
|
+
className,
|
|
1546
|
+
children,
|
|
1547
|
+
onPointerDown,
|
|
1548
|
+
onPointerEnter,
|
|
1549
|
+
onPointerLeave,
|
|
1550
|
+
onFocus,
|
|
1551
|
+
onBlur,
|
|
1552
|
+
onKeyDown,
|
|
1553
|
+
...rest
|
|
1554
|
+
}) {
|
|
1555
|
+
const [open, setOpen] = useState(false);
|
|
1556
|
+
const [side, setSide] = useState("bottom");
|
|
1557
|
+
const menuId = useId();
|
|
1558
|
+
const triggerRef = useRef(null);
|
|
1559
|
+
const contentRef = useRef(null);
|
|
1560
|
+
const timer = useRef(null);
|
|
1561
|
+
const mode = useRef("hover");
|
|
1562
|
+
const lastPointer = useRef("mouse");
|
|
1563
|
+
const focusFirstOnOpen = useRef(false);
|
|
1564
|
+
const isEmpty = items.length === 0 && !preview;
|
|
1565
|
+
const ordered = [...items].sort((a, b) => Number(!!b.primary) - Number(!!a.primary));
|
|
1566
|
+
const primary = ordered[0];
|
|
1567
|
+
const clearTimer = () => {
|
|
1568
|
+
if (timer.current) clearTimeout(timer.current);
|
|
1569
|
+
timer.current = null;
|
|
1570
|
+
};
|
|
1571
|
+
useEffect(() => clearTimer, []);
|
|
1572
|
+
const rows = () => Array.from(contentRef.current?.querySelectorAll('[role="menuitem"]') ?? []);
|
|
1573
|
+
const firstItem = () => rows()[0];
|
|
1574
|
+
const openWith = (next, focusFirst = false) => {
|
|
1575
|
+
clearTimer();
|
|
1576
|
+
mode.current = next;
|
|
1577
|
+
focusFirstOnOpen.current = focusFirst;
|
|
1578
|
+
setSide(next === "press" && isCoarse(lastPointer.current) ? "top" : "bottom");
|
|
1579
|
+
setOpen(true);
|
|
1580
|
+
if (focusFirst) {
|
|
1581
|
+
requestAnimationFrame(() => firstItem()?.focus());
|
|
1582
|
+
}
|
|
1583
|
+
};
|
|
1584
|
+
const close = (returnFocus = false) => {
|
|
1585
|
+
clearTimer();
|
|
1586
|
+
setOpen(false);
|
|
1587
|
+
if (returnFocus) triggerRef.current?.focus({ preventScroll: true });
|
|
1588
|
+
};
|
|
1589
|
+
const schedule = (action, delay) => {
|
|
1590
|
+
clearTimer();
|
|
1591
|
+
timer.current = setTimeout(action, delay);
|
|
1592
|
+
};
|
|
1593
|
+
const handlePointerDown = (e) => {
|
|
1594
|
+
lastPointer.current = e.pointerType;
|
|
1595
|
+
onPointerDown?.(e);
|
|
1596
|
+
};
|
|
1597
|
+
const handlePointerEnter = (e) => {
|
|
1598
|
+
onPointerEnter?.(e);
|
|
1599
|
+
if (isCoarse(e.pointerType) || isEmpty) return;
|
|
1600
|
+
lastPointer.current = e.pointerType;
|
|
1601
|
+
schedule(() => openWith("hover"), openDelay);
|
|
1602
|
+
};
|
|
1603
|
+
const handlePointerLeave = (e) => {
|
|
1604
|
+
onPointerLeave?.(e);
|
|
1605
|
+
if (isCoarse(e.pointerType)) return;
|
|
1606
|
+
if (!open) return clearTimer();
|
|
1607
|
+
if (mode.current === "hover") schedule(() => close(), closeDelay);
|
|
1608
|
+
};
|
|
1609
|
+
const handleFocus = (e) => {
|
|
1610
|
+
onFocus?.(e);
|
|
1611
|
+
if (isEmpty) return;
|
|
1612
|
+
if (isFocusVisible(e.currentTarget)) schedule(() => openWith("focus"), openDelay);
|
|
1613
|
+
};
|
|
1614
|
+
const handleBlur = (e) => {
|
|
1615
|
+
onBlur?.(e);
|
|
1616
|
+
const next = e.relatedTarget;
|
|
1617
|
+
if (next && contentRef.current?.contains(next)) return;
|
|
1618
|
+
if (mode.current === "focus" || mode.current === "key") schedule(() => close(), closeDelay);
|
|
1619
|
+
else clearTimer();
|
|
1620
|
+
};
|
|
1621
|
+
const handleKeyDown = (e) => {
|
|
1622
|
+
onKeyDown?.(e);
|
|
1623
|
+
lastPointer.current = "keyboard";
|
|
1624
|
+
if (e.defaultPrevented || isEmpty) return;
|
|
1625
|
+
if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
|
|
1626
|
+
e.preventDefault();
|
|
1627
|
+
openWith("key", true);
|
|
1628
|
+
} else if (e.key === "Escape" && open) {
|
|
1629
|
+
e.preventDefault();
|
|
1630
|
+
e.stopPropagation();
|
|
1631
|
+
close(true);
|
|
1632
|
+
}
|
|
1633
|
+
};
|
|
1634
|
+
const handleClick = (e) => {
|
|
1635
|
+
if (isEmpty) return;
|
|
1636
|
+
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
|
|
1637
|
+
if (e.detail === 0 && lastPointer.current === "keyboard") {
|
|
1638
|
+
e.preventDefault();
|
|
1639
|
+
return;
|
|
1640
|
+
}
|
|
1641
|
+
if (isCoarse(lastPointer.current)) {
|
|
1642
|
+
e.preventDefault();
|
|
1643
|
+
if (open) close();
|
|
1644
|
+
else openWith("press");
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
if (shouldClickRunPrimary && primary?.onSelect) {
|
|
1648
|
+
e.preventDefault();
|
|
1649
|
+
close();
|
|
1650
|
+
primary.onSelect();
|
|
1651
|
+
}
|
|
1652
|
+
};
|
|
1653
|
+
const handleMenuKeyDown = (e) => {
|
|
1654
|
+
const list = rows();
|
|
1655
|
+
const index = list.indexOf(document.activeElement);
|
|
1656
|
+
let target;
|
|
1657
|
+
if (e.key === "ArrowDown") target = list[(index + 1) % list.length];
|
|
1658
|
+
else if (e.key === "ArrowUp") target = list[(index - 1 + list.length) % list.length];
|
|
1659
|
+
else if (e.key === "Home") target = list[0];
|
|
1660
|
+
else if (e.key === "End") target = list[list.length - 1];
|
|
1661
|
+
else if (e.key === "Escape") {
|
|
1662
|
+
e.preventDefault();
|
|
1663
|
+
e.stopPropagation();
|
|
1664
|
+
close(true);
|
|
1665
|
+
return;
|
|
1666
|
+
} else if (e.key === "Tab") {
|
|
1667
|
+
close();
|
|
1668
|
+
return;
|
|
1669
|
+
}
|
|
1670
|
+
if (target) {
|
|
1671
|
+
e.preventDefault();
|
|
1672
|
+
target.focus();
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
const choose = (item) => {
|
|
1676
|
+
const wasKey = mode.current === "key";
|
|
1677
|
+
close(wasKey);
|
|
1678
|
+
item.onSelect?.();
|
|
1679
|
+
};
|
|
1680
|
+
const setTriggerRef = useCallback(
|
|
1681
|
+
(el) => {
|
|
1682
|
+
triggerRef.current = el;
|
|
1683
|
+
if (typeof externalRef === "function") externalRef(el);
|
|
1684
|
+
else if (externalRef) externalRef.current = el;
|
|
1685
|
+
},
|
|
1686
|
+
[externalRef]
|
|
1687
|
+
);
|
|
1688
|
+
const triggerProps = {
|
|
1689
|
+
ref: setTriggerRef,
|
|
1690
|
+
className,
|
|
1691
|
+
"data-testid": testId,
|
|
1692
|
+
"data-slot": "mark",
|
|
1693
|
+
"aria-haspopup": "true",
|
|
1694
|
+
"aria-expanded": open,
|
|
1695
|
+
"aria-controls": open ? menuId : void 0,
|
|
1696
|
+
onPointerDown: handlePointerDown,
|
|
1697
|
+
onPointerEnter: handlePointerEnter,
|
|
1698
|
+
onPointerLeave: handlePointerLeave,
|
|
1699
|
+
onFocus: handleFocus,
|
|
1700
|
+
onBlur: handleBlur,
|
|
1701
|
+
onKeyDown: handleKeyDown,
|
|
1702
|
+
onClick: handleClick,
|
|
1703
|
+
...rest
|
|
1704
|
+
};
|
|
1705
|
+
return /* @__PURE__ */ jsxs(Popover, { open: open && !isEmpty, children: [
|
|
1706
|
+
/* @__PURE__ */ jsx(PopoverAnchor, { asChild: true, children: as === "a" ? /* @__PURE__ */ jsx("a", { href, ...triggerProps, children }) : /* @__PURE__ */ jsx("span", { role: "button", tabIndex: 0, ...triggerProps, children }) }),
|
|
1707
|
+
/* @__PURE__ */ jsxs(
|
|
1708
|
+
PopoverContent,
|
|
1709
|
+
{
|
|
1710
|
+
ref: contentRef,
|
|
1711
|
+
id: menuId,
|
|
1712
|
+
side,
|
|
1713
|
+
align: "start",
|
|
1714
|
+
sideOffset: 6,
|
|
1715
|
+
collisionPadding: 8,
|
|
1716
|
+
role: "group",
|
|
1717
|
+
"data-testid": menuTestId,
|
|
1718
|
+
"data-slot": "mark-menu",
|
|
1719
|
+
className: "w-auto min-w-[12rem] max-w-[min(22rem,calc(100vw-1rem))] p-1",
|
|
1720
|
+
onOpenAutoFocus: (e) => {
|
|
1721
|
+
e.preventDefault();
|
|
1722
|
+
if (focusFirstOnOpen.current) firstItem()?.focus();
|
|
1723
|
+
},
|
|
1724
|
+
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
1725
|
+
onEscapeKeyDown: (e) => {
|
|
1726
|
+
e.preventDefault();
|
|
1727
|
+
close(true);
|
|
1728
|
+
},
|
|
1729
|
+
onInteractOutside: (e) => {
|
|
1730
|
+
if (triggerRef.current?.contains(e.target)) e.preventDefault();
|
|
1731
|
+
},
|
|
1732
|
+
onPointerDownOutside: () => close(),
|
|
1733
|
+
onPointerEnter: clearTimer,
|
|
1734
|
+
onPointerLeave: (e) => {
|
|
1735
|
+
if (!isCoarse(e.pointerType) && mode.current === "hover")
|
|
1736
|
+
schedule(() => close(), closeDelay);
|
|
1737
|
+
},
|
|
1738
|
+
children: [
|
|
1739
|
+
preview && /* @__PURE__ */ jsx("div", { className: "px-2 py-1.5 text-sm", children: preview }),
|
|
1740
|
+
ordered.length > 0 && /* @__PURE__ */ jsx("div", { role: "menu", "aria-label": menuLabel, onKeyDown: handleMenuKeyDown, children: ordered.map((item) => {
|
|
1741
|
+
const rowClass = cn(
|
|
1742
|
+
"flex w-full cursor-pointer items-center rounded-sm px-2 py-1.5 text-left text-sm outline-none transition-colors hover:bg-accent focus-visible:bg-accent pointer-coarse:min-h-11 pointer-coarse:px-3",
|
|
1743
|
+
item.primary && "font-medium pointer-coarse:text-base",
|
|
1744
|
+
item.destructive && "text-destructive"
|
|
1745
|
+
);
|
|
1746
|
+
return item.href && !item.onSelect ? /* @__PURE__ */ jsx(
|
|
1747
|
+
"a",
|
|
1748
|
+
{
|
|
1749
|
+
role: "menuitem",
|
|
1750
|
+
tabIndex: -1,
|
|
1751
|
+
href: item.href,
|
|
1752
|
+
className: rowClass,
|
|
1753
|
+
"data-testid": item.testId,
|
|
1754
|
+
onClick: () => close(),
|
|
1755
|
+
children: item.label
|
|
1756
|
+
},
|
|
1757
|
+
item.id
|
|
1758
|
+
) : /* @__PURE__ */ jsx(
|
|
1759
|
+
"button",
|
|
1760
|
+
{
|
|
1761
|
+
type: "button",
|
|
1762
|
+
role: "menuitem",
|
|
1763
|
+
tabIndex: -1,
|
|
1764
|
+
className: rowClass,
|
|
1765
|
+
"data-testid": item.testId,
|
|
1766
|
+
onClick: () => choose(item),
|
|
1767
|
+
children: item.label
|
|
1768
|
+
},
|
|
1769
|
+
item.id
|
|
1770
|
+
);
|
|
1771
|
+
}) })
|
|
1772
|
+
]
|
|
1773
|
+
}
|
|
1774
|
+
)
|
|
1775
|
+
] });
|
|
1776
|
+
}
|
|
1777
|
+
var Select = SelectPrimitive.Root;
|
|
1778
|
+
var SelectGroup = SelectPrimitive.Group;
|
|
1779
|
+
var SelectValue = SelectPrimitive.Value;
|
|
1780
|
+
var SelectTrigger = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1781
|
+
SelectPrimitive.Trigger,
|
|
1782
|
+
{
|
|
1783
|
+
ref,
|
|
1784
|
+
className: cn(
|
|
1785
|
+
"flex h-9 pointer-coarse:min-h-11 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm placeholder:text-muted-foreground/60 focus:outline-none focus-visible:border-ring/50 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
1786
|
+
className
|
|
1787
|
+
),
|
|
1788
|
+
...props,
|
|
1789
|
+
children: [
|
|
1790
|
+
children,
|
|
1791
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
1792
|
+
]
|
|
1793
|
+
}
|
|
1794
|
+
));
|
|
1795
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
1796
|
+
var SelectScrollUpButton = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1797
|
+
SelectPrimitive.ScrollUpButton,
|
|
1798
|
+
{
|
|
1799
|
+
ref,
|
|
1800
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
1801
|
+
...props,
|
|
1802
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4" })
|
|
1803
|
+
}
|
|
1804
|
+
));
|
|
1805
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
1806
|
+
var SelectScrollDownButton = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1807
|
+
SelectPrimitive.ScrollDownButton,
|
|
1808
|
+
{
|
|
1809
|
+
ref,
|
|
1810
|
+
className: cn("flex cursor-default items-center justify-center py-1", className),
|
|
1811
|
+
...props,
|
|
1812
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
|
|
1813
|
+
}
|
|
1814
|
+
));
|
|
1815
|
+
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
1816
|
+
var SelectContent = React2.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
1817
|
+
SelectPrimitive.Content,
|
|
1818
|
+
{
|
|
1819
|
+
ref,
|
|
1820
|
+
className: cn(
|
|
1821
|
+
"relative z-50 max-h-[min(24rem,var(--radix-select-content-available-height))] min-w-[8rem] max-w-[calc(100vw-1rem)] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
1822
|
+
position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
1823
|
+
className
|
|
1824
|
+
),
|
|
1825
|
+
position,
|
|
1826
|
+
collisionPadding: getCollisionPadding(),
|
|
1827
|
+
...props,
|
|
1828
|
+
children: [
|
|
1829
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
1830
|
+
/* @__PURE__ */ jsx(
|
|
1831
|
+
SelectPrimitive.Viewport,
|
|
1832
|
+
{
|
|
1833
|
+
className: cn(
|
|
1834
|
+
"p-1",
|
|
1835
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
|
1836
|
+
),
|
|
1837
|
+
children
|
|
1838
|
+
}
|
|
1839
|
+
),
|
|
1840
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
1841
|
+
]
|
|
1842
|
+
}
|
|
1843
|
+
) }));
|
|
1844
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
1845
|
+
var SelectLabel = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1846
|
+
SelectPrimitive.Label,
|
|
1847
|
+
{
|
|
1848
|
+
ref,
|
|
1849
|
+
className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className),
|
|
1850
|
+
...props
|
|
1851
|
+
}
|
|
1852
|
+
));
|
|
1853
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
1854
|
+
var SelectItem = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
1855
|
+
SelectPrimitive.Item,
|
|
1856
|
+
{
|
|
1857
|
+
ref,
|
|
1858
|
+
className: cn(
|
|
1859
|
+
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 pointer-coarse:min-h-11 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
1860
|
+
className
|
|
1861
|
+
),
|
|
1862
|
+
...props,
|
|
1863
|
+
children: [
|
|
1864
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "h-4 w-4" }) }) }),
|
|
1865
|
+
/* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children })
|
|
1866
|
+
]
|
|
1867
|
+
}
|
|
1868
|
+
));
|
|
1869
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
1870
|
+
var SelectSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1871
|
+
SelectPrimitive.Separator,
|
|
1872
|
+
{
|
|
1873
|
+
ref,
|
|
1874
|
+
className: cn("-mx-1 my-1 h-px bg-muted", className),
|
|
1875
|
+
...props
|
|
1876
|
+
}
|
|
1877
|
+
));
|
|
1878
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
1879
|
+
var Command = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1880
|
+
Command$1,
|
|
1881
|
+
{
|
|
1882
|
+
ref,
|
|
1883
|
+
className: cn(
|
|
1884
|
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
1885
|
+
className
|
|
1886
|
+
),
|
|
1887
|
+
...props
|
|
1888
|
+
}
|
|
1889
|
+
));
|
|
1890
|
+
Command.displayName = Command$1.displayName;
|
|
1891
|
+
var CommandDialog = ({ children, ...props }) => {
|
|
1892
|
+
return /* @__PURE__ */ jsx(Dialog, { ...props, children: /* @__PURE__ */ jsx(DialogContent, { className: "overflow-hidden p-0", children: /* @__PURE__ */ jsx(Command, { className: "[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5", children }) }) });
|
|
1893
|
+
};
|
|
1894
|
+
var CommandInput = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { className: "flex items-center border-b px-3", "data-cmdk-input-wrapper": "", children: [
|
|
1895
|
+
/* @__PURE__ */ jsx(Search, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
|
|
1896
|
+
/* @__PURE__ */ jsx(
|
|
1897
|
+
Command$1.Input,
|
|
1898
|
+
{
|
|
1899
|
+
ref,
|
|
1900
|
+
className: cn(
|
|
1901
|
+
"flex h-10 pointer-coarse:h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
1902
|
+
className
|
|
1903
|
+
),
|
|
1904
|
+
...props
|
|
1905
|
+
}
|
|
1906
|
+
)
|
|
1907
|
+
] }));
|
|
1908
|
+
CommandInput.displayName = Command$1.Input.displayName;
|
|
1909
|
+
var CommandList = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1910
|
+
Command$1.List,
|
|
1911
|
+
{
|
|
1912
|
+
ref,
|
|
1913
|
+
className: cn("max-h-[min(300px,50dvh)] overflow-y-auto overflow-x-hidden", className),
|
|
1914
|
+
...props
|
|
1915
|
+
}
|
|
1916
|
+
));
|
|
1917
|
+
CommandList.displayName = Command$1.List.displayName;
|
|
1918
|
+
var CommandEmpty = React2.forwardRef((props, ref) => /* @__PURE__ */ jsx(Command$1.Empty, { ref, className: "py-6 text-center text-sm", ...props }));
|
|
1919
|
+
CommandEmpty.displayName = Command$1.Empty.displayName;
|
|
1920
|
+
var CommandGroup = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1921
|
+
Command$1.Group,
|
|
1922
|
+
{
|
|
1923
|
+
ref,
|
|
1924
|
+
className: cn(
|
|
1925
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-sm [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
1926
|
+
className
|
|
1927
|
+
),
|
|
1928
|
+
...props
|
|
1929
|
+
}
|
|
1930
|
+
));
|
|
1931
|
+
CommandGroup.displayName = Command$1.Group.displayName;
|
|
1932
|
+
var CommandSeparator = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1933
|
+
Command$1.Separator,
|
|
1934
|
+
{
|
|
1935
|
+
ref,
|
|
1936
|
+
className: cn("-mx-1 h-px bg-border", className),
|
|
1937
|
+
...props
|
|
1938
|
+
}
|
|
1939
|
+
));
|
|
1940
|
+
CommandSeparator.displayName = Command$1.Separator.displayName;
|
|
1941
|
+
var CommandItem = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1942
|
+
Command$1.Item,
|
|
1943
|
+
{
|
|
1944
|
+
ref,
|
|
1945
|
+
className: cn(
|
|
1946
|
+
"relative flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 pointer-coarse:min-h-11 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
1947
|
+
className
|
|
1948
|
+
),
|
|
1949
|
+
...props
|
|
1950
|
+
}
|
|
1951
|
+
));
|
|
1952
|
+
CommandItem.displayName = Command$1.Item.displayName;
|
|
1953
|
+
var CommandShortcut = ({ className, ...props }) => {
|
|
1954
|
+
return /* @__PURE__ */ jsx(
|
|
1955
|
+
"span",
|
|
1956
|
+
{
|
|
1957
|
+
className: cn("ml-auto text-sm tracking-widest text-muted-foreground", className),
|
|
1958
|
+
...props
|
|
1959
|
+
}
|
|
1960
|
+
);
|
|
1961
|
+
};
|
|
1962
|
+
CommandShortcut.displayName = "CommandShortcut";
|
|
1963
|
+
var AI_COMPONENTS = {
|
|
1964
|
+
a: (p) => /* @__PURE__ */ jsx(
|
|
1965
|
+
"a",
|
|
1966
|
+
{
|
|
1967
|
+
className: "text-ai-accent underline underline-offset-2",
|
|
1968
|
+
target: "_blank",
|
|
1969
|
+
rel: "noopener noreferrer",
|
|
1970
|
+
...p
|
|
1971
|
+
}
|
|
1972
|
+
),
|
|
1973
|
+
// Redline marks: deletions in red strike, <ins>/<mark> additions accented.
|
|
1974
|
+
del: (p) => /* @__PURE__ */ jsx("del", { className: "rounded bg-destructive/10 text-destructive decoration-destructive/60", ...p }),
|
|
1975
|
+
ins: (p) => /* @__PURE__ */ jsx("ins", { className: "rounded bg-ai-accent-soft px-0.5 text-ai-accent no-underline", ...p }),
|
|
1976
|
+
mark: (p) => /* @__PURE__ */ jsx("mark", { className: "rounded bg-ai-accent-soft px-0.5 text-ai-accent", ...p }),
|
|
1977
|
+
thead: (p) => /* @__PURE__ */ jsx("thead", { className: "bg-secondary/60", ...p })
|
|
1978
|
+
};
|
|
1979
|
+
function AiMarkdown({
|
|
1980
|
+
children,
|
|
1981
|
+
className,
|
|
1982
|
+
isStreaming
|
|
1983
|
+
}) {
|
|
1984
|
+
return /* @__PURE__ */ jsx(
|
|
1985
|
+
MarkdownRenderer,
|
|
1986
|
+
{
|
|
1987
|
+
className: className ?? "text-sm text-foreground",
|
|
1988
|
+
components: AI_COMPONENTS,
|
|
1989
|
+
isStreaming,
|
|
1990
|
+
testId: "ai-markdown",
|
|
1991
|
+
children
|
|
1992
|
+
}
|
|
1993
|
+
);
|
|
1994
|
+
}
|
|
1995
|
+
var EntityPill = forwardRef(function EntityPill2({
|
|
1996
|
+
icon,
|
|
1997
|
+
label,
|
|
1998
|
+
secondaryText,
|
|
1999
|
+
size = "sm",
|
|
2000
|
+
shape = "rounded",
|
|
2001
|
+
className,
|
|
2002
|
+
labelMaxWidth = "max-w-[320px]",
|
|
2003
|
+
labelClassName,
|
|
2004
|
+
fullWidth = false,
|
|
2005
|
+
highlight = false,
|
|
2006
|
+
onClick,
|
|
2007
|
+
onIconClick,
|
|
2008
|
+
onMoreClick,
|
|
2009
|
+
moreContent,
|
|
2010
|
+
href,
|
|
2011
|
+
disabled = false,
|
|
2012
|
+
tooltipContent,
|
|
2013
|
+
tooltipSide = "bottom",
|
|
2014
|
+
"data-testid": testId
|
|
2015
|
+
}, ref) {
|
|
2016
|
+
const shapeClass = shape === "pill" ? "rounded-full" : "rounded-md";
|
|
2017
|
+
const sizeClasses2 = size === "base" ? "gap-1.5 px-1.5 py-0.5" : "gap-1 px-1";
|
|
2018
|
+
const textSizeClass = size === "base" ? "text-base" : "text-sm";
|
|
2019
|
+
const baseClasses = cn(
|
|
2020
|
+
"group/pill items-center",
|
|
2021
|
+
fullWidth ? "flex w-full" : "inline-flex",
|
|
2022
|
+
sizeClasses2,
|
|
2023
|
+
shapeClass,
|
|
2024
|
+
"bg-muted",
|
|
2025
|
+
"border border-border",
|
|
2026
|
+
"transition-all",
|
|
2027
|
+
className
|
|
2028
|
+
);
|
|
2029
|
+
const interactiveClasses = "relative cursor-pointer hover:bg-muted/80 pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']";
|
|
2030
|
+
const disabledClasses = "cursor-default opacity-60";
|
|
2031
|
+
const highlightClasses = "bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground";
|
|
2032
|
+
const mainContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2033
|
+
onIconClick ? /* @__PURE__ */ jsx(
|
|
2034
|
+
"span",
|
|
2035
|
+
{
|
|
2036
|
+
role: "button",
|
|
2037
|
+
tabIndex: 0,
|
|
2038
|
+
className: "flex-shrink-0 cursor-pointer hover:opacity-70 transition-opacity",
|
|
2039
|
+
onClick: (e) => {
|
|
2040
|
+
e.stopPropagation();
|
|
2041
|
+
onIconClick(e);
|
|
2042
|
+
},
|
|
2043
|
+
children: icon
|
|
2044
|
+
}
|
|
2045
|
+
) : icon,
|
|
2046
|
+
/* @__PURE__ */ jsx(
|
|
2047
|
+
"span",
|
|
2048
|
+
{
|
|
2049
|
+
className: cn(
|
|
2050
|
+
textSizeClass,
|
|
2051
|
+
"font-medium truncate leading-tight min-w-0",
|
|
2052
|
+
labelMaxWidth,
|
|
2053
|
+
labelClassName
|
|
2054
|
+
),
|
|
2055
|
+
children: label
|
|
2056
|
+
}
|
|
2057
|
+
),
|
|
2058
|
+
secondaryText && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground flex-shrink-0 leading-none", children: secondaryText })
|
|
2059
|
+
] });
|
|
2060
|
+
const tooltipWrap = (content, tip, side = tooltipSide, triggerClassName, triggerProps) => /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
2061
|
+
/* @__PURE__ */ jsx(
|
|
2062
|
+
TooltipTrigger,
|
|
2063
|
+
{
|
|
2064
|
+
onFocusCapture: (e) => e.stopPropagation(),
|
|
2065
|
+
className: triggerClassName,
|
|
2066
|
+
...triggerProps,
|
|
2067
|
+
children: content
|
|
2068
|
+
}
|
|
2069
|
+
),
|
|
2070
|
+
/* @__PURE__ */ jsx(TooltipContent, { side, className: "p-2", children: tip })
|
|
2071
|
+
] });
|
|
2072
|
+
const mainAreaClass = cn("inline-flex items-center gap-1", fullWidth && "min-w-0 flex-1");
|
|
2073
|
+
const mainAreaTouchClass = cn(
|
|
2074
|
+
mainAreaClass,
|
|
2075
|
+
(onClick || href) && !disabled && "relative pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']"
|
|
2076
|
+
);
|
|
2077
|
+
if (onMoreClick || moreContent) {
|
|
2078
|
+
let mainArea;
|
|
2079
|
+
if (tooltipContent) {
|
|
2080
|
+
mainArea = tooltipWrap(
|
|
2081
|
+
mainContent,
|
|
2082
|
+
tooltipContent,
|
|
2083
|
+
tooltipSide,
|
|
2084
|
+
cn(mainAreaTouchClass, disabled && "opacity-60"),
|
|
2085
|
+
{
|
|
2086
|
+
type: "button",
|
|
2087
|
+
onClick: href ? onClick : disabled ? void 0 : onClick,
|
|
2088
|
+
disabled: disabled || void 0
|
|
2089
|
+
}
|
|
2090
|
+
);
|
|
2091
|
+
} else if (href) {
|
|
2092
|
+
mainArea = /* @__PURE__ */ jsx(
|
|
2093
|
+
"a",
|
|
2094
|
+
{
|
|
2095
|
+
href,
|
|
2096
|
+
target: "_blank",
|
|
2097
|
+
rel: "noopener noreferrer",
|
|
2098
|
+
className: mainAreaTouchClass,
|
|
2099
|
+
onClick,
|
|
2100
|
+
children: mainContent
|
|
2101
|
+
}
|
|
2102
|
+
);
|
|
2103
|
+
} else if (onClick) {
|
|
2104
|
+
mainArea = /* @__PURE__ */ jsx(
|
|
2105
|
+
"button",
|
|
2106
|
+
{
|
|
2107
|
+
type: "button",
|
|
2108
|
+
onClick: disabled ? void 0 : onClick,
|
|
2109
|
+
disabled,
|
|
2110
|
+
className: cn(
|
|
2111
|
+
"relative inline-flex items-center gap-1 pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']",
|
|
2112
|
+
disabled && "opacity-60"
|
|
2113
|
+
),
|
|
2114
|
+
children: mainContent
|
|
2115
|
+
}
|
|
2116
|
+
);
|
|
2117
|
+
} else {
|
|
2118
|
+
mainArea = /* @__PURE__ */ jsx("span", { className: mainAreaTouchClass, children: mainContent });
|
|
2119
|
+
}
|
|
2120
|
+
const moreArea = moreContent ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 leading-none", children: moreContent }) : tooltipWrap(
|
|
2121
|
+
/* @__PURE__ */ jsx(MoreVertical, { className: "w-3.5 h-3.5" }),
|
|
2122
|
+
"Click for more",
|
|
2123
|
+
tooltipSide,
|
|
2124
|
+
"flex-shrink-0 leading-none text-muted-foreground hover:text-foreground",
|
|
2125
|
+
{
|
|
2126
|
+
type: "button",
|
|
2127
|
+
onClick: (e) => {
|
|
2128
|
+
e.stopPropagation();
|
|
2129
|
+
onMoreClick?.(e);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
);
|
|
2133
|
+
return /* @__PURE__ */ jsxs(
|
|
2134
|
+
"span",
|
|
2135
|
+
{
|
|
2136
|
+
ref,
|
|
2137
|
+
className: cn(
|
|
2138
|
+
baseClasses,
|
|
2139
|
+
(onClick || href) && !disabled && "cursor-pointer hover:bg-muted/80",
|
|
2140
|
+
highlight && highlightClasses
|
|
2141
|
+
),
|
|
2142
|
+
"data-testid": testId,
|
|
2143
|
+
children: [
|
|
2144
|
+
mainArea,
|
|
2145
|
+
moreArea
|
|
2146
|
+
]
|
|
2147
|
+
}
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
if (tooltipContent) {
|
|
2151
|
+
if (href) {
|
|
2152
|
+
return tooltipWrap(
|
|
2153
|
+
/* @__PURE__ */ jsx(
|
|
2154
|
+
"a",
|
|
2155
|
+
{
|
|
2156
|
+
href,
|
|
2157
|
+
target: "_blank",
|
|
2158
|
+
rel: "noopener noreferrer",
|
|
2159
|
+
className: mainAreaClass,
|
|
2160
|
+
onClick,
|
|
2161
|
+
children: mainContent
|
|
2162
|
+
}
|
|
2163
|
+
),
|
|
2164
|
+
tooltipContent,
|
|
2165
|
+
tooltipSide,
|
|
2166
|
+
cn(baseClasses, interactiveClasses),
|
|
2167
|
+
{ "data-testid": testId }
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
return tooltipWrap(
|
|
2171
|
+
mainContent,
|
|
2172
|
+
tooltipContent,
|
|
2173
|
+
tooltipSide,
|
|
2174
|
+
cn(
|
|
2175
|
+
baseClasses,
|
|
2176
|
+
onClick && !disabled ? interactiveClasses : "",
|
|
2177
|
+
disabled ? disabledClasses : "",
|
|
2178
|
+
highlight && highlightClasses
|
|
2179
|
+
),
|
|
2180
|
+
{
|
|
2181
|
+
type: "button",
|
|
2182
|
+
ref,
|
|
2183
|
+
onClick: onClick && !disabled ? onClick : void 0,
|
|
2184
|
+
disabled: disabled || void 0,
|
|
2185
|
+
"data-testid": testId
|
|
2186
|
+
}
|
|
2187
|
+
);
|
|
2188
|
+
}
|
|
2189
|
+
if (href) {
|
|
2190
|
+
return /* @__PURE__ */ jsx(
|
|
2191
|
+
"a",
|
|
2192
|
+
{
|
|
2193
|
+
ref,
|
|
2194
|
+
href,
|
|
2195
|
+
target: "_blank",
|
|
2196
|
+
rel: "noopener noreferrer",
|
|
2197
|
+
className: cn(baseClasses, interactiveClasses),
|
|
2198
|
+
"data-testid": testId,
|
|
2199
|
+
onClick,
|
|
2200
|
+
children: mainContent
|
|
2201
|
+
}
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
if (onClick) {
|
|
2205
|
+
return /* @__PURE__ */ jsx(
|
|
2206
|
+
"button",
|
|
2207
|
+
{
|
|
2208
|
+
ref,
|
|
2209
|
+
type: "button",
|
|
2210
|
+
onClick: disabled ? void 0 : onClick,
|
|
2211
|
+
disabled,
|
|
2212
|
+
className: cn(
|
|
2213
|
+
baseClasses,
|
|
2214
|
+
disabled ? disabledClasses : interactiveClasses,
|
|
2215
|
+
highlight && highlightClasses
|
|
2216
|
+
),
|
|
2217
|
+
"data-testid": testId,
|
|
2218
|
+
children: mainContent
|
|
2219
|
+
}
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
return /* @__PURE__ */ jsx(
|
|
2223
|
+
"span",
|
|
2224
|
+
{
|
|
2225
|
+
ref,
|
|
2226
|
+
className: cn(baseClasses, highlight && highlightClasses),
|
|
2227
|
+
"data-testid": testId,
|
|
2228
|
+
children: mainContent
|
|
2229
|
+
}
|
|
2230
|
+
);
|
|
2231
|
+
});
|
|
2232
|
+
var TAG_TYPE_LABELS = {
|
|
2233
|
+
checkbox: "Checkbox",
|
|
2234
|
+
select: "Select",
|
|
2235
|
+
number: "Number",
|
|
2236
|
+
text: "Text",
|
|
2237
|
+
folder: "Folder",
|
|
2238
|
+
search: "Saved Search",
|
|
2239
|
+
date: "Date",
|
|
2240
|
+
assistant: "AI Assistant"
|
|
2241
|
+
};
|
|
2242
|
+
var TAG_TYPE_ICONS = {
|
|
2243
|
+
checkbox: SquareCheckBig,
|
|
2244
|
+
select: List,
|
|
2245
|
+
number: Hash,
|
|
2246
|
+
text: NotebookPen,
|
|
2247
|
+
folder: Folder,
|
|
2248
|
+
search: Search,
|
|
2249
|
+
date: Calendar,
|
|
2250
|
+
assistant: Bot
|
|
2251
|
+
};
|
|
2252
|
+
function getTagTypeIcon(type) {
|
|
2253
|
+
return TAG_TYPE_ICONS[type ?? "text"] || NotebookPen;
|
|
2254
|
+
}
|
|
2255
|
+
function getTagTypeLabel(type) {
|
|
2256
|
+
const t = type ?? "text";
|
|
2257
|
+
return TAG_TYPE_LABELS[t] || t;
|
|
2258
|
+
}
|
|
2259
|
+
var BASE_COLORS = {
|
|
2260
|
+
"0": "#10b981",
|
|
2261
|
+
"1": "#3b82f6",
|
|
2262
|
+
"2": "#8b5cf6",
|
|
2263
|
+
"3": "#f43f5e",
|
|
2264
|
+
"4": "#f59e0b",
|
|
2265
|
+
"5": "#84cc16",
|
|
2266
|
+
"6": "#a855f7",
|
|
2267
|
+
"7": "#06b6d4",
|
|
2268
|
+
"8": "#f97316",
|
|
2269
|
+
"9": "#14b8a6",
|
|
2270
|
+
a: "#ef4444",
|
|
2271
|
+
b: "#6366f1",
|
|
2272
|
+
c: "#ec4899",
|
|
2273
|
+
d: "#22c55e",
|
|
2274
|
+
e: "#eab308",
|
|
2275
|
+
f: "#0ea5e9"
|
|
2276
|
+
};
|
|
2277
|
+
function getEntityColor(entityId) {
|
|
2278
|
+
return BASE_COLORS[entityId[4]] || BASE_COLORS["0"];
|
|
2279
|
+
}
|
|
2280
|
+
function TagEntity({
|
|
2281
|
+
tag,
|
|
2282
|
+
size = "md",
|
|
2283
|
+
className = "",
|
|
2284
|
+
onClick,
|
|
2285
|
+
showTooltip = true,
|
|
2286
|
+
tooltipContent
|
|
2287
|
+
}) {
|
|
2288
|
+
const tagType = tag.tag_type?.type ?? "text";
|
|
2289
|
+
const iconSize = size === "sm" ? 12 : size === "md" ? 14 : 16;
|
|
2290
|
+
const Icon2 = getTagTypeIcon(tagType);
|
|
2291
|
+
const sizeClasses2 = {
|
|
2292
|
+
sm: "p-0.5",
|
|
2293
|
+
md: "p-1",
|
|
2294
|
+
lg: "p-1.5"
|
|
2295
|
+
};
|
|
2296
|
+
const tagColor = tag.color ?? getEntityColor(tag.external_id);
|
|
2297
|
+
const iconElement = /* @__PURE__ */ jsx(
|
|
2298
|
+
"span",
|
|
2299
|
+
{
|
|
2300
|
+
className: `inline-flex items-center justify-center rounded-md text-white flex-shrink-0 ${sizeClasses2[size]}`,
|
|
2301
|
+
style: { backgroundColor: tagColor },
|
|
2302
|
+
children: /* @__PURE__ */ jsx(Icon2, { size: iconSize, className: "flex-shrink-0" })
|
|
2303
|
+
}
|
|
2304
|
+
);
|
|
2305
|
+
const pillSize = size === "lg" ? "base" : "sm";
|
|
2306
|
+
const defaultTooltip = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2307
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2308
|
+
/* @__PURE__ */ jsx(
|
|
2309
|
+
"span",
|
|
2310
|
+
{
|
|
2311
|
+
className: "inline-flex items-center justify-center rounded-md text-white p-1",
|
|
2312
|
+
style: { backgroundColor: tagColor },
|
|
2313
|
+
children: /* @__PURE__ */ jsx(Icon2, { size: 16 })
|
|
2314
|
+
}
|
|
2315
|
+
),
|
|
2316
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: tag.name })
|
|
2317
|
+
] }),
|
|
2318
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5 text-sm", children: [
|
|
2319
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2320
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Type:" }),
|
|
2321
|
+
/* @__PURE__ */ jsx("span", { children: getTagTypeLabel(tagType) })
|
|
2322
|
+
] }),
|
|
2323
|
+
tag.doctag_count != null && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2324
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "Documents:" }),
|
|
2325
|
+
/* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "h-5 min-w-[20px] justify-center", children: tag.doctag_count ?? 0 })
|
|
2326
|
+
] }),
|
|
2327
|
+
tag.shared != null && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: tag.shared ? "Shared" : "Private" }) })
|
|
2328
|
+
] })
|
|
2329
|
+
] });
|
|
2330
|
+
const resolvedTooltip = showTooltip ? tooltipContent ?? defaultTooltip : void 0;
|
|
2331
|
+
return /* @__PURE__ */ jsx(
|
|
2332
|
+
EntityPill,
|
|
2333
|
+
{
|
|
2334
|
+
icon: iconElement,
|
|
2335
|
+
label: tag.name,
|
|
2336
|
+
size: pillSize,
|
|
2337
|
+
shape: "rounded",
|
|
2338
|
+
labelMaxWidth: "max-w-[180px]",
|
|
2339
|
+
tooltipContent: resolvedTooltip,
|
|
2340
|
+
onClick,
|
|
2341
|
+
className,
|
|
2342
|
+
"data-testid": `tag-entity-${tag.external_id}`
|
|
2343
|
+
}
|
|
2344
|
+
);
|
|
2345
|
+
}
|
|
2346
|
+
var TIERS = [
|
|
2347
|
+
{ min: 0.7, tone: "bg-emerald-500", label: "High relevance" },
|
|
2348
|
+
{ min: 0.4, tone: "bg-amber-500", label: "Medium relevance" },
|
|
2349
|
+
{ min: -Infinity, tone: "bg-muted-foreground/40", label: "Low relevance" }
|
|
2350
|
+
];
|
|
2351
|
+
function RelevanceDot({ score }) {
|
|
2352
|
+
if (score == null) return null;
|
|
2353
|
+
const tier = TIERS.find((t) => score >= t.min) ?? TIERS[TIERS.length - 1];
|
|
2354
|
+
return /* @__PURE__ */ jsx(
|
|
2355
|
+
"span",
|
|
2356
|
+
{
|
|
2357
|
+
role: "img",
|
|
2358
|
+
"aria-label": tier.label,
|
|
2359
|
+
title: `${tier.label} (${score.toFixed(2)})`,
|
|
2360
|
+
className: cn("size-1.5 shrink-0 rounded-full", tier.tone),
|
|
2361
|
+
"data-testid": "passage-relevance"
|
|
2362
|
+
}
|
|
2363
|
+
);
|
|
2364
|
+
}
|
|
2365
|
+
function PassageCard({
|
|
2366
|
+
header,
|
|
2367
|
+
score,
|
|
2368
|
+
headerRight,
|
|
2369
|
+
active,
|
|
2370
|
+
onClick,
|
|
2371
|
+
footer,
|
|
2372
|
+
className,
|
|
2373
|
+
children,
|
|
2374
|
+
"data-testid": testId
|
|
2375
|
+
}) {
|
|
2376
|
+
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2377
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-1.5 flex items-center gap-2", children: [
|
|
2378
|
+
header,
|
|
2379
|
+
(score != null || headerRight) && /* @__PURE__ */ jsxs("div", { className: "ml-auto flex shrink-0 items-center gap-2", children: [
|
|
2380
|
+
/* @__PURE__ */ jsx(RelevanceDot, { score }),
|
|
2381
|
+
headerRight
|
|
2382
|
+
] })
|
|
2383
|
+
] }),
|
|
2384
|
+
/* @__PURE__ */ jsx("div", { className: "[&_mark]:rounded-sm [&_mark]:bg-ai-accent/20 [&_mark]:px-0.5 [&_mark]:font-medium [&_mark]:text-foreground", children })
|
|
2385
|
+
] });
|
|
2386
|
+
return /* @__PURE__ */ jsxs(
|
|
2387
|
+
"div",
|
|
2388
|
+
{
|
|
2389
|
+
className: cn(
|
|
2390
|
+
"group rounded-lg border border-border bg-card p-3 text-left transition-colors",
|
|
2391
|
+
onClick && "hover:border-ai-accent/40 focus-within:ring-2 focus-within:ring-ai-accent/40",
|
|
2392
|
+
active && "border-ai-accent/60 ring-1 ring-ai-accent/30",
|
|
2393
|
+
className
|
|
2394
|
+
),
|
|
2395
|
+
children: [
|
|
2396
|
+
onClick ? /* @__PURE__ */ jsx(
|
|
2397
|
+
"div",
|
|
2398
|
+
{
|
|
2399
|
+
role: "button",
|
|
2400
|
+
tabIndex: 0,
|
|
2401
|
+
onClick,
|
|
2402
|
+
onKeyDown: (e) => {
|
|
2403
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
2404
|
+
e.preventDefault();
|
|
2405
|
+
onClick(e);
|
|
2406
|
+
}
|
|
2407
|
+
},
|
|
2408
|
+
"aria-current": active || void 0,
|
|
2409
|
+
"data-testid": testId,
|
|
2410
|
+
className: "cursor-pointer focus:outline-none",
|
|
2411
|
+
children: body
|
|
2412
|
+
}
|
|
2413
|
+
) : /* @__PURE__ */ jsx("div", { "aria-current": active || void 0, "data-testid": testId, children: body }),
|
|
2414
|
+
footer
|
|
2415
|
+
]
|
|
2416
|
+
}
|
|
2417
|
+
);
|
|
2418
|
+
}
|
|
2419
|
+
|
|
2420
|
+
// src/icons/colors.ts
|
|
2421
|
+
var NEUTRAL_GRAY = "#64748b";
|
|
2422
|
+
var FILE_TYPE_COLORS = {
|
|
2423
|
+
pdf: "#ef4444",
|
|
2424
|
+
// red
|
|
2425
|
+
doc: "#3b82f6",
|
|
2426
|
+
// blue (Word docs)
|
|
2427
|
+
docx: "#3b82f6",
|
|
2428
|
+
// blue
|
|
2429
|
+
html: "#0284c7",
|
|
2430
|
+
// sky-600 (web files)
|
|
2431
|
+
img: "#8b5cf6",
|
|
2432
|
+
// violet-500 (images)
|
|
2433
|
+
vid: "#10b981",
|
|
2434
|
+
// emerald-500 (video)
|
|
2435
|
+
aud: "#f59e0b",
|
|
2436
|
+
// amber-500 (audio)
|
|
2437
|
+
xls: "#16a34a",
|
|
2438
|
+
// green-600 (Excel)
|
|
2439
|
+
eml: "#0d9488",
|
|
2440
|
+
// teal-600 (email)
|
|
2441
|
+
txt: NEUTRAL_GRAY,
|
|
2442
|
+
// gray (plain text)
|
|
2443
|
+
generic: NEUTRAL_GRAY,
|
|
2444
|
+
// gray (unknown)
|
|
2445
|
+
white: "#ffffff"
|
|
2446
|
+
// for strokes/text on colored backgrounds
|
|
2447
|
+
};
|
|
2448
|
+
var PdfIcon = ({ size = 16, className = "" }) => {
|
|
2449
|
+
return /* @__PURE__ */ jsxs(
|
|
2450
|
+
"svg",
|
|
2451
|
+
{
|
|
2452
|
+
width: size,
|
|
2453
|
+
height: size,
|
|
2454
|
+
viewBox: "0 0 24 24",
|
|
2455
|
+
fill: "none",
|
|
2456
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2457
|
+
className,
|
|
2458
|
+
children: [
|
|
2459
|
+
/* @__PURE__ */ jsx(
|
|
2460
|
+
"path",
|
|
2461
|
+
{
|
|
2462
|
+
d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
|
|
2463
|
+
fill: FILE_TYPE_COLORS.pdf,
|
|
2464
|
+
stroke: FILE_TYPE_COLORS.pdf,
|
|
2465
|
+
strokeWidth: "1",
|
|
2466
|
+
strokeLinecap: "round",
|
|
2467
|
+
strokeLinejoin: "round"
|
|
2468
|
+
}
|
|
2469
|
+
),
|
|
2470
|
+
/* @__PURE__ */ jsx(
|
|
2471
|
+
"path",
|
|
2472
|
+
{
|
|
2473
|
+
d: "M14 2v6h6",
|
|
2474
|
+
fill: "none",
|
|
2475
|
+
stroke: FILE_TYPE_COLORS.white,
|
|
2476
|
+
strokeWidth: "1",
|
|
2477
|
+
strokeLinecap: "round",
|
|
2478
|
+
strokeLinejoin: "round"
|
|
2479
|
+
}
|
|
2480
|
+
),
|
|
2481
|
+
/* @__PURE__ */ jsx(
|
|
2482
|
+
"text",
|
|
2483
|
+
{
|
|
2484
|
+
x: "12",
|
|
2485
|
+
y: "16",
|
|
2486
|
+
fontSize: "6",
|
|
2487
|
+
fill: "white",
|
|
2488
|
+
textAnchor: "middle",
|
|
2489
|
+
fontWeight: "bold",
|
|
2490
|
+
fontFamily: "Arial, sans-serif",
|
|
2491
|
+
children: "PDF"
|
|
2492
|
+
}
|
|
2493
|
+
)
|
|
2494
|
+
]
|
|
2495
|
+
}
|
|
2496
|
+
);
|
|
2497
|
+
};
|
|
2498
|
+
var AudIcon = ({ size = 16, className = "" }) => {
|
|
2499
|
+
return /* @__PURE__ */ jsxs(
|
|
2500
|
+
"svg",
|
|
2501
|
+
{
|
|
2502
|
+
width: size,
|
|
2503
|
+
height: size,
|
|
2504
|
+
viewBox: "0 0 24 24",
|
|
2505
|
+
fill: "none",
|
|
2506
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2507
|
+
className,
|
|
2508
|
+
children: [
|
|
2509
|
+
/* @__PURE__ */ jsx(
|
|
2510
|
+
"path",
|
|
2511
|
+
{
|
|
2512
|
+
d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
|
|
2513
|
+
fill: FILE_TYPE_COLORS.aud,
|
|
2514
|
+
stroke: FILE_TYPE_COLORS.aud,
|
|
2515
|
+
strokeWidth: "1",
|
|
2516
|
+
strokeLinecap: "round",
|
|
2517
|
+
strokeLinejoin: "round"
|
|
2518
|
+
}
|
|
2519
|
+
),
|
|
2520
|
+
/* @__PURE__ */ jsx(
|
|
2521
|
+
"path",
|
|
2522
|
+
{
|
|
2523
|
+
d: "M14 2v6h6",
|
|
2524
|
+
fill: "none",
|
|
2525
|
+
stroke: FILE_TYPE_COLORS.white,
|
|
2526
|
+
strokeWidth: "1",
|
|
2527
|
+
strokeLinecap: "round",
|
|
2528
|
+
strokeLinejoin: "round"
|
|
2529
|
+
}
|
|
2530
|
+
),
|
|
2531
|
+
/* @__PURE__ */ jsx(
|
|
2532
|
+
"text",
|
|
2533
|
+
{
|
|
2534
|
+
x: "12",
|
|
2535
|
+
y: "16",
|
|
2536
|
+
fontSize: "6",
|
|
2537
|
+
fill: "white",
|
|
2538
|
+
textAnchor: "middle",
|
|
2539
|
+
fontWeight: "bold",
|
|
2540
|
+
fontFamily: "Arial, sans-serif",
|
|
2541
|
+
children: "AUD"
|
|
2542
|
+
}
|
|
2543
|
+
)
|
|
2544
|
+
]
|
|
2545
|
+
}
|
|
2546
|
+
);
|
|
2547
|
+
};
|
|
2548
|
+
var ImgIcon = ({ size = 16, className = "" }) => {
|
|
2549
|
+
return /* @__PURE__ */ jsxs(
|
|
2550
|
+
"svg",
|
|
2551
|
+
{
|
|
2552
|
+
width: size,
|
|
2553
|
+
height: size,
|
|
2554
|
+
viewBox: "0 0 24 24",
|
|
2555
|
+
fill: "none",
|
|
2556
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2557
|
+
className,
|
|
2558
|
+
children: [
|
|
2559
|
+
/* @__PURE__ */ jsx(
|
|
2560
|
+
"path",
|
|
2561
|
+
{
|
|
2562
|
+
d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
|
|
2563
|
+
fill: FILE_TYPE_COLORS.img,
|
|
2564
|
+
stroke: FILE_TYPE_COLORS.img,
|
|
2565
|
+
strokeWidth: "1",
|
|
2566
|
+
strokeLinecap: "round",
|
|
2567
|
+
strokeLinejoin: "round"
|
|
2568
|
+
}
|
|
2569
|
+
),
|
|
2570
|
+
/* @__PURE__ */ jsx(
|
|
2571
|
+
"path",
|
|
2572
|
+
{
|
|
2573
|
+
d: "M14 2v6h6",
|
|
2574
|
+
fill: "none",
|
|
2575
|
+
stroke: FILE_TYPE_COLORS.white,
|
|
2576
|
+
strokeWidth: "1",
|
|
2577
|
+
strokeLinecap: "round",
|
|
2578
|
+
strokeLinejoin: "round"
|
|
2579
|
+
}
|
|
2580
|
+
),
|
|
2581
|
+
/* @__PURE__ */ jsx(
|
|
2582
|
+
"text",
|
|
2583
|
+
{
|
|
2584
|
+
x: "12",
|
|
2585
|
+
y: "16",
|
|
2586
|
+
fontSize: "6",
|
|
2587
|
+
fill: "white",
|
|
2588
|
+
textAnchor: "middle",
|
|
2589
|
+
fontWeight: "bold",
|
|
2590
|
+
fontFamily: "Arial, sans-serif",
|
|
2591
|
+
children: "IMG"
|
|
2592
|
+
}
|
|
2593
|
+
)
|
|
2594
|
+
]
|
|
2595
|
+
}
|
|
2596
|
+
);
|
|
2597
|
+
};
|
|
2598
|
+
var VidIcon = ({ size = 16, className = "" }) => {
|
|
2599
|
+
return /* @__PURE__ */ jsxs(
|
|
2600
|
+
"svg",
|
|
2601
|
+
{
|
|
2602
|
+
width: size,
|
|
2603
|
+
height: size,
|
|
2604
|
+
viewBox: "0 0 24 24",
|
|
2605
|
+
fill: "none",
|
|
2606
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2607
|
+
className,
|
|
2608
|
+
children: [
|
|
2609
|
+
/* @__PURE__ */ jsx(
|
|
2610
|
+
"path",
|
|
2611
|
+
{
|
|
2612
|
+
d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
|
|
2613
|
+
fill: FILE_TYPE_COLORS.vid,
|
|
2614
|
+
stroke: FILE_TYPE_COLORS.vid,
|
|
2615
|
+
strokeWidth: "1",
|
|
2616
|
+
strokeLinecap: "round",
|
|
2617
|
+
strokeLinejoin: "round"
|
|
2618
|
+
}
|
|
2619
|
+
),
|
|
2620
|
+
/* @__PURE__ */ jsx(
|
|
2621
|
+
"path",
|
|
2622
|
+
{
|
|
2623
|
+
d: "M14 2v6h6",
|
|
2624
|
+
fill: "none",
|
|
2625
|
+
stroke: FILE_TYPE_COLORS.white,
|
|
2626
|
+
strokeWidth: "1",
|
|
2627
|
+
strokeLinecap: "round",
|
|
2628
|
+
strokeLinejoin: "round"
|
|
2629
|
+
}
|
|
2630
|
+
),
|
|
2631
|
+
/* @__PURE__ */ jsx(
|
|
2632
|
+
"text",
|
|
2633
|
+
{
|
|
2634
|
+
x: "12",
|
|
2635
|
+
y: "16",
|
|
2636
|
+
fontSize: "6",
|
|
2637
|
+
fill: "white",
|
|
2638
|
+
textAnchor: "middle",
|
|
2639
|
+
fontWeight: "bold",
|
|
2640
|
+
fontFamily: "Arial, sans-serif",
|
|
2641
|
+
children: "VID"
|
|
2642
|
+
}
|
|
2643
|
+
)
|
|
2644
|
+
]
|
|
2645
|
+
}
|
|
2646
|
+
);
|
|
2647
|
+
};
|
|
2648
|
+
var EmlIcon = ({ size = 16, className = "" }) => {
|
|
2649
|
+
return /* @__PURE__ */ jsxs(
|
|
2650
|
+
"svg",
|
|
2651
|
+
{
|
|
2652
|
+
width: size,
|
|
2653
|
+
height: size,
|
|
2654
|
+
viewBox: "0 0 24 24",
|
|
2655
|
+
fill: "none",
|
|
2656
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2657
|
+
className,
|
|
2658
|
+
children: [
|
|
2659
|
+
/* @__PURE__ */ jsx(
|
|
2660
|
+
"path",
|
|
2661
|
+
{
|
|
2662
|
+
d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6z",
|
|
2663
|
+
fill: FILE_TYPE_COLORS.eml,
|
|
2664
|
+
stroke: FILE_TYPE_COLORS.eml,
|
|
2665
|
+
strokeWidth: "1",
|
|
2666
|
+
strokeLinecap: "round",
|
|
2667
|
+
strokeLinejoin: "round"
|
|
2668
|
+
}
|
|
2669
|
+
),
|
|
2670
|
+
/* @__PURE__ */ jsx(
|
|
2671
|
+
"path",
|
|
2672
|
+
{
|
|
2673
|
+
d: "M14 2v6h6",
|
|
2674
|
+
fill: "none",
|
|
2675
|
+
stroke: FILE_TYPE_COLORS.white,
|
|
2676
|
+
strokeWidth: "1",
|
|
2677
|
+
strokeLinecap: "round",
|
|
2678
|
+
strokeLinejoin: "round"
|
|
2679
|
+
}
|
|
2680
|
+
),
|
|
2681
|
+
/* @__PURE__ */ jsx(
|
|
2682
|
+
"rect",
|
|
2683
|
+
{
|
|
2684
|
+
x: "7",
|
|
2685
|
+
y: "12",
|
|
2686
|
+
width: "10",
|
|
2687
|
+
height: "7",
|
|
2688
|
+
rx: "1",
|
|
2689
|
+
fill: "none",
|
|
2690
|
+
stroke: "white",
|
|
2691
|
+
strokeWidth: "1.2"
|
|
2692
|
+
}
|
|
2693
|
+
),
|
|
2694
|
+
/* @__PURE__ */ jsx("path", { d: "M7 13l5 3 5-3", fill: "none", stroke: "white", strokeWidth: "1.2", strokeLinejoin: "round" })
|
|
2695
|
+
]
|
|
2696
|
+
}
|
|
2697
|
+
);
|
|
2698
|
+
};
|
|
2699
|
+
var ArbiBotHeadIcon = ({ size = 24, className = "" }) => {
|
|
2700
|
+
const maskId = useId();
|
|
2701
|
+
return /* @__PURE__ */ jsxs(
|
|
2702
|
+
"svg",
|
|
2703
|
+
{
|
|
2704
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
2705
|
+
width: size,
|
|
2706
|
+
height: size,
|
|
2707
|
+
viewBox: "30 -5 190 190",
|
|
2708
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
2709
|
+
className,
|
|
2710
|
+
children: [
|
|
2711
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("mask", { id: maskId, children: /* @__PURE__ */ jsxs("g", { transform: "translate(0,250) scale(0.1,-0.1)", children: [
|
|
2712
|
+
/* @__PURE__ */ jsx("rect", { x: "0", y: "0", width: "2500", height: "2500", fill: "white" }),
|
|
2713
|
+
/* @__PURE__ */ jsx("circle", { cx: "855", cy: "1715", r: "190", fill: "black" }),
|
|
2714
|
+
/* @__PURE__ */ jsx("circle", { cx: "855", cy: "1715", r: "50", fill: "white" }),
|
|
2715
|
+
/* @__PURE__ */ jsx("circle", { cx: "1665", cy: "1700", r: "190", fill: "black" }),
|
|
2716
|
+
/* @__PURE__ */ jsx("circle", { cx: "1665", cy: "1700", r: "50", fill: "white" })
|
|
2717
|
+
] }) }) }),
|
|
2718
|
+
/* @__PURE__ */ jsxs("g", { mask: `url(#${maskId})`, children: [
|
|
2719
|
+
/* @__PURE__ */ jsx(
|
|
2720
|
+
"g",
|
|
2721
|
+
{
|
|
2722
|
+
transform: "translate(0,250) scale(0.1,-0.1)",
|
|
2723
|
+
fill: "currentColor",
|
|
2724
|
+
stroke: "currentColor",
|
|
2725
|
+
strokeWidth: "100",
|
|
2726
|
+
children: /* @__PURE__ */ jsx("path", { d: "M1038 2434 c-217 -39 -406 -154 -522 -318 -121 -170 -176 -376 -103 -384 l27 -3 0 -106 c0 -88 -3 -108 -17 -118 -15 -11 -16 -18 -5 -66 44 -188 209 -369 420 -459 l65 -28 -74 -7 c-283 -26 -444 -152 -535 -418 -70 -204 -73 -507 -5 -507 4 0 12 75 19 168 18 263 68 419 167 530 78 87 224 162 263 134 9 -6 43 -26 76 -43 224 -117 802 -95 948 38 38 34 165 -22 253 -111 117 -119 168 -268 187 -549 6 -92 15 -167 19 -167 89 0 53 415 -54 627 -88 173 -238 270 -458 295 l-99 11 75 32 c201 88 367 274 406 454 10 47 9 56 -5 66 -13 10 -16 32 -16 118 l0 106 28 3 c91 10 -12 297 -165 459 -202 214 -544 307 -895 243z m472 -84 c170 -43 323 -140 416 -264 47 -61 117 -197 128 -248 l6 -28 -65 0 c-64 0 -65 1 -78 33 -43 102 -109 136 -262 137 l-110 0 -38 -40 c-25 -27 -46 -40 -65 -41 -134 -5 -394 1 -410 10 -11 6 -30 24 -42 41 l-21 30 -112 0 c-156 -1 -219 -33 -262 -136 -14 -34 -14 -34 -80 -34 -76 0 -74 -7 -30 103 96 243 311 406 595 452 118 20 319 13 430 -15z m-561 -505 c97 -50 126 -174 61 -263 -118 -163 -380 -23 -309 165 35 93 162 143 248 98z m799 -15 c129 -96 69 -304 -92 -318 -189 -16 -265 218 -106 326 48 33 149 29 198 -8z m272 -389 c0 -23 -45 -110 -86 -168 -245 -343 -856 -408 -1231 -130 -90 67 -213 236 -213 294 0 11 132 13 765 13 457 0 765 -4 765 -9z" })
|
|
2727
|
+
}
|
|
2728
|
+
),
|
|
2729
|
+
/* @__PURE__ */ jsxs("g", { transform: "translate(0,250) scale(0.1,-0.1)", fill: "currentColor", stroke: "none", children: [
|
|
2730
|
+
/* @__PURE__ */ jsx("path", { d: "M785 1777 c-60 -60 -59 -134 1 -186 92 -82 236 9 204 128 -25 93 -138 125 -205 58z m161 -29 c7 -22 -19 -52 -40 -45 -21 7 -30 35 -17 51 19 23 48 20 57 -6z" }),
|
|
2731
|
+
/* @__PURE__ */ jsx("path", { d: "M1591 1803 c-128 -67 -85 -243 60 -243 83 0 141 99 105 178 -32 69 -103 97 -165 65z m127 -59 c4 -25 -19 -47 -41 -38 -22 8 -30 34 -16 51 17 20 53 12 57 -13z" }),
|
|
2732
|
+
/* @__PURE__ */ jsx("path", { d: "M843 1347 c-9 -15 9 -63 41 -108 148 -202 565 -209 730 -12 37 44 60 103 47 116 -13 13 -810 17 -818 4z" })
|
|
2733
|
+
] })
|
|
2734
|
+
] })
|
|
2735
|
+
]
|
|
2736
|
+
}
|
|
2737
|
+
);
|
|
2738
|
+
};
|
|
2739
|
+
function getDocumentTitle(document2, defaultValue = "") {
|
|
2740
|
+
if (!document2) return defaultValue;
|
|
2741
|
+
return document2.doc_metadata?.title || document2.file_name || defaultValue;
|
|
2742
|
+
}
|
|
2743
|
+
var MAX_LABEL_CHARS = 30;
|
|
2744
|
+
function clampLabel(text) {
|
|
2745
|
+
return text.length > MAX_LABEL_CHARS ? `${text.slice(0, MAX_LABEL_CHARS).trimEnd()}\u2026` : text;
|
|
2746
|
+
}
|
|
2747
|
+
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "webp"]);
|
|
2748
|
+
var VIDEO_EXTENSIONS = /* @__PURE__ */ new Set(["mp4", "mpeg", "mpg", "webm", "mov", "avi", "mkv"]);
|
|
2749
|
+
var AUDIO_EXTENSIONS = /* @__PURE__ */ new Set(["mp3", "wav", "m4a", "aac", "ogg", "flac"]);
|
|
2750
|
+
var EMAIL_EXTENSIONS = /* @__PURE__ */ new Set(["eml", "msg"]);
|
|
2751
|
+
function getDocIcon(fileName, iconSize = 14) {
|
|
2752
|
+
const ext = fileName?.split(".").pop()?.toLowerCase();
|
|
2753
|
+
if (ext && VIDEO_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(VidIcon, { size: iconSize, className: "flex-shrink-0" });
|
|
2754
|
+
if (ext && AUDIO_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(AudIcon, { size: iconSize, className: "flex-shrink-0" });
|
|
2755
|
+
if (ext && IMAGE_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(ImgIcon, { size: iconSize, className: "flex-shrink-0" });
|
|
2756
|
+
if (ext && EMAIL_EXTENSIONS.has(ext)) return /* @__PURE__ */ jsx(EmlIcon, { size: iconSize, className: "flex-shrink-0" });
|
|
2757
|
+
return /* @__PURE__ */ jsx(PdfIcon, { size: iconSize, className: "flex-shrink-0" });
|
|
2758
|
+
}
|
|
2759
|
+
function DocumentEntity({
|
|
2760
|
+
doc,
|
|
2761
|
+
icon,
|
|
2762
|
+
size = "sm",
|
|
2763
|
+
labelMaxWidth,
|
|
2764
|
+
labelClassName,
|
|
2765
|
+
onClick,
|
|
2766
|
+
onIconClick,
|
|
2767
|
+
viewing,
|
|
2768
|
+
iconBadge,
|
|
2769
|
+
actions,
|
|
2770
|
+
tooltipContent,
|
|
2771
|
+
className,
|
|
2772
|
+
fullWidth,
|
|
2773
|
+
noClamp,
|
|
2774
|
+
"data-testid": testId
|
|
2775
|
+
}) {
|
|
2776
|
+
const title = getDocumentTitle(doc);
|
|
2777
|
+
const ext = doc.file_name?.split(".").pop()?.toLowerCase();
|
|
2778
|
+
const iconSize = size === "base" ? 16 : 14;
|
|
2779
|
+
const eyeSizeClass = size === "base" ? "h-4 w-4" : "h-3.5 w-3.5";
|
|
2780
|
+
const baseIcon = icon ?? getDocIcon(doc.file_name, iconSize);
|
|
2781
|
+
const displayIcon = viewing || iconBadge ? /* @__PURE__ */ jsxs("span", { className: "relative inline-flex flex-shrink-0 items-center justify-center", children: [
|
|
2782
|
+
viewing ? /* @__PURE__ */ jsx(Eye, { className: cn("text-primary-foreground", eyeSizeClass) }) : baseIcon,
|
|
2783
|
+
iconBadge
|
|
2784
|
+
] }) : baseIcon;
|
|
2785
|
+
const defaultTooltip = /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 text-xs max-w-[440px]", children: [
|
|
2786
|
+
doc.folder && // `flex-wrap` so a deep folder path wraps WITHIN the balloon instead of
|
|
2787
|
+
// spilling out of it (each path segment is atomic and wraps as a unit;
|
|
2788
|
+
// `min-w-0` + `break-all` lets a single over-long segment break too).
|
|
2789
|
+
/* @__PURE__ */ jsxs("span", { className: "flex flex-wrap items-center gap-0.5 text-muted-foreground", children: [
|
|
2790
|
+
/* @__PURE__ */ jsx(FolderOpen, { className: "h-3 w-3 text-yellow-600 shrink-0" }),
|
|
2791
|
+
doc.folder.split("/").map((part, i, arr) => /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-0.5", children: [
|
|
2792
|
+
i > 0 && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/50 mx-0.5", children: "/" }),
|
|
2793
|
+
/* @__PURE__ */ jsx("span", { className: `break-all ${i < arr.length - 1 ? "text-muted-foreground/70" : ""}`, children: part })
|
|
2794
|
+
] }, i))
|
|
2795
|
+
] }),
|
|
2796
|
+
/* @__PURE__ */ jsxs("span", { className: "font-medium break-words", children: [
|
|
2797
|
+
title,
|
|
2798
|
+
ext ? `.${ext}` : ""
|
|
2799
|
+
] })
|
|
2800
|
+
] });
|
|
2801
|
+
return /* @__PURE__ */ jsx(
|
|
2802
|
+
EntityPill,
|
|
2803
|
+
{
|
|
2804
|
+
icon: displayIcon,
|
|
2805
|
+
size,
|
|
2806
|
+
label: fullWidth || noClamp ? title : clampLabel(title),
|
|
2807
|
+
labelMaxWidth: labelMaxWidth ?? "max-w-[140px]",
|
|
2808
|
+
labelClassName,
|
|
2809
|
+
fullWidth,
|
|
2810
|
+
onClick,
|
|
2811
|
+
onIconClick,
|
|
2812
|
+
moreContent: actions,
|
|
2813
|
+
className,
|
|
2814
|
+
highlight: viewing,
|
|
2815
|
+
"data-testid": testId,
|
|
2816
|
+
tooltipContent: tooltipContent ?? defaultTooltip
|
|
2817
|
+
}
|
|
2818
|
+
);
|
|
2819
|
+
}
|
|
2820
|
+
var VARIANT_STYLES = {
|
|
2821
|
+
"mine-paid": {
|
|
2822
|
+
pill: "bg-primary/10 text-primary border-border/60",
|
|
2823
|
+
icon: "text-primary"
|
|
2824
|
+
},
|
|
2825
|
+
other: {
|
|
2826
|
+
pill: "bg-secondary/10 text-secondary border-border/60",
|
|
2827
|
+
icon: "text-secondary"
|
|
2828
|
+
},
|
|
2829
|
+
"mine-free": {
|
|
2830
|
+
pill: "bg-muted-foreground/10 text-muted-foreground border-border/60",
|
|
2831
|
+
icon: "text-muted-foreground"
|
|
2832
|
+
},
|
|
2833
|
+
common: {
|
|
2834
|
+
pill: "",
|
|
2835
|
+
icon: "text-muted-foreground"
|
|
2836
|
+
}
|
|
2837
|
+
};
|
|
2838
|
+
function resolveVariant(relation, paid, hasCollaborators) {
|
|
2839
|
+
if (relation === "common") return "common";
|
|
2840
|
+
if (relation === "other") return "other";
|
|
2841
|
+
if (relation === "mine") return paid ? "mine-paid" : "mine-free";
|
|
2842
|
+
if (paid) return hasCollaborators ? "other" : "mine-paid";
|
|
2843
|
+
return "mine-free";
|
|
2844
|
+
}
|
|
2845
|
+
function ProjectEntity({
|
|
2846
|
+
name,
|
|
2847
|
+
label,
|
|
2848
|
+
icon,
|
|
2849
|
+
subscription = "none",
|
|
2850
|
+
hasCollaborators = false,
|
|
2851
|
+
size = "sm",
|
|
2852
|
+
className,
|
|
2853
|
+
onClick,
|
|
2854
|
+
relation,
|
|
2855
|
+
isPaid,
|
|
2856
|
+
tooltipContent
|
|
2857
|
+
}) {
|
|
2858
|
+
const paid = isPaid ?? (subscription === "active" || subscription === "past_due" || subscription === "dev");
|
|
2859
|
+
const variant = resolveVariant(relation, paid, hasCollaborators);
|
|
2860
|
+
const { pill, icon: iconClass } = VARIANT_STYLES[variant];
|
|
2861
|
+
const iconSizeClass = size === "base" ? "h-4 w-4" : "h-3.5 w-3.5";
|
|
2862
|
+
const iconNode = icon ?? /* @__PURE__ */ jsx(CreditCard, { className: cn(iconSizeClass, iconClass) });
|
|
2863
|
+
return /* @__PURE__ */ jsx(
|
|
2864
|
+
EntityPill,
|
|
2865
|
+
{
|
|
2866
|
+
icon: iconNode,
|
|
2867
|
+
label: label ?? name,
|
|
2868
|
+
size,
|
|
2869
|
+
shape: "rounded",
|
|
2870
|
+
className: cn(pill, className),
|
|
2871
|
+
onClick,
|
|
2872
|
+
tooltipContent
|
|
2873
|
+
}
|
|
2874
|
+
);
|
|
2875
|
+
}
|
|
2876
|
+
var sizeClasses = {
|
|
2877
|
+
xs: "h-5 w-5",
|
|
2878
|
+
sm: "h-6 w-6",
|
|
2879
|
+
md: "h-8 w-8",
|
|
2880
|
+
lg: "h-10 w-10"
|
|
2881
|
+
};
|
|
2882
|
+
var textSizeClasses = {
|
|
2883
|
+
xs: "text-xs",
|
|
2884
|
+
sm: "text-xs",
|
|
2885
|
+
md: "text-xs",
|
|
2886
|
+
lg: "text-sm"
|
|
2887
|
+
};
|
|
2888
|
+
var presenceDotClasses = {
|
|
2889
|
+
xs: "w-2 h-2 border",
|
|
2890
|
+
sm: "w-2.5 h-2.5 border",
|
|
2891
|
+
md: "w-3 h-3 border-2",
|
|
2892
|
+
lg: "w-3.5 h-3.5 border-2"
|
|
2893
|
+
};
|
|
2894
|
+
var presencePositionClasses = {
|
|
2895
|
+
xs: "-right-1 bottom-0",
|
|
2896
|
+
sm: "-right-1 bottom-0",
|
|
2897
|
+
md: "-right-1.5 -bottom-0.5",
|
|
2898
|
+
lg: "-right-1.5 -bottom-0.5"
|
|
2899
|
+
};
|
|
2900
|
+
var PRESENCE_LABELS = {
|
|
2901
|
+
connected: "Online",
|
|
2902
|
+
connecting: "Connecting",
|
|
2903
|
+
disconnected: "Offline",
|
|
2904
|
+
error: "Connection problem",
|
|
2905
|
+
hidden: "Status hidden"
|
|
2906
|
+
};
|
|
2907
|
+
var presenceColorClasses = {
|
|
2908
|
+
connected: "bg-status-online",
|
|
2909
|
+
connecting: "bg-status-connecting",
|
|
2910
|
+
disconnected: "bg-status-away",
|
|
2911
|
+
error: "bg-status-busy",
|
|
2912
|
+
hidden: "bg-status-offline"
|
|
2913
|
+
};
|
|
2914
|
+
var UserEntity = memo(function UserEntity2({
|
|
2915
|
+
size = "md",
|
|
2916
|
+
variant = "pill",
|
|
2917
|
+
className,
|
|
2918
|
+
showTooltip = true,
|
|
2919
|
+
interactive = true,
|
|
2920
|
+
hasUnreadMessages = false,
|
|
2921
|
+
initials = "",
|
|
2922
|
+
displayName = "",
|
|
2923
|
+
picture,
|
|
2924
|
+
colorClass = "",
|
|
2925
|
+
isAgent = false,
|
|
2926
|
+
agentStyle,
|
|
2927
|
+
avatarStyle,
|
|
2928
|
+
isMe = false,
|
|
2929
|
+
displayStatus,
|
|
2930
|
+
onClick,
|
|
2931
|
+
tooltipContent,
|
|
2932
|
+
empty = false
|
|
2933
|
+
}) {
|
|
2934
|
+
if (empty) {
|
|
2935
|
+
return /* @__PURE__ */ jsx(
|
|
2936
|
+
Avatar,
|
|
2937
|
+
{
|
|
2938
|
+
className: cn(sizeClasses[size], "border border-border", className),
|
|
2939
|
+
"data-testid": "user-entity",
|
|
2940
|
+
children: /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-status-empty text-muted-foreground text-xs font-semibold", children: "?" })
|
|
2941
|
+
}
|
|
2942
|
+
);
|
|
2943
|
+
}
|
|
2944
|
+
const agentBadge = isAgent ? /* @__PURE__ */ jsx(ArbiBotHeadIcon, { className: "w-3.5 h-3.5 text-muted-foreground" }) : void 0;
|
|
2945
|
+
const canMessage = interactive && !isMe && !isAgent;
|
|
2946
|
+
const showUnread = hasUnreadMessages && !isMe && !isAgent;
|
|
2947
|
+
const surfaceStyle = avatarStyle ?? agentStyle;
|
|
2948
|
+
const avatarCore = /* @__PURE__ */ jsxs(
|
|
2949
|
+
Avatar,
|
|
2950
|
+
{
|
|
2951
|
+
className: cn(
|
|
2952
|
+
sizeClasses[size],
|
|
2953
|
+
isAgent ? "rounded-full border-2 border-dashed" : "border border-white"
|
|
2954
|
+
),
|
|
2955
|
+
style: surfaceStyle,
|
|
2956
|
+
"data-testid": "user-entity",
|
|
2957
|
+
children: [
|
|
2958
|
+
picture && /* @__PURE__ */ jsx(AvatarImage, { src: picture, alt: initials }),
|
|
2959
|
+
/* @__PURE__ */ jsx(
|
|
2960
|
+
AvatarFallback,
|
|
2961
|
+
{
|
|
2962
|
+
className: cn(
|
|
2963
|
+
textSizeClasses[size],
|
|
2964
|
+
"font-semibold leading-none",
|
|
2965
|
+
isAgent ? "rounded-full bg-transparent" : `text-white ${colorClass}`
|
|
2966
|
+
),
|
|
2967
|
+
style: surfaceStyle,
|
|
2968
|
+
children: initials
|
|
2969
|
+
}
|
|
2970
|
+
)
|
|
2971
|
+
]
|
|
2972
|
+
}
|
|
2973
|
+
);
|
|
2974
|
+
const statusDot = showUnread || displayStatus ? /* @__PURE__ */ jsx(
|
|
2975
|
+
"span",
|
|
2976
|
+
{
|
|
2977
|
+
className: cn(
|
|
2978
|
+
"absolute rounded-full border-white",
|
|
2979
|
+
presenceDotClasses[size],
|
|
2980
|
+
presencePositionClasses[size],
|
|
2981
|
+
!showUnread && displayStatus ? presenceColorClasses[displayStatus] : ""
|
|
2982
|
+
),
|
|
2983
|
+
style: showUnread ? { backgroundColor: "#00adef" } : void 0,
|
|
2984
|
+
"data-testid": "user-entity-presence",
|
|
2985
|
+
role: "img",
|
|
2986
|
+
"aria-label": showUnread ? "Unread messages" : PRESENCE_LABELS[displayStatus],
|
|
2987
|
+
title: showUnread ? "Unread messages" : PRESENCE_LABELS[displayStatus]
|
|
2988
|
+
}
|
|
2989
|
+
) : null;
|
|
2990
|
+
const avatarElement = statusDot ? /* @__PURE__ */ jsxs(
|
|
2991
|
+
"div",
|
|
2992
|
+
{
|
|
2993
|
+
className: cn(
|
|
2994
|
+
"relative inline-block",
|
|
2995
|
+
sizeClasses[size],
|
|
2996
|
+
variant === "pill" ? "" : className
|
|
2997
|
+
),
|
|
2998
|
+
children: [
|
|
2999
|
+
avatarCore,
|
|
3000
|
+
statusDot
|
|
3001
|
+
]
|
|
3002
|
+
}
|
|
3003
|
+
) : /* @__PURE__ */ jsx("div", { className: cn("inline-block", variant === "pill" ? "" : className), children: avatarCore });
|
|
3004
|
+
const pillAvatar = (
|
|
3005
|
+
// shrink-0: when the pill is squeezed the NAME truncates away — the avatar
|
|
3006
|
+
// must never collapse under it and overflow onto neighbouring text.
|
|
3007
|
+
/* @__PURE__ */ jsxs("span", { className: cn("relative inline-block shrink-0", sizeClasses[size]), children: [
|
|
3008
|
+
/* @__PURE__ */ jsx("span", { className: cn("block transition-opacity", canMessage && "group-hover/pill:opacity-0"), children: avatarCore }),
|
|
3009
|
+
canMessage && /* @__PURE__ */ jsx(
|
|
3010
|
+
"span",
|
|
3011
|
+
{
|
|
3012
|
+
"aria-hidden": true,
|
|
3013
|
+
className: "absolute inset-0 flex items-center justify-center rounded-full bg-muted text-foreground opacity-0 transition-opacity group-hover/pill:opacity-100",
|
|
3014
|
+
children: /* @__PURE__ */ jsx(MessageCircleMore, { className: size === "xs" ? "h-3 w-3" : "h-4 w-4" })
|
|
3015
|
+
}
|
|
3016
|
+
),
|
|
3017
|
+
statusDot
|
|
3018
|
+
] })
|
|
3019
|
+
);
|
|
3020
|
+
const resolvedTooltip = showTooltip ? tooltipContent : void 0;
|
|
3021
|
+
if (variant === "pill") {
|
|
3022
|
+
const row = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3023
|
+
pillAvatar,
|
|
3024
|
+
displayName && /* @__PURE__ */ jsx("span", { className: "min-w-0 max-w-[320px] truncate text-sm leading-tight", children: displayName }),
|
|
3025
|
+
agentBadge
|
|
3026
|
+
] });
|
|
3027
|
+
const rowClass = "group/pill inline-flex min-w-0 items-center gap-2";
|
|
3028
|
+
const clickable = interactive && !!onClick;
|
|
3029
|
+
const clickableClass = "relative cursor-pointer rounded-md px-1 py-0.5 -mx-1 transition-colors hover:bg-muted/60 pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:-inset-y-3 pointer-coarse:after:content-['']";
|
|
3030
|
+
if (resolvedTooltip) {
|
|
3031
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3032
|
+
/* @__PURE__ */ jsx(
|
|
3033
|
+
TooltipTrigger,
|
|
3034
|
+
{
|
|
3035
|
+
type: "button",
|
|
3036
|
+
onClick: clickable ? onClick : void 0,
|
|
3037
|
+
onFocusCapture: (e) => e.stopPropagation(),
|
|
3038
|
+
className: cn(rowClass, clickable && clickableClass, className),
|
|
3039
|
+
"data-testid": "user-entity-pill",
|
|
3040
|
+
children: row
|
|
3041
|
+
}
|
|
3042
|
+
),
|
|
3043
|
+
/* @__PURE__ */ jsx(TooltipContent, { className: "p-2", children: resolvedTooltip })
|
|
3044
|
+
] });
|
|
3045
|
+
}
|
|
3046
|
+
if (clickable) {
|
|
3047
|
+
return /* @__PURE__ */ jsx(
|
|
3048
|
+
"button",
|
|
3049
|
+
{
|
|
3050
|
+
type: "button",
|
|
3051
|
+
onClick,
|
|
3052
|
+
className: cn(rowClass, clickableClass, className),
|
|
3053
|
+
"data-testid": "user-entity-pill",
|
|
3054
|
+
children: row
|
|
3055
|
+
}
|
|
3056
|
+
);
|
|
3057
|
+
}
|
|
3058
|
+
return /* @__PURE__ */ jsx("span", { className: cn(rowClass, className), "data-testid": "user-entity-pill", children: row });
|
|
3059
|
+
}
|
|
3060
|
+
if (showTooltip) {
|
|
3061
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3062
|
+
/* @__PURE__ */ jsx(
|
|
3063
|
+
TooltipTrigger,
|
|
3064
|
+
{
|
|
3065
|
+
onFocusCapture: (e) => e.stopPropagation(),
|
|
3066
|
+
className: "touch-hit inline-flex",
|
|
3067
|
+
children: avatarElement
|
|
3068
|
+
}
|
|
3069
|
+
),
|
|
3070
|
+
/* @__PURE__ */ jsx(TooltipContent, { className: "p-2", children: tooltipContent })
|
|
3071
|
+
] });
|
|
3072
|
+
}
|
|
3073
|
+
return avatarElement;
|
|
3074
|
+
});
|
|
3075
|
+
function AgentBadge({ className }) {
|
|
3076
|
+
return /* @__PURE__ */ jsxs(
|
|
3077
|
+
"span",
|
|
3078
|
+
{
|
|
3079
|
+
"data-testid": "agent-badge",
|
|
3080
|
+
className: cn(
|
|
3081
|
+
"inline-flex shrink-0 items-center gap-1 rounded-full border border-ai-accent/50",
|
|
3082
|
+
"bg-ai-accent-soft px-2 py-0.5 text-xs font-bold uppercase tracking-wider text-ai-accent",
|
|
3083
|
+
className
|
|
3084
|
+
),
|
|
3085
|
+
children: [
|
|
3086
|
+
/* @__PURE__ */ jsx(ArbiBotHeadIcon, { size: 14, className: "text-ai-accent" }),
|
|
3087
|
+
"Agent"
|
|
3088
|
+
]
|
|
3089
|
+
}
|
|
3090
|
+
);
|
|
3091
|
+
}
|
|
3092
|
+
var PRESENCE_WORDS = {
|
|
3093
|
+
connected: "Online",
|
|
3094
|
+
connecting: "Connecting",
|
|
3095
|
+
disconnected: "Offline",
|
|
3096
|
+
error: "Connection problem",
|
|
3097
|
+
hidden: null
|
|
3098
|
+
};
|
|
3099
|
+
function PresenceLabel({
|
|
3100
|
+
status,
|
|
3101
|
+
className
|
|
3102
|
+
}) {
|
|
3103
|
+
if (!status) return null;
|
|
3104
|
+
const word = PRESENCE_WORDS[status];
|
|
3105
|
+
if (!word) return null;
|
|
3106
|
+
const online = status === "connected";
|
|
3107
|
+
return /* @__PURE__ */ jsxs(
|
|
3108
|
+
"span",
|
|
3109
|
+
{
|
|
3110
|
+
"data-testid": "presence-label",
|
|
3111
|
+
className: cn("inline-flex shrink-0 items-center gap-1 text-xs", className),
|
|
3112
|
+
children: [
|
|
3113
|
+
/* @__PURE__ */ jsx(
|
|
3114
|
+
"span",
|
|
3115
|
+
{
|
|
3116
|
+
className: cn(
|
|
3117
|
+
"size-1.5 rounded-full",
|
|
3118
|
+
online ? "bg-status-online" : "bg-muted-foreground/50"
|
|
3119
|
+
),
|
|
3120
|
+
"aria-hidden": "true"
|
|
3121
|
+
}
|
|
3122
|
+
),
|
|
3123
|
+
/* @__PURE__ */ jsx("span", { className: online ? "font-medium text-status-online" : "text-muted-foreground", children: word })
|
|
3124
|
+
]
|
|
3125
|
+
}
|
|
3126
|
+
);
|
|
3127
|
+
}
|
|
3128
|
+
var PACKAGE_BADGE_VARIANTS = [
|
|
3129
|
+
"default",
|
|
3130
|
+
"accent",
|
|
3131
|
+
"secondary",
|
|
3132
|
+
"destructive",
|
|
3133
|
+
"outline"
|
|
3134
|
+
];
|
|
3135
|
+
function isPackageBadgeVariant(v) {
|
|
3136
|
+
return PACKAGE_BADGE_VARIANTS.some((known) => known === v);
|
|
3137
|
+
}
|
|
3138
|
+
function PackageStatusBadge({ variant, ...rest }) {
|
|
3139
|
+
return /* @__PURE__ */ jsx(Badge, { variant: isPackageBadgeVariant(variant) ? variant : "outline", ...rest });
|
|
3140
|
+
}
|
|
3141
|
+
var registry = {
|
|
3142
|
+
variants: {},
|
|
3143
|
+
fallback: "outline",
|
|
3144
|
+
Badge: PackageStatusBadge
|
|
3145
|
+
};
|
|
3146
|
+
function configureStatusRegistry(map, opts) {
|
|
3147
|
+
Object.assign(registry.variants, map);
|
|
3148
|
+
if (opts?.fallback) registry.fallback = opts.fallback;
|
|
3149
|
+
if (opts?.Badge) registry.Badge = opts.Badge;
|
|
3150
|
+
}
|
|
3151
|
+
function getStatusVariant(status) {
|
|
3152
|
+
return registry.variants[status] ?? registry.fallback;
|
|
3153
|
+
}
|
|
3154
|
+
function StatusPill({ status, label, variant, className, testId }) {
|
|
3155
|
+
const Badge2 = registry.Badge;
|
|
3156
|
+
return /* @__PURE__ */ jsx(Badge2, { variant: variant ?? getStatusVariant(status), className, "data-testid": testId, children: label ?? status });
|
|
3157
|
+
}
|
|
3158
|
+
var RAG_LABELS = { red: "At risk", amber: "Attention", green: "On track" };
|
|
3159
|
+
function configureRagLabels(labels) {
|
|
3160
|
+
RAG_LABELS = { ...RAG_LABELS, ...labels };
|
|
3161
|
+
}
|
|
3162
|
+
function RagDot({
|
|
3163
|
+
rag,
|
|
3164
|
+
withLabel,
|
|
3165
|
+
className
|
|
3166
|
+
}) {
|
|
3167
|
+
const color = rag === "red" ? "bg-destructive" : rag === "amber" ? "bg-warning" : "bg-success";
|
|
3168
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex items-center gap-1.5", className), "data-testid": `rag-${rag}`, children: [
|
|
3169
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-2 rounded-full", color) }),
|
|
3170
|
+
withLabel && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: RAG_LABELS[rag] })
|
|
3171
|
+
] });
|
|
3172
|
+
}
|
|
3173
|
+
var ENTITY_MAPPINGS = {
|
|
3174
|
+
PRODUCT: {
|
|
3175
|
+
NAMES: {
|
|
3176
|
+
SINGULAR: "ARBI Docs"
|
|
3177
|
+
},
|
|
3178
|
+
ICONS: {
|
|
3179
|
+
DEFAULT: MessageSquareLock
|
|
3180
|
+
}
|
|
3181
|
+
},
|
|
3182
|
+
SECTION: {
|
|
3183
|
+
NAMES: {
|
|
3184
|
+
SINGULAR: "Section"
|
|
3185
|
+
},
|
|
3186
|
+
ICONS: {
|
|
3187
|
+
DEFAULT: ChevronsDown
|
|
3188
|
+
}
|
|
3189
|
+
},
|
|
3190
|
+
WORKSPACE: {
|
|
3191
|
+
NAMES: {
|
|
3192
|
+
SINGULAR: "Workspace",
|
|
3193
|
+
PLURAL: "Workspaces"
|
|
3194
|
+
},
|
|
3195
|
+
ICONS: {
|
|
3196
|
+
DEFAULT: SquareM,
|
|
3197
|
+
NEW: SquarePlus,
|
|
3198
|
+
LIST: LayoutGrid,
|
|
3199
|
+
SETTINGS: Columns3Cog
|
|
3200
|
+
}
|
|
3201
|
+
},
|
|
3202
|
+
CONVERSATION: {
|
|
3203
|
+
NAMES: {
|
|
3204
|
+
SINGULAR: "Chat",
|
|
3205
|
+
PLURAL: "Chats",
|
|
3206
|
+
NEW: "New ARBI Chat"
|
|
3207
|
+
},
|
|
3208
|
+
ICONS: {
|
|
3209
|
+
DEFAULT: MessagesSquare,
|
|
3210
|
+
OFF: MessageSquareOff,
|
|
3211
|
+
ACTIVE: MessageSquareText,
|
|
3212
|
+
NEW: MessageSquarePlus,
|
|
3213
|
+
LIST: MessageSquareMore
|
|
3214
|
+
}
|
|
3215
|
+
},
|
|
3216
|
+
DOCUMENT: {
|
|
3217
|
+
NAMES: {
|
|
3218
|
+
SINGULAR: "File",
|
|
3219
|
+
PLURAL: "Files"
|
|
3220
|
+
},
|
|
3221
|
+
ICONS: {
|
|
3222
|
+
DEFAULT: FolderOpen,
|
|
3223
|
+
OFF: CaptionsOff
|
|
3224
|
+
}
|
|
3225
|
+
},
|
|
3226
|
+
VIEWER: {
|
|
3227
|
+
NAMES: {
|
|
3228
|
+
SINGULAR: "Viewer",
|
|
3229
|
+
PLURAL: "Viewers"
|
|
3230
|
+
},
|
|
3231
|
+
ICONS: {
|
|
3232
|
+
DEFAULT: Eye,
|
|
3233
|
+
OFF: EyeOff
|
|
3234
|
+
}
|
|
3235
|
+
},
|
|
3236
|
+
TAG: {
|
|
3237
|
+
NAMES: {
|
|
3238
|
+
SINGULAR: "Field",
|
|
3239
|
+
PLURAL: "Fields"
|
|
3240
|
+
},
|
|
3241
|
+
ICONS: {
|
|
3242
|
+
DEFAULT: Hash,
|
|
3243
|
+
NEW: FolderPlus
|
|
3244
|
+
}
|
|
3245
|
+
},
|
|
3246
|
+
ANNOTATION: {
|
|
3247
|
+
NAMES: {
|
|
3248
|
+
SINGULAR: "Annotation",
|
|
3249
|
+
PLURAL: "Annotations"
|
|
3250
|
+
},
|
|
3251
|
+
ICONS: {
|
|
3252
|
+
DEFAULT: StickyNote,
|
|
3253
|
+
NEW: StickyNote
|
|
3254
|
+
}
|
|
3255
|
+
},
|
|
3256
|
+
// Workspace knowledge the assistant retains and recalls — durable free text,
|
|
3257
|
+
// optionally grounded in source passages. Distinct from ANNOTATION, which is
|
|
3258
|
+
// attached TO a document field; a NOTE is workspace-scoped and stands alone.
|
|
3259
|
+
// Stored server-side as `memories` (mem-*); "Note" is the user-facing name.
|
|
3260
|
+
NOTE: {
|
|
3261
|
+
NAMES: {
|
|
3262
|
+
SINGULAR: "Note",
|
|
3263
|
+
PLURAL: "Notes"
|
|
3264
|
+
},
|
|
3265
|
+
ICONS: {
|
|
3266
|
+
DEFAULT: NotebookText,
|
|
3267
|
+
NEW: NotebookPen
|
|
3268
|
+
}
|
|
3269
|
+
},
|
|
3270
|
+
USER: {
|
|
3271
|
+
NAMES: {
|
|
3272
|
+
SINGULAR: "User",
|
|
3273
|
+
PLURAL: "Users"
|
|
3274
|
+
},
|
|
3275
|
+
ICONS: {
|
|
3276
|
+
DEFAULT: User,
|
|
3277
|
+
NEW: UserPlus,
|
|
3278
|
+
SETTINGS: Settings2
|
|
3279
|
+
}
|
|
3280
|
+
},
|
|
3281
|
+
WORKSPACEUSER: {
|
|
3282
|
+
NAMES: {
|
|
3283
|
+
SINGULAR: "Member",
|
|
3284
|
+
PLURAL: "Members"
|
|
3285
|
+
},
|
|
3286
|
+
ICONS: {
|
|
3287
|
+
DEFAULT: User,
|
|
3288
|
+
PLURAL: Users,
|
|
3289
|
+
NEW: UserPlus,
|
|
3290
|
+
SETTINGS: Settings2
|
|
3291
|
+
}
|
|
3292
|
+
},
|
|
3293
|
+
CONTACT: {
|
|
3294
|
+
NAMES: {
|
|
3295
|
+
SINGULAR: "Contact",
|
|
3296
|
+
PLURAL: "Contacts"
|
|
3297
|
+
},
|
|
3298
|
+
ICONS: {
|
|
3299
|
+
// A starred person, not an address-book card: contacts here are the
|
|
3300
|
+
// people you talk to, and the star reads as "your people".
|
|
3301
|
+
DEFAULT: UserStar,
|
|
3302
|
+
NEW: UserPlus
|
|
3303
|
+
}
|
|
3304
|
+
},
|
|
3305
|
+
TASK: {
|
|
3306
|
+
NAMES: {
|
|
3307
|
+
SINGULAR: "Job",
|
|
3308
|
+
PLURAL: "Jobs"
|
|
3309
|
+
},
|
|
3310
|
+
ICONS: {
|
|
3311
|
+
DEFAULT: ClipboardList
|
|
3312
|
+
}
|
|
3313
|
+
},
|
|
3314
|
+
PROJECT: {
|
|
3315
|
+
NAMES: {
|
|
3316
|
+
SINGULAR: "Project",
|
|
3317
|
+
PLURAL: "Projects"
|
|
3318
|
+
},
|
|
3319
|
+
ICONS: {
|
|
3320
|
+
DEFAULT: CreditCard
|
|
3321
|
+
}
|
|
3322
|
+
},
|
|
3323
|
+
SKILL: {
|
|
3324
|
+
NAMES: {
|
|
3325
|
+
SINGULAR: "Skill",
|
|
3326
|
+
PLURAL: "Skills"
|
|
3327
|
+
},
|
|
3328
|
+
ICONS: {
|
|
3329
|
+
DEFAULT: Wrench
|
|
3330
|
+
}
|
|
3331
|
+
},
|
|
3332
|
+
ACCOUNT: {
|
|
3333
|
+
NAMES: {
|
|
3334
|
+
SINGULAR: "Account"
|
|
3335
|
+
},
|
|
3336
|
+
ICONS: {
|
|
3337
|
+
DEFAULT: CircleUserRound
|
|
3338
|
+
}
|
|
3339
|
+
},
|
|
3340
|
+
NOTIFICATIONS: {
|
|
3341
|
+
NAMES: {
|
|
3342
|
+
SINGULAR: "Activity",
|
|
3343
|
+
PLURAL: "Activities"
|
|
3344
|
+
},
|
|
3345
|
+
ICONS: {
|
|
3346
|
+
DEFAULT: Bell
|
|
3347
|
+
}
|
|
3348
|
+
},
|
|
3349
|
+
MESSAGE: {
|
|
3350
|
+
NAMES: {
|
|
3351
|
+
SINGULAR: "Message",
|
|
3352
|
+
PLURAL: "Messages"
|
|
3353
|
+
},
|
|
3354
|
+
ICONS: {
|
|
3355
|
+
DEFAULT: MessageSquare
|
|
3356
|
+
}
|
|
3357
|
+
},
|
|
3358
|
+
NOTIFICATION: {
|
|
3359
|
+
NAMES: {
|
|
3360
|
+
SINGULAR: "Notification",
|
|
3361
|
+
PLURAL: "Notifications"
|
|
3362
|
+
},
|
|
3363
|
+
ICONS: {
|
|
3364
|
+
DEFAULT: Bell
|
|
3365
|
+
}
|
|
3366
|
+
},
|
|
3367
|
+
APP: {
|
|
3368
|
+
NAMES: {
|
|
3369
|
+
SINGULAR: "Application",
|
|
3370
|
+
PLURAL: "Applications"
|
|
3371
|
+
},
|
|
3372
|
+
ICONS: {
|
|
3373
|
+
DEFAULT: LayoutGrid,
|
|
3374
|
+
HOME: LayoutGrid,
|
|
3375
|
+
LOGOUT: LogOut,
|
|
3376
|
+
UPLOAD: Upload
|
|
3377
|
+
}
|
|
3378
|
+
},
|
|
3379
|
+
HELP: {
|
|
3380
|
+
NAMES: {
|
|
3381
|
+
SINGULAR: "Help",
|
|
3382
|
+
PLURAL: "Help"
|
|
3383
|
+
},
|
|
3384
|
+
ICONS: {
|
|
3385
|
+
DEFAULT: MessageSquareLock,
|
|
3386
|
+
DOCS: BookOpen,
|
|
3387
|
+
FAQ: FileQuestion,
|
|
3388
|
+
ABOUT: Info
|
|
3389
|
+
}
|
|
3390
|
+
},
|
|
3391
|
+
USERSHIELD: {
|
|
3392
|
+
NAMES: {
|
|
3393
|
+
SINGULAR: "User Shield",
|
|
3394
|
+
PLURAL: "User Shields"
|
|
3395
|
+
},
|
|
3396
|
+
ICONS: {
|
|
3397
|
+
DEFAULT: MessageSquareLock
|
|
3398
|
+
}
|
|
3399
|
+
}
|
|
3400
|
+
};
|
|
3401
|
+
function configureEntityRegistry(overrides) {
|
|
3402
|
+
for (const [type, def] of Object.entries(overrides)) {
|
|
3403
|
+
const target = ENTITY_MAPPINGS[type];
|
|
3404
|
+
if (!target) continue;
|
|
3405
|
+
if (def?.NAMES) Object.assign(target.NAMES, def.NAMES);
|
|
3406
|
+
if (def?.ICONS) Object.assign(target.ICONS, def.ICONS);
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
var getEntityIcon = (entityType, variant = "DEFAULT") => {
|
|
3410
|
+
const icons = ENTITY_MAPPINGS[entityType]?.ICONS;
|
|
3411
|
+
return icons?.[variant] || icons?.DEFAULT;
|
|
3412
|
+
};
|
|
3413
|
+
var getEntityLabel = (entityType, form = "SINGULAR") => {
|
|
3414
|
+
const entityMapping = ENTITY_MAPPINGS[entityType];
|
|
3415
|
+
if (!entityMapping) return "";
|
|
3416
|
+
const names = entityMapping.NAMES;
|
|
3417
|
+
const singularName = names.SINGULAR || "";
|
|
3418
|
+
if (form === "NEW") return names.NEW !== void 0 ? names.NEW : "New " + singularName;
|
|
3419
|
+
if (form === "SHORT")
|
|
3420
|
+
return names.SHORT !== void 0 ? names.SHORT : singularName.substring(0, 3) + ".";
|
|
3421
|
+
if (form === "PLURAL") return names.PLURAL !== void 0 ? names.PLURAL : singularName + "s";
|
|
3422
|
+
return singularName;
|
|
3423
|
+
};
|
|
3424
|
+
var EntityIcon = ({ entityType, variant = "DEFAULT", ...props }) => {
|
|
3425
|
+
const IconComponent = getEntityIcon(entityType, variant);
|
|
3426
|
+
return IconComponent ? React2__default.createElement(IconComponent, props) : null;
|
|
3427
|
+
};
|
|
3428
|
+
var VISIBILITY_ICONS = {
|
|
3429
|
+
PRIVATE: MessageSquareLock,
|
|
3430
|
+
SHARED: Users
|
|
3431
|
+
};
|
|
3432
|
+
var VisibilityIcon = ({
|
|
3433
|
+
isShared,
|
|
3434
|
+
...props
|
|
3435
|
+
}) => {
|
|
3436
|
+
const IconComponent = isShared ? VISIBILITY_ICONS.SHARED : VISIBILITY_ICONS.PRIVATE;
|
|
3437
|
+
return React2__default.createElement(IconComponent, props);
|
|
3438
|
+
};
|
|
3439
|
+
|
|
3440
|
+
// src/entities/colors.ts
|
|
3441
|
+
var OPACITY_LIGHT = 0.15;
|
|
3442
|
+
var OPACITY_MEDIUM = 1;
|
|
3443
|
+
var OPACITY_BORDER = 0.3;
|
|
3444
|
+
var PLACEHOLDER_COLOR = "#9ca3af";
|
|
3445
|
+
var NEUTRAL_GRAY2 = "#64748b";
|
|
3446
|
+
var BASE_COLORS2 = {
|
|
3447
|
+
"0": "#10b981",
|
|
3448
|
+
"1": "#3b82f6",
|
|
3449
|
+
"2": "#8b5cf6",
|
|
3450
|
+
"3": "#f43f5e",
|
|
3451
|
+
"4": "#f59e0b",
|
|
3452
|
+
"5": "#84cc16",
|
|
3453
|
+
"6": "#a855f7",
|
|
3454
|
+
"7": "#06b6d4",
|
|
3455
|
+
"8": "#f97316",
|
|
3456
|
+
"9": "#14b8a6",
|
|
3457
|
+
a: "#ef4444",
|
|
3458
|
+
b: "#6366f1",
|
|
3459
|
+
c: "#ec4899",
|
|
3460
|
+
d: "#22c55e",
|
|
3461
|
+
e: "#eab308",
|
|
3462
|
+
f: "#0ea5e9"
|
|
3463
|
+
};
|
|
3464
|
+
function hexToRgba(hex, opacity) {
|
|
3465
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
3466
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
3467
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
3468
|
+
return `rgba(${r}, ${g}, ${b}, ${opacity})`;
|
|
3469
|
+
}
|
|
3470
|
+
function getEntityColor2(entityId, variant = "medium") {
|
|
3471
|
+
const baseColor = BASE_COLORS2[entityId[4]] || BASE_COLORS2["0"];
|
|
3472
|
+
switch (variant) {
|
|
3473
|
+
case "light":
|
|
3474
|
+
return hexToRgba(baseColor, OPACITY_LIGHT);
|
|
3475
|
+
case "medium":
|
|
3476
|
+
return hexToRgba(baseColor, OPACITY_MEDIUM);
|
|
3477
|
+
case "text":
|
|
3478
|
+
return baseColor;
|
|
3479
|
+
}
|
|
3480
|
+
}
|
|
3481
|
+
function getEntityColorStyles(entityId) {
|
|
3482
|
+
const baseColor = BASE_COLORS2[entityId[4]] || BASE_COLORS2["0"];
|
|
3483
|
+
return {
|
|
3484
|
+
backgroundColor: getEntityColor2(entityId, "light"),
|
|
3485
|
+
color: baseColor,
|
|
3486
|
+
borderColor: hexToRgba(baseColor, OPACITY_BORDER)
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
var getWorkspaceColor = (workspaceId, useWorkspaceColors) => {
|
|
3490
|
+
const shouldUseWorkspaceColors = useWorkspaceColors !== void 0 ? useWorkspaceColors : true;
|
|
3491
|
+
if (!shouldUseWorkspaceColors) return "hsl(var(--primary))";
|
|
3492
|
+
const isValidId = workspaceId && workspaceId.startsWith("wrk-") && workspaceId.length >= 5;
|
|
3493
|
+
if (!isValidId) return "hsl(var(--primary))";
|
|
3494
|
+
return getEntityColor2(workspaceId, "medium");
|
|
3495
|
+
};
|
|
3496
|
+
function nameInitials(name) {
|
|
3497
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
3498
|
+
if (!parts.length) return "?";
|
|
3499
|
+
return parts.slice(0, 2).map((p) => p[0]?.toUpperCase() ?? "").join("");
|
|
3500
|
+
}
|
|
3501
|
+
var STATUS_DOT = {
|
|
3502
|
+
online: "bg-emerald-500",
|
|
3503
|
+
busy: "bg-amber-500",
|
|
3504
|
+
offline: "bg-destructive"
|
|
3505
|
+
};
|
|
3506
|
+
function UserMenu({
|
|
3507
|
+
user,
|
|
3508
|
+
status,
|
|
3509
|
+
items = [],
|
|
3510
|
+
onLogout,
|
|
3511
|
+
logoutLabel = "Sign out",
|
|
3512
|
+
align = "end",
|
|
3513
|
+
side = "bottom",
|
|
3514
|
+
variant = "avatar",
|
|
3515
|
+
showChevron = true,
|
|
3516
|
+
classNames,
|
|
3517
|
+
testId = "user-menu",
|
|
3518
|
+
logoutTestId
|
|
3519
|
+
}) {
|
|
3520
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
3521
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
3522
|
+
"button",
|
|
3523
|
+
{
|
|
3524
|
+
type: "button",
|
|
3525
|
+
className: cn(
|
|
3526
|
+
"flex items-center gap-2 rounded-md transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
3527
|
+
variant === "account" ? "w-full min-w-0 p-1 text-left pointer-coarse:min-h-11" : "px-1.5 py-1 pointer-coarse:min-h-11 pointer-coarse:min-w-11 pointer-coarse:justify-center",
|
|
3528
|
+
classNames?.trigger
|
|
3529
|
+
),
|
|
3530
|
+
"data-testid": testId,
|
|
3531
|
+
"data-variant": variant,
|
|
3532
|
+
"aria-label": variant === "avatar" ? "Account menu" : void 0,
|
|
3533
|
+
title: variant === "avatar" ? user.name : void 0,
|
|
3534
|
+
children: [
|
|
3535
|
+
/* @__PURE__ */ jsxs("span", { className: "relative", children: [
|
|
3536
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "size-8", children: [
|
|
3537
|
+
user.picture ? /* @__PURE__ */ jsx(AvatarImage, { src: user.picture, alt: user.name }) : null,
|
|
3538
|
+
/* @__PURE__ */ jsx(
|
|
3539
|
+
AvatarFallback,
|
|
3540
|
+
{
|
|
3541
|
+
className: cn("bg-primary text-primary-foreground", classNames?.fallback),
|
|
3542
|
+
children: nameInitials(user.name)
|
|
3543
|
+
}
|
|
3544
|
+
)
|
|
3545
|
+
] }),
|
|
3546
|
+
status && /* @__PURE__ */ jsx(
|
|
3547
|
+
"span",
|
|
3548
|
+
{
|
|
3549
|
+
className: cn(
|
|
3550
|
+
"absolute -bottom-0.5 -right-0.5 size-2.5 rounded-full border-2 border-background",
|
|
3551
|
+
STATUS_DOT[status.tone]
|
|
3552
|
+
),
|
|
3553
|
+
title: status.detail ? `${status.label} \xB7 ${status.detail}` : status.label,
|
|
3554
|
+
"data-testid": status.testId ? `${status.testId}-dot` : void 0
|
|
3555
|
+
}
|
|
3556
|
+
)
|
|
3557
|
+
] }),
|
|
3558
|
+
variant === "account" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3559
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-foreground", children: user.name }),
|
|
3560
|
+
/* @__PURE__ */ jsx(ChevronsUpDown, { className: "mr-1 size-4 shrink-0 text-muted-foreground" })
|
|
3561
|
+
] }) : showChevron && /* @__PURE__ */ jsx(ChevronDown, { className: "size-4 text-muted-foreground" })
|
|
3562
|
+
]
|
|
3563
|
+
}
|
|
3564
|
+
) }),
|
|
3565
|
+
/* @__PURE__ */ jsxs(
|
|
3566
|
+
DropdownMenuContent,
|
|
3567
|
+
{
|
|
3568
|
+
align,
|
|
3569
|
+
side,
|
|
3570
|
+
sideOffset: 8,
|
|
3571
|
+
collisionPadding: 12,
|
|
3572
|
+
className: "w-60 rounded-lg border-border/60 shadow-lg",
|
|
3573
|
+
"data-testid": "user-menu-panel",
|
|
3574
|
+
"data-topbar-popover": "",
|
|
3575
|
+
children: [
|
|
3576
|
+
/* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "relative pr-8 pointer-coarse:pr-12", children: [
|
|
3577
|
+
/* @__PURE__ */ jsx(
|
|
3578
|
+
DropdownMenuItem,
|
|
3579
|
+
{
|
|
3580
|
+
className: "absolute right-1 top-1 flex size-6 items-center justify-center rounded-md p-0 text-muted-foreground transition-colors hover:bg-accent hover:text-foreground focus:bg-accent pointer-coarse:right-0 pointer-coarse:top-0 pointer-coarse:size-11",
|
|
3581
|
+
"aria-label": "Close account menu",
|
|
3582
|
+
"data-testid": "user-menu-close",
|
|
3583
|
+
children: /* @__PURE__ */ jsx(X, { className: "size-3.5" })
|
|
3584
|
+
}
|
|
3585
|
+
),
|
|
3586
|
+
/* @__PURE__ */ jsx("div", { className: "truncate font-medium text-foreground", title: user.name, children: user.name }),
|
|
3587
|
+
user.email && /* @__PURE__ */ jsx("div", { className: "truncate text-xs font-normal text-muted-foreground", title: user.email, children: user.email }),
|
|
3588
|
+
status && /* @__PURE__ */ jsxs(
|
|
3589
|
+
"div",
|
|
3590
|
+
{
|
|
3591
|
+
className: "mt-1 text-xs font-normal text-muted-foreground",
|
|
3592
|
+
"data-testid": status.testId,
|
|
3593
|
+
children: [
|
|
3594
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
|
|
3595
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-2 shrink-0 rounded-full", STATUS_DOT[status.tone]) }),
|
|
3596
|
+
status.label
|
|
3597
|
+
] }),
|
|
3598
|
+
status.detail && /* @__PURE__ */ jsx("div", { className: "mt-0.5 truncate pl-3.5 text-xs leading-tight text-muted-foreground/70", children: status.detail })
|
|
3599
|
+
]
|
|
3600
|
+
}
|
|
3601
|
+
)
|
|
3602
|
+
] }),
|
|
3603
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
3604
|
+
items.map((item) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
3605
|
+
item.separatorBefore && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
3606
|
+
/* @__PURE__ */ jsxs(
|
|
3607
|
+
DropdownMenuItem,
|
|
3608
|
+
{
|
|
3609
|
+
onClick: item.onSelect,
|
|
3610
|
+
"data-testid": item.testId,
|
|
3611
|
+
className: "pointer-coarse:min-h-11",
|
|
3612
|
+
...item.checked !== void 0 ? { role: "menuitemcheckbox", "aria-checked": item.checked } : {},
|
|
3613
|
+
children: [
|
|
3614
|
+
item.icon && /* @__PURE__ */ jsxs("span", { className: "relative flex shrink-0", children: [
|
|
3615
|
+
/* @__PURE__ */ jsx(item.icon, { className: "size-4" }),
|
|
3616
|
+
item.dot && /* @__PURE__ */ jsx(
|
|
3617
|
+
"span",
|
|
3618
|
+
{
|
|
3619
|
+
className: "absolute -right-0.5 -top-0.5 size-2 rounded-full bg-primary ring-2 ring-popover",
|
|
3620
|
+
"aria-hidden": true
|
|
3621
|
+
}
|
|
3622
|
+
)
|
|
3623
|
+
] }),
|
|
3624
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: item.label }),
|
|
3625
|
+
item.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-muted px-1.5 text-xs font-medium tabular-nums text-muted-foreground", children: item.badge }),
|
|
3626
|
+
item.checked !== void 0 && /* @__PURE__ */ jsx(
|
|
3627
|
+
"span",
|
|
3628
|
+
{
|
|
3629
|
+
"aria-hidden": true,
|
|
3630
|
+
className: cn(
|
|
3631
|
+
"flex h-4 w-7 shrink-0 items-center rounded-full p-0.5 transition-colors",
|
|
3632
|
+
item.checked ? "bg-primary" : "bg-border"
|
|
3633
|
+
),
|
|
3634
|
+
children: /* @__PURE__ */ jsx(
|
|
3635
|
+
"span",
|
|
3636
|
+
{
|
|
3637
|
+
className: cn(
|
|
3638
|
+
"size-3 rounded-full bg-background transition-transform",
|
|
3639
|
+
item.checked && "translate-x-3"
|
|
3640
|
+
)
|
|
3641
|
+
}
|
|
3642
|
+
)
|
|
3643
|
+
}
|
|
3644
|
+
)
|
|
3645
|
+
]
|
|
3646
|
+
}
|
|
3647
|
+
)
|
|
3648
|
+
] }, item.label)),
|
|
3649
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
3650
|
+
/* @__PURE__ */ jsxs(
|
|
3651
|
+
DropdownMenuItem,
|
|
3652
|
+
{
|
|
3653
|
+
onClick: onLogout,
|
|
3654
|
+
"data-testid": logoutTestId ?? `${testId}-logout`,
|
|
3655
|
+
className: "pointer-coarse:min-h-11",
|
|
3656
|
+
children: [
|
|
3657
|
+
/* @__PURE__ */ jsx(LogOut, { className: "size-4" }),
|
|
3658
|
+
logoutLabel
|
|
3659
|
+
]
|
|
3660
|
+
}
|
|
3661
|
+
)
|
|
3662
|
+
]
|
|
3663
|
+
}
|
|
3664
|
+
)
|
|
3665
|
+
] });
|
|
3666
|
+
}
|
|
3667
|
+
var ACTIVE_STATUSES = /* @__PURE__ */ new Set([
|
|
3668
|
+
"queued",
|
|
3669
|
+
"processing",
|
|
3670
|
+
"parsing",
|
|
3671
|
+
"encrypting",
|
|
3672
|
+
"indexing",
|
|
3673
|
+
"analysing"
|
|
3674
|
+
]);
|
|
3675
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "skipped", "empty", "low-content"]);
|
|
3676
|
+
var STATUS_LABEL = {
|
|
3677
|
+
queued: "Queued",
|
|
3678
|
+
processing: "Processing",
|
|
3679
|
+
parsing: "Parsing",
|
|
3680
|
+
encrypting: "Encrypting",
|
|
3681
|
+
indexing: "Indexing",
|
|
3682
|
+
analysing: "Analysing"
|
|
3683
|
+
};
|
|
3684
|
+
var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set(["jpg", "jpeg", "png", "gif", "bmp", "tiff", "tif", "webp"]);
|
|
3685
|
+
var VIDEO_EXTENSIONS2 = /* @__PURE__ */ new Set(["mp4", "mpeg", "mpg", "webm", "mov", "avi", "mkv"]);
|
|
3686
|
+
var AUDIO_EXTENSIONS2 = /* @__PURE__ */ new Set(["mp3", "wav", "m4a", "aac", "ogg", "flac"]);
|
|
3687
|
+
var EMAIL_EXTENSIONS2 = /* @__PURE__ */ new Set(["eml", "msg"]);
|
|
3688
|
+
function fileIcon(fileName, size) {
|
|
3689
|
+
const ext = fileName?.split(".").pop()?.toLowerCase();
|
|
3690
|
+
if (ext && VIDEO_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(VidIcon, { size });
|
|
3691
|
+
if (ext && AUDIO_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(AudIcon, { size });
|
|
3692
|
+
if (ext && IMAGE_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(ImgIcon, { size });
|
|
3693
|
+
if (ext && EMAIL_EXTENSIONS2.has(ext)) return /* @__PURE__ */ jsx(EmlIcon, { size });
|
|
3694
|
+
return /* @__PURE__ */ jsx(PdfIcon, { size });
|
|
3695
|
+
}
|
|
3696
|
+
function RenameField({
|
|
3697
|
+
seed,
|
|
3698
|
+
onCommit,
|
|
3699
|
+
onCancel,
|
|
3700
|
+
testId
|
|
3701
|
+
}) {
|
|
3702
|
+
const done = React2__default.useRef(false);
|
|
3703
|
+
const commit = (value) => {
|
|
3704
|
+
if (done.current) return;
|
|
3705
|
+
done.current = true;
|
|
3706
|
+
const trimmed = value.trim();
|
|
3707
|
+
if (trimmed && trimmed !== seed) onCommit(trimmed);
|
|
3708
|
+
else onCancel();
|
|
3709
|
+
};
|
|
3710
|
+
return /* @__PURE__ */ jsx(
|
|
3711
|
+
"input",
|
|
3712
|
+
{
|
|
3713
|
+
autoFocus: true,
|
|
3714
|
+
defaultValue: seed,
|
|
3715
|
+
"data-testid": testId,
|
|
3716
|
+
onFocus: (e) => e.currentTarget.select(),
|
|
3717
|
+
onClick: (e) => e.stopPropagation(),
|
|
3718
|
+
onKeyDown: (e) => {
|
|
3719
|
+
if (e.key === "Enter") {
|
|
3720
|
+
e.preventDefault();
|
|
3721
|
+
commit(e.currentTarget.value);
|
|
3722
|
+
} else if (e.key === "Escape") {
|
|
3723
|
+
e.preventDefault();
|
|
3724
|
+
done.current = true;
|
|
3725
|
+
onCancel();
|
|
3726
|
+
}
|
|
3727
|
+
},
|
|
3728
|
+
onBlur: (e) => commit(e.currentTarget.value),
|
|
3729
|
+
className: "w-full rounded border border-primary bg-background px-1 py-0.5 text-xs text-foreground outline-none"
|
|
3730
|
+
}
|
|
3731
|
+
);
|
|
3732
|
+
}
|
|
3733
|
+
function StatusMarker({ status, testId }) {
|
|
3734
|
+
let icon = null;
|
|
3735
|
+
let title = "";
|
|
3736
|
+
switch (status) {
|
|
3737
|
+
case "completed":
|
|
3738
|
+
icon = /* @__PURE__ */ jsx(CheckCircle, { className: "size-4 text-success", strokeWidth: 2.75 });
|
|
3739
|
+
title = "Ready";
|
|
3740
|
+
break;
|
|
3741
|
+
case "failed":
|
|
3742
|
+
icon = /* @__PURE__ */ jsx(XCircle, { className: "size-4 text-destructive", strokeWidth: 2.75 });
|
|
3743
|
+
title = "Failed";
|
|
3744
|
+
break;
|
|
3745
|
+
case "skipped":
|
|
3746
|
+
icon = /* @__PURE__ */ jsx(SkipForward, { className: "size-4 text-muted-foreground", strokeWidth: 2.75 });
|
|
3747
|
+
title = "Skipped";
|
|
3748
|
+
break;
|
|
3749
|
+
case "empty":
|
|
3750
|
+
icon = /* @__PURE__ */ jsx(FileX, { className: "size-4 text-warning", strokeWidth: 2.75 });
|
|
3751
|
+
title = "Empty \u2014 no extractable content";
|
|
3752
|
+
break;
|
|
3753
|
+
case "low-content":
|
|
3754
|
+
icon = /* @__PURE__ */ jsx(AlertTriangle, { className: "size-4 text-warning", strokeWidth: 2.75 });
|
|
3755
|
+
title = "Low content \u2014 minimal extractable content";
|
|
3756
|
+
break;
|
|
3757
|
+
default:
|
|
3758
|
+
return null;
|
|
3759
|
+
}
|
|
3760
|
+
return /* @__PURE__ */ jsx(
|
|
3761
|
+
"span",
|
|
3762
|
+
{
|
|
3763
|
+
title,
|
|
3764
|
+
"data-testid": testId,
|
|
3765
|
+
className: "flex size-6 items-center justify-center rounded-full bg-background shadow-sm",
|
|
3766
|
+
children: icon
|
|
3767
|
+
}
|
|
3768
|
+
);
|
|
3769
|
+
}
|
|
3770
|
+
function DocumentCard({
|
|
3771
|
+
doc,
|
|
3772
|
+
thumbnailUrl,
|
|
3773
|
+
status,
|
|
3774
|
+
selected = false,
|
|
3775
|
+
onToggleSelect,
|
|
3776
|
+
viewing = false,
|
|
3777
|
+
onOpen,
|
|
3778
|
+
actions,
|
|
3779
|
+
renaming = false,
|
|
3780
|
+
onCommitRename,
|
|
3781
|
+
onCancelRename,
|
|
3782
|
+
tooltipContent,
|
|
3783
|
+
marker,
|
|
3784
|
+
testId = "document-card",
|
|
3785
|
+
className
|
|
3786
|
+
}) {
|
|
3787
|
+
const normalised = (status ?? "").toLowerCase();
|
|
3788
|
+
const isProcessing = ACTIVE_STATUSES.has(normalised);
|
|
3789
|
+
const showStatusMarker = !isProcessing && TERMINAL_STATUSES.has(normalised);
|
|
3790
|
+
const [thumbFailed, setThumbFailed] = React2__default.useState(false);
|
|
3791
|
+
const [thumbLandscape, setThumbLandscape] = React2__default.useState(false);
|
|
3792
|
+
const showThumbnail = !!thumbnailUrl && !thumbFailed && !isProcessing;
|
|
3793
|
+
return /* @__PURE__ */ jsxs(
|
|
3794
|
+
"div",
|
|
3795
|
+
{
|
|
3796
|
+
"data-testid": testId,
|
|
3797
|
+
className: cn(
|
|
3798
|
+
// Square corners and a portrait-page aspect (height = 1.3 × width), so a
|
|
3799
|
+
// cover-page thumbnail reads edge-to-edge.
|
|
3800
|
+
"group relative aspect-[10/13] select-none overflow-hidden border bg-muted/20 transition",
|
|
3801
|
+
selected ? "border-primary bg-primary/10" : "border-border shadow-sm hover:border-border/80 hover:bg-muted/50",
|
|
3802
|
+
className
|
|
3803
|
+
),
|
|
3804
|
+
children: [
|
|
3805
|
+
showThumbnail ? /* @__PURE__ */ jsx(
|
|
3806
|
+
"img",
|
|
3807
|
+
{
|
|
3808
|
+
src: thumbnailUrl,
|
|
3809
|
+
alt: "",
|
|
3810
|
+
loading: "lazy",
|
|
3811
|
+
draggable: false,
|
|
3812
|
+
onError: () => setThumbFailed(true),
|
|
3813
|
+
onLoad: (e) => setThumbLandscape(e.currentTarget.naturalWidth > e.currentTarget.naturalHeight),
|
|
3814
|
+
className: cn(
|
|
3815
|
+
"absolute inset-0 size-full bg-white",
|
|
3816
|
+
thumbLandscape ? "object-contain" : "object-cover object-top"
|
|
3817
|
+
)
|
|
3818
|
+
}
|
|
3819
|
+
) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center text-muted-foreground", children: fileIcon(doc.file_name, 44) }),
|
|
3820
|
+
isProcessing && /* @__PURE__ */ jsxs(
|
|
3821
|
+
"div",
|
|
3822
|
+
{
|
|
3823
|
+
"data-testid": `${testId}-processing`,
|
|
3824
|
+
className: "absolute inset-0 z-10 flex flex-col items-center justify-center gap-1.5 bg-background/80 px-3",
|
|
3825
|
+
children: [
|
|
3826
|
+
/* @__PURE__ */ jsx("div", { className: "h-1.5 w-full overflow-hidden rounded-sm bg-muted", children: /* @__PURE__ */ jsx("div", { className: "h-full w-1/3 animate-pulse rounded-sm bg-primary" }) }),
|
|
3827
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-primary", children: STATUS_LABEL[normalised] ?? normalised })
|
|
3828
|
+
]
|
|
3829
|
+
}
|
|
3830
|
+
),
|
|
3831
|
+
onToggleSelect && /* @__PURE__ */ jsx(
|
|
3832
|
+
Checkbox,
|
|
3833
|
+
{
|
|
3834
|
+
checked: selected,
|
|
3835
|
+
onCheckedChange: () => onToggleSelect(),
|
|
3836
|
+
onClick: (e) => e.stopPropagation(),
|
|
3837
|
+
"aria-label": selected ? "Deselect" : "Select",
|
|
3838
|
+
"data-testid": `${testId}-select`,
|
|
3839
|
+
className: cn(
|
|
3840
|
+
"absolute left-1.5 top-1.5 z-20 size-6 rounded-none border-muted-foreground/60 bg-background shadow-sm transition",
|
|
3841
|
+
selected ? "opacity-100" : "opacity-40 group-hover:opacity-100"
|
|
3842
|
+
)
|
|
3843
|
+
}
|
|
3844
|
+
),
|
|
3845
|
+
actions && /* @__PURE__ */ jsx("div", { className: "absolute right-1.5 top-1.5 z-20", children: actions }),
|
|
3846
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute inset-x-1.5 bottom-1.5 z-20 flex flex-col gap-1", children: [
|
|
3847
|
+
(marker || showStatusMarker) && /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
3848
|
+
marker,
|
|
3849
|
+
showStatusMarker && /* @__PURE__ */ jsx("div", { className: "ml-auto flex", children: /* @__PURE__ */ jsx(StatusMarker, { status: normalised, testId: `${testId}-status` }) })
|
|
3850
|
+
] }),
|
|
3851
|
+
renaming ? /* @__PURE__ */ jsx(
|
|
3852
|
+
RenameField,
|
|
3853
|
+
{
|
|
3854
|
+
seed: doc.doc_metadata?.title || doc.file_name || "",
|
|
3855
|
+
onCommit: (name) => onCommitRename?.(name),
|
|
3856
|
+
onCancel: () => onCancelRename?.(),
|
|
3857
|
+
testId: `${testId}-rename-input`
|
|
3858
|
+
}
|
|
3859
|
+
) : /* @__PURE__ */ jsx(
|
|
3860
|
+
DocumentEntity,
|
|
3861
|
+
{
|
|
3862
|
+
doc,
|
|
3863
|
+
fullWidth: true,
|
|
3864
|
+
viewing,
|
|
3865
|
+
tooltipContent,
|
|
3866
|
+
labelClassName: "font-semibold",
|
|
3867
|
+
className: "w-full min-w-0 max-w-full bg-background/90 backdrop-blur-sm",
|
|
3868
|
+
onClick: (e) => {
|
|
3869
|
+
e.stopPropagation();
|
|
3870
|
+
onOpen?.();
|
|
3871
|
+
}
|
|
3872
|
+
}
|
|
3873
|
+
)
|
|
3874
|
+
] })
|
|
3875
|
+
]
|
|
3876
|
+
}
|
|
3877
|
+
);
|
|
3878
|
+
}
|
|
3879
|
+
|
|
3880
|
+
export { AgentBadge, AiMarkdown, ArbiBotHeadIcon, AudIcon, Avatar, AvatarFallback, AvatarImage, BASE_COLORS2 as BASE_COLORS, Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Checkbox, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DictateProvider, DocumentCard, DocumentEntity, ENTITY_MAPPINGS, EmlIcon, EntityIcon, EntityPill, FILE_TYPE_COLORS, HoverCard, HoverCardContent, HoverCardTrigger, IconToggle, ImgIcon, InlineMicButton, Input, Label, MarkMenu, MarkdownRenderer, MarkdownStreamingContext, MicRecordingOverlay, MicWaveformIndicator, NEUTRAL_GRAY2 as NEUTRAL_GRAY, PLACEHOLDER_COLOR, PassageCard, PdfIcon, Popover, PopoverAnchor, PopoverContent, PopoverTrigger, PresenceLabel, Progress, ProjectEntity, RadioGroup, RadioGroupItem, RagDot, RelevanceDot, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, StatusPill, Switch, TAG_TYPE_ICONS, TAG_TYPE_LABELS, Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow, Tabs, TabsContent, TabsList, TabsTrigger, TagEntity, Textarea, Toggle, ToggleGroup, ToggleGroupItem, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, UserEntity, UserMenu, VISIBILITY_ICONS, VidIcon, VisibilityIcon, badgeVariants, buttonVariants, cardVariants, classifyMediaError, configureEntityRegistry, configureRagLabels, configureStatusRegistry, formatElapsed, getDocIcon, getEntityColor2 as getEntityColor, getEntityColorStyles, getEntityIcon, getEntityLabel, getStatusVariant, getTagTypeIcon, getTagTypeLabel, getWorkspaceColor, markdownBaseComponents, splitMarkdownBlocks, toggleVariants, useAudioRecorder };
|
|
3881
|
+
//# sourceMappingURL=chunk-3CLGHHME.js.map
|
|
3882
|
+
//# sourceMappingURL=chunk-3CLGHHME.js.map
|