@pixerate/editor 0.79.0 → 0.81.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 (70) hide show
  1. package/README.md +13 -3
  2. package/dist/agent/index.cjs +102 -6
  3. package/dist/agent/index.cjs.map +1 -1
  4. package/dist/agent/index.d.cts +4 -2
  5. package/dist/agent/index.d.ts +4 -2
  6. package/dist/agent/index.js +101 -5
  7. package/dist/agent/index.js.map +1 -1
  8. package/dist/{builtins-BKYlHH1s.d.ts → builtins-CV1fDj64.d.ts} +5 -1
  9. package/dist/{builtins-1kqwLUnb.d.cts → builtins-c4w0eAYl.d.cts} +5 -1
  10. package/dist/{chunk-2CJ3LPYQ.js → chunk-424H3P4I.js} +13 -295
  11. package/dist/chunk-424H3P4I.js.map +1 -0
  12. package/dist/{chunk-UN33YOXW.cjs → chunk-PA5S7KPC.cjs} +293 -2
  13. package/dist/chunk-PA5S7KPC.cjs.map +1 -0
  14. package/dist/{chunk-IB3ZHQAX.js → chunk-PTYWCFFW.js} +29 -4
  15. package/dist/chunk-PTYWCFFW.js.map +1 -0
  16. package/dist/{chunk-JQ3BB3E6.js → chunk-PXDEFEG2.js} +293 -2
  17. package/dist/chunk-PXDEFEG2.js.map +1 -0
  18. package/dist/{chunk-YU4WQE5M.cjs → chunk-TAPXWP2B.cjs} +95 -377
  19. package/dist/chunk-TAPXWP2B.cjs.map +1 -0
  20. package/dist/{chunk-HXDMZQTD.cjs → chunk-TPOT575P.cjs} +29 -4
  21. package/dist/{chunk-IB3ZHQAX.js.map → chunk-TPOT575P.cjs.map} +1 -1
  22. package/dist/commands/index.cjs +2 -2
  23. package/dist/commands/index.d.cts +1 -1
  24. package/dist/commands/index.d.ts +1 -1
  25. package/dist/commands/index.js +1 -1
  26. package/dist/generation/index.cjs +932 -791
  27. package/dist/generation/index.cjs.map +1 -1
  28. package/dist/generation/index.d.cts +266 -240
  29. package/dist/generation/index.d.ts +266 -240
  30. package/dist/generation/index.js +926 -785
  31. package/dist/generation/index.js.map +1 -1
  32. package/dist/image-editor/index.cjs +266 -2
  33. package/dist/image-editor/index.cjs.map +1 -1
  34. package/dist/image-editor/index.d.cts +12 -1
  35. package/dist/image-editor/index.d.ts +12 -1
  36. package/dist/image-editor/index.js +265 -1
  37. package/dist/image-editor/index.js.map +1 -1
  38. package/dist/index.cjs +3 -3
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.js +16 -16
  41. package/dist/spreadsheet/index.cjs +3 -3
  42. package/dist/spreadsheet/index.cjs.map +1 -1
  43. package/dist/spreadsheet/index.js +16 -16
  44. package/dist/video-editor/index.cjs +461 -101
  45. package/dist/video-editor/index.cjs.map +1 -1
  46. package/dist/video-editor/index.d.cts +67 -3
  47. package/dist/video-editor/index.d.ts +67 -3
  48. package/dist/video-editor/index.js +426 -66
  49. package/dist/video-editor/index.js.map +1 -1
  50. package/package.json +3 -1
  51. package/skills/README.md +55 -0
  52. package/skills/pixerate-agent-tools/SKILL.md +75 -0
  53. package/skills/pixerate-animation-editor/SKILL.md +155 -0
  54. package/skills/pixerate-animation-editor/references/commands.md +123 -0
  55. package/skills/pixerate-canvas/SKILL.md +230 -0
  56. package/skills/pixerate-chart/SKILL.md +190 -0
  57. package/skills/pixerate-diagram/SKILL.md +134 -0
  58. package/skills/pixerate-generation/SKILL.md +109 -0
  59. package/skills/pixerate-image-editor/SKILL.md +139 -0
  60. package/skills/pixerate-parameters/SKILL.md +83 -0
  61. package/skills/pixerate-rich-text/SKILL.md +160 -0
  62. package/skills/pixerate-spreadsheet/SKILL.md +146 -0
  63. package/skills/pixerate-vector/SKILL.md +191 -0
  64. package/skills/pixerate-vector/references/commands.md +138 -0
  65. package/skills/pixerate-video-editor/SKILL.md +173 -0
  66. package/dist/chunk-2CJ3LPYQ.js.map +0 -1
  67. package/dist/chunk-HXDMZQTD.cjs.map +0 -1
  68. package/dist/chunk-JQ3BB3E6.js.map +0 -1
  69. package/dist/chunk-UN33YOXW.cjs.map +0 -1
  70. package/dist/chunk-YU4WQE5M.cjs.map +0 -1
@@ -0,0 +1,230 @@
1
+ ---
2
+ name: pixerate-canvas
3
+ description: How to build and edit a Pixerate design canvas or node graph through its agent tools - adding, connecting, updating and laying out nodes (canvas_add_node, canvas_layout), reading state with get_editor_state and looking at it with view_editor, reusable components with variants, instances and overrides (create_component, add_variant, set_instance_properties), align, distribute, lock and layer order, shape boolean operations (unite, subtract, offset path, outline stroke), auto layout frames, and keyframe animation with easing and CSS export. Use when working on a canvas, whiteboard, flow chart, node graph, frame, design system, component library, button variants, layout, alignment, z-order or a canvas animation in a Pixerate editor.
4
+ ---
5
+
6
+ # Pixerate canvas
7
+
8
+ The canvas is an xyflow (React Flow / SvelteFlow) graph: an array of **nodes** and **edges**.
9
+ A node is `{ id, type, position: { x, y }, width?, height?, parentId?, zIndex?, data }`; edges are
10
+ `{ id, source, target, label? }`. Everything a design feature knows lives in `node.data`, so it
11
+ survives copy, paste and JSON:
12
+
13
+ - `data.label` / `data.name`: text content and layer name. `data.shape`: a shape node
14
+ (`{ kind: rect | ellipse | polygon | star | path, fill, stroke, strokeWidth, ... }`).
15
+ - `data.layout`: an auto layout frame (`mode` horizontal / vertical / grid, `gap`, `padding`,
16
+ `alignMain`, `alignCross`, `sizing`); its children are the nodes whose `parentId` is the frame,
17
+ in node-array order. `data.childLayout`: a child's sizing (fixed / hug / fill) and constraints.
18
+ - `data.component` (a main component), `data.componentSet` (a set of variants),
19
+ `data.instance` (`{ componentId, properties }`) and `data.componentOverrides`.
20
+ - `data.locked`, `data.animation` (keyframe tracks), `data.tokenBindings` (design tokens).
21
+
22
+ Positions are in canvas (flow) units; a child's position is relative to its parent. Node ids come
23
+ from `get_editor_state`; component and set ids from `list_components`. Tools that take `ids` or
24
+ `id` default to the current selection when you leave them out, so pass ids explicitly unless you
25
+ just selected with `canvas_select`. See `pixerate-agent-tools` for namespacing, `run_commands`
26
+ batching and error codes.
27
+
28
+ ## Working method
29
+
30
+ 1. **Read.** `get_editor_state` with `includeDocument: false` returns `canvas.nodes` and
31
+ `canvas.edges`. For a design system also call `list_components`, and `inspect_instance` before
32
+ changing an instance.
33
+ 2. **Plan the structure first**: which frames, which reusable components and variants, what
34
+ spacing scale. Build the main component once, then place instances; do not copy nodes by hand.
35
+ 3. **Write.** Use the dedicated tools for graph edits (`canvas_add_node`, `canvas_connect`,
36
+ `canvas_update_node`) and components (`create_component`, `create_instance`, ...). Use
37
+ `run_commands` with `atomic: true` for arrange, shape and animation commands, and whenever
38
+ several steps should be one undo step (a param `"$0.ids[0]"` uses an id an earlier step returned).
39
+ 4. **Tidy.** `canvas_layout` for graphs; `canvas.align*` / `canvas.distribute*` for designs;
40
+ layer order with `canvas.bringToFront` and friends; lock finished backgrounds with `canvas.lock`.
41
+ 5. **Look.** `view_editor` (default viewport, JPEG, 1024 px) once a batch is done; use
42
+ `scope: "canvas"` for the whole drawing. Fix overlaps, misalignment and clipped text, then show
43
+ the user with `canvas_select` or `canvas_highlight`.
44
+
45
+ ## Best practices
46
+
47
+ - **Design-system thinking.** Anything that appears twice should be a component: build one main,
48
+ `combine_as_variants` for states and sizes (`State=Default`, `State=Hover`, `Size=Small`), then
49
+ `create_instance` everywhere. Change the main to change every instance; use overrides only for
50
+ per-use content (label text, an icon swap). Name variant properties and values consistently
51
+ (Title Case property, short values) and keep combinations unique.
52
+ - **Name layers that must survive a variant switch** with a stable `data.name`. Matching falls
53
+ back to `data.label`, which for text is its content and differs between variants.
54
+ - **Use component properties, not detaching.** Switch variants and set text or boolean
55
+ properties with `set_instance_properties`; `swap_instance` for another component. Detach only
56
+ when the instance must stop following its main.
57
+ - **Spacing scale.** Pick a base unit (4 or 8) and use multiples for gaps and padding. Put rows
58
+ and stacks in auto layout frames (`data.layout`) instead of positioning children by hand, so
59
+ they reflow when content changes.
60
+ - **Alignment and distribution.** Align to a shared edge or centre, then distribute with equal
61
+ gaps; a design reads as ordered when edges line up. Lock a node you want as the anchor: locked
62
+ nodes never move but still count towards the selection bounds.
63
+ - **Layering.** Backgrounds at the back, content above, overlays on top. Use the restack
64
+ commands; they set `zIndex` per sibling group and never reorder the array.
65
+ - **Graph layout.** Lay flows out in one direction (`LR` for pipelines, `TB` for hierarchies),
66
+ keep edges short, label edges only when the relationship is not obvious.
67
+ - **Motion.** Use ease-out (or `ease-out-back` for a little overshoot) for things arriving,
68
+ ease-in for things leaving, ease-in-out for moves between two resting places, and `linear` only
69
+ for continuous motion such as rotation. Keep UI transitions around 150 to 400 ms and entrances
70
+ under about 600 ms; stagger related elements by 30 to 80 ms with `delay` rather than moving
71
+ everything at once. Animate `opacity`, `x`, `y`, `scale` and `rotation`; colour tweens
72
+ interpolate in OKLab.
73
+
74
+ ## Tool reference
75
+
76
+ ### Read
77
+
78
+ | Tool | Use it to |
79
+ | --- | --- |
80
+ | `get_editor_state` | Read the canvas graph (`canvas.nodes`, `canvas.edges`) and, by default, the prompt document too. Pass `includeDocument: false` on a canvas-only task to keep the result small, `includeCanvas: false` for only the prompt. Call it first and again after edits made by the user. |
81
+ | `view_editor` | Get an image of the editor: `scope` `viewport` (default) or `canvas` (the whole drawing's bounds), `format` `jpeg` (default) or `png`, `maxEdge` in pixels (default 1024). Use it after a batch to judge overlap, balance and legibility; agent cursors are left out. |
82
+ | `list_components` | List main components (id, name, variant values, instance count) and component sets with their variant options. Call it before `create_instance`, `swap_instance` or any variant tool to get ids and the exact property names and values. |
83
+ | `inspect_instance` | Describe one instance (or a layer inside it; default the first selected node): its main, variant, component property values with types, and per-layer overrides. Call it before `set_instance_properties` or `reset_overrides` so you use the right property names and override groups. |
84
+
85
+ ### Write: graph
86
+
87
+ | Tool | Use it to |
88
+ | --- | --- |
89
+ | `canvas_add_node` | Add a node: `node` (`id` optional and must be unused, `type` registered by the host, `data`, `position`, `width`, `height`, `parentId` for a frame). Leave `position` out to auto-place it without overlaps beside `nearNodeId` on `side` (default `right`), which also connects an edge from that node, or beside the last node. Returns the new node id and edge id. |
90
+ | `canvas_connect` | Add an edge from `source` to `target` (two different existing nodes), with an optional `label`. Returns the edge id. |
91
+ | `canvas_update_node` | Merge fields into a node's `data` (for example `{ "label": "Checkout" }`). Treat the merge as shallow: pass nested objects such as `shape` or `layout` whole. It does not move or resize nodes. |
92
+ | `canvas_remove_nodes` | Delete nodes and their edges; every id must exist. Destructive: confirm with the user before removing content they made. |
93
+ | `canvas_layout` | Arrange the graph automatically: `direction` `LR` (default), `TB`, `RL` or `BT`. `incremental` (default true) keeps nodes that already have a position; pass `false` to re-lay everything. Nodes at exactly (0, 0) count as unplaced. |
94
+ | `canvas_select` | Replace the selection (an empty list clears it). Use it to show the user a result and to target commands that act on the selection. |
95
+ | `canvas_highlight` | Flash nodes to point the user at them: `color` (default `#3b82f6`), `durationMs` (default 2000, max 60000). Changes nothing. |
96
+
97
+ ### Write: components
98
+
99
+ These are strict-schema tools. Each returns `{ ids }` of what it created or changed, or fails with
100
+ the reason (for example a variant combination that already exists, or a cycle).
101
+
102
+ | Tool | Use it to |
103
+ | --- | --- |
104
+ | `create_component` | Turn one frame-like node (`ids`) into a main component, or wrap several sibling layers in a new component frame. Returns the component id. |
105
+ | `combine_as_variants` | Wrap sibling components in a component set. Names already in `Property=Value` form become variant values; others get `Property 1=Default`, `Variant2`, ... Rename afterwards with `rename_variant_property` / `rename_variant_value`. |
106
+ | `create_instance` | Place an instance of `componentId` (a component, or a set's default variant), optionally inside frame `parentId`, at `x` / `y` (canvas coordinates, or relative to the parent), with `properties` (variant and component property values). Returns the instance id. |
107
+ | `set_instance_properties` | Set property values on instances (`ids`): a variant property switches the variant (compatible overrides kept), a boolean toggles a layer, a text property sets text, an instance-swap property takes a component id. Get names from `inspect_instance`. |
108
+ | `swap_instance` | Make instances show another component (`componentId`), keeping overrides on layers whose names match. |
109
+ | `reset_overrides` | Reset overrides of a whole instance (default), of one layer (pass the layer as `id`), or one `group` such as `data.label` or `shape.fill`. Destructive. |
110
+ | `push_overrides` | Copy an instance's overrides to its main component, and so to every other instance. Destructive for other instances' look: use it only when the user wants the change everywhere. |
111
+ | `detach_instance` | Turn instances into plain frames that keep their look and stop following the main. Destructive; prefer properties or `swap_instance`. |
112
+ | `go_to_main_component` | Select an instance's main component and get its id, to edit the main itself. |
113
+ | `restore_main_component` | Recreate a deleted main component from one of its instances (its old id comes back, so other instances re-link). |
114
+ | `add_variant` | Add a variant to set `setId` by duplicating `from` (default the set's default variant) with new `variant` values such as `{ "State": "Hover" }`; unnamed properties keep the source's values, a new property name is added to every variant as `Default`. `x` / `y` are optional (default next to the source). Without values the next `VariantN` is used. |
115
+ | `remove_variant` | Remove variant `id` from its set (never the last one); its instances switch to the closest remaining variant, keeping overrides. Destructive. |
116
+ | `set_variant_properties` | Merge `values` into variant `id`'s property values. A combination another variant has is refused. |
117
+ | `rename_variant_property` | Rename property `name` to `newName` across a set; instances keep their variant. |
118
+ | `rename_variant_value` | Rename `value` of `property` to `newValue` across a set; instances keep their variant. |
119
+
120
+ ## Commands
121
+
122
+ Run these through `run_command` / `run_commands`. Each takes `ids` (default: the selection) unless
123
+ noted, is one undo step, and reports in `list_commands` why it cannot run.
124
+
125
+ ### Arrange
126
+
127
+ | Command | Use it to |
128
+ | --- | --- |
129
+ | `canvas.alignLeft` | Align the left edges of two or more nodes to the selection bounds. |
130
+ | `canvas.alignCenter` | Align horizontal centres (a vertical centre line). |
131
+ | `canvas.alignRight` | Align right edges. |
132
+ | `canvas.alignTop` | Align top edges. |
133
+ | `canvas.alignMiddle` | Align vertical centres (a horizontal centre line). |
134
+ | `canvas.alignBottom` | Align bottom edges. |
135
+ | `canvas.distributeHorizontal` | Give three or more nodes equal horizontal gaps; the outermost stay put. |
136
+ | `canvas.distributeVertical` | Give three or more nodes equal vertical gaps. |
137
+ | `canvas.lock` | Lock nodes: they cannot be moved, resized, restacked, deleted or combined, but stay selectable and act as alignment anchors. |
138
+ | `canvas.unlock` | Unlock nodes, restoring their previous drag and delete flags. |
139
+ | `canvas.bringForward` | Move nodes one step up among their siblings (past the next overlapping sibling). |
140
+ | `canvas.sendBackward` | Move nodes one step down among their siblings. |
141
+ | `canvas.bringToFront` | Put nodes on top of their siblings. |
142
+ | `canvas.sendToBack` | Put nodes below their siblings (backgrounds). |
143
+
144
+ ### Shapes
145
+
146
+ These act on shape nodes (`data.shape`) and replace their inputs with a new `path` shape (curves
147
+ are kept exactly). They need unlocked shapes; other selected nodes are ignored.
148
+
149
+ | Command | Use it to |
150
+ | --- | --- |
151
+ | `canvas.unite` | Merge two or more shapes into one outline. |
152
+ | `canvas.intersect` | Keep only the area all shapes share; refused when they do not overlap. |
153
+ | `canvas.subtract` | Cut every other shape out of the back-most one (stacking order decides which is the base). |
154
+ | `canvas.exclude` | Keep the areas covered an odd number of times (XOR). |
155
+ | `canvas.divide` | Split overlapping shapes into one shape per region, each painted like the top shape covering it. |
156
+ | `canvas.offsetPath` | Grow (`distance` > 0) or shrink (< 0) shapes by `distance` canvas units (default 10), with `join` `miter` (default), `round` or `bevel` and `miterLimit` (default 4). |
157
+ | `canvas.outlineStroke` | Turn shapes' strokes into filled shapes: `join` (default miter), `cap` `butt` (default), `round` or `square`, `miterLimit` (default 4). The fill stays as a separate shape below. |
158
+
159
+ ### Components (command form)
160
+
161
+ The same operations as the component tools, for command palettes and `run_commands` batches.
162
+ Prefer the dedicated tool for a single operation: its schema is strict and its errors precise. Use
163
+ the command when you need it inside an atomic batch with arrange or animation steps, or when the
164
+ host registered only commands.
165
+
166
+ | Command | Use it to |
167
+ | --- | --- |
168
+ | `canvas.listComponents` | Read-only; same result as `list_components`. |
169
+ | `canvas.inspectInstance` | Read-only; same as `inspect_instance` (`id`). |
170
+ | `canvas.createComponent` | Same as `create_component` (`ids`). |
171
+ | `canvas.combineAsVariants` | Same as `combine_as_variants` (`ids`). |
172
+ | `canvas.createInstance` | Same as `create_instance` (`componentId`, `parentId`, `x`, `y`, `properties`). |
173
+ | `canvas.setInstanceProperties` | Same as `set_instance_properties` (`properties`, `ids`). |
174
+ | `canvas.swapInstance` | Same as `swap_instance` (`componentId`, `ids`). |
175
+ | `canvas.resetOverrides` | Same as `reset_overrides` (`id`, `group`). |
176
+ | `canvas.pushOverrides` | Same as `push_overrides` (`id`). |
177
+ | `canvas.detachInstance` | Same as `detach_instance` (`ids`). |
178
+ | `canvas.goToMainComponent` | Same as `go_to_main_component` (`id`). |
179
+ | `canvas.restoreMainComponent` | Same as `restore_main_component` (`id`). |
180
+ | `canvas.addVariant` | Same as `add_variant` (`setId`, `from`, `variant`, `x`, `y`). |
181
+ | `canvas.removeVariant` | Same as `remove_variant` (`id`). |
182
+ | `canvas.setVariantProperties` | Same as `set_variant_properties` (`values`, `id`). |
183
+ | `canvas.renameVariantProperty` | Same as `rename_variant_property` (`name`, `newName`, `setId`). |
184
+ | `canvas.renameVariantValue` | Same as `rename_variant_value` (`property`, `value`, `newValue`, `setId`). |
185
+
186
+ ### Animation
187
+
188
+ A node's animation is a set of property tracks of keyframes `{ time (ms), value, easing }`; the
189
+ easing applies to the segment leaving a keyframe. Animatable properties: `x`, `y`, `width`,
190
+ `height`, `rotation` (degrees), `scale`, `opacity` (0 to 1), `fill`, `stroke`, `strokeWidth`,
191
+ `cornerRadius`, `motionPath` (0 to 1). Easings: `linear`, `ease`, `ease-in`, `ease-out`,
192
+ `ease-in-out`, `ease-in-back`, `ease-out-back`, `spring`, `hold`, or `cubic-bezier(x1, y1, x2, y2)`.
193
+
194
+ | Command | Use it to |
195
+ | --- | --- |
196
+ | `canvas.animation.animateNode` | The main authoring command: animate `nodeId` from `from` (default: its current values) to `to` over `duration` ms (default 1000), starting at `delay` ms (default 0), with `easing`. Stagger several nodes with increasing `delay` in one atomic `run_commands`. |
197
+ | `canvas.animation.addKeyframe` | Key nodes (`ids`, default selected) at `time` ms (default the playhead): the listed `properties`, else their animated ones, else `x` and `y`. Set the node's values first, then key. |
198
+ | `canvas.animation.setEasing` | Set `easing` on the segments leaving the selected keyframes. Needs a keyframe selection. |
199
+ | `canvas.animation.deleteKeyframes` | Delete the selected keyframes. Needs a keyframe selection. |
200
+ | `canvas.animation.seek` | Move the playhead to `time` ms (required). Returns the time. |
201
+ | `canvas.animation.play` | Start playback (refused when already playing). |
202
+ | `canvas.animation.pause` | Pause playback (refused when not playing). |
203
+ | `canvas.animation.togglePlay` | Play or pause; returns `playing` and `time`. |
204
+ | `canvas.animation.stop` | Stop and return to the start. |
205
+ | `canvas.animation.toggleRecord` | Toggle record mode, in which changing any property at the playhead keys it. Returns `recording`; turn it off when done. |
206
+ | `canvas.animation.nextKeyframe` | Jump the playhead to the next keyframe. |
207
+ | `canvas.animation.previousKeyframe` | Jump the playhead to the previous keyframe. |
208
+ | `canvas.animation.exportCss` | Read-only: CSS `@keyframes` for `nodeId`'s animation, as `{ css, exact }`. `exact: false` means some tracks were sampled (OKLab colour tweens, `x` / `y` with different timing, motion paths). |
209
+
210
+ ## Pitfalls
211
+
212
+ - `canvas_*` tools validate ids against the current state; an "Unknown node id" error means call
213
+ `get_editor_state` again, not guess.
214
+ - `canvas_add_node` with `nearNodeId` also adds an edge from that node. Pass an explicit
215
+ `position` (and no `nearNodeId`) for a free-standing design element.
216
+ - `canvas_update_node` changes `data` only. Move nodes with layout, align or distribute commands,
217
+ or by the host's own means; do not expect `position` inside `data` to move anything.
218
+ - Align needs at least two nodes and distribute at least three; locked nodes never move. Shape
219
+ booleans refuse locked shapes and empty results, and edges attached to consumed shapes are left
220
+ dangling: reconnect or remove them.
221
+ - Subtract uses stacking order (back-most is the base), not selection order; restack first.
222
+ - Instances never gain or lose layers. Deleting a layer inside an instance hides it; nodes added
223
+ inside an instance move out of it. Edit the main to change structure.
224
+ - `push_overrides`, `detach_instance`, `remove_variant` and `reset_overrides` change other
225
+ instances or discard work; ask before using them on the user's design.
226
+ - Variant edits refuse a combination another variant already has, empty names, and names
227
+ containing `,` or `=`.
228
+ - An instance cannot be placed inside a component it contains (cycle); place it outside.
229
+ - Animation times are milliseconds; `rotation` is degrees and `opacity` 0 to 1 (token bindings use
230
+ percent for opacity, animation does not).
@@ -0,0 +1,190 @@
1
+ ---
2
+ name: pixerate-chart
3
+ description: How to build, edit and check charts in the Pixerate chart editor through its agent tools and chart.* commands - bar, column, line, area, scatter, bubble, pie, donut, radar, waterfall, histogram, box plot, funnel and treemap charts; series, categories, stacking, secondary axis, log axis, number formats, data labels, legend, trendline, error bars, colour palettes and colour-blind checks, CSV and Mermaid import, Office chart XML export, and reading charts out of open .xlsx, .pptx and .docx files. Use when a chart editor's tools (get_chart, update_chart, set_chart_values, list_file_charts...) are available or the user asks to make, restyle, fix or explain a chart.
4
+ ---
5
+
6
+ # Charts
7
+
8
+ A chart editor holds one `ChartSpec`: a `type`, `title` / `subtitle`, `xAxis` / `yAxis` /
9
+ `yAxis2`, `legend`, presentation fields (stacking, orientation, curve, data labels, palette),
10
+ a list of `categories` (strings, in order) and a list of `series`. Each series has an `id`
11
+ (such as `series-1`), a `name` and one value per category (`null` is a gap), plus optional
12
+ per-series settings (type for combos, secondary axis, marker, colour, format, trendlines,
13
+ error bars). Tools take a series by id or exact name and a category by 0-based index or
14
+ exact label; `get_chart` returns both. Pie, donut, funnel and treemap draw only the first
15
+ visible series, one slice per category; histogram and box read every value of the visible
16
+ series.
17
+
18
+ Read `pixerate-agent-tools` first for tool naming, errors and `run_commands` batching.
19
+ Charts inside a rich-text document are not edited with these tools: use `insert_chart`,
20
+ `list_document_charts` and `update_chart_in_document` from the `pixerate-rich-text` skill
21
+ (a chart block goes in the prose, never inside a table row).
22
+
23
+ ## Working method
24
+
25
+ 1. **Read.** `get_chart` returns the spec, the data as a table, the selection and a
26
+ summary at the given size (default 640 x 400): per-series min / max / mean / trend, the
27
+ axes as drawn, layout warnings, a colour check and a plain-language description. If the
28
+ data comes from a file, start with `list_open_files` and `list_file_charts`.
29
+ 2. **Choose the form.** Decide what question the chart answers, then call `recommend_chart`
30
+ (on the current data or on CSV you are about to import) and pick from its list.
31
+ 3. **Load data in one call.** Use `import_chart_csv` (with `chartType: "auto"` for a fresh
32
+ chart) or `set_chart_data` for whole tables, `set_chart_values` for individual cells.
33
+ Avoid adding categories and series one by one when you already have the table.
34
+ 4. **Style in one call.** Put type, titles, axes, legend, stacking and labels in a single
35
+ `update_chart`; it is all-or-nothing and one undo step. Use `apply_chart_preset` for a
36
+ coherent layout or colour scheme, `update_chart_series` for per-series settings.
37
+ 5. **Check.** Read the `warnings` that `get_chart` and `render_chart` return (hidden or
38
+ thinned labels, crowded legend, skipped values) and run `check_chart_colors`. Fix every
39
+ problem.
40
+ 6. **Look once.** `render_chart` with `format: "png"` after a batch of edits, at the size
41
+ the chart will be shown, to check overlap and legibility. Use `undo_chart` for your own
42
+ mistakes.
43
+
44
+ ## Best practices
45
+
46
+ - **Pick the type by the question.** Comparison across categories: bar (horizontal with
47
+ `orientation: "horizontal"` for long labels or many categories). Change over time: line
48
+ (area when volume matters; set `xAxis.kind: "date"` for date categories). Composition:
49
+ stacked bar or `stacking: "percent"` for shares across groups; pie or donut only for one
50
+ whole with few parts. Distribution: histogram (`bins`, default the square root of n) or
51
+ box. Relationship: scatter with `series.x`, bubble with `sizes` for a third measure.
52
+ Running totals and bridges: waterfall (`showTotal`). Staged drop-off: funnel.
53
+ - **Bars start at zero.** Bar length encodes the value, so never set a non-zero `min` on the
54
+ value axis of a bar, column or area chart. Line and scatter charts may zoom to the data
55
+ range when the change, not the magnitude, is the point.
56
+ - **Pie and donut: at most about five slices**, all positive, adding up to a meaningful
57
+ whole. Beyond that, use a sorted bar chart or merge small slices into "Other".
58
+ - **Sort bars** by value (largest first) unless the categories have a natural order (time,
59
+ ranks, age bands). Reorder by sending the sorted table through `set_chart_data`.
60
+ - **Limit colours.** Keep to about seven distinct series colours; beyond that, split into
61
+ small multiples or highlight one series and grey the rest (`color`, `pointColors`).
62
+ Run `check_chart_colors` after any palette change; the `okabe-ito` scheme in
63
+ `apply_chart_preset` stays distinct with colour-blindness. Do not encode meaning by
64
+ colour alone: add labels or markers (`marker`).
65
+ - **Label directly.** With few series or few bars, prefer data labels (`dataLabels`,
66
+ `labelPosition: "auto"` drops labels that do not fit) and the `labelled` or `minimal`
67
+ layout over a legend plus grid. Always set a title that states the takeaway and axis
68
+ titles with units.
69
+ - **Number formats.** Set `format` on the axis (and on series labels when they differ):
70
+ `style: "percent"` (0.25 shows as 25%), `"currency"` with `currency`, `"compact"` (1.2K),
71
+ fixed `decimals`, or a spreadsheet `code` such as `#,##0.0,,"M"`. Use the same format on
72
+ the axis and the labels; avoid more decimals than the data justifies.
73
+ - **Honest dual axes.** Use `axis: "secondary"` only when two series have different units,
74
+ title both axes with those units, and make the series visibly different (bar plus line
75
+ via the series `type`). Never use a second axis to make two same-unit series look
76
+ correlated.
77
+ - **Log scale** (`scale: "log"`) only for data spanning orders of magnitude or for growth
78
+ rates; say so in the axis title. It skips values of 0 or less and refuses percent
79
+ stacking.
80
+ - **Trendlines are models, not data.** Add one only when a fit is meaningful, show R2
81
+ (`showR2`) and read it with `get_chart_trendline` before describing the trend; label any
82
+ `forward` forecast as a projection. Exponential, power and log fits need positive values;
83
+ category charts fit against x = 1, 2, 3.
84
+ - **Error bars:** say what they are (standard deviation, standard error, confidence) in the
85
+ title or subtitle.
86
+
87
+ ## Tool reference
88
+
89
+ ### Read
90
+
91
+ | Tool | Use it to |
92
+ | --- | --- |
93
+ | `get_chart` | Start here. Returns spec, data table, selection, issues and a summary (min / max / mean / trend, axes as drawn, layout warnings, colour check, description) at `width` x `height` px (default 640 x 400). Also says why when the chart is read-only. Cheaper than rendering. |
94
+ | `render_chart` | Draw without changing anything: SVG text by default, or `format: "png"` for an image (only when the host can rasterize; otherwise it fails and says to use SVG). Returns the layout warnings too. Images cost tokens: render after a batch of edits, at the display size, to check overlapping or cut-off labels, a crowded legend and unreadable colours. |
95
+ | `check_chart_colors` | Check the chart's series (or slice) colours, or a `colors` list, for normal vision, protanopia, deuteranopia and tritanopia, and contrast against `surface` (default white). Returns the closest pair per vision and problems as sentences. Run after any colour change. |
96
+ | `recommend_chart` | Ranked chart types with a reason each, from `csv` when given, else the current data (series count, points, dates, negative values). Use before choosing a type. |
97
+ | `get_chart_trendline` | Read a trendline's fit (`series`, `index`): coefficients, R2, equation and point count, or the moving-average points. Fails when the fit needs more or positive values. |
98
+ | `list_chart_presets` | List the quick layouts (`standard`, `minimal`, `labelled`, `legend-right`, `presentation`, `analysis`) and colour schemes (such as `default`, `okabe-ito`, `office`, monochrome) with what each changes. |
99
+ | `export_chart_mermaid` | Get the chart as Mermaid `xychart-beta`, `pie` or `radar-beta` for Markdown or chat. With `meta` (default true) a `%% @pixerate` comment keeps everything Mermaid cannot express so `import_chart_mermaid` restores it exactly. |
100
+ | `export_chart_ooxml` | Get a DrawingML `c:chartSpace` part for Word or PowerPoint, plus sentences for anything that could not be written. |
101
+ | `list_open_files` | List the Office files the user opened (name, size in bytes). Only registered when the host shares open files; otherwise the file tools take the whole file as base64 `data`. |
102
+ | `list_file_charts` | List every chart in an `.xlsx`, `.pptx` or `.docx` (`file` name or base64 `data`) in file order: id (such as `chart-1`), place (sheet and anchor cell, or slide number), title, type, series names, category count, read problems, unsupported features and whether it reads losslessly. |
103
+ | `get_file_chart` | Return one file chart's full spec (`file` or `data`, `chartId` from `list_file_charts`) with its place and read problems, without touching the editor. Data comes from the chart's cached values, not the embedded workbook. |
104
+
105
+ ### Write
106
+
107
+ Write tools are hidden while the chart is read-only. Each is one undo step and returns what
108
+ it changed.
109
+
110
+ | Tool | Use it to |
111
+ | --- | --- |
112
+ | `update_chart` | Change presentation in one all-or-nothing call: `type`, `title`, `subtitle`, `xAxis` / `yAxis` / `yAxis2` (show, title, min, max, step, gridlines, format, kind `"date"`, scale `"log"`, logBase, reverse), `legend` (show, position top / bottom / left / right), `stacking` (none / stacked / percent), `orientation`, `curve`, `points`, `dataLabels`, `labelPosition`, `palette`, `innerRadius` (donut hole, 0-0.9), `gapWidth`, `overlap`, `bins`, `showTotal`. Invalid values change nothing and come back as sentences. Returns the spec. |
113
+ | `set_chart_data` | Replace `categories` and / or all `series` (each with `name`, `values` and optional settings). Values are padded with gaps to the categories. Use for whole tables and for re-sorting. Returns the table and series ids. |
114
+ | `set_chart_values` | Set individual `cells` (`series`, `category`, `value`) all-or-nothing. Values may be numbers, numeric text (`"1,200"`, `"12%"`, `"$40"`, `"(3)"`) or `null` for a gap. Returns the stored values. Acted out with a cursor when the host has a director. |
115
+ | `add_chart_series` | Add a series (`name` required; `values`, `color`, `type` for a combo, `axis: "secondary"`, `x` / `sizes` for scatter and bubble, marker, format, error bars, `id`, `at`). Selects it and returns its id. |
116
+ | `update_chart_series` | Rename, recolour, hide, move to the secondary axis, change `type`, `marker`, `curve`, `dataLabels`, `format`, `x`, `sizes`, `pointColors`, `errorBars` / `xErrorBars` of one series; `null` resets a field. Values change with `set_chart_values`. |
117
+ | `remove_chart_series` | Delete a series and its values. Returns the remaining series ids. |
118
+ | `add_chart_category` | Insert a category (`label`, `at`; default the end) as a gap in every series. Returns its index; fill it with `set_chart_values`. |
119
+ | `remove_chart_category` | Delete a category (index or label) and its value in every series. |
120
+ | `import_chart_csv` | Replace the data with CSV or TSV text. Default: first row series names, first column categories (`seriesIn`, `header` change that). `chartType: "auto"` also picks the recommended type (two unlabelled numeric columns become a scatter). Returns the table, the type and cells that were not numbers. |
121
+ | `import_chart_mermaid` | Replace the chart with Mermaid `xychart-beta`, `pie` or `radar-beta` text (fenced or bare). Unreadable lines are skipped and listed with line numbers. |
122
+ | `import_chart_ooxml` | Replace the chart with a raw Office chart part (`c:chartSpace` or chartex XML). Only listed when the host has a `DOMParser` (every browser does). Prefer `load_file_chart` when you have the whole file. |
123
+ | `load_file_chart` | Replace the editor's chart with one from an Office file (`file` or `data`, `chartId`). Returns the spec, read problems and the features the editor could not keep; tell the user about any. |
124
+ | `add_chart_trendline` | Fit a trendline to a series (`type`: linear, exponential, logarithmic, power, polynomial with `order` 2-6, moving-average with `period`; `forward` / `backward` in x units, `intercept`, `showEquation`, `showR2`). Unstacked bar, line, area, scatter and bubble charts only. Returns its index, coefficients, R2 and equation. |
125
+ | `remove_chart_trendline` | Delete a trendline by `series` and `index`. |
126
+ | `apply_chart_preset` | Apply a quick `layout` and / or a `colors` scheme from `list_chart_presets` in one step. |
127
+ | `transpose_chart` | Swap series and categories. Drops per-series colours and settings, so restyle afterwards. |
128
+ | `select_chart_element` | Select part of the chart (`kind`: none, chart, title, subtitle, legend, axis, series, point, category, trendline) for the user to see or before `press_chart_key`. |
129
+ | `drag_chart_point` | Drag a bar or point as the mouse would, with the same snapping (`fine` = Alt, `lockAxis` = Shift on scatter). Positions are 0-1 fractions of the chart at `width` x `height`; use `render_chart` to find marks. Prefer `set_chart_values` for exact numbers. |
130
+ | `press_chart_key` | Send a key to the selection: ArrowLeft / ArrowRight move between categories, ArrowUp / ArrowDown change the value by a tenth of a tick (`shift` a whole tick, `alt` a hundredth), Delete / Backspace remove, Escape clears. |
131
+ | `undo_chart` | Undo the last chart edit. Returns the label of what was undone and the next undo. |
132
+ | `redo_chart` | Redo the last undone chart edit. |
133
+
134
+ ## Commands
135
+
136
+ The `chart.*` commands (run with `run_command` / `run_commands`) mirror the tools. Prefer
137
+ the dedicated tool: it has a stricter schema and returns more (`get_chart` adds the
138
+ selection and read-only reason; `import_chart_csv` has `chartType: "auto"`;
139
+ `check_chart_colors` takes colours and a surface). Use the commands inside an atomic
140
+ `run_commands` batch when chart edits must roll back together with other edits, and for the
141
+ two operations without a tool: `chart.exportSvg` and its fixed-size accessible SVG. Hosts with
142
+ several charts may register them with another prefix.
143
+
144
+ | Command | Use it to |
145
+ | --- | --- |
146
+ | `chart.describe` | Read spec, data table and summary (as `get_chart`). |
147
+ | `chart.update` | Change presentation (as `update_chart`). |
148
+ | `chart.setData` | Replace categories and series (as `set_chart_data`). |
149
+ | `chart.setValues` | Set individual values (as `set_chart_values`). |
150
+ | `chart.addSeries` | Add a series; returns its id (as `add_chart_series`). |
151
+ | `chart.updateSeries` | Change a series' settings (as `update_chart_series`). |
152
+ | `chart.removeSeries` | Delete a series by id or name. |
153
+ | `chart.addCategory` | Insert a category at `at` (default the end). |
154
+ | `chart.removeCategory` | Delete a category by index or label. |
155
+ | `chart.addTrendline` | Fit a trendline (as `add_chart_trendline`). |
156
+ | `chart.removeTrendline` | Delete a trendline. |
157
+ | `chart.applyPreset` | Apply a quick layout and / or colour scheme. |
158
+ | `chart.transpose` | Swap series and categories. |
159
+ | `chart.importCsv` | Replace data from CSV / TSV (no automatic chart type). |
160
+ | `chart.importMermaid` | Replace the chart from Mermaid chart text. |
161
+ | `chart.exportMermaid` | Get Mermaid text (with the round-trip comment unless `meta` is false). |
162
+ | `chart.exportOoxml` | Get the DrawingML chart part. |
163
+ | `chart.exportSvg` | Get a standalone, accessible SVG (title and desc) at `width` x `height` (default 640 x 400), for saving or embedding. |
164
+ | `chart.recommend` | Suggest chart types for the data or `csv`. |
165
+ | `chart.checkColors` | Check the chart's own series colours (no parameters). |
166
+ | `chart.undo` | Undo the last chart edit. |
167
+ | `chart.redo` | Redo the last undone chart edit. |
168
+
169
+ ## Pitfalls
170
+
171
+ - Series values are positional: one value per category, in category order. After
172
+ `add_chart_category` or `remove_chart_category`, every series shifts with it.
173
+ - `set_chart_data` with only `series` keeps the categories; with only `categories` it keeps
174
+ the series, whose values stay matched by position. Pass both to replace a table.
175
+ - Non-numeric cells are refused by `set_chart_values` ("Nothing was changed"); CSV import
176
+ keeps going and lists them in `issues`. Check that list.
177
+ - Percent-stacked charts, pies and gaps cannot be dragged; use `set_chart_values`.
178
+ - Radar needs at least three categories (it draws as a line chart until then); trendlines
179
+ are refused on stacked charts, pies and the other single-series families.
180
+ - `transpose_chart` and `load_file_chart` drop or replace styling; restyle and re-check
181
+ colours afterwards.
182
+ - A `%% @pixerate` comment is what makes Mermaid round-trip exactly. Keep it when the text
183
+ is going back into a Pixerate editor; pass `meta: false` only for plain Mermaid readers.
184
+ - File charts are read from cached values; if the user edited the workbook without saving
185
+ the chart cache, the numbers can be stale. Say so when it matters.
186
+ - An atomic `run_commands` batch only rolls back chart edits when the host shares one history
187
+ between the command registry and the chart; if a batch is refused for that, use the tools
188
+ one by one and `undo_chart`.
189
+ - When the chart is read-only, only the read tools are listed and `get_chart` returns the
190
+ reason. Tell the user; do not try to edit around it.
@@ -0,0 +1,134 @@
1
+ ---
2
+ name: pixerate-diagram
3
+ description: How to build and edit Mermaid diagrams in the Pixerate diagram editor through its agent tools - flowchart, state, class, ER, sequence, Gantt, pie, mindmap, quadrant, C4, architecture, gitGraph, timeline, journey, XY and radar diagrams; adding, connecting, renaming, reshaping and styling nodes, edge labels, subgraphs and groups, layout direction (LR, TB), node and edge data fields, titles, canvas positions, finding Mermaid in Markdown, and rendering to check the result. Use when diagram tools (get_diagram, add_diagram_node, load_diagram_mermaid...) are available or the user asks for a flowchart, process map, state machine, sequence diagram, org or architecture diagram in Mermaid.
4
+ ---
5
+
6
+ # Mermaid diagrams
7
+
8
+ The diagram editor holds one Mermaid document. Its text is the source of truth: every edit
9
+ rewrites only the statements it touches, and untouched statements, comments, directives and
10
+ formatting round-trip byte for byte. Canvas positions live in one `%% @pixerate {...}`
11
+ comment that Mermaid ignores.
12
+
13
+ `get_diagram` describes the document as a graph: the `family` (flowchart, state, class, er,
14
+ pie, mindmap, quadrant, c4, architecture, sequence, gitGraph, gantt, timeline, journey,
15
+ xychart, radar), `direction`, `title`, `nodes` (Mermaid ids such as `A` or `n3`, label,
16
+ shape, `parentId`), `edges` (ids such as `L_A_B_0`, source, target, label), `groups`
17
+ (subgraphs, composite states, namespaces, sections, boxes, boundaries), the `shapes` the
18
+ family allows, its data `fields` and current `settings`. Non-graph families map onto the
19
+ same model: a pie slice, Gantt task, quadrant point or sequence participant is a node
20
+ whose values live in `data`. Sankey, block, packet, kanban and treemap are kept as text
21
+ only (`editable: false`): change them with `load_diagram_mermaid`.
22
+
23
+ Read `pixerate-agent-tools` first for tool naming, errors and batching. Data charts (bar,
24
+ line, pie with styling, trendlines) belong in the chart editor (`pixerate-chart`); Mermaid
25
+ `xychart-beta`, `pie` and `radar-beta` text can move between the two.
26
+
27
+ ## Working method
28
+
29
+ 1. **Read.** `get_diagram` (with `includeSource: true` when you need the text). Note the
30
+ family, the ids, the allowed `shapes` and `fields`. For Mermaid in a user's Markdown or
31
+ chat, `find_mermaid_diagrams` first.
32
+ 2. **Plan the structure** before writing: the family, the flow direction, the nodes and
33
+ their kinds, the groups. Sketch it as Mermaid in your head.
34
+ 3. **Write.** For a new diagram or a rewrite, send the whole text once with
35
+ `load_diagram_mermaid`. For changes to an existing diagram, use the per-operation tools
36
+ (`add_diagram_node` with `from` to add and connect in one call, `rename_diagram_node`,
37
+ `connect_diagram_nodes`...): they keep the user's formatting and comments.
38
+ 4. **Check.** Read the returned ids and any `diagnostics`; fix parse problems before going
39
+ on.
40
+ 5. **Look.** `render_diagram` (`format: "png"` when offered) after a batch of edits to
41
+ check crossings, crowding and label length. Undo your own mistakes with `undo_diagram`.
42
+
43
+ ## Best practices
44
+
45
+ - **Choose the family by the question.** Process or decision logic: flowchart. Lifecycle of
46
+ one thing with events: state. Messages between parties over time: sequence. Data model:
47
+ ER (tables and cardinality) or class (types and methods). Schedule: Gantt. System context
48
+ and containers: C4 or architecture. Brainstorm or hierarchy: mindmap. Two-axis
49
+ prioritisation: quadrant. History: timeline or gitGraph. Numeric series: the chart editor.
50
+ - **One direction, matched to the content.** `LR` for processes and pipelines read like a
51
+ sentence; `TB` for hierarchies and decision trees. Set it once (`set_diagram_direction`);
52
+ do not mix directions except per-subgraph when a group is clearly separate.
53
+ - **Concise labels.** Verb phrases for steps ("Validate order"), noun phrases for things,
54
+ short questions for decisions ("Paid?"), at most five or six words. Put conditions on the
55
+ edges leaving a decision ("yes" / "no"), not in the node. Stable short ids (`validate`,
56
+ `paid`) beat `A`, `B`, `C` when the user will read the source.
57
+ - **Consistent shape semantics.** In flowcharts: `rounded` or `stadium` for start and end,
58
+ `rect` for steps, `diam` for decisions, `cyl` for data stores, `doc` for documents,
59
+ `subproc` for a call into another process, `lean-r` / `lean-l` for input and output. Use
60
+ each shape for one meaning only. In state diagrams use `choice`, `fork` and `join` for
61
+ branching and concurrency.
62
+ - **Group to reduce noise.** Put related nodes in a subgraph (`group_diagram_nodes`) by
63
+ owner, system or phase (swimlane style); keep to one or two levels of nesting.
64
+ - **Limit crossings and fan-out.** Keep each node to a few edges; order statements so the
65
+ main path runs straight; split very large diagrams (more than about 20-30 nodes) into an
66
+ overview plus detail diagrams rather than one dense graph. Every node should be reachable;
67
+ remove orphans.
68
+ - **Style sparingly.** `set_diagram_node_style` to highlight the one or two nodes the
69
+ reader should look at (the error path, the changed step), not to decorate every node.
70
+ Keep enough contrast between fill and text, and do not rely on colour alone.
71
+ - **Title it** (`set_diagram_title`) with what the diagram shows.
72
+
73
+ ## Tool reference
74
+
75
+ ### Read
76
+
77
+ | Tool | Use it to |
78
+ | --- | --- |
79
+ | `get_diagram` | Start here. Returns family, editable flag, direction, title, nodes, edges, groups, allowed shapes, settings, data fields (`fields.node`, `fields.edge`, `fields.diagram` with types and ranges), stored positions, parse diagnostics, the selection and the read-only reason. `includeSource` (default false) adds the Mermaid text. |
80
+ | `export_diagram_mermaid` | Get the Mermaid text to hand back to the user or paste into Markdown. `withLayout` (default true) keeps the `%% @pixerate` positions comment; pass false for plain Mermaid. |
81
+ | `find_mermaid_diagrams` | Find every Mermaid diagram in a piece of `text` (fenced ```mermaid blocks, a chat reply or a bare diagram). Returns each source, family and title; pass one source to `load_diagram_mermaid`. Changes nothing. |
82
+ | `render_diagram` | Draw the diagram without changing it: SVG text by default, `format: "png"` when the host can rasterize; `maxWidth` / `maxHeight` fit it in px. Only listed when the host can render. Refuses text-only families. Render after a batch of edits, not after each one. |
83
+
84
+ ### Write
85
+
86
+ Write tools are hidden while the diagram is read-only. Each call is checked against the
87
+ diagram first (unknown ids, taken ids, shapes the family lacks), applies as one undo step and
88
+ returns what it created or changed. All but `load_diagram_mermaid` and undo / redo refuse
89
+ text-only families.
90
+
91
+ | Tool | Use it to |
92
+ | --- | --- |
93
+ | `load_diagram_mermaid` | Replace the whole diagram with Mermaid `source` (fenced or bare; must start with a header such as `flowchart LR`). Use for new diagrams, wholesale rewrites and text-only families. Returns family, editable flag, node and edge counts and diagnostics. Rewrites the user's formatting, so prefer the per-operation tools for small changes. |
94
+ | `add_diagram_node` | Add a node with `label` (required); optional `id` (default the family's next free id), `shape`, `data` (family node fields), `parentId` (group), `from` plus `edgeLabel` to connect from an existing node, and `x` / `y` together in canvas px. Returns the node and any edge created. |
95
+ | `remove_diagram_nodes` | Delete nodes (`ids`) and every edge touching them. A group id removes the group but keeps its contents. Returns removed node and edge ids. |
96
+ | `rename_diagram_node` | Change the label of a node or group (`id`, `label`). |
97
+ | `set_diagram_node_shape` | Change a flowchart or state node's `shape` to one of the names `get_diagram` lists (such as `rect`, `rounded`, `stadium`, `diam`, `cyl`, `circle`, `hex`, `doc`). |
98
+ | `set_diagram_node_style` | Replace a node's inline Mermaid `styles` with `property:value` strings, e.g. `["fill:#fde68a", "stroke:#b45309", "stroke-width:2px"]`; an empty list removes them. |
99
+ | `set_diagram_node_data` | Set node field values (`id`, `data`): a pie slice `value`, Gantt `start` / `end`, quadrant `x` / `y`, journey score, XY series values, C4 technology. Keys and types come from `fields.node`; `null` clears a field. |
100
+ | `connect_diagram_nodes` | Draw an edge from `source` to `target` (existing node ids) with an optional `label`. Returns the edge id. |
101
+ | `remove_diagram_edges` | Delete edges by `ids`; the nodes stay. |
102
+ | `set_diagram_edge_label` | Set an edge's `label` by edge `id`; `""` removes it. |
103
+ | `set_diagram_edge_data` | Set edge field values (`id`, `data`): sequence activation, C4 relation technology, architecture sides. Keys from `fields.edge`; `null` clears. |
104
+ | `reconnect_diagram_edge` | Move an edge to a new `source` and `target`, keeping label and style. The returned edge id may change; use it from then on. |
105
+ | `set_diagram_direction` | Set the flow `direction`: `TB` / `TD`, `BT`, `LR` or `RL`. Refused by families whose layout follows their data (pie, sequence, Gantt...). |
106
+ | `set_diagram_title` | Set the `title` shown above the diagram, or `null` to remove it. |
107
+ | `set_diagram_settings` | Set diagram-level fields (`data`): pie `showData`, Gantt `dateFormat` and `excludes`, quadrant axis labels, XY categories and axis range, sequence autonumbering. Keys from `fields.diagram`; `null` clears. |
108
+ | `group_diagram_nodes` | Put `nodeIds` into a new group with `label` (optional `id`, default the next `G<number>`): a flowchart subgraph, composite state, class namespace, or the family's own group kind. Refused by families without groups (ER, pie, mindmap, quadrant, XY, radar). |
109
+ | `ungroup_diagram_group` | Remove a group by `id`; its nodes move to the group's parent. |
110
+ | `move_diagram_nodes` | Place nodes or groups on the canvas: `moves` of `{ id, x, y }` (top-left, canvas px). Stored in the `%% @pixerate` comment only; Mermaid statements and other renderers are unaffected. |
111
+ | `undo_diagram` | Undo the last diagram edit; returns its label. |
112
+ | `redo_diagram` | Redo the last undone diagram edit. |
113
+
114
+ ## Pitfalls
115
+
116
+ - Ids are Mermaid ids, not labels. Always take them from `get_diagram` or from what a write
117
+ returned; a custom `id` must match `^[A-Za-z0-9_][\w.-]*$` and not be taken.
118
+ - `load_diagram_mermaid` takes exactly one diagram. Text with several fenced diagrams is
119
+ refused; pick one with `find_mermaid_diagrams`. Text without a Mermaid header is refused
120
+ and nothing changes.
121
+ - Shapes only apply to flowchart and state nodes; class and ER have none. A shape name not
122
+ in `get_diagram`'s `shapes` is refused.
123
+ - Data tools check keys and types against the family's fields before changing anything.
124
+ Read `fields` first rather than guessing keys.
125
+ - Moving one node of an auto-laid diagram can shift the others when the host does not pin
126
+ current positions; check with `render_diagram` after `move_diagram_nodes`, and prefer
127
+ letting the layout place nodes (omit `x` / `y`) unless the user asked for a position.
128
+ - Mermaid label text with quotes, brackets or `#` may need quoting in the source; the
129
+ per-operation tools quote flowchart labels when needed, so prefer them over hand-written
130
+ text when labels contain punctuation, and check `diagnostics` after a `load_diagram_mermaid`.
131
+ - `export_diagram_mermaid` with `withLayout: false` is for plain Mermaid readers; keep the
132
+ comment when the text will come back into a Pixerate editor.
133
+ - When the diagram is read-only, only the read tools are listed and `get_diagram` returns
134
+ the reason. Tell the user; do not try to edit around it.