@excalimate/mcp-server 0.3.0 → 0.4.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 (41) hide show
  1. package/dist/httpServer.d.ts +1 -1
  2. package/dist/httpServer.d.ts.map +1 -1
  3. package/dist/httpServer.js +6 -25
  4. package/dist/httpServer.js.map +1 -1
  5. package/dist/index.js +12 -7
  6. package/dist/index.js.map +1 -1
  7. package/dist/server/animationTools.d.ts.map +1 -1
  8. package/dist/server/animationTools.js +43 -63
  9. package/dist/server/animationTools.js.map +1 -1
  10. package/dist/server/compositeTools.d.ts +18 -0
  11. package/dist/server/compositeTools.d.ts.map +1 -0
  12. package/dist/server/compositeTools.js +209 -0
  13. package/dist/server/compositeTools.js.map +1 -0
  14. package/dist/server/referenceText.d.ts +2 -2
  15. package/dist/server/referenceText.d.ts.map +1 -1
  16. package/dist/server/referenceText.js +83 -254
  17. package/dist/server/referenceText.js.map +1 -1
  18. package/dist/server/sceneTools.d.ts.map +1 -1
  19. package/dist/server/sceneTools.js +2 -1
  20. package/dist/server/sceneTools.js.map +1 -1
  21. package/dist/server/shareTools.d.ts +6 -3
  22. package/dist/server/shareTools.d.ts.map +1 -1
  23. package/dist/server/shareTools.js +17 -17
  24. package/dist/server/shareTools.js.map +1 -1
  25. package/dist/server/stateContext.d.ts +36 -1
  26. package/dist/server/stateContext.d.ts.map +1 -1
  27. package/dist/server/stateContext.js +157 -13
  28. package/dist/server/stateContext.js.map +1 -1
  29. package/dist/server.d.ts +3 -3
  30. package/dist/server.d.ts.map +1 -1
  31. package/dist/server.js +6 -4
  32. package/dist/server.js.map +1 -1
  33. package/dist/state.d.ts +14 -0
  34. package/dist/state.d.ts.map +1 -1
  35. package/dist/state.js +57 -0
  36. package/dist/state.js.map +1 -1
  37. package/package.json +4 -2
  38. package/dist/shareRoutes.d.ts +0 -4
  39. package/dist/shareRoutes.d.ts.map +0 -1
  40. package/dist/shareRoutes.js +0 -44
  41. package/dist/shareRoutes.js.map +0 -1
@@ -0,0 +1,209 @@
1
+ import { z } from 'zod';
2
+ import { addKeyframesBatchToState } from '../state.js';
3
+ import { ANIMATABLE_PROPERTIES, EASING_TYPES } from '../types.js';
4
+ import { ORIGIN_MAP } from './geometry.js';
5
+ /**
6
+ * Registers the `create_animated_scene` composite tool.
7
+ *
8
+ * This is a high-level tool that replaces the typical multi-call pattern:
9
+ * create_scene → add_keyframes_batch → create_sequence → set_clip_range → set_camera_frame
10
+ *
11
+ * All operations happen in a single tool call with one SSE broadcast at the end,
12
+ * reducing AI round-trips from 5-18 to 1 and minimizing network traffic.
13
+ */
14
+ export function registerCompositeTools(server, ctx, normalizeElements, getElementBounds) {
15
+ ctx.mutatingTool('create_animated_scene', 'Create a complete animated scene in one call: elements + keyframes + sequences + camera + clip range. ' +
16
+ 'Preferred over calling create_scene, add_keyframes_batch, create_sequence separately. ' +
17
+ 'Only elements is required — all other fields are optional.', {
18
+ elements: z.string().describe('JSON string of Excalidraw elements array'),
19
+ keyframes: z.string().optional().describe('JSON array of {targetId, property, time, value, easing?, scaleOrigin?}. ' +
20
+ 'Properties: opacity, translateX, translateY, scaleX, scaleY, rotation, drawProgress.'),
21
+ sequences: z.string().optional().describe('JSON array of {elementIds: string[], property?: "opacity"|"drawProgress", ' +
22
+ 'startTime?: number, delay?: number, duration?: number}. Creates reveal sequences.'),
23
+ duration: z.number().optional().describe('Timeline duration in ms (default: 30000)'),
24
+ clipStart: z.number().optional().describe('Clip start time in ms (default: 0)'),
25
+ clipEnd: z.number().optional().describe('Clip end time in ms'),
26
+ cameraFrame: z.object({
27
+ x: z.number().optional(),
28
+ y: z.number().optional(),
29
+ width: z.number().optional(),
30
+ aspectRatio: z.enum(['16:9', '4:3', '1:1', '3:2']).optional(),
31
+ }).optional().describe('Camera frame position and size'),
32
+ }, async ({ elements, keyframes, sequences, duration, clipStart, clipEnd, cameraFrame }) => {
33
+ const errors = [];
34
+ const stats = { elements: 0, keyframes: 0, sequences: 0 };
35
+ // ── 1. Parse and create scene elements ───────────────
36
+ let parsedElements;
37
+ try {
38
+ parsedElements = JSON.parse(elements);
39
+ if (!Array.isArray(parsedElements)) {
40
+ return { content: [{ type: 'text', text: 'Error: elements must be a JSON array' }] };
41
+ }
42
+ }
43
+ catch (e) {
44
+ return { content: [{ type: 'text', text: `Error parsing elements: ${e}` }] };
45
+ }
46
+ const state = ctx.getState();
47
+ state.scene.elements = normalizeElements(parsedElements);
48
+ stats.elements = parsedElements.length;
49
+ // ── 2. Set timeline duration ─────────────────────────
50
+ if (duration !== undefined) {
51
+ state.timeline.duration = Math.max(1000, duration);
52
+ }
53
+ // ── 3. Camera frame ──────────────────────────────────
54
+ if (cameraFrame) {
55
+ if (cameraFrame.x !== undefined)
56
+ state.cameraFrame.x = cameraFrame.x;
57
+ if (cameraFrame.y !== undefined)
58
+ state.cameraFrame.y = cameraFrame.y;
59
+ if (cameraFrame.width !== undefined)
60
+ state.cameraFrame.width = cameraFrame.width;
61
+ if (cameraFrame.aspectRatio !== undefined)
62
+ state.cameraFrame.aspectRatio = cameraFrame.aspectRatio;
63
+ }
64
+ // ── 4. Collect all keyframes into a single batch ─────
65
+ const allKeyframes = [];
66
+ const validProperties = new Set(ANIMATABLE_PROPERTIES);
67
+ const validEasings = new Set(EASING_TYPES);
68
+ // 4a. Camera initial keyframes (always create at t=0 so camera starts correctly)
69
+ if (cameraFrame) {
70
+ const CAMERA_ID = '__camera_frame__';
71
+ allKeyframes.push({ targetId: CAMERA_ID, property: 'translateX', time: 0, value: 0 }, { targetId: CAMERA_ID, property: 'translateY', time: 0, value: 0 }, { targetId: CAMERA_ID, property: 'scaleX', time: 0, value: 1 }, { targetId: CAMERA_ID, property: 'scaleY', time: 0, value: 1 });
72
+ }
73
+ // 4b. User-supplied keyframes
74
+ if (keyframes) {
75
+ try {
76
+ const parsedKfs = JSON.parse(keyframes);
77
+ if (!Array.isArray(parsedKfs)) {
78
+ errors.push('keyframes must be a JSON array — skipped');
79
+ }
80
+ else {
81
+ // Pre-process scale compensation (same logic as add_keyframes_batch)
82
+ const scaleCompensation = new Map();
83
+ for (const kf of parsedKfs) {
84
+ if (!kf.targetId || !kf.property || kf.time === undefined || kf.value === undefined)
85
+ continue;
86
+ if (!validProperties.has(kf.property))
87
+ continue;
88
+ // Collect scale origin compensation data
89
+ if ((kf.property === 'scaleX' || kf.property === 'scaleY') && kf.scaleOrigin && kf.scaleOrigin !== 'top-left') {
90
+ const key = `${kf.targetId}@${kf.time}`;
91
+ const existing = scaleCompensation.get(key) ?? {
92
+ targetId: kf.targetId, time: kf.time, sx: 1, sy: 1,
93
+ origin: kf.scaleOrigin, easing: kf.easing ?? 'linear',
94
+ };
95
+ if (kf.property === 'scaleX')
96
+ existing.sx = kf.value;
97
+ if (kf.property === 'scaleY')
98
+ existing.sy = kf.value;
99
+ existing.origin = kf.scaleOrigin;
100
+ scaleCompensation.set(key, existing);
101
+ }
102
+ const easing = (kf.easing && validEasings.has(kf.easing)) ? kf.easing : 'linear';
103
+ allKeyframes.push({
104
+ targetId: kf.targetId,
105
+ property: kf.property,
106
+ time: kf.time,
107
+ value: kf.value,
108
+ easing: easing,
109
+ });
110
+ stats.keyframes++;
111
+ }
112
+ // Compute scale origin translation compensation
113
+ for (const skf of scaleCompensation.values()) {
114
+ const [ox, oy] = ORIGIN_MAP[skf.origin] ?? [0.5, 0.5];
115
+ const el = state.scene.elements.find((e) => e.id === skf.targetId);
116
+ if (!el)
117
+ continue;
118
+ const bounds = getElementBounds(el);
119
+ const w = bounds.maxX - bounds.minX;
120
+ const h = bounds.maxY - bounds.minY;
121
+ const tx = -w * (skf.sx - 1) * ox;
122
+ const ty = -h * (skf.sy - 1) * oy;
123
+ const easing = (validEasings.has(skf.easing) ? skf.easing : 'linear');
124
+ allKeyframes.push({ targetId: skf.targetId, property: 'translateX', time: skf.time, value: tx, easing }, { targetId: skf.targetId, property: 'translateY', time: skf.time, value: ty, easing });
125
+ stats.keyframes += 2;
126
+ }
127
+ }
128
+ }
129
+ catch (e) {
130
+ errors.push(`Error parsing keyframes: ${e}`);
131
+ }
132
+ }
133
+ // 4c. Sequence reveals → expand into keyframes
134
+ if (sequences) {
135
+ try {
136
+ const parsedSeqs = JSON.parse(sequences);
137
+ if (!Array.isArray(parsedSeqs)) {
138
+ errors.push('sequences must be a JSON array — skipped');
139
+ }
140
+ else {
141
+ for (const seq of parsedSeqs) {
142
+ const ids = seq.elementIds;
143
+ if (!Array.isArray(ids) || ids.length === 0)
144
+ continue;
145
+ const prop = (seq.property === 'drawProgress') ? 'drawProgress' : 'opacity';
146
+ const startTime = seq.startTime ?? 0;
147
+ const delay = seq.delay ?? 300;
148
+ const dur = seq.duration ?? 500;
149
+ for (let i = 0; i < ids.length; i++) {
150
+ const revealStart = startTime + i * delay;
151
+ const revealEnd = revealStart + dur;
152
+ const targetId = ids[i];
153
+ if (revealStart > 0) {
154
+ allKeyframes.push({ targetId, property: prop, time: 0, value: 0 });
155
+ }
156
+ if (revealStart > 10) {
157
+ allKeyframes.push({ targetId, property: prop, time: revealStart, value: 0 });
158
+ }
159
+ allKeyframes.push({ targetId, property: prop, time: revealEnd, value: 1, easing: 'easeOut' });
160
+ stats.keyframes += (revealStart > 0 ? 1 : 0) + (revealStart > 10 ? 1 : 0) + 1;
161
+ }
162
+ stats.sequences++;
163
+ }
164
+ }
165
+ }
166
+ catch (e) {
167
+ errors.push(`Error parsing sequences: ${e}`);
168
+ }
169
+ }
170
+ // ── 5. Apply all keyframes in one batched pass ───────
171
+ if (allKeyframes.length > 0) {
172
+ const newState = addKeyframesBatchToState(state, allKeyframes);
173
+ ctx.updateState(newState);
174
+ }
175
+ // ── 6. Clip range ────────────────────────────────────
176
+ const finalState = ctx.getState();
177
+ if (clipStart !== undefined)
178
+ finalState.clipStart = clipStart;
179
+ if (clipEnd !== undefined) {
180
+ finalState.clipEnd = Math.max((clipStart ?? finalState.clipStart) + 100, clipEnd);
181
+ }
182
+ else if (clipStart === undefined && stats.sequences > 0) {
183
+ // Auto-set clip end to match the last sequence keyframe
184
+ let maxTime = 0;
185
+ for (const kf of allKeyframes) {
186
+ if (kf.time > maxTime)
187
+ maxTime = kf.time;
188
+ }
189
+ if (maxTime > 0) {
190
+ finalState.clipEnd = Math.max(finalState.clipEnd, maxTime + 500);
191
+ }
192
+ }
193
+ // ── 7. Build response ────────────────────────────────
194
+ const parts = [
195
+ `Scene: ${stats.elements} elements`,
196
+ stats.keyframes > 0 ? `${stats.keyframes} keyframes` : null,
197
+ stats.sequences > 0 ? `${stats.sequences} sequences` : null,
198
+ cameraFrame ? `camera: ${finalState.cameraFrame.aspectRatio} at (${finalState.cameraFrame.x}, ${finalState.cameraFrame.y})` : null,
199
+ `clip: ${finalState.clipStart}ms–${finalState.clipEnd}ms`,
200
+ ].filter(Boolean).join(', ');
201
+ const msg = errors.length > 0
202
+ ? `${parts}\nWarnings: ${errors.join('; ')}`
203
+ : parts;
204
+ return { content: [{ type: 'text', text: msg }] };
205
+ },
206
+ // Mark all areas dirty — this tool touches everything
207
+ ['scene', 'timeline', 'clip', 'cameraFrame']);
208
+ }
209
+ //# sourceMappingURL=compositeTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compositeTools.js","sourceRoot":"","sources":["../../src/server/compositeTools.ts"],"names":[],"mappings":"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"}
@@ -1,3 +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";
1
+ export declare const REFERENCE_TEXT = "# Excalimate Reference\n\n## Element Format (base properties)\n{ id, type, x, y, width, height, strokeColor, backgroundColor, fillStyle, strokeWidth, opacity, groupIds, angle }\n\nTypes: rectangle, ellipse, diamond, arrow, line, text, freedraw, image\n\nText extra: { text, fontSize, fontFamily: 5, textAlign, verticalAlign }\nArrow/Line extra: { points: [[0,0],[dx,dy]], endArrowhead: \"arrow\"|null }\nBound text: text with containerId \u2192 shape with boundElements:[{id,type:\"text\"}]\n\n## Colors\nStroke: #1e1e1e #e03131 #2f9e44 #1971c2 #f08c00 #6741d9 #0c8599 #e8590c\nFill: transparent #ffc9c9 #b2f2bb #a5d8ff #ffec99 #d0bfff #99e9f2 #ffd8a8\n\n## Animation Properties\nopacity (0\u20131), translateX/Y (px), scaleX/Y (0.1+), rotation (deg), drawProgress (0\u20131, lines/arrows only)\n\n## Easings\nlinear, easeIn, easeOut, easeInOut, easeInQuad, easeOutQuad, easeInOutQuad,\neaseInCubic, easeOutCubic, easeInOutCubic, easeInBack, easeOutBack, easeInOutBack,\neaseInElastic, easeOutElastic, easeInBounce, easeOutBounce, step\n\n## Preferred Workflow\n1. Use **create_animated_scene** \u2014 one call for elements + keyframes + sequences + camera + clip range\n2. Use add_keyframes_batch or create_sequence for incremental changes\n3. Use save_checkpoint to persist\n4. Verify with animations_of_item, items_visible_in_camera, is_camera_centered\n\n## Key Tips\n- Set opacity 0 at time 0 for elements that appear later\n- Bound text inherits container animation\n- drawProgress only works on arrows/lines\n- easeOutBack = nice bounce; easeInOutCubic = best general-purpose\n- Camera: scale > 1 = zoomed out, < 1 = zoomed in\n- Set clip range before saving\n";
2
+ export declare const EXAMPLES_TEXT = "# Excalimate Examples\n\n## Complete Scene (preferred \u2014 one call)\n```\ncreate_animated_scene({\n elements: '[\n {\"id\":\"A\",\"type\":\"rectangle\",\"x\":100,\"y\":200,\"width\":150,\"height\":80,\"strokeColor\":\"#1e1e1e\",\"backgroundColor\":\"#b2f2bb\",\"fillStyle\":\"solid\",\"boundElements\":[{\"id\":\"A-label\",\"type\":\"text\"}]},\n {\"id\":\"A-label\",\"type\":\"text\",\"x\":120,\"y\":225,\"width\":110,\"height\":30,\"text\":\"Service A\",\"fontSize\":20,\"fontFamily\":5,\"textAlign\":\"center\",\"verticalAlign\":\"middle\",\"containerId\":\"A\"},\n {\"id\":\"B\",\"type\":\"rectangle\",\"x\":500,\"y\":200,\"width\":150,\"height\":80,\"strokeColor\":\"#1e1e1e\",\"backgroundColor\":\"#a5d8ff\",\"fillStyle\":\"solid\",\"boundElements\":[{\"id\":\"B-label\",\"type\":\"text\"}]},\n {\"id\":\"B-label\",\"type\":\"text\",\"x\":520,\"y\":225,\"width\":110,\"height\":30,\"text\":\"Service B\",\"fontSize\":20,\"fontFamily\":5,\"textAlign\":\"center\",\"verticalAlign\":\"middle\",\"containerId\":\"B\"},\n {\"id\":\"arrow1\",\"type\":\"arrow\",\"x\":250,\"y\":240,\"width\":250,\"height\":0,\"points\":[[0,0],[250,0]],\"endArrowhead\":\"arrow\"}\n ]',\n 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 clipEnd: 3000,\n cameraFrame: { x: 375, y: 240, width: 800 }\n})\n```\n\n## Staggered Reveal (simpler alternative)\n```\ncreate_animated_scene({\n elements: '[...elements...]',\n sequences: '[{\"elementIds\":[\"title\",\"box1\",\"arrow1\",\"box2\"],\"delay\":400,\"duration\":600}]',\n clipEnd: 3500\n})\n```\n\n## Scale Animation (pop-in from center)\n```\nadd_scale_animation({ targetId: \"box1\", origin: \"center\", keyframes: '[{\"time\":0,\"scaleX\":0.3,\"scaleY\":0.3},{\"time\":600,\"scaleX\":1,\"scaleY\":1,\"easing\":\"easeOutBack\"}]' })\n```\nOrigins: center, top-left, top-right, bottom-left, bottom-right, top, bottom, left, right\n\n## Camera Pan + Zoom\n```\nset_camera_frame({ x: 300, y: 200, width: 800 })\nadd_camera_keyframes_batch({ keyframes: '[\n {\"property\":\"translateX\",\"time\":0,\"value\":-200},\n {\"property\":\"translateX\",\"time\":3000,\"value\":200,\"easing\":\"easeInOut\"},\n {\"property\":\"scaleX\",\"time\":0,\"value\":1.5},\n {\"property\":\"scaleY\",\"time\":0,\"value\":1.5},\n {\"property\":\"scaleX\",\"time\":3000,\"value\":1,\"easing\":\"easeInOutCubic\"},\n {\"property\":\"scaleY\",\"time\":3000,\"value\":1,\"easing\":\"easeInOutCubic\"}\n]' })\n```\n";
3
3
  //# sourceMappingURL=referenceText.d.ts.map
@@ -1 +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"}
1
+ {"version":3,"file":"referenceText.d.ts","sourceRoot":"","sources":["../../src/server/referenceText.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,woDAoC1B,CAAC;AAIF,eAAO,MAAM,aAAa,0uGAwDzB,CAAC"}