@semiont/react-ui 0.5.6 → 0.5.7

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 (155) hide show
  1. package/README.md +1 -1
  2. package/dist/{ar-U2EXWUMQ.js → ar-SONK6MON.js} +3 -7
  3. package/dist/ar-SONK6MON.js.map +1 -0
  4. package/dist/{bn-DRJGV772.js → bn-ZKPRITNG.js} +3 -7
  5. package/dist/bn-ZKPRITNG.js.map +1 -0
  6. package/dist/{chunk-3Q3TUKWP.js → chunk-Y2EEAOMZ.js} +29 -29
  7. package/dist/{cs-PTWDM23V.js → cs-LPXQ7NHQ.js} +3 -7
  8. package/dist/cs-LPXQ7NHQ.js.map +1 -0
  9. package/dist/{da-KSNIKYSS.js → da-6TKY7MCY.js} +6 -10
  10. package/dist/da-6TKY7MCY.js.map +1 -0
  11. package/dist/{de-F2XBEWFY.js → de-C3GNII74.js} +3 -7
  12. package/dist/de-C3GNII74.js.map +1 -0
  13. package/dist/{el-DLD2GWAP.js → el-UBCXQDJ7.js} +3 -7
  14. package/dist/el-UBCXQDJ7.js.map +1 -0
  15. package/dist/{es-WLPYWGB5.js → es-BQ23TRI7.js} +11 -15
  16. package/dist/es-BQ23TRI7.js.map +1 -0
  17. package/dist/{fa-BAXHSDZG.js → fa-AFTBZB77.js} +3 -7
  18. package/dist/fa-AFTBZB77.js.map +1 -0
  19. package/dist/{fi-FCHSYVOT.js → fi-WOYNLZC2.js} +3 -7
  20. package/dist/fi-WOYNLZC2.js.map +1 -0
  21. package/dist/{fr-3UERBSL6.js → fr-NDSMIFJM.js} +3 -7
  22. package/dist/fr-NDSMIFJM.js.map +1 -0
  23. package/dist/{he-F6F3FV2K.js → he-VJXVRDOY.js} +3 -7
  24. package/dist/he-VJXVRDOY.js.map +1 -0
  25. package/dist/{hi-4BK6IK7Q.js → hi-BF6PHIE2.js} +3 -7
  26. package/dist/hi-BF6PHIE2.js.map +1 -0
  27. package/dist/{id-7ECCWP3J.js → id-GXG5QCZY.js} +3 -7
  28. package/dist/id-GXG5QCZY.js.map +1 -0
  29. package/dist/index.css +97 -0
  30. package/dist/index.css.map +1 -1
  31. package/dist/index.d.ts +29 -22
  32. package/dist/index.js +346 -301
  33. package/dist/index.js.map +1 -1
  34. package/dist/{it-234Z6XK6.js → it-XKHHCBAF.js} +3 -7
  35. package/dist/it-XKHHCBAF.js.map +1 -0
  36. package/dist/{ja-PJWQI4OQ.js → ja-TX7VM4XD.js} +3 -7
  37. package/dist/ja-TX7VM4XD.js.map +1 -0
  38. package/dist/{ko-APUEW2RS.js → ko-DNC7EQ7J.js} +3 -7
  39. package/dist/ko-DNC7EQ7J.js.map +1 -0
  40. package/dist/{ms-PJBZWZWD.js → ms-POZGBKPH.js} +3 -7
  41. package/dist/ms-POZGBKPH.js.map +1 -0
  42. package/dist/{nl-L4C3ZBCU.js → nl-IRMTKI7Z.js} +4 -11
  43. package/dist/nl-IRMTKI7Z.js.map +1 -0
  44. package/dist/{no-QE5N5KNG.js → no-ZUDJA4S6.js} +20 -24
  45. package/dist/no-ZUDJA4S6.js.map +1 -0
  46. package/dist/{pl-5Q2D23PD.js → pl-2NGAXL5U.js} +3 -7
  47. package/dist/pl-2NGAXL5U.js.map +1 -0
  48. package/dist/{pt-AIGUOIOC.js → pt-ABMCXZUM.js} +118 -122
  49. package/dist/pt-ABMCXZUM.js.map +1 -0
  50. package/dist/{ro-T56CSHTY.js → ro-VOJP6O5X.js} +3 -7
  51. package/dist/ro-VOJP6O5X.js.map +1 -0
  52. package/dist/{sv-L4TJQ2UH.js → sv-4HVFIIE5.js} +43 -47
  53. package/dist/sv-4HVFIIE5.js.map +1 -0
  54. package/dist/test-utils.js +2 -2
  55. package/dist/test-utils.js.map +1 -1
  56. package/dist/{th-6O7Y6O2Q.js → th-IFPZP3HQ.js} +3 -7
  57. package/dist/th-IFPZP3HQ.js.map +1 -0
  58. package/dist/{tr-D4CQCSNO.js → tr-2GYEAMJ4.js} +3 -7
  59. package/dist/tr-2GYEAMJ4.js.map +1 -0
  60. package/dist/{uk-2HMQG6ND.js → uk-XCJBVLLD.js} +3 -7
  61. package/dist/uk-XCJBVLLD.js.map +1 -0
  62. package/dist/{vi-XVJ4RUEJ.js → vi-4FR7CB2F.js} +3 -7
  63. package/dist/vi-4FR7CB2F.js.map +1 -0
  64. package/dist/{zh-K2KDPGHK.js → zh-NSKFOINB.js} +3 -7
  65. package/dist/zh-NSKFOINB.js.map +1 -0
  66. package/package.json +2 -2
  67. package/src/components/ProtectedErrorBoundary.css +119 -0
  68. package/src/components/ProtectedErrorBoundary.tsx +18 -13
  69. package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +1 -1
  70. package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +1 -1
  71. package/src/components/resource/AnnotateView.tsx +35 -37
  72. package/src/components/resource/BrowseView.tsx +31 -31
  73. package/src/components/resource/__tests__/AnnotationHistory.test.tsx +0 -1
  74. package/src/components/resource/__tests__/BrowseView.test.tsx +4 -8
  75. package/src/components/resource/__tests__/HistoryEvent.test.tsx +0 -1
  76. package/src/components/resource/__tests__/event-formatting.test.ts +1 -1
  77. package/src/components/resource/panels/CollaborationPanel.tsx +1 -1
  78. package/src/components/resource/panels/JsonLdPanel.tsx +33 -16
  79. package/src/components/resource/panels/__tests__/AssessmentEntry.test.tsx +1 -1
  80. package/src/components/resource/panels/__tests__/AssessmentPanel.test.tsx +1 -1
  81. package/src/components/resource/panels/__tests__/CommentEntry.test.tsx +1 -1
  82. package/src/components/resource/panels/__tests__/CommentsPanel.test.tsx +1 -1
  83. package/src/components/resource/panels/__tests__/HighlightEntry.test.tsx +1 -1
  84. package/src/components/resource/panels/__tests__/JsonLdPanel.test.tsx +95 -424
  85. package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +1 -1
  86. package/src/components/resource/panels/__tests__/TagEntry.test.tsx +1 -1
  87. package/src/components/resource/panels/__tests__/TaggingPanel.test.tsx +1 -1
  88. package/src/features/admin-exchange/__tests__/AdminExchangePage.test.tsx +7 -10
  89. package/src/features/admin-exchange/__tests__/ImportProgress.test.tsx +38 -27
  90. package/src/features/admin-exchange/components/ImportProgress.tsx +28 -34
  91. package/src/features/moderation-linked-data/__tests__/LinkedDataPage.test.tsx +11 -9
  92. package/src/features/resource-compose/components/ResourceComposePage.tsx +36 -9
  93. package/src/features/resource-compose/state/compose-page-state-unit.ts +5 -8
  94. package/src/features/resource-viewer/components/ResourceViewerPage.tsx +7 -5
  95. package/src/features/resource-viewer/state/__tests__/resource-viewer-page-state-unit.test.ts +37 -0
  96. package/src/features/resource-viewer/state/resource-viewer-page-state-unit.ts +9 -5
  97. package/src/styles/features/exchange.css +0 -30
  98. package/src/styles/index.css +1 -0
  99. package/translations/ar.json +1 -3
  100. package/translations/bn.json +1 -3
  101. package/translations/cs.json +1 -3
  102. package/translations/da.json +4 -6
  103. package/translations/de.json +1 -3
  104. package/translations/el.json +1 -3
  105. package/translations/es.json +9 -11
  106. package/translations/fa.json +1 -3
  107. package/translations/fi.json +1 -3
  108. package/translations/fr.json +1 -3
  109. package/translations/he.json +1 -3
  110. package/translations/hi.json +1 -3
  111. package/translations/id.json +1 -3
  112. package/translations/it.json +1 -3
  113. package/translations/ja.json +1 -3
  114. package/translations/ko.json +1 -3
  115. package/translations/ms.json +1 -3
  116. package/translations/nl.json +2 -7
  117. package/translations/no.json +18 -20
  118. package/translations/pl.json +1 -3
  119. package/translations/pt.json +116 -118
  120. package/translations/ro.json +1 -3
  121. package/translations/sv.json +41 -43
  122. package/translations/th.json +1 -3
  123. package/translations/tr.json +1 -3
  124. package/translations/uk.json +1 -3
  125. package/translations/vi.json +1 -3
  126. package/translations/zh.json +1 -3
  127. package/dist/ar-U2EXWUMQ.js.map +0 -1
  128. package/dist/bn-DRJGV772.js.map +0 -1
  129. package/dist/cs-PTWDM23V.js.map +0 -1
  130. package/dist/da-KSNIKYSS.js.map +0 -1
  131. package/dist/de-F2XBEWFY.js.map +0 -1
  132. package/dist/el-DLD2GWAP.js.map +0 -1
  133. package/dist/es-WLPYWGB5.js.map +0 -1
  134. package/dist/fa-BAXHSDZG.js.map +0 -1
  135. package/dist/fi-FCHSYVOT.js.map +0 -1
  136. package/dist/fr-3UERBSL6.js.map +0 -1
  137. package/dist/he-F6F3FV2K.js.map +0 -1
  138. package/dist/hi-4BK6IK7Q.js.map +0 -1
  139. package/dist/id-7ECCWP3J.js.map +0 -1
  140. package/dist/it-234Z6XK6.js.map +0 -1
  141. package/dist/ja-PJWQI4OQ.js.map +0 -1
  142. package/dist/ko-APUEW2RS.js.map +0 -1
  143. package/dist/ms-PJBZWZWD.js.map +0 -1
  144. package/dist/nl-L4C3ZBCU.js.map +0 -1
  145. package/dist/no-QE5N5KNG.js.map +0 -1
  146. package/dist/pl-5Q2D23PD.js.map +0 -1
  147. package/dist/pt-AIGUOIOC.js.map +0 -1
  148. package/dist/ro-T56CSHTY.js.map +0 -1
  149. package/dist/sv-L4TJQ2UH.js.map +0 -1
  150. package/dist/th-6O7Y6O2Q.js.map +0 -1
  151. package/dist/tr-D4CQCSNO.js.map +0 -1
  152. package/dist/uk-2HMQG6ND.js.map +0 -1
  153. package/dist/vi-XVJ4RUEJ.js.map +0 -1
  154. package/dist/zh-K2KDPGHK.js.map +0 -1
  155. /package/dist/{chunk-3Q3TUKWP.js.map → chunk-Y2EEAOMZ.js.map} +0 -0
package/dist/index.js CHANGED
@@ -124,7 +124,7 @@ import {
124
124
  useSemiont,
125
125
  useToast,
126
126
  useTranslations
127
- } from "./chunk-3Q3TUKWP.js";
127
+ } from "./chunk-Y2EEAOMZ.js";
128
128
  import "./chunk-GERSK2DY.js";
129
129
  import {
130
130
  __commonJS,
@@ -17518,12 +17518,12 @@ function hideWidgetPreview(container) {
17518
17518
  }
17519
17519
 
17520
17520
  // src/lib/media-shapes.ts
17521
- import { isPdfMimeType } from "@semiont/core";
17521
+ import { capabilitiesOf } from "@semiont/core";
17522
17522
  function getSupportedShapes(mediaType) {
17523
17523
  if (!mediaType) {
17524
17524
  return ["rectangle", "circle", "polygon"];
17525
17525
  }
17526
- if (isPdfMimeType(mediaType)) {
17526
+ if (capabilitiesOf(mediaType)?.render === "pdf") {
17527
17527
  return ["rectangle"];
17528
17528
  }
17529
17529
  if (mediaType.startsWith("image/")) {
@@ -17538,7 +17538,7 @@ function getSelectorType(mediaType) {
17538
17538
  if (!mediaType) {
17539
17539
  return "text";
17540
17540
  }
17541
- if (isPdfMimeType(mediaType)) {
17541
+ if (capabilitiesOf(mediaType)?.render === "pdf") {
17542
17542
  return "fragment";
17543
17543
  }
17544
17544
  if (mediaType.startsWith("image/")) {
@@ -17721,27 +17721,23 @@ function toOverlayAnnotations(annotations) {
17721
17721
  }
17722
17722
 
17723
17723
  // src/lib/resource-utils.ts
17724
+ import { baseMediaType, capabilitiesOf as capabilitiesOf2 } from "@semiont/core";
17724
17725
  function getResourceIcon(mediaType) {
17725
17726
  if (!mediaType) return "\u{1F4C4}";
17726
- const baseType = mediaType.split(";")[0]?.trim().toLowerCase() || "";
17727
- if (baseType.startsWith("image/")) {
17728
- return "\u{1F5BC}\uFE0F";
17729
- }
17730
- switch (baseType) {
17727
+ const base2 = baseMediaType(mediaType);
17728
+ if (base2.startsWith("image/")) return "\u{1F5BC}\uFE0F";
17729
+ switch (base2) {
17731
17730
  case "text/markdown":
17732
17731
  return "\u{1F4DD}";
17733
17732
  case "text/html":
17734
17733
  return "\u{1F310}";
17735
- case "text/plain":
17736
- return "\u{1F4C4}";
17737
17734
  default:
17738
17735
  return "\u{1F4C4}";
17739
17736
  }
17740
17737
  }
17741
17738
  function supportsDetection(mediaType) {
17742
17739
  if (!mediaType) return false;
17743
- const baseType = mediaType.split(";")[0]?.trim().toLowerCase() || "";
17744
- return baseType.startsWith("text/");
17740
+ return capabilitiesOf2(mediaType)?.anchoring === "text-selector";
17745
17741
  }
17746
17742
 
17747
17743
  // src/lib/validation.ts
@@ -18497,11 +18493,9 @@ function useResourceContent(rUri, resource, enabled = true) {
18497
18493
  if (!semiont || !enabled || !mediaType) return;
18498
18494
  let cancelled = false;
18499
18495
  setLoading(true);
18500
- semiont.browse.resourceRepresentation(rUri, {
18501
- accept: mediaType
18502
- }).then(({ data: data2 }) => {
18496
+ semiont.browse.resourceRepresentation(rUri).then(({ data: data2, contentType }) => {
18503
18497
  if (cancelled) return;
18504
- setContent(decodeWithCharset(data2, mediaType));
18498
+ setContent(decodeWithCharset(data2, contentType));
18505
18499
  setLoading(false);
18506
18500
  }).catch((error) => {
18507
18501
  if (cancelled) return;
@@ -26887,25 +26881,27 @@ function ProtectedErrorBoundary({
26887
26881
  function ProtectedErrorFallback({ error, resetErrorBoundary }) {
26888
26882
  const message = error instanceof Error ? error.message : String(error);
26889
26883
  const stack = error instanceof Error ? error.stack : void 0;
26890
- return /* @__PURE__ */ jsx9("div", { className: "min-h-[400px] flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs4("div", { className: "max-w-md w-full bg-white dark:bg-gray-800 rounded-lg shadow-lg p-6", children: [
26891
- /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-3 mb-4", children: [
26892
- /* @__PURE__ */ jsx9("div", { className: "flex-shrink-0 w-10 h-10 bg-red-100 dark:bg-red-900/30 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx9("svg", { className: "w-6 h-6 text-red-600 dark:text-red-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }) }),
26893
- /* @__PURE__ */ jsx9("h2", { className: "text-xl font-semibold text-gray-900 dark:text-white", children: "Something went wrong" })
26884
+ return /* @__PURE__ */ jsx9("div", { className: "semiont-protected-error-boundary-container", children: /* @__PURE__ */ jsxs4("div", { className: "semiont-protected-error-boundary-card", children: [
26885
+ /* @__PURE__ */ jsxs4("div", { className: "semiont-protected-error-boundary-header", children: [
26886
+ /* @__PURE__ */ jsx9("div", { className: "semiont-protected-error-boundary-icon-wrapper", children: /* @__PURE__ */ jsx9("svg", { className: "semiont-protected-error-boundary-icon", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx9("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" }) }) }),
26887
+ /* @__PURE__ */ jsx9("h2", { className: "semiont-protected-error-boundary-title", children: "Something went wrong" })
26894
26888
  ] }),
26895
- /* @__PURE__ */ jsx9("p", { className: "text-gray-600 dark:text-gray-300 mb-6", children: "An unexpected error occurred. Try again, or refresh the page." }),
26896
- process.env.NODE_ENV === "development" && /* @__PURE__ */ jsxs4("details", { className: "mb-4", children: [
26897
- /* @__PURE__ */ jsx9("summary", { className: "text-sm text-gray-500 cursor-pointer hover:text-gray-700 dark:hover:text-gray-300", children: "Error details (development only)" }),
26898
- /* @__PURE__ */ jsxs4("pre", { className: "mt-2 text-xs bg-gray-100 dark:bg-gray-900 p-2 rounded-sm overflow-auto", children: [
26889
+ /* @__PURE__ */ jsx9("p", { className: "semiont-protected-error-boundary-message", children: "An unexpected error occurred. Try again, or refresh the page." }),
26890
+ process.env.NODE_ENV === "development" && /* @__PURE__ */ jsxs4("details", { className: "semiont-protected-error-boundary-details", children: [
26891
+ /* @__PURE__ */ jsx9("summary", { className: "semiont-protected-error-boundary-summary", children: "Error details (development only)" }),
26892
+ /* @__PURE__ */ jsxs4("pre", { className: "semiont-protected-error-boundary-stack", children: [
26899
26893
  message,
26900
26894
  stack
26901
26895
  ] })
26902
26896
  ] }),
26903
- /* @__PURE__ */ jsxs4("div", { className: "flex gap-3", children: [
26897
+ /* @__PURE__ */ jsxs4("div", { className: "semiont-protected-error-boundary-actions", children: [
26904
26898
  /* @__PURE__ */ jsx9(
26905
26899
  "button",
26906
26900
  {
26907
26901
  onClick: resetErrorBoundary,
26908
- className: "flex-1 px-4 py-2 text-gray-700 dark:text-gray-200 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors",
26902
+ className: "semiont-button",
26903
+ "data-variant": "secondary",
26904
+ "data-size": "md",
26909
26905
  children: "Try Again"
26910
26906
  }
26911
26907
  ),
@@ -26913,7 +26909,9 @@ function ProtectedErrorFallback({ error, resetErrorBoundary }) {
26913
26909
  "button",
26914
26910
  {
26915
26911
  onClick: () => window.location.reload(),
26916
- className: "flex-1 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors",
26912
+ className: "semiont-button",
26913
+ "data-variant": "primary",
26914
+ "data-size": "md",
26917
26915
  children: "Refresh Page"
26918
26916
  }
26919
26917
  )
@@ -30354,7 +30352,7 @@ function SessionExpiredModal() {
30354
30352
 
30355
30353
  // src/components/resource/AnnotateView.tsx
30356
30354
  import { useRef as useRef13, useEffect as useEffect20, useCallback as useCallback13, lazy, Suspense } from "react";
30357
- import { getMimeCategory, isPdfMimeType as isPdfMimeType2 } from "@semiont/core";
30355
+ import { capabilitiesOf as capabilitiesOf3 } from "@semiont/core";
30358
30356
 
30359
30357
  // src/lib/text-segmentation.ts
30360
30358
  import { getTextPositionSelector as getTextPositionSelector2, getTextQuoteSelector, getTargetSelector as getTargetSelector2 } from "@semiont/core";
@@ -30482,7 +30480,7 @@ function AnnotateView({
30482
30480
  const { newAnnotationIds } = useResourceAnnotations();
30483
30481
  const containerRef = useRef13(null);
30484
30482
  const session = useObservable(useSemiont().activeSession$);
30485
- const category = getMimeCategory(mimeType);
30483
+ const render = capabilitiesOf3(mimeType)?.render ?? "none";
30486
30484
  const { highlights, references, assessments, comments, tags: tags3 } = annotations;
30487
30485
  const allAnnotations = [...highlights, ...references, ...assessments, ...comments, ...tags3];
30488
30486
  const segments = segmentTextWithAnnotations(content4, allAnnotations);
@@ -30561,7 +30559,7 @@ function AnnotateView({
30561
30559
  container.removeEventListener("mousedown", handleMouseDown);
30562
30560
  };
30563
30561
  }, [selectedMotivation, content4]);
30564
- switch (category) {
30562
+ switch (render) {
30565
30563
  case "text":
30566
30564
  return /* @__PURE__ */ jsxs15("div", { className: "semiont-annotate-view", "data-mime-type": "text", ref: containerRef, children: [
30567
30565
  /* @__PURE__ */ jsx22(
@@ -30593,35 +30591,34 @@ function AnnotateView({
30593
30591
  }
30594
30592
  ) })
30595
30593
  ] });
30594
+ case "pdf":
30595
+ return /* @__PURE__ */ jsxs15("div", { className: "semiont-annotate-view", "data-mime-type": "pdf", ref: containerRef, children: [
30596
+ /* @__PURE__ */ jsx22(
30597
+ AnnotateToolbar,
30598
+ {
30599
+ selectedMotivation,
30600
+ selectedClick,
30601
+ showShapeGroup: true,
30602
+ selectedShape,
30603
+ mediaType: mimeType,
30604
+ annotateMode,
30605
+ annotators: ANNOTATORS
30606
+ }
30607
+ ),
30608
+ /* @__PURE__ */ jsx22("div", { className: "semiont-annotate-view__content", children: content4 && /* @__PURE__ */ jsx22(Suspense, { fallback: /* @__PURE__ */ jsx22("div", { className: "semiont-annotate-view__loading", children: "Loading PDF viewer..." }), children: /* @__PURE__ */ jsx22(
30609
+ PdfAnnotationCanvas,
30610
+ {
30611
+ pdfUrl: content4,
30612
+ existingAnnotations: allAnnotations,
30613
+ drawingMode: selectedMotivation ? selectedShape : null,
30614
+ selectedMotivation,
30615
+ session,
30616
+ hoveredAnnotationId: hoveredAnnotationId || null,
30617
+ hoverDelayMs
30618
+ }
30619
+ ) }) })
30620
+ ] });
30596
30621
  case "image":
30597
- if (isPdfMimeType2(mimeType)) {
30598
- return /* @__PURE__ */ jsxs15("div", { className: "semiont-annotate-view", "data-mime-type": "pdf", ref: containerRef, children: [
30599
- /* @__PURE__ */ jsx22(
30600
- AnnotateToolbar,
30601
- {
30602
- selectedMotivation,
30603
- selectedClick,
30604
- showShapeGroup: true,
30605
- selectedShape,
30606
- mediaType: mimeType,
30607
- annotateMode,
30608
- annotators: ANNOTATORS
30609
- }
30610
- ),
30611
- /* @__PURE__ */ jsx22("div", { className: "semiont-annotate-view__content", children: content4 && /* @__PURE__ */ jsx22(Suspense, { fallback: /* @__PURE__ */ jsx22("div", { className: "semiont-annotate-view__loading", children: "Loading PDF viewer..." }), children: /* @__PURE__ */ jsx22(
30612
- PdfAnnotationCanvas,
30613
- {
30614
- pdfUrl: content4,
30615
- existingAnnotations: allAnnotations,
30616
- drawingMode: selectedMotivation ? selectedShape : null,
30617
- selectedMotivation,
30618
- session,
30619
- hoveredAnnotationId: hoveredAnnotationId || null,
30620
- hoverDelayMs
30621
- }
30622
- ) }) })
30623
- ] });
30624
- }
30625
30622
  return /* @__PURE__ */ jsxs15("div", { className: "semiont-annotate-view", "data-mime-type": "image", ref: containerRef, children: [
30626
30623
  /* @__PURE__ */ jsx22(
30627
30624
  AnnotateToolbar,
@@ -30648,7 +30645,7 @@ function AnnotateView({
30648
30645
  }
30649
30646
  ) })
30650
30647
  ] });
30651
- case "unsupported":
30648
+ case "none":
30652
30649
  default:
30653
30650
  return /* @__PURE__ */ jsx22("div", { ref: containerRef, className: "semiont-annotate-view semiont-annotate-view--unsupported", "data-mime-type": "unsupported", children: /* @__PURE__ */ jsxs15("div", { className: "semiont-annotate-view__empty", children: [
30654
30651
  /* @__PURE__ */ jsxs15("p", { className: "semiont-annotate-view__empty-message", children: [
@@ -45643,7 +45640,7 @@ function remarkGfm(options) {
45643
45640
 
45644
45641
  // src/components/resource/BrowseView.tsx
45645
45642
  import { annotationId as toAnnotationId3 } from "@semiont/core";
45646
- import { getMimeCategory as getMimeCategory2, isPdfMimeType as isPdfMimeType3 } from "@semiont/core";
45643
+ import { capabilitiesOf as capabilitiesOf4 } from "@semiont/core";
45647
45644
  import { createHoverHandlers as createHoverHandlers3 } from "@semiont/sdk";
45648
45645
 
45649
45646
  // src/components/viewers/ImageViewer.tsx
@@ -45686,7 +45683,7 @@ var BrowseView = memo(function BrowseView2({
45686
45683
  const { newAnnotationIds } = useResourceAnnotations();
45687
45684
  const session = useObservable(useSemiont().activeSession$);
45688
45685
  const containerRef = useRef16(null);
45689
- const category = getMimeCategory2(mimeType);
45686
+ const render = capabilitiesOf4(mimeType)?.render ?? "none";
45690
45687
  const { highlights, references, assessments, comments, tags: tags3 } = annotations;
45691
45688
  const allAnnotations = useMemo4(
45692
45689
  () => [...highlights, ...references, ...assessments, ...comments, ...tags3],
@@ -45774,7 +45771,7 @@ var BrowseView = memo(function BrowseView2({
45774
45771
  "beckon:hover": handleAnnotationHover,
45775
45772
  "beckon:focus": handleAnnotationFocus
45776
45773
  });
45777
- switch (category) {
45774
+ switch (render) {
45778
45775
  case "text":
45779
45776
  return /* @__PURE__ */ jsxs19("div", { className: "semiont-browse-view", "data-mime-type": "text", children: [
45780
45777
  /* @__PURE__ */ jsx27(
@@ -45790,31 +45787,30 @@ var BrowseView = memo(function BrowseView2({
45790
45787
  ),
45791
45788
  /* @__PURE__ */ jsx27("div", { ref: containerRef, className: "semiont-browse-view__content", children: /* @__PURE__ */ jsx27(MemoizedMarkdown, { content: content4 }) })
45792
45789
  ] });
45790
+ case "pdf":
45791
+ return /* @__PURE__ */ jsxs19("div", { className: "semiont-browse-view", "data-mime-type": "pdf", children: [
45792
+ /* @__PURE__ */ jsx27(
45793
+ AnnotateToolbar,
45794
+ {
45795
+ selectedMotivation: null,
45796
+ selectedClick,
45797
+ showSelectionGroup: false,
45798
+ showDeleteButton: false,
45799
+ annotateMode,
45800
+ annotators: ANNOTATORS
45801
+ }
45802
+ ),
45803
+ /* @__PURE__ */ jsx27("div", { ref: containerRef, className: "semiont-browse-view__content", children: /* @__PURE__ */ jsx27(Suspense2, { fallback: /* @__PURE__ */ jsx27("div", { className: "semiont-browse-view__loading", children: "Loading PDF viewer..." }), children: /* @__PURE__ */ jsx27(
45804
+ PdfAnnotationCanvas2,
45805
+ {
45806
+ pdfUrl: content4,
45807
+ existingAnnotations: allAnnotations,
45808
+ drawingMode: null,
45809
+ selectedMotivation: null
45810
+ }
45811
+ ) }) })
45812
+ ] });
45793
45813
  case "image":
45794
- if (isPdfMimeType3(mimeType)) {
45795
- return /* @__PURE__ */ jsxs19("div", { className: "semiont-browse-view", "data-mime-type": "pdf", children: [
45796
- /* @__PURE__ */ jsx27(
45797
- AnnotateToolbar,
45798
- {
45799
- selectedMotivation: null,
45800
- selectedClick,
45801
- showSelectionGroup: false,
45802
- showDeleteButton: false,
45803
- annotateMode,
45804
- annotators: ANNOTATORS
45805
- }
45806
- ),
45807
- /* @__PURE__ */ jsx27("div", { ref: containerRef, className: "semiont-browse-view__content", children: /* @__PURE__ */ jsx27(Suspense2, { fallback: /* @__PURE__ */ jsx27("div", { className: "semiont-browse-view__loading", children: "Loading PDF viewer..." }), children: /* @__PURE__ */ jsx27(
45808
- PdfAnnotationCanvas2,
45809
- {
45810
- pdfUrl: content4,
45811
- existingAnnotations: allAnnotations,
45812
- drawingMode: null,
45813
- selectedMotivation: null
45814
- }
45815
- ) }) })
45816
- ] });
45817
- }
45818
45814
  return /* @__PURE__ */ jsxs19("div", { className: "semiont-browse-view", "data-mime-type": "image", children: [
45819
45815
  /* @__PURE__ */ jsx27(
45820
45816
  AnnotateToolbar,
@@ -45836,7 +45832,7 @@ var BrowseView = memo(function BrowseView2({
45836
45832
  }
45837
45833
  ) })
45838
45834
  ] });
45839
- case "unsupported":
45835
+ case "none":
45840
45836
  return /* @__PURE__ */ jsx27("div", { ref: containerRef, className: "semiont-browse-view semiont-browse-view--unsupported", "data-mime-type": "unsupported", children: /* @__PURE__ */ jsxs19("div", { className: "semiont-browse-view__empty", children: [
45841
45837
  /* @__PURE__ */ jsxs19("p", { className: "semiont-browse-view__empty-message", children: [
45842
45838
  "Preview not available for ",
@@ -47240,16 +47236,50 @@ function HighlightPanel({
47240
47236
  }
47241
47237
 
47242
47238
  // src/components/resource/panels/JsonLdPanel.tsx
47243
- import { useEffect as useEffect31, useRef as useRef22 } from "react";
47239
+ import { useEffect as useEffect32, useRef as useRef22 } from "react";
47240
+
47241
+ // src/hooks/useResourceGraph.ts
47242
+ import { useEffect as useEffect31, useState as useState24 } from "react";
47243
+ function useResourceGraph(id2) {
47244
+ const semiont = useObservable(useSemiont().activeSession$)?.client;
47245
+ const [graph, setGraph] = useState24(null);
47246
+ const [loading, setLoading] = useState24(true);
47247
+ const [error, setError] = useState24(null);
47248
+ useEffect31(() => {
47249
+ if (!semiont || !id2) {
47250
+ setLoading(false);
47251
+ return;
47252
+ }
47253
+ let cancelled = false;
47254
+ setLoading(true);
47255
+ setError(null);
47256
+ semiont.browse.resourceGraph(id2).then((g2) => {
47257
+ if (cancelled) return;
47258
+ setGraph(g2);
47259
+ setLoading(false);
47260
+ }).catch((err) => {
47261
+ if (cancelled) return;
47262
+ setError(err instanceof Error ? err : new Error(String(err)));
47263
+ setLoading(false);
47264
+ });
47265
+ return () => {
47266
+ cancelled = true;
47267
+ };
47268
+ }, [semiont, id2]);
47269
+ return { graph, loading, error };
47270
+ }
47271
+
47272
+ // src/components/resource/panels/JsonLdPanel.tsx
47244
47273
  import { jsx as jsx37, jsxs as jsxs30 } from "react/jsx-runtime";
47245
- function JsonLdPanel({ resource: semiontResource }) {
47274
+ function JsonLdPanel({ resourceId: resourceId2 }) {
47246
47275
  const editorRef = useRef22(null);
47247
47276
  const viewRef = useRef22(null);
47248
47277
  const { showLineNumbers } = useLineNumbers();
47249
- useEffect31(() => {
47250
- if (!editorRef.current) return;
47278
+ const { graph, loading, error } = useResourceGraph(resourceId2);
47279
+ const documentText = graph ? JSON.stringify(graph, null, 2) : "";
47280
+ useEffect32(() => {
47281
+ if (!editorRef.current || !documentText) return;
47251
47282
  const isDarkMode = document.documentElement?.classList.contains("dark") ?? false;
47252
- const jsonLdContent = JSON.stringify(semiontResource, null, 2);
47253
47283
  const extensions = [
47254
47284
  json(),
47255
47285
  EditorView.editable.of(false),
@@ -47265,7 +47295,7 @@ function JsonLdPanel({ resource: semiontResource }) {
47265
47295
  extensions.push(syntaxHighlighting(jsonLightHighlightStyle));
47266
47296
  }
47267
47297
  const state = EditorState.create({
47268
- doc: jsonLdContent,
47298
+ doc: documentText,
47269
47299
  extensions
47270
47300
  });
47271
47301
  const view = new EditorView({
@@ -47277,10 +47307,11 @@ function JsonLdPanel({ resource: semiontResource }) {
47277
47307
  view.destroy();
47278
47308
  viewRef.current = null;
47279
47309
  };
47280
- }, [semiontResource, showLineNumbers]);
47310
+ }, [documentText, showLineNumbers]);
47281
47311
  const handleCopyToClipboard = async () => {
47312
+ if (!documentText) return;
47282
47313
  try {
47283
- await navigator.clipboard.writeText(JSON.stringify(semiontResource, null, 2));
47314
+ await navigator.clipboard.writeText(documentText);
47284
47315
  } catch (err) {
47285
47316
  console.error("Failed to copy JSON-LD:", err);
47286
47317
  }
@@ -47294,10 +47325,13 @@ function JsonLdPanel({ resource: semiontResource }) {
47294
47325
  onClick: handleCopyToClipboard,
47295
47326
  className: "semiont-button semiont-button--icon",
47296
47327
  title: "Copy to clipboard",
47328
+ disabled: !graph,
47297
47329
  children: "\u{1F4CB} Copy"
47298
47330
  }
47299
47331
  )
47300
47332
  ] }),
47333
+ loading && /* @__PURE__ */ jsx37("p", { className: "semiont-jsonld-panel__status", role: "status", children: "Loading JSON-LD\u2026" }),
47334
+ error && !loading && /* @__PURE__ */ jsx37("p", { className: "semiont-jsonld-panel__status semiont-jsonld-panel__status--error", role: "alert", children: "Failed to load JSON-LD." }),
47301
47335
  /* @__PURE__ */ jsx37(
47302
47336
  "div",
47303
47337
  {
@@ -47490,7 +47524,7 @@ function ReferenceEntry({
47490
47524
  }
47491
47525
 
47492
47526
  // src/components/resource/panels/ReferencesPanel.tsx
47493
- import { useState as useState24, useRef as useRef23, useEffect as useEffect32, useCallback as useCallback21, useMemo as useMemo9 } from "react";
47527
+ import { useState as useState25, useRef as useRef23, useEffect as useEffect33, useCallback as useCallback21, useMemo as useMemo9 } from "react";
47494
47528
  import { getTextPositionSelector as getTextPositionSelector6, getTargetSelector as getTargetSelector9 } from "@semiont/core";
47495
47529
  import { Fragment as Fragment6, jsx as jsx39, jsxs as jsxs32 } from "react/jsx-runtime";
47496
47530
  function getSelectorDisplayText3(selector) {
@@ -47526,18 +47560,18 @@ function ReferencesPanel({
47526
47560
  }) {
47527
47561
  const t12 = useTranslations("ReferencesPanel");
47528
47562
  const session = useObservable(useSemiont().activeSession$);
47529
- const [selectedEntityTypes, setSelectedEntityTypes] = useState24([]);
47530
- const [lastAnnotationLog, setLastDetectionLog] = useState24(null);
47531
- const [pendingEntityTypes, setPendingEntityTypes] = useState24([]);
47532
- const [includeDescriptiveReferences, setIncludeDescriptiveReferences] = useState24(false);
47533
- const [focusedAnnotationId, setFocusedAnnotationId] = useState24(null);
47563
+ const [selectedEntityTypes, setSelectedEntityTypes] = useState25([]);
47564
+ const [lastAnnotationLog, setLastDetectionLog] = useState25(null);
47565
+ const [pendingEntityTypes, setPendingEntityTypes] = useState25([]);
47566
+ const [includeDescriptiveReferences, setIncludeDescriptiveReferences] = useState25(false);
47567
+ const [focusedAnnotationId, setFocusedAnnotationId] = useState25(null);
47534
47568
  const containerRef = useRef23(null);
47535
- const [isAssistExpanded, setIsDetectExpanded] = useState24(() => {
47569
+ const [isAssistExpanded, setIsDetectExpanded] = useState25(() => {
47536
47570
  if (typeof window === "undefined") return true;
47537
47571
  const stored = localStorage.getItem("assist-section-expanded-reference");
47538
47572
  return stored ? stored === "true" : true;
47539
47573
  });
47540
- useEffect32(() => {
47574
+ useEffect33(() => {
47541
47575
  if (typeof window === "undefined") return;
47542
47576
  localStorage.setItem("assist-section-expanded-reference", String(isAssistExpanded));
47543
47577
  }, [isAssistExpanded]);
@@ -47557,7 +47591,7 @@ function ReferencesPanel({
47557
47591
  entryRefs.current.delete(id2);
47558
47592
  }
47559
47593
  }, []);
47560
- useEffect32(() => {
47594
+ useEffect33(() => {
47561
47595
  if (!scrollToAnnotationId) return;
47562
47596
  const element2 = entryRefs.current.get(scrollToAnnotationId);
47563
47597
  if (element2 && containerRef.current) {
@@ -47576,7 +47610,7 @@ function ReferencesPanel({
47576
47610
  console.warn("[ReferencesPanel] Element not found for scrollToAnnotationId:", scrollToAnnotationId);
47577
47611
  }
47578
47612
  }, [scrollToAnnotationId]);
47579
- useEffect32(() => {
47613
+ useEffect33(() => {
47580
47614
  if (!hoveredAnnotationId) return;
47581
47615
  const element2 = entryRefs.current.get(hoveredAnnotationId);
47582
47616
  if (!element2 || !containerRef.current) return;
@@ -47611,7 +47645,7 @@ function ReferencesPanel({
47611
47645
  });
47612
47646
  };
47613
47647
  const hasSavedLogRef = useRef23(false);
47614
- useEffect32(() => {
47648
+ useEffect33(() => {
47615
47649
  if (isAssisting) {
47616
47650
  hasSavedLogRef.current = false;
47617
47651
  return;
@@ -47638,7 +47672,7 @@ function ReferencesPanel({
47638
47672
  setPendingEntityTypes([]);
47639
47673
  }
47640
47674
  };
47641
- useEffect32(() => {
47675
+ useEffect33(() => {
47642
47676
  if (!pendingAnnotation) return;
47643
47677
  const handleEscape = (e6) => {
47644
47678
  if (e6.key === "Escape") {
@@ -48104,7 +48138,7 @@ function TagEntry({
48104
48138
  }
48105
48139
 
48106
48140
  // src/components/resource/panels/TaggingPanel.tsx
48107
- import { useState as useState25, useEffect as useEffect33, useRef as useRef24, useCallback as useCallback22, useMemo as useMemo11 } from "react";
48141
+ import { useState as useState26, useEffect as useEffect34, useRef as useRef24, useCallback as useCallback22, useMemo as useMemo11 } from "react";
48108
48142
  import { getTextPositionSelector as getTextPositionSelector7, getTargetSelector as getTargetSelector10 } from "@semiont/core";
48109
48143
  import { Fragment as Fragment8, jsx as jsx43, jsxs as jsxs36 } from "react/jsx-runtime";
48110
48144
  function getSelectorDisplayText4(selector) {
@@ -48141,21 +48175,21 @@ function TaggingPanel({
48141
48175
  const schemasObserved = useObservable(tagSchemas$);
48142
48176
  const schemas = schemasObserved ?? [];
48143
48177
  const noSchemasRegistered = schemasObserved !== void 0 && schemasObserved.length === 0;
48144
- const [selectedSchemaId, setSelectedSchemaId] = useState25("");
48145
- const [selectedCategories, setSelectedCategories] = useState25(/* @__PURE__ */ new Set());
48146
- useEffect33(() => {
48178
+ const [selectedSchemaId, setSelectedSchemaId] = useState26("");
48179
+ const [selectedCategories, setSelectedCategories] = useState26(/* @__PURE__ */ new Set());
48180
+ useEffect34(() => {
48147
48181
  if (!selectedSchemaId && schemas.length > 0) {
48148
48182
  setSelectedSchemaId(schemas[0].id);
48149
48183
  }
48150
48184
  }, [schemas, selectedSchemaId]);
48151
- const [focusedAnnotationId, setFocusedAnnotationId] = useState25(null);
48185
+ const [focusedAnnotationId, setFocusedAnnotationId] = useState26(null);
48152
48186
  const containerRef = useRef24(null);
48153
- const [isAssistExpanded, setIsDetectExpanded] = useState25(() => {
48187
+ const [isAssistExpanded, setIsDetectExpanded] = useState26(() => {
48154
48188
  if (typeof window === "undefined") return true;
48155
48189
  const stored = localStorage.getItem("assist-section-expanded-tag");
48156
48190
  return stored ? stored === "true" : true;
48157
48191
  });
48158
- useEffect33(() => {
48192
+ useEffect34(() => {
48159
48193
  if (typeof window === "undefined") return;
48160
48194
  localStorage.setItem("assist-section-expanded-tag", String(isAssistExpanded));
48161
48195
  }, [isAssistExpanded]);
@@ -48182,7 +48216,7 @@ function TaggingPanel({
48182
48216
  entryRefs.current.delete(id2);
48183
48217
  }
48184
48218
  }, []);
48185
- useEffect33(() => {
48219
+ useEffect34(() => {
48186
48220
  if (!scrollToAnnotationId) return;
48187
48221
  const element2 = entryRefs.current.get(scrollToAnnotationId);
48188
48222
  if (element2 && containerRef.current) {
@@ -48197,7 +48231,7 @@ function TaggingPanel({
48197
48231
  if (onScrollCompleted) onScrollCompleted();
48198
48232
  }
48199
48233
  }, [scrollToAnnotationId]);
48200
- useEffect33(() => {
48234
+ useEffect34(() => {
48201
48235
  if (!hoveredAnnotationId) return;
48202
48236
  const element2 = entryRefs.current.get(hoveredAnnotationId);
48203
48237
  if (!element2 || !containerRef.current) return;
@@ -48248,7 +48282,7 @@ function TaggingPanel({
48248
48282
  setSelectedCategories(/* @__PURE__ */ new Set());
48249
48283
  }
48250
48284
  };
48251
- useEffect33(() => {
48285
+ useEffect34(() => {
48252
48286
  if (!pendingAnnotation) return;
48253
48287
  const handleEscape = (e6) => {
48254
48288
  if (e6.key === "Escape") {
@@ -48477,7 +48511,7 @@ function TaggingPanel({
48477
48511
  }
48478
48512
 
48479
48513
  // src/components/resource/panels/UnifiedAnnotationsPanel.tsx
48480
- import { useState as useState26, useEffect as useEffect34 } from "react";
48514
+ import { useState as useState27, useEffect as useEffect35 } from "react";
48481
48515
  import { jsx as jsx44, jsxs as jsxs37 } from "react/jsx-runtime";
48482
48516
  var TAB_ORDER = ["statistics", "reference", "highlight", "assessment", "comment", "tag"];
48483
48517
  function UnifiedAnnotationsPanel(props) {
@@ -48499,7 +48533,7 @@ function UnifiedAnnotationsPanel(props) {
48499
48533
  }
48500
48534
  }
48501
48535
  const grouped = groups;
48502
- const [activeTab, setActiveTab] = useState26(() => {
48536
+ const [activeTab, setActiveTab] = useState27(() => {
48503
48537
  if (typeof window === "undefined") return props.initialTab || "statistics";
48504
48538
  const storageKey = props.resourceId ? `annotations-tab-${props.resourceId}` : "annotations-tab-global";
48505
48539
  const stored = localStorage.getItem(storageKey);
@@ -48508,17 +48542,17 @@ function UnifiedAnnotationsPanel(props) {
48508
48542
  }
48509
48543
  return props.initialTab || "statistics";
48510
48544
  });
48511
- useEffect34(() => {
48545
+ useEffect35(() => {
48512
48546
  if (typeof window === "undefined") return;
48513
48547
  const storageKey = props.resourceId ? `annotations-tab-${props.resourceId}` : "annotations-tab-global";
48514
48548
  localStorage.setItem(storageKey, activeTab);
48515
48549
  }, [activeTab, props.resourceId]);
48516
- useEffect34(() => {
48550
+ useEffect35(() => {
48517
48551
  if (props.initialTab && props.initialTabGeneration !== void 0) {
48518
48552
  setActiveTab(props.initialTab);
48519
48553
  }
48520
48554
  }, [props.initialTabGeneration]);
48521
- useEffect34(() => {
48555
+ useEffect35(() => {
48522
48556
  if (props.pendingAnnotation) {
48523
48557
  const motivationToTab = {
48524
48558
  "linking": "reference",
@@ -48661,7 +48695,7 @@ function UnifiedAnnotationsPanel(props) {
48661
48695
  }
48662
48696
 
48663
48697
  // src/components/navigation/Footer.tsx
48664
- import { useState as useState27 } from "react";
48698
+ import { useState as useState28 } from "react";
48665
48699
  import { Fragment as Fragment9, jsx as jsx45, jsxs as jsxs38 } from "react/jsx-runtime";
48666
48700
  function Footer({
48667
48701
  Link,
@@ -48672,7 +48706,7 @@ function Footer({
48672
48706
  sourceCodeUrl = "https://github.com/The-AI-Alliance/semiont",
48673
48707
  showPolicyLinks = true
48674
48708
  }) {
48675
- const [showCookiePreferences, setShowCookiePreferences] = useState27(false);
48709
+ const [showCookiePreferences, setShowCookiePreferences] = useState28(false);
48676
48710
  return /* @__PURE__ */ jsxs38(Fragment9, { children: [
48677
48711
  /* @__PURE__ */ jsx45("footer", { role: "contentinfo", className: "semiont-footer", children: /* @__PURE__ */ jsx45("div", { className: "semiont-footer__container", children: /* @__PURE__ */ jsxs38("div", { className: "semiont-footer__content", children: [
48678
48712
  /* @__PURE__ */ jsx45("div", { className: "semiont-footer__copyright", children: t12("copyright", { year: (/* @__PURE__ */ new Date()).getFullYear() }) }),
@@ -48802,7 +48836,7 @@ function NavigationMenu({
48802
48836
  }
48803
48837
 
48804
48838
  // src/components/navigation/ObservableLink.tsx
48805
- import { useCallback as useCallback23, useRef as useRef25, useEffect as useEffect35 } from "react";
48839
+ import { useCallback as useCallback23, useRef as useRef25, useEffect as useEffect36 } from "react";
48806
48840
  import { jsx as jsx47 } from "react/jsx-runtime";
48807
48841
  function ObservableLink({
48808
48842
  href,
@@ -48813,7 +48847,7 @@ function ObservableLink({
48813
48847
  }) {
48814
48848
  const semiont = useSemiont();
48815
48849
  const onClickRef = useRef25(onClick);
48816
- useEffect35(() => {
48850
+ useEffect36(() => {
48817
48851
  onClickRef.current = onClick;
48818
48852
  });
48819
48853
  const handleClick = useCallback23((e6) => {
@@ -48835,7 +48869,7 @@ function ObservableLink({
48835
48869
  }
48836
48870
 
48837
48871
  // src/components/navigation/SimpleNavigation.tsx
48838
- import { useState as useState28, useRef as useRef26, useEffect as useEffect36 } from "react";
48872
+ import { useState as useState29, useRef as useRef26, useEffect as useEffect37 } from "react";
48839
48873
  import { jsx as jsx48, jsxs as jsxs40 } from "react/jsx-runtime";
48840
48874
  function SimpleNavigation({
48841
48875
  title,
@@ -48850,12 +48884,12 @@ function SimpleNavigation({
48850
48884
  }) {
48851
48885
  const ChevronLeftIcon = icons.chevronLeft;
48852
48886
  const BarsIcon = icons.bars;
48853
- const [isDropdownOpen, setIsDropdownOpen] = useState28(false);
48887
+ const [isDropdownOpen, setIsDropdownOpen] = useState29(false);
48854
48888
  const dropdownRef = useRef26(null);
48855
48889
  const semiont = useSemiont();
48856
48890
  const toggleDropdown = () => setIsDropdownOpen(!isDropdownOpen);
48857
48891
  const closeDropdown = () => setIsDropdownOpen(false);
48858
- useEffect36(() => {
48892
+ useEffect37(() => {
48859
48893
  const handleClickOutside = (event) => {
48860
48894
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
48861
48895
  closeDropdown();
@@ -48931,14 +48965,14 @@ function SimpleNavigation({
48931
48965
  }
48932
48966
 
48933
48967
  // src/components/navigation/CollapsibleResourceNavigation.tsx
48934
- import { useCallback as useCallback29, useState as useState32, useRef as useRef31, useEffect as useEffect41 } from "react";
48968
+ import { useCallback as useCallback29, useState as useState33, useRef as useRef31, useEffect as useEffect42 } from "react";
48935
48969
 
48936
48970
  // ../../node_modules/@dnd-kit/core/dist/core.esm.js
48937
- import React18, { createContext as createContext5, useContext as useContext5, useEffect as useEffect38, useState as useState30, useCallback as useCallback26, useMemo as useMemo13, useRef as useRef28, memo as memo2, useReducer, cloneElement, forwardRef } from "react";
48971
+ import React18, { createContext as createContext5, useContext as useContext5, useEffect as useEffect39, useState as useState31, useCallback as useCallback26, useMemo as useMemo13, useRef as useRef28, memo as memo2, useReducer, cloneElement, forwardRef } from "react";
48938
48972
  import { createPortal, unstable_batchedUpdates } from "react-dom";
48939
48973
 
48940
48974
  // ../../node_modules/@dnd-kit/utilities/dist/utilities.esm.js
48941
- import { useMemo as useMemo12, useLayoutEffect, useEffect as useEffect37, useRef as useRef27, useCallback as useCallback24 } from "react";
48975
+ import { useMemo as useMemo12, useLayoutEffect, useEffect as useEffect38, useRef as useRef27, useCallback as useCallback24 } from "react";
48942
48976
  function useCombinedRefs() {
48943
48977
  for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {
48944
48978
  refs[_key] = arguments[_key];
@@ -49006,7 +49040,7 @@ function getOwnerDocument(target) {
49006
49040
  }
49007
49041
  return document;
49008
49042
  }
49009
- var useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect37;
49043
+ var useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect38;
49010
49044
  function useEvent(handler) {
49011
49045
  const handlerRef = useRef27(handler);
49012
49046
  useIsomorphicLayoutEffect(() => {
@@ -49073,7 +49107,7 @@ function useNodeRef(onChange) {
49073
49107
  }
49074
49108
  function usePrevious(value) {
49075
49109
  const ref = useRef27();
49076
- useEffect37(() => {
49110
+ useEffect38(() => {
49077
49111
  ref.current = value;
49078
49112
  }, [value]);
49079
49113
  return ref.current;
@@ -49214,7 +49248,7 @@ function findFirstFocusableNode(element2) {
49214
49248
  }
49215
49249
 
49216
49250
  // ../../node_modules/@dnd-kit/accessibility/dist/accessibility.esm.js
49217
- import React17, { useState as useState29, useCallback as useCallback25 } from "react";
49251
+ import React17, { useState as useState30, useCallback as useCallback25 } from "react";
49218
49252
  var hiddenStyles = {
49219
49253
  display: "none"
49220
49254
  };
@@ -49257,7 +49291,7 @@ function LiveRegion(_ref) {
49257
49291
  }, announcement);
49258
49292
  }
49259
49293
  function useAnnouncement() {
49260
- const [announcement, setAnnouncement] = useState29("");
49294
+ const [announcement, setAnnouncement] = useState30("");
49261
49295
  const announce = useCallback25((value) => {
49262
49296
  if (value != null) {
49263
49297
  setAnnouncement(value);
@@ -49273,7 +49307,7 @@ function useAnnouncement() {
49273
49307
  var DndMonitorContext = /* @__PURE__ */ createContext5(null);
49274
49308
  function useDndMonitor(listener) {
49275
49309
  const registerListener = useContext5(DndMonitorContext);
49276
- useEffect38(() => {
49310
+ useEffect39(() => {
49277
49311
  if (!registerListener) {
49278
49312
  throw new Error("useDndMonitor must be used within a children of <DndContext>");
49279
49313
  }
@@ -49282,7 +49316,7 @@ function useDndMonitor(listener) {
49282
49316
  }, [listener, registerListener]);
49283
49317
  }
49284
49318
  function useDndMonitorProvider() {
49285
- const [listeners] = useState30(() => /* @__PURE__ */ new Set());
49319
+ const [listeners] = useState31(() => /* @__PURE__ */ new Set());
49286
49320
  const registerListener = useCallback26((listener) => {
49287
49321
  listeners.add(listener);
49288
49322
  return () => listeners.delete(listener);
@@ -49348,8 +49382,8 @@ function Accessibility(_ref) {
49348
49382
  announcement
49349
49383
  } = useAnnouncement();
49350
49384
  const liveRegionId = useUniqueId("DndLiveRegion");
49351
- const [mounted, setMounted] = useState30(false);
49352
- useEffect38(() => {
49385
+ const [mounted, setMounted] = useState31(false);
49386
+ useEffect39(() => {
49353
49387
  setMounted(true);
49354
49388
  }, []);
49355
49389
  useDndMonitor(useMemo13(() => ({
@@ -50717,7 +50751,7 @@ function useAutoScroller(_ref) {
50717
50751
  scrollContainer.scrollBy(scrollLeft, scrollTop);
50718
50752
  }, []);
50719
50753
  const sortedScrollableAncestors = useMemo13(() => order2 === TraversalOrder.TreeOrder ? [...scrollableAncestors].reverse() : scrollableAncestors, [order2, scrollableAncestors]);
50720
- useEffect38(
50754
+ useEffect39(
50721
50755
  () => {
50722
50756
  if (!enabled || !scrollableAncestors.length || !rect) {
50723
50757
  clearAutoScrollInterval();
@@ -50858,7 +50892,7 @@ function useDroppableMeasuring(containers, _ref) {
50858
50892
  dependencies,
50859
50893
  config
50860
50894
  } = _ref;
50861
- const [queue, setQueue] = useState30(null);
50895
+ const [queue, setQueue] = useState31(null);
50862
50896
  const {
50863
50897
  frequency,
50864
50898
  measure,
@@ -50907,10 +50941,10 @@ function useDroppableMeasuring(containers, _ref) {
50907
50941
  }
50908
50942
  return previousValue;
50909
50943
  }, [containers, queue, dragging, disabled, measure]);
50910
- useEffect38(() => {
50944
+ useEffect39(() => {
50911
50945
  containersRef.current = containers;
50912
50946
  }, [containers]);
50913
- useEffect38(
50947
+ useEffect39(
50914
50948
  () => {
50915
50949
  if (disabled) {
50916
50950
  return;
@@ -50920,7 +50954,7 @@ function useDroppableMeasuring(containers, _ref) {
50920
50954
  // eslint-disable-next-line react-hooks/exhaustive-deps
50921
50955
  [dragging, disabled]
50922
50956
  );
50923
- useEffect38(
50957
+ useEffect39(
50924
50958
  () => {
50925
50959
  if (queue && queue.length > 0) {
50926
50960
  setQueue(null);
@@ -50929,7 +50963,7 @@ function useDroppableMeasuring(containers, _ref) {
50929
50963
  //eslint-disable-next-line react-hooks/exhaustive-deps
50930
50964
  [JSON.stringify(queue)]
50931
50965
  );
50932
- useEffect38(
50966
+ useEffect39(
50933
50967
  () => {
50934
50968
  if (disabled || typeof frequency !== "number" || timeoutId.current !== null) {
50935
50969
  return;
@@ -50987,7 +51021,7 @@ function useMutationObserver(_ref) {
50987
51021
  } = window;
50988
51022
  return new MutationObserver2(handleMutations);
50989
51023
  }, [handleMutations, disabled]);
50990
- useEffect38(() => {
51024
+ useEffect39(() => {
50991
51025
  return () => mutationObserver == null ? void 0 : mutationObserver.disconnect();
50992
51026
  }, [mutationObserver]);
50993
51027
  return mutationObserver;
@@ -51011,7 +51045,7 @@ function useResizeObserver(_ref) {
51011
51045
  // eslint-disable-next-line react-hooks/exhaustive-deps
51012
51046
  [disabled]
51013
51047
  );
51014
- useEffect38(() => {
51048
+ useEffect39(() => {
51015
51049
  return () => resizeObserver == null ? void 0 : resizeObserver.disconnect();
51016
51050
  }, [resizeObserver]);
51017
51051
  return resizeObserver;
@@ -51023,7 +51057,7 @@ function useRect(element2, measure, fallbackRect2) {
51023
51057
  if (measure === void 0) {
51024
51058
  measure = defaultMeasure;
51025
51059
  }
51026
- const [rect, setRect] = useState30(null);
51060
+ const [rect, setRect] = useState31(null);
51027
51061
  function measureRect() {
51028
51062
  setRect((currentRect) => {
51029
51063
  if (!element2) {
@@ -51091,13 +51125,13 @@ function useScrollableAncestors(node2) {
51091
51125
  }
51092
51126
  return getScrollableAncestors(node2);
51093
51127
  }, [node2]);
51094
- useEffect38(() => {
51128
+ useEffect39(() => {
51095
51129
  previousNode.current = node2;
51096
51130
  }, [node2]);
51097
51131
  return ancestors;
51098
51132
  }
51099
51133
  function useScrollOffsets(elements) {
51100
- const [scrollCoordinates, setScrollCoordinates] = useState30(null);
51134
+ const [scrollCoordinates, setScrollCoordinates] = useState31(null);
51101
51135
  const prevElements = useRef28(elements);
51102
51136
  const handleScroll = useCallback26((event) => {
51103
51137
  const scrollingElement = getScrollableElement(event.target);
@@ -51112,7 +51146,7 @@ function useScrollOffsets(elements) {
51112
51146
  return new Map(scrollCoordinates2);
51113
51147
  });
51114
51148
  }, []);
51115
- useEffect38(() => {
51149
+ useEffect39(() => {
51116
51150
  const previousElements = prevElements.current;
51117
51151
  if (elements !== previousElements) {
51118
51152
  cleanup(previousElements);
@@ -51152,14 +51186,14 @@ function useScrollOffsetsDelta(scrollOffsets, dependencies) {
51152
51186
  dependencies = [];
51153
51187
  }
51154
51188
  const initialScrollOffsets = useRef28(null);
51155
- useEffect38(
51189
+ useEffect39(
51156
51190
  () => {
51157
51191
  initialScrollOffsets.current = null;
51158
51192
  },
51159
51193
  // eslint-disable-next-line react-hooks/exhaustive-deps
51160
51194
  dependencies
51161
51195
  );
51162
- useEffect38(() => {
51196
+ useEffect39(() => {
51163
51197
  const hasScrollOffsets = scrollOffsets !== defaultCoordinates;
51164
51198
  if (hasScrollOffsets && !initialScrollOffsets.current) {
51165
51199
  initialScrollOffsets.current = scrollOffsets;
@@ -51171,7 +51205,7 @@ function useScrollOffsetsDelta(scrollOffsets, dependencies) {
51171
51205
  return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;
51172
51206
  }
51173
51207
  function useSensorSetup(sensors) {
51174
- useEffect38(
51208
+ useEffect39(
51175
51209
  () => {
51176
51210
  if (!canUseDOM) {
51177
51211
  return;
@@ -51222,7 +51256,7 @@ function useRects(elements, measure) {
51222
51256
  }
51223
51257
  const [firstElement] = elements;
51224
51258
  const windowRect2 = useWindowRect(firstElement ? getWindow(firstElement) : null);
51225
- const [rects, setRects] = useState30(defaultValue$2);
51259
+ const [rects, setRects] = useState31(defaultValue$2);
51226
51260
  function measureRects() {
51227
51261
  setRects(() => {
51228
51262
  if (!elements.length) {
@@ -51255,7 +51289,7 @@ function useDragOverlayMeasuring(_ref) {
51255
51289
  let {
51256
51290
  measure
51257
51291
  } = _ref;
51258
- const [rect, setRect] = useState30(null);
51292
+ const [rect, setRect] = useState31(null);
51259
51293
  const handleResize = useCallback26((entries) => {
51260
51294
  for (const {
51261
51295
  target
@@ -51511,7 +51545,7 @@ function RestoreFocus(_ref) {
51511
51545
  } = useContext5(InternalContext);
51512
51546
  const previousActivatorEvent = usePrevious(activatorEvent);
51513
51547
  const previousActiveId = usePrevious(active == null ? void 0 : active.id);
51514
- useEffect38(() => {
51548
+ useEffect39(() => {
51515
51549
  if (disabled) {
51516
51550
  return;
51517
51551
  }
@@ -51656,7 +51690,7 @@ var DndContext = /* @__PURE__ */ memo2(function DndContext2(_ref) {
51656
51690
  const store = useReducer(reducer, void 0, getInitialState);
51657
51691
  const [state, dispatch] = store;
51658
51692
  const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();
51659
- const [status, setStatus] = useState30(Status.Uninitialized);
51693
+ const [status, setStatus] = useState31(Status.Uninitialized);
51660
51694
  const isInitialized = status === Status.Initialized;
51661
51695
  const {
51662
51696
  draggable: {
@@ -51683,8 +51717,8 @@ var DndContext = /* @__PURE__ */ memo2(function DndContext2(_ref) {
51683
51717
  } : null;
51684
51718
  }, [activeId, node2]);
51685
51719
  const activeRef = useRef28(null);
51686
- const [activeSensor, setActiveSensor] = useState30(null);
51687
- const [activatorEvent, setActivatorEvent] = useState30(null);
51720
+ const [activeSensor, setActiveSensor] = useState31(null);
51721
+ const [activatorEvent, setActivatorEvent] = useState31(null);
51688
51722
  const latestProps = useLatestValue(props, Object.values(props));
51689
51723
  const draggableDescribedById = useUniqueId("DndDescribedBy", id2);
51690
51724
  const enabledDroppableContainers = useMemo13(() => droppableContainers.getEnabled(), [droppableContainers]);
@@ -51768,7 +51802,7 @@ var DndContext = /* @__PURE__ */ memo2(function DndContext2(_ref) {
51768
51802
  pointerCoordinates
51769
51803
  }) : null;
51770
51804
  const overId = getFirstCollision(collisions, "id");
51771
- const [over, setOver] = useState30(null);
51805
+ const [over, setOver] = useState31(null);
51772
51806
  const appliedTranslate = usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta);
51773
51807
  const transform = adjustScale(appliedTranslate, (_over$rect = over == null ? void 0 : over.rect) != null ? _over$rect : null, activeNodeRect);
51774
51808
  const activeSensorRef = useRef28(null);
@@ -51962,7 +51996,7 @@ var DndContext = /* @__PURE__ */ memo2(function DndContext2(_ref) {
51962
51996
  setStatus(Status.Initialized);
51963
51997
  }
51964
51998
  }, [activeNodeRect, status]);
51965
- useEffect38(
51999
+ useEffect39(
51966
52000
  () => {
51967
52001
  const {
51968
52002
  onDragMove
@@ -51997,7 +52031,7 @@ var DndContext = /* @__PURE__ */ memo2(function DndContext2(_ref) {
51997
52031
  // eslint-disable-next-line react-hooks/exhaustive-deps
51998
52032
  [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]
51999
52033
  );
52000
- useEffect38(
52034
+ useEffect39(
52001
52035
  () => {
52002
52036
  const {
52003
52037
  active: active2,
@@ -52280,7 +52314,7 @@ function useDroppable(_ref) {
52280
52314
  }, [resizeObserver]);
52281
52315
  const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);
52282
52316
  const dataRef = useLatestValue(data2);
52283
- useEffect38(() => {
52317
+ useEffect39(() => {
52284
52318
  if (!resizeObserver || !nodeRef.current) {
52285
52319
  return;
52286
52320
  }
@@ -52288,7 +52322,7 @@ function useDroppable(_ref) {
52288
52322
  resizeObserverConnected.current = false;
52289
52323
  resizeObserver.observe(nodeRef.current);
52290
52324
  }, [nodeRef, resizeObserver]);
52291
- useEffect38(
52325
+ useEffect39(
52292
52326
  () => {
52293
52327
  dispatch({
52294
52328
  type: Action.RegisterDroppable,
@@ -52310,7 +52344,7 @@ function useDroppable(_ref) {
52310
52344
  // eslint-disable-next-line react-hooks/exhaustive-deps
52311
52345
  [id2]
52312
52346
  );
52313
- useEffect38(() => {
52347
+ useEffect39(() => {
52314
52348
  if (disabled !== previous3.current.disabled) {
52315
52349
  dispatch({
52316
52350
  type: Action.SetDroppableDisabled,
@@ -52332,7 +52366,7 @@ function useDroppable(_ref) {
52332
52366
  }
52333
52367
 
52334
52368
  // ../../node_modules/@dnd-kit/sortable/dist/sortable.esm.js
52335
- import React19, { useMemo as useMemo14, useRef as useRef29, useEffect as useEffect39, useState as useState31, useContext as useContext6 } from "react";
52369
+ import React19, { useMemo as useMemo14, useRef as useRef29, useEffect as useEffect40, useState as useState32, useContext as useContext6 } from "react";
52336
52370
  function arrayMove(array, from, to) {
52337
52371
  const newArray = array.slice();
52338
52372
  newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);
@@ -52499,7 +52533,7 @@ function SortableContext(_ref) {
52499
52533
  measureDroppableContainers(items);
52500
52534
  }
52501
52535
  }, [itemsHaveChanged, items, isDragging, measureDroppableContainers]);
52502
- useEffect39(() => {
52536
+ useEffect40(() => {
52503
52537
  previousItemsRef.current = items;
52504
52538
  }, [items]);
52505
52539
  const contextValue = useMemo14(
@@ -52573,7 +52607,7 @@ function useDerivedTransform(_ref) {
52573
52607
  node: node2,
52574
52608
  rect
52575
52609
  } = _ref;
52576
- const [derivedTransform, setDerivedtransform] = useState31(null);
52610
+ const [derivedTransform, setDerivedtransform] = useState32(null);
52577
52611
  const previousIndex = useRef29(index2);
52578
52612
  useIsomorphicLayoutEffect(() => {
52579
52613
  if (!disabled && index2 !== previousIndex.current && node2.current) {
@@ -52597,7 +52631,7 @@ function useDerivedTransform(_ref) {
52597
52631
  previousIndex.current = index2;
52598
52632
  }
52599
52633
  }, [disabled, index2, node2, rect]);
52600
- useEffect39(() => {
52634
+ useEffect40(() => {
52601
52635
  if (derivedTransform) {
52602
52636
  setDerivedtransform(null);
52603
52637
  }
@@ -52719,7 +52753,7 @@ function useSortable(_ref) {
52719
52753
  node: node2,
52720
52754
  rect
52721
52755
  });
52722
- useEffect39(() => {
52756
+ useEffect40(() => {
52723
52757
  if (isSorting && previous3.current.newIndex !== newIndex) {
52724
52758
  previous3.current.newIndex = newIndex;
52725
52759
  }
@@ -52730,7 +52764,7 @@ function useSortable(_ref) {
52730
52764
  previous3.current.items = items;
52731
52765
  }
52732
52766
  }, [isSorting, newIndex, containerId, items]);
52733
- useEffect39(() => {
52767
+ useEffect40(() => {
52734
52768
  if (activeId === previous3.current.activeId) {
52735
52769
  return;
52736
52770
  }
@@ -52915,7 +52949,7 @@ function isAfter(a15, b8) {
52915
52949
  }
52916
52950
 
52917
52951
  // src/components/navigation/SortableResourceTab.tsx
52918
- import { useCallback as useCallback27, useRef as useRef30, useEffect as useEffect40 } from "react";
52952
+ import { useCallback as useCallback27, useRef as useRef30, useEffect as useEffect41 } from "react";
52919
52953
  import { jsx as jsx49, jsxs as jsxs41 } from "react/jsx-runtime";
52920
52954
  function SortableResourceTab({
52921
52955
  resource,
@@ -52939,7 +52973,7 @@ function SortableResourceTab({
52939
52973
  isDragging: isSortableDragging
52940
52974
  } = useSortable({ id: resource.id });
52941
52975
  const onReorderRef = useRef30(onReorder);
52942
- useEffect40(() => {
52976
+ useEffect41(() => {
52943
52977
  onReorderRef.current = onReorder;
52944
52978
  });
52945
52979
  const style = {
@@ -53066,7 +53100,7 @@ function CollapsibleResourceNavigation({
53066
53100
  }) {
53067
53101
  const ChevronLeftIcon = icons.chevronLeft;
53068
53102
  const BarsIcon = icons.bars;
53069
- const [isDropdownOpen, setIsDropdownOpen] = useState32(false);
53103
+ const [isDropdownOpen, setIsDropdownOpen] = useState33(false);
53070
53104
  const dropdownRef = useRef31(null);
53071
53105
  const { announcePickup, announceDrop, announceKeyboardReorder, announceCannotMove } = useDragAnnouncements();
53072
53106
  const t12 = useTranslations("CollapsibleResourceNavigation");
@@ -53082,7 +53116,7 @@ function CollapsibleResourceNavigation({
53082
53116
  };
53083
53117
  const toggleDropdown = () => setIsDropdownOpen(!isDropdownOpen);
53084
53118
  const closeDropdown = () => setIsDropdownOpen(false);
53085
- useEffect41(() => {
53119
+ useEffect42(() => {
53086
53120
  const handleClickOutside = (event) => {
53087
53121
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
53088
53122
  closeDropdown();
@@ -53280,10 +53314,10 @@ function CollapsibleResourceNavigation({
53280
53314
  }
53281
53315
 
53282
53316
  // src/components/modals/ReferenceWizardModal.tsx
53283
- import { useState as useState36, useEffect as useEffect43, useCallback as useCallback30 } from "react";
53317
+ import { useState as useState37, useEffect as useEffect44, useCallback as useCallback30 } from "react";
53284
53318
 
53285
53319
  // src/components/modals/GatherContextStep.tsx
53286
- import { useState as useState33, useEffect as useEffect42, useRef as useRef32 } from "react";
53320
+ import { useState as useState34, useEffect as useEffect43, useRef as useRef32 } from "react";
53287
53321
 
53288
53322
  // src/components/modals/ContextSummary.tsx
53289
53323
  import { Fragment as Fragment11, jsx as jsx51, jsxs as jsxs43 } from "react/jsx-runtime";
@@ -53346,11 +53380,11 @@ function GatherContextStep({
53346
53380
  onCompose,
53347
53381
  translations: t12
53348
53382
  }) {
53349
- const [sourceExpanded, setSourceExpanded] = useState33(false);
53383
+ const [sourceExpanded, setSourceExpanded] = useState34(false);
53350
53384
  const contextReady = !contextLoading && !contextError && !!context;
53351
53385
  const sourceContext = context?.sourceContext;
53352
53386
  const highlightRef = useRef32(null);
53353
- useEffect42(() => {
53387
+ useEffect43(() => {
53354
53388
  if (highlightRef.current) {
53355
53389
  highlightRef.current.scrollIntoView({ block: "center", behavior: "instant" });
53356
53390
  }
@@ -53469,7 +53503,7 @@ function GatherContextStep({
53469
53503
  }
53470
53504
 
53471
53505
  // src/components/modals/ConfigureGenerationStep.tsx
53472
- import { useState as useState34 } from "react";
53506
+ import { useState as useState35 } from "react";
53473
53507
  import { LOCALES as LOCALES2 } from "@semiont/core";
53474
53508
  import { jsx as jsx53, jsxs as jsxs45 } from "react/jsx-runtime";
53475
53509
  function ConfigureGenerationStep({
@@ -53481,12 +53515,12 @@ function ConfigureGenerationStep({
53481
53515
  onGenerate,
53482
53516
  translations: t12
53483
53517
  }) {
53484
- const [title, setTitle] = useState34(defaultTitle);
53485
- const [storagePath, setStoragePath] = useState34("");
53486
- const [prompt, setPrompt] = useState34("");
53487
- const [language2, setLanguage] = useState34(locale);
53488
- const [temperature, setTemperature] = useState34(0.7);
53489
- const [maxTokens, setMaxTokens] = useState34(500);
53518
+ const [title, setTitle] = useState35(defaultTitle);
53519
+ const [storagePath, setStoragePath] = useState35("");
53520
+ const [prompt, setPrompt] = useState35("");
53521
+ const [language2, setLanguage] = useState35(locale);
53522
+ const [temperature, setTemperature] = useState35(0.7);
53523
+ const [maxTokens, setMaxTokens] = useState35(500);
53490
53524
  const handleSubmit = (e6) => {
53491
53525
  e6.preventDefault();
53492
53526
  const trimmedPrompt = prompt.trim();
@@ -53645,7 +53679,7 @@ function ConfigureGenerationStep({
53645
53679
  }
53646
53680
 
53647
53681
  // src/components/modals/ConfigureSearchStep.tsx
53648
- import { useState as useState35 } from "react";
53682
+ import { useState as useState36 } from "react";
53649
53683
  import { jsx as jsx54, jsxs as jsxs46 } from "react/jsx-runtime";
53650
53684
  function ConfigureSearchStep({
53651
53685
  isSearching = false,
@@ -53654,8 +53688,8 @@ function ConfigureSearchStep({
53654
53688
  onSearch,
53655
53689
  translations: t12
53656
53690
  }) {
53657
- const [limit, setLimit] = useState35(10);
53658
- const [useSemanticScoring, setUseSemanticScoring] = useState35(true);
53691
+ const [limit, setLimit] = useState36(10);
53692
+ const [useSemanticScoring, setUseSemanticScoring] = useState36(true);
53659
53693
  const handleSubmit = (e6) => {
53660
53694
  e6.preventDefault();
53661
53695
  onSearch({ limit, useSemanticScoring });
@@ -53847,10 +53881,10 @@ function ReferenceWizardModal({
53847
53881
  translations: t12
53848
53882
  }) {
53849
53883
  const session = useObservable(useSemiont().activeSession$);
53850
- const [wizardStep, setWizardStep] = useState36({ step: "gather" });
53851
- const [isSearching, setIsSearching] = useState36(false);
53852
- const [userHint, setUserHint] = useState36("");
53853
- useEffect43(() => {
53884
+ const [wizardStep, setWizardStep] = useState37({ step: "gather" });
53885
+ const [isSearching, setIsSearching] = useState37(false);
53886
+ const [userHint, setUserHint] = useState37("");
53887
+ useEffect44(() => {
53854
53888
  if (isOpen) {
53855
53889
  setWizardStep({ step: "gather" });
53856
53890
  setIsSearching(false);
@@ -54039,7 +54073,7 @@ function ReferenceWizardModal({
54039
54073
  }
54040
54074
 
54041
54075
  // src/components/modals/SearchModal.tsx
54042
- import { useState as useState37, useEffect as useEffect44, useRef as useRef33 } from "react";
54076
+ import { useState as useState38, useEffect as useEffect45, useRef as useRef33 } from "react";
54043
54077
  var import_operators = __toESM(require_operators(), 1);
54044
54078
  import { getResourceId } from "@semiont/core";
54045
54079
  import { createSearchPipeline } from "@semiont/sdk";
@@ -54088,7 +54122,7 @@ function SearchModal({
54088
54122
  const semiont = useObservable(useSemiont().activeSession$)?.client;
54089
54123
  const semiontRef = useRef33(semiont);
54090
54124
  semiontRef.current = semiont;
54091
- const [selectedIndex, setSelectedIndex] = useState37(0);
54125
+ const [selectedIndex, setSelectedIndex] = useState38(0);
54092
54126
  const t12 = {
54093
54127
  placeholder: translations.placeholder || "Search resources, entities...",
54094
54128
  searching: translations.searching || "Searching...",
@@ -54100,7 +54134,7 @@ function SearchModal({
54100
54134
  enter: translations.enter || "Enter",
54101
54135
  esc: translations.esc || "ESC"
54102
54136
  };
54103
- const [pipeline] = useState37(
54137
+ const [pipeline] = useState38(
54104
54138
  () => createSearchPipeline(
54105
54139
  (q2) => semiontRef.current.browse.resources({ search: q2, limit: SEARCH_LIMIT }).pipe(
54106
54140
  (0, import_operators.map)((resources) => {
@@ -54120,21 +54154,21 @@ function SearchModal({
54120
54154
  { debounceMs: SEARCH_DEBOUNCE_MS }
54121
54155
  )
54122
54156
  );
54123
- useEffect44(() => () => pipeline.dispose(), [pipeline]);
54157
+ useEffect45(() => () => pipeline.dispose(), [pipeline]);
54124
54158
  const query = useObservable(pipeline.query$) ?? "";
54125
54159
  const searchState = useObservable(pipeline.state$);
54126
54160
  const results = searchState?.results ?? [];
54127
54161
  const loading = searchState?.isSearching ?? false;
54128
- useEffect44(() => {
54162
+ useEffect45(() => {
54129
54163
  if (isOpen) {
54130
54164
  pipeline.setQuery("");
54131
54165
  setSelectedIndex(0);
54132
54166
  }
54133
54167
  }, [isOpen, pipeline]);
54134
- useEffect44(() => {
54168
+ useEffect45(() => {
54135
54169
  setSelectedIndex(0);
54136
54170
  }, [results.length]);
54137
- useEffect44(() => {
54171
+ useEffect45(() => {
54138
54172
  if (!query.trim()) return;
54139
54173
  if (loading) {
54140
54174
  announceSearching();
@@ -54250,7 +54284,7 @@ function SearchModal({
54250
54284
  }
54251
54285
 
54252
54286
  // src/components/modals/ResourceSearchModal.tsx
54253
- import { useState as useState38, useEffect as useEffect45, useRef as useRef34 } from "react";
54287
+ import { useState as useState39, useEffect as useEffect46, useRef as useRef34 } from "react";
54254
54288
  var import_operators2 = __toESM(require_operators(), 1);
54255
54289
  import { getResourceId as getResourceId2, getPrimaryRepresentation } from "@semiont/core";
54256
54290
  import { createSearchPipeline as createSearchPipeline2 } from "@semiont/sdk";
@@ -54286,7 +54320,7 @@ function ResourceSearchModal({
54286
54320
  noResults: translations.noResults || "No documents found",
54287
54321
  close: translations.close || "\u2715"
54288
54322
  };
54289
- const [pipeline] = useState38(
54323
+ const [pipeline] = useState39(
54290
54324
  () => createSearchPipeline2(
54291
54325
  (q2) => semiontRef.current.browse.resources({ search: q2, limit: SEARCH_LIMIT2 }).pipe(
54292
54326
  (0, import_operators2.map)((resources) => {
@@ -54297,17 +54331,17 @@ function ResourceSearchModal({
54297
54331
  { debounceMs: SEARCH_DEBOUNCE_MS2, initialQuery: searchTerm }
54298
54332
  )
54299
54333
  );
54300
- useEffect45(() => () => pipeline.dispose(), [pipeline]);
54334
+ useEffect46(() => () => pipeline.dispose(), [pipeline]);
54301
54335
  const search2 = useObservable(pipeline.query$) ?? "";
54302
54336
  const searchState = useObservable(pipeline.state$);
54303
54337
  const results = searchState?.results ?? [];
54304
54338
  const loading = searchState?.isSearching ?? false;
54305
- useEffect45(() => {
54339
+ useEffect46(() => {
54306
54340
  if (isOpen && searchTerm) {
54307
54341
  pipeline.setQuery(searchTerm);
54308
54342
  }
54309
54343
  }, [isOpen, searchTerm, pipeline]);
54310
- useEffect45(() => {
54344
+ useEffect46(() => {
54311
54345
  if (!search2.trim()) return;
54312
54346
  if (loading) {
54313
54347
  announceSearching();
@@ -54427,7 +54461,7 @@ function SkipLinks() {
54427
54461
  }
54428
54462
 
54429
54463
  // src/components/StatusDisplay.tsx
54430
- import { useEffect as useEffect46, useState as useState39 } from "react";
54464
+ import { useEffect as useEffect47, useState as useState40 } from "react";
54431
54465
  import { jsx as jsx60, jsxs as jsxs52 } from "react/jsx-runtime";
54432
54466
  function StatusDisplay({
54433
54467
  isFullyAuthenticated = false,
@@ -54435,10 +54469,10 @@ function StatusDisplay({
54435
54469
  hasValidBackendToken = false
54436
54470
  }) {
54437
54471
  const semiont = useObservable(useSemiont().activeSession$)?.client;
54438
- const [data2, setData] = useState39(null);
54439
- const [loading, setLoading] = useState39(true);
54440
- const [error, setError] = useState39(null);
54441
- useEffect46(() => {
54472
+ const [data2, setData] = useState40(null);
54473
+ const [loading, setLoading] = useState40(true);
54474
+ const [error, setError] = useState40(null);
54475
+ useEffect47(() => {
54442
54476
  if (!semiont) {
54443
54477
  setLoading(false);
54444
54478
  return;
@@ -54530,11 +54564,11 @@ function SessionTimer() {
54530
54564
  }
54531
54565
 
54532
54566
  // src/components/SessionExpiryBanner.tsx
54533
- import { useState as useState40 } from "react";
54567
+ import { useState as useState41 } from "react";
54534
54568
  import { jsx as jsx61, jsxs as jsxs54 } from "react/jsx-runtime";
54535
54569
  function SessionExpiryBanner() {
54536
54570
  const { timeRemaining, isExpiringSoon } = useSessionExpiry();
54537
- const [dismissed, setDismissed] = useState40(false);
54571
+ const [dismissed, setDismissed] = useState41(false);
54538
54572
  const formattedTime = formatTime(timeRemaining);
54539
54573
  if (!isExpiringSoon || dismissed || !formattedTime) {
54540
54574
  return null;
@@ -54755,7 +54789,7 @@ function UnifiedHeader({
54755
54789
  }
54756
54790
 
54757
54791
  // src/components/layout/LeftSidebar.tsx
54758
- import { useState as useState41, useEffect as useEffect47 } from "react";
54792
+ import { useState as useState42, useEffect as useEffect48 } from "react";
54759
54793
  import { jsx as jsx65, jsxs as jsxs57 } from "react/jsx-runtime";
54760
54794
  function LeftSidebar({
54761
54795
  Link,
@@ -54770,7 +54804,7 @@ function LeftSidebar({
54770
54804
  isModerator = false,
54771
54805
  currentPath
54772
54806
  }) {
54773
- const [isCollapsed, setIsCollapsed] = useState41(false);
54807
+ const [isCollapsed, setIsCollapsed] = useState42(false);
54774
54808
  const { width, setWidth, minWidth, maxWidth } = usePanelWidth({
54775
54809
  defaultWidth: 256,
54776
54810
  // 16rem
@@ -54780,7 +54814,7 @@ function LeftSidebar({
54780
54814
  // 25rem
54781
54815
  storageKey: "semiont-left-sidebar-width"
54782
54816
  });
54783
- useEffect47(() => {
54817
+ useEffect48(() => {
54784
54818
  if (collapsible) {
54785
54819
  const saved = localStorage.getItem(storageKey);
54786
54820
  if (saved === "true") {
@@ -55969,7 +56003,7 @@ function ExportCard({ onExport, isExporting, translations: t12 }) {
55969
56003
  }
55970
56004
 
55971
56005
  // src/features/admin-exchange/components/ImportCard.tsx
55972
- import { useRef as useRef35, useState as useState42, useCallback as useCallback32 } from "react";
56006
+ import { useRef as useRef35, useState as useState43, useCallback as useCallback32 } from "react";
55973
56007
  import { jsx as jsx74, jsxs as jsxs64 } from "react/jsx-runtime";
55974
56008
  function ImportCard({
55975
56009
  onFileSelected,
@@ -55981,8 +56015,8 @@ function ImportCard({
55981
56015
  translations: t12
55982
56016
  }) {
55983
56017
  const fileInputRef = useRef35(null);
55984
- const [isDragActive, setIsDragActive] = useState42(false);
55985
- const [showConfirm, setShowConfirm] = useState42(false);
56018
+ const [isDragActive, setIsDragActive] = useState43(false);
56019
+ const [showConfirm, setShowConfirm] = useState43(false);
55986
56020
  const handleDragOver = useCallback32((e6) => {
55987
56021
  e6.preventDefault();
55988
56022
  setIsDragActive(true);
@@ -56108,33 +56142,35 @@ function ImportCard({
56108
56142
  }
56109
56143
 
56110
56144
  // src/features/admin-exchange/components/ImportProgress.tsx
56111
- import { Fragment as Fragment14, jsx as jsx75, jsxs as jsxs65 } from "react/jsx-runtime";
56145
+ import { jsx as jsx75, jsxs as jsxs65 } from "react/jsx-runtime";
56112
56146
  var PHASE_LABELS = {
56113
56147
  started: "phaseStarted",
56114
- "entity-types": "phaseEntityTypes",
56115
- resources: "phaseResources",
56116
- annotations: "phaseAnnotations",
56117
56148
  complete: "phaseComplete",
56118
56149
  error: "phaseError"
56119
56150
  };
56151
+ var STAT_LABELS = {
56152
+ eventsReplayed: "statsEventsReplayed",
56153
+ resourcesCreated: "statsResourcesCreated",
56154
+ annotationsCreated: "statsAnnotationsCreated",
56155
+ entityTypesAdded: "statsEntityTypesAdded"
56156
+ };
56120
56157
  function ImportProgress({ phase, message, result, translations: t12 }) {
56121
56158
  const labelKey = PHASE_LABELS[phase];
56122
56159
  const phaseLabel = labelKey ? t12[labelKey] : phase;
56123
56160
  const isComplete = phase === "complete";
56124
56161
  const isError = phase === "error";
56162
+ const stats = result?.stats != null && typeof result.stats === "object" ? result.stats : void 0;
56163
+ const statEntries = stats ? Object.entries(stats).filter((entry) => typeof entry[1] === "number") : [];
56125
56164
  return /* @__PURE__ */ jsxs65("div", { className: "semiont-exchange__progress", children: [
56126
56165
  /* @__PURE__ */ jsx75("div", { className: `semiont-exchange__phase-label${isError ? " semiont-exchange__phase-label--error" : isComplete ? " semiont-exchange__phase-label--complete" : ""}`, children: phaseLabel }),
56127
56166
  message && !isComplete && !isError && /* @__PURE__ */ jsx75("p", { className: "semiont-exchange__progress-message", children: message }),
56128
- isComplete && result && /* @__PURE__ */ jsxs65("div", { className: "semiont-exchange__result", children: [
56129
- result.stats != null && typeof result.stats === "object" && /* @__PURE__ */ jsx75(Fragment14, { children: Object.entries(result.stats).map(([key, value]) => {
56130
- const label = key === "streams" ? t12.streams : key === "events" ? t12.events : key === "blobs" ? t12.blobs : key;
56131
- return /* @__PURE__ */ jsxs65("div", { className: "semiont-exchange__result-stat", children: [
56132
- /* @__PURE__ */ jsx75("span", { className: "semiont-exchange__result-value", children: value }),
56133
- /* @__PURE__ */ jsx75("span", { className: "semiont-exchange__result-label", children: label })
56134
- ] }, key);
56135
- }) }),
56136
- result.hashChainValid !== void 0 && /* @__PURE__ */ jsx75("div", { className: `semiont-exchange__hash-badge${result.hashChainValid ? " semiont-exchange__hash-badge--valid" : " semiont-exchange__hash-badge--invalid"}`, children: result.hashChainValid ? t12.hashChainValid : t12.hashChainInvalid })
56137
- ] }),
56167
+ isComplete && statEntries.length > 0 && /* @__PURE__ */ jsx75("div", { className: "semiont-exchange__result", children: statEntries.map(([key, value]) => {
56168
+ const statKey = STAT_LABELS[key];
56169
+ return /* @__PURE__ */ jsxs65("div", { className: "semiont-exchange__result-stat", children: [
56170
+ /* @__PURE__ */ jsx75("span", { className: "semiont-exchange__result-value", children: value }),
56171
+ /* @__PURE__ */ jsx75("span", { className: "semiont-exchange__result-label", children: statKey ? t12[statKey] : key })
56172
+ ] }, key);
56173
+ }) }),
56138
56174
  isError && message && /* @__PURE__ */ jsx75("p", { className: "semiont-exchange__error-message", children: message })
56139
56175
  ] });
56140
56176
  }
@@ -56393,8 +56429,8 @@ function LinkedDataPage({
56393
56429
  }
56394
56430
 
56395
56431
  // src/features/admin-users/components/AdminUsersPage.tsx
56396
- import { useState as useState43 } from "react";
56397
- import { Fragment as Fragment15, jsx as jsx79, jsxs as jsxs69 } from "react/jsx-runtime";
56432
+ import { useState as useState44 } from "react";
56433
+ import { Fragment as Fragment14, jsx as jsx79, jsxs as jsxs69 } from "react/jsx-runtime";
56398
56434
  function UserTableRow({
56399
56435
  user,
56400
56436
  onUpdate,
@@ -56475,9 +56511,9 @@ function AdminUsersPage({
56475
56511
  Toolbar: Toolbar2,
56476
56512
  buttonStyles: buttonStyles2
56477
56513
  }) {
56478
- const [searchTerm, setSearchTerm] = useState43("");
56479
- const [selectedRole, setSelectedRole] = useState43("all");
56480
- const [selectedStatus, setSelectedStatus] = useState43("all");
56514
+ const [searchTerm, setSearchTerm] = useState44("");
56515
+ const [selectedRole, setSelectedRole] = useState44("all");
56516
+ const [selectedStatus, setSelectedStatus] = useState44("all");
56481
56517
  const filteredUsers = users.filter((user) => {
56482
56518
  const matchesSearch = (user.name || "").toLowerCase().includes(searchTerm.toLowerCase()) || user.email.toLowerCase().includes(searchTerm.toLowerCase());
56483
56519
  const userRole = user.isAdmin ? "admin" : "user";
@@ -56504,7 +56540,7 @@ function AdminUsersPage({
56504
56540
  /* @__PURE__ */ jsx79("div", { className: "semiont-skeleton semiont-skeleton--text" }),
56505
56541
  /* @__PURE__ */ jsx79("div", { className: "semiont-skeleton semiont-skeleton--number" })
56506
56542
  ] })
56507
- ] }) }, i12)) : /* @__PURE__ */ jsxs69(Fragment15, { children: [
56543
+ ] }) }, i12)) : /* @__PURE__ */ jsxs69(Fragment14, { children: [
56508
56544
  /* @__PURE__ */ jsx79("div", { className: "semiont-stat-card", children: /* @__PURE__ */ jsxs69("div", { className: "semiont-stat-card__content", children: [
56509
56545
  /* @__PURE__ */ jsx79("div", { className: "semiont-stat-card__icon-wrapper", children: /* @__PURE__ */ jsx79(UserCircleIcon_default, { className: "semiont-stat-card__icon semiont-stat-card__icon--primary" }) }),
56510
56546
  /* @__PURE__ */ jsxs69("div", { className: "semiont-stat-card__text", children: [
@@ -56642,7 +56678,7 @@ function AdminUsersPage({
56642
56678
 
56643
56679
  // src/features/auth/components/SignInForm.tsx
56644
56680
  import React45 from "react";
56645
- import { Fragment as Fragment16, jsx as jsx80, jsxs as jsxs70 } from "react/jsx-runtime";
56681
+ import { Fragment as Fragment15, jsx as jsx80, jsxs as jsxs70 } from "react/jsx-runtime";
56646
56682
  function GoogleIcon() {
56647
56683
  return /* @__PURE__ */ jsxs70("svg", { className: "semiont-icon semiont-icon--small semiont-icon--inline", viewBox: "0 0 24 24", children: [
56648
56684
  /* @__PURE__ */ jsx80(
@@ -56741,7 +56777,7 @@ function CredentialsAuthForm({
56741
56777
  ]
56742
56778
  }
56743
56779
  ) : null;
56744
- return /* @__PURE__ */ jsxs70(Fragment16, { children: [
56780
+ return /* @__PURE__ */ jsxs70(Fragment15, { children: [
56745
56781
  validationError && /* @__PURE__ */ jsx80("div", { className: "semiont-auth__error", role: "alert", "aria-live": "polite", children: /* @__PURE__ */ jsx80("div", { className: "semiont-auth__error-text", children: validationError }) }),
56746
56782
  /* @__PURE__ */ jsxs70("form", { onSubmit: handleSubmit, className: "semiont-auth__form", noValidate: true, children: [
56747
56783
  /* @__PURE__ */ jsxs70("div", { className: "semiont-form__field", children: [
@@ -56846,7 +56882,7 @@ function SignInForm({
56846
56882
  /* @__PURE__ */ jsx80("p", { className: "semiont-auth__subtitle", children: t12.signInPrompt })
56847
56883
  ] }),
56848
56884
  error && /* @__PURE__ */ jsx80("div", { className: "semiont-auth__error-container", children: /* @__PURE__ */ jsx80("div", { className: "semiont-auth__error", children: /* @__PURE__ */ jsx80("div", { className: "semiont-auth__error-text", children: error }) }) }),
56849
- /* @__PURE__ */ jsx80("div", { className: "semiont-auth__forms", children: !isLoading ? /* @__PURE__ */ jsxs70(Fragment16, { children: [
56885
+ /* @__PURE__ */ jsx80("div", { className: "semiont-auth__forms", children: !isLoading ? /* @__PURE__ */ jsxs70(Fragment15, { children: [
56850
56886
  showCredentialsAuth && onCredentialsSignIn && /* @__PURE__ */ jsx80(
56851
56887
  CredentialsAuthForm,
56852
56888
  {
@@ -56865,7 +56901,7 @@ function SignInForm({
56865
56901
  }
56866
56902
 
56867
56903
  // src/features/auth/components/SignUpForm.tsx
56868
- import { useState as useState44 } from "react";
56904
+ import { useState as useState45 } from "react";
56869
56905
  import { jsx as jsx81, jsxs as jsxs71 } from "react/jsx-runtime";
56870
56906
  function GoogleIcon2() {
56871
56907
  return /* @__PURE__ */ jsxs71("svg", { className: "semiont-icon semiont-icon--small semiont-icon--inline", viewBox: "0 0 24 24", children: [
@@ -56900,7 +56936,7 @@ function GoogleIcon2() {
56900
56936
  ] });
56901
56937
  }
56902
56938
  function SignUpForm({ onSignUp, Link, translations: t12 }) {
56903
- const [isLoading, setIsLoading] = useState44(false);
56939
+ const [isLoading, setIsLoading] = useState45(false);
56904
56940
  const handleSignUp = async () => {
56905
56941
  setIsLoading(true);
56906
56942
  try {
@@ -57105,7 +57141,7 @@ function WelcomePage({
57105
57141
  }
57106
57142
 
57107
57143
  // src/features/moderate-entity-tags/components/EntityTagsPage.tsx
57108
- import { Fragment as Fragment17, jsx as jsx84, jsxs as jsxs74 } from "react/jsx-runtime";
57144
+ import { Fragment as Fragment16, jsx as jsx84, jsxs as jsxs74 } from "react/jsx-runtime";
57109
57145
  function EntityTagsPage({
57110
57146
  entityTypes,
57111
57147
  error,
@@ -57166,7 +57202,7 @@ function EntityTagsPage({
57166
57202
  onClick: onAddTag,
57167
57203
  disabled: isAddingTag || !newTag.trim(),
57168
57204
  className: "semiont-button semiont-button--primary",
57169
- children: isAddingTag ? t12.adding : /* @__PURE__ */ jsxs74(Fragment17, { children: [
57205
+ children: isAddingTag ? t12.adding : /* @__PURE__ */ jsxs74(Fragment16, { children: [
57170
57206
  /* @__PURE__ */ jsx84(PlusIcon_default, { className: "semiont-icon semiont-icon--small semiont-icon--inline" }),
57171
57207
  t12.addTag
57172
57208
  ] })
@@ -57357,11 +57393,11 @@ function TagSchemasPage({
57357
57393
  }
57358
57394
 
57359
57395
  // src/features/resource-compose/components/ResourceComposePage.tsx
57360
- import { useState as useState45, useEffect as useEffect48 } from "react";
57361
- import { isImageMimeType, isPdfMimeType as isPdfMimeType4, LOCALES as LOCALES3 } from "@semiont/core";
57396
+ import { useState as useState46, useEffect as useEffect49 } from "react";
57397
+ import { capabilitiesOf as capabilitiesOf5, AUTHORABLE_MEDIA_TYPES, MEDIA_TYPES, mediaTypeForExtension, isSupportedMediaType, LOCALES as LOCALES3 } from "@semiont/core";
57362
57398
 
57363
57399
  // src/features/resource-compose/components/UploadProgressBar.tsx
57364
- import { Fragment as Fragment18, jsx as jsx87, jsxs as jsxs77 } from "react/jsx-runtime";
57400
+ import { Fragment as Fragment17, jsx as jsx87, jsxs as jsxs77 } from "react/jsx-runtime";
57365
57401
  function formatBytes(bytes) {
57366
57402
  if (bytes < 1024) return `${bytes} B`;
57367
57403
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
@@ -57388,7 +57424,7 @@ function UploadProgressBar({ progress, label = "Upload" }) {
57388
57424
  ": ",
57389
57425
  formatBytes(progress.bytesUploaded),
57390
57426
  "\u2026"
57391
- ] }) : /* @__PURE__ */ jsxs77(Fragment18, { children: [
57427
+ ] }) : /* @__PURE__ */ jsxs77(Fragment17, { children: [
57392
57428
  /* @__PURE__ */ jsxs77("span", { children: [
57393
57429
  label,
57394
57430
  ": ",
@@ -57431,6 +57467,15 @@ function UploadProgressBar({ progress, label = "Upload" }) {
57431
57467
 
57432
57468
  // src/features/resource-compose/components/ResourceComposePage.tsx
57433
57469
  import { jsx as jsx88, jsxs as jsxs78 } from "react/jsx-runtime";
57470
+ var UPLOAD_ACCEPT = Object.values(MEDIA_TYPES).map((c12) => c12.extension).join(",");
57471
+ function detectUploadMediaType(file) {
57472
+ if (file.type && isSupportedMediaType(file.type)) return file.type;
57473
+ if (file.name.includes(".")) {
57474
+ const byExt = mediaTypeForExtension(file.name.slice(file.name.lastIndexOf(".")));
57475
+ if (byExt) return byExt;
57476
+ }
57477
+ return "application/octet-stream";
57478
+ }
57434
57479
  function ResourceComposePage({
57435
57480
  mode,
57436
57481
  cloneData,
@@ -57450,20 +57495,20 @@ function ResourceComposePage({
57450
57495
  Toolbar: Toolbar2
57451
57496
  }) {
57452
57497
  const { announceFormSubmitting, announceFormSuccess, announceFormError } = useFormAnnouncements();
57453
- const [newResourceName, setNewResourceName] = useState45("");
57454
- const [newResourceContent, setNewResourceContent] = useState45("");
57455
- const [selectedEntityTypes, setSelectedEntityTypes] = useState45([]);
57456
- const [isCreating, setIsCreating] = useState45(false);
57457
- const [inputMethod, setInputMethod] = useState45("write");
57458
- const [uploadedFile, setUploadedFile] = useState45(null);
57459
- const [fileMimeType, setFileMimeType] = useState45("text/markdown");
57460
- const [filePreviewUrl, setFilePreviewUrl] = useState45(null);
57461
- const [selectedFormat, setSelectedFormat] = useState45("text/markdown");
57462
- const [selectedLanguage, setSelectedLanguage] = useState45(initialLocale);
57463
- const [selectedCharset, setSelectedCharset] = useState45("");
57464
- const [storagePath, setStoragePath] = useState45("");
57465
- const [archiveOriginal, setArchiveOriginal] = useState45(true);
57466
- useEffect48(() => {
57498
+ const [newResourceName, setNewResourceName] = useState46("");
57499
+ const [newResourceContent, setNewResourceContent] = useState46("");
57500
+ const [selectedEntityTypes, setSelectedEntityTypes] = useState46([]);
57501
+ const [isCreating, setIsCreating] = useState46(false);
57502
+ const [inputMethod, setInputMethod] = useState46("write");
57503
+ const [uploadedFile, setUploadedFile] = useState46(null);
57504
+ const [fileMimeType, setFileMimeType] = useState46("text/markdown");
57505
+ const [filePreviewUrl, setFilePreviewUrl] = useState46(null);
57506
+ const [selectedFormat, setSelectedFormat] = useState46("text/markdown");
57507
+ const [selectedLanguage, setSelectedLanguage] = useState46(initialLocale);
57508
+ const [selectedCharset, setSelectedCharset] = useState46("");
57509
+ const [storagePath, setStoragePath] = useState46("");
57510
+ const [archiveOriginal, setArchiveOriginal] = useState46(true);
57511
+ useEffect49(() => {
57467
57512
  if (mode === "clone" && cloneData) {
57468
57513
  setNewResourceName(cloneData.sourceResource.name);
57469
57514
  setNewResourceContent(cloneData.sourceContent);
@@ -57477,14 +57522,16 @@ function ResourceComposePage({
57477
57522
  const handleFileUpload = (e6) => {
57478
57523
  const file = e6.target.files?.[0];
57479
57524
  if (!file) return;
57525
+ const detectedMediaType = detectUploadMediaType(file);
57480
57526
  setUploadedFile(file);
57481
- setFileMimeType(file.type);
57527
+ setFileMimeType(detectedMediaType);
57482
57528
  setInputMethod("upload");
57483
57529
  if (!newResourceName) {
57484
57530
  const nameWithoutExt = file.name.replace(/\.[^/.]+$/, "");
57485
57531
  setNewResourceName(nameWithoutExt);
57486
57532
  }
57487
- if (isImageMimeType(file.type) || isPdfMimeType4(file.type)) {
57533
+ const detectedRender = capabilitiesOf5(detectedMediaType)?.render;
57534
+ if (detectedRender === "image" || detectedRender === "pdf") {
57488
57535
  const previewUrl = URL.createObjectURL(file);
57489
57536
  setFilePreviewUrl(previewUrl);
57490
57537
  } else {
@@ -57496,7 +57543,7 @@ function ResourceComposePage({
57496
57543
  reader.readAsText(file);
57497
57544
  }
57498
57545
  };
57499
- useEffect48(() => {
57546
+ useEffect49(() => {
57500
57547
  return () => {
57501
57548
  if (filePreviewUrl) {
57502
57549
  URL.revokeObjectURL(filePreviewUrl);
@@ -57747,7 +57794,7 @@ function ResourceComposePage({
57747
57794
  "input",
57748
57795
  {
57749
57796
  type: "file",
57750
- accept: "text/plain,text/markdown,image/png,image/jpeg,application/pdf",
57797
+ accept: UPLOAD_ACCEPT,
57751
57798
  onChange: handleFileUpload,
57752
57799
  className: "semiont-form__upload-input",
57753
57800
  disabled: isCreating
@@ -57779,7 +57826,7 @@ function ResourceComposePage({
57779
57826
  /* @__PURE__ */ jsx88("code", { className: "semiont-form__media-type-value", children: fileMimeType }),
57780
57827
  /* @__PURE__ */ jsx88("span", { className: "semiont-form__media-type-lock", title: t12.autoDetected, children: "\u{1F512}" })
57781
57828
  ] }),
57782
- uploadedFile && filePreviewUrl && isImageMimeType(fileMimeType) && /* @__PURE__ */ jsxs78("div", { className: "semiont-form__image-preview", children: [
57829
+ uploadedFile && filePreviewUrl && capabilitiesOf5(fileMimeType)?.render === "image" && /* @__PURE__ */ jsxs78("div", { className: "semiont-form__image-preview", children: [
57783
57830
  /* @__PURE__ */ jsx88("p", { className: "semiont-form__image-preview-label", children: "Preview:" }),
57784
57831
  /* @__PURE__ */ jsx88("div", { className: "semiont-form__image-preview-container", children: /* @__PURE__ */ jsx88(
57785
57832
  "img",
@@ -57794,7 +57841,7 @@ function ResourceComposePage({
57794
57841
  (isClone || isReferenceCompletion || inputMethod === "write") && /* @__PURE__ */ jsxs78("div", { className: "semiont-form__write-section", children: [
57795
57842
  !isClone && !isReferenceCompletion && /* @__PURE__ */ jsxs78("div", { className: "semiont-form__field", children: [
57796
57843
  /* @__PURE__ */ jsx88("label", { htmlFor: "format-select", className: "semiont-form__label", children: t12.format }),
57797
- /* @__PURE__ */ jsxs78(
57844
+ /* @__PURE__ */ jsx88(
57798
57845
  "select",
57799
57846
  {
57800
57847
  id: "format-select",
@@ -57802,11 +57849,12 @@ function ResourceComposePage({
57802
57849
  onChange: (e6) => setSelectedFormat(e6.target.value),
57803
57850
  disabled: isCreating,
57804
57851
  className: "semiont-select",
57805
- children: [
57806
- /* @__PURE__ */ jsx88("option", { value: "text/markdown", children: "Markdown (text/markdown)" }),
57807
- /* @__PURE__ */ jsx88("option", { value: "text/plain", children: "Plain Text (text/plain)" }),
57808
- /* @__PURE__ */ jsx88("option", { value: "text/html", children: "HTML (text/html)" })
57809
- ]
57852
+ children: AUTHORABLE_MEDIA_TYPES.map((mt) => /* @__PURE__ */ jsxs78("option", { value: mt, children: [
57853
+ capabilitiesOf5(mt)?.label ?? mt,
57854
+ " (",
57855
+ mt,
57856
+ ")"
57857
+ ] }, mt))
57810
57858
  }
57811
57859
  )
57812
57860
  ] }),
@@ -58126,18 +58174,17 @@ function ResourceDiscoveryPage({
58126
58174
  }
58127
58175
 
58128
58176
  // src/features/resource-viewer/components/ResourceViewerPage.tsx
58129
- import { useState as useState47, useEffect as useEffect50, useCallback as useCallback34 } from "react";
58177
+ import { useState as useState48, useEffect as useEffect51, useCallback as useCallback34 } from "react";
58130
58178
  import { annotationId } from "@semiont/core";
58131
- import { getLanguage, getPrimaryRepresentation as getPrimaryRepresentation2, getPrimaryMediaType as getPrimaryMediaType2 } from "@semiont/core";
58132
- import { getMimeCategory as getMimeCategory3 } from "@semiont/core";
58179
+ import { getLanguage, getPrimaryRepresentation as getPrimaryRepresentation2, getPrimaryMediaType as getPrimaryMediaType2, capabilitiesOf as capabilitiesOf6 } from "@semiont/core";
58133
58180
 
58134
58181
  // src/hooks/useMediaToken.ts
58135
- import { useEffect as useEffect49, useState as useState46 } from "react";
58182
+ import { useEffect as useEffect50, useState as useState47 } from "react";
58136
58183
  function useMediaToken(id2) {
58137
58184
  const semiont = useObservable(useSemiont().activeSession$)?.client;
58138
- const [token, setToken] = useState46(void 0);
58139
- const [loading, setLoading] = useState46(true);
58140
- useEffect49(() => {
58185
+ const [token, setToken] = useState47(void 0);
58186
+ const [loading, setLoading] = useState47(true);
58187
+ useEffect50(() => {
58141
58188
  if (!semiont || !id2) {
58142
58189
  setLoading(false);
58143
58190
  return;
@@ -58174,7 +58221,7 @@ import { createMarkStateUnit } from "@semiont/sdk";
58174
58221
  import { createGatherStateUnit } from "@semiont/sdk";
58175
58222
  import { createMatchStateUnit } from "@semiont/sdk";
58176
58223
  import { createYieldStateUnit } from "@semiont/sdk";
58177
- import { decodeWithCharset as decodeWithCharset2 } from "@semiont/core";
58224
+ import { decodeWithCharset as decodeWithCharset2, textExtractionOf } from "@semiont/core";
58178
58225
  import { isHighlight as isHighlight5, isComment as isComment5, isAssessment as isAssessment4, isReference as isReference6, isTag as isTag6 } from "@semiont/core";
58179
58226
  var WIZARD_CLOSED = {
58180
58227
  open: false,
@@ -58225,11 +58272,11 @@ function createResourceViewerPageStateUnit(client, resourceId2, locale, browse,
58225
58272
  const contentLoading$ = new import_rxjs2.BehaviorSubject(false);
58226
58273
  const mediaToken$ = new import_rxjs2.BehaviorSubject(null);
58227
58274
  const mediaType = options?.mediaType || "text/plain";
58228
- const isBinaryType = mediaType.startsWith("image/") || mediaType === "application/pdf";
58275
+ const isBinaryType = textExtractionOf(mediaType) !== "decode";
58229
58276
  if (!isBinaryType && mediaType) {
58230
58277
  contentLoading$.next(true);
58231
- client.browse.resourceRepresentation(resourceId2, { accept: mediaType }).then(({ data: data2 }) => {
58232
- content$.next(decodeWithCharset2(data2, mediaType));
58278
+ client.browse.resourceRepresentation(resourceId2).then(({ data: data2, contentType }) => {
58279
+ content$.next(decodeWithCharset2(data2, contentType));
58233
58280
  contentLoading$.next(false);
58234
58281
  }).catch(() => {
58235
58282
  contentLoading$.next(false);
@@ -58324,7 +58371,8 @@ function ResourceViewerPage({
58324
58371
  const { hoverDelayMs } = useHoverDelay();
58325
58372
  const { triggerSparkleAnimation, clearNewAnnotationId } = useResourceAnnotations();
58326
58373
  const resourceMediaType = getPrimaryMediaType2(resource) || "text/plain";
58327
- const isBinary = getMimeCategory3(resourceMediaType) === "image";
58374
+ const renderMode = capabilitiesOf6(resourceMediaType)?.render;
58375
+ const isBinary = renderMode === "image" || renderMode === "pdf";
58328
58376
  const { content: textContent, loading: textLoading } = useResourceContent(rUri, resource, !isBinary);
58329
58377
  const { token: mediaToken, loading: mediaTokenLoading } = useMediaToken(rUri);
58330
58378
  const binaryContent = isBinary && mediaToken && semiont ? `${semiont.baseUrl}/api/resources/${rUri}?token=${mediaToken}` : "";
@@ -58401,7 +58449,7 @@ function ResourceViewerPage({
58401
58449
  reason: "compose-from-wizard"
58402
58450
  });
58403
58451
  }, [session]);
58404
- useEffect50(() => {
58452
+ useEffect51(() => {
58405
58453
  if (resource && rUri) {
58406
58454
  const mediaType = getPrimaryMediaType2(resource);
58407
58455
  browser2.addOpenResource(rUri, resource.name, mediaType || void 0, resource.storageUri);
@@ -58410,7 +58458,7 @@ function ResourceViewerPage({
58410
58458
  }
58411
58459
  }
58412
58460
  }, [resource, rUri, browser2]);
58413
- useEffect50(() => {
58461
+ useEffect51(() => {
58414
58462
  if (pendingAnnotation) {
58415
58463
  browser2.emit("panel:open", { panel: "annotations" });
58416
58464
  }
@@ -58514,7 +58562,7 @@ function ResourceViewerPage({
58514
58562
  announceResourceLoading,
58515
58563
  announceResourceLoaded
58516
58564
  } = useResourceLoadingAnnouncements();
58517
- useEffect50(() => {
58565
+ useEffect51(() => {
58518
58566
  if (contentLoading) {
58519
58567
  announceResourceLoading(resource.name);
58520
58568
  } else if (content4) {
@@ -58525,7 +58573,7 @@ function ResourceViewerPage({
58525
58573
  const primaryRep = getPrimaryRepresentation2(resource);
58526
58574
  const primaryMediaType = primaryRep?.mediaType;
58527
58575
  const primaryByteSize = primaryRep?.byteSize;
58528
- const [annotateMode, setAnnotateMode] = useState47(() => {
58576
+ const [annotateMode, setAnnotateMode] = useState48(() => {
58529
58577
  if (typeof window !== "undefined") {
58530
58578
  return localStorage.getItem("annotateMode") === "true";
58531
58579
  }
@@ -58643,7 +58691,7 @@ function ResourceViewerPage({
58643
58691
  knowledgeBaseName
58644
58692
  }
58645
58693
  ),
58646
- activePanel === "jsonld" && /* @__PURE__ */ jsx91(JsonLdPanel, { resource })
58694
+ activePanel === "jsonld" && /* @__PURE__ */ jsx91(JsonLdPanel, { resourceId: rUri })
58647
58695
  ]
58648
58696
  }
58649
58697
  ),
@@ -58748,7 +58796,7 @@ function createSessionStateUnit(client) {
58748
58796
  var import_rxjs4 = __toESM(require_cjs(), 1);
58749
58797
  import { resourceId as makeResourceId2, annotationId as makeAnnotationId } from "@semiont/core";
58750
58798
  import { createDisposer as createDisposer2 } from "@semiont/sdk";
58751
- import { getPrimaryMediaType as getPrimaryMediaType3, decodeWithCharset as decodeWithCharset3 } from "@semiont/core";
58799
+ import { decodeWithCharset as decodeWithCharset3, extensionForMediaType } from "@semiont/core";
58752
58800
  function createComposePageStateUnit(client, browse, params, auth) {
58753
58801
  const disposer = createDisposer2();
58754
58802
  disposer.add(browse);
@@ -58785,11 +58833,8 @@ function createComposePageStateUnit(client, browse, params, auth) {
58785
58833
  const tokenResult = await client.yield.fromToken(params.token);
58786
58834
  if (tokenResult && auth) {
58787
58835
  const rId = makeResourceId2(tokenResult["@id"]);
58788
- const mediaType = getPrimaryMediaType3(tokenResult) || "text/plain";
58789
- const { data: data2 } = await client.browse.resourceRepresentation(rId, {
58790
- accept: mediaType
58791
- });
58792
- const content4 = decodeWithCharset3(data2, mediaType);
58836
+ const { data: data2, contentType } = await client.browse.resourceRepresentation(rId);
58837
+ const content4 = decodeWithCharset3(data2, contentType);
58793
58838
  cloneData$.next({ sourceResource: tokenResult, sourceContent: content4 });
58794
58839
  }
58795
58840
  } catch {
@@ -58816,7 +58861,7 @@ function createComposePageStateUnit(client, browse, params, auth) {
58816
58861
  mimeType = saveParams.format ?? "application/octet-stream";
58817
58862
  } else {
58818
58863
  const blob = new Blob([saveParams.content || ""], { type: saveParams.format ?? "application/octet-stream" });
58819
- const extension2 = saveParams.format === "text/plain" ? ".txt" : saveParams.format === "text/html" ? ".html" : ".md";
58864
+ const extension2 = extensionForMediaType(saveParams.format ?? "application/octet-stream");
58820
58865
  fileToUpload = new File([blob], saveParams.name + extension2, { type: saveParams.format ?? "application/octet-stream" });
58821
58866
  mimeType = saveParams.format ?? "application/octet-stream";
58822
58867
  }