@semiont/react-ui 0.2.33 → 0.2.34-build.89

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 (82) hide show
  1. package/dist/EventBusContext-BmzEcGHZ.d.mts +177 -0
  2. package/dist/{PdfAnnotationCanvas.client-FGV33CWN.mjs → PdfAnnotationCanvas.client-VLNA5O5M.mjs} +7 -7
  3. package/dist/PdfAnnotationCanvas.client-VLNA5O5M.mjs.map +1 -0
  4. package/dist/{chunk-YPYLOBA2.mjs → chunk-C63BARI7.mjs} +3 -2
  5. package/dist/chunk-C63BARI7.mjs.map +1 -0
  6. package/dist/{chunk-FC6SGLLT.mjs → chunk-M7SZRRIE.mjs} +24 -16
  7. package/dist/chunk-M7SZRRIE.mjs.map +1 -0
  8. package/dist/chunk-ULIET3MW.mjs +31 -0
  9. package/dist/chunk-ULIET3MW.mjs.map +1 -0
  10. package/dist/index.d.mts +33 -60
  11. package/dist/index.mjs +171 -363
  12. package/dist/index.mjs.map +1 -1
  13. package/dist/test-utils.d.mts +3 -5
  14. package/dist/test-utils.mjs +2 -2
  15. package/dist/test-utils.mjs.map +1 -1
  16. package/package.json +2 -3
  17. package/src/components/CodeMirrorRenderer.tsx +4 -4
  18. package/src/components/DetectionProgressWidget.tsx +3 -3
  19. package/src/components/LiveRegion.tsx +1 -1
  20. package/src/components/Toolbar.tsx +1 -1
  21. package/src/components/annotation/AnnotateToolbar.tsx +5 -5
  22. package/src/components/annotation/__tests__/AnnotateToolbar.test.tsx +4 -4
  23. package/src/components/annotation-popups/JsonLdView.tsx +1 -1
  24. package/src/components/image-annotation/AnnotationOverlay.tsx +9 -9
  25. package/src/components/image-annotation/SvgDrawingCanvas.tsx +5 -5
  26. package/src/components/navigation/CollapsibleResourceNavigation.tsx +4 -4
  27. package/src/components/navigation/ObservableLink.tsx +1 -1
  28. package/src/components/navigation/SimpleNavigation.tsx +1 -1
  29. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +6 -6
  30. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +2 -2
  31. package/src/components/resource/AnnotateView.tsx +5 -4
  32. package/src/components/resource/AnnotationHistory.tsx +1 -1
  33. package/src/components/resource/BrowseView.tsx +5 -4
  34. package/src/components/resource/ResourceViewer.tsx +5 -4
  35. package/src/components/resource/__tests__/BrowseView.test.tsx +11 -22
  36. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +1 -1
  37. package/src/components/resource/event-formatting.ts +1 -1
  38. package/src/components/resource/panels/AssessmentEntry.tsx +2 -2
  39. package/src/components/resource/panels/AssessmentPanel.tsx +4 -4
  40. package/src/components/resource/panels/CommentEntry.tsx +2 -2
  41. package/src/components/resource/panels/CommentsPanel.tsx +4 -4
  42. package/src/components/resource/panels/DetectSection.tsx +3 -3
  43. package/src/components/resource/panels/HighlightEntry.tsx +2 -2
  44. package/src/components/resource/panels/HighlightPanel.tsx +2 -2
  45. package/src/components/resource/panels/JsonLdPanel.tsx +1 -1
  46. package/src/components/resource/panels/ReferenceEntry.tsx +6 -6
  47. package/src/components/resource/panels/ReferencesPanel.tsx +5 -5
  48. package/src/components/resource/panels/ResourceInfoPanel.tsx +3 -3
  49. package/src/components/resource/panels/StatisticsPanel.tsx +1 -1
  50. package/src/components/resource/panels/TagEntry.tsx +2 -2
  51. package/src/components/resource/panels/TaggingPanel.tsx +5 -5
  52. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +1 -1
  53. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +5 -5
  54. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +10 -10
  55. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +5 -5
  56. package/src/components/resource/panels/__tests__/DetectSection.test.tsx +9 -9
  57. package/src/components/resource/panels/__tests__/HighlightPanel.detectionProgress.test.tsx +1 -1
  58. package/src/components/resource/panels/__tests__/JsonLdPanel.test.tsx +1 -1
  59. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +4 -4
  60. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +4 -4
  61. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +5 -5
  62. package/src/components/settings/SettingsPanel.tsx +5 -5
  63. package/src/components/viewers/ImageViewer.tsx +1 -1
  64. package/src/features/resource-compose/components/ResourceComposePage.tsx +1 -1
  65. package/src/features/resource-discovery/components/ResourceCard.tsx +1 -1
  66. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +1 -1
  67. package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +7 -5
  68. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +5 -4
  69. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +5 -5
  70. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +29 -43
  71. package/src/features/resource-viewer/__tests__/DetectionProgressDismissal.test.tsx +20 -39
  72. package/src/features/resource-viewer/__tests__/GenerationFlowIntegration.test.tsx +38 -46
  73. package/src/features/resource-viewer/__tests__/ResolutionFlowIntegration.test.tsx +36 -43
  74. package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +8 -8
  75. package/src/features/resource-viewer/__tests__/detection-progress-flow.test.tsx +14 -21
  76. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +8 -7
  77. package/dist/EventBusContext-CJjL_cCf.d.mts +0 -462
  78. package/dist/PdfAnnotationCanvas.client-FGV33CWN.mjs.map +0 -1
  79. package/dist/chunk-FC6SGLLT.mjs.map +0 -1
  80. package/dist/chunk-XS27QKGP.mjs +0 -55
  81. package/dist/chunk-XS27QKGP.mjs.map +0 -1
  82. package/dist/chunk-YPYLOBA2.mjs.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  import { useState, useEffect, useRef, forwardRef, useImperativeHandle } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
- import type { components } from '@semiont/api-client';
5
+ import type { components } from '@semiont/core';
6
6
  import { getAnnotationExactText, getCommentText } from '@semiont/api-client';
7
7
  import { useEventBus } from '../../../contexts/EventBusContext';
8
8
  import { useHoverEmitter } from '../../../hooks/useAttentionFlow';
@@ -88,7 +88,7 @@ export const CommentEntry = forwardRef<HTMLDivElement, CommentEntryProps>(
88
88
  data-type="comment"
89
89
  data-focused={isFocused ? 'true' : 'false'}
90
90
  onClick={() => {
91
- eventBus.emit('annotation:click', { annotationId: comment.id, motivation: comment.motivation });
91
+ eventBus.get('annotation:click').next({ annotationId: comment.id, motivation: comment.motivation });
92
92
  }}
93
93
  {...hoverProps}
94
94
  >
@@ -4,7 +4,7 @@ import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
5
  import { useEventBus } from '../../../contexts/EventBusContext';
6
6
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
7
- import type { components, Selector } from '@semiont/api-client';
7
+ import type { components, Selector } from '@semiont/core';
8
8
  import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
9
  import { CommentEntry } from './CommentEntry';
10
10
  import { DetectSection } from './DetectSection';
@@ -167,7 +167,7 @@ export function CommentsPanel({
167
167
 
168
168
  const handleSaveNewComment = () => {
169
169
  if (newCommentText.trim() && pendingAnnotation) {
170
- eventBus.emit('annotation:create', {
170
+ eventBus.get('annotation:create').next({
171
171
  motivation: 'commenting',
172
172
  selector: pendingAnnotation.selector,
173
173
  body: [{ type: 'TextualBody', value: newCommentText, purpose: 'commenting' }],
@@ -182,7 +182,7 @@ export function CommentsPanel({
182
182
 
183
183
  const handleEscape = (e: KeyboardEvent) => {
184
184
  if (e.key === 'Escape') {
185
- eventBus.emit('annotation:cancel-pending', undefined);
185
+ eventBus.get('annotation:cancel-pending').next(undefined);
186
186
  setNewCommentText('');
187
187
  }
188
188
  };
@@ -224,7 +224,7 @@ export function CommentsPanel({
224
224
  <div className="semiont-annotation-prompt__actions">
225
225
  <button
226
226
  onClick={() => {
227
- eventBus.emit('annotation:cancel-pending', undefined);
227
+ eventBus.get('annotation:cancel-pending').next(undefined);
228
228
  setNewCommentText('');
229
229
  }}
230
230
  className="semiont-button semiont-button--secondary"
@@ -3,7 +3,7 @@
3
3
  import { useState, useEffect, useCallback } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
5
  import { useEventBus } from '../../../contexts/EventBusContext';
6
- import type { Motivation } from '@semiont/api-client';
6
+ import type { Motivation } from '@semiont/core';
7
7
  import './DetectSection.css';
8
8
 
9
9
  interface DetectSectionProps {
@@ -71,7 +71,7 @@ export function DetectSection({
71
71
  'commenting';
72
72
 
73
73
  // Emit detection:start event with options
74
- eventBus.emit('detection:start', {
74
+ eventBus.get('detection:start').next({
75
75
  motivation,
76
76
  options: {
77
77
  instructions: instructions.trim() || undefined,
@@ -86,7 +86,7 @@ export function DetectSection({
86
86
  }, [annotationType, instructions, tone, useDensity, density]); // eventBus is stable singleton - never in deps
87
87
 
88
88
  const handleDismissProgress = useCallback(() => {
89
- eventBus.emit('detection:dismiss-progress', undefined);
89
+ eventBus.get('detection:dismiss-progress').next(undefined);
90
90
  }, []); // eventBus is stable singleton - never in deps
91
91
 
92
92
  return (
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { forwardRef } from 'react';
4
- import type { components } from '@semiont/api-client';
4
+ import type { components } from '@semiont/core';
5
5
  import { getAnnotationExactText } from '@semiont/api-client';
6
6
  import { useEventBus } from '../../../contexts/EventBusContext';
7
7
  import { useHoverEmitter } from '../../../hooks/useAttentionFlow';
@@ -52,7 +52,7 @@ export const HighlightEntry = forwardRef<HTMLDivElement, HighlightEntryProps>(
52
52
  data-type="highlight"
53
53
  data-focused={isFocused ? 'true' : 'false'}
54
54
  onClick={() => {
55
- eventBus.emit('annotation:click', { annotationId: highlight.id, motivation: highlight.motivation });
55
+ eventBus.get('annotation:click').next({ annotationId: highlight.id, motivation: highlight.motivation });
56
56
  }}
57
57
  {...hoverProps}
58
58
  >
@@ -4,7 +4,7 @@ import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
5
  import { useEventBus } from '../../../contexts/EventBusContext';
6
6
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
7
- import type { components, Selector } from '@semiont/api-client';
7
+ import type { components, Selector } from '@semiont/core';
8
8
  import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
9
  import { HighlightEntry } from './HighlightEntry';
10
10
  import { DetectSection } from './DetectSection';
@@ -132,7 +132,7 @@ export function HighlightPanel({
132
132
  // immediately emit annotation:create event
133
133
  useEffect(() => {
134
134
  if (pendingAnnotation && pendingAnnotation.motivation === 'highlighting') {
135
- eventBus.emit('annotation:create', {
135
+ eventBus.get('annotation:create').next({
136
136
  motivation: 'highlighting',
137
137
  selector: pendingAnnotation.selector,
138
138
  body: [],
@@ -8,7 +8,7 @@ import { oneDark } from '@codemirror/theme-one-dark';
8
8
  import { syntaxHighlighting } from '@codemirror/language';
9
9
  import { jsonLightTheme, jsonLightHighlightStyle } from '../../../lib/codemirror-json-theme';
10
10
  import { useLineNumbers } from '../../../hooks/useLineNumbers';
11
- import type { components } from '@semiont/api-client';
11
+ import type { components } from '@semiont/core';
12
12
  import './JsonLdPanel.css';
13
13
 
14
14
  type SemiontResource = components['schemas']['ResourceDescriptor'];
@@ -3,7 +3,7 @@
3
3
  import { forwardRef } from 'react';
4
4
  import type { RouteBuilder } from '../../../contexts/RoutingContext';
5
5
  import { useTranslations } from '../../../contexts/TranslationContext';
6
- import type { components } from '@semiont/api-client';
6
+ import type { components } from '@semiont/core';
7
7
  import { getAnnotationExactText, isBodyResolved, getBodySource, getFragmentSelector, getSvgSelector, getTargetSelector } from '@semiont/api-client';
8
8
  import { getEntityTypes } from '@semiont/ontology';
9
9
  import { getResourceIcon } from '../../../lib/resource-utils';
@@ -73,7 +73,7 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
73
73
  };
74
74
 
75
75
  const handleComposeDocument = () => {
76
- eventBus.emit('reference:create-manual', {
76
+ eventBus.get('reference:create-manual').next({
77
77
  annotationUri: reference.id,
78
78
  title: selectedText,
79
79
  entityTypes,
@@ -86,7 +86,7 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
86
86
  ? reference.target.source
87
87
  : '';
88
88
  if (sourceUri) {
89
- eventBus.emit('annotation:update-body', {
89
+ eventBus.get('annotation:update-body').next({
90
90
  annotationUri: reference.id,
91
91
  resourceId: sourceUri.split('/resources/')[1] || '',
92
92
  operations: [{ op: 'remove' }], // Remove all body items
@@ -100,7 +100,7 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
100
100
  : '';
101
101
 
102
102
  // Emit request to open generation modal
103
- eventBus.emit('generation:modal-open', {
103
+ eventBus.get('generation:modal-open').next({
104
104
  annotationUri: reference.id,
105
105
  resourceUri,
106
106
  defaultTitle: selectedText,
@@ -108,7 +108,7 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
108
108
  };
109
109
 
110
110
  const handleSearch = () => {
111
- eventBus.emit('reference:link', {
111
+ eventBus.get('reference:link').next({
112
112
  annotationUri: reference.id,
113
113
  searchTerm: selectedText,
114
114
  });
@@ -121,7 +121,7 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
121
121
  data-type="reference"
122
122
  data-focused={isFocused ? 'true' : 'false'}
123
123
  onClick={() => {
124
- eventBus.emit('annotation:click', { annotationId: reference.id, motivation: reference.motivation });
124
+ eventBus.get('annotation:click').next({ annotationId: reference.id, motivation: reference.motivation });
125
125
  }}
126
126
  {...hoverProps}
127
127
  >
@@ -7,7 +7,7 @@ import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
7
7
  import type { RouteBuilder, LinkComponentProps } from '../../../contexts/RoutingContext';
8
8
  import { DetectionProgressWidget } from '../../DetectionProgressWidget';
9
9
  import { ReferenceEntry } from './ReferenceEntry';
10
- import type { components, paths, Selector } from '@semiont/api-client';
10
+ import type { components, paths, Selector } from '@semiont/core';
11
11
  import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
12
12
  import { PanelHeader } from './PanelHeader';
13
13
  import './ReferencesPanel.css';
@@ -207,7 +207,7 @@ export function ReferencesPanel({
207
207
  // Clear log when starting new detection
208
208
  const handleDetect = () => {
209
209
  setLastDetectionLog(null);
210
- eventBus.emit('detection:start', {
210
+ eventBus.get('detection:start').next({
211
211
  motivation: 'linking',
212
212
  options: {
213
213
  entityTypes: selectedEntityTypes,
@@ -250,7 +250,7 @@ export function ReferencesPanel({
250
250
  const handleCreateReference = () => {
251
251
  if (pendingAnnotation) {
252
252
  const entityType = pendingEntityTypes.join(',') || undefined;
253
- eventBus.emit('annotation:create', {
253
+ eventBus.get('annotation:create').next({
254
254
  motivation: 'linking',
255
255
  selector: pendingAnnotation.selector,
256
256
  body: entityType ? [{ type: 'TextualBody', value: entityType, purpose: 'tagging' }] : [],
@@ -265,7 +265,7 @@ export function ReferencesPanel({
265
265
 
266
266
  const handleEscape = (e: KeyboardEvent) => {
267
267
  if (e.key === 'Escape') {
268
- eventBus.emit('annotation:cancel-pending', undefined);
268
+ eventBus.get('annotation:cancel-pending').next(undefined);
269
269
  setPendingEntityTypes([]);
270
270
  }
271
271
  };
@@ -317,7 +317,7 @@ export function ReferencesPanel({
317
317
  <div className="semiont-annotation-prompt__actions">
318
318
  <button
319
319
  onClick={() => {
320
- eventBus.emit('annotation:cancel-pending', undefined);
320
+ eventBus.get('annotation:cancel-pending').next(undefined);
321
321
  setPendingEntityTypes([]);
322
322
  }}
323
323
  className="semiont-button semiont-button--secondary"
@@ -97,7 +97,7 @@ export function ResourceInfoPanel({
97
97
  {/* Clone Action */}
98
98
  <div className="semiont-resource-info-panel__action-section">
99
99
  <button
100
- onClick={() => eventBus.emit('resource:clone', undefined)}
100
+ onClick={() => eventBus.get('resource:clone').next(undefined)}
101
101
  className="semiont-resource-button semiont-resource-button--secondary"
102
102
  >
103
103
  🔗 {t('clone')}
@@ -112,7 +112,7 @@ export function ResourceInfoPanel({
112
112
  {isArchived ? (
113
113
  <>
114
114
  <button
115
- onClick={() => eventBus.emit('resource:unarchive', undefined)}
115
+ onClick={() => eventBus.get('resource:unarchive').next(undefined)}
116
116
  className="semiont-resource-button semiont-resource-button--secondary"
117
117
  >
118
118
  📤 {t('unarchive')}
@@ -124,7 +124,7 @@ export function ResourceInfoPanel({
124
124
  ) : (
125
125
  <>
126
126
  <button
127
- onClick={() => eventBus.emit('resource:archive', undefined)}
127
+ onClick={() => eventBus.get('resource:archive').next(undefined)}
128
128
  className="semiont-resource-button semiont-resource-button--archive"
129
129
  >
130
130
  📦 {t('archive')}
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { useTranslations } from '../../../contexts/TranslationContext';
4
- import type { components } from '@semiont/api-client';
4
+ import type { components } from '@semiont/core';
5
5
  import { isBodyResolved } from '@semiont/api-client';
6
6
  import { getEntityTypes } from '@semiont/ontology';
7
7
  import './StatisticsPanel.css';
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import { forwardRef } from 'react';
4
- import type { components } from '@semiont/api-client';
4
+ import type { components } from '@semiont/core';
5
5
  import { getAnnotationExactText } from '@semiont/api-client';
6
6
  import { getTagCategory, getTagSchemaId } from '@semiont/ontology';
7
7
  import { getTagSchema } from '../../../lib/tag-schemas';
@@ -37,7 +37,7 @@ export const TagEntry = forwardRef<HTMLDivElement, TagEntryProps>(
37
37
  <div
38
38
  ref={ref}
39
39
  onClick={() => {
40
- eventBus.emit('annotation:click', { annotationId: tag.id, motivation: tag.motivation });
40
+ eventBus.get('annotation:click').next({ annotationId: tag.id, motivation: tag.motivation });
41
41
  }}
42
42
  {...hoverProps}
43
43
  className={`semiont-annotation-entry${isHovered ? ' semiont-annotation-pulse' : ''}`}
@@ -4,7 +4,7 @@ import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
5
  import { useEventBus } from '../../../contexts/EventBusContext';
6
6
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
7
- import type { components, Selector } from '@semiont/api-client';
7
+ import type { components, Selector } from '@semiont/core';
8
8
  import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
9
  import { TagEntry } from './TagEntry';
10
10
  import { PanelHeader } from './PanelHeader';
@@ -195,7 +195,7 @@ export function TaggingPanel({
195
195
 
196
196
  const handleDetect = () => {
197
197
  if (selectedCategories.size > 0) {
198
- eventBus.emit('detection:start', {
198
+ eventBus.get('detection:start').next({
199
199
  motivation: 'tagging',
200
200
  options: {
201
201
  schemaId: selectedSchemaId,
@@ -212,7 +212,7 @@ export function TaggingPanel({
212
212
 
213
213
  const handleEscape = (e: KeyboardEvent) => {
214
214
  if (e.key === 'Escape') {
215
- eventBus.emit('annotation:cancel-pending', undefined);
215
+ eventBus.get('annotation:cancel-pending').next(undefined);
216
216
  }
217
217
  };
218
218
 
@@ -274,7 +274,7 @@ export function TaggingPanel({
274
274
  className="semiont-select"
275
275
  onChange={(e) => {
276
276
  if (e.target.value && pendingAnnotation) {
277
- eventBus.emit('annotation:create', {
277
+ eventBus.get('annotation:create').next({
278
278
  motivation: 'tagging',
279
279
  selector: pendingAnnotation.selector,
280
280
  body: [
@@ -305,7 +305,7 @@ export function TaggingPanel({
305
305
  {/* Cancel button */}
306
306
  <div className="semiont-annotation-prompt__footer">
307
307
  <button
308
- onClick={() => eventBus.emit('annotation:cancel-pending', undefined)}
308
+ onClick={() => eventBus.get('annotation:cancel-pending').next(undefined)}
309
309
  className="semiont-button semiont-button--secondary"
310
310
  data-type="tag"
311
311
  >
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useState, useEffect } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
- import type { components, Selector } from '@semiont/api-client';
5
+ import type { components, Selector } from '@semiont/core';
6
6
  import type { RouteBuilder, LinkComponentProps } from '../../../contexts/RoutingContext';
7
7
  import type { Annotator } from '../../../lib/annotation-registry';
8
8
  import { StatisticsPanel } from './StatisticsPanel';
@@ -6,7 +6,7 @@ import userEvent from '@testing-library/user-event';
6
6
  import '@testing-library/jest-dom';
7
7
  import { AssessmentPanel } from '../AssessmentPanel';
8
8
  import { EventBusProvider, resetEventBusForTesting, useEventBus } from '../../../../contexts/EventBusContext';
9
- import type { components } from '@semiont/api-client';
9
+ import type { components } from '@semiont/core';
10
10
 
11
11
  type Annotation = components['schemas']['Annotation'];
12
12
 
@@ -29,16 +29,16 @@ function createEventTracker() {
29
29
  events.push({ event: eventName, payload });
30
30
  };
31
31
 
32
- const panelEvents = ['annotation:create'];
32
+ const panelEvents = ['annotation:create'] as const;
33
33
 
34
34
  panelEvents.forEach(eventName => {
35
35
  const handler = trackEvent(eventName);
36
- eventBus.on(eventName, handler);
37
- handlers.push(() => eventBus.off(eventName, handler));
36
+ const subscription = eventBus.get(eventName).subscribe(handler);
37
+ handlers.push(subscription);
38
38
  });
39
39
 
40
40
  return () => {
41
- handlers.forEach(cleanup => cleanup());
41
+ handlers.forEach(sub => sub.unsubscribe());
42
42
  };
43
43
  }, [eventBus]);
44
44
 
@@ -5,8 +5,8 @@ import { renderWithProviders, resetEventBusForTesting } from '../../../../test-u
5
5
  import userEvent from '@testing-library/user-event';
6
6
  import '@testing-library/jest-dom';
7
7
  import { CommentEntry } from '../CommentEntry';
8
- import type { components } from '@semiont/api-client';
9
- import type { EventBus } from '../../../../contexts/EventBusContext';
8
+ import type { components } from '@semiont/core';
9
+ import type { EventBus } from "@semiont/core"
10
10
 
11
11
  type Annotation = components['schemas']['Annotation'];
12
12
 
@@ -250,7 +250,7 @@ describe('CommentEntry Component', () => {
250
250
  );
251
251
 
252
252
  // Subscribe to actual event on real event bus
253
- eventBus!.on('annotation:click', clickHandler);
253
+ const subscription = eventBus!.get('annotation:click').subscribe(clickHandler);
254
254
 
255
255
  const commentDiv = container.firstChild as HTMLElement;
256
256
  await userEvent.click(commentDiv);
@@ -261,7 +261,7 @@ describe('CommentEntry Component', () => {
261
261
  });
262
262
 
263
263
  // Clean up
264
- eventBus!.off('annotation:click', clickHandler);
264
+ subscription.unsubscribe();
265
265
  });
266
266
 
267
267
  it('should be clickable with cursor-pointer class', () => {
@@ -283,7 +283,7 @@ describe('CommentEntry Component', () => {
283
283
  );
284
284
 
285
285
  // Subscribe to actual event
286
- eventBus!.on('annotation:hover', hoverHandler);
286
+ const subscription = eventBus!.get('annotation:hover').subscribe(hoverHandler);
287
287
 
288
288
  const commentDiv = container.firstChild as HTMLElement;
289
289
  fireEvent.mouseEnter(commentDiv);
@@ -297,7 +297,7 @@ describe('CommentEntry Component', () => {
297
297
  expect(hoverHandler).toHaveBeenCalledWith({ annotationId: 'comment-1' });
298
298
 
299
299
  // Clean up
300
- eventBus!.off('annotation:hover', hoverHandler);
300
+ subscription.unsubscribe();
301
301
  vi.useRealTimers();
302
302
  });
303
303
 
@@ -311,7 +311,7 @@ describe('CommentEntry Component', () => {
311
311
  );
312
312
 
313
313
  // Subscribe to actual event
314
- eventBus!.on('annotation:hover', hoverHandler);
314
+ const subscription = eventBus!.get('annotation:hover').subscribe(hoverHandler);
315
315
 
316
316
  const commentDiv = container.firstChild as HTMLElement;
317
317
  fireEvent.mouseEnter(commentDiv);
@@ -323,7 +323,7 @@ describe('CommentEntry Component', () => {
323
323
  expect(hoverHandler).not.toHaveBeenCalled();
324
324
 
325
325
  // Clean up
326
- eventBus!.off('annotation:hover', hoverHandler);
326
+ subscription.unsubscribe();
327
327
  vi.useRealTimers();
328
328
  });
329
329
 
@@ -336,7 +336,7 @@ describe('CommentEntry Component', () => {
336
336
  { returnEventBus: true }
337
337
  );
338
338
 
339
- eventBus!.on('annotation:hover', hoverHandler);
339
+ const subscription = eventBus!.get('annotation:hover').subscribe(hoverHandler);
340
340
 
341
341
  const commentDiv = container.firstChild as HTMLElement;
342
342
  fireEvent.mouseEnter(commentDiv);
@@ -347,7 +347,7 @@ describe('CommentEntry Component', () => {
347
347
  expect(hoverHandler).toHaveBeenNthCalledWith(1, { annotationId: 'comment-1' });
348
348
  expect(hoverHandler).toHaveBeenNthCalledWith(2, { annotationId: null });
349
349
 
350
- eventBus!.off('annotation:hover', hoverHandler);
350
+ subscription.unsubscribe();
351
351
  vi.useRealTimers();
352
352
  });
353
353
 
@@ -6,7 +6,7 @@ import userEvent from '@testing-library/user-event';
6
6
  import '@testing-library/jest-dom';
7
7
  import { CommentsPanel } from '../CommentsPanel';
8
8
  import { EventBusProvider, resetEventBusForTesting, useEventBus } from '../../../../contexts/EventBusContext';
9
- import type { components } from '@semiont/api-client';
9
+ import type { components } from '@semiont/core';
10
10
 
11
11
  type Annotation = components['schemas']['Annotation'];
12
12
 
@@ -29,16 +29,16 @@ function createEventTracker() {
29
29
  events.push({ event: eventName, payload });
30
30
  };
31
31
 
32
- const panelEvents = ['annotation:create'];
32
+ const panelEvents = ['annotation:create'] as const;
33
33
 
34
34
  panelEvents.forEach(eventName => {
35
35
  const handler = trackEvent(eventName);
36
- eventBus.on(eventName, handler);
37
- handlers.push(() => eventBus.off(eventName, handler));
36
+ const subscription = eventBus.get(eventName).subscribe(handler);
37
+ handlers.push(subscription);
38
38
  });
39
39
 
40
40
  return () => {
41
- handlers.forEach(cleanup => cleanup());
41
+ handlers.forEach(sub => sub.unsubscribe());
42
42
  };
43
43
  }, [eventBus]);
44
44
 
@@ -18,7 +18,7 @@ import { renderWithProviders } from '../../../../test-utils';
18
18
  import userEvent from '@testing-library/user-event';
19
19
  import { DetectSection } from '../DetectSection';
20
20
  import { resetEventBusForTesting } from '../../../../contexts/EventBusContext';
21
- import type { EventBus } from '../../../../contexts/EventBusContext';
21
+ import type { EventBus } from "@semiont/core"
22
22
 
23
23
  // Mock translations
24
24
  const mockT = vi.fn((key: string) => {
@@ -276,7 +276,7 @@ describe('DetectSection', () => {
276
276
  { returnEventBus: true }
277
277
  );
278
278
 
279
- eventBus!.on('detection:start', detectionHandler);
279
+ const subscription = eventBus!.get('detection:start').subscribe(detectionHandler);
280
280
 
281
281
  const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
282
282
  await user.click(detectButton);
@@ -286,7 +286,7 @@ describe('DetectSection', () => {
286
286
  options: expect.any(Object),
287
287
  });
288
288
 
289
- eventBus!.off('detection:start', detectionHandler);
289
+ subscription.unsubscribe();
290
290
  });
291
291
 
292
292
  it('should emit correct motivation for assessment type', async () => {
@@ -302,7 +302,7 @@ describe('DetectSection', () => {
302
302
  { returnEventBus: true }
303
303
  );
304
304
 
305
- eventBus!.on('detection:start', detectionHandler);
305
+ const subscription = eventBus!.get('detection:start').subscribe(detectionHandler);
306
306
 
307
307
  const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
308
308
  await user.click(detectButton);
@@ -312,7 +312,7 @@ describe('DetectSection', () => {
312
312
  options: expect.any(Object),
313
313
  });
314
314
 
315
- eventBus!.off('detection:start', detectionHandler);
315
+ subscription.unsubscribe();
316
316
  });
317
317
 
318
318
  it('should emit correct motivation for comment type', async () => {
@@ -328,7 +328,7 @@ describe('DetectSection', () => {
328
328
  { returnEventBus: true }
329
329
  );
330
330
 
331
- eventBus!.on('detection:start', detectionHandler);
331
+ const subscription = eventBus!.get('detection:start').subscribe(detectionHandler);
332
332
 
333
333
  const detectButton = screen.getByRole('button', { name: /✨ Detect/ });
334
334
  await user.click(detectButton);
@@ -338,7 +338,7 @@ describe('DetectSection', () => {
338
338
  options: expect.any(Object),
339
339
  });
340
340
 
341
- eventBus!.off('detection:start', detectionHandler);
341
+ subscription.unsubscribe();
342
342
  });
343
343
 
344
344
  it('should include instructions in event when provided', async () => {
@@ -354,7 +354,7 @@ describe('DetectSection', () => {
354
354
  { returnEventBus: true }
355
355
  );
356
356
 
357
- eventBus!.on('detection:start', detectionHandler);
357
+ const subscription = eventBus!.get('detection:start').subscribe(detectionHandler);
358
358
 
359
359
  const textarea = screen.getByPlaceholderText('Enter custom instructions...');
360
360
  await user.type(textarea, 'Find key concepts');
@@ -370,7 +370,7 @@ describe('DetectSection', () => {
370
370
  },
371
371
  });
372
372
 
373
- eventBus!.off('detection:start', detectionHandler);
373
+ subscription.unsubscribe();
374
374
  });
375
375
  });
376
376
 
@@ -16,7 +16,7 @@ import React from 'react';
16
16
  import { screen } from '@testing-library/react';
17
17
  import { renderWithProviders } from '../../../../test-utils';
18
18
  import { HighlightPanel } from '../HighlightPanel';
19
- import type { components } from '@semiont/api-client';
19
+ import type { components } from '@semiont/core';
20
20
  import { resetEventBusForTesting } from '../../../../contexts/EventBusContext';
21
21
 
22
22
  type Annotation = components['schemas']['Annotation'];
@@ -4,7 +4,7 @@ import { render, screen, waitFor } from '@testing-library/react';
4
4
  import userEvent from '@testing-library/user-event';
5
5
  import '@testing-library/jest-dom';
6
6
  import { JsonLdPanel } from '../JsonLdPanel';
7
- import type { components } from '@semiont/api-client';
7
+ import type { components } from '@semiont/core';
8
8
 
9
9
  type SemiontResource = components['schemas']['ResourceDescriptor'];
10
10
 
@@ -25,16 +25,16 @@ function createEventTracker() {
25
25
  events.push({ event: eventName, payload });
26
26
  };
27
27
 
28
- const panelEvents = ['detection:start'];
28
+ const panelEvents = ['detection:start'] as const;
29
29
 
30
30
  panelEvents.forEach(eventName => {
31
31
  const handler = trackEvent(eventName);
32
- eventBus.on(eventName, handler);
33
- handlers.push(() => eventBus.off(eventName, handler));
32
+ const subscription = eventBus.get(eventName).subscribe(handler);
33
+ handlers.push(subscription);
34
34
  });
35
35
 
36
36
  return () => {
37
- handlers.forEach(cleanup => cleanup());
37
+ handlers.forEach(sub => sub.unsubscribe());
38
38
  };
39
39
  }, [eventBus]);
40
40
 
@@ -69,16 +69,16 @@ function createEventTracker() {
69
69
  'resource:clone',
70
70
  'resource:archive',
71
71
  'resource:unarchive',
72
- ];
72
+ ] as const;
73
73
 
74
74
  resourceEvents.forEach(eventName => {
75
75
  const handler = trackEvent(eventName);
76
- eventBus.on(eventName, handler);
77
- handlers.push(() => eventBus.off(eventName, handler));
76
+ const subscription = eventBus.get(eventName).subscribe(handler);
77
+ handlers.push(subscription);
78
78
  });
79
79
 
80
80
  return () => {
81
- handlers.forEach(cleanup => cleanup());
81
+ handlers.forEach(sub => sub.unsubscribe());
82
82
  };
83
83
  }, [eventBus]);
84
84