@semiont/react-ui 0.2.46 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{PdfAnnotationCanvas.client-COQREPXU.mjs → PdfAnnotationCanvas.client-PVTVPDBQ.mjs} +3 -4
- package/dist/PdfAnnotationCanvas.client-PVTVPDBQ.mjs.map +1 -0
- package/dist/{ar-7SUXNE34.mjs → ar-5REA6P4J.mjs} +48 -6
- package/dist/ar-5REA6P4J.mjs.map +1 -0
- package/dist/{bn-XOET3DOI.mjs → bn-YHRYHHPD.mjs} +48 -6
- package/dist/bn-YHRYHHPD.mjs.map +1 -0
- package/dist/{chunk-3JTO27MH.mjs → chunk-D4GAAQMM.mjs} +2 -9
- package/dist/{chunk-Q2KV6Y2J.mjs → chunk-PFQYNPQJ.mjs} +32 -32
- package/dist/{chunk-JH7BXE2P.mjs → chunk-VVCCMJS7.mjs} +47 -5
- package/dist/chunk-VVCCMJS7.mjs.map +1 -0
- package/dist/{cs-X63DXX7L.mjs → cs-JTJXTX2T.mjs} +48 -6
- package/dist/cs-JTJXTX2T.mjs.map +1 -0
- package/dist/{da-OWTCV57A.mjs → da-MK37SJB6.mjs} +48 -6
- package/dist/da-MK37SJB6.mjs.map +1 -0
- package/dist/{de-77BMFDVF.mjs → de-LGBCWERA.mjs} +48 -6
- package/dist/de-LGBCWERA.mjs.map +1 -0
- package/dist/dist-YLEIY3JJ.mjs +547 -0
- package/dist/dist-YLEIY3JJ.mjs.map +1 -0
- package/dist/{el-FIBNLH2V.mjs → el-FKJMFCWY.mjs} +48 -6
- package/dist/el-FKJMFCWY.mjs.map +1 -0
- package/dist/{en-XWEPVTB4.mjs → en-AOSMPC2M.mjs} +5 -3
- package/dist/{es-726NTS53.mjs → es-LVDPIXWU.mjs} +48 -6
- package/dist/es-LVDPIXWU.mjs.map +1 -0
- package/dist/{fa-3N4CIWE6.mjs → fa-3VA2PIUD.mjs} +48 -6
- package/dist/fa-3VA2PIUD.mjs.map +1 -0
- package/dist/{fi-JOM3M7Z4.mjs → fi-3WM75ZLR.mjs} +48 -6
- package/dist/fi-3WM75ZLR.mjs.map +1 -0
- package/dist/{fr-56QSXS7E.mjs → fr-NK4A72WA.mjs} +48 -6
- package/dist/fr-NK4A72WA.mjs.map +1 -0
- package/dist/{he-SNAXPJEK.mjs → he-IACZDZMB.mjs} +48 -6
- package/dist/he-IACZDZMB.mjs.map +1 -0
- package/dist/{hi-CRBRD5TB.mjs → hi-JZ7MGMMS.mjs} +48 -6
- package/dist/hi-JZ7MGMMS.mjs.map +1 -0
- package/dist/{id-BRCVLICF.mjs → id-P3KDQGNK.mjs} +48 -6
- package/dist/id-P3KDQGNK.mjs.map +1 -0
- package/dist/index.css +123 -12
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +353 -107
- package/dist/index.mjs +3139 -1811
- package/dist/index.mjs.map +1 -1
- package/dist/{it-M2Z27BNB.mjs → it-LQS33SUY.mjs} +48 -6
- package/dist/it-LQS33SUY.mjs.map +1 -0
- package/dist/{ja-TZUKW7HD.mjs → ja-G4FKZPWD.mjs} +48 -6
- package/dist/ja-G4FKZPWD.mjs.map +1 -0
- package/dist/{ko-NKBGGOL6.mjs → ko-2XWKQ7BA.mjs} +48 -6
- package/dist/ko-2XWKQ7BA.mjs.map +1 -0
- package/dist/{magic-string.es-7FJ3LUGB.mjs → magic-string.es-K77I4ZQN.mjs} +2 -2
- package/dist/{ms-XFXPN6RX.mjs → ms-2SNONIUD.mjs} +48 -6
- package/dist/ms-2SNONIUD.mjs.map +1 -0
- package/dist/{nl-MVYXAS5C.mjs → nl-BMZUAJ7J.mjs} +48 -6
- package/dist/nl-BMZUAJ7J.mjs.map +1 -0
- package/dist/{no-XOLO4JPV.mjs → no-6J3WIZ6L.mjs} +48 -6
- package/dist/no-6J3WIZ6L.mjs.map +1 -0
- package/dist/{pl-TRWLMMC4.mjs → pl-QQ7DAUVK.mjs} +48 -6
- package/dist/pl-QQ7DAUVK.mjs.map +1 -0
- package/dist/{pt-M3TE24UI.mjs → pt-MU3GN7MW.mjs} +48 -6
- package/dist/pt-MU3GN7MW.mjs.map +1 -0
- package/dist/{ro-QBFG2T64.mjs → ro-6GBE72QK.mjs} +48 -6
- package/dist/ro-6GBE72QK.mjs.map +1 -0
- package/dist/{sv-IUECBXWX.mjs → sv-NQIL7PEM.mjs} +48 -6
- package/dist/sv-NQIL7PEM.mjs.map +1 -0
- package/dist/test-utils.mjs +16994 -22140
- package/dist/test-utils.mjs.map +1 -1
- package/dist/{th-US7KIN5Q.mjs → th-6OCNZQBE.mjs} +48 -6
- package/dist/th-6OCNZQBE.mjs.map +1 -0
- package/dist/{tr-DWJ2FFUK.mjs → tr-XWJ5P3SC.mjs} +48 -6
- package/dist/tr-XWJ5P3SC.mjs.map +1 -0
- package/dist/{uk-M4ZE4DPZ.mjs → uk-AKSN6DGW.mjs} +48 -6
- package/dist/uk-AKSN6DGW.mjs.map +1 -0
- package/dist/{vi-FERZNPSH.mjs → vi-23GHQ45M.mjs} +48 -6
- package/dist/vi-23GHQ45M.mjs.map +1 -0
- package/dist/{zh-3J2I3WYK.mjs → zh-ITT4QBSN.mjs} +48 -6
- package/dist/zh-ITT4QBSN.mjs.map +1 -0
- package/package.json +18 -14
- package/src/components/Button/Button.tsx +23 -25
- package/src/components/annotation/AnnotateToolbar.tsx +1 -1
- package/src/components/annotation-popups/SharedPopupElements.tsx +5 -7
- package/src/components/image-annotation/SvgDrawingCanvas.tsx +3 -4
- package/src/components/modals/ConfigureGenerationStep.tsx +190 -0
- package/src/components/modals/ConfigureSearchStep.tsx +105 -0
- package/src/components/modals/ContextSummary.tsx +202 -0
- package/src/components/modals/GatherContextStep.tsx +93 -0
- package/src/components/modals/KeyboardShortcutsHelpModal.tsx +4 -6
- package/src/components/modals/ProposeEntitiesModal.tsx +4 -6
- package/src/components/modals/ReferenceWizardModal.tsx +338 -0
- package/src/components/modals/ResourceSearchModal.tsx +4 -6
- package/src/components/modals/SearchModal.css +43 -0
- package/src/components/modals/SearchModal.tsx +4 -6
- package/src/components/modals/SearchResultsStep.tsx +126 -0
- package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +3 -4
- package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +36 -14
- package/src/components/resource/AnnotateView.tsx +4 -4
- package/src/components/resource/AnnotationHistory.tsx +2 -2
- package/src/components/resource/BrowseView.tsx +4 -4
- package/src/components/resource/ResourceViewer.tsx +4 -7
- package/src/components/resource/__tests__/AnnotationHistory.test.tsx +16 -16
- package/src/components/resource/__tests__/BrowseView.test.tsx +2 -2
- package/src/components/resource/__tests__/HistoryEvent.test.tsx +1 -1
- package/src/components/resource/__tests__/ResourceViewer.mode-switch.test.tsx +1 -1
- package/src/components/resource/panels/AssessmentEntry.tsx +9 -11
- package/src/components/resource/panels/CommentEntry.tsx +10 -12
- package/src/components/resource/panels/HighlightEntry.tsx +9 -11
- package/src/components/resource/panels/ReferenceEntry.tsx +57 -104
- package/src/components/resource/panels/ReferencesPanel.css +94 -13
- package/src/components/resource/panels/ReferencesPanel.tsx +1 -2
- package/src/components/resource/panels/TagEntry.tsx +9 -11
- package/src/components/resource/panels/__tests__/AssistSection.test.tsx +7 -7
- package/src/components/resource/panels/__tests__/HighlightPanel.annotationProgress.test.tsx +2 -2
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +64 -101
- package/src/components/resource/panels/__tests__/StatisticsPanel.test.tsx +1 -1
- package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +3 -3
- package/src/components/viewers/ImageViewer.tsx +3 -6
- package/src/components/viewers/__tests__/ImageViewer.test.tsx +3 -3
- package/src/features/admin-devops/__tests__/AdminDevOpsPage.test.tsx +5 -5
- package/src/features/admin-exchange/__tests__/AdminExchangePage.test.tsx +141 -0
- package/src/features/admin-exchange/__tests__/ExportCard.test.tsx +41 -0
- package/src/features/admin-exchange/__tests__/ImportCard.test.tsx +148 -0
- package/src/features/admin-exchange/__tests__/ImportProgress.test.tsx +106 -0
- package/src/features/admin-exchange/components/AdminExchangePage.tsx +120 -0
- package/src/features/admin-exchange/components/ExportCard.tsx +35 -0
- package/src/features/admin-exchange/components/ImportCard.tsx +188 -0
- package/src/features/admin-exchange/components/ImportProgress.tsx +86 -0
- package/src/features/admin-security/__tests__/AdminSecurityPage.test.tsx +3 -3
- package/src/features/moderate-entity-tags/__tests__/EntityTagsPage.test.tsx +2 -2
- package/src/features/moderate-recent/__tests__/RecentDocumentsPage.test.tsx +4 -4
- package/src/features/moderate-tag-schemas/__tests__/TagSchemasPage.test.tsx +3 -3
- package/src/features/moderation-linked-data/__tests__/LinkedDataPage.test.tsx +117 -0
- package/src/features/moderation-linked-data/components/LinkedDataPage.tsx +121 -0
- package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +5 -5
- package/src/features/resource-compose/components/ResourceComposePage.tsx +56 -1
- package/src/features/resource-discovery/__tests__/ResourceCard.test.tsx +1 -1
- package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +2 -2
- package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +3 -3
- package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +11 -10
- package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +2 -2
- package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +22 -115
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +3 -3
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +20 -20
- package/src/features/resource-viewer/__tests__/ResourceMutations.test.tsx +7 -7
- package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +5 -21
- package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +2 -2
- package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +45 -82
- package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +4 -4
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +146 -72
- package/src/integrations/tailwind-plugin.js +3 -3
- package/src/styles/core/buttons.css +31 -0
- package/src/styles/features/exchange.css +404 -0
- package/src/styles/index.css +1 -0
- package/translations/ar.json +44 -4
- package/translations/bn.json +44 -4
- package/translations/cs.json +44 -4
- package/translations/da.json +130 -90
- package/translations/de.json +124 -84
- package/translations/el.json +44 -4
- package/translations/en.json +44 -4
- package/translations/es.json +44 -4
- package/translations/fa.json +44 -4
- package/translations/fi.json +70 -30
- package/translations/fr.json +44 -4
- package/translations/he.json +44 -4
- package/translations/hi.json +44 -4
- package/translations/id.json +45 -5
- package/translations/it.json +64 -24
- package/translations/ja.json +45 -5
- package/translations/ko.json +44 -4
- package/translations/ms.json +45 -5
- package/translations/nl.json +43 -3
- package/translations/no.json +106 -66
- package/translations/pl.json +44 -4
- package/translations/pt.json +45 -5
- package/translations/ro.json +44 -4
- package/translations/sv.json +44 -4
- package/translations/th.json +44 -4
- package/translations/tr.json +44 -4
- package/translations/uk.json +44 -4
- package/translations/vi.json +44 -4
- package/translations/zh.json +44 -4
- package/dist/PdfAnnotationCanvas.client-COQREPXU.mjs.map +0 -1
- package/dist/ar-7SUXNE34.mjs.map +0 -1
- package/dist/bn-XOET3DOI.mjs.map +0 -1
- package/dist/chunk-JH7BXE2P.mjs.map +0 -1
- package/dist/cs-X63DXX7L.mjs.map +0 -1
- package/dist/da-OWTCV57A.mjs.map +0 -1
- package/dist/de-77BMFDVF.mjs.map +0 -1
- package/dist/el-FIBNLH2V.mjs.map +0 -1
- package/dist/es-726NTS53.mjs.map +0 -1
- package/dist/fa-3N4CIWE6.mjs.map +0 -1
- package/dist/fi-JOM3M7Z4.mjs.map +0 -1
- package/dist/fr-56QSXS7E.mjs.map +0 -1
- package/dist/he-SNAXPJEK.mjs.map +0 -1
- package/dist/hi-CRBRD5TB.mjs.map +0 -1
- package/dist/id-BRCVLICF.mjs.map +0 -1
- package/dist/it-M2Z27BNB.mjs.map +0 -1
- package/dist/ja-TZUKW7HD.mjs.map +0 -1
- package/dist/ko-NKBGGOL6.mjs.map +0 -1
- package/dist/ms-XFXPN6RX.mjs.map +0 -1
- package/dist/nl-MVYXAS5C.mjs.map +0 -1
- package/dist/no-XOLO4JPV.mjs.map +0 -1
- package/dist/pl-TRWLMMC4.mjs.map +0 -1
- package/dist/pt-M3TE24UI.mjs.map +0 -1
- package/dist/ro-QBFG2T64.mjs.map +0 -1
- package/dist/sv-IUECBXWX.mjs.map +0 -1
- package/dist/th-US7KIN5Q.mjs.map +0 -1
- package/dist/tr-DWJ2FFUK.mjs.map +0 -1
- package/dist/uk-M4ZE4DPZ.mjs.map +0 -1
- package/dist/vi-FERZNPSH.mjs.map +0 -1
- package/dist/zh-3J2I3WYK.mjs.map +0 -1
- package/src/examples/ButtonUsageExample.tsx +0 -242
- package/src/examples/button-css-modules.module.css +0 -164
- package/src/examples/button-styled-components.tsx +0 -215
- package/src/examples/button-tailwind.css +0 -51
- /package/dist/{chunk-3JTO27MH.mjs.map → chunk-D4GAAQMM.mjs.map} +0 -0
- /package/dist/{chunk-Q2KV6Y2J.mjs.map → chunk-PFQYNPQJ.mjs.map} +0 -0
- /package/dist/{en-XWEPVTB4.mjs.map → en-AOSMPC2M.mjs.map} +0 -0
- /package/dist/{magic-string.es-7FJ3LUGB.mjs.map → magic-string.es-K77I4ZQN.mjs.map} +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import type { Ref } from 'react';
|
|
4
4
|
import type { RouteBuilder } from '../../../contexts/RoutingContext';
|
|
5
5
|
import { useTranslations } from '../../../contexts/TranslationContext';
|
|
6
6
|
import type { components } from '@semiont/core';
|
|
7
|
+
import { annotationId, resourceId } from '@semiont/core';
|
|
7
8
|
import { getAnnotationExactText, isBodyResolved, getBodySource, getFragmentSelector, getSvgSelector, getTargetSelector } from '@semiont/api-client';
|
|
8
9
|
import { getEntityTypes } from '@semiont/ontology';
|
|
9
10
|
import { getResourceIcon } from '../../../lib/resource-utils';
|
|
@@ -26,20 +27,18 @@ interface ReferenceEntryProps {
|
|
|
26
27
|
routes: RouteBuilder;
|
|
27
28
|
annotateMode?: boolean;
|
|
28
29
|
isGenerating?: boolean;
|
|
30
|
+
ref?: Ref<HTMLDivElement>;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
export
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
},
|
|
41
|
-
ref
|
|
42
|
-
) {
|
|
33
|
+
export function ReferenceEntry({
|
|
34
|
+
reference,
|
|
35
|
+
isFocused,
|
|
36
|
+
isHovered = false,
|
|
37
|
+
routes,
|
|
38
|
+
annotateMode = true,
|
|
39
|
+
isGenerating = false,
|
|
40
|
+
ref,
|
|
41
|
+
}: ReferenceEntryProps) {
|
|
43
42
|
const t = useTranslations('ReferencesPanel');
|
|
44
43
|
const eventBus = useEventBus();
|
|
45
44
|
const navigate = useObservableExternalNavigation();
|
|
@@ -64,56 +63,46 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
|
|
|
64
63
|
|
|
65
64
|
const handleOpen = () => {
|
|
66
65
|
if (resolvedResourceUri) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
// Use observable navigation - emits 'browse:external-navigate' event
|
|
70
|
-
navigate(routes.resourceDetail(resourceId), { resourceId });
|
|
71
|
-
}
|
|
66
|
+
// resolvedResourceUri is already a bare resource ID
|
|
67
|
+
navigate(routes.resourceDetail(resolvedResourceUri), { resourceId: resolvedResourceUri });
|
|
72
68
|
}
|
|
73
69
|
};
|
|
74
70
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
title: selectedText,
|
|
79
|
-
entityTypes,
|
|
80
|
-
});
|
|
81
|
-
};
|
|
71
|
+
const source = typeof reference.target === 'object' && 'source' in reference.target
|
|
72
|
+
? reference.target.source
|
|
73
|
+
: '';
|
|
82
74
|
|
|
83
75
|
const handleUnlink = () => {
|
|
84
|
-
|
|
85
|
-
const sourceUri = typeof reference.target === 'object' && 'source' in reference.target
|
|
86
|
-
? reference.target.source
|
|
87
|
-
: '';
|
|
88
|
-
if (sourceUri) {
|
|
76
|
+
if (source) {
|
|
89
77
|
eventBus.get('bind:update-body').next({
|
|
90
|
-
|
|
91
|
-
resourceId:
|
|
92
|
-
operations: [{ op: 'remove' }],
|
|
78
|
+
annotationId: annotationId(reference.id),
|
|
79
|
+
resourceId: resourceId(source),
|
|
80
|
+
operations: [{ op: 'remove' }],
|
|
93
81
|
});
|
|
94
82
|
}
|
|
95
83
|
};
|
|
96
84
|
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
:
|
|
101
|
-
|
|
102
|
-
// Emit request to open generation modal
|
|
103
|
-
eventBus.get('yield:modal-open').next({
|
|
104
|
-
annotationUri: reference.id,
|
|
105
|
-
resourceUri,
|
|
85
|
+
const handleInitiateWizard = () => {
|
|
86
|
+
eventBus.get('bind:initiate').next({
|
|
87
|
+
annotationId: annotationId(reference.id),
|
|
88
|
+
resourceId: resourceId(source),
|
|
106
89
|
defaultTitle: selectedText,
|
|
90
|
+
entityTypes,
|
|
107
91
|
});
|
|
108
92
|
};
|
|
109
93
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
94
|
+
// Status icon click handler depends on state and mode
|
|
95
|
+
const handleIconClick = (e: React.MouseEvent) => {
|
|
96
|
+
e.stopPropagation();
|
|
97
|
+
if (isResolved) {
|
|
98
|
+
handleOpen();
|
|
99
|
+
} else if (annotateMode) {
|
|
100
|
+
handleInitiateWizard();
|
|
101
|
+
}
|
|
115
102
|
};
|
|
116
103
|
|
|
104
|
+
const iconIsClickable = isResolved || annotateMode;
|
|
105
|
+
|
|
117
106
|
return (
|
|
118
107
|
<div
|
|
119
108
|
ref={ref}
|
|
@@ -127,9 +116,26 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
|
|
|
127
116
|
>
|
|
128
117
|
{/* Status indicator and text quote */}
|
|
129
118
|
<div className="semiont-annotation-entry__header">
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
119
|
+
<div className="semiont-reference-icon-group">
|
|
120
|
+
<button
|
|
121
|
+
className={`semiont-reference-icon${iconIsClickable ? ' semiont-reference-icon--clickable' : ''}`}
|
|
122
|
+
title={isResolved ? t('open') : annotateMode ? t('resolve') : t('stub')}
|
|
123
|
+
onClick={iconIsClickable ? handleIconClick : undefined}
|
|
124
|
+
data-generating={!isResolved && isGenerating ? 'true' : 'false'}
|
|
125
|
+
tabIndex={iconIsClickable ? 0 : -1}
|
|
126
|
+
>
|
|
127
|
+
{isResolved ? '🔗' : '❓'}
|
|
128
|
+
</button>
|
|
129
|
+
{annotateMode && isResolved && (
|
|
130
|
+
<button
|
|
131
|
+
className="semiont-reference-unlink"
|
|
132
|
+
title={t('unlink')}
|
|
133
|
+
onClick={(e) => { e.stopPropagation(); handleUnlink(); }}
|
|
134
|
+
>
|
|
135
|
+
⛓️💥
|
|
136
|
+
</button>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
133
139
|
<div className="semiont-annotation-entry__content">
|
|
134
140
|
{selectedText && (
|
|
135
141
|
<div className="semiont-annotation-entry__quote" data-type="reference">
|
|
@@ -163,59 +169,6 @@ export const ReferenceEntry = forwardRef<HTMLDivElement, ReferenceEntryProps>(
|
|
|
163
169
|
))}
|
|
164
170
|
</div>
|
|
165
171
|
)}
|
|
166
|
-
|
|
167
|
-
{/* Actions based on state - only show curation actions in Annotate mode */}
|
|
168
|
-
<div className="semiont-annotation-entry__actions" onClick={(e) => e.stopPropagation()}>
|
|
169
|
-
{isResolved ? (
|
|
170
|
-
// Resolved reference actions
|
|
171
|
-
<div className="semiont-annotation-entry__action-row">
|
|
172
|
-
<button
|
|
173
|
-
onClick={handleOpen}
|
|
174
|
-
className={`semiont-reference-button semiont-reference-button--primary ${annotateMode ? 'semiont-reference-button--full' : 'semiont-reference-button--wide'}`}
|
|
175
|
-
title={t('open')}
|
|
176
|
-
>
|
|
177
|
-
🔗
|
|
178
|
-
</button>
|
|
179
|
-
{annotateMode && (
|
|
180
|
-
<button
|
|
181
|
-
onClick={handleUnlink}
|
|
182
|
-
className="semiont-reference-button semiont-reference-button--primary"
|
|
183
|
-
title={t('unlink')}
|
|
184
|
-
>
|
|
185
|
-
⛓️💥
|
|
186
|
-
</button>
|
|
187
|
-
)}
|
|
188
|
-
</div>
|
|
189
|
-
) : (
|
|
190
|
-
// Stub reference actions - only in Annotate mode
|
|
191
|
-
annotateMode && (
|
|
192
|
-
<div className="semiont-annotation-entry__action-row">
|
|
193
|
-
<button
|
|
194
|
-
onClick={handleGenerate}
|
|
195
|
-
className="semiont-reference-button semiont-reference-button--primary semiont-reference-button--full"
|
|
196
|
-
title={t('generate')}
|
|
197
|
-
data-generating={isGenerating ? 'true' : 'false'}
|
|
198
|
-
>
|
|
199
|
-
✨
|
|
200
|
-
</button>
|
|
201
|
-
<button
|
|
202
|
-
onClick={handleSearch}
|
|
203
|
-
className="semiont-reference-button semiont-reference-button--primary semiont-reference-button--full"
|
|
204
|
-
title={t('find')}
|
|
205
|
-
>
|
|
206
|
-
🔍
|
|
207
|
-
</button>
|
|
208
|
-
<button
|
|
209
|
-
onClick={handleComposeDocument}
|
|
210
|
-
className="semiont-reference-button semiont-reference-button--primary semiont-reference-button--full"
|
|
211
|
-
title={t('create')}
|
|
212
|
-
>
|
|
213
|
-
✏️
|
|
214
|
-
</button>
|
|
215
|
-
</div>
|
|
216
|
-
)
|
|
217
|
-
)}
|
|
218
|
-
</div>
|
|
219
172
|
</div>
|
|
220
173
|
);
|
|
221
|
-
}
|
|
174
|
+
}
|
|
@@ -61,25 +61,106 @@
|
|
|
61
61
|
color: var(--semiont-text-tertiary);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
/* Reference
|
|
65
|
-
.semiont-reference-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
/* Reference Icon Group — status icon + hover-reveal unlink */
|
|
65
|
+
.semiont-reference-icon-group {
|
|
66
|
+
position: relative;
|
|
67
|
+
display: inline-flex;
|
|
68
|
+
align-items: center;
|
|
69
|
+
flex-shrink: 0;
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
.semiont-reference-
|
|
72
|
-
display: flex;
|
|
72
|
+
.semiont-reference-icon {
|
|
73
|
+
display: inline-flex;
|
|
73
74
|
align-items: center;
|
|
74
75
|
justify-content: center;
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
width: 1.75rem;
|
|
77
|
+
height: 1.75rem;
|
|
78
|
+
font-size: 0.875rem;
|
|
79
|
+
line-height: 1;
|
|
80
|
+
border-radius: var(--semiont-radius-md);
|
|
81
|
+
border: 1px solid var(--semiont-color-gray-300);
|
|
82
|
+
background: var(--semiont-bg-secondary);
|
|
83
|
+
color: var(--semiont-text-secondary);
|
|
84
|
+
transition: all 0.15s ease;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
[data-theme="dark"] .semiont-reference-icon {
|
|
88
|
+
border-color: var(--semiont-color-gray-600);
|
|
89
|
+
background: var(--semiont-color-gray-700);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.semiont-reference-icon--clickable {
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.semiont-reference-icon--clickable:hover {
|
|
97
|
+
background: var(--semiont-gradient-primary);
|
|
98
|
+
border-color: var(--semiont-color-primary-300);
|
|
99
|
+
transform: scale(1.1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
[data-theme="dark"] .semiont-reference-icon--clickable:hover {
|
|
103
|
+
background: var(--semiont-gradient-primary-dark);
|
|
104
|
+
border-color: var(--semiont-color-primary-500);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.semiont-reference-icon--clickable:focus-visible {
|
|
108
|
+
outline: 2px solid var(--semiont-color-primary-500);
|
|
109
|
+
outline-offset: 2px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
[data-theme="dark"] .semiont-reference-icon--clickable:focus-visible {
|
|
113
|
+
outline-color: var(--semiont-color-primary-400);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Generating state pulse on stub icon */
|
|
117
|
+
.semiont-reference-icon[data-generating="true"] {
|
|
118
|
+
animation: semiont-icon-pulse 1.5s ease-in-out infinite;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[data-theme="dark"] .semiont-reference-icon[data-generating="true"] {
|
|
122
|
+
animation: semiont-icon-pulse-dark 1.5s ease-in-out infinite;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
@keyframes semiont-icon-pulse {
|
|
126
|
+
0%, 100% { transform: scale(1); box-shadow: 0 0 8px 2px rgba(59, 130, 246, 0.5); }
|
|
127
|
+
50% { transform: scale(1.2); box-shadow: 0 0 16px 4px rgba(59, 130, 246, 0.8); }
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
@keyframes semiont-icon-pulse-dark {
|
|
131
|
+
0%, 100% { transform: scale(1); box-shadow: 0 0 8px 2px rgba(96, 165, 250, 0.6); }
|
|
132
|
+
50% { transform: scale(1.2); box-shadow: 0 0 16px 4px rgba(96, 165, 250, 0.9); }
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Hover-reveal unlink button */
|
|
136
|
+
.semiont-reference-unlink {
|
|
137
|
+
position: absolute;
|
|
138
|
+
right: -1.25rem;
|
|
139
|
+
top: 50%;
|
|
140
|
+
transform: translateY(-50%);
|
|
141
|
+
background: none;
|
|
142
|
+
border: none;
|
|
143
|
+
padding: 0;
|
|
144
|
+
font-size: 0.75rem;
|
|
145
|
+
cursor: pointer;
|
|
146
|
+
opacity: 0;
|
|
147
|
+
pointer-events: none;
|
|
148
|
+
transition: opacity 0.15s ease;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.semiont-annotation-entry:hover .semiont-reference-unlink {
|
|
152
|
+
opacity: 1;
|
|
153
|
+
pointer-events: auto;
|
|
77
154
|
}
|
|
78
155
|
|
|
79
|
-
.semiont-reference-
|
|
80
|
-
|
|
156
|
+
.semiont-reference-unlink:hover {
|
|
157
|
+
transform: translateY(-50%) scale(1.2);
|
|
81
158
|
}
|
|
82
159
|
|
|
83
|
-
.semiont-reference-
|
|
84
|
-
|
|
160
|
+
.semiont-reference-unlink:focus-visible {
|
|
161
|
+
opacity: 1;
|
|
162
|
+
pointer-events: auto;
|
|
163
|
+
outline: 2px solid var(--semiont-color-primary-500);
|
|
164
|
+
outline-offset: 2px;
|
|
165
|
+
border-radius: 2px;
|
|
85
166
|
}
|
|
@@ -497,8 +497,7 @@ export function ReferencesPanel({
|
|
|
497
497
|
{referencedBy.length > 0 ? (
|
|
498
498
|
<div className="semiont-panel__list">
|
|
499
499
|
{referencedBy.map((ref) => {
|
|
500
|
-
|
|
501
|
-
const resourceId = ref.target.source.split('/').pop() || '';
|
|
500
|
+
const resourceId = ref.target.source;
|
|
502
501
|
|
|
503
502
|
return (
|
|
504
503
|
<div key={ref.id} className="semiont-reference-item semiont-reference-item--incoming">
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import type { Ref } from 'react';
|
|
4
4
|
import type { components } from '@semiont/core';
|
|
5
5
|
import { getAnnotationExactText } from '@semiont/api-client';
|
|
6
6
|
import { getTagCategory, getTagSchemaId } from '@semiont/ontology';
|
|
@@ -14,17 +14,15 @@ interface TagEntryProps {
|
|
|
14
14
|
tag: Annotation;
|
|
15
15
|
isFocused: boolean;
|
|
16
16
|
isHovered?: boolean;
|
|
17
|
+
ref?: Ref<HTMLDivElement>;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
ref
|
|
27
|
-
) {
|
|
20
|
+
export function TagEntry({
|
|
21
|
+
tag,
|
|
22
|
+
isFocused,
|
|
23
|
+
isHovered = false,
|
|
24
|
+
ref,
|
|
25
|
+
}: TagEntryProps) {
|
|
28
26
|
const eventBus = useEventBus();
|
|
29
27
|
const hoverProps = useHoverEmitter(tag.id);
|
|
30
28
|
|
|
@@ -62,4 +60,4 @@ export const TagEntry = forwardRef<HTMLDivElement, TagEntryProps>(
|
|
|
62
60
|
</div>
|
|
63
61
|
</div>
|
|
64
62
|
);
|
|
65
|
-
}
|
|
63
|
+
}
|
|
@@ -135,7 +135,7 @@ describe('AssistSection', () => {
|
|
|
135
135
|
|
|
136
136
|
// Form should not be visible
|
|
137
137
|
expect(screen.queryByPlaceholderText('Enter custom instructions...')).not.toBeInTheDocument();
|
|
138
|
-
expect(screen.queryByRole('button', { name:
|
|
138
|
+
expect(screen.queryByRole('button', { name: /✨\s*Annotate/ })).not.toBeInTheDocument();
|
|
139
139
|
});
|
|
140
140
|
|
|
141
141
|
it('should show form when progress is null', () => {
|
|
@@ -149,7 +149,7 @@ describe('AssistSection', () => {
|
|
|
149
149
|
|
|
150
150
|
// Form should be visible
|
|
151
151
|
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
152
|
-
expect(screen.getByRole('button', { name:
|
|
152
|
+
expect(screen.getByRole('button', { name: /✨\s*Annotate/ })).toBeInTheDocument();
|
|
153
153
|
});
|
|
154
154
|
|
|
155
155
|
it('should show form when progress is undefined', () => {
|
|
@@ -163,7 +163,7 @@ describe('AssistSection', () => {
|
|
|
163
163
|
|
|
164
164
|
// Form should be visible
|
|
165
165
|
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
166
|
-
expect(screen.getByRole('button', { name:
|
|
166
|
+
expect(screen.getByRole('button', { name: /✨\s*Annotate/ })).toBeInTheDocument();
|
|
167
167
|
});
|
|
168
168
|
|
|
169
169
|
it('should keep progress visible after detection completes (isAssisting=false but progress exists)', () => {
|
|
@@ -279,7 +279,7 @@ describe('AssistSection', () => {
|
|
|
279
279
|
|
|
280
280
|
const subscription = eventBus!.get('mark:assist-request').subscribe(detectionHandler);
|
|
281
281
|
|
|
282
|
-
const annotateButton = screen.getByRole('button', { name:
|
|
282
|
+
const annotateButton = screen.getByRole('button', { name: /✨\s*Annotate/ });
|
|
283
283
|
await user.click(annotateButton);
|
|
284
284
|
|
|
285
285
|
expect(detectionHandler).toHaveBeenCalledWith({
|
|
@@ -305,7 +305,7 @@ describe('AssistSection', () => {
|
|
|
305
305
|
|
|
306
306
|
const subscription = eventBus!.get('mark:assist-request').subscribe(detectionHandler);
|
|
307
307
|
|
|
308
|
-
const annotateButton = screen.getByRole('button', { name:
|
|
308
|
+
const annotateButton = screen.getByRole('button', { name: /✨\s*Annotate/ });
|
|
309
309
|
await user.click(annotateButton);
|
|
310
310
|
|
|
311
311
|
expect(detectionHandler).toHaveBeenCalledWith({
|
|
@@ -331,7 +331,7 @@ describe('AssistSection', () => {
|
|
|
331
331
|
|
|
332
332
|
const subscription = eventBus!.get('mark:assist-request').subscribe(detectionHandler);
|
|
333
333
|
|
|
334
|
-
const annotateButton = screen.getByRole('button', { name:
|
|
334
|
+
const annotateButton = screen.getByRole('button', { name: /✨\s*Annotate/ });
|
|
335
335
|
await user.click(annotateButton);
|
|
336
336
|
|
|
337
337
|
expect(detectionHandler).toHaveBeenCalledWith({
|
|
@@ -360,7 +360,7 @@ describe('AssistSection', () => {
|
|
|
360
360
|
const textarea = screen.getByPlaceholderText('Enter custom instructions...');
|
|
361
361
|
await user.type(textarea, 'Find key concepts');
|
|
362
362
|
|
|
363
|
-
const annotateButton = screen.getByRole('button', { name:
|
|
363
|
+
const annotateButton = screen.getByRole('button', { name: /✨\s*Annotate/ });
|
|
364
364
|
await user.click(annotateButton);
|
|
365
365
|
|
|
366
366
|
expect(detectionHandler).toHaveBeenCalledWith({
|
|
@@ -106,7 +106,7 @@ describe('HighlightPanel + AssistSection Integration', () => {
|
|
|
106
106
|
|
|
107
107
|
// Form should be visible (meaning progress was null)
|
|
108
108
|
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
109
|
-
expect(screen.getByRole('button', { name:
|
|
109
|
+
expect(screen.getByRole('button', { name: /✨\s*Annotate/ })).toBeInTheDocument();
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
it('should pass undefined progress to AssistSection', () => {
|
|
@@ -122,7 +122,7 @@ describe('HighlightPanel + AssistSection Integration', () => {
|
|
|
122
122
|
|
|
123
123
|
// Form should be visible (meaning progress was undefined)
|
|
124
124
|
expect(screen.getByPlaceholderText('Enter custom instructions...')).toBeInTheDocument();
|
|
125
|
-
expect(screen.getByRole('button', { name:
|
|
125
|
+
expect(screen.getByRole('button', { name: /✨\s*Annotate/ })).toBeInTheDocument();
|
|
126
126
|
});
|
|
127
127
|
|
|
128
128
|
it('should keep progress visible after detection completes (isAssisting=false)', () => {
|