@semiont/react-ui 0.2.35-build.98 → 0.2.35

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 (209) hide show
  1. package/README.md +1 -0
  2. package/dist/{EventBusContext-DMI4uwYk.d.mts → EventBusContext-CLnb2LmB.d.mts} +5 -5
  3. package/dist/{PdfAnnotationCanvas.client-HNYRKFDS.mjs → PdfAnnotationCanvas.client-COQREPXU.mjs} +7 -7
  4. package/dist/PdfAnnotationCanvas.client-COQREPXU.mjs.map +1 -0
  5. package/dist/ar-7SUXNE34.mjs +376 -0
  6. package/dist/ar-7SUXNE34.mjs.map +1 -0
  7. package/dist/bn-XOET3DOI.mjs +376 -0
  8. package/dist/bn-XOET3DOI.mjs.map +1 -0
  9. package/dist/{chunk-YI5IX5ZA.mjs → chunk-2HGWOLVN.mjs} +1 -1
  10. package/dist/{chunk-YI5IX5ZA.mjs.map → chunk-2HGWOLVN.mjs.map} +1 -1
  11. package/dist/{chunk-3FIQXKQF.mjs → chunk-Q2KV6Y2J.mjs} +28 -28
  12. package/dist/{chunk-MWQ5CNKW.mjs → chunk-ZPV43WN2.mjs} +11 -11
  13. package/dist/chunk-ZPV43WN2.mjs.map +1 -0
  14. package/dist/cs-X63DXX7L.mjs +376 -0
  15. package/dist/cs-X63DXX7L.mjs.map +1 -0
  16. package/dist/da-OWTCV57A.mjs +376 -0
  17. package/dist/da-OWTCV57A.mjs.map +1 -0
  18. package/dist/de-77BMFDVF.mjs +376 -0
  19. package/dist/de-77BMFDVF.mjs.map +1 -0
  20. package/dist/el-FIBNLH2V.mjs +376 -0
  21. package/dist/el-FIBNLH2V.mjs.map +1 -0
  22. package/dist/fa-3N4CIWE6.mjs +376 -0
  23. package/dist/fa-3N4CIWE6.mjs.map +1 -0
  24. package/dist/fi-JOM3M7Z4.mjs +376 -0
  25. package/dist/fi-JOM3M7Z4.mjs.map +1 -0
  26. package/dist/fr-56QSXS7E.mjs +376 -0
  27. package/dist/fr-56QSXS7E.mjs.map +1 -0
  28. package/dist/he-SNAXPJEK.mjs +376 -0
  29. package/dist/he-SNAXPJEK.mjs.map +1 -0
  30. package/dist/hi-CRBRD5TB.mjs +376 -0
  31. package/dist/hi-CRBRD5TB.mjs.map +1 -0
  32. package/dist/id-BRCVLICF.mjs +376 -0
  33. package/dist/id-BRCVLICF.mjs.map +1 -0
  34. package/dist/index.d.mts +169 -165
  35. package/dist/index.mjs +317 -313
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/it-M2Z27BNB.mjs +376 -0
  38. package/dist/it-M2Z27BNB.mjs.map +1 -0
  39. package/dist/ja-TZUKW7HD.mjs +376 -0
  40. package/dist/ja-TZUKW7HD.mjs.map +1 -0
  41. package/dist/ko-NKBGGOL6.mjs +376 -0
  42. package/dist/ko-NKBGGOL6.mjs.map +1 -0
  43. package/dist/ms-XFXPN6RX.mjs +376 -0
  44. package/dist/ms-XFXPN6RX.mjs.map +1 -0
  45. package/dist/nl-MVYXAS5C.mjs +379 -0
  46. package/dist/nl-MVYXAS5C.mjs.map +1 -0
  47. package/dist/no-XOLO4JPV.mjs +376 -0
  48. package/dist/no-XOLO4JPV.mjs.map +1 -0
  49. package/dist/pl-TRWLMMC4.mjs +376 -0
  50. package/dist/pl-TRWLMMC4.mjs.map +1 -0
  51. package/dist/pt-M3TE24UI.mjs +376 -0
  52. package/dist/pt-M3TE24UI.mjs.map +1 -0
  53. package/dist/ro-QBFG2T64.mjs +376 -0
  54. package/dist/ro-QBFG2T64.mjs.map +1 -0
  55. package/dist/sv-IUECBXWX.mjs +376 -0
  56. package/dist/sv-IUECBXWX.mjs.map +1 -0
  57. package/dist/test-utils.d.mts +2 -2
  58. package/dist/test-utils.mjs +2 -2
  59. package/dist/th-US7KIN5Q.mjs +376 -0
  60. package/dist/th-US7KIN5Q.mjs.map +1 -0
  61. package/dist/tr-DWJ2FFUK.mjs +376 -0
  62. package/dist/tr-DWJ2FFUK.mjs.map +1 -0
  63. package/dist/uk-M4ZE4DPZ.mjs +376 -0
  64. package/dist/uk-M4ZE4DPZ.mjs.map +1 -0
  65. package/dist/vi-FERZNPSH.mjs +376 -0
  66. package/dist/vi-FERZNPSH.mjs.map +1 -0
  67. package/dist/zh-3J2I3WYK.mjs +376 -0
  68. package/dist/zh-3J2I3WYK.mjs.map +1 -0
  69. package/package.json +1 -1
  70. package/src/components/AnnotateReferencesProgressWidget.tsx +5 -5
  71. package/src/components/CodeMirrorRenderer.tsx +5 -5
  72. package/src/components/Toolbar.tsx +2 -2
  73. package/src/components/annotation/AnnotateToolbar.tsx +9 -9
  74. package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +17 -17
  75. package/src/components/image-annotation/AnnotationOverlay.tsx +10 -10
  76. package/src/components/image-annotation/SvgDrawingCanvas.tsx +4 -4
  77. package/src/components/navigation/CollapsibleResourceNavigation.tsx +7 -7
  78. package/src/components/navigation/ObservableLink.tsx +3 -3
  79. package/src/components/navigation/SimpleNavigation.tsx +2 -2
  80. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +8 -8
  81. package/src/components/resource/AnnotateView.tsx +12 -12
  82. package/src/components/resource/BrowseView.tsx +9 -9
  83. package/src/components/resource/ResourceViewer.tsx +23 -23
  84. package/src/components/resource/__tests__/BrowseView.test.tsx +27 -27
  85. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +1 -1
  86. package/src/components/resource/panels/AssessmentEntry.tsx +2 -2
  87. package/src/components/resource/panels/AssessmentPanel.tsx +7 -7
  88. package/src/components/resource/panels/AssistSection.tsx +5 -5
  89. package/src/components/resource/panels/CommentEntry.tsx +2 -2
  90. package/src/components/resource/panels/CommentsPanel.tsx +7 -7
  91. package/src/components/resource/panels/HighlightEntry.tsx +2 -2
  92. package/src/components/resource/panels/HighlightPanel.tsx +5 -5
  93. package/src/components/resource/panels/ReferenceEntry.tsx +8 -8
  94. package/src/components/resource/panels/ReferencesPanel.tsx +10 -10
  95. package/src/components/resource/panels/ResourceInfoPanel.tsx +6 -6
  96. package/src/components/resource/panels/TagEntry.tsx +2 -2
  97. package/src/components/resource/panels/TaggingPanel.tsx +8 -8
  98. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +2 -2
  99. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +4 -4
  100. package/src/components/resource/panels/__tests__/AssistSection.test.tsx +4 -4
  101. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +8 -8
  102. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +3 -3
  103. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +1 -1
  104. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +3 -3
  105. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +9 -9
  106. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +5 -5
  107. package/src/features/admin-devops/components/AdminDevOpsPage.tsx +2 -1
  108. package/src/features/admin-security/components/AdminSecurityPage.tsx +2 -1
  109. package/src/features/admin-users/components/AdminUsersPage.tsx +2 -1
  110. package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +2 -1
  111. package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +2 -1
  112. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +2 -1
  113. package/src/features/resource-compose/components/ResourceComposePage.tsx +2 -1
  114. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +2 -1
  115. package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +26 -26
  116. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +21 -21
  117. package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +23 -23
  118. package/src/features/resource-viewer/__tests__/{ResolutionFlowIntegration.test.tsx → BindFlowIntegration.test.tsx} +49 -49
  119. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +18 -18
  120. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +19 -19
  121. package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +19 -19
  122. package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +13 -13
  123. package/src/features/resource-viewer/__tests__/{GenerationFlowIntegration.test.tsx → YieldFlowIntegration.test.tsx} +34 -34
  124. package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +11 -11
  125. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +55 -55
  126. package/translations/ar.json +298 -298
  127. package/translations/bn.json +298 -298
  128. package/translations/cs.json +295 -295
  129. package/translations/da.json +282 -282
  130. package/translations/de.json +281 -281
  131. package/translations/el.json +298 -298
  132. package/translations/fa.json +298 -298
  133. package/translations/fi.json +298 -298
  134. package/translations/fr.json +279 -279
  135. package/translations/he.json +298 -298
  136. package/translations/hi.json +298 -298
  137. package/translations/id.json +295 -295
  138. package/translations/it.json +299 -299
  139. package/translations/ja.json +298 -298
  140. package/translations/ko.json +298 -298
  141. package/translations/ms.json +296 -296
  142. package/translations/nl.json +299 -296
  143. package/translations/no.json +292 -292
  144. package/translations/pl.json +297 -297
  145. package/translations/pt.json +294 -294
  146. package/translations/ro.json +298 -298
  147. package/translations/sv.json +293 -293
  148. package/translations/th.json +298 -298
  149. package/translations/tr.json +298 -298
  150. package/translations/uk.json +298 -298
  151. package/translations/vi.json +298 -298
  152. package/translations/zh.json +298 -298
  153. package/dist/PdfAnnotationCanvas.client-HNYRKFDS.mjs.map +0 -1
  154. package/dist/ar-MDB7HC5S.mjs +0 -376
  155. package/dist/ar-MDB7HC5S.mjs.map +0 -1
  156. package/dist/bn-3SAV2ZEM.mjs +0 -376
  157. package/dist/bn-3SAV2ZEM.mjs.map +0 -1
  158. package/dist/chunk-MWQ5CNKW.mjs.map +0 -1
  159. package/dist/cs-AWCETEUV.mjs +0 -376
  160. package/dist/cs-AWCETEUV.mjs.map +0 -1
  161. package/dist/da-UZZHXYLC.mjs +0 -376
  162. package/dist/da-UZZHXYLC.mjs.map +0 -1
  163. package/dist/de-LQFWN6S5.mjs +0 -376
  164. package/dist/de-LQFWN6S5.mjs.map +0 -1
  165. package/dist/el-IWOETBJ7.mjs +0 -376
  166. package/dist/el-IWOETBJ7.mjs.map +0 -1
  167. package/dist/fa-BVEJZT5S.mjs +0 -376
  168. package/dist/fa-BVEJZT5S.mjs.map +0 -1
  169. package/dist/fi-JBNCGGA6.mjs +0 -376
  170. package/dist/fi-JBNCGGA6.mjs.map +0 -1
  171. package/dist/fr-OLH7PNGI.mjs +0 -376
  172. package/dist/fr-OLH7PNGI.mjs.map +0 -1
  173. package/dist/he-KOJQ4HMA.mjs +0 -376
  174. package/dist/he-KOJQ4HMA.mjs.map +0 -1
  175. package/dist/hi-BKJFZXAY.mjs +0 -376
  176. package/dist/hi-BKJFZXAY.mjs.map +0 -1
  177. package/dist/id-DPLHJVNP.mjs +0 -376
  178. package/dist/id-DPLHJVNP.mjs.map +0 -1
  179. package/dist/it-JXHAM7NL.mjs +0 -376
  180. package/dist/it-JXHAM7NL.mjs.map +0 -1
  181. package/dist/ja-DQRAO3PU.mjs +0 -376
  182. package/dist/ja-DQRAO3PU.mjs.map +0 -1
  183. package/dist/ko-6IFCOP6F.mjs +0 -376
  184. package/dist/ko-6IFCOP6F.mjs.map +0 -1
  185. package/dist/ms-KF5S2TLL.mjs +0 -376
  186. package/dist/ms-KF5S2TLL.mjs.map +0 -1
  187. package/dist/nl-2GUUZLQM.mjs +0 -376
  188. package/dist/nl-2GUUZLQM.mjs.map +0 -1
  189. package/dist/no-2IBCZGEF.mjs +0 -376
  190. package/dist/no-2IBCZGEF.mjs.map +0 -1
  191. package/dist/pl-ZEUBJ7YU.mjs +0 -376
  192. package/dist/pl-ZEUBJ7YU.mjs.map +0 -1
  193. package/dist/pt-WLAFIZWQ.mjs +0 -376
  194. package/dist/pt-WLAFIZWQ.mjs.map +0 -1
  195. package/dist/ro-K56IXFGU.mjs +0 -376
  196. package/dist/ro-K56IXFGU.mjs.map +0 -1
  197. package/dist/sv-VFJLMJRY.mjs +0 -376
  198. package/dist/sv-VFJLMJRY.mjs.map +0 -1
  199. package/dist/th-RICLQ2GW.mjs +0 -376
  200. package/dist/th-RICLQ2GW.mjs.map +0 -1
  201. package/dist/tr-SALXWE2M.mjs +0 -376
  202. package/dist/tr-SALXWE2M.mjs.map +0 -1
  203. package/dist/uk-3U3T3O2E.mjs +0 -376
  204. package/dist/uk-3U3T3O2E.mjs.map +0 -1
  205. package/dist/vi-LIVNZXOB.mjs +0 -376
  206. package/dist/vi-LIVNZXOB.mjs.map +0 -1
  207. package/dist/zh-KDUAZPX3.mjs +0 -376
  208. package/dist/zh-KDUAZPX3.mjs.map +0 -1
  209. /package/dist/{chunk-3FIQXKQF.mjs.map → chunk-Q2KV6Y2J.mjs.map} +0 -0
@@ -1,16 +1,16 @@
1
1
  /**
2
2
  * Layer 3: Feature Integration Test - Resolution Flow (search modal & body update)
3
3
  *
4
- * Tests the UNCOVERED half of useResolutionFlow:
5
- * - resolve:link → emits resolve:search-requested
6
- * - resolve:search-requested → opens search modal with pendingReferenceId
4
+ * Tests the UNCOVERED half of useBindFlow:
5
+ * - bind:link → emits bind:search-requested
6
+ * - bind:search-requested → opens search modal with pendingReferenceId
7
7
  * - onCloseSearchModal → closes modal
8
- * - resolve:update-body → calls updateAnnotationBody API
9
- * - resolve:update-body → emits resolve:body-updated on success
10
- * - resolve:update-body → emits resolve:body-update-failed on error
8
+ * - bind:update-body → calls updateAnnotationBody API
9
+ * - bind:update-body → emits bind:body-updated on success
10
+ * - bind:update-body → emits bind:body-update-failed on error
11
11
  * - auth token passed to updateAnnotationBody
12
12
  *
13
- * The deletion half of useResolutionFlow is covered by AnnotationDeletionIntegration.test.tsx.
13
+ * The deletion half of useBindFlow is covered by AnnotationDeletionIntegration.test.tsx.
14
14
  *
15
15
  * Uses real providers (EventBus, ApiClient, AuthToken) with mocked API boundary.
16
16
  */
@@ -18,7 +18,7 @@
18
18
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
19
19
  import { render, waitFor } from '@testing-library/react';
20
20
  import { act } from 'react';
21
- import { useResolutionFlow } from '../../../hooks/useResolutionFlow';
21
+ import { useBindFlow } from '../../../hooks/useBindFlow';
22
22
  import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
23
23
  import { ApiClientProvider } from '../../../contexts/ApiClientContext';
24
24
  import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
@@ -55,13 +55,13 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
55
55
 
56
56
  // ─── Render helper ──────────────────────────────────────────────────────────
57
57
 
58
- function renderResolutionFlow() {
58
+ function renderBindFlow() {
59
59
  let eventBusInstance: ReturnType<typeof useEventBus> | null = null;
60
- let lastState: ReturnType<typeof useResolutionFlow> | null = null;
60
+ let lastState: ReturnType<typeof useBindFlow> | null = null;
61
61
 
62
62
  function TestComponent() {
63
63
  eventBusInstance = useEventBus();
64
- lastState = useResolutionFlow(testUri);
64
+ lastState = useBindFlow(testUri);
65
65
  return null;
66
66
  }
67
67
 
@@ -84,19 +84,19 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
84
84
  // ─── Initial state ──────────────────────────────────────────────────────────
85
85
 
86
86
  it('starts with search modal closed and no pending reference', () => {
87
- const { getState } = renderResolutionFlow();
87
+ const { getState } = renderBindFlow();
88
88
  expect(getState().searchModalOpen).toBe(false);
89
89
  expect(getState().pendingReferenceId).toBeNull();
90
90
  });
91
91
 
92
- // ─── resolve:link ─────────────────────────────────────────────────────────
92
+ // ─── bind:link ─────────────────────────────────────────────────────────
93
93
 
94
- it('resolve:link emits resolve:search-requested with referenceId and searchTerm', () => {
95
- const { getEventBus } = renderResolutionFlow();
94
+ it('bind:link emits bind:search-requested with referenceId and searchTerm', () => {
95
+ const { getEventBus } = renderBindFlow();
96
96
  const searchRequestedSpy = vi.fn();
97
97
 
98
- const subscription = getEventBus().get('resolve:search-requested').subscribe(searchRequestedSpy);
99
- act(() => { getEventBus().get('resolve:link').next({ annotationUri: 'ann-uri-123', searchTerm: 'climate change' }); });
98
+ const subscription = getEventBus().get('bind:search-requested').subscribe(searchRequestedSpy);
99
+ act(() => { getEventBus().get('bind:link').next({ annotationUri: 'ann-uri-123', searchTerm: 'climate change' }); });
100
100
  subscription.unsubscribe();
101
101
 
102
102
  expect(searchRequestedSpy).toHaveBeenCalledTimes(1);
@@ -106,35 +106,35 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
106
106
  });
107
107
  });
108
108
 
109
- // ─── resolve:search-requested ────────────────────────────────────────────
109
+ // ─── bind:search-requested ────────────────────────────────────────────
110
110
 
111
- it('resolve:search-requested opens the search modal', async () => {
112
- const { getState, getEventBus } = renderResolutionFlow();
111
+ it('bind:search-requested opens the search modal', async () => {
112
+ const { getState, getEventBus } = renderBindFlow();
113
113
 
114
114
  expect(getState().searchModalOpen).toBe(false);
115
115
 
116
- act(() => { getEventBus().get('resolve:search-requested').next({ referenceId: 'ref-abc', searchTerm: 'oceans' }); });
116
+ act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-abc', searchTerm: 'oceans' }); });
117
117
 
118
118
  await waitFor(() => {
119
119
  expect(getState().searchModalOpen).toBe(true);
120
120
  });
121
121
  });
122
122
 
123
- it('resolve:search-requested sets pendingReferenceId', async () => {
124
- const { getState, getEventBus } = renderResolutionFlow();
123
+ it('bind:search-requested sets pendingReferenceId', async () => {
124
+ const { getState, getEventBus } = renderBindFlow();
125
125
 
126
- act(() => { getEventBus().get('resolve:search-requested').next({ referenceId: 'ref-xyz', searchTerm: 'forests' }); });
126
+ act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-xyz', searchTerm: 'forests' }); });
127
127
 
128
128
  await waitFor(() => {
129
129
  expect(getState().pendingReferenceId).toBe('ref-xyz');
130
130
  });
131
131
  });
132
132
 
133
- it('resolve:link → resolve:search-requested chain opens modal end-to-end', async () => {
134
- const { getState, getEventBus } = renderResolutionFlow();
133
+ it('bind:link → bind:search-requested chain opens modal end-to-end', async () => {
134
+ const { getState, getEventBus } = renderBindFlow();
135
135
 
136
136
  // Simulate the full user journey: user clicks "Link Document" on a reference entry
137
- act(() => { getEventBus().get('resolve:link').next({ annotationUri: 'ann-full-chain', searchTerm: 'biodiversity' }); });
137
+ act(() => { getEventBus().get('bind:link').next({ annotationUri: 'ann-full-chain', searchTerm: 'biodiversity' }); });
138
138
 
139
139
  await waitFor(() => {
140
140
  expect(getState().searchModalOpen).toBe(true);
@@ -145,9 +145,9 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
145
145
  // ─── onCloseSearchModal ──────────────────────────────────────────────────────
146
146
 
147
147
  it('onCloseSearchModal closes the search modal', async () => {
148
- const { getState, getEventBus } = renderResolutionFlow();
148
+ const { getState, getEventBus } = renderBindFlow();
149
149
 
150
- act(() => { getEventBus().get('resolve:search-requested').next({ referenceId: 'ref-close', searchTerm: 'test' }); });
150
+ act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-close', searchTerm: 'test' }); });
151
151
 
152
152
  await waitFor(() => expect(getState().searchModalOpen).toBe(true));
153
153
 
@@ -159,9 +159,9 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
159
159
  });
160
160
 
161
161
  it('onCloseSearchModal does not clear pendingReferenceId (preserves for re-open)', async () => {
162
- const { getState, getEventBus } = renderResolutionFlow();
162
+ const { getState, getEventBus } = renderBindFlow();
163
163
 
164
- act(() => { getEventBus().get('resolve:search-requested').next({ referenceId: 'ref-persist', searchTerm: 'test' }); });
164
+ act(() => { getEventBus().get('bind:search-requested').next({ referenceId: 'ref-persist', searchTerm: 'test' }); });
165
165
  await waitFor(() => expect(getState().searchModalOpen).toBe(true));
166
166
 
167
167
  act(() => { getState().onCloseSearchModal(); });
@@ -171,12 +171,12 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
171
171
  expect(getState().pendingReferenceId).toBe('ref-persist');
172
172
  });
173
173
 
174
- // ─── resolve:update-body ──────────────────────────────────────────────────
174
+ // ─── bind:update-body ──────────────────────────────────────────────────
175
175
 
176
- it('resolve:update-body calls updateAnnotationBody API', async () => {
177
- const { getEventBus } = renderResolutionFlow();
176
+ it('bind:update-body calls updateAnnotationBody API', async () => {
177
+ const { getEventBus } = renderBindFlow();
178
178
 
179
- act(() => { getEventBus().get('resolve:update-body').next({
179
+ act(() => { getEventBus().get('bind:update-body').next({
180
180
  annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-body-1',
181
181
  resourceId: 'linked-resource-id',
182
182
  operations: [{ op: 'add', item: { id: 'linked-resource-id' } }],
@@ -187,10 +187,10 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
187
187
  });
188
188
  });
189
189
 
190
- it('resolve:update-body passes auth token to API call', async () => {
191
- const { getEventBus } = renderResolutionFlow();
190
+ it('bind:update-body passes auth token to API call', async () => {
191
+ const { getEventBus } = renderBindFlow();
192
192
 
193
- act(() => { getEventBus().get('resolve:update-body').next({
193
+ act(() => { getEventBus().get('bind:update-body').next({
194
194
  annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-auth',
195
195
  resourceId: 'resource-id',
196
196
  operations: [{ op: 'replace', newItem: { id: 'resource-id' } }],
@@ -205,13 +205,13 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
205
205
  expect(callArgs[2].auth).toBe(accessToken(testToken));
206
206
  });
207
207
 
208
- it('resolve:update-body emits resolve:body-updated on success', async () => {
209
- const { getEventBus } = renderResolutionFlow();
208
+ it('bind:update-body emits bind:body-updated on success', async () => {
209
+ const { getEventBus } = renderBindFlow();
210
210
  const bodyUpdatedSpy = vi.fn();
211
211
 
212
- const subscription = getEventBus().get('resolve:body-updated').subscribe(bodyUpdatedSpy);
212
+ const subscription = getEventBus().get('bind:body-updated').subscribe(bodyUpdatedSpy);
213
213
 
214
- act(() => { getEventBus().get('resolve:update-body').next({
214
+ act(() => { getEventBus().get('bind:update-body').next({
215
215
  annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-success',
216
216
  resourceId: 'resource-id',
217
217
  operations: [{ op: 'add', item: { id: 'resource-id' } }],
@@ -228,15 +228,15 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
228
228
  });
229
229
  });
230
230
 
231
- it('resolve:update-body emits resolve:body-update-failed on API error', async () => {
231
+ it('bind:update-body emits bind:body-update-failed on API error', async () => {
232
232
  updateAnnotationBodySpy.mockRejectedValue(new Error('Update failed'));
233
233
 
234
- const { getEventBus } = renderResolutionFlow();
234
+ const { getEventBus } = renderBindFlow();
235
235
  const bodyUpdateFailedSpy = vi.fn();
236
236
 
237
- const subscription = getEventBus().get('resolve:body-update-failed').subscribe(bodyUpdateFailedSpy);
237
+ const subscription = getEventBus().get('bind:body-update-failed').subscribe(bodyUpdateFailedSpy);
238
238
 
239
- act(() => { getEventBus().get('resolve:update-body').next({
239
+ act(() => { getEventBus().get('bind:update-body').next({
240
240
  annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-fail',
241
241
  resourceId: 'resource-id',
242
242
  operations: [{ op: 'remove', item: { id: 'old-id' } }],
@@ -253,10 +253,10 @@ describe('Resolution Flow - Search Modal & Body Update Integration', () => {
253
253
  });
254
254
  });
255
255
 
256
- it('resolve:update-body called ONCE — no duplicate subscriptions', async () => {
257
- const { getEventBus } = renderResolutionFlow();
256
+ it('bind:update-body called ONCE — no duplicate subscriptions', async () => {
257
+ const { getEventBus } = renderBindFlow();
258
258
 
259
- act(() => { getEventBus().get('resolve:update-body').next({
259
+ act(() => { getEventBus().get('bind:update-body').next({
260
260
  annotationUri: 'http://localhost:4000/resources/test-resource/annotations/ann-dedup',
261
261
  resourceId: 'resource-id',
262
262
  operations: [{ op: 'add', item: { id: 'resource-id' } }],
@@ -2,18 +2,18 @@
2
2
  * FAILING TEST: Reproduces the bug where detection events fire but state doesn't update
3
3
  *
4
4
  * Based on console logs from production:
5
- * ✅ annotate:assist-request emitted
5
+ * ✅ mark:assist-request emitted
6
6
  * ✅ annotate:assist-progress emitted
7
7
  * ❌ assistingMotivation remains null
8
8
  * ❌ progress remains null
9
9
  *
10
- * UPDATED: Now tests useAnnotationFlow hook instead of DetectionFlowContainer
10
+ * UPDATED: Now tests useMarkFlow hook instead of DetectionFlowContainer
11
11
  */
12
12
 
13
13
  import { describe, it, expect, vi, beforeEach } from 'vitest';
14
14
  import { render, screen, waitFor } from '@testing-library/react';
15
15
  import { act } from 'react';
16
- import { useAnnotationFlow } from '../../../hooks/useAnnotationFlow';
16
+ import { useMarkFlow } from '../../../hooks/useMarkFlow';
17
17
  import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
18
18
  import { ApiClientProvider } from '../../../contexts/ApiClientContext';
19
19
  import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
@@ -45,17 +45,17 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
45
45
  vi.restoreAllMocks();
46
46
  });
47
47
 
48
- it('SHOULD update state when annotate:assist-request event is emitted', async () => {
48
+ it('SHOULD update state when mark:assist-request event is emitted', async () => {
49
49
  let eventBusInstance: any;
50
50
  let currentState: any;
51
51
 
52
52
  // Component to capture EventBus and hook state
53
53
  function TestComponent() {
54
54
  eventBusInstance = useEventBus();
55
- const state = useAnnotationFlow('http://localhost:8080/resources/test' as any);
55
+ const state = useMarkFlow('http://localhost:8080/resources/test' as any);
56
56
  currentState = state;
57
57
 
58
- console.log('[TEST] useAnnotationFlow state:', {
58
+ console.log('[TEST] useMarkFlow state:', {
59
59
  assistingMotivation: state.assistingMotivation,
60
60
  progress: state.progress,
61
61
  });
@@ -82,17 +82,17 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
82
82
  expect(screen.getByTestId('detecting')).toHaveTextContent('null');
83
83
  expect(screen.getByTestId('progress')).toHaveTextContent('null');
84
84
 
85
- console.log('[TEST] Emitting annotate:assist-request event...');
85
+ console.log('[TEST] Emitting mark:assist-request event...');
86
86
 
87
- // Emit annotate:assist-request event (exactly like production)
87
+ // Emit mark:assist-request event (exactly like production)
88
88
  act(() => {
89
- eventBusInstance.get('annotate:assist-request').next({
89
+ eventBusInstance.get('mark:assist-request').next({
90
90
  motivation: 'linking',
91
91
  options: { entityTypes: ['Location'] }
92
92
  });
93
93
  });
94
94
 
95
- console.log('[TEST] After annotate:assist-request, checking state...');
95
+ console.log('[TEST] After mark:assist-request, checking state...');
96
96
 
97
97
  // THIS SHOULD PASS but currently FAILS
98
98
  await waitFor(() => {
@@ -109,7 +109,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
109
109
 
110
110
  function TestComponent() {
111
111
  eventBusInstance = useEventBus();
112
- const state = useAnnotationFlow('http://localhost:8080/resources/test' as any);
112
+ const state = useMarkFlow('http://localhost:8080/resources/test' as any);
113
113
  currentState = state;
114
114
 
115
115
  return (
@@ -134,7 +134,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
134
134
 
135
135
  // Emit annotate:assist-progress event (exactly like production)
136
136
  act(() => {
137
- eventBusInstance.get('annotate:progress').next({
137
+ eventBusInstance.get('mark:progress').next({
138
138
  status: 'started',
139
139
  resourceId: 'test',
140
140
  totalEntityTypes: 1,
@@ -162,7 +162,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
162
162
 
163
163
  function TestComponent() {
164
164
  eventBusInstance = useEventBus();
165
- const state = useAnnotationFlow('http://localhost:8080/resources/f45fd44f9cb0b0fe1b7980d3d034bc61' as any);
165
+ const state = useMarkFlow('http://localhost:8080/resources/f45fd44f9cb0b0fe1b7980d3d034bc61' as any);
166
166
 
167
167
  stateSnapshots.push({
168
168
  assistingMotivation: state.assistingMotivation,
@@ -192,18 +192,18 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
192
192
 
193
193
  // Exactly like production logs
194
194
  act(() => {
195
- console.log('[EventBus] emit: annotate:assist-request {motivation: "linking", options: {...}}');
196
- eventBusInstance.get('annotate:assist-request').next({
195
+ console.log('[EventBus] emit: mark:assist-request {motivation: "linking", options: {...}}');
196
+ eventBusInstance.get('mark:assist-request').next({
197
197
  motivation: 'linking',
198
198
  options: { entityTypes: ['Location'] }
199
199
  });
200
200
  });
201
201
 
202
- console.log('After annotate:assist-request:', stateSnapshots[stateSnapshots.length - 1]);
202
+ console.log('After mark:assist-request:', stateSnapshots[stateSnapshots.length - 1]);
203
203
 
204
204
  act(() => {
205
205
  console.log('[EventBus] emit: annotate:assist-progress {status: "started", ...}');
206
- eventBusInstance.get('annotate:progress').next({
206
+ eventBusInstance.get('mark:progress').next({
207
207
  status: 'started',
208
208
  resourceId: 'f45fd44f9cb0b0fe1b7980d3d034bc61',
209
209
  totalEntityTypes: 1,
@@ -216,7 +216,7 @@ describe('REPRODUCING BUG: Detection state not updating', () => {
216
216
 
217
217
  act(() => {
218
218
  console.log('[EventBus] emit: annotate:assist-progress {status: "scanning", ...}');
219
- eventBusInstance.get('annotate:progress').next({
219
+ eventBusInstance.get('mark:progress').next({
220
220
  status: 'scanning',
221
221
  resourceId: 'f45fd44f9cb0b0fe1b7980d3d034bc61',
222
222
  currentEntityType: 'Location',
@@ -4,8 +4,8 @@
4
4
  * Tests the COMPLETE detection flow with real component composition:
5
5
  * - EventBusProvider (REAL)
6
6
  * - ApiClientProvider (REAL, with MOCKED client)
7
- * - useAnnotationFlow (REAL)
8
- * - useResolutionFlow (REAL)
7
+ * - useMarkFlow (REAL)
8
+ * - useBindFlow (REAL)
9
9
  * - useEventSubscriptions (REAL)
10
10
  *
11
11
  * This test focuses on ARCHITECTURE and EVENT WIRING:
@@ -25,7 +25,7 @@ import React from 'react';
25
25
  import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
26
26
  import { render, screen, waitFor } from '@testing-library/react';
27
27
  import { act } from 'react';
28
- import { useAnnotationFlow } from '../../../hooks/useAnnotationFlow';
28
+ import { useMarkFlow } from '../../../hooks/useMarkFlow';
29
29
  import { EventBusProvider, useEventBus, resetEventBusForTesting } from '../../../contexts/EventBusContext';
30
30
  import { ApiClientProvider } from '../../../contexts/ApiClientContext';
31
31
  import { AuthTokenProvider } from '../../../contexts/AuthTokenContext';
@@ -91,7 +91,7 @@ describe('Detection Flow - Feature Integration', () => {
91
91
  });
92
92
 
93
93
  // CRITICAL ASSERTION: API called exactly once (not twice!)
94
- // This would FAIL if useResolutionFlow was called in multiple places
94
+ // This would FAIL if useBindFlow was called in multiple places
95
95
  await waitFor(() => {
96
96
  expect(annotateReferencesSpy).toHaveBeenCalledTimes(1);
97
97
  });
@@ -107,7 +107,7 @@ describe('Detection Flow - Feature Integration', () => {
107
107
  );
108
108
  });
109
109
 
110
- it('should propagate SSE progress events to useAnnotationFlow state', async () => {
110
+ it('should propagate SSE progress events to useMarkFlow state', async () => {
111
111
  const testUri = resourceUri('http://localhost:4000/resources/test-resource');
112
112
 
113
113
  // Render with state observer
@@ -127,7 +127,7 @@ describe('Detection Flow - Feature Integration', () => {
127
127
 
128
128
  // Simulate SSE progress event being emitted to EventBus (how SSE actually works now)
129
129
  act(() => {
130
- getEventBus().get('annotate:progress').next({
130
+ getEventBus().get('mark:progress').next({
131
131
  status: 'scanning',
132
132
  message: 'Scanning for Person...',
133
133
  currentEntityType: 'Person',
@@ -161,7 +161,7 @@ describe('Detection Flow - Feature Integration', () => {
161
161
 
162
162
  // First progress update via EventBus
163
163
  act(() => {
164
- getEventBus().get('annotate:progress').next({
164
+ getEventBus().get('mark:progress').next({
165
165
  status: 'started',
166
166
  message: 'Starting analysis...',
167
167
  percentage: 0,
@@ -174,7 +174,7 @@ describe('Detection Flow - Feature Integration', () => {
174
174
 
175
175
  // Second progress update via EventBus
176
176
  act(() => {
177
- getEventBus().get('annotate:progress').next({
177
+ getEventBus().get('mark:progress').next({
178
178
  status: 'analyzing',
179
179
  message: 'Analyzing text...',
180
180
  percentage: 50,
@@ -187,7 +187,7 @@ describe('Detection Flow - Feature Integration', () => {
187
187
 
188
188
  // Final progress update via EventBus
189
189
  act(() => {
190
- getEventBus().get('annotate:progress').next({
190
+ getEventBus().get('mark:progress').next({
191
191
  status: 'complete',
192
192
  message: 'Created 14 highlights',
193
193
  percentage: 100,
@@ -214,7 +214,7 @@ describe('Detection Flow - Feature Integration', () => {
214
214
 
215
215
  // Send final progress via EventBus
216
216
  act(() => {
217
- getEventBus().get('annotate:progress').next({
217
+ getEventBus().get('mark:progress').next({
218
218
  status: 'complete',
219
219
  message: 'Created 14 highlights',
220
220
  });
@@ -226,7 +226,7 @@ describe('Detection Flow - Feature Integration', () => {
226
226
 
227
227
  // Emit completion event
228
228
  act(() => {
229
- getEventBus().get('annotate:assist-finished').next({ motivation: 'highlighting' });
229
+ getEventBus().get('mark:assist-finished').next({ motivation: 'highlighting' });
230
230
  });
231
231
 
232
232
  // Verify: detecting flag cleared BUT progress still visible
@@ -247,7 +247,7 @@ describe('Detection Flow - Feature Integration', () => {
247
247
 
248
248
  // Add some progress via EventBus
249
249
  act(() => {
250
- getEventBus().get('annotate:progress').next({
250
+ getEventBus().get('mark:progress').next({
251
251
  status: 'scanning',
252
252
  message: 'Scanning...',
253
253
  });
@@ -259,7 +259,7 @@ describe('Detection Flow - Feature Integration', () => {
259
259
 
260
260
  // Emit failure
261
261
  act(() => {
262
- getEventBus().get('annotate:assist-failed').next({
262
+ getEventBus().get('mark:assist-failed').next({
263
263
  type: 'job.failed' as const,
264
264
  resourceId: 'test-resource' as any,
265
265
  userId: 'user' as any,
@@ -322,13 +322,13 @@ describe('Detection Flow - Feature Integration', () => {
322
322
  it('should only call API once even with multiple event listeners', async () => {
323
323
  const testUri = resourceUri('http://localhost:4000/resources/test-resource');
324
324
 
325
- // This test specifically catches the duplicate useResolutionFlow bug
326
- // If multiple components call useResolutionFlow, we'll see multiple API calls
325
+ // This test specifically catches the duplicate useBindFlow bug
326
+ // If multiple components call useBindFlow, we'll see multiple API calls
327
327
  const { emitDetectionStart, getEventBus } = renderDetectionFlow(testUri);
328
328
 
329
329
  // Add an additional event listener (simulating multiple subscribers)
330
330
  const additionalListener = vi.fn();
331
- const subscription = getEventBus().get('annotate:assist-request').subscribe(additionalListener);
331
+ const subscription = getEventBus().get('mark:assist-request').subscribe(additionalListener);
332
332
 
333
333
  // Trigger detection
334
334
  act(() => {
@@ -351,7 +351,7 @@ describe('Detection Flow - Feature Integration', () => {
351
351
  });
352
352
 
353
353
  /**
354
- * Helper: Render useAnnotationFlow hook with real component composition
354
+ * Helper: Render useMarkFlow hook with real component composition
355
355
  * Returns methods to interact with the rendered component
356
356
  */
357
357
  function renderDetectionFlow(testUri: string) {
@@ -365,7 +365,7 @@ function renderDetectionFlow(testUri: string) {
365
365
 
366
366
  // Test harness component that uses the hook
367
367
  function DetectionFlowTestHarness() {
368
- const { progress, assistingMotivation } = useAnnotationFlow(testUri as any);
368
+ const { progress, assistingMotivation } = useMarkFlow(testUri as any);
369
369
  return (
370
370
  <div>
371
371
  <div data-testid="detecting">{assistingMotivation || 'none'}</div>
@@ -389,7 +389,7 @@ function renderDetectionFlow(testUri: string) {
389
389
 
390
390
  return {
391
391
  emitDetectionStart: (motivation: Motivation, options: any) => {
392
- eventBusInstance.get('annotate:assist-request').next({ motivation, options });
392
+ eventBusInstance.get('mark:assist-request').next({ motivation, options });
393
393
  },
394
394
  getEventBus: () => eventBusInstance,
395
395
  };
@@ -80,9 +80,9 @@ function ResourceMutationHarness({ onEventBus }: { onEventBus: (eventBus: EventB
80
80
  }, [generateCloneTokenMutation]);
81
81
 
82
82
  useEventSubscriptions({
83
- 'resource:archive': handleResourceArchive,
84
- 'resource:unarchive': handleResourceUnarchive,
85
- 'generate:clone': handleResourceClone,
83
+ 'mark:archive': handleResourceArchive,
84
+ 'mark:unarchive': handleResourceUnarchive,
85
+ 'yield:clone': handleResourceClone,
86
86
  });
87
87
 
88
88
  return null;
@@ -153,11 +153,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
153
153
 
154
154
  // ── Clone ──────────────────────────────────────────────────────────────────
155
155
 
156
- it('calls generateCloneToken API when generate:clone event fires', async () => {
156
+ it('calls generateCloneToken API when yield:clone event fires', async () => {
157
157
  const { emit } = renderHarness();
158
158
 
159
159
  await act(async () => {
160
- emit('generate:clone', undefined);
160
+ emit('yield:clone', undefined);
161
161
  });
162
162
 
163
163
  await waitFor(() => {
@@ -169,7 +169,7 @@ describe('Resource mutations — hooks hoisted to top level', () => {
169
169
  const { emit } = renderHarness();
170
170
 
171
171
  await act(async () => {
172
- emit('generate:clone', undefined);
172
+ emit('yield:clone', undefined);
173
173
  });
174
174
 
175
175
  await waitFor(() => {
@@ -184,7 +184,7 @@ describe('Resource mutations — hooks hoisted to top level', () => {
184
184
  const { emit } = renderHarness();
185
185
 
186
186
  await act(async () => {
187
- emit('generate:clone', undefined);
187
+ emit('yield:clone', undefined);
188
188
  });
189
189
 
190
190
  await waitFor(() => {
@@ -199,7 +199,7 @@ describe('Resource mutations — hooks hoisted to top level', () => {
199
199
  const { emit } = renderHarness();
200
200
 
201
201
  await act(async () => {
202
- emit('generate:clone', undefined);
202
+ emit('yield:clone', undefined);
203
203
  });
204
204
 
205
205
  await waitFor(() => {
@@ -211,11 +211,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
211
211
  expect(writtenUrl).toContain('/know/clone?token=');
212
212
  });
213
213
 
214
- it('does NOT call updateResource when generate:clone fires', async () => {
214
+ it('does NOT call updateResource when yield:clone fires', async () => {
215
215
  const { emit } = renderHarness();
216
216
 
217
217
  await act(async () => {
218
- emit('generate:clone', undefined);
218
+ emit('yield:clone', undefined);
219
219
  });
220
220
 
221
221
  await waitFor(() => {
@@ -227,11 +227,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
227
227
 
228
228
  // ── Archive ────────────────────────────────────────────────────────────────
229
229
 
230
- it('calls updateResource with archived:true when resource:archive fires', async () => {
230
+ it('calls updateResource with archived:true when mark:archive fires', async () => {
231
231
  const { emit } = renderHarness();
232
232
 
233
233
  await act(async () => {
234
- emit('resource:archive', undefined);
234
+ emit('mark:archive', undefined);
235
235
  });
236
236
 
237
237
  await waitFor(() => {
@@ -245,11 +245,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
245
245
  );
246
246
  });
247
247
 
248
- it('does NOT call generateCloneToken when resource:archive fires', async () => {
248
+ it('does NOT call generateCloneToken when mark:archive fires', async () => {
249
249
  const { emit } = renderHarness();
250
250
 
251
251
  await act(async () => {
252
- emit('resource:archive', undefined);
252
+ emit('mark:archive', undefined);
253
253
  });
254
254
 
255
255
  await waitFor(() => {
@@ -261,11 +261,11 @@ describe('Resource mutations — hooks hoisted to top level', () => {
261
261
 
262
262
  // ── Unarchive ──────────────────────────────────────────────────────────────
263
263
 
264
- it('calls updateResource with archived:false when resource:unarchive fires', async () => {
264
+ it('calls updateResource with archived:false when mark:unarchive fires', async () => {
265
265
  const { emit } = renderHarness();
266
266
 
267
267
  await act(async () => {
268
- emit('resource:unarchive', undefined);
268
+ emit('mark:unarchive', undefined);
269
269
  });
270
270
 
271
271
  await waitFor(() => {
@@ -281,15 +281,15 @@ describe('Resource mutations — hooks hoisted to top level', () => {
281
281
 
282
282
  // ── Isolation ─────────────────────────────────────────────────────────────
283
283
 
284
- it('resource:archive and generate:clone events each call their own API exactly once', async () => {
284
+ it('mark:archive and yield:clone events each call their own API exactly once', async () => {
285
285
  const { emit } = renderHarness();
286
286
 
287
287
  await act(async () => {
288
- emit('resource:archive', undefined);
288
+ emit('mark:archive', undefined);
289
289
  });
290
290
 
291
291
  await act(async () => {
292
- emit('generate:clone', undefined);
292
+ emit('yield:clone', undefined);
293
293
  });
294
294
 
295
295
  await waitFor(() => {