@semiont/react-ui 0.2.34-build.91 → 0.2.34-build.92
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/{EventBusContext-BmzEcGHZ.d.mts → EventBusContext-DMI4uwYk.d.mts} +2 -2
- package/dist/{PdfAnnotationCanvas.client-VLNA5O5M.mjs → PdfAnnotationCanvas.client-HNYRKFDS.mjs} +10 -9
- package/dist/PdfAnnotationCanvas.client-HNYRKFDS.mjs.map +1 -0
- package/dist/{ar-4ZEORRW2.mjs → ar-MDB7HC5S.mjs} +45 -49
- package/dist/ar-MDB7HC5S.mjs.map +1 -0
- package/dist/{bn-SEDE5BQJ.mjs → bn-3SAV2ZEM.mjs} +45 -49
- package/dist/bn-3SAV2ZEM.mjs.map +1 -0
- package/dist/{chunk-C63BARI7.mjs → chunk-3FIQXKQF.mjs} +31 -31
- package/dist/{chunk-D7NBW4RV.mjs → chunk-JH7BXE2P.mjs} +45 -49
- package/dist/chunk-JH7BXE2P.mjs.map +1 -0
- package/dist/{chunk-M7SZRRIE.mjs → chunk-MWQ5CNKW.mjs} +13 -13
- package/dist/chunk-MWQ5CNKW.mjs.map +1 -0
- package/dist/{chunk-ULIET3MW.mjs → chunk-YI5IX5ZA.mjs} +1 -1
- package/dist/{chunk-ULIET3MW.mjs.map → chunk-YI5IX5ZA.mjs.map} +1 -1
- package/dist/{cs-7W4WF5WD.mjs → cs-AWCETEUV.mjs} +45 -49
- package/dist/cs-AWCETEUV.mjs.map +1 -0
- package/dist/{da-75XGBCBK.mjs → da-UZZHXYLC.mjs} +45 -49
- package/dist/da-UZZHXYLC.mjs.map +1 -0
- package/dist/{de-ODJVFLHM.mjs → de-LQFWN6S5.mjs} +45 -49
- package/dist/de-LQFWN6S5.mjs.map +1 -0
- package/dist/{el-C4PM4WB3.mjs → el-IWOETBJ7.mjs} +45 -49
- package/dist/el-IWOETBJ7.mjs.map +1 -0
- package/dist/{en-KJCJQ4OO.mjs → en-XWEPVTB4.mjs} +2 -6
- package/dist/{es-WD33R7QL.mjs → es-726NTS53.mjs} +45 -49
- package/dist/es-726NTS53.mjs.map +1 -0
- package/dist/{fa-2BP6V56P.mjs → fa-BVEJZT5S.mjs} +45 -49
- package/dist/fa-BVEJZT5S.mjs.map +1 -0
- package/dist/{fi-USRRW24J.mjs → fi-JBNCGGA6.mjs} +45 -49
- package/dist/fi-JBNCGGA6.mjs.map +1 -0
- package/dist/{fr-EC5S6WVF.mjs → fr-OLH7PNGI.mjs} +45 -49
- package/dist/fr-OLH7PNGI.mjs.map +1 -0
- package/dist/{he-7TBVIKAA.mjs → he-KOJQ4HMA.mjs} +45 -49
- package/dist/he-KOJQ4HMA.mjs.map +1 -0
- package/dist/{hi-FO4VIZLA.mjs → hi-BKJFZXAY.mjs} +45 -49
- package/dist/hi-BKJFZXAY.mjs.map +1 -0
- package/dist/{id-7U7GGVWY.mjs → id-DPLHJVNP.mjs} +45 -49
- package/dist/id-DPLHJVNP.mjs.map +1 -0
- package/dist/index.css +80 -80
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +215 -201
- package/dist/index.mjs +810 -748
- package/dist/index.mjs.map +1 -1
- package/dist/{it-Y4OPL6I2.mjs → it-JXHAM7NL.mjs} +45 -49
- package/dist/it-JXHAM7NL.mjs.map +1 -0
- package/dist/{ja-PK7SQL55.mjs → ja-DQRAO3PU.mjs} +45 -49
- package/dist/ja-DQRAO3PU.mjs.map +1 -0
- package/dist/{ko-L25PXMYD.mjs → ko-6IFCOP6F.mjs} +45 -49
- package/dist/ko-6IFCOP6F.mjs.map +1 -0
- package/dist/{ms-STH777QM.mjs → ms-KF5S2TLL.mjs} +45 -49
- package/dist/ms-KF5S2TLL.mjs.map +1 -0
- package/dist/{nl-Y7LECDDR.mjs → nl-2GUUZLQM.mjs} +45 -49
- package/dist/nl-2GUUZLQM.mjs.map +1 -0
- package/dist/{no-KEKCEWU6.mjs → no-2IBCZGEF.mjs} +45 -49
- package/dist/no-2IBCZGEF.mjs.map +1 -0
- package/dist/{pl-7A7OC75O.mjs → pl-ZEUBJ7YU.mjs} +45 -49
- package/dist/pl-ZEUBJ7YU.mjs.map +1 -0
- package/dist/{pt-35HTM7RA.mjs → pt-WLAFIZWQ.mjs} +45 -49
- package/dist/pt-WLAFIZWQ.mjs.map +1 -0
- package/dist/{ro-VAWL5KQA.mjs → ro-K56IXFGU.mjs} +45 -49
- package/dist/ro-K56IXFGU.mjs.map +1 -0
- package/dist/{sv-7ZK5EQEB.mjs → sv-VFJLMJRY.mjs} +45 -49
- package/dist/sv-VFJLMJRY.mjs.map +1 -0
- package/dist/test-utils.d.mts +2 -2
- package/dist/test-utils.mjs +3 -3
- package/dist/{th-UDWZ4X34.mjs → th-RICLQ2GW.mjs} +45 -49
- package/dist/th-RICLQ2GW.mjs.map +1 -0
- package/dist/{tr-4WMPK3UX.mjs → tr-SALXWE2M.mjs} +45 -49
- package/dist/tr-SALXWE2M.mjs.map +1 -0
- package/dist/{uk-SSLASQYJ.mjs → uk-3U3T3O2E.mjs} +45 -49
- package/dist/uk-3U3T3O2E.mjs.map +1 -0
- package/dist/{vi-IF42Z5PU.mjs → vi-LIVNZXOB.mjs} +45 -49
- package/dist/vi-LIVNZXOB.mjs.map +1 -0
- package/dist/{zh-HRQTNTAI.mjs → zh-KDUAZPX3.mjs} +45 -49
- package/dist/zh-KDUAZPX3.mjs.map +1 -0
- package/package.json +1 -1
- package/src/components/AnnotateReferencesProgressWidget.tsx +113 -0
- package/src/components/CodeMirrorRenderer.tsx +9 -27
- package/src/components/Toolbar.tsx +2 -2
- package/src/components/annotation/AnnotateToolbar.tsx +9 -9
- package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +17 -17
- package/src/components/image-annotation/AnnotationOverlay.tsx +13 -11
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +8 -4
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +11 -9
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +1 -1
- package/src/components/resource/AnnotateView.tsx +17 -12
- package/src/components/resource/BrowseView.tsx +19 -50
- package/src/components/resource/ResourceViewer.tsx +28 -24
- package/src/components/resource/__tests__/BrowseView.test.tsx +27 -27
- package/src/components/resource/panels/AssessmentEntry.tsx +1 -1
- package/src/components/resource/panels/AssessmentPanel.tsx +16 -16
- package/src/components/resource/panels/{DetectSection.css → AssistSection.css} +79 -79
- package/src/components/resource/panels/{DetectSection.tsx → AssistSection.tsx} +46 -46
- package/src/components/resource/panels/CommentEntry.tsx +1 -1
- package/src/components/resource/panels/CommentsPanel.tsx +16 -16
- package/src/components/resource/panels/HighlightEntry.tsx +1 -1
- package/src/components/resource/panels/HighlightPanel.tsx +14 -14
- package/src/components/resource/panels/ReferenceEntry.tsx +5 -5
- package/src/components/resource/panels/ReferencesPanel.tsx +90 -103
- package/src/components/resource/panels/ResourceInfoPanel.tsx +2 -2
- package/src/components/resource/panels/TagEntry.tsx +1 -1
- package/src/components/resource/panels/TaggingPanel.tsx +53 -53
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +12 -20
- package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +12 -12
- package/src/components/resource/panels/__tests__/{DetectSection.test.tsx → AssistSection.test.tsx} +109 -108
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +8 -8
- package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +3 -3
- package/src/components/resource/panels/__tests__/{HighlightPanel.detectionProgress.test.tsx → HighlightPanel.annotationProgress.test.tsx} +56 -56
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +98 -95
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +3 -3
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +16 -16
- package/src/components/settings/SettingsPanel.tsx +29 -1
- package/src/features/resource-compose/components/ResourceComposePage.tsx +3 -0
- package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +36 -26
- package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +26 -16
- package/src/features/resource-viewer/__tests__/{DetectionProgressDismissal.test.tsx → AnnotationProgressDismissal.test.tsx} +48 -38
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +59 -49
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +55 -33
- package/src/features/resource-viewer/__tests__/GenerationFlowIntegration.test.tsx +24 -16
- package/src/features/resource-viewer/__tests__/ResolutionFlowIntegration.test.tsx +41 -31
- package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +10 -10
- package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +196 -0
- package/src/features/resource-viewer/__tests__/{detection-progress-flow.test.tsx → annotation-progress-flow.test.tsx} +51 -28
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +56 -45
- package/src/styles/core/buttons.css +3 -3
- package/src/styles/core/forms.css +2 -2
- package/src/styles/index.css +1 -1
- package/src/styles/motivations/motivation-assessment.css +9 -9
- package/src/styles/motivations/motivation-comment.css +9 -9
- package/src/styles/motivations/motivation-highlight.css +9 -9
- package/src/styles/motivations/motivation-reference.css +9 -9
- package/src/styles/motivations/motivation-tag.css +9 -9
- package/src/styles/utilities/focus-extended.css +6 -6
- package/translations/ar.json +44 -44
- package/translations/bn.json +44 -44
- package/translations/cs.json +44 -44
- package/translations/da.json +44 -44
- package/translations/de.json +44 -44
- package/translations/el.json +44 -44
- package/translations/en.json +44 -44
- package/translations/es.json +44 -44
- package/translations/fa.json +44 -44
- package/translations/fi.json +44 -44
- package/translations/fr.json +44 -44
- package/translations/he.json +44 -44
- package/translations/hi.json +44 -44
- package/translations/id.json +44 -44
- package/translations/it.json +44 -44
- package/translations/ja.json +44 -44
- package/translations/ko.json +44 -44
- package/translations/ms.json +44 -44
- package/translations/nl.json +44 -44
- package/translations/no.json +44 -44
- package/translations/pl.json +44 -44
- package/translations/pt.json +44 -44
- package/translations/ro.json +44 -44
- package/translations/sv.json +44 -44
- package/translations/th.json +44 -44
- package/translations/tr.json +44 -44
- package/translations/uk.json +44 -44
- package/translations/vi.json +44 -44
- package/translations/zh.json +44 -44
- package/dist/PdfAnnotationCanvas.client-VLNA5O5M.mjs.map +0 -1
- package/dist/ar-4ZEORRW2.mjs.map +0 -1
- package/dist/bn-SEDE5BQJ.mjs.map +0 -1
- package/dist/chunk-D7NBW4RV.mjs.map +0 -1
- package/dist/chunk-M7SZRRIE.mjs.map +0 -1
- package/dist/cs-7W4WF5WD.mjs.map +0 -1
- package/dist/da-75XGBCBK.mjs.map +0 -1
- package/dist/de-ODJVFLHM.mjs.map +0 -1
- package/dist/el-C4PM4WB3.mjs.map +0 -1
- package/dist/es-WD33R7QL.mjs.map +0 -1
- package/dist/fa-2BP6V56P.mjs.map +0 -1
- package/dist/fi-USRRW24J.mjs.map +0 -1
- package/dist/fr-EC5S6WVF.mjs.map +0 -1
- package/dist/he-7TBVIKAA.mjs.map +0 -1
- package/dist/hi-FO4VIZLA.mjs.map +0 -1
- package/dist/id-7U7GGVWY.mjs.map +0 -1
- package/dist/it-Y4OPL6I2.mjs.map +0 -1
- package/dist/ja-PK7SQL55.mjs.map +0 -1
- package/dist/ko-L25PXMYD.mjs.map +0 -1
- package/dist/ms-STH777QM.mjs.map +0 -1
- package/dist/nl-Y7LECDDR.mjs.map +0 -1
- package/dist/no-KEKCEWU6.mjs.map +0 -1
- package/dist/pl-7A7OC75O.mjs.map +0 -1
- package/dist/pt-35HTM7RA.mjs.map +0 -1
- package/dist/ro-VAWL5KQA.mjs.map +0 -1
- package/dist/sv-7ZK5EQEB.mjs.map +0 -1
- package/dist/th-UDWZ4X34.mjs.map +0 -1
- package/dist/tr-4WMPK3UX.mjs.map +0 -1
- package/dist/uk-SSLASQYJ.mjs.map +0 -1
- package/dist/vi-IF42Z5PU.mjs.map +0 -1
- package/dist/zh-HRQTNTAI.mjs.map +0 -1
- package/src/components/DetectionProgressWidget.tsx +0 -113
- /package/dist/{chunk-C63BARI7.mjs.map → chunk-3FIQXKQF.mjs.map} +0 -0
- /package/dist/{en-KJCJQ4OO.mjs.map → en-XWEPVTB4.mjs.map} +0 -0
|
@@ -18,6 +18,7 @@ interface AnnotationOverlayProps {
|
|
|
18
18
|
eventBus?: EventBus;
|
|
19
19
|
hoveredAnnotationId?: string | null;
|
|
20
20
|
selectedAnnotationId?: string | null;
|
|
21
|
+
hoverDelayMs: number;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -62,8 +63,8 @@ function getAnnotationTooltip(annotation: Annotation): string {
|
|
|
62
63
|
/**
|
|
63
64
|
* Render annotation overlay - displays existing annotations as SVG shapes
|
|
64
65
|
*
|
|
65
|
-
* @emits
|
|
66
|
-
* @emits
|
|
66
|
+
* @emits attend:hover - Annotation hovered or unhovered. Payload: { annotationId: string | null }
|
|
67
|
+
* @emits attend:click - Annotation clicked. Payload: { annotationId: string, motivation: Motivation }
|
|
67
68
|
*/
|
|
68
69
|
export function AnnotationOverlay({
|
|
69
70
|
annotations,
|
|
@@ -73,14 +74,15 @@ export function AnnotationOverlay({
|
|
|
73
74
|
displayHeight,
|
|
74
75
|
eventBus,
|
|
75
76
|
hoveredAnnotationId,
|
|
76
|
-
selectedAnnotationId
|
|
77
|
+
selectedAnnotationId,
|
|
78
|
+
hoverDelayMs
|
|
77
79
|
}: AnnotationOverlayProps) {
|
|
78
80
|
const scaleX = displayWidth / imageWidth;
|
|
79
81
|
const scaleY = displayHeight / imageHeight;
|
|
80
82
|
|
|
81
83
|
const { handleMouseEnter, handleMouseLeave } = useMemo(
|
|
82
|
-
() => createHoverHandlers((annotationId) => eventBus?.get('
|
|
83
|
-
[eventBus]
|
|
84
|
+
() => createHoverHandlers((annotationId) => eventBus?.get('attend:hover').next({ annotationId }), hoverDelayMs),
|
|
85
|
+
[eventBus, hoverDelayMs]
|
|
84
86
|
);
|
|
85
87
|
|
|
86
88
|
return (
|
|
@@ -129,7 +131,7 @@ export function AnnotationOverlay({
|
|
|
129
131
|
className="semiont-annotation-overlay__shape"
|
|
130
132
|
data-hovered={isHovered ? 'true' : 'false'}
|
|
131
133
|
data-selected={isSelected ? 'true' : 'false'}
|
|
132
|
-
onClick={() => eventBus?.get('
|
|
134
|
+
onClick={() => eventBus?.get('attend:click').next({ annotationId: annotation.id, motivation: annotation.motivation })}
|
|
133
135
|
onMouseEnter={() => handleMouseEnter(annotation.id)}
|
|
134
136
|
onMouseLeave={handleMouseLeave}
|
|
135
137
|
/>
|
|
@@ -142,7 +144,7 @@ export function AnnotationOverlay({
|
|
|
142
144
|
style={{ userSelect: 'none' }}
|
|
143
145
|
onClick={(e) => {
|
|
144
146
|
e.stopPropagation();
|
|
145
|
-
eventBus?.get('
|
|
147
|
+
eventBus?.get('attend:click').next({ annotationId: annotation.id, motivation: annotation.motivation });
|
|
146
148
|
}}
|
|
147
149
|
onMouseEnter={() => handleMouseEnter(annotation.id)}
|
|
148
150
|
onMouseLeave={handleMouseLeave}
|
|
@@ -176,7 +178,7 @@ export function AnnotationOverlay({
|
|
|
176
178
|
className="semiont-annotation-overlay__shape"
|
|
177
179
|
data-hovered={isHovered ? 'true' : 'false'}
|
|
178
180
|
data-selected={isSelected ? 'true' : 'false'}
|
|
179
|
-
onClick={() => eventBus?.get('
|
|
181
|
+
onClick={() => eventBus?.get('attend:click').next({ annotationId: annotation.id, motivation: annotation.motivation })}
|
|
180
182
|
onMouseEnter={() => handleMouseEnter(annotation.id)}
|
|
181
183
|
onMouseLeave={handleMouseLeave}
|
|
182
184
|
/>
|
|
@@ -189,7 +191,7 @@ export function AnnotationOverlay({
|
|
|
189
191
|
style={{ userSelect: 'none' }}
|
|
190
192
|
onClick={(e) => {
|
|
191
193
|
e.stopPropagation();
|
|
192
|
-
eventBus?.get('
|
|
194
|
+
eventBus?.get('attend:click').next({ annotationId: annotation.id, motivation: annotation.motivation });
|
|
193
195
|
}}
|
|
194
196
|
onMouseEnter={() => handleMouseEnter(annotation.id)}
|
|
195
197
|
onMouseLeave={handleMouseLeave}
|
|
@@ -236,7 +238,7 @@ export function AnnotationOverlay({
|
|
|
236
238
|
className="semiont-annotation-overlay__shape"
|
|
237
239
|
data-hovered={isHovered ? 'true' : 'false'}
|
|
238
240
|
data-selected={isSelected ? 'true' : 'false'}
|
|
239
|
-
onClick={() => eventBus?.get('
|
|
241
|
+
onClick={() => eventBus?.get('attend:click').next({ annotationId: annotation.id, motivation: annotation.motivation })}
|
|
240
242
|
onMouseEnter={() => handleMouseEnter(annotation.id)}
|
|
241
243
|
onMouseLeave={handleMouseLeave}
|
|
242
244
|
/>
|
|
@@ -249,7 +251,7 @@ export function AnnotationOverlay({
|
|
|
249
251
|
style={{ userSelect: 'none' }}
|
|
250
252
|
onClick={(e) => {
|
|
251
253
|
e.stopPropagation();
|
|
252
|
-
eventBus?.get('
|
|
254
|
+
eventBus?.get('attend:click').next({ annotationId: annotation.id, motivation: annotation.motivation });
|
|
253
255
|
}}
|
|
254
256
|
onMouseEnter={() => handleMouseEnter(annotation.id)}
|
|
255
257
|
onMouseLeave={handleMouseLeave}
|
|
@@ -6,6 +6,7 @@ import { createRectangleSvg, createCircleSvg, createPolygonSvg, scaleSvgToNative
|
|
|
6
6
|
import { AnnotationOverlay } from './AnnotationOverlay';
|
|
7
7
|
import type { SelectionMotivation } from '../annotation/AnnotateToolbar';
|
|
8
8
|
import type { EventBus } from "@semiont/core"
|
|
9
|
+
import { useHoverDelay } from '../../hooks/useHoverDelay';
|
|
9
10
|
|
|
10
11
|
type Annotation = components['schemas']['Annotation'];
|
|
11
12
|
|
|
@@ -42,13 +43,14 @@ interface SvgDrawingCanvasProps {
|
|
|
42
43
|
eventBus?: EventBus;
|
|
43
44
|
hoveredAnnotationId?: string | null;
|
|
44
45
|
selectedAnnotationId?: string | null;
|
|
46
|
+
hoverDelayMs?: number;
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
/**
|
|
48
50
|
* SVG-based drawing canvas for creating image annotations with shapes
|
|
49
51
|
*
|
|
50
|
-
* @emits
|
|
51
|
-
* @emits
|
|
52
|
+
* @emits attend:click - Annotation clicked on canvas. Payload: { annotationId: string, motivation: Motivation }
|
|
53
|
+
* @emits annotate:requested - New annotation drawn on canvas. Payload: { selector: SvgSelector, motivation: SelectionMotivation }
|
|
52
54
|
*/
|
|
53
55
|
export function SvgDrawingCanvas({
|
|
54
56
|
resourceUri,
|
|
@@ -59,6 +61,7 @@ export function SvgDrawingCanvas({
|
|
|
59
61
|
hoveredAnnotationId,
|
|
60
62
|
selectedAnnotationId
|
|
61
63
|
}: SvgDrawingCanvasProps) {
|
|
64
|
+
const { hoverDelayMs } = useHoverDelay();
|
|
62
65
|
const imageUrl = useMemo(() => {
|
|
63
66
|
const resourceId = resourceUri.split('/').pop();
|
|
64
67
|
return `/api/resources/${resourceId}`;
|
|
@@ -213,7 +216,7 @@ export function SvgDrawingCanvas({
|
|
|
213
216
|
});
|
|
214
217
|
|
|
215
218
|
if (clickedAnnotation) {
|
|
216
|
-
eventBus?.get('
|
|
219
|
+
eventBus?.get('attend:click').next({ annotationId: clickedAnnotation.id, motivation: clickedAnnotation.motivation });
|
|
217
220
|
setIsDrawing(false);
|
|
218
221
|
setStartPoint(null);
|
|
219
222
|
setCurrentPoint(null);
|
|
@@ -276,7 +279,7 @@ export function SvgDrawingCanvas({
|
|
|
276
279
|
|
|
277
280
|
// Emit annotation:requested event with SvgSelector
|
|
278
281
|
if (eventBus && selectedMotivation) {
|
|
279
|
-
eventBus.get('
|
|
282
|
+
eventBus.get('annotate:requested').next({
|
|
280
283
|
selector: {
|
|
281
284
|
type: 'SvgSelector',
|
|
282
285
|
value: nativeSvg
|
|
@@ -338,6 +341,7 @@ export function SvgDrawingCanvas({
|
|
|
338
341
|
imageHeight={imageDimensions.height}
|
|
339
342
|
displayWidth={displayDimensions.width}
|
|
340
343
|
displayHeight={displayDimensions.height}
|
|
344
|
+
hoverDelayMs={hoverDelayMs}
|
|
341
345
|
{...(eventBus && { eventBus })}
|
|
342
346
|
{...(hoveredAnnotationId !== undefined && { hoveredAnnotationId })}
|
|
343
347
|
{...(selectedAnnotationId !== undefined && { selectedAnnotationId })}
|
|
@@ -55,14 +55,15 @@ interface PdfAnnotationCanvasProps {
|
|
|
55
55
|
eventBus?: EventBus;
|
|
56
56
|
hoveredAnnotationId?: string | null;
|
|
57
57
|
selectedAnnotationId?: string | null;
|
|
58
|
+
hoverDelayMs?: number;
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* PDF annotation canvas with page navigation and rectangle drawing
|
|
62
63
|
*
|
|
63
|
-
* @emits
|
|
64
|
-
* @emits
|
|
65
|
-
* @emits
|
|
64
|
+
* @emits attend:click - Annotation clicked on PDF. Payload: { annotationId: string, motivation: Motivation }
|
|
65
|
+
* @emits annotate:requested - New annotation drawn on PDF. Payload: { selector: FragmentSelector, motivation: SelectionMotivation }
|
|
66
|
+
* @emits attend:hover - Annotation hovered or unhovered. Payload: { annotationId: string | null }
|
|
66
67
|
*/
|
|
67
68
|
export function PdfAnnotationCanvas({
|
|
68
69
|
resourceUri,
|
|
@@ -71,7 +72,8 @@ export function PdfAnnotationCanvas({
|
|
|
71
72
|
selectedMotivation,
|
|
72
73
|
eventBus,
|
|
73
74
|
hoveredAnnotationId,
|
|
74
|
-
selectedAnnotationId
|
|
75
|
+
selectedAnnotationId,
|
|
76
|
+
hoverDelayMs = 150
|
|
75
77
|
}: PdfAnnotationCanvasProps) {
|
|
76
78
|
const pdfUrl = useMemo(() => {
|
|
77
79
|
const resourceId = resourceUri.split('/').pop();
|
|
@@ -285,7 +287,7 @@ export function PdfAnnotationCanvas({
|
|
|
285
287
|
});
|
|
286
288
|
|
|
287
289
|
if (clickedAnnotation) {
|
|
288
|
-
eventBus?.get('
|
|
290
|
+
eventBus?.get('attend:click').next({ annotationId: clickedAnnotation.id, motivation: clickedAnnotation.motivation });
|
|
289
291
|
setIsDrawing(false);
|
|
290
292
|
setSelection(null);
|
|
291
293
|
return;
|
|
@@ -324,7 +326,7 @@ export function PdfAnnotationCanvas({
|
|
|
324
326
|
|
|
325
327
|
// Emit annotation:requested event with FragmentSelector
|
|
326
328
|
if (selectedMotivation) {
|
|
327
|
-
eventBus.get('
|
|
329
|
+
eventBus.get('annotate:requested').next({
|
|
328
330
|
selector: {
|
|
329
331
|
type: 'FragmentSelector',
|
|
330
332
|
conformsTo: 'http://tools.ietf.org/rfc/rfc3778',
|
|
@@ -362,8 +364,8 @@ export function PdfAnnotationCanvas({
|
|
|
362
364
|
|
|
363
365
|
// Hover handlers with currentHover guard and dwell delay
|
|
364
366
|
const { handleMouseEnter, handleMouseLeave } = useMemo(
|
|
365
|
-
() => createHoverHandlers((annotationId) => eventBus?.get('
|
|
366
|
-
[eventBus]
|
|
367
|
+
() => createHoverHandlers((annotationId) => eventBus?.get('attend:hover').next({ annotationId }), hoverDelayMs),
|
|
368
|
+
[eventBus, hoverDelayMs]
|
|
367
369
|
);
|
|
368
370
|
|
|
369
371
|
// Calculate motivation color
|
|
@@ -462,7 +464,7 @@ export function PdfAnnotationCanvas({
|
|
|
462
464
|
cursor: 'pointer',
|
|
463
465
|
opacity: isSelected ? 1 : isHovered ? 0.9 : 0.7
|
|
464
466
|
}}
|
|
465
|
-
onClick={() => eventBus?.get('
|
|
467
|
+
onClick={() => eventBus?.get('attend:click').next({ annotationId: ann.id, motivation: ann.motivation })}
|
|
466
468
|
onMouseEnter={() => handleMouseEnter(ann.id)}
|
|
467
469
|
onMouseLeave={handleMouseLeave}
|
|
468
470
|
/>
|
|
@@ -156,7 +156,7 @@ describe('PdfAnnotationCanvas', () => {
|
|
|
156
156
|
expect(rects?.length).toBeGreaterThan(0);
|
|
157
157
|
});
|
|
158
158
|
|
|
159
|
-
test('emits
|
|
159
|
+
test('emits annotate:requested via eventBus when drawing with sufficient drag', async () => {
|
|
160
160
|
const mockEventBus = {
|
|
161
161
|
emit: vi.fn(),
|
|
162
162
|
on: vi.fn(),
|
|
@@ -41,6 +41,7 @@ interface Props {
|
|
|
41
41
|
getTargetDocumentName?: (documentId: string) => string | undefined;
|
|
42
42
|
generatingReferenceId?: string | null;
|
|
43
43
|
showLineNumbers?: boolean;
|
|
44
|
+
hoverDelayMs?: number;
|
|
44
45
|
annotateMode: boolean;
|
|
45
46
|
}
|
|
46
47
|
|
|
@@ -127,11 +128,11 @@ function segmentTextWithAnnotations(content: string, annotations: Annotation[]):
|
|
|
127
128
|
/**
|
|
128
129
|
* View component for annotating resources with text selection and drawing
|
|
129
130
|
*
|
|
130
|
-
* @emits
|
|
131
|
-
* @subscribes
|
|
132
|
-
* @subscribes
|
|
133
|
-
* @subscribes
|
|
134
|
-
* @subscribes
|
|
131
|
+
* @emits annotate:requested - User requested to create annotation. Payload: { selector: Selector | Selector[], motivation: SelectionMotivation }
|
|
132
|
+
* @subscribes annotate:selection-changed - Toolbar selection changed. Payload: { motivation: string | null }
|
|
133
|
+
* @subscribes annotate:click-changed - Toolbar click action changed. Payload: { action: string }
|
|
134
|
+
* @subscribes annotate:shape-changed - Toolbar shape changed. Payload: { shape: string }
|
|
135
|
+
* @subscribes attend:hover - Annotation hovered. Payload: { annotationId: string | null }
|
|
135
136
|
*/
|
|
136
137
|
export function AnnotateView({
|
|
137
138
|
content,
|
|
@@ -144,6 +145,7 @@ export function AnnotateView({
|
|
|
144
145
|
getTargetDocumentName,
|
|
145
146
|
generatingReferenceId,
|
|
146
147
|
showLineNumbers = false,
|
|
148
|
+
hoverDelayMs = 150,
|
|
147
149
|
annotateMode
|
|
148
150
|
}: Props) {
|
|
149
151
|
const { newAnnotationIds } = useResourceAnnotations();
|
|
@@ -183,10 +185,10 @@ export function AnnotateView({
|
|
|
183
185
|
|
|
184
186
|
// Subscribe to toolbar events and annotation hover
|
|
185
187
|
useEventSubscriptions({
|
|
186
|
-
'
|
|
187
|
-
'
|
|
188
|
-
'
|
|
189
|
-
'
|
|
188
|
+
'annotate:selection-changed': handleToolbarSelectionChanged,
|
|
189
|
+
'annotate:click-changed': handleToolbarClickChanged,
|
|
190
|
+
'annotate:shape-changed': handleToolbarShapeChanged,
|
|
191
|
+
'attend:hover': handleAnnotationHover,
|
|
190
192
|
});
|
|
191
193
|
|
|
192
194
|
// Handle text annotation with sparkle or immediate creation
|
|
@@ -208,7 +210,7 @@ export function AnnotateView({
|
|
|
208
210
|
|
|
209
211
|
const handleMouseUp = (e: MouseEvent) => {
|
|
210
212
|
// Skip if the mouseUp came from PDF or image canvas
|
|
211
|
-
// (those components handle their own
|
|
213
|
+
// (those components handle their own annotate:requested events)
|
|
212
214
|
const target = e.target as Element;
|
|
213
215
|
if (target.closest('.semiont-pdf-annotation-canvas') ||
|
|
214
216
|
target.closest('.semiont-svg-drawing-canvas')) {
|
|
@@ -248,7 +250,7 @@ export function AnnotateView({
|
|
|
248
250
|
|
|
249
251
|
// Unified flow: all text annotations use BOTH TextPositionSelector and TextQuoteSelector
|
|
250
252
|
if (selectedMotivation) {
|
|
251
|
-
eventBus.get('
|
|
253
|
+
eventBus.get('annotate:requested').next({
|
|
252
254
|
selector: [
|
|
253
255
|
{
|
|
254
256
|
type: 'TextPositionSelector',
|
|
@@ -282,7 +284,7 @@ export function AnnotateView({
|
|
|
282
284
|
|
|
283
285
|
// Unified flow: all text annotations use BOTH TextPositionSelector and TextQuoteSelector
|
|
284
286
|
if (selectedMotivation) {
|
|
285
|
-
eventBus.get('
|
|
287
|
+
eventBus.get('annotate:requested').next({
|
|
286
288
|
selector: [
|
|
287
289
|
{
|
|
288
290
|
type: 'TextPositionSelector',
|
|
@@ -338,6 +340,7 @@ export function AnnotateView({
|
|
|
338
340
|
{...(scrollToAnnotationId !== undefined && { scrollToAnnotationId })}
|
|
339
341
|
sourceView={true}
|
|
340
342
|
showLineNumbers={showLineNumbers}
|
|
343
|
+
hoverDelayMs={hoverDelayMs}
|
|
341
344
|
enableWidgets={enableWidgets}
|
|
342
345
|
eventBus={eventBus}
|
|
343
346
|
{...(getTargetDocumentName && { getTargetDocumentName })}
|
|
@@ -373,6 +376,7 @@ export function AnnotateView({
|
|
|
373
376
|
selectedMotivation={selectedMotivation}
|
|
374
377
|
eventBus={eventBus}
|
|
375
378
|
hoveredAnnotationId={hoveredCommentId || hoveredAnnotationId || null}
|
|
379
|
+
hoverDelayMs={hoverDelayMs}
|
|
376
380
|
/>
|
|
377
381
|
</Suspense>
|
|
378
382
|
)}
|
|
@@ -402,6 +406,7 @@ export function AnnotateView({
|
|
|
402
406
|
selectedMotivation={selectedMotivation}
|
|
403
407
|
eventBus={eventBus}
|
|
404
408
|
hoveredAnnotationId={hoveredCommentId || hoveredAnnotationId || null}
|
|
409
|
+
hoverDelayMs={hoverDelayMs}
|
|
405
410
|
/>
|
|
406
411
|
)}
|
|
407
412
|
</div>
|
|
@@ -10,6 +10,7 @@ import { resourceUri as toResourceUri } from '@semiont/core';
|
|
|
10
10
|
import { getExactText, getTextPositionSelector, getTargetSelector, getBodySource, getMimeCategory, isPdfMimeType } from '@semiont/api-client';
|
|
11
11
|
import { ANNOTATORS } from '../../lib/annotation-registry';
|
|
12
12
|
import { createHoverHandlers } from '../../hooks/useAttentionFlow';
|
|
13
|
+
import { scrollAnnotationIntoView } from '../../lib/scroll-utils';
|
|
13
14
|
import { ImageViewer } from '../viewers';
|
|
14
15
|
import { AnnotateToolbar, type ClickAction } from '../annotation/AnnotateToolbar';
|
|
15
16
|
import type { AnnotationsCollection } from '../../types/annotation-props';
|
|
@@ -31,6 +32,7 @@ interface Props {
|
|
|
31
32
|
hoveredCommentId?: string | null;
|
|
32
33
|
selectedClick?: ClickAction;
|
|
33
34
|
annotateMode: boolean;
|
|
35
|
+
hoverDelayMs?: number;
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
/**
|
|
@@ -41,8 +43,8 @@ function prepareAnnotations(annotations: Annotation[]): PreparedAnnotation[] {
|
|
|
41
43
|
/**
|
|
42
44
|
* View component for browsing resources with rendered annotations
|
|
43
45
|
*
|
|
44
|
-
* @emits
|
|
45
|
-
* @emits
|
|
46
|
+
* @emits attend:click - Annotation clicked in browse view. Payload: { annotationId: string, motivation: Motivation }
|
|
47
|
+
* @emits attend:hover - Annotation hovered in browse view. Payload: { annotationId: string | null }
|
|
46
48
|
*/
|
|
47
49
|
return annotations
|
|
48
50
|
.map(ann => {
|
|
@@ -68,11 +70,11 @@ function prepareAnnotations(annotations: Annotation[]): PreparedAnnotation[] {
|
|
|
68
70
|
/**
|
|
69
71
|
* View component for browsing annotated resources in read-only mode
|
|
70
72
|
*
|
|
71
|
-
* @emits
|
|
72
|
-
* @emits
|
|
73
|
+
* @emits attend:click - User clicked on annotation. Payload: { annotationId: string, motivation: Motivation }
|
|
74
|
+
* @emits attend:hover - User hovered over annotation. Payload: { annotationId: string | null }
|
|
73
75
|
*
|
|
74
|
-
* @subscribes
|
|
75
|
-
* @subscribes
|
|
76
|
+
* @subscribes attend:hover - Highlight annotation on hover. Payload: { annotationId: string | null }
|
|
77
|
+
* @subscribes attend:focus - Scroll to and highlight annotation. Payload: { annotationId: string }
|
|
76
78
|
*/
|
|
77
79
|
export function BrowseView({
|
|
78
80
|
content,
|
|
@@ -80,7 +82,8 @@ export function BrowseView({
|
|
|
80
82
|
resourceUri,
|
|
81
83
|
annotations,
|
|
82
84
|
selectedClick = 'detail',
|
|
83
|
-
annotateMode
|
|
85
|
+
annotateMode,
|
|
86
|
+
hoverDelayMs = 150
|
|
84
87
|
}: Props) {
|
|
85
88
|
const { newAnnotationIds } = useResourceAnnotations();
|
|
86
89
|
const eventBus = useEventBus();
|
|
@@ -112,13 +115,14 @@ export function BrowseView({
|
|
|
112
115
|
if (annotationId && annotationType === 'reference') {
|
|
113
116
|
const annotation = allAnnotations.find(a => a.id === annotationId);
|
|
114
117
|
if (annotation) {
|
|
115
|
-
eventBus.get('
|
|
118
|
+
eventBus.get('attend:click').next({ annotationId, motivation: annotation.motivation });
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
};
|
|
119
122
|
|
|
120
123
|
const { handleMouseEnter, handleMouseLeave, cleanup: cleanupHover } = createHoverHandlers(
|
|
121
|
-
(annotationId) => eventBus.get('
|
|
124
|
+
(annotationId) => eventBus.get('attend:hover').next({ annotationId }),
|
|
125
|
+
hoverDelayMs
|
|
122
126
|
);
|
|
123
127
|
|
|
124
128
|
// Single mouseover handler for the container - fires once on enter
|
|
@@ -157,48 +161,13 @@ export function BrowseView({
|
|
|
157
161
|
container.removeEventListener('mouseout', handleMouseOut);
|
|
158
162
|
cleanupHover();
|
|
159
163
|
};
|
|
160
|
-
}, [content, allAnnotations, newAnnotationIds]);
|
|
164
|
+
}, [content, allAnnotations, newAnnotationIds, hoverDelayMs]);
|
|
161
165
|
|
|
162
166
|
// Helper to scroll annotation into view with pulse effect
|
|
163
167
|
const scrollToAnnotation = useCallback((annotationId: string | null, removePulse = false) => {
|
|
164
|
-
if (!containerRef.current
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
`[data-annotation-id="${CSS.escape(annotationId)}"]`
|
|
168
|
-
) as HTMLElement;
|
|
169
|
-
|
|
170
|
-
if (!element) return;
|
|
171
|
-
|
|
172
|
-
// Find the scroll container
|
|
173
|
-
const scrollContainer = element.closest('.semiont-browse-view__content') as HTMLElement;
|
|
174
|
-
|
|
175
|
-
if (scrollContainer) {
|
|
176
|
-
// Check visibility within the scroll container
|
|
177
|
-
const elementRect = element.getBoundingClientRect();
|
|
178
|
-
const containerRect = scrollContainer.getBoundingClientRect();
|
|
179
|
-
|
|
180
|
-
const isVisible =
|
|
181
|
-
elementRect.top >= containerRect.top &&
|
|
182
|
-
elementRect.bottom <= containerRect.bottom;
|
|
183
|
-
|
|
184
|
-
if (!isVisible) {
|
|
185
|
-
// Scroll using container.scrollTo to avoid scrolling ancestors
|
|
186
|
-
const elementTop = element.offsetTop;
|
|
187
|
-
const containerHeight = scrollContainer.clientHeight;
|
|
188
|
-
const elementHeight = element.offsetHeight;
|
|
189
|
-
const scrollTo = elementTop - (containerHeight / 2) + (elementHeight / 2);
|
|
190
|
-
|
|
191
|
-
scrollContainer.scrollTo({ top: scrollTo, behavior: 'smooth' });
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Add pulse effect
|
|
196
|
-
element.classList.add('annotation-pulse');
|
|
197
|
-
if (removePulse) {
|
|
198
|
-
setTimeout(() => {
|
|
199
|
-
element.classList.remove('annotation-pulse');
|
|
200
|
-
}, 2000);
|
|
201
|
-
}
|
|
168
|
+
if (!containerRef.current) return;
|
|
169
|
+
// removePulse = true means "add pulse and auto-remove after 2s"
|
|
170
|
+
scrollAnnotationIntoView(annotationId, containerRef.current, { pulse: removePulse });
|
|
202
171
|
}, []);
|
|
203
172
|
|
|
204
173
|
// Handle hover events for scrolling
|
|
@@ -212,8 +181,8 @@ export function BrowseView({
|
|
|
212
181
|
}, [scrollToAnnotation]);
|
|
213
182
|
|
|
214
183
|
useEventSubscriptions({
|
|
215
|
-
'
|
|
216
|
-
'
|
|
184
|
+
'attend:hover': handleAnnotationHover,
|
|
185
|
+
'attend:focus': handleAnnotationFocus,
|
|
217
186
|
});
|
|
218
187
|
|
|
219
188
|
// Route to appropriate viewer based on MIME type category
|
|
@@ -24,7 +24,7 @@ type SemiontResource = components['schemas']['ResourceDescriptor'];
|
|
|
24
24
|
* ResourceViewer - Display and interact with resource content and annotations
|
|
25
25
|
*
|
|
26
26
|
* This component uses event-driven architecture for real-time updates:
|
|
27
|
-
* - Subscribes to make-meaning events (
|
|
27
|
+
* - Subscribes to make-meaning events (annotate:added, annotate:removed, annotate:body-updated)
|
|
28
28
|
* - Automatically invalidates cache when annotations change
|
|
29
29
|
* - No manual refetch needed - events handle cache invalidation
|
|
30
30
|
*
|
|
@@ -43,27 +43,29 @@ interface Props {
|
|
|
43
43
|
annotations: AnnotationsCollection;
|
|
44
44
|
generatingReferenceId?: string | null;
|
|
45
45
|
showLineNumbers?: boolean;
|
|
46
|
+
hoverDelayMs?: number;
|
|
46
47
|
hoveredAnnotationId?: string | null;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
/**
|
|
50
|
-
* @emits
|
|
51
|
-
* @emits panel
|
|
51
|
+
* @emits annotate:delete - User requested to delete annotation. Payload: { annotationId: string }
|
|
52
|
+
* @emits attend:panel-open - Request to open panel with annotation. Payload: { panel: string, scrollToAnnotationId?: string, motivation?: Motivation }
|
|
52
53
|
*
|
|
53
|
-
* @subscribes
|
|
54
|
-
* @subscribes
|
|
55
|
-
* @subscribes
|
|
56
|
-
* @subscribes
|
|
57
|
-
* @subscribes
|
|
58
|
-
* @subscribes
|
|
59
|
-
* @subscribes
|
|
60
|
-
* @subscribes
|
|
54
|
+
* @subscribes annotate:mode-toggled - Toggles between browse and annotate mode. Payload: { mode: 'browse' | 'annotate' }
|
|
55
|
+
* @subscribes annotate:added - New annotation was added. Payload: { annotation: Annotation }
|
|
56
|
+
* @subscribes annotate:removed - Annotation was removed. Payload: { annotationId: string }
|
|
57
|
+
* @subscribes annotate:body-updated - Annotation was updated. Payload: { annotation: Annotation }
|
|
58
|
+
* @subscribes annotate:selection-changed - Text selection tool changed. Payload: { selection: boolean }
|
|
59
|
+
* @subscribes annotate:click-changed - Click annotation tool changed. Payload: { click: 'detail' | 'scroll' | null }
|
|
60
|
+
* @subscribes annotate:shape-changed - Drawing shape changed. Payload: { shape: string }
|
|
61
|
+
* @subscribes attend:click - User clicked on annotation. Payload: { annotationId: string }
|
|
61
62
|
*/
|
|
62
63
|
export function ResourceViewer({
|
|
63
64
|
resource,
|
|
64
65
|
annotations,
|
|
65
66
|
generatingReferenceId,
|
|
66
67
|
showLineNumbers = false,
|
|
68
|
+
hoverDelayMs,
|
|
67
69
|
hoveredAnnotationId: hoveredAnnotationIdProp
|
|
68
70
|
}: Props) {
|
|
69
71
|
const t = useTranslations('ResourceViewer');
|
|
@@ -122,19 +124,19 @@ export function ResourceViewer({
|
|
|
122
124
|
// This replaces manual onRefetchAnnotations calls with automatic updates
|
|
123
125
|
const cacheManager = useCacheManager();
|
|
124
126
|
|
|
125
|
-
const
|
|
127
|
+
const handleAnnotateAdded = useCallback(() => {
|
|
126
128
|
if (cacheManager) {
|
|
127
129
|
cacheManager.invalidateAnnotations(rUri);
|
|
128
130
|
}
|
|
129
131
|
}, [cacheManager, rUri]);
|
|
130
132
|
|
|
131
|
-
const
|
|
133
|
+
const handleAnnotateRemoved = useCallback(() => {
|
|
132
134
|
if (cacheManager) {
|
|
133
135
|
cacheManager.invalidateAnnotations(rUri);
|
|
134
136
|
}
|
|
135
137
|
}, [cacheManager, rUri]);
|
|
136
138
|
|
|
137
|
-
const
|
|
139
|
+
const handleAnnotateBodyUpdated = useCallback(() => {
|
|
138
140
|
if (cacheManager) {
|
|
139
141
|
cacheManager.invalidateAnnotations(rUri);
|
|
140
142
|
}
|
|
@@ -250,7 +252,7 @@ export function ResourceViewer({
|
|
|
250
252
|
|
|
251
253
|
// Handle deleting annotations - emit event instead of direct call
|
|
252
254
|
const handleDeleteAnnotation = useCallback((id: string) => {
|
|
253
|
-
eventBus.get('
|
|
255
|
+
eventBus.get('annotate:delete').next({ annotationId: id });
|
|
254
256
|
}, []); // eventBus is stable
|
|
255
257
|
|
|
256
258
|
// Handle annotation clicks - memoized
|
|
@@ -339,27 +341,27 @@ export function ResourceViewer({
|
|
|
339
341
|
|
|
340
342
|
// All annotations open the unified annotations panel
|
|
341
343
|
// The panel internally switches tabs based on the motivation → tab mapping in UnifiedAnnotationsPanel
|
|
342
|
-
eventBus.get('panel
|
|
344
|
+
eventBus.get('attend:panel-open').next({ panel: 'annotations', scrollToAnnotationId: annotationId, motivation });
|
|
343
345
|
}, [highlights, references, assessments, comments, tags, handleAnnotationClick, selectedClick]);
|
|
344
346
|
|
|
345
347
|
// Event subscriptions - Combined into single useEventSubscriptions call to prevent hook ordering issues
|
|
346
348
|
// IMPORTANT: All event subscriptions MUST be in a single call to maintain consistent hook order between renders
|
|
347
349
|
useEventSubscriptions({
|
|
348
350
|
// View mode
|
|
349
|
-
'
|
|
351
|
+
'annotate:mode-toggled': handleViewModeToggle,
|
|
350
352
|
|
|
351
353
|
// Annotation cache invalidation
|
|
352
|
-
'
|
|
353
|
-
'
|
|
354
|
-
'
|
|
354
|
+
'annotate:added': handleAnnotateAdded,
|
|
355
|
+
'annotate:removed': handleAnnotateRemoved,
|
|
356
|
+
'annotate:body-updated': handleAnnotateBodyUpdated,
|
|
355
357
|
|
|
356
358
|
// Toolbar state
|
|
357
|
-
'
|
|
358
|
-
'
|
|
359
|
-
'
|
|
359
|
+
'annotate:selection-changed': handleToolbarSelectionChanged,
|
|
360
|
+
'annotate:click-changed': handleToolbarClickChanged,
|
|
361
|
+
'annotate:shape-changed': handleToolbarShapeChanged,
|
|
360
362
|
|
|
361
363
|
// Annotation clicks
|
|
362
|
-
'
|
|
364
|
+
'attend:click': handleAnnotationClickEvent,
|
|
363
365
|
});
|
|
364
366
|
|
|
365
367
|
// Prepare props for child components
|
|
@@ -400,6 +402,7 @@ export function ResourceViewer({
|
|
|
400
402
|
getTargetDocumentName={getTargetDocumentName}
|
|
401
403
|
{...(generatingReferenceId !== undefined && { generatingReferenceId })}
|
|
402
404
|
showLineNumbers={showLineNumbers}
|
|
405
|
+
hoverDelayMs={hoverDelayMs}
|
|
403
406
|
annotateMode={annotateMode}
|
|
404
407
|
/>
|
|
405
408
|
) : (
|
|
@@ -410,6 +413,7 @@ export function ResourceViewer({
|
|
|
410
413
|
annotations={annotationsCollection}
|
|
411
414
|
hoveredCommentId={hoveredCommentId}
|
|
412
415
|
selectedClick={selectedClick}
|
|
416
|
+
hoverDelayMs={hoverDelayMs}
|
|
413
417
|
annotateMode={annotateMode}
|
|
414
418
|
/>
|
|
415
419
|
)}
|