@pixerate/editor 0.26.0 → 0.27.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/README.md +8 -2
- package/dist/agent/index.cjs +59 -9
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +6 -4
- package/dist/agent/index.d.ts +6 -4
- package/dist/agent/index.js +52 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/{builtins-Chj6zv_O.d.ts → builtins-haN82vjT.d.ts} +33 -3
- package/dist/{builtins-CdPcLwwF.d.cts → builtins-nMXh9sT3.d.cts} +33 -3
- package/dist/canvas/index.cjs +372 -8
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +72 -4
- package/dist/canvas/index.d.ts +72 -4
- package/dist/canvas/index.js +368 -4
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-UBCFIABU.js → chunk-5H2OPMXZ.js} +183 -6
- package/dist/chunk-5H2OPMXZ.js.map +1 -0
- package/dist/{chunk-NFVBT3UZ.cjs → chunk-66IMF6OD.cjs} +108 -25
- package/dist/chunk-66IMF6OD.cjs.map +1 -0
- package/dist/{chunk-Q2OHWD2A.js → chunk-6IO7WUSU.js} +19 -5
- package/dist/chunk-6IO7WUSU.js.map +1 -0
- package/dist/{chunk-YOMYSFJU.cjs → chunk-AGR7EVRW.cjs} +49 -35
- package/dist/chunk-AGR7EVRW.cjs.map +1 -0
- package/dist/{chunk-RRREAOVM.cjs → chunk-HNDSPZ5T.cjs} +4 -4
- package/dist/{chunk-RRREAOVM.cjs.map → chunk-HNDSPZ5T.cjs.map} +1 -1
- package/dist/chunk-HXDMZQTD.cjs +497 -0
- package/dist/chunk-HXDMZQTD.cjs.map +1 -0
- package/dist/chunk-IB3ZHQAX.js +497 -0
- package/dist/chunk-IB3ZHQAX.js.map +1 -0
- package/dist/{chunk-X7HXL2SB.js → chunk-JT7AXQTE.js} +336 -10
- package/dist/chunk-JT7AXQTE.js.map +1 -0
- package/dist/{chunk-HDYMLS3X.cjs → chunk-MC2LQN5S.cjs} +196 -19
- package/dist/chunk-MC2LQN5S.cjs.map +1 -0
- package/dist/{chunk-JOIREKL7.js → chunk-UKI64KUD.js} +85 -2
- package/dist/chunk-UKI64KUD.js.map +1 -0
- package/dist/{chunk-MHEPLBFB.js → chunk-WON34HKM.js} +2 -2
- package/dist/{chunk-NQF32I6Z.cjs → chunk-YK5TATOF.cjs} +461 -135
- package/dist/chunk-YK5TATOF.cjs.map +1 -0
- package/dist/commands/index.cjs +30 -410
- package/dist/commands/index.cjs.map +1 -1
- package/dist/commands/index.d.cts +1 -1
- package/dist/commands/index.d.ts +1 -1
- package/dist/commands/index.js +17 -397
- package/dist/commands/index.js.map +1 -1
- package/dist/{controller-CxXGOEmy.d.cts → controller-w6eRTjF8.d.cts} +67 -2
- package/dist/{controller-CxXGOEmy.d.ts → controller-w6eRTjF8.d.ts} +67 -2
- package/dist/extensions/index.cjs +23 -5
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +1 -1
- package/dist/extensions/index.d.ts +1 -1
- package/dist/extensions/index.js +23 -5
- package/dist/{index-jcJwmBYt.d.cts → index-C6gaQRH0.d.cts} +53 -4
- package/dist/{index-B273Zllk.d.ts → index-DXAv_R08.d.ts} +53 -4
- package/dist/index.cjs +66 -26
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -6
- package/dist/index.d.ts +8 -6
- package/dist/index.js +46 -6
- package/dist/index.js.map +1 -1
- package/dist/serializers/index.cjs +5 -3
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +13 -3
- package/dist/serializers/index.d.ts +13 -3
- package/dist/serializers/index.js +4 -2
- package/dist/spreadsheet/index.cjs +22 -2
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +76 -3
- package/dist/spreadsheet/index.d.ts +76 -3
- package/dist/spreadsheet/index.js +21 -1
- package/package.json +1 -1
- package/dist/chunk-HDYMLS3X.cjs.map +0 -1
- package/dist/chunk-JOIREKL7.js.map +0 -1
- package/dist/chunk-NFVBT3UZ.cjs.map +0 -1
- package/dist/chunk-NQF32I6Z.cjs.map +0 -1
- package/dist/chunk-Q2OHWD2A.js.map +0 -1
- package/dist/chunk-UBCFIABU.js.map +0 -1
- package/dist/chunk-X7HXL2SB.js.map +0 -1
- package/dist/chunk-YOMYSFJU.cjs.map +0 -1
- /package/dist/{chunk-MHEPLBFB.js.map → chunk-WON34HKM.js.map} +0 -0
package/dist/canvas/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_ARRANGE_SHORTCUTS,
|
|
3
|
-
matchArrangeShortcut
|
|
4
|
-
} from "../chunk-7DWMJCAT.js";
|
|
5
1
|
import {
|
|
6
2
|
TokenError,
|
|
7
3
|
getTokenCollection,
|
|
@@ -27,6 +23,10 @@ import {
|
|
|
27
23
|
overlaps,
|
|
28
24
|
placeBeside
|
|
29
25
|
} from "../chunk-VHZCXHS4.js";
|
|
26
|
+
import {
|
|
27
|
+
DEFAULT_ARRANGE_SHORTCUTS,
|
|
28
|
+
matchArrangeShortcut
|
|
29
|
+
} from "../chunk-7DWMJCAT.js";
|
|
30
30
|
|
|
31
31
|
// src/canvas/clock.ts
|
|
32
32
|
var pageHidden = () => typeof document !== "undefined" && document.hidden;
|
|
@@ -11382,6 +11382,289 @@ function restoreCanvasMainComponent(nodes, id, options = {}) {
|
|
|
11382
11382
|
for (const nn of nested) after = rebaseInstance(after, nn, options.tokens);
|
|
11383
11383
|
return done(nodes, after, [compId], options);
|
|
11384
11384
|
}
|
|
11385
|
+
var VARIANT_GAP = 20;
|
|
11386
|
+
var variantKey = (values) => formatVariantName(values);
|
|
11387
|
+
function variantNameProblem(kind, s) {
|
|
11388
|
+
const label = kind === "property" ? "Variant property names" : "Variant values";
|
|
11389
|
+
if (!s) return `${label} must not be empty.`;
|
|
11390
|
+
if (/[,=]/.test(s)) return `${label} can't contain "," or "=".`;
|
|
11391
|
+
return void 0;
|
|
11392
|
+
}
|
|
11393
|
+
function cleanVariantPairs(pairs) {
|
|
11394
|
+
const out = {};
|
|
11395
|
+
for (const [rawKey, rawValue] of Object.entries(pairs)) {
|
|
11396
|
+
if (typeof rawValue !== "string") return `"${rawKey}" takes a text value.`;
|
|
11397
|
+
const k = rawKey.trim();
|
|
11398
|
+
const v = rawValue.trim();
|
|
11399
|
+
const problem = variantNameProblem("property", k) ?? variantNameProblem("value", v);
|
|
11400
|
+
if (problem) return problem;
|
|
11401
|
+
out[k] = v;
|
|
11402
|
+
}
|
|
11403
|
+
return out;
|
|
11404
|
+
}
|
|
11405
|
+
function variantOrder(ids, values) {
|
|
11406
|
+
const order = [];
|
|
11407
|
+
for (const id of ids) for (const k of Object.keys(values.get(id) ?? {})) if (!order.includes(k)) order.push(k);
|
|
11408
|
+
return order;
|
|
11409
|
+
}
|
|
11410
|
+
function withVariantValues(node, values, order) {
|
|
11411
|
+
const name = formatVariantName(values, order);
|
|
11412
|
+
const data = { ...dataOf(node), [COMPONENT_DATA_KEY]: { ...getComponentData(node) ?? {}, variant: values }, label: name };
|
|
11413
|
+
if (typeof data.name === "string" && data.name.includes("=")) data.name = name;
|
|
11414
|
+
return same(dataOf(node), data) ? node : withData(node, data);
|
|
11415
|
+
}
|
|
11416
|
+
function closestVariant(list, wanted) {
|
|
11417
|
+
const entries = Object.entries(wanted);
|
|
11418
|
+
let best;
|
|
11419
|
+
const better = (a, b) => {
|
|
11420
|
+
for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return a[i] > b[i];
|
|
11421
|
+
return false;
|
|
11422
|
+
};
|
|
11423
|
+
for (const v of list) {
|
|
11424
|
+
const values = getVariantValues(v);
|
|
11425
|
+
const matches2 = entries.map(([k, val]) => values[k] === val ? 1 : 0);
|
|
11426
|
+
const score = [matches2.reduce((a, b) => a + b, 0), ...matches2];
|
|
11427
|
+
if (!best || better(score, best.score)) best = { score, id: v.id };
|
|
11428
|
+
}
|
|
11429
|
+
return best?.id;
|
|
11430
|
+
}
|
|
11431
|
+
function variantEditIn(g, setId) {
|
|
11432
|
+
const set = g.get(setId);
|
|
11433
|
+
if (!isCanvasComponentSet(set)) return { code: "not-found", reason: "Choose a component set." };
|
|
11434
|
+
if (owningInstanceIn(g, setId)) return { code: "inside-instance", reason: "A component set inside an instance can't be edited: edit its main." };
|
|
11435
|
+
const variants = variantsIn(g, setId);
|
|
11436
|
+
return { set, variants, values: new Map(variants.map((v) => [v.id, getVariantValues(v)])) };
|
|
11437
|
+
}
|
|
11438
|
+
function addMissingProperties(edit, pairs, defaultValue) {
|
|
11439
|
+
const known = /* @__PURE__ */ new Set();
|
|
11440
|
+
for (const v of edit.values.values()) for (const k of Object.keys(v)) known.add(k);
|
|
11441
|
+
const added = Object.keys(pairs).filter((k) => !known.has(k));
|
|
11442
|
+
if (added.length === 0) return void 0;
|
|
11443
|
+
const problem = variantNameProblem("value", defaultValue);
|
|
11444
|
+
if (problem) return problem;
|
|
11445
|
+
const defs = dataOf(edit.set)[COMPONENT_SET_DATA_KEY]?.properties;
|
|
11446
|
+
const clash = isRecord(defs) ? added.find((k) => k in defs) : void 0;
|
|
11447
|
+
if (clash) return `"${clash}" is a component property.`;
|
|
11448
|
+
for (const [id, v] of edit.values) {
|
|
11449
|
+
const next = { ...v };
|
|
11450
|
+
for (const k of added) next[k] = defaultValue;
|
|
11451
|
+
edit.values.set(id, next);
|
|
11452
|
+
}
|
|
11453
|
+
return void 0;
|
|
11454
|
+
}
|
|
11455
|
+
function duplicateAmong(values, ids) {
|
|
11456
|
+
for (const id of ids) {
|
|
11457
|
+
const key = variantKey(values.get(id));
|
|
11458
|
+
for (const [other, v] of values) {
|
|
11459
|
+
if (other !== id && variantKey(v) === key) return formatVariantName(values.get(id), variantOrder([...values.keys()], values));
|
|
11460
|
+
}
|
|
11461
|
+
}
|
|
11462
|
+
return void 0;
|
|
11463
|
+
}
|
|
11464
|
+
function writeVariantEdit(edit, extra = []) {
|
|
11465
|
+
const order = variantOrder([...edit.variants.map((v) => v.id), ...extra], edit.values);
|
|
11466
|
+
const updates = /* @__PURE__ */ new Map();
|
|
11467
|
+
for (const v of edit.variants) {
|
|
11468
|
+
const next = withVariantValues(v, edit.values.get(v.id), order);
|
|
11469
|
+
if (next !== v) updates.set(v.id, next);
|
|
11470
|
+
}
|
|
11471
|
+
return updates;
|
|
11472
|
+
}
|
|
11473
|
+
function nextVariantValuesIn(g, setId, fromId) {
|
|
11474
|
+
const variants = variantsIn(g, setId);
|
|
11475
|
+
const base = getVariantValues(g.get(fromId));
|
|
11476
|
+
const first = variantOptionsIn(g, setId)[0];
|
|
11477
|
+
const prop = first?.name ?? "Property 1";
|
|
11478
|
+
const used = new Set(variants.map((v) => variantKey(getVariantValues(v))));
|
|
11479
|
+
for (let k = variants.length + 1; ; k++) {
|
|
11480
|
+
const values = { ...base, [prop]: `Variant${k}` };
|
|
11481
|
+
if (!first?.values.includes(`Variant${k}`) && !used.has(variantKey(values))) return values;
|
|
11482
|
+
}
|
|
11483
|
+
}
|
|
11484
|
+
function getNextVariantValues(nodes, setId, from) {
|
|
11485
|
+
const g = new Graph(nodes);
|
|
11486
|
+
return nextVariantValuesIn(g, setId, from ?? defaultVariantIn(g, setId));
|
|
11487
|
+
}
|
|
11488
|
+
function relayoutSet(nodes, setId, options) {
|
|
11489
|
+
if (options.layout === false || !getAutoLayout(nodes.find((n) => n.id === setId))) return nodes;
|
|
11490
|
+
return applyNodeUpdates(nodes, layoutUpMany(nodes, [setId], typeof options.layout === "object" ? options.layout : {}));
|
|
11491
|
+
}
|
|
11492
|
+
function addCanvasVariant(nodes, setId, options = {}) {
|
|
11493
|
+
const g = new Graph(nodes);
|
|
11494
|
+
const edit = variantEditIn(g, setId);
|
|
11495
|
+
if (!("set" in edit)) return fail(nodes, edit.code, edit.reason);
|
|
11496
|
+
if (edit.variants.length === 0) return fail(nodes, "invalid", "The set has no variant to duplicate.");
|
|
11497
|
+
const fromId = options.from ?? defaultVariantIn(g, setId);
|
|
11498
|
+
const source = edit.variants.find((v) => v.id === fromId);
|
|
11499
|
+
if (!source) return fail(nodes, "not-found", `"${fromId}" is not a variant of this set.`);
|
|
11500
|
+
const wanted = cleanVariantPairs(options.variant ?? nextVariantValuesIn(g, setId, fromId));
|
|
11501
|
+
if (typeof wanted === "string") return fail(nodes, "invalid", wanted);
|
|
11502
|
+
const problem = addMissingProperties(edit, wanted, (options.defaultValue ?? "Default").trim());
|
|
11503
|
+
if (problem) return fail(nodes, "invalid", problem);
|
|
11504
|
+
const id = options.id ?? uniqueId(`${setId}-variant`, g.byId);
|
|
11505
|
+
if (g.get(id)) return fail(nodes, "invalid", `Id "${id}" is taken.`);
|
|
11506
|
+
edit.values.set(id, { ...edit.values.get(fromId), ...wanted });
|
|
11507
|
+
const dup = duplicateAmong(edit.values, [id]);
|
|
11508
|
+
if (dup) return fail(nodes, "invalid", `A variant with ${dup} exists already.`);
|
|
11509
|
+
const autoLayout = !!getAutoLayout(edit.set);
|
|
11510
|
+
const { width, height } = getNodeSize(source);
|
|
11511
|
+
let position = options.position ? { ...options.position } : { ...source.position };
|
|
11512
|
+
if (!options.position && !autoLayout) {
|
|
11513
|
+
const rects = edit.variants.map((v) => ({ ...v.position, ...getNodeSize(v) }));
|
|
11514
|
+
position = { x: source.position.x + width + VARIANT_GAP, y: source.position.y };
|
|
11515
|
+
for (let k = 0; k <= rects.length; k++) {
|
|
11516
|
+
const hit = rects.find((r) => position.x < r.x + r.width && r.x < position.x + width && position.y < r.y + r.height && r.y < position.y + height);
|
|
11517
|
+
if (!hit) break;
|
|
11518
|
+
position = { x: hit.x + hit.width + VARIANT_GAP, y: position.y };
|
|
11519
|
+
}
|
|
11520
|
+
}
|
|
11521
|
+
const taken = new Set(g.byId.keys());
|
|
11522
|
+
taken.add(id);
|
|
11523
|
+
const map = /* @__PURE__ */ new Map([[fromId, id]]);
|
|
11524
|
+
const sub3 = g.subtree(fromId);
|
|
11525
|
+
for (const d of sub3) {
|
|
11526
|
+
if (d === fromId) continue;
|
|
11527
|
+
const nid = uniqueId(`${id}-${d}`, taken);
|
|
11528
|
+
taken.add(nid);
|
|
11529
|
+
map.set(d, nid);
|
|
11530
|
+
}
|
|
11531
|
+
const order = variantOrder([...edit.variants.map((v) => v.id), id], edit.values);
|
|
11532
|
+
const subSet = new Set(sub3);
|
|
11533
|
+
const copies = nodes.filter((n) => subSet.has(n.id)).map((n) => {
|
|
11534
|
+
const next = { ...n, id: map.get(n.id) };
|
|
11535
|
+
if (n.parentId !== void 0 && n.id !== fromId) next.parentId = map.get(n.parentId) ?? n.parentId;
|
|
11536
|
+
for (const k of RUNTIME_KEYS) delete next[k];
|
|
11537
|
+
if (n.id !== fromId) return next;
|
|
11538
|
+
next.position = position;
|
|
11539
|
+
return withVariantValues(next, edit.values.get(id), order);
|
|
11540
|
+
});
|
|
11541
|
+
const updates = writeVariantEdit(edit, [id]);
|
|
11542
|
+
const inSet = new Set(g.subtree(setId));
|
|
11543
|
+
let last = -1;
|
|
11544
|
+
nodes.forEach((n, i) => {
|
|
11545
|
+
if (inSet.has(n.id)) last = i;
|
|
11546
|
+
});
|
|
11547
|
+
let after = [];
|
|
11548
|
+
nodes.forEach((n, i) => {
|
|
11549
|
+
after.push(updates.get(n.id) ?? n);
|
|
11550
|
+
if (i === last) after.push(...copies);
|
|
11551
|
+
});
|
|
11552
|
+
if (autoLayout && !options.position) after = relayoutSet(after, setId, options);
|
|
11553
|
+
else {
|
|
11554
|
+
const size = getNodeSize(edit.set);
|
|
11555
|
+
const w = Math.max(size.width, position.x + width + VARIANT_GAP);
|
|
11556
|
+
const h = Math.max(size.height, position.y + height + VARIANT_GAP);
|
|
11557
|
+
if (w !== size.width || h !== size.height) after = applyNodeUpdates(after, [{ id: setId, width: w, height: h }]);
|
|
11558
|
+
}
|
|
11559
|
+
return done(nodes, after, [id], options);
|
|
11560
|
+
}
|
|
11561
|
+
function removeCanvasVariant(nodes, variantId, options = {}) {
|
|
11562
|
+
const g = new Graph(nodes);
|
|
11563
|
+
const set = variantSetIn(g, variantId);
|
|
11564
|
+
if (!set) return fail(nodes, "not-found", "Choose a variant of a component set.");
|
|
11565
|
+
if (owningInstanceIn(g, set.id)) return fail(nodes, "inside-instance", "A component set inside an instance can't be edited: edit its main.");
|
|
11566
|
+
const others = variantsIn(g, set.id).filter((v) => v.id !== variantId);
|
|
11567
|
+
if (others.length === 0) return fail(nodes, "invalid", "A component set needs at least one variant: delete the set instead.");
|
|
11568
|
+
const replacement = closestVariant(others, getVariantValues(g.get(variantId)));
|
|
11569
|
+
const swap = (v) => v === variantId ? replacement : v;
|
|
11570
|
+
const repointed = nodes.map((n) => {
|
|
11571
|
+
const data = dataOf(n);
|
|
11572
|
+
let next;
|
|
11573
|
+
const inst = getInstanceData(n);
|
|
11574
|
+
if (inst) {
|
|
11575
|
+
const moved = { ...inst, componentId: swap(inst.componentId) };
|
|
11576
|
+
if (inst.properties) moved.properties = Object.fromEntries(Object.entries(inst.properties).map(([k, v]) => [k, swap(v)]));
|
|
11577
|
+
if (!same(moved, inst)) next = { ...data, [INSTANCE_DATA_KEY]: moved };
|
|
11578
|
+
}
|
|
11579
|
+
for (const key of [COMPONENT_DATA_KEY, COMPONENT_SET_DATA_KEY]) {
|
|
11580
|
+
const owner = data[key];
|
|
11581
|
+
if (!isRecord(owner) || !isRecord(owner.properties)) continue;
|
|
11582
|
+
const defs = {};
|
|
11583
|
+
for (const [k, def] of Object.entries(owner.properties)) {
|
|
11584
|
+
defs[k] = def.type === "instanceSwap" ? { ...def, default: swap(def.default), ...def.preferred ? { preferred: [...new Set(def.preferred.map(swap))] } : {} } : def;
|
|
11585
|
+
}
|
|
11586
|
+
if (!same(defs, owner.properties)) next = { ...next ?? data, [key]: { ...owner, properties: defs } };
|
|
11587
|
+
}
|
|
11588
|
+
return next ? withData(n, next) : n;
|
|
11589
|
+
});
|
|
11590
|
+
const mid = syncCanvasComponents(nodes, repointed, options);
|
|
11591
|
+
const gone = new Set(new Graph(mid).subtree(variantId));
|
|
11592
|
+
const after = relayoutSet(
|
|
11593
|
+
mid.filter((n) => !gone.has(n.id)),
|
|
11594
|
+
set.id,
|
|
11595
|
+
options
|
|
11596
|
+
);
|
|
11597
|
+
return { ok: true, nodes: syncCanvasComponents(mid, after, options), ids: [replacement] };
|
|
11598
|
+
}
|
|
11599
|
+
function setCanvasVariantProperties(nodes, variantId, values, options = {}) {
|
|
11600
|
+
const g = new Graph(nodes);
|
|
11601
|
+
const set = variantSetIn(g, variantId);
|
|
11602
|
+
if (!set) return fail(nodes, "not-found", "Choose a variant of a component set.");
|
|
11603
|
+
const edit = variantEditIn(g, set.id);
|
|
11604
|
+
if (!("set" in edit)) return fail(nodes, edit.code, edit.reason);
|
|
11605
|
+
const wanted = cleanVariantPairs(values);
|
|
11606
|
+
if (typeof wanted === "string") return fail(nodes, "invalid", wanted);
|
|
11607
|
+
const problem = addMissingProperties(edit, wanted, (options.defaultValue ?? "Default").trim());
|
|
11608
|
+
if (problem) return fail(nodes, "invalid", problem);
|
|
11609
|
+
edit.values.set(variantId, { ...edit.values.get(variantId), ...wanted });
|
|
11610
|
+
const dup = duplicateAmong(edit.values, [variantId]);
|
|
11611
|
+
if (dup) return fail(nodes, "invalid", `A variant with ${dup} exists already.`);
|
|
11612
|
+
const updates = writeVariantEdit(edit);
|
|
11613
|
+
if (updates.size === 0) return { ok: true, nodes, ids: [variantId] };
|
|
11614
|
+
return done(nodes, nodes.map((n) => updates.get(n.id) ?? n), [variantId], options);
|
|
11615
|
+
}
|
|
11616
|
+
function updateInstanceValues(g, setId, updates, fn) {
|
|
11617
|
+
const ids = new Set(variantsIn(g, setId).map((v) => v.id));
|
|
11618
|
+
for (const n of g.nodes) {
|
|
11619
|
+
const inst = getInstanceData(n);
|
|
11620
|
+
if (!inst?.properties || !ids.has(inst.componentId)) continue;
|
|
11621
|
+
const props = fn({ ...inst.properties });
|
|
11622
|
+
if (same(props, inst.properties)) continue;
|
|
11623
|
+
const cur = updates.get(n.id) ?? n;
|
|
11624
|
+
updates.set(n.id, withData(cur, { ...dataOf(cur), [INSTANCE_DATA_KEY]: { ...inst, properties: props } }));
|
|
11625
|
+
}
|
|
11626
|
+
}
|
|
11627
|
+
function renameCanvasVariantProperty(nodes, setId, name, newName, options = {}) {
|
|
11628
|
+
const g = new Graph(nodes);
|
|
11629
|
+
const edit = variantEditIn(g, setId);
|
|
11630
|
+
if (!("set" in edit)) return fail(nodes, edit.code, edit.reason);
|
|
11631
|
+
const known = variantOptionsIn(g, setId);
|
|
11632
|
+
if (!known.some((o) => o.name === name)) return fail(nodes, "unknown-property", `Unknown variant property "${name}".`);
|
|
11633
|
+
const to = newName.trim();
|
|
11634
|
+
const problem = variantNameProblem("property", to);
|
|
11635
|
+
if (problem) return fail(nodes, "invalid", problem);
|
|
11636
|
+
if (to === name) return { ok: true, nodes, ids: [setId] };
|
|
11637
|
+
if (known.some((o) => o.name === to)) return fail(nodes, "invalid", `"${to}" exists already.`);
|
|
11638
|
+
if (to in propertyDefsIn(g, edit.variants[0].id)) return fail(nodes, "invalid", `"${to}" is a component property.`);
|
|
11639
|
+
const rename = (v) => Object.fromEntries(Object.entries(v).map(([k, val]) => [k === name ? to : k, val]));
|
|
11640
|
+
for (const [id, v] of edit.values) edit.values.set(id, rename(v));
|
|
11641
|
+
const updates = writeVariantEdit(edit);
|
|
11642
|
+
updateInstanceValues(g, setId, updates, (props) => name in props ? rename(props) : props);
|
|
11643
|
+
return done(nodes, nodes.map((n) => updates.get(n.id) ?? n), [setId], options);
|
|
11644
|
+
}
|
|
11645
|
+
function renameCanvasVariantValue(nodes, setId, property, value, newValue, options = {}) {
|
|
11646
|
+
const g = new Graph(nodes);
|
|
11647
|
+
const edit = variantEditIn(g, setId);
|
|
11648
|
+
if (!("set" in edit)) return fail(nodes, edit.code, edit.reason);
|
|
11649
|
+
const option = variantOptionsIn(g, setId).find((o) => o.name === property);
|
|
11650
|
+
if (!option) return fail(nodes, "unknown-property", `Unknown variant property "${property}".`);
|
|
11651
|
+
if (!option.values.includes(value)) return fail(nodes, "invalid", `"${property}" has no value "${value}".`);
|
|
11652
|
+
const to = newValue.trim();
|
|
11653
|
+
const problem = variantNameProblem("value", to);
|
|
11654
|
+
if (problem) return fail(nodes, "invalid", problem);
|
|
11655
|
+
if (to === value) return { ok: true, nodes, ids: [setId] };
|
|
11656
|
+
const touched = [];
|
|
11657
|
+
for (const [id, v] of edit.values) {
|
|
11658
|
+
if (v[property] !== value) continue;
|
|
11659
|
+
edit.values.set(id, { ...v, [property]: to });
|
|
11660
|
+
touched.push(id);
|
|
11661
|
+
}
|
|
11662
|
+
const dup = duplicateAmong(edit.values, touched);
|
|
11663
|
+
if (dup) return fail(nodes, "invalid", `A variant with ${dup} exists already.`);
|
|
11664
|
+
const updates = writeVariantEdit(edit);
|
|
11665
|
+
updateInstanceValues(g, setId, updates, (props) => props[property] === value ? { ...props, [property]: to } : props);
|
|
11666
|
+
return done(nodes, nodes.map((n) => updates.get(n.id) ?? n), [setId], options);
|
|
11667
|
+
}
|
|
11385
11668
|
|
|
11386
11669
|
// src/canvas/componentsController.ts
|
|
11387
11670
|
function makePatch(from, to) {
|
|
@@ -11449,6 +11732,24 @@ function createCanvasComponentsController(options) {
|
|
|
11449
11732
|
}
|
|
11450
11733
|
const reason = (result) => result.ok ? true : result.reason;
|
|
11451
11734
|
const nodes = () => options.getNodes();
|
|
11735
|
+
const refused = (why) => ({ ok: false, nodes: nodes(), code: "not-found", reason: why });
|
|
11736
|
+
const setOf = (id) => {
|
|
11737
|
+
const at = target(id);
|
|
11738
|
+
const node = at ? nodes().find((n) => n.id === at) : void 0;
|
|
11739
|
+
if (!node) return void 0;
|
|
11740
|
+
return isCanvasComponentSet(node) ? node.id : getVariantSet(nodes(), node.id);
|
|
11741
|
+
};
|
|
11742
|
+
const variantOf = (id) => {
|
|
11743
|
+
const at = target(id);
|
|
11744
|
+
return at && getVariantSet(nodes(), at) ? at : void 0;
|
|
11745
|
+
};
|
|
11746
|
+
const NO_SET = "Select a component set or one of its variants.";
|
|
11747
|
+
const NO_VARIANT = "Select a variant of a component set.";
|
|
11748
|
+
const addOptions = (setId, addOptions_) => {
|
|
11749
|
+
if (addOptions_.from !== void 0 || setId !== void 0) return addOptions_;
|
|
11750
|
+
const v = variantOf();
|
|
11751
|
+
return v ? { ...addOptions_, from: v } : addOptions_;
|
|
11752
|
+
};
|
|
11452
11753
|
const controller = {
|
|
11453
11754
|
sync,
|
|
11454
11755
|
/** Rebuilds every instance from its main (e.g. after loading), not recorded in history. */
|
|
@@ -11563,6 +11864,63 @@ function createCanvasComponentsController(options) {
|
|
|
11563
11864
|
(n) => setCanvasComponentProperty(n, componentId, name, def, { ...syncOptions(), ...propertyOptions })
|
|
11564
11865
|
);
|
|
11565
11866
|
},
|
|
11867
|
+
/**
|
|
11868
|
+
* Adds a variant to a set (default: the selection's set) by duplicating `from` (default:
|
|
11869
|
+
* the selected variant, else the default variant) with the given `variant` values.
|
|
11870
|
+
*/
|
|
11871
|
+
addVariant(setId, variantOptions = {}) {
|
|
11872
|
+
const set2 = setOf(setId);
|
|
11873
|
+
if (!set2) return refused(NO_SET);
|
|
11874
|
+
const opts = addOptions(setId, variantOptions);
|
|
11875
|
+
return run("Add Variant", (n) => addCanvasVariant(n, set2, { ...syncOptions(), ...opts }));
|
|
11876
|
+
},
|
|
11877
|
+
canAddVariant(setId, variantOptions = {}) {
|
|
11878
|
+
const set2 = setOf(setId);
|
|
11879
|
+
return set2 ? reason(addCanvasVariant(nodes(), set2, { ...addOptions(setId, variantOptions), layout: false })) : NO_SET;
|
|
11880
|
+
},
|
|
11881
|
+
/** Removes a variant (default: the selected one); its instances switch to the closest variant. */
|
|
11882
|
+
removeVariant(variantId) {
|
|
11883
|
+
const v = variantOf(variantId);
|
|
11884
|
+
if (!v) return refused(NO_VARIANT);
|
|
11885
|
+
return run("Remove Variant", (n) => removeCanvasVariant(n, v, syncOptions()));
|
|
11886
|
+
},
|
|
11887
|
+
canRemoveVariant(variantId) {
|
|
11888
|
+
const v = variantOf(variantId);
|
|
11889
|
+
return v ? reason(removeCanvasVariant(nodes(), v, { layout: false })) : NO_VARIANT;
|
|
11890
|
+
},
|
|
11891
|
+
/** Edits a variant's property values (default: the selected variant). */
|
|
11892
|
+
setVariantProperties(values, variantId, variantOptions = {}) {
|
|
11893
|
+
const v = variantOf(variantId);
|
|
11894
|
+
if (!v) return refused(NO_VARIANT);
|
|
11895
|
+
return run("Edit Variant", (n) => setCanvasVariantProperties(n, v, values, { ...syncOptions(), ...variantOptions }));
|
|
11896
|
+
},
|
|
11897
|
+
canSetVariantProperties(values, variantId) {
|
|
11898
|
+
const v = variantOf(variantId);
|
|
11899
|
+
if (!v) return NO_VARIANT;
|
|
11900
|
+
return values ? reason(setCanvasVariantProperties(nodes(), v, values, { layout: false })) : true;
|
|
11901
|
+
},
|
|
11902
|
+
/** Renames a variant property across a set (default: the selection's set). */
|
|
11903
|
+
renameVariantProperty(name, newName, setId) {
|
|
11904
|
+
const set2 = setOf(setId);
|
|
11905
|
+
if (!set2) return refused(NO_SET);
|
|
11906
|
+
return run("Rename Variant Property", (n) => renameCanvasVariantProperty(n, set2, name, newName, syncOptions()));
|
|
11907
|
+
},
|
|
11908
|
+
canRenameVariantProperty(name, newName, setId) {
|
|
11909
|
+
const set2 = setOf(setId);
|
|
11910
|
+
if (!set2) return NO_SET;
|
|
11911
|
+
return name !== void 0 && newName !== void 0 ? reason(renameCanvasVariantProperty(nodes(), set2, name, newName, { layout: false })) : true;
|
|
11912
|
+
},
|
|
11913
|
+
/** Renames a value of a variant property across a set (default: the selection's set). */
|
|
11914
|
+
renameVariantValue(property, value, newValue, setId) {
|
|
11915
|
+
const set2 = setOf(setId);
|
|
11916
|
+
if (!set2) return refused(NO_SET);
|
|
11917
|
+
return run("Rename Variant Value", (n) => renameCanvasVariantValue(n, set2, property, value, newValue, syncOptions()));
|
|
11918
|
+
},
|
|
11919
|
+
canRenameVariantValue(property, value, newValue, setId) {
|
|
11920
|
+
const set2 = setOf(setId);
|
|
11921
|
+
if (!set2) return NO_SET;
|
|
11922
|
+
return property !== void 0 && value !== void 0 && newValue !== void 0 ? reason(renameCanvasVariantValue(nodes(), set2, property, value, newValue, { layout: false })) : true;
|
|
11923
|
+
},
|
|
11566
11924
|
/** Binds (or with `null` unbinds) a main layer's field to a component property. */
|
|
11567
11925
|
bindComponentProperty(layerId, field, name) {
|
|
11568
11926
|
return run("Bind Component Property", (n) => bindCanvasComponentProperty(n, layerId, field, name, syncOptions()));
|
|
@@ -11644,6 +12002,7 @@ export {
|
|
|
11644
12002
|
StreamingLayoutManager,
|
|
11645
12003
|
TOKEN_BINDINGS_DATA_KEY,
|
|
11646
12004
|
TOKEN_MODES_DATA_KEY,
|
|
12005
|
+
addCanvasVariant,
|
|
11647
12006
|
addKeyframesAtTime,
|
|
11648
12007
|
alignNodes,
|
|
11649
12008
|
animateNode,
|
|
@@ -11767,6 +12126,7 @@ export {
|
|
|
11767
12126
|
getLayoutParent,
|
|
11768
12127
|
getLayoutSizing,
|
|
11769
12128
|
getLayoutedNodes,
|
|
12129
|
+
getNextVariantValues,
|
|
11770
12130
|
getNodeAnimation,
|
|
11771
12131
|
getNodeOverrides,
|
|
11772
12132
|
getNodeRect,
|
|
@@ -11880,7 +12240,10 @@ export {
|
|
|
11880
12240
|
recordAnimationChanges,
|
|
11881
12241
|
relayoutUpdates,
|
|
11882
12242
|
remapPastedNodes,
|
|
12243
|
+
removeCanvasVariant,
|
|
11883
12244
|
removeTrack,
|
|
12245
|
+
renameCanvasVariantProperty,
|
|
12246
|
+
renameCanvasVariantValue,
|
|
11884
12247
|
reorderNodes,
|
|
11885
12248
|
repositionNodesTo,
|
|
11886
12249
|
resetCanvasInstanceOverrides,
|
|
@@ -11908,6 +12271,7 @@ export {
|
|
|
11908
12271
|
setCanvasComponentProperty,
|
|
11909
12272
|
setCanvasInstanceProperties,
|
|
11910
12273
|
setCanvasTokenMode,
|
|
12274
|
+
setCanvasVariantProperties,
|
|
11911
12275
|
setKeyframe,
|
|
11912
12276
|
setKeyframeEasing,
|
|
11913
12277
|
setMotionPath,
|