@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.
Files changed (147) hide show
  1. package/dist/{ar-RNNSPLQB.mjs → ar-EMHEHPCJ.mjs} +2 -1
  2. package/dist/ar-EMHEHPCJ.mjs.map +1 -0
  3. package/dist/{bn-S2CDL7EC.mjs → bn-OVCI4F6X.mjs} +2 -1
  4. package/dist/bn-OVCI4F6X.mjs.map +1 -0
  5. package/dist/{chunk-35LLVRFK.mjs → chunk-JZIO2A3B.mjs} +31 -31
  6. package/dist/{chunk-UDX2Q35T.mjs → chunk-LIHZTECW.mjs} +2 -1
  7. package/dist/chunk-LIHZTECW.mjs.map +1 -0
  8. package/dist/{cs-RSV675WU.mjs → cs-FAN66Q2F.mjs} +2 -1
  9. package/dist/cs-FAN66Q2F.mjs.map +1 -0
  10. package/dist/{da-CHXNPWJC.mjs → da-YBBIHI2O.mjs} +2 -1
  11. package/dist/da-YBBIHI2O.mjs.map +1 -0
  12. package/dist/{de-KPEZ53D4.mjs → de-MAYU33LB.mjs} +2 -1
  13. package/dist/de-MAYU33LB.mjs.map +1 -0
  14. package/dist/{el-MW2BME5T.mjs → el-MKGSWN4O.mjs} +2 -1
  15. package/dist/el-MKGSWN4O.mjs.map +1 -0
  16. package/dist/{en-EVMIX24Y.mjs → en-DDLIXJCU.mjs} +2 -2
  17. package/dist/{es-HQ24NYS3.mjs → es-52LHUWJD.mjs} +2 -1
  18. package/dist/es-52LHUWJD.mjs.map +1 -0
  19. package/dist/{fa-W34LRLHG.mjs → fa-FJICRANB.mjs} +2 -1
  20. package/dist/fa-FJICRANB.mjs.map +1 -0
  21. package/dist/{fi-3U44IGOA.mjs → fi-O455XFCR.mjs} +2 -1
  22. package/dist/fi-O455XFCR.mjs.map +1 -0
  23. package/dist/{fr-N7DKX6NN.mjs → fr-TXIXHOOE.mjs} +2 -1
  24. package/dist/fr-TXIXHOOE.mjs.map +1 -0
  25. package/dist/{he-CS4WRXN3.mjs → he-JBSOX5IN.mjs} +2 -1
  26. package/dist/he-JBSOX5IN.mjs.map +1 -0
  27. package/dist/{hi-GJDY46KA.mjs → hi-KGHI3XVT.mjs} +2 -1
  28. package/dist/hi-KGHI3XVT.mjs.map +1 -0
  29. package/dist/{id-WAEZJK2Y.mjs → id-5OCPPZLO.mjs} +2 -1
  30. package/dist/id-5OCPPZLO.mjs.map +1 -0
  31. package/dist/index.d.mts +102 -106
  32. package/dist/index.mjs +1814 -1450
  33. package/dist/index.mjs.map +1 -1
  34. package/dist/{it-VDNDMZPU.mjs → it-PNBBZSM2.mjs} +2 -1
  35. package/dist/it-PNBBZSM2.mjs.map +1 -0
  36. package/dist/{ja-5PEH56J5.mjs → ja-LDD7R3TJ.mjs} +2 -1
  37. package/dist/ja-LDD7R3TJ.mjs.map +1 -0
  38. package/dist/{ko-JYPL3WVA.mjs → ko-F47ZDEY3.mjs} +2 -1
  39. package/dist/ko-F47ZDEY3.mjs.map +1 -0
  40. package/dist/{ms-5PZVW76T.mjs → ms-Z7LMXJWL.mjs} +2 -1
  41. package/dist/ms-Z7LMXJWL.mjs.map +1 -0
  42. package/dist/{nl-YXES36KM.mjs → nl-6SJFBPJ3.mjs} +2 -1
  43. package/dist/nl-6SJFBPJ3.mjs.map +1 -0
  44. package/dist/{no-XRA2UCQD.mjs → no-YXPBPSGF.mjs} +2 -1
  45. package/dist/no-YXPBPSGF.mjs.map +1 -0
  46. package/dist/{pl-WH6LJA5G.mjs → pl-P4AZ2QME.mjs} +2 -1
  47. package/dist/pl-P4AZ2QME.mjs.map +1 -0
  48. package/dist/{pt-7GAG57BM.mjs → pt-LHWUS6U6.mjs} +2 -1
  49. package/dist/pt-LHWUS6U6.mjs.map +1 -0
  50. package/dist/{ro-BTDDRB7N.mjs → ro-EA5J2ZON.mjs} +2 -1
  51. package/dist/ro-EA5J2ZON.mjs.map +1 -0
  52. package/dist/{sv-7V5C2IT4.mjs → sv-DATBS3UQ.mjs} +2 -1
  53. package/dist/sv-DATBS3UQ.mjs.map +1 -0
  54. package/dist/test-utils.mjs +2 -2
  55. package/dist/{th-LPKYLBX5.mjs → th-WTFJRWPT.mjs} +2 -1
  56. package/dist/th-WTFJRWPT.mjs.map +1 -0
  57. package/dist/{tr-DU4RQL4M.mjs → tr-IKO3RXOX.mjs} +2 -1
  58. package/dist/tr-IKO3RXOX.mjs.map +1 -0
  59. package/dist/{uk-36UHTDDI.mjs → uk-CF6CTTRK.mjs} +2 -1
  60. package/dist/uk-CF6CTTRK.mjs.map +1 -0
  61. package/dist/{vi-GDHOUZDH.mjs → vi-AJLTXPZQ.mjs} +2 -1
  62. package/dist/vi-AJLTXPZQ.mjs.map +1 -0
  63. package/dist/{zh-TYUID4XZ.mjs → zh-U3ORHHYH.mjs} +2 -1
  64. package/dist/zh-U3ORHHYH.mjs.map +1 -0
  65. package/package.json +6 -2
  66. package/src/components/resource/AnnotateView.tsx +0 -4
  67. package/src/components/resource/AnnotationHistory.tsx +12 -13
  68. package/src/components/resource/BrowseView.tsx +8 -16
  69. package/src/components/resource/HistoryEvent.tsx +3 -4
  70. package/src/components/resource/ResourceViewer.tsx +174 -201
  71. package/src/components/resource/event-formatting.ts +316 -0
  72. package/src/components/resource/panels/AssessmentPanel.tsx +37 -9
  73. package/src/components/resource/panels/CollaborationPanel.tsx +20 -13
  74. package/src/components/resource/panels/CommentsPanel.tsx +38 -9
  75. package/src/components/resource/panels/ReferencesPanel.tsx +39 -14
  76. package/src/components/resource/panels/StatisticsPanel.tsx +9 -19
  77. package/src/components/resource/panels/TaggingPanel.tsx +27 -0
  78. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +28 -21
  79. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +547 -0
  80. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +10 -0
  81. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +10 -0
  82. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +564 -0
  83. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +8 -15
  84. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +13 -6
  85. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +147 -78
  86. package/src/styles/motivations/motivation-assessment.css +28 -0
  87. package/src/styles/patterns/panel-helpers.css +26 -0
  88. package/translations/ar.json +1 -0
  89. package/translations/bn.json +1 -0
  90. package/translations/cs.json +1 -0
  91. package/translations/da.json +1 -0
  92. package/translations/de.json +1 -0
  93. package/translations/el.json +1 -0
  94. package/translations/en.json +1 -0
  95. package/translations/es.json +1 -0
  96. package/translations/fa.json +1 -0
  97. package/translations/fi.json +1 -0
  98. package/translations/fr.json +1 -0
  99. package/translations/he.json +1 -0
  100. package/translations/hi.json +1 -0
  101. package/translations/id.json +1 -0
  102. package/translations/it.json +1 -0
  103. package/translations/ja.json +1 -0
  104. package/translations/ko.json +1 -0
  105. package/translations/ms.json +1 -0
  106. package/translations/nl.json +1 -0
  107. package/translations/no.json +1 -0
  108. package/translations/pl.json +1 -0
  109. package/translations/pt.json +1 -0
  110. package/translations/ro.json +1 -0
  111. package/translations/sv.json +1 -0
  112. package/translations/th.json +1 -0
  113. package/translations/tr.json +1 -0
  114. package/translations/uk.json +1 -0
  115. package/translations/vi.json +1 -0
  116. package/translations/zh.json +1 -0
  117. package/dist/ar-RNNSPLQB.mjs.map +0 -1
  118. package/dist/bn-S2CDL7EC.mjs.map +0 -1
  119. package/dist/chunk-UDX2Q35T.mjs.map +0 -1
  120. package/dist/cs-RSV675WU.mjs.map +0 -1
  121. package/dist/da-CHXNPWJC.mjs.map +0 -1
  122. package/dist/de-KPEZ53D4.mjs.map +0 -1
  123. package/dist/el-MW2BME5T.mjs.map +0 -1
  124. package/dist/es-HQ24NYS3.mjs.map +0 -1
  125. package/dist/fa-W34LRLHG.mjs.map +0 -1
  126. package/dist/fi-3U44IGOA.mjs.map +0 -1
  127. package/dist/fr-N7DKX6NN.mjs.map +0 -1
  128. package/dist/he-CS4WRXN3.mjs.map +0 -1
  129. package/dist/hi-GJDY46KA.mjs.map +0 -1
  130. package/dist/id-WAEZJK2Y.mjs.map +0 -1
  131. package/dist/it-VDNDMZPU.mjs.map +0 -1
  132. package/dist/ja-5PEH56J5.mjs.map +0 -1
  133. package/dist/ko-JYPL3WVA.mjs.map +0 -1
  134. package/dist/ms-5PZVW76T.mjs.map +0 -1
  135. package/dist/nl-YXES36KM.mjs.map +0 -1
  136. package/dist/no-XRA2UCQD.mjs.map +0 -1
  137. package/dist/pl-WH6LJA5G.mjs.map +0 -1
  138. package/dist/pt-7GAG57BM.mjs.map +0 -1
  139. package/dist/ro-BTDDRB7N.mjs.map +0 -1
  140. package/dist/sv-7V5C2IT4.mjs.map +0 -1
  141. package/dist/th-LPKYLBX5.mjs.map +0 -1
  142. package/dist/tr-DU4RQL4M.mjs.map +0 -1
  143. package/dist/uk-36UHTDDI.mjs.map +0 -1
  144. package/dist/vi-GDHOUZDH.mjs.map +0 -1
  145. package/dist/zh-TYUID4XZ.mjs.map +0 -1
  146. /package/dist/{chunk-35LLVRFK.mjs.map → chunk-JZIO2A3B.mjs.map} +0 -0
  147. /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, useMemo } from 'react';
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
- export function ResourceViewerPage({
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
- const [annotateMode, setAnnotateMode] = useState(() => {
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, setFocusedAnnotationId] = useState<string | null>(null);
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
- const [scrollToAnnotationId, setScrollToAnnotationId] = useState<string | null>(null);
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 to annotation
247
- const handleEventClick = useCallback((annotationId: string | null) => {
248
- setScrollToAnnotationId(annotationId);
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
- // Memoized to keep stable reference
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
- }), [client, rUri, cacheManager, showSuccess, showError]);
280
+ };
288
281
 
289
282
  // Generic cancel handler (works for all detection types)
290
- const handleCancelDetection = React.useMemo(
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
- if (annotatorConfig.create.refetchAfter) {
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, onRefetchAnnotations, showSuccess, showError]);
572
+ }, [pendingAnnotation, onCreateAnnotation, rUri, showSuccess, showError]);
486
573
 
487
574
  // Group annotations by type using static ANNOTATORS
488
- const groups = useMemo(() => {
489
- const result = {
490
- highlights: [] as Annotation[],
491
- references: [] as Annotation[],
492
- assessments: [] as Annotation[],
493
- comments: [] as Annotation[],
494
- tags: [] as Annotation[]
495
- };
496
-
497
- for (const ann of annotations) {
498
- const annotator = Object.values(ANNOTATORS).find(a => a.matchesAnnotation(ann));
499
- if (annotator) {
500
- const key = annotator.internalType + 's'; // highlight -> highlights
501
- if (result[key as keyof typeof result]) {
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
- return result;
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
- // Memoize annotation click handlers to prevent infinite re-renders
517
- const handleRefetchAnnotations = useCallback(() => {
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
- const handleAnnotationClickAndFocus = useCallback((annotationId: string) => {
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
- await onRefetchAnnotations();
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%;
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generar",
218
218
  "find": "Buscar",
219
219
  "create": "Crear",
220
+ "cancel": "Cancelar",
220
221
  "incomingReferences": "Referencias Entrantes",
221
222
  "loading": "cargando...",
222
223
  "loadingEllipsis": "Cargando...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",
@@ -217,6 +217,7 @@
217
217
  "generate": "Generate",
218
218
  "find": "Find",
219
219
  "create": "Create",
220
+ "cancel": "Cancel",
220
221
  "incomingReferences": "Incoming References",
221
222
  "loading": "loading...",
222
223
  "loadingEllipsis": "Loading...",