@semiont/react-ui 0.2.45 → 0.3.0

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 (220) hide show
  1. package/dist/{PdfAnnotationCanvas.client-COQREPXU.mjs → PdfAnnotationCanvas.client-PVTVPDBQ.mjs} +3 -4
  2. package/dist/PdfAnnotationCanvas.client-PVTVPDBQ.mjs.map +1 -0
  3. package/dist/{ar-7SUXNE34.mjs → ar-APUOG2AP.mjs} +46 -6
  4. package/dist/ar-APUOG2AP.mjs.map +1 -0
  5. package/dist/{bn-XOET3DOI.mjs → bn-EFK2LJGK.mjs} +46 -6
  6. package/dist/bn-EFK2LJGK.mjs.map +1 -0
  7. package/dist/{chunk-JH7BXE2P.mjs → chunk-7DW2P4UE.mjs} +45 -5
  8. package/dist/chunk-7DW2P4UE.mjs.map +1 -0
  9. package/dist/{chunk-Q2KV6Y2J.mjs → chunk-7GEYABC6.mjs} +32 -32
  10. package/dist/{chunk-3JTO27MH.mjs → chunk-D4GAAQMM.mjs} +2 -9
  11. package/dist/{cs-X63DXX7L.mjs → cs-A26MEEQE.mjs} +46 -6
  12. package/dist/cs-A26MEEQE.mjs.map +1 -0
  13. package/dist/{da-OWTCV57A.mjs → da-U3L2FHSZ.mjs} +46 -6
  14. package/dist/da-U3L2FHSZ.mjs.map +1 -0
  15. package/dist/{de-77BMFDVF.mjs → de-Y5BHEBT7.mjs} +46 -6
  16. package/dist/de-Y5BHEBT7.mjs.map +1 -0
  17. package/dist/dist-YLEIY3JJ.mjs +547 -0
  18. package/dist/dist-YLEIY3JJ.mjs.map +1 -0
  19. package/dist/{el-FIBNLH2V.mjs → el-HU7LAWQY.mjs} +46 -6
  20. package/dist/el-HU7LAWQY.mjs.map +1 -0
  21. package/dist/{en-XWEPVTB4.mjs → en-HAKDCFKL.mjs} +5 -3
  22. package/dist/{es-726NTS53.mjs → es-4BN64QH5.mjs} +46 -6
  23. package/dist/es-4BN64QH5.mjs.map +1 -0
  24. package/dist/{fa-3N4CIWE6.mjs → fa-6ELTBARU.mjs} +46 -6
  25. package/dist/fa-6ELTBARU.mjs.map +1 -0
  26. package/dist/{fi-JOM3M7Z4.mjs → fi-DJ4WGIFW.mjs} +46 -6
  27. package/dist/fi-DJ4WGIFW.mjs.map +1 -0
  28. package/dist/{fr-56QSXS7E.mjs → fr-23XM6H6H.mjs} +46 -6
  29. package/dist/fr-23XM6H6H.mjs.map +1 -0
  30. package/dist/{he-SNAXPJEK.mjs → he-JSWJC2XU.mjs} +46 -6
  31. package/dist/he-JSWJC2XU.mjs.map +1 -0
  32. package/dist/{hi-CRBRD5TB.mjs → hi-BENHG3OJ.mjs} +46 -6
  33. package/dist/hi-BENHG3OJ.mjs.map +1 -0
  34. package/dist/{id-BRCVLICF.mjs → id-4HHQJQNF.mjs} +46 -6
  35. package/dist/id-4HHQJQNF.mjs.map +1 -0
  36. package/dist/index.css +108 -12
  37. package/dist/index.css.map +1 -1
  38. package/dist/index.d.mts +399 -147
  39. package/dist/index.mjs +3573 -2226
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/{it-M2Z27BNB.mjs → it-U6I5PDKU.mjs} +46 -6
  42. package/dist/it-U6I5PDKU.mjs.map +1 -0
  43. package/dist/{ja-TZUKW7HD.mjs → ja-K3YBDWDP.mjs} +46 -6
  44. package/dist/ja-K3YBDWDP.mjs.map +1 -0
  45. package/dist/{ko-NKBGGOL6.mjs → ko-KC2HXRXG.mjs} +46 -6
  46. package/dist/ko-KC2HXRXG.mjs.map +1 -0
  47. package/dist/{magic-string.es-7FJ3LUGB.mjs → magic-string.es-K77I4ZQN.mjs} +2 -2
  48. package/dist/{ms-XFXPN6RX.mjs → ms-KY5QGBNN.mjs} +46 -6
  49. package/dist/ms-KY5QGBNN.mjs.map +1 -0
  50. package/dist/{nl-MVYXAS5C.mjs → nl-6PZFLGY2.mjs} +46 -6
  51. package/dist/nl-6PZFLGY2.mjs.map +1 -0
  52. package/dist/{no-XOLO4JPV.mjs → no-5QR7PLVJ.mjs} +46 -6
  53. package/dist/no-5QR7PLVJ.mjs.map +1 -0
  54. package/dist/{pl-TRWLMMC4.mjs → pl-4GV2NQXE.mjs} +46 -6
  55. package/dist/pl-4GV2NQXE.mjs.map +1 -0
  56. package/dist/{pt-M3TE24UI.mjs → pt-F3F5QD2P.mjs} +46 -6
  57. package/dist/pt-F3F5QD2P.mjs.map +1 -0
  58. package/dist/{ro-QBFG2T64.mjs → ro-TFYL2IQB.mjs} +46 -6
  59. package/dist/ro-TFYL2IQB.mjs.map +1 -0
  60. package/dist/{sv-IUECBXWX.mjs → sv-PRVF2QLR.mjs} +46 -6
  61. package/dist/sv-PRVF2QLR.mjs.map +1 -0
  62. package/dist/test-utils.mjs +16994 -22140
  63. package/dist/test-utils.mjs.map +1 -1
  64. package/dist/{th-US7KIN5Q.mjs → th-SUQOQFUZ.mjs} +46 -6
  65. package/dist/th-SUQOQFUZ.mjs.map +1 -0
  66. package/dist/{tr-DWJ2FFUK.mjs → tr-AYUJZOFJ.mjs} +46 -6
  67. package/dist/tr-AYUJZOFJ.mjs.map +1 -0
  68. package/dist/{uk-M4ZE4DPZ.mjs → uk-YY5WGLBM.mjs} +46 -6
  69. package/dist/uk-YY5WGLBM.mjs.map +1 -0
  70. package/dist/{vi-FERZNPSH.mjs → vi-6RO77ITD.mjs} +46 -6
  71. package/dist/{vi-FERZNPSH.mjs.map → vi-6RO77ITD.mjs.map} +1 -1
  72. package/dist/{zh-3J2I3WYK.mjs → zh-L6GA65H6.mjs} +46 -6
  73. package/dist/zh-L6GA65H6.mjs.map +1 -0
  74. package/package.json +18 -14
  75. package/src/components/Button/Button.tsx +23 -25
  76. package/src/components/annotation/AnnotateToolbar.tsx +1 -1
  77. package/src/components/annotation-popups/SharedPopupElements.tsx +5 -7
  78. package/src/components/image-annotation/SvgDrawingCanvas.tsx +3 -4
  79. package/src/components/modals/ConfigureGenerationStep.tsx +190 -0
  80. package/src/components/modals/ConfigureSearchStep.tsx +105 -0
  81. package/src/components/modals/ContextSummary.tsx +183 -0
  82. package/src/components/modals/GatherContextStep.tsx +89 -0
  83. package/src/components/modals/KeyboardShortcutsHelpModal.tsx +4 -6
  84. package/src/components/modals/ProposeEntitiesModal.tsx +4 -6
  85. package/src/components/modals/ReferenceWizardModal.tsx +326 -0
  86. package/src/components/modals/ResourceSearchModal.tsx +4 -6
  87. package/src/components/modals/SearchModal.css +43 -0
  88. package/src/components/modals/SearchModal.tsx +4 -6
  89. package/src/components/modals/SearchResultsStep.tsx +126 -0
  90. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +3 -4
  91. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +36 -14
  92. package/src/components/resource/AnnotateView.tsx +4 -4
  93. package/src/components/resource/AnnotationHistory.tsx +2 -2
  94. package/src/components/resource/BrowseView.tsx +4 -4
  95. package/src/components/resource/ResourceViewer.tsx +5 -8
  96. package/src/components/resource/__tests__/AnnotationHistory.test.tsx +16 -16
  97. package/src/components/resource/__tests__/BrowseView.test.tsx +2 -2
  98. package/src/components/resource/__tests__/HistoryEvent.test.tsx +1 -1
  99. package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +1 -1
  100. package/src/components/resource/panels/AssessmentEntry.tsx +9 -11
  101. package/src/components/resource/panels/AssessmentPanel.tsx +1 -1
  102. package/src/components/resource/panels/CommentEntry.tsx +10 -12
  103. package/src/components/resource/panels/CommentsPanel.tsx +1 -1
  104. package/src/components/resource/panels/HighlightEntry.tsx +9 -11
  105. package/src/components/resource/panels/HighlightPanel.tsx +2 -2
  106. package/src/components/resource/panels/ReferenceEntry.tsx +57 -104
  107. package/src/components/resource/panels/ReferencesPanel.css +85 -13
  108. package/src/components/resource/panels/ReferencesPanel.tsx +2 -3
  109. package/src/components/resource/panels/TagEntry.tsx +9 -11
  110. package/src/components/resource/panels/TaggingPanel.tsx +1 -1
  111. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +4 -4
  112. package/src/components/resource/panels/__tests__/AssistSection.test.tsx +7 -7
  113. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +3 -3
  114. package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +2 -2
  115. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +64 -101
  116. package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +1 -1
  117. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +7 -7
  118. package/src/components/viewers/ImageViewer.tsx +3 -6
  119. package/src/components/viewers/__tests__/ImageViewer.test.tsx +3 -3
  120. package/src/features/admin-devops/__tests__/AdminDevOpsPage.test.tsx +5 -5
  121. package/src/features/admin-exchange/__tests__/AdminExchangePage.test.tsx +141 -0
  122. package/src/features/admin-exchange/__tests__/ExportCard.test.tsx +41 -0
  123. package/src/features/admin-exchange/__tests__/ImportCard.test.tsx +148 -0
  124. package/src/features/admin-exchange/__tests__/ImportProgress.test.tsx +106 -0
  125. package/src/features/admin-exchange/components/AdminExchangePage.tsx +120 -0
  126. package/src/features/admin-exchange/components/ExportCard.tsx +35 -0
  127. package/src/features/admin-exchange/components/ImportCard.tsx +188 -0
  128. package/src/features/admin-exchange/components/ImportProgress.tsx +86 -0
  129. package/src/features/admin-security/__tests__/AdminSecurityPage.test.tsx +3 -3
  130. package/src/features/moderate-entity-tags/__tests__/EntityTagsPage.test.tsx +2 -2
  131. package/src/features/moderate-recent/__tests__/RecentDocumentsPage.test.tsx +4 -4
  132. package/src/features/moderate-tag-schemas/__tests__/TagSchemasPage.test.tsx +3 -3
  133. package/src/features/moderation-linked-data/__tests__/LinkedDataPage.test.tsx +117 -0
  134. package/src/features/moderation-linked-data/components/LinkedDataPage.tsx +121 -0
  135. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +5 -5
  136. package/src/features/resource-compose/components/ResourceComposePage.tsx +56 -1
  137. package/src/features/resource-discovery/__tests__/ResourceCard.test.tsx +1 -1
  138. package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +2 -2
  139. package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +14 -14
  140. package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +12 -11
  141. package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +2 -2
  142. package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +22 -115
  143. package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +3 -3
  144. package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +20 -20
  145. package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +7 -7
  146. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +43 -20
  147. package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +2 -2
  148. package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +45 -82
  149. package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +4 -4
  150. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +151 -74
  151. package/src/integrations/tailwind-plugin.js +3 -3
  152. package/src/styles/core/buttons.css +31 -0
  153. package/src/styles/features/exchange.css +404 -0
  154. package/src/styles/index.css +1 -0
  155. package/translations/ar.json +42 -4
  156. package/translations/bn.json +42 -4
  157. package/translations/cs.json +42 -4
  158. package/translations/da.json +128 -90
  159. package/translations/de.json +122 -84
  160. package/translations/el.json +42 -4
  161. package/translations/en.json +42 -4
  162. package/translations/es.json +42 -4
  163. package/translations/fa.json +42 -4
  164. package/translations/fi.json +68 -30
  165. package/translations/fr.json +42 -4
  166. package/translations/he.json +42 -4
  167. package/translations/hi.json +42 -4
  168. package/translations/id.json +43 -5
  169. package/translations/it.json +62 -24
  170. package/translations/ja.json +43 -5
  171. package/translations/ko.json +42 -4
  172. package/translations/ms.json +43 -5
  173. package/translations/nl.json +41 -3
  174. package/translations/no.json +104 -66
  175. package/translations/pl.json +42 -4
  176. package/translations/pt.json +43 -5
  177. package/translations/ro.json +42 -4
  178. package/translations/sv.json +42 -4
  179. package/translations/th.json +42 -4
  180. package/translations/tr.json +42 -4
  181. package/translations/uk.json +42 -4
  182. package/translations/vi.json +42 -4
  183. package/translations/zh.json +42 -4
  184. package/dist/PdfAnnotationCanvas.client-COQREPXU.mjs.map +0 -1
  185. package/dist/ar-7SUXNE34.mjs.map +0 -1
  186. package/dist/bn-XOET3DOI.mjs.map +0 -1
  187. package/dist/chunk-JH7BXE2P.mjs.map +0 -1
  188. package/dist/cs-X63DXX7L.mjs.map +0 -1
  189. package/dist/da-OWTCV57A.mjs.map +0 -1
  190. package/dist/de-77BMFDVF.mjs.map +0 -1
  191. package/dist/el-FIBNLH2V.mjs.map +0 -1
  192. package/dist/es-726NTS53.mjs.map +0 -1
  193. package/dist/fa-3N4CIWE6.mjs.map +0 -1
  194. package/dist/fi-JOM3M7Z4.mjs.map +0 -1
  195. package/dist/fr-56QSXS7E.mjs.map +0 -1
  196. package/dist/he-SNAXPJEK.mjs.map +0 -1
  197. package/dist/hi-CRBRD5TB.mjs.map +0 -1
  198. package/dist/id-BRCVLICF.mjs.map +0 -1
  199. package/dist/it-M2Z27BNB.mjs.map +0 -1
  200. package/dist/ja-TZUKW7HD.mjs.map +0 -1
  201. package/dist/ko-NKBGGOL6.mjs.map +0 -1
  202. package/dist/ms-XFXPN6RX.mjs.map +0 -1
  203. package/dist/nl-MVYXAS5C.mjs.map +0 -1
  204. package/dist/no-XOLO4JPV.mjs.map +0 -1
  205. package/dist/pl-TRWLMMC4.mjs.map +0 -1
  206. package/dist/pt-M3TE24UI.mjs.map +0 -1
  207. package/dist/ro-QBFG2T64.mjs.map +0 -1
  208. package/dist/sv-IUECBXWX.mjs.map +0 -1
  209. package/dist/th-US7KIN5Q.mjs.map +0 -1
  210. package/dist/tr-DWJ2FFUK.mjs.map +0 -1
  211. package/dist/uk-M4ZE4DPZ.mjs.map +0 -1
  212. package/dist/zh-3J2I3WYK.mjs.map +0 -1
  213. package/src/examples/ButtonUsageExample.tsx +0 -242
  214. package/src/examples/button-css-modules.module.css +0 -164
  215. package/src/examples/button-styled-components.tsx +0 -215
  216. package/src/examples/button-tailwind.css +0 -51
  217. /package/dist/{chunk-Q2KV6Y2J.mjs.map → chunk-7GEYABC6.mjs.map} +0 -0
  218. /package/dist/{chunk-3JTO27MH.mjs.map → chunk-D4GAAQMM.mjs.map} +0 -0
  219. /package/dist/{en-XWEPVTB4.mjs.map → en-HAKDCFKL.mjs.map} +0 -0
  220. /package/dist/{magic-string.es-7FJ3LUGB.mjs.map → magic-string.es-K77I4ZQN.mjs.map} +0 -0
@@ -7,10 +7,9 @@
7
7
 
8
8
  import React, { useState, useEffect, useCallback, useMemo } from 'react';
9
9
  import { useQueryClient } from '@tanstack/react-query';
10
- import type { components, ResourceUri, ResourceEvent } from '@semiont/core';
11
- import { resourceAnnotationUri } from '@semiont/core';
10
+ import type { components, ResourceId, ResourceEvent, GatheredContext } from '@semiont/core';
11
+ import { annotationId } from '@semiont/core';
12
12
  import { getLanguage, getPrimaryRepresentation, getPrimaryMediaType } from '@semiont/api-client';
13
- import { uriToAnnotationId } from '@semiont/core';
14
13
  import { ANNOTATORS } from '@semiont/react-ui';
15
14
  import { ErrorBoundary } from '@semiont/react-ui';
16
15
  import { AnnotationHistory } from '@semiont/react-ui';
@@ -20,7 +19,6 @@ import { CollaborationPanel } from '@semiont/react-ui';
20
19
  import { JsonLdPanel } from '@semiont/react-ui';
21
20
  import { Toolbar } from '@semiont/react-ui';
22
21
  import { useResourceLoadingAnnouncements } from '@semiont/react-ui';
23
- import type { GenerationOptions } from '@semiont/react-ui';
24
22
  import { ResourceViewer } from '@semiont/react-ui';
25
23
  import { QUERY_KEYS } from '../../../lib/query-keys';
26
24
  import { useResources, useEntityTypes } from '../../../lib/api-hooks';
@@ -43,6 +41,9 @@ import { useBeckonFlow } from '../../../hooks/useBeckonFlow';
43
41
  import { usePanelBrowse } from '../../../hooks/usePanelBrowse';
44
42
  import { useYieldFlow } from '../../../hooks/useYieldFlow';
45
43
  import { useContextGatherFlow } from '../../../hooks/useContextGatherFlow';
44
+ import { useTranslations } from '../../../contexts/TranslationContext';
45
+ import { ReferenceWizardModal } from '../../../components/modals/ReferenceWizardModal';
46
+ import type { GenerationConfig } from '../../../components/modals/ConfigureGenerationStep';
46
47
 
47
48
  type SemiontResource = components['schemas']['ResourceDescriptor'];
48
49
  type Annotation = components['schemas']['Annotation'];
@@ -56,7 +57,7 @@ export interface ResourceViewerPageProps {
56
57
  /**
57
58
  * Resource URI
58
59
  */
59
- rUri: ResourceUri;
60
+ rUri: ResourceId;
60
61
 
61
62
  /**
62
63
  * Current locale
@@ -77,8 +78,6 @@ export interface ResourceViewerPageProps {
77
78
  * Component dependencies - passed from framework layer
78
79
  */
79
80
  ToolbarPanels: React.ComponentType<any>;
80
- SearchResourcesModal: React.ComponentType<any>;
81
- GenerationConfigModal: React.ComponentType<any>;
82
81
 
83
82
  /**
84
83
  * Callback to refetch document from parent
@@ -120,10 +119,11 @@ export function ResourceViewerPage({
120
119
  Link,
121
120
  routes,
122
121
  ToolbarPanels,
123
- SearchResourcesModal,
124
- GenerationConfigModal,
125
122
  refetchDocument,
126
123
  }: ResourceViewerPageProps) {
124
+ // Translations
125
+ const tw = useTranslations('ReferenceWizard');
126
+
127
127
  // Get unified event bus for subscribing to UI events
128
128
  const eventBus = useEventBus();
129
129
  const client = useApiClient();
@@ -160,16 +160,85 @@ export function ResourceViewerPage({
160
160
  const { hoveredAnnotationId } = useBeckonFlow();
161
161
  const { assistingMotivation, progress, pendingAnnotation } = useMarkFlow(rUri);
162
162
  const { activePanel, scrollToAnnotationId, panelInitialTab, onScrollCompleted } = usePanelBrowse();
163
- const { searchModalOpen, pendingReferenceId, onCloseSearchModal } = useBindFlow(rUri);
163
+ useBindFlow(rUri);
164
164
  const {
165
165
  generationProgress,
166
- generationModalOpen,
167
- generationReferenceId,
168
- generationDefaultTitle,
169
166
  onGenerateDocument,
170
- onCloseGenerationModal,
171
- } = useYieldFlow(locale, rUri.split('/').pop() || '', clearNewAnnotationId);
172
- const { gatherContext, gatherLoading, gatherError } = useContextGatherFlow(eventBus, { client, resourceUri: rUri });
167
+ } = useYieldFlow(locale, rUri, clearNewAnnotationId);
168
+ const { gatherContext, gatherLoading, gatherError } = useContextGatherFlow(eventBus, { client, resourceId: rUri });
169
+
170
+ // Wizard state — driven by bind:initiate from ReferenceEntry
171
+ const [wizardOpen, setWizardOpen] = useState(false);
172
+ const [wizardAnnotationId, setWizardAnnotationId] = useState<string | null>(null);
173
+ const [wizardResourceId, setWizardResourceId] = useState<string | null>(null);
174
+ const [wizardDefaultTitle, setWizardDefaultTitle] = useState('');
175
+ const [wizardEntityTypes, setWizardEntityTypes] = useState<string[]>([]);
176
+
177
+ useEffect(() => {
178
+ const subscription = eventBus.get('bind:initiate').subscribe((event) => {
179
+ setWizardAnnotationId(event.annotationId);
180
+ setWizardResourceId(event.resourceId);
181
+ setWizardDefaultTitle(event.defaultTitle);
182
+ setWizardEntityTypes(event.entityTypes);
183
+ setWizardOpen(true);
184
+
185
+ // Trigger context gathering
186
+ eventBus.get('gather:requested').next({ annotationId: event.annotationId, resourceId: event.resourceId });
187
+ });
188
+ return () => subscription.unsubscribe();
189
+ }, [eventBus]);
190
+
191
+ const handleWizardClose = useCallback(() => {
192
+ setWizardOpen(false);
193
+ }, []);
194
+
195
+ const handleWizardGenerateSubmit = useCallback((referenceId: string, config: GenerationConfig) => {
196
+ onGenerateDocument(referenceId, {
197
+ title: config.title,
198
+ prompt: config.prompt,
199
+ language: config.language,
200
+ temperature: config.temperature,
201
+ maxTokens: config.maxTokens,
202
+ context: config.context,
203
+ });
204
+ }, [onGenerateDocument]);
205
+
206
+ const handleWizardLinkResource = useCallback((referenceId: string, targetResourceId: string) => {
207
+ eventBus.get('bind:update-body').next({
208
+ annotationId: annotationId(referenceId),
209
+ resourceId: rUri,
210
+ operations: [{
211
+ op: 'add',
212
+ item: {
213
+ type: 'SpecificResource' as const,
214
+ source: targetResourceId,
215
+ purpose: 'linking' as const,
216
+ },
217
+ }],
218
+ });
219
+ showSuccess('Reference linked successfully');
220
+ }, [rUri, showSuccess]); // eventBus is stable singleton
221
+
222
+ const handleWizardComposeNavigate = useCallback((
223
+ context: GatheredContext,
224
+ annId: string,
225
+ resId: string,
226
+ title: string,
227
+ entTypes: string[],
228
+ ) => {
229
+ // Store context in sessionStorage for the compose page
230
+ sessionStorage.setItem(`gather-context:${annId}`, JSON.stringify(context));
231
+ const params = new URLSearchParams({
232
+ annotationUri: annId,
233
+ sourceDocumentId: resId,
234
+ name: title,
235
+ entityTypes: entTypes.join(','),
236
+ });
237
+ eventBus.get('browse:router-push').next({
238
+ path: `/know/compose?${params.toString()}`,
239
+ reason: 'compose-from-wizard',
240
+ });
241
+ }, []); // eventBus is stable singleton
173
242
 
174
243
  // Debounced invalidation for real-time events
175
244
  const debouncedInvalidateAnnotations = useDebouncedCallback(
@@ -183,11 +252,10 @@ export function ResourceViewerPage({
183
252
  // Add resource to open tabs when it loads
184
253
  useEffect(() => {
185
254
  if (resource && rUri) {
186
- const resourceIdSegment = rUri.split('/').pop() || '';
187
255
  const mediaType = getPrimaryMediaType(resource);
188
- addResource(resourceIdSegment, resource.name, mediaType || undefined);
256
+ addResource(rUri, resource.name, mediaType || undefined);
189
257
  if (typeof localStorage !== 'undefined') {
190
- localStorage.setItem('lastViewedDocumentId', resourceIdSegment);
258
+ localStorage.setItem('lastViewedDocumentId', rUri);
191
259
  }
192
260
  }
193
261
  }, [resource, rUri, addResource]);
@@ -213,8 +281,7 @@ export function ResourceViewerPage({
213
281
  return {
214
282
  ...old,
215
283
  annotations: old.annotations.map((annotation: any) => {
216
- const annotationIdSegment = uriToAnnotationId(annotation.id);
217
- if (annotationIdSegment === event.payload.annotationId) {
284
+ if (annotation.id === event.payload.annotationId) {
218
285
  let bodyArray = Array.isArray(annotation.body) ? [...annotation.body] : [];
219
286
 
220
287
  for (const op of event.payload.operations || []) {
@@ -283,7 +350,7 @@ export function ResourceViewerPage({
283
350
  // Event handlers extracted to useCallback (tenet: no inline handlers in useEventSubscriptions)
284
351
  const handleResourceArchive = useCallback(async () => {
285
352
  try {
286
- await updateMutation.mutateAsync({ rUri, data: { archived: true } });
353
+ await updateMutation.mutateAsync({ id: rUri, data: { archived: true } });
287
354
  await refetchDocument();
288
355
  } catch (err) {
289
356
  console.error('Failed to archive document:', err);
@@ -293,7 +360,7 @@ export function ResourceViewerPage({
293
360
 
294
361
  const handleResourceUnarchive = useCallback(async () => {
295
362
  try {
296
- await updateMutation.mutateAsync({ rUri, data: { archived: false } });
363
+ await updateMutation.mutateAsync({ id: rUri, data: { archived: false } });
297
364
  await refetchDocument();
298
365
  } catch (err) {
299
366
  console.error('Failed to unarchive document:', err);
@@ -361,8 +428,13 @@ export function ResourceViewerPage({
361
428
  }
362
429
  }, [routes.know]); // eventBus is stable singleton - never in deps
363
430
 
431
+ const handleModeToggled = useCallback(() => {
432
+ setAnnotateMode(prev => !prev);
433
+ }, []);
434
+
364
435
  // Event bus subscriptions (combined into single useEventSubscriptions call to prevent hook ordering issues)
365
436
  useEventSubscriptions({
437
+ 'mark:mode-toggled': handleModeToggled,
366
438
  'mark:archive': handleResourceArchive,
367
439
  'mark:unarchive': handleResourceUnarchive,
368
440
  'yield:clone': handleResourceClone,
@@ -406,8 +478,8 @@ export function ResourceViewerPage({
406
478
  const primaryMediaType = primaryRep?.mediaType;
407
479
  const primaryByteSize = primaryRep?.byteSize;
408
480
 
409
- // Annotate mode state - local UI state only
410
- const [annotateMode, _setAnnotateMode] = useState(() => {
481
+ // Annotate mode state - synced via mark:mode-toggled event from AnnotateToolbar
482
+ const [annotateMode, setAnnotateMode] = useState(() => {
411
483
  if (typeof window !== 'undefined') {
412
484
  return localStorage.getItem('annotateMode') === 'true';
413
485
  }
@@ -539,7 +611,7 @@ export function ResourceViewerPage({
539
611
  generatingReferenceId={generationProgress?.referenceId ?? null}
540
612
  referencedBy={referencedBy}
541
613
  referencedByLoading={referencedByLoading}
542
- resourceId={rUri.split('/').pop() || ''}
614
+ resourceId={rUri}
543
615
  scrollToAnnotationId={scrollToAnnotationId}
544
616
  hoveredAnnotationId={hoveredAnnotationId}
545
617
  onScrollCompleted={onScrollCompleted}
@@ -596,57 +668,62 @@ export function ResourceViewerPage({
596
668
  </div>
597
669
  </div>
598
670
 
599
- {/* Search Resources Modal */}
600
- <SearchResourcesModal
601
- isOpen={searchModalOpen}
602
- onClose={onCloseSearchModal}
603
- onSelect={async (documentId: string) => {
604
- if (pendingReferenceId) {
605
- try {
606
- const annotationIdShort = pendingReferenceId.split('/').pop();
607
- if (!annotationIdShort) {
608
- throw new Error('Invalid reference ID');
609
- }
610
-
611
- const resourceIdSegment = rUri.split('/').pop() || '';
612
- const nestedUri = `${window.location.origin}/resources/${resourceIdSegment}/annotations/${annotationIdShort}`;
613
-
614
- eventBus.get('bind:update-body').next({
615
- annotationUri: resourceAnnotationUri(nestedUri),
616
- resourceId: resourceIdSegment,
617
- operations: [{
618
- op: 'add',
619
- item: {
620
- type: 'SpecificResource' as const,
621
- source: documentId,
622
- purpose: 'linking' as const,
623
- },
624
- }],
625
- });
626
- showSuccess('Reference linked successfully');
627
- // Cache invalidation now handled by mark:body-updated event
628
- onCloseSearchModal();
629
- } catch (error) {
630
- console.error('Failed to link reference:', error);
631
- showError('Failed to link reference');
632
- }
633
- }
634
- }}
635
- />
636
-
637
- {/* Generation Config Modal */}
638
- <GenerationConfigModal
639
- isOpen={generationModalOpen}
640
- onClose={onCloseGenerationModal}
641
- onGenerate={(options: GenerationOptions) => {
642
- if (generationReferenceId) {
643
- onGenerateDocument(generationReferenceId, options);
644
- }
645
- }}
646
- defaultTitle={generationDefaultTitle}
671
+ {/* Reference Resolution Wizard */}
672
+ <ReferenceWizardModal
673
+ isOpen={wizardOpen}
674
+ onClose={handleWizardClose}
675
+ annotationId={wizardAnnotationId}
676
+ resourceId={wizardResourceId}
677
+ defaultTitle={wizardDefaultTitle}
678
+ entityTypes={wizardEntityTypes}
679
+ locale={locale}
647
680
  context={gatherContext}
648
681
  contextLoading={gatherLoading}
649
682
  contextError={gatherError}
683
+ eventBus={eventBus}
684
+ onGenerateSubmit={handleWizardGenerateSubmit}
685
+ onLinkResource={handleWizardLinkResource}
686
+ onComposeNavigate={handleWizardComposeNavigate}
687
+ translations={{
688
+ gatherTitle: tw('gatherTitle'),
689
+ configureGenerationTitle: tw('configureGenerationTitle'),
690
+ configureSearchTitle: tw('configureSearchTitle'),
691
+ searchResultsTitle: tw('searchResultsTitle'),
692
+ annotationLabel: tw('annotationLabel'),
693
+ sourceResourceLabel: tw('sourceResourceLabel'),
694
+ motivationLabel: tw('motivationLabel'),
695
+ sourceContextLabel: tw('sourceContextLabel'),
696
+ entityTypesLabel: tw('entityTypesLabel'),
697
+ graphContextLabel: tw('graphContextLabel'),
698
+ connectionsLabel: tw('connectionsLabel'),
699
+ citedByLabel: tw('citedByLabel'),
700
+ siblingTypesLabel: tw('siblingTypesLabel'),
701
+ loadingContext: tw('loadingContext'),
702
+ failedContext: tw('failedContext'),
703
+ cancel: tw('cancel'),
704
+ search: tw('search'),
705
+ searching: tw('searching'),
706
+ generate: tw('generate'),
707
+ compose: tw('compose'),
708
+ back: tw('back'),
709
+ link: tw('link'),
710
+ score: tw('score'),
711
+ noResults: tw('noResults'),
712
+ resourceTitle: tw('resourceTitle'),
713
+ resourceTitlePlaceholder: tw('resourceTitlePlaceholder'),
714
+ additionalInstructions: tw('additionalInstructions'),
715
+ additionalInstructionsPlaceholder: tw('additionalInstructionsPlaceholder'),
716
+ language: tw('language'),
717
+ languageHelp: tw('languageHelp'),
718
+ creativity: tw('creativity'),
719
+ creativityFocused: tw('creativityFocused'),
720
+ creativityCreative: tw('creativityCreative'),
721
+ maxLength: tw('maxLength'),
722
+ maxLengthHelp: tw('maxLengthHelp'),
723
+ maxResults: tw('maxResults'),
724
+ semanticScoring: tw('semanticScoring'),
725
+ semanticScoringHelp: tw('semanticScoringHelp'),
726
+ }}
650
727
  />
651
728
  </div>
652
729
  );
@@ -23,7 +23,7 @@ module.exports = plugin(function({ addBase, addComponents, addUtilities, theme }
23
23
  '.semiont-button': {
24
24
  '@apply relative inline-flex items-center justify-center': {},
25
25
  '@apply font-medium transition-all duration-200': {},
26
- '@apply focus:outline-none focus:ring-2 focus:ring-offset-2': {},
26
+ '@apply focus:outline-hidden focus:ring-2 focus:ring-offset-2': {},
27
27
  '@apply disabled:opacity-50 disabled:cursor-not-allowed': {},
28
28
  },
29
29
 
@@ -56,10 +56,10 @@ module.exports = plugin(function({ addBase, addComponents, addUtilities, theme }
56
56
 
57
57
  // Button sizes
58
58
  '.semiont-button[data-size="xs"]': {
59
- '@apply px-2 py-1 text-xs rounded min-h-[1.75rem]': {},
59
+ '@apply px-2 py-1 text-xs rounded-sm min-h-[1.75rem]': {},
60
60
  },
61
61
  '.semiont-button[data-size="sm"]': {
62
- '@apply px-3 py-1.5 text-sm rounded min-h-[2rem]': {},
62
+ '@apply px-3 py-1.5 text-sm rounded-sm min-h-[2rem]': {},
63
63
  },
64
64
  '.semiont-button[data-size="md"]': {
65
65
  '@apply px-4 py-2 text-base rounded-md min-h-[2.5rem]': {},
@@ -536,6 +536,37 @@
536
536
  border-color: var(--semiont-color-primary-400);
537
537
  }
538
538
 
539
+ /* Generating state pulse — reuses reference-button-pulse keyframes */
540
+ .semiont-button--primary[data-generating="true"] {
541
+ animation: semiont-button-pulse 1.5s ease-in-out infinite;
542
+ }
543
+
544
+ [data-theme="dark"] .semiont-button--primary[data-generating="true"] {
545
+ animation: semiont-button-pulse-dark 1.5s ease-in-out infinite;
546
+ }
547
+
548
+ @keyframes semiont-button-pulse {
549
+ 0%, 100% {
550
+ transform: scale(1);
551
+ box-shadow: 0 0 8px 2px rgba(59, 130, 246, 0.5);
552
+ }
553
+ 50% {
554
+ transform: scale(1.05);
555
+ box-shadow: 0 0 16px 4px rgba(59, 130, 246, 0.8);
556
+ }
557
+ }
558
+
559
+ @keyframes semiont-button-pulse-dark {
560
+ 0%, 100% {
561
+ transform: scale(1);
562
+ box-shadow: 0 0 8px 2px rgba(96, 165, 250, 0.6);
563
+ }
564
+ 50% {
565
+ transform: scale(1.05);
566
+ box-shadow: 0 0 16px 4px rgba(96, 165, 250, 0.9);
567
+ }
568
+ }
569
+
539
570
  /* Large variant */
540
571
  .semiont-button--large {
541
572
  width: 100%;