@semiont/react-ui 0.5.26 → 0.5.28
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.
- package/README.md +28 -4
- package/dist/{PdfAnnotationCanvas.client-6ZSF6ZTJ.js → PdfAnnotationCanvas.client-C2IGG4SW.js} +33 -6
- package/dist/{PdfAnnotationCanvas.client-JCJMXWWJ.css → PdfAnnotationCanvas.client-TGDPPGXJ.css} +6 -1
- package/dist/{ar-YTUUGK2O.js → ar-FABPTJVB.js} +88 -26
- package/dist/{bn-ASGNGPMD.js → bn-LKP6BDMH.js} +88 -26
- package/dist/{chunk-L3WKRWP3.js → chunk-2GOHTTHW.js} +88 -26
- package/dist/{chunk-OBQOZCJE.js → chunk-2YHEE63S.js} +31 -31
- package/dist/{cs-WMYVAOZY.js → cs-YQYNWHRG.js} +88 -26
- package/dist/{da-FSHHN4D6.js → da-QHZOYKRY.js} +88 -26
- package/dist/{de-FJFO3TPT.js → de-GKA7RD7J.js} +88 -26
- package/dist/{el-XOH4QIAG.js → el-45T257AL.js} +88 -26
- package/dist/{en-3FCBW3YD.js → en-RVW5EQ66.js} +4 -2
- package/dist/{es-HDX4QI7E.js → es-AVER7RU4.js} +88 -26
- package/dist/{fa-DJ6WTFTJ.js → fa-K3VPK3O2.js} +88 -26
- package/dist/{fi-4S7H7W7U.js → fi-5NEKF7EB.js} +88 -26
- package/dist/{fr-6UJSYHXC.js → fr-FUMNDLBZ.js} +88 -26
- package/dist/{he-ZZJOHJX2.js → he-3JGNA3PR.js} +88 -26
- package/dist/{hi-HZJTAW7U.js → hi-IJY375DF.js} +88 -26
- package/dist/{id-E3I6ILEM.js → id-LWHKJ7ZD.js} +88 -26
- package/dist/index.css +380 -524
- package/dist/index.d.ts +318 -192
- package/dist/index.js +2960 -2421
- package/dist/integrations/css-modules-helper.js +1 -3
- package/dist/{it-ULAPAD7U.js → it-EBVOV4RW.js} +88 -26
- package/dist/{ja-SAHZQ4CZ.js → ja-KWRIX2NF.js} +88 -26
- package/dist/{ko-DFU2ADQ4.js → ko-L5CJMFDS.js} +88 -26
- package/dist/{ms-NWL76XNT.js → ms-LSNMJDR2.js} +88 -26
- package/dist/{nl-ATCM76WN.js → nl-ZB32MB7U.js} +88 -26
- package/dist/{no-UIAQ5RJF.js → no-4GTNY7M5.js} +88 -26
- package/dist/{pl-NOECQDXD.js → pl-LUHBLTHB.js} +88 -26
- package/dist/{pt-SVWIIUPC.js → pt-C4H3UNQ6.js} +88 -26
- package/dist/{ro-NR2DRTZG.js → ro-GGITS5V4.js} +88 -26
- package/dist/{sv-STVJ37JP.js → sv-T56RTLBP.js} +88 -26
- package/dist/test-utils.css +1 -1
- package/dist/test-utils.d.ts +1 -1
- package/dist/test-utils.js +2 -2
- package/dist/{th-UWQR4K54.js → th-22X2IWCB.js} +88 -26
- package/dist/{tr-WNXZSD27.js → tr-77TFG62H.js} +88 -26
- package/dist/{uk-SJRMB47Y.js → uk-MIIL6NXT.js} +88 -26
- package/dist/{vi-TMRQFES2.js → vi-7JYOIGNV.js} +88 -26
- package/dist/{zh-QOL3LYEM.js → zh-ID6DRYU4.js} +88 -26
- package/package.json +11 -10
- package/src/components/AssistProgress.tsx +178 -134
- package/src/components/CodeMirrorRenderer.tsx +8 -8
- package/src/components/{EntityFoundLog.tsx → ItemFoundLog.tsx} +12 -7
- package/src/components/ProtectedErrorBoundary.css +3 -1
- package/src/components/StatusDisplay.css +1 -1
- package/src/components/Toast.css +3 -1
- package/src/components/__tests__/AssistProgress.test.tsx +268 -141
- package/src/components/annotation/annotation-entries.css +0 -4
- package/src/components/annotation/references.css +0 -4
- package/src/components/image-annotation/AnnotationOverlay.tsx +6 -6
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +1 -1
- package/src/components/image-annotation/__tests__/AnnotationOverlay.click.test.tsx +7 -9
- package/src/components/image-annotation/__tests__/SvgDrawingCanvas.click.test.tsx +1 -2
- package/src/components/layout/Header.css +0 -4
- package/src/components/layout/LeftSidebar.css +0 -4
- package/src/components/modals/ComposeStep.tsx +218 -0
- package/src/components/modals/ConfigureGatherStep.tsx +10 -18
- package/src/components/modals/ConfigureGenerationStep.tsx +131 -54
- package/src/components/modals/ConfigureSearchStep.tsx +42 -40
- package/src/components/modals/ContextSummary.tsx +185 -72
- package/src/components/modals/CorpusPane.tsx +75 -0
- package/src/components/modals/DiscardPrompt.tsx +38 -0
- package/src/components/modals/GatherContextStep.tsx +237 -107
- package/src/components/modals/ReferenceWizardModal.tsx +287 -60
- package/src/components/modals/ResourceGenerateModal.tsx +233 -109
- package/src/components/modals/SearchModal.css +335 -111
- package/src/components/modals/SearchModal.tsx +1 -1
- package/src/components/modals/SearchResultsStep.tsx +63 -88
- package/src/components/modals/WizardFooter.tsx +69 -0
- package/src/components/modals/__tests__/ComposeStep.test.tsx +152 -0
- package/src/components/modals/__tests__/ConfigureGatherStep.test.tsx +14 -26
- package/src/components/modals/__tests__/ConfigureGenerationStep.test.tsx +290 -0
- package/src/components/modals/__tests__/ConfigureSearchStep.test.tsx +95 -0
- package/src/components/modals/__tests__/GatherContextStep.resource.test.tsx +463 -25
- package/src/components/modals/__tests__/ReferenceWizardModal.test.tsx +635 -0
- package/src/components/modals/__tests__/ResourceGenerateModal.test.tsx +277 -85
- package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +6 -2
- package/src/components/modals/__tests__/SearchResultsStep.test.tsx +61 -0
- package/src/components/modals/__tests__/WizardFooter.test.tsx +344 -0
- package/src/components/modals/modals.css +16 -42
- package/src/components/navigation/NavigationTabs.css +0 -20
- package/src/components/pdf-annotation/PdfAnnotationCanvas.css +21 -2
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +36 -3
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +41 -6
- package/src/components/resource/AnnotateView.tsx +19 -8
- package/src/components/resource/AnnotationHistory.tsx +2 -0
- package/src/components/resource/BrowseView.tsx +20 -9
- package/src/components/resource/ResourceViewer.tsx +27 -28
- package/src/components/resource/__tests__/AnnotateView.embeddable.test.tsx +1 -1
- package/src/components/resource/__tests__/AnnotateView.focus.test.tsx +50 -0
- package/src/components/resource/__tests__/AnnotationHistory.test.tsx +2 -0
- package/src/components/resource/__tests__/BrowseView.embeddable.test.tsx +1 -1
- package/src/components/resource/__tests__/BrowseView.test.tsx +38 -12
- package/src/components/resource/__tests__/ResourceViewer.embeddable.test.tsx +47 -3
- package/src/components/resource/annotate-renderers.tsx +3 -3
- package/src/components/resource/event-formatting.ts +0 -3
- package/src/components/resource/panels/AssessmentEntry.tsx +1 -1
- package/src/components/resource/panels/AssessmentPanel.css +5 -6
- package/src/components/resource/panels/AssistSection.css +95 -263
- package/src/components/resource/panels/AssistSection.tsx +4 -4
- package/src/components/resource/panels/AssistShell.tsx +12 -4
- package/src/components/resource/panels/CollaborationPanel.css +47 -22
- package/src/components/resource/panels/CollaborationPanel.tsx +93 -2
- package/src/components/resource/panels/CommentEntry.tsx +1 -1
- package/src/components/resource/panels/CommentsPanel.css +0 -16
- package/src/components/resource/panels/HighlightEntry.tsx +1 -1
- package/src/components/resource/panels/HighlightPanel.css +0 -7
- package/src/components/resource/panels/JsonLdPanel.css +0 -4
- package/src/components/resource/panels/ReferenceEntry.tsx +10 -3
- package/src/components/resource/panels/ReferencesPanel.css +0 -12
- package/src/components/resource/panels/ReferencesPanel.tsx +16 -20
- package/src/components/resource/panels/ResourceInfoPanel.css +0 -32
- package/src/components/resource/panels/ResourceInfoPanel.tsx +89 -20
- package/src/components/resource/panels/StatisticsPanel.css +0 -20
- package/src/components/resource/panels/TagEntry.tsx +1 -1
- package/src/components/resource/panels/TaggingPanel.css +0 -4
- package/src/components/resource/panels/TaggingPanel.tsx +2 -10
- package/src/components/resource/panels/UnifiedAnnotationsPanel.css +0 -4
- package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +7 -2
- package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +0 -1
- package/src/components/resource/panels/__tests__/AssistSection.test.tsx +48 -50
- package/src/components/resource/panels/__tests__/AssistShell.test.tsx +11 -6
- package/src/components/resource/panels/__tests__/CollaborationPanel.test.tsx +89 -0
- package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +1 -2
- package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +0 -1
- package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +44 -36
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +41 -1
- package/src/components/resource/panels/__tests__/ReferencesPanel.headless.test.tsx +1 -1
- package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +67 -54
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +185 -7
- package/src/components/resource/panels/__tests__/TagEntry.test.tsx +0 -1
- package/src/components/settings/SettingsPanel.css +0 -4
- package/src/features/auth/auth.css +2 -26
- package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +0 -65
- package/src/features/resource-compose/components/ResourceComposePage.tsx +17 -130
- package/src/features/resource-compose/state/__tests__/compose-page-state-unit.test.ts +1 -76
- package/src/features/resource-compose/state/compose-page-state-unit.ts +5 -48
- package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +55 -0
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +29 -0
- package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +53 -3
- package/src/features/resource-discovery/state/discover-state-unit.ts +29 -8
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +71 -15
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +166 -71
- package/src/features/resource-viewer/hooks/__tests__/useResourceViewedReport.test.tsx +63 -0
- package/src/features/resource-viewer/hooks/useResourceViewedReport.ts +33 -0
- package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +2 -2
- package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +1 -1
- package/src/styles/core/buttons.css +3 -1
- package/src/styles/core/forms.css +35 -29
- package/src/styles/core/indicators.css +0 -4
- package/src/styles/core/inputs.css +0 -4
- package/src/styles/core/progress.css +2 -34
- package/src/styles/core/sliders.css +0 -4
- package/src/styles/core/toggles.css +0 -4
- package/src/styles/features/resource-discovery.css +13 -0
- package/src/styles/features/resource-viewer.css +0 -42
- package/src/styles/features/resource.css +0 -4
- package/src/styles/motivations/motivation-assessment.css +2 -2
- package/src/styles/panels/history-panel.css +0 -40
- package/src/styles/panels/user-panel.css +0 -3
- package/src/styles/patterns/panel-helpers.css +0 -27
- package/src/styles/patterns/panel-sections.css +0 -59
- package/src/styles/patterns/panels-base.css +0 -32
- package/translations/ar.json +84 -24
- package/translations/bn.json +84 -24
- package/translations/cs.json +84 -24
- package/translations/da.json +84 -24
- package/translations/de.json +84 -24
- package/translations/el.json +84 -24
- package/translations/en.json +84 -24
- package/translations/es.json +84 -24
- package/translations/fa.json +84 -24
- package/translations/fi.json +84 -24
- package/translations/fr.json +84 -24
- package/translations/he.json +84 -24
- package/translations/hi.json +84 -24
- package/translations/id.json +84 -24
- package/translations/it.json +84 -24
- package/translations/ja.json +84 -24
- package/translations/ko.json +84 -24
- package/translations/ms.json +84 -24
- package/translations/nl.json +84 -24
- package/translations/no.json +84 -24
- package/translations/pl.json +84 -24
- package/translations/pt.json +84 -24
- package/translations/ro.json +84 -24
- package/translations/sv.json +84 -24
- package/translations/th.json +84 -24
- package/translations/tr.json +84 -24
- package/translations/uk.json +84 -24
- package/translations/vi.json +84 -24
- package/translations/zh.json +84 -24
- package/dist/PdfAnnotationCanvas.client-6ZSF6ZTJ.js.map +0 -1
- package/dist/PdfAnnotationCanvas.client-JCJMXWWJ.css.map +0 -1
- package/dist/ar-YTUUGK2O.js.map +0 -1
- package/dist/bn-ASGNGPMD.js.map +0 -1
- package/dist/chunk-BTUG3VJJ.js.map +0 -1
- package/dist/chunk-L3WKRWP3.js.map +0 -1
- package/dist/chunk-O23TLLXW.js.map +0 -1
- package/dist/chunk-OBQOZCJE.js.map +0 -1
- package/dist/chunk-QT7LYM72.js.map +0 -1
- package/dist/chunk-VXASXU4K.js.map +0 -1
- package/dist/chunk-XUDKYAVC.js +0 -21
- package/dist/chunk-XUDKYAVC.js.map +0 -1
- package/dist/cs-WMYVAOZY.js.map +0 -1
- package/dist/da-FSHHN4D6.js.map +0 -1
- package/dist/de-FJFO3TPT.js.map +0 -1
- package/dist/el-XOH4QIAG.js.map +0 -1
- package/dist/en-3FCBW3YD.js.map +0 -1
- package/dist/es-HDX4QI7E.js.map +0 -1
- package/dist/fa-DJ6WTFTJ.js.map +0 -1
- package/dist/fi-4S7H7W7U.js.map +0 -1
- package/dist/fr-6UJSYHXC.js.map +0 -1
- package/dist/he-ZZJOHJX2.js.map +0 -1
- package/dist/hi-HZJTAW7U.js.map +0 -1
- package/dist/id-E3I6ILEM.js.map +0 -1
- package/dist/index.css.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/integrations/css-modules-helper.js.map +0 -1
- package/dist/integrations/styled-components-theme.js.map +0 -1
- package/dist/it-ULAPAD7U.js.map +0 -1
- package/dist/ja-SAHZQ4CZ.js.map +0 -1
- package/dist/ko-DFU2ADQ4.js.map +0 -1
- package/dist/ms-NWL76XNT.js.map +0 -1
- package/dist/nl-ATCM76WN.js.map +0 -1
- package/dist/no-UIAQ5RJF.js.map +0 -1
- package/dist/pl-NOECQDXD.js.map +0 -1
- package/dist/pt-SVWIIUPC.js.map +0 -1
- package/dist/ro-NR2DRTZG.js.map +0 -1
- package/dist/sv-STVJ37JP.js.map +0 -1
- package/dist/test-utils.css.map +0 -1
- package/dist/test-utils.js.map +0 -1
- package/dist/th-UWQR4K54.js.map +0 -1
- package/dist/tr-WNXZSD27.js.map +0 -1
- package/dist/uk-SJRMB47Y.js.map +0 -1
- package/dist/vi-TMRQFES2.js.map +0 -1
- package/dist/zh-QOL3LYEM.js.map +0 -1
- package/src/components/modals/ResourceSearchModal.tsx +0 -224
- package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +0 -159
- package/src/integrations/tailwind-plugin.cjs +0 -224
|
@@ -57,10 +57,6 @@
|
|
|
57
57
|
color: var(--semiont-text-secondary);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
[data-theme="dark"] .semiont-statistics-panel__label {
|
|
61
|
-
color: var(--semiont-text-secondary);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
60
|
.semiont-statistics-panel__value {
|
|
65
61
|
font-size: var(--semiont-text-lg);
|
|
66
62
|
font-weight: var(--semiont-font-semibold);
|
|
@@ -68,10 +64,6 @@
|
|
|
68
64
|
margin-left: auto;
|
|
69
65
|
}
|
|
70
66
|
|
|
71
|
-
[data-theme="dark"] .semiont-statistics-panel__value {
|
|
72
|
-
color: var(--semiont-text-primary);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
67
|
/* Sub-items (indented) */
|
|
76
68
|
.semiont-statistics-panel__subitems {
|
|
77
69
|
width: 100%;
|
|
@@ -93,20 +85,12 @@
|
|
|
93
85
|
color: var(--semiont-text-tertiary);
|
|
94
86
|
}
|
|
95
87
|
|
|
96
|
-
[data-theme="dark"] .semiont-statistics-panel__sublabel {
|
|
97
|
-
color: var(--semiont-text-tertiary);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
88
|
.semiont-statistics-panel__subvalue {
|
|
101
89
|
font-size: var(--semiont-text-sm);
|
|
102
90
|
font-weight: var(--semiont-font-medium);
|
|
103
91
|
color: var(--semiont-text-secondary);
|
|
104
92
|
}
|
|
105
93
|
|
|
106
|
-
[data-theme="dark"] .semiont-statistics-panel__subvalue {
|
|
107
|
-
color: var(--semiont-text-secondary);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
94
|
/* Entity Types */
|
|
111
95
|
.semiont-statistics-panel__entity-types {
|
|
112
96
|
display: flex;
|
|
@@ -140,8 +124,4 @@
|
|
|
140
124
|
flex: 1;
|
|
141
125
|
}
|
|
142
126
|
|
|
143
|
-
[data-theme="dark"] .semiont-statistics-panel__entity-name {
|
|
144
|
-
color: var(--semiont-text-primary);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
127
|
/* Tags use .semiont-tag from core/tags.css */
|
|
@@ -52,7 +52,7 @@ export function TagEntry({
|
|
|
52
52
|
<div
|
|
53
53
|
ref={ref}
|
|
54
54
|
onClick={() => {
|
|
55
|
-
session?.client.browse.click(tag.id
|
|
55
|
+
session?.client.browse.click(tag.id);
|
|
56
56
|
}}
|
|
57
57
|
{...hoverProps}
|
|
58
58
|
className={`semiont-annotation-entry${isHovered ? ' semiont-annotation-pulse' : ''}`}
|
|
@@ -30,10 +30,6 @@
|
|
|
30
30
|
letter-spacing: 0.05em;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
[data-theme="dark"] .semiont-tagging-panel__label {
|
|
34
|
-
color: var(--semiont-text-secondary);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
33
|
.semiont-tagging-panel__input {
|
|
38
34
|
padding: var(--semiont-panel-padding-sm);
|
|
39
35
|
background: var(--semiont-bg-secondary);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useRef, useCallback, useMemo } from 'react';
|
|
4
|
+
import { assistProgressTranslations } from '../../../lib/assist-progress-copy';
|
|
4
5
|
import { isReady } from '@semiont/sdk';
|
|
5
6
|
import { useTranslations } from '../../../contexts/TranslationContext';
|
|
6
7
|
import { useObservable } from '../../../hooks/useObservable';
|
|
@@ -364,17 +365,8 @@ export function TaggingPanel({
|
|
|
364
365
|
isAssisting={isAssisting}
|
|
365
366
|
progress={progress}
|
|
366
367
|
progressProps={{
|
|
367
|
-
showPercentBar: true,
|
|
368
368
|
onDismiss: handleDismissProgress,
|
|
369
|
-
translations:
|
|
370
|
-
cancel: t('cancel'),
|
|
371
|
-
inProgress: t('annotating'),
|
|
372
|
-
complete: t('complete'),
|
|
373
|
-
failed: t('failed'),
|
|
374
|
-
paramsTitle: ta('paramsTitle'),
|
|
375
|
-
processing: (label) => ta('processing', { label }),
|
|
376
|
-
close: ta('close'),
|
|
377
|
-
},
|
|
369
|
+
translations: assistProgressTranslations(ta),
|
|
378
370
|
}}
|
|
379
371
|
form={
|
|
380
372
|
<>
|
|
@@ -6,7 +6,7 @@ import type { components, Selector } from '@semiont/core';
|
|
|
6
6
|
type JobProgress = components['schemas']['JobProgress'];
|
|
7
7
|
import type { RouteBuilder, LinkComponentProps } from '../../../contexts/RoutingContext';
|
|
8
8
|
import type { SemiontSession } from '@semiont/sdk';
|
|
9
|
-
import { annotatorKeyForMotivation, type Annotator } from '../../../lib/annotation-registry';
|
|
9
|
+
import { annotatorKeyForMotivation, type Annotator, type AnnotatorKey } from '../../../lib/annotation-registry';
|
|
10
10
|
import { StatisticsPanel } from './StatisticsPanel';
|
|
11
11
|
import { HighlightPanel } from './HighlightPanel';
|
|
12
12
|
import { ReferencesPanel } from './ReferencesPanel';
|
|
@@ -17,7 +17,9 @@ import './UnifiedAnnotationsPanel.css';
|
|
|
17
17
|
|
|
18
18
|
import type { Annotation } from '@semiont/core';
|
|
19
19
|
type Motivation = components['schemas']['Motivation'];
|
|
20
|
-
|
|
20
|
+
// Derived from the annotator registry (the single motivation↔annotator
|
|
21
|
+
// source) — a hand-written union here could drift from it.
|
|
22
|
+
type TabKey = 'statistics' | AnnotatorKey;
|
|
21
23
|
|
|
22
24
|
// Unified pending annotation type
|
|
23
25
|
interface PendingAnnotation {
|
|
@@ -76,6 +78,8 @@ interface UnifiedAnnotationsPanelProps {
|
|
|
76
78
|
entityTypesError?: Error | null;
|
|
77
79
|
referencedByError?: Error | null;
|
|
78
80
|
onRetryReferencedBy?: () => void;
|
|
81
|
+
/** Annotations currently sparkling (recently created or resolved) — RESOLUTION-SPARKLE D6. */
|
|
82
|
+
sparkleAnnotationIds?: Set<string>;
|
|
79
83
|
|
|
80
84
|
// Resource context — threaded to every per-motivation panel, which stamps it
|
|
81
85
|
// as `source` on mark:submit (multi-viewer routing).
|
|
@@ -328,6 +332,7 @@ export function UnifiedAnnotationsPanel(props: UnifiedAnnotationsPanelProps) {
|
|
|
328
332
|
referencedByLoading={props.referencedByLoading}
|
|
329
333
|
referencedByError={props.referencedByError}
|
|
330
334
|
onRetryReferencedBy={props.onRetryReferencedBy}
|
|
335
|
+
sparkleAnnotationIds={props.sparkleAnnotationIds}
|
|
331
336
|
Link={props.Link}
|
|
332
337
|
routes={props.routes}
|
|
333
338
|
/>
|
|
@@ -21,7 +21,7 @@ import type { SemiontSession } from '@semiont/sdk';
|
|
|
21
21
|
import { AssistSection } from '../AssistSection';
|
|
22
22
|
|
|
23
23
|
// Mock translations
|
|
24
|
-
const mockT = vi.fn((key: string) => {
|
|
24
|
+
const mockT = vi.fn((key: string, params?: Record<string, unknown>) => {
|
|
25
25
|
const translations: Record<string, string> = {
|
|
26
26
|
annotateHighlights: 'Annotate Highlights',
|
|
27
27
|
annotateAssessments: 'Annotate Assessments',
|
|
@@ -45,7 +45,29 @@ const mockT = vi.fn((key: string) => {
|
|
|
45
45
|
annotate: 'Annotate',
|
|
46
46
|
annotating: 'Annotating...',
|
|
47
47
|
};
|
|
48
|
-
|
|
48
|
+
// P3: the coded status line. Interpolates `{{var}}` like production —
|
|
49
|
+
// a mock that ignored params would let copy that cannot interpolate in the
|
|
50
|
+
// app still pass here.
|
|
51
|
+
Object.assign(translations, {
|
|
52
|
+
codeLoading: 'Loading…',
|
|
53
|
+
codeAnalyzing: 'Marking…',
|
|
54
|
+
codeDetectingEntities: 'Marking…',
|
|
55
|
+
codeCompleteCreated: 'Created {{count}} {{kind}}',
|
|
56
|
+
kindHighlight: 'highlights',
|
|
57
|
+
subject: '{{kind}}: {{label}}',
|
|
58
|
+
subjectWithPosition: '{{kind}}: {{label}} ({{done}} of {{total}})',
|
|
59
|
+
subjectKindEntityType: 'Entity type',
|
|
60
|
+
subjectKindCategory: 'Category',
|
|
61
|
+
// CLEAN-PROGRESS D3: the widget's own strings now come from the
|
|
62
|
+
// AssistProgress namespace, not from each panel's.
|
|
63
|
+
cancel: 'Cancel',
|
|
64
|
+
inProgress: 'Annotating...',
|
|
65
|
+
});
|
|
66
|
+
let out = translations[key] || key;
|
|
67
|
+
for (const [k, v] of Object.entries((params ?? {}) as Record<string, unknown>)) {
|
|
68
|
+
out = out.replace(`{{${k}}}`, String(v));
|
|
69
|
+
}
|
|
70
|
+
return out;
|
|
49
71
|
});
|
|
50
72
|
|
|
51
73
|
vi.mock('../../../../contexts/TranslationContext', () => ({
|
|
@@ -71,41 +93,37 @@ describe('AssistSection', () => {
|
|
|
71
93
|
});
|
|
72
94
|
|
|
73
95
|
describe('Progress Display', () => {
|
|
74
|
-
it('should render
|
|
96
|
+
it('should render the translated status line when progress prop provided', () => {
|
|
75
97
|
renderWithProviders(
|
|
76
98
|
<AssistSection
|
|
77
99
|
session={session}
|
|
78
100
|
annotationType="highlight"
|
|
79
101
|
isAssisting={true}
|
|
80
102
|
progress={{
|
|
81
|
-
stage: 'analyzing',
|
|
82
103
|
percentage: 30,
|
|
83
|
-
message: 'Analyzing text for highlights...',
|
|
84
104
|
}}
|
|
85
105
|
/>
|
|
86
106
|
);
|
|
87
107
|
|
|
88
|
-
expect(screen.getByText('
|
|
108
|
+
expect(screen.getByText('Annotating...')).toBeInTheDocument();
|
|
89
109
|
});
|
|
90
110
|
|
|
91
|
-
it('should render
|
|
111
|
+
it('should render the status line with sparkle icon', () => {
|
|
92
112
|
renderWithProviders(
|
|
93
113
|
<AssistSection
|
|
94
114
|
session={session}
|
|
95
115
|
annotationType="highlight"
|
|
96
116
|
isAssisting={true}
|
|
97
117
|
progress={{
|
|
98
|
-
stage: 'analyzing',
|
|
99
118
|
percentage: 0,
|
|
100
|
-
message: 'Processing...',
|
|
101
119
|
}}
|
|
102
120
|
/>
|
|
103
121
|
);
|
|
104
122
|
|
|
105
|
-
// Check for icon and
|
|
106
|
-
const progressDiv = screen.getByText('
|
|
123
|
+
// Check for icon and status text
|
|
124
|
+
const progressDiv = screen.getByText('Annotating...').closest('.semiont-assist-progress__status');
|
|
107
125
|
expect(progressDiv).toBeInTheDocument();
|
|
108
|
-
expect(progressDiv?.querySelector('.semiont-
|
|
126
|
+
expect(progressDiv?.querySelector('.semiont-assist-progress__icon')).toBeInTheDocument();
|
|
109
127
|
});
|
|
110
128
|
|
|
111
129
|
it('should render request parameters when provided', () => {
|
|
@@ -115,22 +133,25 @@ describe('AssistSection', () => {
|
|
|
115
133
|
annotationType="highlight"
|
|
116
134
|
isAssisting={true}
|
|
117
135
|
progress={{
|
|
118
|
-
stage: 'analyzing',
|
|
119
136
|
percentage: 0,
|
|
120
|
-
message: 'Analyzing...',
|
|
121
137
|
requestParams: [
|
|
122
|
-
{ label: '
|
|
123
|
-
{ label: '
|
|
138
|
+
{ label: 'instructions', value: 'Find important points' },
|
|
139
|
+
{ label: 'density', value: '5' },
|
|
124
140
|
],
|
|
125
141
|
}}
|
|
126
142
|
/>
|
|
127
143
|
);
|
|
128
144
|
|
|
129
|
-
expect(screen.
|
|
145
|
+
expect(screen.getByTestId('semiont-assist-params')).toBeInTheDocument();
|
|
130
146
|
expect(screen.getByText('Find important points')).toBeInTheDocument();
|
|
131
|
-
expect(screen.getByText(/Instructions:/)).toBeInTheDocument();
|
|
132
147
|
expect(screen.getByText('5')).toBeInTheDocument();
|
|
133
|
-
|
|
148
|
+
// The wire carries a CODE; the label the user reads is LOOKED UP. Under
|
|
149
|
+
// the test translator that lookup echoes the key, so seeing the key is
|
|
150
|
+
// the assertion that the label went through translation — and that the
|
|
151
|
+
// raw wire code ('instructions') never reaches the screen.
|
|
152
|
+
expect(screen.getByText(/paramInstructions:/)).toBeInTheDocument();
|
|
153
|
+
expect(screen.getByText(/paramDensity:/)).toBeInTheDocument();
|
|
154
|
+
expect(screen.queryByText(/^instructions:/)).toBeNull();
|
|
134
155
|
});
|
|
135
156
|
|
|
136
157
|
it('should hide form when progress is present', () => {
|
|
@@ -140,9 +161,7 @@ describe('AssistSection', () => {
|
|
|
140
161
|
annotationType="highlight"
|
|
141
162
|
isAssisting={true}
|
|
142
163
|
progress={{
|
|
143
|
-
stage: 'analyzing',
|
|
144
164
|
percentage: 0,
|
|
145
|
-
message: 'Analyzing...',
|
|
146
165
|
}}
|
|
147
166
|
/>
|
|
148
167
|
);
|
|
@@ -189,15 +208,14 @@ describe('AssistSection', () => {
|
|
|
189
208
|
annotationType="highlight"
|
|
190
209
|
isAssisting={false}
|
|
191
210
|
progress={{
|
|
192
|
-
|
|
211
|
+
message: { code: 'complete-created', count: 3, kind: 'highlight' },
|
|
193
212
|
percentage: 100,
|
|
194
|
-
message: 'Complete! Created 14 highlights',
|
|
195
213
|
}}
|
|
196
214
|
/>
|
|
197
215
|
);
|
|
198
216
|
|
|
199
|
-
// Progress should still be visible
|
|
200
|
-
expect(screen.getByText('
|
|
217
|
+
// Progress should still be visible, with the translated terminal copy
|
|
218
|
+
expect(screen.getByText('Created 3 highlights')).toBeInTheDocument();
|
|
201
219
|
// Form should NOT be visible
|
|
202
220
|
expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
|
|
203
221
|
});
|
|
@@ -455,42 +473,24 @@ describe('AssistSection', () => {
|
|
|
455
473
|
});
|
|
456
474
|
|
|
457
475
|
describe('Edge Cases', () => {
|
|
458
|
-
it('should handle
|
|
476
|
+
it('should handle progress without a message', () => {
|
|
459
477
|
renderWithProviders(
|
|
460
478
|
<AssistSection
|
|
461
479
|
session={session}
|
|
462
480
|
annotationType="highlight"
|
|
463
481
|
isAssisting={true}
|
|
464
482
|
progress={{
|
|
465
|
-
stage: 'analyzing',
|
|
466
483
|
percentage: 0,
|
|
467
|
-
message: '',
|
|
468
484
|
}}
|
|
469
485
|
/>
|
|
470
486
|
);
|
|
471
487
|
|
|
472
|
-
//
|
|
473
|
-
|
|
488
|
+
// Renders the progress section with the translated status line — the
|
|
489
|
+
// wire carries a code (or nothing), never a sentence to fall back on.
|
|
490
|
+
const progressDiv = document.querySelector('.semiont-assist-progress');
|
|
474
491
|
expect(progressDiv).toBeInTheDocument();
|
|
475
492
|
});
|
|
476
493
|
|
|
477
|
-
it('should handle progress without percentage', () => {
|
|
478
|
-
renderWithProviders(
|
|
479
|
-
<AssistSection
|
|
480
|
-
session={session}
|
|
481
|
-
annotationType="highlight"
|
|
482
|
-
isAssisting={true}
|
|
483
|
-
progress={{
|
|
484
|
-
stage: 'analyzing',
|
|
485
|
-
percentage: 0,
|
|
486
|
-
message: 'Processing...',
|
|
487
|
-
}}
|
|
488
|
-
/>
|
|
489
|
-
);
|
|
490
|
-
|
|
491
|
-
expect(screen.getByText('Processing...')).toBeInTheDocument();
|
|
492
|
-
});
|
|
493
|
-
|
|
494
494
|
it('should handle progress with empty requestParams array', () => {
|
|
495
495
|
renderWithProviders(
|
|
496
496
|
<AssistSection
|
|
@@ -498,15 +498,13 @@ describe('AssistSection', () => {
|
|
|
498
498
|
annotationType="highlight"
|
|
499
499
|
isAssisting={true}
|
|
500
500
|
progress={{
|
|
501
|
-
stage: 'analyzing',
|
|
502
501
|
percentage: 0,
|
|
503
|
-
message: 'Processing...',
|
|
504
502
|
requestParams: [],
|
|
505
503
|
}}
|
|
506
504
|
/>
|
|
507
505
|
);
|
|
508
506
|
|
|
509
|
-
expect(screen.
|
|
507
|
+
expect(screen.queryByTestId('semiont-assist-params')).not.toBeInTheDocument();
|
|
510
508
|
});
|
|
511
509
|
});
|
|
512
510
|
});
|
|
@@ -11,12 +11,17 @@ import userEvent from '@testing-library/user-event';
|
|
|
11
11
|
import '@testing-library/jest-dom';
|
|
12
12
|
import { AssistShell } from '../AssistShell';
|
|
13
13
|
|
|
14
|
-
const progress = {
|
|
14
|
+
const progress = { percentage: 50 };
|
|
15
15
|
|
|
16
16
|
/** AssistProgress requires a full translation set; the shell just passes it through. */
|
|
17
|
-
const TR = {
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
const TR = {
|
|
18
|
+
cancel: 'tr.cancel',
|
|
19
|
+
close: 'tr.close',
|
|
20
|
+
inProgress: 'tr.inProgress',
|
|
21
|
+
message: () => 'tr.code',
|
|
22
|
+
subject: (c: { kind: string; value: string }) => `tr.subject(${c.kind}:${c.value})`,
|
|
23
|
+
paramLabel: (c: string) => `tr.param(${c})`,
|
|
24
|
+
};
|
|
20
25
|
|
|
21
26
|
describe('AssistShell', () => {
|
|
22
27
|
beforeEach(() => {
|
|
@@ -34,13 +39,13 @@ describe('AssistShell', () => {
|
|
|
34
39
|
form={<button type="button">the form</button>} progressProps={{ translations: TR }} />,
|
|
35
40
|
);
|
|
36
41
|
expect(screen.queryByText('the form')).not.toBeInTheDocument();
|
|
37
|
-
expect(screen.getByText('
|
|
42
|
+
expect(screen.getByText('tr.inProgress')).toBeInTheDocument();
|
|
38
43
|
});
|
|
39
44
|
|
|
40
45
|
it('withholds dismiss while assisting, offers it once terminal', async () => {
|
|
41
46
|
const onDismiss = vi.fn();
|
|
42
47
|
const props = {
|
|
43
|
-
assistType: 'highlight', title: 'Annotate Highlights', progress,
|
|
48
|
+
assistType: 'highlight' as const, title: 'Annotate Highlights', progress,
|
|
44
49
|
form: <span>form</span>,
|
|
45
50
|
progressProps: { onDismiss, translations: { ...TR, close: 'Close' } },
|
|
46
51
|
};
|
|
@@ -23,12 +23,18 @@ vi.mock('../../../../contexts/TranslationContext', () => ({
|
|
|
23
23
|
reconnecting: 'Reconnecting...',
|
|
24
24
|
sharing: 'Sharing',
|
|
25
25
|
collaborationComingSoon: 'Multi-user collaboration coming soon',
|
|
26
|
+
collaborators: 'Collaborators',
|
|
27
|
+
ceilings: '{{contextTokens}} in / {{maxOutputTokens}} out',
|
|
28
|
+
sharedWindow: '{{contextTokens}} window',
|
|
26
29
|
};
|
|
27
30
|
let result = translations[key] || key;
|
|
28
31
|
// Replace {count} with actual count value if provided
|
|
29
32
|
if (params?.count !== undefined) {
|
|
30
33
|
result = result.replace('{count}', String(params.count));
|
|
31
34
|
}
|
|
35
|
+
for (const [k, v] of Object.entries(params ?? {})) {
|
|
36
|
+
result = result.replace(`{{${k}}}`, String(v));
|
|
37
|
+
}
|
|
32
38
|
return result;
|
|
33
39
|
}),
|
|
34
40
|
}));
|
|
@@ -52,6 +58,89 @@ describe('CollaborationPanel Component', () => {
|
|
|
52
58
|
vi.useRealTimers();
|
|
53
59
|
});
|
|
54
60
|
|
|
61
|
+
// INFERENCE-LIMITS-EXPOSURE P3a. The panel was props-only; it now optionally
|
|
62
|
+
// renders the collaborator roster with each software agent's discovered
|
|
63
|
+
// ceilings. Absence is meaningful and must degrade quietly (D3) — the field
|
|
64
|
+
// is absent whenever discovery could not answer *right now*.
|
|
65
|
+
describe('Collaborators roster', () => {
|
|
66
|
+
const softwareEntry = (over: Record<string, unknown> = {}) => ({
|
|
67
|
+
agent: {
|
|
68
|
+
'@type': 'Software' as const,
|
|
69
|
+
'@id': 'did:web:localhost:agents:anthropic:claude-sonnet-5',
|
|
70
|
+
name: 'Claude Sonnet 5',
|
|
71
|
+
provider: 'anthropic',
|
|
72
|
+
model: 'claude-sonnet-5',
|
|
73
|
+
},
|
|
74
|
+
servesJobTypes: ['generation'],
|
|
75
|
+
limits: { contextTokens: 200_000, maxOutputTokens: 64_000 },
|
|
76
|
+
...over,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('renders one row per software agent with provider, model and ceilings', () => {
|
|
80
|
+
render(<CollaborationPanel {...defaultProps} collaborators={[softwareEntry() as any]} />);
|
|
81
|
+
|
|
82
|
+
expect(screen.getByText('Collaborators')).toBeInTheDocument();
|
|
83
|
+
const row = screen.getByTestId('semiont-collaborator-row');
|
|
84
|
+
expect(row.textContent).toContain('anthropic');
|
|
85
|
+
expect(row.textContent).toContain('claude-sonnet-5');
|
|
86
|
+
expect(row.textContent).toContain('generation');
|
|
87
|
+
// Distinct in/out ceilings render as a pair.
|
|
88
|
+
expect(row.textContent).toContain('200K in / 64K out');
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('renders a single window figure when the provider shares one (Ollama shape)', () => {
|
|
92
|
+
// `maxOutputTokens === contextTokens` is the shared-window sentinel the
|
|
93
|
+
// schema documents; rendering "128K in / 128K out" would be noise.
|
|
94
|
+
const shared = softwareEntry({
|
|
95
|
+
agent: {
|
|
96
|
+
'@type': 'Software' as const,
|
|
97
|
+
name: 'Gemma',
|
|
98
|
+
provider: 'ollama',
|
|
99
|
+
model: 'gemma2:27b',
|
|
100
|
+
},
|
|
101
|
+
limits: { contextTokens: 128_000, maxOutputTokens: 128_000 },
|
|
102
|
+
});
|
|
103
|
+
render(<CollaborationPanel {...defaultProps} collaborators={[shared as any]} />);
|
|
104
|
+
|
|
105
|
+
const row = screen.getByTestId('semiont-collaborator-row');
|
|
106
|
+
expect(row.textContent).toContain('128K window');
|
|
107
|
+
expect(row.textContent).not.toContain('in /');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('renders the row without ceilings when limits are absent (D3)', () => {
|
|
111
|
+
const noLimits = softwareEntry();
|
|
112
|
+
delete (noLimits as Record<string, unknown>).limits;
|
|
113
|
+
render(<CollaborationPanel {...defaultProps} collaborators={[noLimits as any]} />);
|
|
114
|
+
|
|
115
|
+
const row = screen.getByTestId('semiont-collaborator-row');
|
|
116
|
+
expect(row.textContent).toContain('claude-sonnet-5');
|
|
117
|
+
expect(row.textContent).not.toContain('in /');
|
|
118
|
+
expect(row.textContent).not.toContain('window');
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('renders exactly as today when the prop is absent (hosts that never wire it)', () => {
|
|
122
|
+
render(<CollaborationPanel {...defaultProps} />);
|
|
123
|
+
|
|
124
|
+
expect(screen.queryByText('Collaborators')).not.toBeInTheDocument();
|
|
125
|
+
expect(screen.queryByTestId('semiont-collaborator-row')).not.toBeInTheDocument();
|
|
126
|
+
// The pre-existing sections are untouched.
|
|
127
|
+
expect(screen.getByText('Connection Status')).toBeInTheDocument();
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it('lists only software agents — Persons are not inference collaborators', () => {
|
|
131
|
+
const person = { agent: { '@type': 'Person' as const, name: 'Ada' } };
|
|
132
|
+
render(
|
|
133
|
+
<CollaborationPanel
|
|
134
|
+
{...defaultProps}
|
|
135
|
+
collaborators={[softwareEntry() as any, person as any]}
|
|
136
|
+
/>,
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(screen.getAllByTestId('semiont-collaborator-row')).toHaveLength(1);
|
|
140
|
+
expect(screen.queryByText('Ada')).not.toBeInTheDocument();
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
55
144
|
describe('Rendering', () => {
|
|
56
145
|
it('should render connection status section', () => {
|
|
57
146
|
render(<CollaborationPanel {...defaultProps} />);
|
|
@@ -264,8 +264,7 @@ describe('CommentEntry Component', () => {
|
|
|
264
264
|
await userEvent.click(commentDiv);
|
|
265
265
|
|
|
266
266
|
expect(clickHandler).toHaveBeenCalledWith({
|
|
267
|
-
annotationId: 'comment-1'
|
|
268
|
-
motivation: 'commenting'
|
|
267
|
+
annotationId: 'comment-1'
|
|
269
268
|
});
|
|
270
269
|
|
|
271
270
|
// Clean up
|