@plitzi/sdk-style 0.38.3 → 0.38.5

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,537 @@
1
1
  # @plitzi/sdk-style
2
2
 
3
+ ## 0.38.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 3bce653: ## Agents work through the MCP: the builder's AI chat is gone
8
+
9
+ An agent reaches a space through the MCP, from whatever harness the person already uses; Plitzi no longer runs one of
10
+ its own inside the builder. **Breaking** for whoever imported what that chat was built on:
11
+
12
+ - **The builder's Assistant panel is removed**, with its conversations, attachments, previews and provider settings.
13
+ - **`@plitzi/sdk-mcp` no longer exports the in-process AI engine**: `AIEngine`, `toolResponseOk`, `toolResponseErr`,
14
+ `zodToJsonSchema`, `getAllowedModes`, `bindTools`, `isToolActive`, `resolveToolHandler`, `isCallToolResult`,
15
+ `toolResponseFromResult` and `buildAgentGuide`. The MCP server, its tools and `@plitzi/sdk-mcp/server` are unchanged;
16
+ the tool functions are still exported to run in-process.
17
+ - **`@plitzi/sdk-shared` drops the chat's types** — `AITypes` (`AiContext`, `AiMode`, `AiMessageAttachment`,
18
+ `AiUsage`, …) and `McpTypes` (`McpTool`, `McpToolHandler`, `McpContent`, …), with their `./types/AITypes` and
19
+ `./types/McpTypes/index` subpaths — and no longer depends on `@modelcontextprotocol/sdk`.
20
+ - **A change's `origin` is never `coworker`**: `ChangeOrigin` is `builder`, `mcp`, `autofix`, `api` or `system`, and
21
+ the History panel's filter follows.
22
+ - **The builder's platform flags are gone**: `PlatformFlags` is no longer part of the builder's first query, nor
23
+ `platformFlags` of its store — `assistanceAI` was the only one.
24
+ - **Plitzi's own deployment no longer offers the `ai.complete` task** to flows.
25
+ - **Each MCP tool says whether it only reads** (`readOnlyHint`, from the tool's `access`), so a host can run a read
26
+ without asking and ask before a write. Until now `access` was read only by the builder's chat.
27
+ - **The MCP works over the JSON adapters.** `createJsonAdapters` offers `getSchema` and `getStyle`, and — for a space
28
+ read from a path — `saveSchema` and `saveStyle`, each writing its document back into the file. **Breaking**:
29
+ `saveOfflineData` is gone from `SSRAdapters`; nothing called it, and it was the JSON adapters' only write, so an MCP
30
+ over them could neither read nor save.
31
+
32
+ ## Lighter pages: icons on their own
33
+ - **Font Awesome is a stylesheet of its own**, `plitzi-sdk-icons.css`, with its fonts as files beside it
34
+ (`webfonts/`) instead of base64 inside `plitzi-sdk.css` — which drops from 287 KB to 103 KB. A page fetches a face
35
+ only when it shows an icon of that style, and a new SDK version no longer downloads the fonts again. The page server
36
+ links it after `plitzi-sdk.css` (`SSRTemplateProps.iconsCssPath`), the SDK's iframe and shadow modes load it beside
37
+ the stylesheet, and the package exports it: **a project that imports `@plitzi/plitzi-sdk/plitzi-sdk.css` imports
38
+ `@plitzi/plitzi-sdk/plitzi-sdk-icons.css` too** — `plitzi upgrade` adds it to `src/main.ts`, and a new project has
39
+ it. The MCP's rendered widgets inline the sheet, fonts and all, only for a widget that draws an icon.
40
+ - **Material Icons is no longer loaded.** Nothing in Plitzi used it; every page paid a request to Google for it.
41
+ - **A page loads only the plugins it draws.** The page server sends the rest as their declaration
42
+ (`PluginEntry.deferred`, `pluginDeclarationOf` in `@plitzi/sdk-shared/plugins/declaration`); the SDK registers each
43
+ as a stand-in that knows its types from the start, and loads its code and stylesheet the first time one of its
44
+ elements is drawn — on a page reached by navigating too, with no server involved. What a page draws is
45
+ `pageElementTypes` (`@plitzi/sdk-shared/schema/pageElements`): the page, its layouts, the components and references
46
+ it holds. `render()` takes a plugin as `{ load, css, declaration }` beside `{ component }`.
47
+ - **The space travels beside the page, not inside it.** The page names it (`<link id="plitzi-space">`,
48
+ `SSRTemplateProps.spaceDocumentPath`), the browser fetches it while the scripts load, and the page server answers
49
+ `/_plitzi/space/<hash>.json` behind the same gates as its pages — `immutable`, since the name is its content's hash:
50
+ one download for every page and every visit until the space changes. The website's docs page went from 2.6 MB to
51
+ 0.5 MB. Still the whole space, so every navigation after the first page stays in the browser. A draft preview and a
52
+ deployment's own `templateFn` keep it inline.
53
+ - **An arrival on screen plays as the page arrives.** A `motion: { on: 'view' }` element already in view was held
54
+ invisible until the SDK hydrated — the page's content, and a page rendered `ssrOnly` forever. The page server's
55
+ document now sees it as soon as it is parsed, and hands over to the SDK once the page is live.
56
+
57
+ ## Server data: one request per question, the newest winning, and a way to stop
58
+ - **A link asks for its page's server data once.** The navigation's prefetch already brought it; the route change that
59
+ followed asked again — two renders per click. `useRscSync` now asks only for a location the store does not hold.
60
+ - **Answers land in the order they were asked.** `refreshRsc` joins a refresh already in flight for the same URL and
61
+ aborts one a newer refresh would overwrite (a whole payload asked again, an element asked again); a whole payload
62
+ keeps what an element asked for after it. A slow answer no longer paints a page the visitor has left.
63
+ - **Stopping.** `cancelRsc(store, ids)`, an `apiContainer`'s `cancelQuery` callback (`cancelApi(id)` in authoring) and
64
+ `queryCache.cancel(key)` for a browser provider: the request is dropped and what is shown stays. The server hears it:
65
+ `SSRRscContext.signal` aborts when the browser hangs up, and the default `getRscData` stops every element still
66
+ resolving — a shared render run only once nobody is waiting on it.
67
+ - **Pending.** A server provider's `isLoading` is true while it is asked again (`rsc.refreshing`). The `navigation`
68
+ source says `pending` and `pendingLocation` while a link waits for its destination's data; a second link clicked
69
+ before the first went supersedes it, and the first never goes.
70
+ - **A bound `input` asks again.** An `apiContainer`'s `input` is a prop now: bound to state, every change refetches a
71
+ server provider. What a refresh asks for (`req.ctx.rscParams`) wins over the `input` the element was saved with.
72
+ - **A section cut by its budget says how to give it more** (`rsc.elementTimeoutMs`).
73
+
74
+ ## Flows
75
+ - **`whileRunning('latest')`**: a new firing stops the run in progress — no further step; its `runServerAction` is
76
+ cancelled (request and server run) and its `webHook` aborted — and runs. A search as you type. The step's context
77
+ carries the `signal`. Offered in the builder and the MCP.
78
+ - `onApiSuccess` / `onApiError` fire once per answer: a cancelled request or a loading flag that came and went no
79
+ longer runs the flow again.
80
+ - **A debounce is `whileRunning('latest')` and a `delay` first**: `delayTime` ends its wait the moment its run is
81
+ superseded, so only the last firing gets past it. Its `time` is a number.
82
+
83
+ ## Server actions
84
+ - **The request budget is never silent.** A task that caught the refused fetch hid `maxRequests`; the step that ran
85
+ into it now logs it, and the server logs it once, naming `createServer({ action: { limits: { maxRequests } } })`.
86
+ - **`invalid_input` says what the value was and which type takes it** — `windows (text, got a list; declare the field
87
+ \`json\` to take it)`. The templates reference documents that a param that is only `|json_encode` is the value it
88
+ encodes.
89
+ - **`kv` survives a restart with no database.** `createFileKv({ file })` (`@plitzi/sdk-server/actions`) keeps the
90
+ in-process store in one JSON file, written whole as soon as anything changes — for one process.
91
+ `createSqliteKv({ file } | { db })` (`@plitzi/sdk-server/sqlite`, new entry) is a table in a SQLite file over
92
+ `node:sqlite`, every operation one statement, shared safely by every process on the file. Both pass the adapter
93
+ contract every store is held to. The `09-schedules` example uses it rather than its own copy, whose counters read
94
+ `22.0`.
95
+
96
+ ## Authoring
97
+ - **What a space declares and never uses** is suggested now: `unused-class`, `unused-token`, `unused-component`, and
98
+ `literal-colour` — a class painted from the palette typing out a scheme token's light value. A suggestion about
99
+ declarations names them in `subjects`, so the MCP says one a batch left unused beside the ones the space had.
100
+ `unusedDeclarations(schema, style)` is the rule itself, for anything else that says "unused" (the builder does).
101
+ - **`pageFamily(shape, entries)`** writes pages of one shape from data: each page its id, slug, titles, folder and
102
+ layout, and its body built inside `scope(entry.id, …)` so two pages never give one id.
103
+ - **`action-output-path`** (warned): `.data` read on a provider fed by a server action, which publishes its output at
104
+ the root. **`actionSource(id, sample)`** types such a provider by a sample of its output.
105
+ - A value template (`returns: 'value'`, a computed, a step param) may name its parts with `{% set %}` before its one
106
+ expression, and is still that expression's value.
107
+ - `abs()`, `floor()`, `ceil()`, `clamp()` are refused with how they are written here (`x|abs`,
108
+ `x|round(0, 'floor')`, `min(max(x, low), high)`).
109
+ - An unknown attribute is reported against the element's props, not as "'id' does not exist in type ElementSpec[]".
110
+ - `explain` answers a builder's name (`reloadApi`, `cancelApi`) with its step, and knows `whileRunning`.
111
+ - A component's instance takes `quiet`, like any element — `component(id, { quiet: ['repeated-shape'] })`: instances
112
+ whose slots are filled alike on purpose stop being offered as a repeat, and an exported instance that carries one
113
+ typechecks.
114
+ - `container` and `text` take a `title`. A trigger's `preview` may hold numbers, flags, lists and `null`.
115
+ - **A Markdown element's headings are sections a link can name.** Each renders with the anchor its words read as
116
+ (`## Server data` → `#server-data`, numbered when repeated), and a link's `hash` may name one: `anchor-missing` counts
117
+ them, so a table of contents built from the Markdown is checked like any other link.
118
+ - `answerAction(page, actionId, output)` (testing): a test that would save something answers that server action in
119
+ the browser — the server's `kv`, and what the developer kept, are never written. A stream step gets its `done` frame.
120
+
121
+ ## Plugins
122
+ - **A plugin's stylesheet sits below the space's.** The cascade order is now `… utilities, plitzi-sdk-plugin,
123
+ plitzi-sdk-runtime`, and whatever builds a plugin writes its CSS into `plitzi-sdk-plugin` (`inPluginLayer` from
124
+ `@plitzi/sdk-shared/style`): `plitzi pack plugin`, a server compiling one (`action: 'compile'`), and the stylesheet a
125
+ server copies or downloads for one. A space's classes and `customCss` now win over what the plugin's author shipped,
126
+ whatever the specificity — as they do over a built-in element. A plugin packed before this ships unlayered and still
127
+ wins until it is packed again.
128
+ - **Declared param types reach the callback.** A param declared `number` (new, a text box in the builder) or `boolean`
129
+ is handed over as one — written `5000`, or bound to text that says it; an empty number as nothing, so the component's
130
+ default applies.
131
+ - **`useElementVisible(id)`** (`@plitzi/plitzi-sdk`): whether another element is on the page — its own `visible`, every
132
+ container around it, the breakpoint — kept current while the plugin is mounted, at that plugin's cost alone.
133
+ - **A page open on a development server loads again when the server restarts** (`devReload`): `start:dev` restarting
134
+ on a change to the server's code reached the open page only when somebody reloaded it.
135
+ - **A saved plugin is swapped into the open page** (`devReload`, server mode): the page server rebuilds the plugin
136
+ whose source changed and the page renders the new component in place, keeping its state — no restart, no reload. A
137
+ change to its declaration (what the builder and the linter know of it) still reloads the page. `render()` takes
138
+ `{ hotPlugins: true }` and answers `{ unmount, replacePlugin }`; `PluginManager.rebuild(name)` and `onSources`. A new
139
+ folder in `src/plugins` is registered without a restart (`server.plugins.register`), from `create` and `create --from` alike.
140
+ - **A plugin brings its own server half.** `functions/index.ts` beside the component — the `defineFunctions` a
141
+ space's functions use — answers routes under `/fn/plugins/<type>/` and runs steps named `<type>.<action>` (origin
142
+ `'plugin'`, the builder's **Plugins** group). It runs with a narrower `ctx`: its own `kv` (prefixed
143
+ `plugin:<type>:`, its `rateLimit` and `sign` too), none of the space's credentials, no realtime publishing or grants;
144
+ its routes and tasks outside its namespace are refused, as are a space's routes under `/fn/plugins/`. The component
145
+ reaches its routes with `usePluginRoute(type)` (`@plitzi/plitzi-sdk`; `undefined` where no server runs code).
146
+ A page server takes them as `functions.plugins` (`{ [type]: FunctionsDefinition }`), swaps one with
147
+ `server.functions.setPlugin`, and asks a cloud adapter with `actionLookups.getPluginFunctions(spaceId, version)`.
148
+ `plitzi pack plugin` carries the source in the zip as `functions.source.json` (`PLUGIN_FUNCTIONS_SOURCE`, named by
149
+ the manifest's `functions`; `loadFunctionsSource` builds it) — kept privately by the platform, never published.
150
+ - **A plugin lays out the space's elements it holds.** `elementChildren(children)` (`@plitzi/plitzi-sdk`) hands
151
+ over each child element with the id it was authored under, for a dock, tabs or a masonry to place in boxes of its
152
+ own — instead of writing styles onto elements it does not render.
153
+ - **`useDisplayMode()`** (`@plitzi/plitzi-sdk`): `desktop`, `tablet` or `mobile`, at the widths the space's styles are
154
+ compiled at — not a breakpoint of the plugin's own.
155
+ - **A file a library needs whole travels inside the bundle**, imported as Vite imports it: `worker.js?raw` (its text — a
156
+ worker from a Blob), `engine.wasm?inline` (a base64 data URI). `plitzi pack` and a server compiling a plugin share
157
+ one build (`@plitzi/sdk-shared/plugins/bundle`), so a server now inlines `.avif`, `.ttf` and `.otf` as `pack` did.
158
+
159
+ ## CLI and page checks
160
+ - **`plitzi lint`** reads a local space's source the way eslint reads code, for what the document cannot show:
161
+ `file-too-long`, `pages-in-one-file`, `inline-records` (rows of data written in code → `src/data/`), `repeated-css`,
162
+ `special-case-in-map`, `colour-not-token`, `positional-id`, `unused-file` — each at file:line with what to write
163
+ instead — and authoring's suggestions at the line that wrote them. `--json`, `--strict`, `--max-warnings <n>`;
164
+ `// plitzi-lint-disable-next-line <code> -- why` for a departure on purpose. Projects get `npm run lint:space`
165
+ (`upgrade` adds it to older ones). `doctor` stays the project's and never reads the space.
166
+ - **`--template blank`** starts with only the colours its page uses: a token declared and read by nothing is one
167
+ authoring now points out.
168
+ - **The welcome space is written as a folder**, not one 800-line file: `src/space/index.ts` (the page), `tokens.ts`,
169
+ `theme.ts`, `content.ts` — the shape a space keeps as it grows, and clean under `plitzi lint`. **Breaking** for
170
+ whoever called it: `blankSpaceSource()` is now `blankTemplateFiles({ name, dir, plugin })`, which returns the files by
171
+ path; `toPortableSource` keeps imports of the files beside it. A plugin package's preview space is
172
+ `preview/space/index.ts`.
173
+ - **`check`, `shot` and the generated visual tests settle instead of waiting for `networkidle`**, which never came on a
174
+ page with a realtime channel: `openPage` (`@plitzi/sdk-authoring`) waits for load, then quiet, counting no stream
175
+ that stays open.
176
+ - **The server is the project's in `src/config/serverOptions.ts`; `src/main.ts` stays the CLI's.** `create` writes
177
+ `src/config/serverOptions.ts` (handed to `createServer`, typed from `ServerConfig`, now exported by
178
+ `@plitzi/sdk-server`) and, with `--source local`, `src/actions/index.ts` (the space’s server actions), which `main.ts` wires
179
+ for calls, renders and schedules. What `main.ts` wires itself (the space's adapters, the plugins, `public/`,
180
+ `src/data/`, `src/functions/`, the actions' lookups) is left out of `serverOptions`' type and comes after it, so no option unwires it.
181
+ `upgrade` writes either file into a project that has none — only when the `main.ts` reading it is the CLI's — and
182
+ never replaces it; `create --from` projects read `serverOptions.ts` too.
183
+ - **`upgrade packages` brings up the scripts the CLI wrote and nobody changed** (`.plitzi/scaffold.json` now records
184
+ them); a script the project changed is left and said, as before.
185
+ - `start:dev` restarts on a change to the server's code — `src/main.ts`, `src/config/`, `src/actions/` and
186
+ `src/functions/` (there from the start, kept by a `.gitkeep`); a plugin is swapped in the open page instead, and its
187
+ `functions/` set again, without a restart. A function imports its siblings with `.ts`, as `src/`.
188
+ - `add plugin --server` writes the plugin's server half (`functions/index.ts`, a `GET`/`POST /state` example on its
189
+ `kv`); a package gets `@plitzi/sdk-server` as a devDependency for its types. Refused in a client-mode project.
190
+ - `add plugin`: `--prop rows:list` and `--prop meta:json` for data a binding fills; `--headless` writes
191
+ `drawsNothing: true`; the generated events hook never fires on the builder's canvas.
192
+ - A `channel` with no tag is boxless to a page check, like a provider; an empty list is said to have no rows, with what
193
+ to do, instead of "no size (0×0)".
194
+ - **A server-mode project keeps its `kv` in `state/kv.json`** (`createFileKv`; ignored by git): what the space's actions
195
+ save outlives a restart, `start:dev`'s included. `action.kv` in `src/config/serverOptions.ts` names another store.
196
+ - A server-mode project types what its plugins import besides code (`plitzi/assets.d.ts`): a stylesheet, an image,
197
+ `?raw`, `?inline` — a client-mode one has them from `vite/client`.
198
+ - **A project made from a space runs the server `create` writes.** It has the same `src/main.ts` as any project: it
199
+ now takes a free port and writes `tmp/dev-server.json` (which `check`, `shot` and the visual tests read), answers
200
+ `/health`, and re-authors its pages on save instead of waiting for a restart. Its actions are `src/actions/` and its
201
+ connectors `src/connectors/`, both there from the start, and `start:dev` restarts on them; `src/actions/index.ts`
202
+ exports `actions` and `connectors`, as a `create` project's does (`push` reads that). Before, `upgrade` showed its
203
+ `main.ts` as the project's own, and `--take all` would have put `create`'s server in place of the space's.
204
+ - **A `--source cloud` server project starts.** Its key is in `.env`, which nothing read: `npm start` stopped on "Set
205
+ PLITZI_HOST_KEY". Every server project's `src/main.ts` now reads `.env` itself (`process.loadEnvFile`), and every
206
+ one is given a signing key there (`PLITZI_SIGNING_SECRET`, made for it by `create`) — `ctx.sign` refused in a project
207
+ `create` wrote, a plugin's server half included. `PORT` is no longer written into `.env`, where it pinned 8080. A
208
+ cloud project keeps its `kv` in `state/kv.json` too.
209
+ - **`upgrade` keeps the package manager a project was written for** (`.plitzi/scaffold.json`) when it has no lockfile
210
+ of its own yet: a yarn or pnpm project not installed (`--no-install`), or sitting in a monorepo folder, was taken for
211
+ npm and its `AGENTS.md`, Playwright config and `.gitignore` replaced with npm's commands.
212
+ - `author`, `check`, `fix` and `push` know the element types of a project's built-only plugins
213
+ (`vendor/plugins/*/plugin-manifest.json`, every element each provides), as its server does.
214
+ - **`import` reaches Plitzi only when told to.** A site not served from this machine needs `--account` — ask the
215
+ person's Plitzi account whether one of their spaces verified its domain, signing in — and without it is refused,
216
+ saying so, before any request: an agent running `import` in a local project opened a sign-in nobody asked for. The
217
+ CLI skill and the generated `AGENTS.md` say to run `import` only when the user asks, and to ask before `--account`.
218
+ - **A server project's data is no longer on the internet.** It was `public/data/*.json`, served to anyone as a file;
219
+ it is `src/data/*.json`, which the server reads and never serves (`dataDir`, new in `createServer`): a provider with
220
+ `runtime: 'server'` and `query: '/data/<file>'` reads it, and the page arrives with it. `projectData`
221
+ (`@plitzi/sdk-authoring/node`) and `authorSpace`'s `serverData` hold bindings to those files, and a provider asking
222
+ for `/data/…` from the browser is refused (`server-data-in-browser`): nothing would answer it. What a provider reads
223
+ is still in the page it renders — data a page must not carry is a server action's to read. A client-mode project
224
+ keeps `public/data/`, which the browser has to fetch. The catalog template follows the mode
225
+ (`catalogTemplateFiles({ mode })`). `public/` holds only what is meant for everyone.
226
+ - **The project's own server code is `src/functions/`**, with the rest of its source — typechecked with it, left out of
227
+ `tsconfig.build.json` (the server builds it at boot). `functions pull`/`push`/`dev`, `push`, `pull` and `create
228
+ --from` follow. The `kv` folder is `state/` (it was `data/`, beside a data folder that was something else).
229
+ - **What is the CLI's is in `plitzi/`, apart from `src/`.** `plitzi/author.ts`, `plitzi/assets.d.ts` (server mode) or
230
+ `plitzi/preflight.css` (client mode), and `plitzi/README.md` — which says what each folder of `src/` is, instead of a
231
+ README in every one. `src/main.ts` stays where an entry point is looked for, the CLI's all the same.
232
+ `src/plugins/declarations.ts` is gone: a plugin is declared by its folder's `declaration.ts`, found by the server,
233
+ `author`, `check`, `fix`, `push` and the visual test alike (`pluginDeclarations` from `@plitzi/sdk-authoring/node`;
234
+ Vite's `import.meta.glob` in client mode).
235
+ - `functions.plugins` is in `SSRServerConfig`'s type and checked as the server starts: a project passing its plugins'
236
+ server halves did not typecheck.
237
+ - **A project's source is folders that grow.** The space is `src/space/` — its `index.ts` exports it as `space` and
238
+ assembles the rest (the catalog template's `src/site/` is `src/space/` now; `create --from` writes the space's own
239
+ `index.ts` there, exported as `space` too). The server actions are `src/actions/` — `index.ts` lists them, one action
240
+ a file, as `create --from` already had them — and what the server does besides serving the space is
241
+ `src/config/serverOptions.ts`. `start:dev` watches `src/config` and `src/actions` whole.
242
+ - **One server for every project, kept by `upgrade`.** `src/main.ts` runs what a project holds from where it lands — a
243
+ runtime in `src/runtime/` (or built only, `vendor/runtime.bundle`), plugins built only (`vendor/plugins/`), the
244
+ actions' connectors — so `create --from` writes no `main.ts` or `.prettierignore` of its own any more, and `upgrade`
245
+ keeps both current in projects made from a space too. `loadRuntimeModule` (`@plitzi/sdk-server/runtime`): a project's
246
+ runtime module, or nothing when it has none.
247
+ - **`plitzi add runtime`** writes `src/runtime/index.ts` — run by the project's server (`npm start` answers its
248
+ endpoints) and sent by `plitzi runtime push`, whose default entry it is now — and has `start:dev` restart on it. A
249
+ space taken out with a runtime gets `src/runtime/index.ts` handing over the module its source starts at.
250
+ - **`push` sends the space's files back as their CDN addresses.** `create --from` and `pull` write each CDN address as
251
+ the project's path (`/assets/a.png`, served from `public/assets/`); `push` sent those paths as they were, and the
252
+ space's pictures and data pointed at nothing on Plitzi. It also says, before sending, what Plitzi would not have: a
253
+ provider reading a file `src/data/` does not hold, and a file the space names that is not on its CDN.
254
+ - **`push` sends a project's data and its files.** Two new parts: `data` — `src/data/` whole, kept by Plitzi as the
255
+ space's own data (private, frozen with each publish, read by the page server of the version it renders; refused when
256
+ the space's copy changed since the project last had it, unless `--force`) — and `files` — each changed file of
257
+ `public/assets/`, put at the same path under the space's `assets/` on its CDN, so a pull brings it back where it was.
258
+ `create --from` and `pull` write the space's data into `src/data/`. `getData` joins the action lookups
259
+ (`ActionLookupsConfig`), and the page server resolves `/data/<file>` through it when there is no `dataDir`.
260
+ - **A space's data is edited in the builder and by agents.** The builder's Server view has a **Data** tab: the JSON
261
+ files the space's server providers read (`/data/<file>`), a file list and a JSON editor, saved whole against the
262
+ copy it read (⌘S; a newer copy is refused, a broken file named). The MCP reads it as `plitzi://data/{env}` and writes
263
+ it with `upsertDataFile` / `deleteDataFile` (`getData` / `saveData` among the adapters; a file that is not JSON is
264
+ refused as it is written), and the guide has a Data section. One write path for the builder, agents and `plitzi push`
265
+ (`SpaceData` / `SpaceSaveData` over GraphQL, under `spaceManage`), one history. `DataDraft` / `DataSaveResult` are
266
+ in `@plitzi/sdk-shared`. The builder's file list is shared by Functions and Data (`modules/FileTree`).
267
+ - **`plitzi doctor`**: whether the project the CLI set up is whole, checked against what it is now — a developer may
268
+ change any file. Packages (declared, installed at versions that agree, one copy of the SDK and of React), the CLI's
269
+ files and scripts (as `upgrade` sees them, one planner for both), the file each Node script starts and every folder
270
+ `start:dev` watches, the TypeScript configs, `.gitignore` and `.env` (never in git; the signing secret as long as the
271
+ project's server wants it), the code Node runs as written (relative imports with their extension, JSON with its
272
+ attribute, no JSX, every package declared — walked with esbuild), each plugin folder against its declaration, the data
273
+ files, `src/functions/` built by the project's own sdk-server, `.plitzi/` and the skills. Each finding has an area, a
274
+ code, the file and its fix; `--json`, `--strict`; exit 1 on an error. It never checks the space — `npm run author`
275
+ and `check` do — and every report says so. A layout an older CLI left (`src/space.ts`, `src/author.ts`,
276
+ `functions/` at the root…) is its own area, checked first and alone. `--fix` repairs what is simple and safe —
277
+ that layout moved with every import, URL and script following (and the scaffold record with it), dead files,
278
+ `.gitignore`, `"type": "module"`, a watched folder, a signing secret — then checks again; `--dry-run` says what.
279
+ Each report ends with what to run next. `upgrade` writes no file over an older layout, and says `doctor --fix`.
280
+ `buildFunctions` and `FunctionsBuildError` are exported from
281
+ `@plitzi/sdk-server/functions-runner`, `MIN_SIGNING_SECRET_LENGTH` from `@plitzi/sdk-server/actions`.
282
+ - **`--dry-run`** on every command that writes or sends — `create`, `add plugin`, `add runtime`, `pull`, `push`,
283
+ `pack plugin`, `source`, `import`, `upload plugin`, `functions pull`/`push`, `runtime push`/`start`/`stop`/`size`/
284
+ `vars`, `skills update`, `doctor --fix`: each file it would write (`+` new, `~` replaced, `-` removed), what it would install or run, what it would
285
+ send and where, and none of it done. It still reads what it needs to say so.
286
+ - **A new project is formatted from the start**, every template and mode: its first `format` changes nothing. The CLI's
287
+ own files are in its `.prettierignore`, so formatting never turns one into a file `upgrade` believes was changed.
288
+
289
+ ## Builder
290
+ - **The pages panel keeps its folders as you left them** — open or closed, per space, across reloads — the way the
291
+ style inspector keeps its sections. A folder starts closed.
292
+ - **Usages**, a panel beside Layers: where each component, class, token, space variable and data source is used,
293
+ page by page — what reads it and which elements — and which nothing uses, by authoring's own rule. A click selects
294
+ the element, inside a component too.
295
+ - **Revealing an element inside a component opens the component** (the Usages panel, ⌘P, the issues and the history all
296
+ reveal through it); before, the selection was dropped. **Panels stay open** when a component opens or closes.
297
+ - **The canvas dims a page's layout around its body again when the layout or its slot draws no box**
298
+ (`display: contents`, which the efficiency guide recommends): the hole was measured as a rect of zeros and the whole
299
+ page was dimmed. A box-less element is measured by what it holds, and the mask by the box that positions it.
300
+ - **Elements is one category at a time.** A row of chips — each category with its count, and the space's components as
301
+ one more — picks what the panel shows, remembered between sessions, so the panel stays the same height however many
302
+ elements plugins add. A search looks through every category and the components at once. Each element is a tile: its
303
+ icon, its whole name, and what it is on hover. Container, Button, Form, Form Control, Dropdown Popup, List Item, Rich
304
+ Text, Dialog Container and Tab Container Item have icons of their own (`sdk-elements`), none shared with another
305
+ element or with the component and snippet icons.
306
+ - **Layers reads as a tree and is driven from the keyboard.** A guide per depth, a chevron that turns, the component's
307
+ name beside an element that is one, and the selected row kept in view. ↑/↓, Home/End, → to open or go in, ← to close
308
+ or go up. A row under a closed ancestor is no longer shown. (plitzi-ui's `Tree`.)
309
+ - **Motion and preview no longer share an icon.** Playing the page's motion is a wand, which pulses while it plays;
310
+ preview is an eye, and a pen to go back to editing.
311
+ - **A component's settings fit their modal, however many props it has.** The modal is wider; the name and folder
312
+ share a line, and each prop is one compact row — its name, its kind, required, remove — with what a binding writes to
313
+ read it (`{{ props.<name> }}`) or what is wrong with it, and what it is for, beneath. The fields scroll and the buttons
314
+ stay in view. Props and slots are titled sections, and a slot shows its id.
315
+
316
+ ## Packages
317
+ - **`GET /auth/continue` takes `?fallback=`**: where to go when `redirect` is refused, vetted by the same check. A sign-in
318
+ screen's way back sends its site there, so leaving without signing in never lands on "you are signed in".
319
+ - **Markdown renders headings you can link to and code you can copy.** A heading carries its anchor and a `#` link to
320
+ itself; a fenced block a header with its language and a **Copy** button. The anchor is `@plitzi/sdk-shared`'s:
321
+ `anchorOf`, `uniqueAnchor` and `markdownHeadings` (`schema/anchor`, `schema/markdownHeadings`) — what the element
322
+ renders, what authoring checks a link against and what a table of contents is built from are one function. Needs
323
+ `@plitzi/plitzi-ui` 1.6.31 (its `Markdown` takes `headingAnchor`).
324
+ - **Every package declares what it imports, and nothing more.** `react` is a peer of `sdk-auth`, `sdk-event-bridge`,
325
+ `sdk-interactions`, `sdk-style` and `sdk-variables`; `sdk-schema` depends on `immer`, `sdk-elements` on
326
+ `@dr.pogodin/react-helmet`, `sdk-plugins` on `@plitzi/plitzi-ui`, `sdk-style` on `@plitzi/sdk-event-bridge` and
327
+ `sdk-dev-tools` on `@plitzi/sdk-plugins` — each worked only because `@plitzi/plitzi-sdk` brought them, and failed
328
+ installed alone or under a strict linker. `prop-types` and the `@plitzi/*` dependencies nothing imported are gone:
329
+ `sdk-mcp` no longer declares `@plitzi/sdk-elements`, which its code does not import — it still arrives through
330
+ `@plitzi/plitzi-sdk`.
331
+
332
+ - Updated dependencies [3bce653]
333
+ - @plitzi/sdk-event-bridge@0.38.5
334
+ - @plitzi/sdk-shared@0.38.5
335
+ - @plitzi/sdk-variables@0.38.5
336
+
337
+ ## 0.38.4
338
+
339
+ ### Patch Changes
340
+
341
+ - 6ae4161: ## `plitzi push`: a self-hosted project back on its space
342
+
343
+ `plitzi create --from` and `plitzi pull` took a space out as a project and kept it in step; nothing put the project's
344
+ own changes back but a command per part, and no command at all for its pages. `plitzi push` is the way back
345
+ (`docs/en/projects-from-spaces.md`):
346
+
347
+ - **What changed, or what is named.** `plitzi push` sends what changed since the project last had the space — at a
348
+ terminal, offered as a ticked list to choose from (`↑/↓`, space, Enter); `plitzi push space functions` sends only
349
+ those parts: `space`, `functions`, `runtime`, `plugins`.
350
+ - **In order:** each changed plugin packed and uploaded (`pack plugin` + `upload plugin`, `--cdn`/`--bucket`), the
351
+ functions, the runtime, then the space — `src/space.ts` authored, the actions `src/actions.ts` serves and the manifests
352
+ in `src/connectors/` — as the space's draft. Never a published environment.
353
+ - **Never over the builder's work unseen.** The export now carries which state the draft is in (`SpaceExport.draft`),
354
+ recorded in `.plitzi/space.json` by `create --from` and `pull`; a push names it, and a draft edited since is refused
355
+ until `--force`. A project that never had the space may take one nobody has worked on; one holding work takes
356
+ `--force`.
357
+ - **Then `pull` follows it.** `.plitzi/space.json` records what was sent — only that, so a builder's change to a part
358
+ not pushed is still the next pull's — and a project that started on its own works with `pull` from then on.
359
+ - `@plitzi/sdk-shared/source`: `SpaceImport` / `SpaceImportResult` (`SPACE_IMPORT_FORMAT`), the push's one shape for
360
+ both ends, beside `SpaceExport`, which gains `draft`.
361
+ - `functions push`, `runtime push` and `upload plugin` keep their behaviour; their cores are what `push` runs.
362
+
363
+ ## A project's folders: `tmp/` for what it writes, `.plitzi/` committed, `public/` said to be public
364
+ - **`tmp/` is what a project writes for itself.** `@plitzi/sdk-server` keeps the plugins it builds in `tmp/.sdk-plugins`
365
+ and resized pictures in `tmp/images` by default (were `.sdk-plugins` and `.plitzi/images`). A project the CLI writes
366
+ puts the port it took (`tmp/dev-server.json`), the space as last authored while developing (`tmp/space.json`) and
367
+ Playwright's output (`tmp/visual`) there too, and its `.gitignore` ignores `tmp` — one line for all of it.
368
+ - **`.plitzi/` is committed.** The scaffold ignored it whole, so a clone lost `space.json`, `functions.json` and
369
+ `scaffold.json` — what `pull`, `push`, `functions push` and `upgrade` stand on. Now it holds only what the CLI records.
370
+ `npx plitzi upgrade --write` brings an existing project's `.gitignore` up.
371
+ - **No `space/offline-data.json`.** `npm run author` checks the space and writes nothing; the server asks it for the
372
+ documents with `--out tmp/space.json` while developing. The space is `src/space.ts`, and nothing beside it says
373
+ otherwise.
374
+ - **`public/` is on the internet.** The generated `README.md` and `AGENTS.md`, the CLI and authoring skills, the MCP
375
+ guide, `@plitzi/sdk-server`'s README and the docs now say so where data goes: never a secret, a key or data only
376
+ some visitors may read — in `public/`, or in a space's documents, which reach every visitor too.
377
+
378
+ ## An agent leaves the project clean
379
+
380
+ `AGENTS.md` gains **Keep the project clean** — nothing unused left behind, scratch work in `tmp/`, one of everything,
381
+ files a reader can find, and `author`, `typecheck`, `lint`, `format` and `check` passing — and the authoring skill's
382
+ review checklist a **Nothing left behind** section.
383
+
384
+ ## The dev tools' X-ray is the outlines too
385
+
386
+ The QA tab had **Outlines** (every element's box, its type and id when pointed at) and **X-ray** (the same boxes,
387
+ fainter, with what is wired to each). They are one tool now: the X-ray draws every box with its type and id, and marks
388
+ the wiring picked — all of it, one kind, or **Boxes only**.
389
+
390
+ ## A new space that says where to go
391
+
392
+ The space a new account and `plitzi create` start from keeps its welcome, and gains the three ways to change it — the
393
+ builder, code (with the command to run) and an agent — before the guides, which are shorter. Header, navigation, main
394
+ and footer are landmarks; the grid behind the top fades out instead of ending at an edge; the footer's line spans the
395
+ content; the links say their words and icon themselves, with no suggestion left.
396
+
397
+ ## Server data reads the same everywhere
398
+ - **One shape for a provider with a `query`.** A `runtime: 'server'` provider that only reads a JSON file the server
399
+ serves answered the body itself, while the same provider in the browser publishes `{ status, data }` — so moving it
400
+ to the server broke every binding. `publicFileResolver` and the builder's mock now answer `{ status, data }` too:
401
+ `<source>.data.<field>` whichever runtime.
402
+ - **Server data is on unless a space turns it off.** The page render read a missing `rsc` as on and the connector
403
+ resolver as off, so a server provider in a space the builder or the MCP made (neither writes `rsc`) resolved to
404
+ nothing, silently. Both read it as on now; only `rsc: { enabled: false }` turns it off (and is warned with a server
405
+ element). `authorSpace` writes `enabled: true` for a space that has one.
406
+ - **Never inside a component.** The page server resolves a page's tree and its layouts only, so a server provider in a
407
+ component rendered nothing, silently. Refused now (`server-provider-in-component`), with the fix: the provider on
408
+ the page, the rows handed in as a prop.
409
+ - **Bindings held to the data.** `authorSpace` takes `data` — what a provider's `query` answers — and
410
+ `publicData(folder)` (`@plitzi/sdk-authoring/node`) reads it from `public/`. A binding onto a path the file does not
411
+ have is warned (`path-not-in-data`) with the keys it does have. Generated projects pass it.
412
+ - **`plitzi check` reads the data too.** A binding that reads a path its provider's answer lacks, a provider that
413
+ failed (once, not as every element it left empty) and the rows each list rendered (`dataIssues`). `--ssr` names what
414
+ the server's HTML lacks that the hydrated page has. The dev tools' badge and panel (`data-plitzi-devtools`) are hidden
415
+ while `check` and `shot` look.
416
+
417
+ ## Authoring, clearer where agents tripped
418
+ - **`controls` on a button** (`aria-controls`): named by the element's id; authoring gives that element the anchor and
419
+ refuses an id the space lacks (`controls-unknown`); a saved document naming no anchor is warned
420
+ (`controls-no-anchor`). The accordion recipe uses it.
421
+ - **`live` on a container** (`aria-live`, `polite` or `assertive`) for words that change while a visitor reads them.
422
+ - **`subType: 'p'`** for a paragraph made of parts; `span-holds-block` covers it.
423
+ - **`formControl` types `search`, `url` and `tel`.**
424
+ - **Images:** no `src` draws the SDK's own placeholder (the CDN one answered 404); `resize: false` keeps a picture as
425
+ written; an SVG is never resized — `/_plitzi/img` redirects to it (`307`) instead of refusing it.
426
+ - **Messages:** an id taken by another page or layout names it and the id to write; a hyphenated source in a template
427
+ (`list_study-plans`) is explained as valid; an unknown CSS property says to write it in `customCss`; an unknown
428
+ variant on `custom` says it is never a prop of the component it hosts.
429
+ - **`plitzi explain` knows the helpers** — `bindTemplate`, `visibleWhen`, `variantFrom`, `activeOn`, `activeWhen`,
430
+ `when`, `named`, `scope`, `source`, `twig` — and `motion`, from the presets the SDK plays (`MOTION_ENTERS`,
431
+ `MOTION_TRIGGERS`, `MOTION_LOOPS`, now exported). `--list helpers` lists them.
432
+ - **`plitzi shot`** writes to `tmp/shots/` by default, and a full page shows the arrivals tied to the scroll as they
433
+ end. `inspectPage` no longer reports an image a hidden ancestor hides.
434
+ - **Style inspector:** `container-type` in Size.
435
+ - **New recipes:** `server-data.ts`, `accordion.ts`.
436
+
437
+ ## Matching a page to another, measured
438
+ - **A whole page is the whole page.** The SDK scrolls a pane of its own, so `shot`'s full-page picture was one
439
+ screen; the pane is unrolled now (`unrollPage`) — the viewport untouched, so a `100vh` hero stays one screen.
440
+ - **`plitzi shot --compare` says why, not only how much.** Every lazy picture on both pages is loaded before they are
441
+ taken (`loadImages`), so a section no longer swings between 23 % and 40 % on how many covers had arrived. Each section
442
+ is compared where it is on the other page (`alignPictures` over row profiles): a page 400 px longer is said once, with
443
+ the section the drift starts at, instead of a footer with the same styles reading 100 %. And the texts both pages
444
+ have are paired (`pageTexts`, `compareTexts`), each with what it does differently there —
445
+ `h1 "Learn CSS" — font-size 68px → 60px · y +19px` — position less the drift of its section. `comparePictures` takes
446
+ its options as an object now (`{ regions, tolerance, align }`).
447
+ - **`--scheme` is the space's theme.** A space whose default is dark painted dark under `--scheme light`, and the file
448
+ said light. `check` and `shot` now set the `theme` cookie a visitor's toggle writes; left out, the space's default is
449
+ pictured and the file is named by the theme actually painted.
450
+
451
+ ## `motion: { on: 'view' }` arrives once
452
+
453
+ `view` was tied to the scroll both ways: cards faded out again as the reader scrolled back up. Now it plays once, the
454
+ first time the element comes into view, with its `duration`, and stays — `revealOnView` (`@plitzi/sdk-shared/schema/
455
+ motionReveal`), one observer under the SDK's root, marks it `data-motion-seen`. The scroll-driven arrival is
456
+ `on: 'scroll'`. A page read without scripts shows them as they end (`@media (scripting: none)`); the builder's previews
457
+ and the MCP's local screenshots hold motion at its end. The builder's Motion tab has the three.
458
+
459
+ The builder's preview plays motion as the published page does. It held everything at its end, and nothing marked
460
+ the canvas `data-hydrated`, so neither the loops nor a space's own `[data-hydrated]` animations ever started there.
461
+ Now an arrival plays as it comes into view, and the loops and keyframes run; **▶** on the canvas being edited runs the
462
+ space's own `[data-hydrated]` loops too. The motion guide adds the rule this needs from a space: `[data-hydrated]` is for
463
+ loops; an entrance of its own that plays once (`transform`/`opacity` only) plays from the first paint with
464
+ `backwards`, as the presets do — gated on hydration it jumps when the page goes live, and a canvas that never goes
465
+ live holds it on its first frame.
466
+
467
+ ## Thirteen ways in, nine loops
468
+
469
+ `motion` grows from six arrivals and four loops to thirteen and nine, all still `opacity` and the transforms:
470
+
471
+ - **Bold arrivals:** `slide-up` (from well below), `zoom-in` (from 60%), `zoom-out` (settling from 125%), `tilt`
472
+ (rising as it turns straight), `spin-in` (half a turn as it grows).
473
+ - **Springy arrivals:** `pop` overshoots and settles; `bounce-in` falls into place and bounces.
474
+ - **Loops:** `bounce`, `wobble`, `orbit` (a slow circle round where it is), `heartbeat`, `drift`.
475
+
476
+ An arrival is now a list of frames (`MOTION_ENTER_FRAMES` in `@plitzi/sdk-shared/schema/motion`; `MOTION_ENTER_FROM`
477
+ is its first), and so is a loop (`MOTION_LOOP_FRAMES[name].frames`, replacing `transform`/`at`). Arrivals move the
478
+ individual `translate`, `scale` and `rotate`, so they still compose with an element's own `transform` and with a loop.
479
+ The builder's Motion tab previews every frame; authoring, the MCP, `explain motion` and GraphQL read the same lists.
480
+
481
+ An arrival from the side no longer scrolls the page sideways. `slide-left` starts 32px to the right of where it lands,
482
+ past a phone's 16px gutter, and until it had played the page could be dragged sideways. The SDK's root clips that way
483
+ now (`overflow-x: clip`, which keeps the window the scroller: sticky bars and scroll timelines are untouched), and the
484
+ builder's preview does the same. Content wider than the page is cut rather than scrolling the page — give it a box of
485
+ its own with `overflow-x: auto`.
486
+
487
+ **3D and the transform parts are style properties.** `transform-style`, `perspective-origin`, `backface-visibility`,
488
+ `translate`, `rotate` and `scale` join the vocabulary (they were refused as `css-property-unknown` and had to go in
489
+ `customCss`); `scale: 0.94` is a factor, not pixels.
490
+
491
+ **The builder's placeholder for an empty element is 24px** (was 50px), one size for every element that has one. It
492
+ is a minimum, so it also grew empty shapes with a size of their own — a dot, a planet — while editing; 24px is still
493
+ a box to see, pick and drop into.
494
+
495
+ The desktop app's window was blank: authoring, run in the renderer to build the rail, asked Vite's `process` shim for
496
+ a working directory it does not have. It reads one only where there is one now — and only when a class conflict is
497
+ reported, rather than for every element of every space it writes.
498
+
499
+ ## Authoring advice that knows where and when
500
+ - **`class-conflict` says where both declarations are:** `styles('md-menu-button') at src/components/dropdown.ts:12,
501
+ used by button at …, and styles('md-menu-button') at src/site/layout.ts:8, used by …` — `styles()` records its line as
502
+ an element factory does.
503
+ - **`repeated-shape` leaves controls alone.** Siblings that read different sources or write different state keys — a
504
+ menu for the language, one for the level — are not offered as a list.
505
+ - **`quiet: ['repeated-shape']`** on an element says a suggestion was left on purpose, and it is not offered again.
506
+ Only suggestions' codes (`quiet-unknown`). It is saved on the element (`definition.quiet`), so the builder's problems
507
+ panel, the MCP's `upsertElement`/`patchElement` and a project pulled back with `plitzi pull` all leave it alone.
508
+
509
+ ## What the docs say is what the code does
510
+
511
+ A pass across authoring's own messages, the skills, the MCP guide, `docs/en`, the CLI's README and the website, so an
512
+ agent reading two of them is never told two things:
513
+
514
+ - **A binding's `source` is the bound value, and only that.** With no value yet it fell back to the attribute's
515
+ current one — `sourceTo` — so `{{ source|default('…') }}` never took its default and `{{ source ? … }}` read an
516
+ element's placeholder ("Text") as an answer. It is `undefined` until the source has a value now; `sourceTo` is still
517
+ the value before.
518
+ - **`explain` writes a step the way its builder is called:** `delay(ms)`, `openModal('modal-id', data?)`,
519
+ `scrollBy('row-id', { x: '80%' })` — not `delay(…)` above the document's param names, which read as `delay({ time })`.
520
+ - **A page field nobody takes is told what it was probably for** — `seo` → `seoTitle` and `seoDescription` — instead of a
521
+ hint about keeping state appended to every one.
522
+ - Docs set straight: an element's id is `data-plitzi-el` in the page (`data-id` is the builder's, with debugging on);
523
+ a visibility condition writes nothing while its source has no value and is a yes or a no once it has one; `mobile`
524
+ is up to and including 48rem; `loadStrategy` defaults by type (`lazy` for a modal); the accessibility codes listed
525
+ in full everywhere (`embed-without-title`, `dropdown-without-control`, `controls-no-anchor`); the generated
526
+ `AGENTS.md` says a repeated block is a component and rows of data a list, as the skill does; `plitzi runtime` is
527
+ documented in the CLI's README, its skill and the website, which no longer says state across requests needs a
528
+ server of your own.
529
+
530
+ - Updated dependencies [6ae4161]
531
+ - @plitzi/sdk-plugins@0.38.4
532
+ - @plitzi/sdk-shared@0.38.4
533
+ - @plitzi/sdk-variables@0.38.4
534
+
3
535
  ## 0.38.3
4
536
 
5
537
  ### Patch Changes
@@ -4,13 +4,14 @@ import n from "../../components/CategoryOption/index.mjs";
4
4
  import r from "../../components/CategorySection/index.mjs";
5
5
  import i from "../../components/CategoryAdvanced/index.mjs";
6
6
  import a from "../../components/CategoryContainer/index.mjs";
7
- import o from "./SizeFit.mjs";
8
- import s from "./SizeOverflow.mjs";
9
- import c from "./SizePosition.mjs";
10
- import { memo as l, use as u, useCallback as d } from "react";
11
- import { jsx as f, jsxs as p } from "react/jsx-runtime";
7
+ import o from "./SizeContainer.mjs";
8
+ import s from "./SizeFit.mjs";
9
+ import c from "./SizeOverflow.mjs";
10
+ import l from "./SizePosition.mjs";
11
+ import { memo as u, use as d, useCallback as f } from "react";
12
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
12
13
  //#region src/components/StyleInspector/categories/Size/Size.tsx
13
- var m = [
14
+ var h = [
14
15
  "width",
15
16
  "height",
16
17
  "min-width",
@@ -21,111 +22,123 @@ var m = [
21
22
  "box-sizing",
22
23
  "overflow",
23
24
  "object-fit",
24
- "object-position"
25
- ], h = [
25
+ "object-position",
26
+ "container-type",
27
+ "container-name"
28
+ ], g = [
26
29
  "aspect-ratio",
27
30
  "box-sizing",
28
31
  "object-position",
29
- "object-fit"
30
- ], g = ["width", "height"], _ = ["min-width", "min-height"], v = ["max-width", "max-height"], y = l(({ replaceTokens: l = !1, isCollapsed: y = !0, onCollapse: b }) => {
31
- let { setValue: x } = u(e), { width: S, height: C, "min-width": w, "min-height": T, "max-width": E, "max-height": D, "aspect-ratio": O, "box-sizing": k, overflow: A, "object-position": j, "object-fit": M } = t({
32
- keys: m,
32
+ "object-fit",
33
+ "container-type",
34
+ "container-name"
35
+ ], _ = ["width", "height"], v = ["min-width", "min-height"], y = ["max-width", "max-height"], b = u(({ replaceTokens: u = !1, isCollapsed: b = !0, onCollapse: x }) => {
36
+ let { setValue: S } = d(e), { width: C, height: w, "min-width": T, "min-height": E, "max-width": D, "max-height": O, "aspect-ratio": k, "box-sizing": A, overflow: j, "object-position": M, "object-fit": N, "container-type": P, "container-name": F } = t({
37
+ keys: h,
33
38
  asValue: !0,
34
- replaceTokens: l
35
- }), N = d((e) => b?.("size", e), [b]), P = d((e) => (t) => x(e, t), [x]);
36
- return /* @__PURE__ */ p(a, {
39
+ replaceTokens: u
40
+ }), I = f((e) => x?.("size", e), [x]), L = f((e) => (t) => S(e, t), [S]);
41
+ return /* @__PURE__ */ m(a, {
37
42
  title: "Size",
38
- dotKeys: m,
39
- advancedKeys: h,
40
- isCollapsed: y,
41
- onCollapse: N,
43
+ dotKeys: h,
44
+ advancedKeys: g,
45
+ isCollapsed: b,
46
+ onCollapse: I,
42
47
  children: [
43
- /* @__PURE__ */ p(r, {
48
+ /* @__PURE__ */ m(r, {
44
49
  label: "Size",
45
- keys: g,
46
- children: [/* @__PURE__ */ f(n, {
50
+ keys: _,
51
+ children: [/* @__PURE__ */ p(n, {
47
52
  keys: ["width"],
48
53
  preffix: "W",
49
- value: S,
50
- onChange: P("width"),
54
+ value: C,
55
+ onChange: L("width"),
51
56
  type: "metric"
52
- }), /* @__PURE__ */ f(n, {
57
+ }), /* @__PURE__ */ p(n, {
53
58
  keys: ["height"],
54
59
  preffix: "H",
55
- value: C,
56
- onChange: P("height"),
60
+ value: w,
61
+ onChange: L("height"),
57
62
  type: "metric"
58
63
  })]
59
64
  }),
60
- /* @__PURE__ */ p(r, {
65
+ /* @__PURE__ */ m(r, {
61
66
  label: "Min Size",
62
- keys: _,
63
- children: [/* @__PURE__ */ f(n, {
67
+ keys: v,
68
+ children: [/* @__PURE__ */ p(n, {
64
69
  keys: ["min-width"],
65
70
  preffix: "W",
66
- value: w,
67
- onChange: P("min-width"),
71
+ value: T,
72
+ onChange: L("min-width"),
68
73
  type: "metric"
69
- }), /* @__PURE__ */ f(n, {
74
+ }), /* @__PURE__ */ p(n, {
70
75
  keys: ["min-height"],
71
76
  preffix: "H",
72
- value: T,
73
- onChange: P("min-height"),
77
+ value: E,
78
+ onChange: L("min-height"),
74
79
  type: "metric"
75
80
  })]
76
81
  }),
77
- /* @__PURE__ */ p(r, {
82
+ /* @__PURE__ */ m(r, {
78
83
  label: "Max Size",
79
- keys: v,
80
- children: [/* @__PURE__ */ f(n, {
84
+ keys: y,
85
+ children: [/* @__PURE__ */ p(n, {
81
86
  keys: ["max-width"],
82
87
  preffix: "W",
83
- value: E,
84
- onChange: P("max-width"),
88
+ value: D,
89
+ onChange: L("max-width"),
85
90
  type: "metric"
86
- }), /* @__PURE__ */ f(n, {
91
+ }), /* @__PURE__ */ p(n, {
87
92
  keys: ["max-height"],
88
93
  preffix: "H",
89
- value: D,
90
- onChange: P("max-height"),
94
+ value: O,
95
+ onChange: L("max-height"),
91
96
  type: "metric"
92
97
  })]
93
98
  }),
94
- /* @__PURE__ */ f(i, { children: /* @__PURE__ */ p(r, {
99
+ /* @__PURE__ */ p(i, { children: /* @__PURE__ */ m(r, {
95
100
  label: "",
96
- children: [/* @__PURE__ */ f(n, {
101
+ children: [/* @__PURE__ */ p(n, {
97
102
  keys: ["aspect-ratio"],
98
103
  label: "Ratio",
99
- value: O,
100
- onChange: P("aspect-ratio")
101
- }), /* @__PURE__ */ p(n, {
104
+ value: k,
105
+ onChange: L("aspect-ratio")
106
+ }), /* @__PURE__ */ m(n, {
102
107
  keys: ["box-sizing"],
103
108
  label: "Box Sizing",
104
- value: k,
105
- onChange: P("box-sizing"),
109
+ value: A,
110
+ onChange: L("box-sizing"),
106
111
  type: "select",
107
- children: [/* @__PURE__ */ f("option", {
112
+ children: [/* @__PURE__ */ p("option", {
108
113
  value: "border-box",
109
114
  children: "Border Box"
110
- }), /* @__PURE__ */ f("option", {
115
+ }), /* @__PURE__ */ p("option", {
111
116
  value: "content-box",
112
117
  children: "Content Box"
113
118
  })]
114
119
  })]
115
120
  }) }),
116
- /* @__PURE__ */ f(s, {
117
- value: A,
118
- onChange: P
119
- }),
120
- /* @__PURE__ */ p(i, { children: [/* @__PURE__ */ f(c, {
121
+ /* @__PURE__ */ p(c, {
121
122
  value: j,
122
- onChange: P
123
- }), /* @__PURE__ */ f(o, {
124
- value: M,
125
- onChange: P
126
- })] })
123
+ onChange: L
124
+ }),
125
+ /* @__PURE__ */ m(i, { children: [
126
+ /* @__PURE__ */ p(l, {
127
+ value: M,
128
+ onChange: L
129
+ }),
130
+ /* @__PURE__ */ p(s, {
131
+ value: N,
132
+ onChange: L
133
+ }),
134
+ /* @__PURE__ */ p(o, {
135
+ containerType: P,
136
+ containerName: F,
137
+ onChange: L
138
+ })
139
+ ] })
127
140
  ]
128
141
  });
129
142
  });
130
143
  //#endregion
131
- export { y as default };
144
+ export { b as default };
@@ -0,0 +1,12 @@
1
+ import { StyleCategory, StyleValue } from '@plitzi/sdk-shared';
2
+ export type SizeContainerProps = {
3
+ containerType?: StyleValue;
4
+ containerName?: StyleValue;
5
+ onChange?: (type: StyleCategory) => (value: StyleValue | Record<StyleCategory, StyleValue> | boolean) => void;
6
+ };
7
+ /**
8
+ * Whether the element is a container its children measure themselves against — a container query, the `cqw` units —
9
+ * by its width (`inline-size`) or both sides (`size`), and the name a query asks for it by.
10
+ */
11
+ declare const SizeContainer: ({ containerType, containerName, onChange }: SizeContainerProps) => import('react').JSX.Element;
12
+ export default SizeContainer;
@@ -0,0 +1,36 @@
1
+ import e from "../../components/CategoryOption/index.mjs";
2
+ import t from "../../components/CategorySection/index.mjs";
3
+ import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
+ //#region src/components/StyleInspector/categories/Size/SizeContainer.tsx
5
+ var i = ({ containerType: i, containerName: a, onChange: o }) => /* @__PURE__ */ r(t, {
6
+ label: "",
7
+ children: [/* @__PURE__ */ r(e, {
8
+ keys: ["container-type"],
9
+ label: "Container",
10
+ value: i,
11
+ onChange: o?.("container-type"),
12
+ type: "select",
13
+ children: [
14
+ /* @__PURE__ */ n("option", {
15
+ value: "normal",
16
+ children: "None"
17
+ }),
18
+ /* @__PURE__ */ n("option", {
19
+ value: "inline-size",
20
+ children: "Width"
21
+ }),
22
+ /* @__PURE__ */ n("option", {
23
+ value: "size",
24
+ children: "Width and height"
25
+ })
26
+ ]
27
+ }), /* @__PURE__ */ n(e, {
28
+ keys: ["container-name"],
29
+ label: "Container name",
30
+ value: a,
31
+ onChange: o?.("container-name"),
32
+ type: "input"
33
+ })]
34
+ });
35
+ //#endregion
36
+ export { i as default };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plitzi/sdk-style",
3
- "version": "0.38.3",
3
+ "version": "0.38.5",
4
4
  "license": "AGPL-3.0",
5
5
  "files": [
6
6
  "dist"
@@ -594,6 +594,10 @@
594
594
  "types": "./dist/components/StyleInspector/categories/Size/Size.d.ts",
595
595
  "import": "./dist/components/StyleInspector/categories/Size/Size.mjs"
596
596
  },
597
+ "./components/StyleInspector/categories/Size/SizeContainer": {
598
+ "types": "./dist/components/StyleInspector/categories/Size/SizeContainer.d.ts",
599
+ "import": "./dist/components/StyleInspector/categories/Size/SizeContainer.mjs"
600
+ },
597
601
  "./components/StyleInspector/categories/Size/SizeFit": {
598
602
  "types": "./dist/components/StyleInspector/categories/Size/SizeFit.d.ts",
599
603
  "import": "./dist/components/StyleInspector/categories/Size/SizeFit.mjs"
@@ -940,19 +944,22 @@
940
944
  "build:prod": "vite build && node ../sdk-shared/scripts/generate-exports.mjs"
941
945
  },
942
946
  "dependencies": {
943
- "@plitzi/plitzi-ui": "^1.6.29",
944
- "@plitzi/sdk-plugins": "0.38.3",
945
- "@plitzi/sdk-shared": "0.38.3",
946
- "@plitzi/sdk-variables": "0.38.3",
947
+ "@plitzi/plitzi-ui": "^1.6.31",
948
+ "@plitzi/sdk-event-bridge": "0.38.5",
949
+ "@plitzi/sdk-shared": "0.38.5",
950
+ "@plitzi/sdk-variables": "0.38.5",
947
951
  "clsx": "^2.1.1",
948
952
  "immer": "^11.1.21",
949
- "prop-types": "^15.8.1",
950
953
  "zod": "^4.6.5"
951
954
  },
952
955
  "devDependencies": {
953
956
  "eslint": "^9.39.5",
957
+ "react": "^19.3.0",
954
958
  "typescript": "^6.0.3",
955
959
  "vite": "^8.3.2",
956
960
  "vitest": "^5.0.3"
961
+ },
962
+ "peerDependencies": {
963
+ "react": "^19"
957
964
  }
958
965
  }