@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
@@ -0,0 +1,462 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import mitt from 'mitt';
4
+ import { ResourceEvent } from '@semiont/core';
5
+ import { GenerationProgress as GenerationProgress$1, Selector, components, ResourceUri, GenerationContext } from '@semiont/api-client';
6
+
7
+ /**
8
+ * Open Resources Manager Interface
9
+ *
10
+ * Manages a list of open resources (documents/files) with persistence.
11
+ * This interface allows apps to provide their own implementation of resource management
12
+ * (localStorage, sessionStorage, database, etc.) while components remain framework-agnostic.
13
+ *
14
+ * Components accept this manager as a prop instead of consuming from Context.
15
+ *
16
+ * @example
17
+ * ```tsx
18
+ * // In app (e.g., frontend/src/hooks/useOpenResourcesManager.ts)
19
+ * export function useOpenResourcesManager(): OpenResourcesManager {
20
+ * const [openResources, setOpenResources] = useState<OpenResource[]>([]);
21
+ *
22
+ * // Implementation details...
23
+ *
24
+ * return {
25
+ * openResources,
26
+ * addResource,
27
+ * removeResource,
28
+ * updateResourceName,
29
+ * reorderResources
30
+ * };
31
+ * }
32
+ *
33
+ * // Pass to components as props
34
+ * <KnowledgeNavigation openResourcesManager={openResourcesManager} />
35
+ * ```
36
+ */
37
+ interface OpenResource {
38
+ /** Unique identifier for the resource */
39
+ id: string;
40
+ /** Display name of the resource */
41
+ name: string;
42
+ /** Timestamp when the resource was opened */
43
+ openedAt: number;
44
+ /** Order/position for manual sorting (optional for backward compatibility) */
45
+ order?: number;
46
+ /** Media type for icon display (e.g., 'application/pdf', 'text/plain') */
47
+ mediaType?: string;
48
+ }
49
+ interface OpenResourcesManager {
50
+ /** List of currently open resources */
51
+ openResources: OpenResource[];
52
+ /**
53
+ * Add a new resource to the open list or update if already exists
54
+ * @param id - Unique resource identifier
55
+ * @param name - Display name of the resource
56
+ * @param mediaType - Optional media type for icon display
57
+ */
58
+ addResource: (id: string, name: string, mediaType?: string) => void;
59
+ /**
60
+ * Remove a resource from the open list
61
+ * @param id - Resource identifier to remove
62
+ */
63
+ removeResource: (id: string) => void;
64
+ /**
65
+ * Update the display name of an open resource
66
+ * @param id - Resource identifier
67
+ * @param name - New display name
68
+ */
69
+ updateResourceName: (id: string, name: string) => void;
70
+ /**
71
+ * Reorder resources by moving from one index to another
72
+ * @param oldIndex - Current position index
73
+ * @param newIndex - Desired position index
74
+ */
75
+ reorderResources: (oldIndex: number, newIndex: number) => void;
76
+ }
77
+
78
+ /**
79
+ * Session management interface for handling authentication state and session expiry
80
+ * Apps implement this interface and pass it to SessionProvider
81
+ */
82
+ interface SessionState {
83
+ /** Whether the user is currently authenticated */
84
+ isAuthenticated: boolean;
85
+ /** When the session expires (null if not authenticated) */
86
+ expiresAt: Date | null;
87
+ /** Time in milliseconds until session expires (null if not authenticated) */
88
+ timeUntilExpiry: number | null;
89
+ /** Whether the session is expiring soon (< 5 minutes) */
90
+ isExpiringSoon: boolean;
91
+ }
92
+ interface SessionManager extends SessionState {
93
+ }
94
+
95
+ /**
96
+ * Translation management interface
97
+ * Apps implement this to provide translations using their preferred i18n library
98
+ */
99
+ interface TranslationManager {
100
+ /**
101
+ * Translate a key within a namespace
102
+ * @param namespace - Translation namespace (e.g., 'Toolbar', 'ResourceViewer')
103
+ * @param key - Translation key within the namespace
104
+ * @param params - Optional parameters for interpolation
105
+ * @returns Translated string
106
+ */
107
+ t: (namespace: string, key: string, params?: Record<string, any>) => string;
108
+ }
109
+
110
+ /**
111
+ * Progress type definitions for detection and generation flows
112
+ */
113
+
114
+ /**
115
+ * Common detection progress fields shared across all motivation types.
116
+ *
117
+ * The five motivations have different SSE progress shapes
118
+ * (ReferenceDetectionProgress uses entity-type steps; the others use percentage).
119
+ * This local type captures the subset of fields used by the detection UI
120
+ * (DetectionProgressWidget, useDetectionFlow).
121
+ */
122
+ interface DetectionProgress {
123
+ status: string;
124
+ message?: string;
125
+ /** Reference detection: currently scanning entity type */
126
+ currentEntityType?: string;
127
+ /** Reference detection: completed entity types with counts (frontend-only) */
128
+ completedEntityTypes?: Array<{
129
+ entityType: string;
130
+ foundCount: number;
131
+ }>;
132
+ /** Percentage-based motivations (highlight, assessment, comment, tag) */
133
+ percentage?: number;
134
+ /** Category-based motivations (tag) */
135
+ currentCategory?: string;
136
+ processedCategories?: number;
137
+ totalCategories?: number;
138
+ /** Request parameters for display in progress UI (frontend-only, added by annotation-registry) */
139
+ requestParams?: Array<{
140
+ label: string;
141
+ value: string;
142
+ }>;
143
+ }
144
+ /**
145
+ * Generation progress type (no extensions needed, re-export API type)
146
+ */
147
+ type GenerationProgress = GenerationProgress$1;
148
+
149
+ type Annotation = components['schemas']['Annotation'];
150
+ type Motivation = components['schemas']['Motivation'];
151
+ interface SelectionData {
152
+ exact: string;
153
+ start: number;
154
+ end: number;
155
+ svgSelector?: string;
156
+ fragmentSelector?: string;
157
+ conformsTo?: string;
158
+ prefix?: string;
159
+ suffix?: string;
160
+ }
161
+ /**
162
+ * Unified event map for all application events
163
+ *
164
+ * Consolidates events from:
165
+ * - MakeMeaningEventBus (document/annotation operations)
166
+ * - NavigationEventBus (navigation and sidebar UI)
167
+ * - GlobalSettingsEventBus (app-wide settings)
168
+ */
169
+ type EventMap = {
170
+ 'make-meaning:event': ResourceEvent;
171
+ 'detection:started': Extract<ResourceEvent, {
172
+ type: 'job.started';
173
+ }>;
174
+ 'detection:entity-found': Extract<ResourceEvent, {
175
+ type: 'annotation.added';
176
+ }>;
177
+ 'detection:completed': Extract<ResourceEvent, {
178
+ type: 'job.completed';
179
+ }>;
180
+ 'detection:failed': Extract<ResourceEvent, {
181
+ type: 'job.failed';
182
+ }>;
183
+ 'detection:progress': DetectionProgress;
184
+ 'annotation:added': Extract<ResourceEvent, {
185
+ type: 'annotation.added';
186
+ }>;
187
+ 'annotation:removed': Extract<ResourceEvent, {
188
+ type: 'annotation.removed';
189
+ }>;
190
+ 'annotation:updated': Extract<ResourceEvent, {
191
+ type: 'annotation.body.updated';
192
+ }>;
193
+ 'entity-tag:added': Extract<ResourceEvent, {
194
+ type: 'entitytag.added';
195
+ }>;
196
+ 'entity-tag:removed': Extract<ResourceEvent, {
197
+ type: 'entitytag.removed';
198
+ }>;
199
+ 'resource:archived': Extract<ResourceEvent, {
200
+ type: 'resource.archived';
201
+ }>;
202
+ 'resource:unarchived': Extract<ResourceEvent, {
203
+ type: 'resource.unarchived';
204
+ }>;
205
+ 'selection:comment-requested': SelectionData;
206
+ 'selection:tag-requested': SelectionData;
207
+ 'selection:assessment-requested': SelectionData;
208
+ 'selection:reference-requested': SelectionData;
209
+ 'annotation:requested': {
210
+ selector: Selector | Selector[];
211
+ motivation: Motivation;
212
+ };
213
+ 'annotation:cancel-pending': void;
214
+ 'annotation:hover': {
215
+ annotationId: string | null;
216
+ };
217
+ 'annotation:click': {
218
+ annotationId: string;
219
+ motivation: Motivation;
220
+ };
221
+ 'annotation:focus': {
222
+ annotationId: string | null;
223
+ };
224
+ 'annotation:sparkle': {
225
+ annotationId: string;
226
+ };
227
+ 'panel:toggle': {
228
+ panel: string;
229
+ };
230
+ 'panel:open': {
231
+ panel: string;
232
+ scrollToAnnotationId?: string;
233
+ motivation?: string;
234
+ };
235
+ 'panel:close': void;
236
+ 'view:mode-toggled': void;
237
+ 'toolbar:selection-changed': {
238
+ motivation: string | null;
239
+ };
240
+ 'toolbar:click-changed': {
241
+ action: string;
242
+ };
243
+ 'toolbar:shape-changed': {
244
+ shape: string;
245
+ };
246
+ 'navigation:sidebar-toggle': void;
247
+ 'navigation:resource-close': {
248
+ resourceId: string;
249
+ };
250
+ 'navigation:resource-reorder': {
251
+ oldIndex: number;
252
+ newIndex: number;
253
+ };
254
+ 'navigation:link-clicked': {
255
+ href: string;
256
+ label?: string;
257
+ };
258
+ 'navigation:router-push': {
259
+ path: string;
260
+ reason?: string;
261
+ };
262
+ 'navigation:external-navigate': {
263
+ url: string;
264
+ resourceId?: string;
265
+ cancelFallback: () => void;
266
+ };
267
+ 'navigation:reference-navigate': {
268
+ documentId: string;
269
+ };
270
+ 'navigation:entity-type-clicked': {
271
+ entityType: string;
272
+ };
273
+ 'settings:theme-changed': {
274
+ theme: 'light' | 'dark' | 'system';
275
+ };
276
+ 'settings:line-numbers-toggled': void;
277
+ 'settings:locale-changed': {
278
+ locale: string;
279
+ };
280
+ 'resource:archive': void;
281
+ 'resource:unarchive': void;
282
+ 'resource:clone': void;
283
+ 'job:cancel-requested': {
284
+ jobType: 'detection' | 'generation';
285
+ };
286
+ 'annotation:create': {
287
+ motivation: Motivation;
288
+ selector: Selector | Selector[];
289
+ body: components['schemas']['AnnotationBody'][];
290
+ };
291
+ 'annotation:created': {
292
+ annotation: Annotation;
293
+ };
294
+ 'annotation:create-failed': {
295
+ error: Error;
296
+ };
297
+ 'annotation:delete': {
298
+ annotationId: string;
299
+ };
300
+ 'annotation:deleted': {
301
+ annotationId: string;
302
+ };
303
+ 'annotation:delete-failed': {
304
+ error: Error;
305
+ };
306
+ 'annotation:update-body': {
307
+ annotationUri: string;
308
+ resourceId: string;
309
+ operations: Array<{
310
+ op: 'add' | 'remove' | 'replace';
311
+ item?: components['schemas']['AnnotationBody'];
312
+ oldItem?: components['schemas']['AnnotationBody'];
313
+ newItem?: components['schemas']['AnnotationBody'];
314
+ }>;
315
+ };
316
+ 'annotation:body-updated': {
317
+ annotationUri: string;
318
+ };
319
+ 'annotation:body-update-failed': {
320
+ error: Error;
321
+ };
322
+ 'detection:start': {
323
+ motivation: Motivation;
324
+ options: {
325
+ instructions?: string;
326
+ /** Comment tone */
327
+ tone?: 'scholarly' | 'explanatory' | 'conversational' | 'technical' | 'analytical' | 'critical' | 'balanced' | 'constructive';
328
+ density?: number;
329
+ entityTypes?: string[];
330
+ includeDescriptiveReferences?: boolean;
331
+ schemaId?: string;
332
+ categories?: string[];
333
+ };
334
+ };
335
+ 'detection:complete': {
336
+ motivation?: Motivation;
337
+ resourceUri?: ResourceUri;
338
+ progress?: DetectionProgress;
339
+ };
340
+ 'detection:cancelled': void;
341
+ 'detection:dismiss-progress': void;
342
+ 'generation:start': {
343
+ annotationUri: string;
344
+ resourceUri: string;
345
+ options: {
346
+ title: string;
347
+ prompt?: string;
348
+ language?: string;
349
+ temperature?: number;
350
+ maxTokens?: number;
351
+ context: GenerationContext;
352
+ };
353
+ };
354
+ 'generation:progress': GenerationProgress;
355
+ 'generation:complete': {
356
+ annotationUri: string;
357
+ progress: GenerationProgress;
358
+ };
359
+ 'generation:failed': {
360
+ error: Error;
361
+ };
362
+ 'generation:modal-open': {
363
+ annotationUri: string;
364
+ resourceUri: string;
365
+ defaultTitle: string;
366
+ };
367
+ 'reference:create-manual': {
368
+ annotationUri: string;
369
+ title: string;
370
+ entityTypes: string[];
371
+ };
372
+ 'reference:link': {
373
+ annotationUri: string;
374
+ searchTerm: string;
375
+ };
376
+ 'resolution:search-requested': {
377
+ referenceId: string;
378
+ searchTerm: string;
379
+ };
380
+ 'context:retrieval-requested': {
381
+ annotationUri: string;
382
+ resourceUri: string;
383
+ };
384
+ 'context:retrieval-complete': {
385
+ annotationUri: string;
386
+ context: GenerationContext;
387
+ };
388
+ 'context:retrieval-failed': {
389
+ annotationUri: string;
390
+ error: Error;
391
+ };
392
+ };
393
+ type EventBus = ReturnType<typeof mitt<EventMap>> & {
394
+ busId: string;
395
+ };
396
+ /**
397
+ * Reset the global event bus - FOR TESTING ONLY.
398
+ *
399
+ * Call this in test setup (beforeEach) to ensure test isolation.
400
+ * Each test gets a fresh event bus with no lingering subscriptions.
401
+ *
402
+ * @example
403
+ * ```typescript
404
+ * beforeEach(() => {
405
+ * resetEventBusForTesting();
406
+ * });
407
+ * ```
408
+ */
409
+ declare function resetEventBusForTesting(): void;
410
+ interface EventBusProviderProps {
411
+ children: ReactNode;
412
+ }
413
+ /**
414
+ * Unified event bus provider for all application events
415
+ *
416
+ * Consolidates three previous event buses:
417
+ * - MakeMeaningEventBus (document/annotation operations)
418
+ * - NavigationEventBus (navigation and sidebar UI)
419
+ * - GlobalSettingsEventBus (app-wide settings)
420
+ *
421
+ * Benefits:
422
+ * - Single import: useEventBus()
423
+ * - No decision fatigue about which bus to use
424
+ * - Easier cross-domain coordination
425
+ * - Simpler provider hierarchy
426
+ *
427
+ * NOTE: This provider uses a global singleton event bus to ensure all components
428
+ * share the same instance. Multiple providers in the tree will all reference the
429
+ * same global bus.
430
+ *
431
+ * Operation handlers (API calls triggered by events) are set up separately via
432
+ * the useResolutionFlow hook, which should be called at the resource page level.
433
+ */
434
+ declare function EventBusProvider({ children, }: EventBusProviderProps): react_jsx_runtime.JSX.Element;
435
+ /**
436
+ * Hook to access the unified event bus
437
+ *
438
+ * Use this everywhere instead of:
439
+ * - useMakeMeaningEvents()
440
+ * - useNavigationEvents()
441
+ * - useGlobalSettingsEvents()
442
+ *
443
+ * @example
444
+ * ```typescript
445
+ * const eventBus = useEventBus();
446
+ *
447
+ * // Emit any event
448
+ * eventBus.emit('annotation:hover', { annotationId: '123' });
449
+ * eventBus.emit('navigation:sidebar-toggle', undefined);
450
+ * eventBus.emit('settings:theme-changed', { theme: 'dark' });
451
+ *
452
+ * // Subscribe to any event
453
+ * useEffect(() => {
454
+ * const handler = ({ annotationId }) => console.log(annotationId);
455
+ * eventBus.on('annotation:hover', handler);
456
+ * return () => eventBus.off('annotation:hover', handler);
457
+ * }, []);
458
+ * ```
459
+ */
460
+ declare function useEventBus(): EventBus;
461
+
462
+ export { type DetectionProgress as D, type EventBus as E, type GenerationProgress as G, type OpenResourcesManager as O, type SessionManager as S, type TranslationManager as T, type EventMap as a, type OpenResource as b, type SessionState as c, type EventBusProviderProps as d, EventBusProvider as e, resetEventBusForTesting as r, useEventBus as u };
@@ -3,7 +3,7 @@
3
3
  import "./chunk-3JTO27MH.mjs";
4
4
 
5
5
  // src/components/pdf-annotation/PdfAnnotationCanvas.tsx
6
- import { useRef, useState, useCallback, useEffect } from "react";
6
+ import { useRef, useState, useCallback, useEffect, useMemo } from "react";
7
7
  import { getTargetSelector } from "@semiont/api-client";
8
8
 
9
9
  // src/lib/pdf-coordinates.ts
@@ -151,14 +151,14 @@ function PdfAnnotationCanvas({
151
151
  existingAnnotations = [],
152
152
  drawingMode,
153
153
  selectedMotivation,
154
- onAnnotationCreate,
155
- onAnnotationClick,
156
- onAnnotationHover,
154
+ eventBus,
157
155
  hoveredAnnotationId,
158
156
  selectedAnnotationId
159
157
  }) {
160
- const resourceId = resourceUri.split("/").pop();
161
- const pdfUrl = `/api/resources/${resourceId}`;
158
+ const pdfUrl = useMemo(() => {
159
+ const resourceId = resourceUri.split("/").pop();
160
+ return `/api/resources/${resourceId}`;
161
+ }, [resourceUri]);
162
162
  const [pdfDoc, setPdfDoc] = useState(null);
163
163
  const [numPages, setNumPages] = useState(0);
164
164
  const [pageNumber, setPageNumber] = useState(1);
@@ -172,6 +172,7 @@ function PdfAnnotationCanvas({
172
172
  const [selection, setSelection] = useState(null);
173
173
  const containerRef = useRef(null);
174
174
  const imageRef = useRef(null);
175
+ const currentHover = useRef(null);
175
176
  useEffect(() => {
176
177
  let cancelled = false;
177
178
  async function loadPdf() {
@@ -274,7 +275,7 @@ function PdfAnnotationCanvas({
274
275
  });
275
276
  }, [isDrawing, selection]);
276
277
  const handleMouseUp = useCallback(() => {
277
- if (!isDrawing || !selection || !pageDimensions || !displayDimensions || !onAnnotationCreate) {
278
+ if (!isDrawing || !selection || !pageDimensions || !displayDimensions || !eventBus) {
278
279
  setIsDrawing(false);
279
280
  setSelection(null);
280
281
  return;
@@ -284,23 +285,23 @@ function PdfAnnotationCanvas({
284
285
  );
285
286
  const MIN_DRAG_DISTANCE = 10;
286
287
  if (dragDistance < MIN_DRAG_DISTANCE) {
287
- if (onAnnotationClick && existingAnnotations.length > 0) {
288
+ if (existingAnnotations.length > 0) {
288
289
  const clickedAnnotation = pageAnnotations.find((ann) => {
289
290
  const fragmentSel = getFragmentSelector(ann.target);
290
291
  if (!fragmentSel) return false;
291
292
  const pdfCoord2 = parseFragmentSelector(fragmentSel.value);
292
293
  if (!pdfCoord2) return false;
293
- const rect2 = pdfToCanvasCoordinates(pdfCoord2, pageDimensions.height, 1);
294
+ const rect = pdfToCanvasCoordinates(pdfCoord2, pageDimensions.height, 1);
294
295
  const scaleX2 = displayDimensions.width / pageDimensions.width;
295
296
  const scaleY2 = displayDimensions.height / pageDimensions.height;
296
- const displayX = rect2.x * scaleX2;
297
- const displayY = rect2.y * scaleY2;
298
- const displayWidth = rect2.width * scaleX2;
299
- const displayHeight = rect2.height * scaleY2;
297
+ const displayX = rect.x * scaleX2;
298
+ const displayY = rect.y * scaleY2;
299
+ const displayWidth = rect.width * scaleX2;
300
+ const displayHeight = rect.height * scaleY2;
300
301
  return selection.endX >= displayX && selection.endX <= displayX + displayWidth && selection.endY >= displayY && selection.endY <= displayY + displayHeight;
301
302
  });
302
303
  if (clickedAnnotation) {
303
- onAnnotationClick(clickedAnnotation);
304
+ eventBus?.emit("annotation:click", { annotationId: clickedAnnotation.id, motivation: clickedAnnotation.motivation });
304
305
  setIsDrawing(false);
305
306
  setSelection(null);
306
307
  return;
@@ -327,16 +328,18 @@ function PdfAnnotationCanvas({
327
328
  // Use scale 1.0 since we already scaled to native coords
328
329
  );
329
330
  const fragmentSelector = createFragmentSelector(pdfCoord);
330
- const centerX = (selection.startX + selection.endX) / 2;
331
- const centerY = (selection.startY + selection.endY) / 2;
332
- const rect = imageRef.current?.getBoundingClientRect();
333
- const screenPosition = rect ? {
334
- x: rect.left + centerX,
335
- y: rect.top + centerY
336
- } : void 0;
337
- onAnnotationCreate(fragmentSelector, screenPosition);
331
+ if (selectedMotivation) {
332
+ eventBus.emit("annotation:requested", {
333
+ selector: {
334
+ type: "FragmentSelector",
335
+ conformsTo: "http://tools.ietf.org/rfc/rfc3778",
336
+ value: fragmentSelector
337
+ },
338
+ motivation: selectedMotivation
339
+ });
340
+ }
338
341
  setIsDrawing(false);
339
- }, [isDrawing, selection, pageNumber, pageDimensions, displayDimensions, onAnnotationCreate, onAnnotationClick, existingAnnotations]);
342
+ }, [isDrawing, selection, pageNumber, pageDimensions, displayDimensions, selectedMotivation, existingAnnotations]);
340
343
  const getFragmentSelector = (target) => {
341
344
  const selector = getTargetSelector(target);
342
345
  if (!selector) return null;
@@ -351,6 +354,18 @@ function PdfAnnotationCanvas({
351
354
  const page = getPageFromFragment(fragmentSel.value);
352
355
  return page === pageNumber;
353
356
  });
357
+ const handleMouseEnter = (annotationId) => {
358
+ if (currentHover.current !== annotationId) {
359
+ currentHover.current = annotationId;
360
+ eventBus?.emit("annotation:hover", { annotationId });
361
+ }
362
+ };
363
+ const handleMouseLeave = () => {
364
+ if (currentHover.current !== null) {
365
+ currentHover.current = null;
366
+ eventBus?.emit("annotation:hover", { annotationId: null });
367
+ }
368
+ };
354
369
  const { stroke, fill } = getMotivationColor(selectedMotivation ?? null);
355
370
  if (error) {
356
371
  return /* @__PURE__ */ jsx("div", { className: "semiont-pdf-annotation-canvas__error", children: error });
@@ -431,9 +446,9 @@ function PdfAnnotationCanvas({
431
446
  cursor: "pointer",
432
447
  opacity: isSelected ? 1 : isHovered ? 0.9 : 0.7
433
448
  },
434
- onClick: () => onAnnotationClick?.(ann),
435
- onMouseEnter: () => onAnnotationHover?.(ann.id),
436
- onMouseLeave: () => onAnnotationHover?.(null)
449
+ onClick: () => eventBus?.emit("annotation:click", { annotationId: ann.id, motivation: ann.motivation }),
450
+ onMouseEnter: () => handleMouseEnter(ann.id),
451
+ onMouseLeave: handleMouseLeave
437
452
  },
438
453
  ann.id
439
454
  );
@@ -495,4 +510,4 @@ function PdfAnnotationCanvas({
495
510
  export {
496
511
  PdfAnnotationCanvas
497
512
  };
498
- //# sourceMappingURL=PdfAnnotationCanvas.client-ADC4FFSE.mjs.map
513
+ //# sourceMappingURL=PdfAnnotationCanvas.client-RAJRPQLU.mjs.map