SpringML elements
The SpringML elements, their props, helpers, handles and refusals, as JSON generated from ELEMENTS (@canonify/spring-schema).
{
"name": "Spring UI",
"version": "3.4",
"counts": {
"template": 2,
"component": 33,
"part": 22,
"data": 5,
"total": 62
},
"elements": {
"Page": {
"kind": "template",
"summary": "A screen. Data elements first, then content; Action children are header verbs.",
"parents": [],
"children": [
"Query",
"Record",
"Aggregate",
"State",
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form",
"Action",
"Empty"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "title",
"type": "text|element",
"required": true,
"meaning": "the page title; text, an expression or a record (its title)",
"elements": [
"Text",
"Value"
]
},
{
"name": "subtitle",
"type": "text|element",
"required": false,
"meaning": "the author's line under the title (e.g. the order of the queue)",
"elements": [
"Text",
"Value"
]
},
{
"name": "lead",
"type": "ref:Query|list:ref:Query",
"required": false,
"meaning": "the collection(s) that drive the header summary and the nav badge; required when the page has more than one Query; a list sums the attention of each (\"2 over · 3 unassigned\"). The count is in the type's noun (\"23 events\"), or, when the lead's `where` (or its active Preset) keeps only rows holding a named condition that names a count (both `label` and `labelOne`), in that noun (`where={i => i.is_overdue}` with label \"overdue instalments\" → \"14 overdue instalments\", `labelOne` for 1); a condition with a `label` alone (\"Live\") is a tag and leaves the type's noun; a lead whose `where` holds two such conditions is refused (`lead_noun_ambiguous`): declare one condition that is both, with the noun the count reads in; a lead whose `where` keeps rows of a condition that names no count compiles with a warning (`lead_noun_missing`) — declare its `label` and `labelOne` (\"overdue instalments\" / \"overdue instalment\"), or the header counts those rows in the type's noun as if they were all of them"
},
{
"name": "params",
"type": "object",
"required": false,
"meaning": "the view's parameters and their types: {event: \"event\"}; param() reads them"
},
{
"name": "audience",
"type": "list:group",
"required": false,
"meaning": "groups that may open this view (checked against the org's groups); others do not see it in nav or links (reads stay policy-checked)"
},
{
"name": "navLabel",
"type": "text",
"required": false,
"meaning": "the page's name in the app's nav, breadcrumb and Home (literal text); default: the title when it is text, else the view name's last part (`Sales.dashboard` → \"Dashboard\"). A reader who sees two nav entries with the same name sees each followed by its audience (\"Dashboard · Sales\"), else its page name"
},
{
"name": "icon",
"type": "text",
"required": false,
"meaning": "the page's glyph in the app's nav (literal text): a kebab-case Lucide name from the platform's pinned set (lucide.dev/icons), e.g. \"banknote\". Default, by what the page is: a RecordPage \"file-text\"; else the first the page holds of Board \"kanban\", Timeline \"chart-gantt\", DayGrid \"calendar-days\", Matrix \"calendar-range\", Form \"square-pen\", Compare \"file-diff\", Files \"paperclip\", Chart \"chart-column\", Table or List \"list\"; else \"layout-dashboard\". Give each nav page its own"
}
]
},
"RecordPage": {
"kind": "template",
"summary": "A record's screen. Reads param(\"id\"); the record is in scope as `record`; Action children are record header verbs.",
"parents": [],
"children": [
"Query",
"Record",
"Aggregate",
"State",
"Meta",
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form",
"Action",
"Empty"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "type",
"type": "name:type",
"required": true,
"meaning": "the record's type"
},
{
"name": "subtitle",
"type": "text|element",
"required": false,
"meaning": "",
"elements": [
"Text",
"Value"
]
},
{
"name": "lead",
"type": "ref:Query",
"required": false,
"meaning": ""
},
{
"name": "audience",
"type": "list:group",
"required": false,
"meaning": ""
},
{
"name": "icon",
"type": "text",
"required": false,
"meaning": "the page's glyph in the app's nav (literal text): a kebab-case Lucide name from the platform's pinned set (lucide.dev/icons), e.g. \"banknote\". Default, by what the page is: a RecordPage \"file-text\"; else the first the page holds of Board \"kanban\", Timeline \"chart-gantt\", DayGrid \"calendar-days\", Matrix \"calendar-range\", Form \"square-pen\", Compare \"file-diff\", Files \"paperclip\", Chart \"chart-column\", Table or List \"list\"; else \"layout-dashboard\". Give each nav page its own"
}
]
},
"Query": {
"kind": "data",
"summary": "The collection: a declared slice of one type plus the reader's working state (preset, facets, search, sort, page, selection). Served by one server batch.",
"parents": [
"Page",
"RecordPage",
"Section"
],
"children": [
"Preset",
"Flag"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {
"Section": {
"requiresAncestor": [
"Expand"
]
}
},
"props": [
{
"name": "id",
"type": "id",
"required": true,
"meaning": "the name in expressions; may not shadow a helper or scope name"
},
{
"name": "type",
"type": "name:type",
"required": true,
"meaning": ""
},
{
"name": "where",
"type": "predicate",
"required": false,
"meaning": "thin narrowing (§B6.1)"
},
{
"name": "sort",
"type": "field|list:field",
"required": false,
"meaning": "\"due_on\", \"-version\" or a list; own or 1-hop fields; a link sorts by its target's title; an enum by its declared values; a named condition sorts true first with \"-\" (\"-is_full\"); blanks always last"
},
{
"name": "page",
"type": "number",
"required": false,
"meaning": "rows per page (≤ 200); 0 = unpaged (≤ 500). A Query a Timeline, DayGrid, Span or Matrix draws takes no page: those have no pager and read it whole over what they show (≤ 500 rows, then \"Showing 500 of N\")",
"default": 25
},
{
"name": "search",
"type": "list:field|boolean",
"required": false,
"meaning": "own or 1-hop text fields; default the type's searchable; false turns Search off"
},
{
"name": "facets",
"type": "list:field",
"required": false,
"meaning": "≤ 3 enum, set<enum> or link fields shown as facet chips"
},
{
"name": "current",
"type": "predicate",
"required": false,
"meaning": "the first row in sort order that matches and carries no critical condition is the current (\"→ Next\") row"
},
{
"name": "nameBy",
"type": "field",
"required": false,
"meaning": "the field that names a row in the queue header (\"late: 07:15 SR-14\"), e.g. the vehicle; default the title, or the eyebrow when the title is longer than 24 characters"
}
]
},
"Preset": {
"kind": "part",
"summary": "A saved view of the collection; Filters shows it as a chip with its live count.",
"parents": [
"Query"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "id",
"type": "id",
"required": true,
"meaning": ""
},
{
"name": "label",
"type": "text",
"required": true,
"meaning": ""
},
{
"name": "where",
"type": "predicate",
"required": false,
"meaning": "no where = all rows"
},
{
"name": "default",
"type": "boolean",
"required": false,
"meaning": "at most one; none = the first Preset",
"default": false
},
{
"name": "short",
"type": "text",
"required": false,
"meaning": "the chip label at phone width (\"Due 14 d\"); a chip never clips its label"
},
{
"name": "verbs",
"type": "enum",
"required": false,
"meaning": "the collection's verbs mode while this preset is active (\"Ready to issue\" → job, \"Overdue\" → flag)",
"enum": [
"flag",
"job",
"menu"
]
}
]
},
"Flag": {
"kind": "part",
"summary": "Marks rows that need attention, from a named condition of the row type.",
"parents": [
"Query"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "condition",
"type": "name:condition",
"required": true,
"meaning": "a named condition (Part A PA-3); meaning, level, on, amount and label come from the model"
}
]
},
"Record": {
"kind": "data",
"summary": "One record by key.",
"parents": [
"Page",
"RecordPage"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "id",
"type": "id",
"required": true,
"meaning": ""
},
{
"name": "type",
"type": "name:type",
"required": true,
"meaning": ""
},
{
"name": "key",
"type": "expr",
"required": true,
"meaning": "the record's key: param(\"trip\"), another Record's link, or a date for a per-day type whose ids are dates; a type with prefixed ids (\"day_…\") is read by its date field with a Query and a State auto=\"single\" (a date key is refused)"
}
]
},
"Aggregate": {
"kind": "data",
"summary": "One grouped read, keyed; read with `.at()`.",
"parents": [
"Page",
"RecordPage"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "id",
"type": "id",
"required": true,
"meaning": ""
},
{
"name": "type",
"type": "name:type",
"required": false,
"meaning": "the type to aggregate; or use `of`"
},
{
"name": "of",
"type": "ref:Query",
"required": false,
"meaning": "inherit the Query's type and the rows it reads: its base where (incl. bound States) and the window the components drawing it show (a Matrix's columns, a Timeline's or DayGrid's range, a State's weekdays), never its page, preset or search; may only narrow — so a Stat of it agrees with the Matrix, Timeline or DayGrid that draws the Query"
},
{
"name": "op",
"type": "enum",
"required": true,
"meaning": "",
"enum": [
"count",
"sum",
"min",
"max",
"avg",
"list"
]
},
{
"name": "property",
"type": "field",
"required": false,
"meaning": "the measured field (sum/min/max/avg); for list: the link whose target records are listed — without it the aggregated rows themselves are listed (they are the popover records)"
},
{
"name": "by",
"type": "field|list:field",
"required": false,
"meaning": "≤ 2 keys: own or 1-hop fields; date keys may end in @day, @week, @month, @bucket; with span the day key is written `date`"
},
{
"name": "on",
"type": "field",
"required": false,
"meaning": "the date or timestamp that places a row on a day (default: the single date key)"
},
{
"name": "span",
"type": "list:field",
"required": false,
"meaning": "[start, end]: the row counts on every day it covers"
},
{
"name": "over",
"type": "expr",
"required": false,
"meaning": "a day series: days(week)"
},
{
"name": "window",
"type": "object",
"required": false,
"meaning": "{last: n} buckets for @week/@month keys"
},
{
"name": "where",
"type": "predicate",
"required": false,
"meaning": ""
},
{
"name": "facts",
"type": "list:field",
"required": false,
"meaning": "with op=list: ≤ 3 fields of each listed record (the rows, or the `property` targets), shown in the popover"
},
{
"name": "decimals",
"type": "number",
"required": false,
"meaning": "decimal places its numbers are written to (0–6), the word a number property's `scale: { decimals }` uses; default: the measure's declared decimals — an `avg` of a field that declares none to 1 place"
}
]
},
"State": {
"kind": "data",
"summary": "A value the reader chooses; kept in the URL under its id.",
"parents": [
"Page",
"RecordPage"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "id",
"type": "id",
"required": true,
"meaning": ""
},
{
"name": "type",
"type": "enum|name:type",
"required": true,
"meaning": "or an ObjectType name = a ref State",
"enum": [
"date",
"week",
"range",
"month",
"boolean",
"number",
"string",
"enum"
]
},
{
"name": "initial",
"type": "expr",
"required": false,
"meaning": "required for date/week/range/month; a range's is {from: <date>, days: <whole number>}, e.g. {{from: today(), days: 14}} (never {start, end}); wins over auto when not null"
},
{
"name": "options",
"type": "list:object",
"required": false,
"meaning": "enum States: [{value, label}]"
},
{
"name": "where",
"type": "predicate",
"required": false,
"meaning": "ref States without `from`: the choices"
},
{
"name": "sort",
"type": "field|list:field",
"required": false,
"meaning": "ref States without `from`; a link sorts by its target's title, as a Query's"
},
{
"name": "from",
"type": "ref:Query",
"required": false,
"meaning": "ref States: the choices are this Query's rows — its where, active preset, chosen facets and search, in its sort, never just its page — so the picker lists what the page lists; no where or sort of its own"
},
{
"name": "auto",
"type": "enum",
"required": false,
"meaning": "ref States: pick the only choice, the first/second in sort, or the `from` Query's current row. Without auto nothing is picked until the reader chooses (a filter State reads null as \"all\"): `from={upcoming} auto=\"first\"` opens on the first upcoming row",
"enum": [
"single",
"first",
"second",
"current"
]
},
{
"name": "weekdays",
"type": "list:string",
"required": false,
"meaning": "week/range States: the days shown, e.g. [\"mon\",…,\"sat\"]; default every day. days(week), a Matrix, a Timeline day axis, a week DayGrid and PeriodNav (its label and day strip) show only these"
}
]
},
"Preview": {
"kind": "data",
"summary": "The Form action's live preview outputs as `pv.<output>` (typed, policy-checked).",
"parents": [
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [
"Form"
],
"parentRules": {},
"props": [
{
"name": "id",
"type": "id",
"required": true,
"meaning": ""
}
]
},
"Section": {
"kind": "component",
"summary": "A titled region; a top-level Section is one card with its title in the header.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Expand",
"Form",
"Step"
],
"children": [
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form",
"Action",
"Empty",
"Query",
"Field",
"Lines",
"Step",
"Submit",
"Candidates"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "title",
"type": "text|element|expr",
"required": false,
"meaning": "text, or a record expression (its title)",
"elements": [
"Text",
"Value"
]
},
{
"name": "of",
"type": "expr",
"required": false,
"meaning": "the section's record: scope for verbs (incl. its Toolbar), default record of Facts; when null, a record title hides, components that read it render nothing and the Section's Empty speaks"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
},
{
"name": "audience",
"type": "list:group",
"required": false,
"meaning": "groups it is drawn for (checked against the org's groups); a reader in none of them is not served it at all — no title, no lock rows (owners and admins see every one); decided on the server, not a data boundary (reads stay policy-checked)"
}
]
},
"Split": {
"kind": "component",
"summary": "Main + aside, exactly two children; the aside is sticky at ≥ 1024 px when it holds a Form summary. In a Form, the side holding its inputs (Field, Lines, Step, Submit, Candidates) is sized by its fields and the result side takes the rest, in either order.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form",
"Field",
"Lines",
"Step",
"Submit",
"Candidates"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Columns": {
"kind": "component",
"summary": "2–4 different children side by side when the container is ≥ 960 px; stacked otherwise.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Grid": {
"kind": "component",
"summary": "Like items only: Stat or Files tiles; the tile count picks the tracks at every width — wide, 2–5 tiles one track each (3 tiles → 3, never 3 of 4), 6 → 3, 7 or more → 4; on phone 2 (3 for 3, 1 for 5 or 7) — so the first row has no empty track and no later row is an orphan; tiles never stretch; a withheld tile reflows the rest left.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Stat",
"Files"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Tabs": {
"kind": "component",
"summary": "A tool's views (a builder, an editor), or record sections you group yourself; a long RecordPage draws its sections as tabs on its own.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Tab"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Tab": {
"kind": "part",
"summary": "One tab.",
"parents": [
"Tabs"
],
"children": [
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form",
"Action",
"Empty",
"Field",
"Lines",
"Step",
"Submit",
"Candidates"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "label",
"type": "text",
"required": true,
"meaning": ""
},
{
"name": "lead",
"type": "ref:Query",
"required": false,
"meaning": "the collection whose total is the tab's count badge (default: the tab's first collection)"
},
{
"name": "audience",
"type": "list:group",
"required": false,
"meaning": "groups it is drawn for (checked against the org's groups); a reader in none of them is not served it at all — no title, no lock rows (owners and admins see every one); decided on the server, not a data boundary (reads stay policy-checked)"
}
]
},
"Toolbar": {
"kind": "component",
"summary": "Inputs and verbs for the page or a section (a Section's first child).",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Search",
"Filters",
"Control",
"PeriodNav",
"Action"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Value": {
"kind": "component",
"summary": "One field or typed expression, shown the one way its type and container show it.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Text",
"Badge",
"Callout",
"Empty",
"Cell",
"Form",
"Lines"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "expr",
"required": true,
"meaning": "a field, link, aggregate cell, list, handle or typed expression"
},
{
"name": "change",
"type": "boolean",
"required": false,
"meaning": "this is a difference: show the sign (+15) and the `better` tone",
"default": false
}
]
},
"Text": {
"kind": "component",
"summary": "Prose with inline values.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Cell",
"Form"
],
"children": [
"TEXT",
"Value",
"Link",
"Badge"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Badge": {
"kind": "component",
"summary": "A neutral mark with text (\"Rush\", \"Repeat\"); attention marks come from Flags, never from a Badge.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Text",
"Callout",
"Item",
"Form"
],
"children": [
"TEXT",
"Value"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Callout": {
"kind": "component",
"summary": "A note the author writes: info, or a warning about the screen's content (not a refusal, not a data exception).",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"TEXT",
"Value",
"Link",
"Badge"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "tone",
"type": "enum",
"required": false,
"meaning": "",
"default": "info",
"enum": [
"info",
"warn"
]
},
{
"name": "title",
"type": "text",
"required": false,
"meaning": ""
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Stat": {
"kind": "component",
"summary": "A KPI tile: label, value, optional delta, foot line and sparkline.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Grid",
"Tab",
"Form"
],
"children": [
"Ratio"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "label",
"type": "text",
"required": true,
"meaning": ""
},
{
"name": "value",
"type": "expr",
"required": false,
"meaning": "number, money or duration; or a Ratio child"
},
{
"name": "compare",
"type": "enum",
"required": false,
"meaning": "shifts the time key of the Aggregate in value; a period in progress is set against the same elapsed span of the earlier one (\"on 1–10 Nov\"); for the whole earlier period, show its total in a Ratio child instead",
"enum": [
"previous_period",
"same_period_last_year"
]
},
{
"name": "better",
"type": "enum",
"required": false,
"meaning": "default from the field's `better`",
"enum": [
"up",
"down"
]
},
{
"name": "context",
"type": "element",
"required": false,
"meaning": "the foot line",
"elements": [
"Text",
"Value"
]
},
{
"name": "trend",
"type": "ref:Aggregate",
"required": false,
"meaning": "keyed by time → sparkline"
},
{
"name": "decimals",
"type": "number",
"required": false,
"meaning": "decimal places a number value is written to (0–6), the word a number property's `scale: { decimals }` uses; default: its field's or Aggregate's decimals; a computed figure (`a.value * 100 / b.value`) that is not whole to 1 place, and arithmetic keeps the unit of its typed side"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Ratio": {
"kind": "component",
"summary": "\"assigned / needed\": the numerator in 600 ink, \"/ needed\" muted. Its tone comes from its two numbers, never from a prop: `of` is a whole (capacity), `need` a requirement.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Stat",
"Cell",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "value",
"type": "expr",
"required": true,
"meaning": ""
},
{
"name": "of",
"type": "expr",
"required": false,
"meaning": "the whole the value is a share of (capacity, available, total): over it is critical \"over by n\"; at or under it the pair is neutral; a literal (`of={2400}`) is in the value's unit (minutes: \"40 h\")"
},
{
"name": "need",
"type": "expr",
"required": false,
"meaning": "what is needed (staff per shift, coaches per trip): below it is short — critical \"short n\"; at it met — a check; above it over — warn \"over by n\"; a literal is in the value's unit"
},
{
"name": "remainder",
"type": "text",
"required": false,
"meaning": "with `need`: the words for what is still missing below it, after its count — `remainder=\"to check\"` reads \"26 / 35 · 9 to check\" where the default reads \"short 9\" (lines not yet checked are not short); literal text"
}
]
},
"Meter": {
"kind": "component",
"summary": "A bar with its number; tone from the field's `thresholds` (model), healthy = neutral ink.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "value",
"type": "expr",
"required": true,
"meaning": ""
},
{
"name": "of",
"type": "expr",
"required": true,
"meaning": ""
}
]
},
"Chart": {
"kind": "component",
"summary": "A chart by question; the platform picks bars/lines/stacking.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Series"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "shows",
"type": "enum",
"required": true,
"meaning": "",
"enum": [
"trend",
"composition",
"comparison",
"capacity"
]
},
{
"name": "limit",
"type": "expr",
"required": false,
"meaning": "capacity line"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Series": {
"kind": "part",
"summary": "One series of a Chart.",
"parents": [
"Chart"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Aggregate",
"required": true,
"meaning": ""
},
{
"name": "label",
"type": "text",
"required": true,
"meaning": ""
}
]
},
"Facts": {
"kind": "component",
"summary": "Key–value facts of a record.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Fact"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "expr",
"required": false,
"meaning": "the record (default: the nearest Section's `of`, else `record`); a link (record.space) carries the target's title only, so its Facts are refused: read it with a Record and name that"
}
]
},
"Fact": {
"kind": "part",
"summary": "One fact.",
"parents": [
"Facts",
"Meta"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "field",
"type": "field",
"required": false,
"meaning": "a field or link of the record"
},
{
"name": "value",
"type": "expr",
"required": false,
"meaning": ""
},
{
"name": "label",
"type": "text",
"required": false,
"meaning": "default from the field; required with value or span"
},
{
"name": "sub",
"type": "expr|element",
"required": false,
"meaning": "a grey line: \"in 3 days\"",
"elements": [
"Text",
"Value"
]
},
{
"name": "span",
"type": "list:field",
"required": false,
"meaning": "[start, end] dates, times or timestamps shown as one value \"07:00–19:30\""
}
]
},
"Meta": {
"kind": "part",
"summary": "≤ 6 Facts on one line under the record title.",
"parents": [
"RecordPage"
],
"children": [
"Fact"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Breakdown": {
"kind": "component",
"summary": "A money summary; lines in written order (it shows, it does not add).",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Line"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "expr",
"required": true,
"meaning": "a record or a Preview"
}
]
},
"Line": {
"kind": "part",
"summary": "One money line.",
"parents": [
"Breakdown"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "field",
"type": "field",
"required": false,
"meaning": ""
},
{
"name": "value",
"type": "expr",
"required": false,
"meaning": ""
},
{
"name": "label",
"type": "text",
"required": false,
"meaning": ""
},
{
"name": "kind",
"type": "enum",
"required": false,
"meaning": "subtotal = a ruled line (\"Net\"); total and due 16/700; credit = a credit note; minus = discounts, cuts, paid, shown with −; part = an \"of which\" line, indented, not part of the sum",
"enum": [
"subtotal",
"total",
"due",
"credit",
"minus",
"part"
]
},
{
"name": "each",
"type": "expr",
"required": false,
"meaning": "a keyed preview output (one line per key, labelled with the key and its base: \"VAT 13 % on €5,060.00\") or a to-many link of the record (one line per row: `field` = the row's money field, `label` = the row's label field); zero lines hidden"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"History": {
"kind": "component",
"summary": "A record's changes: its transitions and its history: true fields (PA-8), or a declared event log.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "expr",
"required": true,
"meaning": ""
},
{
"name": "fields",
"type": "list:field",
"required": false,
"meaning": "the type's opt-in history fields"
},
{
"name": "log",
"type": "field",
"required": false,
"meaning": "a to-many link of an event type to read instead of the transition log"
},
{
"name": "at",
"type": "field",
"required": false,
"meaning": "the event's date or timestamp",
"default": "at"
},
{
"name": "by",
"type": "field",
"required": false,
"meaning": "who: a field or a link (its record's title)",
"default": "by"
},
{
"name": "action",
"type": "field",
"required": false,
"meaning": "",
"default": "action"
},
{
"name": "note",
"type": "field",
"required": false,
"meaning": "",
"default": "note"
}
]
},
"Lifecycle": {
"kind": "component",
"summary": "Where a record is in its process: the machine's main path with dates; a taken branch replaces the rest of the path.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "expr",
"required": true,
"meaning": ""
}
]
},
"Table": {
"kind": "component",
"summary": "Aligned columns over a collection.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Column",
"Action",
"BulkAction",
"Group",
"Expand",
"Check",
"Empty"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query|ref:Aggregate|expr",
"required": true,
"meaning": "a Query, an Aggregate (one row per key) or a Preview array (pv.items)"
},
{
"name": "opens",
"type": "expr|string",
"required": false,
"meaning": "\"auto\" (the type's record view; rows of a type without one, Aggregate rows and preview rows do not open), a view name, a record expression (opens its view) or \"none\"",
"default": "auto"
},
{
"name": "picks",
"type": "ref:State",
"required": false,
"meaning": "a ref State of the row type: a row click sets it (master–detail); not drawn yet, refused at compile: choose the record with a Control on the ref State, or let the rows open their record (opens)"
},
{
"name": "verbs",
"type": "enum",
"required": false,
"meaning": "flag (default): a verb is visible only on rows whose flag it fixes (the condition's `fix`), as a bordered button; job: the first offered verb is the page's per-row job — a quiet text button (the action's `shortLabel`: \"Record\") on every eligible row, bordered on flagged rows; `rest` is a synonym of job; menu: every verb in ⋯. A queue (a Query with `current`, or a Check) defaults to job. A verb whose preCheck guard fails never shows at rest. ⋯ appears only when it holds a verb (opening the record is the title's job, not a menu item); a job column may show different verbs per row (the first offered differs by state); a create with no subject may be a row verb, its inputs filled from the row.",
"default": "flag",
"enum": [
"flag",
"job",
"rest",
"menu"
]
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Column": {
"kind": "part",
"summary": "One column.",
"parents": [
"Table"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "field",
"type": "field",
"required": false,
"meaning": "own field, 1-hop path, rollup, or a to-many path (a capped list of ≤ 3 linked titles + \"+N\")"
},
{
"name": "value",
"type": "fn",
"required": false,
"meaning": "a row function: r => …"
},
{
"name": "label",
"type": "text",
"required": false,
"meaning": "default from the field; required with value"
},
{
"name": "importance",
"type": "enum",
"required": false,
"meaning": "auto: first column primary, money and status secondary, the rest detail",
"default": "auto",
"enum": [
"auto",
"primary",
"eyebrow",
"secondary",
"detail"
]
},
{
"name": "total",
"type": "enum",
"required": false,
"meaning": "money/number fields; over the whole filtered set; nulls count as 0, \"—\" when every value is null",
"enum": [
"sum",
"count"
]
},
{
"name": "sort",
"type": "boolean",
"required": false,
"meaning": "default true for fields"
},
{
"name": "sortBy",
"type": "field",
"required": false,
"meaning": "with value: the field a value column sorts by"
},
{
"name": "sub",
"type": "fn",
"required": false,
"meaning": "a row function for a sub-line: r => …; a number or amount read from a field is written with that field's label (\"Staff needed 9\"), never bare — for assigned of needed write value={r => <Ratio value={r.assigned} need={r.needed} />}"
}
]
},
"List": {
"kind": "component",
"summary": "Free rows with the card anatomy (queues, run sheets).",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"FN",
"Action",
"Group",
"Check",
"Empty"
],
"fnReturns": [
"Item"
],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query|expr",
"required": true,
"meaning": "a Query or a Preview array"
},
{
"name": "opens",
"type": "expr|string",
"required": false,
"meaning": "\"auto\" (the type's record view; rows of a type without one, Aggregate rows and preview rows do not open), a view name, a record expression (opens its view) or \"none\"",
"default": "auto"
},
{
"name": "picks",
"type": "ref:State",
"required": false,
"meaning": "not drawn yet, refused at compile: choose the record with a Control on the ref State, or let the rows open their record (opens)"
},
{
"name": "verbs",
"type": "enum",
"required": false,
"meaning": "flag (default): a verb is visible only on rows whose flag it fixes (the condition's `fix`), as a bordered button; job: the first offered verb is the page's per-row job — a quiet text button (the action's `shortLabel`: \"Record\") on every eligible row, bordered on flagged rows; `rest` is a synonym of job; menu: every verb in ⋯. A queue (a Query with `current`, or a Check) defaults to job. A verb whose preCheck guard fails never shows at rest. ⋯ appears only when it holds a verb (opening the record is the title's job, not a menu item); a job column may show different verbs per row (the first offered differs by state); a create with no subject may be a row verb, its inputs filled from the row.",
"default": "flag",
"enum": [
"flag",
"job",
"rest",
"menu"
]
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Item": {
"kind": "part",
"summary": "The row/card template: eyebrow, title, ≤ 2 sub facts, value, ≤ 2 Badges after the title (a List row and a Board card; a Timeline bar and a DayGrid block draw its eyebrow, title, lead, sub, value and detail, no Badge); the status pill is automatic.",
"parents": [
"List",
"Board",
"Timeline",
"DayGrid"
],
"children": [
"Badge"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "title",
"type": "expr",
"required": true,
"meaning": "the human name (15 px); the row's link"
},
{
"name": "eyebrow",
"type": "expr",
"required": false,
"meaning": "default the type's code field (display.code), unless the title starts with it or another slot shows it; in containers ≥ 1200 px a muted inline prefix on the title line (\"EV-1187 · Team lunch\"), above the title only in card form"
},
{
"name": "lead",
"type": "expr",
"required": false,
"meaning": "a time or a person; the time leads when the Query is sorted by it; on a Timeline bar or DayGrid block a time lead is the bar's own time (never repeated), a person the first fact"
},
{
"name": "sub",
"type": "list:expr",
"required": false,
"meaning": "≤ 2 render expressions or to-many paths; bare numbers show their label; null facts are hidden"
},
{
"name": "value",
"type": "expr",
"required": false,
"meaning": "number or money, right"
},
{
"name": "detail",
"type": "list:expr",
"required": false,
"meaning": "≤ 3 short labelled facts on one muted line (\"3 sessions · approved €410\"); dropped first on phone; null facts are hidden"
}
]
},
"Group": {
"kind": "part",
"summary": "Groups rows by a key; an Action child is a group verb whose subject is the group's key record.",
"parents": [
"Table",
"List"
],
"children": [
"Action"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "by",
"type": "field",
"required": true,
"meaning": "a path, optional @day/@week/@month/@bucket (Overdue / Today / This week / Later)"
},
{
"name": "order",
"type": "list:string",
"required": false,
"meaning": "key order; default: an enum key's declared order, else by first appearance in the Query's sort"
},
{
"name": "collapsed",
"type": "list:string",
"required": false,
"meaning": "keys collapsed by default"
},
{
"name": "measure",
"type": "field",
"required": false,
"meaning": "numeric field summed in the header"
}
]
},
"Expand": {
"kind": "part",
"summary": "The row opens in place; may hold one scoped Query whose where reads the row (read on open).",
"parents": [
"Table"
],
"children": [
"FN"
],
"fnReturns": [
"Section"
],
"requiresAncestor": [],
"parentRules": {},
"props": []
},
"Check": {
"kind": "part",
"summary": "A leading 24 px check control (44 px hit area on phone).",
"parents": [
"Table",
"List"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "run",
"type": "name:action",
"required": true,
"meaning": "the transition to done"
},
{
"name": "undo",
"type": "name:action",
"required": true,
"meaning": "its inverse"
},
{
"name": "done",
"type": "name:condition",
"required": false,
"meaning": "the condition that counts as checked (default: run's target state)"
}
]
},
"BulkAction": {
"kind": "part",
"summary": "Runs a one-subject action over the selected rows (invoke_many, ≤ 100).",
"parents": [
"Table"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "run",
"type": "name:action",
"required": true,
"meaning": ""
}
]
},
"Empty": {
"kind": "part",
"summary": "The empty state: a title, a reason and ≤ 1 Action; several Empty parts, first match wins.",
"parents": [
"Page",
"RecordPage",
"Section",
"Tab",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Form"
],
"children": [
"TEXT",
"Value",
"Link",
"Action"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "title",
"type": "text",
"required": true,
"meaning": ""
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Board": {
"kind": "component",
"summary": "Cards in lanes of a process.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"FN",
"Action",
"Empty"
],
"fnReturns": [
"Item"
],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": true,
"meaning": "the collection"
},
{
"name": "opens",
"type": "expr|string",
"required": false,
"meaning": "\"auto\" (the type's record view; rows of a type without one, Aggregate rows and preview rows do not open), a view name, a record expression (opens its view) or \"none\"",
"default": "auto"
},
{
"name": "by",
"type": "field",
"required": true,
"meaning": "an enum or state-machine field"
},
{
"name": "sum",
"type": "field",
"required": false,
"meaning": "money/number (incl. rollups) summed in each lane header"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Matrix": {
"kind": "component",
"summary": "Rows × columns of cells.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Rows",
"Empty"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "cols",
"type": "expr",
"required": true,
"meaning": "the grain: days(week) (honours the State's weekdays), weeks(range) or months(range), hours(day), or an enum field \"type.field\""
},
{
"name": "cells",
"type": "ref:Query",
"required": false,
"meaning": "default for every Rows: a Query of a per-cell type (e.g. class_day) whose Flags give each cell its attention"
},
{
"name": "cellKey",
"type": "list:field",
"required": false,
"meaning": "the cells type's fields matching (row, column), e.g. [\"vehicle_class\", \"date\"]; [\"date\"] for a fixed row"
},
{
"name": "closed",
"type": "ref:Query",
"required": false,
"meaning": "the closed days (a plant's holidays and Sundays): each row closes the day column its `closedKey` date falls on, read whole over the columns' days, so its where needs no window term"
},
{
"name": "closedKey",
"type": "field",
"required": false,
"meaning": "the closed Query's date field, e.g. \"date\" (required with `closed`)"
},
{
"name": "closedReason",
"type": "field",
"required": false,
"meaning": "the closed Query's field naming why, e.g. \"holiday_name\" (default: the row's title)"
},
{
"name": "corner",
"type": "text",
"required": false,
"meaning": ""
},
{
"name": "opens",
"type": "expr|string",
"required": false,
"meaning": "the row label's target (auto: the row record's view when rows are records)",
"default": "auto"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Rows": {
"kind": "part",
"summary": "One row set of a Matrix: records, enum values or one fixed row.",
"parents": [
"Matrix"
],
"children": [
"FN"
],
"fnReturns": [
"Cell"
],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": false,
"meaning": "one row per record, every record of the Query (read whole, never a page)"
},
{
"name": "values",
"type": "field",
"required": false,
"meaning": "an enum field \"type.field\": one row per value"
},
{
"name": "label",
"type": "text",
"required": false,
"meaning": "one fixed row (row = null)"
},
{
"name": "sub",
"type": "fn",
"required": false,
"meaning": "row → a sub-line"
},
{
"name": "cells",
"type": "ref:Query",
"required": false,
"meaning": "this row set's cell records (overrides the Matrix's)"
},
{
"name": "cellKey",
"type": "list:field",
"required": false,
"meaning": ""
}
]
},
"Cell": {
"kind": "part",
"summary": "One matrix cell: ≤ 4 inline facts (text, never interactive) and one target.",
"parents": [
"Rows"
],
"children": [
"Ratio",
"Value",
"Text",
"Action"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "opens",
"type": "expr",
"required": false,
"meaning": "a record: the cell opens it (with `list` or Actions: the popover's first row is \"Open <record>\")"
},
{
"name": "list",
"type": "expr",
"required": false,
"meaning": "a list Aggregate cell: the records the popover lists (not counted as a fact)"
},
{
"name": "current",
"type": "boolean",
"required": false,
"meaning": ""
}
]
},
"Timeline": {
"kind": "component",
"summary": "Items over time in lanes.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"FN",
"Span",
"Action",
"Empty"
],
"fnReturns": [
"Item"
],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": true,
"meaning": ""
},
{
"name": "lane",
"type": "field",
"required": true,
"meaning": "a link or enum field; null lanes collect in a derived lane"
},
{
"name": "lanes",
"type": "ref:Query",
"required": false,
"meaning": "a link lane's lane records: a Query of the link's target type, every row a lane in its order, an empty lane kept (the whole fleet, idle coaches too), and no other: an item on a lane it leaves out is not drawn. Omitted: only the lanes that hold an item in the range, in title order. An enum lane draws every value"
},
{
"name": "start",
"type": "field|list:field",
"required": true,
"meaning": "a timestamp or date, or [date, time]"
},
{
"name": "end",
"type": "field|list:field",
"required": true,
"meaning": "blank on a row = open-ended: drawn to the axis end with an open-end mark; never coalesce it to a far date. The Timeline reads its Query over the range itself, so the Query needs no window term: one on the end field (`c.end_date >= span.start`) drops every open-ended item, since a blank never matches `>=`"
},
{
"name": "range",
"type": "ref:State|expr",
"required": true,
"meaning": "a week, range or month State, or a row-free expression; a date State is an hour axis"
},
{
"name": "grain",
"type": "enum",
"required": false,
"meaning": "the axis columns: days, the weeks (from the org's week start) or the months the range touches; not with a date State",
"default": "day",
"enum": [
"day",
"week",
"month"
]
},
{
"name": "capacity",
"type": "expr|string",
"required": false,
"meaning": "how much one lane holds at once; a bar is marked Conflict only while its lane holds more. 1 (the default: a coach, a room or a person does one thing at a time) marks any two bars at once; a number or a row-free expression (`capacity={record.owned_qty}`) is every lane's; a lane function over the `lanes` records (`capacity={k => k.owned_qty}`) is each lane's own; with a second parameter, the day, it is a capacity per day (`capacity={(k, d) => k.owned_qty + hired.at(k, d)}`: owned plus that day's hire-ins, hired a sum Aggregate keyed by lane and date), measured at every day start as well as every bar start; \"none\" marks no overlap (a lane of notes, a day of events). A lane whose capacity reads blank or withheld marks no overlap",
"default": "1"
},
{
"name": "amount",
"type": "field",
"required": false,
"meaning": "a number field of the item: how much of its lane's capacity each bar takes (`amount=\"qty\"`: 30 + 20 tables of 45 owned is over, 30 + 10 is not); without it each bar takes 1; a blank or withheld amount takes 0. Needs a capacity other than \"none\". Kit hire: `<Timeline of={res} lanes={kit} lane=\"kit_item\" start=\"out_on\" end=\"back_on\" range={span} capacity={k => k.owned_qty} amount=\"qty\">`"
},
{
"name": "opens",
"type": "expr|string",
"required": false,
"meaning": "",
"default": "auto"
},
{
"name": "move",
"type": "name:action",
"required": false,
"meaning": "not drawn yet, refused at compile: put <Action run=…> inside the Timeline, each bar offers it with the bar as its subject"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Span": {
"kind": "part",
"summary": "A shaded stretch of time: dates cover whole days, timestamps cover the stretch.",
"parents": [
"Timeline",
"DayGrid"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": true,
"meaning": ""
},
{
"name": "kind",
"type": "enum",
"required": true,
"meaning": "",
"enum": [
"blocked",
"available"
]
},
{
"name": "lane",
"type": "field",
"required": false,
"meaning": "no lane = all lanes"
},
{
"name": "start",
"type": "field",
"required": true,
"meaning": ""
},
{
"name": "end",
"type": "field",
"required": true,
"meaning": ""
},
{
"name": "label",
"type": "field",
"required": false,
"meaning": "the visible text, e.g. \"Time off: course\""
}
]
},
"DayGrid": {
"kind": "component",
"summary": "The calendar: lanes × time of day.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"FN",
"Span",
"Action",
"Empty"
],
"fnReturns": [
"Item"
],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": true,
"meaning": ""
},
{
"name": "lanes",
"type": "ref:Query",
"required": false,
"meaning": "resources; may be a per-day type; omitted with a week range = one column per day"
},
{
"name": "laneKey",
"type": "field",
"required": false,
"meaning": "the lanes row's link to the lane record (when lanes is a per-day type)"
},
{
"name": "lane",
"type": "field",
"required": false,
"meaning": "the item's link to the lane record; required with `lanes`"
},
{
"name": "start",
"type": "field",
"required": true,
"meaning": ""
},
{
"name": "end",
"type": "field",
"required": true,
"meaning": ""
},
{
"name": "range",
"type": "ref:State|expr",
"required": true,
"meaning": ""
},
{
"name": "hours",
"type": "object",
"required": false,
"meaning": "{from: \"08:00\", to: \"19:00\"}"
},
{
"name": "slot",
"type": "enum",
"required": false,
"meaning": "",
"default": "15",
"enum": [
"15",
"30",
"60"
]
},
{
"name": "create",
"type": "name:action",
"required": false,
"meaning": "not drawn yet, refused at compile: put <Action run=…> on the page or its Section, its dialog asks for the start and the lane"
},
{
"name": "move",
"type": "name:action",
"required": false,
"meaning": "not drawn yet, refused at compile: put <Action run=…> inside the DayGrid, each block offers it with the block as its subject"
},
{
"name": "opens",
"type": "expr|string",
"required": false,
"meaning": "",
"default": "auto"
},
{
"name": "when",
"type": "expr",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false."
}
]
},
"Filters": {
"kind": "component",
"summary": "Preset chips and facet chips with live counts.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Toolbar",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": true,
"meaning": ""
}
]
},
"Search": {
"kind": "component",
"summary": "Free text over the Query's search fields ($search).",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Toolbar",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "ref:Query",
"required": true,
"meaning": ""
}
]
},
"Control": {
"kind": "component",
"summary": "One control for one State; the kind follows the State's type.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Toolbar",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "state",
"type": "ref:State",
"required": true,
"meaning": ""
},
{
"name": "label",
"type": "text",
"required": true,
"meaning": ""
}
]
},
"PeriodNav": {
"kind": "component",
"summary": "‹ Today › with the range label; drives every component bound to its State.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Toolbar",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "state",
"type": "ref:State",
"required": true,
"meaning": ""
},
{
"name": "span",
"type": "enum",
"required": true,
"meaning": "the step: a date State steps by day, a week by week, a month by month, a range by its length (fortnight) or by a week or a month (its length kept; a range of whole months keeps its months)",
"enum": [
"day",
"week",
"fortnight",
"month"
]
},
{
"name": "counts",
"type": "ref:Aggregate|list:ref:Aggregate",
"required": false,
"meaning": "keyed by date: a day strip with badges in the header's unit; a list is summed (coach-short and driver-short days)"
},
{
"name": "skip",
"type": "enum",
"required": false,
"meaning": "empty: arrows step to the next day with a count",
"default": "none",
"enum": [
"none",
"empty"
]
}
]
},
"Files": {
"kind": "component",
"summary": "A record's attachments: tiles, lightbox, Add when the reader may attach.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Grid",
"Tab",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "of",
"type": "expr",
"required": true,
"meaning": ""
},
{
"name": "kinds",
"type": "list:string",
"required": false,
"meaning": "attachment kinds of the type (incl. kinds backed by a child type, PA-14)"
}
]
},
"Compare": {
"kind": "component",
"summary": "Two versions of a record with aligned lines, signed deltas and totals.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "a",
"type": "expr",
"required": true,
"meaning": ""
},
{
"name": "b",
"type": "expr",
"required": true,
"meaning": ""
},
{
"name": "lines",
"type": "field",
"required": true,
"meaning": "a to-many link"
},
{
"name": "key",
"type": "field",
"required": true,
"meaning": "unique per record: a field or a link (the line's item); a duplicate is a render refusal naming it"
},
{
"name": "value",
"type": "field",
"required": true,
"meaning": "the line money field: per-line signed delta, totals per side, difference"
},
{
"name": "fields",
"type": "list:field",
"required": false,
"meaning": "line fields compared and shown; a line is Changed when any differs"
},
{
"name": "facts",
"type": "list:field",
"required": false,
"meaning": "header fields aligned above the lines, each with its change"
},
{
"name": "total",
"type": "field",
"required": false,
"meaning": "the record's own money or number total (e.g. incl. VAT): a/b and the difference"
}
]
},
"Action": {
"kind": "component",
"summary": "The one verb element: runs an action (generated dialog) or opens a view.",
"parents": [
"Page",
"RecordPage",
"Section",
"Tab",
"Toolbar",
"Table",
"List",
"Group",
"Empty",
"Board",
"Cell",
"Timeline",
"DayGrid"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "run",
"type": "name:action",
"required": false,
"meaning": "an action"
},
{
"name": "view",
"type": "name:view",
"required": false,
"meaning": "a view to open"
},
{
"name": "params",
"type": "object|fn",
"required": false,
"meaning": "with view: named parameters, or a row function (r => ({customer: r.customer})) so a Form page can be a row's fix verb"
},
{
"name": "label",
"type": "text",
"required": false,
"meaning": "required with view; refused with run (the model's label)"
},
{
"name": "role",
"type": "enum",
"required": false,
"meaning": "may sit on verbs that exclude each other by legality: the first offered one is primary",
"enum": [
"primary"
]
},
{
"name": "with",
"type": "object|fn",
"required": false,
"meaning": "input presets: {{event_id: evt}} or a row function n => ({position: n.position}); null clears a fill"
},
{
"name": "rest",
"type": "boolean",
"required": false,
"meaning": "false: never the at-rest row verb"
},
{
"name": "when",
"type": "expr|fn",
"required": false,
"meaning": "render expression; false hides the element (UX only, never security). A withheld operand makes it false. On a Table/List/Board row verb, a row function d => d.state == \"on_road\" is its row condition: the verb is offered only on the rows it holds for."
}
]
},
"Link": {
"kind": "component",
"summary": "Inline navigation to a view or a record.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Text",
"Callout",
"Empty",
"Form"
],
"children": [
"TEXT"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "view",
"type": "name:view",
"required": false,
"meaning": ""
},
{
"name": "params",
"type": "object",
"required": false,
"meaning": ""
},
{
"name": "record",
"type": "expr",
"required": false,
"meaning": "opens the record's view"
}
]
},
"Form": {
"kind": "component",
"summary": "An action's form as the screen; a scope: any layout inside; Field/Lines/Step/Submit/Candidates/Preview need a Form ancestor.",
"parents": [
"Page",
"RecordPage",
"Section",
"Split",
"Columns",
"Tab",
"Form"
],
"children": [
"Preview",
"Section",
"Split",
"Columns",
"Grid",
"Tabs",
"Toolbar",
"Value",
"Text",
"Badge",
"Callout",
"Stat",
"Ratio",
"Meter",
"Chart",
"Facts",
"Breakdown",
"History",
"Lifecycle",
"Table",
"List",
"Board",
"Matrix",
"Timeline",
"DayGrid",
"Filters",
"Search",
"Control",
"PeriodNav",
"Files",
"Compare",
"Link",
"Form",
"Field",
"Lines",
"Step",
"Submit",
"Candidates",
"Empty"
],
"fnReturns": [],
"requiresAncestor": [],
"parentRules": {},
"props": [
{
"name": "run",
"type": "name:action",
"required": true,
"meaning": ""
},
{
"name": "with",
"type": "object",
"required": false,
"meaning": "input presets, e.g. {{proposal_id: param(\"proposal\")}}; a null value leaves the input to its model default"
},
{
"name": "view",
"type": "name:view",
"required": false,
"meaning": "the view a successful submit opens, with `params` (built like a Link: a view the reader may not open, or a param with no value, opens nothing). Without it the Form resets in place, or opens the record the action navigates to (`presentation.refresh: \"navigate\"`)"
},
{
"name": "params",
"type": "object",
"required": false,
"meaning": "with view: its named parameters, from the page's scope ({{event: ev}})"
}
]
},
"Field": {
"kind": "part",
"summary": "Places one model input; everything else about it is the model's.",
"parents": [
"Section",
"Split",
"Tab",
"Form",
"Lines",
"Step"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [
"Form"
],
"parentRules": {},
"props": [
{
"name": "name",
"type": "name:input",
"required": true,
"meaning": ""
}
]
},
"Lines": {
"kind": "part",
"summary": "An array input as a lines grid: a row per line, a column per sub-input; `<Value of={line.<property>} />` shows each line's own value, a property of the row it inserts (the action's `presentation.preview.rows`).",
"parents": [
"Section",
"Split",
"Tab",
"Form",
"Step"
],
"children": [
"Field",
"Value"
],
"fnReturns": [],
"requiresAncestor": [
"Form"
],
"parentRules": {},
"props": [
{
"name": "field",
"type": "name:input",
"required": true,
"meaning": ""
}
]
},
"Step": {
"kind": "part",
"summary": "Layout of one model step (pure layout): its Fields must belong to that step.",
"parents": [
"Section",
"Split",
"Tab",
"Form"
],
"children": [
"Field",
"Lines",
"Section",
"Candidates"
],
"fnReturns": [],
"requiresAncestor": [
"Form"
],
"parentRules": {},
"props": [
{
"name": "name",
"type": "name:step",
"required": true,
"meaning": ""
}
]
},
"Submit": {
"kind": "part",
"summary": "A submit button for one of the model's submits.",
"parents": [
"Section",
"Split",
"Tab",
"Form"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [
"Form"
],
"parentRules": {},
"props": [
{
"name": "mode",
"type": "name:submit",
"required": false,
"meaning": "the model submit this button runs. Required when the action declares more than one submit: write one `<Submit mode=…>` per submit the screen offers (they render in written order); a `<Submit>` without `mode` is legal only when the action has a single submit (or none), and then runs it. The forward submit (one whose `next` runs a forward transition, e.g. Send) is primary and is the sticky phone bar's button; Save draft is secondary"
}
]
},
"Candidates": {
"kind": "part",
"summary": "Choose a related record with each option's rule outcome (Form-as-screen; generated dialogs render it by themselves).",
"parents": [
"Section",
"Split",
"Tab",
"Form",
"Step"
],
"children": [],
"fnReturns": [],
"requiresAncestor": [
"Form"
],
"parentRules": {},
"props": [
{
"name": "field",
"type": "name:input",
"required": true,
"meaning": ""
},
{
"name": "facts",
"type": "list:field",
"required": false,
"meaning": "candidate fields shown; may read the subject (model)"
}
]
}
},
"helpers": [
{
"call": "today()",
"returns": "date",
"meaning": "the org clock's date (demo clock included)"
},
{
"call": "now()",
"returns": "timestamp",
"meaning": "the org clock's instant"
},
{
"call": "addDays(date, n)",
"returns": "date",
"meaning": ""
},
{
"call": "weekOf(date)",
"returns": "week",
"meaning": "`.start`, `.end`: the Monday–Sunday week holding the date; a State's `weekdays` narrow the days it shows"
},
{
"call": "monthOf(date)",
"returns": "month",
"meaning": "a month key for @month Aggregates"
},
{
"call": "days(weekOrRange)",
"returns": "list:date",
"meaning": "the shown days of a week/range State (its weekdays)"
},
{
"call": "weeks(rangeOrMonth)",
"returns": "list:week",
"meaning": "the weeks a range or month State touches, from the org's week start: Matrix columns or an Aggregate's `over` at week grain"
},
{
"call": "months(range)",
"returns": "list:month",
"meaning": "the months a range State touches: Matrix columns or an Aggregate's `over` at month grain"
},
{
"call": "hours(day)",
"returns": "list:timestamp",
"meaning": "the hours of a date State's day in the org zone (23 or 25 on a DST day): Matrix columns or an Aggregate's `over` at hour grain"
},
{
"call": "param(name)",
"returns": "string|record",
"meaning": "a declared view parameter"
},
{
"call": "me()",
"returns": "record",
"meaning": "the reader (`.name`, `.id`); in predicates only as `r.link == me()`"
},
{
"call": "greeting()",
"returns": "text",
"meaning": "\"Good morning, Lena\" in the org zone"
},
{
"call": "plural(n, one, many)",
"returns": "text",
"meaning": "the word only, by the count: `plural(n, \"stop\", \"stops\")` is \"stop\" for 1 and \"stops\" otherwise. Write the number beside it: `<Text><Value of={n} /> <Value of={plural(n, \"stop\", \"stops\")} /></Text>` reads \"1 stop\" / \"12 stops\""
},
{
"call": "percent(part, whole)",
"returns": "number",
"meaning": "a computed share written as a percentage: `percent(rewash.value, washed.value)` with 29 of 1,000 is \"2.9%\" (\"2,9 %\" in Danish). One argument is a ratio, a fraction of one: `percent(0.029)` is \"2.9%\"; never multiply by 100 yourself. To 1 place unless the percentage is whole (\"50%\"); a Stat's `scale` sets the places. A whole of 0 or none is no value (\"—\"). A field that holds a ratio declares `scale: {as: \"percent\"}` in the model instead"
}
],
"handles": [
{
"form": "q.total",
"returns": "number",
"meaning": "rows the collection shows (all filters)"
},
{
"form": "q.count(id)",
"returns": "number",
"meaning": "a Preset's count or a condition's row count"
},
{
"form": "q.amount(condition)",
"returns": "number",
"meaning": "Σ of the condition's amount (\"7 open positions\")"
},
{
"form": "q.sum(field[, condition])",
"returns": "number|money",
"meaning": "a declared total"
},
{
"form": "q.preset",
"returns": "string",
"meaning": "the active preset id"
},
{
"form": "q.current",
"returns": "record",
"meaning": "the current (→ Next) record, or null"
},
{
"form": "a.at(k1[, k2])",
"returns": "number|list",
"meaning": "an Aggregate cell"
},
{
"form": "a.value",
"returns": "number",
"meaning": "an Aggregate without by"
},
{
"form": "a.next(key)",
"returns": "key",
"meaning": "the first key ≥ key with a non-zero value"
},
{
"form": "a.peak(k)",
"returns": "number|money",
"meaning": "the largest cell along the time key (an over series or a bucketed key), the other key fixed: the busiest day of a range"
},
{
"form": "a.peakAt(k)",
"returns": "date",
"meaning": "the period a.peak(k) falls on (the earliest of equal peaks); null when nothing is counted"
},
{
"form": "a.free(k, capacity)",
"returns": "number|money",
"meaning": "capacity − a.peak(k), never below 0; past the capacity it reads 0 and is short by the excess on the peak day (\"0 short 1 on Sat 28 Nov\", critical, its row railed)"
},
{
"form": "a.free(k, capacity, extra)",
"returns": "number|money",
"meaning": "a capacity that differs by day: on each day capacity + extra.at(k, day) − a.at(k, day), the least of them, never below 0; short by the deficit on the tightest day. extra is a count or sum Aggregate keyed like a (owned stock + what is hired in that day)"
},
{
"form": "s.start / s.end",
"returns": "date",
"meaning": "week and range States"
},
{
"form": "pv.<output>",
"returns": "typed",
"meaning": "a Preview output"
},
{
"form": "line.<output>",
"returns": "typed",
"meaning": "inside Lines: the line's own value (a `preview.rows` property of the row it inserts)"
},
{
"form": "input.<name>",
"returns": "typed",
"meaning": "inside a Form: the current input value"
}
],
"scope": [
"record (RecordPage)",
"input (Form)",
"line (Lines)",
"child-function parameters",
"every data element id",
"every State id"
],
"refusals": [
{
"case": "type name case",
"written": "`type=\"Event\"` on r19",
"message": "the type is 'event'"
},
{
"case": "_id field",
"written": "`<Column field=\"client_id\"/>`",
"message": "use the link 'client'"
},
{
"case": "unknown field",
"written": "`field=\"pasengers\"`",
"message": "trip has no field 'pasengers'; did you mean 'passengers'?"
},
{
"case": "hops",
"written": "`field=\"contract.event.client\"`",
"message": "2 hops: declare a lookup on instalment or read it through a Record"
},
{
"case": "thin predicate",
"written": "`where={d => d.trip.is_live}`",
"message": "comparisons through a link are refused: declare a lookup on trip_day (trip_is_live) or a named condition"
},
{
"case": "or of rows",
"written": "`where={a => a.status == \"booked\" \\|\\| a.is_late}`",
"message": "declare a named condition on appointment (e.g. is_open)"
},
{
"case": "repeated literal",
"written": "the same `status != \"cancelled\"` in two views",
"message": "advice: declare it on <type> (e.g. is_live)"
},
{
"case": "view attention",
"written": "`<Ratio short=\"below\">`, `<Badge tone=\"critical\">`",
"message": "attention comes from a named condition: Flag it, or use a cells Query"
},
{
"case": "Flag shape",
"written": "`<Flag meaning=\"late\" when={…}>`",
"message": "Flag takes condition=…; declare the condition on cue (meaning late, on due_at)"
},
{
"case": "constant Flag",
"written": "`<Query where={i => i.is_overdue}><Flag condition=\"is_overdue\"/>`",
"message": "every row is overdue; the section title says so (the set is flagged)"
},
{
"case": "Field when",
"written": "`<Field name=\"bar_hours\" when={…}>`",
"message": "conditional inputs belong to proposal.build (inputShowWhen)"
},
{
"case": "Step title",
"written": "`<Step title=\"Pain\">`",
"message": "Step names a model step: name=\"pain\""
},
{
"case": "submit mode",
"written": "`<Submit />` in a Form for proposal.build (submits draft, send)",
"message": "<Submit> without mode: proposal.build has 2 submits — write mode= one of draft, send"
},
{
"case": "Form twice",
"written": "a Form for an action that is also an Action on the page",
"message": "pick one: the Form is the screen, or the Action opens the generated dialog"
},
{
"case": "Preview outside",
"written": "`<Preview>` outside a Form",
"message": "Preview reads the enclosing Form"
},
{
"case": "template prop",
"written": "`cell=`, `item=`, `renderItem=`",
"message": "write the template as the child function"
},
{
"case": "Action parent",
"written": "an Action in an unknown parent",
"message": "Action is legal in Page, RecordPage, Section, Tab, Toolbar, Table, List, Board, Group, Empty, Cell, Timeline, DayGrid"
},
{
"case": "with key",
"written": "`with={{event: …}}`",
"message": "proposal.send has no input 'event'; inputs: proposal_id, message"
},
{
"case": "fill tie",
"written": "two Events in scope",
"message": "two events in scope (ev, evt); write with={{event_id: …}}"
},
{
"case": "no-op fill",
"written": "a `sets` input filled from a scope value equal to the subject's current value",
"message": "to_route sets customer.route; filling it from the row's route is a no-op — left empty"
},
{
"case": "subject link fill",
"written": "an input of the type the subject links to, with no `sets`: `van_id` on run.change_van in a runs Table",
"message": "run.change_van.van_id would be filled from the row's van — the run's own value: declare sets: \"van\" on the input (the dialog asks it), or fill it with with={{van_id: …}}"
},
{
"case": "id shadowing",
"written": "`<Query id=\"days\">`",
"message": "'days' is a helper; rename the Query"
},
{
"case": "aggregate arity",
"written": "`have.at(p)` on a 2-key Aggregate",
"message": "have is keyed by (position, date)"
},
{
"case": "period start",
"written": "a week State without initial",
"message": "PeriodNav needs a start: initial={weekOf(today())}"
},
{
"case": "collection props",
"written": "`where=`/`filter=`/`sort=` on a Table",
"message": "filters and sort belong to the Query"
},
{
"case": "presets",
"written": "`<Preset>` inside `<Filters>`",
"message": "Presets are declared in the Query"
},
{
"case": "search in predicate",
"written": "`t.title.includes(x)`",
"message": "use the Query's search"
},
{
"case": "library: Line",
"written": "`<Chart><Line dataKey=…/></Chart>`",
"message": "Line is a Breakdown money line; a Chart takes <Series of={agg} label=…/>"
},
{
"case": "library: Group",
"written": "`<Group><Action/><Action/></Group>` outside a collection",
"message": "Group groups rows of a collection"
},
{
"case": "library: Item",
"written": "`<Item label=\"Qty\"><Field/></Item>`",
"message": "Item is a row template; a form field is <Field name=…> in a Form"
},
{
"case": "library: Page",
"written": "`<Page primaryAction={…}>`",
"message": "write <Action run=… role=\"primary\"/> as a Page child"
},
{
"case": "library: Table",
"written": "`<Table columns={[…]} dataSource={…}>`",
"message": "columns are <Column> children; data is of={query}"
},
{
"case": "library: Tabs",
"written": "`<Tabs items={…}>`",
"message": "write <Tab label=…> children"
},
{
"case": "library: tones",
"written": "`tone=\"success\"`",
"message": "attention comes from conditions; Callout tone is info | warn"
},
{
"case": "library: Form",
"written": "`<Form onSubmit=… initialValues=…>`",
"message": "Form runs an action (run=); defaults are the model's"
},
{
"case": "library: Link",
"written": "`<Link href=\"/trips/1\">`",
"message": "Link takes view= or record="
},
{
"case": "library: Grid",
"written": "`<Grid item xs={6}>`",
"message": "Grid lays out like items; no spans"
},
{
"case": "library: Check",
"written": "`<Check checked={c.done}>`",
"message": "Check runs run/undo transitions"
},
{
"case": "SQL clock",
"written": "`date('now')` in a condition",
"message": "use :today / :now (the org clock)"
},
{
"case": "author a11y",
"written": "`role=`, `tabindex=`, `aria-*`, `onClick=`",
"message": "the platform owns roles and keys"
}
]
}