@semiont/react-ui 0.4.21 → 0.4.22

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/{PdfAnnotationCanvas.client-6ZGFEN2N.mjs → PdfAnnotationCanvas.client-5QESNO5H.mjs} +10 -9
  2. package/dist/PdfAnnotationCanvas.client-5QESNO5H.mjs.map +1 -0
  3. package/dist/{chunk-KEDFYI6N.mjs → chunk-4NOUO3W6.mjs} +2 -2
  4. package/dist/{chunk-KEDFYI6N.mjs.map → chunk-4NOUO3W6.mjs.map} +1 -1
  5. package/dist/index.d.mts +54 -79
  6. package/dist/index.mjs +255 -254
  7. package/dist/index.mjs.map +1 -1
  8. package/dist/test-utils.d.mts +3 -1
  9. package/dist/test-utils.mjs +14 -8
  10. package/dist/test-utils.mjs.map +1 -1
  11. package/package.json +2 -1
  12. package/src/components/AnnotateReferencesProgressWidget.tsx +1 -1
  13. package/src/components/CodeMirrorRenderer.tsx +5 -3
  14. package/src/components/LiveRegion.tsx +1 -2
  15. package/src/components/StatusDisplay.tsx +1 -1
  16. package/src/components/__tests__/StatusDisplay.test.tsx +3 -1
  17. package/src/components/annotation/AnnotateToolbar.tsx +5 -7
  18. package/src/components/annotation-popups/JsonLdView.tsx +1 -2
  19. package/src/components/annotation-popups/__tests__/JsonLdView.test.tsx +1 -1
  20. package/src/components/image-annotation/AnnotationOverlay.tsx +12 -14
  21. package/src/components/image-annotation/SvgDrawingCanvas.tsx +8 -13
  22. package/src/components/modals/ConfigureGenerationStep.tsx +1 -2
  23. package/src/components/modals/ReferenceWizardModal.tsx +1 -1
  24. package/src/components/modals/ResourceSearchModal.tsx +3 -3
  25. package/src/components/modals/SearchModal.tsx +2 -1
  26. package/src/components/modals/SearchResultsStep.tsx +1 -3
  27. package/src/components/modals/__tests__/SearchModal.accessibility.test.tsx +6 -2
  28. package/src/components/modals/__tests__/SearchModal.basic.test.tsx +6 -2
  29. package/src/components/modals/__tests__/SearchModal.keyboard.test.tsx +6 -2
  30. package/src/components/modals/__tests__/SearchModal.visual.test.tsx +6 -2
  31. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +11 -12
  32. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +1 -1
  33. package/src/components/resource/AnnotateView.tsx +2 -5
  34. package/src/components/resource/BrowseView.tsx +6 -4
  35. package/src/components/resource/ResourceViewer.tsx +7 -11
  36. package/src/components/resource/__tests__/BrowseView.test.tsx +4 -4
  37. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +1 -0
  38. package/src/components/resource/__tests__/event-formatting.test.ts +6 -2
  39. package/src/components/resource/event-formatting.ts +2 -3
  40. package/src/components/resource/panels/AssessmentEntry.tsx +3 -5
  41. package/src/components/resource/panels/AssessmentPanel.tsx +5 -5
  42. package/src/components/resource/panels/AssistSection.tsx +6 -10
  43. package/src/components/resource/panels/CollaborationPanel.tsx +1 -1
  44. package/src/components/resource/panels/CommentEntry.tsx +3 -5
  45. package/src/components/resource/panels/CommentsPanel.tsx +5 -5
  46. package/src/components/resource/panels/HighlightEntry.tsx +3 -5
  47. package/src/components/resource/panels/HighlightPanel.tsx +3 -3
  48. package/src/components/resource/panels/ReferenceEntry.tsx +7 -9
  49. package/src/components/resource/panels/ReferencesPanel.tsx +8 -11
  50. package/src/components/resource/panels/ResourceInfoPanel.tsx +5 -5
  51. package/src/components/resource/panels/StatisticsPanel.tsx +2 -3
  52. package/src/components/resource/panels/TagEntry.tsx +3 -5
  53. package/src/components/resource/panels/TaggingPanel.tsx +8 -11
  54. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +1 -1
  55. package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +4 -4
  56. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +4 -5
  57. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +4 -4
  58. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +4 -5
  59. package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +4 -4
  60. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +1 -1
  61. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +4 -4
  62. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +21 -14
  63. package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +3 -3
  64. package/src/components/resource/panels/__tests__/TagEntry.test.tsx +4 -4
  65. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +4 -5
  66. package/src/components/settings/SettingsPanel.tsx +1 -1
  67. package/src/components/settings/__tests__/SettingsPanel.test.tsx +3 -3
  68. package/src/features/admin-devops/components/AdminDevOpsPage.tsx +1 -2
  69. package/src/features/admin-exchange/components/AdminExchangePage.tsx +1 -1
  70. package/src/features/admin-exchange/components/ImportCard.tsx +1 -2
  71. package/src/features/admin-security/components/AdminSecurityPage.tsx +1 -2
  72. package/src/features/admin-users/components/AdminUsersPage.tsx +1 -1
  73. package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +1 -2
  74. package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +1 -2
  75. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +1 -1
  76. package/src/features/moderation-linked-data/components/LinkedDataPage.tsx +1 -1
  77. package/src/features/resource-compose/components/ResourceComposePage.tsx +3 -2
  78. package/src/features/resource-discovery/components/ResourceCard.tsx +1 -2
  79. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +3 -4
  80. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +4 -5
  81. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +12 -11
  82. package/dist/PdfAnnotationCanvas.client-6ZGFEN2N.mjs.map +0 -1
@@ -9,10 +9,14 @@ import {
9
9
  } from '../event-formatting';
10
10
 
11
11
  // Mock api-client functions
12
- vi.mock('@semiont/api-client', () => ({
12
+ vi.mock('@semiont/core', async (importOriginal) => {
13
+ const actual = await importOriginal<typeof import('@semiont/core')>();
14
+ return {
15
+ ...actual,
13
16
  getExactText: vi.fn((selector: any) => selector?.exact ?? null),
14
17
  getTargetSelector: vi.fn((target: any) => target?.selector ?? null),
15
- }));
18
+ };
19
+ });
16
20
 
17
21
  const t = vi.fn((key: string, params?: Record<string, string | number>) => {
18
22
  if (params) return `${key}(${JSON.stringify(params)})`;
@@ -6,11 +6,10 @@
6
6
  */
7
7
 
8
8
  import type { StoredEventLike, PersistedEventType } from '@semiont/core';
9
- import type { components } from '@semiont/core';
10
- import { getExactText, getTargetSelector } from '@semiont/api-client';
9
+ import { getExactText, getTargetSelector } from '@semiont/core';
11
10
  import { ANNOTATORS } from '../../lib/annotation-registry';
12
11
 
13
- type Annotation = components['schemas']['Annotation'];
12
+ import type { Annotation } from '@semiont/core';
14
13
  type TranslateFn = (key: string, params?: Record<string, string | number>) => string;
15
14
 
16
15
  // =============================================================================
@@ -1,14 +1,12 @@
1
1
  'use client';
2
2
 
3
3
  import type { Ref } from 'react';
4
- import type { components } from '@semiont/core';
5
- import { getAnnotationExactText } from '@semiont/api-client';
4
+ import type { Annotation } from '@semiont/core';
5
+ import { getAnnotationExactText } from '@semiont/core';
6
6
  import { useSemiont } from '../../../session/SemiontProvider';
7
7
  import { useObservable } from '../../../hooks/useObservable';
8
8
  import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
9
9
 
10
- type Annotation = components['schemas']['Annotation'];
11
-
12
10
  // W3C Annotation TextualBody type
13
11
  interface TextualBody {
14
12
  type: 'TextualBody';
@@ -88,7 +86,7 @@ export function AssessmentEntry({
88
86
  data-type="assessment"
89
87
  data-focused={isFocused ? 'true' : 'false'}
90
88
  onClick={() => {
91
- session?.client.emit('browse:click', { annotationId: assessment.id, motivation: assessment.motivation });
89
+ session?.client.browse.click(assessment.id, assessment.motivation);
92
90
  }}
93
91
  {...hoverProps}
94
92
  >
@@ -6,13 +6,13 @@ import { useSemiont } from '../../../session/SemiontProvider';
6
6
  import { useObservable } from '../../../hooks/useObservable';
7
7
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
8
8
  import type { components, Selector } from '@semiont/core';
9
- import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
+ import { getTextPositionSelector, getTargetSelector } from '@semiont/core';
10
10
  import { AssessmentEntry } from './AssessmentEntry';
11
11
  import { AssistSection } from './AssistSection';
12
12
  import { PanelHeader } from './PanelHeader';
13
13
  import './AssessmentPanel.css';
14
14
 
15
- type Annotation = components['schemas']['Annotation'];
15
+ import type { Annotation } from '@semiont/core';
16
16
  type Motivation = components['schemas']['Motivation'];
17
17
  type JobProgress = components['schemas']['JobProgress'];
18
18
 
@@ -147,7 +147,7 @@ export function AssessmentPanel({
147
147
  ? { type: 'TextualBody', value: trimmed, purpose: 'assessing' }
148
148
  : undefined;
149
149
 
150
- session?.client.emit('mark:submit', {
150
+ session?.client.mark.submit({
151
151
  motivation: 'assessing',
152
152
  selector: pendingAnnotation.selector,
153
153
  ...(body !== undefined ? { body } : {}),
@@ -162,7 +162,7 @@ export function AssessmentPanel({
162
162
 
163
163
  const handleEscape = (e: KeyboardEvent) => {
164
164
  if (e.key === 'Escape') {
165
- session?.client.emit('mark:cancel-pending', undefined);
165
+ session?.client.mark.cancelPending();
166
166
  setNewAssessmentText('');
167
167
  }
168
168
  };
@@ -215,7 +215,7 @@ export function AssessmentPanel({
215
215
  <div className="semiont-annotation-prompt__actions">
216
216
  <button
217
217
  onClick={() => {
218
- session?.client.emit('mark:cancel-pending', undefined);
218
+ session?.client.mark.cancelPending();
219
219
  setNewAssessmentText('');
220
220
  }}
221
221
  className="semiont-button semiont-button--secondary"
@@ -70,15 +70,11 @@ export function AssistSection({
70
70
  annotationType === 'assessment' ? 'assessing' :
71
71
  'commenting';
72
72
 
73
- // Emit mark:assist-request event with options
74
- session?.client.emit('mark:assist-request', {
75
- motivation,
76
- options: {
77
- instructions: instructions.trim() || undefined,
78
- tone: (annotationType === 'comment' || annotationType === 'assessment') && tone ? tone : undefined,
79
- density: (annotationType === 'comment' || annotationType === 'assessment' || annotationType === 'highlight') && useDensity ? density : undefined,
80
- language: (annotationType === 'comment' || annotationType === 'assessment') ? locale : undefined,
81
- },
73
+ session?.client.mark.requestAssist(motivation, {
74
+ instructions: instructions.trim() || undefined,
75
+ tone: (annotationType === 'comment' || annotationType === 'assessment') && tone ? tone : undefined,
76
+ density: (annotationType === 'comment' || annotationType === 'assessment' || annotationType === 'highlight') && useDensity ? density : undefined,
77
+ language: (annotationType === 'comment' || annotationType === 'assessment') ? locale : undefined,
82
78
  });
83
79
 
84
80
  setInstructions('');
@@ -87,7 +83,7 @@ export function AssistSection({
87
83
  }, [annotationType, instructions, tone, useDensity, density, locale, session]);
88
84
 
89
85
  const handleDismissProgress = useCallback(() => {
90
- session?.client.emit('mark:progress-dismiss', undefined);
86
+ session?.client.mark.dismissProgress();
91
87
  }, [session]);
92
88
 
93
89
  return (
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import type { ConnectionState } from '@semiont/api-client';
3
+ import type { ConnectionState } from '@semiont/core';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
5
  import './CollaborationPanel.css';
6
6
 
@@ -2,14 +2,12 @@
2
2
 
3
3
  import { useState, useEffect, useRef, useImperativeHandle, type Ref } from 'react';
4
4
  import { useTranslations } from '../../../contexts/TranslationContext';
5
- import type { components } from '@semiont/core';
6
- import { getAnnotationExactText, getCommentText } from '@semiont/api-client';
5
+ import type { Annotation } from '@semiont/core';
6
+ import { getAnnotationExactText, getCommentText } from '@semiont/core';
7
7
  import { useSemiont } from '../../../session/SemiontProvider';
8
8
  import { useObservable } from '../../../hooks/useObservable';
9
9
  import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
10
10
 
11
- type Annotation = components['schemas']['Annotation'];
12
-
13
11
  interface CommentEntryProps {
14
12
  comment: Annotation;
15
13
  isFocused: boolean;
@@ -87,7 +85,7 @@ export function CommentEntry({
87
85
  data-type="comment"
88
86
  data-focused={isFocused ? 'true' : 'false'}
89
87
  onClick={() => {
90
- session?.client.emit('browse:click', { annotationId: comment.id, motivation: comment.motivation });
88
+ session?.client.browse.click(comment.id, comment.motivation);
91
89
  }}
92
90
  {...hoverProps}
93
91
  >
@@ -6,13 +6,13 @@ import { useSemiont } from '../../../session/SemiontProvider';
6
6
  import { useObservable } from '../../../hooks/useObservable';
7
7
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
8
8
  import type { components, Selector } from '@semiont/core';
9
- import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
+ import { getTextPositionSelector, getTargetSelector } from '@semiont/core';
10
10
  import { CommentEntry } from './CommentEntry';
11
11
  import { AssistSection } from './AssistSection';
12
12
  import { PanelHeader } from './PanelHeader';
13
13
  import './CommentsPanel.css';
14
14
 
15
- type Annotation = components['schemas']['Annotation'];
15
+ import type { Annotation } from '@semiont/core';
16
16
  type Motivation = components['schemas']['Motivation'];
17
17
  type JobProgress = components['schemas']['JobProgress'];
18
18
 
@@ -167,7 +167,7 @@ export function CommentsPanel({
167
167
 
168
168
  const handleSaveNewComment = () => {
169
169
  if (newCommentText.trim() && pendingAnnotation) {
170
- session?.client.emit('mark:submit', {
170
+ session?.client.mark.submit({
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
- session?.client.emit('mark:cancel-pending', undefined);
185
+ session?.client.mark.cancelPending();
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
- session?.client.emit('mark:cancel-pending', undefined);
227
+ session?.client.mark.cancelPending();
228
228
  setNewCommentText('');
229
229
  }}
230
230
  className="semiont-button semiont-button--secondary"
@@ -1,14 +1,12 @@
1
1
  'use client';
2
2
 
3
3
  import type { Ref } from 'react';
4
- import type { components } from '@semiont/core';
5
- import { getAnnotationExactText } from '@semiont/api-client';
4
+ import type { Annotation } from '@semiont/core';
5
+ import { getAnnotationExactText } from '@semiont/core';
6
6
  import { useSemiont } from '../../../session/SemiontProvider';
7
7
  import { useObservable } from '../../../hooks/useObservable';
8
8
  import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
9
9
 
10
- type Annotation = components['schemas']['Annotation'];
11
-
12
10
  interface HighlightEntryProps {
13
11
  highlight: Annotation;
14
12
  isFocused: boolean;
@@ -51,7 +49,7 @@ export function HighlightEntry({
51
49
  data-type="highlight"
52
50
  data-focused={isFocused ? 'true' : 'false'}
53
51
  onClick={() => {
54
- session?.client.emit('browse:click', { annotationId: highlight.id, motivation: highlight.motivation });
52
+ session?.client.browse.click(highlight.id, highlight.motivation);
55
53
  }}
56
54
  {...hoverProps}
57
55
  >
@@ -6,13 +6,13 @@ import { useSemiont } from '../../../session/SemiontProvider';
6
6
  import { useObservable } from '../../../hooks/useObservable';
7
7
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
8
8
  import type { components, Selector } from '@semiont/core';
9
- import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
+ import { getTextPositionSelector, getTargetSelector } from '@semiont/core';
10
10
  import { HighlightEntry } from './HighlightEntry';
11
11
  import { AssistSection } from './AssistSection';
12
12
  import { PanelHeader } from './PanelHeader';
13
13
  import './HighlightPanel.css';
14
14
 
15
- type Annotation = components['schemas']['Annotation'];
15
+ import type { Annotation } from '@semiont/core';
16
16
  type Motivation = components['schemas']['Motivation'];
17
17
  type JobProgress = components['schemas']['JobProgress'];
18
18
 
@@ -132,7 +132,7 @@ export function HighlightPanel({
132
132
  // per the W3C Web Annotation Model.
133
133
  useEffect(() => {
134
134
  if (pendingAnnotation && pendingAnnotation.motivation === 'highlighting') {
135
- session?.client.emit('mark:submit', {
135
+ session?.client.mark.submit({
136
136
  motivation: 'highlighting',
137
137
  selector: pendingAnnotation.selector,
138
138
  });
@@ -3,9 +3,9 @@
3
3
  import type { Ref } from 'react';
4
4
  import type { RouteBuilder } from '../../../contexts/RoutingContext';
5
5
  import { useTranslations } from '../../../contexts/TranslationContext';
6
- import type { components } from '@semiont/core';
7
- import { annotationId, resourceId } from '@semiont/core';
8
- import { getAnnotationExactText, isBodyResolved, getBodySource, getFragmentSelector, getSvgSelector, getTargetSelector } from '@semiont/api-client';
6
+ import type { Annotation } from '@semiont/core';
7
+ import { resourceId } from '@semiont/core';
8
+ import { getAnnotationExactText, isBodyResolved, getBodySource, getFragmentSelector, getSvgSelector, getTargetSelector } from '@semiont/core';
9
9
  import { getEntityTypes } from '@semiont/ontology';
10
10
  import { getResourceIcon } from '../../../lib/resource-utils';
11
11
  import { useSemiont } from '../../../session/SemiontProvider';
@@ -13,8 +13,6 @@ import { useObservable } from '../../../hooks/useObservable';
13
13
  import { useObservableExternalNavigation } from '../../../hooks/useObservableBrowse';
14
14
  import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
15
15
 
16
- type Annotation = components['schemas']['Annotation'];
17
-
18
16
  // Extended annotation type with runtime properties added by backend enrichment
19
17
  interface EnrichedAnnotation extends Annotation {
20
18
  _resolvedDocumentName?: string;
@@ -78,15 +76,15 @@ export function ReferenceEntry({
78
76
  if (source && resolvedResourceUri && semiont) {
79
77
  semiont.bind.body(
80
78
  resourceId(source),
81
- annotationId(reference.id),
79
+ reference.id,
82
80
  [{ op: 'remove', item: { type: 'SpecificResource', source: resolvedResourceUri, purpose: 'linking' } }],
83
81
  ).catch(() => { /* error handled by events-stream */ });
84
82
  }
85
83
  };
86
84
 
87
85
  const handleInitiateWizard = () => {
88
- session?.client.emit('bind:initiate', {
89
- annotationId: annotationId(reference.id),
86
+ session?.client.bind.initiate({
87
+ annotationId: reference.id,
90
88
  resourceId: resourceId(source),
91
89
  defaultTitle: selectedText,
92
90
  entityTypes,
@@ -112,7 +110,7 @@ export function ReferenceEntry({
112
110
  data-type="reference"
113
111
  data-focused={isFocused ? 'true' : 'false'}
114
112
  onClick={() => {
115
- session?.client.emit('browse:click', { annotationId: reference.id, motivation: reference.motivation });
113
+ session?.client.browse.click(reference.id, reference.motivation);
116
114
  }}
117
115
  {...hoverProps}
118
116
  >
@@ -9,13 +9,13 @@ import type { RouteBuilder, LinkComponentProps } from '../../../contexts/Routing
9
9
  import { AnnotateReferencesProgressWidget } from '../../AnnotateReferencesProgressWidget';
10
10
  import { ReferenceEntry } from './ReferenceEntry';
11
11
  import type { components, Selector } from '@semiont/core';
12
- import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
12
+ import { getTextPositionSelector, getTargetSelector } from '@semiont/core';
13
13
  import { PanelHeader } from './PanelHeader';
14
14
  import './ReferencesPanel.css';
15
15
 
16
16
  type JobProgress = components['schemas']['JobProgress'];
17
17
 
18
- type Annotation = components['schemas']['Annotation'];
18
+ import type { Annotation } from '@semiont/core';
19
19
  type Motivation = components['schemas']['Motivation'];
20
20
  type ReferencedBy = components['schemas']['GetReferencedByResponse']['referencedBy'][number];
21
21
 
@@ -203,12 +203,9 @@ export function ReferencesPanel({
203
203
  // Clear log when starting new annotation
204
204
  const handleAssist = () => {
205
205
  setLastDetectionLog(null);
206
- session?.client.emit('mark:assist-request', {
207
- motivation: 'linking',
208
- options: {
209
- entityTypes: selectedEntityTypes,
210
- includeDescriptiveReferences,
211
- },
206
+ session?.client.mark.requestAssist('linking', {
207
+ entityTypes: selectedEntityTypes,
208
+ includeDescriptiveReferences,
212
209
  });
213
210
  };
214
211
 
@@ -246,7 +243,7 @@ export function ReferencesPanel({
246
243
  const handleCreateReference = () => {
247
244
  if (pendingAnnotation) {
248
245
  const entityType = pendingEntityTypes.join(',') || undefined;
249
- session?.client.emit('mark:submit', {
246
+ session?.client.mark.submit({
250
247
  motivation: 'linking',
251
248
  selector: pendingAnnotation.selector,
252
249
  body: entityType ? [{ type: 'TextualBody', value: entityType, purpose: 'tagging' }] : [],
@@ -261,7 +258,7 @@ export function ReferencesPanel({
261
258
 
262
259
  const handleEscape = (e: KeyboardEvent) => {
263
260
  if (e.key === 'Escape') {
264
- session?.client.emit('mark:cancel-pending', undefined);
261
+ session?.client.mark.cancelPending();
265
262
  setPendingEntityTypes([]);
266
263
  }
267
264
  };
@@ -313,7 +310,7 @@ export function ReferencesPanel({
313
310
  <div className="semiont-annotation-prompt__actions">
314
311
  <button
315
312
  onClick={() => {
316
- session?.client.emit('mark:cancel-pending', undefined);
313
+ session?.client.mark.cancelPending();
317
314
  setPendingEntityTypes([]);
318
315
  }}
319
316
  className="semiont-button semiont-button--secondary"
@@ -3,7 +3,7 @@
3
3
  import { useTranslations } from '../../../contexts/TranslationContext';
4
4
  import { useSemiont } from '../../../session/SemiontProvider';
5
5
  import { useObservable } from '../../../hooks/useObservable';
6
- import { formatLocaleDisplay } from '@semiont/api-client';
6
+ import { formatLocaleDisplay } from '@semiont/core';
7
7
  import { resourceId as makeResourceId, type components } from '@semiont/core';
8
8
  import './ResourceInfoPanel.css';
9
9
 
@@ -149,7 +149,7 @@ export function ResourceInfoPanel({
149
149
  <button
150
150
  key={id}
151
151
  className="semiont-resource-info-panel__link"
152
- onClick={() => session?.client.emit('browse:reference-navigate', { resourceId: id })}
152
+ onClick={() => session?.client.browse.navigateReference(makeResourceId(id))}
153
153
  >
154
154
  {i > 0 && ', '}{id}
155
155
  </button>
@@ -192,7 +192,7 @@ export function ResourceInfoPanel({
192
192
  {/* Clone Action */}
193
193
  <div className="semiont-resource-info-panel__action-section">
194
194
  <button
195
- onClick={() => session?.client.emit('yield:clone', undefined)}
195
+ onClick={() => session?.client.yield.clone()}
196
196
  className="semiont-resource-button semiont-resource-button--secondary"
197
197
  >
198
198
  🔗 {t('clone')}
@@ -207,7 +207,7 @@ export function ResourceInfoPanel({
207
207
  {isArchived ? (
208
208
  <>
209
209
  <button
210
- onClick={() => session?.client.emit('mark:unarchive', { resourceId: makeResourceId(resourceId) })}
210
+ onClick={() => session?.client.mark.unarchive(makeResourceId(resourceId))}
211
211
  className="semiont-resource-button semiont-resource-button--secondary"
212
212
  >
213
213
  📤 {t('unarchive')}
@@ -219,7 +219,7 @@ export function ResourceInfoPanel({
219
219
  ) : (
220
220
  <>
221
221
  <button
222
- onClick={() => session?.client.emit('mark:archive', { resourceId: makeResourceId(resourceId) })}
222
+ onClick={() => session?.client.mark.archive(makeResourceId(resourceId))}
223
223
  className="semiont-resource-button semiont-resource-button--archive"
224
224
  >
225
225
  📦 {t('archive')}
@@ -1,12 +1,11 @@
1
1
  'use client';
2
2
 
3
3
  import { useTranslations } from '../../../contexts/TranslationContext';
4
- import type { components } from '@semiont/core';
5
- import { isBodyResolved } from '@semiont/api-client';
4
+ import { isBodyResolved } from '@semiont/core';
6
5
  import { getEntityTypes } from '@semiont/ontology';
7
6
  import './StatisticsPanel.css';
8
7
 
9
- type Annotation = components['schemas']['Annotation'];
8
+ import type { Annotation } from '@semiont/core';
10
9
 
11
10
  interface StatisticsPanelProps {
12
11
  highlights: Annotation[];
@@ -1,16 +1,14 @@
1
1
  'use client';
2
2
 
3
3
  import type { Ref } from 'react';
4
- import type { components } from '@semiont/core';
5
- import { getAnnotationExactText } from '@semiont/api-client';
4
+ import type { Annotation } from '@semiont/core';
5
+ import { getAnnotationExactText } from '@semiont/core';
6
6
  import { getTagCategory, getTagSchemaId } from '@semiont/ontology';
7
7
  import { getTagSchema } from '../../../lib/tag-schemas';
8
8
  import { useSemiont } from '../../../session/SemiontProvider';
9
9
  import { useObservable } from '../../../hooks/useObservable';
10
10
  import { useHoverEmitter } from '../../../hooks/useHoverEmitter';
11
11
 
12
- type Annotation = components['schemas']['Annotation'];
13
-
14
12
  interface TagEntryProps {
15
13
  tag: Annotation;
16
14
  isFocused: boolean;
@@ -36,7 +34,7 @@ export function TagEntry({
36
34
  <div
37
35
  ref={ref}
38
36
  onClick={() => {
39
- session?.client.emit('browse:click', { annotationId: tag.id, motivation: tag.motivation });
37
+ session?.client.browse.click(tag.id, tag.motivation);
40
38
  }}
41
39
  {...hoverProps}
42
40
  className={`semiont-annotation-entry${isHovered ? ' semiont-annotation-pulse' : ''}`}
@@ -6,13 +6,13 @@ import { useSemiont } from '../../../session/SemiontProvider';
6
6
  import { useObservable } from '../../../hooks/useObservable';
7
7
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
8
8
  import type { components, Selector } from '@semiont/core';
9
- import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
9
+ import { getTextPositionSelector, getTargetSelector } from '@semiont/core';
10
10
  import { TagEntry } from './TagEntry';
11
11
  import { PanelHeader } from './PanelHeader';
12
12
  import { getAllTagSchemas } from '../../../lib/tag-schemas';
13
13
  import './TaggingPanel.css';
14
14
 
15
- type Annotation = components['schemas']['Annotation'];
15
+ import type { Annotation } from '@semiont/core';
16
16
  type Motivation = components['schemas']['Motivation'];
17
17
  type JobProgress = components['schemas']['JobProgress'];
18
18
 
@@ -189,12 +189,9 @@ export function TaggingPanel({
189
189
 
190
190
  const handleAssist = () => {
191
191
  if (selectedCategories.size > 0) {
192
- session?.client.emit('mark:assist-request', {
193
- motivation: 'tagging',
194
- options: {
195
- schemaId: selectedSchemaId,
196
- categories: Array.from(selectedCategories),
197
- },
192
+ session?.client.mark.requestAssist('tagging', {
193
+ schemaId: selectedSchemaId,
194
+ categories: Array.from(selectedCategories),
198
195
  });
199
196
  setSelectedCategories(new Set()); // Reset after annotation
200
197
  }
@@ -206,7 +203,7 @@ export function TaggingPanel({
206
203
 
207
204
  const handleEscape = (e: KeyboardEvent) => {
208
205
  if (e.key === 'Escape') {
209
- session?.client.emit('mark:cancel-pending', undefined);
206
+ session?.client.mark.cancelPending();
210
207
  }
211
208
  };
212
209
 
@@ -268,7 +265,7 @@ export function TaggingPanel({
268
265
  className="semiont-select"
269
266
  onChange={(e) => {
270
267
  if (e.target.value && pendingAnnotation) {
271
- session?.client.emit('mark:submit', {
268
+ session?.client.mark.submit({
272
269
  motivation: 'tagging',
273
270
  selector: pendingAnnotation.selector,
274
271
  body: [
@@ -299,7 +296,7 @@ export function TaggingPanel({
299
296
  {/* Cancel button */}
300
297
  <div className="semiont-annotation-prompt__footer">
301
298
  <button
302
- onClick={() => session?.client.emit('mark:cancel-pending', undefined)}
299
+ onClick={() => session?.client.mark.cancelPending()}
303
300
  className="semiont-button semiont-button--secondary"
304
301
  data-type="tag"
305
302
  >
@@ -14,7 +14,7 @@ import { CommentsPanel } from './CommentsPanel';
14
14
  import { TaggingPanel } from './TaggingPanel';
15
15
  import './UnifiedAnnotationsPanel.css';
16
16
 
17
- type Annotation = components['schemas']['Annotation'];
17
+ import type { Annotation } from '@semiont/core';
18
18
  type Motivation = components['schemas']['Motivation'];
19
19
  type TabKey = 'statistics' | 'reference' | 'highlight' | 'assessment' | 'comment' | 'tag';
20
20
 
@@ -6,18 +6,18 @@ import { renderWithProviders } from '../../../../test-utils';
6
6
  import userEvent from '@testing-library/user-event';
7
7
  import type { components } from '@semiont/core';
8
8
 
9
- type Annotation = components['schemas']['Annotation'];
9
+ import type { Annotation } from '@semiont/core';
10
10
 
11
11
  // Mock @semiont/api-client
12
- vi.mock('@semiont/api-client', async () => {
13
- const actual = await vi.importActual('@semiont/api-client');
12
+ vi.mock('@semiont/core', async () => {
13
+ const actual = await vi.importActual('@semiont/core');
14
14
  return {
15
15
  ...actual,
16
16
  getAnnotationExactText: vi.fn(),
17
17
  };
18
18
  });
19
19
 
20
- import { getAnnotationExactText } from '@semiont/api-client';
20
+ import { getAnnotationExactText } from '@semiont/core';
21
21
  import type { MockedFunction } from 'vitest';
22
22
  import { AssessmentEntry } from '../AssessmentEntry';
23
23
 
@@ -8,7 +8,7 @@ import { AssessmentPanel } from '../AssessmentPanel';
8
8
  import type { components, EventBus } from '@semiont/core';
9
9
  import { createTestSemiontWrapper } from '../../../../test-utils';
10
10
 
11
- type Annotation = components['schemas']['Annotation'];
11
+ import type { Annotation } from '@semiont/core';
12
12
 
13
13
  // Composition-based event tracker
14
14
  interface TrackedEvent {
@@ -58,8 +58,8 @@ vi.mock('../../../../contexts/TranslationContext', () => ({
58
58
  }));
59
59
 
60
60
  // Mock @semiont/api-client utilities
61
- vi.mock('@semiont/api-client', async () => {
62
- const actual = await vi.importActual('@semiont/api-client');
61
+ vi.mock('@semiont/core', async () => {
62
+ const actual = await vi.importActual('@semiont/core');
63
63
  return {
64
64
  ...actual,
65
65
  getTextPositionSelector: vi.fn(),
@@ -86,8 +86,7 @@ vi.mock('../AssistSection', () => ({
86
86
  ),
87
87
  }));
88
88
 
89
- import { getTextPositionSelector, getTargetSelector } from '@semiont/api-client';
90
-
89
+ import { getTextPositionSelector, getTargetSelector } from '@semiont/core';
91
90
  const mockGetTextPositionSelector = getTextPositionSelector as MockedFunction<typeof getTextPositionSelector>;
92
91
  const mockGetTargetSelector = getTargetSelector as MockedFunction<typeof getTargetSelector>;
93
92
 
@@ -8,7 +8,7 @@ import { CommentEntry } from '../CommentEntry';
8
8
  import type { components } from '@semiont/core';
9
9
  import type { EventBus } from "@semiont/core"
10
10
 
11
- type Annotation = components['schemas']['Annotation'];
11
+ import type { Annotation } from '@semiont/core';
12
12
 
13
13
  // Mock TranslationContext
14
14
  vi.mock('../../../../contexts/TranslationContext', () => ({
@@ -24,8 +24,8 @@ vi.mock('../../../../contexts/TranslationContext', () => ({
24
24
  }));
25
25
 
26
26
  // Mock @semiont/api-client utilities
27
- vi.mock('@semiont/api-client', async () => {
28
- const actual = await vi.importActual('@semiont/api-client');
27
+ vi.mock('@semiont/core', async () => {
28
+ const actual = await vi.importActual('@semiont/core');
29
29
  return {
30
30
  ...actual,
31
31
  getCommentText: vi.fn(),
@@ -33,7 +33,7 @@ vi.mock('@semiont/api-client', async () => {
33
33
  };
34
34
  });
35
35
 
36
- import { getCommentText, getAnnotationExactText } from '@semiont/api-client';
36
+ import { getCommentText, getAnnotationExactText } from '@semiont/core';
37
37
  import type { MockedFunction } from 'vitest';
38
38
 
39
39
  const mockGetCommentText = getCommentText as MockedFunction<typeof getCommentText>;