Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changeset/11441-retire-nav-responsive-grid-layout.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ Migration, measured against `objectui validate` on both of its faces:
- `basePath` has no app-document spelling: the strict face refuses it as an unrecognized key. It belongs to the shell, as `AppSchemaRenderer`'s `basePath` prop.

**Clause-②: yes** — two registrations leave the runtime (narrowing), released as `minor` with this banner.

⚠️ **Dated note, 2026-10-02 — `grid` takes one of ten `gap` steps, not any number — objectui#11474.** At this change `grid` accepted any `gap` number; now it accepts one of 0, 1, 2, 3, 4, 5, 6, 8, 10 and 12, the steps the `grid` renderer maps, and `objectui validate` refuses any other `G` at `gap` on both faces with that set named: 7, 9, 11, a number above 12, a negative number or a fraction. For such a number `grid` drew no gap anyway, because the class it built at runtime is in no compiled stylesheet. So in the migration above `G` must be one of those ten steps; each step `ResponsiveGrid`'s own class map drew (0 to 6 and 8) is one of them. `.changeset/11474-layout-spacing-sets.md` states what ships. The rest of this entry is kept as the reading of this change.
42 changes: 42 additions & 0 deletions .changeset/11474-layout-spacing-sets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
'@object-ui/types': minor
'@object-ui/components': minor
'@object-ui/core': minor
---

The `gap` of a `stack`, a `flex` and a `grid` node is one of the steps its renderer maps.
Any other number is refused at validation, with the set named (objectui#11474).

| node | accepted `gap` steps | default |
|---|---|---|
| `stack` | 0, 1, 2, 3, 4, 5, 6, 8, 10 | 2 |
| `flex` | 0, 1, 2, 3, 4, 5, 6, 7, 8 | 2 |
| `grid` | 0, 1, 2, 3, 4, 5, 6, 8, 10, 12 | 4 |

**Breaking for a `stack`, `flex` or `grid` that carries any other `gap` number.** The key
was declared as any number, and the `flex` and `grid` descriptions advertised "Tailwind
scale 0-8". But each renderer has one gap class per step and nothing for the rest:
`{ "type": "stack", "gap": 7 }` and `{ "type": "flex", "properties": { "gap": 9 } }` parsed
clean and rendered with no gap class at all, not even the default, because the default
applies only when the key is absent. A `grid` built a gap class at runtime for such a
number, and no compiled stylesheet defines a class built that way, so it rendered with no
gap either.

- `@object-ui/types`: `StackSchema.gap`, `FlexLayoutProps.gap` (which `FlexSchema` and the
authored `flex` bag share) and `GridSchema.gap` are literal unions of the steps above on
the TypeScript face, so `tsc` refuses any other number. The zod mirrors refuse one at the
key (`invalid_value`, with the steps in the issue), with a message that lists the set. For
`flex` that is `properties.gap`, and the flat spelling stays refused by name.
`safeValidateSchema` (what `objectui validate` runs) and the strict authoring face both
give that refusal. A `gap` that is not a number at all is now reported as `invalid_value`
rather than `invalid_type`.
- `@object-ui/components`: the `gap` input of the `stack`, `flex` and `grid` registrations
changes from `type: 'number'` to a closed `enum` of the same steps, in the object form the
`container` registration's `padding` already uses. In the SDUI manifest, `validateTree`
now answers an unlisted number with `invalid-enum`. The renderers are unchanged: they do
not round or clamp, and an absent key still renders the default step.
- `@object-ui/core`: `GridBuilder.gap()` and `FlexBuilder.gap()` take the declared steps
instead of any number.

Migration: replace the number with the step you meant from that node's set. `0` means no
gap.
14 changes: 14 additions & 0 deletions .changeset/6151-stack-schema-omit-collapse.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,17 @@ package's own tsconfig and asserts (1) `StackSchema` declares exactly what `Flex
declares, and (2) no member of the `LayoutSchema` union has lost any of `BaseSchema`'s
named members — so the next heritage clause that collapses under the index signature reds
for the whole class, not just for this one interface.

⚠️ **Dated note, 2026-10-02 — `StackSchema` declares its own `gap` — objectui#11474.**
At this change `gap` was a `number` member of `FlexLayoutProps`, declared once and inherited by
`FlexSchema` and `StackSchema` alike, and `stack.tsx` was read as feeding it to a Tailwind
numeric scale; now each node's `gap` is the closed set of steps its renderer maps.
`FlexLayoutProps.gap` is `0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8`, shared by `FlexSchema` and the
authored `flex` bag. `StackSchema` extends `BaseSchema` and `Omit<FlexLayoutProps, 'gap'>` and
declares its own `gap?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10`, the nine steps `stack.tsx` has a
gap class for. So `gap` is declared twice while the other members stay declared once, and `tsc`
refuses any other number on a `stack`, as it refuses `gap: 'large'`. That `Omit` crosses no
index signature (`FlexLayoutProps` carries none), so it erases no member name, and
`stack-schema-emitted-members.test.ts`, which measures the emitted declaration, still passes.
`.changeset/11474-layout-spacing-sets.md` states what ships. The rest of this entry is kept as
the reading of this change.
7 changes: 6 additions & 1 deletion content/docs/components/layout/flex.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ interface FlexNode {
className?: string;
properties?: {
direction?: 'row' | 'col' | 'row-reverse' | 'col-reverse';
gap?: number;
gap?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8; // default: 2
align?: 'start' | 'end' | 'center' | 'baseline' | 'stretch';
justify?: 'start' | 'end' | 'center' | 'between' | 'around' | 'evenly';
wrap?: boolean;
Expand All @@ -52,3 +52,8 @@ interface FlexNode {
Nothing changes at render time: `SchemaRenderer` hoists every `properties` key onto the node
before the `flex` renderer reads it, so a stored node that still writes these props flat keeps
rendering.

`gap` is a step on the flex spacing scale, 0 to 8, and `0` means none. Those are the steps the
renderer maps to a gap class, so they are the only values validation accepts:
`"properties": { "gap": 9 }` is refused with the set named (objectui#11474). Such a number
used to pass validation and then render with no gap at all, not even the default.
8 changes: 7 additions & 1 deletion content/docs/components/layout/grid.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,14 @@ import type { SchemaNode } from '@object-ui/types';
interface GridSchema {
type: 'grid';
columns?: number;
gap?: number;
gap?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | 12; // default: 4
children: SchemaNode[];
className?: string;
}
```

`gap` is a step on the grid's spacing scale, and `0` means none. The ten steps are the ones
the renderer maps to a gap class, so they are the only values validation accepts: `"gap": 9`
or `"gap": 16` is refused with the set named (objectui#11474). For such a number the renderer
used to build a gap class at runtime that no compiled stylesheet defines, so the grid rendered
with no gap at all.
8 changes: 7 additions & 1 deletion content/docs/components/layout/stack.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,14 @@ import type { SchemaNode } from '@object-ui/types';

interface StackSchema {
type: 'stack';
gap?: number;
gap?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 8 | 10; // default: 2
children: SchemaNode[];
className?: string;
}
```

`gap` is a step on the stack's spacing scale, and `0` means none. The nine steps are the
ones the renderer maps to a gap class, so they are the only values validation accepts:
`"gap": 7` or `"gap": 9` is refused with the set named (objectui#11474). Such a number used
to pass validation and then render with no gap at all, not even the default. A `flex` maps a
different set: it has `7` and no `10`.

This file was deleted.

Loading
Loading