@pixerate/editor 0.271.0 → 0.272.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/dist/agent/index.cjs +34 -32
  2. package/dist/agent/index.js +10 -8
  3. package/dist/animation-editor/index.cjs +60 -60
  4. package/dist/animation-editor/index.js +4 -4
  5. package/dist/brushes/index.cjs +69 -66
  6. package/dist/brushes/index.js +6 -3
  7. package/dist/brushes/patch.d.cts +1 -1
  8. package/dist/brushes/patch.d.ts +1 -1
  9. package/dist/brushes/schema.d.cts +1 -0
  10. package/dist/brushes/schema.d.ts +1 -0
  11. package/dist/brushes/types.d.cts +8 -0
  12. package/dist/brushes/types.d.ts +8 -0
  13. package/dist/{brushstrokeRender-WR2N5HHY.cjs → brushstrokeRender-5YBCLFDQ.cjs} +15 -15
  14. package/dist/{brushstrokeRender-A727TTNQ.js → brushstrokeRender-DZGFU3J4.js} +3 -3
  15. package/dist/canvas/index.cjs +13 -13
  16. package/dist/canvas/index.js +1 -1
  17. package/dist/chart/contract.d.cts +95 -0
  18. package/dist/chart/contract.d.ts +95 -0
  19. package/dist/chart/controller.d.cts +4 -0
  20. package/dist/chart/controller.d.ts +4 -0
  21. package/dist/chart/index.cjs +492 -26
  22. package/dist/chart/index.d.cts +1 -0
  23. package/dist/chart/index.d.ts +1 -0
  24. package/dist/chart/index.js +476 -10
  25. package/dist/chart/tools.d.cts +3 -0
  26. package/dist/chart/tools.d.ts +3 -0
  27. package/dist/chart-maps/index.cjs +4 -64
  28. package/dist/chart-maps/index.js +3 -63
  29. package/dist/{chunk-YNFSH72F.js → chunk-2F3YDXCN.js} +1 -1
  30. package/dist/{chunk-QYXUE37Q.js → chunk-2XDNF73E.js} +1 -1
  31. package/dist/{chunk-3KNQ2W6X.cjs → chunk-3JKCREEU.cjs} +59 -53
  32. package/dist/{chunk-NMZQMPFZ.js → chunk-4LZQO5Y7.js} +2 -0
  33. package/dist/{chunk-B5W677L7.js → chunk-5HP2VSAS.js} +1 -1
  34. package/dist/chunk-5UGRMVNE.js +328 -0
  35. package/dist/{chunk-X4FTNFIA.js → chunk-7MGPW2OV.js} +1 -1
  36. package/dist/{chunk-BPJSI4NT.cjs → chunk-7W2EQQBP.cjs} +2 -2
  37. package/dist/{chunk-DGITFN73.cjs → chunk-BWJBZAUE.cjs} +8 -8
  38. package/dist/chunk-CHZYVNXZ.js +336 -0
  39. package/dist/{chunk-LETF75CA.js → chunk-CLB2I2FU.js} +1 -1
  40. package/dist/chunk-DRMZ5R3S.cjs +67 -0
  41. package/dist/{chunk-BAZMCFVL.js → chunk-DZVRH63Y.js} +1 -1
  42. package/dist/chunk-EI5GFTKG.js +67 -0
  43. package/dist/{chunk-U2ASNGO6.cjs → chunk-FXVCB6YG.cjs} +35 -35
  44. package/dist/{chunk-EU2ZZA6L.cjs → chunk-GHGBIAWQ.cjs} +126 -39
  45. package/dist/chunk-JV7DKLMX.js +1073 -0
  46. package/dist/{chunk-2WOGXEDX.cjs → chunk-M3RZOF3G.cjs} +1 -1
  47. package/dist/chunk-MFBUQC67.cjs +328 -0
  48. package/dist/{chunk-GSTSZPSR.js → chunk-N3SKPQEH.js} +225 -18
  49. package/dist/{chunk-J5VQYK7T.cjs → chunk-N5IMDAHM.cjs} +251 -44
  50. package/dist/{chunk-ININNHLM.js → chunk-NAHJV3O6.js} +11 -5
  51. package/dist/{chunk-IBXEQOGI.js → chunk-PYHB2EHE.js} +2 -324
  52. package/dist/chunk-QEUI6OGE.cjs +336 -0
  53. package/dist/{chunk-6ZSFRRJI.js → chunk-RSF6BT34.js} +1 -1
  54. package/dist/{chunk-JJ2H25JG.cjs → chunk-SNAFFCAX.cjs} +200 -174
  55. package/dist/chunk-T2HUQBRC.cjs +1073 -0
  56. package/dist/{chunk-M2ZVPU7L.cjs → chunk-TNLKFW7D.cjs} +23 -23
  57. package/dist/{chunk-KZI3YWKW.js → chunk-UXYCY3HP.js} +93 -6
  58. package/dist/{chunk-GSLOH2IN.cjs → chunk-VF6ODSYX.cjs} +2 -0
  59. package/dist/{chunk-NQUKTRKN.cjs → chunk-WZLNNGG3.cjs} +45 -45
  60. package/dist/{chunk-NRBGAEFI.cjs → chunk-Y3RUYOOW.cjs} +8 -330
  61. package/dist/{chunk-DDL3ZBHK.cjs → chunk-YJANF2BL.cjs} +86 -86
  62. package/dist/{chunk-TNHDCP4R.js → chunk-ZEI7ZEA4.js} +31 -5
  63. package/dist/commands/index.cjs +7 -323
  64. package/dist/commands/index.js +5 -321
  65. package/dist/extensions/index.cjs +4 -4
  66. package/dist/extensions/index.js +3 -3
  67. package/dist/image-editor/index.cjs +789 -789
  68. package/dist/image-editor/index.js +5 -5
  69. package/dist/index.cjs +9 -9
  70. package/dist/index.js +3 -3
  71. package/dist/paint/index.cjs +2 -2
  72. package/dist/paint/index.js +1 -1
  73. package/dist/paint/wet/world.d.cts +37 -1
  74. package/dist/paint/wet/world.d.ts +37 -1
  75. package/dist/paint-editor/brush-controls.d.cts +2 -0
  76. package/dist/paint-editor/brush-controls.d.ts +2 -0
  77. package/dist/paint-editor/brush-model.d.cts +14 -1
  78. package/dist/paint-editor/brush-model.d.ts +14 -1
  79. package/dist/paint-editor/index.cjs +343 -306
  80. package/dist/paint-editor/index.js +48 -11
  81. package/dist/paint-editor/ui.d.cts +1 -1
  82. package/dist/paint-editor/ui.d.ts +1 -1
  83. package/dist/paint-editor/wet.d.cts +8 -1
  84. package/dist/paint-editor/wet.d.ts +8 -1
  85. package/dist/persistence/index.cjs +24 -1042
  86. package/dist/persistence/index.js +22 -1040
  87. package/dist/tools/index.cjs +5 -3
  88. package/dist/tools/index.js +8 -6
  89. package/dist/vector/index.cjs +999 -999
  90. package/dist/vector/index.js +5 -5
  91. package/package.json +1 -1
  92. package/skills/pixerate-brushes/SKILL.md +1 -0
  93. package/skills/pixerate-paint-editor/SKILL.md +4 -11
  94. package/skills/pixerate-paint-editor/references/brush-facets.md +1 -0
  95. package/skills/pixerate-paint-editor/references/ghost.md +47 -0
  96. package/skills/pixerate-paint-watercolour/SKILL.md +1 -0
@@ -8,7 +8,7 @@ import {
8
8
  listPresets,
9
9
  normalizeBrushSpec,
10
10
  resolveBrush
11
- } from "./chunk-KZI3YWKW.js";
11
+ } from "./chunk-UXYCY3HP.js";
12
12
  import {
13
13
  editorStampOf,
14
14
  stampCoverage
@@ -61,6 +61,7 @@ import {
61
61
  DEFAULT_FLOW,
62
62
  DEFAULT_WET_PARAMS,
63
63
  FLAT,
64
+ FREE_INTERVAL,
64
65
  PIGMENT_UNIT,
65
66
  WET_TILE,
66
67
  WetMedium,
@@ -73,7 +74,7 @@ import {
73
74
  normalizeTilt,
74
75
  normalizeWetParams,
75
76
  pigmentOf
76
- } from "./chunk-GSTSZPSR.js";
77
+ } from "./chunk-N3SKPQEH.js";
77
78
  import {
78
79
  BrushstrokeCache,
79
80
  brushstrokeDataUrl,
@@ -3729,12 +3730,17 @@ var WetStrokeDriver = class {
3729
3730
  const spacing = Math.max(0.02, brush.tip.spacing);
3730
3731
  const perDab = Math.min(1, spacing * 1.2);
3731
3732
  const thin = wet.thinner;
3733
+ const body = wet.body * (1 - thin);
3732
3734
  this.medium = new WetMedium(init.world, init.laneId, {
3733
3735
  water: STROKE_WATER * Math.min(1, wet.water * (1 + thin)) * perDab,
3734
3736
  mass: STROKE_MASS * wet.pigment * (1 - 0.6 * thin) * perDab,
3735
- body: wet.body * (1 - thin),
3737
+ body,
3736
3738
  light: 0
3737
3739
  });
3740
+ if (wet.tool === "paint" && brush.ghost && wet.pigment > 0) {
3741
+ const one = pigmentOf(init.color, body);
3742
+ init.world.startGhost(init.laneId, [one[0], one[1], one[2], one[3]], brush.ghost.linger, init.speed ?? 120);
3743
+ }
3738
3744
  this.lightBase = wet.tool === "paint" ? STROKE_LIGHT * brush.light.amount * (1 - 0.6 * thin) * perDab : 0;
3739
3745
  const rates = exchangeRates(brush.behavior.pickup, brush.behavior.mix, wet.load, brush.behavior.mixing);
3740
3746
  this.states = copies.map((c, i) => ({
@@ -3863,6 +3869,22 @@ var WetStrokeDriver = class {
3863
3869
  if (!(k > 0)) return;
3864
3870
  switch (wet.tool) {
3865
3871
  case "paint": {
3872
+ if (brush.ghost) {
3873
+ const smear = brush.ghost.smear;
3874
+ if (wet.pigment > 0) {
3875
+ this.medium.options.light = this.medium.options.mass;
3876
+ this.medium.deposit(rect, cov, k, this.init.color, null);
3877
+ } else {
3878
+ this.medium.options.light = 0;
3879
+ world.paint(laneId, rect, cov, this.medium.options.water * k * (wet.water > 0 ? 1 : 0), null);
3880
+ }
3881
+ if (smear > 0) {
3882
+ const rw = Math.max(wet.rewet, 0.6) * smear;
3883
+ if (rw > 0) world.rewet(laneId, rect, cov, rw * k * 0.5, this.init.paperColor, true);
3884
+ if (st.last) world.drag(laneId, rect, tip, d.x - st.last.x, d.y - st.last.y, smear * k);
3885
+ }
3886
+ break;
3887
+ }
3866
3888
  const ex = st.exchange;
3867
3889
  this.medium.options.light = this.lightBase * (brush.light.pressure ? d.pressure : 1);
3868
3890
  let flow = 1;
@@ -4093,7 +4115,7 @@ var PaintWetLayers = class {
4093
4115
  if (!w.hasLane(layerId)) {
4094
4116
  const base = this.host.layerSurface(layerId) ?? new TiledSurface(4, /* @__PURE__ */ new Map(), 0);
4095
4117
  const s = this.settingsOf(layerId, medium);
4096
- w.ensureLane(layerId, { params: s.params, base, light: this.host.layerLight(layerId) });
4118
+ w.ensureLane(layerId, { params: s.params, base, light: this.host.layerLight(layerId), ghost: s.ghost });
4097
4119
  const { width, height } = this.host.canvas();
4098
4120
  if (s.flow.kind !== "none") w.setFlow(layerId, flowField(s.flow, width, height), s.flow.strength);
4099
4121
  }
@@ -4127,6 +4149,7 @@ var PaintWetLayers = class {
4127
4149
  info(layerId) {
4128
4150
  const s = this.settingsOf(layerId);
4129
4151
  const st = this.world?.hasLane(layerId) ? this.world.stats(layerId) : null;
4152
+ const g = this.world?.hasLane(layerId) ? this.world.getGhost(layerId) : s.ghost ?? null;
4130
4153
  return {
4131
4154
  layerId,
4132
4155
  wet: Boolean(st && st.wetCells > 0),
@@ -4134,7 +4157,8 @@ var PaintWetLayers = class {
4134
4157
  wetBounds: st?.wetBounds ?? null,
4135
4158
  activeTiles: st?.activeTiles ?? 0,
4136
4159
  params: { ...s.params },
4137
- flow: { ...s.flow }
4160
+ flow: { ...s.flow },
4161
+ ...g ? { ghost: { remaining: Math.round(g.remaining * FREE_INTERVAL / this.speed * 100) / 100 } } : {}
4138
4162
  };
4139
4163
  }
4140
4164
  backend() {
@@ -4191,6 +4215,8 @@ var PaintWetLayers = class {
4191
4215
  const base = w.getBase(id);
4192
4216
  const light = w.isLit(id) ? w.getLight(id) : null;
4193
4217
  w.removeLane(id);
4218
+ const s = this.settings.get(id);
4219
+ if (s?.ghost) delete s.ghost;
4194
4220
  if (light && this.host.layerLight(id) !== light) this.host.updateLights(/* @__PURE__ */ new Map([[id, light]]));
4195
4221
  this.host.updateSurfaces(/* @__PURE__ */ new Map([[id, base]]), []);
4196
4222
  }
@@ -1,4 +1,9 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});
2
+
3
+
4
+
5
+ var _chunkQEUI6OGEcjs = require('../chunk-QEUI6OGE.cjs');
6
+
2
7
 
3
8
 
4
9
 
@@ -50,327 +55,6 @@ var _chunkVCL7CB56cjs = require('../chunk-VCL7CB56.cjs');
50
55
  require('../chunk-K7ENM55P.cjs');
51
56
  require('../chunk-WOFXZ3XU.cjs');
52
57
 
53
- // src/commands/paletteController.ts
54
- function createCommandPaletteController(registry, options = {}) {
55
- const listeners = /* @__PURE__ */ new Set();
56
- let open = false;
57
- let query = "";
58
- let activeIndex = 0;
59
- let recents = [..._nullishCoalesce(options.recents, () => ( []))];
60
- let lastResult = null;
61
- let state;
62
- const context = () => {
63
- const c = options.context;
64
- if (c === void 0) return registry.context;
65
- return typeof c === "function" ? c() : c;
66
- };
67
- const scope = () => typeof options.scope === "function" ? options.scope() : options.scope;
68
- function computeItems() {
69
- if (!open) return [];
70
- const entries = registry.list({ scope: scope(), context: context() });
71
- const platform = _nullishCoalesce(options.platform, () => ( registry.shortcuts.platform));
72
- return _chunkKIJIONZFcjs.rankCommands.call(void 0, query, entries, {
73
- recents,
74
- recentLimit: options.recentLimit,
75
- limit: _nullishCoalesce(options.limit, () => ( 50))
76
- }).map((ranked) => ({
77
- ...ranked,
78
- id: ranked.entry.id,
79
- label: ranked.entry.label,
80
- ...ranked.entry.group !== void 0 ? { group: ranked.entry.group } : {},
81
- ...ranked.entry.shortcuts[0] ? { shortcut: _chunkQJVOJUTDcjs.formatShortcut.call(void 0, ranked.entry.shortcuts[0], platform) } : {},
82
- enabled: ranked.entry.enabled,
83
- ...ranked.entry.disabledReason ? { disabledReason: ranked.entry.disabledReason } : {}
84
- }));
85
- }
86
- function update() {
87
- const items = computeItems();
88
- activeIndex = items.length === 0 ? 0 : Math.min(Math.max(activeIndex, 0), items.length - 1);
89
- state = { open, query, activeIndex, items, recents, lastResult };
90
- for (const listener of Array.from(listeners)) listener(state);
91
- }
92
- state = { open, query, activeIndex, items: [], recents, lastResult };
93
- let unsubscribeRegistry = null;
94
- const onRegistryChange = () => {
95
- if (open) update();
96
- };
97
- const controller = {
98
- getState: () => state,
99
- subscribe(listener) {
100
- listeners.add(listener);
101
- unsubscribeRegistry ??= registry.subscribe(onRegistryChange);
102
- if (open) update();
103
- return () => {
104
- listeners.delete(listener);
105
- if (listeners.size === 0) {
106
- _optionalChain([unsubscribeRegistry, 'optionalCall', _ => _()]);
107
- unsubscribeRegistry = null;
108
- }
109
- };
110
- },
111
- setOpen(next) {
112
- if (next === open) return;
113
- open = next;
114
- query = "";
115
- activeIndex = 0;
116
- update();
117
- },
118
- toggle() {
119
- controller.setOpen(!open);
120
- },
121
- setQuery(next) {
122
- if (next === query) return;
123
- query = next;
124
- activeIndex = 0;
125
- update();
126
- },
127
- setActiveIndex(index) {
128
- activeIndex = index;
129
- update();
130
- },
131
- /** Moves the active row by `delta`, wrapping around. */
132
- move(delta) {
133
- const n = state.items.length;
134
- if (n === 0) return;
135
- activeIndex = ((activeIndex + delta) % n + n) % n;
136
- update();
137
- },
138
- /** Runs a command by id, closes the palette and records it as recent. Disabled commands do nothing. */
139
- run(id) {
140
- if (!registry.isEnabled(id, void 0, context()).enabled) return null;
141
- open = false;
142
- query = "";
143
- activeIndex = 0;
144
- recents = _chunkKIJIONZFcjs.pushRecent.call(void 0, recents, id, _nullishCoalesce(options.recentLimit, () => ( _chunkKIJIONZFcjs.DEFAULT_RECENT_LIMIT)));
145
- _optionalChain([options, 'access', _2 => _2.onRecentsChange, 'optionalCall', _3 => _3(recents)]);
146
- const result = registry.execute(id, void 0, context());
147
- lastResult = result;
148
- update();
149
- _optionalChain([options, 'access', _4 => _4.onRun, 'optionalCall', _5 => _5(result)]);
150
- return result;
151
- },
152
- runActive() {
153
- const item = state.items[state.activeIndex];
154
- return item ? controller.run(item.id) : null;
155
- },
156
- /**
157
- * Keyboard handling for the palette input: ArrowUp/ArrowDown (wrap), Home/End,
158
- * Enter (run the active row) and Escape (close). Returns whether it handled the key.
159
- */
160
- handleKeyDown(event) {
161
- if (!open) return false;
162
- switch (event.key) {
163
- case "ArrowDown":
164
- controller.move(1);
165
- break;
166
- case "ArrowUp":
167
- controller.move(-1);
168
- break;
169
- case "Home":
170
- controller.setActiveIndex(0);
171
- break;
172
- case "End":
173
- controller.setActiveIndex(state.items.length - 1);
174
- break;
175
- case "Enter":
176
- controller.runActive();
177
- break;
178
- case "Escape":
179
- controller.setOpen(false);
180
- break;
181
- default:
182
- return false;
183
- }
184
- _optionalChain([event, 'access', _6 => _6.preventDefault, 'optionalCall', _7 => _7()]);
185
- return true;
186
- },
187
- /** Re-reads commands and enablement. */
188
- refresh() {
189
- update();
190
- },
191
- destroy() {
192
- _optionalChain([unsubscribeRegistry, 'optionalCall', _8 => _8()]);
193
- unsubscribeRegistry = null;
194
- listeners.clear();
195
- }
196
- };
197
- return controller;
198
- }
199
- function matchPaletteHotkey(event, hotkey, platform) {
200
- const map = new (0, _chunkQJVOJUTDcjs.ShortcutMap)([{ command: "palette", chord: hotkey, allowInEditable: true }], platform ? { platform } : {});
201
- return map.resolve(event) !== null;
202
- }
203
-
204
- // src/commands/animation.ts
205
- var EASING_DESCRIPTION = "Easing preset (linear, ease, ease-in, ease-out, ease-in-out, ease-in-back, ease-out-back, spring, hold) or a CSS cubic-bezier(x1, y1, x2, y2).";
206
- var VALUES = {
207
- type: "object",
208
- description: 'Property \u2192 value, e.g. {"x": 200, "opacity": 0.5, "fill": "#ff0000"}. Properties: x, y, width, height, rotation (degrees), scale, opacity (0\u20131), fill, stroke, strokeWidth, cornerRadius, motionPath (0\u20131).',
209
- additionalProperties: { type: ["number", "string"] }
210
- };
211
- function createCanvasAnimationCommands(controller, options = {}) {
212
- const prefix = _nullishCoalesce(options.prefix, () => ( "canvas.animation."));
213
- const group = _nullishCoalesce(options.group, () => ( "Animation"));
214
- const scope = options.scope === null ? void 0 : _nullishCoalesce(options.scope, () => ( "canvas"));
215
- const base = { group, ...scope ? { scope } : {} };
216
- const hasSelection = () => controller.getState().selection.length > 0 ? true : "Select keyframes first.";
217
- return [
218
- {
219
- ...base,
220
- id: `${prefix}togglePlay`,
221
- label: "Play / Pause Animation",
222
- keywords: ["play", "pause", "preview", "timeline"],
223
- description: "Plays or pauses the canvas animation from the playhead.",
224
- run: () => {
225
- controller.toggle();
226
- return { playing: controller.getState().playing, time: controller.getState().time };
227
- }
228
- },
229
- {
230
- ...base,
231
- id: `${prefix}play`,
232
- label: "Play Animation",
233
- keywords: ["preview", "timeline"],
234
- enabled: () => controller.getState().playing ? "Already playing." : true,
235
- run: () => controller.play()
236
- },
237
- {
238
- ...base,
239
- id: `${prefix}pause`,
240
- label: "Pause Animation",
241
- enabled: () => controller.getState().playing ? true : "Not playing.",
242
- run: () => controller.pause()
243
- },
244
- {
245
- ...base,
246
- id: `${prefix}stop`,
247
- label: "Stop Animation",
248
- keywords: ["rewind", "reset"],
249
- description: "Stops playback and returns to the start.",
250
- run: () => controller.stop()
251
- },
252
- {
253
- ...base,
254
- id: `${prefix}seek`,
255
- label: "Go to Time\u2026",
256
- keywords: ["playhead", "scrub", "time"],
257
- description: "Moves the playhead.",
258
- params: {
259
- type: "object",
260
- properties: { time: { type: "number", minimum: 0, description: "Time in milliseconds." } },
261
- required: ["time"]
262
- },
263
- run: (_ctx, params) => {
264
- controller.seek(params.time);
265
- return { time: controller.getState().time };
266
- }
267
- },
268
- {
269
- ...base,
270
- id: `${prefix}addKeyframe`,
271
- label: "Add Keyframe at Playhead",
272
- keywords: ["key", "animate", "record"],
273
- description: "Keys the selected nodes (or `ids`) at the playhead (or `time`): their animated properties, `properties`, or position.",
274
- params: {
275
- type: "object",
276
- properties: {
277
- ids: { type: "array", items: { type: "string" }, description: "Node ids (default: selected nodes)." },
278
- properties: { type: "array", items: { type: "string" }, description: "Properties to key (default: animated ones, or x and y)." },
279
- time: { type: "number", minimum: 0, description: "Time in ms (default: the playhead)." }
280
- }
281
- },
282
- run: (_ctx, params) => controller.addKeyframe(_optionalChain([params, 'optionalAccess', _9 => _9.ids]), _optionalChain([params, 'optionalAccess', _10 => _10.properties]), _optionalChain([params, 'optionalAccess', _11 => _11.time]))
283
- },
284
- {
285
- ...base,
286
- id: `${prefix}deleteKeyframes`,
287
- label: "Delete Keyframes",
288
- keywords: ["remove", "clear"],
289
- enabled: hasSelection,
290
- run: () => controller.deleteKeyframes()
291
- },
292
- {
293
- ...base,
294
- id: `${prefix}setEasing`,
295
- label: "Set Keyframe Easing\u2026",
296
- keywords: ["interpolation", "ease", "bezier", "spring", "hold", "curve"],
297
- description: "Sets the easing of the segments leaving the selected keyframes.",
298
- params: {
299
- type: "object",
300
- properties: { easing: { type: "string", description: EASING_DESCRIPTION } },
301
- required: ["easing"]
302
- },
303
- enabled: hasSelection,
304
- run: (_ctx, params) => controller.setEasing(params.easing)
305
- },
306
- {
307
- ...base,
308
- id: `${prefix}toggleRecord`,
309
- label: "Toggle Record Mode",
310
- keywords: ["auto key", "record", "keyframe"],
311
- description: "In record mode, changing a property at the playhead keys it.",
312
- run: () => {
313
- controller.toggleRecording();
314
- return { recording: controller.getState().recording };
315
- }
316
- },
317
- {
318
- ...base,
319
- id: `${prefix}nextKeyframe`,
320
- label: "Next Keyframe",
321
- keywords: ["jump", "navigate"],
322
- run: () => controller.nextKeyframe()
323
- },
324
- {
325
- ...base,
326
- id: `${prefix}previousKeyframe`,
327
- label: "Previous Keyframe",
328
- keywords: ["jump", "navigate"],
329
- run: () => controller.previousKeyframe()
330
- },
331
- {
332
- ...base,
333
- id: `${prefix}animateNode`,
334
- label: "Animate Node\u2026",
335
- keywords: ["tween", "transition", "move", "fade"],
336
- description: "Animates a node from `from` (default: its current values) to `to` over `duration` ms, starting at `delay` ms.",
337
- params: {
338
- type: "object",
339
- properties: {
340
- nodeId: { type: "string", description: "Node to animate." },
341
- to: VALUES,
342
- from: VALUES,
343
- duration: { type: "number", exclusiveMinimum: 0, description: "Duration in ms (default 1000)." },
344
- delay: { type: "number", minimum: 0, description: "Start time in ms (default 0)." },
345
- easing: { type: "string", description: EASING_DESCRIPTION }
346
- },
347
- required: ["nodeId", "to"]
348
- },
349
- run: (_ctx, params) => controller.animateNode(params.nodeId, {
350
- to: params.to,
351
- ...params.from ? { from: params.from } : {},
352
- ...params.duration !== void 0 ? { duration: params.duration } : {},
353
- ...params.delay !== void 0 ? { delay: params.delay } : {},
354
- ...params.easing !== void 0 ? { easing: params.easing } : {}
355
- })
356
- },
357
- {
358
- ...base,
359
- id: `${prefix}exportCss`,
360
- label: "Export Animation as CSS",
361
- keywords: ["keyframes", "css", "web animations"],
362
- description: "Returns CSS @keyframes for a node's animation.",
363
- readOnly: true,
364
- params: {
365
- type: "object",
366
- properties: { nodeId: { type: "string" } },
367
- required: ["nodeId"]
368
- },
369
- run: (_ctx, params) => controller.exportCss(params.nodeId)
370
- }
371
- ];
372
- }
373
-
374
58
 
375
59
 
376
60
 
@@ -413,4 +97,4 @@ function createCanvasAnimationCommands(controller, options = {}) {
413
97
 
414
98
 
415
99
 
416
- exports.CommandRegistry = _chunkKIJIONZFcjs.CommandRegistry; exports.CommandRegistryError = _chunkKIJIONZFcjs.CommandRegistryError; exports.DEFAULT_HISTORY_SHORTCUTS = _chunkQEVLRLUNcjs.DEFAULT_HISTORY_SHORTCUTS; exports.DEFAULT_RECENT_LIMIT = _chunkKIJIONZFcjs.DEFAULT_RECENT_LIMIT; exports.PLATFORMS = _chunkQJVOJUTDcjs.PLATFORMS; exports.ShortcutMap = _chunkQJVOJUTDcjs.ShortcutMap; exports.chordToString = _chunkQJVOJUTDcjs.chordToString; exports.codeFromKey = _chunkQJVOJUTDcjs.codeFromKey; exports.codeToKeyText = _chunkQJVOJUTDcjs.codeToKeyText; exports.createArrangeCommands = _chunkQEVLRLUNcjs.createArrangeCommands; exports.createCanvasAnimationCommands = createCanvasAnimationCommands; exports.createCommandPaletteController = createCommandPaletteController; exports.createCommandRegistry = _chunkKIJIONZFcjs.createCommandRegistry; exports.createCommandToolProvider = _chunkKIJIONZFcjs.createCommandToolProvider; exports.createComponentCommands = _chunkQEVLRLUNcjs.createComponentCommands; exports.createDrawCommands = _chunkQEVLRLUNcjs.createDrawCommands; exports.createFormatCommands = _chunkVCL7CB56cjs.createFormatCommands; exports.createHistoryCommands = _chunkQEVLRLUNcjs.createHistoryCommands; exports.createShapeCommands = _chunkQEVLRLUNcjs.createShapeCommands; exports.createSpreadsheetCommands = _chunkQEVLRLUNcjs.createSpreadsheetCommands; exports.defineCommand = _chunkKIJIONZFcjs.defineCommand; exports.detectPlatform = _chunkQJVOJUTDcjs.detectPlatform; exports.effectiveChord = _chunkQJVOJUTDcjs.effectiveChord; exports.effectiveChordKey = _chunkQJVOJUTDcjs.effectiveChordKey; exports.eventCode = _chunkQJVOJUTDcjs.eventCode; exports.exactBonus = _chunkKIJIONZFcjs.exactBonus; exports.formatCommandsFor = _chunkVCL7CB56cjs.formatCommandsFor; exports.formatShortcut = _chunkQJVOJUTDcjs.formatShortcut; exports.fuzzyMatch = _chunkKIJIONZFcjs.fuzzyMatch; exports.fuzzyScore = _chunkKIJIONZFcjs.fuzzyScore; exports.hasVariantCommands = _chunkQEVLRLUNcjs.hasVariantCommands; exports.isEditableEventTarget = _chunkQJVOJUTDcjs.isEditableEventTarget; exports.keyToCode = _chunkQJVOJUTDcjs.keyToCode; exports.matchHistoryShortcut = _chunkQEVLRLUNcjs.matchHistoryShortcut; exports.matchPaletteHotkey = matchPaletteHotkey; exports.normalizeChord = _chunkQJVOJUTDcjs.normalizeChord; exports.parseChord = _chunkQJVOJUTDcjs.parseChord; exports.planFreehandPlayback = _chunkQEVLRLUNcjs.planFreehandPlayback; exports.pushRecent = _chunkKIJIONZFcjs.pushRecent; exports.rankCommands = _chunkKIJIONZFcjs.rankCommands; exports.shortcutCode = _chunkQJVOJUTDcjs.shortcutCode; exports.toShortcutBindings = _chunkQJVOJUTDcjs.toShortcutBindings;
100
+ exports.CommandRegistry = _chunkKIJIONZFcjs.CommandRegistry; exports.CommandRegistryError = _chunkKIJIONZFcjs.CommandRegistryError; exports.DEFAULT_HISTORY_SHORTCUTS = _chunkQEVLRLUNcjs.DEFAULT_HISTORY_SHORTCUTS; exports.DEFAULT_RECENT_LIMIT = _chunkKIJIONZFcjs.DEFAULT_RECENT_LIMIT; exports.PLATFORMS = _chunkQJVOJUTDcjs.PLATFORMS; exports.ShortcutMap = _chunkQJVOJUTDcjs.ShortcutMap; exports.chordToString = _chunkQJVOJUTDcjs.chordToString; exports.codeFromKey = _chunkQJVOJUTDcjs.codeFromKey; exports.codeToKeyText = _chunkQJVOJUTDcjs.codeToKeyText; exports.createArrangeCommands = _chunkQEVLRLUNcjs.createArrangeCommands; exports.createCanvasAnimationCommands = _chunkQEUI6OGEcjs.createCanvasAnimationCommands; exports.createCommandPaletteController = _chunkQEUI6OGEcjs.createCommandPaletteController; exports.createCommandRegistry = _chunkKIJIONZFcjs.createCommandRegistry; exports.createCommandToolProvider = _chunkKIJIONZFcjs.createCommandToolProvider; exports.createComponentCommands = _chunkQEVLRLUNcjs.createComponentCommands; exports.createDrawCommands = _chunkQEVLRLUNcjs.createDrawCommands; exports.createFormatCommands = _chunkVCL7CB56cjs.createFormatCommands; exports.createHistoryCommands = _chunkQEVLRLUNcjs.createHistoryCommands; exports.createShapeCommands = _chunkQEVLRLUNcjs.createShapeCommands; exports.createSpreadsheetCommands = _chunkQEVLRLUNcjs.createSpreadsheetCommands; exports.defineCommand = _chunkKIJIONZFcjs.defineCommand; exports.detectPlatform = _chunkQJVOJUTDcjs.detectPlatform; exports.effectiveChord = _chunkQJVOJUTDcjs.effectiveChord; exports.effectiveChordKey = _chunkQJVOJUTDcjs.effectiveChordKey; exports.eventCode = _chunkQJVOJUTDcjs.eventCode; exports.exactBonus = _chunkKIJIONZFcjs.exactBonus; exports.formatCommandsFor = _chunkVCL7CB56cjs.formatCommandsFor; exports.formatShortcut = _chunkQJVOJUTDcjs.formatShortcut; exports.fuzzyMatch = _chunkKIJIONZFcjs.fuzzyMatch; exports.fuzzyScore = _chunkKIJIONZFcjs.fuzzyScore; exports.hasVariantCommands = _chunkQEVLRLUNcjs.hasVariantCommands; exports.isEditableEventTarget = _chunkQJVOJUTDcjs.isEditableEventTarget; exports.keyToCode = _chunkQJVOJUTDcjs.keyToCode; exports.matchHistoryShortcut = _chunkQEVLRLUNcjs.matchHistoryShortcut; exports.matchPaletteHotkey = _chunkQEUI6OGEcjs.matchPaletteHotkey; exports.normalizeChord = _chunkQJVOJUTDcjs.normalizeChord; exports.parseChord = _chunkQJVOJUTDcjs.parseChord; exports.planFreehandPlayback = _chunkQEVLRLUNcjs.planFreehandPlayback; exports.pushRecent = _chunkKIJIONZFcjs.pushRecent; exports.rankCommands = _chunkKIJIONZFcjs.rankCommands; exports.shortcutCode = _chunkQJVOJUTDcjs.shortcutCode; exports.toShortcutBindings = _chunkQJVOJUTDcjs.toShortcutBindings;