@cyanheads/pixoo-mcp-server 1.2.0 → 1.2.2

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 (54) hide show
  1. package/AGENTS.md +10 -7
  2. package/CLAUDE.md +10 -7
  3. package/Dockerfile +30 -10
  4. package/README.md +65 -86
  5. package/changelog/1.2.x/1.2.1.md +35 -0
  6. package/changelog/1.2.x/1.2.2.md +40 -0
  7. package/dist/mcp-server/resources/definitions/pixoo-design-guide.resource.d.ts.map +1 -1
  8. package/dist/mcp-server/resources/definitions/pixoo-design-guide.resource.js +4 -1
  9. package/dist/mcp-server/resources/definitions/pixoo-design-guide.resource.js.map +1 -1
  10. package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.d.ts +173 -13
  11. package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.d.ts.map +1 -1
  12. package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.js +129 -28
  13. package/dist/mcp-server/tools/definitions/pixoo-compose-scene.tool.js.map +1 -1
  14. package/dist/mcp-server/tools/definitions/pixoo-design-brief.tool.d.ts.map +1 -1
  15. package/dist/mcp-server/tools/definitions/pixoo-design-brief.tool.js +15 -7
  16. package/dist/mcp-server/tools/definitions/pixoo-design-brief.tool.js.map +1 -1
  17. package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.d.ts +2 -0
  18. package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.d.ts.map +1 -1
  19. package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.js +27 -12
  20. package/dist/mcp-server/tools/definitions/pixoo-display-text.tool.js.map +1 -1
  21. package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.d.ts +30 -1
  22. package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.d.ts.map +1 -1
  23. package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.js +105 -26
  24. package/dist/mcp-server/tools/definitions/pixoo-push-image.tool.js.map +1 -1
  25. package/dist/mcp-server/tools/finish-schema.d.ts +28 -0
  26. package/dist/mcp-server/tools/finish-schema.d.ts.map +1 -0
  27. package/dist/mcp-server/tools/finish-schema.js +42 -0
  28. package/dist/mcp-server/tools/finish-schema.js.map +1 -0
  29. package/dist/renderer/finish.d.ts +34 -0
  30. package/dist/renderer/finish.d.ts.map +1 -0
  31. package/dist/renderer/finish.js +62 -0
  32. package/dist/renderer/finish.js.map +1 -0
  33. package/dist/renderer/icons.d.ts +14 -4
  34. package/dist/renderer/icons.d.ts.map +1 -1
  35. package/dist/renderer/icons.js +30 -22
  36. package/dist/renderer/icons.js.map +1 -1
  37. package/dist/renderer/keyframes.d.ts +40 -4
  38. package/dist/renderer/keyframes.d.ts.map +1 -1
  39. package/dist/renderer/keyframes.js +100 -53
  40. package/dist/renderer/keyframes.js.map +1 -1
  41. package/dist/renderer/remote-image.d.ts +13 -7
  42. package/dist/renderer/remote-image.d.ts.map +1 -1
  43. package/dist/renderer/remote-image.js +17 -21
  44. package/dist/renderer/remote-image.js.map +1 -1
  45. package/dist/renderer/scene-renderer.d.ts +45 -6
  46. package/dist/renderer/scene-renderer.d.ts.map +1 -1
  47. package/dist/renderer/scene-renderer.js +328 -159
  48. package/dist/renderer/scene-renderer.js.map +1 -1
  49. package/dist/renderer/text-engine.d.ts +24 -5
  50. package/dist/renderer/text-engine.d.ts.map +1 -1
  51. package/dist/renderer/text-engine.js +51 -28
  52. package/dist/renderer/text-engine.js.map +1 -1
  53. package/package.json +7 -6
  54. package/server.json +3 -3
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @fileoverview Palette finishing — reduce a rendered canvas, or every frame of an
3
+ * animation, to a palette with optional dithering through the toolkit's `quantize`.
4
+ * Tool-agnostic: any render path applies a caller's `finish` here, after the load and
5
+ * before the preview, so the preview is exactly the frame the device receives.
6
+ * @module renderer/finish
7
+ */
8
+ import { Canvas, quantize } from '@cyanheads/pixoo-toolkit';
9
+ /**
10
+ * Apply `finish` to one canvas.
11
+ *
12
+ * @returns A new canvas; the input is never mutated.
13
+ * @throws {Error} The toolkit's `Unknown color` error for an unresolvable palette entry.
14
+ */
15
+ export function finishFrame(canvas, finish) {
16
+ return quantize(canvas, finish);
17
+ }
18
+ /**
19
+ * Apply `finish` to every frame of an animation. `colors` builds one palette from all
20
+ * the frames' visible pixels together, so the whole loop holds at most that many colors;
21
+ * `palette` and `dither` apply to each frame on its own, so dither error never crosses
22
+ * from one frame into the next.
23
+ *
24
+ * @param frames - Frames of one size, up to 4096 stacked rows in all (64 frames of a
25
+ * 64-pixel panel).
26
+ * @returns New canvases, one per frame; the inputs are never mutated.
27
+ * @throws {Error} The toolkit's `Unknown color` error for an unresolvable palette entry.
28
+ */
29
+ export function finishFrames(frames, finish) {
30
+ if (finish.colors === undefined || frames.length <= 1) {
31
+ return frames.map((frame) => quantize(frame, finish));
32
+ }
33
+ const palette = sharedPalette(frames, finish.colors);
34
+ // Nothing visible to reduce — quantize returns such a frame unchanged too.
35
+ if (palette.length === 0)
36
+ return frames.map((frame) => frame.clone());
37
+ return frames.map((frame) => quantize(frame, { palette, dither: finish.dither ?? 'none' }));
38
+ }
39
+ /**
40
+ * The palette of at most `colors` colors `quantize` builds from every frame's visible
41
+ * pixels at once: the frames stacked into one canvas and reduced without dithering,
42
+ * then the reduced canvas's distinct visible colors read back in raster order.
43
+ */
44
+ function sharedPalette(frames, colors) {
45
+ const [first] = frames;
46
+ const stack = new Canvas(first.width, first.height * frames.length);
47
+ frames.forEach((frame, k) => {
48
+ stack.buffer.set(frame.buffer, k * frame.buffer.length);
49
+ });
50
+ const buf = quantize(stack, { colors }).buffer;
51
+ const palette = new Map();
52
+ for (let i = 0; i < buf.length; i += 4) {
53
+ if (buf[i + 3] === 0)
54
+ continue;
55
+ const rgb = [buf[i] ?? 0, buf[i + 1] ?? 0, buf[i + 2] ?? 0];
56
+ const key = (rgb[0] << 16) | (rgb[1] << 8) | rgb[2];
57
+ if (!palette.has(key))
58
+ palette.set(key, rgb);
59
+ }
60
+ return [...palette.values()];
61
+ }
62
+ //# sourceMappingURL=finish.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finish.js","sourceRoot":"","sources":["../../src/renderer/finish.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,EAAwB,QAAQ,EAAY,MAAM,0BAA0B,CAAC;AAS5F;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,MAAc,EAAE,MAAc;IACxD,OAAO,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,YAAY,CAAC,MAAyB,EAAE,MAAc;IACpE,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACtD,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACrD,2EAA2E;IAC3E,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACtE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC;AAC9F,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,MAAyB,EAAE,MAAc;IAC9D,MAAM,CAAC,KAAK,CAAC,GAAG,MAAwC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACpE,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC1B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC;IAC/C,MAAM,OAAO,GAAG,IAAI,GAAG,EAAe,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;YAAE,SAAS;QAC/B,MAAM,GAAG,GAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACjE,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAC/C,CAAC;IACD,OAAO,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AAC/B,CAAC"}
@@ -2,15 +2,25 @@
2
2
  * @fileoverview Built-in icon registry with SVG path data by category.
3
3
  * @module renderer/icons
4
4
  */
5
+ /**
6
+ * An icon's SVG path data, split by how each part draws. `fill` subpaths rasterize with the
7
+ * even-odd rule; `stroke` subpaths draw as 1-pixel lines along their segments — the parts
8
+ * designed as outlines, since a line has no area for a fill to cover.
9
+ */
10
+ export type IconPaths = {
11
+ fill: string;
12
+ stroke?: string;
13
+ } | {
14
+ fill?: undefined;
15
+ stroke: string;
16
+ };
5
17
  /** A single icon entry. */
6
- export interface IconEntry {
18
+ export type IconEntry = IconPaths & {
7
19
  category: string;
8
- /** SVG d attribute for the icon path. */
9
- d: string;
10
20
  name: string;
11
21
  /** viewBox string (default "0 0 16 16"). */
12
22
  viewBox: string;
13
- }
23
+ };
14
24
  /** All icons indexed by name. */
15
25
  export declare const ICONS: Record<string, IconEntry>;
16
26
  export declare const ICON_NAMES: string[];
@@ -1 +1 @@
1
- {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/renderer/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,2BAA2B;AAC3B,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,iCAAiC;AACjC,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CA6H3C,CAAC;AAEF,eAAO,MAAM,UAAU,UAAqB,CAAC;AAE7C,eAAO,MAAM,eAAe,UAA4D,CAAC;AAEzF,qCAAqC;AACrC,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAO7D"}
1
+ {"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../src/renderer/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,CAAC,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjG,2BAA2B;AAC3B,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAKF,iCAAiC;AACjC,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAoI3C,CAAC;AAEF,eAAO,MAAM,UAAU,UAAqB,CAAC;AAE7C,eAAO,MAAM,eAAe,UAA4D,CAAC;AAEzF,qCAAqC;AACrC,wBAAgB,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAO7D"}
@@ -2,130 +2,138 @@
2
2
  * @fileoverview Built-in icon registry with SVG path data by category.
3
3
  * @module renderer/icons
4
4
  */
5
+ /** The circle every status badge is drawn around, as a stroke. */
6
+ const STATUS_RING = 'M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1z';
5
7
  /** All icons indexed by name. */
6
8
  export const ICONS = {
7
9
  // --- weather ---
8
10
  sun: {
9
11
  name: 'sun',
10
12
  category: 'weather',
11
- d: 'M8 5a3 3 0 1 0 0 6 3 3 0 0 0 0-6zM8 1v2M8 13v2M3.22 3.22l1.41 1.41M11.37 11.37l1.41 1.41M1 8h2M13 8h2M3.22 12.78l1.41-1.41M11.37 4.63l1.41-1.41',
13
+ fill: 'M8 5a3 3 0 1 0 0 6 3 3 0 0 0 0-6z',
14
+ stroke: 'M8 1v2M8 13v2M3.22 3.22l1.41 1.41M11.37 11.37l1.41 1.41M1 8h2M13 8h2M3.22 12.78l1.41-1.41M11.37 4.63l1.41-1.41',
12
15
  viewBox: '0 0 16 16',
13
16
  },
14
17
  cloud: {
15
18
  name: 'cloud',
16
19
  category: 'weather',
17
- d: 'M13 10a3 3 0 0 0-3-3h-.5A4.5 4.5 0 1 0 3 10h10z',
20
+ fill: 'M13 10a3 3 0 0 0-3-3h-.5A4.5 4.5 0 1 0 3 10h10z',
18
21
  viewBox: '0 0 16 16',
19
22
  },
20
23
  rain: {
21
24
  name: 'rain',
22
25
  category: 'weather',
23
- d: 'M13 8a3 3 0 0 0-3-3h-.5A4.5 4.5 0 1 0 3 8h10zM5 12l-1 3M8 12v3M11 12l1 3',
26
+ fill: 'M13 8a3 3 0 0 0-3-3h-.5A4.5 4.5 0 1 0 3 8h10z',
27
+ stroke: 'M5 12l-1 3M8 12v3M11 12l1 3',
24
28
  viewBox: '0 0 16 16',
25
29
  },
26
30
  snow: {
27
31
  name: 'snow',
28
32
  category: 'weather',
29
- d: 'M8 1v14M3.5 4l9 8M12.5 4l-9 8M1 8h14M3 5.5l-2-2M13 5.5l2-2M3 10.5l-2 2M13 10.5l2 2',
33
+ stroke: 'M8 1v14M3.5 4l9 8M12.5 4l-9 8M1 8h14M3 5.5l-2-2M13 5.5l2-2M3 10.5l-2 2M13 10.5l2 2',
30
34
  viewBox: '0 0 16 16',
31
35
  },
32
36
  wind: {
33
37
  name: 'wind',
34
38
  category: 'weather',
35
- d: 'M1 6h8a2 2 0 1 0-2-2M1 10h12a2 2 0 1 1-2 2M1 8h6',
39
+ stroke: 'M1 6h8a2 2 0 1 0-2-2M1 10h12a2 2 0 1 1-2 2M1 8h6',
36
40
  viewBox: '0 0 16 16',
37
41
  },
38
42
  lightning: {
39
43
  name: 'lightning',
40
44
  category: 'weather',
41
- d: 'M9 1L4 9h5l-2 6 7-8H9z',
45
+ fill: 'M9 1L4 9h5l-2 6 7-8H9z',
42
46
  viewBox: '0 0 16 16',
43
47
  },
44
- // --- arrows ---
48
+ // --- arrows: a filled head on a stroked shaft ---
45
49
  'arrow-up': {
46
50
  name: 'arrow-up',
47
51
  category: 'arrows',
48
- d: 'M8 2L8 14M3 7l5-5 5 5',
52
+ fill: 'M3 7l5-5 5 5',
53
+ stroke: 'M8 2L8 14',
49
54
  viewBox: '0 0 16 16',
50
55
  },
51
56
  'arrow-down': {
52
57
  name: 'arrow-down',
53
58
  category: 'arrows',
54
- d: 'M8 14L8 2M3 9l5 5 5-5',
59
+ fill: 'M3 9l5 5 5-5',
60
+ stroke: 'M8 14L8 2',
55
61
  viewBox: '0 0 16 16',
56
62
  },
57
63
  'arrow-left': {
58
64
  name: 'arrow-left',
59
65
  category: 'arrows',
60
- d: 'M2 8L14 8M7 3L2 8l5 5',
66
+ fill: 'M7 3L2 8l5 5',
67
+ stroke: 'M2 8L14 8',
61
68
  viewBox: '0 0 16 16',
62
69
  },
63
70
  'arrow-right': {
64
71
  name: 'arrow-right',
65
72
  category: 'arrows',
66
- d: 'M14 8L2 8M9 3L14 8l-5 5',
73
+ fill: 'M9 3L14 8l-5 5',
74
+ stroke: 'M14 8L2 8',
67
75
  viewBox: '0 0 16 16',
68
76
  },
69
- // --- status ---
77
+ // --- status: a stroked ring around a stroked mark, so the mark shows ---
70
78
  'check-circle': {
71
79
  name: 'check-circle',
72
80
  category: 'status',
73
- d: 'M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zM5 8l2 2 4-4',
81
+ stroke: `${STATUS_RING}M5 8l2 2 4-4`,
74
82
  viewBox: '0 0 16 16',
75
83
  },
76
84
  'x-circle': {
77
85
  name: 'x-circle',
78
86
  category: 'status',
79
- d: 'M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zM5 5l6 6M11 5l-6 6',
87
+ stroke: `${STATUS_RING}M5 5l6 6M11 5l-6 6`,
80
88
  viewBox: '0 0 16 16',
81
89
  },
82
90
  'alert-circle': {
83
91
  name: 'alert-circle',
84
92
  category: 'status',
85
- d: 'M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zM8 5v4M8 11v1',
93
+ stroke: `${STATUS_RING}M8 5v4M8 11v1`,
86
94
  viewBox: '0 0 16 16',
87
95
  },
88
96
  info: {
89
97
  name: 'info',
90
98
  category: 'status',
91
- d: 'M8 1a7 7 0 1 0 0 14A7 7 0 0 0 8 1zM8 7v5M8 5v1',
99
+ stroke: `${STATUS_RING}M8 8v4M8 5v1`,
92
100
  viewBox: '0 0 16 16',
93
101
  },
94
102
  heart: {
95
103
  name: 'heart',
96
104
  category: 'status',
97
- d: 'M8 13S1 9 1 4.5a3.5 3.5 0 0 1 7 0 3.5 3.5 0 0 1 7 0C15 9 8 13 8 13z',
105
+ fill: 'M8 13S1 9 1 4.5a3.5 3.5 0 0 1 7 0 3.5 3.5 0 0 1 7 0C15 9 8 13 8 13z',
98
106
  viewBox: '0 0 16 16',
99
107
  },
100
108
  star: {
101
109
  name: 'star',
102
110
  category: 'status',
103
- d: 'M8 1l2 5h5l-4 3 1.5 5L8 11l-4.5 3L5 9 1 6h5z',
111
+ fill: 'M8 1l2 5h5l-4 3 1.5 5L8 11l-4.5 3L5 9 1 6h5z',
104
112
  viewBox: '0 0 16 16',
105
113
  },
106
114
  // --- media ---
107
115
  play: {
108
116
  name: 'play',
109
117
  category: 'media',
110
- d: 'M3 2l10 6-10 6z',
118
+ fill: 'M3 2l10 6-10 6z',
111
119
  viewBox: '0 0 16 16',
112
120
  },
113
121
  pause: {
114
122
  name: 'pause',
115
123
  category: 'media',
116
- d: 'M5 2h2v12H5zM9 2h2v12H9z',
124
+ fill: 'M5 2h2v12H5zM9 2h2v12H9z',
117
125
  viewBox: '0 0 16 16',
118
126
  },
119
127
  stop: {
120
128
  name: 'stop',
121
129
  category: 'media',
122
- d: 'M3 3h10v10H3z',
130
+ fill: 'M3 3h10v10H3z',
123
131
  viewBox: '0 0 16 16',
124
132
  },
125
133
  music: {
126
134
  name: 'music',
127
135
  category: 'media',
128
- d: 'M12 2v7a2 2 0 1 1-2-2V2l-6 1v7a2 2 0 1 1-2-2V3z',
136
+ fill: 'M12 2v7a2 2 0 1 1-2-2V4l-6 1v5a2 2 0 1 1-2-2V3z',
129
137
  viewBox: '0 0 16 16',
130
138
  },
131
139
  };
@@ -1 +1 @@
1
- {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/renderer/icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,iCAAiC;AACjC,MAAM,CAAC,MAAM,KAAK,GAA8B;IAC9C,kBAAkB;IAClB,GAAG,EAAE;QACH,IAAI,EAAE,KAAK;QACX,QAAQ,EAAE,SAAS;QACnB,CAAC,EAAE,iJAAiJ;QACpJ,OAAO,EAAE,WAAW;KACrB;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,SAAS;QACnB,CAAC,EAAE,iDAAiD;QACpD,OAAO,EAAE,WAAW;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS;QACnB,CAAC,EAAE,0EAA0E;QAC7E,OAAO,EAAE,WAAW;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS;QACnB,CAAC,EAAE,oFAAoF;QACvF,OAAO,EAAE,WAAW;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,SAAS;QACnB,CAAC,EAAE,kDAAkD;QACrD,OAAO,EAAE,WAAW;KACrB;IACD,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,QAAQ,EAAE,SAAS;QACnB,CAAC,EAAE,wBAAwB;QAC3B,OAAO,EAAE,WAAW;KACrB;IACD,iBAAiB;IACjB,UAAU,EAAE;QACV,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,uBAAuB;QAC1B,OAAO,EAAE,WAAW;KACrB;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,uBAAuB;QAC1B,OAAO,EAAE,WAAW;KACrB;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,YAAY;QAClB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,uBAAuB;QAC1B,OAAO,EAAE,WAAW;KACrB;IACD,aAAa,EAAE;QACb,IAAI,EAAE,aAAa;QACnB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,yBAAyB;QAC5B,OAAO,EAAE,WAAW;KACrB;IACD,iBAAiB;IACjB,cAAc,EAAE;QACd,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,gDAAgD;QACnD,OAAO,EAAE,WAAW;KACrB;IACD,UAAU,EAAE;QACV,IAAI,EAAE,UAAU;QAChB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,sDAAsD;QACzD,OAAO,EAAE,WAAW;KACrB;IACD,cAAc,EAAE;QACd,IAAI,EAAE,cAAc;QACpB,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,iDAAiD;QACpD,OAAO,EAAE,WAAW;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,gDAAgD;QACnD,OAAO,EAAE,WAAW;KACrB;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,qEAAqE;QACxE,OAAO,EAAE,WAAW;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,QAAQ;QAClB,CAAC,EAAE,8CAA8C;QACjD,OAAO,EAAE,WAAW;KACrB;IACD,gBAAgB;IAChB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,OAAO;QACjB,CAAC,EAAE,iBAAiB;QACpB,OAAO,EAAE,WAAW;KACrB;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,OAAO;QACjB,CAAC,EAAE,0BAA0B;QAC7B,OAAO,EAAE,WAAW;KACrB;IACD,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM;QACZ,QAAQ,EAAE,OAAO;QACjB,CAAC,EAAE,eAAe;QAClB,OAAO,EAAE,WAAW;KACrB;IACD,KAAK,EAAE;QACL,IAAI,EAAE,OAAO;QACb,QAAQ,EAAE,OAAO;QACjB,CAAC,EAAE,iDAAiD;QACpD,OAAO,EAAE,WAAW;KACrB;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAE7C,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEzF,qCAAqC;AACrC,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAA6B,EAAE,CAAC;IAC5C,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QACxC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"icons.js","sourceRoot":"","sources":["../../src/renderer/icons.ts"],"names":[],"mappings":"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"}
@@ -9,14 +9,50 @@ export type KeyframeMap = Record<string, KeyframeEntry[]>;
9
9
  /** Effect preset names. */
10
10
  export type EffectName = 'float' | 'scroll-left' | 'scroll-right' | 'pulse' | 'blink' | 'twinkle' | 'drift' | 'fade-in' | 'fade-out';
11
11
  export declare const EFFECT_NAMES: EffectName[];
12
- /** Compile a named effect preset into a keyframe map. */
12
+ /**
13
+ * Compile a named effect preset into a keyframe map.
14
+ *
15
+ * `amplitude` is pixels of movement for `float`, `scroll-left`/`scroll-right` (speed), and
16
+ * `drift`, default 2. For `pulse` and `twinkle` it is the depth of the opacity dip below 100,
17
+ * on a 0–1 scale: default 0.5 for `pulse` (a 50–100 ramp) and 0.6 for `twinkle` (40–100).
18
+ * `blink`, `fade-in`, and `fade-out` ignore it.
19
+ *
20
+ * `twinkle` jitters each frame's phase by an amount fixed by the frame and `element`, the
21
+ * element's index in the scene, so the flicker is irregular and differs between elements
22
+ * while identical scenes render identically.
23
+ */
13
24
  export declare function compileEffect(name: EffectName, opts: {
14
25
  amplitude?: number;
15
26
  period?: number;
16
27
  phase?: number;
17
- }, totalFrames: number): KeyframeMap;
18
- /** Interpolate a keyframe property at a given frame index. */
19
- export declare function interpolateKeyframe(frames: KeyframeEntry[], frameIdx: number): number | string | boolean;
28
+ }, totalFrames: number, element?: number): KeyframeMap;
29
+ /** A keyframe's value. */
30
+ type KeyframeValue = KeyframeEntry[1];
31
+ /**
32
+ * A number, or a string that reads as one (`"40"`, `"000"`, `"-2.5"`); `undefined` otherwise.
33
+ * `pixoo_compose_scene` validates `dx`, `dy`, and `opacity` keyframes with it, so the input
34
+ * schema and the interpolation agree on what a numeric string is.
35
+ */
36
+ export declare function numericValue(value: KeyframeValue): number | undefined;
37
+ /**
38
+ * Interpolate a keyframe property at a given frame index. Booleans snap at the midpoint.
39
+ * Numbers lerp, and so do numeric strings, read as the same numbers — `"000"` is 0 here, never
40
+ * a color: only the `color` track lerps through RGB, in {@link interpolateColorKeyframe}.
41
+ * Any other value holds until the next keyframe.
42
+ */
43
+ export declare function interpolateKeyframe(frames: KeyframeEntry[], frameIdx: number): KeyframeValue;
44
+ /**
45
+ * Interpolate a `color` keyframe track at a frame index: each keyframe value, number or
46
+ * string, is read as a color and the track lerps through RGB, returning `#rrggbb` between
47
+ * keyframes so it resolves like any other color. Every keyframe value is resolved first, so
48
+ * one that isn't a color fails on every frame — including a keyframe the scene never
49
+ * reaches, which interpolation alone would skip past by holding the previous color.
50
+ *
51
+ * @throws {Error} The toolkit's `Unknown color` error for the first value that isn't a color,
52
+ * or an error for an empty track, which input validation rejects before any render.
53
+ */
54
+ export declare function interpolateColorKeyframe(frames: KeyframeEntry[], frameIdx: number): string;
20
55
  /** Get the interpolated value for a named property at a frame index. */
21
56
  export declare function getKeyframeValue(keyframes: KeyframeMap | undefined, prop: string, frameIdx: number, defaultValue: number | string | boolean): number | string | boolean;
57
+ export {};
22
58
  //# sourceMappingURL=keyframes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyframes.d.ts","sourceRoot":"","sources":["../../src/renderer/keyframes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEhE,qDAAqD;AACrD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;AAE1D,2BAA2B;AAC3B,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,aAAa,GACb,cAAc,GACd,OAAO,GACP,OAAO,GACP,SAAS,GACT,OAAO,GACP,SAAS,GACT,UAAU,CAAC;AAEf,eAAO,MAAM,YAAY,EAAE,UAAU,EAUpC,CAAC;AAEF,yDAAyD;AACzD,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE;IACJ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,WAAW,EAAE,MAAM,GAClB,WAAW,CAkFb;AAED,8DAA8D;AAC9D,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EAAE,EACvB,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,MAAM,GAAG,OAAO,CAmD3B;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GACtC,MAAM,GAAG,MAAM,GAAG,OAAO,CAG3B"}
1
+ {"version":3,"file":"keyframes.d.ts","sourceRoot":"","sources":["../../src/renderer/keyframes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;AAEhE,qDAAqD;AACrD,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;AAE1D,2BAA2B;AAC3B,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,aAAa,GACb,cAAc,GACd,OAAO,GACP,OAAO,GACP,SAAS,GACT,OAAO,GACP,SAAS,GACT,UAAU,CAAC;AAEf,eAAO,MAAM,YAAY,EAAE,UAAU,EAUpC,CAAC;AAaF;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE;IACJ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,EACD,WAAW,EAAE,MAAM,EACnB,OAAO,SAAI,GACV,WAAW,CAoFb;AAED,0BAA0B;AAC1B,KAAK,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;AA4BtC;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAKrE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,CAY5F;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAQ1F;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAC9B,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GACtC,MAAM,GAAG,MAAM,GAAG,OAAO,CAG3B"}
@@ -2,7 +2,7 @@
2
2
  * @fileoverview Keyframe interpolation and effect compiler for animation presets.
3
3
  * @module renderer/keyframes
4
4
  */
5
- import { lerpColor, resolveColor } from '@cyanheads/pixoo-toolkit';
5
+ import { lerpColor, resolveColor, rgbToHex } from '@cyanheads/pixoo-toolkit';
6
6
  export const EFFECT_NAMES = [
7
7
  'float',
8
8
  'scroll-left',
@@ -14,8 +14,29 @@ export const EFFECT_NAMES = [
14
14
  'fade-in',
15
15
  'fade-out',
16
16
  ];
17
- /** Compile a named effect preset into a keyframe map. */
18
- export function compileEffect(name, opts, totalFrames) {
17
+ /**
18
+ * A fixed value in [0, 1) for one frame of one element: a 32-bit integer hash of the pair,
19
+ * so a render repeats exactly while neighbouring frames and elements still land far apart.
20
+ */
21
+ function flicker(frame, element) {
22
+ let h = Math.imul(frame, 0x9e3779b1) ^ Math.imul(element + 1, 0x85ebca6b);
23
+ h = Math.imul(h ^ (h >>> 16), 0x7feb352d);
24
+ h = Math.imul(h ^ (h >>> 15), 0x846ca68b);
25
+ return ((h ^ (h >>> 16)) >>> 0) / 2 ** 32;
26
+ }
27
+ /**
28
+ * Compile a named effect preset into a keyframe map.
29
+ *
30
+ * `amplitude` is pixels of movement for `float`, `scroll-left`/`scroll-right` (speed), and
31
+ * `drift`, default 2. For `pulse` and `twinkle` it is the depth of the opacity dip below 100,
32
+ * on a 0–1 scale: default 0.5 for `pulse` (a 50–100 ramp) and 0.6 for `twinkle` (40–100).
33
+ * `blink`, `fade-in`, and `fade-out` ignore it.
34
+ *
35
+ * `twinkle` jitters each frame's phase by an amount fixed by the frame and `element`, the
36
+ * element's index in the scene, so the flicker is irregular and differs between elements
37
+ * while identical scenes render identically.
38
+ */
39
+ export function compileEffect(name, opts, totalFrames, element = 0) {
19
40
  const amp = opts.amplitude ?? 2;
20
41
  const period = opts.period ?? totalFrames;
21
42
  const phase = opts.phase ?? 0;
@@ -45,12 +66,12 @@ export function compileEffect(name, opts, totalFrames) {
45
66
  return { dx: frames };
46
67
  }
47
68
  case 'pulse': {
69
+ const depth = (opts.amplitude ?? 0.5) * 100;
48
70
  const frames = [];
49
71
  for (let i = 0; i < totalFrames; i++) {
50
72
  const t = (i / period + phase) * 2 * Math.PI;
51
73
  const brightness = 0.5 + 0.5 * Math.sin(t);
52
- // Encode brightness as opacity 50–100
53
- frames.push([i, Math.round(50 + 50 * brightness)]);
74
+ frames.push([i, Math.round(100 - depth + depth * brightness)]);
54
75
  }
55
76
  return { opacity: frames };
56
77
  }
@@ -63,10 +84,12 @@ export function compileEffect(name, opts, totalFrames) {
63
84
  return { visible: frames };
64
85
  }
65
86
  case 'twinkle': {
87
+ const depth = (opts.amplitude ?? 0.6) * 100;
66
88
  const frames = [];
67
89
  for (let i = 0; i < totalFrames; i++) {
68
90
  const t = (i / period + phase) * 2 * Math.PI;
69
- frames.push([i, Math.round(40 + 60 * (0.5 + 0.5 * Math.sin(t + Math.random() * 0.3)))]);
91
+ const brightness = 0.5 + 0.5 * Math.sin(t + flicker(i, element) * 0.3);
92
+ frames.push([i, Math.round(100 - depth + depth * brightness)]);
70
93
  }
71
94
  return { opacity: frames };
72
95
  }
@@ -97,59 +120,83 @@ export function compileEffect(name, opts, totalFrames) {
97
120
  return {};
98
121
  }
99
122
  }
100
- /** Interpolate a keyframe property at a given frame index. */
101
- export function interpolateKeyframe(frames, frameIdx) {
102
- if (frames.length === 0)
103
- return 0;
123
+ /**
124
+ * The keyframes around `frameIdx` and how far between them it falls: `t` runs from 0 on
125
+ * `from`'s frame to 1 on `to`'s. Before the first keyframe or past the last, that keyframe's
126
+ * value is held: `from` and `to` are both it and `t` is 0. `undefined` for an empty track.
127
+ */
128
+ function keyframeSpan(frames, frameIdx) {
104
129
  const first = frames[0];
105
- const last = frames[frames.length - 1];
130
+ const last = frames.at(-1);
106
131
  if (!first || !last)
107
- return 0;
132
+ return;
108
133
  if (frameIdx <= first[0])
109
- return first[1];
110
- if (frameIdx >= last[0])
111
- return last[1];
112
- // Find surrounding keyframes
113
- let lo = 0;
114
- let hi = frames.length - 1;
115
- for (let i = 0; i < frames.length - 1; i++) {
116
- const a = frames[i];
117
- const b = frames[i + 1];
118
- if (a && b && a[0] <= frameIdx && b[0] >= frameIdx) {
119
- lo = i;
120
- hi = i + 1;
121
- break;
134
+ return { from: first[1], to: first[1], t: 0 };
135
+ if (frameIdx < last[0]) {
136
+ let before = first;
137
+ for (const keyframe of frames) {
138
+ if (keyframe[0] >= frameIdx) {
139
+ const t = (frameIdx - before[0]) / (keyframe[0] - before[0]);
140
+ return { from: before[1], to: keyframe[1], t };
141
+ }
142
+ before = keyframe;
122
143
  }
123
144
  }
124
- const loEntry = frames[lo];
125
- const hiEntry = frames[hi];
126
- if (!loEntry || !hiEntry)
145
+ return { from: last[1], to: last[1], t: 0 };
146
+ }
147
+ /**
148
+ * A number, or a string that reads as one (`"40"`, `"000"`, `"-2.5"`); `undefined` otherwise.
149
+ * `pixoo_compose_scene` validates `dx`, `dy`, and `opacity` keyframes with it, so the input
150
+ * schema and the interpolation agree on what a numeric string is.
151
+ */
152
+ export function numericValue(value) {
153
+ if (typeof value === 'number')
154
+ return value;
155
+ if (typeof value !== 'string' || value.trim() === '')
156
+ return;
157
+ const number = Number(value);
158
+ return Number.isFinite(number) ? number : undefined;
159
+ }
160
+ /**
161
+ * Interpolate a keyframe property at a given frame index. Booleans snap at the midpoint.
162
+ * Numbers lerp, and so do numeric strings, read as the same numbers — `"000"` is 0 here, never
163
+ * a color: only the `color` track lerps through RGB, in {@link interpolateColorKeyframe}.
164
+ * Any other value holds until the next keyframe.
165
+ */
166
+ export function interpolateKeyframe(frames, frameIdx) {
167
+ const span = keyframeSpan(frames, frameIdx);
168
+ if (!span)
127
169
  return 0;
128
- const [f0, v0] = loEntry;
129
- const [f1, v1] = hiEntry;
130
- if (f0 === f1)
131
- return v0;
132
- const t = (frameIdx - f0) / (f1 - f0);
133
- // Boolean: snap at midpoint
134
- if (typeof v0 === 'boolean')
135
- return t < 0.5 ? v0 : v1;
136
- // Number: lerp
137
- if (typeof v0 === 'number' && typeof v1 === 'number') {
138
- return v0 + (v1 - v0) * t;
139
- }
140
- // Color string: lerp through RGB
141
- if (typeof v0 === 'string' && typeof v1 === 'string') {
142
- try {
143
- const c0 = resolveColor(v0);
144
- const c1 = resolveColor(v1);
145
- const lerped = lerpColor(c0, c1, t);
146
- return `rgb(${lerped[0]},${lerped[1]},${lerped[2]})`;
147
- }
148
- catch {
149
- return v0;
150
- }
151
- }
152
- return v0;
170
+ const { from, to, t } = span;
171
+ if (typeof from === 'boolean')
172
+ return t < 0.5 ? from : to;
173
+ const n0 = numericValue(from);
174
+ const n1 = numericValue(to);
175
+ if (n0 !== undefined && n1 !== undefined)
176
+ return n0 + (n1 - n0) * t;
177
+ return from;
178
+ }
179
+ /**
180
+ * Interpolate a `color` keyframe track at a frame index: each keyframe value, number or
181
+ * string, is read as a color and the track lerps through RGB, returning `#rrggbb` between
182
+ * keyframes so it resolves like any other color. Every keyframe value is resolved first, so
183
+ * one that isn't a color fails on every frame — including a keyframe the scene never
184
+ * reaches, which interpolation alone would skip past by holding the previous color.
185
+ *
186
+ * @throws {Error} The toolkit's `Unknown color` error for the first value that isn't a color,
187
+ * or an error for an empty track, which input validation rejects before any render.
188
+ */
189
+ export function interpolateColorKeyframe(frames, frameIdx) {
190
+ for (const [, value] of frames)
191
+ resolveColor(String(value));
192
+ const span = keyframeSpan(frames, frameIdx);
193
+ if (!span)
194
+ throw new Error('A color keyframe track needs at least one keyframe.');
195
+ const { from, to, t } = span;
196
+ if (t === 0)
197
+ return String(from);
198
+ const lerped = lerpColor(resolveColor(String(from)), resolveColor(String(to)), t);
199
+ return `#${rgbToHex(lerped).toString(16).padStart(6, '0')}`;
153
200
  }
154
201
  /** Get the interpolated value for a named property at a frame index. */
155
202
  export function getKeyframeValue(keyframes, prop, frameIdx, defaultValue) {
@@ -1 +1 @@
1
- {"version":3,"file":"keyframes.js","sourceRoot":"","sources":["../../src/renderer/keyframes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keyframes.js","sourceRoot":"","sources":["../../src/renderer/keyframes.ts"],"names":[],"mappings":"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"}
@@ -1,15 +1,16 @@
1
1
  /**
2
- * @fileoverview Remote image fetch — downloads an https image to a temp PNG for the
3
- * toolkit's `loadImage`, which reads from disk only. Shared by the scene renderer's
4
- * image elements and the pixoo_push_image tool.
2
+ * @fileoverview Remote image fetch — downloads an https image's encoded bytes into
3
+ * memory for the toolkit's image loaders. Shared by the scene renderer's image elements
4
+ * and the pixoo_push_image tool.
5
5
  * @module renderer/remote-image
6
6
  */
7
7
  import type { Context } from '@cyanheads/mcp-ts-core';
8
8
  /** True when the string is a URL rather than a local filesystem path. */
9
9
  export declare function isRemoteSource(source: string): boolean;
10
10
  /**
11
- * Fetch an https image and write it to a temp PNG, returning the path. The caller
12
- * owns the file and must unlink it once `loadImage` has read it.
11
+ * Fetch an https image and return its bytes as served, undecoded. Nothing is written to
12
+ * disk: the caller passes the bytes to the toolkit's loader, where a body that is not an image
13
+ * fails to decode.
13
14
  *
14
15
  * Private and loopback addresses are deliberately reachable: this server drives a
15
16
  * LAN device, so a NAS or local web server is a legitimate image host.
@@ -18,8 +19,13 @@ export declare function isRemoteSource(source: string): boolean;
18
19
  * down instead of reading on to the deadline or the byte cap.
19
20
  *
20
21
  * @throws {McpError} NotFound with `reason: 'asset_not_found'` for a non-https URL,
21
- * an unreachable or non-2xx endpoint, or a response over {@link MAX_IMAGE_BYTES}.
22
+ * an unreachable or non-2xx endpoint, or a response over {@link MAX_IMAGE_BYTES}. The
23
+ * message names the failure; the recovery is the calling tool's declared one.
22
24
  * @throws {McpError} RequestCancelled when `ctx.signal` aborts while the body streams.
25
+ * @throws {McpError} Timeout when the body outlasts {@link FETCH_TIMEOUT_MS}, or when the
26
+ * `ctx.signal` abort is a caller-side deadline (a `TimeoutError` reason). A tool handler
27
+ * still answers the deadline as RequestCancelled: the handler factory settles any throw
28
+ * after the request's signal fired as a cancellation.
23
29
  */
24
- export declare function fetchRemoteImageToTempPng(source: string, ctx: Context): Promise<string>;
30
+ export declare function fetchRemoteImageBytes(source: string, ctx: Context): Promise<Uint8Array>;
25
31
  //# sourceMappingURL=remote-image.d.ts.map