@semiont/react-ui 0.5.23 → 0.5.24

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 (48) hide show
  1. package/dist/{chunk-RO5CRVIA.js → chunk-4QMTEPQ3.js} +62 -30
  2. package/dist/chunk-4QMTEPQ3.js.map +1 -0
  3. package/dist/index.d.ts +18 -30
  4. package/dist/index.js +371 -409
  5. package/dist/index.js.map +1 -1
  6. package/dist/test-utils.js +3 -2
  7. package/dist/test-utils.js.map +1 -1
  8. package/package.json +4 -4
  9. package/src/components/annotation-popups/JsonLdView.tsx +1 -1
  10. package/src/components/annotation-popups/__tests__/JsonLdView.test.tsx +8 -2
  11. package/src/components/modals/ReferenceWizardModal.tsx +2 -1
  12. package/src/components/resource/panels/JsonLdPanel.tsx +1 -1
  13. package/src/components/resource/panels/__tests__/JsonLdPanel.test.tsx +8 -2
  14. package/src/components/settings/SettingsPanel.tsx +6 -2
  15. package/src/components/settings/__tests__/SettingsPanel.test.tsx +28 -3
  16. package/src/features/admin-devops/__tests__/AdminDevOpsPage.test.tsx +3 -11
  17. package/src/features/admin-devops/components/AdminDevOpsPage.tsx +0 -3
  18. package/src/features/admin-exchange/__tests__/AdminExchangePage.test.tsx +0 -1
  19. package/src/features/admin-exchange/components/AdminExchangePage.tsx +0 -3
  20. package/src/features/admin-exchange/state/__tests__/exchange-state-unit.test.ts +1 -1
  21. package/src/features/admin-security/__tests__/AdminSecurityPage.test.tsx +0 -8
  22. package/src/features/admin-security/components/AdminSecurityPage.tsx +0 -3
  23. package/src/features/admin-security/state/__tests__/admin-security-state-unit.test.ts +1 -1
  24. package/src/features/admin-users/__tests__/AdminUsersPage.test.tsx +0 -1
  25. package/src/features/admin-users/components/AdminUsersPage.tsx +0 -3
  26. package/src/features/admin-users/state/__tests__/admin-users-state-unit.test.ts +1 -1
  27. package/src/features/auth-welcome/state/__tests__/welcome-state-unit.test.ts +1 -1
  28. package/src/features/moderate-entity-tags/__tests__/EntityTagsPage.test.tsx +0 -2
  29. package/src/features/moderate-entity-tags/components/EntityTagsPage.tsx +0 -3
  30. package/src/features/moderate-entity-tags/state/__tests__/entity-tags-state-unit.test.ts +1 -1
  31. package/src/features/moderate-recent/__tests__/RecentDocumentsPage.test.tsx +3 -5
  32. package/src/features/moderate-recent/components/RecentDocumentsPage.tsx +0 -3
  33. package/src/features/moderate-tag-schemas/__tests__/TagSchemasPage.test.tsx +3 -5
  34. package/src/features/moderate-tag-schemas/components/TagSchemasPage.tsx +0 -3
  35. package/src/features/moderation-linked-data/__tests__/LinkedDataPage.test.tsx +0 -1
  36. package/src/features/moderation-linked-data/components/LinkedDataPage.tsx +0 -3
  37. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +17 -7
  38. package/src/features/resource-compose/components/ResourceComposePage.tsx +5 -3
  39. package/src/features/resource-compose/state/__tests__/compose-page-state-unit.test.ts +1 -1
  40. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +0 -1
  41. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +0 -3
  42. package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +1 -1
  43. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +8 -5
  44. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +3 -10
  45. package/src/features/resource-viewer/state/__tests__/resource-loader-state-unit.test.ts +1 -1
  46. package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +1 -1
  47. package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +2 -2
  48. package/dist/chunk-RO5CRVIA.js.map +0 -1
@@ -10,12 +10,14 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
10
10
  import { ResourceComposePage } from '../components/ResourceComposePage';
11
11
  import type { ResourceComposePageProps } from '../components/ResourceComposePage';
12
12
  import { createTestSemiontWrapper } from '../../../test-utils';
13
+ import { LineNumbersProvider } from '../../../contexts/LineNumbersContext';
13
14
 
14
15
  // Mock CodeMirrorRenderer to avoid CodeMirror dependencies
15
16
  vi.mock('../../../components/CodeMirrorRenderer', () => ({
16
- CodeMirrorRenderer: ({ content, onChange, editable }: any) => (
17
+ CodeMirrorRenderer: ({ content, onChange, editable, showLineNumbers }: any) => (
17
18
  <textarea
18
19
  data-testid="code-editor"
20
+ data-line-numbers={String(showLineNumbers)}
19
21
  value={content}
20
22
  onChange={(e) => editable && onChange?.(e.target.value)}
21
23
  disabled={!editable}
@@ -62,7 +64,6 @@ const createMockProps = (overrides?: Partial<ResourceComposePageProps>): Resourc
62
64
  availableEntityTypes: ['Document', 'Article', 'Report'],
63
65
  initialLocale: 'en',
64
66
  theme: 'light',
65
- showLineNumbers: false,
66
67
  hoverDelayMs: 0,
67
68
  activePanel: null,
68
69
  onSaveResource: vi.fn().mockResolvedValue(undefined),
@@ -77,7 +78,11 @@ const createMockProps = (overrides?: Partial<ResourceComposePageProps>): Resourc
77
78
  // component reaches for via useSemiont/useObservable).
78
79
  const renderWithProviders = (ui: React.ReactElement) => {
79
80
  const { SemiontWrapper } = createTestSemiontWrapper();
80
- return render(<SemiontWrapper>{ui}</SemiontWrapper>);
81
+ return render(
82
+ <LineNumbersProvider>
83
+ <SemiontWrapper>{ui}</SemiontWrapper>
84
+ </LineNumbersProvider>,
85
+ );
81
86
  };
82
87
 
83
88
  describe('ResourceComposePage', () => {
@@ -500,11 +505,16 @@ describe('ResourceComposePage', () => {
500
505
  expect(editor.value).toBe('New content');
501
506
  });
502
507
 
503
- it('respects showLineNumbers prop', () => {
504
- const props = createMockProps({ showLineNumbers: true });
505
- renderWithProviders(<ResourceComposePage {...props} />);
508
+ it('feeds the editor the shared line-numbers setting from context', () => {
509
+ localStorage.setItem('showLineNumbers', 'true');
510
+ try {
511
+ const props = createMockProps({});
512
+ renderWithProviders(<ResourceComposePage {...props} />);
506
513
 
507
- expect(screen.getByTestId('code-editor')).toBeInTheDocument();
514
+ expect(screen.getByTestId('code-editor')).toHaveAttribute('data-line-numbers', 'true');
515
+ } finally {
516
+ localStorage.removeItem('showLineNumbers');
517
+ }
508
518
  });
509
519
  });
510
520
  });
@@ -15,6 +15,7 @@ import { COMMON_PANELS, type ToolbarPanelType } from '../../../state/shell-state
15
15
  import { buttonStyles } from '../../../lib/button-styles';
16
16
  import { CodeMirrorRenderer } from '../../../components/CodeMirrorRenderer';
17
17
  import { useFormAnnouncements } from '../../../components/LiveRegion';
18
+ import { useLineNumbers } from '../../../contexts/LineNumbersContext';
18
19
  import { UploadProgressBar } from './UploadProgressBar';
19
20
 
20
21
  /**
@@ -54,7 +55,6 @@ export interface ResourceComposePageProps {
54
55
 
55
56
  // UI state
56
57
  theme: 'light' | 'dark';
57
- showLineNumbers: boolean;
58
58
  hoverDelayMs: number;
59
59
  activePanel: string | null;
60
60
 
@@ -133,7 +133,6 @@ export function ResourceComposePage({
133
133
  availableEntityTypes,
134
134
  initialLocale,
135
135
  theme,
136
- showLineNumbers,
137
136
  hoverDelayMs,
138
137
  activePanel,
139
138
  onSaveResource,
@@ -146,6 +145,10 @@ export function ResourceComposePage({
146
145
  // Form announcements
147
146
  const { announceFormSubmitting, announceFormSuccess, announceFormError } = useFormAnnouncements();
148
147
 
148
+ // Shared display setting (LineNumbersContext) — was a prop threaded from
149
+ // the route, which desynced it from the Settings toggle.
150
+ const { showLineNumbers } = useLineNumbers();
151
+
149
152
  // Form state
150
153
  const [newResourceName, setNewResourceName] = useState('');
151
154
  const [newResourceContent, setNewResourceContent] = useState('');
@@ -746,7 +749,6 @@ export function ResourceComposePage({
746
749
  <ToolbarPanels
747
750
  activePanel={activePanel}
748
751
  theme={theme}
749
- showLineNumbers={showLineNumbers}
750
752
  />
751
753
 
752
754
  {/* Toolbar - Always visible on the right */}
@@ -6,7 +6,7 @@ import { filter } from 'rxjs/operators';
6
6
  import type { SemiontClient } from '@semiont/sdk';
7
7
  import type { ShellStateUnit } from '../../../../state/shell-state-unit';
8
8
  import { createComposePageStateUnit } from '../compose-page-state-unit';
9
- import { assertStateUnitAxioms, disposeProbe } from '@semiont/core/testing';
9
+ import { assertStateUnitAxioms, disposeProbe } from '@semiont/core/testing/axioms';
10
10
 
11
11
  /** Build an `UploadObservable`-shaped mock that emits started → finished. */
12
12
  function mockUpload(resourceId: string) {
@@ -36,7 +36,6 @@ const createMockProps = (overrides?: Partial<ResourceDiscoveryPageProps>): Resou
36
36
  selectedEntityType: '',
37
37
  onSelectedEntityTypeChange: vi.fn(),
38
38
  theme: 'light',
39
- showLineNumbers: false,
40
39
  activePanel: null,
41
40
  onNavigateToResource: vi.fn(),
42
41
  onNavigateToCompose: vi.fn(),
@@ -40,7 +40,6 @@ export interface ResourceDiscoveryPageProps {
40
40
 
41
41
  // UI state props
42
42
  theme: 'light' | 'dark';
43
- showLineNumbers: boolean;
44
43
  activePanel: string | null;
45
44
 
46
45
  // Navigation props
@@ -86,7 +85,6 @@ export function ResourceDiscoveryPage({
86
85
  selectedEntityType,
87
86
  onSelectedEntityTypeChange,
88
87
  theme,
89
- showLineNumbers,
90
88
  activePanel,
91
89
  onNavigateToResource,
92
90
  onNavigateToCompose,
@@ -286,7 +284,6 @@ export function ResourceDiscoveryPage({
286
284
  <ToolbarPanels
287
285
  activePanel={activePanel}
288
286
  theme={theme}
289
- showLineNumbers={showLineNumbers}
290
287
  />
291
288
 
292
289
  {/* Toolbar - Always visible on the right */}
@@ -6,7 +6,7 @@ import { filter, skip, take, toArray } from 'rxjs/operators';
6
6
  import type { SemiontClient } from '@semiont/sdk';
7
7
  import type { ShellStateUnit } from '../../../../state/shell-state-unit';
8
8
  import { createDiscoverStateUnit } from '../discover-state-unit';
9
- import { assertStateUnitAxioms, disposeProbe } from '@semiont/core/testing';
9
+ import { assertStateUnitAxioms, disposeProbe } from '@semiont/core/testing/axioms';
10
10
 
11
11
  function mockBrowse(): ShellStateUnit {
12
12
  return { dispose: vi.fn() } as unknown as ShellStateUnit;
@@ -12,6 +12,7 @@ import { ResourceViewerPage } from '../components/ResourceViewerPage';
12
12
  import type { ResourceViewerPageProps } from '../components/ResourceViewerPage';
13
13
  import { ToastProvider } from '../../../components/Toast';
14
14
  import { ThemeProvider } from '../../../contexts/ThemeContext';
15
+ import { LineNumbersProvider } from '../../../contexts/LineNumbersContext';
15
16
  import { createTestSemiontWrapper } from '../../../test-utils';
16
17
  import type { ResourceId } from '@semiont/core';
17
18
 
@@ -163,11 +164,13 @@ const renderWithProviders = (ui: React.ReactElement) => {
163
164
  const { SemiontWrapper } = createTestSemiontWrapper();
164
165
  return render(
165
166
  <ThemeProvider>
166
- <ToastProvider>
167
- <SemiontWrapper>
168
- {ui}
169
- </SemiontWrapper>
170
- </ToastProvider>
167
+ <LineNumbersProvider>
168
+ <ToastProvider>
169
+ <SemiontWrapper>
170
+ {ui}
171
+ </SemiontWrapper>
172
+ </ToastProvider>
173
+ </LineNumbersProvider>
171
174
  </ThemeProvider>
172
175
  );
173
176
  };
@@ -27,7 +27,7 @@ import { useMediaToken } from '../../../hooks/useMediaToken';
27
27
  import { useToast } from '../../../components/Toast';
28
28
  import { useOutcomeToasts } from '../../../hooks/useOutcomeToasts';
29
29
  import { useTheme } from '../../../contexts/ThemeContext';
30
- import { useLineNumbers } from '../../../hooks/useLineNumbers';
30
+ import { useLineNumbers } from '../../../contexts/LineNumbersContext';
31
31
  import { useHoverDelay } from '../../../hooks/useHoverDelay';
32
32
  import { useEventSubscriptions } from '../../../contexts/useEventSubscription';
33
33
  import { useObservableExternalNavigation } from '../../../hooks/useObservableBrowse';
@@ -116,8 +116,6 @@ export interface ResourceViewerPageProps {
116
116
  * @subscribes yield:clone - Clone the current resource
117
117
  * @subscribes beckon:sparkle - Trigger sparkle animation
118
118
  * @subscribes mark:added - Annotation was created (sparkle)
119
- * @subscribes settings:theme-changed - UI theme changed
120
- * @subscribes settings:line-numbers-toggled - Line numbers display toggled
121
119
  * @subscribes browse:reference-navigate - Navigate to a referenced document
122
120
  * @subscribes browse:entity-type-clicked - Navigate filtered by entity type
123
121
  *
@@ -159,8 +157,8 @@ export function ResourceViewerPage({
159
157
 
160
158
  // UI state hooks
161
159
  const { showError, showSuccess } = useToast();
162
- const { theme, setTheme } = useTheme();
163
- const { showLineNumbers, toggleLineNumbers } = useLineNumbers();
160
+ const { theme } = useTheme();
161
+ const { showLineNumbers } = useLineNumbers();
164
162
  const { hoverDelayMs } = useHoverDelay();
165
163
  const { triggerSparkleAnimation, clearNewAnnotationId, newAnnotationIds } = useResourceAnnotations();
166
164
 
@@ -380,8 +378,6 @@ export function ResourceViewerPage({
380
378
  triggerSparkleAnimation(stored.payload.annotation.id);
381
379
  }, [triggerSparkleAnimation]);
382
380
 
383
- const handleSettingsThemeChanged = useCallback(({ theme }: { theme: any }) => setTheme(theme), [setTheme]);
384
-
385
381
  const handleReferenceNavigate = useCallback(({ resourceId }: { resourceId: string }) => {
386
382
  if (routes.resourceDetail) {
387
383
  const path = routes.resourceDetail(resourceId);
@@ -411,8 +407,6 @@ export function ResourceViewerPage({
411
407
  'yield:clone': handleResourceClone,
412
408
  'beckon:sparkle': handleAnnotationSparkle,
413
409
  'mark:added': handleAnnotationAdded,
414
- 'settings:theme-changed': handleSettingsThemeChanged,
415
- 'settings:line-numbers-toggled': toggleLineNumbers,
416
410
  'browse:reference-navigate': handleReferenceNavigate,
417
411
  'browse:entity-type-clicked': handleEntityTypeClicked,
418
412
  });
@@ -542,7 +536,6 @@ export function ResourceViewerPage({
542
536
  <ToolbarPanels
543
537
  activePanel={activePanel}
544
538
  theme={theme}
545
- showLineNumbers={showLineNumbers}
546
539
  width={
547
540
  activePanel === 'jsonld' ? 'w-[600px]' :
548
541
  activePanel === 'annotations' ? 'w-[400px]' :
@@ -6,7 +6,7 @@ import { filter } from 'rxjs/operators';
6
6
  import { resourceId as makeResourceId } from '@semiont/core';
7
7
  import type { SemiontClient } from '@semiont/sdk';
8
8
  import { createResourceLoaderStateUnit } from '../resource-loader-state-unit';
9
- import { assertStateUnitAxioms } from '@semiont/core/testing';
9
+ import { assertStateUnitAxioms } from '@semiont/core/testing/axioms';
10
10
 
11
11
  const RID = makeResourceId('res-1');
12
12
 
@@ -5,7 +5,7 @@ import { filter } from 'rxjs/operators';
5
5
  import { annotationId, resourceId as makeResourceId } from '@semiont/core';
6
6
  import type { ShellStateUnit } from '../../../../state/shell-state-unit';
7
7
  import { createResourceViewerPageStateUnit, type ResourceViewerPageStateUnit } from '../resource-viewer-page-state-unit';
8
- import { assertStateUnitAxioms, disposeProbe } from '@semiont/core/testing';
8
+ import { assertStateUnitAxioms, disposeProbe } from '@semiont/core/testing/axioms';
9
9
  import { makeTestSession, type TestSession } from '../../../../__tests__/test-client';
10
10
 
11
11
  const RID = makeResourceId('res-1');
@@ -10,7 +10,7 @@ import { createGatherStateUnit, type GatherStateUnit } from '@semiont/sdk';
10
10
  import { createMatchStateUnit } from '@semiont/sdk';
11
11
  import { createYieldStateUnit, type YieldStateUnit } from '@semiont/sdk';
12
12
  import type { SemiontSession } from '@semiont/sdk';
13
- import { decodeWithCharset, textExtractionOf } from '@semiont/core';
13
+ import { decodeWithCharset, textExtractionOf, uuidV4 } from '@semiont/core';
14
14
  import { groupAnnotations } from '../../../lib/annotation-groups';
15
15
  import type { ReferencedByEntry } from '@semiont/sdk';
16
16
 
@@ -144,7 +144,7 @@ export function createResourceViewerPageStateUnit(
144
144
  entityTypes: event.entityTypes,
145
145
  });
146
146
  client.bus.get('gather:requested').next({
147
- correlationId: crypto.randomUUID(),
147
+ correlationId: uuidV4(),
148
148
  annotationId: event.annotationId,
149
149
  resourceId: event.resourceId,
150
150
  options: { contextWindow: 2000 },