@semiont/react-ui 0.2.33-build.79 → 0.2.33-build.81

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 (213) hide show
  1. package/dist/EventBusContext-CJjL_cCf.d.mts +462 -0
  2. package/dist/{PdfAnnotationCanvas.client-ADC4FFSE.mjs → PdfAnnotationCanvas.client-RAJRPQLU.mjs} +42 -27
  3. package/dist/PdfAnnotationCanvas.client-RAJRPQLU.mjs.map +1 -0
  4. package/dist/{ar-EMHEHPCJ.mjs → ar-4ZEORRW2.mjs} +7 -4
  5. package/dist/ar-4ZEORRW2.mjs.map +1 -0
  6. package/dist/{bn-OVCI4F6X.mjs → bn-SEDE5BQJ.mjs} +7 -4
  7. package/dist/bn-SEDE5BQJ.mjs.map +1 -0
  8. package/dist/{chunk-LIHZTECW.mjs → chunk-D7NBW4RV.mjs} +7 -4
  9. package/dist/chunk-D7NBW4RV.mjs.map +1 -0
  10. package/dist/{chunk-JZIO2A3B.mjs → chunk-QB52Q7EQ.mjs} +206 -146
  11. package/dist/chunk-QB52Q7EQ.mjs.map +1 -0
  12. package/dist/{cs-FAN66Q2F.mjs → cs-7W4WF5WD.mjs} +7 -4
  13. package/dist/cs-7W4WF5WD.mjs.map +1 -0
  14. package/dist/{da-YBBIHI2O.mjs → da-75XGBCBK.mjs} +7 -4
  15. package/dist/da-75XGBCBK.mjs.map +1 -0
  16. package/dist/{de-MAYU33LB.mjs → de-ODJVFLHM.mjs} +7 -4
  17. package/dist/de-ODJVFLHM.mjs.map +1 -0
  18. package/dist/{el-MKGSWN4O.mjs → el-C4PM4WB3.mjs} +7 -4
  19. package/dist/el-C4PM4WB3.mjs.map +1 -0
  20. package/dist/{en-DDLIXJCU.mjs → en-KJCJQ4OO.mjs} +2 -2
  21. package/dist/{es-52LHUWJD.mjs → es-WD33R7QL.mjs} +7 -4
  22. package/dist/es-WD33R7QL.mjs.map +1 -0
  23. package/dist/{fa-FJICRANB.mjs → fa-2BP6V56P.mjs} +7 -4
  24. package/dist/fa-2BP6V56P.mjs.map +1 -0
  25. package/dist/{fi-O455XFCR.mjs → fi-USRRW24J.mjs} +7 -4
  26. package/dist/fi-USRRW24J.mjs.map +1 -0
  27. package/dist/{fr-TXIXHOOE.mjs → fr-EC5S6WVF.mjs} +7 -4
  28. package/dist/fr-EC5S6WVF.mjs.map +1 -0
  29. package/dist/{he-JBSOX5IN.mjs → he-7TBVIKAA.mjs} +7 -4
  30. package/dist/he-7TBVIKAA.mjs.map +1 -0
  31. package/dist/{hi-KGHI3XVT.mjs → hi-FO4VIZLA.mjs} +7 -4
  32. package/dist/hi-FO4VIZLA.mjs.map +1 -0
  33. package/dist/{id-5OCPPZLO.mjs → id-7U7GGVWY.mjs} +7 -4
  34. package/dist/id-7U7GGVWY.mjs.map +1 -0
  35. package/dist/index.css +123 -85
  36. package/dist/index.css.map +1 -1
  37. package/dist/index.d.mts +715 -574
  38. package/dist/index.mjs +3898 -3575
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/{it-PNBBZSM2.mjs → it-Y4OPL6I2.mjs} +7 -4
  41. package/dist/it-Y4OPL6I2.mjs.map +1 -0
  42. package/dist/{ja-LDD7R3TJ.mjs → ja-PK7SQL55.mjs} +7 -4
  43. package/dist/ja-PK7SQL55.mjs.map +1 -0
  44. package/dist/{ko-F47ZDEY3.mjs → ko-L25PXMYD.mjs} +7 -4
  45. package/dist/ko-L25PXMYD.mjs.map +1 -0
  46. package/dist/{ms-Z7LMXJWL.mjs → ms-STH777QM.mjs} +7 -4
  47. package/dist/ms-STH777QM.mjs.map +1 -0
  48. package/dist/{nl-6SJFBPJ3.mjs → nl-Y7LECDDR.mjs} +7 -4
  49. package/dist/nl-Y7LECDDR.mjs.map +1 -0
  50. package/dist/{no-YXPBPSGF.mjs → no-KEKCEWU6.mjs} +7 -4
  51. package/dist/no-KEKCEWU6.mjs.map +1 -0
  52. package/dist/{pl-P4AZ2QME.mjs → pl-7A7OC75O.mjs} +7 -4
  53. package/dist/pl-7A7OC75O.mjs.map +1 -0
  54. package/dist/{pt-LHWUS6U6.mjs → pt-35HTM7RA.mjs} +7 -4
  55. package/dist/pt-35HTM7RA.mjs.map +1 -0
  56. package/dist/{ro-EA5J2ZON.mjs → ro-VAWL5KQA.mjs} +7 -4
  57. package/dist/ro-VAWL5KQA.mjs.map +1 -0
  58. package/dist/{sv-DATBS3UQ.mjs → sv-7ZK5EQEB.mjs} +7 -4
  59. package/dist/sv-7ZK5EQEB.mjs.map +1 -0
  60. package/dist/test-utils.d.mts +18 -8
  61. package/dist/test-utils.mjs +36 -14
  62. package/dist/test-utils.mjs.map +1 -1
  63. package/dist/{th-WTFJRWPT.mjs → th-UDWZ4X34.mjs} +7 -4
  64. package/dist/th-UDWZ4X34.mjs.map +1 -0
  65. package/dist/{tr-IKO3RXOX.mjs → tr-4WMPK3UX.mjs} +7 -4
  66. package/dist/tr-4WMPK3UX.mjs.map +1 -0
  67. package/dist/{uk-CF6CTTRK.mjs → uk-SSLASQYJ.mjs} +7 -4
  68. package/dist/uk-SSLASQYJ.mjs.map +1 -0
  69. package/dist/{vi-AJLTXPZQ.mjs → vi-IF42Z5PU.mjs} +7 -4
  70. package/dist/vi-IF42Z5PU.mjs.map +1 -0
  71. package/dist/{zh-U3ORHHYH.mjs → zh-HRQTNTAI.mjs} +7 -4
  72. package/dist/zh-HRQTNTAI.mjs.map +1 -0
  73. package/package.json +3 -1
  74. package/src/components/CodeMirrorRenderer.tsx +66 -93
  75. package/src/components/DetectionProgressWidget.tsx +16 -5
  76. package/src/components/ResizeHandle.tsx +10 -4
  77. package/src/components/SessionExpiryBanner.tsx +2 -3
  78. package/src/components/SessionTimer.tsx +3 -3
  79. package/src/components/Toolbar.tsx +18 -9
  80. package/src/components/__tests__/SessionTimer.test.tsx +33 -33
  81. package/src/components/annotation/AnnotateToolbar.tsx +17 -15
  82. package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +165 -63
  83. package/src/components/annotation/annotation-entries.css +10 -0
  84. package/src/components/annotation-popups/JsonLdView.tsx +8 -2
  85. package/src/components/image-annotation/AnnotationOverlay.tsx +42 -22
  86. package/src/components/image-annotation/SvgDrawingCanvas.tsx +27 -30
  87. package/src/components/layout/__tests__/LeftSidebar.test.tsx +12 -33
  88. package/src/components/layout/__tests__/PageLayout.test.tsx +37 -32
  89. package/src/components/layout/__tests__/UnifiedHeader.test.tsx +21 -40
  90. package/src/components/modals/ResourceSearchModal.tsx +2 -2
  91. package/src/components/modals/SearchModal.tsx +1 -1
  92. package/src/components/navigation/CollapsibleResourceNavigation.tsx +14 -9
  93. package/src/components/navigation/NavigationTabs.css +36 -24
  94. package/src/components/navigation/ObservableLink.tsx +91 -0
  95. package/src/components/navigation/SimpleNavigation.tsx +20 -16
  96. package/src/components/navigation/SortableResourceTab.tsx +11 -5
  97. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +51 -26
  98. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +28 -22
  99. package/src/components/resource/AnnotateView.tsx +64 -134
  100. package/src/components/resource/BrowseView.tsx +86 -166
  101. package/src/components/resource/HistoryEvent.tsx +13 -7
  102. package/src/components/resource/ResourceViewer.tsx +122 -264
  103. package/src/components/resource/__tests__/BrowseView.test.tsx +631 -0
  104. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +231 -0
  105. package/src/components/resource/panels/AssessmentEntry.tsx +25 -33
  106. package/src/components/resource/panels/AssessmentPanel.tsx +106 -28
  107. package/src/components/resource/panels/CommentEntry.tsx +38 -32
  108. package/src/components/resource/panels/CommentsPanel.tsx +121 -28
  109. package/src/components/resource/panels/DetectSection.css +36 -1
  110. package/src/components/resource/panels/DetectSection.tsx +49 -15
  111. package/src/components/resource/panels/HighlightEntry.tsx +25 -33
  112. package/src/components/resource/panels/HighlightPanel.tsx +100 -25
  113. package/src/components/resource/panels/ReferenceEntry.tsx +61 -75
  114. package/src/components/resource/panels/ReferencesPanel.tsx +134 -42
  115. package/src/components/resource/panels/ResourceInfoPanel.tsx +47 -48
  116. package/src/components/resource/panels/TagEntry.tsx +25 -33
  117. package/src/components/resource/panels/TaggingPanel.tsx +118 -30
  118. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +30 -92
  119. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +129 -110
  120. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +86 -78
  121. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +144 -149
  122. package/src/components/resource/panels/__tests__/DetectSection.test.tsx +480 -0
  123. package/src/components/resource/panels/__tests__/HighlightPanel.detectionProgress.test.tsx +362 -0
  124. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +226 -111
  125. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +117 -61
  126. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +128 -106
  127. package/src/components/settings/SettingsPanel.tsx +15 -12
  128. package/src/features/admin-devops/__tests__/AdminDevOpsPage.test.tsx +1 -46
  129. package/src/features/admin-devops/components/AdminDevOpsPage.tsx +0 -9
  130. package/src/features/admin-security/__tests__/AdminSecurityPage.test.tsx +0 -3
  131. package/src/features/admin-security/components/AdminSecurityPage.tsx +0 -9
  132. package/src/features/admin-users/__tests__/AdminUsersPage.test.tsx +0 -3
  133. package/src/features/admin-users/components/AdminUsersPage.tsx +0 -9
  134. package/src/features/moderate-entity-tags/__tests__/EntityTagsPage.test.tsx +0 -3
  135. package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +1 -9
  136. package/src/features/moderate-recent/__tests__/RecentDocumentsPage.test.tsx +0 -32
  137. package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +1 -9
  138. package/src/features/moderate-tag-schemas/__tests__/TagSchemasPage.test.tsx +0 -32
  139. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -9
  140. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +51 -54
  141. package/src/features/resource-compose/components/ResourceComposePage.tsx +3 -13
  142. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +39 -45
  143. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +9 -13
  144. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +234 -0
  145. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +234 -0
  146. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +388 -0
  147. package/src/features/resource-viewer/__tests__/DetectionProgressDismissal.test.tsx +318 -0
  148. package/src/features/resource-viewer/__tests__/GenerationFlowIntegration.test.tsx +503 -0
  149. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +139 -93
  150. package/src/features/resource-viewer/__tests__/detection-progress-flow.test.tsx +322 -0
  151. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +341 -524
  152. package/translations/ar.json +6 -3
  153. package/translations/bn.json +6 -3
  154. package/translations/cs.json +6 -3
  155. package/translations/da.json +6 -3
  156. package/translations/de.json +6 -3
  157. package/translations/el.json +6 -3
  158. package/translations/en.json +6 -3
  159. package/translations/es.json +6 -3
  160. package/translations/fa.json +6 -3
  161. package/translations/fi.json +6 -3
  162. package/translations/fr.json +6 -3
  163. package/translations/he.json +6 -3
  164. package/translations/hi.json +6 -3
  165. package/translations/id.json +6 -3
  166. package/translations/it.json +6 -3
  167. package/translations/ja.json +6 -3
  168. package/translations/ko.json +6 -3
  169. package/translations/ms.json +6 -3
  170. package/translations/nl.json +6 -3
  171. package/translations/no.json +6 -3
  172. package/translations/pl.json +6 -3
  173. package/translations/pt.json +6 -3
  174. package/translations/ro.json +6 -3
  175. package/translations/sv.json +6 -3
  176. package/translations/th.json +6 -3
  177. package/translations/tr.json +6 -3
  178. package/translations/uk.json +6 -3
  179. package/translations/vi.json +6 -3
  180. package/translations/zh.json +6 -3
  181. package/dist/PdfAnnotationCanvas.client-ADC4FFSE.mjs.map +0 -1
  182. package/dist/TranslationManager-Co_5fSxl.d.mts +0 -118
  183. package/dist/ar-EMHEHPCJ.mjs.map +0 -1
  184. package/dist/bn-OVCI4F6X.mjs.map +0 -1
  185. package/dist/chunk-JZIO2A3B.mjs.map +0 -1
  186. package/dist/chunk-LIHZTECW.mjs.map +0 -1
  187. package/dist/cs-FAN66Q2F.mjs.map +0 -1
  188. package/dist/da-YBBIHI2O.mjs.map +0 -1
  189. package/dist/de-MAYU33LB.mjs.map +0 -1
  190. package/dist/el-MKGSWN4O.mjs.map +0 -1
  191. package/dist/es-52LHUWJD.mjs.map +0 -1
  192. package/dist/fa-FJICRANB.mjs.map +0 -1
  193. package/dist/fi-O455XFCR.mjs.map +0 -1
  194. package/dist/fr-TXIXHOOE.mjs.map +0 -1
  195. package/dist/he-JBSOX5IN.mjs.map +0 -1
  196. package/dist/hi-KGHI3XVT.mjs.map +0 -1
  197. package/dist/id-5OCPPZLO.mjs.map +0 -1
  198. package/dist/it-PNBBZSM2.mjs.map +0 -1
  199. package/dist/ja-LDD7R3TJ.mjs.map +0 -1
  200. package/dist/ko-F47ZDEY3.mjs.map +0 -1
  201. package/dist/ms-Z7LMXJWL.mjs.map +0 -1
  202. package/dist/nl-6SJFBPJ3.mjs.map +0 -1
  203. package/dist/no-YXPBPSGF.mjs.map +0 -1
  204. package/dist/pl-P4AZ2QME.mjs.map +0 -1
  205. package/dist/pt-LHWUS6U6.mjs.map +0 -1
  206. package/dist/ro-EA5J2ZON.mjs.map +0 -1
  207. package/dist/sv-DATBS3UQ.mjs.map +0 -1
  208. package/dist/th-WTFJRWPT.mjs.map +0 -1
  209. package/dist/tr-IKO3RXOX.mjs.map +0 -1
  210. package/dist/uk-CF6CTTRK.mjs.map +0 -1
  211. package/dist/vi-AJLTXPZQ.mjs.map +0 -1
  212. package/dist/zh-U3ORHHYH.mjs.map +0 -1
  213. /package/dist/{en-DDLIXJCU.mjs.map → en-KJCJQ4OO.mjs.map} +0 -0
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
- import { useRef, useCallback, useEffect, lazy, Suspense } from 'react';
4
- import type { components, Selector } from '@semiont/api-client';
3
+ import { useRef, useEffect, useCallback, lazy, Suspense } from 'react';
4
+ import type { components } from '@semiont/api-client';
5
5
  import { getTextPositionSelector, getTextQuoteSelector, getTargetSelector, getMimeCategory, isPdfMimeType, resourceUri as toResourceUri } from '@semiont/api-client';
6
- import type { Annotator } from '../../lib/annotation-registry';
6
+ import { ANNOTATORS } from '../../lib/annotation-registry';
7
7
  import { SvgDrawingCanvas } from '../image-annotation/SvgDrawingCanvas';
8
8
  import { useResourceAnnotations } from '../../contexts/ResourceAnnotationsContext';
9
9
  import { findTextWithContext } from '@semiont/api-client';
@@ -12,24 +12,19 @@ import { findTextWithContext } from '@semiont/api-client';
12
12
  const PdfAnnotationCanvas = lazy(() => import('../pdf-annotation/PdfAnnotationCanvas.client').then(mod => ({ default: mod.PdfAnnotationCanvas })));
13
13
 
14
14
  type Annotation = components['schemas']['Annotation'];
15
- type Motivation = components['schemas']['Motivation'];
16
-
17
- // Unified pending annotation type - all human-created annotations flow through this
18
- interface PendingAnnotation {
19
- selector: Selector | Selector[];
20
- motivation: Motivation;
21
- }
22
15
 
23
16
  import { CodeMirrorRenderer } from '../CodeMirrorRenderer';
24
17
  import type { TextSegment } from '../CodeMirrorRenderer';
25
18
  import type { EditorView } from '@codemirror/view';
19
+ import { useEventBus } from '../../contexts/EventBusContext';
20
+ import { useEventSubscriptions } from '../../contexts/useEventSubscription';
26
21
 
27
22
  // Type augmentation for custom DOM properties
28
23
  interface EnrichedHTMLElement extends HTMLElement {
29
24
  __cmView?: EditorView;
30
25
  }
31
26
  import { AnnotateToolbar, type SelectionMotivation, type ClickAction, type ShapeType } from '../annotation/AnnotateToolbar';
32
- import type { AnnotationsCollection, AnnotationHandlers, AnnotationCreationHandler, AnnotationUIState } from '../../types/annotation-props';
27
+ import type { AnnotationsCollection, AnnotationUIState } from '../../types/annotation-props';
33
28
 
34
29
  // Re-export for convenience
35
30
  export type { SelectionMotivation, ClickAction, ShapeType };
@@ -39,23 +34,14 @@ interface Props {
39
34
  mimeType?: string;
40
35
  resourceUri?: string;
41
36
  annotations: AnnotationsCollection;
42
- handlers?: AnnotationHandlers;
43
- creationHandler?: AnnotationCreationHandler;
44
37
  uiState: AnnotationUIState;
45
38
  onUIStateChange?: (state: Partial<AnnotationUIState>) => void;
46
39
  editable?: boolean;
47
40
  enableWidgets?: boolean;
48
- onEntityTypeClick?: (entityType: string) => void;
49
- onReferenceNavigate?: (documentId: string) => void;
50
- onUnresolvedReferenceClick?: (annotation: Annotation) => void;
51
41
  getTargetDocumentName?: (documentId: string) => string | undefined;
52
42
  generatingReferenceId?: string | null;
53
- onDeleteAnnotation?: (annotation: Annotation) => void;
54
43
  showLineNumbers?: boolean;
55
44
  annotateMode: boolean;
56
- onAnnotateModeToggle: () => void;
57
- onAnnotationRequested?: (pending: PendingAnnotation) => void;
58
- annotators: Record<string, Annotator>;
59
45
  }
60
46
 
61
47
  /**
@@ -159,30 +145,31 @@ function segmentTextWithAnnotations(content: string, annotations: Annotation[]):
159
145
  return segments;
160
146
  }
161
147
 
148
+ /**
149
+ * View component for annotating resources with text selection and drawing
150
+ *
151
+ * @emits annotation:requested - User requested to create annotation. Payload: { selector: Selector | Selector[], motivation: SelectionMotivation }
152
+ * @subscribes toolbar:selection-changed - Toolbar selection changed. Payload: { motivation: string | null }
153
+ * @subscribes toolbar:click-changed - Toolbar click action changed. Payload: { action: string }
154
+ * @subscribes toolbar:shape-changed - Toolbar shape changed. Payload: { shape: string }
155
+ * @subscribes annotation:hover - Annotation hovered. Payload: { annotationId: string | null }
156
+ */
162
157
  export function AnnotateView({
163
158
  content,
164
159
  mimeType = 'text/plain',
165
160
  resourceUri,
166
161
  annotations,
167
- handlers,
168
- creationHandler,
169
162
  uiState,
170
163
  onUIStateChange,
171
164
  enableWidgets = false,
172
- onEntityTypeClick,
173
- onReferenceNavigate,
174
- onUnresolvedReferenceClick,
175
165
  getTargetDocumentName,
176
166
  generatingReferenceId,
177
- onDeleteAnnotation,
178
167
  showLineNumbers = false,
179
- annotateMode,
180
- onAnnotateModeToggle,
181
- onAnnotationRequested,
182
- annotators
168
+ annotateMode
183
169
  }: Props) {
184
170
  const { newAnnotationIds } = useResourceAnnotations();
185
171
  const containerRef = useRef<HTMLDivElement>(null);
172
+ const eventBus = useEventBus();
186
173
 
187
174
  const category = getMimeCategory(mimeType);
188
175
 
@@ -191,59 +178,38 @@ export function AnnotateView({
191
178
  const allAnnotations = [...highlights, ...references, ...assessments, ...comments, ...tags];
192
179
  const segments = segmentTextWithAnnotations(content, allAnnotations);
193
180
 
194
- // Extract individual handlers from grouped objects
195
- const onAnnotationClick = handlers?.onClick;
196
- const onAnnotationHover = handlers?.onHover;
197
- const onCommentHover = handlers?.onCommentHover;
198
-
199
- const onCreate = creationHandler?.onCreate;
200
-
201
181
  // Extract UI state
202
182
  const { selectedMotivation, selectedClick, selectedShape, hoveredAnnotationId, hoveredCommentId, scrollToAnnotationId } = uiState;
203
183
 
204
- console.log('[AnnotateView] Current UI state:', {
205
- selectedMotivation,
206
- selectedShape,
207
- selectedClick,
208
- annotateMode
184
+ // Store onUIStateChange in ref to avoid dependency issues
185
+ const onUIStateChangeRef = useRef(onUIStateChange);
186
+ onUIStateChangeRef.current = onUIStateChange;
187
+
188
+ // Toolbar event handlers (extracted to avoid inline arrow functions)
189
+ const handleToolbarSelectionChanged = useCallback(({ motivation }: { motivation: string | null }) => {
190
+ onUIStateChangeRef.current?.({ selectedMotivation: motivation as SelectionMotivation | null });
191
+ }, []);
192
+
193
+ const handleToolbarClickChanged = useCallback(({ action }: { action: string }) => {
194
+ onUIStateChangeRef.current?.({ selectedClick: action as ClickAction });
195
+ }, []);
196
+
197
+ const handleToolbarShapeChanged = useCallback(({ shape }: { shape: string }) => {
198
+ onUIStateChangeRef.current?.({ selectedShape: shape as ShapeType });
199
+ }, []);
200
+
201
+ const handleAnnotationHover = useCallback(({ annotationId }: { annotationId: string | null }) => {
202
+ onUIStateChangeRef.current?.({ hoveredAnnotationId: annotationId });
203
+ }, []);
204
+
205
+ // Subscribe to toolbar events and annotation hover
206
+ useEventSubscriptions({
207
+ 'toolbar:selection-changed': handleToolbarSelectionChanged,
208
+ 'toolbar:click-changed': handleToolbarClickChanged,
209
+ 'toolbar:shape-changed': handleToolbarShapeChanged,
210
+ 'annotation:hover': handleAnnotationHover,
209
211
  });
210
212
 
211
- // UI state change handlers
212
- const onSelectionChange = (motivation: SelectionMotivation | null) => {
213
- console.log('[AnnotateView] onSelectionChange called with:', motivation);
214
- onUIStateChange?.({ selectedMotivation: motivation });
215
- };
216
- const onClickChange = (motivation: ClickAction) => {
217
- onUIStateChange?.({ selectedClick: motivation });
218
- };
219
- const onShapeChange = (shape: ShapeType) => {
220
- onUIStateChange?.({ selectedShape: shape });
221
- };
222
-
223
- // Wrapper for annotation hover that routes based on registry metadata
224
- const handleAnnotationHover = useCallback((annotationId: string | null) => {
225
- if (annotationId) {
226
- const annotation = allAnnotations.find(a => a.id === annotationId);
227
- const metadata = annotation ? Object.values(annotators).find(a => a.matchesAnnotation(annotation!)) : null;
228
-
229
- // Route to side panel if annotation type has one
230
- if (metadata?.hasSidePanel) {
231
- // Clear the other hover state when switching
232
- if (onAnnotationHover) onAnnotationHover(null);
233
- if (onCommentHover) onCommentHover(annotationId);
234
- return;
235
- } else {
236
- // Clear the other hover state when switching
237
- if (onCommentHover) onCommentHover(null);
238
- if (onAnnotationHover) onAnnotationHover(annotationId);
239
- return;
240
- }
241
- }
242
- // Clear both when null
243
- if (onAnnotationHover) onAnnotationHover(null);
244
- if (onCommentHover) onCommentHover(null);
245
- }, [allAnnotations, onAnnotationHover, onCommentHover, annotators]);
246
-
247
213
  // Handle text annotation with sparkle or immediate creation
248
214
  useEffect(() => {
249
215
  const container = containerRef.current;
@@ -261,7 +227,15 @@ export function AnnotateView({
261
227
  }
262
228
  };
263
229
 
264
- const handleMouseUp = (_e: MouseEvent) => {
230
+ const handleMouseUp = (e: MouseEvent) => {
231
+ // Skip if the mouseUp came from PDF or image canvas
232
+ // (those components handle their own annotation:requested events)
233
+ const target = e.target as Element;
234
+ if (target.closest('.semiont-pdf-annotation-canvas') ||
235
+ target.closest('.semiont-svg-drawing-canvas')) {
236
+ return;
237
+ }
238
+
265
239
  const selection = window.getSelection();
266
240
  if (!selection || selection.isCollapsed || !selection.toString()) {
267
241
  clickedOnAnnotation = false;
@@ -294,8 +268,8 @@ export function AnnotateView({
294
268
  const context = extractContext(content, start, end);
295
269
 
296
270
  // Unified flow: all text annotations use BOTH TextPositionSelector and TextQuoteSelector
297
- if (selectedMotivation && onAnnotationRequested) {
298
- onAnnotationRequested({
271
+ if (selectedMotivation) {
272
+ eventBus.emit('annotation:requested', {
299
273
  selector: [
300
274
  {
301
275
  type: 'TextPositionSelector',
@@ -328,8 +302,8 @@ export function AnnotateView({
328
302
  const context = extractContext(content, start, end);
329
303
 
330
304
  // Unified flow: all text annotations use BOTH TextPositionSelector and TextQuoteSelector
331
- if (selectedMotivation && onAnnotationRequested) {
332
- onAnnotationRequested({
305
+ if (selectedMotivation) {
306
+ eventBus.emit('annotation:requested', {
333
307
  selector: [
334
308
  {
335
309
  type: 'TextPositionSelector',
@@ -360,7 +334,7 @@ export function AnnotateView({
360
334
  container.removeEventListener('mouseup', handleMouseUp);
361
335
  container.removeEventListener('mousedown', handleMouseDown);
362
336
  };
363
- }, [selectedMotivation, onCreate, content]);
337
+ }, [selectedMotivation, content]);
364
338
 
365
339
  // Route to appropriate viewer based on MIME type category
366
340
  switch (category) {
@@ -370,19 +344,14 @@ export function AnnotateView({
370
344
  <AnnotateToolbar
371
345
  selectedMotivation={selectedMotivation}
372
346
  selectedClick={selectedClick}
373
- onSelectionChange={onSelectionChange || (() => {})}
374
- onClickChange={onClickChange || (() => {})}
375
347
  mediaType={mimeType}
376
348
  annotateMode={annotateMode}
377
- onAnnotateModeToggle={onAnnotateModeToggle}
378
- annotators={annotators}
349
+ annotators={ANNOTATORS}
379
350
  />
380
351
  <div className="semiont-annotate-view__content">
381
352
  <CodeMirrorRenderer
382
353
  content={content}
383
354
  segments={segments}
384
- {...(onAnnotationClick && { onAnnotationClick })}
385
- onAnnotationHover={handleAnnotationHover}
386
355
  editable={false}
387
356
  newAnnotationIds={newAnnotationIds}
388
357
  {...(hoveredAnnotationId !== undefined && { hoveredAnnotationId })}
@@ -391,13 +360,9 @@ export function AnnotateView({
391
360
  sourceView={true}
392
361
  showLineNumbers={showLineNumbers}
393
362
  enableWidgets={enableWidgets}
394
- {...(onEntityTypeClick && { onEntityTypeClick })}
395
- {...(onReferenceNavigate && { onReferenceNavigate })}
396
- {...(onUnresolvedReferenceClick && { onUnresolvedReferenceClick })}
363
+ eventBus={eventBus}
397
364
  {...(getTargetDocumentName && { getTargetDocumentName })}
398
365
  {...(generatingReferenceId !== undefined && { generatingReferenceId })}
399
- {...(onDeleteAnnotation && { onDeleteAnnotation })}
400
- annotators={annotators}
401
366
  />
402
367
 
403
368
  </div>
@@ -413,15 +378,11 @@ export function AnnotateView({
413
378
  <AnnotateToolbar
414
379
  selectedMotivation={selectedMotivation}
415
380
  selectedClick={selectedClick}
416
- onSelectionChange={onSelectionChange}
417
- onClickChange={onClickChange}
418
381
  showShapeGroup={true}
419
382
  selectedShape={selectedShape}
420
- onShapeChange={onShapeChange}
421
383
  mediaType={mimeType}
422
384
  annotateMode={annotateMode}
423
- onAnnotateModeToggle={onAnnotateModeToggle}
424
- annotators={annotators}
385
+ annotators={ANNOTATORS}
425
386
  />
426
387
  <div className="semiont-annotate-view__content">
427
388
  {resourceUri && (
@@ -431,21 +392,7 @@ export function AnnotateView({
431
392
  existingAnnotations={allAnnotations}
432
393
  drawingMode={selectedMotivation ? selectedShape : null}
433
394
  selectedMotivation={selectedMotivation}
434
- onAnnotationCreate={async (fragmentSelector) => {
435
- if (!selectedMotivation) return;
436
-
437
- // Unified flow: all annotations go through pending state
438
- onAnnotationRequested?.({
439
- selector: {
440
- type: 'FragmentSelector',
441
- conformsTo: 'http://tools.ietf.org/rfc/rfc3778',
442
- value: fragmentSelector
443
- },
444
- motivation: selectedMotivation
445
- });
446
- }}
447
- {...(onAnnotationClick && { onAnnotationClick })}
448
- {...(onAnnotationHover && { onAnnotationHover: handleAnnotationHover })}
395
+ eventBus={eventBus}
449
396
  hoveredAnnotationId={hoveredCommentId || hoveredAnnotationId || null}
450
397
  />
451
398
  </Suspense>
@@ -461,15 +408,11 @@ export function AnnotateView({
461
408
  <AnnotateToolbar
462
409
  selectedMotivation={selectedMotivation}
463
410
  selectedClick={selectedClick}
464
- onSelectionChange={onSelectionChange}
465
- onClickChange={onClickChange}
466
411
  showShapeGroup={true}
467
412
  selectedShape={selectedShape}
468
- onShapeChange={onShapeChange}
469
413
  mediaType={mimeType}
470
414
  annotateMode={annotateMode}
471
- onAnnotateModeToggle={onAnnotateModeToggle}
472
- annotators={annotators}
415
+ annotators={ANNOTATORS}
473
416
  />
474
417
  <div className="semiont-annotate-view__content">
475
418
  {resourceUri && (
@@ -478,20 +421,7 @@ export function AnnotateView({
478
421
  existingAnnotations={allAnnotations}
479
422
  drawingMode={selectedMotivation ? selectedShape : null}
480
423
  selectedMotivation={selectedMotivation}
481
- onAnnotationCreate={async (svg) => {
482
- if (!selectedMotivation) return;
483
-
484
- // Unified flow: all annotations go through pending state
485
- onAnnotationRequested?.({
486
- selector: {
487
- type: 'SvgSelector',
488
- value: svg
489
- },
490
- motivation: selectedMotivation
491
- });
492
- }}
493
- {...(onAnnotationClick && { onAnnotationClick })}
494
- {...(onAnnotationHover && { onAnnotationHover: handleAnnotationHover })}
424
+ eventBus={eventBus}
495
425
  hoveredAnnotationId={hoveredCommentId || hoveredAnnotationId || null}
496
426
  />
497
427
  )}