@semiont/react-ui 0.5.25 → 0.5.27

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 (267) hide show
  1. package/README.md +28 -4
  2. package/dist/PdfAnnotationCanvas.client-EVUPTUWZ.js +677 -0
  3. package/dist/PdfAnnotationCanvas.client-EVUPTUWZ.js.map +1 -0
  4. package/dist/PdfAnnotationCanvas.client-TGDPPGXJ.css +185 -0
  5. package/dist/PdfAnnotationCanvas.client-TGDPPGXJ.css.map +1 -0
  6. package/dist/{ar-CULRHLNG.js → ar-OU3DQGC6.js} +65 -7
  7. package/dist/ar-OU3DQGC6.js.map +1 -0
  8. package/dist/{bn-HYR7CEL2.js → bn-PHWCR6AZ.js} +65 -7
  9. package/dist/bn-PHWCR6AZ.js.map +1 -0
  10. package/dist/chunk-5VDTWRXJ.js +287 -0
  11. package/dist/chunk-5VDTWRXJ.js.map +1 -0
  12. package/dist/{chunk-TG2XQEC4.js → chunk-BTUG3VJJ.js} +18 -298
  13. package/dist/chunk-BTUG3VJJ.js.map +1 -0
  14. package/dist/{chunk-NH6L2GIL.js → chunk-PCRRBU7H.js} +65 -7
  15. package/dist/chunk-PCRRBU7H.js.map +1 -0
  16. package/dist/{cs-YBRWY7NH.js → cs-NEXYZ62I.js} +65 -7
  17. package/dist/cs-NEXYZ62I.js.map +1 -0
  18. package/dist/{da-PHDEOBV3.js → da-FAT43YCU.js} +65 -7
  19. package/dist/da-FAT43YCU.js.map +1 -0
  20. package/dist/{de-O4UCCVLJ.js → de-KRQ3WBCU.js} +65 -7
  21. package/dist/de-KRQ3WBCU.js.map +1 -0
  22. package/dist/{el-MVGO6WZV.js → el-Q4IU3EKC.js} +65 -7
  23. package/dist/el-Q4IU3EKC.js.map +1 -0
  24. package/dist/{en-2KQILFKQ.js → en-2KADE7N4.js} +6 -2
  25. package/dist/{es-USSLXQY7.js → es-2IO3R2MK.js} +65 -7
  26. package/dist/es-2IO3R2MK.js.map +1 -0
  27. package/dist/{fa-WMAREFWY.js → fa-Q5GOQFXX.js} +65 -7
  28. package/dist/fa-Q5GOQFXX.js.map +1 -0
  29. package/dist/{fi-B3NBNOTS.js → fi-R6NMRWBE.js} +65 -7
  30. package/dist/fi-R6NMRWBE.js.map +1 -0
  31. package/dist/{fr-TXYK5T5W.js → fr-QY4D5E6J.js} +65 -7
  32. package/dist/fr-QY4D5E6J.js.map +1 -0
  33. package/dist/{he-JCJACW5D.js → he-X6Y77XHY.js} +65 -7
  34. package/dist/he-X6Y77XHY.js.map +1 -0
  35. package/dist/{hi-VOQLZNJU.js → hi-XL7IOEQM.js} +65 -7
  36. package/dist/hi-XL7IOEQM.js.map +1 -0
  37. package/dist/{id-BFN5RZNZ.js → id-QZ4ZZS67.js} +65 -7
  38. package/dist/id-QZ4ZZS67.js.map +1 -0
  39. package/dist/index.css +241 -508
  40. package/dist/index.css.map +1 -1
  41. package/dist/index.d.ts +155 -54
  42. package/dist/index.js +1815 -1642
  43. package/dist/index.js.map +1 -1
  44. package/dist/integrations/css-modules-helper.js +1 -3
  45. package/dist/integrations/css-modules-helper.js.map +1 -1
  46. package/dist/{it-TWWDHKKM.js → it-ME2Q7OB6.js} +65 -7
  47. package/dist/it-ME2Q7OB6.js.map +1 -0
  48. package/dist/{ja-YRQLEBFM.js → ja-HX7QASRI.js} +65 -7
  49. package/dist/ja-HX7QASRI.js.map +1 -0
  50. package/dist/{ko-PG6B3CRB.js → ko-EQO5AHAV.js} +65 -7
  51. package/dist/ko-EQO5AHAV.js.map +1 -0
  52. package/dist/{ms-7EZECVKM.js → ms-UILFSF3I.js} +65 -7
  53. package/dist/ms-UILFSF3I.js.map +1 -0
  54. package/dist/{nl-HP753YAP.js → nl-NNI45PMK.js} +65 -7
  55. package/dist/nl-NNI45PMK.js.map +1 -0
  56. package/dist/{no-JUD5WX3N.js → no-MAL5F6P6.js} +65 -7
  57. package/dist/no-MAL5F6P6.js.map +1 -0
  58. package/dist/{pl-RVUL4CBM.js → pl-4RMY6JAJ.js} +65 -7
  59. package/dist/pl-4RMY6JAJ.js.map +1 -0
  60. package/dist/{pt-RPOVD4QM.js → pt-VQH2X3QQ.js} +65 -7
  61. package/dist/pt-VQH2X3QQ.js.map +1 -0
  62. package/dist/{ro-DMYWQTRD.js → ro-XXCQO2OG.js} +65 -7
  63. package/dist/ro-XXCQO2OG.js.map +1 -0
  64. package/dist/{sv-DMZ4FGXD.js → sv-7Z6EJ6U4.js} +65 -7
  65. package/dist/sv-7Z6EJ6U4.js.map +1 -0
  66. package/dist/test-utils.css +1 -1
  67. package/dist/test-utils.css.map +1 -1
  68. package/dist/test-utils.d.ts +1 -1
  69. package/dist/test-utils.js +5 -3
  70. package/dist/test-utils.js.map +1 -1
  71. package/dist/{th-4HVBJBQ2.js → th-L3DXXYVQ.js} +65 -7
  72. package/dist/th-L3DXXYVQ.js.map +1 -0
  73. package/dist/{tr-6BDPU5ML.js → tr-P3DFVLFJ.js} +65 -7
  74. package/dist/tr-P3DFVLFJ.js.map +1 -0
  75. package/dist/{uk-TBZBT2TL.js → uk-7C5D3PXS.js} +65 -7
  76. package/dist/uk-7C5D3PXS.js.map +1 -0
  77. package/dist/{vi-UMKZKZL3.js → vi-ZLTLEO7P.js} +65 -7
  78. package/dist/vi-ZLTLEO7P.js.map +1 -0
  79. package/dist/{zh-YBJWJJYB.js → zh-5FHVWDIN.js} +65 -7
  80. package/dist/zh-5FHVWDIN.js.map +1 -0
  81. package/package.json +7 -7
  82. package/src/components/AssistProgress.tsx +144 -134
  83. package/src/components/{EntityFoundLog.tsx → ItemFoundLog.tsx} +12 -7
  84. package/src/components/ProtectedErrorBoundary.css +3 -1
  85. package/src/components/StatusDisplay.css +35 -35
  86. package/src/components/Toast.css +3 -1
  87. package/src/components/__tests__/AssistProgress.test.tsx +216 -148
  88. package/src/components/annotation/annotation-entries.css +0 -4
  89. package/src/components/annotation/annotations.css +1 -1
  90. package/src/components/annotation/references.css +0 -4
  91. package/src/components/image-annotation/AnnotationOverlay.tsx +6 -6
  92. package/src/components/image-annotation/SvgDrawingCanvas.tsx +1 -1
  93. package/src/components/image-annotation/__tests__/AnnotationOverlay.click.test.tsx +7 -9
  94. package/src/components/image-annotation/__tests__/SvgDrawingCanvas.click.test.tsx +1 -2
  95. package/src/components/layout/Header.css +0 -4
  96. package/src/components/layout/LeftSidebar.css +0 -4
  97. package/src/components/modals/ConfigureGenerationStep.tsx +109 -48
  98. package/src/components/modals/ConfigureSearchStep.tsx +23 -40
  99. package/src/components/modals/ReferenceWizardModal.tsx +55 -16
  100. package/src/components/modals/ResourceGenerateModal.tsx +24 -8
  101. package/src/components/modals/ResourceSearchModal.tsx +1 -1
  102. package/src/components/modals/SearchModal.css +5 -17
  103. package/src/components/modals/SearchModal.tsx +1 -1
  104. package/src/components/modals/SearchResultsStep.tsx +2 -20
  105. package/src/components/modals/WizardFooter.tsx +63 -0
  106. package/src/components/modals/__tests__/ConfigureGenerationStep.test.tsx +255 -0
  107. package/src/components/modals/__tests__/ConfigureSearchStep.test.tsx +72 -0
  108. package/src/components/modals/__tests__/ReferenceWizardModal.test.tsx +256 -0
  109. package/src/components/modals/__tests__/ResourceGenerateModal.test.tsx +1 -0
  110. package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +6 -2
  111. package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +6 -2
  112. package/src/components/modals/__tests__/WizardFooter.test.tsx +235 -0
  113. package/src/components/modals/modals.css +16 -42
  114. package/src/components/navigation/NavigationTabs.css +0 -20
  115. package/src/components/pdf-annotation/PdfAnnotationCanvas.css +162 -6
  116. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +623 -232
  117. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +764 -7
  118. package/src/components/pdf-annotation/__tests__/estimate-slot-height.test.ts +53 -0
  119. package/src/components/pdf-annotation/estimate-slot-height.ts +31 -0
  120. package/src/components/resource/AnnotateView.tsx +16 -5
  121. package/src/components/resource/AnnotationHistory.tsx +2 -0
  122. package/src/components/resource/BrowseView.tsx +15 -4
  123. package/src/components/resource/ResourceViewer.tsx +23 -24
  124. package/src/components/resource/__tests__/AnnotateView.focus.test.tsx +50 -0
  125. package/src/components/resource/__tests__/AnnotationHistory.test.tsx +2 -0
  126. package/src/components/resource/__tests__/BrowseView.test.tsx +29 -3
  127. package/src/components/resource/__tests__/ResourceViewer.embeddable.test.tsx +47 -3
  128. package/src/components/resource/__tests__/browse-renderers.dispatch.test.tsx +33 -0
  129. package/src/components/resource/annotate-renderers.tsx +10 -1
  130. package/src/components/resource/browse-renderers.tsx +10 -1
  131. package/src/components/resource/event-formatting.ts +0 -3
  132. package/src/components/resource/panels/AssessmentEntry.tsx +1 -1
  133. package/src/components/resource/panels/AssessmentPanel.css +5 -6
  134. package/src/components/resource/panels/AssistSection.css +68 -271
  135. package/src/components/resource/panels/AssistSection.tsx +4 -4
  136. package/src/components/resource/panels/AssistShell.tsx +12 -4
  137. package/src/components/resource/panels/CollaborationPanel.css +47 -22
  138. package/src/components/resource/panels/CollaborationPanel.tsx +93 -2
  139. package/src/components/resource/panels/CommentEntry.tsx +1 -1
  140. package/src/components/resource/panels/CommentsPanel.css +0 -16
  141. package/src/components/resource/panels/HighlightEntry.tsx +1 -1
  142. package/src/components/resource/panels/HighlightPanel.css +0 -7
  143. package/src/components/resource/panels/JsonLdPanel.css +0 -4
  144. package/src/components/resource/panels/ReferenceEntry.tsx +1 -1
  145. package/src/components/resource/panels/ReferencesPanel.css +0 -12
  146. package/src/components/resource/panels/ReferencesPanel.tsx +12 -20
  147. package/src/components/resource/panels/ResourceInfoPanel.css +0 -32
  148. package/src/components/resource/panels/ResourceInfoPanel.tsx +1 -1
  149. package/src/components/resource/panels/StatisticsPanel.css +0 -20
  150. package/src/components/resource/panels/TagEntry.tsx +1 -1
  151. package/src/components/resource/panels/TaggingPanel.css +0 -4
  152. package/src/components/resource/panels/TaggingPanel.tsx +2 -10
  153. package/src/components/resource/panels/UnifiedAnnotationsPanel.css +0 -4
  154. package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +0 -1
  155. package/src/components/resource/panels/__tests__/AssistSection.test.tsx +48 -50
  156. package/src/components/resource/panels/__tests__/AssistShell.test.tsx +11 -6
  157. package/src/components/resource/panels/__tests__/CollaborationPanel.test.tsx +89 -0
  158. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +1 -2
  159. package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +0 -1
  160. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +44 -36
  161. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +0 -1
  162. package/src/components/resource/panels/__tests__/ReferencesPanel.headless.test.tsx +1 -1
  163. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +34 -53
  164. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +37 -1
  165. package/src/components/resource/panels/__tests__/TagEntry.test.tsx +0 -1
  166. package/src/components/settings/SettingsPanel.css +0 -4
  167. package/src/features/auth/auth.css +9 -33
  168. package/src/features/resource-compose/state/__tests__/compose-page-state-unit.test.ts +25 -1
  169. package/src/features/resource-compose/state/compose-page-state-unit.ts +11 -2
  170. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +55 -0
  171. package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +29 -0
  172. package/src/features/resource-discovery/state/__tests__/discover-state-unit.test.ts +53 -3
  173. package/src/features/resource-discovery/state/discover-state-unit.ts +29 -8
  174. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +26 -0
  175. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +42 -21
  176. package/src/features/resource-viewer/hooks/__tests__/useResourceViewedReport.test.tsx +63 -0
  177. package/src/features/resource-viewer/hooks/useResourceViewedReport.ts +33 -0
  178. package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +2 -2
  179. package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +1 -1
  180. package/src/styles/core/buttons.css +3 -1
  181. package/src/styles/core/forms.css +0 -21
  182. package/src/styles/core/indicators.css +0 -4
  183. package/src/styles/core/inputs.css +1 -5
  184. package/src/styles/core/progress.css +2 -34
  185. package/src/styles/core/sliders.css +0 -4
  186. package/src/styles/core/toggles.css +0 -4
  187. package/src/styles/features/compose.css +1 -1
  188. package/src/styles/features/resource-discovery.css +13 -0
  189. package/src/styles/features/resource-viewer.css +1 -21
  190. package/src/styles/features/static-pages.css +11 -11
  191. package/src/styles/motivations/motivation-assessment.css +2 -2
  192. package/src/styles/motivations/motivation-comment.css +2 -2
  193. package/src/styles/motivations/motivation-reference.css +2 -2
  194. package/src/styles/panels/history-panel.css +0 -40
  195. package/src/styles/panels/user-panel.css +0 -3
  196. package/src/styles/patterns/panel-helpers.css +0 -27
  197. package/src/styles/patterns/panel-sections.css +0 -59
  198. package/src/styles/patterns/panels-base.css +4 -36
  199. package/src/styles/utilities/motion.css +15 -15
  200. package/src/styles/variables.css +29 -1
  201. package/translations/ar.json +59 -5
  202. package/translations/bn.json +59 -5
  203. package/translations/cs.json +59 -5
  204. package/translations/da.json +59 -5
  205. package/translations/de.json +59 -5
  206. package/translations/el.json +59 -5
  207. package/translations/en.json +59 -5
  208. package/translations/es.json +59 -5
  209. package/translations/fa.json +59 -5
  210. package/translations/fi.json +59 -5
  211. package/translations/fr.json +59 -5
  212. package/translations/he.json +59 -5
  213. package/translations/hi.json +59 -5
  214. package/translations/id.json +59 -5
  215. package/translations/it.json +59 -5
  216. package/translations/ja.json +59 -5
  217. package/translations/ko.json +59 -5
  218. package/translations/ms.json +59 -5
  219. package/translations/nl.json +59 -5
  220. package/translations/no.json +59 -5
  221. package/translations/pl.json +59 -5
  222. package/translations/pt.json +59 -5
  223. package/translations/ro.json +59 -5
  224. package/translations/sv.json +59 -5
  225. package/translations/th.json +59 -5
  226. package/translations/tr.json +59 -5
  227. package/translations/uk.json +59 -5
  228. package/translations/vi.json +59 -5
  229. package/translations/zh.json +59 -5
  230. package/dist/PdfAnnotationCanvas.client-EHQWF6BR.js +0 -462
  231. package/dist/PdfAnnotationCanvas.client-EHQWF6BR.js.map +0 -1
  232. package/dist/PdfAnnotationCanvas.client-SU5KNT7G.css +0 -98
  233. package/dist/PdfAnnotationCanvas.client-SU5KNT7G.css.map +0 -1
  234. package/dist/ar-CULRHLNG.js.map +0 -1
  235. package/dist/bn-HYR7CEL2.js.map +0 -1
  236. package/dist/chunk-NH6L2GIL.js.map +0 -1
  237. package/dist/chunk-TG2XQEC4.js.map +0 -1
  238. package/dist/chunk-XUDKYAVC.js +0 -21
  239. package/dist/chunk-XUDKYAVC.js.map +0 -1
  240. package/dist/cs-YBRWY7NH.js.map +0 -1
  241. package/dist/da-PHDEOBV3.js.map +0 -1
  242. package/dist/de-O4UCCVLJ.js.map +0 -1
  243. package/dist/el-MVGO6WZV.js.map +0 -1
  244. package/dist/es-USSLXQY7.js.map +0 -1
  245. package/dist/fa-WMAREFWY.js.map +0 -1
  246. package/dist/fi-B3NBNOTS.js.map +0 -1
  247. package/dist/fr-TXYK5T5W.js.map +0 -1
  248. package/dist/he-JCJACW5D.js.map +0 -1
  249. package/dist/hi-VOQLZNJU.js.map +0 -1
  250. package/dist/id-BFN5RZNZ.js.map +0 -1
  251. package/dist/it-TWWDHKKM.js.map +0 -1
  252. package/dist/ja-YRQLEBFM.js.map +0 -1
  253. package/dist/ko-PG6B3CRB.js.map +0 -1
  254. package/dist/ms-7EZECVKM.js.map +0 -1
  255. package/dist/nl-HP753YAP.js.map +0 -1
  256. package/dist/no-JUD5WX3N.js.map +0 -1
  257. package/dist/pl-RVUL4CBM.js.map +0 -1
  258. package/dist/pt-RPOVD4QM.js.map +0 -1
  259. package/dist/ro-DMYWQTRD.js.map +0 -1
  260. package/dist/sv-DMZ4FGXD.js.map +0 -1
  261. package/dist/th-4HVBJBQ2.js.map +0 -1
  262. package/dist/tr-6BDPU5ML.js.map +0 -1
  263. package/dist/uk-TBZBT2TL.js.map +0 -1
  264. package/dist/vi-UMKZKZL3.js.map +0 -1
  265. package/dist/zh-YBJWJJYB.js.map +0 -1
  266. package/src/integrations/tailwind-plugin.cjs +0 -224
  267. /package/dist/{en-2KQILFKQ.js.map → en-2KADE7N4.js.map} +0 -0
@@ -1,181 +1,191 @@
1
1
  'use client';
2
2
 
3
3
  import type { components } from '@semiont/core';
4
- import { EntityFoundLog } from './EntityFoundLog';
4
+ import { ItemFoundLog } from './ItemFoundLog';
5
5
 
6
6
  type JobProgress = components['schemas']['JobProgress'];
7
+ type JobProgressMessage = components['schemas']['JobProgressMessage'];
7
8
 
8
9
  /**
9
- * Every string this component renders. Required by default and with NO
10
- * English fallbacks (ASSIST-SURFACE-WARTS Lane A): a `tr.x || 'X'` default
11
- * turns a forgotten key into English text in a Japanese UI, silently and
12
- * only at runtime. Required keys make the same mistake a type error at the
13
- * call site. Only genuinely conditional copy is optional.
10
+ * Every string this component renders. Required by default and with NO English
11
+ * fallbacks (ASSIST-SURFACE-WARTS Lane A): a `tr.x || 'X'` default turns a
12
+ * forgotten key into English text in a Japanese UI, silently and only at
13
+ * runtime. Required keys make the same mistake a type error at the call site.
14
+ *
15
+ * The nine wire codes collapse to ONE required function rather than nine keys:
16
+ * the code→copy switch belongs in one place, and threading nine strings through
17
+ * five call sites would put five copies of it in the tree. Build it with
18
+ * `assistProgressCopy(t)`.
14
19
  */
15
20
  export interface AssistProgressTranslations {
16
- /** Header title (e.g. "Annotating Entity References" / "Generating Resource"). Omit for the headerless inline style. */
17
- title?: string;
18
- /** Cancel-button title attribute. */
21
+ /** Control label while the run is in flight. */
19
22
  cancel: string;
20
- /** Default in-progress status message (used when the job sends no `message`). */
23
+ /** Control label once the run has ended. */
24
+ close: string;
25
+ /** Localized copy for a progress code. */
26
+ message: (m: JobProgressMessage) => string;
27
+ /**
28
+ * Shown when no code has arrived yet — a pure liveness heartbeat, or an event
29
+ * predating the coded wire. `JobProgress.message` is optional for exactly
30
+ * these cases.
31
+ */
21
32
  inProgress: string;
22
- /** Status copy for the terminal 'complete' stage. */
23
- complete: string;
24
- /** Fallback status copy for the terminal 'error' stage. */
25
- failed: string;
26
- /** Request-parameters block heading. */
27
- paramsTitle: string;
28
- /** Current-work detail line — the generic form, used by every flow. */
29
- processing: (label: string) => string;
33
+ /**
34
+ * The subject line: what is being worked on, with its position when known.
35
+ * Takes the wire's `{ kind, value }` — the localized name for `kind` is the
36
+ * translation layer's business, not this component's.
37
+ */
38
+ subject: (current: NonNullable<JobProgress['current']>, done?: number, total?: number) => string;
39
+ /**
40
+ * Localized NAME for an echoed request parameter. The wire sends a code
41
+ * (`instructions`, `tone`, …); the VALUE beside it is the user's own words
42
+ * and is never translated.
43
+ */
44
+ paramLabel: (code: string) => string;
30
45
  /** Completed entity-type log line (reference flow only). */
31
46
  found?: (count: number) => string;
32
- /** Current-work detail line, reference-flow wording; falls back to `processing`. */
33
- current?: (label: string) => string;
34
- /** Dismiss-button label. */
35
- close: string;
36
47
  }
37
48
 
49
+ /**
50
+ * The CSS `data-type` hook: five motivations plus generation. A closed set, so
51
+ * it is typed as one — a typo used to produce unstyled chrome, silently
52
+ * (CLEAN-PROGRESS A9).
53
+ */
54
+ export type AssistDataType =
55
+ | 'highlight' | 'comment' | 'assessment' | 'reference' | 'tag' | 'generation';
56
+
38
57
  export interface AssistProgressProps {
39
58
  progress: JobProgress;
40
- /** CSS `data-type` hook ('highlight' | 'comment' | … | 'reference' | 'tag' | 'generation'). */
41
- dataType: string;
42
- /** Cancel the underlying job — rendered while running when provided. Caller wires `client.job.cancelRequest(...)`. */
43
- onCancel?: () => void;
59
+ dataType: AssistDataType;
44
60
  /**
45
- * Dismiss the display rendered whenever provided. WHEN dismissal is
46
- * offered is the caller's policy (AssistShell withholds the callback while
47
- * the assist is still running). Caller wires `client.mark.dismissProgress()`.
61
+ * The run has ENDED. The owner's fact, not the payload's
62
+ * (ASSIST-PROGRESS-CONSOLIDATION D7): terminality is signalled on
63
+ * `job:complete` / `job:fail`, which `AssistShell` already observes via
64
+ * `isAssisting`. This component deliberately does not read `progress.stage` —
65
+ * no producer in the repo emits a terminal stage, and the two branches that
66
+ * believed the schema's description were unreachable for exactly that reason.
67
+ *
68
+ * REQUIRED (CLEAN-PROGRESS A1). It was optional, and the one call site that
69
+ * forgot it shipped a flow that could never reach the ended state at all.
70
+ * Nothing about a progress payload can tell this component the run is over,
71
+ * so the owner must say — and a default of `false` is a wrong answer, not a
72
+ * safe one.
48
73
  */
74
+ ended: boolean;
75
+ /** Cancel the underlying job. Caller wires `client.job.cancelRequest(...)`. */
76
+ onCancel?: () => void;
77
+ /** Dismiss the display. Caller wires `client.mark.dismissProgress()`. */
49
78
  onDismiss?: () => void;
50
- /** Render the percentage bar (tag flow's visual; percentage itself comes from `progress`). */
51
- showPercentBar?: boolean;
52
79
  translations: AssistProgressTranslations;
53
80
  }
54
81
 
55
82
  /**
56
- * The one job-progress renderer (#7) unifies the three previous shapes
57
- * (AssistSection's inline block, the reference/generation widget, TaggingPanel's
58
- * inline block). Presentational and provider-free: no session, no context —
59
- * cancel/dismiss arrive as callbacks, so it renders identically on the page and
60
- * in embeddable (bring-your-own-session) hosts. Feature blocks are
61
- * data-presence-driven: each call site keeps its established visuals by passing
62
- * the data and translations it always had.
83
+ * The one job-progress renderer, for all five motivations.
84
+ *
85
+ * Presentational and provider-free: no session, no context — cancel/dismiss
86
+ * arrive as callbacks, so it renders identically on the page and in embeddable
87
+ * (bring-your-own-session) hosts.
88
+ *
89
+ * One shape for every flow. What varies is DATA, not flags: a bar appears
90
+ * because there is a fraction to fill it, a subject line appears because there
91
+ * is a subject. The previous `title` / `showPercentBar` / `found` / `current`
92
+ * opt-ins produced four unrelated layouts from one component, which is what
93
+ * generated the duplicate renders and doubled chrome this replaces.
63
94
  */
64
95
  export function AssistProgress({
65
96
  progress,
66
97
  dataType,
98
+ ended,
67
99
  onCancel,
68
100
  onDismiss,
69
- showPercentBar = false,
70
101
  translations: tr,
71
102
  }: AssistProgressProps) {
72
- const terminal = progress.stage === 'complete' || progress.stage === 'error';
73
- // The reference flow words this line its own way; everyone else gets the
74
- // generic one. Both are translated there is no untranslated branch.
75
- const currentLabel = tr.current ?? tr.processing;
103
+ // One vocabulary, so no guessing (CLEAN-PROGRESS D2). This used to be a pair
104
+ // of `??` chains reconciling entity-type fields with category fields the
105
+ // component had to know which flow it was drawing to find the same two facts.
106
+ const current = progress.current;
107
+ const done = progress.processed;
108
+ const total = progress.total;
76
109
 
77
- return (
78
- <div className="semiont-annotation-progress" data-status={progress.stage} data-type={dataType}>
79
- {/* Header (title + cancel)reference/generation style; omitted inline */}
80
- {tr.title && (
81
- <div className="semiont-annotation-header">
82
- <h3 className="semiont-annotation-title">
83
- <span className="semiont-annotation-sparkle">✨</span>
84
- {tr.title}
85
- </h3>
86
- {onCancel && !terminal && (
87
- <button
88
- onClick={onCancel}
89
- className="semiont-annotation-cancel"
90
- title={tr.cancel}
91
- aria-label={tr.cancel}
92
- type="button"
93
- >
94
-
95
- </button>
96
- )}
97
- </div>
98
- )}
110
+ // H1: the params line earns its space only when it says something the status
111
+ // line does not. The ONLY redundant case is a single entity type, where the
112
+ // subject beneath already names it so that case alone is suppressed.
113
+ //
114
+ // Deliberately NOT `total > 1`: other flows send params that never restate the
115
+ // subject (a highlight run reports Instructions and Density), and those have
116
+ // no `total` at all. Gating on the presence of a count would have hidden
117
+ // genuinely informative parameters — an over-application of H1 caught by
118
+ // AssistSection's highlight fixture.
119
+ const params = total === 1 ? undefined : progress.requestParams;
120
+
121
+ // `percentage` is REQUIRED on JobProgress, so every progress event can fill a
122
+ // bar — the bar's existence is not conditional on anything.
123
+ //
124
+ // It used to also require the fraction (`done`/`total`), which SILENTLY
125
+ // REMOVED THE TAG FLOW'S BAR: `processTagJob` reports percentage only and
126
+ // emits no category fields at all, so `done`/`total` are permanently
127
+ // undefined there (caught in review of PR #1179). The fraction is a richer,
128
+ // optional signal that only flows counting per-item work have; it belongs to
129
+ // the SUBJECT line, not to whether a bar exists.
99
130
 
100
- {/* Request parameters */}
101
- {progress.requestParams && progress.requestParams.length > 0 && (
102
- <div className="semiont-annotation-progress__params" data-type={dataType}>
103
- <div className="semiont-annotation-progress__params-title">{tr.paramsTitle}</div>
104
- {progress.requestParams.map((param, idx) => (
105
- <div key={idx} className="semiont-annotation-progress__param">
106
- <span className="semiont-annotation-progress__param-label">{param.label}:</span> <span>{param.value}</span>
107
- </div>
131
+ return (
132
+ <div className="semiont-assist-progress" data-type={dataType} data-ended={ended}>
133
+ {params && params.length > 0 && (
134
+ <div className="semiont-assist-progress__params" data-testid="semiont-assist-params">
135
+ {/* H1 removed the BLOCK HEADING ("Request Parameters:"), not the
136
+ per-parameter labels: a bare "5" for Density says nothing. */}
137
+ {params.map((param, idx) => (
138
+ <span key={idx} className="semiont-assist-progress__param">
139
+ <span className="semiont-assist-progress__param-label">
140
+ {tr.paramLabel(param.label)}:
141
+ </span>{' '}
142
+ <span>{param.value}</span>
143
+ </span>
108
144
  ))}
109
145
  </div>
110
146
  )}
111
147
 
112
- {/* Completed entity-type log (reference flow) */}
113
- {tr.found && progress.completedEntityTypes && (
114
- <EntityFoundLog entries={progress.completedEntityTypes} formatFound={tr.found} />
148
+ {/* H2: kept uncapped — per-item counts are small in practice. */}
149
+ {tr.found && progress.completedItems && (
150
+ <ItemFoundLog entries={progress.completedItems} formatFound={tr.found} />
115
151
  )}
116
152
 
117
- {/* Status line with stage branching */}
118
- <div className="semiont-annotation-progress__status">
119
- {progress.stage === 'complete' ? (
120
- <div className="semiont-annotation-progress__message">
121
- <span className="semiont-annotation-progress__icon">✅</span>
122
- {/* Same precedence as 'error' below: the job's own message carries
123
- detail no static string can ("Created 14 highlights"), and
124
- `tr.complete` covers the required-but-possibly-'' case so a
125
- terminal line is never blank. NOTE: job messages are composed
126
- backend-side and are not localized — a real gap, but a backend
127
- one; see ASSIST-SURFACE-WARTS watch-items. */}
128
- <span>{progress.message || tr.complete}</span>
129
- </div>
130
- ) : progress.stage === 'error' ? (
131
- <div className="semiont-annotation-progress__message">
132
- <span className="semiont-annotation-progress__icon">❌</span>
133
- <span>{progress.message || tr.failed}</span>
134
- </div>
135
- ) : (
136
- <div className="semiont-annotation-progress__message">
137
- <span className="semiont-annotation-progress__icon">✨</span>
138
- <span>
139
- {progress.message
140
- || (progress.currentEntityType ? currentLabel(progress.currentEntityType) : tr.inProgress)}
141
- </span>
142
- </div>
143
- )}
153
+ <div className="semiont-assist-progress__status">
154
+ <span className="semiont-assist-progress__icon" aria-hidden="true">
155
+ {ended ? '' : '✨'}
156
+ </span>
157
+ <span data-testid="semiont-assist-status">
158
+ {progress.message ? tr.message(progress.message) : tr.inProgress}
159
+ </span>
160
+ </div>
144
161
 
145
- {/* Current-work detail while running */}
146
- {!terminal && progress.currentEntityType && (
147
- <div className="semiont-annotation-progress__details">
148
- {currentLabel(progress.currentEntityType)}
149
- </div>
150
- )}
151
- {!terminal && progress.currentCategory && (
152
- <div className="semiont-annotation-progress__details">
153
- {tr.processing(progress.currentCategory)}
154
- {progress.processedCategories !== undefined && progress.totalCategories !== undefined && (
155
- <> ({progress.processedCategories}/{progress.totalCategories})</>
156
- )}
157
- </div>
158
- )}
162
+ {/* H3: stage above, subject beneath. */}
163
+ {current && (
164
+ <div className="semiont-assist-progress__subject" data-testid="semiont-assist-subject">
165
+ {tr.subject(current, done, total)}
166
+ </div>
167
+ )}
159
168
 
160
- {/* Dismiss — rendered whenever the caller offers it */}
161
- {onDismiss && (
162
- <button
163
- onClick={onDismiss}
164
- className="semiont-annotation-progress__close"
165
- aria-label={tr.close}
166
- title={tr.close}
167
- type="button"
168
- >
169
- ×
170
- </button>
171
- )}
169
+ <div className="semiont-progress-bar" data-testid="semiont-assist-bar">
170
+ <div
171
+ className="semiont-progress-bar__fill"
172
+ data-type={dataType}
173
+ style={{ width: `${progress.percentage}%` }}
174
+ />
172
175
  </div>
173
176
 
174
- {/* Percentage bar (tag flow) */}
175
- {showPercentBar && progress.percentage !== undefined && (
176
- <div className="semiont-progress-bar">
177
- <div className="semiont-progress-bar__fill" data-type={dataType} style={{ width: `${progress.percentage}%` }} />
178
- </div>
177
+ {/* D3: ONE control, its meaning set by the lifecycle. */}
178
+ {(ended ? onDismiss : onCancel) && (
179
+ <button
180
+ onClick={ended ? onDismiss : onCancel}
181
+ className="semiont-assist-progress__control"
182
+ data-testid="semiont-assist-control"
183
+ title={ended ? tr.close : tr.cancel}
184
+ aria-label={ended ? tr.close : tr.cancel}
185
+ type="button"
186
+ >
187
+
188
+ </button>
179
189
  )}
180
190
  </div>
181
191
  );
@@ -1,18 +1,19 @@
1
1
  'use client';
2
2
 
3
- export interface EntityFoundEntry {
4
- entityType: string;
3
+ export interface ItemFoundEntry {
4
+ /** The item itself — an entity type, a tag category — shown verbatim. */
5
+ value: string;
5
6
  foundCount: number;
6
7
  }
7
8
 
8
- export interface EntityFoundLogProps {
9
- entries: EntityFoundEntry[];
9
+ export interface ItemFoundLogProps {
10
+ entries: ItemFoundEntry[];
10
11
  /** Formats the per-entity count line, e.g. `(n) => t('found', { count: n })`. */
11
12
  formatFound: (count: number) => string;
12
13
  }
13
14
 
14
15
  /**
15
- * "✓ Person: 5 found" — the completed entity-type log.
16
+ * "✓ Person: 5 found" — the completed-items log.
16
17
  *
17
18
  * One markup for one concept (ASSIST-SURFACE-WARTS Lane B). This was two
18
19
  * class families a single panel apart: the live progress display used
@@ -20,8 +21,12 @@ export interface EntityFoundLogProps {
20
21
  * `semiont-assist-widget__log*`, with the same rows rendered by hand in both.
21
22
  * Presentational and provider-free, like AssistProgress — the caller brings
22
23
  * the formatter.
24
+ *
25
+ * Item-shaped rather than entity-type-shaped (CLEAN-PROGRESS D2): the tag flow
26
+ * counts categories the same way the reference flow counts entity types, and a
27
+ * shared component should not be named for one of its callers.
23
28
  */
24
- export function EntityFoundLog({ entries, formatFound }: EntityFoundLogProps) {
29
+ export function ItemFoundLog({ entries, formatFound }: ItemFoundLogProps) {
25
30
  if (entries.length === 0) return null;
26
31
 
27
32
  return (
@@ -29,7 +34,7 @@ export function EntityFoundLog({ entries, formatFound }: EntityFoundLogProps) {
29
34
  {entries.map((item, index) => (
30
35
  <div key={index} className="semiont-annotation-log-item">
31
36
  <span className="semiont-annotation-check">✓</span>
32
- <span className="semiont-annotation-entity-type">{item.entityType}:</span>
37
+ <span className="semiont-annotation-entity-type">{item.value}:</span>
33
38
  <span>{formatFound(item.foundCount)}</span>
34
39
  </div>
35
40
  ))}
@@ -88,8 +88,10 @@
88
88
  color: var(--semiont-color-gray-700);
89
89
  }
90
90
 
91
+ /* gray-500 is thin for this size on a near-black surface, and the hover below
92
+ already lifts to gray-300 — resting darker than its own hover target. */
91
93
  [data-theme="dark"] .semiont-protected-error-boundary-summary {
92
- color: var(--semiont-color-gray-500);
94
+ color: var(--semiont-color-gray-400);
93
95
  }
94
96
 
95
97
  [data-theme="dark"] .semiont-protected-error-boundary-summary:hover {
@@ -161,7 +161,7 @@
161
161
 
162
162
  .semiont-toolbar-icon-large {
163
163
  font-size: 1.875rem; /* 30px - was 2xl/1.5rem */
164
- font-weight: var(--semiont-font-weight-bold);
164
+ font-weight: var(--semiont-font-bold);
165
165
  }
166
166
 
167
167
  /* Dark mode for Toolbar - Fixed to respect data-theme attribute */
@@ -206,7 +206,7 @@
206
206
  color: var(--semiont-color-primary-700);
207
207
  border: 1px solid var(--semiont-color-primary-200);
208
208
  border-radius: var(--semiont-radius-base);
209
- font-size: var(--semiont-font-size-xs);
209
+ font-size: var(--semiont-text-xs);
210
210
  }
211
211
 
212
212
  /* Editing affordances (RESOURCE-TAGS-INLINE-EDITING) */
@@ -217,7 +217,7 @@
217
217
  border: none;
218
218
  background: none;
219
219
  color: inherit;
220
- font-size: var(--semiont-font-size-xs);
220
+ font-size: var(--semiont-text-xs);
221
221
  cursor: pointer;
222
222
  opacity: 0.7;
223
223
  }
@@ -279,8 +279,8 @@
279
279
  }
280
280
 
281
281
  .semiont-error-boundary-title {
282
- font-size: var(--semiont-font-size-2xl);
283
- font-weight: var(--semiont-font-weight-bold);
282
+ font-size: var(--semiont-text-2xl);
283
+ font-weight: var(--semiont-font-bold);
284
284
  color: var(--semiont-color-neutral-900);
285
285
  margin-bottom: var(--semiont-spacing-xs);
286
286
  }
@@ -290,30 +290,30 @@
290
290
  }
291
291
 
292
292
  .semiont-error-boundary-details {
293
- background-color: var(--semiont-color-danger-50);
294
- border: 1px solid var(--semiont-color-danger-200);
293
+ background-color: var(--semiont-color-red-50);
294
+ border: 1px solid var(--semiont-color-red-200);
295
295
  border-radius: var(--semiont-radius-md);
296
296
  padding: var(--semiont-spacing-md);
297
297
  }
298
298
 
299
299
  .semiont-error-boundary-details-title {
300
- font-size: var(--semiont-font-size-sm);
301
- font-weight: var(--semiont-font-weight-semibold);
302
- color: var(--semiont-color-danger-800);
300
+ font-size: var(--semiont-text-sm);
301
+ font-weight: var(--semiont-font-semibold);
302
+ color: var(--semiont-color-red-800);
303
303
  margin-bottom: calc(var(--semiont-spacing-xs) / 2);
304
304
  }
305
305
 
306
306
  .semiont-error-boundary-details-message {
307
- font-size: var(--semiont-font-size-xs);
308
- color: var(--semiont-color-danger-700);
307
+ font-size: var(--semiont-text-xs);
308
+ color: var(--semiont-color-red-700);
309
309
  font-family: monospace;
310
310
  word-break: break-all;
311
311
  }
312
312
 
313
313
  .semiont-error-boundary-stack {
314
314
  margin-top: var(--semiont-spacing-xs);
315
- font-size: var(--semiont-font-size-xs);
316
- color: var(--semiont-color-danger-600);
315
+ font-size: var(--semiont-text-xs);
316
+ color: var(--semiont-color-red-600);
317
317
  overflow-x: auto;
318
318
  }
319
319
 
@@ -326,8 +326,8 @@
326
326
  /* AsyncErrorBoundary Component */
327
327
  .semiont-async-error-boundary {
328
328
  padding: var(--semiont-spacing-md);
329
- background-color: var(--semiont-color-warning-50);
330
- border: 1px solid var(--semiont-color-warning-200);
329
+ background-color: var(--semiont-color-amber-50);
330
+ border: 1px solid var(--semiont-color-amber-200);
331
331
  border-radius: var(--semiont-radius-md);
332
332
  }
333
333
 
@@ -343,7 +343,7 @@
343
343
  .semiont-icon-warning {
344
344
  height: 1.25rem;
345
345
  width: 1.25rem;
346
- color: var(--semiont-color-warning-400);
346
+ color: var(--semiont-color-amber-400);
347
347
  }
348
348
 
349
349
  .semiont-async-error-details {
@@ -352,21 +352,21 @@
352
352
  }
353
353
 
354
354
  .semiont-async-error-title {
355
- font-size: var(--semiont-font-size-sm);
356
- font-weight: var(--semiont-font-weight-medium);
357
- color: var(--semiont-color-warning-800);
355
+ font-size: var(--semiont-text-sm);
356
+ font-weight: var(--semiont-font-medium);
357
+ color: var(--semiont-color-amber-800);
358
358
  }
359
359
 
360
360
  .semiont-async-error-message {
361
361
  margin-top: calc(var(--semiont-spacing-xs) / 2);
362
- font-size: var(--semiont-font-size-sm);
363
- color: var(--semiont-color-warning-700);
362
+ font-size: var(--semiont-text-sm);
363
+ color: var(--semiont-color-amber-700);
364
364
  }
365
365
 
366
366
  .semiont-async-error-retry {
367
367
  margin-top: var(--semiont-spacing-xs);
368
- font-size: var(--semiont-font-size-sm);
369
- color: var(--semiont-color-warning-600);
368
+ font-size: var(--semiont-text-sm);
369
+ color: var(--semiont-color-amber-600);
370
370
  text-decoration: underline;
371
371
  background: none;
372
372
  border: none;
@@ -375,7 +375,7 @@
375
375
  }
376
376
 
377
377
  .semiont-async-error-retry:hover {
378
- color: var(--semiont-color-warning-500);
378
+ color: var(--semiont-color-amber-500);
379
379
  }
380
380
 
381
381
  /* Dark mode for ErrorBoundary */
@@ -393,43 +393,43 @@
393
393
 
394
394
  [data-theme="dark"] .semiont-error-boundary-details {
395
395
  background-color: rgba(239, 68, 68, 0.2);
396
- border-color: var(--semiont-color-danger-800);
396
+ border-color: var(--semiont-color-red-800);
397
397
  }
398
398
 
399
399
  [data-theme="dark"] .semiont-error-boundary-details-title {
400
- color: var(--semiont-color-danger-300);
400
+ color: var(--semiont-color-red-300);
401
401
  }
402
402
 
403
403
  [data-theme="dark"] .semiont-error-boundary-details-message {
404
- color: var(--semiont-color-danger-400);
404
+ color: var(--semiont-color-red-400);
405
405
  }
406
406
 
407
407
  [data-theme="dark"] .semiont-error-boundary-stack {
408
- color: var(--semiont-color-danger-500);
408
+ color: var(--semiont-color-red-500);
409
409
  }
410
410
 
411
411
  [data-theme="dark"] .semiont-async-error-boundary {
412
412
  background-color: rgba(245, 158, 11, 0.2);
413
- border-color: var(--semiont-color-warning-800);
413
+ border-color: var(--semiont-color-amber-800);
414
414
  }
415
415
 
416
416
  [data-theme="dark"] .semiont-icon-warning {
417
- color: var(--semiont-color-warning-400);
417
+ color: var(--semiont-color-warning-light);
418
418
  }
419
419
 
420
420
  [data-theme="dark"] .semiont-async-error-title {
421
- color: var(--semiont-color-warning-300);
421
+ color: var(--semiont-color-amber-300);
422
422
  }
423
423
 
424
424
  [data-theme="dark"] .semiont-async-error-message {
425
- color: var(--semiont-color-warning-400);
425
+ color: var(--semiont-color-amber-400);
426
426
  }
427
427
 
428
428
  [data-theme="dark"] .semiont-async-error-retry {
429
- color: var(--semiont-color-warning-400);
429
+ color: var(--semiont-color-amber-400);
430
430
  }
431
431
 
432
432
  [data-theme="dark"] .semiont-async-error-retry:hover {
433
- color: var(--semiont-color-warning-300);
433
+ color: var(--semiont-color-amber-300);
434
434
  }
435
435
 
@@ -26,8 +26,10 @@
26
26
  animation: slideIn var(--semiont-duration-base) var(--semiont-ease);
27
27
  }
28
28
 
29
+ /* Separation, not decoration: a 10%-black shadow is invisible against a dark
30
+ backdrop, so the dark theme takes the deeper one. */
29
31
  [data-theme="dark"] .semiont-toast {
30
- box-shadow: var(--semiont-shadow-lg);
32
+ box-shadow: var(--semiont-shadow-xl);
31
33
  }
32
34
 
33
35
  @keyframes slideIn {