@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.
- package/dist/{DesignCanvas-JTSAL6KX.js → DesignCanvas-MA5EH324.js} +2 -2
- package/dist/DesignCanvasEditor-YLCO7I5I.js +9 -0
- package/dist/{chunk-NSKJFV4Y.js → chunk-FSUR2752.js} +156 -22
- package/dist/chunk-FSUR2752.js.map +1 -0
- package/dist/{chunk-2W4YCAFH.js → chunk-LPAVBGVY.js} +485 -174
- package/dist/chunk-LPAVBGVY.js.map +1 -0
- package/dist/design-canvas-react/index.d.ts +42 -5
- package/dist/design-canvas-react/index.js +60 -124
- package/dist/design-canvas-react/index.js.map +1 -1
- package/package.json +1 -6
- package/dist/DesignCanvasEditor-YPVETLZG.js +0 -9
- package/dist/chunk-2W4YCAFH.js.map +0 -1
- package/dist/chunk-NSKJFV4Y.js.map +0 -1
- /package/dist/{DesignCanvas-JTSAL6KX.js.map → DesignCanvas-MA5EH324.js.map} +0 -0
- /package/dist/{DesignCanvasEditor-YPVETLZG.js.map → DesignCanvasEditor-YLCO7I5I.js.map} +0 -0
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
} from "./chunk-JZAJE3JL.js";
|
|
10
10
|
|
|
11
11
|
// src/design-canvas-react/components/DesignCanvas.tsx
|
|
12
|
-
import { useCallback as useCallback2, useEffect as
|
|
12
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useMemo, useRef as useRef5, useState as useState5, useSyncExternalStore } from "react";
|
|
13
13
|
|
|
14
14
|
// src/design-canvas-react/engine/command-stack.ts
|
|
15
15
|
var SCENE_COMMAND_HISTORY_LIMIT = 200;
|
|
16
|
-
function createSceneCommandStack(
|
|
16
|
+
function createSceneCommandStack(document2, activePageId) {
|
|
17
17
|
let state = {
|
|
18
|
-
document,
|
|
18
|
+
document: document2,
|
|
19
19
|
activePageId,
|
|
20
20
|
selectedElementIds: [],
|
|
21
21
|
zoom: 1,
|
|
@@ -862,6 +862,16 @@ var DuplicateGlyph = glyph(
|
|
|
862
862
|
var ZoomFitGlyph = glyph(
|
|
863
863
|
/* @__PURE__ */ jsx2(Fragment2, { children: /* @__PURE__ */ jsx2("path", { d: "M15 3h6v6M14 10l6.1-6.1M9 21H3v-6M10 14l-6.1 6.1" }) })
|
|
864
864
|
);
|
|
865
|
+
var ExportGlyph = glyph(
|
|
866
|
+
/* @__PURE__ */ jsx2(Fragment2, { children: /* @__PURE__ */ jsx2("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3" }) })
|
|
867
|
+
);
|
|
868
|
+
var ShapesGlyph = glyph(
|
|
869
|
+
/* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
870
|
+
/* @__PURE__ */ jsx2("rect", { x: "3", y: "13", width: "8", height: "8", rx: "1" }),
|
|
871
|
+
/* @__PURE__ */ jsx2("circle", { cx: "17", cy: "17", r: "4" }),
|
|
872
|
+
/* @__PURE__ */ jsx2("path", { d: "M8.5 3 13 11H4z" })
|
|
873
|
+
] })
|
|
874
|
+
);
|
|
865
875
|
|
|
866
876
|
// src/design-canvas-react/components/PagesStrip.tsx
|
|
867
877
|
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
@@ -1263,11 +1273,54 @@ function VerticalRuler({ pageHeight, zoom, scrollTop, guides, onGuidesChange })
|
|
|
1263
1273
|
}
|
|
1264
1274
|
|
|
1265
1275
|
// src/design-canvas-react/components/Toolbar.tsx
|
|
1266
|
-
import { useState as useState3 } from "react";
|
|
1276
|
+
import { useEffect as useEffect2, useRef as useRef3, useState as useState3 } from "react";
|
|
1267
1277
|
import { Fragment as Fragment4, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1278
|
+
var FONT_FAMILIES = [
|
|
1279
|
+
"Inter",
|
|
1280
|
+
"Arial",
|
|
1281
|
+
"Helvetica",
|
|
1282
|
+
"Verdana",
|
|
1283
|
+
"Tahoma",
|
|
1284
|
+
"Trebuchet MS",
|
|
1285
|
+
"Times New Roman",
|
|
1286
|
+
"Georgia",
|
|
1287
|
+
"Garamond",
|
|
1288
|
+
"Courier New",
|
|
1289
|
+
"Brush Script MT",
|
|
1290
|
+
"Impact"
|
|
1291
|
+
];
|
|
1268
1292
|
var BTN2 = "flex h-7 w-7 items-center justify-center rounded border border-[var(--border-default)] text-[var(--text-secondary)] transition hover:text-[var(--text-primary)] disabled:cursor-default disabled:opacity-40";
|
|
1269
1293
|
var BTN_ACTIVE = `${BTN2} border-[var(--brand-primary)] text-[var(--brand-primary)] hover:text-[var(--brand-primary)]`;
|
|
1270
|
-
var SEP = /* @__PURE__ */ jsx5("div", { className: "mx-1 h-5 w-px bg-[var(--border-default)]" });
|
|
1294
|
+
var SEP = /* @__PURE__ */ jsx5("div", { className: "mx-1 h-5 w-px shrink-0 bg-[var(--border-default)]" });
|
|
1295
|
+
var POPOVER_PANEL = "absolute top-full left-0 z-50 mt-1 flex flex-col rounded border border-[var(--border-default)] bg-[var(--bg-input)] shadow-lg";
|
|
1296
|
+
function Popover({
|
|
1297
|
+
open,
|
|
1298
|
+
onClose,
|
|
1299
|
+
trigger,
|
|
1300
|
+
children
|
|
1301
|
+
}) {
|
|
1302
|
+
const ref = useRef3(null);
|
|
1303
|
+
useEffect2(() => {
|
|
1304
|
+
if (!open) return;
|
|
1305
|
+
function onDocPointer(event) {
|
|
1306
|
+
if (ref.current && !ref.current.contains(event.target)) onClose();
|
|
1307
|
+
}
|
|
1308
|
+
function onKey(event) {
|
|
1309
|
+
if (event.key === "Escape") onClose();
|
|
1310
|
+
}
|
|
1311
|
+
document.addEventListener("pointerdown", onDocPointer);
|
|
1312
|
+
document.addEventListener("keydown", onKey);
|
|
1313
|
+
return () => {
|
|
1314
|
+
document.removeEventListener("pointerdown", onDocPointer);
|
|
1315
|
+
document.removeEventListener("keydown", onKey);
|
|
1316
|
+
};
|
|
1317
|
+
}, [open, onClose]);
|
|
1318
|
+
return /* @__PURE__ */ jsxs5("div", { ref, className: "relative", children: [
|
|
1319
|
+
trigger,
|
|
1320
|
+
open ? children : null
|
|
1321
|
+
] });
|
|
1322
|
+
}
|
|
1323
|
+
var FIELD_LABEL = "text-[9px] uppercase tracking-wide text-[var(--text-muted)]";
|
|
1271
1324
|
function NumberInput({
|
|
1272
1325
|
label,
|
|
1273
1326
|
value,
|
|
@@ -1283,7 +1336,7 @@ function NumberInput({
|
|
|
1283
1336
|
setRaw(null);
|
|
1284
1337
|
}
|
|
1285
1338
|
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1286
|
-
/* @__PURE__ */ jsx5("span", { className:
|
|
1339
|
+
/* @__PURE__ */ jsx5("span", { className: FIELD_LABEL, children: label }),
|
|
1287
1340
|
/* @__PURE__ */ jsx5(
|
|
1288
1341
|
"input",
|
|
1289
1342
|
{
|
|
@@ -1302,16 +1355,170 @@ function NumberInput({
|
|
|
1302
1355
|
)
|
|
1303
1356
|
] });
|
|
1304
1357
|
}
|
|
1305
|
-
function
|
|
1306
|
-
|
|
1307
|
-
|
|
1358
|
+
function SelectControl({
|
|
1359
|
+
label,
|
|
1360
|
+
value,
|
|
1361
|
+
options,
|
|
1362
|
+
disabled,
|
|
1363
|
+
onChange,
|
|
1364
|
+
buttonClassName = "w-24"
|
|
1365
|
+
}) {
|
|
1366
|
+
const [open, setOpen] = useState3(false);
|
|
1367
|
+
const current = options.find((o) => o.value === value);
|
|
1368
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1369
|
+
/* @__PURE__ */ jsx5("span", { className: FIELD_LABEL, children: label }),
|
|
1308
1370
|
/* @__PURE__ */ jsx5(
|
|
1309
|
-
|
|
1371
|
+
Popover,
|
|
1310
1372
|
{
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1373
|
+
open,
|
|
1374
|
+
onClose: () => setOpen(false),
|
|
1375
|
+
trigger: /* @__PURE__ */ jsxs5(
|
|
1376
|
+
"button",
|
|
1377
|
+
{
|
|
1378
|
+
type: "button",
|
|
1379
|
+
disabled,
|
|
1380
|
+
"aria-haspopup": "listbox",
|
|
1381
|
+
"aria-expanded": open,
|
|
1382
|
+
onClick: () => setOpen((v) => !v),
|
|
1383
|
+
className: `${buttonClassName} flex items-center justify-between gap-1 rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-2 py-0.5 text-left text-[12px] text-[var(--text-primary)] outline-none hover:border-[var(--brand-primary)] disabled:cursor-default disabled:opacity-40`,
|
|
1384
|
+
children: [
|
|
1385
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: current?.label ?? value }),
|
|
1386
|
+
/* @__PURE__ */ jsx5("span", { className: "text-[8px] text-[var(--text-muted)]", children: "\u25BE" })
|
|
1387
|
+
]
|
|
1388
|
+
}
|
|
1389
|
+
),
|
|
1390
|
+
children: /* @__PURE__ */ jsx5("div", { role: "listbox", className: `${POPOVER_PANEL} max-h-64 w-44 overflow-y-auto py-1`, children: options.map((opt) => /* @__PURE__ */ jsx5(
|
|
1391
|
+
"button",
|
|
1392
|
+
{
|
|
1393
|
+
type: "button",
|
|
1394
|
+
role: "option",
|
|
1395
|
+
"aria-selected": opt.value === value,
|
|
1396
|
+
onClick: () => {
|
|
1397
|
+
onChange(opt.value);
|
|
1398
|
+
setOpen(false);
|
|
1399
|
+
},
|
|
1400
|
+
className: `px-3 py-1 text-left text-[12px] hover:bg-[var(--brand-primary)]/10 ${opt.value === value ? "text-[var(--brand-primary)]" : "text-[var(--text-primary)]"}`,
|
|
1401
|
+
children: opt.label
|
|
1402
|
+
},
|
|
1403
|
+
opt.value
|
|
1404
|
+
)) })
|
|
1405
|
+
}
|
|
1406
|
+
)
|
|
1407
|
+
] });
|
|
1408
|
+
}
|
|
1409
|
+
function FontPicker({
|
|
1410
|
+
value,
|
|
1411
|
+
disabled,
|
|
1412
|
+
onChange
|
|
1413
|
+
}) {
|
|
1414
|
+
const [open, setOpen] = useState3(false);
|
|
1415
|
+
const [query, setQuery] = useState3("");
|
|
1416
|
+
const families = FONT_FAMILIES.includes(value) ? [...FONT_FAMILIES] : [value, ...FONT_FAMILIES];
|
|
1417
|
+
const filtered = families.filter((f) => f.toLowerCase().includes(query.trim().toLowerCase()));
|
|
1418
|
+
return /* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1419
|
+
/* @__PURE__ */ jsx5("span", { className: FIELD_LABEL, children: "Font" }),
|
|
1420
|
+
/* @__PURE__ */ jsx5(
|
|
1421
|
+
Popover,
|
|
1422
|
+
{
|
|
1423
|
+
open,
|
|
1424
|
+
onClose: () => {
|
|
1425
|
+
setOpen(false);
|
|
1426
|
+
setQuery("");
|
|
1427
|
+
},
|
|
1428
|
+
trigger: /* @__PURE__ */ jsxs5(
|
|
1429
|
+
"button",
|
|
1430
|
+
{
|
|
1431
|
+
type: "button",
|
|
1432
|
+
disabled,
|
|
1433
|
+
"aria-haspopup": "listbox",
|
|
1434
|
+
"aria-expanded": open,
|
|
1435
|
+
"aria-label": "Font family",
|
|
1436
|
+
onClick: () => setOpen((v) => !v),
|
|
1437
|
+
className: "flex w-28 items-center justify-between gap-1 rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-2 py-0.5 text-left text-[12px] text-[var(--text-primary)] outline-none hover:border-[var(--brand-primary)] disabled:cursor-default disabled:opacity-40",
|
|
1438
|
+
style: { fontFamily: value },
|
|
1439
|
+
children: [
|
|
1440
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: value }),
|
|
1441
|
+
/* @__PURE__ */ jsx5("span", { className: "text-[8px] text-[var(--text-muted)]", children: "\u25BE" })
|
|
1442
|
+
]
|
|
1443
|
+
}
|
|
1444
|
+
),
|
|
1445
|
+
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-52`, children: [
|
|
1446
|
+
/* @__PURE__ */ jsx5(
|
|
1447
|
+
"input",
|
|
1448
|
+
{
|
|
1449
|
+
autoFocus: true,
|
|
1450
|
+
value: query,
|
|
1451
|
+
onChange: (event) => setQuery(event.target.value),
|
|
1452
|
+
placeholder: "Search fonts",
|
|
1453
|
+
"aria-label": "Search fonts",
|
|
1454
|
+
className: "m-1 rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
1455
|
+
}
|
|
1456
|
+
),
|
|
1457
|
+
/* @__PURE__ */ jsx5("div", { role: "listbox", className: "max-h-60 overflow-y-auto py-1", children: filtered.length === 0 ? /* @__PURE__ */ jsx5("div", { className: "px-3 py-2 text-[11px] text-[var(--text-muted)]", children: "No matches" }) : filtered.map((family) => /* @__PURE__ */ jsx5(
|
|
1458
|
+
"button",
|
|
1459
|
+
{
|
|
1460
|
+
type: "button",
|
|
1461
|
+
role: "option",
|
|
1462
|
+
"aria-selected": family === value,
|
|
1463
|
+
onClick: () => {
|
|
1464
|
+
onChange(family);
|
|
1465
|
+
setOpen(false);
|
|
1466
|
+
setQuery("");
|
|
1467
|
+
},
|
|
1468
|
+
style: { fontFamily: family },
|
|
1469
|
+
className: `block w-full px-3 py-1 text-left text-[13px] hover:bg-[var(--brand-primary)]/10 ${family === value ? "text-[var(--brand-primary)]" : "text-[var(--text-primary)]"}`,
|
|
1470
|
+
children: family
|
|
1471
|
+
},
|
|
1472
|
+
family
|
|
1473
|
+
)) })
|
|
1474
|
+
] })
|
|
1475
|
+
}
|
|
1476
|
+
)
|
|
1477
|
+
] });
|
|
1478
|
+
}
|
|
1479
|
+
function ColorSwatch({ label, value, onCommit, disabled }) {
|
|
1480
|
+
const [open, setOpen] = useState3(false);
|
|
1481
|
+
const normalized = value.startsWith("#") ? value : "#ffffff";
|
|
1482
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1483
|
+
/* @__PURE__ */ jsx5("span", { className: FIELD_LABEL, children: label }),
|
|
1484
|
+
/* @__PURE__ */ jsx5(
|
|
1485
|
+
Popover,
|
|
1486
|
+
{
|
|
1487
|
+
open,
|
|
1488
|
+
onClose: () => setOpen(false),
|
|
1489
|
+
trigger: /* @__PURE__ */ jsx5(
|
|
1490
|
+
"button",
|
|
1491
|
+
{
|
|
1492
|
+
type: "button",
|
|
1493
|
+
disabled,
|
|
1494
|
+
"aria-label": `${label} color`,
|
|
1495
|
+
onClick: () => setOpen((v) => !v),
|
|
1496
|
+
className: "h-6 w-10 rounded border border-[var(--border-default)] disabled:cursor-default disabled:opacity-40",
|
|
1497
|
+
style: { backgroundColor: normalized }
|
|
1498
|
+
}
|
|
1499
|
+
),
|
|
1500
|
+
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-40 gap-2 p-2`, children: [
|
|
1501
|
+
/* @__PURE__ */ jsx5(
|
|
1502
|
+
"input",
|
|
1503
|
+
{
|
|
1504
|
+
type: "color",
|
|
1505
|
+
"aria-label": `${label} color picker`,
|
|
1506
|
+
value: normalized,
|
|
1507
|
+
onChange: (event) => onCommit(event.target.value),
|
|
1508
|
+
className: "h-8 w-full cursor-pointer rounded border border-[var(--border-default)] p-0.5"
|
|
1509
|
+
}
|
|
1510
|
+
),
|
|
1511
|
+
/* @__PURE__ */ jsx5(
|
|
1512
|
+
"input",
|
|
1513
|
+
{
|
|
1514
|
+
type: "text",
|
|
1515
|
+
"aria-label": `${label} hex value`,
|
|
1516
|
+
value,
|
|
1517
|
+
onChange: (event) => onCommit(event.target.value),
|
|
1518
|
+
className: "rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
1519
|
+
}
|
|
1520
|
+
)
|
|
1521
|
+
] })
|
|
1315
1522
|
}
|
|
1316
1523
|
)
|
|
1317
1524
|
] });
|
|
@@ -1355,16 +1562,18 @@ function Toolbar({
|
|
|
1355
1562
|
const selectedIds = selectedElements.map((e) => e.id);
|
|
1356
1563
|
const isGroup = single?.kind === "group";
|
|
1357
1564
|
const groupable = selectedElements.length >= 2;
|
|
1358
|
-
return /* @__PURE__ */ jsxs5("div", { className: "flex h-11 shrink-0 items-center gap-2
|
|
1359
|
-
/* @__PURE__ */
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1565
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex min-h-11 shrink-0 flex-wrap items-center gap-x-2 gap-y-1 border-b border-[var(--border-default)] bg-[var(--bg-input)] px-3 py-1", children: [
|
|
1566
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex shrink-0 items-center gap-2", children: [
|
|
1567
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Undo", disabled: !canUndo || !canWrite, onClick: onUndo, className: BTN2, children: /* @__PURE__ */ jsx5(UndoGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1568
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Redo", disabled: !canRedo || !canWrite, onClick: onRedo, className: BTN2, children: /* @__PURE__ */ jsx5(RedoGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1569
|
+
SEP,
|
|
1570
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Toggle rulers", "aria-pressed": showRulers, onClick: onToggleRulers, className: showRulers ? BTN_ACTIVE : BTN2, children: /* @__PURE__ */ jsx5(RulerGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1571
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Toggle grid", "aria-pressed": gridEnabled, onClick: onToggleGrid, className: gridEnabled ? BTN_ACTIVE : BTN2, children: /* @__PURE__ */ jsx5(GridGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1572
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Toggle snap", "aria-pressed": snapEnabled, onClick: onToggleSnap, className: snapEnabled ? BTN_ACTIVE : BTN2, children: /* @__PURE__ */ jsx5(MagnetGlyph, { className: "h-3.5 w-3.5" }) }),
|
|
1573
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Toggle bleed overlay", "aria-pressed": showBleed, onClick: onToggleBleed, className: showBleed ? BTN_ACTIVE : BTN2, disabled: !page.bleed, children: /* @__PURE__ */ jsx5(BleedGlyph, { className: "h-3.5 w-3.5" }) })
|
|
1574
|
+
] }),
|
|
1366
1575
|
SEP,
|
|
1367
|
-
hasSelection ? /* @__PURE__ */ jsx5(
|
|
1576
|
+
/* @__PURE__ */ jsx5("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-1", children: hasSelection ? /* @__PURE__ */ jsx5(
|
|
1368
1577
|
SelectionControls,
|
|
1369
1578
|
{
|
|
1370
1579
|
elements: selectedElements,
|
|
@@ -1392,7 +1601,7 @@ function Toolbar({
|
|
|
1392
1601
|
onSetPageProps,
|
|
1393
1602
|
onSetPageGuides
|
|
1394
1603
|
}
|
|
1395
|
-
)
|
|
1604
|
+
) })
|
|
1396
1605
|
] });
|
|
1397
1606
|
}
|
|
1398
1607
|
function SelectionControls({
|
|
@@ -1458,75 +1667,69 @@ function SelectionControls({
|
|
|
1458
1667
|
children: single.locked ? /* @__PURE__ */ jsx5(LockGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx5(UnlockGlyph, { className: "h-3.5 w-3.5" })
|
|
1459
1668
|
}
|
|
1460
1669
|
) : null,
|
|
1461
|
-
single && onBindSlot ? /* @__PURE__ */
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
setSlotInput(currentSlot ?? "");
|
|
1469
|
-
setSlotPopoverOpen((v) => !v);
|
|
1470
|
-
},
|
|
1471
|
-
className: currentSlot ? BTN_ACTIVE : BTN2,
|
|
1472
|
-
title: currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1473
|
-
children: /* @__PURE__ */ jsx5(SlotGlyph, { className: "h-3.5 w-3.5" })
|
|
1474
|
-
}
|
|
1475
|
-
),
|
|
1476
|
-
slotPopoverOpen ? /* @__PURE__ */ jsxs5("div", { className: "absolute top-full left-0 z-50 mt-1 flex w-48 flex-col gap-2 rounded border border-[var(--border-default)] bg-[var(--bg-input)] p-2 shadow-lg", children: [
|
|
1477
|
-
/* @__PURE__ */ jsx5(
|
|
1478
|
-
"input",
|
|
1670
|
+
single && onBindSlot ? /* @__PURE__ */ jsx5(
|
|
1671
|
+
Popover,
|
|
1672
|
+
{
|
|
1673
|
+
open: slotPopoverOpen,
|
|
1674
|
+
onClose: () => setSlotPopoverOpen(false),
|
|
1675
|
+
trigger: /* @__PURE__ */ jsx5(
|
|
1676
|
+
"button",
|
|
1479
1677
|
{
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1678
|
+
type: "button",
|
|
1679
|
+
"aria-label": currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1680
|
+
onClick: () => {
|
|
1681
|
+
setSlotInput(currentSlot ?? "");
|
|
1682
|
+
setSlotPopoverOpen((v) => !v);
|
|
1683
|
+
},
|
|
1684
|
+
className: currentSlot ? BTN_ACTIVE : BTN2,
|
|
1685
|
+
title: currentSlot ? `Slot: ${currentSlot}` : "Bind slot",
|
|
1686
|
+
children: /* @__PURE__ */ jsx5(SlotGlyph, { className: "h-3.5 w-3.5" })
|
|
1485
1687
|
}
|
|
1486
1688
|
),
|
|
1487
|
-
/* @__PURE__ */ jsxs5("div", { className:
|
|
1689
|
+
children: /* @__PURE__ */ jsxs5("div", { className: `${POPOVER_PANEL} w-48 gap-2 p-2`, children: [
|
|
1488
1690
|
/* @__PURE__ */ jsx5(
|
|
1489
|
-
"
|
|
1691
|
+
"input",
|
|
1490
1692
|
{
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
className: "flex-1 rounded border border-[var(--brand-primary)] px-2 py-0.5 text-[11px] text-[var(--brand-primary)] hover:bg-[var(--brand-primary)]/10",
|
|
1497
|
-
children: slotInput.trim() ? "Bind" : "Unbind"
|
|
1693
|
+
autoFocus: true,
|
|
1694
|
+
value: slotInput,
|
|
1695
|
+
onChange: (event) => setSlotInput(event.target.value),
|
|
1696
|
+
placeholder: "slot-name",
|
|
1697
|
+
className: "rounded border border-[var(--border-default)] bg-transparent px-2 py-1 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
1498
1698
|
}
|
|
1499
1699
|
),
|
|
1500
|
-
/* @__PURE__ */
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1700
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex gap-2", children: [
|
|
1701
|
+
/* @__PURE__ */ jsx5(
|
|
1702
|
+
"button",
|
|
1703
|
+
{
|
|
1704
|
+
type: "button",
|
|
1705
|
+
onClick: () => {
|
|
1706
|
+
onBindSlot(slotInput.trim() || null);
|
|
1707
|
+
setSlotPopoverOpen(false);
|
|
1708
|
+
},
|
|
1709
|
+
className: "flex-1 rounded border border-[var(--brand-primary)] px-2 py-0.5 text-[11px] text-[var(--brand-primary)] hover:bg-[var(--brand-primary)]/10",
|
|
1710
|
+
children: slotInput.trim() ? "Bind" : "Unbind"
|
|
1711
|
+
}
|
|
1712
|
+
),
|
|
1713
|
+
/* @__PURE__ */ jsx5(
|
|
1714
|
+
"button",
|
|
1715
|
+
{
|
|
1716
|
+
type: "button",
|
|
1717
|
+
onClick: () => setSlotPopoverOpen(false),
|
|
1718
|
+
className: "rounded border border-[var(--border-default)] px-2 py-0.5 text-[11px] text-[var(--text-secondary)]",
|
|
1719
|
+
children: "Cancel"
|
|
1720
|
+
}
|
|
1721
|
+
)
|
|
1722
|
+
] })
|
|
1509
1723
|
] })
|
|
1510
|
-
|
|
1511
|
-
|
|
1724
|
+
}
|
|
1725
|
+
) : null,
|
|
1512
1726
|
SEP,
|
|
1513
1727
|
/* @__PURE__ */ jsx5("button", { type: "button", "aria-label": "Delete selection", disabled: !canWrite, onClick: onDelete, className: BTN2, children: /* @__PURE__ */ jsx5(TrashGlyph, { className: "h-3.5 w-3.5 text-rose-400" }) })
|
|
1514
1728
|
] });
|
|
1515
1729
|
}
|
|
1516
1730
|
function TextControls({ element, canWrite, onPatch }) {
|
|
1517
1731
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1518
|
-
/* @__PURE__ */ jsx5(
|
|
1519
|
-
"input",
|
|
1520
|
-
{
|
|
1521
|
-
type: "text",
|
|
1522
|
-
"aria-label": "Font family",
|
|
1523
|
-
value: element.fontFamily,
|
|
1524
|
-
disabled: !canWrite,
|
|
1525
|
-
onChange: (event) => onPatch({ fontFamily: event.target.value }),
|
|
1526
|
-
className: "w-28 rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-2 py-0.5 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]",
|
|
1527
|
-
placeholder: "Font"
|
|
1528
|
-
}
|
|
1529
|
-
),
|
|
1732
|
+
/* @__PURE__ */ jsx5(FontPicker, { value: element.fontFamily, disabled: !canWrite, onChange: (fontFamily) => onPatch({ fontFamily }) }),
|
|
1530
1733
|
/* @__PURE__ */ jsx5(NumberInput, { label: "Size", value: element.fontSize, min: 1, onCommit: (v) => onPatch({ fontSize: v }), className: "w-12" }),
|
|
1531
1734
|
/* @__PURE__ */ jsx5(
|
|
1532
1735
|
"button",
|
|
@@ -1564,35 +1767,33 @@ function TextControls({ element, canWrite, onPatch }) {
|
|
|
1564
1767
|
)),
|
|
1565
1768
|
/* @__PURE__ */ jsx5(NumberInput, { label: "Line H", value: element.lineHeight, step: 0.1, min: 0.5, onCommit: (v) => onPatch({ lineHeight: v }), className: "w-12" }),
|
|
1566
1769
|
/* @__PURE__ */ jsx5(NumberInput, { label: "Spacing", value: element.letterSpacing, step: 0.5, onCommit: (v) => onPatch({ letterSpacing: v }), className: "w-14" }),
|
|
1567
|
-
/* @__PURE__ */ jsx5(ColorSwatch, { label: "Fill", value: element.fill, onCommit: (v) => onPatch({ fill: v }) })
|
|
1770
|
+
/* @__PURE__ */ jsx5(ColorSwatch, { label: "Fill", value: element.fill, onCommit: (v) => onPatch({ fill: v }), disabled: !canWrite })
|
|
1568
1771
|
] });
|
|
1569
1772
|
}
|
|
1570
1773
|
function ShapeControls({ element, canWrite, onPatch, showCornerRadius }) {
|
|
1571
1774
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1572
|
-
/* @__PURE__ */ jsx5(ColorSwatch, { label: "Fill", value: element.fill, onCommit: (v) => onPatch({ fill: v }) }),
|
|
1573
|
-
/* @__PURE__ */ jsx5(ColorSwatch, { label: "Stroke", value: element.stroke ?? "#000000", onCommit: (v) => onPatch({ stroke: v }) }),
|
|
1775
|
+
/* @__PURE__ */ jsx5(ColorSwatch, { label: "Fill", value: element.fill, onCommit: (v) => onPatch({ fill: v }), disabled: !canWrite }),
|
|
1776
|
+
/* @__PURE__ */ jsx5(ColorSwatch, { label: "Stroke", value: element.stroke ?? "#000000", onCommit: (v) => onPatch({ stroke: v }), disabled: !canWrite }),
|
|
1574
1777
|
/* @__PURE__ */ jsx5(NumberInput, { label: "Stroke W", value: element.strokeWidth ?? 0, min: 0, onCommit: (v) => onPatch({ strokeWidth: v }), className: "w-14" }),
|
|
1575
1778
|
showCornerRadius && "cornerRadius" in element ? /* @__PURE__ */ jsx5(NumberInput, { label: "Corner R", value: element.cornerRadius ?? 0, min: 0, onCommit: (v) => onPatch({ cornerRadius: v }), className: "w-14" }) : null
|
|
1576
1779
|
] });
|
|
1577
1780
|
}
|
|
1578
1781
|
function ImageControls({ element, canWrite, onPatch }) {
|
|
1579
|
-
return /* @__PURE__ */
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
"
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
)
|
|
1595
|
-
] });
|
|
1782
|
+
return /* @__PURE__ */ jsx5(
|
|
1783
|
+
SelectControl,
|
|
1784
|
+
{
|
|
1785
|
+
label: "Fit",
|
|
1786
|
+
value: element.fit,
|
|
1787
|
+
disabled: !canWrite,
|
|
1788
|
+
onChange: (fit) => onPatch({ fit }),
|
|
1789
|
+
buttonClassName: "w-24",
|
|
1790
|
+
options: [
|
|
1791
|
+
{ value: "fill", label: "Fill" },
|
|
1792
|
+
{ value: "cover", label: "Cover" },
|
|
1793
|
+
{ value: "contain", label: "Contain" }
|
|
1794
|
+
]
|
|
1795
|
+
}
|
|
1796
|
+
);
|
|
1596
1797
|
}
|
|
1597
1798
|
function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides }) {
|
|
1598
1799
|
const matchedPreset = matchPreset(page.width, page.height);
|
|
@@ -1604,6 +1805,10 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1604
1805
|
if (dim === "width") setCustomW(null);
|
|
1605
1806
|
else setCustomH(null);
|
|
1606
1807
|
}
|
|
1808
|
+
const presetOptions = [
|
|
1809
|
+
{ value: "custom", label: "Custom" },
|
|
1810
|
+
...SIZE_PRESETS.map((p) => ({ value: p.id, label: p.label }))
|
|
1811
|
+
];
|
|
1607
1812
|
return /* @__PURE__ */ jsxs5(Fragment4, { children: [
|
|
1608
1813
|
/* @__PURE__ */ jsx5(
|
|
1609
1814
|
"input",
|
|
@@ -1617,27 +1822,21 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1617
1822
|
}
|
|
1618
1823
|
),
|
|
1619
1824
|
SEP,
|
|
1825
|
+
/* @__PURE__ */ jsx5(
|
|
1826
|
+
SelectControl,
|
|
1827
|
+
{
|
|
1828
|
+
label: "Preset",
|
|
1829
|
+
value: matchedPreset?.id ?? "custom",
|
|
1830
|
+
disabled: !canWrite,
|
|
1831
|
+
onChange: (id) => {
|
|
1832
|
+
const preset = SIZE_PRESETS.find((p) => p.id === id);
|
|
1833
|
+
if (preset) onSetPageProps({ width: preset.width, height: preset.height });
|
|
1834
|
+
},
|
|
1835
|
+
options: presetOptions
|
|
1836
|
+
}
|
|
1837
|
+
),
|
|
1620
1838
|
/* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1621
|
-
/* @__PURE__ */ jsx5("span", { className:
|
|
1622
|
-
/* @__PURE__ */ jsxs5(
|
|
1623
|
-
"select",
|
|
1624
|
-
{
|
|
1625
|
-
value: matchedPreset?.id ?? "custom",
|
|
1626
|
-
disabled: !canWrite,
|
|
1627
|
-
onChange: (event) => {
|
|
1628
|
-
const preset = SIZE_PRESETS.find((p) => p.id === event.target.value);
|
|
1629
|
-
if (preset) onSetPageProps({ width: preset.width, height: preset.height });
|
|
1630
|
-
},
|
|
1631
|
-
className: "rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-1 py-0.5 text-[12px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]",
|
|
1632
|
-
children: [
|
|
1633
|
-
/* @__PURE__ */ jsx5("option", { value: "custom", children: "Custom" }),
|
|
1634
|
-
SIZE_PRESETS.map((p) => /* @__PURE__ */ jsx5("option", { value: p.id, children: p.label }, p.id))
|
|
1635
|
-
]
|
|
1636
|
-
}
|
|
1637
|
-
)
|
|
1638
|
-
] }),
|
|
1639
|
-
/* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1640
|
-
/* @__PURE__ */ jsx5("span", { className: "text-[9px] uppercase tracking-wide text-[var(--text-muted)]", children: "W" }),
|
|
1839
|
+
/* @__PURE__ */ jsx5("span", { className: FIELD_LABEL, children: "W" }),
|
|
1641
1840
|
/* @__PURE__ */ jsx5(
|
|
1642
1841
|
"input",
|
|
1643
1842
|
{
|
|
@@ -1657,7 +1856,7 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1657
1856
|
] }),
|
|
1658
1857
|
/* @__PURE__ */ jsx5("span", { className: "text-[var(--text-muted)]", children: "\xD7" }),
|
|
1659
1858
|
/* @__PURE__ */ jsxs5("label", { className: "flex flex-col items-center gap-0.5", children: [
|
|
1660
|
-
/* @__PURE__ */ jsx5("span", { className:
|
|
1859
|
+
/* @__PURE__ */ jsx5("span", { className: FIELD_LABEL, children: "H" }),
|
|
1661
1860
|
/* @__PURE__ */ jsx5(
|
|
1662
1861
|
"input",
|
|
1663
1862
|
{
|
|
@@ -1676,7 +1875,7 @@ function PagePropsControls({ page, canWrite, onSetPageProps, onSetPageGuides })
|
|
|
1676
1875
|
)
|
|
1677
1876
|
] }),
|
|
1678
1877
|
SEP,
|
|
1679
|
-
/* @__PURE__ */ jsx5(ColorSwatch, { label: "BG", value: page.background, onCommit: (v) => onSetPageProps({ background: v }) }),
|
|
1878
|
+
/* @__PURE__ */ jsx5(ColorSwatch, { label: "BG", value: page.background, onCommit: (v) => onSetPageProps({ background: v }), disabled: !canWrite }),
|
|
1680
1879
|
SEP,
|
|
1681
1880
|
/* @__PURE__ */ jsx5(BleedControls, { page, canWrite, onSetPageProps })
|
|
1682
1881
|
] });
|
|
@@ -1793,8 +1992,106 @@ function ZoomControls({ zoom, onZoom, onFit }) {
|
|
|
1793
1992
|
] });
|
|
1794
1993
|
}
|
|
1795
1994
|
|
|
1796
|
-
// src/design-canvas-react/components/
|
|
1995
|
+
// src/design-canvas-react/components/ExportControl.tsx
|
|
1996
|
+
import { useRef as useRef4, useState as useState4 } from "react";
|
|
1797
1997
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1998
|
+
var FORMATS = [
|
|
1999
|
+
{ id: "png", label: "PNG" },
|
|
2000
|
+
{ id: "jpeg", label: "JPEG" }
|
|
2001
|
+
];
|
|
2002
|
+
var SCALES = [
|
|
2003
|
+
{ value: 1, label: "1x" },
|
|
2004
|
+
{ value: 2, label: "2x" }
|
|
2005
|
+
];
|
|
2006
|
+
function ExportControl({ defaults, onExport, className }) {
|
|
2007
|
+
const [open, setOpen] = useState4(false);
|
|
2008
|
+
const [format, setFormat] = useState4(defaults?.format ?? "png");
|
|
2009
|
+
const [pixelRatio, setPixelRatio] = useState4(defaults?.pixelRatio ?? 1);
|
|
2010
|
+
const containerRef = useRef4(null);
|
|
2011
|
+
function confirm() {
|
|
2012
|
+
onExport({ format, pixelRatio });
|
|
2013
|
+
setOpen(false);
|
|
2014
|
+
}
|
|
2015
|
+
return /* @__PURE__ */ jsxs7("div", { ref: containerRef, className: `relative ${className ?? ""}`, children: [
|
|
2016
|
+
/* @__PURE__ */ jsxs7(
|
|
2017
|
+
"button",
|
|
2018
|
+
{
|
|
2019
|
+
type: "button",
|
|
2020
|
+
"aria-label": "Export",
|
|
2021
|
+
"aria-haspopup": "dialog",
|
|
2022
|
+
"aria-expanded": open,
|
|
2023
|
+
onClick: () => setOpen((v) => !v),
|
|
2024
|
+
onBlur: (event) => {
|
|
2025
|
+
if (!containerRef.current?.contains(event.relatedTarget)) {
|
|
2026
|
+
setOpen(false);
|
|
2027
|
+
}
|
|
2028
|
+
},
|
|
2029
|
+
className: "flex h-8 items-center gap-1.5 rounded-md border border-[var(--border-default)] px-2.5 text-xs font-medium text-[var(--text-primary)] transition-colors hover:border-[var(--brand-primary)]/40",
|
|
2030
|
+
children: [
|
|
2031
|
+
/* @__PURE__ */ jsx7(ExportGlyph, { className: "h-3.5 w-3.5" }),
|
|
2032
|
+
"Export",
|
|
2033
|
+
/* @__PURE__ */ jsx7(ChevronDownGlyph, { className: "h-3 w-3 text-[var(--text-muted)]" })
|
|
2034
|
+
]
|
|
2035
|
+
}
|
|
2036
|
+
),
|
|
2037
|
+
open ? /* @__PURE__ */ jsxs7(
|
|
2038
|
+
"div",
|
|
2039
|
+
{
|
|
2040
|
+
role: "dialog",
|
|
2041
|
+
"aria-label": "Export options",
|
|
2042
|
+
onBlur: (event) => {
|
|
2043
|
+
if (!containerRef.current?.contains(event.relatedTarget)) {
|
|
2044
|
+
setOpen(false);
|
|
2045
|
+
}
|
|
2046
|
+
},
|
|
2047
|
+
className: "absolute right-0 top-full z-50 mt-1 flex w-52 flex-col gap-3 rounded-md border border-[var(--border-default)] bg-[var(--bg-input)] p-3 shadow-lg",
|
|
2048
|
+
children: [
|
|
2049
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1.5", children: [
|
|
2050
|
+
/* @__PURE__ */ jsx7("span", { className: "text-[11px] font-medium text-[var(--text-muted)]", children: "Format" }),
|
|
2051
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-1.5", children: FORMATS.map((f) => /* @__PURE__ */ jsx7(
|
|
2052
|
+
"button",
|
|
2053
|
+
{
|
|
2054
|
+
type: "button",
|
|
2055
|
+
"aria-pressed": format === f.id,
|
|
2056
|
+
onClick: () => setFormat(f.id),
|
|
2057
|
+
className: `flex-1 rounded border px-2 py-1 text-[11px] transition-colors ${format === f.id ? "border-[var(--brand-primary)] text-[var(--brand-primary)]" : "border-[var(--border-default)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]"}`,
|
|
2058
|
+
children: f.label
|
|
2059
|
+
},
|
|
2060
|
+
f.id
|
|
2061
|
+
)) })
|
|
2062
|
+
] }),
|
|
2063
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1.5", children: [
|
|
2064
|
+
/* @__PURE__ */ jsx7("span", { className: "text-[11px] font-medium text-[var(--text-muted)]", children: "Scale" }),
|
|
2065
|
+
/* @__PURE__ */ jsx7("div", { className: "flex gap-1.5", children: SCALES.map((s) => /* @__PURE__ */ jsx7(
|
|
2066
|
+
"button",
|
|
2067
|
+
{
|
|
2068
|
+
type: "button",
|
|
2069
|
+
"aria-pressed": pixelRatio === s.value,
|
|
2070
|
+
onClick: () => setPixelRatio(s.value),
|
|
2071
|
+
className: `flex-1 rounded border px-2 py-1 text-[11px] transition-colors ${pixelRatio === s.value ? "border-[var(--brand-primary)] text-[var(--brand-primary)]" : "border-[var(--border-default)] text-[var(--text-secondary)] hover:text-[var(--text-primary)]"}`,
|
|
2072
|
+
children: s.label
|
|
2073
|
+
},
|
|
2074
|
+
s.value
|
|
2075
|
+
)) })
|
|
2076
|
+
] }),
|
|
2077
|
+
/* @__PURE__ */ jsx7(
|
|
2078
|
+
"button",
|
|
2079
|
+
{
|
|
2080
|
+
type: "button",
|
|
2081
|
+
"aria-label": "Export image",
|
|
2082
|
+
onClick: confirm,
|
|
2083
|
+
className: "rounded border border-[var(--brand-primary)] px-2 py-1 text-[11px] font-medium text-[var(--brand-primary)] transition-colors hover:bg-[var(--brand-primary)]/10",
|
|
2084
|
+
children: "Export"
|
|
2085
|
+
}
|
|
2086
|
+
)
|
|
2087
|
+
]
|
|
2088
|
+
}
|
|
2089
|
+
) : null
|
|
2090
|
+
] });
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
// src/design-canvas-react/components/DesignCanvas.tsx
|
|
2094
|
+
import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1798
2095
|
function mintId() {
|
|
1799
2096
|
const uuid = globalThis.crypto && "randomUUID" in globalThis.crypto ? globalThis.crypto.randomUUID() : null;
|
|
1800
2097
|
return `local-${uuid ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2)}`}`;
|
|
@@ -1834,6 +2131,7 @@ function DesignCanvas({
|
|
|
1834
2131
|
renderAgentPanel,
|
|
1835
2132
|
renderSidePanel,
|
|
1836
2133
|
onExport,
|
|
2134
|
+
exportDefaults,
|
|
1837
2135
|
className,
|
|
1838
2136
|
fitOnMount,
|
|
1839
2137
|
onReady,
|
|
@@ -1846,23 +2144,24 @@ function DesignCanvas({
|
|
|
1846
2144
|
[]
|
|
1847
2145
|
);
|
|
1848
2146
|
const editorState = useSyncExternalStore(stack.subscribe, stack.getState, stack.getState);
|
|
1849
|
-
const appliedDocumentRef =
|
|
1850
|
-
|
|
2147
|
+
const appliedDocumentRef = useRef5(initialDocument);
|
|
2148
|
+
useEffect3(() => {
|
|
1851
2149
|
if (appliedDocumentRef.current === initialDocument) return;
|
|
1852
2150
|
appliedDocumentRef.current = initialDocument;
|
|
1853
2151
|
stack.reset(initialDocument);
|
|
1854
2152
|
}, [initialDocument, stack]);
|
|
1855
|
-
const [commitError, setCommitError] =
|
|
2153
|
+
const [commitError, setCommitError] = useState5(null);
|
|
1856
2154
|
const commit = useCommitCommand(stack, onApplyOperations, canWrite, setCommitError);
|
|
1857
|
-
const selectionChangeRef =
|
|
2155
|
+
const selectionChangeRef = useRef5(onSelectionChange);
|
|
1858
2156
|
selectionChangeRef.current = onSelectionChange;
|
|
1859
|
-
|
|
2157
|
+
useEffect3(() => {
|
|
1860
2158
|
const page = editorState.document.pages.find((p) => p.id === editorState.activePageId);
|
|
1861
2159
|
if (!page) return;
|
|
1862
2160
|
const selected = editorState.selectedElementIds.map((id) => page.elements.find((el) => el.id === id)).filter((el) => el !== void 0);
|
|
1863
2161
|
selectionChangeRef.current?.(selected);
|
|
1864
2162
|
}, [editorState.selectedElementIds, editorState.activePageId, editorState.document]);
|
|
1865
|
-
const fitRef =
|
|
2163
|
+
const fitRef = useRef5(null);
|
|
2164
|
+
const exportRef = useRef5(null);
|
|
1866
2165
|
const setZoom = useCallback2((zoom) => stack.setView({ zoom }), [stack]);
|
|
1867
2166
|
const setPan = useCallback2((panX, panY) => stack.setView({ panX, panY }), [stack]);
|
|
1868
2167
|
const setActivePage = useCallback2((activePageId) => stack.setView({ activePageId, selectedElementIds: [] }), [stack]);
|
|
@@ -2048,7 +2347,7 @@ function DesignCanvas({
|
|
|
2048
2347
|
setCommitError(error instanceof Error ? error.message : String(error));
|
|
2049
2348
|
});
|
|
2050
2349
|
}, [stack, canWrite, onApplyOperations]);
|
|
2051
|
-
|
|
2350
|
+
useEffect3(() => {
|
|
2052
2351
|
function onKeyDown(event) {
|
|
2053
2352
|
const mod = event.metaKey || event.ctrlKey;
|
|
2054
2353
|
if (mod && !isTypingTarget(event.target)) {
|
|
@@ -2087,7 +2386,7 @@ function DesignCanvas({
|
|
|
2087
2386
|
return editorState.selectedElementIds.map((id) => activePage.elements.find((el) => el.id === id)).filter((el) => el !== void 0);
|
|
2088
2387
|
}, [activePage, editorState.selectedElementIds]);
|
|
2089
2388
|
if (!activePage) {
|
|
2090
|
-
return /* @__PURE__ */
|
|
2389
|
+
return /* @__PURE__ */ jsx8("div", { className: `flex h-full items-center justify-center bg-[var(--bg-input)] text-[var(--text-muted)] ${className ?? ""}`, children: "No pages in document" });
|
|
2091
2390
|
}
|
|
2092
2391
|
const bleedScreen = editorState.showBleed && activePage.bleed ? {
|
|
2093
2392
|
top: activePage.bleed.top * editorState.zoom,
|
|
@@ -2095,45 +2394,54 @@ function DesignCanvas({
|
|
|
2095
2394
|
bottom: activePage.bleed.bottom * editorState.zoom,
|
|
2096
2395
|
left: activePage.bleed.left * editorState.zoom
|
|
2097
2396
|
} : null;
|
|
2098
|
-
return /* @__PURE__ */
|
|
2099
|
-
renderSidePanel ? /* @__PURE__ */
|
|
2100
|
-
/* @__PURE__ */
|
|
2101
|
-
/* @__PURE__ */
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2397
|
+
return /* @__PURE__ */ jsxs8("div", { className: `flex h-full min-h-0 bg-[var(--bg-input)] text-[var(--text-primary)] ${className ?? ""}`, children: [
|
|
2398
|
+
renderSidePanel ? /* @__PURE__ */ jsx8("aside", { className: "flex w-64 shrink-0 flex-col overflow-hidden border-r border-[var(--border-default)]", children: renderSidePanel() }) : null,
|
|
2399
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
2400
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-stretch", children: [
|
|
2401
|
+
/* @__PURE__ */ jsx8("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsx8(
|
|
2402
|
+
Toolbar,
|
|
2403
|
+
{
|
|
2404
|
+
page: activePage,
|
|
2405
|
+
selectedElements,
|
|
2406
|
+
canWrite,
|
|
2407
|
+
canUndo: stack.canUndo(),
|
|
2408
|
+
canRedo: stack.canRedo(),
|
|
2409
|
+
gridEnabled: editorState.gridEnabled,
|
|
2410
|
+
snapEnabled: editorState.snapEnabled,
|
|
2411
|
+
showRulers: editorState.showRulers,
|
|
2412
|
+
showBleed: editorState.showBleed,
|
|
2413
|
+
onUndo: handleUndo,
|
|
2414
|
+
onRedo: handleRedo,
|
|
2415
|
+
onToggleGrid: () => stack.setView({ gridEnabled: !editorState.gridEnabled }),
|
|
2416
|
+
onToggleSnap: () => stack.setView({ snapEnabled: !editorState.snapEnabled }),
|
|
2417
|
+
onToggleRulers: () => stack.setView({ showRulers: !editorState.showRulers }),
|
|
2418
|
+
onToggleBleed: () => stack.setView({ showBleed: !editorState.showBleed }),
|
|
2419
|
+
onSetAttrs: handleSetAttrs,
|
|
2420
|
+
onSetPageProps: handleSetPageProps,
|
|
2421
|
+
onSetPageGuides: handleSetPageGuides,
|
|
2422
|
+
onReorder: handleReorder,
|
|
2423
|
+
onGroup: handleGroup,
|
|
2424
|
+
onUngroup: handleUngroup,
|
|
2425
|
+
onDelete: handleDelete,
|
|
2426
|
+
onBindSlot: handleBindSlot
|
|
2427
|
+
}
|
|
2428
|
+
) }),
|
|
2429
|
+
onExport ? /* @__PURE__ */ jsx8("div", { className: "flex shrink-0 items-center border-b border-l border-[var(--border-default)] bg-[var(--bg-input)] px-2", children: /* @__PURE__ */ jsx8(
|
|
2430
|
+
ExportControl,
|
|
2431
|
+
{
|
|
2432
|
+
defaults: exportDefaults,
|
|
2433
|
+
onExport: (opts) => exportRef.current?.(opts)
|
|
2434
|
+
}
|
|
2435
|
+
) }) : null
|
|
2436
|
+
] }),
|
|
2437
|
+
commitError ? /* @__PURE__ */ jsxs8(
|
|
2130
2438
|
"div",
|
|
2131
2439
|
{
|
|
2132
2440
|
className: "flex shrink-0 items-center justify-between gap-3 border-b border-rose-500/30 bg-rose-500/10 px-3 py-1.5 text-xs text-rose-300",
|
|
2133
2441
|
role: "alert",
|
|
2134
2442
|
children: [
|
|
2135
|
-
/* @__PURE__ */
|
|
2136
|
-
/* @__PURE__ */
|
|
2443
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 truncate", children: commitError }),
|
|
2444
|
+
/* @__PURE__ */ jsx8(
|
|
2137
2445
|
"button",
|
|
2138
2446
|
{
|
|
2139
2447
|
type: "button",
|
|
@@ -2145,8 +2453,8 @@ function DesignCanvas({
|
|
|
2145
2453
|
]
|
|
2146
2454
|
}
|
|
2147
2455
|
) : null,
|
|
2148
|
-
/* @__PURE__ */
|
|
2149
|
-
/* @__PURE__ */
|
|
2456
|
+
/* @__PURE__ */ jsxs8("div", { className: "relative min-h-0 flex-1", children: [
|
|
2457
|
+
/* @__PURE__ */ jsx8(
|
|
2150
2458
|
Rulers,
|
|
2151
2459
|
{
|
|
2152
2460
|
pageWidth: activePage.width,
|
|
@@ -2159,12 +2467,12 @@ function DesignCanvas({
|
|
|
2159
2467
|
onGuidesChange: handleSetPageGuides
|
|
2160
2468
|
}
|
|
2161
2469
|
),
|
|
2162
|
-
bleedScreen && activePage.bleed ? /* @__PURE__ */
|
|
2470
|
+
bleedScreen && activePage.bleed ? /* @__PURE__ */ jsx8(
|
|
2163
2471
|
"div",
|
|
2164
2472
|
{
|
|
2165
2473
|
className: "pointer-events-none absolute inset-0 z-10 overflow-hidden",
|
|
2166
2474
|
"aria-hidden": true,
|
|
2167
|
-
children: /* @__PURE__ */
|
|
2475
|
+
children: /* @__PURE__ */ jsx8(
|
|
2168
2476
|
"div",
|
|
2169
2477
|
{
|
|
2170
2478
|
style: {
|
|
@@ -2172,7 +2480,7 @@ function DesignCanvas({
|
|
|
2172
2480
|
left: editorState.panX,
|
|
2173
2481
|
top: editorState.panY
|
|
2174
2482
|
},
|
|
2175
|
-
children: /* @__PURE__ */
|
|
2483
|
+
children: /* @__PURE__ */ jsx8(
|
|
2176
2484
|
BleedTrimOverlay,
|
|
2177
2485
|
{
|
|
2178
2486
|
pageWidthPx: activePage.width * editorState.zoom,
|
|
@@ -2199,6 +2507,7 @@ function DesignCanvas({
|
|
|
2199
2507
|
stack,
|
|
2200
2508
|
activePage,
|
|
2201
2509
|
onFitRef: fitRef,
|
|
2510
|
+
onExportRef: exportRef,
|
|
2202
2511
|
fitOnMount,
|
|
2203
2512
|
onReady,
|
|
2204
2513
|
onZoomChange: setZoom,
|
|
@@ -2206,8 +2515,8 @@ function DesignCanvas({
|
|
|
2206
2515
|
onSelectElements: setSelectedElements
|
|
2207
2516
|
})
|
|
2208
2517
|
] }),
|
|
2209
|
-
/* @__PURE__ */
|
|
2210
|
-
/* @__PURE__ */
|
|
2518
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex shrink-0 items-stretch border-t border-[var(--border-default)]", children: [
|
|
2519
|
+
/* @__PURE__ */ jsx8("div", { className: "min-w-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsx8(
|
|
2211
2520
|
PagesStrip,
|
|
2212
2521
|
{
|
|
2213
2522
|
pages: editorState.document.pages,
|
|
@@ -2221,7 +2530,7 @@ function DesignCanvas({
|
|
|
2221
2530
|
onReorderPage: handleReorderPage
|
|
2222
2531
|
}
|
|
2223
2532
|
) }),
|
|
2224
|
-
/* @__PURE__ */
|
|
2533
|
+
/* @__PURE__ */ jsx8("div", { className: "flex shrink-0 items-center border-l border-[var(--border-default)]", children: /* @__PURE__ */ jsx8(
|
|
2225
2534
|
ZoomControls,
|
|
2226
2535
|
{
|
|
2227
2536
|
zoom: editorState.zoom,
|
|
@@ -2231,7 +2540,7 @@ function DesignCanvas({
|
|
|
2231
2540
|
) })
|
|
2232
2541
|
] })
|
|
2233
2542
|
] }),
|
|
2234
|
-
renderAgentPanel ? /* @__PURE__ */
|
|
2543
|
+
renderAgentPanel ? /* @__PURE__ */ jsx8("aside", { className: "flex w-80 shrink-0 flex-col overflow-hidden border-l border-[var(--border-default)]", children: renderAgentPanel({ selectedElements, activePageId: editorState.activePageId }) }) : null
|
|
2235
2544
|
] });
|
|
2236
2545
|
}
|
|
2237
2546
|
var DesignCanvas_default = DesignCanvas;
|
|
@@ -2270,11 +2579,13 @@ export {
|
|
|
2270
2579
|
ImageGlyph,
|
|
2271
2580
|
VideoGlyph,
|
|
2272
2581
|
SlotGlyph,
|
|
2582
|
+
ShapesGlyph,
|
|
2273
2583
|
PagesStrip,
|
|
2274
2584
|
Rulers,
|
|
2275
2585
|
Toolbar,
|
|
2276
2586
|
ZoomControls,
|
|
2587
|
+
ExportControl,
|
|
2277
2588
|
DesignCanvas,
|
|
2278
2589
|
DesignCanvas_default
|
|
2279
2590
|
};
|
|
2280
|
-
//# sourceMappingURL=chunk-
|
|
2591
|
+
//# sourceMappingURL=chunk-LPAVBGVY.js.map
|