@opengeni/react 3.8.0-canary.0 → 4.0.1-canary.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +11 -24
  2. package/dist/artifacts.js +7 -7
  3. package/dist/{browser-viewer-SS46LUAC.js → browser-viewer-NTD6UIPR.js} +3 -3
  4. package/dist/{chunk-VEPNNDNG.js → chunk-24M4YBCL.js} +4 -4
  5. package/dist/chunk-5M6VTFJ5.js +171 -0
  6. package/dist/chunk-5M6VTFJ5.js.map +1 -0
  7. package/dist/{chunk-IOLVN74D.js → chunk-6J56T3MG.js} +15 -1
  8. package/dist/chunk-6J56T3MG.js.map +1 -0
  9. package/dist/{chunk-ELIYWBZR.js → chunk-BV5A4OTE.js} +4 -4
  10. package/dist/{chunk-3HIF5IFC.js → chunk-HO6X4FHG.js} +2597 -1030
  11. package/dist/chunk-HO6X4FHG.js.map +1 -0
  12. package/dist/{chunk-BXJOQFCD.js → chunk-HUMIRRYI.js} +84 -221
  13. package/dist/chunk-HUMIRRYI.js.map +1 -0
  14. package/dist/{chunk-ZFOFY5ST.js → chunk-NLTS7JHI.js} +16 -31
  15. package/dist/chunk-NLTS7JHI.js.map +1 -0
  16. package/dist/chunk-NOSYBS2D.js +208 -0
  17. package/dist/chunk-NOSYBS2D.js.map +1 -0
  18. package/dist/chunk-YBM6CQRU.js +292 -0
  19. package/dist/chunk-YBM6CQRU.js.map +1 -0
  20. package/dist/{chunk-BQGIXRKV.js → chunk-Z7WBDB4E.js} +416 -290
  21. package/dist/chunk-Z7WBDB4E.js.map +1 -0
  22. package/dist/chunk-ZYRGEKWS.js +216 -0
  23. package/dist/chunk-ZYRGEKWS.js.map +1 -0
  24. package/dist/components/composer.d.ts +4 -2
  25. package/dist/components/human-input-form.d.ts +3 -1
  26. package/dist/components/human-input-surface.d.ts +3 -2
  27. package/dist/components/message-timeline.d.ts +9 -2
  28. package/dist/components/session-conversation.d.ts +2 -0
  29. package/dist/components/timeline-annotation-chrome.d.ts +25 -0
  30. package/dist/components/timeline-annotation-layout.d.ts +42 -0
  31. package/dist/components/timeline-annotation-markers.d.ts +8 -0
  32. package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
  33. package/dist/components/timeline-annotation-shared.d.ts +31 -0
  34. package/dist/components/timeline-annotations-dialog.d.ts +1 -1
  35. package/dist/components/timeline-annotations.d.ts +8 -2
  36. package/dist/composer.js +3 -4
  37. package/dist/{computer-viewer-FWEZISW4.js → computer-viewer-7TEZC6Y2.js} +3 -3
  38. package/dist/hooks/use-codex-accounts.d.ts +11 -1
  39. package/dist/hooks/use-composer.d.ts +2 -0
  40. package/dist/hooks/use-session-events.d.ts +2 -2
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.js +50 -37
  43. package/dist/index.js.map +1 -1
  44. package/dist/interaction.js +3 -3
  45. package/dist/machines.js +1 -1
  46. package/dist/older-history.d.ts +3 -2
  47. package/dist/{platform-activity-row-BJHUHXAT.js → platform-activity-row-27LKAWZD.js} +2 -2
  48. package/dist/platform-activity-row-27LKAWZD.js.map +1 -0
  49. package/dist/{queue-surface-implementation-XL2A6PBM.js → queue-surface-implementation-LK3S4BIW.js} +5 -2
  50. package/dist/{queue-surface-implementation-XL2A6PBM.js.map → queue-surface-implementation-LK3S4BIW.js.map} +1 -1
  51. package/dist/realtime.js +3 -3
  52. package/dist/session-ui.js +11 -11
  53. package/dist/session.js +2 -2
  54. package/dist/timeline/types.d.ts +3 -0
  55. package/dist/timeline-annotation-markers-DRSTLEM6.js +165 -0
  56. package/dist/timeline-annotation-markers-DRSTLEM6.js.map +1 -0
  57. package/dist/timeline-annotation-selection-IHLUGVND.js +236 -0
  58. package/dist/timeline-annotation-selection-IHLUGVND.js.map +1 -0
  59. package/dist/timeline-annotations-dialog-6Q53N5FG.js +262 -0
  60. package/dist/timeline-annotations-dialog-6Q53N5FG.js.map +1 -0
  61. package/package.json +2 -6
  62. package/src/components/chat-composer.tsx +5 -2
  63. package/src/components/composer.tsx +40 -5
  64. package/src/components/copy-button.tsx +1 -0
  65. package/src/components/human-input-form.tsx +185 -53
  66. package/src/components/human-input-surface.tsx +3 -0
  67. package/src/components/machines-dashboard.tsx +1 -16
  68. package/src/components/message-timeline.tsx +397 -302
  69. package/src/components/session-commands-panel.tsx +7 -1
  70. package/src/components/session-conversation.tsx +4 -1
  71. package/src/components/timeline-annotation-chrome.tsx +183 -0
  72. package/src/components/timeline-annotation-layout.ts +268 -0
  73. package/src/components/timeline-annotation-markers.tsx +185 -0
  74. package/src/components/timeline-annotation-reveal-context.ts +9 -0
  75. package/src/components/timeline-annotation-selection.tsx +99 -54
  76. package/src/components/timeline-annotation-shared.ts +245 -0
  77. package/src/components/timeline-annotations-dialog.tsx +172 -128
  78. package/src/components/timeline-annotations.tsx +178 -45
  79. package/src/hooks/use-codex-accounts.ts +32 -5
  80. package/src/hooks/use-composer.ts +17 -0
  81. package/src/hooks/use-session-events.ts +16 -277
  82. package/src/index.ts +0 -1
  83. package/src/older-history.ts +22 -4
  84. package/src/timeline/platform-activity-row.tsx +4 -1
  85. package/src/timeline/projection.ts +99 -9
  86. package/src/timeline/types.ts +3 -0
  87. package/styles/compiled.css +86 -22
  88. package/dist/chat.d.ts +0 -37
  89. package/dist/chat.js +0 -315
  90. package/dist/chat.js.map +0 -1
  91. package/dist/chunk-3HIF5IFC.js.map +0 -1
  92. package/dist/chunk-BQGIXRKV.js.map +0 -1
  93. package/dist/chunk-BXJOQFCD.js.map +0 -1
  94. package/dist/chunk-F2CFHN3Y.js +0 -1415
  95. package/dist/chunk-F2CFHN3Y.js.map +0 -1
  96. package/dist/chunk-HQV2I5HV.js +0 -124
  97. package/dist/chunk-HQV2I5HV.js.map +0 -1
  98. package/dist/chunk-IOLVN74D.js.map +0 -1
  99. package/dist/chunk-W3OUAH6M.js +0 -170
  100. package/dist/chunk-W3OUAH6M.js.map +0 -1
  101. package/dist/chunk-ZFOFY5ST.js.map +0 -1
  102. package/dist/platform-activity-row-BJHUHXAT.js.map +0 -1
  103. package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
  104. package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
  105. package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
  106. package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
  107. package/src/chat.tsx +0 -393
  108. /package/dist/{browser-viewer-SS46LUAC.js.map → browser-viewer-NTD6UIPR.js.map} +0 -0
  109. /package/dist/{chunk-VEPNNDNG.js.map → chunk-24M4YBCL.js.map} +0 -0
  110. /package/dist/{chunk-ELIYWBZR.js.map → chunk-BV5A4OTE.js.map} +0 -0
  111. /package/dist/{computer-viewer-FWEZISW4.js.map → computer-viewer-7TEZC6Y2.js.map} +0 -0
@@ -0,0 +1,208 @@
1
+ // src/components/timeline-annotation-shared.ts
2
+ var ANNOTATION_CHROME_SELECTOR = "[data-og-annotation-chrome], [data-og-annotation-badge], [data-og-annotation-popover]";
3
+ function annotationHasNote(note) {
4
+ return note.trim().length > 0;
5
+ }
6
+ function annotationDisplayOrdinal(annotation, index) {
7
+ return typeof annotation.ordinal === "number" ? annotation.ordinal : index + 1;
8
+ }
9
+ function sourceKindLabel(kind) {
10
+ switch (kind) {
11
+ case "user_message":
12
+ return "Your message";
13
+ case "assistant_message":
14
+ return "Assistant";
15
+ case "tool_output":
16
+ return "Tool output";
17
+ }
18
+ }
19
+ function annotationSourceLabel(source) {
20
+ return source.label?.trim() || sourceKindLabel(source.kind);
21
+ }
22
+ function truncateAnnotationQuote(quote, maxChars = 160) {
23
+ const normalized = quote.replace(/\s+/g, " ").trim();
24
+ if (normalized.length <= maxChars) return normalized;
25
+ return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}\u2026`;
26
+ }
27
+ function cssEscapeAttribute(value) {
28
+ if (typeof CSS !== "undefined" && typeof CSS.escape === "function") return CSS.escape(value);
29
+ return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
30
+ }
31
+ function isAnnotationChromeNode(node) {
32
+ const element = node instanceof Element ? node : node?.parentElement;
33
+ return Boolean(element?.closest(ANNOTATION_CHROME_SELECTOR));
34
+ }
35
+ function occurrenceOffsets(text, quote) {
36
+ if (!quote) return [];
37
+ const offsets = [];
38
+ let cursor = 0;
39
+ while (cursor <= text.length - quote.length) {
40
+ const offset = text.indexOf(quote, cursor);
41
+ if (offset < 0) break;
42
+ offsets.push(offset);
43
+ cursor = offset + 1;
44
+ }
45
+ return offsets;
46
+ }
47
+ function uniqueNonEmpty(values) {
48
+ const seen = /* @__PURE__ */ new Set();
49
+ const out = [];
50
+ for (const value of values) {
51
+ if (!value || seen.has(value)) continue;
52
+ seen.add(value);
53
+ out.push(value);
54
+ }
55
+ return out;
56
+ }
57
+ function matchingQuoteInSource(sourceText, quote) {
58
+ for (const candidate of uniqueNonEmpty([quote, quote.trim()])) {
59
+ if (sourceText.includes(candidate)) return candidate;
60
+ }
61
+ const trimmed = quote.trim();
62
+ for (let length = trimmed.length; length >= 8; length--) {
63
+ const slice = trimmed.slice(0, length);
64
+ if (sourceText.includes(slice)) return slice;
65
+ }
66
+ for (let start = 1; start <= trimmed.length - 8; start++) {
67
+ const slice = trimmed.slice(start);
68
+ if (sourceText.includes(slice)) return slice;
69
+ }
70
+ return null;
71
+ }
72
+ function annotatableText(root) {
73
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {
74
+ acceptNode(node) {
75
+ if (!(node instanceof Text) || node.data.length === 0) return NodeFilter.FILTER_REJECT;
76
+ if (isAnnotationChromeNode(node)) return NodeFilter.FILTER_REJECT;
77
+ return NodeFilter.FILTER_ACCEPT;
78
+ }
79
+ });
80
+ const spans = [];
81
+ let text = "";
82
+ let current;
83
+ while (current = walker.nextNode()) {
84
+ if (!(current instanceof Text)) continue;
85
+ spans.push({ node: current, start: text.length, length: current.data.length });
86
+ text += current.data;
87
+ }
88
+ return { text, spans };
89
+ }
90
+ function pointAt(spans, offset, stickEnd) {
91
+ if (spans.length === 0) return null;
92
+ for (let index = 0; index < spans.length; index++) {
93
+ const span = spans[index];
94
+ const local = offset - span.start;
95
+ if (local < 0) continue;
96
+ if (local < span.length || local === span.length && (stickEnd || index === spans.length - 1)) {
97
+ return { node: span.node, offset: local };
98
+ }
99
+ }
100
+ const last = spans[spans.length - 1];
101
+ return { node: last.node, offset: last.length };
102
+ }
103
+ function rangeFromOffsets(spans, startOffset, endOffset) {
104
+ const start = pointAt(spans, startOffset, false);
105
+ const end = pointAt(spans, endOffset, true);
106
+ if (!start || !end) return null;
107
+ const range = document.createRange();
108
+ range.setStart(start.node, start.offset);
109
+ range.setEnd(end.node, end.offset);
110
+ return range.collapsed ? null : range;
111
+ }
112
+ function buildQuoteRange(sourceEl, quote, occurrenceIndex = 0) {
113
+ if (!quote) return null;
114
+ const { text, spans } = annotatableText(sourceEl);
115
+ const offsets = occurrenceOffsets(text, quote);
116
+ if (offsets.length === 0) return null;
117
+ const start = offsets[Math.min(Math.max(0, occurrenceIndex), offsets.length - 1)];
118
+ return rangeFromOffsets(spans, start, start + quote.length);
119
+ }
120
+ function quoteOccurrenceIndex(sourceEl, range, quote) {
121
+ try {
122
+ const prefix = range.cloneRange();
123
+ prefix.selectNodeContents(sourceEl);
124
+ prefix.setEnd(range.startContainer, range.startOffset);
125
+ return occurrenceOffsets(prefix.toString(), quote).length;
126
+ } catch {
127
+ return 0;
128
+ }
129
+ }
130
+ function clipRangeToSource(range, sourceEl) {
131
+ const startOk = sourceEl.contains(range.startContainer) && !isAnnotationChromeNode(range.startContainer);
132
+ const endOk = sourceEl.contains(range.endContainer) && !isAnnotationChromeNode(range.endContainer);
133
+ if (!startOk && !endOk) return null;
134
+ const { spans } = annotatableText(sourceEl);
135
+ if (spans.length === 0) return null;
136
+ const next = range.cloneRange();
137
+ const first = spans[0];
138
+ const last = spans[spans.length - 1];
139
+ if (!startOk) next.setStart(first.node, 0);
140
+ if (!endOk) next.setEnd(last.node, last.node.data.length);
141
+ return next.collapsed ? null : next;
142
+ }
143
+ function visibleClientRect(range) {
144
+ try {
145
+ const bounding = range.getBoundingClientRect();
146
+ if (bounding.width > 0 || bounding.height > 0) return bounding;
147
+ } catch {
148
+ }
149
+ try {
150
+ const rects = range.getClientRects();
151
+ for (let index = 0; index < rects.length; index++) {
152
+ const rect = rects.item(index);
153
+ if (rect && (rect.width > 0 || rect.height > 0)) return rect;
154
+ }
155
+ } catch {
156
+ }
157
+ return null;
158
+ }
159
+ function resolveAnnotationRevealRoot(from) {
160
+ const conversation = from?.closest("[data-og-conversation]");
161
+ if (conversation instanceof HTMLElement) {
162
+ const nested = conversation.querySelector("[data-og-timeline-scroller]");
163
+ return nested instanceof HTMLElement ? nested : conversation;
164
+ }
165
+ const scroller = from?.closest("[data-og-timeline-scroller]");
166
+ return scroller instanceof HTMLElement ? scroller : null;
167
+ }
168
+ function revealLoadedAnnotationSource(source, root) {
169
+ if (typeof document === "undefined") return false;
170
+ if (root === null) return false;
171
+ const element = (root ?? document).querySelector(
172
+ `[data-og-annotation-source-key="${cssEscapeAttribute(source.eventId)}"]`
173
+ );
174
+ if (!(element instanceof HTMLElement)) return false;
175
+ element.scrollIntoView({ block: "center", behavior: "smooth" });
176
+ element.animate?.(
177
+ [
178
+ {
179
+ boxShadow: "inset 0 0 0 2px color-mix(in oklch, var(--og-accent) 70%, transparent)",
180
+ backgroundColor: "color-mix(in oklch, var(--og-accent) 14%, transparent)"
181
+ },
182
+ {
183
+ boxShadow: "inset 0 0 0 2px transparent",
184
+ backgroundColor: "transparent"
185
+ }
186
+ ],
187
+ { duration: 1400, easing: "ease-out" }
188
+ );
189
+ return true;
190
+ }
191
+
192
+ export {
193
+ annotationHasNote,
194
+ annotationDisplayOrdinal,
195
+ annotationSourceLabel,
196
+ truncateAnnotationQuote,
197
+ cssEscapeAttribute,
198
+ occurrenceOffsets,
199
+ matchingQuoteInSource,
200
+ annotatableText,
201
+ buildQuoteRange,
202
+ quoteOccurrenceIndex,
203
+ clipRangeToSource,
204
+ visibleClientRect,
205
+ resolveAnnotationRevealRoot,
206
+ revealLoadedAnnotationSource
207
+ };
208
+ //# sourceMappingURL=chunk-NOSYBS2D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/timeline-annotation-shared.ts"],"sourcesContent":["import type { TimelineAnnotationSource } from \"@opengeni/sdk\";\n\nexport const ANNOTATION_CHROME_SELECTOR =\n \"[data-og-annotation-chrome], [data-og-annotation-badge], [data-og-annotation-popover]\";\n\nexport function annotationHasNote(note: string): boolean {\n return note.trim().length > 0;\n}\n\nexport function annotationDisplayOrdinal(\n annotation: { readonly id?: string; readonly ordinal?: number | undefined },\n index: number,\n): number {\n return typeof annotation.ordinal === \"number\" ? annotation.ordinal : index + 1;\n}\n\nexport function sourceKindLabel(kind: TimelineAnnotationSource[\"kind\"]): string {\n switch (kind) {\n case \"user_message\":\n return \"Your message\";\n case \"assistant_message\":\n return \"Assistant\";\n case \"tool_output\":\n return \"Tool output\";\n }\n}\n\nexport function annotationSourceLabel(source: TimelineAnnotationSource): string {\n return source.label?.trim() || sourceKindLabel(source.kind);\n}\n\nexport function truncateAnnotationQuote(quote: string, maxChars = 160): string {\n const normalized = quote.replace(/\\s+/g, \" \").trim();\n if (normalized.length <= maxChars) return normalized;\n return `${normalized.slice(0, Math.max(0, maxChars - 1)).trimEnd()}…`;\n}\n\nexport function cssEscapeAttribute(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") return CSS.escape(value);\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n}\n\nexport function isAnnotationChromeNode(node: Node | null): boolean {\n const element = node instanceof Element ? node : node?.parentElement;\n return Boolean(element?.closest(ANNOTATION_CHROME_SELECTOR));\n}\n\nexport function occurrenceOffsets(text: string, quote: string): number[] {\n if (!quote) return [];\n const offsets: number[] = [];\n let cursor = 0;\n while (cursor <= text.length - quote.length) {\n const offset = text.indexOf(quote, cursor);\n if (offset < 0) break;\n offsets.push(offset);\n cursor = offset + 1;\n }\n return offsets;\n}\n\nfunction uniqueNonEmpty(values: string[]): string[] {\n const seen = new Set<string>();\n const out: string[] = [];\n for (const value of values) {\n if (!value || seen.has(value)) continue;\n seen.add(value);\n out.push(value);\n }\n return out;\n}\n\nexport function matchingQuoteInSource(sourceText: string, quote: string): string | null {\n for (const candidate of uniqueNonEmpty([quote, quote.trim()])) {\n if (sourceText.includes(candidate)) return candidate;\n }\n const trimmed = quote.trim();\n for (let length = trimmed.length; length >= 8; length--) {\n const slice = trimmed.slice(0, length);\n if (sourceText.includes(slice)) return slice;\n }\n for (let start = 1; start <= trimmed.length - 8; start++) {\n const slice = trimmed.slice(start);\n if (sourceText.includes(slice)) return slice;\n }\n return null;\n}\n\ntype AnnotatableSpan = {\n node: Text;\n start: number;\n length: number;\n};\n\nexport function annotatableText(root: HTMLElement): { text: string; spans: AnnotatableSpan[] } {\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n if (!(node instanceof Text) || node.data.length === 0) return NodeFilter.FILTER_REJECT;\n if (isAnnotationChromeNode(node)) return NodeFilter.FILTER_REJECT;\n return NodeFilter.FILTER_ACCEPT;\n },\n });\n const spans: AnnotatableSpan[] = [];\n let text = \"\";\n let current: Node | null;\n while ((current = walker.nextNode())) {\n if (!(current instanceof Text)) continue;\n spans.push({ node: current, start: text.length, length: current.data.length });\n text += current.data;\n }\n return { text, spans };\n}\n\nfunction pointAt(\n spans: AnnotatableSpan[],\n offset: number,\n stickEnd: boolean,\n): { node: Text; offset: number } | null {\n if (spans.length === 0) return null;\n for (let index = 0; index < spans.length; index++) {\n const span = spans[index]!;\n const local = offset - span.start;\n if (local < 0) continue;\n if (\n local < span.length ||\n (local === span.length && (stickEnd || index === spans.length - 1))\n ) {\n return { node: span.node, offset: local };\n }\n }\n const last = spans[spans.length - 1]!;\n return { node: last.node, offset: last.length };\n}\n\nexport function rangeFromOffsets(\n spans: AnnotatableSpan[],\n startOffset: number,\n endOffset: number,\n): Range | null {\n const start = pointAt(spans, startOffset, false);\n const end = pointAt(spans, endOffset, true);\n if (!start || !end) return null;\n const range = document.createRange();\n range.setStart(start.node, start.offset);\n range.setEnd(end.node, end.offset);\n return range.collapsed ? null : range;\n}\n\nexport function buildQuoteRange(\n sourceEl: HTMLElement,\n quote: string,\n occurrenceIndex = 0,\n): Range | null {\n if (!quote) return null;\n const { text, spans } = annotatableText(sourceEl);\n const offsets = occurrenceOffsets(text, quote);\n if (offsets.length === 0) return null;\n const start = offsets[Math.min(Math.max(0, occurrenceIndex), offsets.length - 1)]!;\n return rangeFromOffsets(spans, start, start + quote.length);\n}\n\nexport function quoteOccurrenceIndex(sourceEl: HTMLElement, range: Range, quote: string): number {\n try {\n const prefix = range.cloneRange();\n prefix.selectNodeContents(sourceEl);\n prefix.setEnd(range.startContainer, range.startOffset);\n return occurrenceOffsets(prefix.toString(), quote).length;\n } catch {\n return 0;\n }\n}\n\nexport function clipRangeToSource(range: Range, sourceEl: HTMLElement): Range | null {\n const startOk =\n sourceEl.contains(range.startContainer) && !isAnnotationChromeNode(range.startContainer);\n const endOk =\n sourceEl.contains(range.endContainer) && !isAnnotationChromeNode(range.endContainer);\n if (!startOk && !endOk) return null;\n const { spans } = annotatableText(sourceEl);\n if (spans.length === 0) return null;\n const next = range.cloneRange();\n const first = spans[0]!;\n const last = spans[spans.length - 1]!;\n if (!startOk) next.setStart(first.node, 0);\n if (!endOk) next.setEnd(last.node, last.node.data.length);\n return next.collapsed ? null : next;\n}\n\nexport function visibleClientRect(range: Range): DOMRect | null {\n try {\n const bounding = range.getBoundingClientRect();\n if (bounding.width > 0 || bounding.height > 0) return bounding;\n } catch {\n // jsdom ranges may omit layout geometry.\n }\n try {\n const rects = range.getClientRects();\n for (let index = 0; index < rects.length; index++) {\n const rect = rects.item(index);\n if (rect && (rect.width > 0 || rect.height > 0)) return rect;\n }\n } catch {\n // jsdom ranges may omit client rects.\n }\n return null;\n}\n\nexport function resolveAnnotationRevealRoot(from: Element | null | undefined): HTMLElement | null {\n const conversation = from?.closest(\"[data-og-conversation]\");\n if (conversation instanceof HTMLElement) {\n const nested = conversation.querySelector(\"[data-og-timeline-scroller]\");\n return nested instanceof HTMLElement ? nested : conversation;\n }\n const scroller = from?.closest(\"[data-og-timeline-scroller]\");\n return scroller instanceof HTMLElement ? scroller : null;\n}\n\nexport function revealLoadedAnnotationSource(\n source: TimelineAnnotationSource,\n root?: ParentNode | null,\n): boolean {\n if (typeof document === \"undefined\") return false;\n // An explicit null root means the caller already scoped the search and found\n // no owning timeline. Do not fall back to `document`, or a second mounted\n // timeline with the same event id would steal the reveal.\n if (root === null) return false;\n const element = (root ?? document).querySelector(\n `[data-og-annotation-source-key=\"${cssEscapeAttribute(source.eventId)}\"]`,\n );\n if (!(element instanceof HTMLElement)) return false;\n element.scrollIntoView({ block: \"center\", behavior: \"smooth\" });\n element.animate?.(\n [\n {\n boxShadow: \"inset 0 0 0 2px color-mix(in oklch, var(--og-accent) 70%, transparent)\",\n backgroundColor: \"color-mix(in oklch, var(--og-accent) 14%, transparent)\",\n },\n {\n boxShadow: \"inset 0 0 0 2px transparent\",\n backgroundColor: \"transparent\",\n },\n ],\n { duration: 1400, easing: \"ease-out\" },\n );\n return true;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,292 @@
1
+ import {
2
+ AnnotationAccentRow,
3
+ AnnotationNotePreview,
4
+ AnnotationQuoteSourceButton,
5
+ TimelineAnnotationSourceRootContext,
6
+ useTimelineAnnotationSourceRoot
7
+ } from "./chunk-5M6VTFJ5.js";
8
+ import {
9
+ ANNOTATION_CARD_STACK_SCROLL_AT
10
+ } from "./chunk-ZYRGEKWS.js";
11
+ import {
12
+ annotationDisplayOrdinal,
13
+ annotationHasNote,
14
+ resolveAnnotationRevealRoot
15
+ } from "./chunk-NOSYBS2D.js";
16
+ import {
17
+ cn
18
+ } from "./chunk-22KP6LR5.js";
19
+
20
+ // src/components/timeline-annotations.tsx
21
+ import { QuoteIcon, XIcon } from "lucide-react";
22
+ import {
23
+ Suspense,
24
+ lazy,
25
+ useEffect,
26
+ useLayoutEffect,
27
+ useRef,
28
+ useState
29
+ } from "react";
30
+ import { jsx, jsxs } from "react/jsx-runtime";
31
+ var TimelineAnnotationsDialog = lazy(() => import("./timeline-annotations-dialog-6Q53N5FG.js"));
32
+ function AnnotationSourceRootBridge({
33
+ triggerRef,
34
+ children
35
+ }) {
36
+ const inheritedRoot = useTimelineAnnotationSourceRoot();
37
+ const conversationRootRef = useRef(null);
38
+ if (!inheritedRoot) {
39
+ conversationRootRef.current = resolveAnnotationRevealRoot(triggerRef.current);
40
+ }
41
+ useLayoutEffect(() => {
42
+ if (inheritedRoot) return;
43
+ conversationRootRef.current = resolveAnnotationRevealRoot(triggerRef.current);
44
+ });
45
+ if (inheritedRoot) return children;
46
+ return /* @__PURE__ */ jsx(TimelineAnnotationSourceRootContext.Provider, { value: conversationRootRef, children });
47
+ }
48
+ function TimelineAnnotationCards({
49
+ annotations,
50
+ onRevealSource,
51
+ className
52
+ }) {
53
+ const [unavailableId, setUnavailableId] = useState(null);
54
+ if (annotations.length === 0) return null;
55
+ return /* @__PURE__ */ jsx(
56
+ "div",
57
+ {
58
+ "data-og-annotation-cards": "",
59
+ className: cn(
60
+ "grid gap-2",
61
+ annotations.length >= ANNOTATION_CARD_STACK_SCROLL_AT && "max-h-[min(28rem,55vh)] overflow-x-hidden overflow-y-auto overscroll-contain pr-1",
62
+ className
63
+ ),
64
+ children: annotations.map((annotation, index) => {
65
+ const ordinal = annotationDisplayOrdinal(annotation, index);
66
+ return /* @__PURE__ */ jsx("section", { "aria-label": `Annotation ${ordinal}`, children: /* @__PURE__ */ jsxs(AnnotationAccentRow, { children: [
67
+ /* @__PURE__ */ jsxs("p", { className: "mb-0.5 text-og-xs font-medium tabular-nums text-og-fg-subtle", children: [
68
+ "Annotation ",
69
+ ordinal
70
+ ] }),
71
+ /* @__PURE__ */ jsx(
72
+ AnnotationQuoteSourceButton,
73
+ {
74
+ annotation,
75
+ lines: 2,
76
+ onRevealSource,
77
+ onUnavailable: setUnavailableId
78
+ }
79
+ ),
80
+ unavailableId === annotation.id ? /* @__PURE__ */ jsx("p", { role: "status", className: "text-og-xs text-og-status-waiting", children: "Source is outside the loaded timeline window." }) : null,
81
+ /* @__PURE__ */ jsx(
82
+ AnnotationNotePreview,
83
+ {
84
+ note: annotation.note,
85
+ annotationId: annotation.id,
86
+ ordinal
87
+ }
88
+ )
89
+ ] }) }, annotation.id);
90
+ })
91
+ }
92
+ );
93
+ }
94
+ function TimelineAnnotationsChip({
95
+ annotations,
96
+ editable = false,
97
+ focusAnnotationId,
98
+ onFocusConsumed,
99
+ onUpdate,
100
+ onRemove,
101
+ onRevealSource,
102
+ className
103
+ }) {
104
+ const focusRequested = Boolean(
105
+ focusAnnotationId && annotations.some((item) => item.id === focusAnnotationId)
106
+ );
107
+ const [open, setOpen] = useState(focusRequested);
108
+ const triggerRef = useRef(null);
109
+ const openedFocusId = useRef(focusRequested ? focusAnnotationId ?? null : null);
110
+ useEffect(() => {
111
+ if (!focusRequested || !focusAnnotationId) {
112
+ if (!focusRequested) openedFocusId.current = null;
113
+ return;
114
+ }
115
+ if (openedFocusId.current === focusAnnotationId) return;
116
+ openedFocusId.current = focusAnnotationId;
117
+ setOpen(true);
118
+ }, [focusAnnotationId, focusRequested]);
119
+ if (annotations.length === 0) return null;
120
+ const countLabel = `${annotations.length} ${annotations.length === 1 ? "annotation" : "annotations"}`;
121
+ const incomplete = annotations.some((annotation) => !annotationHasNote(annotation.note));
122
+ const canClear = Boolean(editable && onRemove);
123
+ const dismiss = (restoreFocus) => {
124
+ setOpen(false);
125
+ onFocusConsumed?.();
126
+ if (restoreFocus) triggerRef.current?.focus();
127
+ };
128
+ return /* @__PURE__ */ jsxs("span", { className: cn("inline-flex max-w-full items-center", className), children: [
129
+ /* @__PURE__ */ jsxs(
130
+ "span",
131
+ {
132
+ className: cn(
133
+ "inline-flex max-w-full items-center rounded-full border bg-og-surface-1 text-og-fg-muted",
134
+ incomplete ? "border-og-accent/45 bg-og-accent-soft/50" : "border-og-border"
135
+ ),
136
+ children: [
137
+ /* @__PURE__ */ jsxs(
138
+ "button",
139
+ {
140
+ ref: triggerRef,
141
+ type: "button",
142
+ className: cn(
143
+ "inline-flex min-h-8 min-w-0 max-w-full items-center gap-1.5 rounded-full border-0 bg-transparent py-1 text-og-sm font-medium outline-hidden transition hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]",
144
+ canClear ? "pr-1 pl-2.5" : "px-2.5"
145
+ ),
146
+ "aria-label": `Review ${countLabel}`,
147
+ "aria-haspopup": "dialog",
148
+ "aria-expanded": open,
149
+ onClick: () => setOpen((current) => !current),
150
+ children: [
151
+ /* @__PURE__ */ jsx(QuoteIcon, { className: "size-3.5 shrink-0 text-og-accent", "aria-hidden": "true" }),
152
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 truncate", children: countLabel })
153
+ ]
154
+ }
155
+ ),
156
+ canClear ? /* @__PURE__ */ jsx(
157
+ "button",
158
+ {
159
+ type: "button",
160
+ className: "inline-flex size-7 shrink-0 items-center justify-center rounded-full border-0 bg-transparent text-og-fg-subtle outline-hidden hover:text-og-status-failed focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:size-11",
161
+ "aria-label": "Remove all annotations",
162
+ onClick: () => {
163
+ for (const annotation of annotations) onRemove?.(annotation.id);
164
+ },
165
+ children: /* @__PURE__ */ jsx(XIcon, { className: "size-3.5", "aria-hidden": "true" })
166
+ }
167
+ ) : null
168
+ ]
169
+ }
170
+ ),
171
+ open ? /* @__PURE__ */ jsx(AnnotationSourceRootBridge, { triggerRef, children: /* @__PURE__ */ jsx(Suspense, { fallback: null, children: /* @__PURE__ */ jsx(
172
+ TimelineAnnotationsDialog,
173
+ {
174
+ annotations,
175
+ editable,
176
+ focusAnnotationId,
177
+ onFocusConsumed,
178
+ onUpdate,
179
+ onRemove,
180
+ onRevealSource,
181
+ triggerRef,
182
+ countLabel,
183
+ onDismiss: dismiss
184
+ }
185
+ ) }) }) : null
186
+ ] });
187
+ }
188
+
189
+ // src/components/queue-draft-policy.ts
190
+ function requestQueueDraftEdit(composer, confirmReplacement, editImmediately) {
191
+ if (composer.hasDraftContent()) {
192
+ confirmReplacement();
193
+ } else {
194
+ editImmediately();
195
+ }
196
+ }
197
+
198
+ // src/components/queue-surface-state.tsx
199
+ import { Loader2Icon, RotateCwIcon } from "lucide-react";
200
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
201
+ function EmptyQueueStateSurface({ queue }) {
202
+ const hasError = Boolean(queue.error || queue.mutationError);
203
+ return /* @__PURE__ */ jsx2(
204
+ "div",
205
+ {
206
+ className: "og-root mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6",
207
+ "data-testid": "queue-surface",
208
+ children: /* @__PURE__ */ jsxs2("div", { className: "overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm", children: [
209
+ queue.stoppingPreviousAttempt ? /* @__PURE__ */ jsx2(QueueStoppingStatus, { queue, dividerAfter: hasError }) : null,
210
+ hasError ? /* @__PURE__ */ jsx2(QueueErrorAlert, { queue }) : null
211
+ ] })
212
+ }
213
+ );
214
+ }
215
+ function QueueStoppingStatus({
216
+ queue,
217
+ dividerAfter = false
218
+ }) {
219
+ return /* @__PURE__ */ jsxs2(
220
+ "div",
221
+ {
222
+ role: "status",
223
+ "aria-live": "polite",
224
+ className: `flex min-h-11 items-center gap-2.5 bg-status-waiting/[0.07] px-3 py-2 text-og-control text-fg ${dividerAfter ? "border-b border-status-waiting/20" : ""}`,
225
+ "data-testid": "stopping-previous-attempt",
226
+ children: [
227
+ /* @__PURE__ */ jsx2(
228
+ Loader2Icon,
229
+ {
230
+ "aria-hidden": "true",
231
+ className: "size-3.5 shrink-0 animate-spin text-status-waiting motion-reduce:animate-none"
232
+ }
233
+ ),
234
+ /* @__PURE__ */ jsxs2("span", { className: "min-w-0", children: [
235
+ /* @__PURE__ */ jsx2("span", { className: "font-medium", children: queue.effectiveControl?.state === "paused" ? "Stopping current attempt\u2026" : "Stopping previous attempt\u2026" }),
236
+ " ",
237
+ /* @__PURE__ */ jsx2("span", { className: "text-fg-muted", children: queue.effectiveControl?.state === "paused" ? "Queued work stays saved until you resume." : "Queued work is saved and starts automatically." })
238
+ ] })
239
+ ]
240
+ }
241
+ );
242
+ }
243
+ function QueueErrorAlert({
244
+ queue,
245
+ dividerBefore = false
246
+ }) {
247
+ return /* @__PURE__ */ jsx2("div", { className: `${dividerBefore ? "border-t border-border" : ""} p-2`, children: /* @__PURE__ */ jsxs2(
248
+ "div",
249
+ {
250
+ role: "alert",
251
+ className: "flex min-w-0 max-w-full flex-wrap items-start gap-2 rounded-md bg-status-failed/10 px-2 py-1.5 text-og-control text-status-failed",
252
+ children: [
253
+ /* @__PURE__ */ jsx2(
254
+ "span",
255
+ {
256
+ role: "region",
257
+ "aria-label": "Queue error details",
258
+ tabIndex: 0,
259
+ className: "max-h-[min(5rem,20dvh)] min-w-0 max-w-full flex-[1_1_5rem] overflow-auto overscroll-contain whitespace-pre-wrap rounded-sm outline-hidden [overflow-wrap:anywhere] [unicode-bidi:plaintext] focus-visible:ring-2 focus-visible:ring-ring/40",
260
+ "data-testid": "queue-error-message",
261
+ dir: "auto",
262
+ children: (queue.mutationError ?? queue.error)?.message
263
+ }
264
+ ),
265
+ /* @__PURE__ */ jsx2(
266
+ "button",
267
+ {
268
+ type: "button",
269
+ onClick: () => {
270
+ queue.clearMutationError();
271
+ void queue.refresh();
272
+ },
273
+ "aria-label": "Dismiss queue error and retry",
274
+ title: "Retry loading the queue",
275
+ className: "ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-hidden transition-colors hover:bg-surface-3 focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none pointer-coarse:size-[44px]",
276
+ children: /* @__PURE__ */ jsx2(RotateCwIcon, { className: "size-3.5" })
277
+ }
278
+ )
279
+ ]
280
+ }
281
+ ) });
282
+ }
283
+
284
+ export {
285
+ TimelineAnnotationCards,
286
+ TimelineAnnotationsChip,
287
+ requestQueueDraftEdit,
288
+ EmptyQueueStateSurface,
289
+ QueueStoppingStatus,
290
+ QueueErrorAlert
291
+ };
292
+ //# sourceMappingURL=chunk-YBM6CQRU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/timeline-annotations.tsx","../src/components/queue-draft-policy.ts","../src/components/queue-surface-state.tsx"],"sourcesContent":["import type { TimelineAnnotationSource } from \"@opengeni/sdk\";\nimport { QuoteIcon, XIcon } from \"lucide-react\";\nimport {\n Suspense,\n lazy,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type ReactNode,\n type RefObject,\n} from \"react\";\nimport { cn } from \"../lib/cn\";\nimport {\n AnnotationAccentRow,\n AnnotationNotePreview,\n AnnotationQuoteSourceButton,\n type TimelineAnnotationLike,\n} from \"./timeline-annotation-chrome\";\nimport { ANNOTATION_CARD_STACK_SCROLL_AT } from \"./timeline-annotation-layout\";\nimport {\n TimelineAnnotationSourceRootContext,\n useTimelineAnnotationSourceRoot,\n} from \"./timeline-annotation-reveal-context\";\nimport {\n annotationDisplayOrdinal,\n annotationHasNote,\n resolveAnnotationRevealRoot,\n} from \"./timeline-annotation-shared\";\n\nexport type { TimelineAnnotationLike } from \"./timeline-annotation-chrome\";\n\nconst TimelineAnnotationsDialog = lazy(() => import(\"./timeline-annotations-dialog\"));\n\nfunction AnnotationSourceRootBridge({\n triggerRef,\n children,\n}: {\n triggerRef: RefObject<HTMLElement | null>;\n children: ReactNode;\n}) {\n const inheritedRoot = useTimelineAnnotationSourceRoot();\n const conversationRootRef = useRef<HTMLElement | null>(null);\n if (!inheritedRoot) {\n conversationRootRef.current = resolveAnnotationRevealRoot(triggerRef.current);\n }\n useLayoutEffect(() => {\n if (inheritedRoot) return;\n conversationRootRef.current = resolveAnnotationRevealRoot(triggerRef.current);\n });\n if (inheritedRoot) return children;\n return (\n <TimelineAnnotationSourceRootContext.Provider value={conversationRootRef}>\n {children}\n </TimelineAnnotationSourceRootContext.Provider>\n );\n}\n\nexport function TimelineAnnotationCards({\n annotations,\n onRevealSource,\n className,\n}: {\n annotations: readonly TimelineAnnotationLike[];\n onRevealSource?: ((source: TimelineAnnotationSource) => boolean) | undefined;\n className?: string | undefined;\n}) {\n const [unavailableId, setUnavailableId] = useState<string | null>(null);\n if (annotations.length === 0) return null;\n return (\n <div\n data-og-annotation-cards=\"\"\n className={cn(\n \"grid gap-2\",\n annotations.length >= ANNOTATION_CARD_STACK_SCROLL_AT &&\n \"max-h-[min(28rem,55vh)] overflow-x-hidden overflow-y-auto overscroll-contain pr-1\",\n className,\n )}\n >\n {annotations.map((annotation, index) => {\n const ordinal = annotationDisplayOrdinal(annotation, index);\n return (\n <section key={annotation.id} aria-label={`Annotation ${ordinal}`}>\n <AnnotationAccentRow>\n <p className=\"mb-0.5 text-og-xs font-medium tabular-nums text-og-fg-subtle\">\n Annotation {ordinal}\n </p>\n <AnnotationQuoteSourceButton\n annotation={annotation}\n lines={2}\n onRevealSource={onRevealSource}\n onUnavailable={setUnavailableId}\n />\n {unavailableId === annotation.id ? (\n <p role=\"status\" className=\"text-og-xs text-og-status-waiting\">\n Source is outside the loaded timeline window.\n </p>\n ) : null}\n <AnnotationNotePreview\n note={annotation.note}\n annotationId={annotation.id}\n ordinal={ordinal}\n />\n </AnnotationAccentRow>\n </section>\n );\n })}\n </div>\n );\n}\n\nexport function TimelineAnnotationsChip({\n annotations,\n editable = false,\n focusAnnotationId,\n onFocusConsumed,\n onUpdate,\n onRemove,\n onRevealSource,\n className,\n}: {\n annotations: readonly TimelineAnnotationLike[];\n editable?: boolean | undefined;\n focusAnnotationId?: string | null | undefined;\n onFocusConsumed?: (() => void) | undefined;\n onUpdate?: ((id: string, note: string) => void) | undefined;\n onRemove?: ((id: string) => void) | undefined;\n onRevealSource?: ((source: TimelineAnnotationSource) => boolean) | undefined;\n className?: string | undefined;\n}) {\n const focusRequested = Boolean(\n focusAnnotationId && annotations.some((item) => item.id === focusAnnotationId),\n );\n const [open, setOpen] = useState(focusRequested);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const openedFocusId = useRef<string | null>(focusRequested ? (focusAnnotationId ?? null) : null);\n\n useEffect(() => {\n if (!focusRequested || !focusAnnotationId) {\n if (!focusRequested) openedFocusId.current = null;\n return;\n }\n if (openedFocusId.current === focusAnnotationId) return;\n openedFocusId.current = focusAnnotationId;\n setOpen(true);\n }, [focusAnnotationId, focusRequested]);\n\n if (annotations.length === 0) return null;\n const countLabel = `${annotations.length} ${annotations.length === 1 ? \"annotation\" : \"annotations\"}`;\n const incomplete = annotations.some((annotation) => !annotationHasNote(annotation.note));\n const canClear = Boolean(editable && onRemove);\n\n const dismiss = (restoreFocus: boolean) => {\n setOpen(false);\n onFocusConsumed?.();\n if (restoreFocus) triggerRef.current?.focus();\n };\n\n return (\n <span className={cn(\"inline-flex max-w-full items-center\", className)}>\n <span\n className={cn(\n \"inline-flex max-w-full items-center rounded-full border bg-og-surface-1 text-og-fg-muted\",\n incomplete ? \"border-og-accent/45 bg-og-accent-soft/50\" : \"border-og-border\",\n )}\n >\n <button\n ref={triggerRef}\n type=\"button\"\n className={cn(\n \"inline-flex min-h-8 min-w-0 max-w-full items-center gap-1.5 rounded-full border-0 bg-transparent py-1 text-og-sm font-medium outline-hidden transition hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]\",\n canClear ? \"pr-1 pl-2.5\" : \"px-2.5\",\n )}\n aria-label={`Review ${countLabel}`}\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n onClick={() => setOpen((current) => !current)}\n >\n <QuoteIcon className=\"size-3.5 shrink-0 text-og-accent\" aria-hidden=\"true\" />\n <span className=\"min-w-0 truncate\">{countLabel}</span>\n </button>\n {canClear ? (\n <button\n type=\"button\"\n className=\"inline-flex size-7 shrink-0 items-center justify-center rounded-full border-0 bg-transparent text-og-fg-subtle outline-hidden hover:text-og-status-failed focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:size-11\"\n aria-label=\"Remove all annotations\"\n onClick={() => {\n for (const annotation of annotations) onRemove?.(annotation.id);\n }}\n >\n <XIcon className=\"size-3.5\" aria-hidden=\"true\" />\n </button>\n ) : null}\n </span>\n {open ? (\n <AnnotationSourceRootBridge triggerRef={triggerRef}>\n <Suspense fallback={null}>\n <TimelineAnnotationsDialog\n annotations={annotations}\n editable={editable}\n focusAnnotationId={focusAnnotationId}\n onFocusConsumed={onFocusConsumed}\n onUpdate={onUpdate}\n onRemove={onRemove}\n onRevealSource={onRevealSource}\n triggerRef={triggerRef}\n countLabel={countLabel}\n onDismiss={dismiss}\n />\n </Suspense>\n </AnnotationSourceRootBridge>\n ) : null}\n </span>\n );\n}\n\nexport default TimelineAnnotationsChip;\n","import type { ComposerState } from \"../hooks/use-composer\";\n\n/**\n * Decide whether checking out a queued prompt would replace current composer\n * content. `hasDraftContent` reads the synchronous draft refs, so this stays\n * correct even when a controlled input update has not rendered yet.\n */\nexport function requestQueueDraftEdit(\n composer: Pick<ComposerState, \"hasDraftContent\">,\n confirmReplacement: () => void,\n editImmediately: () => void,\n): void {\n if (composer.hasDraftContent()) {\n confirmReplacement();\n } else {\n editImmediately();\n }\n}\n","import { Loader2Icon, RotateCwIcon } from \"lucide-react\";\n\nimport type { UseTurnQueueResult } from \"../hooks/use-turn-queue\";\n\ntype QueueStateProps = {\n queue: UseTurnQueueResult;\n};\n\nexport function EmptyQueueStateSurface({ queue }: QueueStateProps) {\n const hasError = Boolean(queue.error || queue.mutationError);\n return (\n <div\n className=\"og-root mx-auto mb-2 w-full max-w-3xl shrink-0 px-4 sm:px-6\"\n data-testid=\"queue-surface\"\n >\n <div className=\"overflow-hidden rounded-lg border border-border bg-surface/80 shadow-sm\">\n {queue.stoppingPreviousAttempt ? (\n <QueueStoppingStatus queue={queue} dividerAfter={hasError} />\n ) : null}\n {hasError ? <QueueErrorAlert queue={queue} /> : null}\n </div>\n </div>\n );\n}\n\nexport function QueueStoppingStatus({\n queue,\n dividerAfter = false,\n}: QueueStateProps & { dividerAfter?: boolean }) {\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className={`flex min-h-11 items-center gap-2.5 bg-status-waiting/[0.07] px-3 py-2 text-og-control text-fg ${\n dividerAfter ? \"border-b border-status-waiting/20\" : \"\"\n }`}\n data-testid=\"stopping-previous-attempt\"\n >\n <Loader2Icon\n aria-hidden=\"true\"\n className=\"size-3.5 shrink-0 animate-spin text-status-waiting motion-reduce:animate-none\"\n />\n <span className=\"min-w-0\">\n <span className=\"font-medium\">\n {queue.effectiveControl?.state === \"paused\"\n ? \"Stopping current attempt…\"\n : \"Stopping previous attempt…\"}\n </span>{\" \"}\n <span className=\"text-fg-muted\">\n {queue.effectiveControl?.state === \"paused\"\n ? \"Queued work stays saved until you resume.\"\n : \"Queued work is saved and starts automatically.\"}\n </span>\n </span>\n </div>\n );\n}\n\nexport function QueueErrorAlert({\n queue,\n dividerBefore = false,\n}: QueueStateProps & { dividerBefore?: boolean }) {\n return (\n <div className={`${dividerBefore ? \"border-t border-border\" : \"\"} p-2`}>\n <div\n role=\"alert\"\n className=\"flex min-w-0 max-w-full flex-wrap items-start gap-2 rounded-md bg-status-failed/10 px-2 py-1.5 text-og-control text-status-failed\"\n >\n <span\n role=\"region\"\n aria-label=\"Queue error details\"\n tabIndex={0}\n className=\"max-h-[min(5rem,20dvh)] min-w-0 max-w-full flex-[1_1_5rem] overflow-auto overscroll-contain whitespace-pre-wrap rounded-sm outline-hidden [overflow-wrap:anywhere] [unicode-bidi:plaintext] focus-visible:ring-2 focus-visible:ring-ring/40\"\n data-testid=\"queue-error-message\"\n dir=\"auto\"\n >\n {(queue.mutationError ?? queue.error)?.message}\n </span>\n <button\n type=\"button\"\n onClick={() => {\n queue.clearMutationError();\n void queue.refresh();\n }}\n aria-label=\"Dismiss queue error and retry\"\n title=\"Retry loading the queue\"\n className=\"ms-auto inline-flex size-7 shrink-0 items-center justify-center self-start rounded-md outline-hidden transition-colors hover:bg-surface-3 focus-visible:ring-2 focus-visible:ring-ring/40 motion-reduce:transition-none pointer-coarse:size-[44px]\"\n >\n <RotateCwIcon className=\"size-3.5\" />\n </button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs"]}