@tangle-network/agent-app 0.23.0 → 0.25.0

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.
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  DesignCanvas,
3
3
  DesignCanvas_default
4
- } from "./chunk-2W4YCAFH.js";
4
+ } from "./chunk-LPAVBGVY.js";
5
5
  import "./chunk-JZAJE3JL.js";
6
6
  export {
7
7
  DesignCanvas,
8
8
  DesignCanvas_default as default
9
9
  };
10
- //# sourceMappingURL=DesignCanvas-JTSAL6KX.js.map
10
+ //# sourceMappingURL=DesignCanvas-MA5EH324.js.map
@@ -0,0 +1,9 @@
1
+ import {
2
+ DesignCanvasEditor
3
+ } from "./chunk-FSUR2752.js";
4
+ import "./chunk-LPAVBGVY.js";
5
+ import "./chunk-JZAJE3JL.js";
6
+ export {
7
+ DesignCanvasEditor
8
+ };
9
+ //# sourceMappingURL=DesignCanvasEditor-YLCO7I5I.js.map
@@ -8,11 +8,14 @@ import {
8
8
  multiSetAttrsCommand,
9
9
  setAttrsCommand,
10
10
  ungroupElementCommand
11
- } from "./chunk-2W4YCAFH.js";
11
+ } from "./chunk-LPAVBGVY.js";
12
12
  import {
13
+ SCENE_SCHEMA_VERSION,
14
+ bleedAwareExportBounds,
13
15
  boundsIntersect,
14
16
  elementAabb,
15
- findElement
17
+ findElement,
18
+ scaleForPreset
16
19
  } from "./chunk-JZAJE3JL.js";
17
20
 
18
21
  // src/design-canvas-react/components/Workspace.tsx
@@ -26,6 +29,121 @@ import {
26
29
  } from "react";
27
30
  import { Stage, Layer as Layer4, Rect as Rect2, Group as Group2 } from "react-konva";
28
31
 
32
+ // src/design-canvas-react/export-math.ts
33
+ function isExportHiddenNodeName(name) {
34
+ return name.startsWith("overlay:") || name === "Transformer";
35
+ }
36
+ function resolveExportParams(page, opts) {
37
+ const includeBleed = opts.preset !== void 0 ? opts.preset.includeBleed : opts.includeBleed ?? false;
38
+ const cropRect = bleedAwareExportBounds(page, includeBleed);
39
+ const pixelRatio = opts.preset !== void 0 ? scaleForPreset(opts.preset, cropRect) : opts.pixelRatio ?? 1;
40
+ const format = opts.preset !== void 0 ? opts.preset.format : opts.format;
41
+ const mimeType = format === "jpeg" ? "image/jpeg" : "image/png";
42
+ return {
43
+ cropRect,
44
+ pixelRatio,
45
+ mimeType,
46
+ quality: format === "jpeg" ? 0.92 : void 0
47
+ };
48
+ }
49
+ function identifyTaintedSrc(imageSrcs) {
50
+ for (const { src } of imageSrcs) {
51
+ if (isCrossOriginSrc(src)) return src;
52
+ }
53
+ return null;
54
+ }
55
+ function isCrossOriginSrc(src) {
56
+ return /^https?:\/\//i.test(src);
57
+ }
58
+ function documentCropToStageCoords(cropRect, stageScale, stageX, stageY) {
59
+ return {
60
+ x: stageX + cropRect.x * stageScale,
61
+ y: stageY + cropRect.y * stageScale,
62
+ width: cropRect.width * stageScale,
63
+ height: cropRect.height * stageScale
64
+ };
65
+ }
66
+
67
+ // src/design-canvas-react/export.ts
68
+ async function exportPageDataUrl(stage, page, opts) {
69
+ const { cropRect, pixelRatio, mimeType, quality } = resolveExportParams(page, opts);
70
+ const imageSrcs = collectImageSrcs(stage);
71
+ const hiddenNodes = [];
72
+ for (const layer of stage.getLayers()) {
73
+ for (const node of layer.getChildren()) {
74
+ const name = node.name();
75
+ if (isExportHiddenNodeName(name) && node.visible()) {
76
+ node.visible(false);
77
+ hiddenNodes.push(node);
78
+ }
79
+ }
80
+ }
81
+ const stageScale = stage.scaleX();
82
+ const stageCrop = documentCropToStageCoords(cropRect, stageScale, stage.x(), stage.y());
83
+ let dataUrl;
84
+ try {
85
+ dataUrl = stage.toDataURL({
86
+ mimeType,
87
+ ...quality !== void 0 ? { quality } : {},
88
+ pixelRatio,
89
+ x: stageCrop.x,
90
+ y: stageCrop.y,
91
+ width: stageCrop.width,
92
+ height: stageCrop.height
93
+ });
94
+ } catch (err) {
95
+ for (const node of hiddenNodes) {
96
+ node.visible(true);
97
+ }
98
+ if (err instanceof Error && err.name === "SecurityError") {
99
+ const taintedSrc = identifyTaintedSrc(imageSrcs);
100
+ if (taintedSrc !== null) {
101
+ throw new Error(
102
+ `Export failed: image source is CORS-tainted and cannot be read by the canvas. Offending src: "${taintedSrc}". Ensure the image is served with Access-Control-Allow-Origin or use a proxied /api/ path.`
103
+ );
104
+ }
105
+ throw new Error(
106
+ `Export failed: a canvas SecurityError occurred but no cross-origin image src could be identified. The stage may contain a tainted video or image loaded without CORS headers.`
107
+ );
108
+ }
109
+ throw err;
110
+ }
111
+ for (const node of hiddenNodes) {
112
+ node.visible(true);
113
+ }
114
+ return dataUrl;
115
+ }
116
+ function collectImageSrcs(stage) {
117
+ const result = [];
118
+ for (const layer of stage.getLayers()) {
119
+ for (const node of layer.getChildren()) {
120
+ const src = node.getAttr("src");
121
+ if (typeof src === "string" && src.length > 0) {
122
+ result.push({ name: node.name(), src });
123
+ }
124
+ }
125
+ }
126
+ return result;
127
+ }
128
+ function exportDocumentJson(document) {
129
+ if (document.schemaVersion !== SCENE_SCHEMA_VERSION) {
130
+ throw new Error(
131
+ `exportDocumentJson: document schemaVersion is ${document.schemaVersion}, expected ${SCENE_SCHEMA_VERSION} \u2014 upgrade the document before exporting`
132
+ );
133
+ }
134
+ return JSON.stringify(document, null, 2);
135
+ }
136
+ function downloadDataUrl(dataUrl, filename) {
137
+ if (typeof globalThis.document === "undefined") return;
138
+ const a = globalThis.document.createElement("a");
139
+ a.href = dataUrl;
140
+ a.download = filename;
141
+ a.style.display = "none";
142
+ globalThis.document.body.appendChild(a);
143
+ a.click();
144
+ globalThis.document.body.removeChild(a);
145
+ }
146
+
29
147
  // src/design-canvas-react/engine/snap.ts
30
148
  var KIND_PRIORITY = {
31
149
  "guide": 0,
@@ -310,8 +428,8 @@ function normalizeMarquee(startX, startY, endX, endY) {
310
428
  };
311
429
  }
312
430
  function computeTextOverlayPosition(input) {
313
- const left = input.panX + input.elementX * input.zoom + input.stageLeft;
314
- const top = input.panY + input.elementY * input.zoom + input.stageTop;
431
+ const left = input.panX + input.elementX * input.zoom;
432
+ const top = input.panY + input.elementY * input.zoom;
315
433
  return {
316
434
  left,
317
435
  top,
@@ -883,7 +1001,6 @@ function InlineTextEditor({
883
1001
  zoom,
884
1002
  panX,
885
1003
  panY,
886
- stageRect,
887
1004
  onCommit,
888
1005
  onCancel
889
1006
  }) {
@@ -897,8 +1014,6 @@ function InlineTextEditor({
897
1014
  zoom,
898
1015
  panX,
899
1016
  panY,
900
- stageLeft: stageRect.left,
901
- stageTop: stageRect.top,
902
1017
  elementFontSize: element.fontSize
903
1018
  });
904
1019
  useEffect3(() => {
@@ -945,8 +1060,11 @@ function InlineTextEditor({
945
1060
  lineHeight: element.lineHeight,
946
1061
  letterSpacing: element.letterSpacing * zoom,
947
1062
  color: element.fill,
948
- background: "rgba(255,255,255,0.95)",
949
- border: "2px solid #3b82f6",
1063
+ // Neutral token surface rather than a forced white: a white fill makes
1064
+ // light text invisible while editing. The token surface stays legible
1065
+ // for any text color and matches the editor chrome.
1066
+ background: "var(--bg-input)",
1067
+ border: "2px solid var(--brand-primary)",
950
1068
  borderRadius: 2,
951
1069
  padding: 2,
952
1070
  resize: "none",
@@ -973,12 +1091,12 @@ function WorkspaceView({
973
1091
  canWrite,
974
1092
  onApplyOperations,
975
1093
  onSelectionChange,
976
- renderAgentPanel,
977
- renderSidePanel,
978
1094
  className,
979
1095
  stack,
980
1096
  activePage,
981
1097
  onFitRef,
1098
+ onExport,
1099
+ onExportRef,
982
1100
  fitOnMount = true,
983
1101
  onReady
984
1102
  }) {
@@ -1024,6 +1142,20 @@ function WorkspaceView({
1024
1142
  if (onFitRef.current !== null) onFitRef.current = null;
1025
1143
  };
1026
1144
  });
1145
+ useEffect4(() => {
1146
+ if (!onExportRef || !onExport) return;
1147
+ onExportRef.current = ({ format, pixelRatio }) => {
1148
+ const stage = stageRef.current;
1149
+ if (!stage) return;
1150
+ void (async () => {
1151
+ const dataUrl = await exportPageDataUrl(stage, activePage, { format, pixelRatio });
1152
+ await onExport({ pageId: activePageId, format, dataUrl, pixelRatio });
1153
+ })();
1154
+ };
1155
+ return () => {
1156
+ if (onExportRef.current !== null) onExportRef.current = null;
1157
+ };
1158
+ });
1027
1159
  const gestureRef = useRef4("idle");
1028
1160
  const panOriginRef = useRef4({ screenX: 0, screenY: 0, panX: 0, panY: 0 });
1029
1161
  const [marquee, setMarquee] = useState2(NO_MARQUEE);
@@ -1378,7 +1510,6 @@ function WorkspaceView({
1378
1510
  [selectedElementIds, activePage]
1379
1511
  );
1380
1512
  const editingTextElement = editingElementId ? findElement(activePage, editingElementId)?.element ?? null : null;
1381
- const stageRect = containerRef.current?.getBoundingClientRect() ?? { left: 0, top: 0 };
1382
1513
  const dpr = typeof window !== "undefined" ? window.devicePixelRatio : 1;
1383
1514
  const pageScreenX = panX;
1384
1515
  const pageScreenY = panY;
@@ -1390,7 +1521,7 @@ function WorkspaceView({
1390
1521
  return /* @__PURE__ */ jsxs3(
1391
1522
  "div",
1392
1523
  {
1393
- className: `design-canvas-workspace relative overflow-hidden bg-[#1a1a1a] outline-none ${className ?? ""}`,
1524
+ className: `design-canvas-workspace relative overflow-hidden bg-[var(--canvas-backdrop,#1a1a1a)] outline-none ${className ?? ""}`,
1394
1525
  ref: containerRef,
1395
1526
  tabIndex: 0,
1396
1527
  onWheel: handleWheel,
@@ -1401,7 +1532,6 @@ function WorkspaceView({
1401
1532
  onKeyUp: handleKeyUp,
1402
1533
  style: { cursor: spaceHeldRef.current ? "grab" : "default" },
1403
1534
  children: [
1404
- renderSidePanel && /* @__PURE__ */ jsx6("div", { className: "absolute left-0 top-0 bottom-0 z-20 w-60 pointer-events-auto", children: renderSidePanel() }),
1405
1535
  /* @__PURE__ */ jsxs3(
1406
1536
  Stage,
1407
1537
  {
@@ -1523,12 +1653,10 @@ function WorkspaceView({
1523
1653
  zoom,
1524
1654
  panX,
1525
1655
  panY,
1526
- stageRect: { left: stageRect.left, top: stageRect.top },
1527
1656
  onCommit: handleTextCommit,
1528
1657
  onCancel: handleTextCancel
1529
1658
  }
1530
- ),
1531
- renderAgentPanel && /* @__PURE__ */ jsx6("div", { className: "absolute right-0 top-0 bottom-0 z-20 w-80 pointer-events-auto", children: renderAgentPanel({ selectedElements, activePageId }) })
1659
+ )
1532
1660
  ]
1533
1661
  }
1534
1662
  );
@@ -1563,8 +1691,6 @@ function Workspace(props) {
1563
1691
  canWrite: props.canWrite,
1564
1692
  onApplyOperations: props.onApplyOperations,
1565
1693
  onSelectionChange: props.onSelectionChange,
1566
- renderAgentPanel: props.renderAgentPanel,
1567
- renderSidePanel: props.renderSidePanel,
1568
1694
  className: props.className
1569
1695
  }
1570
1696
  );
@@ -1722,9 +1848,9 @@ function DesignCanvasEditor(props) {
1722
1848
  canWrite: ctx.canWrite,
1723
1849
  onApplyOperations: props.onApplyOperations,
1724
1850
  onSelectionChange: props.onSelectionChange,
1725
- renderAgentPanel: props.renderAgentPanel,
1726
- renderSidePanel: props.renderSidePanel,
1727
1851
  onFitRef: ctx.onFitRef,
1852
+ onExport: props.onExport,
1853
+ onExportRef: ctx.onExportRef,
1728
1854
  fitOnMount: ctx.fitOnMount,
1729
1855
  onReady: ctx.onReady
1730
1856
  }
@@ -1742,6 +1868,14 @@ export {
1742
1868
  nudgeDelta,
1743
1869
  DUPLICATE_OFFSET,
1744
1870
  createZoomPanMath,
1871
+ isExportHiddenNodeName,
1872
+ resolveExportParams,
1873
+ identifyTaintedSrc,
1874
+ isCrossOriginSrc,
1875
+ documentCropToStageCoords,
1876
+ exportPageDataUrl,
1877
+ exportDocumentJson,
1878
+ downloadDataUrl,
1745
1879
  bakeRectTransform,
1746
1880
  bakeLineTransform,
1747
1881
  bakeTextTransform,
@@ -1752,4 +1886,4 @@ export {
1752
1886
  Workspace,
1753
1887
  DesignCanvasEditor
1754
1888
  };
1755
- //# sourceMappingURL=chunk-NSKJFV4Y.js.map
1889
+ //# sourceMappingURL=chunk-FSUR2752.js.map