@semiont/react-ui 0.5.5 → 0.5.7

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 (218) hide show
  1. package/README.md +59 -55
  2. package/dist/{PdfAnnotationCanvas.client-CN3C3S55.js → PdfAnnotationCanvas.client-NIMALXNZ.js} +7 -27
  3. package/dist/PdfAnnotationCanvas.client-NIMALXNZ.js.map +1 -0
  4. package/dist/{ar-U2EXWUMQ.js → ar-SONK6MON.js} +3 -7
  5. package/dist/ar-SONK6MON.js.map +1 -0
  6. package/dist/{bn-DRJGV772.js → bn-ZKPRITNG.js} +3 -7
  7. package/dist/bn-ZKPRITNG.js.map +1 -0
  8. package/dist/{chunk-3Q3TUKWP.js → chunk-Y2EEAOMZ.js} +29 -29
  9. package/dist/{cs-PTWDM23V.js → cs-LPXQ7NHQ.js} +3 -7
  10. package/dist/cs-LPXQ7NHQ.js.map +1 -0
  11. package/dist/{da-KSNIKYSS.js → da-6TKY7MCY.js} +6 -10
  12. package/dist/da-6TKY7MCY.js.map +1 -0
  13. package/dist/{de-F2XBEWFY.js → de-C3GNII74.js} +3 -7
  14. package/dist/de-C3GNII74.js.map +1 -0
  15. package/dist/{el-DLD2GWAP.js → el-UBCXQDJ7.js} +3 -7
  16. package/dist/el-UBCXQDJ7.js.map +1 -0
  17. package/dist/{es-WLPYWGB5.js → es-BQ23TRI7.js} +11 -15
  18. package/dist/es-BQ23TRI7.js.map +1 -0
  19. package/dist/{fa-BAXHSDZG.js → fa-AFTBZB77.js} +3 -7
  20. package/dist/fa-AFTBZB77.js.map +1 -0
  21. package/dist/{fi-FCHSYVOT.js → fi-WOYNLZC2.js} +3 -7
  22. package/dist/fi-WOYNLZC2.js.map +1 -0
  23. package/dist/{fr-3UERBSL6.js → fr-NDSMIFJM.js} +3 -7
  24. package/dist/fr-NDSMIFJM.js.map +1 -0
  25. package/dist/{he-F6F3FV2K.js → he-VJXVRDOY.js} +3 -7
  26. package/dist/he-VJXVRDOY.js.map +1 -0
  27. package/dist/{hi-4BK6IK7Q.js → hi-BF6PHIE2.js} +3 -7
  28. package/dist/hi-BF6PHIE2.js.map +1 -0
  29. package/dist/{id-7ECCWP3J.js → id-GXG5QCZY.js} +3 -7
  30. package/dist/id-GXG5QCZY.js.map +1 -0
  31. package/dist/index.css +103 -0
  32. package/dist/index.css.map +1 -1
  33. package/dist/index.d.ts +271 -120
  34. package/dist/index.js +877 -698
  35. package/dist/index.js.map +1 -1
  36. package/dist/{it-234Z6XK6.js → it-XKHHCBAF.js} +3 -7
  37. package/dist/it-XKHHCBAF.js.map +1 -0
  38. package/dist/{ja-PJWQI4OQ.js → ja-TX7VM4XD.js} +3 -7
  39. package/dist/ja-TX7VM4XD.js.map +1 -0
  40. package/dist/{ko-APUEW2RS.js → ko-DNC7EQ7J.js} +3 -7
  41. package/dist/ko-DNC7EQ7J.js.map +1 -0
  42. package/dist/{ms-PJBZWZWD.js → ms-POZGBKPH.js} +3 -7
  43. package/dist/ms-POZGBKPH.js.map +1 -0
  44. package/dist/{nl-L4C3ZBCU.js → nl-IRMTKI7Z.js} +4 -11
  45. package/dist/nl-IRMTKI7Z.js.map +1 -0
  46. package/dist/{no-QE5N5KNG.js → no-ZUDJA4S6.js} +20 -24
  47. package/dist/no-ZUDJA4S6.js.map +1 -0
  48. package/dist/{pl-5Q2D23PD.js → pl-2NGAXL5U.js} +3 -7
  49. package/dist/pl-2NGAXL5U.js.map +1 -0
  50. package/dist/{pt-AIGUOIOC.js → pt-ABMCXZUM.js} +118 -122
  51. package/dist/pt-ABMCXZUM.js.map +1 -0
  52. package/dist/{ro-T56CSHTY.js → ro-VOJP6O5X.js} +3 -7
  53. package/dist/ro-VOJP6O5X.js.map +1 -0
  54. package/dist/{sv-L4TJQ2UH.js → sv-4HVFIIE5.js} +43 -47
  55. package/dist/sv-4HVFIIE5.js.map +1 -0
  56. package/dist/test-utils.js +2 -2
  57. package/dist/test-utils.js.map +1 -1
  58. package/dist/{th-6O7Y6O2Q.js → th-IFPZP3HQ.js} +3 -7
  59. package/dist/th-IFPZP3HQ.js.map +1 -0
  60. package/dist/{tr-D4CQCSNO.js → tr-2GYEAMJ4.js} +3 -7
  61. package/dist/tr-2GYEAMJ4.js.map +1 -0
  62. package/dist/{uk-2HMQG6ND.js → uk-XCJBVLLD.js} +3 -7
  63. package/dist/uk-XCJBVLLD.js.map +1 -0
  64. package/dist/{vi-XVJ4RUEJ.js → vi-4FR7CB2F.js} +3 -7
  65. package/dist/vi-4FR7CB2F.js.map +1 -0
  66. package/dist/{zh-K2KDPGHK.js → zh-NSKFOINB.js} +3 -7
  67. package/dist/zh-NSKFOINB.js.map +1 -0
  68. package/package.json +17 -13
  69. package/src/components/Button/__tests__/Button.test.tsx +0 -2
  70. package/src/components/CodeMirrorRenderer.tsx +2 -0
  71. package/src/components/ErrorBoundary.tsx +0 -9
  72. package/src/components/ProtectedErrorBoundary.css +119 -0
  73. package/src/components/ProtectedErrorBoundary.tsx +24 -15
  74. package/src/components/__tests__/AnnotateReferencesProgressWidget.test.tsx +0 -1
  75. package/src/components/__tests__/ErrorBoundary.test.tsx +20 -13
  76. package/src/components/__tests__/LiveRegion.hooks.test.tsx +1 -1
  77. package/src/components/__tests__/ProtectedErrorBoundary.test.tsx +2 -1
  78. package/src/components/__tests__/ResizeHandle.test.tsx +0 -1
  79. package/src/components/__tests__/SessionExpiryBanner.test.tsx +0 -1
  80. package/src/components/__tests__/StatusDisplay.test.tsx +0 -1
  81. package/src/components/__tests__/Toast.test.tsx +2 -3
  82. package/src/components/__tests__/Toolbar.test.tsx +0 -1
  83. package/src/components/annotation/annotations.css +14 -0
  84. package/src/components/annotation-popups/__tests__/JsonLdView.test.tsx +3 -5
  85. package/src/components/annotation-popups/__tests__/SharedPopupElements.test.tsx +0 -1
  86. package/src/components/branding/__tests__/SemiontBranding.test.tsx +1 -2
  87. package/src/components/layout/__tests__/LeftSidebar.test.tsx +5 -6
  88. package/src/components/layout/__tests__/PageLayout.test.tsx +1 -3
  89. package/src/components/layout/__tests__/SkipLinks.a11y.test.tsx +8 -8
  90. package/src/components/layout/__tests__/UnifiedHeader.test.tsx +12 -1
  91. package/src/components/modals/__tests__/KeyboardShortcutsHelpModal.test.tsx +0 -1
  92. package/src/components/modals/__tests__/PermissionDeniedModal.test.tsx +3 -4
  93. package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +1 -2
  94. package/src/components/modals/__tests__/SearchModal.basic.test.tsx +1 -1
  95. package/src/components/modals/__tests__/SearchModal.keyboard.test.tsx +0 -5
  96. package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +1 -2
  97. package/src/components/modals/__tests__/SearchModal.visual.test.tsx +2 -2
  98. package/src/components/modals/__tests__/SessionExpiredModal.test.tsx +0 -1
  99. package/src/components/navigation/NavigationMenu.tsx +1 -1
  100. package/src/components/navigation/__tests__/Footer.a11y.test.tsx +4 -0
  101. package/src/components/navigation/__tests__/Footer.test.tsx +3 -6
  102. package/src/components/navigation/__tests__/NavigationMenu.a11y.test.tsx +1 -1
  103. package/src/components/navigation/__tests__/NavigationMenu.test.tsx +7 -9
  104. package/src/components/navigation/__tests__/ObservableLink.test.tsx +0 -1
  105. package/src/components/navigation/__tests__/SimpleNavigation.test.tsx +1 -2
  106. package/src/components/navigation/__tests__/SortableResourceTab.test.tsx +0 -1
  107. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +6 -4
  108. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +10 -19
  109. package/src/components/resource/AnnotateView.tsx +35 -37
  110. package/src/components/resource/BrowseView.tsx +31 -31
  111. package/src/components/resource/__tests__/AnnotationHistory.test.tsx +0 -1
  112. package/src/components/resource/__tests__/BrowseView.test.tsx +12 -14
  113. package/src/components/resource/__tests__/HistoryEvent.test.tsx +0 -5
  114. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +4 -6
  115. package/src/components/resource/__tests__/event-formatting.test.ts +1 -1
  116. package/src/components/resource/panels/CollaborationPanel.tsx +1 -1
  117. package/src/components/resource/panels/JsonLdPanel.tsx +33 -16
  118. package/src/components/resource/panels/ReferencesPanel.tsx +1 -1
  119. package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +4 -5
  120. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +8 -7
  121. package/src/components/resource/panels/__tests__/AssistSection.test.tsx +14 -10
  122. package/src/components/resource/panels/__tests__/CollaborationPanel.test.tsx +0 -1
  123. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +31 -18
  124. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +7 -6
  125. package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +5 -6
  126. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +19 -13
  127. package/src/components/resource/panels/__tests__/JsonLdPanel.test.tsx +95 -426
  128. package/src/components/resource/panels/__tests__/PanelHeader.test.tsx +0 -1
  129. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +5 -5
  130. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +40 -7
  131. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +4 -4
  132. package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +30 -32
  133. package/src/components/resource/panels/__tests__/TagEntry.test.tsx +6 -6
  134. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +7 -6
  135. package/src/components/settings/__tests__/SettingsPanel.test.tsx +0 -1
  136. package/src/components/viewers/__tests__/ImageViewer.test.tsx +0 -1
  137. package/src/features/admin-exchange/__tests__/AdminExchangePage.test.tsx +7 -10
  138. package/src/features/admin-exchange/__tests__/ImportProgress.test.tsx +38 -27
  139. package/src/features/admin-exchange/components/ImportProgress.tsx +28 -34
  140. package/src/features/auth/__tests__/SignInForm.a11y.test.tsx +2 -0
  141. package/src/features/auth/__tests__/SignUpForm.a11y.test.tsx +11 -12
  142. package/src/features/auth/__tests__/SignUpForm.test.tsx +3 -3
  143. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -0
  144. package/src/features/moderation-linked-data/__tests__/LinkedDataPage.test.tsx +11 -9
  145. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +2 -1
  146. package/src/features/resource-compose/components/ResourceComposePage.tsx +36 -9
  147. package/src/features/resource-compose/state/compose-page-state-unit.ts +5 -8
  148. package/src/features/resource-discovery/__tests__/ResourceCard.test.tsx +0 -1
  149. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +33 -35
  150. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +12 -11
  151. package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +204 -11
  152. package/src/features/resource-discovery/state/discover-state-unit.ts +70 -11
  153. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +2 -2
  154. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +10 -7
  155. package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +37 -1
  156. package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +14 -7
  157. package/src/integrations/__tests__/css-modules-helper.test.tsx +2 -3
  158. package/src/integrations/__tests__/styled-components-theme.test.ts +1 -3
  159. package/src/styles/features/exchange.css +0 -30
  160. package/src/styles/index.css +1 -0
  161. package/translations/ar.json +1 -3
  162. package/translations/bn.json +1 -3
  163. package/translations/cs.json +1 -3
  164. package/translations/da.json +4 -6
  165. package/translations/de.json +1 -3
  166. package/translations/el.json +1 -3
  167. package/translations/es.json +9 -11
  168. package/translations/fa.json +1 -3
  169. package/translations/fi.json +1 -3
  170. package/translations/fr.json +1 -3
  171. package/translations/he.json +1 -3
  172. package/translations/hi.json +1 -3
  173. package/translations/id.json +1 -3
  174. package/translations/it.json +1 -3
  175. package/translations/ja.json +1 -3
  176. package/translations/ko.json +1 -3
  177. package/translations/ms.json +1 -3
  178. package/translations/nl.json +2 -7
  179. package/translations/no.json +18 -20
  180. package/translations/pl.json +1 -3
  181. package/translations/pt.json +116 -118
  182. package/translations/ro.json +1 -3
  183. package/translations/sv.json +41 -43
  184. package/translations/th.json +1 -3
  185. package/translations/tr.json +1 -3
  186. package/translations/uk.json +1 -3
  187. package/translations/vi.json +1 -3
  188. package/translations/zh.json +1 -3
  189. package/dist/PdfAnnotationCanvas.client-CN3C3S55.js.map +0 -1
  190. package/dist/ar-U2EXWUMQ.js.map +0 -1
  191. package/dist/bn-DRJGV772.js.map +0 -1
  192. package/dist/cs-PTWDM23V.js.map +0 -1
  193. package/dist/da-KSNIKYSS.js.map +0 -1
  194. package/dist/de-F2XBEWFY.js.map +0 -1
  195. package/dist/el-DLD2GWAP.js.map +0 -1
  196. package/dist/es-WLPYWGB5.js.map +0 -1
  197. package/dist/fa-BAXHSDZG.js.map +0 -1
  198. package/dist/fi-FCHSYVOT.js.map +0 -1
  199. package/dist/fr-3UERBSL6.js.map +0 -1
  200. package/dist/he-F6F3FV2K.js.map +0 -1
  201. package/dist/hi-4BK6IK7Q.js.map +0 -1
  202. package/dist/id-7ECCWP3J.js.map +0 -1
  203. package/dist/it-234Z6XK6.js.map +0 -1
  204. package/dist/ja-PJWQI4OQ.js.map +0 -1
  205. package/dist/ko-APUEW2RS.js.map +0 -1
  206. package/dist/ms-PJBZWZWD.js.map +0 -1
  207. package/dist/nl-L4C3ZBCU.js.map +0 -1
  208. package/dist/no-QE5N5KNG.js.map +0 -1
  209. package/dist/pl-5Q2D23PD.js.map +0 -1
  210. package/dist/pt-AIGUOIOC.js.map +0 -1
  211. package/dist/ro-T56CSHTY.js.map +0 -1
  212. package/dist/sv-L4TJQ2UH.js.map +0 -1
  213. package/dist/th-6O7Y6O2Q.js.map +0 -1
  214. package/dist/tr-D4CQCSNO.js.map +0 -1
  215. package/dist/uk-2HMQG6ND.js.map +0 -1
  216. package/dist/vi-XVJ4RUEJ.js.map +0 -1
  217. package/dist/zh-K2KDPGHK.js.map +0 -1
  218. /package/dist/{chunk-3Q3TUKWP.js.map → chunk-Y2EEAOMZ.js.map} +0 -0
@@ -63,7 +63,7 @@ describe('SkipLinks - Accessibility', () => {
63
63
 
64
64
  it('should become visible on focus', async () => {
65
65
  const user = userEvent.setup();
66
- const { container } = render(<SkipLinks />);
66
+ render(<SkipLinks />);
67
67
 
68
68
  const firstLink = screen.getAllByRole('link')[0];
69
69
 
@@ -76,12 +76,12 @@ describe('SkipLinks - Accessibility', () => {
76
76
 
77
77
  it('should hide when focus leaves', async () => {
78
78
  const user = userEvent.setup();
79
- const { container } = render(
80
- <div>
81
- <SkipLinks />
82
- <button>Next focusable element</button>
83
- </div>
84
- );
79
+ render(
80
+ <div>
81
+ <SkipLinks />
82
+ <button>Next focusable element</button>
83
+ </div>
84
+ );
85
85
 
86
86
  // Tab to first skip link
87
87
  await user.tab();
@@ -239,7 +239,7 @@ describe('SkipLinks - Accessibility', () => {
239
239
 
240
240
  it('should maintain focus management with multiple links', async () => {
241
241
  const user = userEvent.setup();
242
- const { container } = render(<SkipLinks />);
242
+ render(<SkipLinks />);
243
243
 
244
244
  // Tab to first link
245
245
  await user.tab();
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import React from 'react';
3
2
  import { render, screen, fireEvent } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { UnifiedHeader } from '../UnifiedHeader';
@@ -9,6 +8,7 @@ vi.mock('@/hooks/useUI', () => ({
9
8
  useDropdown: vi.fn(() => ({
10
9
  isOpen: false,
11
10
  toggle: vi.fn(),
11
+ open: vi.fn(),
12
12
  close: vi.fn(),
13
13
  dropdownRef: { current: null },
14
14
  })),
@@ -37,6 +37,7 @@ describe('UnifiedHeader Component', () => {
37
37
  vi.mocked(useDropdown).mockReturnValue({
38
38
  isOpen: false,
39
39
  toggle: vi.fn(),
40
+ open: vi.fn(),
40
41
  close: vi.fn(),
41
42
  dropdownRef: { current: null },
42
43
  });
@@ -216,6 +217,7 @@ describe('UnifiedHeader Component', () => {
216
217
  vi.mocked(useDropdown).mockReturnValue({
217
218
  isOpen: false,
218
219
  toggle: mockToggle,
220
+ open: vi.fn(),
219
221
  close: vi.fn(),
220
222
  dropdownRef: { current: null },
221
223
  });
@@ -239,6 +241,7 @@ describe('UnifiedHeader Component', () => {
239
241
  vi.mocked(useDropdown).mockReturnValue({
240
242
  isOpen: true,
241
243
  toggle: vi.fn(),
244
+ open: vi.fn(),
242
245
  close: vi.fn(),
243
246
  dropdownRef: { current: null },
244
247
  });
@@ -261,6 +264,7 @@ describe('UnifiedHeader Component', () => {
261
264
  vi.mocked(useDropdown).mockReturnValue({
262
265
  isOpen: true,
263
266
  toggle: vi.fn(),
267
+ open: vi.fn(),
264
268
  close: vi.fn(),
265
269
  dropdownRef: { current: null },
266
270
  });
@@ -282,6 +286,7 @@ describe('UnifiedHeader Component', () => {
282
286
  vi.mocked(useDropdown).mockReturnValue({
283
287
  isOpen: false,
284
288
  toggle: vi.fn(),
289
+ open: vi.fn(),
285
290
  close: vi.fn(),
286
291
  dropdownRef: { current: null },
287
292
  });
@@ -304,6 +309,7 @@ describe('UnifiedHeader Component', () => {
304
309
  vi.mocked(useDropdown).mockReturnValue({
305
310
  isOpen: true,
306
311
  toggle: vi.fn(),
312
+ open: vi.fn(),
307
313
  close: mockClose,
308
314
  dropdownRef: { current: null },
309
315
  });
@@ -331,6 +337,7 @@ describe('UnifiedHeader Component', () => {
331
337
  vi.mocked(useDropdown).mockReturnValue({
332
338
  isOpen: false,
333
339
  toggle: vi.fn(),
340
+ open: vi.fn(),
334
341
  close: vi.fn(),
335
342
  dropdownRef: { current: null },
336
343
  });
@@ -366,6 +373,7 @@ describe('UnifiedHeader Component', () => {
366
373
  vi.mocked(useDropdown).mockReturnValue({
367
374
  isOpen: true,
368
375
  toggle: vi.fn(),
376
+ open: vi.fn(),
369
377
  close: vi.fn(),
370
378
  dropdownRef: { current: null },
371
379
  });
@@ -389,6 +397,7 @@ describe('UnifiedHeader Component', () => {
389
397
  vi.mocked(useDropdown).mockReturnValue({
390
398
  isOpen: true,
391
399
  toggle: vi.fn(),
400
+ open: vi.fn(),
392
401
  close: vi.fn(),
393
402
  dropdownRef: { current: null },
394
403
  });
@@ -450,6 +459,7 @@ describe('UnifiedHeader Component', () => {
450
459
  vi.mocked(useDropdown).mockReturnValue({
451
460
  isOpen: true,
452
461
  toggle: vi.fn(),
462
+ open: vi.fn(),
453
463
  close: vi.fn(),
454
464
  dropdownRef: { current: null },
455
465
  });
@@ -471,6 +481,7 @@ describe('UnifiedHeader Component', () => {
471
481
  vi.mocked(useDropdown).mockReturnValue({
472
482
  isOpen: true,
473
483
  toggle: vi.fn(),
484
+ open: vi.fn(),
474
485
  close: vi.fn(),
475
486
  dropdownRef: { current: null },
476
487
  });
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import React from 'react';
3
2
  import { screen, fireEvent } from '@testing-library/react';
4
3
  import { renderWithProviders } from '../../../test-utils';
5
4
  import '@testing-library/jest-dom';
@@ -6,8 +6,7 @@
6
6
  * `acknowledgePermissionDenied()` and navigate the window or history.
7
7
  */
8
8
 
9
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
- import React from 'react';
9
+ import { describe, it, expect, beforeEach, afterEach, vi, type Mock } from 'vitest';
11
10
  import { screen, fireEvent } from '@testing-library/react';
12
11
  import '@testing-library/jest-dom';
13
12
  import {
@@ -27,7 +26,7 @@ vi.mock('@headlessui/react', () => ({
27
26
  const originalLocation = window.location;
28
27
  const originalHistoryBack = window.history.back;
29
28
  let mockLocation: { href: string; pathname: string };
30
- let mockHistoryBack: ReturnType<typeof vi.fn>;
29
+ let mockHistoryBack: Mock<() => void>;
31
30
 
32
31
  beforeEach(() => {
33
32
  mockLocation = { href: '', pathname: '/admin/users' };
@@ -36,7 +35,7 @@ beforeEach(() => {
36
35
  writable: true,
37
36
  configurable: true,
38
37
  });
39
- mockHistoryBack = vi.fn();
38
+ mockHistoryBack = vi.fn<() => void>();
40
39
  window.history.back = mockHistoryBack;
41
40
  });
42
41
 
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, beforeEach, vi } from 'vitest';
2
- import React from 'react';
3
2
  import { screen, fireEvent, waitFor } from '@testing-library/react';
4
3
  import { BehaviorSubject } from 'rxjs';
5
4
  import { renderWithProviders } from '../../../test-utils';
@@ -15,7 +14,7 @@ vi.mock('@headlessui/react', () => ({
15
14
  TransitionChild: ({ children }: any) => <>{children}</>,
16
15
  }));
17
16
 
18
- // Mock the api-client Observable surface.
17
+ // Mock the http-transport Observable surface.
19
18
  // The session-based useSemiont path: useObservable(useSemiont().activeSession$)?.client
20
19
  // We mock useSemiont to return a stable browser whose activeSession$ emits a
21
20
  // session-shaped object that carries the mock client.
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { describe, it, expect, vi, beforeEach } from 'vitest';
6
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
6
+ import { render, screen, fireEvent } from '@testing-library/react';
7
7
  import userEvent from '@testing-library/user-event';
8
8
  import { SearchModal } from '../SearchModal';
9
9
 
@@ -52,11 +52,6 @@ describe.skip('SearchModal Component - Keyboard Navigation', () => {
52
52
  });
53
53
 
54
54
  it('should handle Arrow Down key to navigate results', async () => {
55
- const mockResults = [
56
- { type: 'resource' as const, id: '1', name: 'Resource 1', content: 'Content 1' },
57
- { type: 'resource' as const, id: '2', name: 'Resource 2', content: 'Content 2' },
58
- { type: 'entity' as const, id: '3', name: 'Entity 1', entityType: 'Person' }
59
- ];
60
55
 
61
56
  // TODO: Mock search results when API is integrated
62
57
  render(<SearchModal {...defaultProps} />);
@@ -12,7 +12,6 @@
12
12
  */
13
13
 
14
14
  import { describe, it, expect, beforeEach, vi } from 'vitest';
15
- import React from 'react';
16
15
  import { screen, fireEvent, waitFor, act } from '@testing-library/react';
17
16
  import { BehaviorSubject } from 'rxjs';
18
17
  import { renderWithProviders } from '../../../test-utils';
@@ -32,7 +31,7 @@ vi.mock('@headlessui/react', () => ({
32
31
  TransitionChild: ({ children }: any) => <>{children}</>,
33
32
  }));
34
33
 
35
- // Mock the api-client Observable surface
34
+ // Mock the http-transport Observable surface
36
35
  const browseResourcesSubject = new BehaviorSubject<any[] | undefined>(undefined);
37
36
  const browseResourcesMock = vi.fn(() => browseResourcesSubject.asObservable());
38
37
 
@@ -3,7 +3,7 @@
3
3
  */
4
4
 
5
5
  import { describe, it, expect, vi, beforeEach } from 'vitest';
6
- import { render, screen, fireEvent, waitFor } from '@testing-library/react';
6
+ import { render, screen, fireEvent } from '@testing-library/react';
7
7
  import { SearchModal } from '../SearchModal';
8
8
 
9
9
  // Mock the hooks
@@ -102,7 +102,7 @@ describe.skip('SearchModal Component - Visual States', () => {
102
102
  rerender(<SearchModal {...defaultProps} isOpen={false} />);
103
103
  rerender(<SearchModal {...defaultProps} isOpen={true} />);
104
104
 
105
- const input = screen.getByPlaceholderText('Search resources, entities...');
105
+ const input = screen.getByPlaceholderText<HTMLInputElement>('Search resources, entities...');
106
106
  expect(input).toBeInTheDocument();
107
107
  expect(input.value).toBe('');
108
108
  });
@@ -7,7 +7,6 @@
7
7
  */
8
8
 
9
9
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
10
- import React from 'react';
11
10
  import { screen, fireEvent } from '@testing-library/react';
12
11
  import '@testing-library/jest-dom';
13
12
  import {
@@ -8,7 +8,7 @@ type TranslateFn = (key: string, params?: Record<string, any>) => string;
8
8
 
9
9
  interface NavigationMenuProps {
10
10
  Link: React.ComponentType<LinkComponentProps>;
11
- routes: RouteBuilder;
11
+ routes: Partial<RouteBuilder>;
12
12
  t: TranslateFn;
13
13
  isAdmin?: boolean;
14
14
  isModerator?: boolean;
@@ -21,6 +21,10 @@ describe('Footer - Accessibility', () => {
21
21
  ));
22
22
 
23
23
  const mockRoutes = {
24
+ resourceDetail: vi.fn((id: string) => `/resource/${id}`),
25
+ userProfile: vi.fn((id: string) => `/user/${id}`),
26
+ search: vi.fn((query: string) => `/search?q=${query}`),
27
+ home: vi.fn(() => '/'),
24
28
  about: vi.fn(() => '/about'),
25
29
  privacy: vi.fn(() => '/privacy'),
26
30
  terms: vi.fn(() => '/terms'),
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import React from 'react';
3
2
  import { render, screen, fireEvent } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { Footer } from '../Footer';
@@ -124,7 +123,7 @@ describe('Footer Component', () => {
124
123
  });
125
124
 
126
125
  it('should render Cookie Preferences button when provided', () => {
127
- const MockCookiePrefs = ({ isOpen, onClose }: any) => null;
126
+ const MockCookiePrefs = ({ }: any) => null;
128
127
 
129
128
  render(
130
129
  <Footer
@@ -139,7 +138,7 @@ describe('Footer Component', () => {
139
138
  });
140
139
 
141
140
  it('should open Cookie Preferences modal when button clicked', () => {
142
- const MockCookiePrefs = ({ isOpen, onClose }: any) => (
141
+ const MockCookiePrefs = ({ isOpen }: any) => (
143
142
  isOpen ? <div data-testid="cookie-modal">Cookie Preferences</div> : null
144
143
  );
145
144
 
@@ -161,9 +160,7 @@ describe('Footer Component', () => {
161
160
  });
162
161
 
163
162
  it('should close Cookie Preferences modal when onClose called', () => {
164
- let closeHandler: (() => void) | null = null;
165
163
  const MockCookiePrefs = ({ isOpen, onClose }: any) => {
166
- closeHandler = onClose;
167
164
  return isOpen ? (
168
165
  <div data-testid="cookie-modal">
169
166
  <button onClick={onClose}>Close</button>
@@ -387,7 +384,7 @@ describe('Footer Component', () => {
387
384
 
388
385
  it('should have proper button elements for interactive features', () => {
389
386
  const mockHandler = vi.fn();
390
- const MockCookiePrefs = ({ isOpen, onClose }: any) => null;
387
+ const MockCookiePrefs = ({ }: any) => null;
391
388
 
392
389
  render(
393
390
  <Footer
@@ -56,7 +56,7 @@ describe('NavigationMenu - Accessibility', () => {
56
56
  Link={mockLink}
57
57
  routes={mockRoutes}
58
58
  t={mockTranslate}
59
- activePath="/knowledge"
59
+ currentPath="/knowledge"
60
60
  />
61
61
  );
62
62
 
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import React from 'react';
3
2
  import { render, screen, fireEvent } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { NavigationMenu } from '../NavigationMenu';
@@ -287,14 +286,13 @@ describe('NavigationMenu Component', () => {
287
286
  });
288
287
 
289
288
  it('should not show extra divider after admin link', () => {
290
- const { container } = render(
291
- <NavigationMenu
292
- Link={mockLink}
293
- routes={mockRoutes}
294
- t={mockTranslate}
295
- isAdmin={true}
296
- />
297
- );
289
+ render(
290
+ <NavigationMenu
291
+ Link={mockLink}
292
+ routes={mockRoutes}
293
+ t={mockTranslate}
294
+ isAdmin={true} />
295
+ );
298
296
 
299
297
  const adminLink = screen.getByText('Administer').closest('a');
300
298
  const nextSibling = adminLink?.nextElementSibling;
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import React from 'react';
3
2
  import { screen, fireEvent } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { renderWithProviders } from '../../../test-utils';
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
- import React from 'react';
3
2
  import { screen, fireEvent } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { renderWithProviders } from '../../../test-utils';
@@ -143,7 +142,7 @@ describe('SimpleNavigation', () => {
143
142
  });
144
143
 
145
144
  it('closes dropdown on outside click', () => {
146
- const dropdownContent = (onClose: () => void) => (
145
+ const dropdownContent = () => (
147
146
  <div data-testid="dropdown-content">Dropdown</div>
148
147
  );
149
148
 
@@ -1,5 +1,4 @@
1
1
  import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import React from 'react';
3
2
  import { screen, fireEvent } from '@testing-library/react';
4
3
  import '@testing-library/jest-dom';
5
4
  import { renderWithProviders } from '../../../test-utils';
@@ -2,15 +2,17 @@
2
2
 
3
3
  import React, { useRef, useState, useCallback, useEffect, useMemo } from 'react';
4
4
  import type { Annotation } from '@semiont/core';
5
- import { getTargetSelector } from '@semiont/core';
5
+ import {
6
+ getTargetSelector,
7
+ createFragmentSelector,
8
+ parseFragmentSelector,
9
+ getPageFromFragment,
10
+ } from '@semiont/core';
6
11
  import { createHoverHandlers, type SemiontSession } from '@semiont/sdk';
7
12
  import type { SelectionMotivation } from '../annotation/AnnotateToolbar';
8
13
  import {
9
14
  canvasToPdfCoordinates,
10
15
  pdfToCanvasCoordinates,
11
- createFragmentSelector,
12
- parseFragmentSelector,
13
- getPageFromFragment,
14
16
  type CanvasRectangle
15
17
  } from '../../lib/pdf-coordinates';
16
18
  import {
@@ -11,8 +11,7 @@ import { describe, test, expect, vi, beforeEach } from 'vitest';
11
11
  import { render, screen, waitFor, fireEvent } from '@testing-library/react';
12
12
  import userEvent from '@testing-library/user-event';
13
13
  import { PdfAnnotationCanvas } from '../PdfAnnotationCanvas';
14
- import { resourceId } from '@semiont/core';
15
- import type { components } from '@semiont/core';
14
+ import { resourceId, annotationId } from '@semiont/core';
16
15
 
17
16
  import type { Annotation } from '@semiont/core';
18
17
 
@@ -41,6 +40,7 @@ vi.mock('../../../lib/browser-pdfjs', () => ({
41
40
 
42
41
  describe('PdfAnnotationCanvas', () => {
43
42
  const mockResourceId = resourceId('123');
43
+ const mockPdfUrl = 'https://example.com/resources/123.pdf';
44
44
 
45
45
  beforeEach(() => {
46
46
  vi.clearAllMocks();
@@ -57,7 +57,7 @@ describe('PdfAnnotationCanvas', () => {
57
57
  test('renders loading state initially', () => {
58
58
  render(
59
59
  <PdfAnnotationCanvas
60
- resourceUri={mockResourceId}
60
+ pdfUrl={mockPdfUrl}
61
61
  drawingMode={null}
62
62
  />
63
63
  );
@@ -68,7 +68,7 @@ describe('PdfAnnotationCanvas', () => {
68
68
  test('renders page navigation controls after loading', async () => {
69
69
  render(
70
70
  <PdfAnnotationCanvas
71
- resourceUri={mockResourceId}
71
+ pdfUrl={mockPdfUrl}
72
72
  drawingMode={null}
73
73
  />
74
74
  );
@@ -84,7 +84,7 @@ describe('PdfAnnotationCanvas', () => {
84
84
  test('previous button is disabled on first page', async () => {
85
85
  render(
86
86
  <PdfAnnotationCanvas
87
- resourceUri={mockResourceId}
87
+ pdfUrl={mockPdfUrl}
88
88
  drawingMode={null}
89
89
  />
90
90
  );
@@ -100,7 +100,7 @@ describe('PdfAnnotationCanvas', () => {
100
100
  test('next button is disabled on last page', async () => {
101
101
  render(
102
102
  <PdfAnnotationCanvas
103
- resourceUri={mockResourceId}
103
+ pdfUrl={mockPdfUrl}
104
104
  drawingMode={null}
105
105
  />
106
106
  );
@@ -129,7 +129,7 @@ describe('PdfAnnotationCanvas', () => {
129
129
  {
130
130
  '@context': 'http://www.w3.org/ns/anno.jsonld',
131
131
  type: 'Annotation',
132
- id: 'ann-1',
132
+ id: annotationId('ann-1'),
133
133
  target: {
134
134
  source: mockResourceId,
135
135
  selector: {
@@ -145,7 +145,7 @@ describe('PdfAnnotationCanvas', () => {
145
145
 
146
146
  render(
147
147
  <PdfAnnotationCanvas
148
- resourceUri={mockResourceId}
148
+ pdfUrl={mockPdfUrl}
149
149
  existingAnnotations={mockAnnotations}
150
150
  drawingMode={null}
151
151
  />
@@ -177,21 +177,12 @@ describe('PdfAnnotationCanvas', () => {
177
177
  });
178
178
  });
179
179
 
180
- test('emits annotate:requested via eventBus when drawing with sufficient drag', async () => {
181
- const mockSubject = { next: vi.fn(), subscribe: vi.fn() };
182
- const mockEventBus = {
183
- emit: vi.fn(),
184
- on: vi.fn(),
185
- off: vi.fn(),
186
- get: vi.fn().mockReturnValue(mockSubject),
187
- };
188
-
180
+ test('accepts a drawing gesture without throwing when drawing mode is active', async () => {
189
181
  render(
190
182
  <PdfAnnotationCanvas
191
- resourceUri={mockResourceId}
183
+ pdfUrl={mockPdfUrl}
192
184
  drawingMode="rectangle"
193
185
  selectedMotivation="highlighting"
194
- eventBus={mockEventBus as any}
195
186
  />
196
187
  );
197
188
 
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useRef, useEffect, useCallback, lazy, Suspense } from 'react';
4
- import { getMimeCategory, isPdfMimeType } from '@semiont/core';
4
+ import { capabilitiesOf } from '@semiont/core';
5
5
  import { ANNOTATORS } from '../../lib/annotation-registry';
6
6
  import { segmentTextWithAnnotations } from '../../lib/text-segmentation';
7
7
  import { buildTextSelectors, fallbackTextPosition } from '../../lib/text-selection-handler';
@@ -71,7 +71,7 @@ export function AnnotateView({
71
71
  const containerRef = useRef<HTMLDivElement>(null);
72
72
  const session = useObservable(useSemiont().activeSession$);
73
73
 
74
- const category = getMimeCategory(mimeType);
74
+ const render = capabilitiesOf(mimeType)?.render ?? 'none';
75
75
 
76
76
  const { highlights, references, assessments, comments, tags } = annotations;
77
77
 
@@ -192,8 +192,8 @@ export function AnnotateView({
192
192
  };
193
193
  }, [selectedMotivation, content]);
194
194
 
195
- // Route to appropriate viewer based on MIME type category
196
- switch (category) {
195
+ // Route to the annotation viewer for this media type's render mode.
196
+ switch (render) {
197
197
  case 'text':
198
198
  return (
199
199
  <div className="semiont-annotate-view" data-mime-type="text" ref={containerRef}>
@@ -225,40 +225,38 @@ export function AnnotateView({
225
225
  </div>
226
226
  );
227
227
 
228
- case 'image':
229
- // MIME-specific viewer selection within spatial annotation category
230
- if (isPdfMimeType(mimeType)) {
231
- // Phase 2: PDF annotation support
232
- return (
233
- <div className="semiont-annotate-view" data-mime-type="pdf" ref={containerRef}>
234
- <AnnotateToolbar
235
- selectedMotivation={selectedMotivation}
236
- selectedClick={selectedClick}
237
- showShapeGroup={true}
238
- selectedShape={selectedShape}
239
- mediaType={mimeType}
240
- annotateMode={annotateMode}
241
- annotators={ANNOTATORS}
242
- />
243
- <div className="semiont-annotate-view__content">
244
- {content && (
245
- <Suspense fallback={<div className="semiont-annotate-view__loading">Loading PDF viewer...</div>}>
246
- <PdfAnnotationCanvas
247
- pdfUrl={content}
248
- existingAnnotations={allAnnotations}
249
- drawingMode={selectedMotivation ? selectedShape : null}
250
- selectedMotivation={selectedMotivation}
251
- session={session}
252
- hoveredAnnotationId={hoveredAnnotationId || null}
253
- hoverDelayMs={hoverDelayMs}
254
- />
255
- </Suspense>
256
- )}
257
- </div>
228
+ case 'pdf':
229
+ // PDF annotation support (spatial, FragmentSelector)
230
+ return (
231
+ <div className="semiont-annotate-view" data-mime-type="pdf" ref={containerRef}>
232
+ <AnnotateToolbar
233
+ selectedMotivation={selectedMotivation}
234
+ selectedClick={selectedClick}
235
+ showShapeGroup={true}
236
+ selectedShape={selectedShape}
237
+ mediaType={mimeType}
238
+ annotateMode={annotateMode}
239
+ annotators={ANNOTATORS}
240
+ />
241
+ <div className="semiont-annotate-view__content">
242
+ {content && (
243
+ <Suspense fallback={<div className="semiont-annotate-view__loading">Loading PDF viewer...</div>}>
244
+ <PdfAnnotationCanvas
245
+ pdfUrl={content}
246
+ existingAnnotations={allAnnotations}
247
+ drawingMode={selectedMotivation ? selectedShape : null}
248
+ selectedMotivation={selectedMotivation}
249
+ session={session}
250
+ hoveredAnnotationId={hoveredAnnotationId || null}
251
+ hoverDelayMs={hoverDelayMs}
252
+ />
253
+ </Suspense>
254
+ )}
258
255
  </div>
259
- );
260
- }
256
+ </div>
257
+ );
261
258
 
259
+ case 'image':
262
260
  // PNG, JPEG, etc. - full annotation support
263
261
  return (
264
262
  <div className="semiont-annotate-view" data-mime-type="image" ref={containerRef}>
@@ -287,7 +285,7 @@ export function AnnotateView({
287
285
  </div>
288
286
  );
289
287
 
290
- case 'unsupported':
288
+ case 'none':
291
289
  default:
292
290
  return (
293
291
  <div ref={containerRef} className="semiont-annotate-view semiont-annotate-view--unsupported" data-mime-type="unsupported">