@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
@@ -0,0 +1,326 @@
1
+ 'use client';
2
+
3
+ import { useState, useEffect, useCallback } from 'react';
4
+ import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react';
5
+ import type { GatheredContext, EventBus } from '@semiont/core';
6
+ import { GatherContextStep } from './GatherContextStep';
7
+ import { ConfigureGenerationStep } from './ConfigureGenerationStep';
8
+ import type { GenerationConfig } from './ConfigureGenerationStep';
9
+ import { ConfigureSearchStep } from './ConfigureSearchStep';
10
+ import type { SearchConfig } from './ConfigureSearchStep';
11
+ import { SearchResultsStep } from './SearchResultsStep';
12
+ import type { ScoredResult } from './SearchResultsStep';
13
+
14
+ type WizardStep =
15
+ | { step: 'gather' }
16
+ | { step: 'configure-search' }
17
+ | { step: 'search-results'; results: ScoredResult[] }
18
+ | { step: 'configure-generation' };
19
+
20
+ export interface ReferenceWizardModalProps {
21
+ isOpen: boolean;
22
+ onClose: () => void;
23
+ /** The annotation being resolved */
24
+ annotationId: string | null;
25
+ /** The resource containing the annotation */
26
+ resourceId: string | null;
27
+ /** Default title (selected text) */
28
+ defaultTitle: string;
29
+ /** Entity types from the annotation */
30
+ entityTypes: string[];
31
+ /** Current locale for generation defaults */
32
+ locale: string;
33
+ /** Gathered context state */
34
+ context: GatheredContext | null;
35
+ contextLoading: boolean;
36
+ contextError: Error | null;
37
+ /** Event bus for emitting downstream events */
38
+ eventBus: EventBus;
39
+ /** Callbacks */
40
+ onGenerateSubmit: (referenceId: string, config: GenerationConfig) => void;
41
+ onLinkResource: (referenceId: string, targetResourceId: string) => void;
42
+ onComposeNavigate: (context: GatheredContext, annotationId: string, resourceId: string, title: string, entityTypes: string[]) => void;
43
+ /** Translation strings */
44
+ translations: {
45
+ gatherTitle: string;
46
+ configureGenerationTitle: string;
47
+ configureSearchTitle: string;
48
+ searchResultsTitle: string;
49
+ annotationLabel: string;
50
+ sourceResourceLabel: string;
51
+ motivationLabel: string;
52
+ sourceContextLabel: string;
53
+ entityTypesLabel: string;
54
+ graphContextLabel: string;
55
+ connectionsLabel: string;
56
+ citedByLabel: string;
57
+ siblingTypesLabel: string;
58
+ loadingContext: string;
59
+ failedContext: string;
60
+ cancel: string;
61
+ search: string;
62
+ searching: string;
63
+ generate: string;
64
+ compose: string;
65
+ back: string;
66
+ link: string;
67
+ score: string;
68
+ noResults: string;
69
+ resourceTitle: string;
70
+ resourceTitlePlaceholder: string;
71
+ additionalInstructions: string;
72
+ additionalInstructionsPlaceholder: string;
73
+ language: string;
74
+ languageHelp: string;
75
+ creativity: string;
76
+ creativityFocused: string;
77
+ creativityCreative: string;
78
+ maxLength: string;
79
+ maxLengthHelp: string;
80
+ maxResults: string;
81
+ semanticScoring: string;
82
+ semanticScoringHelp: string;
83
+ };
84
+ }
85
+
86
+ export function ReferenceWizardModal({
87
+ isOpen,
88
+ onClose,
89
+ annotationId,
90
+ resourceId,
91
+ defaultTitle,
92
+ entityTypes,
93
+ locale,
94
+ context,
95
+ contextLoading,
96
+ contextError,
97
+ eventBus,
98
+ onGenerateSubmit,
99
+ onLinkResource,
100
+ onComposeNavigate,
101
+ translations: t,
102
+ }: ReferenceWizardModalProps) {
103
+ const [wizardStep, setWizardStep] = useState<WizardStep>({ step: 'gather' });
104
+ const [isSearching, setIsSearching] = useState(false);
105
+
106
+ // Reset to gather step when modal opens
107
+ useEffect(() => {
108
+ if (isOpen) {
109
+ setWizardStep({ step: 'gather' });
110
+ setIsSearching(false);
111
+ }
112
+ }, [isOpen]);
113
+
114
+ // Subscribe to search results
115
+ useEffect(() => {
116
+ if (!isOpen) return;
117
+
118
+ const subscription = eventBus.get('bind:search-results').subscribe((event) => {
119
+ if (annotationId && event.referenceId === annotationId) {
120
+ setIsSearching(false);
121
+ setWizardStep({ step: 'search-results', results: event.results as ScoredResult[] });
122
+ }
123
+ });
124
+
125
+ return () => subscription.unsubscribe();
126
+ }, [isOpen, eventBus, annotationId]);
127
+
128
+ const handleBind = useCallback(() => {
129
+ setWizardStep({ step: 'configure-search' });
130
+ }, []);
131
+
132
+ const handleGenerate = useCallback(() => {
133
+ setWizardStep({ step: 'configure-generation' });
134
+ }, []);
135
+
136
+ const handleCompose = useCallback(() => {
137
+ if (!context || !annotationId || !resourceId) return;
138
+ onComposeNavigate(context, annotationId, resourceId, defaultTitle, entityTypes);
139
+ onClose();
140
+ }, [context, annotationId, resourceId, defaultTitle, entityTypes, onComposeNavigate, onClose]);
141
+
142
+ const handleBackToGather = useCallback(() => {
143
+ setWizardStep({ step: 'gather' });
144
+ }, []);
145
+
146
+ const handleSearchSubmit = useCallback((config: SearchConfig) => {
147
+ if (!annotationId || !context) return;
148
+ setIsSearching(true);
149
+ eventBus.get('bind:search-requested').next({
150
+ referenceId: annotationId,
151
+ context,
152
+ limit: config.limit,
153
+ useSemanticScoring: config.useSemanticScoring,
154
+ });
155
+ // Stay on configure-search until results arrive (subscription above handles transition)
156
+ }, [annotationId, context, eventBus]);
157
+
158
+ const handleGenerateSubmit = useCallback((config: GenerationConfig) => {
159
+ if (!annotationId) return;
160
+ onGenerateSubmit(annotationId, config);
161
+ onClose();
162
+ }, [annotationId, onGenerateSubmit, onClose]);
163
+
164
+ const handleLink = useCallback((targetResourceId: string) => {
165
+ if (!annotationId) return;
166
+ onLinkResource(annotationId, targetResourceId);
167
+ onClose();
168
+ }, [annotationId, onLinkResource, onClose]);
169
+
170
+ // Determine title based on step
171
+ const stepTitle = wizardStep.step === 'gather'
172
+ ? t.gatherTitle
173
+ : wizardStep.step === 'configure-generation'
174
+ ? t.configureGenerationTitle
175
+ : wizardStep.step === 'configure-search'
176
+ ? t.configureSearchTitle
177
+ : t.searchResultsTitle;
178
+
179
+ return (
180
+ <Transition appear show={isOpen}>
181
+ <Dialog as="div" className="semiont-search-modal" onClose={onClose}>
182
+ {/* Backdrop */}
183
+ <TransitionChild
184
+ enter="ease-out duration-200"
185
+ enterFrom="opacity-0"
186
+ enterTo="opacity-100"
187
+ leave="ease-in duration-150"
188
+ leaveFrom="opacity-100"
189
+ leaveTo="opacity-0"
190
+ >
191
+ <div className="semiont-search-modal__backdrop" />
192
+ </TransitionChild>
193
+
194
+ {/* Modal panel */}
195
+ <div className="semiont-search-modal__wrapper">
196
+ <div className="semiont-search-modal__centering semiont-search-modal__centering--center">
197
+ <TransitionChild
198
+ enter="ease-out duration-200"
199
+ enterFrom="opacity-0 scale-95"
200
+ enterTo="opacity-100 scale-100"
201
+ leave="ease-in duration-150"
202
+ leaveFrom="opacity-100 scale-100"
203
+ leaveTo="opacity-0 scale-95"
204
+ >
205
+ <DialogPanel className={`semiont-search-modal__panel semiont-search-modal__panel--with-border${wizardStep.step === 'search-results' ? ' semiont-search-modal__panel--wide' : ''}`}>
206
+ <div className="semiont-search-modal__header">
207
+ <DialogTitle className="semiont-search-modal__title">
208
+ {stepTitle}
209
+ </DialogTitle>
210
+ <button
211
+ onClick={onClose}
212
+ className="semiont-search-modal__close-button"
213
+ aria-label="Close"
214
+ >
215
+
216
+ </button>
217
+ </div>
218
+
219
+ {wizardStep.step === 'gather' && (
220
+ <GatherContextStep
221
+ context={context}
222
+ contextLoading={contextLoading}
223
+ contextError={contextError}
224
+ onCancel={onClose}
225
+ onBind={handleBind}
226
+ onGenerate={handleGenerate}
227
+ onCompose={handleCompose}
228
+ translations={{
229
+ title: t.gatherTitle,
230
+ annotationLabel: t.annotationLabel,
231
+ sourceResourceLabel: t.sourceResourceLabel,
232
+ motivationLabel: t.motivationLabel,
233
+ sourceContextLabel: t.sourceContextLabel,
234
+ entityTypesLabel: t.entityTypesLabel,
235
+ graphContextLabel: t.graphContextLabel,
236
+ connectionsLabel: t.connectionsLabel,
237
+ citedByLabel: t.citedByLabel,
238
+ siblingTypesLabel: t.siblingTypesLabel,
239
+ loadingContext: t.loadingContext,
240
+ failedContext: t.failedContext,
241
+ cancel: t.cancel,
242
+ search: t.search,
243
+ generate: t.generate,
244
+ compose: t.compose,
245
+ }}
246
+ />
247
+ )}
248
+
249
+ {wizardStep.step === 'configure-generation' && context && (
250
+ <ConfigureGenerationStep
251
+ defaultTitle={defaultTitle}
252
+ locale={locale}
253
+ context={context}
254
+ onBack={handleBackToGather}
255
+ onCancel={onClose}
256
+ onGenerate={handleGenerateSubmit}
257
+ translations={{
258
+ resourceTitle: t.resourceTitle,
259
+ resourceTitlePlaceholder: t.resourceTitlePlaceholder,
260
+ additionalInstructions: t.additionalInstructions,
261
+ additionalInstructionsPlaceholder: t.additionalInstructionsPlaceholder,
262
+ language: t.language,
263
+ languageHelp: t.languageHelp,
264
+ creativity: t.creativity,
265
+ creativityFocused: t.creativityFocused,
266
+ creativityCreative: t.creativityCreative,
267
+ maxLength: t.maxLength,
268
+ maxLengthHelp: t.maxLengthHelp,
269
+ cancel: t.cancel,
270
+ back: t.back,
271
+ generate: t.generate,
272
+ }}
273
+ />
274
+ )}
275
+
276
+ {wizardStep.step === 'configure-search' && (
277
+ <ConfigureSearchStep
278
+ isSearching={isSearching}
279
+ onBack={handleBackToGather}
280
+ onCancel={onClose}
281
+ onSearch={handleSearchSubmit}
282
+ translations={{
283
+ maxResults: t.maxResults,
284
+ semanticScoring: t.semanticScoring,
285
+ semanticScoringHelp: t.semanticScoringHelp,
286
+ cancel: t.cancel,
287
+ back: t.back,
288
+ search: t.search,
289
+ searching: t.searching,
290
+ }}
291
+ />
292
+ )}
293
+
294
+ {wizardStep.step === 'search-results' && context && (
295
+ <SearchResultsStep
296
+ results={wizardStep.results}
297
+ context={context}
298
+ onLink={handleLink}
299
+ onBack={handleBackToGather}
300
+ onCancel={onClose}
301
+ translations={{
302
+ noResults: t.noResults,
303
+ link: t.link,
304
+ back: t.back,
305
+ cancel: t.cancel,
306
+ score: t.score,
307
+ annotationLabel: t.annotationLabel,
308
+ sourceResourceLabel: t.sourceResourceLabel,
309
+ motivationLabel: t.motivationLabel,
310
+ sourceContextLabel: t.sourceContextLabel,
311
+ entityTypesLabel: t.entityTypesLabel,
312
+ graphContextLabel: t.graphContextLabel,
313
+ connectionsLabel: t.connectionsLabel,
314
+ citedByLabel: t.citedByLabel,
315
+ siblingTypesLabel: t.siblingTypesLabel,
316
+ }}
317
+ />
318
+ )}
319
+ </DialogPanel>
320
+ </TransitionChild>
321
+ </div>
322
+ </div>
323
+ </Dialog>
324
+ </Transition>
325
+ );
326
+ }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import React, { useState, useEffect, Fragment } from 'react';
3
+ import React, { useState, useEffect } from 'react';
4
4
  import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react';
5
5
  import { useResources } from '../../lib/api-hooks';
6
6
  import { useSearchAnnouncements } from '../../hooks/useSearchAnnouncements';
@@ -103,12 +103,11 @@ export function ResourceSearchModal({
103
103
  };
104
104
 
105
105
  return (
106
- <Transition appear show={isOpen} as={Fragment}>
106
+ <Transition appear show={isOpen}>
107
107
  <Dialog as="div" className="semiont-search-modal semiont-search-modal--resource" onClose={onClose}>
108
108
  {/* Backdrop */}
109
109
  <TransitionChild
110
- as={Fragment}
111
- enter="ease-out duration-200"
110
+ enter="ease-out duration-200"
112
111
  enterFrom="opacity-0"
113
112
  enterTo="opacity-100"
114
113
  leave="ease-in duration-150"
@@ -122,8 +121,7 @@ export function ResourceSearchModal({
122
121
  <div className="semiont-search-modal__wrapper">
123
122
  <div className="semiont-search-modal__centering semiont-search-modal__centering--center">
124
123
  <TransitionChild
125
- as={Fragment}
126
- enter="ease-out duration-200"
124
+ enter="ease-out duration-200"
127
125
  enterFrom="opacity-0 scale-95"
128
126
  enterTo="opacity-100 scale-100"
129
127
  leave="ease-in duration-150"
@@ -461,3 +461,46 @@
461
461
  [data-theme="dark"] .semiont-search-modal__resource-media-type {
462
462
  color: var(--semiont-color-gray-500);
463
463
  }
464
+
465
+ /* Wide panel variant for two-pane layouts */
466
+ .semiont-search-modal__panel--wide {
467
+ max-width: 1100px;
468
+ }
469
+
470
+ /* Two-pane layout for search results + context */
471
+ .semiont-search-results__two-pane {
472
+ display: flex;
473
+ gap: 1.5rem;
474
+ }
475
+
476
+ .semiont-search-results__context-pane {
477
+ flex: 0 0 340px;
478
+ max-height: 500px;
479
+ overflow-y: auto;
480
+ }
481
+
482
+ .semiont-search-results__results-pane {
483
+ flex: 1;
484
+ max-height: 500px;
485
+ overflow-y: auto;
486
+ }
487
+
488
+ /* Narrow screens: stack vertically, context above results */
489
+ @media (max-width: 640px) {
490
+ .semiont-search-modal__panel--wide {
491
+ max-width: 100%;
492
+ }
493
+
494
+ .semiont-search-results__two-pane {
495
+ flex-direction: column;
496
+ }
497
+
498
+ .semiont-search-results__context-pane {
499
+ flex: none;
500
+ max-height: 200px;
501
+ }
502
+
503
+ .semiont-search-results__results-pane {
504
+ max-height: 350px;
505
+ }
506
+ }
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import React, { useState, useEffect, Fragment } from 'react';
3
+ import React, { useState, useEffect } from 'react';
4
4
  import { Dialog, DialogPanel, Transition, TransitionChild } from '@headlessui/react';
5
5
  // import { useResources } from '../../hooks/useResources';
6
6
  import { useSearchAnnouncements } from '../../hooks/useSearchAnnouncements';
@@ -134,12 +134,11 @@ export function SearchModal({
134
134
  };
135
135
 
136
136
  return (
137
- <Transition appear show={isOpen} as={Fragment}>
137
+ <Transition appear show={isOpen}>
138
138
  <Dialog as="div" className="semiont-search-modal" onClose={onClose}>
139
139
  {/* Backdrop */}
140
140
  <TransitionChild
141
- as={Fragment}
142
- enter="ease-out duration-200"
141
+ enter="ease-out duration-200"
143
142
  enterFrom="opacity-0"
144
143
  enterTo="opacity-100"
145
144
  leave="ease-in duration-150"
@@ -153,8 +152,7 @@ export function SearchModal({
153
152
  <div className="semiont-search-modal__wrapper">
154
153
  <div className="semiont-search-modal__centering">
155
154
  <TransitionChild
156
- as={Fragment}
157
- enter="ease-out duration-200"
155
+ enter="ease-out duration-200"
158
156
  enterFrom="opacity-0 scale-95"
159
157
  enterTo="opacity-100 scale-100"
160
158
  leave="ease-in duration-150"
@@ -0,0 +1,126 @@
1
+ 'use client';
2
+
3
+ import type { components, GatheredContext } from '@semiont/core';
4
+ import { ContextSummary } from './ContextSummary';
5
+ import type { ContextSummaryTranslations } from './ContextSummary';
6
+
7
+ type ResourceDescriptor = components['schemas']['ResourceDescriptor'];
8
+
9
+ export type ScoredResult = ResourceDescriptor & {
10
+ score?: number;
11
+ matchReason?: string;
12
+ };
13
+
14
+ export interface SearchResultsStepProps {
15
+ results: ScoredResult[];
16
+ context: GatheredContext;
17
+ onLink: (resourceId: string) => void;
18
+ onBack: () => void;
19
+ onCancel: () => void;
20
+ translations: {
21
+ noResults: string;
22
+ link: string;
23
+ back: string;
24
+ cancel: string;
25
+ score: string;
26
+ } & ContextSummaryTranslations;
27
+ }
28
+
29
+ export function SearchResultsStep({
30
+ results,
31
+ context,
32
+ onLink,
33
+ onBack,
34
+ onCancel,
35
+ translations: t,
36
+ }: SearchResultsStepProps) {
37
+ return (
38
+ <>
39
+ {/* Two-pane layout: context left, results right */}
40
+ <div className="semiont-search-results__two-pane">
41
+ {/* Left: Gathered Context */}
42
+ <div className="semiont-search-results__context-pane">
43
+ <ContextSummary context={context} translations={t} />
44
+ </div>
45
+
46
+ {/* Right: Results List */}
47
+ <div className="semiont-search-results__results-pane">
48
+ {results.length === 0 ? (
49
+ <div className="semiont-modal__empty-state" style={{ textAlign: 'center', padding: '2rem 0' }}>
50
+ {t.noResults}
51
+ </div>
52
+ ) : (
53
+ results.map((result) => {
54
+ const id = result['@id'];
55
+ return (
56
+ <div
57
+ key={id}
58
+ style={{
59
+ padding: '0.75rem',
60
+ borderBottom: '1px solid var(--semiont-border-primary)',
61
+ display: 'flex',
62
+ alignItems: 'center',
63
+ justifyContent: 'space-between',
64
+ gap: '0.75rem',
65
+ }}
66
+ >
67
+ <div style={{ flex: 1, minWidth: 0 }}>
68
+ <div style={{ fontWeight: 500, color: 'var(--semiont-text-primary)' }}>
69
+ {result.name}
70
+ </div>
71
+ {result.description && (
72
+ <div style={{
73
+ fontSize: 'var(--semiont-text-sm)',
74
+ color: 'var(--semiont-text-secondary)',
75
+ marginTop: '0.25rem',
76
+ overflow: 'hidden',
77
+ textOverflow: 'ellipsis',
78
+ whiteSpace: 'nowrap',
79
+ }}>
80
+ {result.description}
81
+ </div>
82
+ )}
83
+ <div style={{ fontSize: 'var(--semiont-text-xs)', color: 'var(--semiont-text-tertiary)', marginTop: '0.25rem', display: 'flex', gap: '0.5rem' }}>
84
+ {result.score !== undefined && (
85
+ <span>{t.score}: {result.score}</span>
86
+ )}
87
+ {result.matchReason && (
88
+ <span>{result.matchReason}</span>
89
+ )}
90
+ </div>
91
+ </div>
92
+ <button
93
+ type="button"
94
+ onClick={() => onLink(id)}
95
+ className="semiont-button--primary"
96
+ style={{ flexShrink: 0 }}
97
+ >
98
+ 🔗 {t.link}
99
+ </button>
100
+ </div>
101
+ );
102
+ })
103
+ )}
104
+ </div>
105
+ </div>
106
+
107
+ {/* Action Buttons */}
108
+ <div className="semiont-modal__actions" style={{ paddingTop: '0.5rem' }}>
109
+ <button
110
+ type="button"
111
+ onClick={onCancel}
112
+ className="semiont-button--secondary semiont-button--flex"
113
+ >
114
+ ✕ {t.cancel}
115
+ </button>
116
+ <button
117
+ type="button"
118
+ onClick={onBack}
119
+ className="semiont-button--secondary semiont-button--flex"
120
+ >
121
+ ◀ {t.back}
122
+ </button>
123
+ </div>
124
+ </>
125
+ );
126
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useRef, useState, useCallback, useEffect, useMemo } from 'react';
4
4
  import { createHoverHandlers } from '../../hooks/useBeckonFlow';
5
- import type { components, ResourceUri } from '@semiont/core';
5
+ import type { components, ResourceId } from '@semiont/core';
6
6
  import { getTargetSelector } from '@semiont/api-client';
7
7
  import type { SelectionMotivation } from '../annotation/AnnotateToolbar';
8
8
  import type { EventBus } from "@semiont/core"
@@ -48,7 +48,7 @@ function getMotivationColor(motivation: SelectionMotivation | null): { stroke: s
48
48
  }
49
49
 
50
50
  interface PdfAnnotationCanvasProps {
51
- resourceUri: ResourceUri;
51
+ resourceUri: ResourceId;
52
52
  existingAnnotations?: Annotation[];
53
53
  drawingMode: DrawingMode;
54
54
  selectedMotivation?: SelectionMotivation | null;
@@ -76,8 +76,7 @@ export function PdfAnnotationCanvas({
76
76
  hoverDelayMs = 150
77
77
  }: PdfAnnotationCanvasProps) {
78
78
  const pdfUrl = useMemo(() => {
79
- const resourceId = resourceUri.split('/').pop();
80
- return `/api/resources/${resourceId}`;
79
+ return `/api/resources/${resourceUri}`;
81
80
  }, [resourceUri]);
82
81
 
83
82
  // Removed excessive logging