@semiont/react-ui 0.2.36 → 0.2.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -0
- package/dist/index.mjs +252 -166
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/CodeMirrorRenderer.tsx +71 -203
- package/src/components/__tests__/AnnotateReferencesProgressWidget.test.tsx +142 -0
- package/src/components/__tests__/LiveRegion.hooks.test.tsx +79 -0
- package/src/components/__tests__/ResizeHandle.test.tsx +165 -0
- package/src/components/__tests__/SessionExpiryBanner.test.tsx +123 -0
- package/src/components/__tests__/StatusDisplay.test.tsx +160 -0
- package/src/components/__tests__/Toolbar.test.tsx +110 -0
- package/src/components/annotation-popups/__tests__/JsonLdView.test.tsx +285 -0
- package/src/components/annotation-popups/__tests__/SharedPopupElements.test.tsx +273 -0
- package/src/components/modals/__tests__/KeyboardShortcutsHelpModal.test.tsx +90 -0
- package/src/components/modals/__tests__/ProposeEntitiesModal.test.tsx +129 -0
- package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +180 -0
- package/src/components/navigation/__tests__/ObservableLink.test.tsx +90 -0
- package/src/components/navigation/__tests__/SimpleNavigation.test.tsx +169 -0
- package/src/components/navigation/__tests__/SortableResourceTab.test.tsx +371 -0
- package/src/components/resource/AnnotateView.tsx +27 -153
- package/src/components/resource/__tests__/AnnotationHistory.test.tsx +349 -0
- package/src/components/resource/__tests__/HistoryEvent.test.tsx +492 -0
- package/src/components/resource/__tests__/event-formatting.test.ts +273 -0
- package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +226 -0
- package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +188 -0
- package/src/components/resource/panels/__tests__/PanelHeader.test.tsx +69 -0
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +445 -0
- package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +271 -0
- package/src/components/resource/panels/__tests__/TagEntry.test.tsx +210 -0
- package/src/components/settings/__tests__/SettingsPanel.test.tsx +190 -0
- package/src/components/viewers/__tests__/ImageViewer.test.tsx +63 -0
- package/src/integrations/__tests__/css-modules-helper.test.tsx +225 -0
- package/src/integrations/__tests__/styled-components-theme.test.ts +179 -0
package/dist/index.d.mts
CHANGED
|
@@ -1724,6 +1724,13 @@ declare function usePreloadTranslations(): {
|
|
|
1724
1724
|
isLoaded: (locale: string) => boolean;
|
|
1725
1725
|
};
|
|
1726
1726
|
|
|
1727
|
+
/**
|
|
1728
|
+
* Pure logic extracted from CodeMirrorRenderer
|
|
1729
|
+
*
|
|
1730
|
+
* These functions have zero dependency on CodeMirror's DOM or React.
|
|
1731
|
+
* They handle position conversion, tooltip generation, and decoration metadata.
|
|
1732
|
+
*/
|
|
1733
|
+
|
|
1727
1734
|
type Annotation$g = components['schemas']['Annotation'];
|
|
1728
1735
|
interface TextSegment {
|
|
1729
1736
|
exact: string;
|
|
@@ -1731,6 +1738,7 @@ interface TextSegment {
|
|
|
1731
1738
|
start: number;
|
|
1732
1739
|
end: number;
|
|
1733
1740
|
}
|
|
1741
|
+
|
|
1734
1742
|
interface Props$b {
|
|
1735
1743
|
content: string;
|
|
1736
1744
|
segments?: TextSegment[];
|
package/dist/index.mjs
CHANGED
|
@@ -26141,10 +26141,10 @@ function scrollAnnotationIntoView(annotationId, rootElement, options = {}) {
|
|
|
26141
26141
|
}
|
|
26142
26142
|
|
|
26143
26143
|
// src/components/CodeMirrorRenderer.tsx
|
|
26144
|
+
import { isReference as isReference3 } from "@semiont/api-client";
|
|
26145
|
+
|
|
26146
|
+
// src/lib/codemirror-logic.ts
|
|
26144
26147
|
import { isHighlight as isHighlight2, isReference as isReference2, isResolvedReference as isResolvedReference2, isComment as isComment2, isAssessment, isTag as isTag3, getBodySource as getBodySource3 } from "@semiont/api-client";
|
|
26145
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
26146
|
-
var updateAnnotationsEffect = StateEffect.define();
|
|
26147
|
-
var updateWidgetsEffect = StateEffect.define();
|
|
26148
26148
|
function convertSegmentPositions(segments, content4) {
|
|
26149
26149
|
if (!content4.includes("\r\n")) {
|
|
26150
26150
|
return segments;
|
|
@@ -26193,34 +26193,148 @@ function getAnnotationTooltip(annotation) {
|
|
|
26193
26193
|
}
|
|
26194
26194
|
return "Annotation";
|
|
26195
26195
|
}
|
|
26196
|
+
function getAnnotationDecorationMeta(annotation, isNew) {
|
|
26197
|
+
const baseClassName = Object.values(ANNOTATORS).find((a15) => a15.matchesAnnotation(annotation))?.className || "annotation-highlight";
|
|
26198
|
+
const className = isNew ? `${baseClassName} annotation-sparkle` : baseClassName;
|
|
26199
|
+
const isHighlightAnn = isHighlight2(annotation);
|
|
26200
|
+
const isReferenceAnn = isReference2(annotation);
|
|
26201
|
+
const isCommentAnn = isComment2(annotation);
|
|
26202
|
+
const isAssessmentAnn = isAssessment(annotation);
|
|
26203
|
+
const isTagAnn = isTag3(annotation);
|
|
26204
|
+
let annotationType = "highlight";
|
|
26205
|
+
if (isCommentAnn) annotationType = "comment";
|
|
26206
|
+
else if (isReferenceAnn) annotationType = "reference";
|
|
26207
|
+
else if (isAssessmentAnn) annotationType = "assessment";
|
|
26208
|
+
else if (isTagAnn) annotationType = "tag";
|
|
26209
|
+
else if (isHighlightAnn) annotationType = "highlight";
|
|
26210
|
+
return {
|
|
26211
|
+
className,
|
|
26212
|
+
annotationType,
|
|
26213
|
+
annotationId: annotation.id,
|
|
26214
|
+
tooltip: getAnnotationTooltip(annotation)
|
|
26215
|
+
};
|
|
26216
|
+
}
|
|
26217
|
+
function computeAnnotationDecorations(segments, newAnnotationIds) {
|
|
26218
|
+
return segments.filter((s11) => s11.annotation).sort((a15, b8) => a15.start - b8.start).map((segment) => {
|
|
26219
|
+
const annotation = segment.annotation;
|
|
26220
|
+
const isNew = newAnnotationIds?.has(annotation.id) || false;
|
|
26221
|
+
return {
|
|
26222
|
+
start: segment.start,
|
|
26223
|
+
end: segment.end,
|
|
26224
|
+
meta: getAnnotationDecorationMeta(annotation, isNew)
|
|
26225
|
+
};
|
|
26226
|
+
});
|
|
26227
|
+
}
|
|
26228
|
+
function computeWidgetDecorations(segments, generatingReferenceId, getTargetDocumentName) {
|
|
26229
|
+
return segments.filter((s11) => s11.annotation && isReference2(s11.annotation)).sort((a15, b8) => a15.end - b8.end).map((segment) => {
|
|
26230
|
+
const annotation = segment.annotation;
|
|
26231
|
+
const bodySource = getBodySource3(annotation.body);
|
|
26232
|
+
const targetName = bodySource ? getTargetDocumentName?.(bodySource) : void 0;
|
|
26233
|
+
const isGenerating = generatingReferenceId ? annotation.id === generatingReferenceId : false;
|
|
26234
|
+
return {
|
|
26235
|
+
annotationId: annotation.id,
|
|
26236
|
+
position: segment.end,
|
|
26237
|
+
targetName,
|
|
26238
|
+
isGenerating,
|
|
26239
|
+
bodySource: bodySource ?? void 0
|
|
26240
|
+
};
|
|
26241
|
+
});
|
|
26242
|
+
}
|
|
26243
|
+
|
|
26244
|
+
// src/lib/codemirror-handlers.ts
|
|
26245
|
+
function handleAnnotationClick(target, segmentsById, eventBus) {
|
|
26246
|
+
const annotationElement = target.closest("[data-annotation-id]");
|
|
26247
|
+
const annotationId = annotationElement?.getAttribute("data-annotation-id");
|
|
26248
|
+
if (!annotationId) return false;
|
|
26249
|
+
const segment = segmentsById.get(annotationId);
|
|
26250
|
+
if (!segment?.annotation) return false;
|
|
26251
|
+
eventBus.get("browse:click").next({
|
|
26252
|
+
annotationId,
|
|
26253
|
+
motivation: segment.annotation.motivation
|
|
26254
|
+
});
|
|
26255
|
+
return true;
|
|
26256
|
+
}
|
|
26257
|
+
function handleWidgetClick(target) {
|
|
26258
|
+
const widget = target.closest(".reference-preview-widget");
|
|
26259
|
+
if (!widget || widget.dataset.widgetGenerating === "true") {
|
|
26260
|
+
return { handled: false };
|
|
26261
|
+
}
|
|
26262
|
+
const annotationId = widget.dataset.widgetAnnotationId;
|
|
26263
|
+
const bodySource = widget.dataset.widgetBodySource;
|
|
26264
|
+
const isResolved = widget.dataset.widgetResolved === "true";
|
|
26265
|
+
if (!annotationId) return { handled: false };
|
|
26266
|
+
if (isResolved && bodySource) {
|
|
26267
|
+
return {
|
|
26268
|
+
handled: true,
|
|
26269
|
+
action: "navigate",
|
|
26270
|
+
documentId: bodySource,
|
|
26271
|
+
annotationId
|
|
26272
|
+
};
|
|
26273
|
+
}
|
|
26274
|
+
return {
|
|
26275
|
+
handled: true,
|
|
26276
|
+
action: "browse-click",
|
|
26277
|
+
annotationId,
|
|
26278
|
+
motivation: widget.dataset.widgetMotivation || "linking"
|
|
26279
|
+
};
|
|
26280
|
+
}
|
|
26281
|
+
function dispatchWidgetClick(result, eventBus) {
|
|
26282
|
+
if (!result.handled) return;
|
|
26283
|
+
if (result.action === "navigate" && result.documentId) {
|
|
26284
|
+
eventBus.get("browse:reference-navigate").next({ documentId: result.documentId });
|
|
26285
|
+
} else if (result.action === "browse-click" && result.annotationId) {
|
|
26286
|
+
eventBus.get("browse:click").next({
|
|
26287
|
+
annotationId: result.annotationId,
|
|
26288
|
+
motivation: result.motivation || "linking"
|
|
26289
|
+
});
|
|
26290
|
+
}
|
|
26291
|
+
}
|
|
26292
|
+
function handleWidgetMouseEnter(target) {
|
|
26293
|
+
const widget = target.closest(".reference-preview-widget");
|
|
26294
|
+
if (!widget || widget.dataset.widgetGenerating === "true") {
|
|
26295
|
+
return { showPreview: false, widget: null };
|
|
26296
|
+
}
|
|
26297
|
+
const indicator = widget.querySelector(".reference-indicator");
|
|
26298
|
+
if (indicator) indicator.style.opacity = "1";
|
|
26299
|
+
if (widget.dataset.widgetResolved === "true" && widget.dataset.widgetTargetName) {
|
|
26300
|
+
return {
|
|
26301
|
+
showPreview: true,
|
|
26302
|
+
targetName: widget.dataset.widgetTargetName,
|
|
26303
|
+
widget
|
|
26304
|
+
};
|
|
26305
|
+
}
|
|
26306
|
+
return { showPreview: false, widget };
|
|
26307
|
+
}
|
|
26308
|
+
function handleWidgetMouseLeave(target) {
|
|
26309
|
+
const widget = target.closest(".reference-preview-widget");
|
|
26310
|
+
if (!widget) {
|
|
26311
|
+
return { hidePreview: false, widget: null };
|
|
26312
|
+
}
|
|
26313
|
+
const indicator = widget.querySelector(".reference-indicator");
|
|
26314
|
+
if (indicator) indicator.style.opacity = "0.6";
|
|
26315
|
+
if (widget.dataset.widgetResolved === "true") {
|
|
26316
|
+
return { hidePreview: true, widget };
|
|
26317
|
+
}
|
|
26318
|
+
return { hidePreview: false, widget };
|
|
26319
|
+
}
|
|
26320
|
+
|
|
26321
|
+
// src/components/CodeMirrorRenderer.tsx
|
|
26322
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
26323
|
+
var updateAnnotationsEffect = StateEffect.define();
|
|
26324
|
+
var updateWidgetsEffect = StateEffect.define();
|
|
26196
26325
|
function buildAnnotationDecorations(segments, newAnnotationIds) {
|
|
26197
26326
|
const builder = new RangeSetBuilder();
|
|
26198
|
-
const
|
|
26199
|
-
for (const
|
|
26200
|
-
if (!segment.annotation) continue;
|
|
26201
|
-
const isNew = newAnnotationIds?.has(segment.annotation.id) || false;
|
|
26202
|
-
const baseClassName = Object.values(ANNOTATORS).find((a15) => a15.matchesAnnotation(segment.annotation))?.className || "annotation-highlight";
|
|
26203
|
-
const className = isNew ? `${baseClassName} annotation-sparkle` : baseClassName;
|
|
26204
|
-
const isHighlightAnn = isHighlight2(segment.annotation);
|
|
26205
|
-
const isReferenceAnn = isReference2(segment.annotation);
|
|
26206
|
-
const isCommentAnn = isComment2(segment.annotation);
|
|
26207
|
-
const isAssessmentAnn = isAssessment(segment.annotation);
|
|
26208
|
-
const isTagAnn = isTag3(segment.annotation);
|
|
26209
|
-
let annotationType = "highlight";
|
|
26210
|
-
if (isCommentAnn) annotationType = "comment";
|
|
26211
|
-
else if (isReferenceAnn) annotationType = "reference";
|
|
26212
|
-
else if (isAssessmentAnn) annotationType = "assessment";
|
|
26213
|
-
else if (isTagAnn) annotationType = "tag";
|
|
26214
|
-
else if (isHighlightAnn) annotationType = "highlight";
|
|
26327
|
+
const entries = computeAnnotationDecorations(segments, newAnnotationIds);
|
|
26328
|
+
for (const { start: start2, end, meta: meta2 } of entries) {
|
|
26215
26329
|
const decoration = Decoration.mark({
|
|
26216
|
-
class: className,
|
|
26330
|
+
class: meta2.className,
|
|
26217
26331
|
attributes: {
|
|
26218
|
-
"data-annotation-id":
|
|
26219
|
-
"data-annotation-type": annotationType,
|
|
26220
|
-
title:
|
|
26332
|
+
"data-annotation-id": meta2.annotationId,
|
|
26333
|
+
"data-annotation-type": meta2.annotationType,
|
|
26334
|
+
title: meta2.tooltip
|
|
26221
26335
|
}
|
|
26222
26336
|
});
|
|
26223
|
-
builder.add(
|
|
26337
|
+
builder.add(start2, end, decoration);
|
|
26224
26338
|
}
|
|
26225
26339
|
return builder.finish();
|
|
26226
26340
|
}
|
|
@@ -26243,26 +26357,23 @@ function createAnnotationDecorationsField() {
|
|
|
26243
26357
|
}
|
|
26244
26358
|
function buildWidgetDecorations(_content, segments, generatingReferenceId, getTargetDocumentName) {
|
|
26245
26359
|
const builder = new RangeSetBuilder();
|
|
26246
|
-
const
|
|
26247
|
-
|
|
26248
|
-
|
|
26249
|
-
|
|
26250
|
-
|
|
26251
|
-
const bodySource = getBodySource3(annotation.body);
|
|
26252
|
-
const targetName = bodySource ? getTargetDocumentName?.(bodySource) : void 0;
|
|
26253
|
-
const isGenerating = generatingReferenceId ? annotation.id === generatingReferenceId : false;
|
|
26254
|
-
const widget = new ReferenceResolutionWidget(
|
|
26255
|
-
annotation,
|
|
26256
|
-
targetName,
|
|
26257
|
-
isGenerating
|
|
26258
|
-
);
|
|
26259
|
-
builder.add(
|
|
26260
|
-
segment.end,
|
|
26261
|
-
segment.end,
|
|
26262
|
-
Decoration.widget({ widget, side: 1 })
|
|
26263
|
-
);
|
|
26360
|
+
const widgetMetas = computeWidgetDecorations(segments, generatingReferenceId, getTargetDocumentName);
|
|
26361
|
+
const annotationsByEnd = /* @__PURE__ */ new Map();
|
|
26362
|
+
for (const s11 of segments) {
|
|
26363
|
+
if (s11.annotation && isReference3(s11.annotation)) {
|
|
26364
|
+
annotationsByEnd.set(s11.end, s11);
|
|
26264
26365
|
}
|
|
26265
26366
|
}
|
|
26367
|
+
for (const meta2 of widgetMetas) {
|
|
26368
|
+
const segment = annotationsByEnd.get(meta2.position);
|
|
26369
|
+
if (!segment?.annotation) continue;
|
|
26370
|
+
const widget = new ReferenceResolutionWidget(
|
|
26371
|
+
segment.annotation,
|
|
26372
|
+
meta2.targetName,
|
|
26373
|
+
meta2.isGenerating
|
|
26374
|
+
);
|
|
26375
|
+
builder.add(meta2.position, meta2.position, Decoration.widget({ widget, side: 1 }));
|
|
26376
|
+
}
|
|
26266
26377
|
return builder.finish();
|
|
26267
26378
|
}
|
|
26268
26379
|
var widgetDecorationsField = StateField.define({
|
|
@@ -26338,27 +26449,18 @@ function CodeMirrorRenderer({
|
|
|
26338
26449
|
onChange(newContent);
|
|
26339
26450
|
}
|
|
26340
26451
|
}),
|
|
26341
|
-
// Handle clicks on annotations
|
|
26452
|
+
// Handle clicks on annotations — delegates to extracted handler
|
|
26342
26453
|
EditorView.domEventHandlers({
|
|
26343
26454
|
click: (event, _view) => {
|
|
26344
26455
|
const target = event.target;
|
|
26345
|
-
|
|
26346
|
-
|
|
26347
|
-
|
|
26348
|
-
const segment = segmentsByIdRef.current.get(annotationId);
|
|
26349
|
-
if (segment?.annotation) {
|
|
26350
|
-
event.preventDefault();
|
|
26351
|
-
eventBusRef.current.get("browse:click").next({
|
|
26352
|
-
annotationId,
|
|
26353
|
-
motivation: segment.annotation.motivation
|
|
26354
|
-
});
|
|
26355
|
-
return true;
|
|
26356
|
-
}
|
|
26456
|
+
if (eventBusRef.current && handleAnnotationClick(target, segmentsByIdRef.current, eventBusRef.current)) {
|
|
26457
|
+
event.preventDefault();
|
|
26458
|
+
return true;
|
|
26357
26459
|
}
|
|
26358
26460
|
return false;
|
|
26359
26461
|
}
|
|
26360
26462
|
}),
|
|
26361
|
-
// Style the editor
|
|
26463
|
+
// Style the editor
|
|
26362
26464
|
EditorView.baseTheme({
|
|
26363
26465
|
"&.cm-editor": {
|
|
26364
26466
|
height: "100%",
|
|
@@ -26369,7 +26471,6 @@ function CodeMirrorRenderer({
|
|
|
26369
26471
|
},
|
|
26370
26472
|
".cm-scroller": {
|
|
26371
26473
|
overflow: "visible !important",
|
|
26372
|
-
// Let parent container handle scrolling
|
|
26373
26474
|
height: "auto !important"
|
|
26374
26475
|
},
|
|
26375
26476
|
".cm-content, .cm-gutters": {
|
|
@@ -26423,54 +26524,41 @@ function CodeMirrorRenderer({
|
|
|
26423
26524
|
const annotationElement = target.closest("[data-annotation-id]");
|
|
26424
26525
|
if (annotationElement) handleMouseLeave();
|
|
26425
26526
|
};
|
|
26426
|
-
const
|
|
26527
|
+
const onWidgetClick = (e6) => {
|
|
26427
26528
|
const target = e6.target;
|
|
26428
|
-
const
|
|
26429
|
-
if (!
|
|
26529
|
+
const result = handleWidgetClick(target);
|
|
26530
|
+
if (!result.handled) return;
|
|
26430
26531
|
e6.preventDefault();
|
|
26431
26532
|
e6.stopPropagation();
|
|
26432
|
-
|
|
26433
|
-
|
|
26434
|
-
const isResolved = widget.dataset.widgetResolved === "true";
|
|
26435
|
-
if (!annotationId || !eventBusRef.current) return;
|
|
26436
|
-
if (isResolved && bodySource) {
|
|
26437
|
-
eventBusRef.current.get("browse:reference-navigate").next({ documentId: bodySource });
|
|
26438
|
-
} else {
|
|
26439
|
-
const motivation = widget.dataset.widgetMotivation || "linking";
|
|
26440
|
-
eventBusRef.current.get("browse:click").next({ annotationId, motivation });
|
|
26533
|
+
if (eventBusRef.current) {
|
|
26534
|
+
dispatchWidgetClick(result, eventBusRef.current);
|
|
26441
26535
|
}
|
|
26442
26536
|
};
|
|
26443
|
-
const
|
|
26537
|
+
const onWidgetMouseEnter = (e6) => {
|
|
26444
26538
|
const target = e6.target;
|
|
26445
|
-
const
|
|
26446
|
-
if (
|
|
26447
|
-
|
|
26448
|
-
if (indicator) indicator.style.opacity = "1";
|
|
26449
|
-
if (widget.dataset.widgetResolved === "true" && widget.dataset.widgetTargetName) {
|
|
26450
|
-
showWidgetPreview(widget, widget.dataset.widgetTargetName);
|
|
26539
|
+
const result = handleWidgetMouseEnter(target);
|
|
26540
|
+
if (result.showPreview && result.targetName && result.widget) {
|
|
26541
|
+
showWidgetPreview(result.widget, result.targetName);
|
|
26451
26542
|
}
|
|
26452
26543
|
};
|
|
26453
|
-
const
|
|
26544
|
+
const onWidgetMouseLeave = (e6) => {
|
|
26454
26545
|
const target = e6.target;
|
|
26455
|
-
const
|
|
26456
|
-
if (
|
|
26457
|
-
|
|
26458
|
-
if (indicator) indicator.style.opacity = "0.6";
|
|
26459
|
-
if (widget.dataset.widgetResolved === "true") {
|
|
26460
|
-
hideWidgetPreview(widget);
|
|
26546
|
+
const result = handleWidgetMouseLeave(target);
|
|
26547
|
+
if (result.hidePreview && result.widget) {
|
|
26548
|
+
hideWidgetPreview(result.widget);
|
|
26461
26549
|
}
|
|
26462
26550
|
};
|
|
26463
26551
|
container.addEventListener("mouseover", handleMouseOver);
|
|
26464
26552
|
container.addEventListener("mouseout", handleMouseOut);
|
|
26465
|
-
container.addEventListener("click",
|
|
26466
|
-
container.addEventListener("mouseenter",
|
|
26467
|
-
container.addEventListener("mouseleave",
|
|
26553
|
+
container.addEventListener("click", onWidgetClick);
|
|
26554
|
+
container.addEventListener("mouseenter", onWidgetMouseEnter, true);
|
|
26555
|
+
container.addEventListener("mouseleave", onWidgetMouseLeave, true);
|
|
26468
26556
|
return () => {
|
|
26469
26557
|
container.removeEventListener("mouseover", handleMouseOver);
|
|
26470
26558
|
container.removeEventListener("mouseout", handleMouseOut);
|
|
26471
|
-
container.removeEventListener("click",
|
|
26472
|
-
container.removeEventListener("mouseenter",
|
|
26473
|
-
container.removeEventListener("mouseleave",
|
|
26559
|
+
container.removeEventListener("click", onWidgetClick);
|
|
26560
|
+
container.removeEventListener("mouseenter", onWidgetMouseEnter, true);
|
|
26561
|
+
container.removeEventListener("mouseleave", onWidgetMouseLeave, true);
|
|
26474
26562
|
cleanupHover();
|
|
26475
26563
|
view.destroy();
|
|
26476
26564
|
viewRef.current = null;
|
|
@@ -29271,13 +29359,13 @@ function PopupContainer({ children, position: position3, onClose, isOpen, wide =
|
|
|
29271
29359
|
|
|
29272
29360
|
// src/components/image-annotation/AnnotationOverlay.tsx
|
|
29273
29361
|
import { useMemo as useMemo2 } from "react";
|
|
29274
|
-
import { getSvgSelector, isHighlight as isHighlight3, isReference as
|
|
29362
|
+
import { getSvgSelector, isHighlight as isHighlight3, isReference as isReference4, isAssessment as isAssessment2, isComment as isComment3, isTag as isTag4, isBodyResolved, isResolvedReference as isResolvedReference3 } from "@semiont/api-client";
|
|
29275
29363
|
import { parseSvgSelector } from "@semiont/api-client";
|
|
29276
29364
|
import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
29277
29365
|
function getAnnotationColor(annotation) {
|
|
29278
29366
|
if (isHighlight3(annotation)) {
|
|
29279
29367
|
return { stroke: "rgb(250, 204, 21)", fill: "rgba(250, 204, 21, 0.2)" };
|
|
29280
|
-
} else if (
|
|
29368
|
+
} else if (isReference4(annotation)) {
|
|
29281
29369
|
return { stroke: "rgb(59, 130, 246)", fill: "rgba(59, 130, 246, 0.2)" };
|
|
29282
29370
|
} else if (isAssessment2(annotation)) {
|
|
29283
29371
|
return { stroke: "rgb(239, 68, 68)", fill: "rgba(239, 68, 68, 0.2)" };
|
|
@@ -29299,7 +29387,7 @@ function getAnnotationTooltip2(annotation) {
|
|
|
29299
29387
|
return "Tag";
|
|
29300
29388
|
} else if (isResolvedReference3(annotation)) {
|
|
29301
29389
|
return "Resolved Reference";
|
|
29302
|
-
} else if (
|
|
29390
|
+
} else if (isReference4(annotation)) {
|
|
29303
29391
|
return "Unresolved Reference";
|
|
29304
29392
|
}
|
|
29305
29393
|
return "Annotation";
|
|
@@ -29335,7 +29423,7 @@ function AnnotationOverlay({
|
|
|
29335
29423
|
const isHovered = annotation.id === hoveredAnnotationId;
|
|
29336
29424
|
const isSelected = annotation.id === selectedAnnotationId;
|
|
29337
29425
|
const colors = getAnnotationColor(annotation);
|
|
29338
|
-
const isRef =
|
|
29426
|
+
const isRef = isReference4(annotation);
|
|
29339
29427
|
const isResolved = isRef && isBodyResolved(annotation.body);
|
|
29340
29428
|
const statusEmoji = isRef ? isResolved ? "\u{1F517}" : "\u2753" : null;
|
|
29341
29429
|
switch (parsed.type) {
|
|
@@ -30102,9 +30190,10 @@ function ProposeEntitiesModal({
|
|
|
30102
30190
|
// src/components/resource/AnnotateView.tsx
|
|
30103
30191
|
import { useRef as useRef12, useEffect as useEffect18, useCallback as useCallback13, lazy, Suspense } from "react";
|
|
30104
30192
|
import { resourceUri as toResourceUri } from "@semiont/core";
|
|
30105
|
-
import {
|
|
30106
|
-
|
|
30107
|
-
|
|
30193
|
+
import { getMimeCategory, isPdfMimeType as isPdfMimeType2 } from "@semiont/api-client";
|
|
30194
|
+
|
|
30195
|
+
// src/lib/text-segmentation.ts
|
|
30196
|
+
import { getTextPositionSelector as getTextPositionSelector2, getTextQuoteSelector, getTargetSelector as getTargetSelector2, findTextWithContext, buildContentCache } from "@semiont/api-client";
|
|
30108
30197
|
function segmentTextWithAnnotations(content4, annotations) {
|
|
30109
30198
|
if (!content4) {
|
|
30110
30199
|
return [{ exact: "", start: 0, end: 0 }];
|
|
@@ -30164,6 +30253,37 @@ function segmentTextWithAnnotations(content4, annotations) {
|
|
|
30164
30253
|
}
|
|
30165
30254
|
return segments;
|
|
30166
30255
|
}
|
|
30256
|
+
|
|
30257
|
+
// src/lib/text-selection-handler.ts
|
|
30258
|
+
import { extractContext } from "@semiont/api-client";
|
|
30259
|
+
function buildTextSelectors(content4, selectedText, start2, end) {
|
|
30260
|
+
if (!selectedText || start2 < 0 || end <= start2 || end > content4.length) {
|
|
30261
|
+
return null;
|
|
30262
|
+
}
|
|
30263
|
+
const context = extractContext(content4, start2, end);
|
|
30264
|
+
return [
|
|
30265
|
+
{
|
|
30266
|
+
type: "TextPositionSelector",
|
|
30267
|
+
start: start2,
|
|
30268
|
+
end
|
|
30269
|
+
},
|
|
30270
|
+
{
|
|
30271
|
+
type: "TextQuoteSelector",
|
|
30272
|
+
exact: selectedText,
|
|
30273
|
+
...context.prefix && { prefix: context.prefix },
|
|
30274
|
+
...context.suffix && { suffix: context.suffix }
|
|
30275
|
+
}
|
|
30276
|
+
];
|
|
30277
|
+
}
|
|
30278
|
+
function fallbackTextPosition(content4, selectedText) {
|
|
30279
|
+
const start2 = content4.indexOf(selectedText);
|
|
30280
|
+
if (start2 === -1) return null;
|
|
30281
|
+
return { start: start2, end: start2 + selectedText.length };
|
|
30282
|
+
}
|
|
30283
|
+
|
|
30284
|
+
// src/components/resource/AnnotateView.tsx
|
|
30285
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
30286
|
+
var PdfAnnotationCanvas = lazy(() => import("./PdfAnnotationCanvas.client-COQREPXU.mjs").then((mod) => ({ default: mod.PdfAnnotationCanvas })));
|
|
30167
30287
|
function AnnotateView({
|
|
30168
30288
|
content: content4,
|
|
30169
30289
|
mimeType = "text/plain",
|
|
@@ -30235,59 +30355,25 @@ function AnnotateView({
|
|
|
30235
30355
|
const text7 = selection2.toString();
|
|
30236
30356
|
const cmContainer = container.querySelector(".codemirror-renderer");
|
|
30237
30357
|
const view = cmContainer?.__cmView;
|
|
30358
|
+
let start2;
|
|
30359
|
+
let end;
|
|
30238
30360
|
if (!view || !view.posAtDOM) {
|
|
30239
|
-
const
|
|
30240
|
-
if (
|
|
30241
|
-
|
|
30242
|
-
|
|
30243
|
-
|
|
30244
|
-
|
|
30245
|
-
|
|
30246
|
-
|
|
30247
|
-
|
|
30248
|
-
|
|
30249
|
-
|
|
30250
|
-
|
|
30251
|
-
|
|
30252
|
-
|
|
30253
|
-
|
|
30254
|
-
|
|
30255
|
-
exact: text7,
|
|
30256
|
-
...context.prefix && { prefix: context.prefix },
|
|
30257
|
-
...context.suffix && { suffix: context.suffix }
|
|
30258
|
-
}
|
|
30259
|
-
],
|
|
30260
|
-
motivation: selectedMotivation
|
|
30261
|
-
});
|
|
30262
|
-
selection2.removeAllRanges();
|
|
30263
|
-
return;
|
|
30264
|
-
}
|
|
30265
|
-
return;
|
|
30266
|
-
}
|
|
30267
|
-
const start2 = view.posAtDOM(range.startContainer, range.startOffset);
|
|
30268
|
-
const end = start2 + text7.length;
|
|
30269
|
-
if (start2 >= 0) {
|
|
30270
|
-
const context = extractContext(content4, start2, end);
|
|
30271
|
-
if (selectedMotivation) {
|
|
30272
|
-
eventBus.get("mark:requested").next({
|
|
30273
|
-
selector: [
|
|
30274
|
-
{
|
|
30275
|
-
type: "TextPositionSelector",
|
|
30276
|
-
start: start2,
|
|
30277
|
-
end
|
|
30278
|
-
},
|
|
30279
|
-
{
|
|
30280
|
-
type: "TextQuoteSelector",
|
|
30281
|
-
exact: text7,
|
|
30282
|
-
...context.prefix && { prefix: context.prefix },
|
|
30283
|
-
...context.suffix && { suffix: context.suffix }
|
|
30284
|
-
}
|
|
30285
|
-
],
|
|
30286
|
-
motivation: selectedMotivation
|
|
30287
|
-
});
|
|
30288
|
-
selection2.removeAllRanges();
|
|
30289
|
-
return;
|
|
30290
|
-
}
|
|
30361
|
+
const pos = fallbackTextPosition(content4, text7);
|
|
30362
|
+
if (!pos) return;
|
|
30363
|
+
start2 = pos.start;
|
|
30364
|
+
end = pos.end;
|
|
30365
|
+
} else {
|
|
30366
|
+
start2 = view.posAtDOM(range.startContainer, range.startOffset);
|
|
30367
|
+
end = start2 + text7.length;
|
|
30368
|
+
}
|
|
30369
|
+
if (start2 >= 0 && selectedMotivation) {
|
|
30370
|
+
const selectors = buildTextSelectors(content4, text7, start2, end);
|
|
30371
|
+
if (!selectors) return;
|
|
30372
|
+
eventBus.get("mark:requested").next({
|
|
30373
|
+
selector: selectors,
|
|
30374
|
+
motivation: selectedMotivation
|
|
30375
|
+
});
|
|
30376
|
+
selection2.removeAllRanges();
|
|
30291
30377
|
}
|
|
30292
30378
|
};
|
|
30293
30379
|
container.addEventListener("mouseup", handleMouseUp);
|
|
@@ -45562,7 +45648,7 @@ var BrowseView = memo(function BrowseView2({
|
|
|
45562
45648
|
// src/components/resource/ResourceViewer.tsx
|
|
45563
45649
|
import { useState as useState17, useEffect as useEffect23, useCallback as useCallback16, useRef as useRef16, useMemo as useMemo5 } from "react";
|
|
45564
45650
|
import { resourceUri } from "@semiont/core";
|
|
45565
|
-
import { getExactText as getExactText3, getTargetSelector as getTargetSelector4, isHighlight as isHighlight4, isAssessment as isAssessment3, isReference as
|
|
45651
|
+
import { getExactText as getExactText3, getTargetSelector as getTargetSelector4, isHighlight as isHighlight4, isAssessment as isAssessment3, isReference as isReference5, isComment as isComment4, isTag as isTag5, getBodySource as getBodySource4 } from "@semiont/api-client";
|
|
45566
45652
|
import { jsx as jsx28, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
45567
45653
|
function ResourceViewer({
|
|
45568
45654
|
resource,
|
|
@@ -45694,7 +45780,7 @@ function ResourceViewer({
|
|
|
45694
45780
|
const handleDeleteAnnotation = useCallback16((id2) => {
|
|
45695
45781
|
eventBus.get("mark:delete").next({ annotationId: id2 });
|
|
45696
45782
|
}, []);
|
|
45697
|
-
const
|
|
45783
|
+
const handleAnnotationClick2 = useCallback16((annotation, event) => {
|
|
45698
45784
|
const metadata = Object.values(ANNOTATORS).find((a15) => a15.matchesAnnotation(annotation));
|
|
45699
45785
|
if (metadata?.hasSidePanel) {
|
|
45700
45786
|
if (selectedClick === "detail") {
|
|
@@ -45705,8 +45791,8 @@ function ResourceViewer({
|
|
|
45705
45791
|
return;
|
|
45706
45792
|
}
|
|
45707
45793
|
}
|
|
45708
|
-
const isSimpleAnnotation = isHighlight4(annotation) || isAssessment3(annotation) || isComment4(annotation) ||
|
|
45709
|
-
if (selectedClick === "follow" &&
|
|
45794
|
+
const isSimpleAnnotation = isHighlight4(annotation) || isAssessment3(annotation) || isComment4(annotation) || isReference5(annotation) || isTag5(annotation);
|
|
45795
|
+
if (selectedClick === "follow" && isReference5(annotation)) {
|
|
45710
45796
|
const bodySource = getBodySource4(annotation.body);
|
|
45711
45797
|
if (bodySource) {
|
|
45712
45798
|
const resourceId = bodySource.split("/resources/")[1];
|
|
@@ -45734,7 +45820,7 @@ function ResourceViewer({
|
|
|
45734
45820
|
const allAnnotations = [...highlights, ...references, ...assessments, ...comments, ...tags3];
|
|
45735
45821
|
const annotation = allAnnotations.find((a15) => a15.id === annotationId);
|
|
45736
45822
|
if (annotation) {
|
|
45737
|
-
|
|
45823
|
+
handleAnnotationClick2(annotation);
|
|
45738
45824
|
}
|
|
45739
45825
|
return;
|
|
45740
45826
|
}
|
|
@@ -45742,12 +45828,12 @@ function ResourceViewer({
|
|
|
45742
45828
|
const allAnnotations = [...highlights, ...references, ...assessments, ...comments, ...tags3];
|
|
45743
45829
|
const annotation = allAnnotations.find((a15) => a15.id === annotationId);
|
|
45744
45830
|
if (annotation) {
|
|
45745
|
-
|
|
45831
|
+
handleAnnotationClick2(annotation);
|
|
45746
45832
|
}
|
|
45747
45833
|
return;
|
|
45748
45834
|
}
|
|
45749
45835
|
eventBus.get("browse:panel-open").next({ panel: "annotations", scrollToAnnotationId: annotationId, motivation });
|
|
45750
|
-
}, [highlights, references, assessments, comments, tags3,
|
|
45836
|
+
}, [highlights, references, assessments, comments, tags3, handleAnnotationClick2, selectedClick]);
|
|
45751
45837
|
useEventSubscriptions({
|
|
45752
45838
|
// View mode
|
|
45753
45839
|
"mark:mode-toggled": handleViewModeToggle,
|
|
@@ -46272,12 +46358,12 @@ function AssessmentPanel({
|
|
|
46272
46358
|
document.addEventListener("keydown", handleEscape);
|
|
46273
46359
|
return () => document.removeEventListener("keydown", handleEscape);
|
|
46274
46360
|
}, [pendingAnnotation]);
|
|
46275
|
-
const
|
|
46361
|
+
const handleAnnotationClick2 = useCallback18(({ annotationId }) => {
|
|
46276
46362
|
setFocusedAnnotationId(annotationId);
|
|
46277
46363
|
setTimeout(() => setFocusedAnnotationId(null), 3e3);
|
|
46278
46364
|
}, []);
|
|
46279
46365
|
useEventSubscriptions({
|
|
46280
|
-
"browse:click":
|
|
46366
|
+
"browse:click": handleAnnotationClick2
|
|
46281
46367
|
});
|
|
46282
46368
|
return /* @__PURE__ */ jsxs22("div", { className: "semiont-panel", children: [
|
|
46283
46369
|
/* @__PURE__ */ jsx32(PanelHeader, { annotationType: "assessment", count: annotations.length, title: t12("title") }),
|
|
@@ -46645,12 +46731,12 @@ function CommentsPanel({
|
|
|
46645
46731
|
container.scrollTo({ top: scrollTo, behavior: "smooth" });
|
|
46646
46732
|
}
|
|
46647
46733
|
}, [hoveredAnnotationId]);
|
|
46648
|
-
const
|
|
46734
|
+
const handleAnnotationClick2 = useCallback19(({ annotationId }) => {
|
|
46649
46735
|
setFocusedAnnotationId(annotationId);
|
|
46650
46736
|
setTimeout(() => setFocusedAnnotationId(null), 3e3);
|
|
46651
46737
|
}, []);
|
|
46652
46738
|
useEventSubscriptions({
|
|
46653
|
-
"browse:click":
|
|
46739
|
+
"browse:click": handleAnnotationClick2
|
|
46654
46740
|
});
|
|
46655
46741
|
const handleSaveNewComment = () => {
|
|
46656
46742
|
if (newCommentText.trim() && pendingAnnotation) {
|
|
@@ -46872,12 +46958,12 @@ function HighlightPanel({
|
|
|
46872
46958
|
container.scrollTo({ top: scrollTo, behavior: "smooth" });
|
|
46873
46959
|
}
|
|
46874
46960
|
}, [hoveredAnnotationId]);
|
|
46875
|
-
const
|
|
46961
|
+
const handleAnnotationClick2 = useCallback20(({ annotationId }) => {
|
|
46876
46962
|
setFocusedAnnotationId(annotationId);
|
|
46877
46963
|
setTimeout(() => setFocusedAnnotationId(null), 3e3);
|
|
46878
46964
|
}, []);
|
|
46879
46965
|
useEventSubscriptions({
|
|
46880
|
-
"browse:click":
|
|
46966
|
+
"browse:click": handleAnnotationClick2
|
|
46881
46967
|
});
|
|
46882
46968
|
useEffect28(() => {
|
|
46883
46969
|
if (pendingAnnotation && pendingAnnotation.motivation === "highlighting") {
|
|
@@ -47252,12 +47338,12 @@ function ReferencesPanel({
|
|
|
47252
47338
|
container.scrollTo({ top: scrollTo, behavior: "smooth" });
|
|
47253
47339
|
}
|
|
47254
47340
|
}, [hoveredAnnotationId]);
|
|
47255
|
-
const
|
|
47341
|
+
const handleAnnotationClick2 = useCallback21(({ annotationId }) => {
|
|
47256
47342
|
setFocusedAnnotationId(annotationId);
|
|
47257
47343
|
setTimeout(() => setFocusedAnnotationId(null), 3e3);
|
|
47258
47344
|
}, []);
|
|
47259
47345
|
useEventSubscriptions({
|
|
47260
|
-
"browse:click":
|
|
47346
|
+
"browse:click": handleAnnotationClick2
|
|
47261
47347
|
});
|
|
47262
47348
|
const handleAssist = () => {
|
|
47263
47349
|
setLastDetectionLog(null);
|
|
@@ -47751,12 +47837,12 @@ function TaggingPanel({
|
|
|
47751
47837
|
if (typeof window === "undefined") return;
|
|
47752
47838
|
localStorage.setItem("assist-section-expanded-tag", String(isAssistExpanded));
|
|
47753
47839
|
}, [isAssistExpanded]);
|
|
47754
|
-
const
|
|
47840
|
+
const handleAnnotationClick2 = useCallback22(({ annotationId }) => {
|
|
47755
47841
|
setFocusedAnnotationId(annotationId);
|
|
47756
47842
|
setTimeout(() => setFocusedAnnotationId(null), 3e3);
|
|
47757
47843
|
}, []);
|
|
47758
47844
|
useEventSubscriptions({
|
|
47759
|
-
"browse:click":
|
|
47845
|
+
"browse:click": handleAnnotationClick2
|
|
47760
47846
|
});
|
|
47761
47847
|
const entryRefs = useRef23(/* @__PURE__ */ new Map());
|
|
47762
47848
|
const sortedAnnotations = useMemo10(() => {
|