@semiont/react-ui 0.4.7 → 0.4.9

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 (190) hide show
  1. package/dist/{PdfAnnotationCanvas.client-LF6DDTCV.mjs → PdfAnnotationCanvas.client-CW6SKH2U.mjs} +7 -25
  2. package/dist/PdfAnnotationCanvas.client-CW6SKH2U.mjs.map +1 -0
  3. package/dist/{EventBusContext-DUIMowqQ.d.mts → TranslationManager-CudgH3gw.d.mts} +1 -74
  4. package/dist/{ar-3URRW77J.mjs → ar-R4CRNXEF.mjs} +3 -2
  5. package/dist/ar-R4CRNXEF.mjs.map +1 -0
  6. package/dist/{bn-DCQD3XZ5.mjs → bn-CZKGRHTA.mjs} +3 -2
  7. package/dist/bn-CZKGRHTA.mjs.map +1 -0
  8. package/dist/{chunk-XMCUHQ2Y.mjs → chunk-BQJWOK4C.mjs} +15 -34
  9. package/dist/chunk-BQJWOK4C.mjs.map +1 -0
  10. package/dist/{chunk-5JZFKRLW.mjs → chunk-HNZOXH4L.mjs} +33 -35
  11. package/dist/chunk-HNZOXH4L.mjs.map +1 -0
  12. package/dist/{chunk-PWIVZQ4X.mjs → chunk-HVMAGUFA.mjs} +3 -2
  13. package/dist/chunk-HVMAGUFA.mjs.map +1 -0
  14. package/dist/{chunk-4RMWYJUJ.mjs → chunk-OL5UST25.mjs} +31 -31
  15. package/dist/{cs-23KOZUFE.mjs → cs-4WIB2IHH.mjs} +3 -2
  16. package/dist/cs-4WIB2IHH.mjs.map +1 -0
  17. package/dist/{da-OIQ66A42.mjs → da-JWYEUYPX.mjs} +3 -2
  18. package/dist/da-JWYEUYPX.mjs.map +1 -0
  19. package/dist/{de-FCCLKE2X.mjs → de-GWUQZGER.mjs} +3 -2
  20. package/dist/de-GWUQZGER.mjs.map +1 -0
  21. package/dist/{el-3ADITCGI.mjs → el-DM2GT7P5.mjs} +3 -2
  22. package/dist/el-DM2GT7P5.mjs.map +1 -0
  23. package/dist/{en-LNW2A3RA.mjs → en-IUV4ZXKH.mjs} +2 -2
  24. package/dist/{es-POQEEYIW.mjs → es-6LVQIM3D.mjs} +3 -2
  25. package/dist/es-6LVQIM3D.mjs.map +1 -0
  26. package/dist/{fa-RQPXVELG.mjs → fa-IRUJY3QI.mjs} +3 -2
  27. package/dist/fa-IRUJY3QI.mjs.map +1 -0
  28. package/dist/{fi-UXOVOUGT.mjs → fi-53FBOEVT.mjs} +3 -2
  29. package/dist/fi-53FBOEVT.mjs.map +1 -0
  30. package/dist/{fr-6W2T3R7G.mjs → fr-Q5KY7QL6.mjs} +3 -2
  31. package/dist/fr-Q5KY7QL6.mjs.map +1 -0
  32. package/dist/{he-65UHPZIU.mjs → he-HJNKULBY.mjs} +3 -2
  33. package/dist/he-HJNKULBY.mjs.map +1 -0
  34. package/dist/{hi-SGJIVPTN.mjs → hi-UYZ4X6CR.mjs} +3 -2
  35. package/dist/hi-UYZ4X6CR.mjs.map +1 -0
  36. package/dist/{id-EYJJQCS2.mjs → id-UAQMH6U2.mjs} +3 -2
  37. package/dist/id-UAQMH6U2.mjs.map +1 -0
  38. package/dist/index.css +48 -0
  39. package/dist/index.css.map +1 -1
  40. package/dist/index.d.mts +176 -125
  41. package/dist/index.mjs +556 -781
  42. package/dist/index.mjs.map +1 -1
  43. package/dist/{it-IZGQEDO7.mjs → it-C7QEBNFA.mjs} +3 -2
  44. package/dist/it-C7QEBNFA.mjs.map +1 -0
  45. package/dist/{ja-SR272JSY.mjs → ja-THS6AOSJ.mjs} +3 -2
  46. package/dist/ja-THS6AOSJ.mjs.map +1 -0
  47. package/dist/{ko-YWTXVVXE.mjs → ko-XKK3TWQG.mjs} +3 -2
  48. package/dist/ko-XKK3TWQG.mjs.map +1 -0
  49. package/dist/{ms-3K2XSJGM.mjs → ms-GSK7LIF7.mjs} +3 -2
  50. package/dist/ms-GSK7LIF7.mjs.map +1 -0
  51. package/dist/{nl-YIGP4SLE.mjs → nl-KUBWITGY.mjs} +3 -2
  52. package/dist/nl-KUBWITGY.mjs.map +1 -0
  53. package/dist/{no-IFYIL3ND.mjs → no-ECWZUHT6.mjs} +3 -2
  54. package/dist/no-ECWZUHT6.mjs.map +1 -0
  55. package/dist/{pl-6MWSASJR.mjs → pl-PLVWSZWS.mjs} +3 -2
  56. package/dist/pl-PLVWSZWS.mjs.map +1 -0
  57. package/dist/{pt-NZNN6WUN.mjs → pt-AL74ZTKB.mjs} +3 -2
  58. package/dist/pt-AL74ZTKB.mjs.map +1 -0
  59. package/dist/{ro-NF3SMUJS.mjs → ro-WTPHLHGS.mjs} +3 -2
  60. package/dist/ro-WTPHLHGS.mjs.map +1 -0
  61. package/dist/{sv-ZHM7GSTD.mjs → sv-QCLI7SG4.mjs} +3 -2
  62. package/dist/sv-QCLI7SG4.mjs.map +1 -0
  63. package/dist/test-utils.d.mts +1 -4
  64. package/dist/test-utils.mjs +4 -6
  65. package/dist/test-utils.mjs.map +1 -1
  66. package/dist/{th-LX4NO5BJ.mjs → th-WCKVZU6U.mjs} +3 -2
  67. package/dist/th-WCKVZU6U.mjs.map +1 -0
  68. package/dist/{tr-DZ4GDSRR.mjs → tr-2CAFS2XS.mjs} +3 -2
  69. package/dist/tr-2CAFS2XS.mjs.map +1 -0
  70. package/dist/{uk-KC5KVVBY.mjs → uk-TDE4JLCY.mjs} +3 -2
  71. package/dist/uk-TDE4JLCY.mjs.map +1 -0
  72. package/dist/{vi-KNCR3OXZ.mjs → vi-KKXZ4PCX.mjs} +3 -2
  73. package/dist/vi-KKXZ4PCX.mjs.map +1 -0
  74. package/dist/{zh-M2HV2A27.mjs → zh-VH4XN5PV.mjs} +3 -2
  75. package/dist/zh-VH4XN5PV.mjs.map +1 -0
  76. package/package.json +1 -1
  77. package/src/components/Toolbar.tsx +15 -0
  78. package/src/components/__tests__/AnnotateReferencesProgressWidget.test.tsx +2 -6
  79. package/src/components/__tests__/Toolbar.test.tsx +2 -6
  80. package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +1 -2
  81. package/src/components/image-annotation/SvgDrawingCanvas.tsx +4 -7
  82. package/src/components/modals/ConfigureGenerationStep.tsx +54 -60
  83. package/src/components/modals/ReferenceWizardModal.tsx +3 -3
  84. package/src/components/navigation/__tests__/ObservableLink.test.tsx +2 -6
  85. package/src/components/navigation/__tests__/SimpleNavigation.test.tsx +2 -6
  86. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +3 -9
  87. package/src/components/resource/AnnotateView.tsx +4 -5
  88. package/src/components/resource/AnnotationHistory.tsx +2 -5
  89. package/src/components/resource/BrowseView.tsx +2 -3
  90. package/src/components/resource/HistoryEvent.tsx +3 -3
  91. package/src/components/resource/__tests__/BrowseView.test.tsx +1 -2
  92. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +8 -8
  93. package/src/components/resource/event-formatting.ts +22 -19
  94. package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +1 -2
  95. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +1 -2
  96. package/src/components/resource/panels/__tests__/AssistSection.test.tsx +0 -2
  97. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +1 -2
  98. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +1 -2
  99. package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +1 -2
  100. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +0 -2
  101. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +1 -2
  102. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +1 -2
  103. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +1 -2
  104. package/src/components/resource/panels/__tests__/TagEntry.test.tsx +1 -2
  105. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +1 -2
  106. package/src/components/settings/__tests__/SettingsPanel.test.tsx +1 -2
  107. package/src/components/viewers/ImageViewer.tsx +2 -8
  108. package/src/components/viewers/__tests__/ImageViewer.test.tsx +3 -16
  109. package/src/features/auth/__tests__/SignInForm.a11y.test.tsx +8 -0
  110. package/src/features/auth/auth.css +62 -0
  111. package/src/features/auth/components/SignInForm.tsx +139 -29
  112. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +2 -6
  113. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +1 -2
  114. package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +1 -2
  115. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +1 -2
  116. package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +1 -2
  117. package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +1 -2
  118. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +1 -2
  119. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +1 -2
  120. package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +9 -10
  121. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +9 -6
  122. package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +2 -12
  123. package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +1 -2
  124. package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +16 -6
  125. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +45 -75
  126. package/src/styles/core/forms.css +32 -0
  127. package/src/styles/core/sliders.css +5 -0
  128. package/translations/ar.json +3 -2
  129. package/translations/bn.json +3 -2
  130. package/translations/cs.json +3 -2
  131. package/translations/da.json +3 -2
  132. package/translations/de.json +3 -2
  133. package/translations/el.json +3 -2
  134. package/translations/en.json +4 -3
  135. package/translations/es.json +3 -2
  136. package/translations/fa.json +3 -2
  137. package/translations/fi.json +3 -2
  138. package/translations/fr.json +3 -2
  139. package/translations/he.json +3 -2
  140. package/translations/hi.json +3 -2
  141. package/translations/id.json +3 -2
  142. package/translations/it.json +3 -2
  143. package/translations/ja.json +3 -2
  144. package/translations/ko.json +3 -2
  145. package/translations/ms.json +3 -2
  146. package/translations/nl.json +3 -2
  147. package/translations/no.json +3 -2
  148. package/translations/pl.json +3 -2
  149. package/translations/pt.json +3 -2
  150. package/translations/ro.json +3 -2
  151. package/translations/sv.json +3 -2
  152. package/translations/th.json +3 -2
  153. package/translations/tr.json +3 -2
  154. package/translations/uk.json +3 -2
  155. package/translations/vi.json +3 -2
  156. package/translations/zh.json +3 -2
  157. package/dist/PdfAnnotationCanvas.client-LF6DDTCV.mjs.map +0 -1
  158. package/dist/ar-3URRW77J.mjs.map +0 -1
  159. package/dist/bn-DCQD3XZ5.mjs.map +0 -1
  160. package/dist/chunk-5JZFKRLW.mjs.map +0 -1
  161. package/dist/chunk-PWIVZQ4X.mjs.map +0 -1
  162. package/dist/chunk-XMCUHQ2Y.mjs.map +0 -1
  163. package/dist/cs-23KOZUFE.mjs.map +0 -1
  164. package/dist/da-OIQ66A42.mjs.map +0 -1
  165. package/dist/de-FCCLKE2X.mjs.map +0 -1
  166. package/dist/el-3ADITCGI.mjs.map +0 -1
  167. package/dist/es-POQEEYIW.mjs.map +0 -1
  168. package/dist/fa-RQPXVELG.mjs.map +0 -1
  169. package/dist/fi-UXOVOUGT.mjs.map +0 -1
  170. package/dist/fr-6W2T3R7G.mjs.map +0 -1
  171. package/dist/he-65UHPZIU.mjs.map +0 -1
  172. package/dist/hi-SGJIVPTN.mjs.map +0 -1
  173. package/dist/id-EYJJQCS2.mjs.map +0 -1
  174. package/dist/it-IZGQEDO7.mjs.map +0 -1
  175. package/dist/ja-SR272JSY.mjs.map +0 -1
  176. package/dist/ko-YWTXVVXE.mjs.map +0 -1
  177. package/dist/ms-3K2XSJGM.mjs.map +0 -1
  178. package/dist/nl-YIGP4SLE.mjs.map +0 -1
  179. package/dist/no-IFYIL3ND.mjs.map +0 -1
  180. package/dist/pl-6MWSASJR.mjs.map +0 -1
  181. package/dist/pt-NZNN6WUN.mjs.map +0 -1
  182. package/dist/ro-NF3SMUJS.mjs.map +0 -1
  183. package/dist/sv-ZHM7GSTD.mjs.map +0 -1
  184. package/dist/th-LX4NO5BJ.mjs.map +0 -1
  185. package/dist/tr-DZ4GDSRR.mjs.map +0 -1
  186. package/dist/uk-KC5KVVBY.mjs.map +0 -1
  187. package/dist/vi-KNCR3OXZ.mjs.map +0 -1
  188. package/dist/zh-M2HV2A27.mjs.map +0 -1
  189. /package/dist/{chunk-4RMWYJUJ.mjs.map → chunk-OL5UST25.mjs.map} +0 -0
  190. /package/dist/{en-LNW2A3RA.mjs.map → en-IUV4ZXKH.mjs.map} +0 -0
@@ -70,7 +70,7 @@ export function ConfigureGenerationStep({
70
70
  };
71
71
 
72
72
  return (
73
- <form onSubmit={handleSubmit} className="semiont-form">
73
+ <form onSubmit={handleSubmit} className="semiont-form semiont-form--scrollable">
74
74
  {/* Resource Title */}
75
75
  <div className="semiont-form__field">
76
76
  <label htmlFor="wizard-title" className="semiont-form__label">
@@ -115,73 +115,67 @@ export function ConfigureGenerationStep({
115
115
  id="wizard-prompt"
116
116
  value={prompt}
117
117
  onChange={(e) => setPrompt(e.target.value)}
118
- rows={3}
118
+ rows={2}
119
119
  className="semiont-textarea"
120
120
  placeholder={t.additionalInstructionsPlaceholder}
121
121
  />
122
122
  </div>
123
123
 
124
- {/* Language Selection */}
125
- <div className="semiont-form__field">
126
- <label htmlFor="wizard-language" className="semiont-form__label">
127
- {t.language}
128
- </label>
129
- <select
130
- id="wizard-language"
131
- value={language}
132
- onChange={(e) => setLanguage(e.target.value)}
133
- className="semiont-select"
134
- >
135
- {LOCALES.map((lang) => (
136
- <option key={lang.code} value={lang.code}>
137
- {lang.nativeName}
138
- </option>
139
- ))}
140
- </select>
141
- <p className="semiont-form__help">
142
- {t.languageHelp}
143
- </p>
144
- </div>
124
+ {/* Language / Creativity / Max Length — compact inline row */}
125
+ <div className="semiont-form__inline-row">
126
+ <div className="semiont-form__field semiont-form__field--inline">
127
+ <label htmlFor="wizard-language" className="semiont-form__label">
128
+ {t.language}
129
+ </label>
130
+ <select
131
+ id="wizard-language"
132
+ value={language}
133
+ onChange={(e) => setLanguage(e.target.value)}
134
+ className="semiont-select"
135
+ >
136
+ {LOCALES.map((lang) => (
137
+ <option key={lang.code} value={lang.code}>
138
+ {lang.nativeName}
139
+ </option>
140
+ ))}
141
+ </select>
142
+ </div>
145
143
 
146
- {/* Temperature Slider */}
147
- <div className="semiont-form__field">
148
- <label htmlFor="wizard-temperature" className="semiont-form__label">
149
- {t.creativity} ({temperature.toFixed(1)})
150
- </label>
151
- <input
152
- id="wizard-temperature"
153
- type="range"
154
- min="0"
155
- max="1"
156
- step="0.1"
157
- value={temperature}
158
- onChange={(e) => setTemperature(parseFloat(e.target.value))}
159
- className="semiont-slider"
160
- />
161
- <div className="semiont-slider__labels">
162
- <span>{t.creativityFocused}</span>
163
- <span>{t.creativityCreative}</span>
144
+ <div className="semiont-form__field semiont-form__field--inline semiont-form__field--grow">
145
+ <label htmlFor="wizard-temperature" className="semiont-form__label">
146
+ {t.creativity} ({temperature.toFixed(1)})
147
+ </label>
148
+ <input
149
+ id="wizard-temperature"
150
+ type="range"
151
+ min="0"
152
+ max="1"
153
+ step="0.1"
154
+ value={temperature}
155
+ onChange={(e) => setTemperature(parseFloat(e.target.value))}
156
+ className="semiont-slider"
157
+ />
158
+ <div className="semiont-slider__labels semiont-slider__labels--small">
159
+ <span>{t.creativityFocused}</span>
160
+ <span>{t.creativityCreative}</span>
161
+ </div>
164
162
  </div>
165
- </div>
166
163
 
167
- {/* Max Tokens Input */}
168
- <div className="semiont-form__field">
169
- <label htmlFor="wizard-maxTokens" className="semiont-form__label">
170
- {t.maxLength}
171
- </label>
172
- <input
173
- id="wizard-maxTokens"
174
- type="number"
175
- min="100"
176
- max="4000"
177
- step="100"
178
- value={maxTokens}
179
- onChange={(e) => setMaxTokens(parseInt(e.target.value))}
180
- className="semiont-input"
181
- />
182
- <p className="semiont-form__help">
183
- {t.maxLengthHelp}
184
- </p>
164
+ <div className="semiont-form__field semiont-form__field--inline semiont-form__field--narrow">
165
+ <label htmlFor="wizard-maxTokens" className="semiont-form__label">
166
+ {t.maxLength}
167
+ </label>
168
+ <input
169
+ id="wizard-maxTokens"
170
+ type="number"
171
+ min="100"
172
+ max="4000"
173
+ step="100"
174
+ value={maxTokens}
175
+ onChange={(e) => setMaxTokens(parseInt(e.target.value))}
176
+ className="semiont-input"
177
+ />
178
+ </div>
185
179
  </div>
186
180
 
187
181
  {/* Action Buttons */}
@@ -115,10 +115,9 @@ export function ReferenceWizardModal({
115
115
  if (!isOpen) return;
116
116
 
117
117
  const subscription = eventBus.get('match:search-results').subscribe((event) => {
118
- const e = event as { referenceId: string; results: ScoredResult[] };
119
- if (annotationId && e.referenceId === annotationId) {
118
+ if (annotationId && event.referenceId === annotationId) {
120
119
  setIsSearching(false);
121
- setWizardStep({ step: 'search-results', results: e.results });
120
+ setWizardStep({ step: 'search-results', results: event.response as ScoredResult[] });
122
121
  }
123
122
  });
124
123
 
@@ -149,6 +148,7 @@ export function ReferenceWizardModal({
149
148
  setIsSearching(true);
150
149
  const contextWithHint = userHint ? { ...context, userHint } : context;
151
150
  eventBus.get('match:search-requested').next({
151
+ correlationId: crypto.randomUUID(),
152
152
  referenceId: annotationId,
153
153
  context: contextWithHint,
154
154
  limit: config.limit,
@@ -1,15 +1,11 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
1
+ import { describe, it, expect, vi } from 'vitest';
2
2
  import React from 'react';
3
3
  import { screen, fireEvent } from '@testing-library/react';
4
4
  import '@testing-library/jest-dom';
5
- import { renderWithProviders, resetEventBusForTesting } from '../../../test-utils';
5
+ import { renderWithProviders } from '../../../test-utils';
6
6
  import { ObservableLink } from '../ObservableLink';
7
7
 
8
8
  describe('ObservableLink', () => {
9
- beforeEach(() => {
10
- resetEventBusForTesting();
11
- });
12
-
13
9
  it('renders anchor with href', () => {
14
10
  renderWithProviders(
15
11
  <ObservableLink href="/discover">Discover</ObservableLink>
@@ -1,8 +1,8 @@
1
- import { describe, it, expect, beforeEach, vi } from 'vitest';
1
+ import { describe, it, expect, vi } from 'vitest';
2
2
  import React from 'react';
3
3
  import { screen, fireEvent } from '@testing-library/react';
4
4
  import '@testing-library/jest-dom';
5
- import { renderWithProviders, resetEventBusForTesting } from '../../../test-utils';
5
+ import { renderWithProviders } from '../../../test-utils';
6
6
  import { SimpleNavigation } from '../SimpleNavigation';
7
7
  import type { SimpleNavigationItem } from '../SimpleNavigation';
8
8
 
@@ -36,10 +36,6 @@ const defaultProps = {
36
36
  };
37
37
 
38
38
  describe('SimpleNavigation', () => {
39
- beforeEach(() => {
40
- resetEventBusForTesting();
41
- });
42
-
43
39
  describe('title visibility', () => {
44
40
  it('renders title when not collapsed', () => {
45
41
  renderWithProviders(<SimpleNavigation {...defaultProps} />);
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useRef, useState, useCallback, useEffect, useMemo } from 'react';
4
4
  import { createHoverHandlers } from '../../hooks/useBeckonFlow';
5
- import type { components, ResourceId } from '@semiont/core';
5
+ import type { components } from '@semiont/core';
6
6
  import { getTargetSelector } from '@semiont/api-client';
7
7
  import type { SelectionMotivation } from '../annotation/AnnotateToolbar';
8
8
  import type { EventBus } from "@semiont/core"
@@ -48,7 +48,7 @@ function getMotivationColor(motivation: SelectionMotivation | null): { stroke: s
48
48
  }
49
49
 
50
50
  interface PdfAnnotationCanvasProps {
51
- resourceUri: ResourceId;
51
+ pdfUrl: string;
52
52
  existingAnnotations?: Annotation[];
53
53
  drawingMode: DrawingMode;
54
54
  selectedMotivation?: SelectionMotivation | null;
@@ -66,7 +66,7 @@ interface PdfAnnotationCanvasProps {
66
66
  * @emits beckon:hover - Annotation hovered or unhovered. Payload: { annotationId: string | null }
67
67
  */
68
68
  export function PdfAnnotationCanvas({
69
- resourceUri,
69
+ pdfUrl,
70
70
  existingAnnotations = [],
71
71
  drawingMode,
72
72
  selectedMotivation,
@@ -75,12 +75,6 @@ export function PdfAnnotationCanvas({
75
75
  selectedAnnotationId,
76
76
  hoverDelayMs = 150
77
77
  }: PdfAnnotationCanvasProps) {
78
- const pdfUrl = useMemo(() => {
79
- return `/api/resources/${resourceUri}`;
80
- }, [resourceUri]);
81
-
82
- // Removed excessive logging
83
-
84
78
  // PDF state
85
79
  const [pdfDoc, setPdfDoc] = useState<PDFDocumentProxy | null>(null);
86
80
  const [numPages, setNumPages] = useState<number>(0);
@@ -1,7 +1,6 @@
1
1
  'use client';
2
2
 
3
3
  import { useRef, useEffect, useCallback, lazy, Suspense } from 'react';
4
- import { resourceId as toResourceId } from '@semiont/core';
5
4
  import { getMimeCategory, isPdfMimeType } from '@semiont/api-client';
6
5
  import { ANNOTATORS } from '../../lib/annotation-registry';
7
6
  import { segmentTextWithAnnotations } from '../../lib/text-segmentation';
@@ -244,10 +243,10 @@ export function AnnotateView({
244
243
  annotators={ANNOTATORS}
245
244
  />
246
245
  <div className="semiont-annotate-view__content">
247
- {resourceUri && (
246
+ {content && (
248
247
  <Suspense fallback={<div className="semiont-annotate-view__loading">Loading PDF viewer...</div>}>
249
248
  <PdfAnnotationCanvas
250
- resourceUri={toResourceId(resourceUri)}
249
+ pdfUrl={content}
251
250
  existingAnnotations={allAnnotations}
252
251
  drawingMode={selectedMotivation ? selectedShape : null}
253
252
  selectedMotivation={selectedMotivation}
@@ -275,9 +274,9 @@ export function AnnotateView({
275
274
  annotators={ANNOTATORS}
276
275
  />
277
276
  <div className="semiont-annotate-view__content">
278
- {resourceUri && (
277
+ {content && (
279
278
  <SvgDrawingCanvas
280
- resourceUri={toResourceId(resourceUri)}
279
+ imageUrl={content}
281
280
  existingAnnotations={allAnnotations}
282
281
  drawingMode={selectedMotivation ? selectedShape : null}
283
282
  selectedMotivation={selectedMotivation}
@@ -5,7 +5,6 @@ import { useTranslations } from '../../contexts/TranslationContext';
5
5
  import type { RouteBuilder, LinkComponentProps } from '../../contexts/RoutingContext';
6
6
  import { useResources } from '../../lib/api-hooks';
7
7
  import type { ResourceId } from '@semiont/core';
8
- import type { StoredEvent } from '@semiont/core';
9
8
  import { getAnnotationUriFromEvent } from '@semiont/core';
10
9
  import { HistoryEvent } from './HistoryEvent';
11
10
 
@@ -39,13 +38,11 @@ export function AnnotationHistory({ rUri, hoveredAnnotationId, onEventHover, onE
39
38
  // Sort events by oldest first (most recent at bottom)
40
39
  // Filter out all job events - they're represented by annotation.body.updated events instead
41
40
  const events = !eventsData?.events ? [] : [...eventsData.events]
42
- .filter((e: StoredEvent) => {
41
+ .filter((e) => {
43
42
  const eventType = e.event.type;
44
43
  return eventType !== 'job.started' && eventType !== 'job.progress' && eventType !== 'job.completed';
45
44
  })
46
- .sort((a: StoredEvent, b: StoredEvent) =>
47
- a.metadata.sequenceNumber - b.metadata.sequenceNumber
48
- );
45
+ .sort((a, b) => a.metadata.sequenceNumber - b.metadata.sequenceNumber);
49
46
 
50
47
  // Scroll to bottom when History is first shown or when events change
51
48
  useEffect(() => {
@@ -3,7 +3,6 @@
3
3
  import { useEffect, useRef, useCallback, useMemo, memo, lazy, Suspense } from 'react';
4
4
  import ReactMarkdown from 'react-markdown';
5
5
  import remarkGfm from 'remark-gfm';
6
- import { resourceId as toResourceId } from '@semiont/core';
7
6
  import { getMimeCategory, isPdfMimeType } from '@semiont/api-client';
8
7
  import { ANNOTATORS } from '../../lib/annotation-registry';
9
8
  import { createHoverHandlers } from '../../hooks/useBeckonFlow';
@@ -240,7 +239,7 @@ export const BrowseView = memo(function BrowseView({
240
239
  <div ref={containerRef} className="semiont-browse-view__content">
241
240
  <Suspense fallback={<div className="semiont-browse-view__loading">Loading PDF viewer...</div>}>
242
241
  <PdfAnnotationCanvas
243
- resourceUri={toResourceId(resourceUri)}
242
+ pdfUrl={content}
244
243
  existingAnnotations={allAnnotations}
245
244
  drawingMode={null}
246
245
  selectedMotivation={null}
@@ -264,7 +263,7 @@ export const BrowseView = memo(function BrowseView({
264
263
  />
265
264
  <div ref={containerRef} className="semiont-browse-view__content">
266
265
  <ImageViewer
267
- resourceUri={toResourceId(resourceUri)}
266
+ imageUrl={content}
268
267
  mimeType={mimeType}
269
268
  alt="Resource content"
270
269
  />
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useRef, useCallback, useEffect } from 'react';
4
4
  import type { RouteBuilder, LinkComponentProps } from '../../contexts/RoutingContext';
5
- import type { StoredEvent, ResourceEventType } from '@semiont/core';
5
+ import type { StoredEventLike, ResourceEventType } from '@semiont/core';
6
6
  import { getAnnotationUriFromEvent } from '@semiont/core';
7
7
  import {
8
8
  formatEventType,
@@ -16,9 +16,9 @@ import {
16
16
  type TranslateFn = (key: string, params?: Record<string, string | number>) => string;
17
17
 
18
18
  interface Props {
19
- event: StoredEvent;
19
+ event: StoredEventLike;
20
20
  annotations: any[]; // Unified annotations array (all types)
21
- allEvents: StoredEvent[];
21
+ allEvents: StoredEventLike[];
22
22
  isRelated: boolean;
23
23
  t: TranslateFn;
24
24
  Link: React.ComponentType<LinkComponentProps>;
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { render, screen, fireEvent, waitFor } from '@testing-library/react';
4
4
  import { BrowseView } from '../BrowseView';
5
5
  import type { components } from '@semiont/core';
6
- import { EventBusProvider, resetEventBusForTesting, useEventBus } from '../../../contexts/EventBusContext';
6
+ import { EventBusProvider, useEventBus } from '../../../contexts/EventBusContext';
7
7
 
8
8
  type Annotation = components['schemas']['Annotation'];
9
9
 
@@ -214,7 +214,6 @@ describe('BrowseView Component', () => {
214
214
  };
215
215
 
216
216
  beforeEach(() => {
217
- resetEventBusForTesting();
218
217
  vi.clearAllMocks();
219
218
  mockNewAnnotationIds = new Set();
220
219
 
@@ -75,19 +75,19 @@ const mockTranslationManager = {
75
75
  function TestWrapper({ children }: { children: React.ReactNode }) {
76
76
  return (
77
77
  <TranslationProvider translationManager={mockTranslationManager}>
78
- <AuthTokenProvider token="test-token">
79
- <ApiClientProvider baseUrl="http://localhost:4000">
80
- <QueryClientProvider client={queryClient}>
81
- <EventBusProvider>
78
+ <EventBusProvider>
79
+ <AuthTokenProvider token="test-token">
80
+ <ApiClientProvider baseUrl="http://localhost:4000">
81
+ <QueryClientProvider client={queryClient}>
82
82
  <ResourceAnnotationsProvider>
83
83
  <CacheProvider cacheManager={mockCacheManager}>
84
84
  {children}
85
85
  </CacheProvider>
86
86
  </ResourceAnnotationsProvider>
87
- </EventBusProvider>
88
- </QueryClientProvider>
89
- </ApiClientProvider>
90
- </AuthTokenProvider>
87
+ </QueryClientProvider>
88
+ </ApiClientProvider>
89
+ </AuthTokenProvider>
90
+ </EventBusProvider>
91
91
  </TranslationProvider>
92
92
  );
93
93
  }
@@ -5,7 +5,7 @@
5
5
  * No React dependencies - safe to use in any JavaScript environment.
6
6
  */
7
7
 
8
- import type { StoredEvent, ResourceEventType } from '@semiont/core';
8
+ import type { StoredEventLike, ResourceEventType } from '@semiont/core';
9
9
  import type { components } from '@semiont/core';
10
10
  import { getExactText, getTargetSelector } from '@semiont/api-client';
11
11
  import { ANNOTATORS } from '../../lib/annotation-registry';
@@ -144,17 +144,18 @@ function truncateText(text: string, maxLength = 50): string {
144
144
  * Get display content from event payload - complete implementation
145
145
  */
146
146
  export function getEventDisplayContent(
147
- event: StoredEvent,
147
+ event: StoredEventLike,
148
148
  annotations: Annotation[], // Unified annotations array (all types)
149
- allEvents: StoredEvent[]
149
+ allEvents: StoredEventLike[]
150
150
  ): { exact: string; isQuoted: boolean; isTag: boolean } | null {
151
151
  const eventData = event.event;
152
+ const payload = eventData.payload as any;
152
153
 
153
154
  // Use type discriminators for proper narrowing
154
155
  switch (eventData.type) {
155
156
  case 'resource.created':
156
157
  case 'resource.cloned': {
157
- return { exact: eventData.payload.name, isQuoted: false, isTag: false };
158
+ return { exact: payload.name, isQuoted: false, isTag: false };
158
159
  }
159
160
 
160
161
  // Unified annotation events
@@ -162,7 +163,7 @@ export function getEventDisplayContent(
162
163
  // Find current annotation to get its text
163
164
  // payload.annotationId is just the UUID, but annotation.id is the full URI
164
165
  const annotation = annotations.find(a =>
165
- a.id.endsWith(`/annotations/${eventData.payload.annotationId}`)
166
+ a.id.endsWith(`/annotations/${payload.annotationId}`)
166
167
  );
167
168
 
168
169
  if (annotation?.target) {
@@ -184,11 +185,11 @@ export function getEventDisplayContent(
184
185
  // payload.annotationId is just the UUID, but annotation.id in the added event is the full URI
185
186
  const addedEvent = allEvents.find(e =>
186
187
  e.event.type === 'annotation.added' &&
187
- e.event.payload.annotation.id.endsWith(`/annotations/${eventData.payload.annotationId}`)
188
+ (e.event.payload as any).annotation.id.endsWith(`/annotations/${payload.annotationId}`)
188
189
  );
189
190
  if (addedEvent && addedEvent.event.type === 'annotation.added') {
190
191
  try {
191
- const target = addedEvent.event.payload.annotation.target;
192
+ const target = (addedEvent.event.payload as any).annotation.target;
192
193
  if (typeof target !== 'string' && target.selector) {
193
194
  const exact = getExactText(target.selector);
194
195
  if (exact) {
@@ -205,7 +206,7 @@ export function getEventDisplayContent(
205
206
  case 'annotation.added': {
206
207
  // New unified event structure - annotation is in payload
207
208
  try {
208
- const target = eventData.payload.annotation.target;
209
+ const target = payload.annotation.target;
209
210
  if (typeof target !== 'string' && target.selector) {
210
211
  const exact = getExactText(target.selector);
211
212
  if (exact) {
@@ -220,14 +221,14 @@ export function getEventDisplayContent(
220
221
 
221
222
  case 'entitytag.added':
222
223
  case 'entitytag.removed': {
223
- return { exact: eventData.payload.entityType, isQuoted: false, isTag: true };
224
+ return { exact: payload.entityType, isQuoted: false, isTag: true };
224
225
  }
225
226
 
226
227
  case 'job.completed': {
227
228
  // Find the annotation that was used to generate the resource
228
- if (eventData.payload.annotationUri) {
229
+ if (payload.annotationUri) {
229
230
  const annotation = annotations.find(a =>
230
- a.id === eventData.payload.annotationUri
231
+ a.id === payload.annotationUri
231
232
  );
232
233
 
233
234
  if (annotation?.target) {
@@ -260,12 +261,13 @@ export function getEventDisplayContent(
260
261
  /**
261
262
  * Get entity types from event payload
262
263
  */
263
- export function getEventEntityTypes(event: StoredEvent): string[] {
264
+ export function getEventEntityTypes(event: StoredEventLike): string[] {
264
265
  const eventData = event.event;
266
+ const payload = eventData.payload as any;
265
267
 
266
268
  if (eventData.type === 'annotation.added') {
267
- const motivation = eventData.payload.annotation.motivation;
268
- const body = eventData.payload.annotation.body;
269
+ const motivation = payload.annotation.motivation;
270
+ const body = payload.annotation.body;
269
271
  if (motivation === 'linking' && body && 'entityTypes' in body) {
270
272
  return (body as any).entityTypes ?? [];
271
273
  }
@@ -289,13 +291,14 @@ export interface ResourceCreationDetails {
289
291
  /**
290
292
  * Get resource creation details from event
291
293
  */
292
- export function getResourceCreationDetails(event: StoredEvent): ResourceCreationDetails | null {
294
+ export function getResourceCreationDetails(event: StoredEventLike): ResourceCreationDetails | null {
293
295
  const eventData = event.event;
296
+ const payload = eventData.payload as any;
294
297
 
295
298
  if (eventData.type === 'resource.created') {
296
299
  return {
297
300
  type: 'created',
298
- method: eventData.payload.creationMethod || 'unknown',
301
+ method: payload.creationMethod || 'unknown',
299
302
  userId: eventData.userId,
300
303
  metadata: undefined,
301
304
  };
@@ -304,10 +307,10 @@ export function getResourceCreationDetails(event: StoredEvent): ResourceCreation
304
307
  if (eventData.type === 'resource.cloned') {
305
308
  return {
306
309
  type: 'cloned',
307
- method: eventData.payload.creationMethod || 'clone',
310
+ method: payload.creationMethod || 'clone',
308
311
  userId: eventData.userId,
309
- sourceDocId: eventData.payload.parentResourceId,
310
- parentResourceId: eventData.payload.parentResourceId,
312
+ sourceDocId: payload.parentResourceId,
313
+ parentResourceId: payload.parentResourceId,
311
314
  metadata: undefined,
312
315
  };
313
316
  }
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
2
  import React from 'react';
3
3
  import { screen } from '@testing-library/react';
4
4
  import '@testing-library/jest-dom';
5
- import { renderWithProviders, resetEventBusForTesting } from '../../../../test-utils';
5
+ import { renderWithProviders } from '../../../../test-utils';
6
6
  import userEvent from '@testing-library/user-event';
7
7
  import type { components } from '@semiont/core';
8
8
 
@@ -56,7 +56,6 @@ describe('AssessmentEntry', () => {
56
56
 
57
57
  beforeEach(() => {
58
58
  vi.clearAllMocks();
59
- resetEventBusForTesting();
60
59
  mockGetAnnotationExactText.mockReturnValue('Selected passage text');
61
60
  });
62
61
 
@@ -5,7 +5,7 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
5
5
  import userEvent from '@testing-library/user-event';
6
6
  import '@testing-library/jest-dom';
7
7
  import { AssessmentPanel } from '../AssessmentPanel';
8
- import { EventBusProvider, resetEventBusForTesting, useEventBus } from '../../../../contexts/EventBusContext';
8
+ import { EventBusProvider, useEventBus } from '../../../../contexts/EventBusContext';
9
9
  import type { components } from '@semiont/core';
10
10
 
11
11
  type Annotation = components['schemas']['Annotation'];
@@ -178,7 +178,6 @@ describe('AssessmentPanel Component', () => {
178
178
  };
179
179
 
180
180
  beforeEach(() => {
181
- resetEventBusForTesting();
182
181
  vi.clearAllMocks();
183
182
 
184
183
  // Mock scrollIntoView for jsdom
@@ -17,7 +17,6 @@ import { screen } from '@testing-library/react';
17
17
  import { renderWithProviders } from '../../../../test-utils';
18
18
  import userEvent from '@testing-library/user-event';
19
19
  import { AssistSection } from '../AssistSection';
20
- import { resetEventBusForTesting } from '../../../../contexts/EventBusContext';
21
20
  import type { EventBus } from "@semiont/core"
22
21
 
23
22
  // Mock translations
@@ -56,7 +55,6 @@ vi.mock('../../../../contexts/TranslationContext', () => ({
56
55
  describe('AssistSection', () => {
57
56
  beforeEach(() => {
58
57
  vi.clearAllMocks();
59
- resetEventBusForTesting();
60
58
  // Clear localStorage
61
59
  if (typeof window !== 'undefined') {
62
60
  localStorage.clear();
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
2
  import React from 'react';
3
3
  import { screen, fireEvent, waitFor } from '@testing-library/react';
4
- import { renderWithProviders, resetEventBusForTesting } from '../../../../test-utils';
4
+ import { renderWithProviders } from '../../../../test-utils';
5
5
  import userEvent from '@testing-library/user-event';
6
6
  import '@testing-library/jest-dom';
7
7
  import { CommentEntry } from '../CommentEntry';
@@ -105,7 +105,6 @@ describe('CommentEntry Component', () => {
105
105
 
106
106
  beforeEach(() => {
107
107
  vi.clearAllMocks();
108
- resetEventBusForTesting(); // Reset event bus between tests
109
108
  mockGetCommentText.mockReturnValue('This is a test comment');
110
109
  mockGetAnnotationExactText.mockReturnValue('This is th');
111
110
 
@@ -5,7 +5,7 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
5
5
  import userEvent from '@testing-library/user-event';
6
6
  import '@testing-library/jest-dom';
7
7
  import { CommentsPanel } from '../CommentsPanel';
8
- import { EventBusProvider, resetEventBusForTesting, useEventBus } from '../../../../contexts/EventBusContext';
8
+ import { EventBusProvider, useEventBus } from '../../../../contexts/EventBusContext';
9
9
  import type { components } from '@semiont/core';
10
10
 
11
11
  type Annotation = components['schemas']['Annotation'];
@@ -178,7 +178,6 @@ describe('CommentsPanel Component', () => {
178
178
  };
179
179
 
180
180
  beforeEach(() => {
181
- resetEventBusForTesting();
182
181
  vi.clearAllMocks();
183
182
 
184
183
  // Mock scrollIntoView for jsdom
@@ -2,7 +2,7 @@ import { describe, it, expect, beforeEach, vi } from 'vitest';
2
2
  import React from 'react';
3
3
  import { screen, fireEvent } from '@testing-library/react';
4
4
  import '@testing-library/jest-dom';
5
- import { renderWithProviders, resetEventBusForTesting } from '../../../../test-utils';
5
+ import { renderWithProviders } from '../../../../test-utils';
6
6
  import userEvent from '@testing-library/user-event';
7
7
  import type { components } from '@semiont/core';
8
8
 
@@ -52,7 +52,6 @@ describe('HighlightEntry', () => {
52
52
 
53
53
  beforeEach(() => {
54
54
  vi.clearAllMocks();
55
- resetEventBusForTesting();
56
55
  mockGetAnnotationExactText.mockReturnValue('This is the highlighted text');
57
56
  });
58
57
 
@@ -17,7 +17,6 @@ import { screen } from '@testing-library/react';
17
17
  import { renderWithProviders } from '../../../../test-utils';
18
18
  import { HighlightPanel } from '../HighlightPanel';
19
19
  import type { components } from '@semiont/core';
20
- import { resetEventBusForTesting } from '../../../../contexts/EventBusContext';
21
20
 
22
21
  type Annotation = components['schemas']['Annotation'];
23
22
 
@@ -53,7 +52,6 @@ describe('HighlightPanel + AssistSection Integration', () => {
53
52
 
54
53
  beforeEach(() => {
55
54
  vi.clearAllMocks();
56
- resetEventBusForTesting();
57
55
 
58
56
  mockAnnotations = [
59
57
  {