@pixerate/editor 0.223.8 → 0.224.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/animation-editor/index.cjs +9 -9
  2. package/dist/animation-editor/index.js +1 -1
  3. package/dist/canvas/index.cjs +7 -7
  4. package/dist/canvas/index.js +1 -1
  5. package/dist/{chunk-6DUEV36F.cjs → chunk-7AAS3JO6.cjs} +14 -14
  6. package/dist/{chunk-6G2NLMVK.js → chunk-HKPLKISO.js} +58 -9
  7. package/dist/{chunk-Z64NRDEH.cjs → chunk-MDNYYOBZ.cjs} +7 -7
  8. package/dist/{chunk-A3A5TI6R.cjs → chunk-NTWR5TQB.cjs} +59 -10
  9. package/dist/{chunk-OZSA5YEJ.js → chunk-RDTCG5MS.js} +1 -1
  10. package/dist/{chunk-WMVEYSOA.js → chunk-WA4IS2EY.js} +1 -1
  11. package/dist/effects/fake.d.cts +6 -1
  12. package/dist/effects/fake.d.ts +6 -1
  13. package/dist/effects/helpers.d.cts +24 -1
  14. package/dist/effects/helpers.d.ts +24 -1
  15. package/dist/effects/index.cjs +257 -62
  16. package/dist/effects/index.js +202 -7
  17. package/dist/effects/types.d.cts +121 -4
  18. package/dist/effects/types.d.ts +121 -4
  19. package/dist/image-editor/index.cjs +13 -13
  20. package/dist/image-editor/index.js +1 -1
  21. package/dist/paint-editor/index.cjs +7 -7
  22. package/dist/paint-editor/index.js +2 -2
  23. package/dist/tools/skill-evals.d.cts +8 -1
  24. package/dist/tools/skill-evals.d.ts +8 -1
  25. package/dist/vector/index.cjs +6 -6
  26. package/dist/vector/index.js +1 -1
  27. package/dist/video-editor/index.cjs +309 -309
  28. package/dist/video-editor/index.js +3 -3
  29. package/package.json +1 -1
  30. package/skills/README.md +4 -1
  31. package/skills/pixerate-animation-editor/SKILL.md +1 -1
  32. package/skills/pixerate-canvas/SKILL.md +8 -0
  33. package/skills/pixerate-canvas-design-system-components/SKILL.md +103 -0
  34. package/skills/pixerate-canvas-design-system-components/evals/add-variant.json +172 -0
  35. package/skills/pixerate-canvas-design-system-components/evals/combine-variants.json +172 -0
  36. package/skills/pixerate-canvas-design-system-components/evals/make-component.json +103 -0
  37. package/skills/pixerate-canvas-layout/SKILL.md +95 -0
  38. package/skills/pixerate-canvas-layout/evals/align-tops.json +98 -0
  39. package/skills/pixerate-canvas-layout/evals/distribute-evenly.json +98 -0
  40. package/skills/pixerate-canvas-layout/evals/order-and-lock.json +110 -0
  41. package/skills/pixerate-video-editor/SKILL.md +1 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createEffectAuthoringSession
3
- } from "../chunk-WMVEYSOA.js";
3
+ } from "../chunk-WA4IS2EY.js";
4
4
  import {
5
5
  VIDEO_ADJUSTMENT_SCOPES,
6
6
  VIDEO_BLEND_MODES,
@@ -148,7 +148,7 @@ import {
148
148
  videoTransitionEase,
149
149
  videoValueAt,
150
150
  videoWipeRect
151
- } from "../chunk-OZSA5YEJ.js";
151
+ } from "../chunk-RDTCG5MS.js";
152
152
  import "../chunk-EHLOCVWB.js";
153
153
  import {
154
154
  namedWithSuggestion
@@ -157,7 +157,7 @@ import {
157
157
  EffectsSlot,
158
158
  createEffectToolProvider,
159
159
  isEffectError
160
- } from "../chunk-6G2NLMVK.js";
160
+ } from "../chunk-HKPLKISO.js";
161
161
  import "../chunk-V2ZCJRDM.js";
162
162
  import {
163
163
  defineEditorDocument
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor",
3
- "version": "0.223.8",
3
+ "version": "0.224.0",
4
4
  "description": "UI-agnostic rich text and media editing core library",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
package/skills/README.md CHANGED
@@ -67,6 +67,8 @@ request like "clean up this export" finds it.
67
67
  | [`pixerate-effect-look-development`](pixerate-effect-look-development/SKILL.md) | Effects (`pixerate-effect-authoring`) | Tune a look in a few moves, save it as a preset, animate with eased keyframes, seamless loops. |
68
68
  | [`pixerate-accessibility-audit`](pixerate-accessibility-audit/SKILL.md) | Cross-domain (`pixerate-color`) | Text and non-text contrast, colour-blind-safe meaning, both modes, smallest fixes and a report, in any editor. |
69
69
  | [`pixerate-brand-application`](pixerate-brand-application/SKILL.md) | Cross-domain (`pixerate-color`) | Brand roles mapped to exact palette values, near-misses snapped, readable text on brand colours, derivatives and house-style checks. |
70
+ | [`pixerate-canvas-design-system-components`](pixerate-canvas-design-system-components/SKILL.md) | Canvas (`pixerate-canvas`) | Main components and linked instances, component sets with named variant properties, overrides kept linked. |
71
+ | [`pixerate-canvas-layout`](pixerate-canvas-layout/SKILL.md) | Canvas (`pixerate-canvas`) | Align, distribute, order and lock with the arrange commands, changing only the intended axis. |
70
72
  | [`pixerate-talking-head-edit`](pixerate-talking-head-edit/SKILL.md) | Video (`pixerate-video-editor`) | Talking-head cleanup by transcript: fillers, long pauses and stutters found in one pass and cut as one plan reviewed before it applies. Owns the dialogue tools. |
71
73
  | [`pixerate-bgm-alignment`](pixerate-bgm-alignment/SKILL.md) | Video (`pixerate-video-editor`) | Background music: beats and cuts on the beat, ducking under speech, loudness in LUFS. Owns the music tools. |
72
74
 
@@ -135,7 +137,8 @@ same change.
135
137
  "chart", "setup" }` `{ "editor": "diagram", "setup" }` with tool calls,
136
138
  `{ "editor": "rich-text", "html" }`,
137
139
  `{ "editor": "animation", "setup" }`, `{ "editor": "generation", "models", "prices", "history" }`
138
- (a fake host that records each generation) or `{ "editor": "effect", "effectId", "setup" }`), `checks` (a read-only
140
+ (a fake host that records each generation) `{ "editor": "effect", "effectId", "setup" }` or `{ "editor": "canvas",
141
+ "nodes", "setup" }` (a headless canvas with the component, arrange and document tools)), `checks` (a read-only
139
142
  tool, or `run_command` with a read-only command such as `vector.list`, its `args`, what its result must match in `expect`, and `why`) and a `solution` (the
140
143
  tool calls an expert would make). The test proves each eval: some check fails on the fixture,
141
144
  and all pass after the solution. A model harness runs the same file with the model in place
@@ -155,7 +155,7 @@ refuse.
155
155
 
156
156
  | Tool | Use it to |
157
157
  | --- | --- |
158
- | `search_effects` | Find effects: `kind` motion (primitives to apply to nodes) or vector (effects with their own picture), `query`, `category`. |
158
+ | `search_effects` | Find effects: `kind` motion (primitives to apply to nodes) or vector (effects with their own picture), `query`, `category`. `kind` camera lists camera moves (with `camera`: role transition or hold, `durationMs`, `cut`); they move a scene's camera and cannot be applied with these tools. |
159
159
  | `describe_effect` | Read an effect's `controls` (names, ranges, units), `defaults` and `presets`, and whether it `appliesHere` (a motion effect). |
160
160
  | `list_applied_effects` | See the provider effects in the scene: their `instance` ids, the nodes they animate, their shots and values. |
161
161
  | `apply_effect` | Animate a node (`target`, a group animates as one) with a motion effect: the changes become ordinary commands, tagged with the effect, in a new shot after the last. Returns the instance id. |
@@ -25,6 +25,14 @@ from `get_editor_state`; component and set ids from `list_components`. Tools tha
25
25
  just selected with `canvas_select`. See `pixerate-agent-tools` for namespacing, `run_commands`
26
26
  batching and error codes.
27
27
 
28
+ ## Workflow skills
29
+
30
+ For these jobs, load the workflow skill too: it has the method, the checks between steps and
31
+ the pitfalls, and uses the tools below.
32
+
33
+ - `pixerate-canvas-design-system-components`: components, instances, variant sets and overrides.
34
+ - `pixerate-canvas-layout`: align, distribute, order and lock.
35
+
28
36
  ## Working method
29
37
 
30
38
  1. **Read.** `get_editor_state` with `includeDocument: false` returns `canvas.nodes` and
@@ -0,0 +1,103 @@
1
+ ---
2
+ name: pixerate-canvas-design-system-components
3
+ description: The design system components workflow in the Pixerate canvas - turning repeated design into main components, placing instances instead of copies, combining versions into a component set with named variant properties and values, adding variants, keeping instances linked, swapping, resetting and pushing overrides, and keeping the library tidy and named. Use when asked to build or tidy a design system, component library or UI kit, make a component, instance, variant or component set, add a state (hover, disabled) or size, rename variant properties, or replace copies with instances, or when create_component, combine_as_variants, add_variant or create_instance are available. Load with pixerate-canvas, which lists every tool.
4
+ metadata:
5
+ kind: workflow
6
+ reference: pixerate-canvas
7
+ ---
8
+
9
+ # Building design system components
10
+
11
+ A design system replaces copies with components. A main component holds the design; instances
12
+ show it elsewhere and update when it changes, with per-instance overrides where they differ.
13
+ Versions of one thing (styles, states, sizes) become variants in a component set, described by
14
+ properties ("Style=Primary, State=Disabled") a person or agent can switch between. Names and
15
+ properties are the interface: keep them clear and consistent.
16
+
17
+ This skill is the method. `pixerate-canvas` has the full tool reference.
18
+
19
+ ## Goal and quality bar
20
+
21
+ - Anything used more than once is a main component; its uses are linked instances
22
+ (`inspect_instance` `status: "linked"`), not copies.
23
+ - Versions of one element are variants in one component set, with named properties (Style,
24
+ State, Size) and named values (Primary, Disabled, Large), never "Property 1" and "Variant2".
25
+ - Every combination of property values is unique; the default variant is the most common one.
26
+ - Instances keep their link; detach only when one must diverge for good.
27
+ - Components are named by what they are ("Button", "Card"), sets list their options clearly.
28
+
29
+ ## Inputs to confirm
30
+
31
+ - **What becomes a component**, and which existing copies should become its instances.
32
+ - **Properties and values** for variants (Style: Primary / Secondary; State: Default / Hover /
33
+ Disabled; Size: Small / Medium / Large).
34
+ - **Naming conventions** of the team's library.
35
+
36
+ ## Working method
37
+
38
+ 1. **Read.** `list_components` (components, sets, their variants and options) and
39
+ `get_canvas_document` for the nodes.
40
+ **Check:** you know which nodes are already components and which are copies.
41
+ 2. **Make components.** `create_component` with the frame's id(s).
42
+ **Check:** `list_components` lists it with its name.
43
+ 3. **Replace copies with instances.** `create_instance` with `componentId`, `x`, `y`; remove the
44
+ copies once instances stand in their place.
45
+ **Check:** `get_canvas_document` shows instance nodes where the copies were.
46
+ 4. **Combine versions into variants.** `create_component` each version, then
47
+ `combine_as_variants` with their ids; the set gets generic names ("Property 1", "Default",
48
+ "Variant2"). Rename at once: `rename_variant_property` (`name`, `newName`, `setId`) and
49
+ `rename_variant_value` (`property`, `value`, `newValue`, `setId`).
50
+ **Check:** `list_components` `sets[].options` shows the real names; each variant's `variant`
51
+ map is right.
52
+ 5. **Add variants.** `add_variant` with `setId` and the new `variant` values (it duplicates the
53
+ default, or `from`); `set_variant_properties` to change a variant's values.
54
+ **Check:** the set lists every combination once.
55
+ 6. **Maintain instances.** `swap_instance` to another component or variant, `reset_overrides` to
56
+ go back to the main, `push_overrides` to promote an instance's change to the main,
57
+ `go_to_main_component` to edit the source.
58
+
59
+ ## Decision table
60
+
61
+ | Situation | Tool |
62
+ | --- | --- |
63
+ | The same element appears several times | `create_component`, then `create_instance` for each use |
64
+ | Versions of one element (styles, states, sizes) | `combine_as_variants`, then rename properties and values |
65
+ | A new state or size | `add_variant` with `variant` values |
66
+ | An instance should look like another variant | `set_instance_properties` or `swap_instance` |
67
+ | An instance's change belongs in the main | `push_overrides` |
68
+ | An instance drifted by accident | `reset_overrides` |
69
+ | One copy must diverge permanently | `detach_instance` (last resort) |
70
+
71
+ ## Recipes
72
+
73
+ **Card component with two instances.** `create_component` `{ ids: ["card"] }` →
74
+ `create_instance` `{ componentId: "card", x: 0, y: 150 }` and `{ componentId: "card", x: 240,
75
+ y: 150 }`.
76
+
77
+ **Primary and Secondary variants.** `create_component` each button → `combine_as_variants`
78
+ `{ ids }` → `rename_variant_property` `{ name: "Property 1", newName: "Style", setId }` →
79
+ `rename_variant_value` `Default` → `Primary`, `Variant2` → `Secondary`.
80
+
81
+ **A Disabled variant.** `add_variant` `{ setId, variant: { Style: "Disabled" } }`.
82
+
83
+ ## Pitfalls
84
+
85
+ - **Copies instead of instances** drift apart and cannot be updated together.
86
+ - **Generic variant names** ("Property 1", "Variant2") left after combining make the set unusable;
87
+ rename right away.
88
+ - **The rename and add tools need the set** (`setId` from `list_components`) when nothing is
89
+ selected.
90
+ - **Duplicate combinations** are refused; every variant needs a unique set of values.
91
+ - **Detaching to make a small change** loses future updates; override instead.
92
+ - **Combining unrelated components** into one set; a set is one element's versions.
93
+
94
+ ## Tools used
95
+
96
+ - `list_components`, `inspect_instance`: components, sets, variants and instance status
97
+ - `get_canvas_document`: the nodes, to check placement
98
+ - `create_component`, `create_instance`: components and their instances
99
+ - `combine_as_variants`, `add_variant`, `remove_variant`, `set_variant_properties`: component sets
100
+ - `rename_variant_property`, `rename_variant_value`: clear property and value names
101
+ - `set_instance_properties`, `swap_instance`, `reset_overrides`, `push_overrides`: instances and overrides
102
+ - `detach_instance`, `go_to_main_component`, `restore_main_component`: break links, edit or restore mains
103
+ - `undo_canvas`: take back a step
@@ -0,0 +1,172 @@
1
+ {
2
+ "prompt": "Add a Disabled style to the button component set, as a third variant of its Style property.",
3
+ "fixture": {
4
+ "editor": "canvas",
5
+ "nodes": [
6
+ {
7
+ "id": "primary",
8
+ "type": "group",
9
+ "position": {
10
+ "x": 0,
11
+ "y": 0
12
+ },
13
+ "width": 120,
14
+ "height": 40,
15
+ "data": {
16
+ "label": "Button / Primary"
17
+ }
18
+ },
19
+ {
20
+ "id": "pbg",
21
+ "type": "shape",
22
+ "parentId": "primary",
23
+ "position": {
24
+ "x": 0,
25
+ "y": 0
26
+ },
27
+ "width": 120,
28
+ "height": 40,
29
+ "data": {
30
+ "label": "Bg",
31
+ "shape": {
32
+ "kind": "rect",
33
+ "fill": "#1d3557"
34
+ }
35
+ }
36
+ },
37
+ {
38
+ "id": "secondary",
39
+ "type": "group",
40
+ "position": {
41
+ "x": 0,
42
+ "y": 60
43
+ },
44
+ "width": 120,
45
+ "height": 40,
46
+ "data": {
47
+ "label": "Button / Secondary"
48
+ }
49
+ },
50
+ {
51
+ "id": "sbg",
52
+ "type": "shape",
53
+ "parentId": "secondary",
54
+ "position": {
55
+ "x": 0,
56
+ "y": 0
57
+ },
58
+ "width": 120,
59
+ "height": 40,
60
+ "data": {
61
+ "label": "Bg",
62
+ "shape": {
63
+ "kind": "rect",
64
+ "fill": "#ffffff"
65
+ }
66
+ }
67
+ }
68
+ ],
69
+ "setup": [
70
+ {
71
+ "tool": "create_component",
72
+ "args": {
73
+ "ids": [
74
+ "primary"
75
+ ]
76
+ }
77
+ },
78
+ {
79
+ "tool": "create_component",
80
+ "args": {
81
+ "ids": [
82
+ "secondary"
83
+ ]
84
+ }
85
+ },
86
+ {
87
+ "tool": "combine_as_variants",
88
+ "args": {
89
+ "ids": [
90
+ "primary",
91
+ "secondary"
92
+ ]
93
+ }
94
+ },
95
+ {
96
+ "tool": "rename_variant_property",
97
+ "args": {
98
+ "name": "Property 1",
99
+ "newName": "Style",
100
+ "setId": {
101
+ "$read": "list_components",
102
+ "path": "sets.0.id"
103
+ }
104
+ }
105
+ },
106
+ {
107
+ "tool": "rename_variant_value",
108
+ "args": {
109
+ "property": "Style",
110
+ "value": "Default",
111
+ "newValue": "Primary",
112
+ "setId": {
113
+ "$read": "list_components",
114
+ "path": "sets.0.id"
115
+ }
116
+ }
117
+ },
118
+ {
119
+ "tool": "rename_variant_value",
120
+ "args": {
121
+ "property": "Style",
122
+ "value": "Variant2",
123
+ "newValue": "Secondary",
124
+ "setId": {
125
+ "$read": "list_components",
126
+ "path": "sets.0.id"
127
+ }
128
+ }
129
+ }
130
+ ]
131
+ },
132
+ "checks": [
133
+ {
134
+ "why": "three variants: Primary, Secondary and Disabled",
135
+ "tool": "list_components",
136
+ "expect": {
137
+ "sets": [
138
+ {
139
+ "variants": {
140
+ "$length": 3
141
+ },
142
+ "options": [
143
+ {
144
+ "name": "Style",
145
+ "values": {
146
+ "$expr": "[...v].sort().join() === 'Disabled,Primary,Secondary'"
147
+ }
148
+ }
149
+ ]
150
+ }
151
+ ]
152
+ }
153
+ }
154
+ ],
155
+ "solution": [
156
+ {
157
+ "tool": "list_components"
158
+ },
159
+ {
160
+ "tool": "add_variant",
161
+ "args": {
162
+ "setId": {
163
+ "$read": "list_components",
164
+ "path": "sets.0.id"
165
+ },
166
+ "variant": {
167
+ "Style": "Disabled"
168
+ }
169
+ }
170
+ }
171
+ ]
172
+ }
@@ -0,0 +1,172 @@
1
+ {
2
+ "prompt": "These two buttons are versions of one button. Combine them into a single component with a 'Style' property whose values are Primary and Secondary.",
3
+ "fixture": {
4
+ "editor": "canvas",
5
+ "nodes": [
6
+ {
7
+ "id": "primary",
8
+ "type": "group",
9
+ "position": {
10
+ "x": 0,
11
+ "y": 0
12
+ },
13
+ "width": 120,
14
+ "height": 40,
15
+ "data": {
16
+ "label": "Button / Primary"
17
+ }
18
+ },
19
+ {
20
+ "id": "pbg",
21
+ "type": "shape",
22
+ "position": {
23
+ "x": 0,
24
+ "y": 0
25
+ },
26
+ "width": 120,
27
+ "height": 40,
28
+ "data": {
29
+ "label": "Bg",
30
+ "shape": {
31
+ "kind": "rect",
32
+ "fill": "#1d3557"
33
+ }
34
+ },
35
+ "parentId": "primary"
36
+ },
37
+ {
38
+ "id": "secondary",
39
+ "type": "group",
40
+ "position": {
41
+ "x": 0,
42
+ "y": 60
43
+ },
44
+ "width": 120,
45
+ "height": 40,
46
+ "data": {
47
+ "label": "Button / Secondary"
48
+ }
49
+ },
50
+ {
51
+ "id": "sbg",
52
+ "type": "shape",
53
+ "position": {
54
+ "x": 0,
55
+ "y": 0
56
+ },
57
+ "width": 120,
58
+ "height": 40,
59
+ "data": {
60
+ "label": "Bg",
61
+ "shape": {
62
+ "kind": "rect",
63
+ "fill": "#ffffff"
64
+ }
65
+ },
66
+ "parentId": "secondary"
67
+ }
68
+ ],
69
+ "setup": [
70
+ {
71
+ "tool": "create_component",
72
+ "args": {
73
+ "ids": [
74
+ "primary"
75
+ ]
76
+ }
77
+ },
78
+ {
79
+ "tool": "create_component",
80
+ "args": {
81
+ "ids": [
82
+ "secondary"
83
+ ]
84
+ }
85
+ }
86
+ ]
87
+ },
88
+ "checks": [
89
+ {
90
+ "why": "one component set with a Style property whose values are Primary and Secondary",
91
+ "tool": "list_components",
92
+ "expect": {
93
+ "sets": {
94
+ "$length": 1,
95
+ "$some": {
96
+ "options": [
97
+ {
98
+ "name": "Style",
99
+ "values": {
100
+ "$expr": "[...v].sort().join() === 'Primary,Secondary'"
101
+ }
102
+ }
103
+ ]
104
+ }
105
+ }
106
+ }
107
+ },
108
+ {
109
+ "why": "the primary button is the Primary variant",
110
+ "tool": "list_components",
111
+ "expect": {
112
+ "components": {
113
+ "$some": {
114
+ "id": "primary",
115
+ "variant": {
116
+ "Style": "Primary"
117
+ }
118
+ }
119
+ }
120
+ }
121
+ }
122
+ ],
123
+ "solution": [
124
+ {
125
+ "tool": "combine_as_variants",
126
+ "args": {
127
+ "ids": [
128
+ "primary",
129
+ "secondary"
130
+ ]
131
+ }
132
+ },
133
+ {
134
+ "tool": "list_components"
135
+ },
136
+ {
137
+ "tool": "rename_variant_property",
138
+ "args": {
139
+ "name": "Property 1",
140
+ "newName": "Style",
141
+ "setId": {
142
+ "$read": "list_components",
143
+ "path": "sets.0.id"
144
+ }
145
+ }
146
+ },
147
+ {
148
+ "tool": "rename_variant_value",
149
+ "args": {
150
+ "property": "Style",
151
+ "value": "Default",
152
+ "newValue": "Primary",
153
+ "setId": {
154
+ "$read": "list_components",
155
+ "path": "sets.0.id"
156
+ }
157
+ }
158
+ },
159
+ {
160
+ "tool": "rename_variant_value",
161
+ "args": {
162
+ "property": "Style",
163
+ "value": "Variant2",
164
+ "newValue": "Secondary",
165
+ "setId": {
166
+ "$read": "list_components",
167
+ "path": "sets.0.id"
168
+ }
169
+ }
170
+ }
171
+ ]
172
+ }
@@ -0,0 +1,103 @@
1
+ {
2
+ "prompt": "Turn the card into a reusable component and place two instances of it below the original, side by side.",
3
+ "fixture": {
4
+ "editor": "canvas",
5
+ "nodes": [
6
+ {
7
+ "id": "card",
8
+ "type": "group",
9
+ "position": {
10
+ "x": 0,
11
+ "y": 0
12
+ },
13
+ "width": 200,
14
+ "height": 100,
15
+ "data": {
16
+ "label": "Card"
17
+ }
18
+ },
19
+ {
20
+ "id": "bg",
21
+ "type": "shape",
22
+ "position": {
23
+ "x": 0,
24
+ "y": 0
25
+ },
26
+ "width": 200,
27
+ "height": 100,
28
+ "data": {
29
+ "label": "Bg",
30
+ "shape": {
31
+ "kind": "rect",
32
+ "fill": "#eeeeee"
33
+ }
34
+ },
35
+ "parentId": "card"
36
+ },
37
+ {
38
+ "id": "title",
39
+ "type": "text",
40
+ "parentId": "card",
41
+ "position": {
42
+ "x": 10,
43
+ "y": 10
44
+ },
45
+ "data": {
46
+ "label": "Hello",
47
+ "name": "Title"
48
+ }
49
+ }
50
+ ]
51
+ },
52
+ "checks": [
53
+ {
54
+ "why": "one component, made from the card",
55
+ "tool": "list_components",
56
+ "expect": {
57
+ "components": {
58
+ "$length": 1,
59
+ "$some": {
60
+ "id": "card"
61
+ }
62
+ }
63
+ }
64
+ },
65
+ {
66
+ "why": "two instances below the card",
67
+ "tool": "get_canvas_document",
68
+ "expect": {
69
+ "document": {
70
+ "nodes": {
71
+ "$expr": "v.filter((n) => n.data && n.data.instance && n.position.y >= 100).length === 2"
72
+ }
73
+ }
74
+ }
75
+ }
76
+ ],
77
+ "solution": [
78
+ {
79
+ "tool": "create_component",
80
+ "args": {
81
+ "ids": [
82
+ "card"
83
+ ]
84
+ }
85
+ },
86
+ {
87
+ "tool": "create_instance",
88
+ "args": {
89
+ "componentId": "card",
90
+ "x": 0,
91
+ "y": 150
92
+ }
93
+ },
94
+ {
95
+ "tool": "create_instance",
96
+ "args": {
97
+ "componentId": "card",
98
+ "x": 240,
99
+ "y": 150
100
+ }
101
+ }
102
+ ]
103
+ }