@pipelex/mthds-ui 0.5.0 → 0.5.2

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.
@@ -10,7 +10,7 @@ import {
10
10
  getPipeBlueprint,
11
11
  resolveConceptRef,
12
12
  stuffDigestFromId
13
- } from "../../chunk-CCUSQM3E.js";
13
+ } from "../../chunk-OMJ6DRXM.js";
14
14
  import {
15
15
  __spreadProps,
16
16
  __spreadValues
@@ -176,7 +176,13 @@ function downloadUrl(url, filename) {
176
176
  link.target = "_blank";
177
177
  link.click();
178
178
  }
179
- function StuffViewer({ stuff, className, resolveStorageUrl }) {
179
+ function StuffViewer({
180
+ stuff,
181
+ className,
182
+ resolveStorageUrl,
183
+ canEmbedPdf,
184
+ onOpenExternally
185
+ }) {
180
186
  var _a;
181
187
  const [activeTab, setActiveTab] = React.useState("html");
182
188
  const [copied, setCopied] = React.useState(false);
@@ -242,10 +248,29 @@ function StuffViewer({ stuff, className, resolveStorageUrl }) {
242
248
  function renderContent() {
243
249
  if (activeTab === "html") {
244
250
  if (isPdf) {
245
- if (inlineUrl) {
251
+ const canEmbed = canEmbedPdf !== false;
252
+ if (canEmbed && inlineUrl) {
246
253
  const pdfUrl = inlineUrl.includes("#") ? inlineUrl : `${inlineUrl}#pagemode=none`;
247
254
  return /* @__PURE__ */ jsx("div", { className: "stuff-viewer-pdf", children: /* @__PURE__ */ jsx("embed", { src: pdfUrl, type: "application/pdf" }) });
248
255
  }
256
+ if (externalUrl) {
257
+ const displayName = filename || stuff.name;
258
+ return /* @__PURE__ */ jsxs(
259
+ "button",
260
+ {
261
+ type: "button",
262
+ className: "stuff-viewer-local-file stuff-viewer-local-file--button",
263
+ onClick: handleOpenExternal,
264
+ children: [
265
+ /* @__PURE__ */ jsx("div", { className: "stuff-viewer-local-file-icon", children: ICON_LOCAL_FILE }),
266
+ /* @__PURE__ */ jsxs("div", { className: "stuff-viewer-local-file-info", children: [
267
+ displayName && /* @__PURE__ */ jsx("div", { className: "stuff-viewer-local-file-name", children: displayName }),
268
+ /* @__PURE__ */ jsx("div", { className: "stuff-viewer-local-file-hint", children: "Click to open PDF externally" })
269
+ ] })
270
+ ]
271
+ }
272
+ );
273
+ }
249
274
  return renderMediaFallback("PDF");
250
275
  }
251
276
  if (isImage) {
@@ -351,9 +376,12 @@ function StuffViewer({ stuff, className, resolveStorageUrl }) {
351
376
  }
352
377
  }
353
378
  function handleOpenExternal() {
354
- if (externalUrl) {
355
- window.open(externalUrl, "_blank", "noopener,noreferrer");
379
+ if (!externalUrl) return;
380
+ if (onOpenExternally) {
381
+ onOpenExternally(externalUrl, filename != null ? filename : void 0);
382
+ return;
356
383
  }
384
+ window.open(externalUrl, "_blank", "noopener,noreferrer");
357
385
  }
358
386
  const rootClass = ["stuff-viewer", className].filter(Boolean).join(" ");
359
387
  return /* @__PURE__ */ jsxs("div", { className: rootClass, children: [
@@ -541,10 +569,7 @@ function KV({
541
569
  /* @__PURE__ */ jsx3("span", { className: "detail-kv-value", children: String(value) })
542
570
  ] });
543
571
  }
544
- function PromptBlock({
545
- label,
546
- text
547
- }) {
572
+ function PromptBlock({ label, text }) {
548
573
  if (!text) return null;
549
574
  return /* @__PURE__ */ jsxs3("div", { children: [
550
575
  /* @__PURE__ */ jsx3("div", { className: "detail-section-label", children: label }),
@@ -591,37 +616,36 @@ function PromptToggle({
591
616
  });
592
617
  }
593
618
  return /* @__PURE__ */ jsxs3("div", { children: [
594
- /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 }, children: [
595
- /* @__PURE__ */ jsx3("div", { className: "detail-section-label", style: { marginBottom: 0 }, children: label }),
596
- /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
597
- /* @__PURE__ */ jsx3(
598
- "button",
599
- {
600
- onClick: () => setExpanded((prev) => !prev),
601
- title: expanded ? "Collapse prompt" : "Expand prompt",
602
- "aria-label": expanded ? "Collapse prompt" : "Expand prompt",
603
- className: "detail-prompt-expand-btn",
604
- children: expanded ? COLLAPSE_ICON : EXPAND_ICON
605
- }
606
- ),
607
- /* @__PURE__ */ jsx3(
608
- "button",
609
- {
610
- onClick: handleCopy,
611
- title: "Copy prompt",
612
- "aria-label": "Copy prompt",
613
- style: __spreadProps(__spreadValues({}, promptActionStyle), {
614
- color: copied ? "#10b981" : "#64748b"
615
- }),
616
- children: copied ? CHECK_ICON : COPY_ICON
617
- }
618
- ),
619
- canToggle && /* @__PURE__ */ jsxs3(
620
- "button",
621
- {
622
- onClick: () => setShowTemplate((prev) => !prev),
623
- style: promptActionStyle,
624
- children: [
619
+ /* @__PURE__ */ jsxs3(
620
+ "div",
621
+ {
622
+ style: { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 4 },
623
+ children: [
624
+ /* @__PURE__ */ jsx3("div", { className: "detail-section-label", style: { marginBottom: 0 }, children: label }),
625
+ /* @__PURE__ */ jsxs3("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
626
+ /* @__PURE__ */ jsx3(
627
+ "button",
628
+ {
629
+ onClick: () => setExpanded((prev) => !prev),
630
+ title: expanded ? "Collapse prompt" : "Expand prompt",
631
+ "aria-label": expanded ? "Collapse prompt" : "Expand prompt",
632
+ className: "detail-prompt-expand-btn",
633
+ children: expanded ? COLLAPSE_ICON : EXPAND_ICON
634
+ }
635
+ ),
636
+ /* @__PURE__ */ jsx3(
637
+ "button",
638
+ {
639
+ onClick: handleCopy,
640
+ title: "Copy prompt",
641
+ "aria-label": "Copy prompt",
642
+ style: __spreadProps(__spreadValues({}, promptActionStyle), {
643
+ color: copied ? "#10b981" : "#64748b"
644
+ }),
645
+ children: copied ? CHECK_ICON : COPY_ICON
646
+ }
647
+ ),
648
+ canToggle && /* @__PURE__ */ jsxs3("button", { onClick: () => setShowTemplate((prev) => !prev), style: promptActionStyle, children: [
625
649
  /* @__PURE__ */ jsx3(
626
650
  "span",
627
651
  {
@@ -652,11 +676,11 @@ function PromptToggle({
652
676
  }
653
677
  ),
654
678
  showTemplate ? "template" : "rendered"
655
- ]
656
- }
657
- )
658
- ] })
659
- ] }),
679
+ ] })
680
+ ] })
681
+ ]
682
+ }
683
+ ),
660
684
  /* @__PURE__ */ jsx3(
661
685
  "div",
662
686
  {
@@ -696,9 +720,27 @@ function PipeLLMSection({
696
720
  /* @__PURE__ */ jsx4(KV, { label: "Output Multiplicity", value: blueprint.output_multiplicity }),
697
721
  /* @__PURE__ */ jsx4(KV, { label: "Prompt Category", value: (_c = spec.prompt_blueprint) == null ? void 0 : _c.category }),
698
722
  hasImageRefs && /* @__PURE__ */ jsx4(KV, { label: "User Image Refs", value: `${spec.user_image_references.length} references` }),
699
- hasDocRefs && /* @__PURE__ */ jsx4(KV, { label: "User Document Refs", value: `${spec.user_document_references.length} references` }),
700
- hasSysImageRefs && /* @__PURE__ */ jsx4(KV, { label: "System Image Refs", value: `${spec.system_image_references.length} references` }),
701
- hasSysDocRefs && /* @__PURE__ */ jsx4(KV, { label: "System Document Refs", value: `${spec.system_document_references.length} references` }),
723
+ hasDocRefs && /* @__PURE__ */ jsx4(
724
+ KV,
725
+ {
726
+ label: "User Document Refs",
727
+ value: `${spec.user_document_references.length} references`
728
+ }
729
+ ),
730
+ hasSysImageRefs && /* @__PURE__ */ jsx4(
731
+ KV,
732
+ {
733
+ label: "System Image Refs",
734
+ value: `${spec.system_image_references.length} references`
735
+ }
736
+ ),
737
+ hasSysDocRefs && /* @__PURE__ */ jsx4(
738
+ KV,
739
+ {
740
+ label: "System Document Refs",
741
+ value: `${spec.system_document_references.length} references`
742
+ }
743
+ ),
702
744
  /* @__PURE__ */ jsx4(
703
745
  PromptToggle,
704
746
  {
@@ -755,7 +797,13 @@ function PipeImgGenSection({
755
797
  /* @__PURE__ */ jsx5(KV, { label: "Background", value: blueprint.background }),
756
798
  /* @__PURE__ */ jsx5(KV, { label: "Is Raw", value: blueprint.is_raw }),
757
799
  /* @__PURE__ */ jsx5(KV, { label: "Seed", value: blueprint.seed }),
758
- /* @__PURE__ */ jsx5(KV, { label: "Images", value: (_c = executionData == null ? void 0 : executionData.nb_images) != null ? _c : blueprint.output_multiplicity })
800
+ /* @__PURE__ */ jsx5(
801
+ KV,
802
+ {
803
+ label: "Images",
804
+ value: (_c = executionData == null ? void 0 : executionData.nb_images) != null ? _c : blueprint.output_multiplicity
805
+ }
806
+ )
759
807
  ] });
760
808
  }
761
809
  function ImgGenExecutionData(_props) {
@@ -846,7 +894,7 @@ function FieldBlock({ label, value }) {
846
894
  function ConstructFieldsBlock({
847
895
  blueprint,
848
896
  depth,
849
- resolvedFields
897
+ fieldResolutions
850
898
  }) {
851
899
  const leafFields = [];
852
900
  const nestedFields = [];
@@ -870,14 +918,13 @@ function ConstructFieldsBlock({
870
918
  return /* @__PURE__ */ jsx8("div", { style: indentStyle, children: /* @__PURE__ */ jsx8(KV, { label: name, value: display }) }, name);
871
919
  }),
872
920
  templateFields.map(([name, field]) => {
873
- var _a;
874
- const resolvedForField = resolvedFields == null ? void 0 : resolvedFields[name];
875
- const renderedForField = typeof resolvedForField === "string" ? resolvedForField : void 0;
921
+ var _a, _b;
922
+ const renderedForField = (_a = fieldResolutions == null ? void 0 : fieldResolutions[name]) == null ? void 0 : _a.rendered;
876
923
  return /* @__PURE__ */ jsx8("div", { style: indentStyle, children: /* @__PURE__ */ jsx8(
877
924
  PromptToggle,
878
925
  {
879
926
  label: `Template \u2014 ${name}`,
880
- templateText: (_a = field.template) != null ? _a : null,
927
+ templateText: (_b = field.template) != null ? _b : null,
881
928
  renderedText: renderedForField
882
929
  }
883
930
  ) }, name);
@@ -906,7 +953,7 @@ function ConstructFieldsBlock({
906
953
  {
907
954
  blueprint: field.nested,
908
955
  depth: depth + 1,
909
- resolvedFields: resolvedFields && typeof resolvedFields[name] === "object" && resolvedFields[name] !== null ? resolvedFields[name] : null
956
+ fieldResolutions: null
910
957
  }
911
958
  )
912
959
  ] }, name);
@@ -920,7 +967,7 @@ function PipeComposeSection({
920
967
  var _a;
921
968
  const renderedText = executionData == null ? void 0 : executionData.rendered_text;
922
969
  const composeMode = executionData == null ? void 0 : executionData.compose_mode;
923
- const resolvedFields = (_a = executionData == null ? void 0 : executionData.resolved_fields) != null ? _a : null;
970
+ const fieldResolutions = (_a = executionData == null ? void 0 : executionData.fields) != null ? _a : null;
924
971
  const constructBlueprint = blueprint.construct_blueprint;
925
972
  const hasConstruct = constructBlueprint !== null && Object.keys(constructBlueprint.fields).length > 0;
926
973
  return /* @__PURE__ */ jsxs8(Fragment5, { children: [
@@ -942,7 +989,7 @@ function PipeComposeSection({
942
989
  {
943
990
  blueprint: constructBlueprint,
944
991
  depth: 0,
945
- resolvedFields
992
+ fieldResolutions
946
993
  }
947
994
  )
948
995
  ] })
@@ -972,7 +1019,14 @@ function PipeConditionSection({
972
1019
  style: selectedOutcome === pipeCode ? { background: "rgba(80,250,123,0.08)" } : void 0,
973
1020
  children: [
974
1021
  /* @__PURE__ */ jsx9("span", { className: "detail-kv-key", children: outcome }),
975
- /* @__PURE__ */ jsx9("span", { className: "detail-kv-value", style: selectedOutcome === pipeCode ? { color: "#50FA7B" } : void 0, children: pipeCode })
1022
+ /* @__PURE__ */ jsx9(
1023
+ "span",
1024
+ {
1025
+ className: "detail-kv-value",
1026
+ style: selectedOutcome === pipeCode ? { color: "#50FA7B" } : void 0,
1027
+ children: pipeCode
1028
+ }
1029
+ )
976
1030
  ]
977
1031
  },
978
1032
  outcome
@@ -1103,8 +1157,20 @@ function PipeDetailPanel({ node, spec, onConceptClick }) {
1103
1157
  return /* @__PURE__ */ jsxs13(Fragment9, { children: [
1104
1158
  /* @__PURE__ */ jsxs13("div", { className: "detail-sticky-header", children: [
1105
1159
  /* @__PURE__ */ jsxs13("div", { className: "detail-header", children: [
1106
- /* @__PURE__ */ jsx13("span", { className: `detail-badge ${isController ? "detail-badge--controller" : "detail-badge--operator"}`, children: badge }),
1107
- /* @__PURE__ */ jsx13("span", { className: `detail-pipe-code ${isController ? "detail-pipe-code--controller" : ""}`, children: (_j = node.pipe_code) != null ? _j : "unknown" })
1160
+ /* @__PURE__ */ jsx13(
1161
+ "span",
1162
+ {
1163
+ className: `detail-badge ${isController ? "detail-badge--controller" : "detail-badge--operator"}`,
1164
+ children: badge
1165
+ }
1166
+ ),
1167
+ /* @__PURE__ */ jsx13(
1168
+ "span",
1169
+ {
1170
+ className: `detail-pipe-code ${isController ? "detail-pipe-code--controller" : ""}`,
1171
+ children: (_j = node.pipe_code) != null ? _j : "unknown"
1172
+ }
1173
+ )
1108
1174
  ] }),
1109
1175
  /* @__PURE__ */ jsxs13("div", { className: "detail-status", children: [
1110
1176
  /* @__PURE__ */ jsx13("span", { className: "detail-status-dot", style: { background: statusColor } }),
@@ -1161,7 +1227,14 @@ function PipeDetailPanel({ node, spec, onConceptClick }) {
1161
1227
  ] }),
1162
1228
  node.metrics && Object.keys(node.metrics).length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
1163
1229
  /* @__PURE__ */ jsx13("div", { className: "detail-section-label", children: "Metrics" }),
1164
- Object.entries(node.metrics).map(([key, value]) => /* @__PURE__ */ jsx13(KV, { label: key, value: typeof value === "number" ? value.toLocaleString() : String(value) }, key))
1230
+ Object.entries(node.metrics).map(([key, value]) => /* @__PURE__ */ jsx13(
1231
+ KV,
1232
+ {
1233
+ label: key,
1234
+ value: typeof value === "number" ? value.toLocaleString() : String(value)
1235
+ },
1236
+ key
1237
+ ))
1165
1238
  ] }),
1166
1239
  node.tags && Object.keys(node.tags).length > 0 && /* @__PURE__ */ jsxs13("div", { children: [
1167
1240
  /* @__PURE__ */ jsx13("div", { className: "detail-section-label", children: "Tags" }),
@@ -1241,7 +1314,14 @@ function GenericExecutionData({ data }) {
1241
1314
 
1242
1315
  // src/graph/react/detail/ConceptDetailPanel.tsx
1243
1316
  import { Fragment as Fragment10, jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
1244
- function ConceptDetailPanel({ concept, ioData, isDryRun, resolveStorageUrl }) {
1317
+ function ConceptDetailPanel({
1318
+ concept,
1319
+ ioData,
1320
+ isDryRun,
1321
+ resolveStorageUrl,
1322
+ canEmbedPdf,
1323
+ onOpenExternally
1324
+ }) {
1245
1325
  return /* @__PURE__ */ jsxs14(Fragment10, { children: [
1246
1326
  /* @__PURE__ */ jsxs14("div", { className: "detail-header", children: [
1247
1327
  /* @__PURE__ */ jsx14("span", { className: "detail-concept-code", children: concept.code }),
@@ -1258,7 +1338,15 @@ function ConceptDetailPanel({ concept, ioData, isDryRun, resolveStorageUrl }) {
1258
1338
  ] }) : /* @__PURE__ */ jsx14("div", { className: "detail-not-available", children: "Schema not available" }),
1259
1339
  ioData && !isDryRun && /* @__PURE__ */ jsxs14("div", { children: [
1260
1340
  /* @__PURE__ */ jsx14("div", { className: "detail-section-label", children: "Data" }),
1261
- /* @__PURE__ */ jsx14(StuffViewer, { stuff: toStuffViewerData(ioData), resolveStorageUrl })
1341
+ /* @__PURE__ */ jsx14(
1342
+ StuffViewer,
1343
+ {
1344
+ stuff: toStuffViewerData(ioData),
1345
+ resolveStorageUrl,
1346
+ canEmbedPdf,
1347
+ onOpenExternally
1348
+ }
1349
+ )
1262
1350
  ] })
1263
1351
  ] });
1264
1352
  }
@@ -1449,39 +1537,117 @@ function hydrateLabels(nodes) {
1449
1537
 
1450
1538
  // src/graph/react/viewer/GraphToolbar.tsx
1451
1539
  import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
1452
- var ARROW_RIGHT_ICON = /* @__PURE__ */ jsxs16("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1453
- /* @__PURE__ */ jsx16("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
1454
- /* @__PURE__ */ jsx16("polyline", { points: "12 5 19 12 12 19" })
1455
- ] });
1456
- var ARROW_DOWN_ICON = /* @__PURE__ */ jsxs16("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1457
- /* @__PURE__ */ jsx16("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
1458
- /* @__PURE__ */ jsx16("polyline", { points: "19 12 12 19 5 12" })
1459
- ] });
1460
- var MINUS_ICON = /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx16("line", { x1: "5", y1: "12", x2: "19", y2: "12" }) });
1461
- var PLUS_ICON = /* @__PURE__ */ jsxs16("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1462
- /* @__PURE__ */ jsx16("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
1463
- /* @__PURE__ */ jsx16("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
1464
- ] });
1465
- var FIT_VIEW_ICON = /* @__PURE__ */ jsxs16("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1466
- /* @__PURE__ */ jsx16("polyline", { points: "15 3 21 3 21 9" }),
1467
- /* @__PURE__ */ jsx16("polyline", { points: "9 21 3 21 3 15" }),
1468
- /* @__PURE__ */ jsx16("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
1469
- /* @__PURE__ */ jsx16("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
1470
- ] });
1471
- var BOXES_ICON = /* @__PURE__ */ jsxs16("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1472
- /* @__PURE__ */ jsx16("path", { d: "M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" }),
1473
- /* @__PURE__ */ jsx16("path", { d: "m7 16.5-4.74-2.85" }),
1474
- /* @__PURE__ */ jsx16("path", { d: "m7 16.5 5-3" }),
1475
- /* @__PURE__ */ jsx16("path", { d: "M7 16.5v5.17" }),
1476
- /* @__PURE__ */ jsx16("path", { d: "M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" }),
1477
- /* @__PURE__ */ jsx16("path", { d: "m17 16.5-5-3" }),
1478
- /* @__PURE__ */ jsx16("path", { d: "m17 16.5 4.74-2.85" }),
1479
- /* @__PURE__ */ jsx16("path", { d: "M17 16.5v5.17" }),
1480
- /* @__PURE__ */ jsx16("path", { d: "M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z" }),
1481
- /* @__PURE__ */ jsx16("path", { d: "M12 8 7.26 5.15" }),
1482
- /* @__PURE__ */ jsx16("path", { d: "m12 8 4.74-2.85" }),
1483
- /* @__PURE__ */ jsx16("path", { d: "M12 13.5V8" })
1484
- ] });
1540
+ var ARROW_RIGHT_ICON = /* @__PURE__ */ jsxs16(
1541
+ "svg",
1542
+ {
1543
+ viewBox: "0 0 24 24",
1544
+ width: "14",
1545
+ height: "14",
1546
+ fill: "none",
1547
+ stroke: "currentColor",
1548
+ strokeWidth: "2",
1549
+ strokeLinecap: "round",
1550
+ strokeLinejoin: "round",
1551
+ children: [
1552
+ /* @__PURE__ */ jsx16("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
1553
+ /* @__PURE__ */ jsx16("polyline", { points: "12 5 19 12 12 19" })
1554
+ ]
1555
+ }
1556
+ );
1557
+ var ARROW_DOWN_ICON = /* @__PURE__ */ jsxs16(
1558
+ "svg",
1559
+ {
1560
+ viewBox: "0 0 24 24",
1561
+ width: "14",
1562
+ height: "14",
1563
+ fill: "none",
1564
+ stroke: "currentColor",
1565
+ strokeWidth: "2",
1566
+ strokeLinecap: "round",
1567
+ strokeLinejoin: "round",
1568
+ children: [
1569
+ /* @__PURE__ */ jsx16("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
1570
+ /* @__PURE__ */ jsx16("polyline", { points: "19 12 12 19 5 12" })
1571
+ ]
1572
+ }
1573
+ );
1574
+ var MINUS_ICON = /* @__PURE__ */ jsx16(
1575
+ "svg",
1576
+ {
1577
+ viewBox: "0 0 24 24",
1578
+ width: "14",
1579
+ height: "14",
1580
+ fill: "none",
1581
+ stroke: "currentColor",
1582
+ strokeWidth: "2",
1583
+ strokeLinecap: "round",
1584
+ strokeLinejoin: "round",
1585
+ children: /* @__PURE__ */ jsx16("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
1586
+ }
1587
+ );
1588
+ var PLUS_ICON = /* @__PURE__ */ jsxs16(
1589
+ "svg",
1590
+ {
1591
+ viewBox: "0 0 24 24",
1592
+ width: "14",
1593
+ height: "14",
1594
+ fill: "none",
1595
+ stroke: "currentColor",
1596
+ strokeWidth: "2",
1597
+ strokeLinecap: "round",
1598
+ strokeLinejoin: "round",
1599
+ children: [
1600
+ /* @__PURE__ */ jsx16("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
1601
+ /* @__PURE__ */ jsx16("line", { x1: "5", y1: "12", x2: "19", y2: "12" })
1602
+ ]
1603
+ }
1604
+ );
1605
+ var FIT_VIEW_ICON = /* @__PURE__ */ jsxs16(
1606
+ "svg",
1607
+ {
1608
+ viewBox: "0 0 24 24",
1609
+ width: "14",
1610
+ height: "14",
1611
+ fill: "none",
1612
+ stroke: "currentColor",
1613
+ strokeWidth: "2",
1614
+ strokeLinecap: "round",
1615
+ strokeLinejoin: "round",
1616
+ children: [
1617
+ /* @__PURE__ */ jsx16("polyline", { points: "15 3 21 3 21 9" }),
1618
+ /* @__PURE__ */ jsx16("polyline", { points: "9 21 3 21 3 15" }),
1619
+ /* @__PURE__ */ jsx16("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
1620
+ /* @__PURE__ */ jsx16("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
1621
+ ]
1622
+ }
1623
+ );
1624
+ var BOXES_ICON = /* @__PURE__ */ jsxs16(
1625
+ "svg",
1626
+ {
1627
+ viewBox: "0 0 24 24",
1628
+ width: "14",
1629
+ height: "14",
1630
+ fill: "none",
1631
+ stroke: "currentColor",
1632
+ strokeWidth: "2",
1633
+ strokeLinecap: "round",
1634
+ strokeLinejoin: "round",
1635
+ children: [
1636
+ /* @__PURE__ */ jsx16("path", { d: "M2.97 12.92A2 2 0 0 0 2 14.63v3.24a2 2 0 0 0 .97 1.71l3 1.8a2 2 0 0 0 2.06 0L12 19v-5.5l-5-3-4.03 2.42Z" }),
1637
+ /* @__PURE__ */ jsx16("path", { d: "m7 16.5-4.74-2.85" }),
1638
+ /* @__PURE__ */ jsx16("path", { d: "m7 16.5 5-3" }),
1639
+ /* @__PURE__ */ jsx16("path", { d: "M7 16.5v5.17" }),
1640
+ /* @__PURE__ */ jsx16("path", { d: "M12 13.5V19l3.97 2.38a2 2 0 0 0 2.06 0l3-1.8a2 2 0 0 0 .97-1.71v-3.24a2 2 0 0 0-.97-1.71L17 10.5l-5 3Z" }),
1641
+ /* @__PURE__ */ jsx16("path", { d: "m17 16.5-5-3" }),
1642
+ /* @__PURE__ */ jsx16("path", { d: "m17 16.5 4.74-2.85" }),
1643
+ /* @__PURE__ */ jsx16("path", { d: "M17 16.5v5.17" }),
1644
+ /* @__PURE__ */ jsx16("path", { d: "M7.97 4.42A2 2 0 0 0 7 6.13v4.37l5 3 5-3V6.13a2 2 0 0 0-.97-1.71l-3-1.8a2 2 0 0 0-2.06 0l-3 1.8Z" }),
1645
+ /* @__PURE__ */ jsx16("path", { d: "M12 8 7.26 5.15" }),
1646
+ /* @__PURE__ */ jsx16("path", { d: "m12 8 4.74-2.85" }),
1647
+ /* @__PURE__ */ jsx16("path", { d: "M12 13.5V8" })
1648
+ ]
1649
+ }
1650
+ );
1485
1651
  function GraphToolbar({
1486
1652
  direction,
1487
1653
  onDirectionChange,
@@ -1495,71 +1661,64 @@ function GraphToolbar({
1495
1661
  const isVertical = direction === GRAPH_DIRECTION.TB || direction === GRAPH_DIRECTION.BT;
1496
1662
  const directionLabel = isVertical ? "Switch to horizontal layout" : "Switch to vertical layout";
1497
1663
  const controllersLabel = showControllers ? "Hide pipe controllers" : "Show pipe controllers \u2014 groups pipes by their controlling pipe";
1498
- return /* @__PURE__ */ jsxs16(
1499
- "div",
1500
- {
1501
- className: "graph-toolbar",
1502
- style: { right: `${rightOffset + 8}px` },
1503
- children: [
1504
- /* @__PURE__ */ jsx16(
1505
- "button",
1506
- {
1507
- type: "button",
1508
- className: "graph-toolbar-btn",
1509
- onClick: () => onDirectionChange(isVertical ? GRAPH_DIRECTION.LR : GRAPH_DIRECTION.TB),
1510
- title: directionLabel,
1511
- "aria-label": directionLabel,
1512
- children: isVertical ? ARROW_RIGHT_ICON : ARROW_DOWN_ICON
1513
- }
1514
- ),
1515
- /* @__PURE__ */ jsx16(
1516
- "button",
1517
- {
1518
- type: "button",
1519
- className: `graph-toolbar-btn${showControllers ? " graph-toolbar-btn--active" : ""}`,
1520
- onClick: () => onShowControllersChange(!showControllers),
1521
- title: controllersLabel,
1522
- "aria-label": controllersLabel,
1523
- children: BOXES_ICON
1524
- }
1525
- ),
1526
- (onZoomOut || onZoomIn || onFitView) && /* @__PURE__ */ jsx16("div", { className: "graph-toolbar-separator" }),
1527
- onZoomOut && /* @__PURE__ */ jsx16(
1528
- "button",
1529
- {
1530
- type: "button",
1531
- className: "graph-toolbar-btn",
1532
- onClick: onZoomOut,
1533
- title: "Zoom out",
1534
- "aria-label": "Zoom out",
1535
- children: MINUS_ICON
1536
- }
1537
- ),
1538
- onZoomIn && /* @__PURE__ */ jsx16(
1539
- "button",
1540
- {
1541
- type: "button",
1542
- className: "graph-toolbar-btn",
1543
- onClick: onZoomIn,
1544
- title: "Zoom in",
1545
- "aria-label": "Zoom in",
1546
- children: PLUS_ICON
1547
- }
1548
- ),
1549
- onFitView && /* @__PURE__ */ jsx16(
1550
- "button",
1551
- {
1552
- type: "button",
1553
- className: "graph-toolbar-btn",
1554
- onClick: onFitView,
1555
- title: "Fit view",
1556
- "aria-label": "Fit view",
1557
- children: FIT_VIEW_ICON
1558
- }
1559
- )
1560
- ]
1561
- }
1562
- );
1664
+ return /* @__PURE__ */ jsxs16("div", { className: "graph-toolbar", style: { right: `${rightOffset + 8}px` }, children: [
1665
+ /* @__PURE__ */ jsx16(
1666
+ "button",
1667
+ {
1668
+ type: "button",
1669
+ className: "graph-toolbar-btn",
1670
+ onClick: () => onDirectionChange(isVertical ? GRAPH_DIRECTION.LR : GRAPH_DIRECTION.TB),
1671
+ title: directionLabel,
1672
+ "aria-label": directionLabel,
1673
+ children: isVertical ? ARROW_RIGHT_ICON : ARROW_DOWN_ICON
1674
+ }
1675
+ ),
1676
+ /* @__PURE__ */ jsx16(
1677
+ "button",
1678
+ {
1679
+ type: "button",
1680
+ className: `graph-toolbar-btn${showControllers ? " graph-toolbar-btn--active" : ""}`,
1681
+ onClick: () => onShowControllersChange(!showControllers),
1682
+ title: controllersLabel,
1683
+ "aria-label": controllersLabel,
1684
+ children: BOXES_ICON
1685
+ }
1686
+ ),
1687
+ (onZoomOut || onZoomIn || onFitView) && /* @__PURE__ */ jsx16("div", { className: "graph-toolbar-separator" }),
1688
+ onZoomOut && /* @__PURE__ */ jsx16(
1689
+ "button",
1690
+ {
1691
+ type: "button",
1692
+ className: "graph-toolbar-btn",
1693
+ onClick: onZoomOut,
1694
+ title: "Zoom out",
1695
+ "aria-label": "Zoom out",
1696
+ children: MINUS_ICON
1697
+ }
1698
+ ),
1699
+ onZoomIn && /* @__PURE__ */ jsx16(
1700
+ "button",
1701
+ {
1702
+ type: "button",
1703
+ className: "graph-toolbar-btn",
1704
+ onClick: onZoomIn,
1705
+ title: "Zoom in",
1706
+ "aria-label": "Zoom in",
1707
+ children: PLUS_ICON
1708
+ }
1709
+ ),
1710
+ onFitView && /* @__PURE__ */ jsx16(
1711
+ "button",
1712
+ {
1713
+ type: "button",
1714
+ className: "graph-toolbar-btn",
1715
+ onClick: onFitView,
1716
+ title: "Fit view",
1717
+ "aria-label": "Fit view",
1718
+ children: FIT_VIEW_ICON
1719
+ }
1720
+ )
1721
+ ] });
1563
1722
  }
1564
1723
 
1565
1724
  // src/graph/react/nodes/controller/ControllerGroupNode.tsx
@@ -1752,7 +1911,9 @@ var nodeTypes = __spreadProps(__spreadValues({}, controllerNodeTypes), {
1752
1911
  function StuffNodeDetail({
1753
1912
  stuffData,
1754
1913
  graphspec,
1755
- resolveStorageUrl
1914
+ resolveStorageUrl,
1915
+ canEmbedPdf,
1916
+ onOpenExternally
1756
1917
  }) {
1757
1918
  const conceptInfo = stuffData.concept && graphspec ? resolveConceptRef(graphspec, stuffData.concept) : void 0;
1758
1919
  return /* @__PURE__ */ jsx20(Fragment12, { children: conceptInfo ? /* @__PURE__ */ jsx20(
@@ -1760,11 +1921,21 @@ function StuffNodeDetail({
1760
1921
  {
1761
1922
  concept: conceptInfo,
1762
1923
  ioData: stuffData,
1763
- resolveStorageUrl
1924
+ resolveStorageUrl,
1925
+ canEmbedPdf,
1926
+ onOpenExternally
1764
1927
  }
1765
1928
  ) : (
1766
1929
  /* Fallback: just show the StuffViewer if no concept info */
1767
- /* @__PURE__ */ jsx20(StuffViewer, { stuff: stuffData, resolveStorageUrl })
1930
+ /* @__PURE__ */ jsx20(
1931
+ StuffViewer,
1932
+ {
1933
+ stuff: stuffData,
1934
+ resolveStorageUrl,
1935
+ canEmbedPdf,
1936
+ onOpenExternally
1937
+ }
1938
+ )
1768
1939
  ) });
1769
1940
  }
1770
1941
  function cloneCachedNodes(nodes) {
@@ -1804,7 +1975,9 @@ function GraphViewer(props) {
1804
1975
  onNodeSelect,
1805
1976
  onPaneClick,
1806
1977
  renderDetailExtra,
1807
- resolveStorageUrl
1978
+ resolveStorageUrl,
1979
+ canEmbedPdf,
1980
+ onOpenExternally
1808
1981
  } = props;
1809
1982
  const [direction, setDirection] = React7.useState(
1810
1983
  () => {
@@ -2067,11 +2240,24 @@ function GraphViewer(props) {
2067
2240
  } else if (nodeData.isStuff && graphspec) {
2068
2241
  const digest = stuffDigestFromId(node.id);
2069
2242
  const sd = findStuffDataByDigest(graphspec, digest);
2070
- setDetailSelection({ kind: "stuff", nodeId: node.id, nodeData, stuffData: sd != null ? sd : void 0 });
2243
+ setDetailSelection({
2244
+ kind: "stuff",
2245
+ nodeId: node.id,
2246
+ nodeData,
2247
+ stuffData: sd != null ? sd : void 0
2248
+ });
2071
2249
  }
2072
2250
  setNodes((nds) => nds.map((n) => __spreadProps(__spreadValues({}, n), { selected: n.id === node.id })));
2073
2251
  },
2074
- [setNodes, onNavigateToPipe, onNodeSelect, onStuffNodeClick, graphspec, detailSelection, conceptOverride]
2252
+ [
2253
+ setNodes,
2254
+ onNavigateToPipe,
2255
+ onNodeSelect,
2256
+ onStuffNodeClick,
2257
+ graphspec,
2258
+ detailSelection,
2259
+ conceptOverride
2260
+ ]
2075
2261
  );
2076
2262
  const onInit = React7.useCallback(
2077
2263
  (reactFlowInstance) => {
@@ -2115,6 +2301,7 @@ function GraphViewer(props) {
2115
2301
  panOnScroll: true,
2116
2302
  minZoom: 0.1,
2117
2303
  proOptions: { hideAttribution: true },
2304
+ panActivationKeyCode: null,
2118
2305
  children: /* @__PURE__ */ jsx20(
2119
2306
  Background,
2120
2307
  {
@@ -2147,7 +2334,9 @@ function GraphViewer(props) {
2147
2334
  {
2148
2335
  stuffData: detailSelection.stuffData,
2149
2336
  graphspec,
2150
- resolveStorageUrl
2337
+ resolveStorageUrl,
2338
+ canEmbedPdf,
2339
+ onOpenExternally
2151
2340
  }
2152
2341
  ) : null,
2153
2342
  renderDetailExtra && detailSelection && !conceptOverride && renderDetailExtra(detailSelection.nodeId, detailSelection.nodeData)