@semiont/react-ui 0.5.27 → 0.5.28

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 (162) hide show
  1. package/dist/{PdfAnnotationCanvas.client-EVUPTUWZ.js → PdfAnnotationCanvas.client-C2IGG4SW.js} +31 -4
  2. package/dist/{ar-OU3DQGC6.js → ar-FABPTJVB.js} +39 -23
  3. package/dist/{bn-PHWCR6AZ.js → bn-LKP6BDMH.js} +39 -23
  4. package/dist/{chunk-PCRRBU7H.js → chunk-2GOHTTHW.js} +39 -23
  5. package/dist/{chunk-5VDTWRXJ.js → chunk-2YHEE63S.js} +31 -31
  6. package/dist/{cs-NEXYZ62I.js → cs-YQYNWHRG.js} +39 -23
  7. package/dist/{da-FAT43YCU.js → da-QHZOYKRY.js} +39 -23
  8. package/dist/{de-KRQ3WBCU.js → de-GKA7RD7J.js} +39 -23
  9. package/dist/{el-Q4IU3EKC.js → el-45T257AL.js} +39 -23
  10. package/dist/{en-2KADE7N4.js → en-RVW5EQ66.js} +2 -2
  11. package/dist/{es-2IO3R2MK.js → es-AVER7RU4.js} +39 -23
  12. package/dist/{fa-Q5GOQFXX.js → fa-K3VPK3O2.js} +39 -23
  13. package/dist/{fi-R6NMRWBE.js → fi-5NEKF7EB.js} +39 -23
  14. package/dist/{fr-QY4D5E6J.js → fr-FUMNDLBZ.js} +39 -23
  15. package/dist/{he-X6Y77XHY.js → he-3JGNA3PR.js} +39 -23
  16. package/dist/{hi-XL7IOEQM.js → hi-IJY375DF.js} +39 -23
  17. package/dist/{id-QZ4ZZS67.js → id-LWHKJ7ZD.js} +39 -23
  18. package/dist/index.css +279 -74
  19. package/dist/index.d.ts +170 -145
  20. package/dist/index.js +2743 -2365
  21. package/dist/{it-ME2Q7OB6.js → it-EBVOV4RW.js} +39 -23
  22. package/dist/{ja-HX7QASRI.js → ja-KWRIX2NF.js} +39 -23
  23. package/dist/{ko-EQO5AHAV.js → ko-L5CJMFDS.js} +39 -23
  24. package/dist/{ms-UILFSF3I.js → ms-LSNMJDR2.js} +39 -23
  25. package/dist/{nl-NNI45PMK.js → nl-ZB32MB7U.js} +39 -23
  26. package/dist/{no-MAL5F6P6.js → no-4GTNY7M5.js} +39 -23
  27. package/dist/{pl-4RMY6JAJ.js → pl-LUHBLTHB.js} +39 -23
  28. package/dist/{pt-VQH2X3QQ.js → pt-C4H3UNQ6.js} +39 -23
  29. package/dist/{ro-XXCQO2OG.js → ro-GGITS5V4.js} +39 -23
  30. package/dist/{sv-7Z6EJ6U4.js → sv-T56RTLBP.js} +39 -23
  31. package/dist/test-utils.js +2 -2
  32. package/dist/{th-L3DXXYVQ.js → th-22X2IWCB.js} +39 -23
  33. package/dist/{tr-P3DFVLFJ.js → tr-77TFG62H.js} +39 -23
  34. package/dist/{uk-7C5D3PXS.js → uk-MIIL6NXT.js} +39 -23
  35. package/dist/{vi-ZLTLEO7P.js → vi-7JYOIGNV.js} +39 -23
  36. package/dist/{zh-5FHVWDIN.js → zh-ID6DRYU4.js} +39 -23
  37. package/package.json +9 -8
  38. package/src/components/AssistProgress.tsx +36 -2
  39. package/src/components/CodeMirrorRenderer.tsx +8 -8
  40. package/src/components/__tests__/AssistProgress.test.tsx +59 -0
  41. package/src/components/modals/ComposeStep.tsx +218 -0
  42. package/src/components/modals/ConfigureGatherStep.tsx +10 -18
  43. package/src/components/modals/ConfigureGenerationStep.tsx +35 -19
  44. package/src/components/modals/ConfigureSearchStep.tsx +19 -0
  45. package/src/components/modals/ContextSummary.tsx +185 -72
  46. package/src/components/modals/CorpusPane.tsx +75 -0
  47. package/src/components/modals/DiscardPrompt.tsx +38 -0
  48. package/src/components/modals/GatherContextStep.tsx +237 -107
  49. package/src/components/modals/ReferenceWizardModal.tsx +238 -50
  50. package/src/components/modals/ResourceGenerateModal.tsx +216 -108
  51. package/src/components/modals/SearchModal.css +337 -101
  52. package/src/components/modals/SearchResultsStep.tsx +61 -68
  53. package/src/components/modals/WizardFooter.tsx +7 -1
  54. package/src/components/modals/__tests__/ComposeStep.test.tsx +152 -0
  55. package/src/components/modals/__tests__/ConfigureGatherStep.test.tsx +14 -26
  56. package/src/components/modals/__tests__/ConfigureGenerationStep.test.tsx +35 -0
  57. package/src/components/modals/__tests__/ConfigureSearchStep.test.tsx +24 -1
  58. package/src/components/modals/__tests__/GatherContextStep.resource.test.tsx +463 -25
  59. package/src/components/modals/__tests__/ReferenceWizardModal.test.tsx +417 -38
  60. package/src/components/modals/__tests__/ResourceGenerateModal.test.tsx +276 -85
  61. package/src/components/modals/__tests__/SearchResultsStep.test.tsx +61 -0
  62. package/src/components/modals/__tests__/WizardFooter.test.tsx +113 -4
  63. package/src/components/pdf-annotation/PdfAnnotationCanvas.tsx +34 -1
  64. package/src/components/pdf-annotation/__tests__/PdfAnnotationCanvas.test.tsx +38 -1
  65. package/src/components/resource/AnnotateView.tsx +3 -3
  66. package/src/components/resource/BrowseView.tsx +5 -5
  67. package/src/components/resource/ResourceViewer.tsx +4 -4
  68. package/src/components/resource/__tests__/AnnotateView.embeddable.test.tsx +1 -1
  69. package/src/components/resource/__tests__/BrowseView.embeddable.test.tsx +1 -1
  70. package/src/components/resource/__tests__/BrowseView.test.tsx +9 -9
  71. package/src/components/resource/annotate-renderers.tsx +3 -3
  72. package/src/components/resource/panels/AssistSection.css +35 -0
  73. package/src/components/resource/panels/ReferenceEntry.tsx +9 -2
  74. package/src/components/resource/panels/ReferencesPanel.tsx +4 -0
  75. package/src/components/resource/panels/ResourceInfoPanel.tsx +89 -20
  76. package/src/components/resource/panels/UnifiedAnnotationsPanel.tsx +7 -2
  77. package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +41 -0
  78. package/src/components/resource/panels/__tests__/ReferencesPanel.test.tsx +33 -1
  79. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +148 -6
  80. package/src/features/resource-compose/__tests__/ResourceComposePage.test.tsx +0 -65
  81. package/src/features/resource-compose/components/ResourceComposePage.tsx +17 -130
  82. package/src/features/resource-compose/state/__tests__/compose-page-state-unit.test.ts +1 -100
  83. package/src/features/resource-compose/state/compose-page-state-unit.ts +5 -57
  84. package/src/features/resource-viewer/__tests__/ResourceViewerPage.test.tsx +71 -15
  85. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +133 -59
  86. package/src/styles/core/forms.css +35 -8
  87. package/src/styles/features/resource-viewer.css +0 -22
  88. package/src/styles/features/resource.css +0 -4
  89. package/translations/ar.json +38 -22
  90. package/translations/bn.json +38 -22
  91. package/translations/cs.json +38 -22
  92. package/translations/da.json +38 -22
  93. package/translations/de.json +38 -22
  94. package/translations/el.json +38 -22
  95. package/translations/en.json +38 -22
  96. package/translations/es.json +38 -22
  97. package/translations/fa.json +38 -22
  98. package/translations/fi.json +38 -22
  99. package/translations/fr.json +38 -22
  100. package/translations/he.json +38 -22
  101. package/translations/hi.json +38 -22
  102. package/translations/id.json +38 -22
  103. package/translations/it.json +38 -22
  104. package/translations/ja.json +38 -22
  105. package/translations/ko.json +38 -22
  106. package/translations/ms.json +38 -22
  107. package/translations/nl.json +38 -22
  108. package/translations/no.json +38 -22
  109. package/translations/pl.json +38 -22
  110. package/translations/pt.json +38 -22
  111. package/translations/ro.json +38 -22
  112. package/translations/sv.json +38 -22
  113. package/translations/th.json +38 -22
  114. package/translations/tr.json +38 -22
  115. package/translations/uk.json +38 -22
  116. package/translations/vi.json +38 -22
  117. package/translations/zh.json +38 -22
  118. package/dist/PdfAnnotationCanvas.client-EVUPTUWZ.js.map +0 -1
  119. package/dist/PdfAnnotationCanvas.client-TGDPPGXJ.css.map +0 -1
  120. package/dist/ar-OU3DQGC6.js.map +0 -1
  121. package/dist/bn-PHWCR6AZ.js.map +0 -1
  122. package/dist/chunk-5VDTWRXJ.js.map +0 -1
  123. package/dist/chunk-BTUG3VJJ.js.map +0 -1
  124. package/dist/chunk-O23TLLXW.js.map +0 -1
  125. package/dist/chunk-PCRRBU7H.js.map +0 -1
  126. package/dist/chunk-QT7LYM72.js.map +0 -1
  127. package/dist/chunk-VXASXU4K.js.map +0 -1
  128. package/dist/cs-NEXYZ62I.js.map +0 -1
  129. package/dist/da-FAT43YCU.js.map +0 -1
  130. package/dist/de-KRQ3WBCU.js.map +0 -1
  131. package/dist/el-Q4IU3EKC.js.map +0 -1
  132. package/dist/en-2KADE7N4.js.map +0 -1
  133. package/dist/es-2IO3R2MK.js.map +0 -1
  134. package/dist/fa-Q5GOQFXX.js.map +0 -1
  135. package/dist/fi-R6NMRWBE.js.map +0 -1
  136. package/dist/fr-QY4D5E6J.js.map +0 -1
  137. package/dist/he-X6Y77XHY.js.map +0 -1
  138. package/dist/hi-XL7IOEQM.js.map +0 -1
  139. package/dist/id-QZ4ZZS67.js.map +0 -1
  140. package/dist/index.css.map +0 -1
  141. package/dist/index.js.map +0 -1
  142. package/dist/integrations/css-modules-helper.js.map +0 -1
  143. package/dist/integrations/styled-components-theme.js.map +0 -1
  144. package/dist/it-ME2Q7OB6.js.map +0 -1
  145. package/dist/ja-HX7QASRI.js.map +0 -1
  146. package/dist/ko-EQO5AHAV.js.map +0 -1
  147. package/dist/ms-UILFSF3I.js.map +0 -1
  148. package/dist/nl-NNI45PMK.js.map +0 -1
  149. package/dist/no-MAL5F6P6.js.map +0 -1
  150. package/dist/pl-4RMY6JAJ.js.map +0 -1
  151. package/dist/pt-VQH2X3QQ.js.map +0 -1
  152. package/dist/ro-XXCQO2OG.js.map +0 -1
  153. package/dist/sv-7Z6EJ6U4.js.map +0 -1
  154. package/dist/test-utils.css.map +0 -1
  155. package/dist/test-utils.js.map +0 -1
  156. package/dist/th-L3DXXYVQ.js.map +0 -1
  157. package/dist/tr-P3DFVLFJ.js.map +0 -1
  158. package/dist/uk-7C5D3PXS.js.map +0 -1
  159. package/dist/vi-ZLTLEO7P.js.map +0 -1
  160. package/dist/zh-5FHVWDIN.js.map +0 -1
  161. package/src/components/modals/ResourceSearchModal.tsx +0 -224
  162. package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +0 -163
@@ -6,11 +6,6 @@
6
6
  z-index: 1000;
7
7
  }
8
8
 
9
- /* Resource search modal variant (higher z-index) */
10
- .semiont-search-modal--resource {
11
- z-index: 1001;
12
- }
13
-
14
9
  /* Backdrop */
15
10
  .semiont-search-modal__backdrop {
16
11
  position: fixed;
@@ -369,12 +364,7 @@
369
364
  outline-color: var(--semiont-color-primary-400);
370
365
  }
371
366
 
372
- /* Search form */
373
- .semiont-search-modal__search-form {
374
- margin-bottom: 1rem;
375
- }
376
-
377
- /* Search input (for ResourceSearchModal) */
367
+ /* Search input */
378
368
  .semiont-search-modal__search-input {
379
369
  width: 100%;
380
370
  padding: 0.5rem 0.75rem;
@@ -398,79 +388,16 @@
398
388
  outline-color: var(--semiont-color-primary-400);
399
389
  }
400
390
 
401
- /* Resource list */
402
- .semiont-search-modal__resource-list {
403
- display: flex;
404
- flex-direction: column;
405
- gap: 0.5rem;
406
- }
407
-
408
- /* Resource item */
409
- .semiont-search-modal__resource-item {
410
- padding: 0.75rem;
411
- border: 1px solid var(--semiont-color-gray-200);
412
- border-radius: 0.5rem;
413
- cursor: pointer;
414
- transition: background-color 0.2s;
415
- }
416
-
417
- .semiont-search-modal__resource-item:hover {
418
- background-color: var(--semiont-color-gray-50);
419
- }
420
-
421
- [data-theme="dark"] .semiont-search-modal__resource-item {
422
- border-color: var(--semiont-color-gray-700);
423
- }
424
-
425
- [data-theme="dark"] .semiont-search-modal__resource-item:hover {
426
- background-color: rgba(55, 65, 81, 0.5);
427
- }
428
-
429
- /* Resource name */
430
- .semiont-search-modal__resource-name {
431
- font-weight: 500;
432
- color: var(--semiont-color-gray-900);
433
- margin-bottom: 0.25rem;
434
- }
435
-
436
- [data-theme="dark"] .semiont-search-modal__resource-name {
437
- color: var(--semiont-color-white);
438
- }
439
-
440
- /* Resource description */
441
- .semiont-search-modal__resource-description {
442
- font-size: 0.875rem;
443
- color: var(--semiont-color-gray-600);
444
- display: -webkit-box;
445
- -webkit-line-clamp: 2;
446
- -webkit-box-orient: vertical;
447
- overflow: hidden;
448
- }
449
-
450
- [data-theme="dark"] .semiont-search-modal__resource-description {
451
- color: var(--semiont-color-gray-400);
452
- }
453
-
454
- /* Resource media type */
455
- .semiont-search-modal__resource-media-type {
456
- font-size: 0.875rem;
457
- font-style: italic;
458
- color: var(--semiont-color-gray-500);
459
- }
460
-
461
- [data-theme="dark"] .semiont-search-modal__resource-media-type {
462
- color: var(--semiont-color-gray-500);
463
- }
464
-
465
391
  /* Wide panel variant for two-pane layouts */
466
392
  .semiont-search-modal__panel--wide {
467
393
  max-width: 1100px;
468
394
  }
469
395
 
470
- /* Gather-context step: wider modal */
396
+ /* Gather-context step. Width comes from `--wide` (GEP D2: the family's own
397
+ 1100px precedent), applied alongside at both call sites — this class owns
398
+ only the gather-specific flex/height shape. */
471
399
  .semiont-search-modal__panel--gather {
472
- max-width: min(90vw, 820px);
473
- max-height: min(90vh, 680px);
400
+ max-height: min(92vh, 860px);
474
401
  display: flex;
475
402
  flex-direction: column;
476
403
  overflow: hidden;
@@ -497,6 +424,53 @@
497
424
  padding: 2rem 0;
498
425
  }
499
426
 
427
+ /* The gather skeleton: the loading screen is the loaded screen minus the
428
+ data — known annotation facts up top, pane headers in place, shimmer bars
429
+ where the gather's answers will land. */
430
+ .semiont-gather__skeleton {
431
+ display: flex;
432
+ flex-direction: column;
433
+ gap: 1rem;
434
+ flex: 1;
435
+ }
436
+
437
+ .semiont-gather__skeleton-source {
438
+ font-size: var(--semiont-text-sm);
439
+ color: var(--semiont-text-secondary);
440
+ }
441
+
442
+ .semiont-gather__skeleton-header {
443
+ display: flex;
444
+ align-items: center;
445
+ justify-content: space-between;
446
+ gap: 0.5rem;
447
+ }
448
+
449
+ .semiont-gather__skeleton-exact {
450
+ font-weight: var(--semiont-font-medium);
451
+ color: var(--semiont-text-primary);
452
+ }
453
+
454
+ .semiont-gather__skeleton-panes {
455
+ display: grid;
456
+ grid-template-columns: 1fr 1fr;
457
+ gap: 1.5rem;
458
+ }
459
+
460
+ .semiont-gather__skeleton-pane {
461
+ display: flex;
462
+ flex-direction: column;
463
+ gap: 0.5rem;
464
+ }
465
+
466
+ /* One small dots animation per zone, sitting exactly where that zone's
467
+ content will land. Reuses the loading-dot spans (same animation). */
468
+ .semiont-gather__skeleton-dots {
469
+ display: flex;
470
+ gap: 0.375rem;
471
+ padding: 0.375rem 0;
472
+ }
473
+
500
474
  .semiont-gather__loading-text {
501
475
  font-size: 1.125rem;
502
476
  color: var(--semiont-text-secondary);
@@ -531,6 +505,231 @@
531
505
  padding-top: 0.25rem;
532
506
  }
533
507
 
508
+ /* GEP P2: the evidence panes — quiet lists under small-cap headers (D1/D3/D4). */
509
+ .semiont-gather-pane {
510
+ display: flex;
511
+ flex-direction: column;
512
+ gap: 0.5rem;
513
+ min-height: 0;
514
+ overflow-y: auto; /* a pane scrolls inside itself; the panel never grows */
515
+ }
516
+
517
+ .semiont-gather-pane__title {
518
+ font-size: var(--semiont-text-xs);
519
+ font-weight: 700;
520
+ text-transform: uppercase;
521
+ letter-spacing: 0.06em;
522
+ color: var(--semiont-text-tertiary);
523
+ }
524
+
525
+ .semiont-gather-pane__summary {
526
+ margin: 0;
527
+ font-size: var(--semiont-text-sm);
528
+ color: var(--semiont-text-primary);
529
+ }
530
+
531
+ .semiont-gather-pane__empty {
532
+ margin: 0;
533
+ font-size: var(--semiont-text-sm);
534
+ font-style: italic;
535
+ color: var(--semiont-text-secondary);
536
+ }
537
+
538
+ .semiont-corpus__list {
539
+ display: flex;
540
+ flex-direction: column;
541
+ gap: 0.5rem;
542
+ list-style: none;
543
+ padding: 0;
544
+ margin: 0;
545
+ }
546
+
547
+ .semiont-corpus__card {
548
+ padding: 0.375rem 0.5rem;
549
+ border: 1px solid var(--semiont-border-primary);
550
+ border-radius: 0.375rem;
551
+ }
552
+
553
+ .semiont-corpus__card-head {
554
+ display: flex;
555
+ align-items: baseline;
556
+ flex-wrap: wrap;
557
+ gap: 0.375rem;
558
+ }
559
+
560
+ .semiont-corpus__source {
561
+ font-size: var(--semiont-text-sm);
562
+ font-weight: 500;
563
+ color: var(--semiont-text-primary);
564
+ }
565
+
566
+ .semiont-corpus__score {
567
+ margin-left: auto;
568
+ font-size: var(--semiont-text-xs);
569
+ font-variant-numeric: tabular-nums;
570
+ color: var(--semiont-text-tertiary);
571
+ }
572
+
573
+ .semiont-corpus__snippet {
574
+ margin: 0.25rem 0 0;
575
+ font-size: var(--semiont-text-xs);
576
+ color: var(--semiont-text-secondary);
577
+ }
578
+
579
+ .semiont-corpus__receipt {
580
+ margin: 0;
581
+ font-size: var(--semiont-text-xs);
582
+ font-style: italic;
583
+ color: var(--semiont-text-tertiary);
584
+ }
585
+
586
+ /* GEP P4 (D3): the graph pane's body — a deterministic, hand-rolled SVG. */
587
+ .semiont-graph {
588
+ width: 100%;
589
+ height: auto;
590
+ flex-shrink: 0;
591
+ }
592
+
593
+ .semiont-graph__node rect {
594
+ fill: var(--semiont-bg-secondary);
595
+ stroke: var(--semiont-border-primary);
596
+ stroke-width: 1;
597
+ }
598
+
599
+ .semiont-graph__node text {
600
+ font-size: 11px;
601
+ fill: var(--semiont-text-primary);
602
+ }
603
+
604
+ .semiont-graph__node--focal rect {
605
+ fill: var(--semiont-color-primary-100);
606
+ stroke: var(--semiont-color-primary-600);
607
+ stroke-width: 2;
608
+ }
609
+
610
+ .semiont-graph__node--annotation rect {
611
+ fill: var(--semiont-bg-primary);
612
+ stroke-dasharray: 4 3;
613
+ }
614
+
615
+ .semiont-graph__edge line {
616
+ stroke: var(--semiont-border-primary);
617
+ stroke-width: 1.5;
618
+ }
619
+
620
+ .semiont-graph__edge--cites line {
621
+ stroke: var(--semiont-color-primary-600);
622
+ }
623
+
624
+ .semiont-graph__edge--annotation-of line {
625
+ stroke-dasharray: 4 3;
626
+ }
627
+
628
+ [data-theme="dark"] .semiont-graph__node--focal rect {
629
+ fill: var(--semiont-color-primary-900);
630
+ stroke: var(--semiont-color-primary-400);
631
+ }
632
+
633
+ [data-theme="dark"] .semiont-graph__edge--cites line {
634
+ stroke: var(--semiont-color-primary-400);
635
+ }
636
+
637
+ /* Recall chips: the exclusion picker inverted — every entity type starts
638
+ INCLUDED, wearing the app's token look (the semiont-tag tint), and a click
639
+ crosses one off the recall: outline, tertiary text, struck through. The
640
+ wire still carries the exclude list; only the presentation inverted. */
641
+ .semiont-form__recall-chips {
642
+ display: flex;
643
+ flex-wrap: wrap;
644
+ gap: 0.375rem;
645
+ }
646
+
647
+ .semiont-form__recall-chip {
648
+ padding: 0.25rem 0.75rem;
649
+ border-radius: var(--semiont-radius-full);
650
+ font-size: var(--semiont-text-sm);
651
+ cursor: pointer;
652
+ border: 1px solid transparent;
653
+ background: var(--semiont-color-primary-100);
654
+ color: var(--semiont-color-primary-700);
655
+ }
656
+
657
+ [data-theme="dark"] .semiont-form__recall-chip {
658
+ background: var(--semiont-color-primary-900);
659
+ color: var(--semiont-color-primary-300);
660
+ }
661
+
662
+ .semiont-form__recall-chip[data-included="false"] {
663
+ background: none;
664
+ border-color: var(--semiont-border-primary);
665
+ color: var(--semiont-text-tertiary);
666
+ text-decoration: line-through;
667
+ }
668
+
669
+ .semiont-form__recall-chip:hover {
670
+ opacity: 0.85;
671
+ }
672
+
673
+ .semiont-form__recall-chip:focus-visible {
674
+ outline: 2px solid var(--semiont-color-primary-500);
675
+ outline-offset: 1px;
676
+ }
677
+
678
+ /* Post-gather receipt: the spent controls' compact echo — what THIS gather
679
+ asked for, and the way back to the full form. Same vocabulary as the
680
+ corpus pane's exclusion receipt and the wizard's strategy band: a choice
681
+ made upstream, echoed compactly. Dashed like the graph's annotation
682
+ nodes — a stand-in for something expandable. */
683
+ .semiont-gather-receipt {
684
+ display: block;
685
+ width: 100%;
686
+ flex-shrink: 0;
687
+ text-align: left;
688
+ padding: 0.5rem 0.75rem;
689
+ font-size: var(--semiont-text-sm);
690
+ color: var(--semiont-text-secondary);
691
+ background: none;
692
+ border: 1px dashed var(--semiont-border-primary);
693
+ border-radius: 0.375rem;
694
+ cursor: pointer;
695
+ }
696
+
697
+ .semiont-gather-receipt:hover {
698
+ color: var(--semiont-text-primary);
699
+ border-color: var(--semiont-color-primary-600);
700
+ }
701
+
702
+ /* GEP D5: the hint on its own full-width row, input-then-act above the footer. */
703
+ .semiont-gather__hint-row {
704
+ flex-shrink: 0;
705
+ padding-top: 0.5rem;
706
+ }
707
+
708
+ .semiont-gather__hint-effect {
709
+ font-weight: 400;
710
+ color: var(--semiont-text-tertiary);
711
+ }
712
+
713
+ /* GEP D8: the gather step's hint stays visible while being steered by. */
714
+ .semiont-wizard__hint-echo {
715
+ margin: 0 0 0.5rem;
716
+ font-size: var(--semiont-text-xs);
717
+ font-style: italic;
718
+ color: var(--semiont-text-secondary);
719
+ }
720
+
721
+ /* Suggested references are prose (D3) — sentences, listed, not chipped. */
722
+ .semiont-gather__suggested {
723
+ margin: 0.5rem 0 0;
724
+ padding-left: 1.25rem;
725
+ font-size: var(--semiont-text-xs);
726
+ color: var(--semiont-text-secondary);
727
+ }
728
+
729
+ .semiont-gather__suggested li {
730
+ margin-bottom: 0.25rem;
731
+ }
732
+
534
733
  /* Two-column body below the strip */
535
734
  .semiont-gather__body {
536
735
  display: flex;
@@ -595,6 +794,26 @@
595
794
  margin-bottom: 0.5rem;
596
795
  }
597
796
 
797
+ /* The chosen strategy on a strategy step — the chooser band collapsed to its
798
+ selection: a passive echo on the label's own line (--echo). Sized like the
799
+ form's text and in the TEXT color: blue is reserved for controls, and this
800
+ is never a control — the emoji carries the strategy's identity. */
801
+ .semiont-gather__footer--echo {
802
+ display: flex;
803
+ align-items: baseline;
804
+ gap: 0.75rem;
805
+ }
806
+
807
+ .semiont-gather__footer--echo .semiont-gather__footer-label {
808
+ margin-bottom: 0;
809
+ }
810
+
811
+ .semiont-gather__chosen-strategy {
812
+ font-size: var(--semiont-text-sm);
813
+ font-weight: var(--semiont-font-semibold);
814
+ color: var(--semiont-text-primary);
815
+ }
816
+
598
817
  .semiont-gather__actions {
599
818
  display: flex;
600
819
  flex-flow: row nowrap;
@@ -696,40 +915,57 @@
696
915
  }
697
916
  }
698
917
 
699
- /* Two-pane layout for search results + context */
700
- .semiont-search-results__two-pane {
918
+ /* D4 discard guard: inline prompt raised when dismissal would destroy a
919
+ non-empty compose draft. Never window.confirm; the footer stays
920
+ dismissal-free (A4) — this band owns the decision. */
921
+ .semiont-wizard__discard-prompt {
701
922
  display: flex;
702
- gap: 1.5rem;
923
+ align-items: center;
924
+ gap: 0.75rem;
925
+ margin-bottom: 0.75rem;
926
+ padding: 0.5rem 0.75rem;
927
+ border: 1px solid var(--semiont-color-red-600);
928
+ border-radius: var(--semiont-radius-md);
703
929
  }
704
930
 
705
- .semiont-search-results__context-pane {
706
- flex: 0 0 340px;
707
- max-height: 500px;
708
- overflow-y: auto;
931
+ .semiont-wizard__discard-prompt-text {
932
+ flex: 1;
933
+ font-weight: var(--semiont-font-semibold);
709
934
  }
710
935
 
711
- .semiont-search-results__results-pane {
936
+ /* The strategy steps' single scroll pane: evidence + step content scroll
937
+ TOGETHER inside the clipped gather panel. The hosts start it scrolled to
938
+ the bottom on entry, so the step's own content shows in full and the
939
+ evidence tucks up under the modal top. */
940
+ .semiont-wizard__step-scroll {
712
941
  flex: 1;
713
- max-height: 500px;
942
+ min-height: 0;
714
943
  overflow-y: auto;
944
+ display: flex;
945
+ flex-direction: column;
946
+ }
947
+
948
+ /* Inside the single pane the display flows at natural height — the gather
949
+ step's clip-and-scroll flex (outer/body/panes each scrolling internally)
950
+ would otherwise compress the evidence AND nest scrollbars. One scrollbar
951
+ governs the whole step. */
952
+ .semiont-wizard__step-scroll .semiont-gather__outer,
953
+ .semiont-wizard__step-scroll .semiont-gather__body {
954
+ flex: none;
955
+ min-height: auto;
956
+ overflow: visible;
715
957
  }
716
958
 
717
- /* Narrow screens: stack vertically, context above results */
959
+ .semiont-wizard__step-scroll .semiont-gather__left,
960
+ .semiont-wizard__step-scroll .semiont-gather__right,
961
+ .semiont-wizard__step-scroll .semiont-gather-pane {
962
+ min-height: auto;
963
+ overflow-y: visible;
964
+ }
965
+
966
+ /* Narrow screens */
718
967
  @media (max-width: 640px) {
719
968
  .semiont-search-modal__panel--wide {
720
969
  max-width: 100%;
721
970
  }
722
-
723
- .semiont-search-results__two-pane {
724
- flex-direction: column;
725
- }
726
-
727
- .semiont-search-results__context-pane {
728
- flex: none;
729
- max-height: 200px;
730
- }
731
-
732
- .semiont-search-results__results-pane {
733
- max-height: 350px;
734
- }
735
971
  }
@@ -1,18 +1,21 @@
1
1
  'use client';
2
2
  import { WizardFooter } from './WizardFooter';
3
3
 
4
- import type { GatheredContext, ResourceDescriptor } from '@semiont/core';
5
- import { ContextSummary } from './ContextSummary';
6
- import type { ContextSummaryTranslations } from './ContextSummary';
4
+ import type { ResourceDescriptor } from '@semiont/core';
7
5
 
8
6
  export type ScoredResult = ResourceDescriptor & {
9
7
  score?: number;
10
8
  matchReason?: string;
11
9
  };
12
10
 
11
+ /**
12
+ * Pure RESULTS (GEP D10, amended): ranked rows with scores and Link buttons.
13
+ * The evidence display is the HOST's job — the wizard stacks the full
14
+ * display-only GatherContextStep (with the collapsed strategy band) above
15
+ * this step, the same grammar as the configure steps.
16
+ */
13
17
  export interface SearchResultsStepProps {
14
18
  results: ScoredResult[];
15
- context: GatheredContext;
16
19
  onLink: (resourceId: string) => void;
17
20
  onBack: () => void;
18
21
  translations: {
@@ -20,84 +23,74 @@ export interface SearchResultsStepProps {
20
23
  link: string;
21
24
  back: string;
22
25
  score: string;
23
- } & ContextSummaryTranslations;
26
+ };
24
27
  }
25
28
 
26
29
  export function SearchResultsStep({
27
30
  results,
28
- context,
29
31
  onLink,
30
32
  onBack,
31
33
  translations: t,
32
34
  }: SearchResultsStepProps) {
33
35
  return (
34
36
  <>
35
- {/* Two-pane layout: context left, results right */}
36
- <div className="semiont-search-results__two-pane">
37
- {/* Left: Gathered Context */}
38
- <div className="semiont-search-results__context-pane">
39
- <ContextSummary context={context} translations={t} />
40
- </div>
41
-
42
- {/* Right: Results List */}
43
- <div className="semiont-search-results__results-pane">
44
- {results.length === 0 ? (
45
- <div className="semiont-modal__empty-state" style={{ textAlign: 'center', padding: '2rem 0' }}>
46
- {t.noResults}
47
- </div>
48
- ) : (
49
- results.map((result) => {
50
- const id = result['@id'];
51
- return (
52
- <div
53
- key={id}
54
- style={{
55
- padding: '0.75rem',
56
- borderBottom: '1px solid var(--semiont-border-primary)',
57
- display: 'flex',
58
- alignItems: 'center',
59
- justifyContent: 'space-between',
60
- gap: '0.75rem',
61
- }}
62
- >
63
- <div style={{ flex: 1, minWidth: 0 }}>
64
- <div style={{ fontWeight: 500, color: 'var(--semiont-text-primary)' }}>
65
- {result.name}
37
+ <div className="semiont-search-results">
38
+ {results.length === 0 ? (
39
+ <div className="semiont-modal__empty-state" style={{ textAlign: 'center', padding: '2rem 0' }}>
40
+ {t.noResults}
41
+ </div>
42
+ ) : (
43
+ results.map((result) => {
44
+ const id = result['@id'];
45
+ return (
46
+ <div
47
+ key={id}
48
+ style={{
49
+ padding: '0.75rem',
50
+ borderBottom: '1px solid var(--semiont-border-primary)',
51
+ display: 'flex',
52
+ alignItems: 'center',
53
+ justifyContent: 'space-between',
54
+ gap: '0.75rem',
55
+ }}
56
+ >
57
+ <div style={{ flex: 1, minWidth: 0 }}>
58
+ <div style={{ fontWeight: 500, color: 'var(--semiont-text-primary)' }}>
59
+ {result.name}
60
+ </div>
61
+ {result.description && (
62
+ <div style={{
63
+ fontSize: 'var(--semiont-text-sm)',
64
+ color: 'var(--semiont-text-secondary)',
65
+ marginTop: '0.25rem',
66
+ overflow: 'hidden',
67
+ textOverflow: 'ellipsis',
68
+ whiteSpace: 'nowrap',
69
+ }}>
70
+ {result.description}
66
71
  </div>
67
- {result.description && (
68
- <div style={{
69
- fontSize: 'var(--semiont-text-sm)',
70
- color: 'var(--semiont-text-secondary)',
71
- marginTop: '0.25rem',
72
- overflow: 'hidden',
73
- textOverflow: 'ellipsis',
74
- whiteSpace: 'nowrap',
75
- }}>
76
- {result.description}
77
- </div>
72
+ )}
73
+ <div style={{ fontSize: 'var(--semiont-text-xs)', color: 'var(--semiont-text-tertiary)', marginTop: '0.25rem', display: 'flex', gap: '0.5rem' }}>
74
+ {result.score !== undefined && (
75
+ <span>{t.score}: {result.score}</span>
76
+ )}
77
+ {result.matchReason && (
78
+ <span>{result.matchReason}</span>
78
79
  )}
79
- <div style={{ fontSize: 'var(--semiont-text-xs)', color: 'var(--semiont-text-tertiary)', marginTop: '0.25rem', display: 'flex', gap: '0.5rem' }}>
80
- {result.score !== undefined && (
81
- <span>{t.score}: {result.score}</span>
82
- )}
83
- {result.matchReason && (
84
- <span>{result.matchReason}</span>
85
- )}
86
- </div>
87
80
  </div>
88
- <button
89
- type="button"
90
- onClick={() => onLink(id)}
91
- className="semiont-button--primary"
92
- style={{ flexShrink: 0 }}
93
- >
94
- 🔗 {t.link}
95
- </button>
96
81
  </div>
97
- );
98
- })
99
- )}
100
- </div>
82
+ <button
83
+ type="button"
84
+ onClick={() => onLink(id)}
85
+ className="semiont-button--primary"
86
+ style={{ flexShrink: 0 }}
87
+ >
88
+ 🔗 {t.link}
89
+ </button>
90
+ </div>
91
+ );
92
+ })
93
+ )}
101
94
  </div>
102
95
 
103
96
  <WizardFooter backLabel={t.back} onBack={onBack} />
@@ -20,6 +20,12 @@ export interface WizardFooterPrimary {
20
20
  /** Shown while `pending`; falls back to `label`. */
21
21
  pendingLabel?: string;
22
22
  pending?: boolean;
23
+ /**
24
+ * The action's PRECONDITION is not met yet (e.g. the review step waiting on
25
+ * gather). Unlike `pending` — the action itself running — this disables only
26
+ * the primary: retreat must stay live while a precondition loads.
27
+ */
28
+ disabled?: boolean;
23
29
  type: 'submit' | 'button';
24
30
  onClick?: () => void;
25
31
  }
@@ -52,7 +58,7 @@ export function WizardFooter({ backLabel, onBack, primary }: WizardFooterProps)
52
58
  type={primary.type}
53
59
  {...(primary.onClick ? { onClick: primary.onClick } : {})}
54
60
  className="semiont-button--primary"
55
- disabled={pending}
61
+ disabled={pending || (primary.disabled ?? false)}
56
62
  data-pending={pending ? 'true' : 'false'}
57
63
  >
58
64
  {pending ? (primary.pendingLabel ?? primary.label) : primary.label}