@tangle-network/agent-app 0.46.2 → 0.46.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/assistant/index.js +3 -1
- package/dist/assistant/index.js.map +1 -1
- package/dist/chunk-KKBTPZIE.js +805 -0
- package/dist/chunk-KKBTPZIE.js.map +1 -0
- package/dist/{chunk-2RTYQU4W.js → chunk-LEGZX5MQ.js} +150 -4
- package/dist/chunk-LEGZX5MQ.js.map +1 -0
- package/dist/chunk-RLOHIX5Y.js +36 -0
- package/dist/chunk-RLOHIX5Y.js.map +1 -0
- package/dist/{chunk-MBKNKAN2.js → chunk-YTEUZXX2.js} +584 -1252
- package/dist/chunk-YTEUZXX2.js.map +1 -0
- package/dist/mention-editor-GVLG3W7C.js +521 -0
- package/dist/mention-editor-GVLG3W7C.js.map +1 -0
- package/dist/stories/studio/StudioProviders.d.ts +10 -0
- package/dist/stories/studio/fixtures.d.ts +10 -2
- package/dist/studio/audio-preview.d.ts +12 -0
- package/dist/studio/generation.d.ts +22 -1
- package/dist/studio/index.d.ts +2 -0
- package/dist/studio/index.js +29 -1
- package/dist/studio/ports.d.ts +54 -0
- package/dist/studio-react/composer-option-controls.d.ts +19 -8
- package/dist/studio-react/download-generations.d.ts +4 -0
- package/dist/studio-react/index.d.ts +38 -22
- package/dist/studio-react/index.js +2198 -545
- package/dist/studio-react/index.js.map +1 -1
- package/dist/studio-react/media-tile.d.ts +21 -0
- package/dist/studio-react/media-viewer.d.ts +12 -0
- package/dist/studio-react/studio-confirm.d.ts +8 -0
- package/dist/studio-react/studio-generation-screen.d.ts +42 -0
- package/dist/studio-react/studio-history-screen.d.ts +28 -0
- package/dist/studio-react/studio-home-screen.d.ts +20 -0
- package/dist/studio-react/studio-playback.d.ts +31 -0
- package/dist/studio-react/studio-toasts.d.ts +21 -0
- package/dist/studio-react/studio.css +142 -72
- package/dist/studio-react/use-batch-navigation.d.ts +20 -0
- package/dist/studio-react/use-deferred-delete.d.ts +19 -0
- package/dist/studio-react/use-generation-history.d.ts +22 -0
- package/dist/studio-react/vault-path-popover.d.ts +12 -0
- package/dist/teams/drizzle/invitations-schema.d.ts +1 -1
- package/dist/teams/drizzle/schema.d.ts +1 -1
- package/dist/web-react/chat-composer.d.ts +24 -4
- package/dist/web-react/index.d.ts +1 -0
- package/dist/web-react/index.js +12 -6
- package/dist/web-react/mention-boundaries.d.ts +33 -0
- package/dist/web-react/mention-editor.d.ts +84 -0
- package/dist/web-react/mention-list.d.ts +35 -0
- package/dist/web-react/mention-pill.d.ts +10 -0
- package/dist/web-react/mention-serialize.d.ts +44 -0
- package/dist/web-react/use-file-mentions.d.ts +28 -14
- package/package.json +33 -7
- package/dist/chunk-2RTYQU4W.js.map +0 -1
- package/dist/chunk-MBKNKAN2.js.map +0 -1
- package/dist/studio-react/generation-card.d.ts +0 -9
- package/dist/studio-react/generation-detail-modal.d.ts +0 -11
- package/dist/studio-react/generation-detail.d.ts +0 -6
- package/dist/studio-react/generation-grid.d.ts +0 -15
- package/dist/studio-react/library-drawer.d.ts +0 -12
- package/dist/studio-react/library-panel.d.ts +0 -15
- package/dist/studio-react/result-canvas.d.ts +0 -6
- package/dist/studio-react/studio-header.d.ts +0 -5
- package/dist/studio-react/studio-sheet.d.ts +0 -12
- package/dist/studio-react/studio-workspace.d.ts +0 -21
- package/dist/studio-react/type-config.d.ts +0 -11
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PATH_CONTINUATION_CHAR,
|
|
3
|
+
WORD_CHAR,
|
|
4
|
+
charAt,
|
|
5
|
+
charBefore,
|
|
6
|
+
joinClasses
|
|
7
|
+
} from "./chunk-RLOHIX5Y.js";
|
|
1
8
|
import {
|
|
2
9
|
stepActivityFlowTrace
|
|
3
10
|
} from "./chunk-FBVLEGEG.js";
|
|
@@ -23,11 +30,8 @@ import {
|
|
|
23
30
|
AsyncView
|
|
24
31
|
} from "./chunk-3UBAO3N5.js";
|
|
25
32
|
import {
|
|
26
|
-
UNTITLED_SESSION_LABEL,
|
|
27
33
|
filterCommandPaletteItems,
|
|
28
|
-
groupCommandPaletteItems
|
|
29
|
-
mergeSessionPages,
|
|
30
|
-
sessionLabel
|
|
34
|
+
groupCommandPaletteItems
|
|
31
35
|
} from "./chunk-EDTWGSQT.js";
|
|
32
36
|
import {
|
|
33
37
|
attachmentPartsFromMessageParts
|
|
@@ -48,7 +52,7 @@ import {
|
|
|
48
52
|
} from "./chunk-YJMCRXQQ.js";
|
|
49
53
|
|
|
50
54
|
// src/web-react/index.tsx
|
|
51
|
-
import { useEffect as
|
|
55
|
+
import { useEffect as useEffect13, useMemo as useMemo8, useRef as useRef13, useState as useState17, memo } from "react";
|
|
52
56
|
import { InlineToolItem, RunRowShell } from "@tangle-network/ui/run";
|
|
53
57
|
|
|
54
58
|
// src/web-react/smooth-text.ts
|
|
@@ -1415,6 +1419,9 @@ async function streamChatTurn(opts) {
|
|
|
1415
1419
|
|
|
1416
1420
|
// src/web-react/chat-composer.tsx
|
|
1417
1421
|
import {
|
|
1422
|
+
Component,
|
|
1423
|
+
lazy as lazy2,
|
|
1424
|
+
Suspense as Suspense2,
|
|
1418
1425
|
useCallback as useCallback3,
|
|
1419
1426
|
useEffect as useEffect6,
|
|
1420
1427
|
useMemo as useMemo3,
|
|
@@ -1557,6 +1564,56 @@ function useDictation({ onDictate, onError }) {
|
|
|
1557
1564
|
|
|
1558
1565
|
// src/web-react/chat-composer.tsx
|
|
1559
1566
|
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1567
|
+
function createLazyMentionEditor() {
|
|
1568
|
+
return lazy2(() => import("./mention-editor-GVLG3W7C.js").then((m) => m.loadMentionEditor()));
|
|
1569
|
+
}
|
|
1570
|
+
var MentionEditorBoundary = class extends Component {
|
|
1571
|
+
state = { error: null };
|
|
1572
|
+
static getDerivedStateFromError(error) {
|
|
1573
|
+
return { error };
|
|
1574
|
+
}
|
|
1575
|
+
componentDidCatch() {
|
|
1576
|
+
this.props.onFailed();
|
|
1577
|
+
}
|
|
1578
|
+
render() {
|
|
1579
|
+
if (this.state.error === null) return this.props.children;
|
|
1580
|
+
const message = this.state.error instanceof Error ? this.state.error.message : String(this.state.error);
|
|
1581
|
+
return /* @__PURE__ */ jsxs5(
|
|
1582
|
+
"div",
|
|
1583
|
+
{
|
|
1584
|
+
role: "alert",
|
|
1585
|
+
"data-testid": "composer-mention-editor-error",
|
|
1586
|
+
className: "rounded-xl border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
1587
|
+
children: [
|
|
1588
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-2", children: [
|
|
1589
|
+
/* @__PURE__ */ jsxs5("span", { className: "min-w-0 flex-1", children: [
|
|
1590
|
+
"The mention input failed to load: ",
|
|
1591
|
+
message
|
|
1592
|
+
] }),
|
|
1593
|
+
/* @__PURE__ */ jsx7(
|
|
1594
|
+
"button",
|
|
1595
|
+
{
|
|
1596
|
+
type: "button",
|
|
1597
|
+
"aria-label": "Retry loading the mention input",
|
|
1598
|
+
onClick: this.props.onRetry,
|
|
1599
|
+
className: "shrink-0 font-medium underline-offset-2 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-destructive/50",
|
|
1600
|
+
children: "Retry"
|
|
1601
|
+
}
|
|
1602
|
+
)
|
|
1603
|
+
] }),
|
|
1604
|
+
this.props.draft.trim() !== "" && /* @__PURE__ */ jsx7(
|
|
1605
|
+
"p",
|
|
1606
|
+
{
|
|
1607
|
+
"data-testid": "composer-error-held-draft",
|
|
1608
|
+
className: "mt-1.5 max-h-20 overflow-y-auto whitespace-pre-wrap rounded-lg border border-destructive/30 bg-card px-2 py-1 text-foreground",
|
|
1609
|
+
children: this.props.draft
|
|
1610
|
+
}
|
|
1611
|
+
)
|
|
1612
|
+
]
|
|
1613
|
+
}
|
|
1614
|
+
);
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1560
1617
|
var IS_APPLE_PLATFORM = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/i.test(navigator.platform);
|
|
1561
1618
|
function SendGlyph({ className }) {
|
|
1562
1619
|
return /* @__PURE__ */ jsx7("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx7("path", { d: "M22 2 11 13M22 2l-7 20-4-9-9-4 20-7z" }) });
|
|
@@ -1647,6 +1704,7 @@ function ChatComposer({
|
|
|
1647
1704
|
minRows = 2,
|
|
1648
1705
|
maxHeight = DEFAULT_MAX_HEIGHT,
|
|
1649
1706
|
trailing,
|
|
1707
|
+
mention,
|
|
1650
1708
|
slashCommands,
|
|
1651
1709
|
onDictate,
|
|
1652
1710
|
onDictateError,
|
|
@@ -1662,6 +1720,13 @@ function ChatComposer({
|
|
|
1662
1720
|
const textRef = useRef6(text);
|
|
1663
1721
|
textRef.current = text;
|
|
1664
1722
|
const textareaRef = useRef6(null);
|
|
1723
|
+
const richFocusRef = useRef6(null);
|
|
1724
|
+
const registerRichFocus = useCallback3((focus) => {
|
|
1725
|
+
richFocusRef.current = focus;
|
|
1726
|
+
}, []);
|
|
1727
|
+
const [editorEpoch, setEditorEpoch] = useState8(0);
|
|
1728
|
+
const MentionEditor = useMemo3(createLazyMentionEditor, [editorEpoch]);
|
|
1729
|
+
const [editorFailed, setEditorFailed] = useState8(false);
|
|
1665
1730
|
const fileInputRef = useRef6(null);
|
|
1666
1731
|
const folderInputRef = useRef6(null);
|
|
1667
1732
|
const [dragOver, setDragOver] = useState8(false);
|
|
@@ -1733,21 +1798,30 @@ function ChatComposer({
|
|
|
1733
1798
|
const end = Math.min(pending.end, text.length);
|
|
1734
1799
|
el.setSelectionRange(start, end);
|
|
1735
1800
|
}, [text]);
|
|
1801
|
+
const mentionEnabled = mention != null;
|
|
1736
1802
|
useEffect6(() => {
|
|
1737
1803
|
if (!focusShortcut || disabled) return;
|
|
1738
1804
|
function onKeyDown(e) {
|
|
1739
1805
|
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "l") {
|
|
1740
|
-
|
|
1741
|
-
|
|
1806
|
+
if (mentionEnabled) {
|
|
1807
|
+
const focus = richFocusRef.current;
|
|
1808
|
+
if (!focus) return;
|
|
1809
|
+
e.preventDefault();
|
|
1810
|
+
focus();
|
|
1811
|
+
} else {
|
|
1812
|
+
e.preventDefault();
|
|
1813
|
+
textareaRef.current?.focus();
|
|
1814
|
+
}
|
|
1742
1815
|
}
|
|
1743
1816
|
}
|
|
1744
1817
|
document.addEventListener("keydown", onKeyDown);
|
|
1745
1818
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
1746
|
-
}, [focusShortcut, disabled]);
|
|
1819
|
+
}, [focusShortcut, disabled, mentionEnabled]);
|
|
1747
1820
|
const sendableFiles = canSubmitAttachmentsOnly ? pendingFiles : pendingFiles.filter((f) => f.status === "ready");
|
|
1748
1821
|
const hasSendable = text.trim().length > 0 || sendableFiles.length > 0;
|
|
1749
1822
|
const sendBlockedByStream = isStreaming && !canSubmitWhileBusy;
|
|
1750
|
-
const
|
|
1823
|
+
const editorInputLost = mention != null && editorFailed;
|
|
1824
|
+
const canSend = hasSendable && !sendBlockedByStream && !disabled && !editorInputLost;
|
|
1751
1825
|
const [failedSend, setFailedSend] = useState8(null);
|
|
1752
1826
|
const failSend = useCallback3(
|
|
1753
1827
|
(error, draft, trimmed, parts, caret) => {
|
|
@@ -1792,7 +1866,7 @@ function ChatComposer({
|
|
|
1792
1866
|
);
|
|
1793
1867
|
const send = useCallback3(() => {
|
|
1794
1868
|
const trimmed = text.trim();
|
|
1795
|
-
if (sendBlockedByStream || disabled) return;
|
|
1869
|
+
if (sendBlockedByStream || disabled || editorInputLost) return;
|
|
1796
1870
|
const readyFiles = pendingFiles.filter((f) => f.status === "ready");
|
|
1797
1871
|
const sendable = canSubmitAttachmentsOnly ? pendingFiles : readyFiles;
|
|
1798
1872
|
if (!trimmed && sendable.length === 0) return;
|
|
@@ -1812,6 +1886,7 @@ function ChatComposer({
|
|
|
1812
1886
|
text,
|
|
1813
1887
|
sendBlockedByStream,
|
|
1814
1888
|
disabled,
|
|
1889
|
+
editorInputLost,
|
|
1815
1890
|
canSubmitAttachmentsOnly,
|
|
1816
1891
|
attachmentsNotReadyMessage,
|
|
1817
1892
|
onSendParts,
|
|
@@ -1831,7 +1906,7 @@ function ChatComposer({
|
|
|
1831
1906
|
const slashListId = useId();
|
|
1832
1907
|
const [slashActive, setSlashActive] = useState8(0);
|
|
1833
1908
|
const [slashDismissedFor, setSlashDismissedFor] = useState8(null);
|
|
1834
|
-
const slashToken = slashCommands && slashCommands.length > 0 ? /^\/(\S*)$/.exec(text)?.[1] : void 0;
|
|
1909
|
+
const slashToken = !mention && slashCommands && slashCommands.length > 0 ? /^\/(\S*)$/.exec(text)?.[1] : void 0;
|
|
1835
1910
|
const slashOpen = slashToken !== void 0 && text !== slashDismissedFor;
|
|
1836
1911
|
const slashItems = useMemo3(
|
|
1837
1912
|
() => (slashCommands ?? []).map((command) => ({
|
|
@@ -1929,11 +2004,8 @@ function ChatComposer({
|
|
|
1929
2004
|
if (e.target.files?.length) deliverFiles(Array.from(e.target.files), e.target.files);
|
|
1930
2005
|
e.target.value = "";
|
|
1931
2006
|
};
|
|
1932
|
-
const
|
|
1933
|
-
if (!onAttach) return;
|
|
1934
|
-
const clipboardFiles = e.clipboardData?.files;
|
|
1935
|
-
if (!clipboardFiles || clipboardFiles.length === 0) return;
|
|
1936
|
-
e.preventDefault();
|
|
2007
|
+
const ingestPastedFiles = (clipboardFiles) => {
|
|
2008
|
+
if (!onAttach || clipboardFiles.length === 0) return false;
|
|
1937
2009
|
const { files, nextIndex } = renamePastedImages(
|
|
1938
2010
|
Array.from(clipboardFiles),
|
|
1939
2011
|
pastedImageCount.current,
|
|
@@ -1941,6 +2013,12 @@ function ChatComposer({
|
|
|
1941
2013
|
);
|
|
1942
2014
|
pastedImageCount.current = nextIndex;
|
|
1943
2015
|
deliverFiles(files, clipboardFiles);
|
|
2016
|
+
return true;
|
|
2017
|
+
};
|
|
2018
|
+
const handlePaste = (e) => {
|
|
2019
|
+
const clipboardFiles = e.clipboardData?.files;
|
|
2020
|
+
if (!clipboardFiles || clipboardFiles.length === 0) return;
|
|
2021
|
+
if (ingestPastedFiles(clipboardFiles)) e.preventDefault();
|
|
1944
2022
|
};
|
|
1945
2023
|
const handleFolderChange = (e) => {
|
|
1946
2024
|
if (e.target.files?.length) (onAttachFolder ?? onAttach)?.(e.target.files);
|
|
@@ -1981,6 +2059,7 @@ function ChatComposer({
|
|
|
1981
2059
|
const fileChips = pendingFiles.filter((f) => f.kind !== "folder");
|
|
1982
2060
|
const showAbove = controls != null && controlsPlacement === "above";
|
|
1983
2061
|
const showInline = controls != null && !showAbove;
|
|
2062
|
+
const inputMinHeight = minRows * LINE_HEIGHT + TEXTAREA_PADDING_Y;
|
|
1984
2063
|
return /* @__PURE__ */ jsxs5(
|
|
1985
2064
|
"div",
|
|
1986
2065
|
{
|
|
@@ -2131,22 +2210,79 @@ function ChatComposer({
|
|
|
2131
2210
|
"data-testid": "composer-card",
|
|
2132
2211
|
className: `flex flex-col gap-1.5 rounded-2xl border border-card-edge bg-card px-3 py-2.5 transition focus-within:border-primary/40 focus-within:ring-2 focus-within:ring-primary/15 ${floating ? "shadow-raised" : ""}`,
|
|
2133
2212
|
children: [
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2213
|
+
mention ? (
|
|
2214
|
+
// The editor arrives as a lazy chunk; until it lands, a read-only
|
|
2215
|
+
// textarea with the same metrics holds the layout so the card
|
|
2216
|
+
// doesn't jump. The boundary contains a failed load (e.g. the
|
|
2217
|
+
// missing-peer error) to the input area instead of unmounting the
|
|
2218
|
+
// host's region.
|
|
2219
|
+
/* @__PURE__ */ jsx7(
|
|
2220
|
+
MentionEditorBoundary,
|
|
2221
|
+
{
|
|
2222
|
+
onRetry: () => {
|
|
2223
|
+
setEditorFailed(false);
|
|
2224
|
+
setEditorEpoch((epoch) => epoch + 1);
|
|
2225
|
+
},
|
|
2226
|
+
onFailed: () => setEditorFailed(true),
|
|
2227
|
+
draft: text,
|
|
2228
|
+
children: /* @__PURE__ */ jsx7(
|
|
2229
|
+
Suspense2,
|
|
2230
|
+
{
|
|
2231
|
+
fallback: /* @__PURE__ */ jsx7(
|
|
2232
|
+
"textarea",
|
|
2233
|
+
{
|
|
2234
|
+
rows: minRows,
|
|
2235
|
+
value: text,
|
|
2236
|
+
readOnly: true,
|
|
2237
|
+
disabled: true,
|
|
2238
|
+
placeholder,
|
|
2239
|
+
"aria-label": "Message input",
|
|
2240
|
+
style: { minHeight: inputMinHeight, maxHeight },
|
|
2241
|
+
className: "w-full resize-none bg-transparent px-1.5 py-1 text-base leading-6 text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-50"
|
|
2242
|
+
}
|
|
2243
|
+
),
|
|
2244
|
+
children: /* @__PURE__ */ jsx7(
|
|
2245
|
+
MentionEditor,
|
|
2246
|
+
{
|
|
2247
|
+
value: text,
|
|
2248
|
+
onChange: setText,
|
|
2249
|
+
onSubmit: send,
|
|
2250
|
+
placeholder,
|
|
2251
|
+
disabled,
|
|
2252
|
+
autoFocus,
|
|
2253
|
+
minHeight: inputMinHeight,
|
|
2254
|
+
maxHeight,
|
|
2255
|
+
mention,
|
|
2256
|
+
registerFocus: registerRichFocus,
|
|
2257
|
+
onPasteFiles: onAttach ? ingestPastedFiles : void 0
|
|
2258
|
+
}
|
|
2259
|
+
)
|
|
2260
|
+
}
|
|
2261
|
+
)
|
|
2262
|
+
},
|
|
2263
|
+
editorEpoch
|
|
2264
|
+
)
|
|
2265
|
+
) : (
|
|
2266
|
+
// Focus: `outline-none` is safe because the card above draws the
|
|
2267
|
+
// keyboard indicator through `focus-within:` — one ring for
|
|
2268
|
+
// whichever input mode is mounted.
|
|
2269
|
+
/* @__PURE__ */ jsx7(
|
|
2270
|
+
"textarea",
|
|
2271
|
+
{
|
|
2272
|
+
ref: textareaRef,
|
|
2273
|
+
value: text,
|
|
2274
|
+
onChange: (e) => setText(e.target.value),
|
|
2275
|
+
onKeyDown: handleKeyDown,
|
|
2276
|
+
onPaste: onAttach ? handlePaste : void 0,
|
|
2277
|
+
placeholder,
|
|
2278
|
+
disabled,
|
|
2279
|
+
autoFocus,
|
|
2280
|
+
rows: minRows,
|
|
2281
|
+
style: { minHeight: inputMinHeight, maxHeight },
|
|
2282
|
+
"aria-label": "Message input",
|
|
2283
|
+
className: "w-full resize-none bg-transparent px-1.5 py-1 text-base leading-6 text-foreground outline-none placeholder:text-muted-foreground disabled:opacity-50"
|
|
2284
|
+
}
|
|
2285
|
+
)
|
|
2150
2286
|
),
|
|
2151
2287
|
/* @__PURE__ */ jsxs5("div", { className: "flex items-end gap-2", children: [
|
|
2152
2288
|
onAttach && /* @__PURE__ */ jsxs5(Fragment2, { children: [
|
|
@@ -2824,8 +2960,6 @@ function useFileMentions(options) {
|
|
|
2824
2960
|
}
|
|
2825
2961
|
|
|
2826
2962
|
// src/web-react/chat-mentions.ts
|
|
2827
|
-
var PATH_CONTINUATION_CHAR = /[\p{L}\p{N}._\-/]/u;
|
|
2828
|
-
var WORD_CHAR = /[\p{L}\p{N}]/u;
|
|
2829
2963
|
function segmentMentionContent(content, parts) {
|
|
2830
2964
|
const matched = /* @__PURE__ */ new Set();
|
|
2831
2965
|
if (!content) return { segments: [], matched };
|
|
@@ -2839,7 +2973,7 @@ function segmentMentionContent(content, parts) {
|
|
|
2839
2973
|
cursor += 1;
|
|
2840
2974
|
continue;
|
|
2841
2975
|
}
|
|
2842
|
-
const prevChar =
|
|
2976
|
+
const prevChar = charBefore(content, cursor);
|
|
2843
2977
|
if (prevChar && WORD_CHAR.test(prevChar)) {
|
|
2844
2978
|
cursor += 1;
|
|
2845
2979
|
continue;
|
|
@@ -2850,7 +2984,7 @@ function segmentMentionContent(content, parts) {
|
|
|
2850
2984
|
continue;
|
|
2851
2985
|
}
|
|
2852
2986
|
const endIdx = cursor + candidate.token.length;
|
|
2853
|
-
const nextChar =
|
|
2987
|
+
const nextChar = charAt(content, endIdx);
|
|
2854
2988
|
if (nextChar && PATH_CONTINUATION_CHAR.test(nextChar)) {
|
|
2855
2989
|
cursor += 1;
|
|
2856
2990
|
continue;
|
|
@@ -3722,8 +3856,10 @@ function SeatPaywall({
|
|
|
3722
3856
|
] }) });
|
|
3723
3857
|
}
|
|
3724
3858
|
|
|
3725
|
-
// src/web-react/
|
|
3859
|
+
// src/web-react/record-grid.tsx
|
|
3726
3860
|
import {
|
|
3861
|
+
Fragment as Fragment5,
|
|
3862
|
+
isValidElement,
|
|
3727
3863
|
useCallback as useCallback9,
|
|
3728
3864
|
useEffect as useEffect10,
|
|
3729
3865
|
useId as useId3,
|
|
@@ -3731,794 +3867,6 @@ import {
|
|
|
3731
3867
|
useRef as useRef10,
|
|
3732
3868
|
useState as useState14
|
|
3733
3869
|
} from "react";
|
|
3734
|
-
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3735
|
-
function rethrowAsync(error) {
|
|
3736
|
-
queueMicrotask(() => {
|
|
3737
|
-
throw error;
|
|
3738
|
-
});
|
|
3739
|
-
}
|
|
3740
|
-
function useInfiniteScroll(onLoadMore, { enabled, root, rootMargin = "300px" }) {
|
|
3741
|
-
const [sentinel, setSentinel] = useState14(null);
|
|
3742
|
-
const sentinelRef = useCallback9((node) => setSentinel(node), []);
|
|
3743
|
-
const onLoadMoreRef = useRef10(onLoadMore);
|
|
3744
|
-
useEffect10(() => {
|
|
3745
|
-
onLoadMoreRef.current = onLoadMore;
|
|
3746
|
-
}, [onLoadMore]);
|
|
3747
|
-
useEffect10(() => {
|
|
3748
|
-
if (!sentinel || !enabled) return;
|
|
3749
|
-
if (typeof IntersectionObserver === "undefined") return;
|
|
3750
|
-
const observer = new IntersectionObserver(
|
|
3751
|
-
(entries) => {
|
|
3752
|
-
if (!entries.some((entry) => entry.isIntersecting)) return;
|
|
3753
|
-
try {
|
|
3754
|
-
onLoadMoreRef.current();
|
|
3755
|
-
} catch (error) {
|
|
3756
|
-
rethrowAsync(error);
|
|
3757
|
-
}
|
|
3758
|
-
},
|
|
3759
|
-
{ root: root?.current ?? null, rootMargin }
|
|
3760
|
-
);
|
|
3761
|
-
observer.observe(sentinel);
|
|
3762
|
-
return () => observer.disconnect();
|
|
3763
|
-
}, [sentinel, enabled, root, rootMargin]);
|
|
3764
|
-
return sentinelRef;
|
|
3765
|
-
}
|
|
3766
|
-
function seedSignature(page) {
|
|
3767
|
-
return `${page.nextCursor ?? ""}|${page.items.map((item) => item.id).join(",")}`;
|
|
3768
|
-
}
|
|
3769
|
-
function useSessionHistory({
|
|
3770
|
-
fetchPage,
|
|
3771
|
-
q,
|
|
3772
|
-
sort,
|
|
3773
|
-
initialPage,
|
|
3774
|
-
defaultSort = "newest"
|
|
3775
|
-
}) {
|
|
3776
|
-
const [items, setItems] = useState14(initialPage.items);
|
|
3777
|
-
const [nextCursor, setNextCursor] = useState14(initialPage.nextCursor ?? null);
|
|
3778
|
-
const [phase, setPhase] = useState14("idle");
|
|
3779
|
-
const [reloadKey, setReloadKey] = useState14(0);
|
|
3780
|
-
const seqRef = useRef10(0);
|
|
3781
|
-
const resetAbortRef = useRef10(null);
|
|
3782
|
-
const loadMoreAbortRef = useRef10(null);
|
|
3783
|
-
const loadingMoreRef = useRef10(false);
|
|
3784
|
-
const lastOpRef = useRef10("first");
|
|
3785
|
-
const nextCursorRef = useRef10(nextCursor);
|
|
3786
|
-
nextCursorRef.current = nextCursor;
|
|
3787
|
-
const viewRef = useRef10({ q, sort, fetchPage });
|
|
3788
|
-
viewRef.current = { q, sort, fetchPage };
|
|
3789
|
-
const seedRef = useRef10(initialPage);
|
|
3790
|
-
seedRef.current = initialPage;
|
|
3791
|
-
const isDefaultView = q === "" && sort === defaultSort;
|
|
3792
|
-
const seedKey = useMemo6(() => seedSignature(initialPage), [initialPage]);
|
|
3793
|
-
useEffect10(() => {
|
|
3794
|
-
resetAbortRef.current?.abort();
|
|
3795
|
-
loadMoreAbortRef.current?.abort();
|
|
3796
|
-
loadingMoreRef.current = false;
|
|
3797
|
-
const seq = ++seqRef.current;
|
|
3798
|
-
if (isDefaultView && reloadKey === 0) {
|
|
3799
|
-
setItems(seedRef.current.items);
|
|
3800
|
-
setNextCursor(seedRef.current.nextCursor ?? null);
|
|
3801
|
-
setPhase("idle");
|
|
3802
|
-
return;
|
|
3803
|
-
}
|
|
3804
|
-
const controller = new AbortController();
|
|
3805
|
-
resetAbortRef.current = controller;
|
|
3806
|
-
lastOpRef.current = "first";
|
|
3807
|
-
setItems([]);
|
|
3808
|
-
setNextCursor(null);
|
|
3809
|
-
setPhase("loadingFirst");
|
|
3810
|
-
void (async () => {
|
|
3811
|
-
try {
|
|
3812
|
-
const page = await viewRef.current.fetchPage({ q, sort, cursor: null, signal: controller.signal });
|
|
3813
|
-
if (seq !== seqRef.current) return;
|
|
3814
|
-
setItems(page.items);
|
|
3815
|
-
setNextCursor(page.nextCursor ?? null);
|
|
3816
|
-
setPhase("idle");
|
|
3817
|
-
} catch {
|
|
3818
|
-
if (controller.signal.aborted || seq !== seqRef.current) return;
|
|
3819
|
-
setPhase("error");
|
|
3820
|
-
}
|
|
3821
|
-
})();
|
|
3822
|
-
return () => controller.abort();
|
|
3823
|
-
}, [q, sort, seedKey, isDefaultView, reloadKey]);
|
|
3824
|
-
const loadMore = useCallback9(() => {
|
|
3825
|
-
const cursor = nextCursorRef.current;
|
|
3826
|
-
if (!cursor || loadingMoreRef.current) return;
|
|
3827
|
-
const { q: currentQ, sort: currentSort, fetchPage: currentFetch } = viewRef.current;
|
|
3828
|
-
const seq = seqRef.current;
|
|
3829
|
-
loadingMoreRef.current = true;
|
|
3830
|
-
lastOpRef.current = "more";
|
|
3831
|
-
const controller = new AbortController();
|
|
3832
|
-
loadMoreAbortRef.current = controller;
|
|
3833
|
-
setPhase("loadingMore");
|
|
3834
|
-
void (async () => {
|
|
3835
|
-
try {
|
|
3836
|
-
const page = await currentFetch({ q: currentQ, sort: currentSort, cursor, signal: controller.signal });
|
|
3837
|
-
if (seq !== seqRef.current) return;
|
|
3838
|
-
setItems((prev) => mergeSessionPages(prev, page.items));
|
|
3839
|
-
setNextCursor(page.nextCursor ?? null);
|
|
3840
|
-
setPhase("idle");
|
|
3841
|
-
} catch {
|
|
3842
|
-
if (controller.signal.aborted || seq !== seqRef.current) return;
|
|
3843
|
-
setPhase("error");
|
|
3844
|
-
} finally {
|
|
3845
|
-
if (seq === seqRef.current) loadingMoreRef.current = false;
|
|
3846
|
-
}
|
|
3847
|
-
})();
|
|
3848
|
-
}, []);
|
|
3849
|
-
const retry = useCallback9(() => {
|
|
3850
|
-
if (lastOpRef.current === "more") loadMore();
|
|
3851
|
-
else setReloadKey((key) => key + 1);
|
|
3852
|
-
}, [loadMore]);
|
|
3853
|
-
const reload = useCallback9(() => {
|
|
3854
|
-
setReloadKey((key) => key + 1);
|
|
3855
|
-
}, []);
|
|
3856
|
-
useEffect10(
|
|
3857
|
-
() => () => {
|
|
3858
|
-
resetAbortRef.current?.abort();
|
|
3859
|
-
loadMoreAbortRef.current?.abort();
|
|
3860
|
-
},
|
|
3861
|
-
[]
|
|
3862
|
-
);
|
|
3863
|
-
return {
|
|
3864
|
-
items,
|
|
3865
|
-
hasMore: nextCursor !== null,
|
|
3866
|
-
isLoadingFirst: phase === "loadingFirst",
|
|
3867
|
-
isLoadingMore: phase === "loadingMore",
|
|
3868
|
-
isError: phase === "error",
|
|
3869
|
-
loadMore,
|
|
3870
|
-
retry,
|
|
3871
|
-
reload
|
|
3872
|
-
};
|
|
3873
|
-
}
|
|
3874
|
-
var DEFAULT_LABELS = {
|
|
3875
|
-
renameTitle: "Rename session",
|
|
3876
|
-
renameField: "Title",
|
|
3877
|
-
renameSubmit: "Save",
|
|
3878
|
-
deleteTitle: "Delete session?",
|
|
3879
|
-
deleteBody: (title) => `This will permanently delete \u201C${title}\u201D and its messages. This cannot be undone.`,
|
|
3880
|
-
deleteSubmit: "Delete",
|
|
3881
|
-
cancel: "Cancel",
|
|
3882
|
-
renamed: "Session renamed",
|
|
3883
|
-
deleted: "Session deleted",
|
|
3884
|
-
renameFailed: "Failed to rename session",
|
|
3885
|
-
deleteFailed: "Failed to delete session"
|
|
3886
|
-
};
|
|
3887
|
-
function useSessionActions({
|
|
3888
|
-
renameSession,
|
|
3889
|
-
deleteSession,
|
|
3890
|
-
onChanged,
|
|
3891
|
-
onDeletedCurrent,
|
|
3892
|
-
currentSessionId,
|
|
3893
|
-
notify,
|
|
3894
|
-
labels
|
|
3895
|
-
}) {
|
|
3896
|
-
const text = { ...DEFAULT_LABELS, ...labels };
|
|
3897
|
-
const [renameTarget, setRenameTarget] = useState14(null);
|
|
3898
|
-
const [renameValue, setRenameValue] = useState14("");
|
|
3899
|
-
const [deleteTarget, setDeleteTarget] = useState14(null);
|
|
3900
|
-
const [busy, setBusy] = useState14(false);
|
|
3901
|
-
const [error, setError] = useState14(null);
|
|
3902
|
-
const openRename = useCallback9((session) => {
|
|
3903
|
-
setError(null);
|
|
3904
|
-
setRenameTarget(session);
|
|
3905
|
-
setRenameValue(session.title ?? "");
|
|
3906
|
-
}, []);
|
|
3907
|
-
const openDelete = useCallback9((session) => {
|
|
3908
|
-
setError(null);
|
|
3909
|
-
setDeleteTarget(session);
|
|
3910
|
-
}, []);
|
|
3911
|
-
const submitRename = useCallback9(async () => {
|
|
3912
|
-
if (!renameTarget) return;
|
|
3913
|
-
const title = renameValue.trim();
|
|
3914
|
-
if (!title || title === renameTarget.title) {
|
|
3915
|
-
setRenameTarget(null);
|
|
3916
|
-
return;
|
|
3917
|
-
}
|
|
3918
|
-
setBusy(true);
|
|
3919
|
-
setError(null);
|
|
3920
|
-
try {
|
|
3921
|
-
await renameSession(renameTarget.id, title);
|
|
3922
|
-
setRenameTarget(null);
|
|
3923
|
-
notify?.("success", text.renamed);
|
|
3924
|
-
onChanged?.();
|
|
3925
|
-
} catch (e) {
|
|
3926
|
-
const message = e instanceof Error ? e.message : text.renameFailed;
|
|
3927
|
-
setError(message);
|
|
3928
|
-
notify?.("error", message);
|
|
3929
|
-
} finally {
|
|
3930
|
-
setBusy(false);
|
|
3931
|
-
}
|
|
3932
|
-
}, [renameTarget, renameValue, renameSession, notify, onChanged, text.renamed, text.renameFailed]);
|
|
3933
|
-
const confirmDelete = useCallback9(async () => {
|
|
3934
|
-
if (!deleteTarget) return;
|
|
3935
|
-
const deletingCurrent = currentSessionId != null && deleteTarget.id === currentSessionId;
|
|
3936
|
-
setBusy(true);
|
|
3937
|
-
setError(null);
|
|
3938
|
-
try {
|
|
3939
|
-
await deleteSession(deleteTarget.id);
|
|
3940
|
-
setDeleteTarget(null);
|
|
3941
|
-
notify?.("success", text.deleted);
|
|
3942
|
-
onChanged?.();
|
|
3943
|
-
if (deletingCurrent) onDeletedCurrent?.();
|
|
3944
|
-
} catch (e) {
|
|
3945
|
-
const message = e instanceof Error ? e.message : text.deleteFailed;
|
|
3946
|
-
setError(message);
|
|
3947
|
-
notify?.("error", message);
|
|
3948
|
-
} finally {
|
|
3949
|
-
setBusy(false);
|
|
3950
|
-
}
|
|
3951
|
-
}, [deleteTarget, currentSessionId, deleteSession, notify, onChanged, onDeletedCurrent, text.deleted, text.deleteFailed]);
|
|
3952
|
-
const dialogs = /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
3953
|
-
renameTarget && /* @__PURE__ */ jsxs9(
|
|
3954
|
-
SessionDialog,
|
|
3955
|
-
{
|
|
3956
|
-
title: text.renameTitle,
|
|
3957
|
-
onClose: () => setRenameTarget(null),
|
|
3958
|
-
busy,
|
|
3959
|
-
error,
|
|
3960
|
-
footer: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
3961
|
-
/* @__PURE__ */ jsx11(DialogButton, { onClick: () => setRenameTarget(null), disabled: busy, variant: "ghost", children: text.cancel }),
|
|
3962
|
-
/* @__PURE__ */ jsx11(DialogButton, { onClick: () => void submitRename(), disabled: busy || !renameValue.trim(), children: text.renameSubmit })
|
|
3963
|
-
] }),
|
|
3964
|
-
children: [
|
|
3965
|
-
/* @__PURE__ */ jsx11("label", { htmlFor: "agent-app-rename-session", className: "text-xs text-muted-foreground", children: text.renameField }),
|
|
3966
|
-
/* @__PURE__ */ jsx11(
|
|
3967
|
-
"input",
|
|
3968
|
-
{
|
|
3969
|
-
id: "agent-app-rename-session",
|
|
3970
|
-
value: renameValue,
|
|
3971
|
-
autoFocus: true,
|
|
3972
|
-
onChange: (e) => setRenameValue(e.target.value),
|
|
3973
|
-
onKeyDown: (e) => {
|
|
3974
|
-
if (e.key === "Enter" && !busy) {
|
|
3975
|
-
e.preventDefault();
|
|
3976
|
-
void submitRename();
|
|
3977
|
-
}
|
|
3978
|
-
},
|
|
3979
|
-
className: "mt-1.5 h-9 w-full rounded-md border border-strong bg-background px-3 text-sm text-foreground"
|
|
3980
|
-
}
|
|
3981
|
-
)
|
|
3982
|
-
]
|
|
3983
|
-
}
|
|
3984
|
-
),
|
|
3985
|
-
deleteTarget && /* @__PURE__ */ jsx11(
|
|
3986
|
-
SessionDialog,
|
|
3987
|
-
{
|
|
3988
|
-
title: text.deleteTitle,
|
|
3989
|
-
onClose: () => setDeleteTarget(null),
|
|
3990
|
-
busy,
|
|
3991
|
-
error,
|
|
3992
|
-
footer: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
3993
|
-
/* @__PURE__ */ jsx11(DialogButton, { onClick: () => setDeleteTarget(null), disabled: busy, variant: "ghost", children: text.cancel }),
|
|
3994
|
-
/* @__PURE__ */ jsx11(DialogButton, { onClick: () => void confirmDelete(), disabled: busy, variant: "destructive", children: text.deleteSubmit })
|
|
3995
|
-
] }),
|
|
3996
|
-
children: /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: text.deleteBody(sessionLabel(deleteTarget)) })
|
|
3997
|
-
}
|
|
3998
|
-
)
|
|
3999
|
-
] });
|
|
4000
|
-
return { openRename, openDelete, dialogs, busy };
|
|
4001
|
-
}
|
|
4002
|
-
function DialogButton({
|
|
4003
|
-
children,
|
|
4004
|
-
onClick,
|
|
4005
|
-
disabled,
|
|
4006
|
-
variant = "primary"
|
|
4007
|
-
}) {
|
|
4008
|
-
const tone = variant === "ghost" ? "text-muted-foreground hover:bg-accent hover:text-foreground" : variant === "destructive" ? "bg-destructive text-destructive-foreground hover:opacity-90" : "bg-primary text-primary-foreground hover:opacity-90";
|
|
4009
|
-
return /* @__PURE__ */ jsx11(
|
|
4010
|
-
"button",
|
|
4011
|
-
{
|
|
4012
|
-
type: "button",
|
|
4013
|
-
onClick,
|
|
4014
|
-
disabled,
|
|
4015
|
-
className: `h-9 rounded-md px-3 text-sm font-medium transition disabled:opacity-50 ${tone}`,
|
|
4016
|
-
children
|
|
4017
|
-
}
|
|
4018
|
-
);
|
|
4019
|
-
}
|
|
4020
|
-
function SessionDialog({
|
|
4021
|
-
title,
|
|
4022
|
-
children,
|
|
4023
|
-
footer,
|
|
4024
|
-
onClose,
|
|
4025
|
-
busy,
|
|
4026
|
-
error
|
|
4027
|
-
}) {
|
|
4028
|
-
useEffect10(() => {
|
|
4029
|
-
const onKey = (e) => {
|
|
4030
|
-
if (e.key === "Escape" && !busy) onClose();
|
|
4031
|
-
};
|
|
4032
|
-
document.addEventListener("keydown", onKey);
|
|
4033
|
-
return () => document.removeEventListener("keydown", onKey);
|
|
4034
|
-
}, [busy, onClose]);
|
|
4035
|
-
return /* @__PURE__ */ jsxs9("div", { className: "fixed inset-0 z-50 flex items-center justify-center p-4", children: [
|
|
4036
|
-
/* @__PURE__ */ jsx11(
|
|
4037
|
-
"div",
|
|
4038
|
-
{
|
|
4039
|
-
className: "absolute inset-0 bg-black/50",
|
|
4040
|
-
onClick: () => {
|
|
4041
|
-
if (!busy) onClose();
|
|
4042
|
-
},
|
|
4043
|
-
"aria-hidden": true
|
|
4044
|
-
}
|
|
4045
|
-
),
|
|
4046
|
-
/* @__PURE__ */ jsxs9(
|
|
4047
|
-
"div",
|
|
4048
|
-
{
|
|
4049
|
-
role: "dialog",
|
|
4050
|
-
"aria-modal": "true",
|
|
4051
|
-
"aria-label": title,
|
|
4052
|
-
className: `relative w-full max-w-sm rounded-xl border border-card-edge bg-popover p-5 ${OVERLAY_SHADOW}`,
|
|
4053
|
-
children: [
|
|
4054
|
-
/* @__PURE__ */ jsx11("h2", { className: "text-sm font-semibold text-foreground", children: title }),
|
|
4055
|
-
/* @__PURE__ */ jsx11("div", { className: "mt-3", children }),
|
|
4056
|
-
error && /* @__PURE__ */ jsx11("p", { role: "alert", className: "mt-3 rounded-md bg-destructive/10 px-3 py-2 text-xs text-destructive", children: error }),
|
|
4057
|
-
/* @__PURE__ */ jsx11("div", { className: "mt-5 flex justify-end gap-2", children: footer })
|
|
4058
|
-
]
|
|
4059
|
-
}
|
|
4060
|
-
)
|
|
4061
|
-
] });
|
|
4062
|
-
}
|
|
4063
|
-
function AnchorLink({ to, className, children }) {
|
|
4064
|
-
return /* @__PURE__ */ jsx11("a", { href: to, className, children });
|
|
4065
|
-
}
|
|
4066
|
-
var MINUTE = 6e4;
|
|
4067
|
-
var HOUR = 60 * MINUTE;
|
|
4068
|
-
var DAY = 24 * HOUR;
|
|
4069
|
-
function formatSessionTimestamp(isoDate) {
|
|
4070
|
-
if (!isoDate) return "";
|
|
4071
|
-
const at = Date.parse(isoDate);
|
|
4072
|
-
if (Number.isNaN(at)) return "";
|
|
4073
|
-
const delta = Date.now() - at;
|
|
4074
|
-
if (delta < MINUTE) return "just now";
|
|
4075
|
-
if (delta < HOUR) return `${Math.floor(delta / MINUTE)}m ago`;
|
|
4076
|
-
if (delta < DAY) return `${Math.floor(delta / HOUR)}h ago`;
|
|
4077
|
-
if (delta < 7 * DAY) return `${Math.floor(delta / DAY)}d ago`;
|
|
4078
|
-
return new Date(at).toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
4079
|
-
}
|
|
4080
|
-
function SkeletonRows() {
|
|
4081
|
-
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
4082
|
-
/* @__PURE__ */ jsx11("span", { role: "status", "aria-live": "polite", "aria-busy": true, className: "sr-only", children: "Loading sessions\u2026" }),
|
|
4083
|
-
/* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-0.5", "aria-hidden": true, children: Array.from({ length: 8 }).map((_, i) => /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 px-3 py-2.5", children: [
|
|
4084
|
-
/* @__PURE__ */ jsx11("div", { className: "h-4 w-4 animate-pulse rounded bg-muted" }),
|
|
4085
|
-
/* @__PURE__ */ jsx11("div", { className: "h-4 w-1/2 animate-pulse rounded bg-muted" }),
|
|
4086
|
-
/* @__PURE__ */ jsx11("div", { className: "ml-auto h-3 w-12 animate-pulse rounded bg-muted" })
|
|
4087
|
-
] }, i)) })
|
|
4088
|
-
] });
|
|
4089
|
-
}
|
|
4090
|
-
function MessageIcon({ className }) {
|
|
4091
|
-
return /* @__PURE__ */ jsx11("svg", { viewBox: "0 0 24 24", className, fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx11("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
|
|
4092
|
-
}
|
|
4093
|
-
function SessionHistoryPanel({
|
|
4094
|
-
history,
|
|
4095
|
-
hasAnySessions,
|
|
4096
|
-
query,
|
|
4097
|
-
onQueryChange,
|
|
4098
|
-
sort,
|
|
4099
|
-
onSortChange,
|
|
4100
|
-
hrefForSession,
|
|
4101
|
-
linkComponent: Link = AnchorLink,
|
|
4102
|
-
respondingSessionIds,
|
|
4103
|
-
onRename,
|
|
4104
|
-
onDelete,
|
|
4105
|
-
onBulkAction,
|
|
4106
|
-
renameLabel = "Rename",
|
|
4107
|
-
deleteLabel = "Delete",
|
|
4108
|
-
extraActions,
|
|
4109
|
-
newSessionHref,
|
|
4110
|
-
title = "History",
|
|
4111
|
-
untitledLabel = UNTITLED_SESSION_LABEL,
|
|
4112
|
-
emptyTitle = "No sessions yet",
|
|
4113
|
-
emptyDescription = "Your chat sessions will show up here once you start one.",
|
|
4114
|
-
formatTimestamp = formatSessionTimestamp,
|
|
4115
|
-
contentWidth = "reading",
|
|
4116
|
-
className
|
|
4117
|
-
}) {
|
|
4118
|
-
const scrollRef = useRef10(null);
|
|
4119
|
-
const sentinelRef = useInfiniteScroll(history.loadMore, {
|
|
4120
|
-
enabled: history.hasMore && !history.isLoadingMore && !history.isError,
|
|
4121
|
-
root: scrollRef,
|
|
4122
|
-
rootMargin: "300px"
|
|
4123
|
-
});
|
|
4124
|
-
const searchTerm = query.trim();
|
|
4125
|
-
const isSearching = searchTerm.length > 0;
|
|
4126
|
-
const column = contentWidth === "full" ? "w-full" : "mx-auto w-full max-w-4xl";
|
|
4127
|
-
const [selectedIds, setSelectedIds] = useState14(/* @__PURE__ */ new Set());
|
|
4128
|
-
const [ageDays, setAgeDays] = useState14("30");
|
|
4129
|
-
const [bulkTarget, setBulkTarget] = useState14(null);
|
|
4130
|
-
const [bulkBusy, setBulkBusy] = useState14(false);
|
|
4131
|
-
const [bulkError, setBulkError] = useState14(null);
|
|
4132
|
-
useEffect10(() => {
|
|
4133
|
-
setSelectedIds(/* @__PURE__ */ new Set());
|
|
4134
|
-
}, [searchTerm, sort]);
|
|
4135
|
-
useEffect10(() => {
|
|
4136
|
-
const visible = new Set(history.items.map((item) => item.id));
|
|
4137
|
-
setSelectedIds((current) => {
|
|
4138
|
-
const next = new Set([...current].filter((id) => visible.has(id)));
|
|
4139
|
-
return next.size === current.size ? current : next;
|
|
4140
|
-
});
|
|
4141
|
-
}, [history.items]);
|
|
4142
|
-
const selectedCount = selectedIds.size;
|
|
4143
|
-
const allVisibleSelected = history.items.length > 0 && history.items.every((item) => selectedIds.has(item.id));
|
|
4144
|
-
const parsedAgeDays = Number(ageDays);
|
|
4145
|
-
const validAgeDays = Number.isInteger(parsedAgeDays) && parsedAgeDays >= 1 && parsedAgeDays <= 36500;
|
|
4146
|
-
const openBulkAction = useCallback9((action) => {
|
|
4147
|
-
const verb = deleteLabel.toLowerCase();
|
|
4148
|
-
if (action.kind === "selected") {
|
|
4149
|
-
setBulkTarget({
|
|
4150
|
-
action,
|
|
4151
|
-
title: `${deleteLabel} selected sessions?`,
|
|
4152
|
-
body: `${verb === "delete" ? "This permanently removes" : `This ${verb}s`} ${action.ids.length} selected session${action.ids.length === 1 ? "" : "s"} and its messages.`
|
|
4153
|
-
});
|
|
4154
|
-
return;
|
|
4155
|
-
}
|
|
4156
|
-
const range = action.kind === "older-than" ? `older than ${action.days} days` : `from the last ${action.days} days`;
|
|
4157
|
-
setBulkTarget({
|
|
4158
|
-
action,
|
|
4159
|
-
title: `${deleteLabel} sessions ${range}?`,
|
|
4160
|
-
body: "This applies to every matching session in this workspace, including sessions not currently loaded in this list."
|
|
4161
|
-
});
|
|
4162
|
-
}, [deleteLabel]);
|
|
4163
|
-
const confirmBulkAction = useCallback9(async () => {
|
|
4164
|
-
if (!bulkTarget || !onBulkAction) return;
|
|
4165
|
-
setBulkBusy(true);
|
|
4166
|
-
setBulkError(null);
|
|
4167
|
-
try {
|
|
4168
|
-
await onBulkAction(bulkTarget.action);
|
|
4169
|
-
setBulkTarget(null);
|
|
4170
|
-
setSelectedIds(/* @__PURE__ */ new Set());
|
|
4171
|
-
history.reload();
|
|
4172
|
-
} catch (error) {
|
|
4173
|
-
setBulkError(error instanceof Error ? error.message : `Could not ${deleteLabel.toLowerCase()} sessions`);
|
|
4174
|
-
} finally {
|
|
4175
|
-
setBulkBusy(false);
|
|
4176
|
-
}
|
|
4177
|
-
}, [bulkTarget, deleteLabel, history, onBulkAction]);
|
|
4178
|
-
return /* @__PURE__ */ jsxs9("div", { className: `flex min-h-0 min-w-0 flex-1 flex-col ${className ?? ""}`, children: [
|
|
4179
|
-
/* @__PURE__ */ jsx11("header", { className: "flex h-14 shrink-0 items-center border-b border-border px-4 sm:px-6", children: /* @__PURE__ */ jsxs9("div", { className: `flex items-center gap-3 px-3 ${column}`, children: [
|
|
4180
|
-
/* @__PURE__ */ jsx11("h1", { className: "flex-1 truncate text-sm font-semibold text-foreground", children: title }),
|
|
4181
|
-
newSessionHref && /* @__PURE__ */ jsxs9(
|
|
4182
|
-
Link,
|
|
4183
|
-
{
|
|
4184
|
-
to: newSessionHref,
|
|
4185
|
-
className: "inline-flex h-8 shrink-0 items-center gap-1.5 rounded-md bg-primary px-3 text-xs font-medium text-primary-foreground transition hover:opacity-90",
|
|
4186
|
-
children: [
|
|
4187
|
-
/* @__PURE__ */ jsx11("span", { "aria-hidden": true, className: "text-sm leading-none", children: "+" }),
|
|
4188
|
-
"New chat"
|
|
4189
|
-
]
|
|
4190
|
-
}
|
|
4191
|
-
)
|
|
4192
|
-
] }) }),
|
|
4193
|
-
/* @__PURE__ */ jsxs9("div", { ref: scrollRef, className: "min-h-0 flex-1 overflow-y-auto", children: [
|
|
4194
|
-
hasAnySessions && /* @__PURE__ */ jsxs9("div", { className: "sticky top-0 z-10 bg-background px-4 sm:px-6", children: [
|
|
4195
|
-
/* @__PURE__ */ jsxs9("div", { className: `flex flex-col gap-2 px-3 pb-3 pt-4 sm:flex-row sm:items-center sm:gap-3 ${column}`, children: [
|
|
4196
|
-
/* @__PURE__ */ jsx11(
|
|
4197
|
-
"input",
|
|
4198
|
-
{
|
|
4199
|
-
type: "search",
|
|
4200
|
-
value: query,
|
|
4201
|
-
onChange: (e) => onQueryChange(e.target.value),
|
|
4202
|
-
placeholder: "Search your sessions\u2026",
|
|
4203
|
-
"aria-label": "Search sessions",
|
|
4204
|
-
className: "h-9 min-w-0 appearance-none rounded-md border border-strong bg-card px-3 text-sm text-foreground placeholder:text-muted-foreground sm:flex-1 [&::-webkit-search-cancel-button]:appearance-none"
|
|
4205
|
-
}
|
|
4206
|
-
),
|
|
4207
|
-
/* @__PURE__ */ jsxs9(
|
|
4208
|
-
"select",
|
|
4209
|
-
{
|
|
4210
|
-
value: sort,
|
|
4211
|
-
onChange: (e) => onSortChange(e.target.value),
|
|
4212
|
-
"aria-label": "Sort sessions",
|
|
4213
|
-
className: "h-9 shrink-0 appearance-none rounded-md border border-strong bg-card px-2 text-sm text-foreground sm:w-[132px]",
|
|
4214
|
-
children: [
|
|
4215
|
-
/* @__PURE__ */ jsx11("option", { value: "newest", children: "Newest" }),
|
|
4216
|
-
/* @__PURE__ */ jsx11("option", { value: "oldest", children: "Oldest" })
|
|
4217
|
-
]
|
|
4218
|
-
}
|
|
4219
|
-
)
|
|
4220
|
-
] }),
|
|
4221
|
-
onBulkAction && /* @__PURE__ */ jsxs9("div", { className: `flex flex-col gap-2 border-t border-border px-3 py-3 ${column}`, children: [
|
|
4222
|
-
/* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4223
|
-
/* @__PURE__ */ jsx11(
|
|
4224
|
-
"button",
|
|
4225
|
-
{
|
|
4226
|
-
type: "button",
|
|
4227
|
-
onClick: () => setSelectedIds(new Set(history.items.map((item) => item.id))),
|
|
4228
|
-
disabled: allVisibleSelected || history.items.length === 0,
|
|
4229
|
-
className: "h-8 rounded-md border border-border px-2.5 text-xs font-medium text-foreground transition hover:bg-accent disabled:opacity-50",
|
|
4230
|
-
children: "Select all"
|
|
4231
|
-
}
|
|
4232
|
-
),
|
|
4233
|
-
/* @__PURE__ */ jsx11(
|
|
4234
|
-
"button",
|
|
4235
|
-
{
|
|
4236
|
-
type: "button",
|
|
4237
|
-
onClick: () => setSelectedIds(/* @__PURE__ */ new Set()),
|
|
4238
|
-
disabled: selectedCount === 0,
|
|
4239
|
-
className: "h-8 rounded-md border border-border px-2.5 text-xs font-medium text-foreground transition hover:bg-accent disabled:opacity-50",
|
|
4240
|
-
children: "Deselect all"
|
|
4241
|
-
}
|
|
4242
|
-
),
|
|
4243
|
-
/* @__PURE__ */ jsxs9("span", { className: "text-xs text-muted-foreground", "aria-live": "polite", children: [
|
|
4244
|
-
selectedCount,
|
|
4245
|
-
" selected"
|
|
4246
|
-
] }),
|
|
4247
|
-
selectedCount > 0 && /* @__PURE__ */ jsxs9(
|
|
4248
|
-
"button",
|
|
4249
|
-
{
|
|
4250
|
-
type: "button",
|
|
4251
|
-
onClick: () => openBulkAction({ kind: "selected", ids: [...selectedIds] }),
|
|
4252
|
-
className: "h-8 rounded-md bg-destructive px-2.5 text-xs font-medium text-destructive-foreground transition hover:opacity-90",
|
|
4253
|
-
children: [
|
|
4254
|
-
deleteLabel,
|
|
4255
|
-
" selected"
|
|
4256
|
-
]
|
|
4257
|
-
}
|
|
4258
|
-
)
|
|
4259
|
-
] }),
|
|
4260
|
-
/* @__PURE__ */ jsxs9("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
4261
|
-
/* @__PURE__ */ jsx11("label", { htmlFor: "agent-app-session-age", className: "text-xs text-muted-foreground", children: "Session age" }),
|
|
4262
|
-
/* @__PURE__ */ jsx11(
|
|
4263
|
-
"input",
|
|
4264
|
-
{
|
|
4265
|
-
id: "agent-app-session-age",
|
|
4266
|
-
type: "number",
|
|
4267
|
-
min: 1,
|
|
4268
|
-
max: 36500,
|
|
4269
|
-
value: ageDays,
|
|
4270
|
-
onChange: (event) => setAgeDays(event.target.value),
|
|
4271
|
-
"aria-invalid": ageDays.length > 0 && !validAgeDays,
|
|
4272
|
-
className: "h-8 w-20 rounded-md border border-strong bg-card px-2 text-xs tabular-nums text-foreground"
|
|
4273
|
-
}
|
|
4274
|
-
),
|
|
4275
|
-
/* @__PURE__ */ jsx11("span", { className: "text-xs text-muted-foreground", children: "days" }),
|
|
4276
|
-
/* @__PURE__ */ jsxs9(
|
|
4277
|
-
"button",
|
|
4278
|
-
{
|
|
4279
|
-
type: "button",
|
|
4280
|
-
onClick: () => openBulkAction({ kind: "older-than", days: parsedAgeDays }),
|
|
4281
|
-
disabled: !validAgeDays,
|
|
4282
|
-
className: "h-8 rounded-md border border-border px-2.5 text-xs font-medium text-foreground transition hover:bg-accent disabled:opacity-50",
|
|
4283
|
-
children: [
|
|
4284
|
-
deleteLabel,
|
|
4285
|
-
" older"
|
|
4286
|
-
]
|
|
4287
|
-
}
|
|
4288
|
-
),
|
|
4289
|
-
/* @__PURE__ */ jsxs9(
|
|
4290
|
-
"button",
|
|
4291
|
-
{
|
|
4292
|
-
type: "button",
|
|
4293
|
-
onClick: () => openBulkAction({ kind: "newer-than", days: parsedAgeDays }),
|
|
4294
|
-
disabled: !validAgeDays,
|
|
4295
|
-
className: "h-8 rounded-md border border-border px-2.5 text-xs font-medium text-foreground transition hover:bg-accent disabled:opacity-50",
|
|
4296
|
-
children: [
|
|
4297
|
-
deleteLabel,
|
|
4298
|
-
" recent"
|
|
4299
|
-
]
|
|
4300
|
-
}
|
|
4301
|
-
)
|
|
4302
|
-
] })
|
|
4303
|
-
] })
|
|
4304
|
-
] }),
|
|
4305
|
-
/* @__PURE__ */ jsx11("div", { className: `px-4 pb-8 pt-1 sm:px-6 ${column}`, children: !hasAnySessions ? /* @__PURE__ */ jsxs9("div", { className: "flex min-h-[50vh] flex-col items-center justify-center gap-2 text-center", children: [
|
|
4306
|
-
/* @__PURE__ */ jsx11("p", { className: "text-sm font-medium text-foreground", children: emptyTitle }),
|
|
4307
|
-
/* @__PURE__ */ jsx11("p", { className: "max-w-xs text-xs text-muted-foreground", children: emptyDescription })
|
|
4308
|
-
] }) : history.isLoadingFirst ? /* @__PURE__ */ jsx11(SkeletonRows, {}) : history.items.length === 0 ? history.isError ? /* @__PURE__ */ jsx11(ErrorBlock, { onRetry: history.retry, message: "Couldn\u2019t load your sessions." }) : isSearching ? /* @__PURE__ */ jsxs9("p", { className: "py-16 text-center text-sm text-muted-foreground", children: [
|
|
4309
|
-
"No sessions match \u201C",
|
|
4310
|
-
searchTerm,
|
|
4311
|
-
"\u201D."
|
|
4312
|
-
] }) : /* @__PURE__ */ jsx11("p", { className: "py-16 text-center text-sm text-muted-foreground", children: "No sessions remain." }) : /* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-0.5", children: [
|
|
4313
|
-
history.items.map((session) => /* @__PURE__ */ jsx11(
|
|
4314
|
-
SessionRow,
|
|
4315
|
-
{
|
|
4316
|
-
session,
|
|
4317
|
-
href: hrefForSession(session.id),
|
|
4318
|
-
Link,
|
|
4319
|
-
responding: respondingSessionIds?.has(session.id) ?? false,
|
|
4320
|
-
untitledLabel,
|
|
4321
|
-
timestamp: formatTimestamp(session.updatedAt),
|
|
4322
|
-
onRename,
|
|
4323
|
-
onDelete,
|
|
4324
|
-
selectable: Boolean(onBulkAction),
|
|
4325
|
-
selected: selectedIds.has(session.id),
|
|
4326
|
-
onSelectedChange: (selected) => {
|
|
4327
|
-
setSelectedIds((current) => {
|
|
4328
|
-
const next = new Set(current);
|
|
4329
|
-
if (selected) next.add(session.id);
|
|
4330
|
-
else next.delete(session.id);
|
|
4331
|
-
return next;
|
|
4332
|
-
});
|
|
4333
|
-
},
|
|
4334
|
-
renameLabel,
|
|
4335
|
-
deleteLabel,
|
|
4336
|
-
extraActions
|
|
4337
|
-
},
|
|
4338
|
-
session.id
|
|
4339
|
-
)),
|
|
4340
|
-
history.isError ? /* @__PURE__ */ jsx11(ErrorBlock, { onRetry: history.retry, message: "Couldn\u2019t load more sessions.", inline: true }) : history.hasMore ? /* @__PURE__ */ jsx11("div", { ref: sentinelRef, className: "flex items-center justify-center py-6", children: history.isLoadingMore && /* @__PURE__ */ jsx11("span", { role: "status", "aria-live": "polite", "aria-busy": true, className: "text-xs text-muted-foreground", children: "Loading\u2026" }) }) : null
|
|
4341
|
-
] }) })
|
|
4342
|
-
] }),
|
|
4343
|
-
bulkTarget && /* @__PURE__ */ jsx11(
|
|
4344
|
-
SessionDialog,
|
|
4345
|
-
{
|
|
4346
|
-
title: bulkTarget.title,
|
|
4347
|
-
onClose: () => {
|
|
4348
|
-
if (!bulkBusy) {
|
|
4349
|
-
setBulkTarget(null);
|
|
4350
|
-
setBulkError(null);
|
|
4351
|
-
}
|
|
4352
|
-
},
|
|
4353
|
-
busy: bulkBusy,
|
|
4354
|
-
error: bulkError,
|
|
4355
|
-
footer: /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
4356
|
-
/* @__PURE__ */ jsx11(
|
|
4357
|
-
DialogButton,
|
|
4358
|
-
{
|
|
4359
|
-
onClick: () => {
|
|
4360
|
-
setBulkTarget(null);
|
|
4361
|
-
setBulkError(null);
|
|
4362
|
-
},
|
|
4363
|
-
disabled: bulkBusy,
|
|
4364
|
-
variant: "ghost",
|
|
4365
|
-
children: "Cancel"
|
|
4366
|
-
}
|
|
4367
|
-
),
|
|
4368
|
-
/* @__PURE__ */ jsx11(DialogButton, { onClick: () => void confirmBulkAction(), disabled: bulkBusy, variant: "destructive", children: bulkBusy ? "Working\u2026" : deleteLabel })
|
|
4369
|
-
] }),
|
|
4370
|
-
children: /* @__PURE__ */ jsx11("p", { className: "text-sm text-muted-foreground", children: bulkTarget.body })
|
|
4371
|
-
}
|
|
4372
|
-
)
|
|
4373
|
-
] });
|
|
4374
|
-
}
|
|
4375
|
-
function ErrorBlock({ message, onRetry, inline }) {
|
|
4376
|
-
return /* @__PURE__ */ jsxs9(
|
|
4377
|
-
"div",
|
|
4378
|
-
{
|
|
4379
|
-
className: inline ? "flex items-center justify-center gap-3 py-6 text-sm text-muted-foreground" : "flex min-h-[40vh] flex-col items-center justify-center gap-3 text-center",
|
|
4380
|
-
children: [
|
|
4381
|
-
/* @__PURE__ */ jsx11("span", { className: "text-sm text-muted-foreground", children: message }),
|
|
4382
|
-
/* @__PURE__ */ jsx11(
|
|
4383
|
-
"button",
|
|
4384
|
-
{
|
|
4385
|
-
type: "button",
|
|
4386
|
-
onClick: onRetry,
|
|
4387
|
-
className: "h-8 rounded-md border border-border px-3 text-xs font-medium text-foreground transition hover:bg-accent",
|
|
4388
|
-
children: "Retry"
|
|
4389
|
-
}
|
|
4390
|
-
)
|
|
4391
|
-
]
|
|
4392
|
-
}
|
|
4393
|
-
);
|
|
4394
|
-
}
|
|
4395
|
-
function SessionRow({
|
|
4396
|
-
session,
|
|
4397
|
-
href,
|
|
4398
|
-
Link,
|
|
4399
|
-
responding,
|
|
4400
|
-
untitledLabel,
|
|
4401
|
-
timestamp,
|
|
4402
|
-
onRename,
|
|
4403
|
-
onDelete,
|
|
4404
|
-
renameLabel,
|
|
4405
|
-
deleteLabel,
|
|
4406
|
-
extraActions,
|
|
4407
|
-
selectable,
|
|
4408
|
-
selected,
|
|
4409
|
-
onSelectedChange
|
|
4410
|
-
}) {
|
|
4411
|
-
const [menuOpen, setMenuOpen] = useState14(false);
|
|
4412
|
-
const panelId = useId3();
|
|
4413
|
-
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(menuOpen, setMenuOpen);
|
|
4414
|
-
const extras = extraActions?.(session) ?? [];
|
|
4415
|
-
const hasMenu = Boolean(onRename) || Boolean(onDelete) || extras.length > 0;
|
|
4416
|
-
const showUnread = Boolean(session.unread) && !responding;
|
|
4417
|
-
return /* @__PURE__ */ jsxs9("div", { className: `group relative flex items-center gap-2 rounded-lg px-3 py-2.5 transition-colors hover:bg-accent ${selected ? "bg-primary/10" : ""}`, children: [
|
|
4418
|
-
selectable && /* @__PURE__ */ jsx11(
|
|
4419
|
-
"input",
|
|
4420
|
-
{
|
|
4421
|
-
type: "checkbox",
|
|
4422
|
-
checked: selected,
|
|
4423
|
-
onChange: (event) => onSelectedChange(event.target.checked),
|
|
4424
|
-
"aria-label": `Select ${sessionLabel(session, untitledLabel)}`,
|
|
4425
|
-
className: "h-4 w-4 shrink-0 rounded border-border accent-primary"
|
|
4426
|
-
}
|
|
4427
|
-
),
|
|
4428
|
-
/* @__PURE__ */ jsxs9(Link, { to: href, className: "flex min-w-0 flex-1 items-center gap-3", children: [
|
|
4429
|
-
showUnread && /* @__PURE__ */ jsx11("span", { className: "h-1.5 w-1.5 shrink-0 rounded-full bg-primary", "aria-hidden": true }),
|
|
4430
|
-
/* @__PURE__ */ jsx11(MessageIcon, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
4431
|
-
/* @__PURE__ */ jsx11(
|
|
4432
|
-
"span",
|
|
4433
|
-
{
|
|
4434
|
-
className: `truncate text-sm ${responding ? "text-muted-foreground" : "text-foreground"} ${showUnread ? "font-semibold" : ""}`,
|
|
4435
|
-
...responding ? { role: "status", "aria-label": "Agent responding" } : {},
|
|
4436
|
-
children: sessionLabel(session, untitledLabel)
|
|
4437
|
-
}
|
|
4438
|
-
)
|
|
4439
|
-
] }),
|
|
4440
|
-
/* @__PURE__ */ jsx11("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: timestamp }),
|
|
4441
|
-
hasMenu && /* @__PURE__ */ jsxs9("div", { ref: containerRef, className: "relative shrink-0", children: [
|
|
4442
|
-
/* @__PURE__ */ jsx11(
|
|
4443
|
-
"button",
|
|
4444
|
-
{
|
|
4445
|
-
type: "button",
|
|
4446
|
-
...triggerProps,
|
|
4447
|
-
"aria-label": "Session actions",
|
|
4448
|
-
"aria-controls": menuOpen ? panelId : void 0,
|
|
4449
|
-
onClick: () => setMenuOpen((open) => !open),
|
|
4450
|
-
className: "flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition hover:bg-muted hover:text-foreground focus-visible:opacity-100 sm:opacity-0 sm:group-hover:opacity-100 aria-expanded:opacity-100",
|
|
4451
|
-
children: /* @__PURE__ */ jsx11("span", { "aria-hidden": true, className: "text-base leading-none", children: "\u22EF" })
|
|
4452
|
-
}
|
|
4453
|
-
),
|
|
4454
|
-
/* @__PURE__ */ jsxs9(
|
|
4455
|
-
PopoverSurface,
|
|
4456
|
-
{
|
|
4457
|
-
open: menuOpen,
|
|
4458
|
-
id: panelId,
|
|
4459
|
-
role: "menu",
|
|
4460
|
-
triggerRef,
|
|
4461
|
-
panelRef,
|
|
4462
|
-
className: `w-36 overflow-hidden rounded-md border border-card-edge bg-popover py-1 ${OVERLAY_SHADOW}`,
|
|
4463
|
-
children: [
|
|
4464
|
-
onRename && /* @__PURE__ */ jsx11(
|
|
4465
|
-
"button",
|
|
4466
|
-
{
|
|
4467
|
-
type: "button",
|
|
4468
|
-
role: "menuitem",
|
|
4469
|
-
onClick: () => {
|
|
4470
|
-
setMenuOpen(false);
|
|
4471
|
-
onRename(session);
|
|
4472
|
-
},
|
|
4473
|
-
className: "block w-full px-3 py-1.5 text-left text-xs text-foreground transition hover:bg-accent",
|
|
4474
|
-
children: renameLabel
|
|
4475
|
-
}
|
|
4476
|
-
),
|
|
4477
|
-
extras.map((action) => /* @__PURE__ */ jsx11(
|
|
4478
|
-
"button",
|
|
4479
|
-
{
|
|
4480
|
-
type: "button",
|
|
4481
|
-
role: "menuitem",
|
|
4482
|
-
onClick: () => {
|
|
4483
|
-
setMenuOpen(false);
|
|
4484
|
-
action.onSelect();
|
|
4485
|
-
},
|
|
4486
|
-
className: `block w-full px-3 py-1.5 text-left text-xs transition ${action.destructive ? "text-destructive hover:bg-destructive/10" : "text-foreground hover:bg-accent"}`,
|
|
4487
|
-
children: action.label
|
|
4488
|
-
},
|
|
4489
|
-
action.id
|
|
4490
|
-
)),
|
|
4491
|
-
onDelete && /* @__PURE__ */ jsx11(
|
|
4492
|
-
"button",
|
|
4493
|
-
{
|
|
4494
|
-
type: "button",
|
|
4495
|
-
role: "menuitem",
|
|
4496
|
-
onClick: () => {
|
|
4497
|
-
setMenuOpen(false);
|
|
4498
|
-
onDelete(session);
|
|
4499
|
-
},
|
|
4500
|
-
className: "block w-full px-3 py-1.5 text-left text-xs text-destructive transition hover:bg-destructive/10",
|
|
4501
|
-
children: deleteLabel
|
|
4502
|
-
}
|
|
4503
|
-
)
|
|
4504
|
-
]
|
|
4505
|
-
}
|
|
4506
|
-
)
|
|
4507
|
-
] })
|
|
4508
|
-
] });
|
|
4509
|
-
}
|
|
4510
|
-
|
|
4511
|
-
// src/web-react/record-grid.tsx
|
|
4512
|
-
import {
|
|
4513
|
-
Fragment as Fragment6,
|
|
4514
|
-
isValidElement,
|
|
4515
|
-
useCallback as useCallback10,
|
|
4516
|
-
useEffect as useEffect11,
|
|
4517
|
-
useId as useId4,
|
|
4518
|
-
useMemo as useMemo7,
|
|
4519
|
-
useRef as useRef11,
|
|
4520
|
-
useState as useState15
|
|
4521
|
-
} from "react";
|
|
4522
3870
|
|
|
4523
3871
|
// src/web-react/record-grid-model.ts
|
|
4524
3872
|
function recordGridOk(value) {
|
|
@@ -4873,7 +4221,7 @@ function pruneRecordGridOverlay(rows, overlay) {
|
|
|
4873
4221
|
}
|
|
4874
4222
|
|
|
4875
4223
|
// src/web-react/record-grid.tsx
|
|
4876
|
-
import { jsx as
|
|
4224
|
+
import { jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
4877
4225
|
var EMPTY_RECORD_GRID_ROWS = [];
|
|
4878
4226
|
var CELL_KEY_SEPARATOR = "\0";
|
|
4879
4227
|
function cellKey(rowId, columnId) {
|
|
@@ -4932,57 +4280,57 @@ function RecordGrid({
|
|
|
4932
4280
|
loadingRowCount = 3,
|
|
4933
4281
|
className
|
|
4934
4282
|
}) {
|
|
4935
|
-
const fieldPrefix =
|
|
4936
|
-
const [overlay, setOverlay] =
|
|
4937
|
-
const [editing, setEditingState] =
|
|
4938
|
-
const [cellErrors, setCellErrors] =
|
|
4939
|
-
const [rowErrors, setRowErrors] =
|
|
4940
|
-
const [pendingRows, setPendingRows] =
|
|
4941
|
-
const [focus, setFocus] =
|
|
4942
|
-
const [openSource, setOpenSource] =
|
|
4943
|
-
const [confirmDelete, setConfirmDelete] =
|
|
4944
|
-
const [adding, setAdding] =
|
|
4945
|
-
const [draft, setDraft] =
|
|
4946
|
-
const [draftErrors, setDraftErrors] =
|
|
4947
|
-
const [draftError, setDraftError] =
|
|
4948
|
-
const [creating, setCreating] =
|
|
4949
|
-
const cellRefs =
|
|
4950
|
-
const settling =
|
|
4951
|
-
const draftCounter =
|
|
4952
|
-
const editingRef =
|
|
4953
|
-
const setEditing =
|
|
4283
|
+
const fieldPrefix = useId3();
|
|
4284
|
+
const [overlay, setOverlay] = useState14(EMPTY_RECORD_GRID_OVERLAY);
|
|
4285
|
+
const [editing, setEditingState] = useState14(null);
|
|
4286
|
+
const [cellErrors, setCellErrors] = useState14({});
|
|
4287
|
+
const [rowErrors, setRowErrors] = useState14({});
|
|
4288
|
+
const [pendingRows, setPendingRows] = useState14({});
|
|
4289
|
+
const [focus, setFocus] = useState14(null);
|
|
4290
|
+
const [openSource, setOpenSource] = useState14(null);
|
|
4291
|
+
const [confirmDelete, setConfirmDelete] = useState14(null);
|
|
4292
|
+
const [adding, setAdding] = useState14(false);
|
|
4293
|
+
const [draft, setDraft] = useState14({ ...newRowDefaults ?? {} });
|
|
4294
|
+
const [draftErrors, setDraftErrors] = useState14({});
|
|
4295
|
+
const [draftError, setDraftError] = useState14(null);
|
|
4296
|
+
const [creating, setCreating] = useState14(false);
|
|
4297
|
+
const cellRefs = useRef10(/* @__PURE__ */ new Map());
|
|
4298
|
+
const settling = useRef10(false);
|
|
4299
|
+
const draftCounter = useRef10(0);
|
|
4300
|
+
const editingRef = useRef10(null);
|
|
4301
|
+
const setEditing = useCallback9((next) => {
|
|
4954
4302
|
editingRef.current = next;
|
|
4955
4303
|
setEditingState(next);
|
|
4956
4304
|
}, []);
|
|
4957
4305
|
const callerRows = state.status === "ready" || state.status === "empty" ? state.value : EMPTY_RECORD_GRID_ROWS;
|
|
4958
|
-
|
|
4306
|
+
useEffect10(() => {
|
|
4959
4307
|
setOverlay((current) => pruneRecordGridOverlay(callerRows, current));
|
|
4960
4308
|
}, [callerRows]);
|
|
4961
|
-
const visibleRows =
|
|
4962
|
-
const diffs =
|
|
4309
|
+
const visibleRows = useMemo6(() => projectRecordGridRows(callerRows, overlay), [callerRows, overlay]);
|
|
4310
|
+
const diffs = useMemo6(
|
|
4963
4311
|
() => proposed === void 0 ? null : diffRecordGridProposal(visibleRows, proposed),
|
|
4964
4312
|
[proposed, visibleRows]
|
|
4965
4313
|
);
|
|
4966
4314
|
const reviewing = diffs !== null && diffs.length > 0;
|
|
4967
|
-
const diffByRow =
|
|
4968
|
-
const diffCellByKey =
|
|
4315
|
+
const diffByRow = useMemo6(() => new Map((diffs ?? []).map((diff) => [diff.rowId, diff])), [diffs]);
|
|
4316
|
+
const diffCellByKey = useMemo6(() => {
|
|
4969
4317
|
const map = /* @__PURE__ */ new Map();
|
|
4970
4318
|
for (const diff of diffs ?? []) {
|
|
4971
4319
|
for (const cell of diff.cells) map.set(cellKey(diff.rowId, cell.columnId), cell);
|
|
4972
4320
|
}
|
|
4973
4321
|
return map;
|
|
4974
4322
|
}, [diffs]);
|
|
4975
|
-
const addedRows =
|
|
4323
|
+
const addedRows = useMemo6(
|
|
4976
4324
|
() => (diffs ?? []).filter((diff) => diff.kind === "added").map((diff) => diff.row),
|
|
4977
4325
|
[diffs]
|
|
4978
4326
|
);
|
|
4979
|
-
const activeFocus =
|
|
4327
|
+
const activeFocus = useMemo6(() => {
|
|
4980
4328
|
if (focus === null) return null;
|
|
4981
4329
|
if (!visibleRows.some((row) => row.id === focus.rowId)) return null;
|
|
4982
4330
|
if (!columns.some((column) => column.id === focus.columnId)) return null;
|
|
4983
4331
|
return focus;
|
|
4984
4332
|
}, [columns, focus, visibleRows]);
|
|
4985
|
-
const setCellError =
|
|
4333
|
+
const setCellError = useCallback9((key, message) => {
|
|
4986
4334
|
setCellErrors((current) => {
|
|
4987
4335
|
if (message === null) {
|
|
4988
4336
|
if (!(key in current)) return current;
|
|
@@ -4994,7 +4342,7 @@ function RecordGrid({
|
|
|
4994
4342
|
return { ...current, [key]: message };
|
|
4995
4343
|
});
|
|
4996
4344
|
}, []);
|
|
4997
|
-
const setRowError =
|
|
4345
|
+
const setRowError = useCallback9((rowId, message) => {
|
|
4998
4346
|
setRowErrors((current) => {
|
|
4999
4347
|
if (message === null) {
|
|
5000
4348
|
if (!(rowId in current)) return current;
|
|
@@ -5005,7 +4353,7 @@ function RecordGrid({
|
|
|
5005
4353
|
return { ...current, [rowId]: message };
|
|
5006
4354
|
});
|
|
5007
4355
|
}, []);
|
|
5008
|
-
const setRowPending =
|
|
4356
|
+
const setRowPending = useCallback9((rowId, pending) => {
|
|
5009
4357
|
setPendingRows((current) => {
|
|
5010
4358
|
if (pending) return rowId in current ? current : { ...current, [rowId]: true };
|
|
5011
4359
|
if (!(rowId in current)) return current;
|
|
@@ -5014,11 +4362,11 @@ function RecordGrid({
|
|
|
5014
4362
|
return next;
|
|
5015
4363
|
});
|
|
5016
4364
|
}, []);
|
|
5017
|
-
const focusCell =
|
|
4365
|
+
const focusCell = useCallback9((rowId, columnId) => {
|
|
5018
4366
|
setFocus({ rowId, columnId });
|
|
5019
4367
|
cellRefs.current.get(cellKey(rowId, columnId))?.focus();
|
|
5020
4368
|
}, []);
|
|
5021
|
-
const beginEdit =
|
|
4369
|
+
const beginEdit = useCallback9(
|
|
5022
4370
|
(row, column) => {
|
|
5023
4371
|
setCellError(cellKey(row.id, column.id), null);
|
|
5024
4372
|
setEditing({
|
|
@@ -5029,7 +4377,7 @@ function RecordGrid({
|
|
|
5029
4377
|
},
|
|
5030
4378
|
[setCellError, setEditing]
|
|
5031
4379
|
);
|
|
5032
|
-
const applyCellWrite =
|
|
4380
|
+
const applyCellWrite = useCallback9(
|
|
5033
4381
|
async (row, column, value) => {
|
|
5034
4382
|
if (!onUpdate) return;
|
|
5035
4383
|
const values = { ...row.values, [column.id]: value };
|
|
@@ -5057,7 +4405,7 @@ function RecordGrid({
|
|
|
5057
4405
|
},
|
|
5058
4406
|
[locale, onUpdate, setRowError, setRowPending]
|
|
5059
4407
|
);
|
|
5060
|
-
const commitEdit =
|
|
4408
|
+
const commitEdit = useCallback9(
|
|
5061
4409
|
async (row, column, text) => {
|
|
5062
4410
|
const open = editingRef.current;
|
|
5063
4411
|
if (open === null || open.rowId !== row.id || open.columnId !== column.id) return;
|
|
@@ -5081,7 +4429,7 @@ function RecordGrid({
|
|
|
5081
4429
|
},
|
|
5082
4430
|
[applyCellWrite, setCellError, setEditing]
|
|
5083
4431
|
);
|
|
5084
|
-
const cancelEdit =
|
|
4432
|
+
const cancelEdit = useCallback9(
|
|
5085
4433
|
(row, column) => {
|
|
5086
4434
|
setCellError(cellKey(row.id, column.id), null);
|
|
5087
4435
|
setEditing(null);
|
|
@@ -5089,7 +4437,7 @@ function RecordGrid({
|
|
|
5089
4437
|
},
|
|
5090
4438
|
[focusCell, setCellError, setEditing]
|
|
5091
4439
|
);
|
|
5092
|
-
const performDelete =
|
|
4440
|
+
const performDelete = useCallback9(
|
|
5093
4441
|
async (row) => {
|
|
5094
4442
|
if (!onDelete) return;
|
|
5095
4443
|
setConfirmDelete(null);
|
|
@@ -5107,16 +4455,16 @@ function RecordGrid({
|
|
|
5107
4455
|
},
|
|
5108
4456
|
[columns, onDelete, setRowError]
|
|
5109
4457
|
);
|
|
5110
|
-
const resetDraft =
|
|
4458
|
+
const resetDraft = useCallback9(() => {
|
|
5111
4459
|
setDraft({ ...newRowDefaults ?? {} });
|
|
5112
4460
|
setDraftErrors({});
|
|
5113
4461
|
setDraftError(null);
|
|
5114
4462
|
}, [newRowDefaults]);
|
|
5115
|
-
const openAdd =
|
|
4463
|
+
const openAdd = useCallback9(() => {
|
|
5116
4464
|
resetDraft();
|
|
5117
4465
|
setAdding(true);
|
|
5118
4466
|
}, [resetDraft]);
|
|
5119
|
-
const submitDraft =
|
|
4467
|
+
const submitDraft = useCallback9(async () => {
|
|
5120
4468
|
if (!onCreate) return;
|
|
5121
4469
|
const validated = validateRecordGridRow(columns, draft);
|
|
5122
4470
|
if (!validated.succeeded) {
|
|
@@ -5146,7 +4494,7 @@ function RecordGrid({
|
|
|
5146
4494
|
setOverlay((current) => withoutRecordGridCreated(current, draftId));
|
|
5147
4495
|
setDraftError(outcome.error);
|
|
5148
4496
|
}, [columns, draft, fieldPrefix, onCreate, resetDraft]);
|
|
5149
|
-
const handleGridKeyDown =
|
|
4497
|
+
const handleGridKeyDown = useCallback9(
|
|
5150
4498
|
(event) => {
|
|
5151
4499
|
if (editing !== null) return;
|
|
5152
4500
|
const target = event.target;
|
|
@@ -5185,9 +4533,9 @@ function RecordGrid({
|
|
|
5185
4533
|
[beginEdit, columns, editing, focusCell, onUpdate, reviewing, visibleRows]
|
|
5186
4534
|
);
|
|
5187
4535
|
if (state.status === "idle" || state.status === "loading") {
|
|
5188
|
-
return /* @__PURE__ */
|
|
4536
|
+
return /* @__PURE__ */ jsxs9("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
5189
4537
|
toolbar,
|
|
5190
|
-
/* @__PURE__ */
|
|
4538
|
+
/* @__PURE__ */ jsxs9(
|
|
5191
4539
|
"div",
|
|
5192
4540
|
{
|
|
5193
4541
|
role: "status",
|
|
@@ -5195,22 +4543,22 @@ function RecordGrid({
|
|
|
5195
4543
|
"aria-live": "polite",
|
|
5196
4544
|
className: "space-y-2 rounded-xl border border-card-edge bg-card p-4",
|
|
5197
4545
|
children: [
|
|
5198
|
-
/* @__PURE__ */
|
|
4546
|
+
/* @__PURE__ */ jsxs9("span", { className: "sr-only", children: [
|
|
5199
4547
|
"Loading ",
|
|
5200
4548
|
caption
|
|
5201
4549
|
] }),
|
|
5202
|
-
Array.from({ length: Math.max(1, loadingRowCount) }, (_, index) => /* @__PURE__ */
|
|
4550
|
+
Array.from({ length: Math.max(1, loadingRowCount) }, (_, index) => /* @__PURE__ */ jsx11("div", { className: "h-8 animate-pulse rounded-md bg-secondary", "aria-hidden": true }, index))
|
|
5203
4551
|
]
|
|
5204
4552
|
}
|
|
5205
4553
|
)
|
|
5206
4554
|
] });
|
|
5207
4555
|
}
|
|
5208
4556
|
if (state.status === "error") {
|
|
5209
|
-
return /* @__PURE__ */
|
|
4557
|
+
return /* @__PURE__ */ jsxs9("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
5210
4558
|
toolbar,
|
|
5211
|
-
/* @__PURE__ */
|
|
5212
|
-
/* @__PURE__ */
|
|
5213
|
-
/* @__PURE__ */
|
|
4559
|
+
/* @__PURE__ */ jsxs9("div", { role: "alert", className: "rounded-xl border border-destructive/40 bg-destructive/10 px-4 py-4", children: [
|
|
4560
|
+
/* @__PURE__ */ jsx11("p", { className: "text-sm font-medium text-destructive", children: state.message }),
|
|
4561
|
+
/* @__PURE__ */ jsx11(
|
|
5214
4562
|
"button",
|
|
5215
4563
|
{
|
|
5216
4564
|
type: "button",
|
|
@@ -5222,7 +4570,7 @@ function RecordGrid({
|
|
|
5222
4570
|
] })
|
|
5223
4571
|
] });
|
|
5224
4572
|
}
|
|
5225
|
-
const addForm = adding && onCreate && !reviewing ? /* @__PURE__ */
|
|
4573
|
+
const addForm = adding && onCreate && !reviewing ? /* @__PURE__ */ jsx11(
|
|
5226
4574
|
AddRecordForm,
|
|
5227
4575
|
{
|
|
5228
4576
|
columns,
|
|
@@ -5241,13 +4589,13 @@ function RecordGrid({
|
|
|
5241
4589
|
}
|
|
5242
4590
|
) : null;
|
|
5243
4591
|
if (visibleRows.length === 0 && !reviewing) {
|
|
5244
|
-
return /* @__PURE__ */
|
|
4592
|
+
return /* @__PURE__ */ jsxs9("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
5245
4593
|
toolbar,
|
|
5246
|
-
addForm ?? /* @__PURE__ */
|
|
5247
|
-
/* @__PURE__ */
|
|
5248
|
-
empty.description && /* @__PURE__ */
|
|
5249
|
-
/* @__PURE__ */
|
|
5250
|
-
empty.action && (isValidElement(empty.action) ? empty.action : /* @__PURE__ */
|
|
4594
|
+
addForm ?? /* @__PURE__ */ jsxs9("div", { className: "rounded-xl border border-dashed border-border px-6 py-10 text-center", children: [
|
|
4595
|
+
/* @__PURE__ */ jsx11("p", { className: "text-sm font-medium text-foreground", children: empty.title }),
|
|
4596
|
+
empty.description && /* @__PURE__ */ jsx11("p", { className: "mx-auto mt-1 max-w-md text-sm text-muted-foreground", children: empty.description }),
|
|
4597
|
+
/* @__PURE__ */ jsxs9("div", { className: "mt-4 flex flex-wrap items-center justify-center gap-2", children: [
|
|
4598
|
+
empty.action && (isValidElement(empty.action) ? empty.action : /* @__PURE__ */ jsx11(
|
|
5251
4599
|
"button",
|
|
5252
4600
|
{
|
|
5253
4601
|
type: "button",
|
|
@@ -5256,7 +4604,7 @@ function RecordGrid({
|
|
|
5256
4604
|
children: empty.action.label
|
|
5257
4605
|
}
|
|
5258
4606
|
)),
|
|
5259
|
-
onCreate && /* @__PURE__ */
|
|
4607
|
+
onCreate && /* @__PURE__ */ jsx11(
|
|
5260
4608
|
"button",
|
|
5261
4609
|
{
|
|
5262
4610
|
type: "button",
|
|
@@ -5281,18 +4629,18 @@ function RecordGrid({
|
|
|
5281
4629
|
addedCount > 0 ? `${addedCount} added` : null,
|
|
5282
4630
|
removedCount > 0 ? `${removedCount} removed` : null
|
|
5283
4631
|
].filter((part) => part !== null).join(" \xB7 ");
|
|
5284
|
-
const reviewBar = reviewing ? /* @__PURE__ */
|
|
4632
|
+
const reviewBar = reviewing ? /* @__PURE__ */ jsxs9(
|
|
5285
4633
|
"div",
|
|
5286
4634
|
{
|
|
5287
4635
|
"data-record-grid-review": "",
|
|
5288
4636
|
className: "flex flex-wrap items-center justify-between gap-3 rounded-xl border border-card-edge bg-card px-4 py-2.5",
|
|
5289
4637
|
children: [
|
|
5290
|
-
/* @__PURE__ */
|
|
5291
|
-
/* @__PURE__ */
|
|
5292
|
-
/* @__PURE__ */
|
|
4638
|
+
/* @__PURE__ */ jsxs9("div", { className: "min-w-0", children: [
|
|
4639
|
+
/* @__PURE__ */ jsx11("p", { className: "text-[11px] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: "Proposed changes" }),
|
|
4640
|
+
/* @__PURE__ */ jsx11("p", { className: "mt-0.5 text-xs tabular-nums text-muted-foreground", children: reviewSummary })
|
|
5293
4641
|
] }),
|
|
5294
|
-
(onAcceptAll || onRejectAll) && /* @__PURE__ */
|
|
5295
|
-
onRejectAll && /* @__PURE__ */
|
|
4642
|
+
(onAcceptAll || onRejectAll) && /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
4643
|
+
onRejectAll && /* @__PURE__ */ jsx11(
|
|
5296
4644
|
"button",
|
|
5297
4645
|
{
|
|
5298
4646
|
type: "button",
|
|
@@ -5302,7 +4650,7 @@ function RecordGrid({
|
|
|
5302
4650
|
children: "Reject all"
|
|
5303
4651
|
}
|
|
5304
4652
|
),
|
|
5305
|
-
onAcceptAll && /* @__PURE__ */
|
|
4653
|
+
onAcceptAll && /* @__PURE__ */ jsx11(
|
|
5306
4654
|
"button",
|
|
5307
4655
|
{
|
|
5308
4656
|
type: "button",
|
|
@@ -5316,10 +4664,10 @@ function RecordGrid({
|
|
|
5316
4664
|
]
|
|
5317
4665
|
}
|
|
5318
4666
|
) : null;
|
|
5319
|
-
return /* @__PURE__ */
|
|
4667
|
+
return /* @__PURE__ */ jsxs9("div", { className: `space-y-3 ${className ?? ""}`, children: [
|
|
5320
4668
|
toolbar,
|
|
5321
4669
|
reviewBar,
|
|
5322
|
-
/* @__PURE__ */
|
|
4670
|
+
/* @__PURE__ */ jsx11("div", { className: "overflow-x-auto rounded-xl border border-card-edge bg-card", children: /* @__PURE__ */ jsxs9(
|
|
5323
4671
|
"table",
|
|
5324
4672
|
{
|
|
5325
4673
|
role: "grid",
|
|
@@ -5327,8 +4675,8 @@ function RecordGrid({
|
|
|
5327
4675
|
className: "w-full border-collapse text-left text-sm",
|
|
5328
4676
|
onKeyDown: handleGridKeyDown,
|
|
5329
4677
|
children: [
|
|
5330
|
-
/* @__PURE__ */
|
|
5331
|
-
columns.map((column) => /* @__PURE__ */
|
|
4678
|
+
/* @__PURE__ */ jsx11("thead", { children: /* @__PURE__ */ jsxs9("tr", { role: "row", className: "border-b border-border text-xs uppercase tracking-[0.05em] text-muted-foreground", children: [
|
|
4679
|
+
columns.map((column) => /* @__PURE__ */ jsx11(
|
|
5332
4680
|
"th",
|
|
5333
4681
|
{
|
|
5334
4682
|
role: "columnheader",
|
|
@@ -5338,17 +4686,17 @@ function RecordGrid({
|
|
|
5338
4686
|
},
|
|
5339
4687
|
column.id
|
|
5340
4688
|
)),
|
|
5341
|
-
showActionsColumn && /* @__PURE__ */
|
|
4689
|
+
showActionsColumn && /* @__PURE__ */ jsx11("th", { role: "columnheader", scope: "col", className: "w-px px-3 py-2 font-medium", children: /* @__PURE__ */ jsx11("span", { className: "sr-only", children: reviewing ? "Review" : "Row actions" }) })
|
|
5342
4690
|
] }) }),
|
|
5343
|
-
/* @__PURE__ */
|
|
4691
|
+
/* @__PURE__ */ jsxs9("tbody", { children: [
|
|
5344
4692
|
visibleRows.map((row) => {
|
|
5345
4693
|
const rowLabel = recordGridRowLabel(columns, row);
|
|
5346
4694
|
const pending = row.id in pendingRows;
|
|
5347
4695
|
const rowError = rowErrors[row.id];
|
|
5348
4696
|
const rowDiff = reviewing ? diffByRow.get(row.id) : void 0;
|
|
5349
4697
|
const removedRow = rowDiff?.kind === "removed";
|
|
5350
|
-
return /* @__PURE__ */
|
|
5351
|
-
/* @__PURE__ */
|
|
4698
|
+
return /* @__PURE__ */ jsxs9(Fragment5, { children: [
|
|
4699
|
+
/* @__PURE__ */ jsxs9(
|
|
5352
4700
|
"tr",
|
|
5353
4701
|
{
|
|
5354
4702
|
role: "row",
|
|
@@ -5368,8 +4716,8 @@ function RecordGrid({
|
|
|
5368
4716
|
const errorId = `${fieldPrefix}-cell-error-${row.id}-${column.id}`;
|
|
5369
4717
|
const cellDiff = rowDiff?.kind === "changed" ? diffCellByKey.get(key) : void 0;
|
|
5370
4718
|
if (isEditing && editable) {
|
|
5371
|
-
return /* @__PURE__ */
|
|
5372
|
-
/* @__PURE__ */
|
|
4719
|
+
return /* @__PURE__ */ jsxs9("td", { role: "gridcell", className: `px-3 py-1.5 ${alignmentClass(column)}`, children: [
|
|
4720
|
+
/* @__PURE__ */ jsx11(
|
|
5373
4721
|
CellEditor,
|
|
5374
4722
|
{
|
|
5375
4723
|
column,
|
|
@@ -5382,11 +4730,11 @@ function RecordGrid({
|
|
|
5382
4730
|
onCancel: () => cancelEdit(row, column)
|
|
5383
4731
|
}
|
|
5384
4732
|
),
|
|
5385
|
-
cellError !== void 0 && /* @__PURE__ */
|
|
4733
|
+
cellError !== void 0 && /* @__PURE__ */ jsx11("p", { id: errorId, role: "alert", className: "mt-1 text-xs leading-snug text-destructive", children: cellError })
|
|
5386
4734
|
] }, column.id);
|
|
5387
4735
|
}
|
|
5388
4736
|
if (column.kind === "boolean" && editable) {
|
|
5389
|
-
return /* @__PURE__ */
|
|
4737
|
+
return /* @__PURE__ */ jsx11("td", { role: "gridcell", className: `px-3 py-2 ${alignmentClass(column)}`, children: /* @__PURE__ */ jsx11(
|
|
5390
4738
|
"input",
|
|
5391
4739
|
{
|
|
5392
4740
|
type: "checkbox",
|
|
@@ -5405,7 +4753,7 @@ function RecordGrid({
|
|
|
5405
4753
|
) }, column.id);
|
|
5406
4754
|
}
|
|
5407
4755
|
const display = applicable ? formatRecordGridValue(column, value, locale) : "";
|
|
5408
|
-
return /* @__PURE__ */
|
|
4756
|
+
return /* @__PURE__ */ jsx11(
|
|
5409
4757
|
"td",
|
|
5410
4758
|
{
|
|
5411
4759
|
role: "gridcell",
|
|
@@ -5423,20 +4771,20 @@ function RecordGrid({
|
|
|
5423
4771
|
className: `px-3 py-2 outline-none focus:ring-2 focus:ring-inset focus:ring-primary/50 ${alignmentClass(
|
|
5424
4772
|
column
|
|
5425
4773
|
)} ${editable ? "cursor-text" : ""}`,
|
|
5426
|
-
children: /* @__PURE__ */
|
|
5427
|
-
column.id === columns[0]?.id && removedRow && /* @__PURE__ */
|
|
5428
|
-
cellDiff ? /* @__PURE__ */
|
|
5429
|
-
/* @__PURE__ */
|
|
5430
|
-
/* @__PURE__ */
|
|
5431
|
-
/* @__PURE__ */
|
|
5432
|
-
] }) : /* @__PURE__ */
|
|
4774
|
+
children: /* @__PURE__ */ jsxs9("span", { className: "inline-flex max-w-full items-center gap-1.5", children: [
|
|
4775
|
+
column.id === columns[0]?.id && removedRow && /* @__PURE__ */ jsx11("span", { className: "inline-flex shrink-0 rounded border border-destructive/60 px-1 py-px text-[11px] font-semibold uppercase tracking-[0.05em] text-destructive", children: "Remove" }),
|
|
4776
|
+
cellDiff ? /* @__PURE__ */ jsxs9("span", { className: "inline-flex max-w-full flex-wrap items-baseline gap-x-1.5", children: [
|
|
4777
|
+
/* @__PURE__ */ jsx11("span", { className: "tabular-nums text-destructive line-through decoration-destructive/60", children: formatRecordGridValue(column, cellDiff.before, locale) || "\u2014" }),
|
|
4778
|
+
/* @__PURE__ */ jsx11("span", { "aria-hidden": "true", className: "text-muted-foreground", children: "\u2192" }),
|
|
4779
|
+
/* @__PURE__ */ jsx11("span", { className: "tabular-nums font-medium text-success", children: formatRecordGridValue(column, cellDiff.after, locale) || "\u2014" })
|
|
4780
|
+
] }) : /* @__PURE__ */ jsx11(
|
|
5433
4781
|
"span",
|
|
5434
4782
|
{
|
|
5435
4783
|
className: removedRow ? "truncate text-destructive line-through decoration-destructive/60" : display === "" ? "text-muted-foreground" : "truncate text-foreground",
|
|
5436
4784
|
children: display === "" ? applicable ? "\u2014" : "n/a" : display
|
|
5437
4785
|
}
|
|
5438
4786
|
),
|
|
5439
|
-
source && /* @__PURE__ */
|
|
4787
|
+
source && /* @__PURE__ */ jsx11(
|
|
5440
4788
|
SourceMarker,
|
|
5441
4789
|
{
|
|
5442
4790
|
panelId: `${fieldPrefix}-source-${row.id}-${column.id}`,
|
|
@@ -5452,7 +4800,7 @@ function RecordGrid({
|
|
|
5452
4800
|
column.id
|
|
5453
4801
|
);
|
|
5454
4802
|
}),
|
|
5455
|
-
showActionsColumn && /* @__PURE__ */
|
|
4803
|
+
showActionsColumn && /* @__PURE__ */ jsx11("td", { role: "gridcell", className: "px-3 py-2 text-right", children: reviewing ? rowDiff && /* @__PURE__ */ jsx11(
|
|
5456
4804
|
ReviewActions,
|
|
5457
4805
|
{
|
|
5458
4806
|
rowId: row.id,
|
|
@@ -5461,8 +4809,8 @@ function RecordGrid({
|
|
|
5461
4809
|
onAccept: onAcceptRow,
|
|
5462
4810
|
onReject: onRejectRow
|
|
5463
4811
|
}
|
|
5464
|
-
) : row.readOnly === true ? null : confirmDelete === row.id ? /* @__PURE__ */
|
|
5465
|
-
/* @__PURE__ */
|
|
4812
|
+
) : row.readOnly === true ? null : confirmDelete === row.id ? /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
4813
|
+
/* @__PURE__ */ jsx11(
|
|
5466
4814
|
"button",
|
|
5467
4815
|
{
|
|
5468
4816
|
type: "button",
|
|
@@ -5472,7 +4820,7 @@ function RecordGrid({
|
|
|
5472
4820
|
children: "Delete"
|
|
5473
4821
|
}
|
|
5474
4822
|
),
|
|
5475
|
-
/* @__PURE__ */
|
|
4823
|
+
/* @__PURE__ */ jsx11(
|
|
5476
4824
|
"button",
|
|
5477
4825
|
{
|
|
5478
4826
|
type: "button",
|
|
@@ -5482,14 +4830,14 @@ function RecordGrid({
|
|
|
5482
4830
|
children: "Cancel"
|
|
5483
4831
|
}
|
|
5484
4832
|
)
|
|
5485
|
-
] }) : /* @__PURE__ */
|
|
4833
|
+
] }) : /* @__PURE__ */ jsx11(
|
|
5486
4834
|
"button",
|
|
5487
4835
|
{
|
|
5488
4836
|
type: "button",
|
|
5489
4837
|
"aria-label": `Delete ${rowLabel}`,
|
|
5490
4838
|
onClick: () => setConfirmDelete(row.id),
|
|
5491
4839
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-destructive/10 hover:text-destructive",
|
|
5492
|
-
children: /* @__PURE__ */
|
|
4840
|
+
children: /* @__PURE__ */ jsxs9(
|
|
5493
4841
|
"svg",
|
|
5494
4842
|
{
|
|
5495
4843
|
viewBox: "0 0 24 24",
|
|
@@ -5501,8 +4849,8 @@ function RecordGrid({
|
|
|
5501
4849
|
strokeLinejoin: "round",
|
|
5502
4850
|
"aria-hidden": true,
|
|
5503
4851
|
children: [
|
|
5504
|
-
/* @__PURE__ */
|
|
5505
|
-
/* @__PURE__ */
|
|
4852
|
+
/* @__PURE__ */ jsx11("polyline", { points: "3 6 5 6 21 6" }),
|
|
4853
|
+
/* @__PURE__ */ jsx11("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
|
|
5506
4854
|
]
|
|
5507
4855
|
}
|
|
5508
4856
|
)
|
|
@@ -5511,12 +4859,12 @@ function RecordGrid({
|
|
|
5511
4859
|
]
|
|
5512
4860
|
}
|
|
5513
4861
|
),
|
|
5514
|
-
rowError !== void 0 && /* @__PURE__ */
|
|
4862
|
+
rowError !== void 0 && /* @__PURE__ */ jsx11("tr", { role: "row", className: "border-b border-border", children: /* @__PURE__ */ jsx11("td", { role: "gridcell", colSpan: columnSpan, className: "px-3 pb-2", children: /* @__PURE__ */ jsx11("p", { role: "alert", className: "rounded-md bg-destructive/10 px-2.5 py-1.5 text-xs text-destructive", children: rowError }) }) })
|
|
5515
4863
|
] }, row.id);
|
|
5516
4864
|
}),
|
|
5517
4865
|
reviewing && addedRows.map((row) => {
|
|
5518
4866
|
const rowLabel = recordGridRowLabel(columns, row);
|
|
5519
|
-
return /* @__PURE__ */
|
|
4867
|
+
return /* @__PURE__ */ jsxs9(
|
|
5520
4868
|
"tr",
|
|
5521
4869
|
{
|
|
5522
4870
|
role: "row",
|
|
@@ -5527,9 +4875,9 @@ function RecordGrid({
|
|
|
5527
4875
|
const applicable = isRecordGridCellApplicable(column, row.values);
|
|
5528
4876
|
const value = row.values[column.id] ?? null;
|
|
5529
4877
|
const display = applicable ? formatRecordGridValue(column, value, locale) : "";
|
|
5530
|
-
return /* @__PURE__ */
|
|
5531
|
-
columnIndex === 0 && /* @__PURE__ */
|
|
5532
|
-
/* @__PURE__ */
|
|
4878
|
+
return /* @__PURE__ */ jsx11("td", { role: "gridcell", className: `px-3 py-2 ${alignmentClass(column)}`, children: /* @__PURE__ */ jsxs9("span", { className: "inline-flex max-w-full items-center gap-1.5", children: [
|
|
4879
|
+
columnIndex === 0 && /* @__PURE__ */ jsx11("span", { className: "inline-flex shrink-0 rounded border border-success/60 px-1 py-px text-[11px] font-semibold uppercase tracking-[0.05em] text-success", children: "New" }),
|
|
4880
|
+
/* @__PURE__ */ jsx11(
|
|
5533
4881
|
"span",
|
|
5534
4882
|
{
|
|
5535
4883
|
className: `tabular-nums ${display === "" ? "text-muted-foreground" : "truncate text-foreground"}`,
|
|
@@ -5538,7 +4886,7 @@ function RecordGrid({
|
|
|
5538
4886
|
)
|
|
5539
4887
|
] }) }, column.id);
|
|
5540
4888
|
}),
|
|
5541
|
-
/* @__PURE__ */
|
|
4889
|
+
/* @__PURE__ */ jsx11("td", { role: "gridcell", className: "px-3 py-2 text-right", children: /* @__PURE__ */ jsx11(
|
|
5542
4890
|
ReviewActions,
|
|
5543
4891
|
{
|
|
5544
4892
|
rowId: row.id,
|
|
@@ -5554,8 +4902,8 @@ function RecordGrid({
|
|
|
5554
4902
|
);
|
|
5555
4903
|
})
|
|
5556
4904
|
] }),
|
|
5557
|
-
hasFooter && /* @__PURE__ */
|
|
5558
|
-
columns.map((column) => /* @__PURE__ */
|
|
4905
|
+
hasFooter && /* @__PURE__ */ jsx11("tfoot", { children: /* @__PURE__ */ jsxs9("tr", { role: "row", className: "border-t-2 border-border", children: [
|
|
4906
|
+
columns.map((column) => /* @__PURE__ */ jsx11(
|
|
5559
4907
|
"td",
|
|
5560
4908
|
{
|
|
5561
4909
|
role: "gridcell",
|
|
@@ -5564,19 +4912,19 @@ function RecordGrid({
|
|
|
5564
4912
|
},
|
|
5565
4913
|
column.id
|
|
5566
4914
|
)),
|
|
5567
|
-
showActionsColumn && /* @__PURE__ */
|
|
4915
|
+
showActionsColumn && /* @__PURE__ */ jsx11("td", { role: "gridcell" })
|
|
5568
4916
|
] }) })
|
|
5569
4917
|
]
|
|
5570
4918
|
}
|
|
5571
4919
|
) }),
|
|
5572
|
-
onCreate && !reviewing && (addForm ?? /* @__PURE__ */
|
|
4920
|
+
onCreate && !reviewing && (addForm ?? /* @__PURE__ */ jsxs9(
|
|
5573
4921
|
"button",
|
|
5574
4922
|
{
|
|
5575
4923
|
type: "button",
|
|
5576
4924
|
onClick: openAdd,
|
|
5577
4925
|
className: "inline-flex items-center gap-1.5 rounded-md border border-border px-3 py-1.5 text-sm font-medium text-foreground transition hover:bg-accent",
|
|
5578
4926
|
children: [
|
|
5579
|
-
/* @__PURE__ */
|
|
4927
|
+
/* @__PURE__ */ jsxs9(
|
|
5580
4928
|
"svg",
|
|
5581
4929
|
{
|
|
5582
4930
|
viewBox: "0 0 24 24",
|
|
@@ -5588,8 +4936,8 @@ function RecordGrid({
|
|
|
5588
4936
|
strokeLinejoin: "round",
|
|
5589
4937
|
"aria-hidden": true,
|
|
5590
4938
|
children: [
|
|
5591
|
-
/* @__PURE__ */
|
|
5592
|
-
/* @__PURE__ */
|
|
4939
|
+
/* @__PURE__ */ jsx11("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
4940
|
+
/* @__PURE__ */ jsx11("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
|
|
5593
4941
|
]
|
|
5594
4942
|
}
|
|
5595
4943
|
),
|
|
@@ -5601,8 +4949,8 @@ function RecordGrid({
|
|
|
5601
4949
|
}
|
|
5602
4950
|
function ReviewActions({ rowId, kind, rowLabel, onAccept, onReject }) {
|
|
5603
4951
|
const noun = kind === "changed" ? `proposed change to ${rowLabel}` : kind === "added" ? `new row ${rowLabel}` : `removal of ${rowLabel}`;
|
|
5604
|
-
return /* @__PURE__ */
|
|
5605
|
-
onReject && /* @__PURE__ */
|
|
4952
|
+
return /* @__PURE__ */ jsxs9("span", { className: "inline-flex items-center gap-1.5", children: [
|
|
4953
|
+
onReject && /* @__PURE__ */ jsx11(
|
|
5606
4954
|
"button",
|
|
5607
4955
|
{
|
|
5608
4956
|
type: "button",
|
|
@@ -5612,7 +4960,7 @@ function ReviewActions({ rowId, kind, rowLabel, onAccept, onReject }) {
|
|
|
5612
4960
|
children: "Reject"
|
|
5613
4961
|
}
|
|
5614
4962
|
),
|
|
5615
|
-
onAccept && /* @__PURE__ */
|
|
4963
|
+
onAccept && /* @__PURE__ */ jsx11(
|
|
5616
4964
|
"button",
|
|
5617
4965
|
{
|
|
5618
4966
|
type: "button",
|
|
@@ -5633,7 +4981,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5633
4981
|
className: INPUT_CLASS
|
|
5634
4982
|
};
|
|
5635
4983
|
if (column.kind === "select") {
|
|
5636
|
-
return /* @__PURE__ */
|
|
4984
|
+
return /* @__PURE__ */ jsxs9(
|
|
5637
4985
|
"select",
|
|
5638
4986
|
{
|
|
5639
4987
|
...shared,
|
|
@@ -5650,8 +4998,8 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5650
4998
|
},
|
|
5651
4999
|
onBlur: () => onCommit(text),
|
|
5652
5000
|
children: [
|
|
5653
|
-
/* @__PURE__ */
|
|
5654
|
-
column.options.map((option) => /* @__PURE__ */
|
|
5001
|
+
/* @__PURE__ */ jsx11("option", { value: "", children: "\u2014" }),
|
|
5002
|
+
column.options.map((option) => /* @__PURE__ */ jsx11("option", { value: option.value, children: option.label }, option.value))
|
|
5655
5003
|
]
|
|
5656
5004
|
}
|
|
5657
5005
|
);
|
|
@@ -5669,7 +5017,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5669
5017
|
}
|
|
5670
5018
|
};
|
|
5671
5019
|
if (column.kind === "text" && column.multiline === true) {
|
|
5672
|
-
return /* @__PURE__ */
|
|
5020
|
+
return /* @__PURE__ */ jsx11(
|
|
5673
5021
|
"textarea",
|
|
5674
5022
|
{
|
|
5675
5023
|
...shared,
|
|
@@ -5681,7 +5029,7 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5681
5029
|
}
|
|
5682
5030
|
);
|
|
5683
5031
|
}
|
|
5684
|
-
return /* @__PURE__ */
|
|
5032
|
+
return /* @__PURE__ */ jsx11(
|
|
5685
5033
|
"input",
|
|
5686
5034
|
{
|
|
5687
5035
|
...shared,
|
|
@@ -5696,15 +5044,15 @@ function CellEditor({ column, rowLabel, text, invalid, describedBy, onText, onCo
|
|
|
5696
5044
|
}
|
|
5697
5045
|
function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle }) {
|
|
5698
5046
|
const basis = source.basis ?? "asserted";
|
|
5699
|
-
const setOpen =
|
|
5047
|
+
const setOpen = useCallback9(
|
|
5700
5048
|
(next) => {
|
|
5701
5049
|
if (!next) onToggle();
|
|
5702
5050
|
},
|
|
5703
5051
|
[onToggle]
|
|
5704
5052
|
);
|
|
5705
5053
|
const { containerRef, triggerRef, panelRef, triggerProps } = usePopover(open, setOpen);
|
|
5706
|
-
return /* @__PURE__ */
|
|
5707
|
-
/* @__PURE__ */
|
|
5054
|
+
return /* @__PURE__ */ jsxs9("span", { ref: containerRef, className: "relative inline-flex", children: [
|
|
5055
|
+
/* @__PURE__ */ jsx11(
|
|
5708
5056
|
"button",
|
|
5709
5057
|
{
|
|
5710
5058
|
type: "button",
|
|
@@ -5717,7 +5065,7 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
5717
5065
|
onToggle();
|
|
5718
5066
|
},
|
|
5719
5067
|
className: `inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full border ${BASIS_TONES2[basis]}`,
|
|
5720
|
-
children: /* @__PURE__ */
|
|
5068
|
+
children: /* @__PURE__ */ jsx11(
|
|
5721
5069
|
"svg",
|
|
5722
5070
|
{
|
|
5723
5071
|
viewBox: "0 0 24 24",
|
|
@@ -5727,12 +5075,12 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
5727
5075
|
strokeWidth: "2.5",
|
|
5728
5076
|
strokeLinecap: "round",
|
|
5729
5077
|
"aria-hidden": true,
|
|
5730
|
-
children: /* @__PURE__ */
|
|
5078
|
+
children: /* @__PURE__ */ jsx11("path", { d: "M9 8h6M9 12h6M9 16h3" })
|
|
5731
5079
|
}
|
|
5732
5080
|
)
|
|
5733
5081
|
}
|
|
5734
5082
|
),
|
|
5735
|
-
/* @__PURE__ */
|
|
5083
|
+
/* @__PURE__ */ jsxs9(
|
|
5736
5084
|
PopoverSurface,
|
|
5737
5085
|
{
|
|
5738
5086
|
open,
|
|
@@ -5742,17 +5090,17 @@ function SourceMarker({ panelId, columnHeader, rowLabel, source, open, onToggle
|
|
|
5742
5090
|
panelRef,
|
|
5743
5091
|
className: `w-64 rounded-lg border border-card-edge bg-popover p-3 text-left ${OVERLAY_SHADOW}`,
|
|
5744
5092
|
children: [
|
|
5745
|
-
source.quote && /* @__PURE__ */
|
|
5093
|
+
source.quote && /* @__PURE__ */ jsxs9("span", { className: "block border-l-2 border-primary/50 pl-2 text-xs italic leading-snug text-foreground", children: [
|
|
5746
5094
|
"\u201C",
|
|
5747
5095
|
source.quote,
|
|
5748
5096
|
"\u201D"
|
|
5749
5097
|
] }),
|
|
5750
|
-
/* @__PURE__ */
|
|
5098
|
+
/* @__PURE__ */ jsxs9("span", { className: "mt-2 block text-xs text-muted-foreground", children: [
|
|
5751
5099
|
source.label ?? "Source",
|
|
5752
5100
|
source.locator ? ` \xB7 ${source.locator}` : "",
|
|
5753
5101
|
` \xB7 ${BASIS_TITLES[basis]}`
|
|
5754
5102
|
] }),
|
|
5755
|
-
source.href && /* @__PURE__ */
|
|
5103
|
+
source.href && /* @__PURE__ */ jsx11(
|
|
5756
5104
|
"a",
|
|
5757
5105
|
{
|
|
5758
5106
|
href: source.href,
|
|
@@ -5780,8 +5128,8 @@ function AddRecordForm({
|
|
|
5780
5128
|
onSubmit,
|
|
5781
5129
|
onCancel
|
|
5782
5130
|
}) {
|
|
5783
|
-
const groups =
|
|
5784
|
-
return /* @__PURE__ */
|
|
5131
|
+
const groups = useMemo6(() => groupColumns(columns), [columns]);
|
|
5132
|
+
return /* @__PURE__ */ jsxs9(
|
|
5785
5133
|
"form",
|
|
5786
5134
|
{
|
|
5787
5135
|
noValidate: true,
|
|
@@ -5792,31 +5140,31 @@ function AddRecordForm({
|
|
|
5792
5140
|
},
|
|
5793
5141
|
className: "space-y-4 rounded-xl border border-card-edge bg-card p-4",
|
|
5794
5142
|
children: [
|
|
5795
|
-
/* @__PURE__ */
|
|
5796
|
-
formError !== null && /* @__PURE__ */
|
|
5143
|
+
/* @__PURE__ */ jsx11("h3", { className: "text-sm font-semibold text-foreground", children: label }),
|
|
5144
|
+
formError !== null && /* @__PURE__ */ jsx11("p", { role: "alert", className: "rounded-md bg-destructive/10 px-3 py-2 text-xs text-destructive", children: formError }),
|
|
5797
5145
|
groups.map((group) => {
|
|
5798
5146
|
const fields = group.columns.filter((column) => isRecordGridCellApplicable(column, draft));
|
|
5799
5147
|
if (fields.length === 0) return null;
|
|
5800
|
-
return /* @__PURE__ */
|
|
5148
|
+
return /* @__PURE__ */ jsxs9(
|
|
5801
5149
|
"fieldset",
|
|
5802
5150
|
{
|
|
5803
5151
|
className: group.label === null ? "min-w-0" : "min-w-0 rounded-lg border border-card-edge p-3",
|
|
5804
5152
|
children: [
|
|
5805
|
-
group.label !== null && /* @__PURE__ */
|
|
5806
|
-
/* @__PURE__ */
|
|
5153
|
+
group.label !== null && /* @__PURE__ */ jsx11("legend", { className: "px-1 text-xs font-medium text-muted-foreground", children: group.label }),
|
|
5154
|
+
/* @__PURE__ */ jsx11("div", { className: "grid gap-3 sm:grid-cols-2", children: fields.map((column) => {
|
|
5807
5155
|
const fieldId = `${fieldPrefix}-${column.id}`;
|
|
5808
5156
|
const errorId = `${fieldId}-error`;
|
|
5809
5157
|
const message = errors[column.id];
|
|
5810
|
-
return /* @__PURE__ */
|
|
5158
|
+
return /* @__PURE__ */ jsxs9(
|
|
5811
5159
|
"div",
|
|
5812
5160
|
{
|
|
5813
5161
|
className: column.kind === "text" && column.multiline === true ? "sm:col-span-2" : "",
|
|
5814
5162
|
children: [
|
|
5815
|
-
/* @__PURE__ */
|
|
5163
|
+
/* @__PURE__ */ jsxs9("label", { htmlFor: fieldId, className: "mb-1 block text-xs font-medium text-muted-foreground", children: [
|
|
5816
5164
|
column.header,
|
|
5817
|
-
column.required === true && /* @__PURE__ */
|
|
5165
|
+
column.required === true && /* @__PURE__ */ jsx11("span", { className: "ml-0.5 text-destructive", children: "*" })
|
|
5818
5166
|
] }),
|
|
5819
|
-
/* @__PURE__ */
|
|
5167
|
+
/* @__PURE__ */ jsx11(
|
|
5820
5168
|
DraftField,
|
|
5821
5169
|
{
|
|
5822
5170
|
column,
|
|
@@ -5827,8 +5175,8 @@ function AddRecordForm({
|
|
|
5827
5175
|
onValue: (next) => setDraft({ ...draft, [column.id]: next })
|
|
5828
5176
|
}
|
|
5829
5177
|
),
|
|
5830
|
-
column.hint && /* @__PURE__ */
|
|
5831
|
-
message !== void 0 && /* @__PURE__ */
|
|
5178
|
+
column.hint && /* @__PURE__ */ jsx11("p", { className: "mt-1 text-xs text-muted-foreground", children: column.hint }),
|
|
5179
|
+
message !== void 0 && /* @__PURE__ */ jsx11("p", { id: errorId, role: "alert", className: "mt-1 text-xs text-destructive", children: message })
|
|
5832
5180
|
]
|
|
5833
5181
|
},
|
|
5834
5182
|
column.id
|
|
@@ -5839,8 +5187,8 @@ function AddRecordForm({
|
|
|
5839
5187
|
group.label ?? "_"
|
|
5840
5188
|
);
|
|
5841
5189
|
}),
|
|
5842
|
-
/* @__PURE__ */
|
|
5843
|
-
/* @__PURE__ */
|
|
5190
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
|
|
5191
|
+
/* @__PURE__ */ jsx11(
|
|
5844
5192
|
"button",
|
|
5845
5193
|
{
|
|
5846
5194
|
type: "submit",
|
|
@@ -5849,7 +5197,7 @@ function AddRecordForm({
|
|
|
5849
5197
|
children: busy ? "Saving\u2026" : "Save"
|
|
5850
5198
|
}
|
|
5851
5199
|
),
|
|
5852
|
-
/* @__PURE__ */
|
|
5200
|
+
/* @__PURE__ */ jsx11(
|
|
5853
5201
|
"button",
|
|
5854
5202
|
{
|
|
5855
5203
|
type: "button",
|
|
@@ -5870,7 +5218,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5870
5218
|
"aria-describedby": describedBy
|
|
5871
5219
|
};
|
|
5872
5220
|
if (column.kind === "boolean") {
|
|
5873
|
-
return /* @__PURE__ */
|
|
5221
|
+
return /* @__PURE__ */ jsx11(
|
|
5874
5222
|
"input",
|
|
5875
5223
|
{
|
|
5876
5224
|
...shared,
|
|
@@ -5882,7 +5230,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5882
5230
|
);
|
|
5883
5231
|
}
|
|
5884
5232
|
if (column.kind === "select") {
|
|
5885
|
-
return /* @__PURE__ */
|
|
5233
|
+
return /* @__PURE__ */ jsxs9(
|
|
5886
5234
|
"select",
|
|
5887
5235
|
{
|
|
5888
5236
|
...shared,
|
|
@@ -5890,14 +5238,14 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5890
5238
|
value: typeof value === "string" ? value : "",
|
|
5891
5239
|
onChange: (event) => onValue(event.target.value === "" ? null : event.target.value),
|
|
5892
5240
|
children: [
|
|
5893
|
-
/* @__PURE__ */
|
|
5894
|
-
column.options.map((option) => /* @__PURE__ */
|
|
5241
|
+
/* @__PURE__ */ jsx11("option", { value: "", children: "\u2014" }),
|
|
5242
|
+
column.options.map((option) => /* @__PURE__ */ jsx11("option", { value: option.value, children: option.label }, option.value))
|
|
5895
5243
|
]
|
|
5896
5244
|
}
|
|
5897
5245
|
);
|
|
5898
5246
|
}
|
|
5899
5247
|
if (column.kind === "text" && column.multiline === true) {
|
|
5900
|
-
return /* @__PURE__ */
|
|
5248
|
+
return /* @__PURE__ */ jsx11(
|
|
5901
5249
|
"textarea",
|
|
5902
5250
|
{
|
|
5903
5251
|
...shared,
|
|
@@ -5909,7 +5257,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5909
5257
|
);
|
|
5910
5258
|
}
|
|
5911
5259
|
if (column.kind === "number" || column.kind === "currency") {
|
|
5912
|
-
return /* @__PURE__ */
|
|
5260
|
+
return /* @__PURE__ */ jsx11(
|
|
5913
5261
|
"input",
|
|
5914
5262
|
{
|
|
5915
5263
|
...shared,
|
|
@@ -5929,7 +5277,7 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5929
5277
|
}
|
|
5930
5278
|
);
|
|
5931
5279
|
}
|
|
5932
|
-
return /* @__PURE__ */
|
|
5280
|
+
return /* @__PURE__ */ jsx11(
|
|
5933
5281
|
"input",
|
|
5934
5282
|
{
|
|
5935
5283
|
...shared,
|
|
@@ -5943,19 +5291,19 @@ function DraftField({ column, id, value, invalid, describedBy, onValue }) {
|
|
|
5943
5291
|
|
|
5944
5292
|
// src/web-react/command-palette.tsx
|
|
5945
5293
|
import {
|
|
5946
|
-
useCallback as
|
|
5947
|
-
useEffect as
|
|
5948
|
-
useId as
|
|
5949
|
-
useMemo as
|
|
5950
|
-
useRef as
|
|
5951
|
-
useState as
|
|
5294
|
+
useCallback as useCallback10,
|
|
5295
|
+
useEffect as useEffect11,
|
|
5296
|
+
useId as useId4,
|
|
5297
|
+
useMemo as useMemo7,
|
|
5298
|
+
useRef as useRef11,
|
|
5299
|
+
useState as useState15
|
|
5952
5300
|
} from "react";
|
|
5953
5301
|
import { createPortal } from "react-dom";
|
|
5954
|
-
import { Fragment as
|
|
5302
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
5955
5303
|
function SearchGlyph({ className }) {
|
|
5956
|
-
return /* @__PURE__ */
|
|
5957
|
-
/* @__PURE__ */
|
|
5958
|
-
/* @__PURE__ */
|
|
5304
|
+
return /* @__PURE__ */ jsxs10("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
5305
|
+
/* @__PURE__ */ jsx12("circle", { cx: "11", cy: "11", r: "8" }),
|
|
5306
|
+
/* @__PURE__ */ jsx12("path", { d: "m21 21-4.3-4.3" })
|
|
5959
5307
|
] });
|
|
5960
5308
|
}
|
|
5961
5309
|
function CommandPalette({
|
|
@@ -5970,25 +5318,25 @@ function CommandPalette({
|
|
|
5970
5318
|
emptyMessage,
|
|
5971
5319
|
label = "Command palette"
|
|
5972
5320
|
}) {
|
|
5973
|
-
const [internalOpen, setInternalOpen] =
|
|
5321
|
+
const [internalOpen, setInternalOpen] = useState15(false);
|
|
5974
5322
|
const open = controlledOpen ?? internalOpen;
|
|
5975
|
-
const setOpen =
|
|
5323
|
+
const setOpen = useCallback10(
|
|
5976
5324
|
(next) => {
|
|
5977
5325
|
if (controlledOpen === void 0) setInternalOpen(next);
|
|
5978
5326
|
onOpenChange?.(next);
|
|
5979
5327
|
},
|
|
5980
5328
|
[controlledOpen, onOpenChange]
|
|
5981
5329
|
);
|
|
5982
|
-
const [query, setQuery] =
|
|
5983
|
-
const [active, setActive] =
|
|
5984
|
-
const inputRef =
|
|
5985
|
-
const surfaceId =
|
|
5330
|
+
const [query, setQuery] = useState15(initialQuery ?? "");
|
|
5331
|
+
const [active, setActive] = useState15(0);
|
|
5332
|
+
const inputRef = useRef11(null);
|
|
5333
|
+
const surfaceId = useId4();
|
|
5986
5334
|
const listId = `${surfaceId}-list`;
|
|
5987
|
-
const flat =
|
|
5988
|
-
const sections =
|
|
5335
|
+
const flat = useMemo7(() => filterCommandPaletteItems(items, query), [items, query]);
|
|
5336
|
+
const sections = useMemo7(() => groupCommandPaletteItems(flat), [flat]);
|
|
5989
5337
|
const activeIndex = flat.length === 0 ? 0 : Math.min(active, flat.length - 1);
|
|
5990
5338
|
const activeId = flat.length > 0 ? `${listId}-${activeIndex}` : void 0;
|
|
5991
|
-
|
|
5339
|
+
useEffect11(() => {
|
|
5992
5340
|
if (!hotkey) return;
|
|
5993
5341
|
function onKeyDown(e) {
|
|
5994
5342
|
if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
|
|
@@ -5999,8 +5347,8 @@ function CommandPalette({
|
|
|
5999
5347
|
document.addEventListener("keydown", onKeyDown);
|
|
6000
5348
|
return () => document.removeEventListener("keydown", onKeyDown);
|
|
6001
5349
|
}, [hotkey, open, setOpen]);
|
|
6002
|
-
const restoreFocusRef =
|
|
6003
|
-
|
|
5350
|
+
const restoreFocusRef = useRef11(null);
|
|
5351
|
+
useEffect11(() => {
|
|
6004
5352
|
if (open) {
|
|
6005
5353
|
restoreFocusRef.current = document.activeElement;
|
|
6006
5354
|
inputRef.current?.focus();
|
|
@@ -6012,11 +5360,11 @@ function CommandPalette({
|
|
|
6012
5360
|
restoreFocusRef.current = null;
|
|
6013
5361
|
if (restore instanceof HTMLElement) restore.focus();
|
|
6014
5362
|
}, [open]);
|
|
6015
|
-
|
|
5363
|
+
useEffect11(() => {
|
|
6016
5364
|
if (!open || !activeId) return;
|
|
6017
5365
|
document.getElementById(activeId)?.scrollIntoView?.({ block: "nearest" });
|
|
6018
5366
|
}, [open, activeId]);
|
|
6019
|
-
const choose =
|
|
5367
|
+
const choose = useCallback10(
|
|
6020
5368
|
(item) => {
|
|
6021
5369
|
onSelect(item);
|
|
6022
5370
|
setOpen(false);
|
|
@@ -6042,8 +5390,8 @@ function CommandPalette({
|
|
|
6042
5390
|
if (!open || typeof document === "undefined") return null;
|
|
6043
5391
|
let rowIndex = -1;
|
|
6044
5392
|
return createPortal(
|
|
6045
|
-
/* @__PURE__ */
|
|
6046
|
-
/* @__PURE__ */
|
|
5393
|
+
/* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
5394
|
+
/* @__PURE__ */ jsx12(
|
|
6047
5395
|
"div",
|
|
6048
5396
|
{
|
|
6049
5397
|
"aria-hidden": true,
|
|
@@ -6052,7 +5400,7 @@ function CommandPalette({
|
|
|
6052
5400
|
className: "fixed inset-0 z-[999] bg-background/80"
|
|
6053
5401
|
}
|
|
6054
5402
|
),
|
|
6055
|
-
/* @__PURE__ */
|
|
5403
|
+
/* @__PURE__ */ jsx12("div", { className: "pointer-events-none fixed inset-x-0 top-[15%] z-[1000] flex justify-center px-4", children: /* @__PURE__ */ jsxs10(
|
|
6056
5404
|
"div",
|
|
6057
5405
|
{
|
|
6058
5406
|
role: "dialog",
|
|
@@ -6061,9 +5409,9 @@ function CommandPalette({
|
|
|
6061
5409
|
...{ [POPOVER_SURFACE_ATTR]: surfaceId },
|
|
6062
5410
|
className: `agent-pop-in pointer-events-auto flex max-h-[70vh] w-[560px] max-w-full flex-col overflow-hidden rounded-xl border border-card-edge bg-popover ${OVERLAY_SHADOW}`,
|
|
6063
5411
|
children: [
|
|
6064
|
-
/* @__PURE__ */
|
|
6065
|
-
/* @__PURE__ */
|
|
6066
|
-
/* @__PURE__ */
|
|
5412
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex shrink-0 items-center gap-2 border-b border-border px-3 py-2.5", children: [
|
|
5413
|
+
/* @__PURE__ */ jsx12(SearchGlyph, { className: "h-4 w-4 shrink-0 text-muted-foreground" }),
|
|
5414
|
+
/* @__PURE__ */ jsx12(
|
|
6067
5415
|
"input",
|
|
6068
5416
|
{
|
|
6069
5417
|
ref: inputRef,
|
|
@@ -6084,15 +5432,15 @@ function CommandPalette({
|
|
|
6084
5432
|
}
|
|
6085
5433
|
)
|
|
6086
5434
|
] }),
|
|
6087
|
-
/* @__PURE__ */
|
|
6088
|
-
loading && /* @__PURE__ */
|
|
6089
|
-
!loading && flat.length === 0 && /* @__PURE__ */
|
|
6090
|
-
!loading && sections.map((section) => /* @__PURE__ */
|
|
6091
|
-
/* @__PURE__ */
|
|
5435
|
+
/* @__PURE__ */ jsxs10("div", { role: "listbox", id: listId, className: "min-h-0 flex-1 overflow-y-auto p-1 pb-2", children: [
|
|
5436
|
+
loading && /* @__PURE__ */ jsx12("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: "Loading\u2026" }),
|
|
5437
|
+
!loading && flat.length === 0 && /* @__PURE__ */ jsx12("div", { className: "px-3 py-4 text-center text-sm text-muted-foreground", children: emptyMessage ?? (query.trim() ? `No results for \u201C${query.trim()}\u201D` : "Nothing here yet") }),
|
|
5438
|
+
!loading && sections.map((section) => /* @__PURE__ */ jsxs10("div", { children: [
|
|
5439
|
+
/* @__PURE__ */ jsx12("div", { className: "px-3 pb-1 pt-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: section.group }),
|
|
6092
5440
|
section.items.map((item) => {
|
|
6093
5441
|
rowIndex += 1;
|
|
6094
5442
|
const index = rowIndex;
|
|
6095
|
-
return /* @__PURE__ */
|
|
5443
|
+
return /* @__PURE__ */ jsxs10(
|
|
6096
5444
|
"div",
|
|
6097
5445
|
{
|
|
6098
5446
|
id: `${listId}-${index}`,
|
|
@@ -6102,9 +5450,9 @@ function CommandPalette({
|
|
|
6102
5450
|
onClick: () => choose(item),
|
|
6103
5451
|
className: `flex w-full cursor-pointer items-center gap-2.5 rounded-md px-3 py-2.5 text-left text-sm ${index === activeIndex ? "bg-accent" : ""}`,
|
|
6104
5452
|
children: [
|
|
6105
|
-
/* @__PURE__ */
|
|
6106
|
-
item.description && /* @__PURE__ */
|
|
6107
|
-
item.hint && /* @__PURE__ */
|
|
5453
|
+
/* @__PURE__ */ jsx12("span", { className: "truncate text-foreground", children: item.label }),
|
|
5454
|
+
item.description && /* @__PURE__ */ jsx12("span", { className: "truncate text-xs text-muted-foreground", children: item.description }),
|
|
5455
|
+
item.hint && /* @__PURE__ */ jsx12("span", { className: "ml-auto shrink-0 text-xs tabular-nums text-muted-foreground", children: item.hint })
|
|
6108
5456
|
]
|
|
6109
5457
|
},
|
|
6110
5458
|
item.id
|
|
@@ -6112,15 +5460,15 @@ function CommandPalette({
|
|
|
6112
5460
|
})
|
|
6113
5461
|
] }, section.group))
|
|
6114
5462
|
] }),
|
|
6115
|
-
/* @__PURE__ */
|
|
6116
|
-
/* @__PURE__ */
|
|
6117
|
-
/* @__PURE__ */
|
|
6118
|
-
/* @__PURE__ */
|
|
6119
|
-
/* @__PURE__ */
|
|
6120
|
-
/* @__PURE__ */
|
|
6121
|
-
/* @__PURE__ */
|
|
6122
|
-
/* @__PURE__ */
|
|
6123
|
-
/* @__PURE__ */
|
|
5463
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex shrink-0 items-center justify-between border-t border-border px-3 py-2 text-xs text-muted-foreground", children: [
|
|
5464
|
+
/* @__PURE__ */ jsx12("span", { className: "tabular-nums", children: query.trim() ? `${flat.length} of ${items.length}` : `${items.length} items` }),
|
|
5465
|
+
/* @__PURE__ */ jsxs10("span", { className: "flex items-center gap-1.5", children: [
|
|
5466
|
+
/* @__PURE__ */ jsx12("kbd", { className: "rounded border border-border bg-background px-1 py-0.5", children: "\u2191\u2193" }),
|
|
5467
|
+
/* @__PURE__ */ jsx12("span", { children: "navigate" }),
|
|
5468
|
+
/* @__PURE__ */ jsx12("kbd", { className: "ml-1.5 rounded border border-border bg-background px-1 py-0.5", children: "\u21B5" }),
|
|
5469
|
+
/* @__PURE__ */ jsx12("span", { children: "select" }),
|
|
5470
|
+
/* @__PURE__ */ jsx12("kbd", { className: "ml-1.5 rounded border border-border bg-background px-1 py-0.5", children: "esc" }),
|
|
5471
|
+
/* @__PURE__ */ jsx12("span", { children: "close" })
|
|
6124
5472
|
] })
|
|
6125
5473
|
] })
|
|
6126
5474
|
]
|
|
@@ -6131,19 +5479,8 @@ function CommandPalette({
|
|
|
6131
5479
|
);
|
|
6132
5480
|
}
|
|
6133
5481
|
|
|
6134
|
-
// src/web-react/class-names.ts
|
|
6135
|
-
function joinClasses(...parts) {
|
|
6136
|
-
const kept = [];
|
|
6137
|
-
for (const part of parts) {
|
|
6138
|
-
if (typeof part !== "string") continue;
|
|
6139
|
-
const trimmed = part.trim();
|
|
6140
|
-
if (trimmed.length > 0) kept.push(trimmed);
|
|
6141
|
-
}
|
|
6142
|
-
return kept.join(" ");
|
|
6143
|
-
}
|
|
6144
|
-
|
|
6145
5482
|
// src/web-react/sparkline.tsx
|
|
6146
|
-
import { jsx as
|
|
5483
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
6147
5484
|
var DEFAULT_SPARKLINE_WIDTH = 96;
|
|
6148
5485
|
var DEFAULT_SPARKLINE_HEIGHT = 24;
|
|
6149
5486
|
var DEFAULT_INSET = 2.5;
|
|
@@ -6249,21 +5586,21 @@ function Sparkline({
|
|
|
6249
5586
|
const geometry = sparklineGeometry(values, { width, height });
|
|
6250
5587
|
const accessibleName = sparklineLabel(values, { label, format });
|
|
6251
5588
|
if (geometry.points.length === 0) {
|
|
6252
|
-
return /* @__PURE__ */
|
|
5589
|
+
return /* @__PURE__ */ jsxs11(
|
|
6253
5590
|
"span",
|
|
6254
5591
|
{
|
|
6255
5592
|
"data-sparkline": geometry.gaps > 0 ? "unavailable" : "empty",
|
|
6256
5593
|
className: joinClasses("text-[11px] text-muted-foreground", className),
|
|
6257
5594
|
children: [
|
|
6258
|
-
/* @__PURE__ */
|
|
6259
|
-
/* @__PURE__ */
|
|
5595
|
+
/* @__PURE__ */ jsx13("span", { className: "sr-only", children: accessibleName }),
|
|
5596
|
+
/* @__PURE__ */ jsx13("span", { "aria-hidden": "true", children: geometry.gaps > 0 ? unavailableLabel : emptyLabel })
|
|
6260
5597
|
]
|
|
6261
5598
|
}
|
|
6262
5599
|
);
|
|
6263
5600
|
}
|
|
6264
5601
|
const drawsLine = geometry.segments.some((segment) => segment.length > 1);
|
|
6265
5602
|
const end = geometry.points[geometry.points.length - 1];
|
|
6266
|
-
return /* @__PURE__ */
|
|
5603
|
+
return /* @__PURE__ */ jsxs11(
|
|
6267
5604
|
"svg",
|
|
6268
5605
|
{
|
|
6269
5606
|
role: "img",
|
|
@@ -6280,7 +5617,7 @@ function Sparkline({
|
|
|
6280
5617
|
geometry.segments.map((segment, index) => {
|
|
6281
5618
|
const key = `segment-${index}`;
|
|
6282
5619
|
if (segment.length > 1) {
|
|
6283
|
-
return /* @__PURE__ */
|
|
5620
|
+
return /* @__PURE__ */ jsx13(
|
|
6284
5621
|
"polyline",
|
|
6285
5622
|
{
|
|
6286
5623
|
points: sparklinePointsAttribute(segment),
|
|
@@ -6296,9 +5633,9 @@ function Sparkline({
|
|
|
6296
5633
|
}
|
|
6297
5634
|
const only = segment[0];
|
|
6298
5635
|
if (only.x === end.x && only.y === end.y) return null;
|
|
6299
|
-
return /* @__PURE__ */
|
|
5636
|
+
return /* @__PURE__ */ jsx13("circle", { cx: only.x, cy: only.y, r: DOT_RADIUS, fill: "currentColor" }, key);
|
|
6300
5637
|
}),
|
|
6301
|
-
/* @__PURE__ */
|
|
5638
|
+
/* @__PURE__ */ jsx13("circle", { cx: end.x, cy: end.y, r: DOT_RADIUS, fill: "currentColor" })
|
|
6302
5639
|
]
|
|
6303
5640
|
}
|
|
6304
5641
|
);
|
|
@@ -6307,12 +5644,12 @@ function Sparkline({
|
|
|
6307
5644
|
// src/web-react/insight-card.tsx
|
|
6308
5645
|
import {
|
|
6309
5646
|
isValidElement as isValidElement2,
|
|
6310
|
-
useCallback as
|
|
6311
|
-
useEffect as
|
|
6312
|
-
useRef as
|
|
6313
|
-
useState as
|
|
5647
|
+
useCallback as useCallback11,
|
|
5648
|
+
useEffect as useEffect12,
|
|
5649
|
+
useRef as useRef12,
|
|
5650
|
+
useState as useState16
|
|
6314
5651
|
} from "react";
|
|
6315
|
-
import { Fragment as
|
|
5652
|
+
import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
6316
5653
|
function insightDelta(value, previous) {
|
|
6317
5654
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
6318
5655
|
if (typeof previous !== "number" || !Number.isFinite(previous)) return null;
|
|
@@ -6365,7 +5702,7 @@ function InsightCard({
|
|
|
6365
5702
|
const tone = delta ? insightDeltaTone(delta.direction, polarity) : "neutral";
|
|
6366
5703
|
const unavailable = typeof value === "number" && !Number.isFinite(value);
|
|
6367
5704
|
const shown = typeof value === "number" ? format(value) : value;
|
|
6368
|
-
return /* @__PURE__ */
|
|
5705
|
+
return /* @__PURE__ */ jsxs12(
|
|
6369
5706
|
"article",
|
|
6370
5707
|
{
|
|
6371
5708
|
"data-insight-card": "",
|
|
@@ -6373,40 +5710,40 @@ function InsightCard({
|
|
|
6373
5710
|
className: joinClasses("agent-arrive flex h-full flex-col rounded-xl border border-card-edge bg-card p-4", className),
|
|
6374
5711
|
style,
|
|
6375
5712
|
children: [
|
|
6376
|
-
eyebrow ? /* @__PURE__ */
|
|
6377
|
-
/* @__PURE__ */
|
|
6378
|
-
/* @__PURE__ */
|
|
5713
|
+
eyebrow ? /* @__PURE__ */ jsx14("p", { "data-insight-eyebrow": "", className: "mb-0.5 text-[11px] font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: eyebrow }) : null,
|
|
5714
|
+
/* @__PURE__ */ jsxs12("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
5715
|
+
/* @__PURE__ */ jsx14("h3", { className: "text-[13px] font-medium text-muted-foreground", children: title }),
|
|
6379
5716
|
live ? (
|
|
6380
5717
|
// No `data-motion` opt-out: the word is the signal and the sweep is
|
|
6381
5718
|
// emphasis, so the reduced-motion floor reaches this like everything
|
|
6382
5719
|
// else and leaves a static, legible label.
|
|
6383
|
-
/* @__PURE__ */
|
|
5720
|
+
/* @__PURE__ */ jsx14("span", { className: "agent-shimmer shrink-0 text-[11px] font-medium", "data-insight-live": "", children: liveLabel })
|
|
6384
5721
|
) : null
|
|
6385
5722
|
] }),
|
|
6386
|
-
/* @__PURE__ */
|
|
6387
|
-
/* @__PURE__ */
|
|
6388
|
-
/* @__PURE__ */
|
|
6389
|
-
] }) : /* @__PURE__ */
|
|
6390
|
-
/* @__PURE__ */
|
|
6391
|
-
unit ? /* @__PURE__ */
|
|
5723
|
+
/* @__PURE__ */ jsx14("p", { className: "mt-1 flex items-baseline gap-1", children: unavailable ? /* @__PURE__ */ jsxs12("span", { "data-insight-value": "unavailable", className: "text-xl font-semibold text-muted-foreground", children: [
|
|
5724
|
+
/* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: INSIGHT_UNAVAILABLE_GLYPH }),
|
|
5725
|
+
/* @__PURE__ */ jsx14("span", { className: "sr-only", children: INSIGHT_UNAVAILABLE_LABEL })
|
|
5726
|
+
] }) : /* @__PURE__ */ jsxs12(Fragment7, { children: [
|
|
5727
|
+
/* @__PURE__ */ jsx14("span", { className: "text-xl font-semibold tabular-nums text-foreground", children: shown }),
|
|
5728
|
+
unit ? /* @__PURE__ */ jsx14("span", { className: "text-[11px] text-muted-foreground", children: unit }) : null
|
|
6392
5729
|
] }) }),
|
|
6393
|
-
delta ? /* @__PURE__ */
|
|
6394
|
-
/* @__PURE__ */
|
|
5730
|
+
delta ? /* @__PURE__ */ jsxs12("p", { "data-insight-delta": delta.direction, className: `mt-0.5 text-[11px] font-medium ${TONE_CLASS[tone]}`, children: [
|
|
5731
|
+
/* @__PURE__ */ jsxs12("span", { "aria-hidden": "true", children: [
|
|
6395
5732
|
DIRECTION_GLYPH[delta.direction],
|
|
6396
5733
|
" "
|
|
6397
5734
|
] }),
|
|
6398
5735
|
formatInsightDelta(delta, format)
|
|
6399
5736
|
] }) : null,
|
|
6400
|
-
description ? /* @__PURE__ */
|
|
6401
|
-
series ? /* @__PURE__ */
|
|
6402
|
-
action ? /* @__PURE__ */
|
|
5737
|
+
description ? /* @__PURE__ */ jsx14("p", { className: "mt-1 text-[11px] text-muted-foreground", children: description }) : null,
|
|
5738
|
+
series ? /* @__PURE__ */ jsx14("div", { className: "mt-2 text-muted-foreground", children: /* @__PURE__ */ jsx14(Sparkline, { values: series, label: seriesLabel ?? title, format }) }) : null,
|
|
5739
|
+
action ? /* @__PURE__ */ jsx14("div", { className: "mt-3", children: renderInsightAction(action) }) : null
|
|
6403
5740
|
]
|
|
6404
5741
|
}
|
|
6405
5742
|
);
|
|
6406
5743
|
}
|
|
6407
5744
|
function renderInsightAction(action) {
|
|
6408
5745
|
if (isValidElement2(action)) return action;
|
|
6409
|
-
return /* @__PURE__ */
|
|
5746
|
+
return /* @__PURE__ */ jsx14(
|
|
6410
5747
|
"button",
|
|
6411
5748
|
{
|
|
6412
5749
|
type: "button",
|
|
@@ -6475,15 +5812,15 @@ function InsightDeck({
|
|
|
6475
5812
|
className,
|
|
6476
5813
|
onPageChange
|
|
6477
5814
|
}) {
|
|
6478
|
-
const [page, setPage] =
|
|
6479
|
-
const [held, setHeld] =
|
|
5815
|
+
const [page, setPage] = useState16(0);
|
|
5816
|
+
const [held, setHeld] = useState16(null);
|
|
6480
5817
|
const answered = state.status === "error" || state.status === "empty";
|
|
6481
5818
|
const carried = state.status === "ready" ? state.value : answered ? null : held;
|
|
6482
5819
|
if (carried !== held) setHeld(carried);
|
|
6483
5820
|
const shown = carried !== null && state.status !== "ready" ? { status: "ready", value: carried, retry: state.retry } : state;
|
|
6484
5821
|
const refreshing = shown !== state;
|
|
6485
|
-
const reported =
|
|
6486
|
-
const settlePage =
|
|
5822
|
+
const reported = useRef12(0);
|
|
5823
|
+
const settlePage = useCallback11(
|
|
6487
5824
|
(next) => {
|
|
6488
5825
|
if (reported.current === next) return;
|
|
6489
5826
|
reported.current = next;
|
|
@@ -6491,7 +5828,7 @@ function InsightDeck({
|
|
|
6491
5828
|
},
|
|
6492
5829
|
[onPageChange]
|
|
6493
5830
|
);
|
|
6494
|
-
return /* @__PURE__ */
|
|
5831
|
+
return /* @__PURE__ */ jsx14(
|
|
6495
5832
|
AsyncView,
|
|
6496
5833
|
{
|
|
6497
5834
|
state: shown,
|
|
@@ -6499,7 +5836,7 @@ function InsightDeck({
|
|
|
6499
5836
|
loadingLabel,
|
|
6500
5837
|
retryLabel,
|
|
6501
5838
|
className,
|
|
6502
|
-
children: (insights) => /* @__PURE__ */
|
|
5839
|
+
children: (insights) => /* @__PURE__ */ jsx14(
|
|
6503
5840
|
InsightPages,
|
|
6504
5841
|
{
|
|
6505
5842
|
insights,
|
|
@@ -6566,18 +5903,18 @@ function InsightPages({
|
|
|
6566
5903
|
const pageCount = insightPageCount(insights.length, size);
|
|
6567
5904
|
const current = Math.min(Math.max(page, 0), pageCount - 1);
|
|
6568
5905
|
const visible = insightPageSlice(insights, current, size);
|
|
6569
|
-
const sectionRef =
|
|
6570
|
-
const listRef =
|
|
6571
|
-
const recoverFocus =
|
|
6572
|
-
|
|
5906
|
+
const sectionRef = useRef12(null);
|
|
5907
|
+
const listRef = useRef12(null);
|
|
5908
|
+
const recoverFocus = useRef12(false);
|
|
5909
|
+
useEffect12(() => {
|
|
6573
5910
|
onPageSettled(current);
|
|
6574
5911
|
}, [current, onPageSettled]);
|
|
6575
|
-
|
|
5912
|
+
useEffect12(() => {
|
|
6576
5913
|
if (!recoverFocus.current) return;
|
|
6577
5914
|
recoverFocus.current = false;
|
|
6578
5915
|
sectionRef.current?.focus();
|
|
6579
5916
|
}, [current]);
|
|
6580
|
-
const goTo =
|
|
5917
|
+
const goTo = useCallback11(
|
|
6581
5918
|
(next) => {
|
|
6582
5919
|
const clamped = Math.min(Math.max(next, 0), pageCount - 1);
|
|
6583
5920
|
if (clamped === current) return false;
|
|
@@ -6612,7 +5949,7 @@ function InsightPages({
|
|
|
6612
5949
|
}
|
|
6613
5950
|
if (moved) event.preventDefault();
|
|
6614
5951
|
};
|
|
6615
|
-
return /* @__PURE__ */
|
|
5952
|
+
return /* @__PURE__ */ jsxs12(
|
|
6616
5953
|
"section",
|
|
6617
5954
|
{
|
|
6618
5955
|
ref: sectionRef,
|
|
@@ -6624,7 +5961,7 @@ function InsightPages({
|
|
|
6624
5961
|
tabIndex: pageCount > 1 ? 0 : void 0,
|
|
6625
5962
|
"aria-keyshortcuts": pageCount > 1 ? "ArrowLeft ArrowRight PageUp PageDown Home End" : void 0,
|
|
6626
5963
|
children: [
|
|
6627
|
-
/* @__PURE__ */
|
|
5964
|
+
/* @__PURE__ */ jsx14("ul", { ref: listRef, className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-3", children: visible.map(({ id, style, ...card }, index) => (
|
|
6628
5965
|
// The page index is in the key on purpose: a page turn is an arrival,
|
|
6629
5966
|
// and reusing the node would swap the text under a card that never
|
|
6630
5967
|
// moved. Remounting replays `.agent-arrive` with the new stagger.
|
|
@@ -6635,10 +5972,10 @@ function InsightPages({
|
|
|
6635
5972
|
// does not arrive a second time. The key does BOTH jobs — but only
|
|
6636
5973
|
// because the deck now keeps this subtree mounted across a reload
|
|
6637
5974
|
// (see `InsightDeck`); a key is never compared across a teardown.
|
|
6638
|
-
/* @__PURE__ */
|
|
5975
|
+
/* @__PURE__ */ jsx14("li", { children: /* @__PURE__ */ jsx14(InsightCard, { ...card, style: staggerStyle(index, style) }) }, `${current}:${id}`)
|
|
6639
5976
|
)) }),
|
|
6640
|
-
/* @__PURE__ */
|
|
6641
|
-
/* @__PURE__ */
|
|
5977
|
+
/* @__PURE__ */ jsxs12("div", { className: pageCount > 1 ? "flex items-center justify-between gap-2" : void 0, children: [
|
|
5978
|
+
/* @__PURE__ */ jsxs12(
|
|
6642
5979
|
"p",
|
|
6643
5980
|
{
|
|
6644
5981
|
role: "status",
|
|
@@ -6652,8 +5989,8 @@ function InsightPages({
|
|
|
6652
5989
|
]
|
|
6653
5990
|
}
|
|
6654
5991
|
),
|
|
6655
|
-
pageCount > 1 ? /* @__PURE__ */
|
|
6656
|
-
/* @__PURE__ */
|
|
5992
|
+
pageCount > 1 ? /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-1", children: [
|
|
5993
|
+
/* @__PURE__ */ jsx14(PagerButton, { label: "Previous insights", glyph: "\u2039", atEnd: current === 0, onClick: () => goTo(current - 1) }),
|
|
6657
5994
|
pageCount <= MAX_PAGE_DOTS ? Array.from({ length: pageCount }, (_, index) => (
|
|
6658
5995
|
// WCAG 2.2 SC 2.5.8 wants a 24x24 CSS px target. The dot stays
|
|
6659
5996
|
// 8px because a 24px dot is a different control; the BUTTON
|
|
@@ -6661,7 +5998,7 @@ function InsightPages({
|
|
|
6661
5998
|
// and the span is the graphic. The Spacing exception cannot
|
|
6662
5999
|
// rescue the bare dot — at a 12px pitch the 24px circle around
|
|
6663
6000
|
// each centre overlaps its neighbour's.
|
|
6664
|
-
/* @__PURE__ */
|
|
6001
|
+
/* @__PURE__ */ jsx14(
|
|
6665
6002
|
"button",
|
|
6666
6003
|
{
|
|
6667
6004
|
type: "button",
|
|
@@ -6669,7 +6006,7 @@ function InsightPages({
|
|
|
6669
6006
|
"aria-current": index === current ? "page" : void 0,
|
|
6670
6007
|
onClick: () => goTo(index),
|
|
6671
6008
|
className: "group flex h-6 w-6 shrink-0 items-center justify-center rounded-full",
|
|
6672
|
-
children: /* @__PURE__ */
|
|
6009
|
+
children: /* @__PURE__ */ jsx14(
|
|
6673
6010
|
"span",
|
|
6674
6011
|
{
|
|
6675
6012
|
"aria-hidden": "true",
|
|
@@ -6683,7 +6020,7 @@ function InsightPages({
|
|
|
6683
6020
|
index
|
|
6684
6021
|
)
|
|
6685
6022
|
)) : null,
|
|
6686
|
-
/* @__PURE__ */
|
|
6023
|
+
/* @__PURE__ */ jsx14(
|
|
6687
6024
|
PagerButton,
|
|
6688
6025
|
{
|
|
6689
6026
|
label: "Next insights",
|
|
@@ -6704,7 +6041,7 @@ function PagerButton({
|
|
|
6704
6041
|
atEnd,
|
|
6705
6042
|
onClick
|
|
6706
6043
|
}) {
|
|
6707
|
-
return /* @__PURE__ */
|
|
6044
|
+
return /* @__PURE__ */ jsx14(
|
|
6708
6045
|
"button",
|
|
6709
6046
|
{
|
|
6710
6047
|
type: "button",
|
|
@@ -6714,13 +6051,13 @@ function PagerButton({
|
|
|
6714
6051
|
if (!atEnd) onClick();
|
|
6715
6052
|
},
|
|
6716
6053
|
className: `flex h-6 w-6 items-center justify-center rounded-md border border-border text-xs text-muted-foreground transition ${atEnd ? "opacity-40" : "hover:bg-accent hover:text-foreground"}`,
|
|
6717
|
-
children: /* @__PURE__ */
|
|
6054
|
+
children: /* @__PURE__ */ jsx14("span", { "aria-hidden": "true", children: glyph })
|
|
6718
6055
|
}
|
|
6719
6056
|
);
|
|
6720
6057
|
}
|
|
6721
6058
|
|
|
6722
6059
|
// src/web-react/index.tsx
|
|
6723
|
-
import { Fragment as
|
|
6060
|
+
import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
6724
6061
|
function formatModelCost(msg, models) {
|
|
6725
6062
|
if (msg.promptTokens == null && msg.completionTokens == null) return null;
|
|
6726
6063
|
const pricing = models.find((m) => m.id === msg.modelUsed)?.pricing;
|
|
@@ -6739,41 +6076,41 @@ function formatTokensPerSecond(msg) {
|
|
|
6739
6076
|
return `${Math.round(msg.completionTokens / (msg.durationMs / 1e3))} tok/s`;
|
|
6740
6077
|
}
|
|
6741
6078
|
function RunDrillIn({ run, onClose }) {
|
|
6742
|
-
return /* @__PURE__ */
|
|
6743
|
-
/* @__PURE__ */
|
|
6744
|
-
/* @__PURE__ */
|
|
6079
|
+
return /* @__PURE__ */ jsxs13("div", { className: `fixed inset-y-0 right-0 z-50 flex w-[480px] max-w-full flex-col border-l border-card-edge bg-popover ${OVERLAY_SHADOW}`, children: [
|
|
6080
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 border-b border-border px-4 py-3", children: [
|
|
6081
|
+
/* @__PURE__ */ jsx15(
|
|
6745
6082
|
"span",
|
|
6746
6083
|
{
|
|
6747
6084
|
className: `h-2 w-2 shrink-0 rounded-full ${run.status === "running" ? "bg-warning" : run.status === "error" ? "bg-destructive" : "bg-success"}`
|
|
6748
6085
|
}
|
|
6749
6086
|
),
|
|
6750
|
-
/* @__PURE__ */
|
|
6751
|
-
/* @__PURE__ */
|
|
6752
|
-
/* @__PURE__ */
|
|
6087
|
+
/* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
|
|
6088
|
+
/* @__PURE__ */ jsx15("p", { className: "truncate text-[15px] font-semibold", children: run.title }),
|
|
6089
|
+
/* @__PURE__ */ jsx15("p", { className: "truncate font-mono text-xs text-muted-foreground", children: run.toolName })
|
|
6753
6090
|
] }),
|
|
6754
|
-
/* @__PURE__ */
|
|
6091
|
+
/* @__PURE__ */ jsx15(
|
|
6755
6092
|
"button",
|
|
6756
6093
|
{
|
|
6757
6094
|
type: "button",
|
|
6758
6095
|
onClick: onClose,
|
|
6759
6096
|
"aria-label": "Close",
|
|
6760
6097
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
|
|
6761
|
-
children: /* @__PURE__ */
|
|
6098
|
+
children: /* @__PURE__ */ jsx15("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
6762
6099
|
}
|
|
6763
6100
|
)
|
|
6764
6101
|
] }),
|
|
6765
|
-
/* @__PURE__ */
|
|
6766
|
-
run.steps.length === 0 && /* @__PURE__ */
|
|
6767
|
-
run.steps.map((step, i) => /* @__PURE__ */
|
|
6768
|
-
/* @__PURE__ */
|
|
6769
|
-
/* @__PURE__ */
|
|
6770
|
-
/* @__PURE__ */
|
|
6771
|
-
/* @__PURE__ */
|
|
6102
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex-1 space-y-3 overflow-y-auto p-4", children: [
|
|
6103
|
+
run.steps.length === 0 && /* @__PURE__ */ jsx15("p", { className: "text-sm text-muted-foreground", children: "No steps recorded yet." }),
|
|
6104
|
+
run.steps.map((step, i) => /* @__PURE__ */ jsxs13("div", { className: "rounded-lg border border-card-edge bg-card", children: [
|
|
6105
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-baseline gap-2 border-b border-border px-3 py-1.5", children: [
|
|
6106
|
+
/* @__PURE__ */ jsx15("span", { className: `font-mono text-xs ${step.status === "error" ? "text-destructive" : "text-muted-foreground"}`, children: step.status === "error" ? "\u2717" : "$" }),
|
|
6107
|
+
/* @__PURE__ */ jsx15("code", { className: "min-w-0 flex-1 truncate font-mono text-xs", children: step.label }),
|
|
6108
|
+
/* @__PURE__ */ jsx15("span", { className: "shrink-0 text-xs tabular-nums text-muted-foreground", children: new Date(step.at).toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }) })
|
|
6772
6109
|
] }),
|
|
6773
|
-
step.detail && /* @__PURE__ */
|
|
6110
|
+
step.detail && /* @__PURE__ */ jsx15("pre", { className: "max-h-48 overflow-auto whitespace-pre-wrap px-3 py-2 font-mono text-xs leading-relaxed text-muted-foreground", children: step.detail })
|
|
6774
6111
|
] }, i))
|
|
6775
6112
|
] }),
|
|
6776
|
-
/* @__PURE__ */
|
|
6113
|
+
/* @__PURE__ */ jsx15("p", { className: "border-t border-border px-4 py-2 text-xs text-muted-foreground", children: "Read-only transcript \u2014 reply in the main chat." })
|
|
6777
6114
|
] });
|
|
6778
6115
|
}
|
|
6779
6116
|
function pendingApprovalOf(call) {
|
|
@@ -6789,23 +6126,23 @@ function ChatEmptyState({
|
|
|
6789
6126
|
}) {
|
|
6790
6127
|
const doorCount = Math.min(doors?.length ?? 0, 3);
|
|
6791
6128
|
const doorsGridClass = doorCount === 1 ? "mx-auto max-w-sm sm:grid-cols-1" : doorCount === 2 ? "sm:grid-cols-2" : "sm:grid-cols-3";
|
|
6792
|
-
return /* @__PURE__ */
|
|
6793
|
-
/* @__PURE__ */
|
|
6794
|
-
/* @__PURE__ */
|
|
6795
|
-
/* @__PURE__ */
|
|
6796
|
-
subline && /* @__PURE__ */
|
|
6797
|
-
doors && doors.length > 0 && /* @__PURE__ */
|
|
6129
|
+
return /* @__PURE__ */ jsxs13("div", { className: "mx-auto flex w-full max-w-2xl flex-col items-center px-6 py-12 text-center sm:py-20", children: [
|
|
6130
|
+
/* @__PURE__ */ jsx15("span", { className: "mb-5 inline-flex h-14 w-14 items-center justify-center rounded-2xl bg-primary/10 ring-1 ring-primary/15", children: /* @__PURE__ */ jsx15(BrandMark, { size: 32, className: "shrink-0" }) }),
|
|
6131
|
+
/* @__PURE__ */ jsx15("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: productName }),
|
|
6132
|
+
/* @__PURE__ */ jsx15("h2", { className: "mt-1.5 text-balance text-2xl font-semibold leading-tight text-foreground", children: headline }),
|
|
6133
|
+
subline && /* @__PURE__ */ jsx15("p", { className: "mt-3 max-w-md text-[15px] leading-relaxed text-muted-foreground", children: subline }),
|
|
6134
|
+
doors && doors.length > 0 && /* @__PURE__ */ jsx15("div", { className: `mt-7 grid w-full gap-2.5 ${doorsGridClass}`, children: doors.slice(0, 3).map((door, i) => /* @__PURE__ */ jsxs13(
|
|
6798
6135
|
"button",
|
|
6799
6136
|
{
|
|
6800
6137
|
type: "button",
|
|
6801
6138
|
onClick: door.onSelect,
|
|
6802
6139
|
className: "group flex min-h-[44px] flex-col items-start rounded-xl border border-border bg-card px-4 py-3 text-left transition hover:border-primary/40 hover:bg-accent",
|
|
6803
6140
|
children: [
|
|
6804
|
-
/* @__PURE__ */
|
|
6141
|
+
/* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-2 text-sm font-semibold text-foreground", children: [
|
|
6805
6142
|
door.icon,
|
|
6806
6143
|
door.label
|
|
6807
6144
|
] }),
|
|
6808
|
-
door.description && /* @__PURE__ */
|
|
6145
|
+
door.description && /* @__PURE__ */ jsx15("span", { className: "mt-0.5 text-[12px] leading-snug text-muted-foreground", children: door.description })
|
|
6809
6146
|
]
|
|
6810
6147
|
},
|
|
6811
6148
|
i
|
|
@@ -6814,26 +6151,26 @@ function ChatEmptyState({
|
|
|
6814
6151
|
}
|
|
6815
6152
|
function ToolGlyph({ name, className }) {
|
|
6816
6153
|
if (name.startsWith("sandbox_")) {
|
|
6817
|
-
return /* @__PURE__ */
|
|
6818
|
-
/* @__PURE__ */
|
|
6819
|
-
/* @__PURE__ */
|
|
6154
|
+
return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
6155
|
+
/* @__PURE__ */ jsx15("polyline", { points: "4 17 10 11 4 5" }),
|
|
6156
|
+
/* @__PURE__ */ jsx15("line", { x1: "12", y1: "19", x2: "20", y2: "19" })
|
|
6820
6157
|
] });
|
|
6821
6158
|
}
|
|
6822
6159
|
if (name === "submit_proposal") {
|
|
6823
|
-
return /* @__PURE__ */
|
|
6824
|
-
/* @__PURE__ */
|
|
6825
|
-
/* @__PURE__ */
|
|
6160
|
+
return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
6161
|
+
/* @__PURE__ */ jsx15("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
|
|
6162
|
+
/* @__PURE__ */ jsx15("path", { d: "M14 2v6h6M9 15l2 2 4-4" })
|
|
6826
6163
|
] });
|
|
6827
6164
|
}
|
|
6828
6165
|
if (name === "schedule_followup") {
|
|
6829
|
-
return /* @__PURE__ */
|
|
6830
|
-
/* @__PURE__ */
|
|
6831
|
-
/* @__PURE__ */
|
|
6166
|
+
return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", "aria-hidden": true, children: [
|
|
6167
|
+
/* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "9" }),
|
|
6168
|
+
/* @__PURE__ */ jsx15("path", { d: "M12 7v5l3 3" })
|
|
6832
6169
|
] });
|
|
6833
6170
|
}
|
|
6834
|
-
return /* @__PURE__ */
|
|
6835
|
-
/* @__PURE__ */
|
|
6836
|
-
/* @__PURE__ */
|
|
6171
|
+
return /* @__PURE__ */ jsxs13("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
6172
|
+
/* @__PURE__ */ jsx15("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3" }),
|
|
6173
|
+
/* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "4" })
|
|
6837
6174
|
] });
|
|
6838
6175
|
}
|
|
6839
6176
|
function toolOutcomeOf(call) {
|
|
@@ -6919,40 +6256,40 @@ function truncate(v, max = 240) {
|
|
|
6919
6256
|
function KvRows({ data }) {
|
|
6920
6257
|
const entries = Object.entries(data).filter(([, v]) => v !== void 0 && v !== null && v !== "");
|
|
6921
6258
|
if (!entries.length) return null;
|
|
6922
|
-
return /* @__PURE__ */
|
|
6923
|
-
/* @__PURE__ */
|
|
6924
|
-
/* @__PURE__ */
|
|
6259
|
+
return /* @__PURE__ */ jsx15("dl", { className: "grid grid-cols-[auto_1fr] gap-x-3 gap-y-1", children: entries.map(([k, v]) => /* @__PURE__ */ jsxs13("div", { className: "contents", children: [
|
|
6260
|
+
/* @__PURE__ */ jsx15("dt", { className: "font-mono text-xs text-muted-foreground", children: k }),
|
|
6261
|
+
/* @__PURE__ */ jsx15("dd", { className: "min-w-0 whitespace-pre-wrap break-words font-mono text-xs text-muted-foreground", children: truncate(v) })
|
|
6925
6262
|
] }, k)) });
|
|
6926
6263
|
}
|
|
6927
6264
|
function ShellDetail({ call }) {
|
|
6928
6265
|
const outcome = toolOutcomeOf(call);
|
|
6929
6266
|
const r = outcome?.result ?? {};
|
|
6930
|
-
return /* @__PURE__ */
|
|
6931
|
-
/* @__PURE__ */
|
|
6932
|
-
/* @__PURE__ */
|
|
6933
|
-
/* @__PURE__ */
|
|
6934
|
-
r.exitCode != null && /* @__PURE__ */
|
|
6267
|
+
return /* @__PURE__ */ jsxs13("div", { className: "overflow-hidden rounded-md bg-zinc-900 font-mono text-xs leading-relaxed", children: [
|
|
6268
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 px-3 pt-2 text-zinc-400", children: [
|
|
6269
|
+
/* @__PURE__ */ jsx15("span", { className: "select-none text-zinc-500", children: "$" }),
|
|
6270
|
+
/* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 truncate text-zinc-200", children: String(call.args?.command ?? "") }),
|
|
6271
|
+
r.exitCode != null && /* @__PURE__ */ jsxs13("span", { className: r.exitCode === 0 ? "text-success" : "text-destructive", children: [
|
|
6935
6272
|
"exit ",
|
|
6936
6273
|
r.exitCode
|
|
6937
6274
|
] })
|
|
6938
6275
|
] }),
|
|
6939
|
-
/* @__PURE__ */
|
|
6276
|
+
/* @__PURE__ */ jsx15("pre", { className: "max-h-56 overflow-auto whitespace-pre-wrap px-3 pb-2.5 pt-1.5 text-zinc-300", children: outcome?.ok === false ? outcome.message ?? "failed" : [r.stdout, r.stderr].filter(Boolean).join("\n") || "(no output)" })
|
|
6940
6277
|
] });
|
|
6941
6278
|
}
|
|
6942
6279
|
function DefaultToolDetail({ call }) {
|
|
6943
6280
|
const result = call.result;
|
|
6944
6281
|
const envelope = typeof result === "object" && result !== null ? result : null;
|
|
6945
|
-
return /* @__PURE__ */
|
|
6946
|
-
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */
|
|
6947
|
-
/* @__PURE__ */
|
|
6948
|
-
/* @__PURE__ */
|
|
6282
|
+
return /* @__PURE__ */ jsxs13("div", { className: "space-y-2", children: [
|
|
6283
|
+
call.args && Object.keys(call.args).length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
|
|
6284
|
+
/* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Called with" }),
|
|
6285
|
+
/* @__PURE__ */ jsx15(KvRows, { data: call.args })
|
|
6949
6286
|
] }),
|
|
6950
|
-
envelope ? /* @__PURE__ */
|
|
6951
|
-
/* @__PURE__ */
|
|
6952
|
-
envelope.ok === false ? /* @__PURE__ */
|
|
6953
|
-
] }) : result != null ? /* @__PURE__ */
|
|
6954
|
-
/* @__PURE__ */
|
|
6955
|
-
/* @__PURE__ */
|
|
6287
|
+
envelope ? /* @__PURE__ */ jsxs13("div", { children: [
|
|
6288
|
+
/* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: envelope.ok === false ? "Failed" : "Result" }),
|
|
6289
|
+
envelope.ok === false ? /* @__PURE__ */ jsx15("p", { className: "text-xs text-destructive", children: envelope.message ?? "Tool failed" }) : envelope.result && typeof envelope.result === "object" ? /* @__PURE__ */ jsx15(KvRows, { data: envelope.result }) : envelope.result != null ? /* @__PURE__ */ jsx15("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(envelope.result) }) : null
|
|
6290
|
+
] }) : result != null ? /* @__PURE__ */ jsxs13("div", { children: [
|
|
6291
|
+
/* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Result" }),
|
|
6292
|
+
/* @__PURE__ */ jsx15("p", { className: "font-mono text-xs text-muted-foreground", children: truncate(result) })
|
|
6956
6293
|
] }) : null
|
|
6957
6294
|
] });
|
|
6958
6295
|
}
|
|
@@ -6963,24 +6300,24 @@ function ProposalCard({
|
|
|
6963
6300
|
approval,
|
|
6964
6301
|
renderers
|
|
6965
6302
|
}) {
|
|
6966
|
-
const [expanded, setExpanded] =
|
|
6303
|
+
const [expanded, setExpanded] = useState17(false);
|
|
6967
6304
|
const { summary, meta, typeSlug } = proposalPreview(call);
|
|
6968
6305
|
const custom = renderers?.[call.name]?.(call, message);
|
|
6969
6306
|
const { pending: deciding, run: decide } = usePending();
|
|
6970
|
-
return /* @__PURE__ */
|
|
6971
|
-
/* @__PURE__ */
|
|
6972
|
-
/* @__PURE__ */
|
|
6973
|
-
/* @__PURE__ */
|
|
6974
|
-
/* @__PURE__ */
|
|
6975
|
-
/* @__PURE__ */
|
|
6976
|
-
summary && /* @__PURE__ */
|
|
6977
|
-
typeSlug && /* @__PURE__ */
|
|
6978
|
-
meta.length > 0 && /* @__PURE__ */
|
|
6307
|
+
return /* @__PURE__ */ jsxs13("div", { className: "w-full max-w-full rounded-xl border border-warning/50 bg-warning/[0.06] text-sm shadow-sm ring-1 ring-warning/10", children: [
|
|
6308
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-2.5 px-4 pt-3.5", children: [
|
|
6309
|
+
/* @__PURE__ */ jsx15("span", { className: "mt-0.5 inline-flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-warning/15 text-warning", children: /* @__PURE__ */ jsx15(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
|
|
6310
|
+
/* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
|
|
6311
|
+
/* @__PURE__ */ jsx15("p", { className: "text-xs font-semibold uppercase tracking-[0.05em] text-warning-strong", children: approval ? "Needs your approval" : "Awaiting approval" }),
|
|
6312
|
+
/* @__PURE__ */ jsx15("p", { className: "mt-0.5 text-[15px] font-semibold leading-snug text-foreground", children: friendlyToolTitle(call) }),
|
|
6313
|
+
summary && /* @__PURE__ */ jsx15("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: summary }),
|
|
6314
|
+
typeSlug && /* @__PURE__ */ jsx15("p", { className: "mt-1 font-mono text-xs text-muted-foreground", children: typeSlug }),
|
|
6315
|
+
meta.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-1.5 flex flex-wrap items-center gap-1.5", children: meta.map((m, i) => /* @__PURE__ */ jsx15("span", { className: "rounded-full bg-secondary px-2 py-0.5 text-xs font-medium text-muted-foreground", children: m }, i)) })
|
|
6979
6316
|
] })
|
|
6980
6317
|
] }),
|
|
6981
|
-
/* @__PURE__ */
|
|
6982
|
-
approval && /* @__PURE__ */
|
|
6983
|
-
/* @__PURE__ */
|
|
6318
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap items-center gap-2 px-4 pb-3.5 pt-3", children: [
|
|
6319
|
+
approval && /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
6320
|
+
/* @__PURE__ */ jsx15(
|
|
6984
6321
|
"button",
|
|
6985
6322
|
{
|
|
6986
6323
|
type: "button",
|
|
@@ -6990,7 +6327,7 @@ function ProposalCard({
|
|
|
6990
6327
|
children: "Approve & run"
|
|
6991
6328
|
}
|
|
6992
6329
|
),
|
|
6993
|
-
/* @__PURE__ */
|
|
6330
|
+
/* @__PURE__ */ jsx15(
|
|
6994
6331
|
"button",
|
|
6995
6332
|
{
|
|
6996
6333
|
type: "button",
|
|
@@ -7001,7 +6338,7 @@ function ProposalCard({
|
|
|
7001
6338
|
}
|
|
7002
6339
|
)
|
|
7003
6340
|
] }),
|
|
7004
|
-
/* @__PURE__ */
|
|
6341
|
+
/* @__PURE__ */ jsxs13(
|
|
7005
6342
|
"button",
|
|
7006
6343
|
{
|
|
7007
6344
|
type: "button",
|
|
@@ -7010,12 +6347,12 @@ function ProposalCard({
|
|
|
7010
6347
|
className: "ml-auto inline-flex items-center gap-1 rounded text-[12px] font-medium text-muted-foreground transition hover:text-foreground",
|
|
7011
6348
|
children: [
|
|
7012
6349
|
expanded ? "Hide details" : "View details",
|
|
7013
|
-
/* @__PURE__ */
|
|
6350
|
+
/* @__PURE__ */ jsx15(ChevronDown, { className: `h-3 w-3 transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
7014
6351
|
]
|
|
7015
6352
|
}
|
|
7016
6353
|
)
|
|
7017
6354
|
] }),
|
|
7018
|
-
expanded && /* @__PURE__ */
|
|
6355
|
+
expanded && /* @__PURE__ */ jsx15("div", { className: "border-t border-warning/20 px-4 py-3 text-xs", children: custom ?? /* @__PURE__ */ jsx15(DefaultToolDetail, { call }) })
|
|
7019
6356
|
] });
|
|
7020
6357
|
}
|
|
7021
6358
|
function formatFollowupWhen(when) {
|
|
@@ -7030,14 +6367,14 @@ function FollowupCard({ call }) {
|
|
|
7030
6367
|
const when = typeof a.when === "string" ? a.when : typeof a.at === "string" ? a.at : typeof a.schedule === "string" ? a.schedule : null;
|
|
7031
6368
|
const failed = toolCallFailed(call);
|
|
7032
6369
|
const errorText = failed ? toolOutcomeOf(call)?.message ?? "Scheduling failed" : null;
|
|
7033
|
-
return /* @__PURE__ */
|
|
7034
|
-
/* @__PURE__ */
|
|
7035
|
-
/* @__PURE__ */
|
|
7036
|
-
/* @__PURE__ */
|
|
7037
|
-
when && /* @__PURE__ */
|
|
7038
|
-
/* @__PURE__ */
|
|
6370
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex items-start gap-2", children: /* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1 overflow-hidden rounded-[var(--radius-lg)] border border-[var(--border-subtle)] bg-[var(--md3-surface-container)]", children: [
|
|
6371
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex w-full items-center gap-2.5 px-3 py-2", children: [
|
|
6372
|
+
/* @__PURE__ */ jsx15("span", { className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-sm)] border border-border bg-muted text-muted-foreground", children: /* @__PURE__ */ jsx15(ToolGlyph, { name: call.name, className: "h-3.5 w-3.5" }) }),
|
|
6373
|
+
/* @__PURE__ */ jsx15("span", { className: "shrink-0 whitespace-nowrap text-xs font-medium text-foreground", children: friendlyToolTitle(call) }),
|
|
6374
|
+
when && /* @__PURE__ */ jsx15("span", { title: when, className: "hidden min-w-0 flex-1 truncate font-mono text-xs tabular-nums text-muted-foreground sm:inline", children: formatFollowupWhen(when) }),
|
|
6375
|
+
/* @__PURE__ */ jsx15("span", { className: "ml-auto flex shrink-0 items-center gap-1.5", children: call.status === "running" ? /* @__PURE__ */ jsx15("svg", { className: "h-3 w-3 shrink-0 animate-spin text-[var(--accent-text)]", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }) : /* @__PURE__ */ jsx15("span", { className: `h-1.5 w-1.5 shrink-0 rounded-full ${failed ? "bg-[var(--surface-danger-text)]" : "bg-[var(--surface-success-text)]"}` }) })
|
|
7039
6376
|
] }),
|
|
7040
|
-
errorText && /* @__PURE__ */
|
|
6377
|
+
errorText && /* @__PURE__ */ jsx15("div", { className: "border-t border-border px-3 py-2 text-xs text-[var(--surface-danger-text)]", children: errorText })
|
|
7041
6378
|
] }) });
|
|
7042
6379
|
}
|
|
7043
6380
|
function toolRowTitle(call) {
|
|
@@ -7060,10 +6397,10 @@ function ToolCallCard({
|
|
|
7060
6397
|
const arrival = useArrivalStyle(staggerIndex ?? 0);
|
|
7061
6398
|
const pending = call.status === "done" ? pendingApprovalOf(call) : null;
|
|
7062
6399
|
const kind = blockKindOf(call);
|
|
7063
|
-
const arrive = (row) => /* @__PURE__ */
|
|
6400
|
+
const arrive = (row) => /* @__PURE__ */ jsx15("div", { className: "agent-arrive", style: arrival, children: row });
|
|
7064
6401
|
if (pending) {
|
|
7065
6402
|
return arrive(
|
|
7066
|
-
/* @__PURE__ */
|
|
6403
|
+
/* @__PURE__ */ jsx15(
|
|
7067
6404
|
ProposalCard,
|
|
7068
6405
|
{
|
|
7069
6406
|
call,
|
|
@@ -7076,18 +6413,18 @@ function ToolCallCard({
|
|
|
7076
6413
|
);
|
|
7077
6414
|
}
|
|
7078
6415
|
if (kind === "followup") {
|
|
7079
|
-
return arrive(/* @__PURE__ */
|
|
6416
|
+
return arrive(/* @__PURE__ */ jsx15(FollowupCard, { call }));
|
|
7080
6417
|
}
|
|
7081
6418
|
const custom = renderers?.[call.name]?.(call, message);
|
|
7082
6419
|
return arrive(
|
|
7083
|
-
/* @__PURE__ */
|
|
6420
|
+
/* @__PURE__ */ jsx15(
|
|
7084
6421
|
InlineToolItem,
|
|
7085
6422
|
{
|
|
7086
6423
|
part: chatToolCallPart(call),
|
|
7087
6424
|
title: toolRowTitle(call),
|
|
7088
6425
|
description: toolRowDescription(call),
|
|
7089
|
-
renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */
|
|
7090
|
-
actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */
|
|
6426
|
+
renderToolDetail: () => custom ?? (call.name === "sandbox_run_command" ? /* @__PURE__ */ jsx15(ShellDetail, { call }) : /* @__PURE__ */ jsx15(DefaultToolDetail, { call })),
|
|
6427
|
+
actions: onOpenRun && call.name.startsWith("sandbox_") ? /* @__PURE__ */ jsx15(
|
|
7091
6428
|
"button",
|
|
7092
6429
|
{
|
|
7093
6430
|
type: "button",
|
|
@@ -7095,9 +6432,9 @@ function ToolCallCard({
|
|
|
7095
6432
|
"aria-label": "Open full transcript",
|
|
7096
6433
|
title: "Open full transcript",
|
|
7097
6434
|
className: "rounded-md p-1.5 text-muted-foreground transition hover:bg-accent hover:text-foreground",
|
|
7098
|
-
children: /* @__PURE__ */
|
|
7099
|
-
/* @__PURE__ */
|
|
7100
|
-
/* @__PURE__ */
|
|
6435
|
+
children: /* @__PURE__ */ jsxs13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
6436
|
+
/* @__PURE__ */ jsx15("path", { d: "M7 17 17 7" }),
|
|
6437
|
+
/* @__PURE__ */ jsx15("path", { d: "M7 7h10v10" })
|
|
7101
6438
|
] })
|
|
7102
6439
|
}
|
|
7103
6440
|
) : void 0
|
|
@@ -7106,7 +6443,7 @@ function ToolCallCard({
|
|
|
7106
6443
|
);
|
|
7107
6444
|
}
|
|
7108
6445
|
function StreamingCaret() {
|
|
7109
|
-
return /* @__PURE__ */
|
|
6446
|
+
return /* @__PURE__ */ jsx15(
|
|
7110
6447
|
"span",
|
|
7111
6448
|
{
|
|
7112
6449
|
className: "ml-0.5 inline-block h-[1.1em] w-[3px] translate-y-[2px] animate-[agent-caret_1s_step-end_infinite] rounded-sm bg-foreground/70",
|
|
@@ -7123,7 +6460,7 @@ function SegmentText({
|
|
|
7123
6460
|
messageClassName
|
|
7124
6461
|
}) {
|
|
7125
6462
|
const text = useSmoothText(content, streaming);
|
|
7126
|
-
const body =
|
|
6463
|
+
const body = useMemo8(() => renderBody(text), [renderBody, text]);
|
|
7127
6464
|
if (!content.trim() && !showCaret) return null;
|
|
7128
6465
|
return (
|
|
7129
6466
|
// A settled run arrives from a short blur; the LIVE run does not, because
|
|
@@ -7131,9 +6468,9 @@ function SegmentText({
|
|
|
7131
6468
|
// the container on top of that makes the paragraph shimmer while it types.
|
|
7132
6469
|
// The distinction is what separates "the answer materialised" from "the
|
|
7133
6470
|
// log was appended to".
|
|
7134
|
-
/* @__PURE__ */
|
|
6471
|
+
/* @__PURE__ */ jsxs13("div", { className: `${messageClassName}${streaming ? "" : " agent-stream-in"}`, children: [
|
|
7135
6472
|
body,
|
|
7136
|
-
showCaret && /* @__PURE__ */
|
|
6473
|
+
showCaret && /* @__PURE__ */ jsx15(StreamingCaret, {})
|
|
7137
6474
|
] })
|
|
7138
6475
|
);
|
|
7139
6476
|
}
|
|
@@ -7158,7 +6495,7 @@ function SegmentedBody({
|
|
|
7158
6495
|
const leftoverToolCalls = (msg.toolCalls ?? []).filter(
|
|
7159
6496
|
(tc) => !segmentToolIds.has(tc.id)
|
|
7160
6497
|
);
|
|
7161
|
-
const renderToolCard = (call, index) => /* @__PURE__ */
|
|
6498
|
+
const renderToolCard = (call, index) => /* @__PURE__ */ jsx15(
|
|
7162
6499
|
ToolCallCard,
|
|
7163
6500
|
{
|
|
7164
6501
|
call,
|
|
@@ -7186,7 +6523,7 @@ function SegmentedBody({
|
|
|
7186
6523
|
for (const g of groups) {
|
|
7187
6524
|
if (g.kind === "text") {
|
|
7188
6525
|
children.push(
|
|
7189
|
-
/* @__PURE__ */
|
|
6526
|
+
/* @__PURE__ */ jsx15(
|
|
7190
6527
|
SegmentText,
|
|
7191
6528
|
{
|
|
7192
6529
|
content: g.content,
|
|
@@ -7202,13 +6539,13 @@ function SegmentedBody({
|
|
|
7202
6539
|
}
|
|
7203
6540
|
if (!streaming && g.calls.length >= COLLAPSE_TOOL_RUN_AT && !g.calls.some(isImportantTool)) {
|
|
7204
6541
|
children.push(
|
|
7205
|
-
/* @__PURE__ */
|
|
7206
|
-
/* @__PURE__ */
|
|
6542
|
+
/* @__PURE__ */ jsxs13("details", { children: [
|
|
6543
|
+
/* @__PURE__ */ jsxs13("summary", { className: "cursor-pointer select-none rounded-md py-0.5 text-xs font-medium text-muted-foreground [transition:color_var(--motion-control)] hover:text-foreground", children: [
|
|
7207
6544
|
"Worked through ",
|
|
7208
6545
|
g.calls.length,
|
|
7209
6546
|
" steps"
|
|
7210
6547
|
] }),
|
|
7211
|
-
/* @__PURE__ */
|
|
6548
|
+
/* @__PURE__ */ jsx15("div", { className: "mt-1.5 flex flex-col gap-1.5", children: g.calls.map(renderToolCard) })
|
|
7212
6549
|
] }, `tools-fold-${g.index}`)
|
|
7213
6550
|
);
|
|
7214
6551
|
continue;
|
|
@@ -7217,9 +6554,9 @@ function SegmentedBody({
|
|
|
7217
6554
|
}
|
|
7218
6555
|
leftoverToolCalls.forEach((call, index) => children.push(renderToolCard(call, index)));
|
|
7219
6556
|
if (streaming && segments[lastIndex]?.kind === "tool") {
|
|
7220
|
-
children.push(/* @__PURE__ */
|
|
6557
|
+
children.push(/* @__PURE__ */ jsx15(StreamingCaret, {}, "streaming-caret"));
|
|
7221
6558
|
}
|
|
7222
|
-
return /* @__PURE__ */
|
|
6559
|
+
return /* @__PURE__ */ jsx15("div", { className: "flex flex-col gap-2", children });
|
|
7223
6560
|
}
|
|
7224
6561
|
var QUIET_META_LANE_CLASS = "mt-1 flex h-[18px] items-center gap-2 text-xs tabular-nums text-muted-foreground opacity-0 transition-opacity duration-150 group-hover:opacity-100 group-focus-within:opacity-100 motion-reduce:transition-none [@media(hover:none)]:opacity-100";
|
|
7225
6562
|
function copyTextOf(msg) {
|
|
@@ -7228,9 +6565,9 @@ function copyTextOf(msg) {
|
|
|
7228
6565
|
return msg.content;
|
|
7229
6566
|
}
|
|
7230
6567
|
function CopyMessageButton({ text }) {
|
|
7231
|
-
const [copied, setCopied] =
|
|
7232
|
-
const timerRef =
|
|
7233
|
-
|
|
6568
|
+
const [copied, setCopied] = useState17(false);
|
|
6569
|
+
const timerRef = useRef13(null);
|
|
6570
|
+
useEffect13(
|
|
7234
6571
|
() => () => {
|
|
7235
6572
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
7236
6573
|
},
|
|
@@ -7249,7 +6586,7 @@ function CopyMessageButton({ text }) {
|
|
|
7249
6586
|
}
|
|
7250
6587
|
);
|
|
7251
6588
|
};
|
|
7252
|
-
return /* @__PURE__ */
|
|
6589
|
+
return /* @__PURE__ */ jsx15(
|
|
7253
6590
|
"button",
|
|
7254
6591
|
{
|
|
7255
6592
|
type: "button",
|
|
@@ -7257,9 +6594,9 @@ function CopyMessageButton({ text }) {
|
|
|
7257
6594
|
"aria-label": "Copy message",
|
|
7258
6595
|
title: "Copy message",
|
|
7259
6596
|
className: "rounded p-0.5 text-muted-foreground transition hover:bg-accent hover:text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
7260
|
-
children: copied ? /* @__PURE__ */
|
|
7261
|
-
/* @__PURE__ */
|
|
7262
|
-
/* @__PURE__ */
|
|
6597
|
+
children: copied ? /* @__PURE__ */ jsx15("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx15("polyline", { points: "20 6 9 17 4 12" }) }) : /* @__PURE__ */ jsxs13("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
6598
|
+
/* @__PURE__ */ jsx15("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2" }),
|
|
6599
|
+
/* @__PURE__ */ jsx15("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
|
|
7263
6600
|
] })
|
|
7264
6601
|
}
|
|
7265
6602
|
);
|
|
@@ -7282,34 +6619,34 @@ function AssistantMessageImpl({
|
|
|
7282
6619
|
}) {
|
|
7283
6620
|
const content = useSmoothText(msg.content, streaming);
|
|
7284
6621
|
const reasoning = useSmoothText(msg.reasoning ?? "", streaming);
|
|
7285
|
-
const body =
|
|
6622
|
+
const body = useMemo8(() => renderBody(content), [renderBody, content]);
|
|
7286
6623
|
const segments = msg.segments;
|
|
7287
6624
|
const hasAnswerText = content !== "" || (segments?.some((s) => s.kind === "text" && s.content.trim() !== "") ?? false);
|
|
7288
|
-
const reasoningScrollRef =
|
|
7289
|
-
const thinkStartRef =
|
|
7290
|
-
const thinkMsRef =
|
|
6625
|
+
const reasoningScrollRef = useRef13(null);
|
|
6626
|
+
const thinkStartRef = useRef13(null);
|
|
6627
|
+
const thinkMsRef = useRef13(null);
|
|
7291
6628
|
if (streaming && reasoning && !hasAnswerText && thinkStartRef.current === null) {
|
|
7292
6629
|
thinkStartRef.current = performance.now();
|
|
7293
6630
|
}
|
|
7294
6631
|
if (hasAnswerText && thinkStartRef.current !== null && thinkMsRef.current === null) {
|
|
7295
6632
|
thinkMsRef.current = performance.now() - thinkStartRef.current;
|
|
7296
6633
|
}
|
|
7297
|
-
|
|
6634
|
+
useEffect13(() => {
|
|
7298
6635
|
const el = reasoningScrollRef.current;
|
|
7299
6636
|
if (el && streaming && !hasAnswerText) el.scrollTop = el.scrollHeight;
|
|
7300
6637
|
}, [reasoning, streaming, hasAnswerText]);
|
|
7301
6638
|
const thinkingSeconds = useThinkingSeconds(
|
|
7302
6639
|
streaming && !!reasoning && !hasAnswerText
|
|
7303
6640
|
);
|
|
7304
|
-
const [reasoningToggled, setReasoningToggled] =
|
|
6641
|
+
const [reasoningToggled, setReasoningToggled] = useState17(null);
|
|
7305
6642
|
const reasoningOpen = reasoningToggled ?? !hasAnswerText;
|
|
7306
6643
|
const quiet = chrome === "quiet";
|
|
7307
|
-
return /* @__PURE__ */
|
|
7308
|
-
!quiet && /* @__PURE__ */
|
|
7309
|
-
/* @__PURE__ */
|
|
7310
|
-
msg.modelUsed && /* @__PURE__ */
|
|
7311
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
7312
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
6644
|
+
return /* @__PURE__ */ jsxs13("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
|
|
6645
|
+
!quiet && /* @__PURE__ */ jsxs13("div", { className: "mb-1 flex items-baseline gap-2 text-xs tabular-nums text-muted-foreground", children: [
|
|
6646
|
+
/* @__PURE__ */ jsx15("span", { className: "font-semibold uppercase tracking-[0.05em]", children: agentLabel }),
|
|
6647
|
+
msg.modelUsed && /* @__PURE__ */ jsx15("span", { className: "font-mono normal-case", children: msg.modelUsed }),
|
|
6648
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx15("span", { children: formatTokensPerSecond(msg) }),
|
|
6649
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx15("span", { children: formatModelCost(msg, models) })
|
|
7313
6650
|
] }),
|
|
7314
6651
|
reasoning && // The canonical run-row grammar (RunRowShell — the same shell the tool
|
|
7315
6652
|
// rows compose): one family of rows instead of a bespoke disclosure per
|
|
@@ -7319,12 +6656,12 @@ function AssistantMessageImpl({
|
|
|
7319
6656
|
// and a click outranks the default from then on — the contract the old
|
|
7320
6657
|
// hand-rolled disclosure had, now enforced through the shell's
|
|
7321
6658
|
// controlled `open`.
|
|
7322
|
-
/* @__PURE__ */
|
|
6659
|
+
/* @__PURE__ */ jsx15(
|
|
7323
6660
|
RunRowShell,
|
|
7324
6661
|
{
|
|
7325
6662
|
className: "mb-2",
|
|
7326
|
-
icon: /* @__PURE__ */
|
|
7327
|
-
title: !hasAnswerText ? /* @__PURE__ */
|
|
6663
|
+
icon: /* @__PURE__ */ jsx15(BrainGlyph, { className: "h-3.5 w-3.5" }),
|
|
6664
|
+
title: !hasAnswerText ? /* @__PURE__ */ jsxs13("span", { className: "agent-shimmer", "data-motion": "essential", children: [
|
|
7328
6665
|
"Thinking",
|
|
7329
6666
|
thinkingSeconds >= 1 ? ` \xB7 ${thinkingSeconds}s` : "\u2026"
|
|
7330
6667
|
] }) : thinkMsRef.current != null ? (
|
|
@@ -7339,7 +6676,7 @@ function AssistantMessageImpl({
|
|
|
7339
6676
|
status: hasAnswerText ? "idle" : "running",
|
|
7340
6677
|
open: reasoningOpen,
|
|
7341
6678
|
onOpenChange: (next) => setReasoningToggled(next),
|
|
7342
|
-
children: /* @__PURE__ */
|
|
6679
|
+
children: /* @__PURE__ */ jsx15(
|
|
7343
6680
|
"div",
|
|
7344
6681
|
{
|
|
7345
6682
|
ref: reasoningScrollRef,
|
|
@@ -7349,7 +6686,7 @@ function AssistantMessageImpl({
|
|
|
7349
6686
|
)
|
|
7350
6687
|
}
|
|
7351
6688
|
),
|
|
7352
|
-
segments && segments.length > 0 ? /* @__PURE__ */
|
|
6689
|
+
segments && segments.length > 0 ? /* @__PURE__ */ jsx15(
|
|
7353
6690
|
SegmentedBody,
|
|
7354
6691
|
{
|
|
7355
6692
|
segments,
|
|
@@ -7361,12 +6698,12 @@ function AssistantMessageImpl({
|
|
|
7361
6698
|
toolRenderers,
|
|
7362
6699
|
messageClassName
|
|
7363
6700
|
}
|
|
7364
|
-
) : /* @__PURE__ */
|
|
7365
|
-
/* @__PURE__ */
|
|
6701
|
+
) : /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
6702
|
+
/* @__PURE__ */ jsxs13("div", { className: messageClassName, children: [
|
|
7366
6703
|
body,
|
|
7367
|
-
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */
|
|
6704
|
+
streaming && content && !msg.toolCalls?.length && /* @__PURE__ */ jsx15(StreamingCaret, {})
|
|
7368
6705
|
] }),
|
|
7369
|
-
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */
|
|
6706
|
+
msg.toolCalls && msg.toolCalls.length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2 flex flex-col gap-1.5", children: msg.toolCalls.map((tc, index) => /* @__PURE__ */ jsx15(
|
|
7370
6707
|
ToolCallCard,
|
|
7371
6708
|
{
|
|
7372
6709
|
call: tc,
|
|
@@ -7379,7 +6716,7 @@ function AssistantMessageImpl({
|
|
|
7379
6716
|
tc.id
|
|
7380
6717
|
)) })
|
|
7381
6718
|
] }),
|
|
7382
|
-
durableCards && msg.parts && /* @__PURE__ */
|
|
6719
|
+
durableCards && msg.parts && /* @__PURE__ */ jsx15(
|
|
7383
6720
|
DurableChatCards,
|
|
7384
6721
|
{
|
|
7385
6722
|
...durableCards,
|
|
@@ -7388,7 +6725,7 @@ function AssistantMessageImpl({
|
|
|
7388
6725
|
className: "mt-3"
|
|
7389
6726
|
}
|
|
7390
6727
|
),
|
|
7391
|
-
workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */
|
|
6728
|
+
workProductCards && workProductPartsFromMessageParts(msg.parts).map((part) => /* @__PURE__ */ jsx15(
|
|
7392
6729
|
WorkProductCard,
|
|
7393
6730
|
{
|
|
7394
6731
|
part,
|
|
@@ -7398,7 +6735,7 @@ function AssistantMessageImpl({
|
|
|
7398
6735
|
`${part.ref.id}:${part.ref.version}`
|
|
7399
6736
|
)),
|
|
7400
6737
|
renderExtras?.(msg),
|
|
7401
|
-
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */
|
|
6738
|
+
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-2", children: /* @__PURE__ */ jsx15(
|
|
7402
6739
|
MessageAttachments,
|
|
7403
6740
|
{
|
|
7404
6741
|
parts: attachmentPartsFromMessageParts(msg.parts),
|
|
@@ -7406,18 +6743,18 @@ function AssistantMessageImpl({
|
|
|
7406
6743
|
justify: "start"
|
|
7407
6744
|
}
|
|
7408
6745
|
) }),
|
|
7409
|
-
quiet && /* @__PURE__ */
|
|
7410
|
-
/* @__PURE__ */
|
|
7411
|
-
msg.modelUsed && /* @__PURE__ */
|
|
7412
|
-
formatTokensPerSecond(msg) && /* @__PURE__ */
|
|
7413
|
-
formatModelCost(msg, models) && /* @__PURE__ */
|
|
6746
|
+
quiet && /* @__PURE__ */ jsxs13("div", { "data-testid": "message-meta-lane", className: QUIET_META_LANE_CLASS, children: [
|
|
6747
|
+
/* @__PURE__ */ jsx15(CopyMessageButton, { text: copyTextOf(msg) }),
|
|
6748
|
+
msg.modelUsed && /* @__PURE__ */ jsx15("span", { className: "font-mono", children: msg.modelUsed }),
|
|
6749
|
+
formatTokensPerSecond(msg) && /* @__PURE__ */ jsx15("span", { children: formatTokensPerSecond(msg) }),
|
|
6750
|
+
formatModelCost(msg, models) && /* @__PURE__ */ jsx15("span", { children: formatModelCost(msg, models) })
|
|
7414
6751
|
] })
|
|
7415
6752
|
] });
|
|
7416
6753
|
}
|
|
7417
6754
|
var AssistantMessage = memo(AssistantMessageImpl);
|
|
7418
6755
|
function useThinkingSeconds(active) {
|
|
7419
|
-
const [seconds, setSeconds] =
|
|
7420
|
-
|
|
6756
|
+
const [seconds, setSeconds] = useState17(0);
|
|
6757
|
+
useEffect13(() => {
|
|
7421
6758
|
if (!active) return;
|
|
7422
6759
|
setSeconds(0);
|
|
7423
6760
|
const id = setInterval(() => setSeconds((s) => s + 1), 1e3);
|
|
@@ -7427,23 +6764,23 @@ function useThinkingSeconds(active) {
|
|
|
7427
6764
|
}
|
|
7428
6765
|
function ThinkingRow({ agentLabel, chrome = "labeled" }) {
|
|
7429
6766
|
const seconds = useThinkingSeconds(true);
|
|
7430
|
-
return /* @__PURE__ */
|
|
7431
|
-
chrome !== "quiet" && /* @__PURE__ */
|
|
7432
|
-
/* @__PURE__ */
|
|
7433
|
-
/* @__PURE__ */
|
|
6767
|
+
return /* @__PURE__ */ jsxs13("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: [
|
|
6768
|
+
chrome !== "quiet" && /* @__PURE__ */ jsx15("p", { className: "mb-1 text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: agentLabel }),
|
|
6769
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2 text-[15px] text-muted-foreground", children: [
|
|
6770
|
+
/* @__PURE__ */ jsx15("svg", { className: "h-4 w-4 animate-spin", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx15("path", { d: "M21 12a9 9 0 1 1-6.219-8.56", strokeLinecap: "round" }) }),
|
|
7434
6771
|
"Thinking",
|
|
7435
6772
|
seconds >= 3 ? ` \xB7 ${seconds}s` : "..."
|
|
7436
6773
|
] })
|
|
7437
6774
|
] });
|
|
7438
6775
|
}
|
|
7439
6776
|
function StreamErrorRow({ message, onRetry }) {
|
|
7440
|
-
return /* @__PURE__ */
|
|
7441
|
-
/* @__PURE__ */
|
|
7442
|
-
/* @__PURE__ */
|
|
7443
|
-
/* @__PURE__ */
|
|
6777
|
+
return /* @__PURE__ */ jsx15("div", { className: "mx-auto w-full max-w-3xl px-6 py-3", children: /* @__PURE__ */ jsxs13("div", { role: "alert", className: "flex items-start gap-2.5 rounded-lg border border-destructive/40 bg-destructive/5 px-3 py-2.5 text-sm text-destructive", children: [
|
|
6778
|
+
/* @__PURE__ */ jsxs13("svg", { className: "mt-0.5 h-4 w-4 shrink-0", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: [
|
|
6779
|
+
/* @__PURE__ */ jsx15("circle", { cx: "12", cy: "12", r: "9" }),
|
|
6780
|
+
/* @__PURE__ */ jsx15("path", { d: "M12 8v4m0 4h.01" })
|
|
7444
6781
|
] }),
|
|
7445
|
-
/* @__PURE__ */
|
|
7446
|
-
onRetry && /* @__PURE__ */
|
|
6782
|
+
/* @__PURE__ */ jsx15("span", { className: "min-w-0 flex-1 break-words", children: message }),
|
|
6783
|
+
onRetry && /* @__PURE__ */ jsx15(
|
|
7447
6784
|
"button",
|
|
7448
6785
|
{
|
|
7449
6786
|
type: "button",
|
|
@@ -7477,33 +6814,33 @@ function ChatMessages({
|
|
|
7477
6814
|
workProductCards
|
|
7478
6815
|
}) {
|
|
7479
6816
|
const messageClassName = messageSize === "large" ? "agent-app-message-copy text-[17px] leading-[1.6]" : "agent-app-message-copy text-base leading-[1.6]";
|
|
7480
|
-
const renderBody =
|
|
7481
|
-
() => renderMarkdown ?? ((content) => /* @__PURE__ */
|
|
6817
|
+
const renderBody = useMemo8(
|
|
6818
|
+
() => renderMarkdown ?? ((content) => /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: content })),
|
|
7482
6819
|
[renderMarkdown]
|
|
7483
6820
|
);
|
|
7484
6821
|
const lastIsUser = messages[messages.length - 1]?.role === "user";
|
|
7485
6822
|
const quiet = chrome === "quiet";
|
|
7486
6823
|
if (messages.length === 0 && !loading && !error) {
|
|
7487
|
-
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */
|
|
7488
|
-
return /* @__PURE__ */
|
|
6824
|
+
const empty = renderEmpty ? renderEmpty() : /* @__PURE__ */ jsx15(ChatEmptyState, { ...emptyState });
|
|
6825
|
+
return /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
7489
6826
|
header,
|
|
7490
6827
|
empty
|
|
7491
6828
|
] });
|
|
7492
6829
|
}
|
|
7493
|
-
return /* @__PURE__ */
|
|
6830
|
+
return /* @__PURE__ */ jsxs13(Fragment8, { children: [
|
|
7494
6831
|
header,
|
|
7495
6832
|
messages.map(
|
|
7496
|
-
(msg) => msg.role === "user" ? /* @__PURE__ */
|
|
7497
|
-
/* @__PURE__ */
|
|
7498
|
-
!quiet && /* @__PURE__ */
|
|
7499
|
-
/* @__PURE__ */
|
|
6833
|
+
(msg) => msg.role === "user" ? /* @__PURE__ */ jsxs13("div", { className: `mx-auto w-full max-w-3xl px-6 ${quiet ? "group pb-1 pt-3" : "py-3"}`, children: [
|
|
6834
|
+
/* @__PURE__ */ jsxs13("div", { className: `ml-auto w-fit ${quiet ? "max-w-[72%]" : "max-w-[85%]"}`, children: [
|
|
6835
|
+
!quiet && /* @__PURE__ */ jsx15("p", { className: "mb-1 text-right text-xs font-semibold uppercase tracking-[0.05em] text-muted-foreground", children: userLabel }),
|
|
6836
|
+
/* @__PURE__ */ jsx15(
|
|
7500
6837
|
"div",
|
|
7501
6838
|
{
|
|
7502
6839
|
className: quiet ? `rounded-2xl bg-[color-mix(in_srgb,hsl(var(--secondary))_65%,hsl(var(--background)))] px-4 py-2.5 ${messageClassName}` : `rounded-2xl rounded-tr-md bg-primary/10 px-4 py-2.5 ${messageClassName}`,
|
|
7503
|
-
children: /* @__PURE__ */
|
|
6840
|
+
children: /* @__PURE__ */ jsx15("p", { className: "whitespace-pre-wrap", children: msg.content })
|
|
7504
6841
|
}
|
|
7505
6842
|
),
|
|
7506
|
-
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */
|
|
6843
|
+
resolveAttachmentUrl && attachmentPartsFromMessageParts(msg.parts).length > 0 && /* @__PURE__ */ jsx15("div", { className: "mt-1.5", children: /* @__PURE__ */ jsx15(
|
|
7507
6844
|
MessageAttachments,
|
|
7508
6845
|
{
|
|
7509
6846
|
parts: attachmentPartsFromMessageParts(msg.parts),
|
|
@@ -7512,8 +6849,8 @@ function ChatMessages({
|
|
|
7512
6849
|
}
|
|
7513
6850
|
) })
|
|
7514
6851
|
] }),
|
|
7515
|
-
quiet && /* @__PURE__ */
|
|
7516
|
-
] }, msg.id) : /* @__PURE__ */
|
|
6852
|
+
quiet && /* @__PURE__ */ jsx15("div", { "data-testid": "message-meta-lane", className: `${QUIET_META_LANE_CLASS} justify-end`, children: /* @__PURE__ */ jsx15(CopyMessageButton, { text: msg.content }) })
|
|
6853
|
+
] }, msg.id) : /* @__PURE__ */ jsx15(
|
|
7517
6854
|
AssistantMessage,
|
|
7518
6855
|
{
|
|
7519
6856
|
msg,
|
|
@@ -7534,8 +6871,8 @@ function ChatMessages({
|
|
|
7534
6871
|
msg.id
|
|
7535
6872
|
)
|
|
7536
6873
|
),
|
|
7537
|
-
loading && lastIsUser && /* @__PURE__ */
|
|
7538
|
-
error && !loading && /* @__PURE__ */
|
|
6874
|
+
loading && lastIsUser && /* @__PURE__ */ jsx15(ThinkingRow, { agentLabel, chrome }),
|
|
6875
|
+
error && !loading && /* @__PURE__ */ jsx15(StreamErrorRow, { message: error, onRetry })
|
|
7539
6876
|
] });
|
|
7540
6877
|
}
|
|
7541
6878
|
|
|
@@ -7620,11 +6957,6 @@ export {
|
|
|
7620
6957
|
ProvenanceValue,
|
|
7621
6958
|
ProvenanceLegend,
|
|
7622
6959
|
SeatPaywall,
|
|
7623
|
-
useInfiniteScroll,
|
|
7624
|
-
useSessionHistory,
|
|
7625
|
-
useSessionActions,
|
|
7626
|
-
formatSessionTimestamp,
|
|
7627
|
-
SessionHistoryPanel,
|
|
7628
6960
|
recordGridOk,
|
|
7629
6961
|
recordGridFail,
|
|
7630
6962
|
isRecordGridCellApplicable,
|
|
@@ -7679,4 +7011,4 @@ export {
|
|
|
7679
7011
|
useThinkingSeconds,
|
|
7680
7012
|
ChatMessages
|
|
7681
7013
|
};
|
|
7682
|
-
//# sourceMappingURL=chunk-
|
|
7014
|
+
//# sourceMappingURL=chunk-YTEUZXX2.js.map
|