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
17 changes: 17 additions & 0 deletions .changeset/23710-liveness-print-flow-messages.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
'@objectstack/spec': patch
---

fix(spec): a page that declares `print` is no longer warned that nothing applies it, and the flow terminal-toast translations read `live` (#23710)

Clause-②: no

**What was wrong.** The console now prints a page that declares `print`: its `PageRenderer` mounts a print stylesheet built from every key of the declaration (paper size and orientation, the four margins, the running header and footer, page numbers, and the two page-break hints). But the liveness ledger shipped with `@objectstack/spec` still graded `page.print` `planned` with an author warning, so `os validate` / `os build` / `os lint` told every author of a print page that printing it prints the screen layout. The `print` describes said the same ("until it ships, nothing applies it").

**What changes.**

- `liveness/page.json`: `print`, its eight keys and the four `margins` sides read `live`, citing the console reader at the `.objectui-sha` pin. The container's `authorWarn` / `authorHint` are dropped, so `lintLivenessProperties` no longer emits `liveness-planned-property` for a page that declares `print`.
- `liveness/translation.json`: `flows.successMessage` and `flows.errorMessage` read `live`. The console's flow runner shows the translated terminal toast through `translateFlow` and falls back to the flow's own text when the bundle has none.
- `PagePrintSchema` and `PageSchema.print`: the describes name the console's browser print rendering as the consumer that applies each key. The server-side PDF renderer is still to come.

Unchanged: what a `print` declaration accepts and refuses, and every other ledger row.
34 changes: 17 additions & 17 deletions content/docs/references/ui/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ View filter rule
| **assignedProfiles** | `never` | optional | [REMOVED] `page.assignedProfiles` was removed in @objectstack/spec 17.5.0 (ADR-0090 D2, ADR-0049 enforce-or-remove) — it was named for the Profile concept ADR-0090 D2 deleted, and it gated nothing: no renderer, route or metadata read door ever read the key, so a page that "assigned profiles" stayed open to every caller who could reach it. Delete the key. Page audience is the permission set's: gate the DATA the page shows with the object's permission sets, and bind those sets to people through positions (named in a position's `permissionSets`) — those are the checks the runtime actually runs. Run `os migrate meta --from 17` to list the mechanical edits for existing sources; `--write` applies the ones it can prove, and you apply the rest by hand. |
| **interfaceConfig** | `{ source?: string; columns?: string[] \| object[]; sort?: object[]; filterBy?: object[]; … }` | optional | Interface-level page configuration (for Airtable-style interface pages) |
| **aria** | `{ ariaLabel?: string \| Record<string, string>; ariaDescribedBy?: string; role?: string }` | optional | ARIA accessibility attributes |
| **print** | `{ paperSize?: Enum<'A4' \| 'A5' \| 'Letter' \| 'Legal'>; orientation?: Enum<'portrait' \| 'landscape'>; margins?: object; repeatHeader?: boolean; … }` | optional | Print declaration — makes this page a print page, a document authored in the page's own blocks: paper size and orientation, margins in millimetres, the running header and footer (the page's own `header` / `footer` regions), page numbers and page-break hints, each mapped to print CSS. A print page is a `kind: 'full'` page of `type: 'record'`, `'home'` or `'app'` with its blocks in `regions`, and every block in it must come from the printable block subset: containers that draw every child (`page:section`, `page:card`, `page:footer`), field blocks (`record:details`, `record:highlights`), the child-record table `record:line_items`, `element:text`, `element:image`, `element:divider`, `element:definition-list`, `element:repeater`, `element:number` and `object-metric`; `os validate` / `os build` / `os lint` and the metadata save door refuse any other block inside it. Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, the declaration is validated but nothing applies it. A list view's print button is `allowPrinting`, not this. |
| **print** | `{ paperSize?: Enum<'A4' \| 'A5' \| 'Letter' \| 'Legal'>; orientation?: Enum<'portrait' \| 'landscape'>; margins?: object; repeatHeader?: boolean; … }` | optional | Print declaration — makes this page a print page, a document authored in the page's own blocks: paper size and orientation, margins in millimetres, the running header and footer (the page's own `header` / `footer` regions), page numbers and page-break hints, each mapped to print CSS. A print page is a `kind: 'full'` page of `type: 'record'`, `'home'` or `'app'` with its blocks in `regions`, and every block in it must come from the printable block subset: containers that draw every child (`page:section`, `page:card`, `page:footer`), field blocks (`record:details`, `record:highlights`), the child-record table `record:line_items`, `element:text`, `element:image`, `element:divider`, `element:definition-list`, `element:repeater`, `element:number` and `object-metric`; `os validate` / `os build` / `os lint` and the metadata save door refuse any other block inside it. Applied by the console's browser print rendering, which prints the page through the browser's own print dialog (where it can be saved as PDF); the server-side PDF renderer is to follow. A list view's print button is `allowPrinting`, not this. |
| **kind** | `Enum<'full' \| 'slotted' \| 'html' \| 'react'>` | optional (default: `"full"`) | Page override mode. full \| slotted = structured authoring; html = author-written constrained JSX compiled (parsed, never executed) to the tree (ADR-0080; ADR-0081 named it html), styled by the registered components' structured props plus a JSON `style` object with hsl(var(--token)) theme colors; react = real-React source executed at render by the runtime (ADR-0081), styled by inline `style` with the same token colors; it runs author JS, so it is gated by a host capability that defaults ON and is disabled server-side via the OS_PAGE_REACT=off env toggle. Do not author Tailwind classes in page source in either tier: `source` is runtime metadata the build-time Tailwind never scans, so utility classNames silently produce no CSS (ADR-0065; ADR-0080). |
| **slots** | `{ header?: object \| object[]; actions?: object \| object[]; alerts?: object \| object[]; highlights?: object \| object[]; … }` | optional | Slot override map for slotted pages |
| **source** | `string` | optional | Page source text. For kind==='html' it is constrained JSX compiled to the tree by @objectstack/sdui-parser at save time (parse, never execute), styled by the registered components' structured props plus a JSON `style` object with hsl(var(--token)) theme colors. For kind==='react' it is real React/JSX executed at render by @object-ui/react-runtime (trusted tier), styled by inline `style` with the same token colors. Do not author Tailwind classes in page source in either tier: `source` is runtime metadata the build-time Tailwind never scans, so utility classNames silently produce no CSS (ADR-0065; ADR-0080). Authoritative over `regions` in both. |
Expand Down Expand Up @@ -275,14 +275,14 @@ View filter rule

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **paperSize** | `Enum<'A4' \| 'A5' \| 'Letter' \| 'Legal'>` | optional | Paper size — the size keyword of the print CSS `@page { size }` rule (A4 when omitted). Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, nothing applies it. |
| **orientation** | `Enum<'portrait' \| 'landscape'>` | optional | Sheet orientation — the orientation keyword of the `@page { size }` rule (portrait when omitted). Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, nothing applies it. |
| **margins** | `{ top?: number; right?: number; bottom?: number; left?: number }` | optional | Sheet margins in MILLIMETRES, one number per side — the `@page { margin }` rule; a side left out takes the renderer's default. Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, nothing applies it. |
| **repeatHeader** | `boolean` | optional | Repeat the page's `header` region (its `regions` entry named `header`) at the top of every printed sheet — the running header. The parse refuses it on a page with no `header` region. Off when omitted: the region prints once, at the top of the first sheet. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **repeatFooter** | `boolean` | optional | Repeat the page's `footer` region (its `regions` entry named `footer`) at the bottom of every printed sheet — the running footer. The parse refuses it on a page with no `footer` region. Off when omitted: the region prints once, after the body. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **pageNumbers** | `boolean` | optional | Print the sheet number and the sheet count in the bottom margin of every sheet — the `@page` margin box with `counter(page)` and `counter(pages)`. Off when omitted. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **repeatTableHeaders** | `boolean` | optional | Page-break hint: repeat a table's column headings at the top of every sheet the table runs onto (`thead { display: table-header-group }`). On when omitted. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **avoidBreakInside** | `boolean` | optional | Page-break hint: keep each block whole on one sheet when it fits, moving it to the next sheet instead of splitting it (`break-inside: avoid` on every block). Off when omitted. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **paperSize** | `Enum<'A4' \| 'A5' \| 'Letter' \| 'Legal'>` | optional | Paper size — the size keyword of the print CSS `@page { size }` rule (A4 when omitted). Applied by the console's browser print rendering; the server-side PDF renderer is to follow. |
| **orientation** | `Enum<'portrait' \| 'landscape'>` | optional | Sheet orientation — the orientation keyword of the `@page { size }` rule (portrait when omitted). Applied by the console's browser print rendering; the server-side PDF renderer is to follow. |
| **margins** | `{ top?: number; right?: number; bottom?: number; left?: number }` | optional | Sheet margins in MILLIMETRES, one number per side — the `@page { margin }` rule; a side left out takes the renderer's default. Applied by the console's browser print rendering; the server-side PDF renderer is to follow. |
| **repeatHeader** | `boolean` | optional | Repeat the page's `header` region (its `regions` entry named `header`) at the top of every printed sheet — the running header. The parse refuses it on a page with no `header` region. Off when omitted: the region prints once, at the top of the first sheet. Applied by the console's browser print rendering. |
| **repeatFooter** | `boolean` | optional | Repeat the page's `footer` region (its `regions` entry named `footer`) at the bottom of every printed sheet — the running footer. The parse refuses it on a page with no `footer` region. Off when omitted: the region prints once, after the body. Applied by the console's browser print rendering. |
| **pageNumbers** | `boolean` | optional | Print the sheet number and the sheet count in the bottom margin of every sheet — the `@page` margin box with `counter(page)` and `counter(pages)`. Off when omitted. Applied by the console's browser print rendering. |
| **repeatTableHeaders** | `boolean` | optional | Page-break hint: repeat a table's column headings at the top of every sheet the table runs onto (`thead { display: table-header-group }`). On when omitted. Applied by the console's browser print rendering. |
| **avoidBreakInside** | `boolean` | optional | Page-break hint: keep each block whole on one sheet when it fits, moving it to the next sheet instead of splitting it (`break-inside: avoid` on every block). Off when omitted. Applied by the console's browser print rendering. |


---
Expand Down Expand Up @@ -397,14 +397,14 @@ Print declaration: paper size, orientation, margins, the running header and foot

| Property | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| **paperSize** | `Enum<'A4' \| 'A5' \| 'Letter' \| 'Legal'>` | optional | Paper size — the size keyword of the print CSS `@page { size }` rule (A4 when omitted). Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, nothing applies it. |
| **orientation** | `Enum<'portrait' \| 'landscape'>` | optional | Sheet orientation — the orientation keyword of the `@page { size }` rule (portrait when omitted). Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, nothing applies it. |
| **margins** | `{ top?: number; right?: number; bottom?: number; left?: number }` | optional | Sheet margins in MILLIMETRES, one number per side — the `@page { margin }` rule; a side left out takes the renderer's default. Consumer: the console's browser print rendering, and later the server-side PDF renderer; until it ships, nothing applies it. |
| **repeatHeader** | `boolean` | optional | Repeat the page's `header` region (its `regions` entry named `header`) at the top of every printed sheet — the running header. The parse refuses it on a page with no `header` region. Off when omitted: the region prints once, at the top of the first sheet. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **repeatFooter** | `boolean` | optional | Repeat the page's `footer` region (its `regions` entry named `footer`) at the bottom of every printed sheet — the running footer. The parse refuses it on a page with no `footer` region. Off when omitted: the region prints once, after the body. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **pageNumbers** | `boolean` | optional | Print the sheet number and the sheet count in the bottom margin of every sheet — the `@page` margin box with `counter(page)` and `counter(pages)`. Off when omitted. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **repeatTableHeaders** | `boolean` | optional | Page-break hint: repeat a table's column headings at the top of every sheet the table runs onto (`thead { display: table-header-group }`). On when omitted. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **avoidBreakInside** | `boolean` | optional | Page-break hint: keep each block whole on one sheet when it fits, moving it to the next sheet instead of splitting it (`break-inside: avoid` on every block). Off when omitted. Consumer: the console's browser print rendering; until it ships, nothing applies it. |
| **paperSize** | `Enum<'A4' \| 'A5' \| 'Letter' \| 'Legal'>` | optional | Paper size — the size keyword of the print CSS `@page { size }` rule (A4 when omitted). Applied by the console's browser print rendering; the server-side PDF renderer is to follow. |
| **orientation** | `Enum<'portrait' \| 'landscape'>` | optional | Sheet orientation — the orientation keyword of the `@page { size }` rule (portrait when omitted). Applied by the console's browser print rendering; the server-side PDF renderer is to follow. |
| **margins** | `{ top?: number; right?: number; bottom?: number; left?: number }` | optional | Sheet margins in MILLIMETRES, one number per side — the `@page { margin }` rule; a side left out takes the renderer's default. Applied by the console's browser print rendering; the server-side PDF renderer is to follow. |
| **repeatHeader** | `boolean` | optional | Repeat the page's `header` region (its `regions` entry named `header`) at the top of every printed sheet — the running header. The parse refuses it on a page with no `header` region. Off when omitted: the region prints once, at the top of the first sheet. Applied by the console's browser print rendering. |
| **repeatFooter** | `boolean` | optional | Repeat the page's `footer` region (its `regions` entry named `footer`) at the bottom of every printed sheet — the running footer. The parse refuses it on a page with no `footer` region. Off when omitted: the region prints once, after the body. Applied by the console's browser print rendering. |
| **pageNumbers** | `boolean` | optional | Print the sheet number and the sheet count in the bottom margin of every sheet — the `@page` margin box with `counter(page)` and `counter(pages)`. Off when omitted. Applied by the console's browser print rendering. |
| **repeatTableHeaders** | `boolean` | optional | Page-break hint: repeat a table's column headings at the top of every sheet the table runs onto (`thead { display: table-header-group }`). On when omitted. Applied by the console's browser print rendering. |
| **avoidBreakInside** | `boolean` | optional | Page-break hint: keep each block whole on one sheet when it fits, moving it to the next sheet instead of splitting it (`break-inside: avoid` on every block). Off when omitted. Applied by the console's browser print rendering. |

### Nested Shape: `PagePrint.margins`

Expand Down
Loading
Loading