@excalimate/mcp-server 0.1.0 → 0.3.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.
Files changed (64) hide show
  1. package/README.md +176 -16
  2. package/dist/checkpoint-store.d.ts +1 -0
  3. package/dist/checkpoint-store.d.ts.map +1 -1
  4. package/dist/checkpoint-store.js +23 -2
  5. package/dist/checkpoint-store.js.map +1 -1
  6. package/dist/httpServer.d.ts +4 -0
  7. package/dist/httpServer.d.ts.map +1 -0
  8. package/dist/httpServer.js +199 -0
  9. package/dist/httpServer.js.map +1 -0
  10. package/dist/index.d.ts +0 -7
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +35 -177
  13. package/dist/index.js.map +1 -1
  14. package/dist/server/animationTools.d.ts +9 -0
  15. package/dist/server/animationTools.d.ts.map +1 -0
  16. package/dist/server/animationTools.js +254 -0
  17. package/dist/server/animationTools.js.map +1 -0
  18. package/dist/server/checkpointTools.d.ts +5 -0
  19. package/dist/server/checkpointTools.d.ts.map +1 -0
  20. package/dist/server/checkpointTools.js +22 -0
  21. package/dist/server/checkpointTools.js.map +1 -0
  22. package/dist/server/elementNormalizer.d.ts +3 -0
  23. package/dist/server/elementNormalizer.d.ts.map +1 -0
  24. package/dist/server/elementNormalizer.js +52 -0
  25. package/dist/server/elementNormalizer.js.map +1 -0
  26. package/dist/server/geometry.d.ts +24 -0
  27. package/dist/server/geometry.d.ts.map +1 -0
  28. package/dist/server/geometry.js +102 -0
  29. package/dist/server/geometry.js.map +1 -0
  30. package/dist/server/queryTools.d.ts +28 -0
  31. package/dist/server/queryTools.d.ts.map +1 -0
  32. package/dist/server/queryTools.js +107 -0
  33. package/dist/server/queryTools.js.map +1 -0
  34. package/dist/server/referenceText.d.ts +3 -0
  35. package/dist/server/referenceText.d.ts.map +1 -0
  36. package/dist/server/referenceText.js +268 -0
  37. package/dist/server/referenceText.js.map +1 -0
  38. package/dist/server/sceneTools.d.ts +4 -0
  39. package/dist/server/sceneTools.d.ts.map +1 -0
  40. package/dist/server/sceneTools.js +86 -0
  41. package/dist/server/sceneTools.js.map +1 -0
  42. package/dist/server/shareTools.d.ts +11 -0
  43. package/dist/server/shareTools.d.ts.map +1 -0
  44. package/dist/server/shareTools.js +81 -0
  45. package/dist/server/shareTools.js.map +1 -0
  46. package/dist/server/stateContext.d.ts +21 -0
  47. package/dist/server/stateContext.d.ts.map +1 -0
  48. package/dist/server/stateContext.js +85 -0
  49. package/dist/server/stateContext.js.map +1 -0
  50. package/dist/server.d.ts +5 -10
  51. package/dist/server.d.ts.map +1 -1
  52. package/dist/server.js +24 -891
  53. package/dist/server.js.map +1 -1
  54. package/dist/shareRoutes.d.ts +4 -0
  55. package/dist/shareRoutes.d.ts.map +1 -0
  56. package/dist/shareRoutes.js +44 -0
  57. package/dist/shareRoutes.js.map +1 -0
  58. package/dist/stdioServer.d.ts +3 -0
  59. package/dist/stdioServer.d.ts.map +1 -0
  60. package/dist/stdioServer.js +5 -0
  61. package/dist/stdioServer.js.map +1 -0
  62. package/package.json +6 -2
  63. package/SKILL.md +0 -110
  64. package/references/REFERENCE.md +0 -192
@@ -0,0 +1,52 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ let _elementIndexCounter = 0;
3
+ export function normalizeElement(el) {
4
+ const index = el.index ?? `a${_elementIndexCounter++}`;
5
+ return {
6
+ angle: 0,
7
+ strokeColor: '#1e1e1e',
8
+ backgroundColor: 'transparent',
9
+ fillStyle: 'solid',
10
+ strokeWidth: 2,
11
+ strokeStyle: 'solid',
12
+ roughness: 1,
13
+ groupIds: [],
14
+ frameId: null,
15
+ index,
16
+ roundness: null,
17
+ boundElements: null,
18
+ updated: Date.now(),
19
+ link: null,
20
+ locked: false,
21
+ isDeleted: false,
22
+ ...(el.type === 'text' ? {
23
+ fontSize: 20,
24
+ fontFamily: 5,
25
+ textAlign: 'left',
26
+ verticalAlign: 'top',
27
+ lineHeight: 1.25,
28
+ baseline: 0,
29
+ containerId: null,
30
+ originalText: el.text ?? '',
31
+ autoResize: true,
32
+ } : {}),
33
+ ...(el.type === 'arrow' || el.type === 'line' ? {
34
+ points: el.points ?? [[0, 0], [el.width ?? 100, el.height ?? 0]],
35
+ startBinding: null,
36
+ endBinding: null,
37
+ startArrowhead: null,
38
+ endArrowhead: el.type === 'arrow' ? 'arrow' : null,
39
+ lastCommittedPoint: null,
40
+ } : {}),
41
+ ...el,
42
+ opacity: 100,
43
+ ...(el.type === 'text' && !el.containerId ? { autoResize: true } : {}),
44
+ seed: el.seed ?? (Math.random() * 2147483647 | 0),
45
+ version: el.version ?? 1,
46
+ versionNonce: el.versionNonce ?? (Math.random() * 2147483647 | 0),
47
+ };
48
+ }
49
+ export function normalizeElements(elements) {
50
+ return elements.map(normalizeElement);
51
+ }
52
+ //# sourceMappingURL=elementNormalizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elementNormalizer.js","sourceRoot":"","sources":["../../src/server/elementNormalizer.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,IAAI,oBAAoB,GAAG,CAAC,CAAC;AAE7B,MAAM,UAAU,gBAAgB,CAAC,EAAO;IACtC,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,IAAI,IAAI,oBAAoB,EAAE,EAAE,CAAC;IAEvD,OAAO;QACL,KAAK,EAAE,CAAC;QACR,WAAW,EAAE,SAAS;QACtB,eAAe,EAAE,aAAa;QAC9B,SAAS,EAAE,OAAO;QAClB,WAAW,EAAE,CAAC;QACd,WAAW,EAAE,OAAO;QACpB,SAAS,EAAE,CAAC;QACZ,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,IAAI;QACb,KAAK;QACL,SAAS,EAAE,IAAI;QACf,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,IAAI,CAAC,GAAG,EAAE;QACnB,IAAI,EAAE,IAAI;QACV,MAAM,EAAE,KAAK;QACb,SAAS,EAAE,KAAK;QAChB,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;YACvB,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,CAAC;YACb,SAAS,EAAE,MAAM;YACjB,aAAa,EAAE,KAAK;YACpB,UAAU,EAAE,IAAI;YAChB,QAAQ,EAAE,CAAC;YACX,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE;YAC3B,UAAU,EAAE,IAAI;SACjB,CAAC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,OAAO,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC;YAC9C,MAAM,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,IAAI,GAAG,EAAE,EAAE,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;YAChE,YAAY,EAAE,IAAI;YAClB,UAAU,EAAE,IAAI;YAChB,cAAc,EAAE,IAAI;YACpB,YAAY,EAAE,EAAE,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI;YAClD,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,EAAE;QACL,OAAO,EAAE,GAAG;QACZ,GAAG,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,GAAG,CAAC,CAAC;QACjD,OAAO,EAAE,EAAE,CAAC,OAAO,IAAI,CAAC;QACxB,YAAY,EAAE,EAAE,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,UAAU,GAAG,CAAC,CAAC;KAClE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAe;IAC/C,OAAO,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;AACxC,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { AnimationTrack, ServerState } from '../types.js';
2
+ export declare const ORIGIN_MAP: Record<string, [number, number]>;
3
+ export declare function getElementBounds(el: any): {
4
+ minX: number;
5
+ minY: number;
6
+ maxX: number;
7
+ maxY: number;
8
+ };
9
+ export declare function interpolateTrackAt(track: AnimationTrack, time: number): number;
10
+ export declare function getAnimatedBoundsAt(state: ServerState, elId: string, time: number): {
11
+ minX: number;
12
+ minY: number;
13
+ maxX: number;
14
+ maxY: number;
15
+ } | null;
16
+ export declare function getCameraRectAt(state: ServerState, time: number): {
17
+ left: number;
18
+ top: number;
19
+ right: number;
20
+ bottom: number;
21
+ cx: number;
22
+ cy: number;
23
+ };
24
+ //# sourceMappingURL=geometry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/server/geometry.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/D,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAUvD,CAAC;AAEF,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,GAAG,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAapG;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAY9E;AAED,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAgBnE;AAED,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE,MAAM,GACX;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAgBtF"}
@@ -0,0 +1,102 @@
1
+ import { ASPECT_RATIOS, PROPERTY_DEFAULTS } from '../types.js';
2
+ export const ORIGIN_MAP = {
3
+ 'top-left': [0, 0],
4
+ 'top': [0.5, 0],
5
+ 'top-right': [1, 0],
6
+ 'left': [0, 0.5],
7
+ 'center': [0.5, 0.5],
8
+ 'right': [1, 0.5],
9
+ 'bottom-left': [0, 1],
10
+ 'bottom': [0.5, 1],
11
+ 'bottom-right': [1, 1],
12
+ };
13
+ export function getElementBounds(el) {
14
+ if (el.points?.length > 0) {
15
+ let minX = Infinity;
16
+ let minY = Infinity;
17
+ let maxX = -Infinity;
18
+ let maxY = -Infinity;
19
+ for (const [px, py] of el.points) {
20
+ const ax = el.x + px;
21
+ const ay = el.y + py;
22
+ if (ax < minX)
23
+ minX = ax;
24
+ if (ay < minY)
25
+ minY = ay;
26
+ if (ax > maxX)
27
+ maxX = ax;
28
+ if (ay > maxY)
29
+ maxY = ay;
30
+ }
31
+ return { minX, minY, maxX, maxY };
32
+ }
33
+ const x1 = Math.min(el.x, el.x + el.width);
34
+ const y1 = Math.min(el.y, el.y + el.height);
35
+ return { minX: x1, minY: y1, maxX: x1 + Math.abs(el.width), maxY: y1 + Math.abs(el.height) };
36
+ }
37
+ export function interpolateTrackAt(track, time) {
38
+ const kfs = track.keyframes;
39
+ if (kfs.length === 0)
40
+ return PROPERTY_DEFAULTS[track.property];
41
+ if (time <= kfs[0].time)
42
+ return kfs[0].value;
43
+ if (time >= kfs[kfs.length - 1].time)
44
+ return kfs[kfs.length - 1].value;
45
+ for (let i = 0; i < kfs.length - 1; i++) {
46
+ if (time >= kfs[i].time && time <= kfs[i + 1].time) {
47
+ const t = (time - kfs[i].time) / (kfs[i + 1].time - kfs[i].time);
48
+ return kfs[i].value + (kfs[i + 1].value - kfs[i].value) * t;
49
+ }
50
+ }
51
+ return kfs[kfs.length - 1].value;
52
+ }
53
+ export function getAnimatedBoundsAt(state, elId, time) {
54
+ const el = state.scene.elements.find((e) => e.id === elId);
55
+ if (!el)
56
+ return null;
57
+ const base = getElementBounds(el);
58
+ const tracks = state.timeline.tracks.filter((t) => t.targetId === elId);
59
+ let tx = 0;
60
+ let ty = 0;
61
+ let sx = 1;
62
+ let sy = 1;
63
+ for (const track of tracks) {
64
+ const v = interpolateTrackAt(track, time);
65
+ if (track.property === 'translateX')
66
+ tx = v;
67
+ if (track.property === 'translateY')
68
+ ty = v;
69
+ if (track.property === 'scaleX')
70
+ sx = v;
71
+ if (track.property === 'scaleY')
72
+ sy = v;
73
+ }
74
+ const w = (base.maxX - base.minX) * sx;
75
+ const h = (base.maxY - base.minY) * sy;
76
+ return { minX: base.minX + tx, minY: base.minY + ty, maxX: base.minX + tx + w, maxY: base.minY + ty + h };
77
+ }
78
+ export function getCameraRectAt(state, time) {
79
+ const cf = state.cameraFrame;
80
+ const camTracks = state.timeline.tracks.filter((t) => t.targetId === '__camera_frame__');
81
+ let tx = 0;
82
+ let ty = 0;
83
+ let sx = 1;
84
+ let sy = 1;
85
+ for (const track of camTracks) {
86
+ const v = interpolateTrackAt(track, time);
87
+ if (track.property === 'translateX')
88
+ tx = v;
89
+ if (track.property === 'translateY')
90
+ ty = v;
91
+ if (track.property === 'scaleX')
92
+ sx = v;
93
+ if (track.property === 'scaleY')
94
+ sy = v;
95
+ }
96
+ const w = cf.width * sx;
97
+ const h = (cf.width / (ASPECT_RATIOS[cf.aspectRatio] ?? 16 / 9)) * sy;
98
+ const cx = cf.x + tx;
99
+ const cy = cf.y + ty;
100
+ return { left: cx - w / 2, top: cy - h / 2, right: cx + w / 2, bottom: cy + h / 2, cx, cy };
101
+ }
102
+ //# sourceMappingURL=geometry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../src/server/geometry.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,CAAC,MAAM,UAAU,GAAqC;IAC1D,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IAClB,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IACf,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACnB,MAAM,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC;IAChB,QAAQ,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC;IACpB,OAAO,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC;IACjB,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACrB,QAAQ,EAAE,CAAC,GAAG,EAAE,CAAC,CAAC;IAClB,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,EAAO;IACtC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,IAAI,IAAI,GAAG,QAAQ,CAAC;QAAC,IAAI,IAAI,GAAG,QAAQ,CAAC;QAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC;QAAC,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC;QACrF,KAAK,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;YACjC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAAC,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YAC3C,IAAI,EAAE,GAAG,IAAI;gBAAE,IAAI,GAAG,EAAE,CAAC;YAAC,IAAI,EAAE,GAAG,IAAI;gBAAE,IAAI,GAAG,EAAE,CAAC;YACnD,IAAI,EAAE,GAAG,IAAI;gBAAE,IAAI,GAAG,EAAE,CAAC;YAAC,IAAI,EAAE,GAAG,IAAI;gBAAE,IAAI,GAAG,EAAE,CAAC;QACrD,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACpC,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC;IAC5C,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAqB,EAAE,IAAY;IACpE,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC;IAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC/D,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7C,IAAI,IAAI,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,IAAI;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;IACvE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACnD,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACjE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,KAAkB,EAClB,IAAY,EACZ,IAAY;IAEZ,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC;IAChE,IAAI,CAAC,EAAE;QAAE,OAAO,IAAI,CAAC;IACrB,MAAM,IAAI,GAAG,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,IAAI,CAAC,CAAC;IAC7E,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY;YAAE,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY;YAAE,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;YAAE,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;YAAE,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACvC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IACvC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;AAC5G,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,KAAkB,EAClB,IAAY;IAEZ,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC;IAC7B,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,kBAAkB,CAAC,CAAC;IAC9F,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/C,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,kBAAkB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;QAC1C,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY;YAAE,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,QAAQ,KAAK,YAAY;YAAE,EAAE,GAAG,CAAC,CAAC;QAC5C,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;YAAE,EAAE,GAAG,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;YAAE,EAAE,GAAG,CAAC,CAAC;IAC1C,CAAC;IACD,MAAM,CAAC,GAAG,EAAE,CAAC,KAAK,GAAG,EAAE,CAAC;IACxB,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;IACtE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IACrB,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IACrB,OAAO,EAAE,IAAI,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { StateContext } from './stateContext.js';
3
+ interface Geometry {
4
+ getElementBounds: (el: any) => {
5
+ minX: number;
6
+ minY: number;
7
+ maxX: number;
8
+ maxY: number;
9
+ };
10
+ getAnimatedBoundsAt: (state: any, elId: string, time: number) => {
11
+ minX: number;
12
+ minY: number;
13
+ maxX: number;
14
+ maxY: number;
15
+ } | null;
16
+ getCameraRectAt: (state: any, time: number) => {
17
+ left: number;
18
+ top: number;
19
+ right: number;
20
+ bottom: number;
21
+ cx: number;
22
+ cy: number;
23
+ };
24
+ interpolateTrackAt: (track: any, time: number) => number;
25
+ }
26
+ export declare function registerQueryTools(server: McpServer, ctx: StateContext, geometry: Geometry): void;
27
+ export {};
28
+ //# sourceMappingURL=queryTools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryTools.d.ts","sourceRoot":"","sources":["../../src/server/queryTools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD,UAAU,QAAQ;IAChB,gBAAgB,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1F,mBAAmB,EAAE,CACnB,KAAK,EAAE,GAAG,EACV,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,KACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,eAAe,EAAE,CACf,KAAK,EAAE,GAAG,EACV,IAAI,EAAE,MAAM,KACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1F,kBAAkB,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC1D;AAED,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,SAAS,EACjB,GAAG,EAAE,YAAY,EACjB,QAAQ,EAAE,QAAQ,GACjB,IAAI,CAiHN"}
@@ -0,0 +1,107 @@
1
+ import { z } from 'zod';
2
+ export function registerQueryTools(server, ctx, geometry) {
3
+ server.tool('are_items_in_line', 'Check if the given items are aligned horizontally or vertically (within a tolerance).', {
4
+ ids: z.array(z.string()).describe('Element IDs to check'),
5
+ axis: z.enum(['horizontal', 'vertical']).describe('Alignment axis'),
6
+ tolerance: z.number().optional().describe('Max deviation in scene units (default 10)'),
7
+ }, async ({ ids, axis, tolerance = 10 }) => {
8
+ const state = ctx.getState();
9
+ const centers = [];
10
+ for (const id of ids) {
11
+ const el = state.scene.elements.find((e) => e.id === id);
12
+ if (!el)
13
+ return { content: [{ type: 'text', text: `Element "${id}" not found.` }] };
14
+ const b = geometry.getElementBounds(el);
15
+ centers.push({ id, cx: (b.minX + b.maxX) / 2, cy: (b.minY + b.maxY) / 2 });
16
+ }
17
+ const values = centers.map(c => axis === 'horizontal' ? c.cy : c.cx);
18
+ const avg = values.reduce((a, b) => a + b, 0) / values.length;
19
+ const maxDev = Math.max(...values.map(v => Math.abs(v - avg)));
20
+ const aligned = maxDev <= tolerance;
21
+ const details = centers.map(c => `${c.id}: (${Math.round(c.cx)}, ${Math.round(c.cy)})`).join(', ');
22
+ return { content: [{ type: 'text', text: `${aligned ? '✅ Aligned' : '❌ Not aligned'} (max deviation: ${Math.round(maxDev)}px, tolerance: ${tolerance}px). Centers: ${details}` }] };
23
+ });
24
+ server.tool('is_camera_centered', 'Check if the camera is centered on the scene content (horizontally, vertically, or both).', {
25
+ axis: z.enum(['horizontal', 'vertical', 'both']).describe('Which axis to check'),
26
+ time: z.number().min(0).default(0).describe('Time in ms to check at'),
27
+ tolerance: z.number().optional().describe('Max deviation (default 20)'),
28
+ }, async ({ axis, time, tolerance = 20 }) => {
29
+ const state = ctx.getState();
30
+ let sMinX = Infinity;
31
+ let sMinY = Infinity;
32
+ let sMaxX = -Infinity;
33
+ let sMaxY = -Infinity;
34
+ for (const el of state.scene.elements) {
35
+ const b = geometry.getElementBounds(el);
36
+ if (b.minX < sMinX)
37
+ sMinX = b.minX;
38
+ if (b.minY < sMinY)
39
+ sMinY = b.minY;
40
+ if (b.maxX > sMaxX)
41
+ sMaxX = b.maxX;
42
+ if (b.maxY > sMaxY)
43
+ sMaxY = b.maxY;
44
+ }
45
+ const sceneCX = (sMinX + sMaxX) / 2;
46
+ const sceneCY = (sMinY + sMaxY) / 2;
47
+ const cam = geometry.getCameraRectAt(state, time);
48
+ const dxOk = Math.abs(cam.cx - sceneCX) <= tolerance;
49
+ const dyOk = Math.abs(cam.cy - sceneCY) <= tolerance;
50
+ const ok = axis === 'horizontal' ? dxOk : axis === 'vertical' ? dyOk : dxOk && dyOk;
51
+ return { content: [{ type: 'text', text: `${ok ? '✅ Centered' : '❌ Not centered'} (scene center: ${Math.round(sceneCX)},${Math.round(sceneCY)}, camera center: ${Math.round(cam.cx)},${Math.round(cam.cy)}, offsets: dx=${Math.round(cam.cx - sceneCX)} dy=${Math.round(cam.cy - sceneCY)})` }] };
52
+ });
53
+ server.tool('items_visible_in_camera', 'Check what percentage of items are visible in the camera frame at a given time.', {
54
+ time: z.number().min(0).default(0).describe('Time in ms'),
55
+ }, async ({ time }) => {
56
+ const state = ctx.getState();
57
+ const cam = geometry.getCameraRectAt(state, time);
58
+ const elements = state.scene.elements.filter((e) => !e.isDeleted && e.id !== '__camera_frame__');
59
+ let visible = 0;
60
+ const details = [];
61
+ for (const el of elements) {
62
+ const b = geometry.getAnimatedBoundsAt(state, el.id, time);
63
+ if (!b)
64
+ continue;
65
+ const opTrack = state.timeline.tracks.find((t) => t.targetId === el.id && t.property === 'opacity');
66
+ const opacity = opTrack ? geometry.interpolateTrackAt(opTrack, time) : 1;
67
+ const inView = b.maxX > cam.left && b.minX < cam.right && b.maxY > cam.top && b.minY < cam.bottom;
68
+ const isVisible = inView && opacity > 0.01;
69
+ if (isVisible)
70
+ visible++;
71
+ details.push(`${el.id}: ${isVisible ? '✅' : '❌'} (opacity=${(opacity * 100).toFixed(0)}%, inView=${inView})`);
72
+ }
73
+ const pct = elements.length > 0 ? Math.round(visible / elements.length * 100) : 0;
74
+ return { content: [{ type: 'text', text: `${visible}/${elements.length} items visible (${pct}%) at ${time}ms.\n${details.join('\n')}` }] };
75
+ });
76
+ server.tool('animations_of_item', 'Returns a timeline description of all animations an item goes through.', {
77
+ targetId: z.string().describe('Element ID'),
78
+ }, async ({ targetId }) => {
79
+ const state = ctx.getState();
80
+ const tracks = state.timeline.tracks.filter((t) => t.targetId === targetId);
81
+ if (tracks.length === 0) {
82
+ return { content: [{ type: 'text', text: `No animations for "${targetId}".` }] };
83
+ }
84
+ const lines = [`Animations for "${targetId}":`];
85
+ for (const track of tracks) {
86
+ if (track.keyframes.length === 0)
87
+ continue;
88
+ lines.push(` ${track.property}:`);
89
+ for (let i = 0; i < track.keyframes.length; i++) {
90
+ const kf = track.keyframes[i];
91
+ const next = track.keyframes[i + 1];
92
+ if (next) {
93
+ const fromLabel = track.property === 'opacity' ? `${(kf.value * 100).toFixed(0)}%` : String(kf.value);
94
+ const toLabel = track.property === 'opacity' ? `${(next.value * 100).toFixed(0)}%` : String(next.value);
95
+ const direction = next.value > kf.value ? '↑' : next.value < kf.value ? '↓' : '→';
96
+ lines.push(` ${kf.time}ms ${fromLabel} ${direction} ${toLabel} ${next.time}ms (${kf.easing})`);
97
+ }
98
+ else {
99
+ const label = track.property === 'opacity' ? `${(kf.value * 100).toFixed(0)}%` : String(kf.value);
100
+ lines.push(` ${kf.time}ms ${label} (hold)`);
101
+ }
102
+ }
103
+ }
104
+ return { content: [{ type: 'text', text: lines.join('\n') }] };
105
+ });
106
+ }
107
+ //# sourceMappingURL=queryTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryTools.js","sourceRoot":"","sources":["../../src/server/queryTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare const REFERENCE_TEXT = "# Excalimate MCP Reference\n\n## Excalidraw Element Format\n\nEvery element has these base properties:\n```json\n{\n \"id\": \"unique-id\",\n \"type\": \"rectangle|ellipse|diamond|arrow|line|text|freedraw|image\",\n \"x\": 100, \"y\": 200,\n \"width\": 300, \"height\": 150,\n \"angle\": 0,\n \"strokeColor\": \"#1e1e1e\",\n \"backgroundColor\": \"transparent\",\n \"fillStyle\": \"solid\",\n \"strokeWidth\": 2,\n \"roughness\": 1,\n \"opacity\": 100,\n \"groupIds\": [],\n \"isDeleted\": false\n}\n```\n\n### Text Elements\n```json\n{\n \"type\": \"text\",\n \"text\": \"Hello World\",\n \"fontSize\": 20,\n \"fontFamily\": 5,\n \"textAlign\": \"center\",\n \"verticalAlign\": \"middle\"\n}\n```\n\n### Arrow/Line Elements\n```json\n{\n \"type\": \"arrow\",\n \"points\": [[0, 0], [200, 100]],\n \"startArrowhead\": null,\n \"endArrowhead\": \"arrow\",\n \"startBinding\": null,\n \"endBinding\": null\n}\n```\n\n### Bound Text (Label on Shape)\nCreate a text element with `containerId` pointing to the shape:\n```json\n{ \"type\": \"text\", \"containerId\": \"shape-id\", ... }\n```\nAnd add to the shape: `\"boundElements\": [{\"id\": \"text-id\", \"type\": \"text\"}]`\n\n## Color Palettes\n\n**Stroke**: #1e1e1e, #e03131, #2f9e44, #1971c2, #f08c00, #6741d9, #0c8599, #e8590c\n**Background**: transparent, #ffc9c9, #b2f2bb, #a5d8ff, #ffec99, #d0bfff, #99e9f2, #ffd8a8\n\n## Animatable Properties\n\n| Property | Range | Description |\n|----------|-------|-------------|\n| opacity | 0\u20131 | Element visibility (0=hidden, 1=visible) |\n| translateX | px | Horizontal position offset |\n| translateY | px | Vertical position offset |\n| scaleX | 0.1+ | Horizontal scale (1=normal) |\n| scaleY | 0.1+ | Vertical scale (1=normal) |\n| rotation | degrees | Rotation angle |\n| drawProgress | 0\u20131 | Stroke draw-on progress (for lines/arrows) |\n\n## Easing Types\n\nlinear, easeIn, easeOut, easeInOut, easeInQuad, easeOutQuad, easeInOutQuad,\neaseInCubic, easeOutCubic, easeInOutCubic, easeInBack, easeOutBack, easeInOutBack,\neaseInElastic, easeOutElastic, easeInBounce, easeOutBounce, step\n\n## Workflow\n\n1. Call `read_me` (this tool) to get the reference\n2. Call `create_scene` with Excalidraw elements JSON (or `clear_scene` to start fresh)\n3. Call `add_keyframe` or `add_keyframes_batch` to animate elements\n4. Use `create_sequence` for reveal animations\n5. Call `set_clip_range` to set export bounds\n6. Call `save_checkpoint` to persist\n7. User opens the checkpoint in the Excalimate web app for preview/export\n\nUse `clear_scene` to reset everything (elements + animations) or `clear_animation` to keep elements but remove all keyframes.\n\n## Example: Fade-in Rectangle\n\n```\n1. create_scene: [{\"id\":\"rect1\",\"type\":\"rectangle\",\"x\":100,\"y\":100,\"width\":200,\"height\":100,...}]\n2. add_keyframe: {targetId:\"rect1\", property:\"opacity\", time:0, value:0}\n3. add_keyframe: {targetId:\"rect1\", property:\"opacity\", time:1000, value:1, easing:\"easeOut\"}\n```\n";
2
+ export declare const EXAMPLES_TEXT = "# Excalimate \u2014 Few-Shot Examples\n\n## Example 1: Single Rectangle\n```\ncreate_scene({ elements: '[{\"id\":\"box1\",\"type\":\"rectangle\",\"x\":200,\"y\":150,\"width\":250,\"height\":120,\"strokeColor\":\"#1971c2\",\"backgroundColor\":\"#a5d8ff\",\"fillStyle\":\"solid\"}]' })\n```\n\n## Example 2: Rectangle with Bound Text Label\n```\ncreate_scene({ elements: '[{\"id\":\"server\",\"type\":\"rectangle\",\"x\":100,\"y\":100,\"width\":200,\"height\":80,\"strokeColor\":\"#1e1e1e\",\"backgroundColor\":\"#a5d8ff\",\"fillStyle\":\"solid\",\"boundElements\":[{\"id\":\"server-label\",\"type\":\"text\"}]},{\"id\":\"server-label\",\"type\":\"text\",\"x\":140,\"y\":125,\"width\":120,\"height\":30,\"text\":\"API Server\",\"fontSize\":20,\"fontFamily\":5,\"textAlign\":\"center\",\"verticalAlign\":\"middle\",\"containerId\":\"server\"}]' })\n```\n\n## Example 3: Two Shapes Connected by Arrow\n```\ncreate_scene({ elements: '[{\"id\":\"A\",\"type\":\"rectangle\",\"x\":100,\"y\":200,\"width\":150,\"height\":80,\"strokeColor\":\"#1e1e1e\",\"backgroundColor\":\"#b2f2bb\",\"fillStyle\":\"solid\"},{\"id\":\"B\",\"type\":\"rectangle\",\"x\":500,\"y\":200,\"width\":150,\"height\":80,\"strokeColor\":\"#1e1e1e\",\"backgroundColor\":\"#a5d8ff\",\"fillStyle\":\"solid\"},{\"id\":\"arrow1\",\"type\":\"arrow\",\"x\":250,\"y\":240,\"width\":250,\"height\":0,\"points\":[[0,0],[250,0]],\"endArrowhead\":\"arrow\",\"startBinding\":{\"elementId\":\"A\",\"focus\":0,\"gap\":1},\"endBinding\":{\"elementId\":\"B\",\"focus\":0,\"gap\":1}}]' })\n```\n\n## Example 4: Ellipse and Diamond\n```\nadd_elements({ elements: '[{\"id\":\"circle1\",\"type\":\"ellipse\",\"x\":300,\"y\":100,\"width\":120,\"height\":120,\"strokeColor\":\"#e03131\",\"backgroundColor\":\"#ffc9c9\",\"fillStyle\":\"solid\"},{\"id\":\"diamond1\",\"type\":\"diamond\",\"x\":500,\"y\":90,\"width\":140,\"height\":140,\"strokeColor\":\"#6741d9\",\"backgroundColor\":\"#d0bfff\",\"fillStyle\":\"solid\"}]' })\n```\n\n## Example 5: Multi-Point Line\n```\nadd_elements({ elements: '[{\"id\":\"line1\",\"type\":\"line\",\"x\":100,\"y\":300,\"width\":400,\"height\":80,\"points\":[[0,0],[200,-80],[400,0]],\"strokeColor\":\"#e03131\",\"strokeWidth\":3}]' })\n```\n\n## Example 6: Standalone Text\n```\nadd_elements({ elements: '[{\"id\":\"title\",\"type\":\"text\",\"x\":200,\"y\":50,\"width\":300,\"height\":50,\"text\":\"Architecture Overview\",\"fontSize\":36,\"fontFamily\":5,\"textAlign\":\"center\",\"strokeColor\":\"#1e1e1e\"}]' })\n```\n\n---\n\n# Animation Examples\n\n## Example 7: Fade In\n```\nadd_keyframe({ targetId: \"box1\", property: \"opacity\", time: 0, value: 0 })\nadd_keyframe({ targetId: \"box1\", property: \"opacity\", time: 800, value: 1, easing: \"easeOut\" })\n```\n\n## Example 8: Slide In from Left\n```\nadd_keyframes_batch({ keyframes: '[{\"targetId\":\"box1\",\"property\":\"translateX\",\"time\":0,\"value\":-300},{\"targetId\":\"box1\",\"property\":\"translateX\",\"time\":1000,\"value\":0,\"easing\":\"easeOutCubic\"},{\"targetId\":\"box1\",\"property\":\"opacity\",\"time\":0,\"value\":0},{\"targetId\":\"box1\",\"property\":\"opacity\",\"time\":500,\"value\":1,\"easing\":\"easeOut\"}]' })\n```\n\n## Example 9: Pop In from Center (Scale Up with Bounce)\n```\nadd_keyframes_batch({ keyframes: '[{\"targetId\":\"box1\",\"property\":\"scaleX\",\"time\":0,\"value\":0.3,\"scaleOrigin\":\"center\"},{\"targetId\":\"box1\",\"property\":\"scaleY\",\"time\":0,\"value\":0.3,\"scaleOrigin\":\"center\"},{\"targetId\":\"box1\",\"property\":\"scaleX\",\"time\":600,\"value\":1,\"easing\":\"easeOutBack\",\"scaleOrigin\":\"center\"},{\"targetId\":\"box1\",\"property\":\"scaleY\",\"time\":600,\"value\":1,\"easing\":\"easeOutBack\",\"scaleOrigin\":\"center\"},{\"targetId\":\"box1\",\"property\":\"opacity\",\"time\":0,\"value\":0},{\"targetId\":\"box1\",\"property\":\"opacity\",\"time\":300,\"value\":1}]' })\n```\n\n## Example 9b: Scale from Bottom Edge\n```\nadd_scale_animation({ targetId: \"box1\", origin: \"bottom\", keyframes: '[{\"time\":0,\"scaleX\":1,\"scaleY\":0},{\"time\":800,\"scaleX\":1,\"scaleY\":1,\"easing\":\"easeOutCubic\"}]' })\n```\nScale origins: center, top-left, top-right, bottom-left, bottom-right, top, bottom, left, right.\nAdd \"scaleOrigin\" per scaleX/scaleY keyframe in add_keyframes_batch, or use add_scale_animation for a single element.\n\n## Example 10: Draw In an Arrow (Stroke Animation)\n```\nadd_keyframe({ targetId: \"arrow1\", property: \"drawProgress\", time: 0, value: 0 })\nadd_keyframe({ targetId: \"arrow1\", property: \"drawProgress\", time: 1200, value: 1, easing: \"easeInOut\" })\n```\n\n## Example 11: Sequential Reveal \u2014 A \u2192 Arrow \u2192 B (Most Common Pattern)\n```\nadd_keyframes_batch({ keyframes: '[\n {\"targetId\":\"A\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"A\",\"property\":\"opacity\",\"time\":600,\"value\":1,\"easing\":\"easeOut\"},\n {\"targetId\":\"arrow1\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"arrow1\",\"property\":\"opacity\",\"time\":600,\"value\":0},\n {\"targetId\":\"arrow1\",\"property\":\"opacity\",\"time\":700,\"value\":1},\n {\"targetId\":\"arrow1\",\"property\":\"drawProgress\",\"time\":600,\"value\":0},\n {\"targetId\":\"arrow1\",\"property\":\"drawProgress\",\"time\":1800,\"value\":1,\"easing\":\"easeInOut\"},\n {\"targetId\":\"B\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"B\",\"property\":\"opacity\",\"time\":1800,\"value\":0},\n {\"targetId\":\"B\",\"property\":\"opacity\",\"time\":2400,\"value\":1,\"easing\":\"easeOut\"}\n]' })\n```\n\n## Example 12: Bidirectional Flow \u2014 A \u2194 B\n```\nadd_keyframes_batch({ keyframes: '[\n {\"targetId\":\"A\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"A\",\"property\":\"opacity\",\"time\":500,\"value\":1,\"easing\":\"easeOut\"},\n {\"targetId\":\"arrowAB\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"arrowAB\",\"property\":\"opacity\",\"time\":500,\"value\":1},\n {\"targetId\":\"arrowAB\",\"property\":\"drawProgress\",\"time\":500,\"value\":0},\n {\"targetId\":\"arrowAB\",\"property\":\"drawProgress\",\"time\":1500,\"value\":1,\"easing\":\"easeInOut\"},\n {\"targetId\":\"B\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"B\",\"property\":\"opacity\",\"time\":1500,\"value\":0},\n {\"targetId\":\"B\",\"property\":\"opacity\",\"time\":2000,\"value\":1,\"easing\":\"easeOut\"},\n {\"targetId\":\"arrowBA\",\"property\":\"opacity\",\"time\":0,\"value\":0},\n {\"targetId\":\"arrowBA\",\"property\":\"opacity\",\"time\":2000,\"value\":1},\n {\"targetId\":\"arrowBA\",\"property\":\"drawProgress\",\"time\":2000,\"value\":0},\n {\"targetId\":\"arrowBA\",\"property\":\"drawProgress\",\"time\":3000,\"value\":1,\"easing\":\"easeInOut\"}\n]' })\n```\n\n## Example 13: Staggered Reveal via create_sequence\n```\ncreate_sequence({ elementIds: [\"title\",\"box1\",\"arrow1\",\"box2\",\"arrow2\",\"box3\"], property: \"opacity\", startTime: 0, delay: 400, duration: 600 })\n```\nResult: title at 0ms, box1 at 400ms, arrow1 at 800ms, box2 at 1200ms, arrow2 at 1600ms, box3 at 2000ms.\n\n## Example 14: Camera Pan\n```\nset_camera_frame({ x: 300, y: 200, width: 800, aspectRatio: \"16:9\" })\nadd_camera_keyframe({ property: \"translateX\", time: 0, value: -200 })\nadd_camera_keyframe({ property: \"translateX\", time: 3000, value: 200, easing: \"easeInOut\" })\n```\n\n## Example 15: Camera Zoom In\n```\nadd_camera_keyframe({ property: \"scaleX\", time: 0, value: 2 })\nadd_camera_keyframe({ property: \"scaleY\", time: 0, value: 2 })\nadd_camera_keyframe({ property: \"scaleX\", time: 2000, value: 1, easing: \"easeInOutCubic\" })\nadd_camera_keyframe({ property: \"scaleY\", time: 2000, value: 1, easing: \"easeInOutCubic\" })\n```\n\n## Example 16: Clip Range + Save\n```\nset_clip_range({ start: 0, end: 5000 })\nsave_checkpoint({ id: \"my-animation\" })\n```\n\n---\n\n# Tips\n\n1. Always call create_scene first (or clear_scene to start fresh), then animate.\n2. Use add_keyframes_batch for efficiency \u2014 one call for many keyframes.\n3. Use create_sequence for simple staggered reveals.\n4. Bound text inherits container animation \u2014 animating arrow opacity also hides its label.\n5. drawProgress only works on arrows and lines.\n6. easeOutBack gives a nice bounce for pop-in effects.\n7. easeInOutCubic is the best general-purpose easing.\n8. Set elements to opacity 0 at time 0 if they should appear later.\n9. Set clip range before saving \u2014 it defines what gets exported.\n10. Camera scale > 1 = zoomed out, < 1 = zoomed in.\n11. Use delete_items to remove elements AND their animation tracks in one call.\n12. Verify your work with animations_of_item, items_visible_in_camera, are_items_in_line, is_camera_centered.\n\n## Example 17: Verify Animation\n```\nanimations_of_item({ targetId: \"box1\" })\n// Returns:\n// opacity:\n// 0ms 0% \u2191 100% 600ms (easeOut)\n\nitems_visible_in_camera({ time: 1000 })\n// Returns: 5/8 items visible (62%) at 1000ms\n\nare_items_in_line({ ids: [\"box1\",\"box2\",\"box3\"], axis: \"horizontal\" })\n// Returns: \u2705 Aligned (max deviation: 3px)\n\nis_camera_centered({ axis: \"both\", time: 0 })\n// Returns: \u2705 Centered (offsets: dx=5 dy=2)\n```\n\n## Example 18: Delete and Rebuild\n```\ndelete_items({ ids: [\"old_box\", \"old_arrow\"] })\n// Removes elements + all their animation tracks\n\nclear_scene()\n// Nuclear option: removes everything\n```\n";
3
+ //# sourceMappingURL=referenceText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"referenceText.d.ts","sourceRoot":"","sources":["../../src/server/referenceText.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,w9FAgG1B,CAAC;AAEF,eAAO,MAAM,aAAa,m0SAyKzB,CAAC"}