@tangle-network/agent-app 0.42.5 → 0.42.6

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 (48) hide show
  1. package/dist/{DesignCanvas-AOIVN3SJ.js → DesignCanvas-GUTCY763.js} +2 -2
  2. package/dist/{DesignCanvasEditor-QQNAZRJQ.js → DesignCanvasEditor-ZO4V7H6A.js} +4 -4
  3. package/dist/{TimelineEditor-Z7C6BFP5.js → TimelineEditor-SNOAGBV6.js} +2 -2
  4. package/dist/brand/index.d.ts +35 -0
  5. package/dist/brand/index.js +89 -0
  6. package/dist/brand/index.js.map +1 -0
  7. package/dist/{chunk-YYYXGLLQ.js → chunk-6JYDS34Y.js} +184 -54
  8. package/dist/chunk-6JYDS34Y.js.map +1 -0
  9. package/dist/{chunk-FJUOBNIY.js → chunk-A5Z53E3A.js} +3 -3
  10. package/dist/{chunk-V5XZKHCL.js → chunk-AFQXKJAE.js} +132 -2
  11. package/dist/chunk-AFQXKJAE.js.map +1 -0
  12. package/dist/{chunk-S6WS2B32.js → chunk-EX3LD5G6.js} +322 -122
  13. package/dist/chunk-EX3LD5G6.js.map +1 -0
  14. package/dist/{chunk-DTS5TZRN.js → chunk-MFI4ZM7W.js} +2 -2
  15. package/dist/chunk-MFI4ZM7W.js.map +1 -0
  16. package/dist/{chunk-YEWTVDDT.js → chunk-OVUQNKLM.js} +379 -323
  17. package/dist/chunk-OVUQNKLM.js.map +1 -0
  18. package/dist/chunk-ZN5J47UX.js +1 -0
  19. package/dist/chunk-ZN5J47UX.js.map +1 -0
  20. package/dist/{command-stack-CkjelfK_.d.ts → command-stack-CcWi_2bN.d.ts} +15 -0
  21. package/dist/design-canvas-react/engine.d.ts +2 -2
  22. package/dist/design-canvas-react/engine.js +5 -6
  23. package/dist/design-canvas-react/index.d.ts +61 -8
  24. package/dist/design-canvas-react/index.js +10 -9
  25. package/dist/design-canvas-react/lazy.d.ts +2 -2
  26. package/dist/design-canvas-react/lazy.js +1 -1
  27. package/dist/{lazy-BHHqS8-j.d.ts → lazy-2XBVp1_e.d.ts} +6 -2
  28. package/dist/sequences-react/index.d.ts +94 -2
  29. package/dist/sequences-react/index.js +12 -2
  30. package/dist/sequences-react/index.js.map +1 -1
  31. package/dist/studio/index.d.ts +1 -1
  32. package/dist/studio/index.js +1 -1
  33. package/dist/studio-react/index.js +1 -1
  34. package/dist/web-react/index.d.ts +57 -6
  35. package/dist/web-react/index.js +361 -200
  36. package/dist/web-react/index.js.map +1 -1
  37. package/package.json +14 -9
  38. package/dist/chunk-DTS5TZRN.js.map +0 -1
  39. package/dist/chunk-S6WS2B32.js.map +0 -1
  40. package/dist/chunk-SQV7NUEM.js +0 -136
  41. package/dist/chunk-SQV7NUEM.js.map +0 -1
  42. package/dist/chunk-V5XZKHCL.js.map +0 -1
  43. package/dist/chunk-YEWTVDDT.js.map +0 -1
  44. package/dist/chunk-YYYXGLLQ.js.map +0 -1
  45. /package/dist/{DesignCanvas-AOIVN3SJ.js.map → DesignCanvas-GUTCY763.js.map} +0 -0
  46. /package/dist/{DesignCanvasEditor-QQNAZRJQ.js.map → DesignCanvasEditor-ZO4V7H6A.js.map} +0 -0
  47. /package/dist/{TimelineEditor-Z7C6BFP5.js.map → TimelineEditor-SNOAGBV6.js.map} +0 -0
  48. /package/dist/{chunk-FJUOBNIY.js.map → chunk-A5Z53E3A.js.map} +0 -0
@@ -1,8 +1,12 @@
1
1
  import {
2
2
  BleedTrimOverlay,
3
- DesignCanvas
4
- } from "./chunk-YEWTVDDT.js";
3
+ BrandKnot,
4
+ DesignCanvas,
5
+ PlusGlyph,
6
+ ShapesGlyph
7
+ } from "./chunk-OVUQNKLM.js";
5
8
  import {
9
+ DEFAULT_INSERT_TEMPLATES,
6
10
  collectGridTargets,
7
11
  createSnapEngine,
8
12
  createZoomPanMath,
@@ -12,7 +16,7 @@ import {
12
16
  isExportHiddenNodeName,
13
17
  marqueeSelect,
14
18
  resolveExportParams
15
- } from "./chunk-V5XZKHCL.js";
19
+ } from "./chunk-AFQXKJAE.js";
16
20
  import {
17
21
  addElementCommand,
18
22
  createSceneCommandStack,
@@ -123,6 +127,82 @@ function downloadDataUrl(dataUrl, filename) {
123
127
  globalThis.document.body.removeChild(a);
124
128
  }
125
129
 
130
+ // src/design-canvas-react/components/CanvasEmptyState.tsx
131
+ import { jsx, jsxs } from "react/jsx-runtime";
132
+ function SparkleGlyph({ className }) {
133
+ return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M12 3v3m0 12v3M3 12h3m12 0h3M5.6 5.6l2.1 2.1m8.6 8.6 2.1 2.1m0-12.8-2.1 2.1M7.7 16.3l-2.1 2.1" }) });
134
+ }
135
+ function CanvasEmptyState({
136
+ onStartTemplate,
137
+ onAddElement,
138
+ onAskAgent,
139
+ title = "Start your design",
140
+ subtitle = "Drop in a template, add an element by hand, or let the agent draft it for you.",
141
+ className
142
+ }) {
143
+ const doors = [
144
+ {
145
+ key: "template",
146
+ label: "Start with a template",
147
+ hint: "A headline, shape, or block to build on",
148
+ Icon: ShapesGlyph,
149
+ onClick: onStartTemplate
150
+ },
151
+ {
152
+ key: "element",
153
+ label: "Add an element",
154
+ hint: "Place text on the page and edit it",
155
+ Icon: PlusGlyph,
156
+ onClick: onAddElement
157
+ }
158
+ ];
159
+ if (onAskAgent) {
160
+ doors.push({
161
+ key: "agent",
162
+ label: "Ask the agent",
163
+ hint: "Describe what you want made",
164
+ Icon: SparkleGlyph,
165
+ onClick: onAskAgent
166
+ });
167
+ }
168
+ return (
169
+ // Overlay is non-interactive so empty-space clicks reach the canvas; the
170
+ // centered card re-enables pointer events for its own controls.
171
+ /* @__PURE__ */ jsx(
172
+ "div",
173
+ {
174
+ className: `pointer-events-none absolute inset-0 z-20 flex items-center justify-center p-4 ${className ?? ""}`,
175
+ role: "group",
176
+ "aria-label": "Start your design",
177
+ children: /* @__PURE__ */ jsxs("div", { className: "pointer-events-auto flex w-full max-w-lg flex-col items-center gap-5 rounded-xl border border-[var(--border-default)] bg-[var(--bg-input)]/95 px-6 py-7 text-center shadow-xl backdrop-blur sm:px-8", children: [
178
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 text-[var(--text-muted)]", children: [
179
+ /* @__PURE__ */ jsx(BrandKnot, { size: 22, className: "shrink-0" }),
180
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium uppercase tracking-[0.14em]", children: "Tangle Design" })
181
+ ] }),
182
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
183
+ /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-[var(--text-primary)]", children: title }),
184
+ /* @__PURE__ */ jsx("p", { className: "text-sm leading-5 text-[var(--text-secondary)]", children: subtitle })
185
+ ] }),
186
+ /* @__PURE__ */ jsx("div", { className: "grid w-full gap-2 sm:grid-cols-3", children: doors.map(({ key, label, hint, Icon, onClick }) => /* @__PURE__ */ jsxs(
187
+ "button",
188
+ {
189
+ type: "button",
190
+ onClick,
191
+ className: "group flex min-h-[44px] flex-col items-center gap-2 rounded-lg border border-[var(--border-default)] bg-[hsl(var(--card))] px-3 py-4 text-center transition-colors hover:border-[var(--brand-primary)] focus:outline-none focus-visible:ring-2 focus-visible:ring-[hsl(var(--ring))] focus-visible:ring-offset-1 focus-visible:ring-offset-[var(--bg-input)]",
192
+ children: [
193
+ /* @__PURE__ */ jsx("span", { className: "flex h-9 w-9 items-center justify-center rounded-full bg-[var(--brand-primary)]/10 text-[var(--brand-primary)] transition-colors group-hover:bg-[var(--brand-primary)]/15", children: /* @__PURE__ */ jsx(Icon, { className: "h-4 w-4" }) }),
194
+ /* @__PURE__ */ jsx("span", { className: "text-[13px] font-medium text-[var(--text-primary)]", children: label }),
195
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] leading-4 text-[var(--text-muted)]", children: hint })
196
+ ]
197
+ },
198
+ key
199
+ )) })
200
+ ] })
201
+ }
202
+ )
203
+ );
204
+ }
205
+
126
206
  // src/design-canvas-react/components/ElementNode.tsx
127
207
  import { memo, useEffect, useRef, useState } from "react";
128
208
  import { Group, Rect, Ellipse, Line, Text, Image as KonvaImage } from "react-konva";
@@ -229,7 +309,7 @@ function gridVisible(gridSize, zoom, minScreenPx = 4) {
229
309
  }
230
310
 
231
311
  // src/design-canvas-react/components/ElementNode.tsx
232
- import { jsx } from "react/jsx-runtime";
312
+ import { jsx as jsx2 } from "react/jsx-runtime";
233
313
  var IMAGE_CACHE_MAX = 256;
234
314
  var imageCache = /* @__PURE__ */ new Map();
235
315
  function imageCacheSet(src, img) {
@@ -262,19 +342,19 @@ function ElementNodeImpl(props) {
262
342
  if (!element.visible) return null;
263
343
  switch (element.kind) {
264
344
  case "rect":
265
- return /* @__PURE__ */ jsx(RectNode, { ...props, element });
345
+ return /* @__PURE__ */ jsx2(RectNode, { ...props, element });
266
346
  case "ellipse":
267
- return /* @__PURE__ */ jsx(EllipseNode, { ...props, element });
347
+ return /* @__PURE__ */ jsx2(EllipseNode, { ...props, element });
268
348
  case "line":
269
- return /* @__PURE__ */ jsx(LineNode, { ...props, element });
349
+ return /* @__PURE__ */ jsx2(LineNode, { ...props, element });
270
350
  case "text":
271
- return /* @__PURE__ */ jsx(TextNode, { ...props, element });
351
+ return /* @__PURE__ */ jsx2(TextNode, { ...props, element });
272
352
  case "image":
273
- return /* @__PURE__ */ jsx(ImageNode, { ...props, element });
353
+ return /* @__PURE__ */ jsx2(ImageNode, { ...props, element });
274
354
  case "video":
275
- return /* @__PURE__ */ jsx(VideoNode, { ...props, element });
355
+ return /* @__PURE__ */ jsx2(VideoNode, { ...props, element });
276
356
  case "group":
277
- return /* @__PURE__ */ jsx(GroupNode, { ...props, element });
357
+ return /* @__PURE__ */ jsx2(GroupNode, { ...props, element });
278
358
  }
279
359
  }
280
360
  var ElementNode = memo(ElementNodeImpl);
@@ -322,7 +402,7 @@ function RectNode({ element, ...rest }) {
322
402
  const { dragging, ...drag } = useDragBindings({ element, ...rest }, element.x, element.y);
323
403
  const ref = useRef(null);
324
404
  useNodeCache(ref, rest.isSelected, dragging, rest.zoom, element);
325
- return /* @__PURE__ */ jsx(
405
+ return /* @__PURE__ */ jsx2(
326
406
  Rect,
327
407
  {
328
408
  ref,
@@ -346,7 +426,7 @@ function EllipseNode({ element, ...rest }) {
346
426
  const { dragging, ...drag } = useDragBindings({ element, ...rest }, element.x, element.y);
347
427
  const ref = useRef(null);
348
428
  useNodeCache(ref, rest.isSelected, dragging, rest.zoom, element);
349
- return /* @__PURE__ */ jsx(
429
+ return /* @__PURE__ */ jsx2(
350
430
  Ellipse,
351
431
  {
352
432
  ref,
@@ -368,7 +448,7 @@ function LineNode({ element, ...rest }) {
368
448
  const { dragging, ...drag } = useDragBindings({ element, ...rest }, element.x, element.y);
369
449
  const ref = useRef(null);
370
450
  useNodeCache(ref, rest.isSelected, dragging, rest.zoom, element);
371
- return /* @__PURE__ */ jsx(
451
+ return /* @__PURE__ */ jsx2(
372
452
  Line,
373
453
  {
374
454
  ref,
@@ -396,7 +476,7 @@ function TextNode({ element, ...rest }) {
396
476
  const ref = useRef(null);
397
477
  useNodeCache(ref, rest.isSelected, dragging, rest.zoom, element);
398
478
  const { fontStyle, fontWeight } = FONT_STYLE_MAP[element.fontStyle];
399
- return /* @__PURE__ */ jsx(
479
+ return /* @__PURE__ */ jsx2(
400
480
  Text,
401
481
  {
402
482
  ref,
@@ -432,7 +512,7 @@ function ImageNode({ element, ...rest }) {
432
512
  `${imgReady}:${element.src}:${element.width}x${element.height}:${element.fit}`
433
513
  );
434
514
  if (!img || !img.complete || img.naturalWidth === 0) {
435
- return /* @__PURE__ */ jsx(
515
+ return /* @__PURE__ */ jsx2(
436
516
  Rect,
437
517
  {
438
518
  ref,
@@ -476,7 +556,7 @@ function ImageNode({ element, ...rest }) {
476
556
  };
477
557
  }
478
558
  }
479
- return /* @__PURE__ */ jsx(
559
+ return /* @__PURE__ */ jsx2(
480
560
  KonvaImage,
481
561
  {
482
562
  ref,
@@ -507,7 +587,7 @@ function VideoNode({ element, ...rest }) {
507
587
  `${posterReady}:${element.posterSrc ?? ""}:${element.width}x${element.height}`
508
588
  );
509
589
  if (!element.posterSrc || !img || !img.complete || img.naturalWidth === 0) {
510
- return /* @__PURE__ */ jsx(
590
+ return /* @__PURE__ */ jsx2(
511
591
  Rect,
512
592
  {
513
593
  ref,
@@ -525,7 +605,7 @@ function VideoNode({ element, ...rest }) {
525
605
  }
526
606
  );
527
607
  }
528
- return /* @__PURE__ */ jsx(
608
+ return /* @__PURE__ */ jsx2(
529
609
  KonvaImage,
530
610
  {
531
611
  ref,
@@ -544,7 +624,7 @@ function VideoNode({ element, ...rest }) {
544
624
  function GroupNode({ element, ...rest }) {
545
625
  const { dragging: _dragging, ...drag } = useDragBindings({ element, ...rest }, element.x, element.y);
546
626
  void _dragging;
547
- return /* @__PURE__ */ jsx(
627
+ return /* @__PURE__ */ jsx2(
548
628
  Group,
549
629
  {
550
630
  name: element.id,
@@ -553,7 +633,7 @@ function GroupNode({ element, ...rest }) {
553
633
  rotation: element.rotation,
554
634
  opacity: element.opacity,
555
635
  ...drag,
556
- children: element.children.map((child) => /* @__PURE__ */ jsx(ElementNode, { ...rest, element: child }, child.id))
636
+ children: element.children.map((child) => /* @__PURE__ */ jsx2(ElementNode, { ...rest, element: child }, child.id))
557
637
  }
558
638
  );
559
639
  }
@@ -561,7 +641,7 @@ function GroupNode({ element, ...rest }) {
561
641
  // src/design-canvas-react/components/SelectionLayer.tsx
562
642
  import { useEffect as useEffect2, useRef as useRef2 } from "react";
563
643
  import { Layer, Transformer } from "react-konva";
564
- import { jsx as jsx2 } from "react/jsx-runtime";
644
+ import { jsx as jsx3 } from "react/jsx-runtime";
565
645
  var MIN_SIZE = 4;
566
646
  function SelectionLayer({
567
647
  stageRef,
@@ -612,7 +692,7 @@ function SelectionLayer({
612
692
  // regions have no shapes, so pointer hits fall through to the content layer.
613
693
  // Export exclusion is unaffected: export.ts hides nodes by the 'overlay:'
614
694
  // name prefix, not by `listening` (see export-math.isExportHiddenNodeName).
615
- /* @__PURE__ */ jsx2(Layer, { name: "overlay:selection", listening: canWrite, children: /* @__PURE__ */ jsx2(
695
+ /* @__PURE__ */ jsx3(Layer, { name: "overlay:selection", listening: canWrite, children: /* @__PURE__ */ jsx3(
616
696
  Transformer,
617
697
  {
618
698
  ref: trRef,
@@ -725,7 +805,7 @@ function bakeNodeToAttrs(node, element) {
725
805
 
726
806
  // src/design-canvas-react/components/GridLayer.tsx
727
807
  import { Layer as Layer2, Group as Group2, Shape } from "react-konva";
728
- import { jsx as jsx3 } from "react/jsx-runtime";
808
+ import { jsx as jsx4 } from "react/jsx-runtime";
729
809
  function gridVerticalLines(pageWidth, gridSize) {
730
810
  const out = [];
731
811
  if (gridSize <= 0) return out;
@@ -766,7 +846,7 @@ function GridLayer({
766
846
  ctx.stroke();
767
847
  void shape;
768
848
  };
769
- return /* @__PURE__ */ jsx3(Layer2, { name: "overlay:grid", listening: false, children: /* @__PURE__ */ jsx3(Group2, { x: panX, y: panY, scaleX: zoom, scaleY: zoom, children: /* @__PURE__ */ jsx3(
849
+ return /* @__PURE__ */ jsx4(Layer2, { name: "overlay:grid", listening: false, children: /* @__PURE__ */ jsx4(Group2, { x: panX, y: panY, scaleX: zoom, scaleY: zoom, children: /* @__PURE__ */ jsx4(
770
850
  Shape,
771
851
  {
772
852
  name: "overlay:grid-shape",
@@ -782,7 +862,7 @@ function GridLayer({
782
862
 
783
863
  // src/design-canvas-react/components/SnapGuidesOverlay.tsx
784
864
  import { Layer as Layer3, Line as Line2 } from "react-konva";
785
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
865
+ import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
786
866
  function kindColors(render) {
787
867
  return {
788
868
  "grid": render.snapGrid,
@@ -804,8 +884,8 @@ function SnapGuidesOverlay({
804
884
  if (!activeVertical && !activeHorizontal) return null;
805
885
  const KIND_COLOR = kindColors(render);
806
886
  const strokeWidth = 1 / zoom;
807
- return /* @__PURE__ */ jsxs(Layer3, { name: "overlay:snap", listening: false, children: [
808
- activeVertical && /* @__PURE__ */ jsx4(
887
+ return /* @__PURE__ */ jsxs2(Layer3, { name: "overlay:snap", listening: false, children: [
888
+ activeVertical && /* @__PURE__ */ jsx5(
809
889
  Line2,
810
890
  {
811
891
  name: "overlay:snap-vertical",
@@ -817,7 +897,7 @@ function SnapGuidesOverlay({
817
897
  perfectDrawEnabled: false
818
898
  }
819
899
  ),
820
- activeHorizontal && /* @__PURE__ */ jsx4(
900
+ activeHorizontal && /* @__PURE__ */ jsx5(
821
901
  Line2,
822
902
  {
823
903
  name: "overlay:snap-horizontal",
@@ -834,7 +914,7 @@ function SnapGuidesOverlay({
834
914
 
835
915
  // src/design-canvas-react/components/InlineTextEditor.tsx
836
916
  import { useEffect as useEffect3, useRef as useRef3 } from "react";
837
- import { jsx as jsx5 } from "react/jsx-runtime";
917
+ import { jsx as jsx6 } from "react/jsx-runtime";
838
918
  function InlineTextEditor({
839
919
  element,
840
920
  zoom,
@@ -877,7 +957,7 @@ function InlineTextEditor({
877
957
  }
878
958
  const fontWeight = element.fontStyle.includes("bold") ? "bold" : "normal";
879
959
  const fontStyle = element.fontStyle.includes("italic") ? "italic" : "normal";
880
- return /* @__PURE__ */ jsx5(
960
+ return /* @__PURE__ */ jsx6(
881
961
  "textarea",
882
962
  {
883
963
  ref,
@@ -919,7 +999,7 @@ function InlineTextEditor({
919
999
  }
920
1000
 
921
1001
  // src/design-canvas-react/components/Workspace.tsx
922
- import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
1002
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
923
1003
  var SNAP_THRESHOLD_SCREEN_PX = 8;
924
1004
  var DUPLICATE_OFFSET = 10;
925
1005
  var ZOOM_FACTOR_WHEEL = 0.998;
@@ -938,7 +1018,9 @@ function WorkspaceView({
938
1018
  onExportRef,
939
1019
  fitOnMount = true,
940
1020
  onReady,
941
- render = lightTheme.canvasRender
1021
+ render = lightTheme.canvasRender,
1022
+ showEmptyState = true,
1023
+ onAskAgent
942
1024
  }) {
943
1025
  const [, setTick] = useState2(0);
944
1026
  const forceRender = useCallback(() => setTick((t) => t + 1), []);
@@ -1202,6 +1284,43 @@ function WorkspaceView({
1202
1284
  if (!canWrite || entries.length === 0) return;
1203
1285
  await persist(multiSetAttrsCommand(entries));
1204
1286
  }
1287
+ async function handleStartTemplate() {
1288
+ if (!canWrite) return;
1289
+ const template = DEFAULT_INSERT_TEMPLATES[0];
1290
+ if (!template) return;
1291
+ const ops = template.build({ pageId: activePageId, width: activePage.width, height: activePage.height });
1292
+ for (const op of ops) {
1293
+ if (op.type === "add_element") {
1294
+ await persist(addElementCommand({ pageId: op.pageId, element: op.element }));
1295
+ }
1296
+ }
1297
+ }
1298
+ async function handleAddElement() {
1299
+ if (!canWrite) return;
1300
+ const width = Math.min(420, Math.round(activePage.width * 0.6)) || 320;
1301
+ const element = {
1302
+ id: crypto.randomUUID(),
1303
+ kind: "text",
1304
+ name: "Text",
1305
+ x: Math.max(0, Math.round((activePage.width - width) / 2)),
1306
+ y: Math.max(0, Math.round(activePage.height / 2 - 24)),
1307
+ rotation: 0,
1308
+ opacity: 1,
1309
+ locked: false,
1310
+ visible: true,
1311
+ width,
1312
+ text: "Double-click to edit",
1313
+ fontFamily: "Inter",
1314
+ fontSize: 32,
1315
+ fontStyle: "normal",
1316
+ fill: "#111827",
1317
+ align: "left",
1318
+ lineHeight: 1.2,
1319
+ letterSpacing: 0
1320
+ };
1321
+ await persist(addElementCommand({ pageId: activePageId, element }));
1322
+ stack.setView({ selectedElementIds: [element.id] });
1323
+ }
1205
1324
  function handleKeyDown(e) {
1206
1325
  if (e.key === " ") {
1207
1326
  e.preventDefault();
@@ -1407,7 +1526,7 @@ function WorkspaceView({
1407
1526
  (el) => pinned.has(el.id) || boundsIntersect(elementAabb(el), pageRect)
1408
1527
  );
1409
1528
  }, [activePage.elements, activePage.width, activePage.height, selectedElementIds, editingElementId]);
1410
- return /* @__PURE__ */ jsxs2(
1529
+ return /* @__PURE__ */ jsxs3(
1411
1530
  "div",
1412
1531
  {
1413
1532
  className: `design-canvas-workspace relative overflow-hidden bg-[var(--canvas-backdrop,#1a1a1a)] outline-none ${className ?? ""}`,
@@ -1419,9 +1538,9 @@ function WorkspaceView({
1419
1538
  onPointerUp: handlePointerUp,
1420
1539
  onKeyDown: handleKeyDown,
1421
1540
  onKeyUp: handleKeyUp,
1422
- style: { cursor: spaceHeldRef.current ? "grab" : "default" },
1541
+ style: { cursor: spaceHeldRef.current ? "grab" : "default", touchAction: "none" },
1423
1542
  children: [
1424
- /* @__PURE__ */ jsxs2(
1543
+ /* @__PURE__ */ jsxs3(
1425
1544
  Stage,
1426
1545
  {
1427
1546
  ref: stageRef,
@@ -1430,7 +1549,7 @@ function WorkspaceView({
1430
1549
  pixelRatio: dpr,
1431
1550
  listening: true,
1432
1551
  children: [
1433
- gridEnabled && /* @__PURE__ */ jsx6(
1552
+ gridEnabled && /* @__PURE__ */ jsx7(
1434
1553
  GridLayer,
1435
1554
  {
1436
1555
  pageWidth: activePage.width,
@@ -1442,8 +1561,8 @@ function WorkspaceView({
1442
1561
  color: render.grid
1443
1562
  }
1444
1563
  ),
1445
- /* @__PURE__ */ jsx6(Layer4, { children: /* @__PURE__ */ jsxs2(Group3, { x: panX, y: panY, scaleX: zoom, scaleY: zoom, children: [
1446
- /* @__PURE__ */ jsx6(
1564
+ /* @__PURE__ */ jsx7(Layer4, { children: /* @__PURE__ */ jsxs3(Group3, { x: panX, y: panY, scaleX: zoom, scaleY: zoom, children: [
1565
+ /* @__PURE__ */ jsx7(
1447
1566
  Rect2,
1448
1567
  {
1449
1568
  name: "page-background",
@@ -1458,14 +1577,14 @@ function WorkspaceView({
1458
1577
  listening: false
1459
1578
  }
1460
1579
  ),
1461
- /* @__PURE__ */ jsx6(
1580
+ /* @__PURE__ */ jsx7(
1462
1581
  Group3,
1463
1582
  {
1464
1583
  clipX: 0,
1465
1584
  clipY: 0,
1466
1585
  clipWidth: activePage.width,
1467
1586
  clipHeight: activePage.height,
1468
- children: visibleElements.map((element) => /* @__PURE__ */ jsx6(
1587
+ children: visibleElements.map((element) => /* @__PURE__ */ jsx7(
1469
1588
  ElementNode,
1470
1589
  {
1471
1590
  element,
@@ -1483,7 +1602,7 @@ function WorkspaceView({
1483
1602
  }
1484
1603
  )
1485
1604
  ] }) }),
1486
- (activeVerticalGuide || activeHorizontalGuide) && /* @__PURE__ */ jsx6(Layer4, { children: /* @__PURE__ */ jsx6(Group3, { x: panX, y: panY, scaleX: zoom, scaleY: zoom, children: /* @__PURE__ */ jsx6(
1605
+ (activeVerticalGuide || activeHorizontalGuide) && /* @__PURE__ */ jsx7(Layer4, { children: /* @__PURE__ */ jsx7(Group3, { x: panX, y: panY, scaleX: zoom, scaleY: zoom, children: /* @__PURE__ */ jsx7(
1487
1606
  SnapGuidesOverlay,
1488
1607
  {
1489
1608
  pageWidth: activePage.width,
@@ -1494,7 +1613,7 @@ function WorkspaceView({
1494
1613
  render
1495
1614
  }
1496
1615
  ) }) }),
1497
- /* @__PURE__ */ jsx6(
1616
+ /* @__PURE__ */ jsx7(
1498
1617
  SelectionLayer,
1499
1618
  {
1500
1619
  stageRef,
@@ -1509,12 +1628,12 @@ function WorkspaceView({
1509
1628
  ]
1510
1629
  }
1511
1630
  ),
1512
- showBleed && activePage.bleed && /* @__PURE__ */ jsx6(
1631
+ showBleed && activePage.bleed && /* @__PURE__ */ jsx7(
1513
1632
  "div",
1514
1633
  {
1515
1634
  className: "pointer-events-none absolute",
1516
1635
  style: { left: pageScreenX, top: pageScreenY, width: pageScreenW, height: pageScreenH },
1517
- children: /* @__PURE__ */ jsx6(
1636
+ children: /* @__PURE__ */ jsx7(
1518
1637
  BleedTrimOverlay,
1519
1638
  {
1520
1639
  pageWidthPx: pageScreenW,
@@ -1529,7 +1648,7 @@ function WorkspaceView({
1529
1648
  )
1530
1649
  }
1531
1650
  ),
1532
- normalizedMarquee && /* @__PURE__ */ jsx6(
1651
+ normalizedMarquee && /* @__PURE__ */ jsx7(
1533
1652
  "div",
1534
1653
  {
1535
1654
  className: "pointer-events-none absolute border border-blue-400 bg-blue-400/10",
@@ -1541,7 +1660,7 @@ function WorkspaceView({
1541
1660
  }
1542
1661
  }
1543
1662
  ),
1544
- editingTextElement && /* @__PURE__ */ jsx6(
1663
+ editingTextElement && /* @__PURE__ */ jsx7(
1545
1664
  InlineTextEditor,
1546
1665
  {
1547
1666
  element: editingTextElement,
@@ -1551,7 +1670,15 @@ function WorkspaceView({
1551
1670
  onCommit: handleTextCommit,
1552
1671
  onCancel: handleTextCancel
1553
1672
  }
1554
- )
1673
+ ),
1674
+ showEmptyState && canWrite && activePage.elements.length === 0 && !editingElementId ? /* @__PURE__ */ jsx7(
1675
+ CanvasEmptyState,
1676
+ {
1677
+ onStartTemplate: () => void handleStartTemplate(),
1678
+ onAddElement: () => void handleAddElement(),
1679
+ onAskAgent
1680
+ }
1681
+ ) : null
1555
1682
  ]
1556
1683
  }
1557
1684
  );
@@ -1578,7 +1705,7 @@ function Workspace(props) {
1578
1705
  const state = stackRef.current.getState();
1579
1706
  const activePage = state.document.pages.find((p) => p.id === state.activePageId) ?? state.document.pages[0];
1580
1707
  if (!activePage) return null;
1581
- return /* @__PURE__ */ jsx6(
1708
+ return /* @__PURE__ */ jsx7(
1582
1709
  WorkspaceView,
1583
1710
  {
1584
1711
  stack: stackRef.current,
@@ -1593,7 +1720,7 @@ function Workspace(props) {
1593
1720
  }
1594
1721
 
1595
1722
  // src/design-canvas-react/components/DesignCanvasEditor.tsx
1596
- import { jsx as jsx7 } from "react/jsx-runtime";
1723
+ import { jsx as jsx8 } from "react/jsx-runtime";
1597
1724
  var THUMBNAIL_HEIGHT_PX = 96;
1598
1725
  var thumbnailCache = /* @__PURE__ */ new Map();
1599
1726
  var THUMBNAIL_CACHE_LIMIT = 200;
@@ -1730,13 +1857,13 @@ function paintElements(Konva, parent, elements) {
1730
1857
  }
1731
1858
  }
1732
1859
  function DesignCanvasEditor(props) {
1733
- return /* @__PURE__ */ jsx7(
1860
+ return /* @__PURE__ */ jsx8(
1734
1861
  DesignCanvas,
1735
1862
  {
1736
1863
  ...props,
1737
1864
  renderWorkspace: (ctx) => {
1738
1865
  if (!ctx.activePage) return null;
1739
- return /* @__PURE__ */ jsx7(
1866
+ return /* @__PURE__ */ jsx8(
1740
1867
  WorkspaceView,
1741
1868
  {
1742
1869
  stack: ctx.stack,
@@ -1749,7 +1876,9 @@ function DesignCanvasEditor(props) {
1749
1876
  onExportRef: ctx.onExportRef,
1750
1877
  fitOnMount: ctx.fitOnMount,
1751
1878
  onReady: ctx.onReady,
1752
- render: ctx.render
1879
+ render: ctx.render,
1880
+ showEmptyState: ctx.showEmptyState,
1881
+ onAskAgent: ctx.onAskAgent
1753
1882
  }
1754
1883
  );
1755
1884
  },
@@ -1762,6 +1891,7 @@ export {
1762
1891
  exportPageDataUrl,
1763
1892
  exportDocumentJson,
1764
1893
  downloadDataUrl,
1894
+ CanvasEmptyState,
1765
1895
  bakeRectTransform,
1766
1896
  bakeLineTransform,
1767
1897
  bakeTextTransform,
@@ -1772,4 +1902,4 @@ export {
1772
1902
  Workspace,
1773
1903
  DesignCanvasEditor
1774
1904
  };
1775
- //# sourceMappingURL=chunk-YYYXGLLQ.js.map
1905
+ //# sourceMappingURL=chunk-6JYDS34Y.js.map