@tangle-network/agent-app 0.22.0 → 0.23.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/chunk-XDCHKFBX.js +897 -0
- package/dist/chunk-XDCHKFBX.js.map +1 -0
- package/dist/design-canvas-react/index.d.ts +89 -1
- package/dist/design-canvas-react/index.js +352 -26
- package/dist/design-canvas-react/index.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +78 -0
- package/dist/sandbox/index.d.ts +183 -1
- package/dist/sandbox/index.js +54 -532
- package/dist/sandbox/index.js.map +1 -1
- package/dist/web-react/index.d.ts +62 -1
- package/dist/web-react/index.js +435 -142
- package/dist/web-react/index.js.map +1 -1
- package/package.json +6 -1
|
@@ -56,6 +56,7 @@ import {
|
|
|
56
56
|
} from "../chunk-2W4YCAFH.js";
|
|
57
57
|
import {
|
|
58
58
|
SCENE_SCHEMA_VERSION,
|
|
59
|
+
assertSceneMediaSrc,
|
|
59
60
|
bleedAwareExportBounds,
|
|
60
61
|
scaleForPreset
|
|
61
62
|
} from "../chunk-JZAJE3JL.js";
|
|
@@ -175,8 +176,326 @@ function downloadDataUrl(dataUrl, filename) {
|
|
|
175
176
|
globalThis.document.body.removeChild(a);
|
|
176
177
|
}
|
|
177
178
|
|
|
179
|
+
// src/design-canvas-react/insert-builders.ts
|
|
180
|
+
var MAX_INSERT_DIMENSION = 600;
|
|
181
|
+
function mintElementId() {
|
|
182
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
183
|
+
return crypto.randomUUID();
|
|
184
|
+
}
|
|
185
|
+
return `el-${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
186
|
+
}
|
|
187
|
+
function fittedSize(naturalW, naturalH, pageWidth, pageHeight) {
|
|
188
|
+
const cap = Math.min(MAX_INSERT_DIMENSION, pageWidth * 0.8, pageHeight * 0.8);
|
|
189
|
+
const longest = Math.max(naturalW, naturalH);
|
|
190
|
+
const scale = naturalW > 0 && naturalH > 0 ? Math.min(1, cap / longest) : 1;
|
|
191
|
+
const width = Math.max(1, Math.round((naturalW || cap) * scale));
|
|
192
|
+
const height = Math.max(1, Math.round((naturalH || cap) * scale));
|
|
193
|
+
return { width, height };
|
|
194
|
+
}
|
|
195
|
+
function centeredPosition(width, height, pageWidth, pageHeight) {
|
|
196
|
+
return {
|
|
197
|
+
x: Math.round((pageWidth - width) / 2),
|
|
198
|
+
y: Math.round((pageHeight - height) / 2)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function baseAttrs(name, x, y) {
|
|
202
|
+
return { id: mintElementId(), name, x, y, rotation: 0, opacity: 1, locked: false, visible: true };
|
|
203
|
+
}
|
|
204
|
+
function addElementOp(pageId, element) {
|
|
205
|
+
return { type: "add_element", pageId, element };
|
|
206
|
+
}
|
|
207
|
+
function buildInsertImageOp(src, naturalSize, page) {
|
|
208
|
+
assertSceneMediaSrc(src, "image src");
|
|
209
|
+
const { width, height } = fittedSize(naturalSize.width, naturalSize.height, page.width, page.height);
|
|
210
|
+
const { x, y } = centeredPosition(width, height, page.width, page.height);
|
|
211
|
+
const element = {
|
|
212
|
+
...baseAttrs("Image", x, y),
|
|
213
|
+
kind: "image",
|
|
214
|
+
width,
|
|
215
|
+
height,
|
|
216
|
+
src,
|
|
217
|
+
fit: "contain"
|
|
218
|
+
};
|
|
219
|
+
return addElementOp(page.pageId, element);
|
|
220
|
+
}
|
|
221
|
+
var DEFAULT_INSERT_TEMPLATES = [
|
|
222
|
+
{
|
|
223
|
+
id: "heading",
|
|
224
|
+
label: "Heading",
|
|
225
|
+
build(page) {
|
|
226
|
+
const width = Math.min(480, Math.round(page.width * 0.7));
|
|
227
|
+
const { x, y } = centeredPosition(width, 60, page.width, page.height);
|
|
228
|
+
const element = {
|
|
229
|
+
...baseAttrs("Heading", x, y),
|
|
230
|
+
kind: "text",
|
|
231
|
+
text: "Add a headline",
|
|
232
|
+
width,
|
|
233
|
+
fontFamily: "Inter",
|
|
234
|
+
fontSize: 48,
|
|
235
|
+
fontStyle: "bold",
|
|
236
|
+
fill: "#111827",
|
|
237
|
+
align: "left",
|
|
238
|
+
lineHeight: 1.1,
|
|
239
|
+
letterSpacing: 0
|
|
240
|
+
};
|
|
241
|
+
return [addElementOp(page.pageId, element)];
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
id: "body",
|
|
246
|
+
label: "Body text",
|
|
247
|
+
build(page) {
|
|
248
|
+
const width = Math.min(420, Math.round(page.width * 0.6));
|
|
249
|
+
const { x, y } = centeredPosition(width, 80, page.width, page.height);
|
|
250
|
+
const element = {
|
|
251
|
+
...baseAttrs("Body", x, y),
|
|
252
|
+
kind: "text",
|
|
253
|
+
text: "Add a paragraph of supporting copy.",
|
|
254
|
+
width,
|
|
255
|
+
fontFamily: "Inter",
|
|
256
|
+
fontSize: 20,
|
|
257
|
+
fontStyle: "normal",
|
|
258
|
+
fill: "#374151",
|
|
259
|
+
align: "left",
|
|
260
|
+
lineHeight: 1.4,
|
|
261
|
+
letterSpacing: 0
|
|
262
|
+
};
|
|
263
|
+
return [addElementOp(page.pageId, element)];
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
id: "rect",
|
|
268
|
+
label: "Rectangle",
|
|
269
|
+
build(page) {
|
|
270
|
+
const width = Math.min(320, Math.round(page.width * 0.4));
|
|
271
|
+
const height = Math.min(200, Math.round(page.height * 0.3));
|
|
272
|
+
const { x, y } = centeredPosition(width, height, page.width, page.height);
|
|
273
|
+
const element = {
|
|
274
|
+
...baseAttrs("Rectangle", x, y),
|
|
275
|
+
kind: "rect",
|
|
276
|
+
width,
|
|
277
|
+
height,
|
|
278
|
+
fill: "#6366f1",
|
|
279
|
+
cornerRadius: 12
|
|
280
|
+
};
|
|
281
|
+
return [addElementOp(page.pageId, element)];
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
id: "ellipse",
|
|
286
|
+
label: "Ellipse",
|
|
287
|
+
build(page) {
|
|
288
|
+
const size = Math.min(220, Math.round(Math.min(page.width, page.height) * 0.3));
|
|
289
|
+
const { x, y } = centeredPosition(size, size, page.width, page.height);
|
|
290
|
+
const element = {
|
|
291
|
+
...baseAttrs("Ellipse", x, y),
|
|
292
|
+
kind: "ellipse",
|
|
293
|
+
width: size,
|
|
294
|
+
height: size,
|
|
295
|
+
fill: "#10b981"
|
|
296
|
+
};
|
|
297
|
+
return [addElementOp(page.pageId, element)];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
];
|
|
301
|
+
|
|
302
|
+
// src/design-canvas-react/components/CanvasInsertPanel.tsx
|
|
303
|
+
import { useEffect, useRef, useState } from "react";
|
|
304
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
305
|
+
var DEFAULT_ACCEPT = "image/png,image/jpeg,image/gif,image/webp";
|
|
306
|
+
var PROBE_TIMEOUT_MS = 4e3;
|
|
307
|
+
function probeImageSize(url) {
|
|
308
|
+
return new Promise((resolve) => {
|
|
309
|
+
if (typeof Image === "undefined") return resolve({ width: 0, height: 0 });
|
|
310
|
+
let settled = false;
|
|
311
|
+
const finish = (size) => {
|
|
312
|
+
if (settled) return;
|
|
313
|
+
settled = true;
|
|
314
|
+
resolve(size);
|
|
315
|
+
};
|
|
316
|
+
const img = new Image();
|
|
317
|
+
img.onload = () => finish({ width: img.naturalWidth, height: img.naturalHeight });
|
|
318
|
+
img.onerror = () => finish({ width: 0, height: 0 });
|
|
319
|
+
setTimeout(() => finish({ width: 0, height: 0 }), PROBE_TIMEOUT_MS);
|
|
320
|
+
img.src = url;
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
function UploadGlyph({ className }) {
|
|
324
|
+
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: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 9l5-5 5 5M12 4v12" }) });
|
|
325
|
+
}
|
|
326
|
+
function SparkleGlyph({ className }) {
|
|
327
|
+
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" }) });
|
|
328
|
+
}
|
|
329
|
+
function SpinnerGlyph({ className }) {
|
|
330
|
+
return /* @__PURE__ */ jsx("svg", { className: `${className ?? ""} animate-spin`, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": true, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.2-8.6", strokeLinecap: "round" }) });
|
|
331
|
+
}
|
|
332
|
+
function CanvasInsertPanel({
|
|
333
|
+
canWrite,
|
|
334
|
+
page,
|
|
335
|
+
onInsert,
|
|
336
|
+
onUploadImage,
|
|
337
|
+
loadGenerations,
|
|
338
|
+
templates = DEFAULT_INSERT_TEMPLATES,
|
|
339
|
+
accept = DEFAULT_ACCEPT,
|
|
340
|
+
className
|
|
341
|
+
}) {
|
|
342
|
+
const [tab, setTab] = useState("uploads");
|
|
343
|
+
const [busy, setBusy] = useState(false);
|
|
344
|
+
const [error, setError] = useState("");
|
|
345
|
+
const [dragOver, setDragOver] = useState(false);
|
|
346
|
+
const [generations, setGenerations] = useState([]);
|
|
347
|
+
const [generationsLoaded, setGenerationsLoaded] = useState(false);
|
|
348
|
+
const fileInputRef = useRef(null);
|
|
349
|
+
useEffect(() => {
|
|
350
|
+
if (tab !== "generations" || generationsLoaded || !loadGenerations) return;
|
|
351
|
+
let cancelled = false;
|
|
352
|
+
void (async () => {
|
|
353
|
+
try {
|
|
354
|
+
const rows = await loadGenerations();
|
|
355
|
+
if (!cancelled) setGenerations(rows.filter((g) => g.url));
|
|
356
|
+
} catch (err) {
|
|
357
|
+
if (!cancelled) setError(err instanceof Error ? err.message : "Could not load generations");
|
|
358
|
+
} finally {
|
|
359
|
+
if (!cancelled) setGenerationsLoaded(true);
|
|
360
|
+
}
|
|
361
|
+
})();
|
|
362
|
+
return () => {
|
|
363
|
+
cancelled = true;
|
|
364
|
+
};
|
|
365
|
+
}, [tab, generationsLoaded, loadGenerations]);
|
|
366
|
+
async function insertImageFromUrl(url) {
|
|
367
|
+
assertSceneMediaSrc(url, "image src");
|
|
368
|
+
const natural = await probeImageSize(url);
|
|
369
|
+
await onInsert([buildInsertImageOp(url, natural, page)]);
|
|
370
|
+
}
|
|
371
|
+
async function handleFiles(files) {
|
|
372
|
+
if (!canWrite || busy) return;
|
|
373
|
+
const list = Array.from(files).filter((f) => f.type.startsWith("image/"));
|
|
374
|
+
if (list.length === 0) {
|
|
375
|
+
setError("Only image files can be added to the canvas");
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
setBusy(true);
|
|
379
|
+
setError("");
|
|
380
|
+
try {
|
|
381
|
+
for (const file of list) {
|
|
382
|
+
const url = await onUploadImage(file);
|
|
383
|
+
await insertImageFromUrl(url);
|
|
384
|
+
}
|
|
385
|
+
} catch (err) {
|
|
386
|
+
setError(err instanceof Error ? err.message : "Upload failed");
|
|
387
|
+
} finally {
|
|
388
|
+
setBusy(false);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
async function runInsert(build) {
|
|
392
|
+
if (!canWrite || busy) return;
|
|
393
|
+
setBusy(true);
|
|
394
|
+
setError("");
|
|
395
|
+
try {
|
|
396
|
+
await onInsert(await build());
|
|
397
|
+
} catch (err) {
|
|
398
|
+
setError(err instanceof Error ? err.message : "Insert failed");
|
|
399
|
+
} finally {
|
|
400
|
+
setBusy(false);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const tabs = [
|
|
404
|
+
{ id: "uploads", label: "Uploads", icon: ImageGlyph, show: true },
|
|
405
|
+
{ id: "templates", label: "Templates", icon: TextGlyph, show: templates.length > 0 },
|
|
406
|
+
{ id: "generations", label: "Generations", icon: SparkleGlyph, show: !!loadGenerations }
|
|
407
|
+
];
|
|
408
|
+
const visibleTabs = tabs.filter((t) => t.show);
|
|
409
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex h-full min-h-0 flex-col bg-[var(--bg-input)] text-[var(--text-primary)] ${className ?? ""}`, children: [
|
|
410
|
+
/* @__PURE__ */ jsx("div", { className: "flex shrink-0 border-b border-[var(--border-default)]", children: visibleTabs.map(({ id, label, icon: Icon }) => /* @__PURE__ */ jsxs(
|
|
411
|
+
"button",
|
|
412
|
+
{
|
|
413
|
+
type: "button",
|
|
414
|
+
onClick: () => setTab(id),
|
|
415
|
+
className: `flex flex-1 items-center justify-center gap-1.5 px-2 py-2.5 text-xs font-medium transition-colors ${tab === id ? "border-b-2 border-[var(--brand-primary)] text-[var(--text-primary)]" : "text-[var(--text-muted)] hover:text-[var(--text-primary)]"}`,
|
|
416
|
+
children: [
|
|
417
|
+
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5" }),
|
|
418
|
+
label
|
|
419
|
+
]
|
|
420
|
+
},
|
|
421
|
+
id
|
|
422
|
+
)) }),
|
|
423
|
+
!canWrite ? /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-center justify-center p-4 text-center text-sm text-[var(--text-muted)]", children: "You have view-only access to this design." }) : /* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto p-3", children: [
|
|
424
|
+
tab === "uploads" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
425
|
+
/* @__PURE__ */ jsxs(
|
|
426
|
+
"button",
|
|
427
|
+
{
|
|
428
|
+
type: "button",
|
|
429
|
+
disabled: busy,
|
|
430
|
+
onClick: () => fileInputRef.current?.click(),
|
|
431
|
+
onDragOver: (e) => {
|
|
432
|
+
e.preventDefault();
|
|
433
|
+
setDragOver(true);
|
|
434
|
+
},
|
|
435
|
+
onDragLeave: () => setDragOver(false),
|
|
436
|
+
onDrop: (e) => {
|
|
437
|
+
e.preventDefault();
|
|
438
|
+
setDragOver(false);
|
|
439
|
+
if (e.dataTransfer?.files?.length) void handleFiles(e.dataTransfer.files);
|
|
440
|
+
},
|
|
441
|
+
className: `flex flex-col items-center justify-center gap-2 rounded-lg border-2 border-dashed px-4 py-8 text-center transition-colors disabled:opacity-50 ${dragOver ? "border-[var(--brand-primary)] bg-[var(--brand-primary)]/5" : "border-[var(--border-default)] hover:border-[var(--brand-primary)]/40"}`,
|
|
442
|
+
children: [
|
|
443
|
+
busy ? /* @__PURE__ */ jsx(SpinnerGlyph, { className: "h-6 w-6 text-[var(--brand-primary)]" }) : /* @__PURE__ */ jsx(UploadGlyph, { className: "h-6 w-6 text-[var(--text-muted)]" }),
|
|
444
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--text-primary)]", children: busy ? "Uploading\u2026" : "Drop an image or click to upload" }),
|
|
445
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-[var(--text-muted)]", children: "PNG, JPEG, GIF, or WebP" })
|
|
446
|
+
]
|
|
447
|
+
}
|
|
448
|
+
),
|
|
449
|
+
/* @__PURE__ */ jsx(
|
|
450
|
+
"input",
|
|
451
|
+
{
|
|
452
|
+
ref: fileInputRef,
|
|
453
|
+
type: "file",
|
|
454
|
+
accept,
|
|
455
|
+
multiple: true,
|
|
456
|
+
className: "hidden",
|
|
457
|
+
onChange: (e) => {
|
|
458
|
+
if (e.target.files?.length) void handleFiles(e.target.files);
|
|
459
|
+
e.target.value = "";
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
)
|
|
463
|
+
] }),
|
|
464
|
+
tab === "templates" && /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: templates.map((tpl) => /* @__PURE__ */ jsx(
|
|
465
|
+
"button",
|
|
466
|
+
{
|
|
467
|
+
type: "button",
|
|
468
|
+
disabled: busy,
|
|
469
|
+
onClick: () => void runInsert(() => tpl.build(page)),
|
|
470
|
+
className: "flex h-20 flex-col items-center justify-center gap-1.5 rounded-md border border-[var(--border-default)] bg-[var(--bg-input)] text-xs font-medium text-[var(--text-primary)] transition-colors hover:border-[var(--brand-primary)]/40 disabled:opacity-50",
|
|
471
|
+
children: /* @__PURE__ */ jsx("span", { children: tpl.label })
|
|
472
|
+
},
|
|
473
|
+
tpl.id
|
|
474
|
+
)) }),
|
|
475
|
+
tab === "generations" && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: !generationsLoaded ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8 text-[var(--text-muted)]", children: /* @__PURE__ */ jsx(SpinnerGlyph, { className: "h-5 w-5" }) }) : generations.length === 0 ? /* @__PURE__ */ jsx("p", { className: "px-1 py-6 text-center text-sm text-[var(--text-muted)]", children: "No generated images yet. Ask the agent to generate one." }) : /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-2", children: generations.map((gen) => /* @__PURE__ */ jsx(
|
|
476
|
+
"button",
|
|
477
|
+
{
|
|
478
|
+
type: "button",
|
|
479
|
+
disabled: busy,
|
|
480
|
+
onClick: () => {
|
|
481
|
+
if (busy || !canWrite) return;
|
|
482
|
+
setBusy(true);
|
|
483
|
+
setError("");
|
|
484
|
+
insertImageFromUrl(gen.url).catch((err) => setError(err instanceof Error ? err.message : "Insert failed")).finally(() => setBusy(false));
|
|
485
|
+
},
|
|
486
|
+
title: gen.label,
|
|
487
|
+
className: "group relative aspect-square overflow-hidden rounded-md border border-[var(--border-default)] bg-[var(--bg-input)] transition-colors hover:border-[var(--brand-primary)] disabled:opacity-50",
|
|
488
|
+
children: /* @__PURE__ */ jsx("img", { src: gen.url, alt: gen.label || "Generated image", className: "h-full w-full object-cover" })
|
|
489
|
+
},
|
|
490
|
+
gen.id
|
|
491
|
+
)) }) }),
|
|
492
|
+
error ? /* @__PURE__ */ jsx("p", { className: "mt-3 text-xs leading-5 text-[var(--text-danger,#dc2626)]", children: error }) : null
|
|
493
|
+
] })
|
|
494
|
+
] });
|
|
495
|
+
}
|
|
496
|
+
|
|
178
497
|
// src/design-canvas-react/components/LayersPanel.tsx
|
|
179
|
-
import { useMemo, useRef, useState } from "react";
|
|
498
|
+
import { useMemo, useRef as useRef2, useState as useState2 } from "react";
|
|
180
499
|
|
|
181
500
|
// src/design-canvas-react/components/layer-tree.ts
|
|
182
501
|
function flattenLayerTree(page) {
|
|
@@ -203,32 +522,32 @@ function flattenLayerTree(page) {
|
|
|
203
522
|
var LAYERS_PANEL_ROW_LIMIT = 500;
|
|
204
523
|
|
|
205
524
|
// src/design-canvas-react/components/LayersPanel.tsx
|
|
206
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
525
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
207
526
|
function KindIcon({ kind, className }) {
|
|
208
527
|
switch (kind) {
|
|
209
528
|
case "rect":
|
|
210
|
-
return /* @__PURE__ */
|
|
529
|
+
return /* @__PURE__ */ jsx2(RectGlyph, { className });
|
|
211
530
|
case "ellipse":
|
|
212
|
-
return /* @__PURE__ */
|
|
531
|
+
return /* @__PURE__ */ jsx2(EllipseGlyph, { className });
|
|
213
532
|
case "line":
|
|
214
|
-
return /* @__PURE__ */
|
|
533
|
+
return /* @__PURE__ */ jsx2(LineGlyph, { className });
|
|
215
534
|
case "text":
|
|
216
|
-
return /* @__PURE__ */
|
|
535
|
+
return /* @__PURE__ */ jsx2(TextGlyph, { className });
|
|
217
536
|
case "image":
|
|
218
|
-
return /* @__PURE__ */
|
|
537
|
+
return /* @__PURE__ */ jsx2(ImageGlyph, { className });
|
|
219
538
|
case "video":
|
|
220
|
-
return /* @__PURE__ */
|
|
539
|
+
return /* @__PURE__ */ jsx2(VideoGlyph, { className });
|
|
221
540
|
case "group":
|
|
222
|
-
return /* @__PURE__ */
|
|
541
|
+
return /* @__PURE__ */ jsx2(GroupGlyph, { className });
|
|
223
542
|
}
|
|
224
543
|
}
|
|
225
544
|
var INDENT_PX = 16;
|
|
226
545
|
function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder, onSelect }) {
|
|
227
546
|
const rows = useMemo(() => flattenLayerTree(page), [page]);
|
|
228
|
-
const [renamingId, setRenamingId] =
|
|
229
|
-
const [renameValue, setRenameValue] =
|
|
230
|
-
const dragRowRef =
|
|
231
|
-
const [dragOverIndex, setDragOverIndex] =
|
|
547
|
+
const [renamingId, setRenamingId] = useState2(null);
|
|
548
|
+
const [renameValue, setRenameValue] = useState2("");
|
|
549
|
+
const dragRowRef = useRef2(null);
|
|
550
|
+
const [dragOverIndex, setDragOverIndex] = useState2(null);
|
|
232
551
|
function startRename(element) {
|
|
233
552
|
setRenamingId(element.id);
|
|
234
553
|
setRenameValue(element.name);
|
|
@@ -239,14 +558,14 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
239
558
|
setRenamingId(null);
|
|
240
559
|
}
|
|
241
560
|
const visible = rows.length > LAYERS_PANEL_ROW_LIMIT ? rows.slice(0, LAYERS_PANEL_ROW_LIMIT) : rows;
|
|
242
|
-
return /* @__PURE__ */
|
|
243
|
-
/* @__PURE__ */
|
|
244
|
-
/* @__PURE__ */
|
|
561
|
+
return /* @__PURE__ */ jsxs2("div", { className: "flex h-full flex-col overflow-hidden text-[var(--text-primary)]", children: [
|
|
562
|
+
/* @__PURE__ */ jsx2("div", { className: "shrink-0 border-b border-[var(--border-default)] px-3 py-1.5 text-[11px] font-medium uppercase tracking-wide text-[var(--text-muted)]", children: "Layers" }),
|
|
563
|
+
/* @__PURE__ */ jsxs2("div", { className: "min-h-0 flex-1 overflow-y-auto", children: [
|
|
245
564
|
visible.map((row) => {
|
|
246
565
|
const { element } = row;
|
|
247
566
|
const isSelected = selectedElementIds.includes(element.id);
|
|
248
567
|
const isRenaming = renamingId === element.id;
|
|
249
|
-
return /* @__PURE__ */
|
|
568
|
+
return /* @__PURE__ */ jsxs2(
|
|
250
569
|
"div",
|
|
251
570
|
{
|
|
252
571
|
"data-layer-row": element.id,
|
|
@@ -285,9 +604,9 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
285
604
|
].join(" "),
|
|
286
605
|
style: { paddingLeft: 8 + row.depth * INDENT_PX },
|
|
287
606
|
children: [
|
|
288
|
-
/* @__PURE__ */
|
|
289
|
-
element.slot ? /* @__PURE__ */
|
|
290
|
-
/* @__PURE__ */
|
|
607
|
+
/* @__PURE__ */ jsx2(KindIcon, { kind: element.kind, className: "h-3.5 w-3.5 shrink-0 opacity-60" }),
|
|
608
|
+
element.slot ? /* @__PURE__ */ jsx2(SlotGlyph, { className: "h-3 w-3 shrink-0 text-[var(--brand-primary)]" }) : null,
|
|
609
|
+
/* @__PURE__ */ jsx2("span", { className: "min-w-0 flex-1 truncate", children: isRenaming ? /* @__PURE__ */ jsx2(
|
|
291
610
|
"input",
|
|
292
611
|
{
|
|
293
612
|
autoFocus: true,
|
|
@@ -302,7 +621,7 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
302
621
|
onClick: (event) => event.stopPropagation(),
|
|
303
622
|
className: "w-full rounded border border-[var(--border-default)] bg-[var(--bg-input)] px-1 py-0 text-[13px] text-[var(--text-primary)] outline-none focus:border-[var(--brand-primary)]"
|
|
304
623
|
}
|
|
305
|
-
) : /* @__PURE__ */
|
|
624
|
+
) : /* @__PURE__ */ jsx2(
|
|
306
625
|
"span",
|
|
307
626
|
{
|
|
308
627
|
onDoubleClick: (event) => {
|
|
@@ -313,7 +632,7 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
313
632
|
children: element.name
|
|
314
633
|
}
|
|
315
634
|
) }),
|
|
316
|
-
/* @__PURE__ */
|
|
635
|
+
/* @__PURE__ */ jsx2(
|
|
317
636
|
"button",
|
|
318
637
|
{
|
|
319
638
|
type: "button",
|
|
@@ -324,10 +643,10 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
324
643
|
},
|
|
325
644
|
disabled: !canWrite,
|
|
326
645
|
className: "shrink-0 rounded p-0.5 opacity-0 transition-opacity hover:opacity-100 focus:opacity-100 group-hover:opacity-100 [.flex:hover_&]:opacity-60",
|
|
327
|
-
children: element.visible ? /* @__PURE__ */
|
|
646
|
+
children: element.visible ? /* @__PURE__ */ jsx2(EyeGlyph, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsx2(EyeOffGlyph, { className: "h-3.5 w-3.5 text-[var(--text-muted)]" })
|
|
328
647
|
}
|
|
329
648
|
),
|
|
330
|
-
/* @__PURE__ */
|
|
649
|
+
/* @__PURE__ */ jsx2(
|
|
331
650
|
"button",
|
|
332
651
|
{
|
|
333
652
|
type: "button",
|
|
@@ -338,7 +657,7 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
338
657
|
},
|
|
339
658
|
disabled: !canWrite,
|
|
340
659
|
className: "shrink-0 rounded p-0.5 opacity-0 transition-opacity hover:opacity-100 focus:opacity-100 [.flex:hover_&]:opacity-60",
|
|
341
|
-
children: element.locked ? /* @__PURE__ */
|
|
660
|
+
children: element.locked ? /* @__PURE__ */ jsx2(LockGlyph, { className: "h-3.5 w-3.5 text-amber-400" }) : /* @__PURE__ */ jsx2(UnlockGlyph, { className: "h-3.5 w-3.5" })
|
|
342
661
|
}
|
|
343
662
|
)
|
|
344
663
|
]
|
|
@@ -346,7 +665,7 @@ function LayersPanel({ page, selectedElementIds, canWrite, onSetAttrs, onReorder
|
|
|
346
665
|
element.id
|
|
347
666
|
);
|
|
348
667
|
}),
|
|
349
|
-
rows.length > LAYERS_PANEL_ROW_LIMIT ? /* @__PURE__ */
|
|
668
|
+
rows.length > LAYERS_PANEL_ROW_LIMIT ? /* @__PURE__ */ jsxs2("div", { className: "px-3 py-2 text-[11px] text-[var(--text-muted)]", children: [
|
|
350
669
|
"+",
|
|
351
670
|
rows.length - LAYERS_PANEL_ROW_LIMIT,
|
|
352
671
|
" more elements \u2014 select a group to scope the list"
|
|
@@ -364,6 +683,8 @@ var DesignCanvasChromeLazy = lazy(
|
|
|
364
683
|
() => import("../DesignCanvas-JTSAL6KX.js").then((m) => ({ default: m.DesignCanvas }))
|
|
365
684
|
);
|
|
366
685
|
export {
|
|
686
|
+
CanvasInsertPanel,
|
|
687
|
+
DEFAULT_INSERT_TEMPLATES,
|
|
367
688
|
DUPLICATE_OFFSET,
|
|
368
689
|
DesignCanvas,
|
|
369
690
|
DesignCanvasChromeLazy,
|
|
@@ -373,6 +694,7 @@ export {
|
|
|
373
694
|
GridLayer,
|
|
374
695
|
LAYERS_PANEL_ROW_LIMIT,
|
|
375
696
|
LayersPanel,
|
|
697
|
+
MAX_INSERT_DIMENSION,
|
|
376
698
|
PagesStrip,
|
|
377
699
|
Rulers,
|
|
378
700
|
SCENE_COMMAND_HISTORY_LIMIT,
|
|
@@ -388,7 +710,9 @@ export {
|
|
|
388
710
|
bakeTextTransform,
|
|
389
711
|
bindSlotCommand,
|
|
390
712
|
bleedAwareExportBounds,
|
|
713
|
+
buildInsertImageOp,
|
|
391
714
|
buildRulerTicks,
|
|
715
|
+
centeredPosition,
|
|
392
716
|
collectGridTargets,
|
|
393
717
|
createSceneCommandStack,
|
|
394
718
|
createSnapEngine,
|
|
@@ -400,6 +724,7 @@ export {
|
|
|
400
724
|
duplicatePageCommand,
|
|
401
725
|
exportDocumentJson,
|
|
402
726
|
exportPageDataUrl,
|
|
727
|
+
fittedSize,
|
|
403
728
|
flattenLayerTree,
|
|
404
729
|
formatRulerLabel,
|
|
405
730
|
groupElementsCommand,
|
|
@@ -407,6 +732,7 @@ export {
|
|
|
407
732
|
isCrossOriginSrc,
|
|
408
733
|
isExportHiddenNodeName,
|
|
409
734
|
marqueeSelect,
|
|
735
|
+
mintElementId,
|
|
410
736
|
multiSetAttrsCommand,
|
|
411
737
|
nudgeDelta,
|
|
412
738
|
reorderElementCommand,
|