@semiont/react-ui 0.2.33-build.77 → 0.2.33-build.79
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/{ar-RNNSPLQB.mjs → ar-EMHEHPCJ.mjs} +2 -1
- package/dist/ar-EMHEHPCJ.mjs.map +1 -0
- package/dist/{bn-S2CDL7EC.mjs → bn-OVCI4F6X.mjs} +2 -1
- package/dist/bn-OVCI4F6X.mjs.map +1 -0
- package/dist/{chunk-35LLVRFK.mjs → chunk-JZIO2A3B.mjs} +31 -31
- package/dist/{chunk-UDX2Q35T.mjs → chunk-LIHZTECW.mjs} +2 -1
- package/dist/chunk-LIHZTECW.mjs.map +1 -0
- package/dist/{cs-RSV675WU.mjs → cs-FAN66Q2F.mjs} +2 -1
- package/dist/cs-FAN66Q2F.mjs.map +1 -0
- package/dist/{da-CHXNPWJC.mjs → da-YBBIHI2O.mjs} +2 -1
- package/dist/da-YBBIHI2O.mjs.map +1 -0
- package/dist/{de-KPEZ53D4.mjs → de-MAYU33LB.mjs} +2 -1
- package/dist/de-MAYU33LB.mjs.map +1 -0
- package/dist/{el-MW2BME5T.mjs → el-MKGSWN4O.mjs} +2 -1
- package/dist/el-MKGSWN4O.mjs.map +1 -0
- package/dist/{en-EVMIX24Y.mjs → en-DDLIXJCU.mjs} +2 -2
- package/dist/{es-HQ24NYS3.mjs → es-52LHUWJD.mjs} +2 -1
- package/dist/es-52LHUWJD.mjs.map +1 -0
- package/dist/{fa-W34LRLHG.mjs → fa-FJICRANB.mjs} +2 -1
- package/dist/fa-FJICRANB.mjs.map +1 -0
- package/dist/{fi-3U44IGOA.mjs → fi-O455XFCR.mjs} +2 -1
- package/dist/fi-O455XFCR.mjs.map +1 -0
- package/dist/{fr-N7DKX6NN.mjs → fr-TXIXHOOE.mjs} +2 -1
- package/dist/fr-TXIXHOOE.mjs.map +1 -0
- package/dist/{he-CS4WRXN3.mjs → he-JBSOX5IN.mjs} +2 -1
- package/dist/he-JBSOX5IN.mjs.map +1 -0
- package/dist/{hi-GJDY46KA.mjs → hi-KGHI3XVT.mjs} +2 -1
- package/dist/hi-KGHI3XVT.mjs.map +1 -0
- package/dist/{id-WAEZJK2Y.mjs → id-5OCPPZLO.mjs} +2 -1
- package/dist/id-5OCPPZLO.mjs.map +1 -0
- package/dist/index.d.mts +102 -106
- package/dist/index.mjs +1814 -1450
- package/dist/index.mjs.map +1 -1
- package/dist/{it-VDNDMZPU.mjs → it-PNBBZSM2.mjs} +2 -1
- package/dist/it-PNBBZSM2.mjs.map +1 -0
- package/dist/{ja-5PEH56J5.mjs → ja-LDD7R3TJ.mjs} +2 -1
- package/dist/ja-LDD7R3TJ.mjs.map +1 -0
- package/dist/{ko-JYPL3WVA.mjs → ko-F47ZDEY3.mjs} +2 -1
- package/dist/ko-F47ZDEY3.mjs.map +1 -0
- package/dist/{ms-5PZVW76T.mjs → ms-Z7LMXJWL.mjs} +2 -1
- package/dist/ms-Z7LMXJWL.mjs.map +1 -0
- package/dist/{nl-YXES36KM.mjs → nl-6SJFBPJ3.mjs} +2 -1
- package/dist/nl-6SJFBPJ3.mjs.map +1 -0
- package/dist/{no-XRA2UCQD.mjs → no-YXPBPSGF.mjs} +2 -1
- package/dist/no-YXPBPSGF.mjs.map +1 -0
- package/dist/{pl-WH6LJA5G.mjs → pl-P4AZ2QME.mjs} +2 -1
- package/dist/pl-P4AZ2QME.mjs.map +1 -0
- package/dist/{pt-7GAG57BM.mjs → pt-LHWUS6U6.mjs} +2 -1
- package/dist/pt-LHWUS6U6.mjs.map +1 -0
- package/dist/{ro-BTDDRB7N.mjs → ro-EA5J2ZON.mjs} +2 -1
- package/dist/ro-EA5J2ZON.mjs.map +1 -0
- package/dist/{sv-7V5C2IT4.mjs → sv-DATBS3UQ.mjs} +2 -1
- package/dist/sv-DATBS3UQ.mjs.map +1 -0
- package/dist/test-utils.mjs +2 -2
- package/dist/{th-LPKYLBX5.mjs → th-WTFJRWPT.mjs} +2 -1
- package/dist/th-WTFJRWPT.mjs.map +1 -0
- package/dist/{tr-DU4RQL4M.mjs → tr-IKO3RXOX.mjs} +2 -1
- package/dist/tr-IKO3RXOX.mjs.map +1 -0
- package/dist/{uk-36UHTDDI.mjs → uk-CF6CTTRK.mjs} +2 -1
- package/dist/uk-CF6CTTRK.mjs.map +1 -0
- package/dist/{vi-GDHOUZDH.mjs → vi-AJLTXPZQ.mjs} +2 -1
- package/dist/vi-AJLTXPZQ.mjs.map +1 -0
- package/dist/{zh-TYUID4XZ.mjs → zh-U3ORHHYH.mjs} +2 -1
- package/dist/zh-U3ORHHYH.mjs.map +1 -0
- package/package.json +6 -2
- package/src/components/resource/AnnotateView.tsx +0 -4
- package/src/components/resource/AnnotationHistory.tsx +12 -13
- package/src/components/resource/BrowseView.tsx +8 -16
- package/src/components/resource/HistoryEvent.tsx +3 -4
- package/src/components/resource/ResourceViewer.tsx +174 -201
- package/src/components/resource/event-formatting.ts +316 -0
- package/src/components/resource/panels/AssessmentPanel.tsx +37 -9
- package/src/components/resource/panels/CollaborationPanel.tsx +20 -13
- package/src/components/resource/panels/CommentsPanel.tsx +38 -9
- package/src/components/resource/panels/ReferencesPanel.tsx +39 -14
- package/src/components/resource/panels/StatisticsPanel.tsx +9 -19
- package/src/components/resource/panels/TaggingPanel.tsx +27 -0
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +28 -21
- package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +547 -0
- package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +10 -0
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +10 -0
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +564 -0
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +8 -15
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +13 -6
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +147 -78
- package/src/styles/motivations/motivation-assessment.css +28 -0
- package/src/styles/patterns/panel-helpers.css +26 -0
- package/translations/ar.json +1 -0
- package/translations/bn.json +1 -0
- package/translations/cs.json +1 -0
- package/translations/da.json +1 -0
- package/translations/de.json +1 -0
- package/translations/el.json +1 -0
- package/translations/en.json +1 -0
- package/translations/es.json +1 -0
- package/translations/fa.json +1 -0
- package/translations/fi.json +1 -0
- package/translations/fr.json +1 -0
- package/translations/he.json +1 -0
- package/translations/hi.json +1 -0
- package/translations/id.json +1 -0
- package/translations/it.json +1 -0
- package/translations/ja.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +1 -0
- package/translations/nl.json +1 -0
- package/translations/no.json +1 -0
- package/translations/pl.json +1 -0
- package/translations/pt.json +1 -0
- package/translations/ro.json +1 -0
- package/translations/sv.json +1 -0
- package/translations/th.json +1 -0
- package/translations/tr.json +1 -0
- package/translations/uk.json +1 -0
- package/translations/vi.json +1 -0
- package/translations/zh.json +1 -0
- package/dist/ar-RNNSPLQB.mjs.map +0 -1
- package/dist/bn-S2CDL7EC.mjs.map +0 -1
- package/dist/chunk-UDX2Q35T.mjs.map +0 -1
- package/dist/cs-RSV675WU.mjs.map +0 -1
- package/dist/da-CHXNPWJC.mjs.map +0 -1
- package/dist/de-KPEZ53D4.mjs.map +0 -1
- package/dist/el-MW2BME5T.mjs.map +0 -1
- package/dist/es-HQ24NYS3.mjs.map +0 -1
- package/dist/fa-W34LRLHG.mjs.map +0 -1
- package/dist/fi-3U44IGOA.mjs.map +0 -1
- package/dist/fr-N7DKX6NN.mjs.map +0 -1
- package/dist/he-CS4WRXN3.mjs.map +0 -1
- package/dist/hi-GJDY46KA.mjs.map +0 -1
- package/dist/id-WAEZJK2Y.mjs.map +0 -1
- package/dist/it-VDNDMZPU.mjs.map +0 -1
- package/dist/ja-5PEH56J5.mjs.map +0 -1
- package/dist/ko-JYPL3WVA.mjs.map +0 -1
- package/dist/ms-5PZVW76T.mjs.map +0 -1
- package/dist/nl-YXES36KM.mjs.map +0 -1
- package/dist/no-XRA2UCQD.mjs.map +0 -1
- package/dist/pl-WH6LJA5G.mjs.map +0 -1
- package/dist/pt-7GAG57BM.mjs.map +0 -1
- package/dist/ro-BTDDRB7N.mjs.map +0 -1
- package/dist/sv-7V5C2IT4.mjs.map +0 -1
- package/dist/th-LPKYLBX5.mjs.map +0 -1
- package/dist/tr-DU4RQL4M.mjs.map +0 -1
- package/dist/uk-36UHTDDI.mjs.map +0 -1
- package/dist/vi-GDHOUZDH.mjs.map +0 -1
- package/dist/zh-TYUID4XZ.mjs.map +0 -1
- /package/dist/{chunk-35LLVRFK.mjs.map → chunk-JZIO2A3B.mjs.map} +0 -0
- /package/dist/{en-EVMIX24Y.mjs.map → en-DDLIXJCU.mjs.map} +0 -0
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* This component handles the UI rendering and state management for the resource viewer.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React, { useState, useEffect, useCallback
|
|
8
|
+
import React, { useState, useEffect, useCallback } from 'react';
|
|
9
9
|
import type { components, ResourceUri, GenerationContext, Selector } from '@semiont/api-client';
|
|
10
10
|
import { getLanguage, getPrimaryRepresentation, annotationUri, resourceUri, resourceAnnotationUri } from '@semiont/api-client';
|
|
11
11
|
import { createCancelDetectionHandler, ANNOTATORS } from '@semiont/react-ui';
|
|
@@ -20,6 +20,7 @@ import { Toolbar } from '@semiont/react-ui';
|
|
|
20
20
|
import { useResourceLoadingAnnouncements } from '@semiont/react-ui';
|
|
21
21
|
import type { GenerationOptions } from '@semiont/react-ui';
|
|
22
22
|
import { ResourceViewer } from '@semiont/react-ui';
|
|
23
|
+
import { MakeMeaningEventBusProvider, useMakeMeaningEvents } from '@semiont/react-ui';
|
|
23
24
|
|
|
24
25
|
type SemiontResource = components['schemas']['ResourceDescriptor'];
|
|
25
26
|
type Annotation = components['schemas']['Annotation'];
|
|
@@ -106,7 +107,6 @@ export interface ResourceViewerPageProps {
|
|
|
106
107
|
onUnarchive: () => Promise<void>;
|
|
107
108
|
onClone: () => Promise<void>;
|
|
108
109
|
onUpdateAnnotationBody: (annotationUri: string, data: any) => Promise<void>;
|
|
109
|
-
onRefetchAnnotations: () => Promise<void>;
|
|
110
110
|
|
|
111
111
|
/**
|
|
112
112
|
* Annotation CRUD callbacks
|
|
@@ -154,7 +154,8 @@ export interface ResourceViewerPageProps {
|
|
|
154
154
|
GenerationConfigModal: React.ComponentType<any>;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
-
|
|
157
|
+
// Inner component that has access to event bus
|
|
158
|
+
function ResourceViewerPageInner({
|
|
158
159
|
resource,
|
|
159
160
|
rUri,
|
|
160
161
|
content,
|
|
@@ -175,7 +176,6 @@ export function ResourceViewerPage({
|
|
|
175
176
|
onUnarchive,
|
|
176
177
|
onClone,
|
|
177
178
|
onUpdateAnnotationBody,
|
|
178
|
-
onRefetchAnnotations,
|
|
179
179
|
onCreateAnnotation,
|
|
180
180
|
onTriggerSparkleAnimation,
|
|
181
181
|
onClearNewAnnotationId,
|
|
@@ -189,6 +189,8 @@ export function ResourceViewerPage({
|
|
|
189
189
|
SearchResourcesModal,
|
|
190
190
|
GenerationConfigModal,
|
|
191
191
|
}: ResourceViewerPageProps) {
|
|
192
|
+
// Get unified event bus for subscribing to UI events
|
|
193
|
+
const eventBus = useMakeMeaningEvents();
|
|
192
194
|
// Resource loading announcements
|
|
193
195
|
const {
|
|
194
196
|
announceResourceLoading,
|
|
@@ -203,17 +205,19 @@ export function ResourceViewerPage({
|
|
|
203
205
|
const primaryMediaType = primaryRep?.mediaType;
|
|
204
206
|
const primaryByteSize = primaryRep?.byteSize;
|
|
205
207
|
|
|
206
|
-
|
|
208
|
+
// Annotate mode state - read-only copy for sidebar panel coordination
|
|
209
|
+
// ResourceViewer manages the authoritative state and persists to localStorage
|
|
210
|
+
const [annotateMode, _setAnnotateMode] = useState(() => {
|
|
207
211
|
if (typeof window !== 'undefined') {
|
|
208
212
|
return localStorage.getItem('annotateMode') === 'true';
|
|
209
213
|
}
|
|
210
214
|
return false;
|
|
211
215
|
});
|
|
212
216
|
|
|
213
|
-
// Unified annotation state (motivation-agnostic)
|
|
214
|
-
const [focusedAnnotationId,
|
|
217
|
+
// Unified annotation state (motivation-agnostic) - used by sidebar panels
|
|
218
|
+
const [focusedAnnotationId, _setFocusedAnnotationId] = useState<string | null>(null);
|
|
215
219
|
const [hoveredAnnotationId, setHoveredAnnotationId] = useState<string | null>(null);
|
|
216
|
-
|
|
220
|
+
// scrollToAnnotationId removed - ResourceViewer now manages scroll state internally
|
|
217
221
|
|
|
218
222
|
// Unified pending annotation - all human-created annotations flow through this
|
|
219
223
|
const [pendingAnnotation, setPendingAnnotation] = useState<PendingAnnotation | null>(null);
|
|
@@ -243,20 +247,11 @@ export function ResourceViewerPage({
|
|
|
243
247
|
}
|
|
244
248
|
}, [onTriggerSparkleAnimation]);
|
|
245
249
|
|
|
246
|
-
// Handle event click - scroll
|
|
247
|
-
const handleEventClick = useCallback((
|
|
248
|
-
|
|
250
|
+
// Handle event click - scroll handled internally by ResourceViewer now
|
|
251
|
+
const handleEventClick = useCallback((_annotationId: string | null) => {
|
|
252
|
+
// ResourceViewer now manages scroll state internally
|
|
249
253
|
}, []);
|
|
250
254
|
|
|
251
|
-
// Handle annotate mode toggle - memoized
|
|
252
|
-
const handleAnnotateModeToggle = useCallback(() => {
|
|
253
|
-
const newMode = !annotateMode;
|
|
254
|
-
setAnnotateMode(newMode);
|
|
255
|
-
if (typeof window !== 'undefined') {
|
|
256
|
-
localStorage.setItem('annotateMode', newMode.toString());
|
|
257
|
-
}
|
|
258
|
-
}, [annotateMode]);
|
|
259
|
-
|
|
260
255
|
// Use SSE-based document generation progress - provides inline sparkle animation
|
|
261
256
|
const {
|
|
262
257
|
progress: generationProgress,
|
|
@@ -273,9 +268,7 @@ export function ResourceViewerPage({
|
|
|
273
268
|
});
|
|
274
269
|
|
|
275
270
|
// Generic detection context for all annotation types
|
|
276
|
-
|
|
277
|
-
// Note: State setters (setDetectingMotivation, setMotivationDetectionProgress) are stable and don't need deps
|
|
278
|
-
const detectionContext = useMemo(() => ({
|
|
271
|
+
const detectionContext = {
|
|
279
272
|
client,
|
|
280
273
|
rUri,
|
|
281
274
|
setDetectingMotivation,
|
|
@@ -284,15 +277,15 @@ export function ResourceViewerPage({
|
|
|
284
277
|
cacheManager,
|
|
285
278
|
showSuccess,
|
|
286
279
|
showError
|
|
287
|
-
}
|
|
280
|
+
};
|
|
288
281
|
|
|
289
282
|
// Generic cancel handler (works for all detection types)
|
|
290
|
-
const handleCancelDetection =
|
|
283
|
+
const handleCancelDetection = useCallback(
|
|
291
284
|
() => createCancelDetectionHandler({
|
|
292
285
|
detectionStreamRef,
|
|
293
286
|
setDetectingMotivation,
|
|
294
287
|
setMotivationDetectionProgress
|
|
295
|
-
}),
|
|
288
|
+
})(),
|
|
296
289
|
[]
|
|
297
290
|
);
|
|
298
291
|
|
|
@@ -393,7 +386,103 @@ export function ResourceViewerPage({
|
|
|
393
386
|
|
|
394
387
|
setActivePanel(MOTIVATION_TO_TAB[pending.motivation] || 'annotations');
|
|
395
388
|
setPendingAnnotation(pending);
|
|
396
|
-
}, []);
|
|
389
|
+
}, [setActivePanel]);
|
|
390
|
+
|
|
391
|
+
// Subscribe to UI events from ResourceViewer
|
|
392
|
+
useEffect(() => {
|
|
393
|
+
const handleCommentRequested = (selection: any) => {
|
|
394
|
+
handleAnnotationRequested({
|
|
395
|
+
selector: {
|
|
396
|
+
type: 'TextQuoteSelector',
|
|
397
|
+
exact: selection.exact,
|
|
398
|
+
start: selection.start,
|
|
399
|
+
end: selection.end,
|
|
400
|
+
...(selection.prefix && { prefix: selection.prefix }),
|
|
401
|
+
...(selection.suffix && { suffix: selection.suffix })
|
|
402
|
+
},
|
|
403
|
+
motivation: 'commenting'
|
|
404
|
+
});
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
const handleTagRequested = (selection: any) => {
|
|
408
|
+
handleAnnotationRequested({
|
|
409
|
+
selector: {
|
|
410
|
+
type: 'TextQuoteSelector',
|
|
411
|
+
exact: selection.exact,
|
|
412
|
+
start: selection.start,
|
|
413
|
+
end: selection.end,
|
|
414
|
+
...(selection.prefix && { prefix: selection.prefix }),
|
|
415
|
+
...(selection.suffix && { suffix: selection.suffix })
|
|
416
|
+
},
|
|
417
|
+
motivation: 'tagging'
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const handleAssessmentRequested = (selection: any) => {
|
|
422
|
+
handleAnnotationRequested({
|
|
423
|
+
selector: {
|
|
424
|
+
type: 'TextQuoteSelector',
|
|
425
|
+
exact: selection.exact,
|
|
426
|
+
start: selection.start,
|
|
427
|
+
end: selection.end,
|
|
428
|
+
...(selection.prefix && { prefix: selection.prefix }),
|
|
429
|
+
...(selection.suffix && { suffix: selection.suffix })
|
|
430
|
+
},
|
|
431
|
+
motivation: 'assessing'
|
|
432
|
+
});
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
const handleReferenceRequested = (selection: any) => {
|
|
436
|
+
// Build selector based on what's present in the selection
|
|
437
|
+
let selector: any;
|
|
438
|
+
|
|
439
|
+
if (selection.svgSelector) {
|
|
440
|
+
selector = {
|
|
441
|
+
type: 'SvgSelector',
|
|
442
|
+
value: selection.svgSelector
|
|
443
|
+
};
|
|
444
|
+
} else if (selection.fragmentSelector) {
|
|
445
|
+
selector = {
|
|
446
|
+
type: 'FragmentSelector',
|
|
447
|
+
value: selection.fragmentSelector,
|
|
448
|
+
...(selection.conformsTo && { conformsTo: selection.conformsTo })
|
|
449
|
+
};
|
|
450
|
+
} else {
|
|
451
|
+
selector = {
|
|
452
|
+
type: 'TextQuoteSelector',
|
|
453
|
+
exact: selection.exact,
|
|
454
|
+
start: selection.start,
|
|
455
|
+
end: selection.end,
|
|
456
|
+
...(selection.prefix && { prefix: selection.prefix }),
|
|
457
|
+
...(selection.suffix && { suffix: selection.suffix })
|
|
458
|
+
};
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
handleAnnotationRequested({
|
|
462
|
+
selector,
|
|
463
|
+
motivation: 'linking'
|
|
464
|
+
});
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
// Handle cancel pending annotation
|
|
468
|
+
const handleCancelPending = () => {
|
|
469
|
+
setPendingAnnotation(null);
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
eventBus.on('ui:selection:comment-requested', handleCommentRequested);
|
|
473
|
+
eventBus.on('ui:selection:tag-requested', handleTagRequested);
|
|
474
|
+
eventBus.on('ui:selection:assessment-requested', handleAssessmentRequested);
|
|
475
|
+
eventBus.on('ui:selection:reference-requested', handleReferenceRequested);
|
|
476
|
+
eventBus.on('ui:annotation:cancel-pending', handleCancelPending);
|
|
477
|
+
|
|
478
|
+
return () => {
|
|
479
|
+
eventBus.off('ui:selection:comment-requested', handleCommentRequested);
|
|
480
|
+
eventBus.off('ui:selection:tag-requested', handleTagRequested);
|
|
481
|
+
eventBus.off('ui:selection:assessment-requested', handleAssessmentRequested);
|
|
482
|
+
eventBus.off('ui:selection:reference-requested', handleReferenceRequested);
|
|
483
|
+
eventBus.off('ui:annotation:cancel-pending', handleCancelPending);
|
|
484
|
+
};
|
|
485
|
+
}, [eventBus, handleAnnotationRequested]);
|
|
397
486
|
|
|
398
487
|
// Manual tag creation handler
|
|
399
488
|
// Shared UI handlers - same across all annotation types
|
|
@@ -470,9 +559,7 @@ export function ResourceViewerPage({
|
|
|
470
559
|
await onCreateAnnotation(rUri, motivation, selector, body);
|
|
471
560
|
setPendingAnnotation(null);
|
|
472
561
|
|
|
473
|
-
|
|
474
|
-
await onRefetchAnnotations();
|
|
475
|
-
}
|
|
562
|
+
// Cache invalidation now handled by annotation:added event
|
|
476
563
|
|
|
477
564
|
if (annotatorConfig.create.successMessage) {
|
|
478
565
|
const message = annotatorConfig.create.successMessage.replace('{value}', args[1] || '');
|
|
@@ -482,47 +569,33 @@ export function ResourceViewerPage({
|
|
|
482
569
|
console.error(`Failed to create ${annotatorConfig.internalType}:`, error);
|
|
483
570
|
showError(`Failed to create ${annotatorConfig.displayName.toLowerCase()}`);
|
|
484
571
|
}
|
|
485
|
-
}, [pendingAnnotation, onCreateAnnotation, rUri,
|
|
572
|
+
}, [pendingAnnotation, onCreateAnnotation, rUri, showSuccess, showError]);
|
|
486
573
|
|
|
487
574
|
// Group annotations by type using static ANNOTATORS
|
|
488
|
-
const
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
result[key as keyof typeof result].push(ann);
|
|
503
|
-
}
|
|
575
|
+
const result = {
|
|
576
|
+
highlights: [] as Annotation[],
|
|
577
|
+
references: [] as Annotation[],
|
|
578
|
+
assessments: [] as Annotation[],
|
|
579
|
+
comments: [] as Annotation[],
|
|
580
|
+
tags: [] as Annotation[]
|
|
581
|
+
};
|
|
582
|
+
|
|
583
|
+
for (const ann of annotations) {
|
|
584
|
+
const annotator = Object.values(ANNOTATORS).find(a => a.matchesAnnotation(ann));
|
|
585
|
+
if (annotator) {
|
|
586
|
+
const key = annotator.internalType + 's'; // highlight -> highlights
|
|
587
|
+
if (result[key as keyof typeof result]) {
|
|
588
|
+
result[key as keyof typeof result].push(ann);
|
|
504
589
|
}
|
|
505
590
|
}
|
|
591
|
+
}
|
|
506
592
|
|
|
507
|
-
|
|
508
|
-
}, [annotations]);
|
|
509
|
-
|
|
510
|
-
// Memoize resource with content to prevent infinite re-renders
|
|
511
|
-
const resourceWithContent = useMemo(
|
|
512
|
-
() => ({ ...resource, content }),
|
|
513
|
-
[resource, content]
|
|
514
|
-
);
|
|
593
|
+
const groups = result;
|
|
515
594
|
|
|
516
|
-
//
|
|
517
|
-
const
|
|
518
|
-
// Don't refetch immediately - the SSE event will trigger invalidation after projection is updated
|
|
519
|
-
}, []);
|
|
595
|
+
// Combine resource with content
|
|
596
|
+
const resourceWithContent = { ...resource, content };
|
|
520
597
|
|
|
521
|
-
|
|
522
|
-
setActivePanel('annotations');
|
|
523
|
-
setFocusedAnnotationId(annotationId);
|
|
524
|
-
setTimeout(() => setFocusedAnnotationId(null), 3000);
|
|
525
|
-
}, []);
|
|
598
|
+
// handleAnnotationClickAndFocus removed - ResourceViewer now manages focus/click state internally
|
|
526
599
|
|
|
527
600
|
// Document rendering
|
|
528
601
|
return (
|
|
@@ -567,21 +640,8 @@ export function ResourceViewerPage({
|
|
|
567
640
|
<ResourceViewer
|
|
568
641
|
resource={resourceWithContent}
|
|
569
642
|
annotations={groups}
|
|
570
|
-
onRefetchAnnotations={handleRefetchAnnotations}
|
|
571
|
-
annotateMode={annotateMode}
|
|
572
|
-
onAnnotateModeToggle={handleAnnotateModeToggle}
|
|
573
643
|
onAnnotationRequested={handleAnnotationRequested}
|
|
574
|
-
onCommentClick={handleAnnotationClickAndFocus}
|
|
575
|
-
onReferenceClick={handleAnnotationClickAndFocus}
|
|
576
|
-
onHighlightClick={handleAnnotationClickAndFocus}
|
|
577
|
-
onAssessmentClick={handleAnnotationClickAndFocus}
|
|
578
|
-
onTagClick={handleAnnotationClickAndFocus}
|
|
579
644
|
generatingReferenceId={generationProgress?.referenceId ?? null}
|
|
580
|
-
onAnnotationHover={setHoveredAnnotationId}
|
|
581
|
-
onCommentHover={setHoveredAnnotationId}
|
|
582
|
-
hoveredAnnotationId={hoveredAnnotationId}
|
|
583
|
-
hoveredCommentId={hoveredAnnotationId}
|
|
584
|
-
scrollToAnnotationId={scrollToAnnotationId}
|
|
585
645
|
showLineNumbers={showLineNumbers}
|
|
586
646
|
annotators={ANNOTATORS}
|
|
587
647
|
/>
|
|
@@ -724,7 +784,7 @@ export function ResourceViewerPage({
|
|
|
724
784
|
}],
|
|
725
785
|
});
|
|
726
786
|
showSuccess('Reference linked successfully');
|
|
727
|
-
|
|
787
|
+
// Cache invalidation now handled by annotation:updated event
|
|
728
788
|
setSearchModalOpen(false);
|
|
729
789
|
setPendingReferenceId(null);
|
|
730
790
|
} catch (error) {
|
|
@@ -755,3 +815,12 @@ export function ResourceViewerPage({
|
|
|
755
815
|
</div>
|
|
756
816
|
);
|
|
757
817
|
}
|
|
818
|
+
|
|
819
|
+
// Outer component that wraps MakeMeaningEventBusProvider
|
|
820
|
+
export function ResourceViewerPage(props: ResourceViewerPageProps) {
|
|
821
|
+
return (
|
|
822
|
+
<MakeMeaningEventBusProvider rUri={props.rUri}>
|
|
823
|
+
<ResourceViewerPageInner {...props} />
|
|
824
|
+
</MakeMeaningEventBusProvider>
|
|
825
|
+
);
|
|
826
|
+
}
|
|
@@ -139,6 +139,34 @@
|
|
|
139
139
|
border-color: var(--semiont-color-error-dark);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
/* ============================================
|
|
143
|
+
Annotation Prompt (Pending State)
|
|
144
|
+
============================================ */
|
|
145
|
+
.semiont-annotation-prompt[data-type="assessment"] {
|
|
146
|
+
background: var(--semiont-motivation-assessment-panel-bg);
|
|
147
|
+
padding: var(--semiont-panel-padding);
|
|
148
|
+
border-radius: var(--semiont-radius-md);
|
|
149
|
+
border: 2px dashed var(--semiont-motivation-assessment-border);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
[data-theme="dark"] .semiont-annotation-prompt[data-type="assessment"] {
|
|
153
|
+
background: var(--semiont-motivation-assessment-panel-bg-dark);
|
|
154
|
+
border-color: var(--semiont-motivation-assessment-border);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.semiont-annotation-prompt__quote[data-type="assessment"] {
|
|
158
|
+
background: var(--semiont-bg-primary);
|
|
159
|
+
padding: var(--semiont-panel-padding-sm);
|
|
160
|
+
border-radius: var(--semiont-radius-sm);
|
|
161
|
+
border-left: 3px solid var(--semiont-motivation-assessment-primary);
|
|
162
|
+
margin-bottom: var(--semiont-panel-gap-sm);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
[data-theme="dark"] .semiont-annotation-prompt__quote[data-type="assessment"] {
|
|
166
|
+
background: var(--semiont-bg-secondary);
|
|
167
|
+
border-left-color: var(--semiont-motivation-assessment-dark-primary);
|
|
168
|
+
}
|
|
169
|
+
|
|
142
170
|
/* ============================================
|
|
143
171
|
Button Styling
|
|
144
172
|
============================================ */
|
|
@@ -11,6 +11,32 @@
|
|
|
11
11
|
- panels/*.css (individual panel styles)
|
|
12
12
|
============================================ */
|
|
13
13
|
|
|
14
|
+
/* ============================================
|
|
15
|
+
Annotation Prompt (Pending Annotation Forms)
|
|
16
|
+
Shared footer and char-count styles
|
|
17
|
+
============================================ */
|
|
18
|
+
.semiont-annotation-prompt__footer {
|
|
19
|
+
display: flex;
|
|
20
|
+
justify-content: space-between;
|
|
21
|
+
align-items: center;
|
|
22
|
+
margin-top: 0.5rem;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.semiont-annotation-prompt__char-count {
|
|
26
|
+
font-size: var(--semiont-text-xs);
|
|
27
|
+
color: var(--semiont-text-tertiary);
|
|
28
|
+
margin-left: 0.5rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
[data-theme="dark"] .semiont-annotation-prompt__char-count {
|
|
32
|
+
color: var(--semiont-text-tertiary);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.semiont-annotation-prompt__actions {
|
|
36
|
+
display: flex;
|
|
37
|
+
gap: 0.5rem;
|
|
38
|
+
}
|
|
39
|
+
|
|
14
40
|
/* Panel Button Layouts (kept for backward compatibility) */
|
|
15
41
|
.semiont-panel-button-full {
|
|
16
42
|
width: 100%;
|
package/translations/ar.json
CHANGED
package/translations/bn.json
CHANGED
package/translations/cs.json
CHANGED
package/translations/da.json
CHANGED
package/translations/de.json
CHANGED
package/translations/el.json
CHANGED
package/translations/en.json
CHANGED
package/translations/es.json
CHANGED
package/translations/fa.json
CHANGED
package/translations/fi.json
CHANGED
package/translations/fr.json
CHANGED
package/translations/he.json
CHANGED
package/translations/hi.json
CHANGED
package/translations/id.json
CHANGED
package/translations/it.json
CHANGED
package/translations/ja.json
CHANGED
package/translations/ko.json
CHANGED
package/translations/ms.json
CHANGED
package/translations/nl.json
CHANGED
package/translations/no.json
CHANGED
package/translations/pl.json
CHANGED
package/translations/pt.json
CHANGED
package/translations/ro.json
CHANGED
package/translations/sv.json
CHANGED
package/translations/th.json
CHANGED