@plitzi/sdk-mcp 0.38.1 → 0.38.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,154 @@
1
1
  # @plitzi/sdk-mcp
2
2
 
3
+ ## 0.38.3
4
+
5
+ ### Patch Changes
6
+
7
+ - e047e1d: ## `plitzi upgrade`: a project brought up to its CLI
8
+
9
+ A project written by an older CLI had no way up but `plitzi create` in a scratch folder and a file-by-file comparison:
10
+ `skills update` brought the skills and nothing else, so the `check` and `shot` scripts they teach did not exist.
11
+ `plitzi upgrade` (also `update`) shows what this CLI writes today for what is the CLI's in the project, and `--write`
12
+ makes it. One part or several: `plitzi upgrade skills`, `plitzi upgrade files packages`.
13
+
14
+ - **`files`:** the CLI's machinery — `author.ts`, `main.ts`, the Playwright, TypeScript and lint configs, AGENTS.md. One
15
+ nobody changed since the CLI wrote it is replaced, a missing one added; one the project made its own is shown as a
16
+ diff and left, until `--take <file>` (or `all`). `plitzi create` now records what it wrote, by digest, in
17
+ `.plitzi/scaffold.json`; a project made before that sees every file that differs as its own.
18
+ - **`packages`:** `package.json` merged, never replaced — the scripts and dependencies it lacks added, `@plitzi/*`
19
+ raised to this version, then the install (`--no-install` to leave it). A script of the project's own stays.
20
+ - **`skills`:** `.claude/skills/plitzi-*` from the packages installed, each replaced whole, and the ones a newer CLI
21
+ writes added. `plitzi skills update` is `plitzi upgrade skills --write`.
22
+ - **`renames`:** a name a version renamed with no alias, at its file and line — `canTemplate` → `canSnippet`,
23
+ `authorTemplate` → `authorSnippet` and its kin (renamed only where imported from `@plitzi/sdk-authoring`) — renamed
24
+ with `--write`.
25
+
26
+ `npm run author` says when the skills or the CLI's files are older than the SDK installed, and `plitzi --version`
27
+ prints the CLI's.
28
+
29
+ ## Page checks that can be the definition of done
30
+
31
+ `inspectPage`, `plitzi check` and the scaffold's visual test failed pages that were whole, so an agent learnt to ignore
32
+ them:
33
+
34
+ - **A breakpoint hiding an element on purpose** — the desktop navigation on a phone, a bottom bar only a phone shows —
35
+ is no longer "not visible": an element whose `display` or `visibility` a breakpoint rule sets is checked at the width
36
+ it shows at.
37
+ - **A lazy image out of sight** waits whichever side it is out of: below the fold, as before, or beside the screen in a
38
+ carousel's track — cut off by any ancestor that clips, as the browser decides when to fetch it.
39
+ - **A plugin that draws nothing** says so: `drawsNothing: true` in its declaration (a clock that fires a flow), and its
40
+ handle is `boxless`, so no check waits for it on screen.
41
+
42
+ `plitzi check --json` and `PageReport` carry `issues` beside `problems`: each with its `code` (`element-hidden`,
43
+ `image-not-loaded`, `sideways-scroll`…), the `elementId` it is about and, in `check`, the `width`.
44
+
45
+ ## Authoring
46
+ - **A link's `content` names it.** `control-without-name` read only a link's `label`, so applying the
47
+ `content-attribute` suggestion as written turned every link into a warning.
48
+ - **`plitzi fix` writes `content-attribute`** where it has one reading: a button's or link's children that are only
49
+ `text(…)` and `fontAwesome({ icon })` become its own `content` and `icon` — the words kept as written, an import left
50
+ unused taken out. A child with an id, options or a class of the space's own stays, and is said. `npm run author`'s
51
+ `[fix]` line counts these too.
52
+ - **The recipes, the skill's examples and the catalog template** hold to the suggestions as well as the warnings, and
53
+ their tests say so: six recipes and the template wrote a link's or a button's words as a child.
54
+
55
+ ## Declared motion — in code, in the builder and over MCP
56
+
57
+ An element says how it arrives and whether it keeps moving with `motion`, and the SDK's stylesheet plays it — no
58
+ keyframes to write: `{ enter: 'fade-up', on: 'view' }` arrives as it scrolls into view, `{ enter: 'scale', stagger:
59
+ 60 }` brings its children one by one (a grid, a list's rows), `{ loop: 'float' }` keeps it moving. Enters: `fade`,
60
+ `fade-up`, `fade-down`, `slide-left`, `slide-right`, `scale`; loops: `float`, `pulse`, `spin`, `sway`; `duration`,
61
+ `delay`, `stagger` in ms. Opacity and the transforms only — an arrival on `translate`/`scale`, so it composes with an
62
+ element's own `transform` — a loop held until the page is live (`data-hydrated`), and none of it for a visitor who asked
63
+ for less motion. `view` follows the scroll where the browser has scroll timelines and plays on load where not.
64
+
65
+ - **Authoring:** `motion` on any factory; refused where it cannot play (`motion-invalid`, `motion-no-tag`), and carried
66
+ by `specFromSpace` and `compareSpaces`.
67
+ - **Builder:** a **Motion** tab in an element's tools: the presets as chips, a stage that plays the one pointed at (a
68
+ loop shown stronger than the page plays it, and saying so), when and how long, children one by one, and the choices
69
+ read back as a sentence — laid out side by side once the sidebar is wide enough. The canvas holds motion still while
70
+ editing; **▶** in the header (or **Play on the canvas** in the tab) plays it from the start, restarting what already
71
+ played, and an arrival tied to the scroll plays by the clock there, where it is usually in view already.
72
+ - **MCP:** `motion` on `upsertElement` and `patchElement`, checked the same way; the guide names the presets.
73
+ - **Schema:** `definition.motion` (`ElementMotion`, `@plitzi/sdk-shared/schema/motion` — the presets, `motionProblems`,
74
+ `motionAttributes`, `isMotionAnimation`, and each preset's frames, which the stylesheet is tested against), in both
75
+ init queries. **The platform's GraphQL schema has to declare `SpaceElementMotion`
76
+ before this version's builder or SDK queries it.**
77
+
78
+ ## Dev tools QA: x-ray and motion
79
+
80
+ The **QA** tab gains an **X-ray**: every element the document wires something to — bound to data, shown on a condition,
81
+ running a flow, moving, behind a flag — outlined in its colour and named on the page, read from the space's document by
82
+ the element's name; its legend counts each kind on the page and picks one to show alone. Beside **Pause**, **Slow**
83
+ plays every animation at a quarter of its speed and **Replay** plays the declared motion again from the start, without
84
+ reloading the page.
85
+
86
+ ## Plugins that draw
87
+
88
+ `useCanvas2d`, `useWebGL`, `useWebGL2` and `useAnimationFrame` (`@plitzi/plitzi-sdk`): a canvas sized to the device (at
89
+ most 2×), followed as it resizes, animating only while somebody can see it move — a live page, no reduced motion, the
90
+ tab in front, the canvas on screen — and one still frame otherwise (the builder included). `createShaderProgram`
91
+ compiles and links, and a shader that fails throws a `ShaderError` with the driver's log, printed as
92
+ `[plugin <type> "<id>"] fragment shader failed: …` instead of an empty canvas; `error` and `ready` say where it is.
93
+ `useReducedMotion` for the rest.
94
+
95
+ ## A space re-authored without a restart
96
+
97
+ A project's `npm run start:dev` restarts for its server code and its plugins only: a save to the space is re-authored
98
+ in a process of its own and every open page loads again (`server.reloadPages()` over an SSE endpoint, on with
99
+ `createServer({ devReload: true })` — never by `devMode` alone, since every open page holds a connection for it); an
100
+ edit authoring refuses is printed and the page keeps the last space that authored. A shutdown also ends WebSockets at
101
+ once (`1001`, going away) rather than waiting out the grace — the ten seconds a restart used to wait on an open page.
102
+
103
+ ## Checks and authoring, from the stripe.com experiment
104
+ - **A component's instance** is found by its own name: its root carries `data-plitzi-instance`, and the instance's
105
+ handle selects it — `inspectPage` no longer reports every named instance as missing.
106
+ - **Hidden at this width on purpose** — the burger on a desktop, the desktop menu on a phone — is listed apart
107
+ (`hiddenAtWidth`, and a dim line under `plitzi check`'s ✓) rather than as a problem.
108
+ - **An element whose every child is conditional** — four flyouts in one list, each opening on the state that names
109
+ it — is conditional too: at rest it shows nothing, and that is it working.
110
+ - **A carousel that scrolls by itself** (`overflow-x: auto`) is not the page scrolling sideways; the page's own pane
111
+ still is.
112
+ - **Templates:** `{{ state.faq ?? -1 }}` — a sign on the right of `??` — reads.
113
+ - **A plugin attribute named as an element field** (`variant`, `class`, `id`…) is warned about
114
+ (`plugin-attribute-reserved`): a factory never hands it to the plugin. A `variant` no class or type style declares is
115
+ `unknown-variant`.
116
+ - **Lists:** a list with `items` renders as the `<ul>` (or `<ol>`) its `subType` says — it was a `<div>` — with no
117
+ markers and the same spacing, so a page looks as it did; the builder offers the list type for it too. Its rows are
118
+ `<li>`s: `list-row-not-li` warns of one that is not — a plain container is made one by `fixSpace`, a link or a button
119
+ is wrapped — and the recipes, the catalog template and the docs write rows as `listItem`.
120
+ - **CSS:** `mask-size`, `mask-position`, `mask-repeat`, `mask-composite`, `-webkit-mask-image`,
121
+ `-webkit-background-clip`, `box-decoration-break` and `-webkit-box-decoration-break`.
122
+ - **`plitzi shot`:** `--clip <element>`, `--scroll-to <element>` and `--viewport`; `--frames` takes the same framing.
123
+ - **SVG from files:** `svgFile` and `svgFiles` (`@plitzi/sdk-authoring/node`) read a logo or a folder of them,
124
+ compacted (`compactSvg`, also on the main entry), instead of strings in the space's source.
125
+ - The plugin scaffolds say that an inline `style` on `RootElement` outranks the element's classes.
126
+
127
+ - Updated dependencies [e047e1d]
128
+ - @plitzi/sdk-authoring@0.38.3
129
+ - @plitzi/sdk-elements@0.38.3
130
+ - @plitzi/sdk-interactions@0.38.3
131
+ - @plitzi/sdk-schema@0.38.3
132
+ - @plitzi/sdk-shared@0.38.3
133
+ - @plitzi/sdk-style@0.38.3
134
+ - @plitzi/plitzi-sdk@0.38.3
135
+ - @plitzi/sdk-server@0.38.3
136
+
137
+ ## 0.38.2
138
+
139
+ ### Patch Changes
140
+
141
+ - v0.38.2
142
+ - Updated dependencies
143
+ - @plitzi/plitzi-sdk@0.38.2
144
+ - @plitzi/sdk-authoring@0.38.2
145
+ - @plitzi/sdk-elements@0.38.2
146
+ - @plitzi/sdk-interactions@0.38.2
147
+ - @plitzi/sdk-schema@0.38.2
148
+ - @plitzi/sdk-server@0.38.2
149
+ - @plitzi/sdk-shared@0.38.2
150
+ - @plitzi/sdk-style@0.38.2
151
+
3
152
  ## 0.38.1
4
153
 
5
154
  ### Patch Changes
@@ -616,7 +616,9 @@ reads \`list_<name>.item.values.<field>\`), \`.pageInfo\` (\`page\`, \`pageCount
616
616
  instead of \`.records\` — that is what a **detail page** uses. Bind an empty-state block's visibility to \`.isEmpty\`
617
617
  and an error block's to \`.hasError\`; they are ordinary bindings, no special mechanism.
618
618
 
619
- **A list page** — provider, then a \`list\` inside it bound to the records, then the row template reading the item:
619
+ **A list page** — provider, then a \`list\` inside it bound to the records, then the row template reading the item
620
+ (a \`list\` is a \`<ul>\`, or \`<ol>\` by \`subType\`; its row a \`listItem\`, an \`<li>\` — any other row is warned
621
+ \`list-row-not-li\`):
620
622
  \`\`\`json
621
623
  { "operations": [
622
624
  { "type": "upsertElement", "pageRef": "blog", "element": {
@@ -922,7 +924,11 @@ Space-level configuration lives in \`plitzi://settings/{env}\` and is edited wit
922
924
  \`{ "type": "patchSettings", "customCss": "@keyframes spin { to { transform: rotate(360deg); } }" }\`.
923
925
 
924
926
  ## Motion — good practices
925
- Keyframes go in \`customCss\` (\`patchSettings\`), a definition names them (\`animation\`). Only \`opacity\` and
927
+ A preset first: an element's \`motion\` field (\`upsertElement\`/\`patchElement\`) —
928
+ \`{ "enter": "fade-up", "on": "view" }\`, \`"stagger": 60\` for its children one by one, \`"loop": "float"\` — is
929
+ played by the SDK, cheap and stilled for reduced motion. Enters: fade, fade-up, fade-down, slide-left, slide-right,
930
+ scale; loops: float, pulse, spin, sway. Beyond them, keyframes go in \`customCss\` (\`patchSettings\`), a
931
+ definition names them (\`animation\`). Only \`opacity\` and
926
932
  \`transform\` (\`translate\`, \`scale\`, \`rotate\`) animate off the main thread: they stay smooth while the page
927
933
  hydrates and on a slow phone. Anything else repaints or lays the page out again on every frame, and freezes while the
928
934
  page's scripts run.
@@ -69,7 +69,7 @@ var createMcpServer = async ({ adapters, getGrant, preview, screenshot, logger,
69
69
  const getSpace = () => spacePromise ??= loadSpace();
70
70
  const server = new McpServer({
71
71
  name: "plitzi-mcp",
72
- version: "0.38.1"
72
+ version: "0.38.3"
73
73
  }, { instructions: hasSpace ? serverInstructions : widgetsOnlyInstructions });
74
74
  const { getChanges } = adapters;
75
75
  registerResources(server, getSpace, MCP_ENV, log, hasSpace, getChanges ? (query) => getChanges(requireSpaceId(), MCP_ENV, query) : void 0);
@@ -56,6 +56,7 @@ export declare const applyShape: {
56
56
  }>>;
57
57
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
58
58
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
59
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
59
60
  }, z.core.$strip>, z.ZodObject<{
60
61
  type: z.ZodLiteral<"deleteElement">;
61
62
  pageRef: z.ZodString;
@@ -52,6 +52,7 @@ export declare const documentOperation: z.ZodDiscriminatedUnion<readonly [z.ZodO
52
52
  }>>;
53
53
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
54
54
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
55
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
55
56
  }, z.core.$strip>, z.ZodObject<{
56
57
  type: z.ZodLiteral<"deleteElement">;
57
58
  pageRef: z.ZodString;
@@ -836,6 +837,7 @@ export declare const operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
836
837
  }>>;
837
838
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
838
839
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
840
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
839
841
  }, z.core.$strip>, z.ZodObject<{
840
842
  type: z.ZodLiteral<"deleteElement">;
841
843
  pageRef: z.ZodString;
@@ -1892,6 +1894,7 @@ export declare const operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject
1892
1894
  }>>;
1893
1895
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1894
1896
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1897
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
1895
1898
  }, z.core.$strip>, z.ZodObject<{
1896
1899
  type: z.ZodLiteral<"deleteElement">;
1897
1900
  pageRef: z.ZodString;
@@ -2943,6 +2946,7 @@ export declare const documentOperations: z.ZodArray<z.ZodDiscriminatedUnion<read
2943
2946
  }>>;
2944
2947
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2945
2948
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2949
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
2946
2950
  }, z.core.$strip>, z.ZodObject<{
2947
2951
  type: z.ZodLiteral<"deleteElement">;
2948
2952
  pageRef: z.ZodString;
@@ -24,6 +24,7 @@ export declare const patchElementOp: z.ZodObject<{
24
24
  }>>;
25
25
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
26
26
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
27
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
27
28
  }, z.core.$strip>;
28
29
  export type PatchElement = z.infer<typeof patchElementOp>;
29
30
  export declare const patchElement: (space: Space, env: Env, op: PatchElement) => OpResult;
@@ -1,10 +1,11 @@
1
1
  import { findRootByRef, invalidateIndex, resolveRef } from "../../../../helpers/space.js";
2
2
  import { pageUri } from "../../../../helpers/uris.js";
3
3
  import { empty, fail } from "../../../../helpers/opResult.js";
4
- import { elementAnchor, elementFlag, elementRuntime, initialStateInput, styleRefs } from "../shared.js";
4
+ import { elementAnchor, elementFlag, elementMotion, elementRuntime, initialStateInput, styleRefs } from "../shared.js";
5
5
  import { guardNewRef, writeInitialState } from "../write.js";
6
6
  import { flagGateOf } from "@plitzi/sdk-authoring";
7
7
  import { z } from "zod";
8
+ import { isMotion } from "@plitzi/sdk-shared/schema/motion";
8
9
  import { repointIds } from "@plitzi/sdk-schema/helpers/elementId";
9
10
  //#region src/modules/mcp/tools/operations/schema/elements/patchElement.ts
10
11
  var patchElementOp = z.object({
@@ -19,7 +20,8 @@ var patchElementOp = z.object({
19
20
  initialState: initialStateInput.optional().describe("Merged onto existing initialState: styleVariant overlays per class/selector, visibility overrides"),
20
21
  runtime: elementRuntime.optional(),
21
22
  flag: elementFlag.nullable().optional(),
22
- anchor: elementAnchor.nullable().optional().describe("null removes it")
23
+ anchor: elementAnchor.nullable().optional().describe("null removes it"),
24
+ motion: elementMotion.nullable().optional().describe("null removes it")
23
25
  }).describe("Partially update an EXISTING element: only the fields you pass change (props/style/initialState are merged, not replaced). Never creates — fails if ref does not resolve. Use upsertElement to create or fully replace.");
24
26
  var patchElement = (space, env, op) => {
25
27
  const page = findRootByRef(space.schema, op.pageRef);
@@ -55,6 +57,8 @@ var patchElement = (space, env, op) => {
55
57
  else if (op.flag !== void 0) el.definition.flag = flagGateOf(op.flag, `Element "${op.ref}"`);
56
58
  if (op.anchor === null) Reflect.deleteProperty(el.definition, "anchor");
57
59
  else if (op.anchor !== void 0) el.definition.anchor = op.anchor;
60
+ if (op.motion === null) Reflect.deleteProperty(el.definition, "motion");
61
+ else if (isMotion(op.motion)) el.definition.motion = op.motion;
58
62
  return {
59
63
  ...empty(),
60
64
  updated: 1,
@@ -5,6 +5,7 @@ import { elementInput, position } from "../shared.js";
5
5
  import { DROP_POSITION, collectInputRefs, createElement, guardNewRef, writeInitialState } from "../write.js";
6
6
  import { flagGateOf } from "@plitzi/sdk-authoring";
7
7
  import { z } from "zod";
8
+ import { isMotion } from "@plitzi/sdk-shared/schema/motion";
8
9
  //#region src/modules/mcp/tools/operations/schema/elements/upsertElement.ts
9
10
  var upsertElementOp = z.object({
10
11
  type: z.literal("upsertElement"),
@@ -35,6 +36,7 @@ var upsertElement = (space, env, op) => {
35
36
  if (op.element.runtime !== void 0) existing.definition.runtime = op.element.runtime;
36
37
  if (op.element.flag !== void 0) existing.definition.flag = flagGateOf(op.element.flag, `Element "${op.element.ref}"`);
37
38
  if (op.element.anchor !== void 0) existing.definition.anchor = op.element.anchor;
39
+ if (isMotion(op.element.motion)) existing.definition.motion = op.element.motion;
38
40
  return {
39
41
  ...empty(),
40
42
  updated: 1,
@@ -52,6 +52,7 @@ export declare const elementOps: {
52
52
  }>>;
53
53
  flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
54
54
  anchor: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
55
+ motion: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>>;
55
56
  }, import('zod/v4/core').$strip>;
56
57
  deleteElement: import('zod').ZodObject<{
57
58
  type: import('zod').ZodLiteral<"deleteElement">;
@@ -20,6 +20,8 @@ export interface ElementInput {
20
20
  runtime?: ElementRuntime;
21
21
  flag?: string;
22
22
  anchor?: string;
23
+ /** Checked by `motionProblems`: what arrives here is one, which `isMotion` narrows it to where it is written. */
24
+ motion?: Record<string, unknown>;
23
25
  children?: ElementInput[];
24
26
  }
25
27
  export declare const styleRefs: z.ZodObject<{
@@ -39,6 +41,14 @@ export declare const elementRuntime: z.ZodEnum<{
39
41
  export declare const elementFlag: z.ZodString;
40
42
  /** The element's `id` in the DOM, so `/page#anchor` lands on it — the one pattern every writer holds it to. */
41
43
  export declare const elementAnchor: z.ZodString;
44
+ /**
45
+ * How an element arrives and whether it keeps moving — the presets the SDK's stylesheet plays, and nothing else.
46
+ *
47
+ * An open object, checked by `motionProblems`, rather than its fields spelled out: this schema is in every tool that
48
+ * carries the op union, and spelled out it cost the listing more than its budget had room for. A wrong preset is
49
+ * refused with the list of right ones, and the guide's Motion section names them all.
50
+ */
51
+ export declare const elementMotion: z.ZodRecord<z.ZodString, z.ZodUnknown>;
42
52
  export declare const initialStateInput: z.ZodObject<{
43
53
  styleVariant: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
44
54
  visibility: z.ZodOptional<z.ZodBoolean>;
@@ -64,6 +74,7 @@ export declare const elementShape: {
64
74
  }>>;
65
75
  flag: z.ZodOptional<z.ZodString>;
66
76
  anchor: z.ZodOptional<z.ZodString>;
77
+ motion: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
67
78
  };
68
79
  export declare const elementInput: z.ZodType<ElementInput>;
69
80
  export declare const position: z.ZodEnum<{
@@ -1,6 +1,7 @@
1
1
  import { z } from "zod";
2
2
  import { FLAG_GATE_PATTERN } from "@plitzi/sdk-shared/flags";
3
3
  import { ANCHOR_PATTERN } from "@plitzi/sdk-shared/schema/anchor";
4
+ import { motionProblems } from "@plitzi/sdk-shared/schema/motion";
4
5
  //#region src/modules/mcp/tools/operations/schema/shared.ts
5
6
  var combinator = z.enum(["and", "or"]);
6
7
  var operator = z.enum([
@@ -70,6 +71,19 @@ var elementRuntime = z.enum([
70
71
  var elementFlag = z.string().regex(FLAG_GATE_PATTERN).describe("Feature flag: `name` renders only while on, `!name` only while off");
71
72
  /** The element's `id` in the DOM, so `/page#anchor` lands on it — the one pattern every writer holds it to. */
72
73
  var elementAnchor = z.string().regex(ANCHOR_PATTERN).describe("Its DOM id, for `/page#anchor` and the `hash` of a link; one per page");
74
+ /**
75
+ * How an element arrives and whether it keeps moving — the presets the SDK's stylesheet plays, and nothing else.
76
+ *
77
+ * An open object, checked by `motionProblems`, rather than its fields spelled out: this schema is in every tool that
78
+ * carries the op union, and spelled out it cost the listing more than its budget had room for. A wrong preset is
79
+ * refused with the list of right ones, and the guide's Motion section names them all.
80
+ */
81
+ var elementMotion = z.record(z.string(), z.unknown()).superRefine((motion, ctx) => {
82
+ for (const problem of motionProblems(motion)) ctx.addIssue({
83
+ code: "custom",
84
+ message: problem
85
+ });
86
+ }).describe("{enter,on,duration,delay,stagger,loop} — guide: Motion");
73
87
  var initialStateInput = z.object({
74
88
  styleVariant: styleVariantInput.optional().describe("Variant each attached class uses: { className: { base|slot: variantName | [names] } }"),
75
89
  visibility: z.boolean().optional().describe("Initial visibility of the element")
@@ -84,7 +98,8 @@ var elementShape = {
84
98
  initialState: initialStateInput.optional().describe("Applied style variant(s) and initial visibility (see plitzi://guide styling)"),
85
99
  runtime: elementRuntime.optional(),
86
100
  flag: elementFlag.optional(),
87
- anchor: elementAnchor.optional()
101
+ anchor: elementAnchor.optional(),
102
+ motion: elementMotion.optional()
88
103
  };
89
104
  var elementInput = z.lazy(() => z.object({
90
105
  ...elementShape,
@@ -141,4 +156,4 @@ var interactionNode = z.object({
141
156
  preview: z.record(z.string(), z.unknown()).optional()
142
157
  });
143
158
  //#endregion
144
- export { bindingCategory, bindingInput, elementAnchor, elementFlag, elementInput, elementRuntime, elementShape, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
159
+ export { bindingCategory, bindingInput, elementAnchor, elementFlag, elementInput, elementMotion, elementRuntime, elementShape, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
@@ -3,6 +3,7 @@ import { folderUri, foldersUri, layoutsUri, pageUri, pagesUri, schemaVarsUri, se
3
3
  import { fail } from "../../../helpers/opResult.js";
4
4
  import { flagGateOf } from "@plitzi/sdk-authoring";
5
5
  import { documentIds } from "@plitzi/sdk-schema/helpers/components";
6
+ import { isMotion } from "@plitzi/sdk-shared/schema/motion";
6
7
  import { elementIdConflict, isValidElementId } from "@plitzi/sdk-schema/helpers/elementId";
7
8
  import FlatMap from "@plitzi/sdk-schema/helpers/FlatMap";
8
9
  //#region src/modules/mcp/tools/operations/schema/write.ts
@@ -67,7 +68,8 @@ var createElement = (space, page, input, anchorId, drop) => {
67
68
  styleSelectors,
68
69
  ...input.runtime === void 0 ? {} : { runtime: input.runtime },
69
70
  ...input.flag === void 0 ? {} : { flag: flagGateOf(input.flag, `Element "${input.ref}"`) },
70
- ...input.anchor === void 0 ? {} : { anchor: input.anchor }
71
+ ...input.anchor === void 0 ? {} : { anchor: input.anchor },
72
+ ...isMotion(input.motion) ? { motion: input.motion } : {}
71
73
  }
72
74
  };
73
75
  if (!new FlatMap({ flat: space.schema.flat }).addElement(el, anchorId, drop)) return false;
@@ -1,6 +1,6 @@
1
1
  import { actionAccess, actionField, actionLimits, actionNode, actionTriggerParams } from "./actions/document.js";
2
2
  import { connectorConnection, readEndpoint, writeEndpoint } from "./connectors/manifest.js";
3
- import { bindingInput, elementAnchor, elementFlag, elementInput, initialStateInput, interactionNode, position, ruleGroup, styleRefs, styleVariantInput } from "./schema/shared.js";
3
+ import { bindingInput, elementAnchor, elementFlag, elementInput, elementMotion, initialStateInput, interactionNode, position, ruleGroup, styleRefs, styleVariantInput } from "./schema/shared.js";
4
4
  import { ancestors, ancestorsPatch, cssMap, cssPatchMap, definitionSlot, definitionSlotPatch, displayModeCss, displayModeCssPatch, themeValue } from "./style/shared.js";
5
5
  import { z } from "zod";
6
6
  //#region src/modules/mcp/tools/operations/schemaIds.ts
@@ -25,6 +25,7 @@ var SHARED_SCHEMAS = [
25
25
  [elementInput, "Element"],
26
26
  [elementFlag, "ElementFlag"],
27
27
  [elementAnchor, "ElementAnchor"],
28
+ [elementMotion, "ElementMotion"],
28
29
  [ruleGroup, "RuleGroup"],
29
30
  [styleRefs, "StyleRefs"],
30
31
  [initialStateInput, "InitialState"],
@@ -52,6 +52,7 @@ export declare const previewShape: {
52
52
  }>>;
53
53
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
54
54
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
55
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
55
56
  }, z.core.$strip>, z.ZodObject<{
56
57
  type: z.ZodLiteral<"deleteElement">;
57
58
  pageRef: z.ZodString;
@@ -54,6 +54,7 @@ export declare const renderShape: {
54
54
  }>>;
55
55
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
56
56
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
57
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
57
58
  }, z.core.$strip>, z.ZodObject<{
58
59
  type: z.ZodLiteral<"deleteElement">;
59
60
  pageRef: z.ZodString;
@@ -52,6 +52,7 @@ export declare const screenshotShape: {
52
52
  }>>;
53
53
  flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
54
54
  anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
55
+ motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
55
56
  }, z.core.$strip>, z.ZodObject<{
56
57
  type: z.ZodLiteral<"deleteElement">;
57
58
  pageRef: z.ZodString;
@@ -53,6 +53,7 @@ export declare const validateShape: {
53
53
  }>>;
54
54
  flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
55
55
  anchor: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
56
+ motion: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>>;
56
57
  }, import('zod/v4/core').$strip>, import('zod').ZodObject<{
57
58
  type: import('zod').ZodLiteral<"deleteElement">;
58
59
  pageRef: import('zod').ZodString;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plitzi/sdk-mcp",
3
- "version": "0.38.1",
3
+ "version": "0.38.3",
4
4
  "license": "AGPL-3.0",
5
5
  "files": [
6
6
  "dist",
@@ -30,14 +30,14 @@
30
30
  "dependencies": {
31
31
  "@modelcontextprotocol/ext-apps": "^1.7.5",
32
32
  "@modelcontextprotocol/sdk": "^1.32.0",
33
- "@plitzi/plitzi-sdk": "0.38.1",
34
- "@plitzi/sdk-authoring": "0.38.1",
35
- "@plitzi/sdk-elements": "0.38.1",
36
- "@plitzi/sdk-interactions": "0.38.1",
37
- "@plitzi/sdk-schema": "0.38.1",
38
- "@plitzi/sdk-server": "0.38.1",
39
- "@plitzi/sdk-shared": "0.38.1",
40
- "@plitzi/sdk-style": "0.38.1",
33
+ "@plitzi/plitzi-sdk": "0.38.3",
34
+ "@plitzi/sdk-authoring": "0.38.3",
35
+ "@plitzi/sdk-elements": "0.38.3",
36
+ "@plitzi/sdk-interactions": "0.38.3",
37
+ "@plitzi/sdk-schema": "0.38.3",
38
+ "@plitzi/sdk-server": "0.38.3",
39
+ "@plitzi/sdk-shared": "0.38.3",
40
+ "@plitzi/sdk-style": "0.38.3",
41
41
  "ejs": "^6.0.1",
42
42
  "esbuild": "^0.28.2",
43
43
  "zod": "^4.6.5"