@opengeni/react 3.7.0-canary.7 → 3.8.0-canary.1
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 +6 -0
- package/dist/chat.js +1 -1
- package/dist/chunk-5M6VTFJ5.js +171 -0
- package/dist/chunk-5M6VTFJ5.js.map +1 -0
- package/dist/{chunk-IOLVN74D.js → chunk-6J56T3MG.js} +15 -1
- package/dist/chunk-6J56T3MG.js.map +1 -0
- package/dist/{chunk-BQGIXRKV.js → chunk-7BWFU6H4.js} +22 -4
- package/dist/chunk-7BWFU6H4.js.map +1 -0
- package/dist/{chunk-3HIF5IFC.js → chunk-7W6PVVTK.js} +63 -18
- package/dist/chunk-7W6PVVTK.js.map +1 -0
- package/dist/{chunk-ZFOFY5ST.js → chunk-NLTS7JHI.js} +16 -31
- package/dist/chunk-NLTS7JHI.js.map +1 -0
- package/dist/chunk-NOSYBS2D.js +208 -0
- package/dist/chunk-NOSYBS2D.js.map +1 -0
- package/dist/{chunk-F2CFHN3Y.js → chunk-YAIPFO5D.js} +2 -1
- package/dist/chunk-YAIPFO5D.js.map +1 -0
- package/dist/chunk-YBM6CQRU.js +292 -0
- package/dist/chunk-YBM6CQRU.js.map +1 -0
- package/dist/chunk-ZYRGEKWS.js +216 -0
- package/dist/chunk-ZYRGEKWS.js.map +1 -0
- package/dist/components/composer.d.ts +4 -2
- package/dist/components/message-timeline.d.ts +9 -2
- package/dist/components/timeline-annotation-chrome.d.ts +25 -0
- package/dist/components/timeline-annotation-layout.d.ts +42 -0
- package/dist/components/timeline-annotation-markers.d.ts +8 -0
- package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
- package/dist/components/timeline-annotation-shared.d.ts +31 -0
- package/dist/components/timeline-annotations-dialog.d.ts +1 -1
- package/dist/components/timeline-annotations.d.ts +8 -2
- package/dist/composer.js +2 -2
- package/dist/hooks/use-composer.d.ts +2 -0
- package/dist/index.js +9 -6
- package/dist/index.js.map +1 -1
- package/dist/interaction.js +6 -6
- package/dist/machines.js +1 -1
- package/dist/{queue-surface-implementation-XL2A6PBM.js → queue-surface-implementation-LK3S4BIW.js} +5 -2
- package/dist/{queue-surface-implementation-XL2A6PBM.js.map → queue-surface-implementation-LK3S4BIW.js.map} +1 -1
- package/dist/session-ui.js +8 -5
- package/dist/session.js +1 -1
- package/dist/timeline-annotation-markers-DRSTLEM6.js +165 -0
- package/dist/timeline-annotation-markers-DRSTLEM6.js.map +1 -0
- package/dist/timeline-annotation-selection-IHLUGVND.js +236 -0
- package/dist/timeline-annotation-selection-IHLUGVND.js.map +1 -0
- package/dist/timeline-annotations-dialog-6Q53N5FG.js +262 -0
- package/dist/timeline-annotations-dialog-6Q53N5FG.js.map +1 -0
- package/package.json +2 -2
- package/src/components/chat-composer.tsx +5 -2
- package/src/components/composer.tsx +40 -5
- package/src/components/copy-button.tsx +1 -0
- package/src/components/machines-dashboard.tsx +1 -16
- package/src/components/message-timeline.tsx +357 -297
- package/src/components/timeline-annotation-chrome.tsx +183 -0
- package/src/components/timeline-annotation-layout.ts +268 -0
- package/src/components/timeline-annotation-markers.tsx +185 -0
- package/src/components/timeline-annotation-reveal-context.ts +9 -0
- package/src/components/timeline-annotation-selection.tsx +99 -54
- package/src/components/timeline-annotation-shared.ts +245 -0
- package/src/components/timeline-annotations-dialog.tsx +172 -128
- package/src/components/timeline-annotations.tsx +178 -45
- package/src/hooks/use-composer.ts +17 -0
- package/styles/compiled.css +86 -22
- package/dist/chunk-3HIF5IFC.js.map +0 -1
- package/dist/chunk-BQGIXRKV.js.map +0 -1
- package/dist/chunk-F2CFHN3Y.js.map +0 -1
- package/dist/chunk-IOLVN74D.js.map +0 -1
- package/dist/chunk-W3OUAH6M.js +0 -170
- package/dist/chunk-W3OUAH6M.js.map +0 -1
- package/dist/chunk-ZFOFY5ST.js.map +0 -1
- package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
- package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
- package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
- package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
// src/components/timeline-annotation-selection.tsx
|
|
2
|
-
import { useEffect, useRef, useState } from "react";
|
|
3
|
-
import { createPortal } from "react-dom";
|
|
4
|
-
import { jsx } from "react/jsx-runtime";
|
|
5
|
-
var INTERACTIVE_SELECTOR = 'a,button,input,textarea,select,summary,[role="button"],[contenteditable="true"],[tabindex]:not([tabindex="-1"])';
|
|
6
|
-
var SOURCE_CONTEXT_BYTES = 160;
|
|
7
|
-
var MAX_QUOTE_BYTES = 16 * 1024;
|
|
8
|
-
function utf8Prefix(value, maxBytes) {
|
|
9
|
-
let output = "";
|
|
10
|
-
let bytes = 0;
|
|
11
|
-
for (const character of value) {
|
|
12
|
-
const next = new TextEncoder().encode(character).byteLength;
|
|
13
|
-
if (bytes + next > maxBytes) break;
|
|
14
|
-
output += character;
|
|
15
|
-
bytes += next;
|
|
16
|
-
}
|
|
17
|
-
return output;
|
|
18
|
-
}
|
|
19
|
-
function utf8Suffix(value, maxBytes) {
|
|
20
|
-
let output = "";
|
|
21
|
-
let bytes = 0;
|
|
22
|
-
for (const character of [...value].reverse()) {
|
|
23
|
-
const next = new TextEncoder().encode(character).byteLength;
|
|
24
|
-
if (bytes + next > maxBytes) break;
|
|
25
|
-
output = character + output;
|
|
26
|
-
bytes += next;
|
|
27
|
-
}
|
|
28
|
-
return output;
|
|
29
|
-
}
|
|
30
|
-
function selectionElement(node) {
|
|
31
|
-
return node instanceof Element ? node : node?.parentElement ?? null;
|
|
32
|
-
}
|
|
33
|
-
function containingSource(node) {
|
|
34
|
-
const element = selectionElement(node);
|
|
35
|
-
const source = element?.closest("[data-og-annotation-source-key]");
|
|
36
|
-
return source instanceof HTMLElement ? source : null;
|
|
37
|
-
}
|
|
38
|
-
function isInteractiveSelection(node, boundary) {
|
|
39
|
-
const element = selectionElement(node);
|
|
40
|
-
const interactive = element?.closest(INTERACTIVE_SELECTOR);
|
|
41
|
-
return interactive instanceof Element && boundary.contains(interactive);
|
|
42
|
-
}
|
|
43
|
-
function occurrenceOffsets(text, quote) {
|
|
44
|
-
const offsets = [];
|
|
45
|
-
let cursor = 0;
|
|
46
|
-
while (cursor <= text.length - quote.length) {
|
|
47
|
-
const offset = text.indexOf(quote, cursor);
|
|
48
|
-
if (offset < 0) break;
|
|
49
|
-
offsets.push(offset);
|
|
50
|
-
cursor = offset + 1;
|
|
51
|
-
}
|
|
52
|
-
return offsets;
|
|
53
|
-
}
|
|
54
|
-
function selectedOccurrence(boundary, range, quote) {
|
|
55
|
-
try {
|
|
56
|
-
const prefix = range.cloneRange();
|
|
57
|
-
prefix.selectNodeContents(boundary);
|
|
58
|
-
prefix.setEnd(range.startContainer, range.startOffset);
|
|
59
|
-
return occurrenceOffsets(prefix.toString(), quote).length;
|
|
60
|
-
} catch {
|
|
61
|
-
return 0;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function annotationId() {
|
|
65
|
-
if (typeof globalThis.crypto?.randomUUID === "function") {
|
|
66
|
-
return globalThis.crypto.randomUUID();
|
|
67
|
-
}
|
|
68
|
-
return `annotation-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
69
|
-
}
|
|
70
|
-
function buildCandidate(root, sources, keyboard) {
|
|
71
|
-
const selection = document.getSelection();
|
|
72
|
-
if (!selection || selection.rangeCount !== 1 || selection.isCollapsed) return null;
|
|
73
|
-
const range = selection.getRangeAt(0);
|
|
74
|
-
const startBoundary = containingSource(range.startContainer);
|
|
75
|
-
const endBoundary = containingSource(range.endContainer);
|
|
76
|
-
if (!startBoundary || startBoundary !== endBoundary || !root.contains(startBoundary)) return null;
|
|
77
|
-
if (isInteractiveSelection(range.startContainer, startBoundary) || isInteractiveSelection(range.endContainer, startBoundary)) {
|
|
78
|
-
return null;
|
|
79
|
-
}
|
|
80
|
-
const sourceKey = startBoundary.dataset.ogAnnotationSourceKey;
|
|
81
|
-
const source = sourceKey ? sources.get(sourceKey) : void 0;
|
|
82
|
-
const quote = selection.toString();
|
|
83
|
-
if (!source || quote.trim().length === 0 || new TextEncoder().encode(quote).byteLength > MAX_QUOTE_BYTES) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
const sourceOffsets = occurrenceOffsets(source.text, quote);
|
|
87
|
-
if (sourceOffsets.length === 0) return null;
|
|
88
|
-
const occurrence = selectedOccurrence(startBoundary, range, quote);
|
|
89
|
-
const startOffset = sourceOffsets[Math.min(occurrence, sourceOffsets.length - 1)];
|
|
90
|
-
const endOffset = startOffset + quote.length;
|
|
91
|
-
const rect = range.getBoundingClientRect();
|
|
92
|
-
if (rect.width === 0 && rect.height === 0) return null;
|
|
93
|
-
return {
|
|
94
|
-
annotation: {
|
|
95
|
-
id: annotationId(),
|
|
96
|
-
quote,
|
|
97
|
-
note: "",
|
|
98
|
-
source: {
|
|
99
|
-
kind: source.kind,
|
|
100
|
-
eventId: source.eventId,
|
|
101
|
-
eventType: source.eventType,
|
|
102
|
-
sequence: source.sequence,
|
|
103
|
-
turnId: source.turnId,
|
|
104
|
-
startOffset,
|
|
105
|
-
endOffset,
|
|
106
|
-
contextBefore: utf8Suffix(source.text.slice(0, startOffset), SOURCE_CONTEXT_BYTES),
|
|
107
|
-
contextAfter: utf8Prefix(source.text.slice(endOffset), SOURCE_CONTEXT_BYTES),
|
|
108
|
-
...source.label ? { label: source.label } : {}
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
left: Math.min(Math.max(12, rect.left + rect.width / 2), window.innerWidth - 12),
|
|
112
|
-
top: rect.bottom + 48 <= window.innerHeight ? rect.bottom + 8 : Math.max(12, rect.top - 40),
|
|
113
|
-
keyboard
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
function TimelineAnnotationSelection({
|
|
117
|
-
rootRef,
|
|
118
|
-
sources,
|
|
119
|
-
onAnnotate
|
|
120
|
-
}) {
|
|
121
|
-
const [candidate, setCandidate] = useState(null);
|
|
122
|
-
const buttonRef = useRef(null);
|
|
123
|
-
useEffect(() => {
|
|
124
|
-
const root = rootRef.current;
|
|
125
|
-
if (!root || !onAnnotate) {
|
|
126
|
-
setCandidate(null);
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
const update = (keyboard) => {
|
|
130
|
-
setCandidate(buildCandidate(root, sources, keyboard));
|
|
131
|
-
};
|
|
132
|
-
const onPointerUp = () => window.setTimeout(() => update(false), 0);
|
|
133
|
-
const onKeyUp = (event) => {
|
|
134
|
-
if (event.key === "Escape") {
|
|
135
|
-
setCandidate(null);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
window.setTimeout(() => update(true), 0);
|
|
139
|
-
};
|
|
140
|
-
const onPointerDown = (event) => {
|
|
141
|
-
if (candidate && !(event.target instanceof Node && buttonRef.current?.contains(event.target))) {
|
|
142
|
-
setCandidate(null);
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
const onDocumentKeyDown = (event) => {
|
|
146
|
-
if (event.key === "Escape") setCandidate(null);
|
|
147
|
-
};
|
|
148
|
-
root.addEventListener("pointerup", onPointerUp);
|
|
149
|
-
root.addEventListener("keyup", onKeyUp);
|
|
150
|
-
document.addEventListener("pointerdown", onPointerDown);
|
|
151
|
-
document.addEventListener("keydown", onDocumentKeyDown);
|
|
152
|
-
return () => {
|
|
153
|
-
root.removeEventListener("pointerup", onPointerUp);
|
|
154
|
-
root.removeEventListener("keyup", onKeyUp);
|
|
155
|
-
document.removeEventListener("pointerdown", onPointerDown);
|
|
156
|
-
document.removeEventListener("keydown", onDocumentKeyDown);
|
|
157
|
-
};
|
|
158
|
-
}, [candidate, onAnnotate, rootRef, sources]);
|
|
159
|
-
useEffect(() => {
|
|
160
|
-
if (candidate?.keyboard) buttonRef.current?.focus();
|
|
161
|
-
}, [candidate]);
|
|
162
|
-
if (!candidate || !onAnnotate || typeof document === "undefined") return null;
|
|
163
|
-
return createPortal(
|
|
164
|
-
/* @__PURE__ */ jsx(
|
|
165
|
-
"button",
|
|
166
|
-
{
|
|
167
|
-
ref: buttonRef,
|
|
168
|
-
type: "button",
|
|
169
|
-
style: { left: candidate.left, top: candidate.top },
|
|
170
|
-
className: "og-root fixed z-[80] -translate-x-1/2 rounded-full border border-og-border bg-og-surface-1 px-3 py-1.5 text-og-sm font-medium text-og-fg shadow-lg outline-hidden transition hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]",
|
|
171
|
-
onClick: () => {
|
|
172
|
-
onAnnotate(candidate.annotation);
|
|
173
|
-
document.getSelection()?.removeAllRanges();
|
|
174
|
-
setCandidate(null);
|
|
175
|
-
},
|
|
176
|
-
children: "Annotate"
|
|
177
|
-
}
|
|
178
|
-
),
|
|
179
|
-
document.body
|
|
180
|
-
);
|
|
181
|
-
}
|
|
182
|
-
var timeline_annotation_selection_default = TimelineAnnotationSelection;
|
|
183
|
-
export {
|
|
184
|
-
TimelineAnnotationSelection,
|
|
185
|
-
timeline_annotation_selection_default as default
|
|
186
|
-
};
|
|
187
|
-
//# sourceMappingURL=timeline-annotation-selection-3L7LHGG2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/timeline-annotation-selection.tsx"],"sourcesContent":["import type { DraftTimelineAnnotation } from \"@opengeni/sdk\";\nimport { useEffect, useRef, useState, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { TimelineAnnotationSourceDescriptor } from \"../timeline\";\n\ntype SelectionCandidate = {\n annotation: DraftTimelineAnnotation;\n left: number;\n top: number;\n keyboard: boolean;\n};\n\nconst INTERACTIVE_SELECTOR =\n 'a,button,input,textarea,select,summary,[role=\"button\"],[contenteditable=\"true\"],[tabindex]:not([tabindex=\"-1\"])';\nconst SOURCE_CONTEXT_BYTES = 160;\nconst MAX_QUOTE_BYTES = 16 * 1024;\n\nfunction utf8Prefix(value: string, maxBytes: number): string {\n let output = \"\";\n let bytes = 0;\n for (const character of value) {\n const next = new TextEncoder().encode(character).byteLength;\n if (bytes + next > maxBytes) break;\n output += character;\n bytes += next;\n }\n return output;\n}\n\nfunction utf8Suffix(value: string, maxBytes: number): string {\n let output = \"\";\n let bytes = 0;\n for (const character of [...value].reverse()) {\n const next = new TextEncoder().encode(character).byteLength;\n if (bytes + next > maxBytes) break;\n output = character + output;\n bytes += next;\n }\n return output;\n}\n\nfunction selectionElement(node: Node | null): Element | null {\n return node instanceof Element ? node : (node?.parentElement ?? null);\n}\n\nfunction containingSource(node: Node | null): HTMLElement | null {\n const element = selectionElement(node);\n const source = element?.closest(\"[data-og-annotation-source-key]\");\n return source instanceof HTMLElement ? source : null;\n}\n\nfunction isInteractiveSelection(node: Node | null, boundary: HTMLElement): boolean {\n const element = selectionElement(node);\n const interactive = element?.closest(INTERACTIVE_SELECTOR);\n return interactive instanceof Element && boundary.contains(interactive);\n}\n\nfunction occurrenceOffsets(text: string, quote: string): number[] {\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 selectedOccurrence(boundary: HTMLElement, range: Range, quote: string): number {\n try {\n const prefix = range.cloneRange();\n prefix.selectNodeContents(boundary);\n prefix.setEnd(range.startContainer, range.startOffset);\n return occurrenceOffsets(prefix.toString(), quote).length;\n } catch {\n return 0;\n }\n}\n\nfunction annotationId(): string {\n if (typeof globalThis.crypto?.randomUUID === \"function\") {\n return globalThis.crypto.randomUUID();\n }\n return `annotation-${Date.now()}-${Math.random().toString(16).slice(2)}`;\n}\n\nfunction buildCandidate(\n root: HTMLElement,\n sources: ReadonlyMap<string, TimelineAnnotationSourceDescriptor>,\n keyboard: boolean,\n): SelectionCandidate | null {\n const selection = document.getSelection();\n if (!selection || selection.rangeCount !== 1 || selection.isCollapsed) return null;\n const range = selection.getRangeAt(0);\n const startBoundary = containingSource(range.startContainer);\n const endBoundary = containingSource(range.endContainer);\n if (!startBoundary || startBoundary !== endBoundary || !root.contains(startBoundary)) return null;\n if (\n isInteractiveSelection(range.startContainer, startBoundary) ||\n isInteractiveSelection(range.endContainer, startBoundary)\n ) {\n return null;\n }\n const sourceKey = startBoundary.dataset.ogAnnotationSourceKey;\n const source = sourceKey ? sources.get(sourceKey) : undefined;\n const quote = selection.toString();\n if (\n !source ||\n quote.trim().length === 0 ||\n new TextEncoder().encode(quote).byteLength > MAX_QUOTE_BYTES\n ) {\n return null;\n }\n const sourceOffsets = occurrenceOffsets(source.text, quote);\n if (sourceOffsets.length === 0) return null;\n const occurrence = selectedOccurrence(startBoundary, range, quote);\n const startOffset = sourceOffsets[Math.min(occurrence, sourceOffsets.length - 1)]!;\n const endOffset = startOffset + quote.length;\n const rect = range.getBoundingClientRect();\n if (rect.width === 0 && rect.height === 0) return null;\n return {\n annotation: {\n id: annotationId(),\n quote,\n note: \"\",\n source: {\n kind: source.kind,\n eventId: source.eventId,\n eventType: source.eventType,\n sequence: source.sequence,\n turnId: source.turnId,\n startOffset,\n endOffset,\n contextBefore: utf8Suffix(source.text.slice(0, startOffset), SOURCE_CONTEXT_BYTES),\n contextAfter: utf8Prefix(source.text.slice(endOffset), SOURCE_CONTEXT_BYTES),\n ...(source.label ? { label: source.label } : {}),\n },\n },\n left: Math.min(Math.max(12, rect.left + rect.width / 2), window.innerWidth - 12),\n top: rect.bottom + 48 <= window.innerHeight ? rect.bottom + 8 : Math.max(12, rect.top - 40),\n keyboard,\n };\n}\n\nexport function TimelineAnnotationSelection({\n rootRef,\n sources,\n onAnnotate,\n}: {\n rootRef: RefObject<HTMLElement | null>;\n sources: ReadonlyMap<string, TimelineAnnotationSourceDescriptor>;\n onAnnotate?: ((annotation: DraftTimelineAnnotation) => void) | undefined;\n}) {\n const [candidate, setCandidate] = useState<SelectionCandidate | null>(null);\n const buttonRef = useRef<HTMLButtonElement | null>(null);\n\n useEffect(() => {\n const root = rootRef.current;\n if (!root || !onAnnotate) {\n setCandidate(null);\n return;\n }\n const update = (keyboard: boolean) => {\n setCandidate(buildCandidate(root, sources, keyboard));\n };\n const onPointerUp = () => window.setTimeout(() => update(false), 0);\n const onKeyUp = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setCandidate(null);\n return;\n }\n window.setTimeout(() => update(true), 0);\n };\n const onPointerDown = (event: PointerEvent) => {\n if (\n candidate &&\n !(event.target instanceof Node && buttonRef.current?.contains(event.target))\n ) {\n setCandidate(null);\n }\n };\n const onDocumentKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") setCandidate(null);\n };\n root.addEventListener(\"pointerup\", onPointerUp);\n root.addEventListener(\"keyup\", onKeyUp);\n document.addEventListener(\"pointerdown\", onPointerDown);\n document.addEventListener(\"keydown\", onDocumentKeyDown);\n return () => {\n root.removeEventListener(\"pointerup\", onPointerUp);\n root.removeEventListener(\"keyup\", onKeyUp);\n document.removeEventListener(\"pointerdown\", onPointerDown);\n document.removeEventListener(\"keydown\", onDocumentKeyDown);\n };\n }, [candidate, onAnnotate, rootRef, sources]);\n\n useEffect(() => {\n if (candidate?.keyboard) buttonRef.current?.focus();\n }, [candidate]);\n\n if (!candidate || !onAnnotate || typeof document === \"undefined\") return null;\n return createPortal(\n <button\n ref={buttonRef}\n type=\"button\"\n style={{ left: candidate.left, top: candidate.top }}\n className=\"og-root fixed z-[80] -translate-x-1/2 rounded-full border border-og-border bg-og-surface-1 px-3 py-1.5 text-og-sm font-medium text-og-fg shadow-lg outline-hidden transition hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]\"\n onClick={() => {\n onAnnotate(candidate.annotation);\n document.getSelection()?.removeAllRanges();\n setCandidate(null);\n }}\n >\n Annotate\n </button>,\n document.body,\n );\n}\n\nexport default TimelineAnnotationSelection;\n"],"mappings":"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","names":[]}
|
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
// src/components/timeline-annotations-dialog.tsx
|
|
2
|
-
import { useEffect, useLayoutEffect, useRef, useState } from "react";
|
|
3
|
-
import { createPortal } from "react-dom";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
function cssEscapeAttribute(value) {
|
|
6
|
-
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") return CSS.escape(value);
|
|
7
|
-
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
8
|
-
}
|
|
9
|
-
function revealLoadedSource(source) {
|
|
10
|
-
if (typeof document === "undefined") return false;
|
|
11
|
-
const element = document.querySelector(
|
|
12
|
-
`[data-og-annotation-source-key="${cssEscapeAttribute(source.eventId)}"]`
|
|
13
|
-
);
|
|
14
|
-
if (!(element instanceof HTMLElement)) return false;
|
|
15
|
-
element.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
16
|
-
element.animate?.(
|
|
17
|
-
[
|
|
18
|
-
{ outline: "2px solid color-mix(in srgb, currentColor 55%, transparent)" },
|
|
19
|
-
{ outline: "2px solid transparent" }
|
|
20
|
-
],
|
|
21
|
-
{ duration: 1600, easing: "ease-out" }
|
|
22
|
-
);
|
|
23
|
-
return true;
|
|
24
|
-
}
|
|
25
|
-
function sourceLabel(annotation) {
|
|
26
|
-
if (annotation.source.label) return annotation.source.label;
|
|
27
|
-
switch (annotation.source.kind) {
|
|
28
|
-
case "user_message":
|
|
29
|
-
return "User message";
|
|
30
|
-
case "assistant_message":
|
|
31
|
-
return "Assistant message";
|
|
32
|
-
case "tool_output":
|
|
33
|
-
return "Tool output";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
function TimelineAnnotationsDialog({
|
|
37
|
-
annotations,
|
|
38
|
-
editable,
|
|
39
|
-
focusAnnotationId,
|
|
40
|
-
onFocusConsumed,
|
|
41
|
-
onUpdate,
|
|
42
|
-
onRemove,
|
|
43
|
-
onRevealSource,
|
|
44
|
-
triggerRef,
|
|
45
|
-
countLabel,
|
|
46
|
-
onDismiss
|
|
47
|
-
}) {
|
|
48
|
-
const [unavailableId, setUnavailableId] = useState(null);
|
|
49
|
-
const [position, setPosition] = useState({ left: 12, top: 12, above: false });
|
|
50
|
-
const panelRef = useRef(null);
|
|
51
|
-
const noteRefs = useRef(/* @__PURE__ */ new Map());
|
|
52
|
-
useLayoutEffect(() => {
|
|
53
|
-
if (!focusAnnotationId) return;
|
|
54
|
-
const note = noteRefs.current.get(focusAnnotationId);
|
|
55
|
-
note?.focus();
|
|
56
|
-
if (note && document.activeElement === note) onFocusConsumed?.();
|
|
57
|
-
}, [focusAnnotationId, onFocusConsumed]);
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
const updatePosition = () => {
|
|
60
|
-
const rect = triggerRef.current?.getBoundingClientRect();
|
|
61
|
-
if (!rect) return;
|
|
62
|
-
const panelWidth = Math.min(400, window.innerWidth - 24);
|
|
63
|
-
const left = Math.min(
|
|
64
|
-
Math.max(12, rect.left),
|
|
65
|
-
Math.max(12, window.innerWidth - panelWidth - 12)
|
|
66
|
-
);
|
|
67
|
-
const above = rect.top > Math.min(360, window.innerHeight * 0.55);
|
|
68
|
-
setPosition({ left, top: above ? rect.top - 8 : rect.bottom + 8, above });
|
|
69
|
-
};
|
|
70
|
-
const onKeyDown = (event) => {
|
|
71
|
-
if (event.key === "Escape") onDismiss(true);
|
|
72
|
-
};
|
|
73
|
-
const onPointerDown = (event) => {
|
|
74
|
-
if (!(event.target instanceof Node)) return;
|
|
75
|
-
if (panelRef.current?.contains(event.target) || triggerRef.current?.contains(event.target)) {
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
onDismiss(false);
|
|
79
|
-
};
|
|
80
|
-
updatePosition();
|
|
81
|
-
window.addEventListener("resize", updatePosition);
|
|
82
|
-
window.addEventListener("scroll", updatePosition, true);
|
|
83
|
-
document.addEventListener("keydown", onKeyDown);
|
|
84
|
-
document.addEventListener("pointerdown", onPointerDown);
|
|
85
|
-
if (!focusAnnotationId) {
|
|
86
|
-
window.setTimeout(() => {
|
|
87
|
-
if (document.activeElement === triggerRef.current) panelRef.current?.focus();
|
|
88
|
-
}, 0);
|
|
89
|
-
}
|
|
90
|
-
return () => {
|
|
91
|
-
window.removeEventListener("resize", updatePosition);
|
|
92
|
-
window.removeEventListener("scroll", updatePosition, true);
|
|
93
|
-
document.removeEventListener("keydown", onKeyDown);
|
|
94
|
-
document.removeEventListener("pointerdown", onPointerDown);
|
|
95
|
-
};
|
|
96
|
-
}, [focusAnnotationId, onDismiss, triggerRef]);
|
|
97
|
-
if (typeof document === "undefined") return null;
|
|
98
|
-
return createPortal(
|
|
99
|
-
/* @__PURE__ */ jsxs(
|
|
100
|
-
"div",
|
|
101
|
-
{
|
|
102
|
-
ref: panelRef,
|
|
103
|
-
role: "dialog",
|
|
104
|
-
tabIndex: -1,
|
|
105
|
-
style: {
|
|
106
|
-
left: position.left,
|
|
107
|
-
top: position.top,
|
|
108
|
-
transform: position.above ? "translateY(-100%)" : void 0
|
|
109
|
-
},
|
|
110
|
-
className: "og-root fixed z-[75] box-border max-h-[min(32rem,70vh)] w-[min(25rem,calc(100vw-1.5rem))] overflow-y-auto rounded-og-lg border border-og-border bg-og-surface-1 p-3 text-og-fg shadow-xl outline-hidden",
|
|
111
|
-
"aria-label": editable ? "Review timeline annotations" : "Timeline annotations",
|
|
112
|
-
children: [
|
|
113
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [
|
|
114
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
115
|
-
/* @__PURE__ */ jsx("p", { className: "text-og-sm font-semibold", children: countLabel }),
|
|
116
|
-
/* @__PURE__ */ jsx("p", { className: "text-og-xs text-og-fg-subtle", children: editable ? "Add a note for each quoted source." : "Sent with this message." })
|
|
117
|
-
] }),
|
|
118
|
-
/* @__PURE__ */ jsx(
|
|
119
|
-
"button",
|
|
120
|
-
{
|
|
121
|
-
type: "button",
|
|
122
|
-
className: "rounded-md border-0 bg-transparent px-2 py-1 text-og-xs text-og-fg outline-hidden hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]",
|
|
123
|
-
onClick: () => onDismiss(true),
|
|
124
|
-
children: "Close"
|
|
125
|
-
}
|
|
126
|
-
)
|
|
127
|
-
] }),
|
|
128
|
-
/* @__PURE__ */ jsx("div", { className: "grid gap-2.5", children: annotations.map((annotation, index) => /* @__PURE__ */ jsxs(
|
|
129
|
-
"section",
|
|
130
|
-
{
|
|
131
|
-
className: "rounded-og-md border border-og-border bg-og-surface-2/60 p-2.5",
|
|
132
|
-
"aria-label": `Annotation ${index + 1}`,
|
|
133
|
-
children: [
|
|
134
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
135
|
-
/* @__PURE__ */ jsxs(
|
|
136
|
-
"button",
|
|
137
|
-
{
|
|
138
|
-
type: "button",
|
|
139
|
-
className: "truncate rounded border-0 bg-transparent text-left text-og-xs font-medium text-og-fg-muted underline-offset-2 outline-hidden hover:text-og-fg hover:underline focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]",
|
|
140
|
-
onClick: () => {
|
|
141
|
-
const revealed = onRevealSource?.(annotation.source) ?? revealLoadedSource(annotation.source);
|
|
142
|
-
setUnavailableId(revealed ? null : annotation.id);
|
|
143
|
-
},
|
|
144
|
-
children: [
|
|
145
|
-
sourceLabel(annotation),
|
|
146
|
-
" \xB7 view source"
|
|
147
|
-
]
|
|
148
|
-
}
|
|
149
|
-
),
|
|
150
|
-
editable && onRemove ? /* @__PURE__ */ jsx(
|
|
151
|
-
"button",
|
|
152
|
-
{
|
|
153
|
-
type: "button",
|
|
154
|
-
className: "shrink-0 rounded border-0 bg-transparent p-1 text-og-fg-subtle outline-hidden hover:bg-og-surface-1 hover:text-og-status-failed focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:size-[44px]",
|
|
155
|
-
"aria-label": `Remove annotation ${index + 1}`,
|
|
156
|
-
onClick: () => onRemove(annotation.id),
|
|
157
|
-
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "text-og-md leading-none", children: "\xD7" })
|
|
158
|
-
}
|
|
159
|
-
) : null
|
|
160
|
-
] }),
|
|
161
|
-
unavailableId === annotation.id ? /* @__PURE__ */ jsx("p", { role: "status", className: "mt-1 text-og-xs text-og-status-waiting", children: "Source is outside the loaded timeline window." }) : null,
|
|
162
|
-
/* @__PURE__ */ jsx("blockquote", { className: "mt-2 max-h-28 overflow-auto whitespace-pre-wrap border-l-2 border-og-border pl-2 text-og-sm leading-5 text-og-fg-muted", children: annotation.quote }),
|
|
163
|
-
editable && onUpdate ? /* @__PURE__ */ jsxs("label", { className: "mt-2 block text-og-xs font-medium text-og-fg-muted", children: [
|
|
164
|
-
"Note",
|
|
165
|
-
/* @__PURE__ */ jsx(
|
|
166
|
-
"textarea",
|
|
167
|
-
{
|
|
168
|
-
ref: (node) => {
|
|
169
|
-
if (node) noteRefs.current.set(annotation.id, node);
|
|
170
|
-
else noteRefs.current.delete(annotation.id);
|
|
171
|
-
},
|
|
172
|
-
value: annotation.note,
|
|
173
|
-
rows: 2,
|
|
174
|
-
maxLength: 2048,
|
|
175
|
-
placeholder: "What should the agent do with this?",
|
|
176
|
-
className: "mt-1 w-full resize-y rounded-og-sm border border-og-border bg-og-surface-1 px-2.5 py-2 text-og-sm leading-5 text-og-fg outline-hidden placeholder:text-og-fg-subtle focus:border-og-accent focus:ring-1 focus:ring-og-accent",
|
|
177
|
-
onInput: (event) => onUpdate(annotation.id, event.currentTarget.value)
|
|
178
|
-
}
|
|
179
|
-
)
|
|
180
|
-
] }) : annotation.note ? /* @__PURE__ */ jsx("p", { className: "mt-2 whitespace-pre-wrap text-og-sm leading-5 text-og-fg", children: annotation.note }) : null
|
|
181
|
-
]
|
|
182
|
-
},
|
|
183
|
-
annotation.id
|
|
184
|
-
)) })
|
|
185
|
-
]
|
|
186
|
-
}
|
|
187
|
-
),
|
|
188
|
-
document.body
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
var timeline_annotations_dialog_default = TimelineAnnotationsDialog;
|
|
192
|
-
export {
|
|
193
|
-
TimelineAnnotationsDialog,
|
|
194
|
-
timeline_annotations_dialog_default as default
|
|
195
|
-
};
|
|
196
|
-
//# sourceMappingURL=timeline-annotations-dialog-U7EVLR75.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/timeline-annotations-dialog.tsx"],"sourcesContent":["import type { TimelineAnnotationSource } from \"@opengeni/sdk\";\nimport { useEffect, useLayoutEffect, useRef, useState, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { TimelineAnnotationLike } from \"./timeline-annotations\";\n\nfunction 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\nfunction revealLoadedSource(source: TimelineAnnotationSource): boolean {\n if (typeof document === \"undefined\") return false;\n const element = 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 { outline: \"2px solid color-mix(in srgb, currentColor 55%, transparent)\" },\n { outline: \"2px solid transparent\" },\n ],\n { duration: 1600, easing: \"ease-out\" },\n );\n return true;\n}\n\nfunction sourceLabel(annotation: TimelineAnnotationLike): string {\n if (annotation.source.label) return annotation.source.label;\n switch (annotation.source.kind) {\n case \"user_message\":\n return \"User message\";\n case \"assistant_message\":\n return \"Assistant message\";\n case \"tool_output\":\n return \"Tool output\";\n }\n}\n\nexport function TimelineAnnotationsDialog({\n annotations,\n editable,\n focusAnnotationId,\n onFocusConsumed,\n onUpdate,\n onRemove,\n onRevealSource,\n triggerRef,\n countLabel,\n onDismiss,\n}: {\n annotations: readonly TimelineAnnotationLike[];\n editable: boolean;\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 triggerRef: RefObject<HTMLButtonElement | null>;\n countLabel: string;\n onDismiss: (restoreFocus: boolean) => void;\n}) {\n const [unavailableId, setUnavailableId] = useState<string | null>(null);\n const [position, setPosition] = useState({ left: 12, top: 12, above: false });\n const panelRef = useRef<HTMLDivElement | null>(null);\n const noteRefs = useRef(new Map<string, HTMLTextAreaElement>());\n\n useLayoutEffect(() => {\n if (!focusAnnotationId) return;\n const note = noteRefs.current.get(focusAnnotationId);\n note?.focus();\n if (note && document.activeElement === note) onFocusConsumed?.();\n }, [focusAnnotationId, onFocusConsumed]);\n\n useEffect(() => {\n const updatePosition = () => {\n const rect = triggerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const panelWidth = Math.min(400, window.innerWidth - 24);\n const left = Math.min(\n Math.max(12, rect.left),\n Math.max(12, window.innerWidth - panelWidth - 12),\n );\n const above = rect.top > Math.min(360, window.innerHeight * 0.55);\n setPosition({ left, top: above ? rect.top - 8 : rect.bottom + 8, above });\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") onDismiss(true);\n };\n const onPointerDown = (event: PointerEvent) => {\n if (!(event.target instanceof Node)) return;\n if (panelRef.current?.contains(event.target) || triggerRef.current?.contains(event.target)) {\n return;\n }\n onDismiss(false);\n };\n updatePosition();\n window.addEventListener(\"resize\", updatePosition);\n window.addEventListener(\"scroll\", updatePosition, true);\n document.addEventListener(\"keydown\", onKeyDown);\n document.addEventListener(\"pointerdown\", onPointerDown);\n if (!focusAnnotationId) {\n window.setTimeout(() => {\n if (document.activeElement === triggerRef.current) panelRef.current?.focus();\n }, 0);\n }\n return () => {\n window.removeEventListener(\"resize\", updatePosition);\n window.removeEventListener(\"scroll\", updatePosition, true);\n document.removeEventListener(\"keydown\", onKeyDown);\n document.removeEventListener(\"pointerdown\", onPointerDown);\n };\n }, [focusAnnotationId, onDismiss, triggerRef]);\n\n if (typeof document === \"undefined\") return null;\n return createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n tabIndex={-1}\n style={{\n left: position.left,\n top: position.top,\n transform: position.above ? \"translateY(-100%)\" : undefined,\n }}\n className=\"og-root fixed z-[75] box-border max-h-[min(32rem,70vh)] w-[min(25rem,calc(100vw-1.5rem))] overflow-y-auto rounded-og-lg border border-og-border bg-og-surface-1 p-3 text-og-fg shadow-xl outline-hidden\"\n aria-label={editable ? \"Review timeline annotations\" : \"Timeline annotations\"}\n >\n <div className=\"mb-2 flex items-center justify-between gap-3\">\n <div>\n <p className=\"text-og-sm font-semibold\">{countLabel}</p>\n <p className=\"text-og-xs text-og-fg-subtle\">\n {editable ? \"Add a note for each quoted source.\" : \"Sent with this message.\"}\n </p>\n </div>\n <button\n type=\"button\"\n className=\"rounded-md border-0 bg-transparent px-2 py-1 text-og-xs text-og-fg outline-hidden hover:bg-og-surface-2 focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]\"\n onClick={() => onDismiss(true)}\n >\n Close\n </button>\n </div>\n <div className=\"grid gap-2.5\">\n {annotations.map((annotation, index) => (\n <section\n key={annotation.id}\n className=\"rounded-og-md border border-og-border bg-og-surface-2/60 p-2.5\"\n aria-label={`Annotation ${index + 1}`}\n >\n <div className=\"flex items-center justify-between gap-2\">\n <button\n type=\"button\"\n className=\"truncate rounded border-0 bg-transparent text-left text-og-xs font-medium text-og-fg-muted underline-offset-2 outline-hidden hover:text-og-fg hover:underline focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:min-h-[44px]\"\n onClick={() => {\n const revealed =\n onRevealSource?.(annotation.source) ?? revealLoadedSource(annotation.source);\n setUnavailableId(revealed ? null : annotation.id);\n }}\n >\n {sourceLabel(annotation)} · view source\n </button>\n {editable && onRemove ? (\n <button\n type=\"button\"\n className=\"shrink-0 rounded border-0 bg-transparent p-1 text-og-fg-subtle outline-hidden hover:bg-og-surface-1 hover:text-og-status-failed focus-visible:ring-2 focus-visible:ring-og-accent pointer-coarse:size-[44px]\"\n aria-label={`Remove annotation ${index + 1}`}\n onClick={() => onRemove(annotation.id)}\n >\n <span aria-hidden=\"true\" className=\"text-og-md leading-none\">\n ×\n </span>\n </button>\n ) : null}\n </div>\n {unavailableId === annotation.id ? (\n <p role=\"status\" className=\"mt-1 text-og-xs text-og-status-waiting\">\n Source is outside the loaded timeline window.\n </p>\n ) : null}\n <blockquote className=\"mt-2 max-h-28 overflow-auto whitespace-pre-wrap border-l-2 border-og-border pl-2 text-og-sm leading-5 text-og-fg-muted\">\n {annotation.quote}\n </blockquote>\n {editable && onUpdate ? (\n <label className=\"mt-2 block text-og-xs font-medium text-og-fg-muted\">\n Note\n <textarea\n ref={(node) => {\n if (node) noteRefs.current.set(annotation.id, node);\n else noteRefs.current.delete(annotation.id);\n }}\n value={annotation.note}\n rows={2}\n maxLength={2048}\n placeholder=\"What should the agent do with this?\"\n className=\"mt-1 w-full resize-y rounded-og-sm border border-og-border bg-og-surface-1 px-2.5 py-2 text-og-sm leading-5 text-og-fg outline-hidden placeholder:text-og-fg-subtle focus:border-og-accent focus:ring-1 focus:ring-og-accent\"\n onInput={(event) => onUpdate(annotation.id, event.currentTarget.value)}\n />\n </label>\n ) : annotation.note ? (\n <p className=\"mt-2 whitespace-pre-wrap text-og-sm leading-5 text-og-fg\">\n {annotation.note}\n </p>\n ) : null}\n </section>\n ))}\n </div>\n </div>,\n document.body,\n );\n}\n\nexport default TimelineAnnotationsDialog;\n"],"mappings":"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","names":[]}
|