@semiont/react-ui 0.4.3 → 0.4.5

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 (144) hide show
  1. package/dist/{ar-5REA6P4J.mjs → ar-RJLR7NDD.mjs} +13 -11
  2. package/dist/ar-RJLR7NDD.mjs.map +1 -0
  3. package/dist/{bn-YHRYHHPD.mjs → bn-4NU2UAZ7.mjs} +13 -11
  4. package/dist/bn-4NU2UAZ7.mjs.map +1 -0
  5. package/dist/{chunk-VVCCMJS7.mjs → chunk-2VWLGQIO.mjs} +13 -11
  6. package/dist/chunk-2VWLGQIO.mjs.map +1 -0
  7. package/dist/{chunk-F74ZQJMA.mjs → chunk-EKQMINCV.mjs} +31 -31
  8. package/dist/{cs-JTJXTX2T.mjs → cs-6UJZFF55.mjs} +13 -11
  9. package/dist/cs-6UJZFF55.mjs.map +1 -0
  10. package/dist/{da-MK37SJB6.mjs → da-CFFBBOH3.mjs} +13 -11
  11. package/dist/da-CFFBBOH3.mjs.map +1 -0
  12. package/dist/{de-LGBCWERA.mjs → de-2KAG6KMX.mjs} +13 -11
  13. package/dist/de-2KAG6KMX.mjs.map +1 -0
  14. package/dist/{el-FKJMFCWY.mjs → el-KVPQ7VNF.mjs} +13 -11
  15. package/dist/el-KVPQ7VNF.mjs.map +1 -0
  16. package/dist/{en-AOSMPC2M.mjs → en-ZW4UKTVX.mjs} +2 -2
  17. package/dist/{es-LVDPIXWU.mjs → es-ZU2ECPVG.mjs} +13 -11
  18. package/dist/es-ZU2ECPVG.mjs.map +1 -0
  19. package/dist/{fa-3VA2PIUD.mjs → fa-CBIVKDIQ.mjs} +13 -11
  20. package/dist/fa-CBIVKDIQ.mjs.map +1 -0
  21. package/dist/{fi-3WM75ZLR.mjs → fi-5HUVT7IK.mjs} +13 -11
  22. package/dist/fi-5HUVT7IK.mjs.map +1 -0
  23. package/dist/{fr-NK4A72WA.mjs → fr-O5WU2US2.mjs} +13 -11
  24. package/dist/fr-O5WU2US2.mjs.map +1 -0
  25. package/dist/{he-IACZDZMB.mjs → he-WP4C2SNJ.mjs} +13 -11
  26. package/dist/he-WP4C2SNJ.mjs.map +1 -0
  27. package/dist/{hi-JZ7MGMMS.mjs → hi-HLQXNRWI.mjs} +13 -11
  28. package/dist/hi-HLQXNRWI.mjs.map +1 -0
  29. package/dist/{id-P3KDQGNK.mjs → id-DTJT2ZA6.mjs} +13 -11
  30. package/dist/id-DTJT2ZA6.mjs.map +1 -0
  31. package/dist/index.css +213 -0
  32. package/dist/index.css.map +1 -1
  33. package/dist/index.d.mts +23 -41
  34. package/dist/index.mjs +377 -350
  35. package/dist/index.mjs.map +1 -1
  36. package/dist/{it-LQS33SUY.mjs → it-2DK57IMT.mjs} +13 -11
  37. package/dist/it-2DK57IMT.mjs.map +1 -0
  38. package/dist/{ja-G4FKZPWD.mjs → ja-52ZNY72Y.mjs} +13 -11
  39. package/dist/ja-52ZNY72Y.mjs.map +1 -0
  40. package/dist/{ko-2XWKQ7BA.mjs → ko-4Z2IMYZO.mjs} +13 -11
  41. package/dist/ko-4Z2IMYZO.mjs.map +1 -0
  42. package/dist/{ms-2SNONIUD.mjs → ms-HKU73KEX.mjs} +13 -11
  43. package/dist/ms-HKU73KEX.mjs.map +1 -0
  44. package/dist/{nl-BMZUAJ7J.mjs → nl-HPHQMXPT.mjs} +13 -11
  45. package/dist/nl-HPHQMXPT.mjs.map +1 -0
  46. package/dist/{no-6J3WIZ6L.mjs → no-Q7G4PVFT.mjs} +13 -11
  47. package/dist/no-Q7G4PVFT.mjs.map +1 -0
  48. package/dist/{pl-QQ7DAUVK.mjs → pl-D43C2CE3.mjs} +13 -11
  49. package/dist/pl-D43C2CE3.mjs.map +1 -0
  50. package/dist/{pt-MU3GN7MW.mjs → pt-V3GFSY7B.mjs} +13 -11
  51. package/dist/pt-V3GFSY7B.mjs.map +1 -0
  52. package/dist/{ro-6GBE72QK.mjs → ro-3UIRV3OA.mjs} +13 -11
  53. package/dist/ro-3UIRV3OA.mjs.map +1 -0
  54. package/dist/{sv-NQIL7PEM.mjs → sv-BMW26A7M.mjs} +13 -11
  55. package/dist/sv-BMW26A7M.mjs.map +1 -0
  56. package/dist/test-utils.mjs +2 -2
  57. package/dist/{th-6OCNZQBE.mjs → th-CMND2QET.mjs} +13 -11
  58. package/dist/th-CMND2QET.mjs.map +1 -0
  59. package/dist/{tr-XWJ5P3SC.mjs → tr-P3AD7MYA.mjs} +13 -11
  60. package/dist/tr-P3AD7MYA.mjs.map +1 -0
  61. package/dist/{uk-AKSN6DGW.mjs → uk-QPONRQ5O.mjs} +13 -11
  62. package/dist/uk-QPONRQ5O.mjs.map +1 -0
  63. package/dist/{vi-23GHQ45M.mjs → vi-G2OMVMCI.mjs} +13 -11
  64. package/dist/vi-G2OMVMCI.mjs.map +1 -0
  65. package/dist/{zh-ITT4QBSN.mjs → zh-HTDN4LKE.mjs} +13 -11
  66. package/dist/zh-HTDN4LKE.mjs.map +1 -0
  67. package/package.json +1 -1
  68. package/src/components/CodeMirrorRenderer.tsx +9 -9
  69. package/src/components/ResourceTagsInline.tsx +1 -1
  70. package/src/components/__tests__/ResourceTagsInline.test.tsx +3 -3
  71. package/src/components/modals/ContextSummary.tsx +56 -165
  72. package/src/components/modals/GatherContextStep.tsx +124 -42
  73. package/src/components/modals/ReferenceWizardModal.tsx +8 -25
  74. package/src/components/modals/SearchModal.css +241 -0
  75. package/src/components/resource/AnnotateView.tsx +3 -3
  76. package/src/components/resource/ResourceViewer.tsx +4 -4
  77. package/src/components/resource/__tests__/annotation-interactions.test.tsx +1 -1
  78. package/src/components/resource/panels/AssessmentPanel.tsx +3 -0
  79. package/src/components/resource/panels/AssistSection.tsx +4 -1
  80. package/src/components/resource/panels/CommentsPanel.tsx +3 -0
  81. package/src/components/resource/panels/ResourceInfoPanel.tsx +82 -0
  82. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +4 -0
  83. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +94 -0
  84. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +12 -10
  85. package/translations/ar.json +12 -10
  86. package/translations/bn.json +12 -10
  87. package/translations/cs.json +12 -10
  88. package/translations/da.json +12 -10
  89. package/translations/de.json +12 -10
  90. package/translations/el.json +12 -10
  91. package/translations/en.json +13 -11
  92. package/translations/es.json +12 -10
  93. package/translations/fa.json +12 -10
  94. package/translations/fi.json +12 -10
  95. package/translations/fr.json +12 -10
  96. package/translations/he.json +12 -10
  97. package/translations/hi.json +12 -10
  98. package/translations/id.json +12 -10
  99. package/translations/it.json +12 -10
  100. package/translations/ja.json +12 -10
  101. package/translations/ko.json +12 -10
  102. package/translations/ms.json +12 -10
  103. package/translations/nl.json +12 -10
  104. package/translations/no.json +12 -10
  105. package/translations/pl.json +12 -10
  106. package/translations/pt.json +12 -10
  107. package/translations/ro.json +12 -10
  108. package/translations/sv.json +12 -10
  109. package/translations/th.json +12 -10
  110. package/translations/tr.json +12 -10
  111. package/translations/uk.json +12 -10
  112. package/translations/vi.json +12 -10
  113. package/translations/zh.json +12 -10
  114. package/dist/ar-5REA6P4J.mjs.map +0 -1
  115. package/dist/bn-YHRYHHPD.mjs.map +0 -1
  116. package/dist/chunk-VVCCMJS7.mjs.map +0 -1
  117. package/dist/cs-JTJXTX2T.mjs.map +0 -1
  118. package/dist/da-MK37SJB6.mjs.map +0 -1
  119. package/dist/de-LGBCWERA.mjs.map +0 -1
  120. package/dist/el-FKJMFCWY.mjs.map +0 -1
  121. package/dist/es-LVDPIXWU.mjs.map +0 -1
  122. package/dist/fa-3VA2PIUD.mjs.map +0 -1
  123. package/dist/fi-3WM75ZLR.mjs.map +0 -1
  124. package/dist/fr-NK4A72WA.mjs.map +0 -1
  125. package/dist/he-IACZDZMB.mjs.map +0 -1
  126. package/dist/hi-JZ7MGMMS.mjs.map +0 -1
  127. package/dist/id-P3KDQGNK.mjs.map +0 -1
  128. package/dist/it-LQS33SUY.mjs.map +0 -1
  129. package/dist/ja-G4FKZPWD.mjs.map +0 -1
  130. package/dist/ko-2XWKQ7BA.mjs.map +0 -1
  131. package/dist/ms-2SNONIUD.mjs.map +0 -1
  132. package/dist/nl-BMZUAJ7J.mjs.map +0 -1
  133. package/dist/no-6J3WIZ6L.mjs.map +0 -1
  134. package/dist/pl-QQ7DAUVK.mjs.map +0 -1
  135. package/dist/pt-MU3GN7MW.mjs.map +0 -1
  136. package/dist/ro-6GBE72QK.mjs.map +0 -1
  137. package/dist/sv-NQIL7PEM.mjs.map +0 -1
  138. package/dist/th-6OCNZQBE.mjs.map +0 -1
  139. package/dist/tr-XWJ5P3SC.mjs.map +0 -1
  140. package/dist/uk-AKSN6DGW.mjs.map +0 -1
  141. package/dist/vi-23GHQ45M.mjs.map +0 -1
  142. package/dist/zh-ITT4QBSN.mjs.map +0 -1
  143. /package/dist/{chunk-F74ZQJMA.mjs.map → chunk-EKQMINCV.mjs.map} +0 -0
  144. /package/dist/{en-AOSMPC2M.mjs.map → en-ZW4UKTVX.mjs.map} +0 -0
@@ -46,15 +46,9 @@ export interface ReferenceWizardModalProps {
46
46
  configureGenerationTitle: string;
47
47
  configureSearchTitle: string;
48
48
  searchResultsTitle: string;
49
- annotationLabel: string;
50
- sourceResourceLabel: string;
51
- motivationLabel: string;
52
49
  sourceContextLabel: string;
53
- entityTypesLabel: string;
54
- graphContextLabel: string;
55
50
  connectionsLabel: string;
56
51
  citedByLabel: string;
57
- siblingTypesLabel: string;
58
52
  userHintLabel: string;
59
53
  userHintPlaceholder: string;
60
54
  loadingContext: string;
@@ -64,6 +58,7 @@ export interface ReferenceWizardModalProps {
64
58
  searching: string;
65
59
  generate: string;
66
60
  compose: string;
61
+ resolutionStrategyLabel: string;
67
62
  back: string;
68
63
  link: string;
69
64
  score: string;
@@ -119,10 +114,11 @@ export function ReferenceWizardModal({
119
114
  useEffect(() => {
120
115
  if (!isOpen) return;
121
116
 
122
- const subscription = eventBus.get('bind:search-results').subscribe((event) => {
123
- if (annotationId && event.referenceId === annotationId) {
117
+ const subscription = eventBus.get('match:search-results').subscribe((event) => {
118
+ const e = event as { referenceId: string; results: ScoredResult[] };
119
+ if (annotationId && e.referenceId === annotationId) {
124
120
  setIsSearching(false);
125
- setWizardStep({ step: 'search-results', results: event.results as ScoredResult[] });
121
+ setWizardStep({ step: 'search-results', results: e.results });
126
122
  }
127
123
  });
128
124
 
@@ -152,7 +148,7 @@ export function ReferenceWizardModal({
152
148
  if (!annotationId || !context) return;
153
149
  setIsSearching(true);
154
150
  const contextWithHint = userHint ? { ...context, userHint } : context;
155
- eventBus.get('bind:search-requested').next({
151
+ eventBus.get('match:search-requested').next({
156
152
  referenceId: annotationId,
157
153
  context: contextWithHint,
158
154
  limit: config.limit,
@@ -208,7 +204,7 @@ export function ReferenceWizardModal({
208
204
  leaveFrom="opacity-100 scale-100"
209
205
  leaveTo="opacity-0 scale-95"
210
206
  >
211
- <DialogPanel className={`semiont-search-modal__panel semiont-search-modal__panel--with-border${wizardStep.step === 'search-results' ? ' semiont-search-modal__panel--wide' : ''}`}>
207
+ <DialogPanel className={`semiont-search-modal__panel semiont-search-modal__panel--with-border${wizardStep.step === 'search-results' ? ' semiont-search-modal__panel--wide' : ''}${wizardStep.step === 'gather' ? ' semiont-search-modal__panel--gather' : ''}`}>
212
208
  <div className="semiont-search-modal__header">
213
209
  <DialogTitle className="semiont-search-modal__title">
214
210
  {stepTitle}
@@ -229,29 +225,22 @@ export function ReferenceWizardModal({
229
225
  contextError={contextError}
230
226
  userHint={userHint}
231
227
  onUserHintChange={setUserHint}
232
- onCancel={onClose}
233
228
  onBind={handleBind}
234
229
  onGenerate={handleGenerate}
235
230
  onCompose={handleCompose}
236
231
  translations={{
237
232
  title: t.gatherTitle,
238
- annotationLabel: t.annotationLabel,
239
- sourceResourceLabel: t.sourceResourceLabel,
240
- motivationLabel: t.motivationLabel,
241
233
  sourceContextLabel: t.sourceContextLabel,
242
- entityTypesLabel: t.entityTypesLabel,
243
- graphContextLabel: t.graphContextLabel,
244
234
  connectionsLabel: t.connectionsLabel,
245
235
  citedByLabel: t.citedByLabel,
246
- siblingTypesLabel: t.siblingTypesLabel,
247
236
  userHintLabel: t.userHintLabel,
248
237
  userHintPlaceholder: t.userHintPlaceholder,
249
238
  loadingContext: t.loadingContext,
250
239
  failedContext: t.failedContext,
251
- cancel: t.cancel,
252
240
  search: t.search,
253
241
  generate: t.generate,
254
242
  compose: t.compose,
243
+ resolutionStrategyLabel: t.resolutionStrategyLabel,
255
244
  }}
256
245
  />
257
246
  )}
@@ -314,15 +303,9 @@ export function ReferenceWizardModal({
314
303
  back: t.back,
315
304
  cancel: t.cancel,
316
305
  score: t.score,
317
- annotationLabel: t.annotationLabel,
318
- sourceResourceLabel: t.sourceResourceLabel,
319
- motivationLabel: t.motivationLabel,
320
306
  sourceContextLabel: t.sourceContextLabel,
321
- entityTypesLabel: t.entityTypesLabel,
322
- graphContextLabel: t.graphContextLabel,
323
307
  connectionsLabel: t.connectionsLabel,
324
308
  citedByLabel: t.citedByLabel,
325
- siblingTypesLabel: t.siblingTypesLabel,
326
309
  userHintLabel: t.userHintLabel,
327
310
  userHintPlaceholder: t.userHintPlaceholder,
328
311
  }}
@@ -467,6 +467,247 @@
467
467
  max-width: 1100px;
468
468
  }
469
469
 
470
+ /* Gather-context step: wider modal */
471
+ .semiont-search-modal__panel--gather {
472
+ max-width: min(90vw, 820px);
473
+ max-height: min(90vh, 680px);
474
+ display: flex;
475
+ flex-direction: column;
476
+ overflow: hidden;
477
+ }
478
+
479
+ /* Outer flex column: source strip + two-column body */
480
+ .semiont-gather__outer {
481
+ display: flex;
482
+ flex-direction: column;
483
+ flex: 1;
484
+ min-height: 0;
485
+ gap: 0.75rem;
486
+ overflow: hidden;
487
+ }
488
+
489
+ /* Loading state */
490
+ .semiont-gather__loading {
491
+ display: flex;
492
+ flex-direction: column;
493
+ align-items: center;
494
+ justify-content: center;
495
+ gap: 1rem;
496
+ flex: 1;
497
+ padding: 2rem 0;
498
+ }
499
+
500
+ .semiont-gather__loading-text {
501
+ font-size: 1.125rem;
502
+ color: var(--semiont-text-secondary);
503
+ font-weight: 500;
504
+ }
505
+
506
+ [data-theme="dark"] .semiont-gather__loading-text {
507
+ color: var(--semiont-text-secondary);
508
+ }
509
+
510
+ .semiont-gather__loading-dot {
511
+ display: inline-block;
512
+ width: 0.625rem;
513
+ height: 0.625rem;
514
+ border-radius: 50%;
515
+ background-color: var(--semiont-color-primary-500);
516
+ animation: semiont-gather-pulse 1.2s ease-in-out infinite;
517
+ }
518
+
519
+ [data-theme="dark"] .semiont-gather__loading-dot {
520
+ background-color: var(--semiont-color-primary-400);
521
+ }
522
+
523
+ .semiont-gather__loading-dot:nth-child(1) { animation-delay: 0s; }
524
+ .semiont-gather__loading-dot:nth-child(2) { animation-delay: 0.2s; }
525
+ .semiont-gather__loading-dot:nth-child(3) { animation-delay: 0.4s; }
526
+
527
+ @keyframes semiont-gather-pulse {
528
+ 0%, 80%, 100% { transform: scale(0.6); opacity: 0.4; }
529
+ 40% { transform: scale(1); opacity: 1; }
530
+ }
531
+
532
+ /* Full-width source context strip */
533
+ .semiont-gather__source-strip {
534
+ flex-shrink: 0;
535
+ padding-top: 0.25rem;
536
+ }
537
+
538
+ /* Two-column body below the strip */
539
+ .semiont-gather__body {
540
+ display: flex;
541
+ flex: 1;
542
+ min-height: 0;
543
+ overflow: hidden;
544
+ }
545
+
546
+ .semiont-gather__left {
547
+ flex: 0 0 55%;
548
+ overflow-y: auto;
549
+ padding-right: 1.25rem;
550
+ display: flex;
551
+ flex-direction: column;
552
+ gap: 0.75rem;
553
+ border-right: 1px solid var(--semiont-border-primary);
554
+ }
555
+
556
+ [data-theme="dark"] .semiont-gather__left {
557
+ border-right-color: var(--semiont-border-primary);
558
+ }
559
+
560
+ .semiont-gather__right {
561
+ flex: 0 0 45%;
562
+ padding-left: 1.25rem;
563
+ display: flex;
564
+ flex-direction: column;
565
+ gap: 0.75rem;
566
+ overflow-y: auto;
567
+ }
568
+
569
+ .semiont-gather__right .semiont-form__field {
570
+ display: flex;
571
+ flex-direction: column;
572
+ flex: 1;
573
+ min-height: 0;
574
+ }
575
+
576
+ .semiont-gather__hint-textarea {
577
+ width: 100%;
578
+ flex: 1;
579
+ min-height: 0;
580
+ }
581
+
582
+ .semiont-gather__hint-textarea:focus-visible {
583
+ outline: 2px solid var(--semiont-color-primary-500);
584
+ outline-offset: 0;
585
+ }
586
+
587
+ .semiont-gather__footer {
588
+ flex-shrink: 0;
589
+ padding-top: 0.75rem;
590
+ border-top: 1px solid var(--semiont-border-primary);
591
+ }
592
+
593
+ .semiont-gather__footer-label {
594
+ font-size: var(--semiont-text-xs);
595
+ font-weight: 700;
596
+ text-transform: uppercase;
597
+ letter-spacing: 0.06em;
598
+ color: var(--semiont-text-tertiary);
599
+ margin-bottom: 0.5rem;
600
+ }
601
+
602
+ [data-theme="dark"] .semiont-gather__footer-label {
603
+ color: var(--semiont-text-tertiary);
604
+ }
605
+
606
+ .semiont-gather__actions {
607
+ display: flex;
608
+ flex-flow: row nowrap;
609
+ gap: 0.5rem;
610
+ }
611
+
612
+ /* Source context collapsible */
613
+ .semiont-gather__source-box {
614
+ padding: 0.75rem;
615
+ background-color: var(--semiont-bg-secondary);
616
+ border-radius: var(--semiont-radius-md);
617
+ border: 1px solid var(--semiont-border-primary);
618
+ position: relative;
619
+ }
620
+
621
+ [data-theme="dark"] .semiont-gather__source-box {
622
+ background-color: var(--semiont-bg-secondary);
623
+ }
624
+
625
+ .semiont-gather__source-box::after {
626
+ content: '';
627
+ position: absolute;
628
+ bottom: 2rem; /* above the expand button */
629
+ left: 0;
630
+ right: 0;
631
+ height: 2rem;
632
+ background: linear-gradient(to bottom, transparent, var(--semiont-bg-secondary));
633
+ pointer-events: none;
634
+ border-radius: 0 0 var(--semiont-radius-md) var(--semiont-radius-md);
635
+ transition: opacity 0.15s ease;
636
+ }
637
+
638
+ .semiont-gather__source-box--expanded::after {
639
+ opacity: 0;
640
+ }
641
+
642
+ .semiont-gather__source-context {
643
+ max-height: 8rem;
644
+ overflow: hidden;
645
+ transition: max-height 0.2s ease;
646
+ }
647
+
648
+ .semiont-gather__source-box--expanded .semiont-gather__source-context {
649
+ max-height: 16rem;
650
+ }
651
+
652
+ .semiont-gather__expand-btn {
653
+ font-size: var(--semiont-text-xs);
654
+ color: var(--semiont-text-tertiary);
655
+ background: none;
656
+ border: none;
657
+ cursor: pointer;
658
+ padding: 0.125rem 0;
659
+ margin-top: 0.25rem;
660
+ text-decoration: none;
661
+ outline: none;
662
+ }
663
+
664
+ .semiont-gather__expand-btn:hover {
665
+ color: var(--semiont-color-primary-600);
666
+ }
667
+
668
+ [data-theme="dark"] .semiont-gather__expand-btn {
669
+ color: var(--semiont-text-tertiary);
670
+ }
671
+
672
+ [data-theme="dark"] .semiont-gather__expand-btn:hover {
673
+ color: var(--semiont-color-primary-400);
674
+ }
675
+
676
+ /* Narrow screens: stack vertically */
677
+ @media (max-width: 640px) {
678
+ .semiont-search-modal__panel--gather {
679
+ max-width: 100%;
680
+ max-height: 100dvh;
681
+ }
682
+
683
+ .semiont-gather__outer {
684
+ overflow-y: auto;
685
+ }
686
+
687
+ .semiont-gather__body {
688
+ flex-direction: column;
689
+ overflow: visible;
690
+ }
691
+
692
+ .semiont-gather__left {
693
+ flex: none;
694
+ border-right: none;
695
+ border-bottom: 1px solid var(--semiont-border-primary);
696
+ padding-right: 0;
697
+ padding-bottom: 0.75rem;
698
+ }
699
+
700
+ .semiont-gather__right {
701
+ flex: none;
702
+ padding-left: 0;
703
+ padding-top: 0.75rem;
704
+ }
705
+
706
+ .semiont-gather__actions {
707
+ flex-flow: row wrap;
708
+ }
709
+ }
710
+
470
711
  /* Two-pane layout for search results + context */
471
712
  .semiont-search-results__two-pane {
472
713
  display: flex;
@@ -37,7 +37,7 @@ interface Props {
37
37
  onUIStateChange?: (state: Partial<AnnotationUIState>) => void;
38
38
  editable?: boolean;
39
39
  enableWidgets?: boolean;
40
- getTargetDocumentName?: (documentId: string) => string | undefined;
40
+ getTargetResourceName?: (resourceId: string) => string | undefined;
41
41
  generatingReferenceId?: string | null;
42
42
  showLineNumbers?: boolean;
43
43
  hoverDelayMs?: number;
@@ -61,7 +61,7 @@ export function AnnotateView({
61
61
  uiState,
62
62
  onUIStateChange,
63
63
  enableWidgets = false,
64
- getTargetDocumentName,
64
+ getTargetResourceName,
65
65
  generatingReferenceId,
66
66
  showLineNumbers = false,
67
67
  hoverDelayMs = 150,
@@ -220,7 +220,7 @@ export function AnnotateView({
220
220
  hoverDelayMs={hoverDelayMs}
221
221
  enableWidgets={enableWidgets}
222
222
  eventBus={eventBus}
223
- {...(getTargetDocumentName && { getTargetDocumentName })}
223
+ {...(getTargetResourceName && { getTargetResourceName })}
224
224
  {...(generatingReferenceId !== undefined && { generatingReferenceId })}
225
225
  />
226
226
 
@@ -374,10 +374,10 @@ export function ResourceViewer({
374
374
  scrollToAnnotationId
375
375
  };
376
376
 
377
- // Define getTargetDocumentName callback OUTSIDE the conditional
377
+ // Define getTargetResourceName callback OUTSIDE the conditional
378
378
  // IMPORTANT: This must be defined before the return statement to avoid hook ordering violations
379
- const getTargetDocumentName = useCallback((documentId: string) => {
380
- const referencedResource = references.find((a: Annotation) => getBodySource(a.body) === documentId);
379
+ const getTargetResourceName = useCallback((resourceId: string) => {
380
+ const referencedResource = references.find((a: Annotation) => getBodySource(a.body) === resourceId);
381
381
  return referencedResource ? getExactText(getTargetSelector(referencedResource.target)) : undefined;
382
382
  }, [references]);
383
383
 
@@ -397,7 +397,7 @@ export function ResourceViewer({
397
397
  if ('selectedShape' in updates) setSelectedShape(updates.selectedShape!);
398
398
  }}
399
399
  enableWidgets={true}
400
- getTargetDocumentName={getTargetDocumentName}
400
+ getTargetResourceName={getTargetResourceName}
401
401
  {...(generatingReferenceId !== undefined && { generatingReferenceId })}
402
402
  showLineNumbers={showLineNumbers}
403
403
  hoverDelayMs={hoverDelayMs}
@@ -40,7 +40,7 @@ describe('Annotation Interaction Transitions', () => {
40
40
  // When: User clicks on the reference text
41
41
  // Then: Should navigate to the referenced document
42
42
  // - In both Browse mode and Annotate mode
43
- // - Router should push to /know/resource/{documentId}
43
+ // - Router should push to /know/resource/{resourceId}
44
44
  expect(true).toBe(true); // Placeholder - implement actual test
45
45
  });
46
46
 
@@ -46,6 +46,7 @@ interface AssessmentPanelProps {
46
46
  percentage?: number;
47
47
  message?: string;
48
48
  } | null;
49
+ locale?: string;
49
50
  annotateMode?: boolean;
50
51
  scrollToAnnotationId?: string | null;
51
52
  onScrollCompleted?: () => void;
@@ -64,6 +65,7 @@ export function AssessmentPanel({
64
65
  pendingAnnotation,
65
66
  isAssisting = false,
66
67
  progress,
68
+ locale,
67
69
  annotateMode = true,
68
70
  scrollToAnnotationId,
69
71
  onScrollCompleted,
@@ -236,6 +238,7 @@ export function AssessmentPanel({
236
238
  <AssistSection
237
239
  annotationType="assessment"
238
240
  isAssisting={isAssisting}
241
+ locale={locale}
239
242
  progress={progress}
240
243
  />
241
244
  )}
@@ -9,6 +9,7 @@ import './AssistSection.css';
9
9
  interface AssistSectionProps {
10
10
  annotationType: 'highlight' | 'assessment' | 'comment';
11
11
  isAssisting: boolean;
12
+ locale?: string;
12
13
  progress?: {
13
14
  status: string;
14
15
  percentage?: number;
@@ -34,6 +35,7 @@ interface AssistSectionProps {
34
35
  export function AssistSection({
35
36
  annotationType,
36
37
  isAssisting,
38
+ locale,
37
39
  progress,
38
40
  }: AssistSectionProps) {
39
41
 
@@ -77,13 +79,14 @@ export function AssistSection({
77
79
  instructions: instructions.trim() || undefined,
78
80
  tone: (annotationType === 'comment' || annotationType === 'assessment') && tone ? tone : undefined,
79
81
  density: (annotationType === 'comment' || annotationType === 'assessment' || annotationType === 'highlight') && useDensity ? density : undefined,
82
+ language: (annotationType === 'comment' || annotationType === 'assessment') ? locale : undefined,
80
83
  },
81
84
  });
82
85
 
83
86
  setInstructions('');
84
87
  setTone('');
85
88
  // Don't reset density/useDensity - persist across assists
86
- }, [annotationType, instructions, tone, useDensity, density]); // eventBus is stable singleton - never in deps
89
+ }, [annotationType, instructions, tone, useDensity, density, locale]); // eventBus is stable singleton - never in deps
87
90
 
88
91
  const handleDismissProgress = useCallback(() => {
89
92
  eventBus.get('mark:progress-dismiss').next(undefined);
@@ -47,6 +47,7 @@ interface CommentsPanelProps {
47
47
  percentage?: number;
48
48
  message?: string;
49
49
  } | null;
50
+ locale?: string;
50
51
  scrollToAnnotationId?: string | null;
51
52
  onScrollCompleted?: () => void;
52
53
  hoveredAnnotationId?: string | null;
@@ -65,6 +66,7 @@ export function CommentsPanel({
65
66
  annotateMode = true,
66
67
  isAssisting = false,
67
68
  progress,
69
+ locale,
68
70
  scrollToAnnotationId,
69
71
  onScrollCompleted,
70
72
  hoveredAnnotationId,
@@ -252,6 +254,7 @@ export function CommentsPanel({
252
254
  <AssistSection
253
255
  annotationType="comment"
254
256
  isAssisting={isAssisting}
257
+ locale={locale}
255
258
  progress={progress}
256
259
  />
257
260
  )}
@@ -3,14 +3,23 @@
3
3
  import { useTranslations } from '../../../contexts/TranslationContext';
4
4
  import { useEventBus } from '../../../contexts/EventBusContext';
5
5
  import { formatLocaleDisplay } from '@semiont/api-client';
6
+ import type { components } from '@semiont/core';
6
7
  import './ResourceInfoPanel.css';
7
8
 
9
+ type Agent = components['schemas']['Agent'];
10
+
8
11
  interface Props {
9
12
  documentEntityTypes: string[];
10
13
  documentLocale?: string | undefined;
11
14
  primaryMediaType?: string | undefined;
12
15
  primaryByteSize?: number | undefined;
13
16
  isArchived?: boolean;
17
+ dateCreated?: string | undefined;
18
+ dateModified?: string | undefined;
19
+ creationMethod?: string | undefined;
20
+ wasAttributedTo?: Agent | Agent[] | undefined;
21
+ wasDerivedFrom?: string | string[] | undefined;
22
+ generator?: Agent | Agent[] | undefined;
14
23
  }
15
24
 
16
25
  /**
@@ -26,6 +35,12 @@ export function ResourceInfoPanel({
26
35
  primaryMediaType,
27
36
  primaryByteSize,
28
37
  isArchived = false,
38
+ dateCreated,
39
+ dateModified,
40
+ creationMethod,
41
+ wasAttributedTo,
42
+ wasDerivedFrom,
43
+ generator,
29
44
  }: Props) {
30
45
  const t = useTranslations('ResourceInfoPanel');
31
46
  const eventBus = useEventBus();
@@ -76,6 +91,73 @@ export function ResourceInfoPanel({
76
91
  </div>
77
92
  )}
78
93
 
94
+ {/* Provenance Section */}
95
+ {(dateCreated || dateModified || creationMethod || wasAttributedTo || wasDerivedFrom || generator) && (
96
+ <div className="semiont-resource-info-panel__section">
97
+ <h3 className="semiont-resource-info-panel__heading">{t('provenance')}</h3>
98
+ <div className="semiont-resource-info-panel__field-group">
99
+ {dateCreated && (
100
+ <div>
101
+ <span className="semiont-resource-info-panel__label">{t('createdAt')}</span>
102
+ <span className="semiont-resource-info-panel__value">
103
+ {new Date(dateCreated).toLocaleString()}
104
+ </span>
105
+ </div>
106
+ )}
107
+ {dateModified && (
108
+ <div>
109
+ <span className="semiont-resource-info-panel__label">{t('modifiedAt')}</span>
110
+ <span className="semiont-resource-info-panel__value">
111
+ {new Date(dateModified).toLocaleString()}
112
+ </span>
113
+ </div>
114
+ )}
115
+ {creationMethod && (
116
+ <div>
117
+ <span className="semiont-resource-info-panel__label">{t('creationMethod')}</span>
118
+ <span className="semiont-resource-info-panel__value">{creationMethod}</span>
119
+ </div>
120
+ )}
121
+ {wasAttributedTo && (
122
+ <div>
123
+ <span className="semiont-resource-info-panel__label">{t('attributedTo')}</span>
124
+ <span className="semiont-resource-info-panel__value">
125
+ {(Array.isArray(wasAttributedTo) ? wasAttributedTo : [wasAttributedTo])
126
+ .map(a => a.name)
127
+ .join(', ')}
128
+ </span>
129
+ </div>
130
+ )}
131
+ {wasDerivedFrom && (
132
+ <div>
133
+ <span className="semiont-resource-info-panel__label">{t('derivedFrom')}</span>
134
+ <span className="semiont-resource-info-panel__value">
135
+ {(Array.isArray(wasDerivedFrom) ? wasDerivedFrom : [wasDerivedFrom]).map((id, i) => (
136
+ <button
137
+ key={id}
138
+ className="semiont-resource-info-panel__link"
139
+ onClick={() => eventBus.get('browse:reference-navigate').next({ resourceId: id })}
140
+ >
141
+ {i > 0 && ', '}{id}
142
+ </button>
143
+ ))}
144
+ </span>
145
+ </div>
146
+ )}
147
+ {generator && (
148
+ <div>
149
+ <span className="semiont-resource-info-panel__label">{t('generatedBy')}</span>
150
+ <span className="semiont-resource-info-panel__value">
151
+ {(Array.isArray(generator) ? generator : [generator])
152
+ .map(a => a.name)
153
+ .join(', ')}
154
+ </span>
155
+ </div>
156
+ )}
157
+ </div>
158
+ </div>
159
+ )}
160
+
79
161
  {/* Entity Type Tags Section */}
80
162
  {documentEntityTypes.length > 0 && (
81
163
  <div className="semiont-resource-info-panel__section">
@@ -70,6 +70,9 @@ interface UnifiedAnnotationsPanelProps {
70
70
  // Hover coordination (for bidirectional hover highlighting)
71
71
  hoveredAnnotationId?: string | null;
72
72
 
73
+ // Locale for AI-generated text language
74
+ locale?: string;
75
+
73
76
  // Routing
74
77
  Link: React.ComponentType<LinkComponentProps>;
75
78
  routes: RouteBuilder;
@@ -238,6 +241,7 @@ export function UnifiedAnnotationsPanel(props: UnifiedAnnotationsPanelProps) {
238
241
  isAssisting,
239
242
  progress,
240
243
  annotateMode: props.annotateMode,
244
+ locale: props.locale,
241
245
  scrollToAnnotationId: props.scrollToAnnotationId,
242
246
  onScrollCompleted: props.onScrollCompleted,
243
247
  hoveredAnnotationId: props.hoveredAnnotationId