@peripheries/renderer 0.23.1 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -2
- package/dist/catalog.js +1 -1
- package/dist/chunks/{projection-zhu32_KJ.js → projection-e8MHn6Bt.js} +40 -2
- package/dist/chunks/{validate-BcB_PA1k.js → validate-CrHGlwey.js} +18 -0
- package/dist/core.js +24 -4
- package/dist/react.js +64 -16
- package/dist/styles.css +6 -0
- package/dist/types/core/cell-props.d.ts +3 -0
- package/dist/types/core/cells.d.ts +2 -1
- package/dist/types/core/diagnostics.d.ts +4 -0
- package/dist/types/core/index.d.ts +3 -2
- package/dist/types/core/layers.d.ts +8 -0
- package/dist/types/core/layers.gen.d.ts +12 -0
- package/dist/types/core/types.d.ts +5 -2
- package/dist/types/forms/index.d.ts +1 -0
- package/dist/types/forms/model.d.ts +4 -4
- package/dist/types/forms/section.d.ts +22 -0
- package/dist/types/react/cell-states.d.ts +4 -1
- package/dist/types/react/cell-view.d.ts +2 -0
- package/dist/types/react/index.d.ts +1 -1
- package/dist/types/react/page-renderer.d.ts +2 -0
- package/dist/types/react/use-forms-runtime.d.ts +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,13 +6,13 @@ the same in each.
|
|
|
6
6
|
|
|
7
7
|
| Entry | Holds |
|
|
8
8
|
|---|---|
|
|
9
|
-
| `@peripheries/renderer/core` | Framework-free: cells and thin-ref hydration, references and conditions, the data context, walks and state names, cell props, layout, document structure, bundle refs and resolution, the shared store, `loadPageData(page, source)`, validation, `DIAGNOSTICS` and `PAGE_RULES` |
|
|
9
|
+
| `@peripheries/renderer/core` | Framework-free: cells and thin-ref hydration, references and conditions, the data context, walks and state names (`layerName`, the layer catalog `LAYER_ROLES`), cell props, layout, document structure, bundle refs and resolution, the shared store, `loadPageData(page, source)`, validation, `DIAGNOSTICS` and `PAGE_RULES` |
|
|
10
10
|
| `@peripheries/renderer/catalog` | `checkCatalog`: what a component repo runs on the knowledge it emits. The only entry with a JSON Schema validator (ajv) |
|
|
11
11
|
| `@peripheries/renderer/react` | `PageRenderer`, `CellView`, `StructureView`, the cell states, `useContainerSize`, `useFormsRuntime` and its `FormSlotProps` and `FormAnswer` |
|
|
12
12
|
| `@peripheries/renderer/runtime` | What a page boots with: the import map and boot script, the shims, `installRuntime`, the store bundles import |
|
|
13
13
|
| `@peripheries/renderer/theme` | The org theme pipeline: `parseTheme` (version 1 or 2 in, version 2 out, with diagnostics), `themeTokens` (semantic overrides derived in OKLCH), `themeCss` (the `theme` layer), `checkTheme` (WCAG contrast) |
|
|
14
14
|
| `@peripheries/renderer/print` | The print pipeline, framework-free: `collectBlocks` (the page map), `paginate`, `buildPrintLayout` (the packer's decision as CSS), `buildPageStylesheet` (`@page` geometry and margin boxes), running headers, `@printPolicy` parsing, print lint, `resolveDocumentProfile`, region bindings, map staleness, and the `layout.structure[].print` writer |
|
|
15
|
-
| `@peripheries/renderer/forms` | The forms runtime, framework-free: the steps overlay and its model, conditions, modes, navigation, progress, deep links, and the persistence port (`FormsPort`); the React hook is `useFormsRuntime` in `/react` |
|
|
15
|
+
| `@peripheries/renderer/forms` | The forms runtime, framework-free: the steps overlay and its model, conditions, modes, navigation, progress, deep links, and the persistence port (`FormsPort`), and the form-section contract's type (`FormSection`, `FormContentBlock`); the React hook is `useFormsRuntime` in `/react` |
|
|
16
16
|
| `@peripheries/renderer/testing` | The golden pages, synthetic fixtures, and sources that serve them |
|
|
17
17
|
| `@peripheries/renderer/styles.css` | Page and cell containers, the responsive buckets, placeholders and notices, in the `renderer` layer |
|
|
18
18
|
|
|
@@ -51,6 +51,11 @@ const runtime = await loadPageData(page, source, { params, baseProps, viewer, co
|
|
|
51
51
|
- `frameProps(cell, contract)`: extra attributes and style on a cell's frame,
|
|
52
52
|
for what the host doesn't apply yet (a print policy, say).
|
|
53
53
|
- `onDiagnostic(d)`: a page configuration problem.
|
|
54
|
+
- `showHiddenCells`: where a page is being built or reviewed (an editor, a
|
|
55
|
+
harness, a preview), a cell its `hide_when_empty` leaves out shows as a
|
|
56
|
+
small "hidden (empty)" placeholder instead of nothing.
|
|
57
|
+
- `showProblemCodes`: a cell's problem notice adds its diagnostic code, for
|
|
58
|
+
staff and editors; without it a viewer reads only the plain wording.
|
|
54
59
|
|
|
55
60
|
A consumer with resolved values instead of a graph (the component repos'
|
|
56
61
|
harness) builds its runtime with `pageRuntimeFromValues(page, { values,
|
|
@@ -70,6 +75,7 @@ names: 0.8.0 dropped the old client-prefixed twins and container names.
|
|
|
70
75
|
| A cell's buckets | `data-hide-when`, `data-show-when`, `data-stack-when`, `data-truncate-when` |
|
|
71
76
|
| A structure section | `data-section`, `data-section-level`, `data-section-kind`, `data-derived-ordinal` |
|
|
72
77
|
| A missing component's notice | `data-missing-component` |
|
|
78
|
+
| A cell `hide_when_empty` left out, shown by `showHiddenCells` | `.cell-hidden`, `data-cell-state="hidden-empty"` |
|
|
73
79
|
|
|
74
80
|
The store specifier and runtime global are in `@peripheries/runtime`'s README.
|
|
75
81
|
The theme reaches a page as CSS, in the `theme` layer; the renderer ignores a
|
|
@@ -77,6 +83,46 @@ bundle's `ThemeProvider` export.
|
|
|
77
83
|
|
|
78
84
|
## Versions
|
|
79
85
|
|
|
86
|
+
- **0.25.0** (2026-10-24): `hide_when_empty`, a cell-level list of prop names.
|
|
87
|
+
- **A cell with `hide_when_empty: ["title", "items"]`** renders nothing, and leaves no gap,
|
|
88
|
+
when every prop it names is empty once bound: null, undefined, text that is blank once
|
|
89
|
+
trimmed, `[]` or `{}`. `0` and `false` are content. A slot or `children` filled by child
|
|
90
|
+
cells is content. Print follows the screen. The check runs before the bundles load, so a
|
|
91
|
+
server render and the browser agree.
|
|
92
|
+
- **A refused, failed or unresolved read is not empty.** A named prop that reads a label whose
|
|
93
|
+
read was refused or failed keeps the cell's error notice. One whose query never ran because
|
|
94
|
+
its own reference resolved to nothing (`QUERY_UNRESOLVED`) shows the same notice instead of
|
|
95
|
+
hiding (`hideWhenEmptyProblem`). A label still loading isn't decided yet (the cell renders).
|
|
96
|
+
- **`RendererEnvironment.showProblemCodes`**: a problem notice adds its diagnostic code
|
|
97
|
+
(`data-cell-code`, `.cell-notice__code`) for staff and editors; a client reads only "This
|
|
98
|
+
part of the page couldn't load." The host sets it in the platform environment and in a
|
|
99
|
+
proposal preview.
|
|
100
|
+
- **`RendererEnvironment.showHiddenCells`**: an editor, a harness or a preview shows a hidden
|
|
101
|
+
cell as a small "hidden (empty)" placeholder (`CellHidden`, `.cell-hidden`).
|
|
102
|
+
- **Validation:** `validatePage` reports `PROP_UNKNOWN` (warning) at
|
|
103
|
+
`content.cells[i].hide_when_empty[j]` for a name the component's `props_schema` doesn't
|
|
104
|
+
declare, and `HIDE_WHEN_EMPTY_INVALID` (error) for anything but a non-empty list of names.
|
|
105
|
+
- A ref cell's node owns `hide_when_empty` (`CONTENT_FIELDS`, via `RENDER_FIELDS`). `/core`
|
|
106
|
+
exports `hiddenWhenEmpty`, `hideWhenEmptyProblem` and `isEmptyPropValue`. `PAGE_RULES` names the key.
|
|
107
|
+
- The renderer's `PageCell` type adds `hide_when_empty?: string[]`; `@peripheries/runtime`'s
|
|
108
|
+
`PageCell` gains it at its next release.
|
|
109
|
+
|
|
110
|
+
- **0.24.0** (2026-10-20): one renderer batch (CX).
|
|
111
|
+
- **`layerName(system)` and `LAYER_ROLES`** in `/core`: a system's state name (its layer's role,
|
|
112
|
+
else a registered layer's own type, `question`, `answer`, …) from the layer catalog, which is
|
|
113
|
+
generated from `public.system_layer` (`npm run gen:layers`; CI checks it is current). A host
|
|
114
|
+
and BEA's preview resolve a page's state names alike. An unregistered type has no name.
|
|
115
|
+
- **`FormSection` and `FormContentBlock`** in `/forms`: a form section cell's `props.section`,
|
|
116
|
+
contract v1 (`contracts/form-section.schema.json`): the section node's `id`, its authored
|
|
117
|
+
`sectionId`, `title`, `description?`, `sectionType?`, its `questions` (`{ key, label, required,
|
|
118
|
+
definition }`, the definition the form-definition contract's question or null) and its
|
|
119
|
+
`content` blocks (the form-definition contract's content block). Static: visibility, answers
|
|
120
|
+
and totals stay runtime (`forms.*`, `FormAnswer`, unchanged). v1 is the target shape: the
|
|
121
|
+
component engine doesn't emit `props.section` yet; the cutover is in the stack's
|
|
122
|
+
`contracts/README.md`.
|
|
123
|
+
- **`FormQuestionDefinition`'s** `options`, `validation`, `description` and `helpText` may be
|
|
124
|
+
null, as the form-definition contract's question has them.
|
|
125
|
+
|
|
80
126
|
- **0.23.1** (2026-10-15): the published files carry no comments and no
|
|
81
127
|
source maps (declarations included); this README is the documentation.
|
|
82
128
|
No API change.
|
package/dist/catalog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { x as isEach } from "./chunks/query-D6xQbTFK.js";
|
|
2
|
-
import { i as eachFormProblems, s as validatePage } from "./chunks/validate-
|
|
2
|
+
import { i as eachFormProblems, s as validatePage } from "./chunks/validate-CrHGlwey.js";
|
|
3
3
|
import { KNOWLEDGE_BUDGETS, KNOWLEDGE_KEY } from "@peripheries/runtime";
|
|
4
4
|
import Ajv2020 from "ajv/dist/2020.js";
|
|
5
5
|
var ref = (kind, key) => `${kind}:${key}`;
|
|
@@ -16,7 +16,12 @@ var STORE_FIELDS = [
|
|
|
16
16
|
"viewState",
|
|
17
17
|
"live"
|
|
18
18
|
];
|
|
19
|
-
var
|
|
19
|
+
var RENDER_FIELDS = ["hide_when_empty"];
|
|
20
|
+
var CONTENT_FIELDS = [
|
|
21
|
+
...HYDRATED_CELL_FIELDS.filter((f) => f !== "layout"),
|
|
22
|
+
...STORE_FIELDS,
|
|
23
|
+
...RENDER_FIELDS
|
|
24
|
+
];
|
|
20
25
|
function normalizeCell(cell, path = "cell") {
|
|
21
26
|
const diagnostics = [];
|
|
22
27
|
if (cell.ref) return {
|
|
@@ -114,6 +119,39 @@ function failedLabels(cell, data) {
|
|
|
114
119
|
return Boolean(entry?.error) && !entry?.unresolved?.length && !entry?.isLoading && (entry?.data === void 0 || entry?.data === null);
|
|
115
120
|
});
|
|
116
121
|
}
|
|
122
|
+
function isEmptyPropValue(value) {
|
|
123
|
+
if (value === null || value === void 0) return true;
|
|
124
|
+
if (typeof value === "string") return value.trim() === "";
|
|
125
|
+
if (Array.isArray(value)) return value.length === 0;
|
|
126
|
+
if (typeof value === "object") {
|
|
127
|
+
const proto = Object.getPrototypeOf(value);
|
|
128
|
+
return (proto === Object.prototype || proto === null) && Object.keys(value).length === 0;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
var propLabels = (value) => [...JSON.stringify(value ?? null).matchAll(LABEL_REF)].map((m) => m[1]);
|
|
133
|
+
function hideWhenEmptyProblem(cell, data) {
|
|
134
|
+
const names = cell.hide_when_empty;
|
|
135
|
+
if (!Array.isArray(names)) return null;
|
|
136
|
+
for (const name of names) {
|
|
137
|
+
if (typeof name !== "string") continue;
|
|
138
|
+
for (const label of propLabels(cell.props?.[name])) if (data[label]?.unresolved?.length && !data[label]?.isLoading) return "QUERY_UNRESOLVED";
|
|
139
|
+
}
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
function hiddenWhenEmpty(cell, props, data) {
|
|
143
|
+
const names = cell.hide_when_empty;
|
|
144
|
+
if (!Array.isArray(names) || names.length === 0) return false;
|
|
145
|
+
for (const name of names) {
|
|
146
|
+
if (typeof name !== "string") return false;
|
|
147
|
+
for (const label of propLabels(cell.props?.[name])) {
|
|
148
|
+
const entry = data[label];
|
|
149
|
+
if (entry?.isLoading || entry?.error) return false;
|
|
150
|
+
}
|
|
151
|
+
if (!isEmptyPropValue(props[name])) return false;
|
|
152
|
+
}
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
117
155
|
function assembleCellProps(i) {
|
|
118
156
|
const { style: _fromConfig, ...resolved } = i.resolvedProps;
|
|
119
157
|
const props = { ...resolved };
|
|
@@ -304,4 +342,4 @@ function collectScopeIds(ctx, selections, viewState) {
|
|
|
304
342
|
}
|
|
305
343
|
return [...ids];
|
|
306
344
|
}
|
|
307
|
-
export {
|
|
345
|
+
export { HYDRATED_CELL_FIELDS as C, normalizeCell as D, hasRef as E, resolveCell as O, CONTENT_FIELDS as S, STORE_FIELDS as T, failedLabels as _, projectSelections as a, isEmptyPropValue as b, pageScopeKey as c, resolveComponent as d, cellAttributes as f, assembleCellProps as g, pageContainerStyle as h, projectLive as i, rootCells as k, projectScopeKey as l, documentProfile as m, attachViewStateSetters as n, projectViewState as o, cellPlacementStyle as p, collectScopeIds as r, shallowEqualBundle as s, attachSelectionSetters as t, resolveScopeId as u, hiddenWhenEmpty as v, RENDER_FIELDS as w, projectCellData as x, hideWhenEmptyProblem as y };
|
|
@@ -641,6 +641,16 @@ function validateCell(cell, catalog, path = "cell", ids, options = {}) {
|
|
|
641
641
|
message: `${cell.component} requires ${prop}`
|
|
642
642
|
});
|
|
643
643
|
}
|
|
644
|
+
const listed = schema?.properties;
|
|
645
|
+
if (listed && Array.isArray(cell.hide_when_empty)) cell.hide_when_empty.forEach((prop, i) => {
|
|
646
|
+
if (typeof prop === "string" && prop !== "children" && !(prop in listed)) push({
|
|
647
|
+
severity: "warning",
|
|
648
|
+
code: "PROP_UNKNOWN",
|
|
649
|
+
cellId,
|
|
650
|
+
path: `${path}.hide_when_empty[${i}]`,
|
|
651
|
+
message: `hide_when_empty names ${prop}, which ${cell.component} doesn’t declare`
|
|
652
|
+
});
|
|
653
|
+
});
|
|
644
654
|
const declared = schema?.properties;
|
|
645
655
|
if (declared && schema?.additionalProperties !== true && typeof schema?.additionalProperties !== "object") {
|
|
646
656
|
for (const prop of Object.keys(cell.props ?? {})) if (prop !== "children" && prop !== "style" && !(prop in declared)) push({
|
|
@@ -674,6 +684,14 @@ function validateCell(cell, catalog, path = "cell", ids, options = {}) {
|
|
|
674
684
|
path: `${path}.children`,
|
|
675
685
|
message: `child cell "${child}" is not on the page`
|
|
676
686
|
});
|
|
687
|
+
const hide = cell.hide_when_empty;
|
|
688
|
+
if (hide !== void 0 && (!Array.isArray(hide) || hide.length === 0 || hide.some((p) => typeof p !== "string" || !p))) push({
|
|
689
|
+
severity: "error",
|
|
690
|
+
code: "HIDE_WHEN_EMPTY_INVALID",
|
|
691
|
+
cellId,
|
|
692
|
+
path: `${path}.hide_when_empty`,
|
|
693
|
+
message: "hide_when_empty takes a non-empty list of prop names"
|
|
694
|
+
});
|
|
677
695
|
checkBindings(cell.data?.queries, `${path}.data.queries`, push, cellId, options.template);
|
|
678
696
|
checkActions(cell, path, push);
|
|
679
697
|
checkProjections(cell.props, `${path}.props`, push, cellId);
|
package/dist/core.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { C as normalizeCell,
|
|
1
|
+
import { C as HYDRATED_CELL_FIELDS, D as normalizeCell, E as hasRef, O as resolveCell, S as CONTENT_FIELDS, T as STORE_FIELDS, a as projectSelections, b as isEmptyPropValue, c as pageScopeKey, d as resolveComponent, f as cellAttributes, g as assembleCellProps, h as pageContainerStyle, i as projectLive, k as rootCells, l as projectScopeKey, n as attachViewStateSetters, o as projectViewState, p as cellPlacementStyle, r as collectScopeIds, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, v as hiddenWhenEmpty, w as RENDER_FIELDS, x as projectCellData, y as hideWhenEmptyProblem } from "./chunks/projection-e8MHn6Bt.js";
|
|
2
2
|
import { C as passesConditions, S as pageContext, T as settled, _ as EACH, a as VARIABLE_NAMESPACES, b as cellResolutionContext, c as pageVariables, d as resolveDescriptorVariables, f as selectionShape, g as variableReferences, h as variableLabels, i as UnsafeDocumentError, l as prepareDocument, m as validateDescriptor, n as RENDER_FUNCTIONS, o as descriptorShape, p as shapeAt, r as RENDER_FUNCTIONS_AHEAD, s as orderByVariable, t as PAGING_VARIABLES, u as queryKey, v as EACH_DEFAULT_AS, w as resolveReferences, x as isEach, y as cellContext } from "./chunks/query-D6xQbTFK.js";
|
|
3
|
-
import { _ as stateValue, a as nearestNames, b as walkKey, c as selectionIssues, d as needsWalk, f as readField, g as stateNames, h as resolveWalkStart, i as eachFormProblems, l as RESERVED_LABELS, m as referencedLabels, n as STORE_SCOPES, o as validateCell, p as readWalk, r as WALK_DIRECTIONS, s as validatePage, t as RESPONSIVE_BUCKETS, u as mergeStates, v as systemsFromGraphs, x as walkRequest, y as systemsFromProcess } from "./chunks/validate-
|
|
3
|
+
import { _ as stateValue, a as nearestNames, b as walkKey, c as selectionIssues, d as needsWalk, f as readField, g as stateNames, h as resolveWalkStart, i as eachFormProblems, l as RESERVED_LABELS, m as referencedLabels, n as STORE_SCOPES, o as validateCell, p as readWalk, r as WALK_DIRECTIONS, s as validatePage, t as RESPONSIVE_BUCKETS, u as mergeStates, v as systemsFromGraphs, x as walkRequest, y as systemsFromProcess } from "./chunks/validate-CrHGlwey.js";
|
|
4
4
|
import { C as resolveAction, S as projectCellActions, _ as actionBindingKey, a as deriveSectionReferences, b as declaredActions, c as nodePrintStyle, d as referencesFor, f as sectionAnchor, g as usesStructureLayout, h as tableOfContents, i as deriveSectionNumbering, l as normalizeStructure, m as structureIssues, n as SECTION_KINDS, r as deriveElementReferences, s as mergeSectionReferences, t as PAGE_DOCUMENT, u as numberingFor, v as actionProblems, x as normalizeActionDeclaration, y as actionReferences } from "./chunks/structure-CKBtQHJq.js";
|
|
5
5
|
import { a as loadBundlesSettled, i as loadBundles, n as isComponentExport, o as projectModule, r as loadBundle, s as runtimeReady, t as _clearBundleCache } from "./chunks/load-b38vUiZM.js";
|
|
6
6
|
import { a as normalizeRef, i as bundleScope, n as MAIN, o as refKey, r as PUBLIC, t as CORE_SPECIFIER } from "./chunks/refs-Csgh6rXq.js";
|
|
@@ -90,6 +90,22 @@ function buildDataContext(input) {
|
|
|
90
90
|
}
|
|
91
91
|
return ctx;
|
|
92
92
|
}
|
|
93
|
+
var LAYER_ROLES = {
|
|
94
|
+
"answer": null,
|
|
95
|
+
"appraisal-system": "appraisal",
|
|
96
|
+
"data-system": "data",
|
|
97
|
+
"edits": null,
|
|
98
|
+
"model-system": "model",
|
|
99
|
+
"organisation": null,
|
|
100
|
+
"process-system": "process",
|
|
101
|
+
"question": null,
|
|
102
|
+
"submission": null
|
|
103
|
+
};
|
|
104
|
+
function layerName(s) {
|
|
105
|
+
if (s.system_layer) return s.system_layer.role ?? s.system_type ?? null;
|
|
106
|
+
if (!s.system_type || !Object.hasOwn(LAYER_ROLES, s.system_type)) return null;
|
|
107
|
+
return LAYER_ROLES[s.system_type] ?? s.system_type;
|
|
108
|
+
}
|
|
93
109
|
async function resolveSystems(source, page) {
|
|
94
110
|
const systems = !page.process_id ? {} : source.graphSystems ? systemsFromGraphs(await source.graphSystems(page.process_id)) : systemsFromProcess(await source.processSystems?.(page.process_id));
|
|
95
111
|
if (!systems.eng_data) {
|
|
@@ -785,6 +801,10 @@ var DIAGNOSTICS = {
|
|
|
785
801
|
meaning: "A literal prop value fails its schema.",
|
|
786
802
|
fix: "Write the value in the shape `props_schema` gives, or bind it with a whole-string `@label.path` reference."
|
|
787
803
|
},
|
|
804
|
+
HIDE_WHEN_EMPTY_INVALID: {
|
|
805
|
+
meaning: "A cell’s `hide_when_empty` isn’t a list of prop names.",
|
|
806
|
+
fix: "Write `hide_when_empty: [\"title\", \"items\"]`: the props that, all empty once bound (null, blank text, `[]`, `{}`), leave the cell out."
|
|
807
|
+
},
|
|
788
808
|
CELL_UNKNOWN_CHILD: {
|
|
789
809
|
meaning: "`children` names a cell that is not on the page.",
|
|
790
810
|
fix: "List only ids of cells on this page in `children`."
|
|
@@ -1038,7 +1058,7 @@ The host's rules for every page. Components, kits and patterns are in the catalo
|
|
|
1038
1058
|
- Every cell has a unique \`id\`. Inline: \`{ id, component, props, layout? }\`. Managed by a cell node: \`{ id, ref: { graph_node_id }, layout? }\`; its \`component\` and \`props\` are the fallback.
|
|
1039
1059
|
- \`children\` lists child cell ids, rendered inside the cell in place of \`props.children\`.
|
|
1040
1060
|
- A child with \`slot\` fills that \`x-slot\` of its parent; others are \`children\`.
|
|
1041
|
-
- \`conditions.showIf\` / \`hideIf\` test a value
|
|
1061
|
+
- \`conditions.showIf\` / \`hideIf\` test a value for truthiness; \`hide_when_empty: [props]\` hides the cell if all are empty.
|
|
1042
1062
|
- An embed cell \`{ id, embed: { page_id } | { page_type, project_id?, process_id? } }\` renders another published page, one level deep.
|
|
1043
1063
|
|
|
1044
1064
|
## Data and references
|
|
@@ -1116,4 +1136,4 @@ function manifestPageFrom(graphNodeId, data) {
|
|
|
1116
1136
|
}
|
|
1117
1137
|
};
|
|
1118
1138
|
}
|
|
1119
|
-
export { CONTENT_FIELDS, CORE_SPECIFIER, DIAGNOSTICS, EACH, EACH_DEFAULT_AS, HYDRATED_CELL_FIELDS, LAYOUT_TYPES, MAIN, PAGE_DOCUMENT, PAGE_RULES, PAGING_VARIABLES, PUBLIC, RENDER_FUNCTIONS, RENDER_FUNCTIONS_AHEAD, RESERVED_LABELS, RESPONSIVE_BUCKETS, SECTION_KINDS, STORE_FIELDS, STORE_SCOPES, STRUCTURE_FIELDS, TOOL_OWNED_KEYS, UnsafeDocumentError, VARIABLE_NAMESPACES, WALK_DIRECTIONS, _clearBundleCache, actionBindingKey, actionProblems, actionReferences, assembleCellProps, attachSelectionSetters, attachViewStateSetters, buildDataContext, bundleScope, cellAttributes, cellContext, cellPlacementStyle, cellPropSources, cellResolutionContext, clearScope, collectDeclarations, collectDescriptors, collectScopeIds, collectStatic, createStackStore, declaredActions, deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, descriptorShape, eachFormProblems, editTarget, hasRef, isComponentExport, isEach, loadBundle, loadBundles, loadBundlesSettled, loadPageData, loadScope, manifestPageFrom, mergeSectionReferences, mergeStates, nearestNames, needsWalk, nodePrintStyle, normalizeActionDeclaration, normalizeCell, normalizeRef, normalizeStructure, numberingFor, orderByVariable, pageBundleRefs, pageBundles, pageContainerStyle, pageContext, pageRuntimeFromValues, pageScopeKey, pageVariables, passesConditions, patchAt, prepareDocument, projectCellActions, projectCellData, projectLive, projectModule, projectScopeKey, projectSelections, projectViewState, queryKey, readField, readWalk, refKey, referencedLabels, referencesFor, resolveAction, resolveCell, resolveComponent, resolveDataSystem, resolveDeclarations, resolveDescriptorVariables, resolveReferences, resolveScopeId, resolveSystems, resolveWalkStart, rootCells, runtimeReady, saveScope, sectionAnchor, selectionIssues, selectionShape, settled, shallowEqualBundle, shapeAt, stateNames, stateValue, structureIssues, systemsFromGraphs, systemsFromProcess, tableOfContents, usesStructureLayout, validateCell, validateDescriptor, validateManifest, validatePage, variableLabels, variableReferences, walkKey, walkRequest };
|
|
1139
|
+
export { CONTENT_FIELDS, CORE_SPECIFIER, DIAGNOSTICS, EACH, EACH_DEFAULT_AS, HYDRATED_CELL_FIELDS, LAYER_ROLES, LAYOUT_TYPES, MAIN, PAGE_DOCUMENT, PAGE_RULES, PAGING_VARIABLES, PUBLIC, RENDER_FIELDS, RENDER_FUNCTIONS, RENDER_FUNCTIONS_AHEAD, RESERVED_LABELS, RESPONSIVE_BUCKETS, SECTION_KINDS, STORE_FIELDS, STORE_SCOPES, STRUCTURE_FIELDS, TOOL_OWNED_KEYS, UnsafeDocumentError, VARIABLE_NAMESPACES, WALK_DIRECTIONS, _clearBundleCache, actionBindingKey, actionProblems, actionReferences, assembleCellProps, attachSelectionSetters, attachViewStateSetters, buildDataContext, bundleScope, cellAttributes, cellContext, cellPlacementStyle, cellPropSources, cellResolutionContext, clearScope, collectDeclarations, collectDescriptors, collectScopeIds, collectStatic, createStackStore, declaredActions, deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, descriptorShape, eachFormProblems, editTarget, hasRef, hiddenWhenEmpty, hideWhenEmptyProblem, isComponentExport, isEach, isEmptyPropValue, layerName, loadBundle, loadBundles, loadBundlesSettled, loadPageData, loadScope, manifestPageFrom, mergeSectionReferences, mergeStates, nearestNames, needsWalk, nodePrintStyle, normalizeActionDeclaration, normalizeCell, normalizeRef, normalizeStructure, numberingFor, orderByVariable, pageBundleRefs, pageBundles, pageContainerStyle, pageContext, pageRuntimeFromValues, pageScopeKey, pageVariables, passesConditions, patchAt, prepareDocument, projectCellActions, projectCellData, projectLive, projectModule, projectScopeKey, projectSelections, projectViewState, queryKey, readField, readWalk, refKey, referencedLabels, referencesFor, resolveAction, resolveCell, resolveComponent, resolveDataSystem, resolveDeclarations, resolveDescriptorVariables, resolveReferences, resolveScopeId, resolveSystems, resolveWalkStart, rootCells, runtimeReady, saveScope, sectionAnchor, selectionIssues, selectionShape, settled, shallowEqualBundle, shapeAt, stateNames, stateValue, structureIssues, systemsFromGraphs, systemsFromProcess, tableOfContents, usesStructureLayout, validateCell, validateDescriptor, validateManifest, validatePage, variableLabels, variableReferences, walkKey, walkRequest };
|
package/dist/react.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as failedLabels, a as projectSelections, d as resolveComponent, f as cellAttributes, g as assembleCellProps, h as pageContainerStyle, i as projectLive, k as rootCells, m as documentProfile, n as attachViewStateSetters, o as projectViewState, p as cellPlacementStyle, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, v as hiddenWhenEmpty, x as projectCellData, y as hideWhenEmptyProblem } from "./chunks/projection-e8MHn6Bt.js";
|
|
2
2
|
import { C as passesConditions, S as pageContext, T as settled, b as cellResolutionContext, c as pageVariables, v as EACH_DEFAULT_AS, w as resolveReferences, y as cellContext } from "./chunks/query-D6xQbTFK.js";
|
|
3
3
|
import { a as deriveSectionReferences, b as declaredActions, c as nodePrintStyle, d as referencesFor, f as sectionAnchor, g as usesStructureLayout, i as deriveSectionNumbering, l as normalizeStructure, m as structureIssues, o as isSectionNode, p as sortByOrder, r as deriveElementReferences, s as mergeSectionReferences, t as PAGE_DOCUMENT, u as numberingFor } from "./chunks/structure-CKBtQHJq.js";
|
|
4
4
|
import { a as goToQuestion, c as missing, f as progress, g as visibleSteps, h as stepKind, i as goTo, l as move, m as settle, n as enterAdvances, o as isReadOnlyStatus, p as questionsOf, s as linkTo, t as defaultMode, u as positionFromLink } from "./chunks/forms-DxA9WzCt.js";
|
|
@@ -12,18 +12,34 @@ function CellPlaceholder({ state }) {
|
|
|
12
12
|
"aria-busy": state === "loading"
|
|
13
13
|
});
|
|
14
14
|
}
|
|
15
|
-
function
|
|
15
|
+
function CellHidden() {
|
|
16
|
+
return jsx("div", {
|
|
17
|
+
className: "cell-hidden",
|
|
18
|
+
"data-cell-state": "hidden-empty",
|
|
19
|
+
role: "note",
|
|
20
|
+
children: "hidden (empty)"
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function CellNotice({ state, component, onRetry, code, showCode, children }) {
|
|
16
24
|
return jsxs("div", {
|
|
17
25
|
className: "cell-notice",
|
|
18
26
|
"data-cell-state": state,
|
|
19
27
|
role: state === "error" ? "alert" : "note",
|
|
20
28
|
...state === "not-found" && component ? { "data-missing-component": component } : {},
|
|
21
|
-
children: [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
children: [
|
|
30
|
+
children,
|
|
31
|
+
code && showCode && jsxs(Fragment$1, { children: [" ", jsx("code", {
|
|
32
|
+
className: "cell-notice__code",
|
|
33
|
+
"data-cell-code": code,
|
|
34
|
+
children: code
|
|
35
|
+
})] }),
|
|
36
|
+
onRetry && jsxs(Fragment$1, { children: [" ", jsx("button", {
|
|
37
|
+
type: "button",
|
|
38
|
+
className: "cell-notice__retry",
|
|
39
|
+
onClick: onRetry,
|
|
40
|
+
children: "Try again"
|
|
41
|
+
})] })
|
|
42
|
+
]
|
|
27
43
|
});
|
|
28
44
|
}
|
|
29
45
|
var CellErrorBoundary = class extends Component {
|
|
@@ -219,6 +235,23 @@ function mergeActions(a, b) {
|
|
|
219
235
|
...b
|
|
220
236
|
} : void 0;
|
|
221
237
|
}
|
|
238
|
+
function boundProps(cell, ctx, env, injectedProps) {
|
|
239
|
+
const out = { ...resolveReferences(cell.props ?? {}, ctx) };
|
|
240
|
+
for (const id of cell.children ?? []) {
|
|
241
|
+
const child = env.cellsById.get(id);
|
|
242
|
+
if (!child) continue;
|
|
243
|
+
const slot = typeof child.slot === "string" && child.slot ? child.slot : "children";
|
|
244
|
+
if (slot === "item" && cell.props?.each !== void 0) {
|
|
245
|
+
const each = out.each;
|
|
246
|
+
out[slot] = Array.isArray(each) ? each : out[slot];
|
|
247
|
+
} else out[slot] = [...Array.isArray(out[slot]) ? out[slot] : [], id];
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
...out,
|
|
251
|
+
...injectedProps,
|
|
252
|
+
...env.cellProps?.(cell)
|
|
253
|
+
};
|
|
254
|
+
}
|
|
222
255
|
function CellView({ cell, env, nested = false, injectedProps }) {
|
|
223
256
|
const frame = useRef(null);
|
|
224
257
|
const store = useCellStore(cell, env.scope, env.store);
|
|
@@ -305,8 +338,19 @@ function CellView({ cell, env, nested = false, injectedProps }) {
|
|
|
305
338
|
context
|
|
306
339
|
]);
|
|
307
340
|
if (!passesConditions(cell.conditions, ctx)) return null;
|
|
341
|
+
const deciding = Boolean(cell.hide_when_empty?.length && cell.component && !cell.embed && !failedLabels(cell, ctx.data).length);
|
|
342
|
+
const problem = deciding ? hideWhenEmptyProblem(cell, ctx.data) : null;
|
|
343
|
+
const hidden = deciding && !problem && hiddenWhenEmpty(cell, boundProps(cell, ctx, env, injectedProps), ctx.data);
|
|
344
|
+
if (hidden && !env.showHiddenCells) return null;
|
|
308
345
|
let body;
|
|
309
|
-
if (
|
|
346
|
+
if (hidden) body = jsx(CellHidden, {});
|
|
347
|
+
else if (problem) body = jsx(CellNotice, {
|
|
348
|
+
state: "error",
|
|
349
|
+
code: problem,
|
|
350
|
+
showCode: env.showProblemCodes,
|
|
351
|
+
children: "This part of the page couldn't load."
|
|
352
|
+
});
|
|
353
|
+
else if (cell.embed) body = env.renderEmbed?.(cell.id) ?? null;
|
|
310
354
|
else if (!cell.component) body = jsx(CellPlaceholder, { state: "pending" });
|
|
311
355
|
else if (failedLabels(cell, ctx.data).length) body = jsx(CellNotice, {
|
|
312
356
|
state: "error",
|
|
@@ -528,7 +572,7 @@ var warn = (d) => console.warn(`[render] ${d.code}${d.cellId ? ` (cell ${d.cellI
|
|
|
528
572
|
function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, environment }) {
|
|
529
573
|
const { page, cells } = runtime;
|
|
530
574
|
const declared = useMemo(() => new Set(runtime.declared), [runtime.declared]);
|
|
531
|
-
const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, cellProps, retry } = environment;
|
|
575
|
+
const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, cellProps, retry, showHiddenCells, showProblemCodes } = environment;
|
|
532
576
|
useEffect(() => {
|
|
533
577
|
for (const d of runtime.diagnostics) onDiagnostic(d);
|
|
534
578
|
}, [runtime.diagnostics, onDiagnostic]);
|
|
@@ -556,6 +600,8 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
556
600
|
onDiagnostic,
|
|
557
601
|
frameProps,
|
|
558
602
|
cellProps,
|
|
603
|
+
showHiddenCells,
|
|
604
|
+
showProblemCodes,
|
|
559
605
|
renderEmbed: (cellId) => {
|
|
560
606
|
const embedded = runtime.embeds?.[cellId];
|
|
561
607
|
if (!embedded) return jsx(CellNotice, {
|
|
@@ -607,6 +653,8 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
607
653
|
frameProps,
|
|
608
654
|
cellProps,
|
|
609
655
|
retry,
|
|
656
|
+
showHiddenCells,
|
|
657
|
+
showProblemCodes,
|
|
610
658
|
environment
|
|
611
659
|
]);
|
|
612
660
|
const structured = usesStructureLayout(page.layout);
|
|
@@ -662,7 +710,7 @@ function useFormsRuntime(o) {
|
|
|
662
710
|
const steps = useMemo(() => visibleSteps(o.model, values), [o.model, values]);
|
|
663
711
|
const [at, setAt] = useState(() => positionFromLink(visibleSteps(o.model, answeredOf(o.initial)), mode, o.link ?? {}));
|
|
664
712
|
const here = settle(steps, mode, at);
|
|
665
|
-
const readOnly = isReadOnlyStatus(status);
|
|
713
|
+
const readOnly = o.readOnly === true || isReadOnlyStatus(status);
|
|
666
714
|
const opts = useRef(o);
|
|
667
715
|
opts.current = o;
|
|
668
716
|
const expected = useRef(new Map(Object.entries(o.initial).map(([k, a]) => [k, a.stateId ?? null])));
|
|
@@ -713,7 +761,7 @@ function useFormsRuntime(o) {
|
|
|
713
761
|
return chain.current;
|
|
714
762
|
}, []);
|
|
715
763
|
const change = useCallback((key, value) => {
|
|
716
|
-
if (
|
|
764
|
+
if (readOnly) return;
|
|
717
765
|
setValues((v) => ({
|
|
718
766
|
...v,
|
|
719
767
|
[key]: value
|
|
@@ -721,7 +769,7 @@ function useFormsRuntime(o) {
|
|
|
721
769
|
pending.current.set(key, value);
|
|
722
770
|
if (timer.current) clearTimeout(timer.current);
|
|
723
771
|
timer.current = setTimeout(() => void flush(), FORM_SAVE_DEBOUNCE_MS);
|
|
724
|
-
}, [flush,
|
|
772
|
+
}, [flush, readOnly]);
|
|
725
773
|
useEffect(() => {
|
|
726
774
|
const onLeave = () => void flush();
|
|
727
775
|
window.addEventListener("pagehide", onLeave);
|
|
@@ -841,7 +889,7 @@ function useFormsRuntime(o) {
|
|
|
841
889
|
refusal: refusals[q.key] ?? null,
|
|
842
890
|
inputId: answerInputId(q.key),
|
|
843
891
|
...port.upload ? { upload: async (file) => {
|
|
844
|
-
if (
|
|
892
|
+
if (readOnly) return {
|
|
845
893
|
ok: false,
|
|
846
894
|
refusal: words("FORM_NOT_OPEN")
|
|
847
895
|
};
|
|
@@ -919,7 +967,7 @@ function useFormsRuntime(o) {
|
|
|
919
967
|
run: () => void runSubmit(),
|
|
920
968
|
blocked: o.model.submitRequired === "block" && allMissing.length > 0
|
|
921
969
|
} : null,
|
|
922
|
-
reopen: status === "submitted" && o.model.submittable !== false ? {
|
|
970
|
+
reopen: status === "submitted" && !o.readOnly && o.model.submittable !== false ? {
|
|
923
971
|
label: "Edit answers",
|
|
924
972
|
run: () => void runReopen()
|
|
925
973
|
} : null,
|
|
@@ -980,4 +1028,4 @@ function bindActions(v, path, latest) {
|
|
|
980
1028
|
if (v && typeof v === "object") return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, bindActions(x, [...path, k], latest)]));
|
|
981
1029
|
return v;
|
|
982
1030
|
}
|
|
983
|
-
export { CellErrorBoundary, CellNotice, CellPlaceholder, CellView, FORM_SAVE_DEBOUNCE_MS, PageRenderer, StructureView, answerInputId, cellLabels, useCellStore, useContainerSize, useFormsRuntime, usePaging, useStructureFacts };
|
|
1031
|
+
export { CellErrorBoundary, CellHidden, CellNotice, CellPlaceholder, CellView, FORM_SAVE_DEBOUNCE_MS, PageRenderer, StructureView, answerInputId, cellLabels, useCellStore, useContainerSize, useFormsRuntime, usePaging, useStructureFacts };
|
package/dist/styles.css
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
--cell-placeholder-bg: var(--color-surface-sunken, #f1f1f1);
|
|
7
7
|
--cell-notice-bg: var(--color-warning-surface, #fff4d6);
|
|
8
8
|
--cell-notice-fg: var(--color-warning, #6b4e00);
|
|
9
|
+
--cell-hidden-border: var(--color-border, #c8c8c8);
|
|
10
|
+
--cell-hidden-fg: var(--color-text-muted, #6b6b6b);
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
[data-page-container] { font-family: var(--font-body, system-ui, sans-serif); color: var(--color-text, inherit); }
|
|
@@ -17,7 +19,9 @@
|
|
|
17
19
|
.cell-placeholder[aria-busy='true'] { animation: cell-pulse 1.5s ease-in-out infinite; }
|
|
18
20
|
@keyframes cell-pulse { 50% { opacity: 0.55; } }
|
|
19
21
|
@media (prefers-reduced-motion: reduce) { .cell-placeholder[aria-busy='true'] { animation: none; } }
|
|
22
|
+
.cell-hidden { padding: 0.125rem 0.5rem; border: 1px dashed var(--cell-hidden-border); border-radius: 0.375rem; color: var(--cell-hidden-fg); font-size: 0.75rem; line-height: 1.5; }
|
|
20
23
|
.cell-notice { padding: 0.75rem 1rem; border-radius: 0.5rem; background: var(--cell-notice-bg); color: var(--cell-notice-fg); }
|
|
24
|
+
.cell-notice__code { font-family: var(--font-mono, ui-monospace, monospace); font-size: 0.75rem; }
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
[data-show-when] { display: none; }
|
|
@@ -45,6 +49,8 @@
|
|
|
45
49
|
--cell-placeholder-bg: #262626;
|
|
46
50
|
--cell-notice-bg: #3a300f;
|
|
47
51
|
--cell-notice-fg: #f5dc9a;
|
|
52
|
+
--cell-hidden-border: #4a4a4a;
|
|
53
|
+
--cell-hidden-fg: #a3a3a3;
|
|
48
54
|
}
|
|
49
55
|
}
|
|
50
56
|
|
|
@@ -9,6 +9,9 @@ export declare function projectCellData(cell: PageCell, ctx: DataContext): {
|
|
|
9
9
|
status: CellStatus;
|
|
10
10
|
} | null;
|
|
11
11
|
export declare function failedLabels(cell: PageCell, data: DataContext): string[];
|
|
12
|
+
export declare function isEmptyPropValue(value: unknown): boolean;
|
|
13
|
+
export declare function hideWhenEmptyProblem(cell: Pick<PageCell, 'hide_when_empty' | 'props'>, data: DataContext): 'QUERY_UNRESOLVED' | null;
|
|
14
|
+
export declare function hiddenWhenEmpty(cell: Pick<PageCell, 'hide_when_empty' | 'props'>, props: Record<string, unknown>, data: DataContext): boolean;
|
|
12
15
|
export type AssembledInputs = {
|
|
13
16
|
resolvedProps: Record<string, unknown>;
|
|
14
17
|
children: unknown;
|
|
@@ -2,7 +2,8 @@ import type { Diagnostic } from './graph.js';
|
|
|
2
2
|
import type { PageCell } from './types.js';
|
|
3
3
|
export declare const HYDRATED_CELL_FIELDS: readonly ["component", "props", "layout", "conditions", "children", "traversal", "data", "bundle_ref", "actions", "embed"];
|
|
4
4
|
export declare const STORE_FIELDS: readonly ["selections", "viewState", "live"];
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const RENDER_FIELDS: readonly ["hide_when_empty"];
|
|
6
|
+
export declare const CONTENT_FIELDS: readonly [...("component" | "props" | "conditions" | "children" | "traversal" | "data" | "bundle_ref" | "actions" | "embed")[], "selections", "viewState", "live", "hide_when_empty"];
|
|
6
7
|
export type CellSource = 'inline' | 'node' | 'fallback' | 'pending';
|
|
7
8
|
export type ResolvedCell = PageCell & {
|
|
8
9
|
source: CellSource;
|
|
@@ -51,6 +51,10 @@ export declare const DIAGNOSTICS: {
|
|
|
51
51
|
readonly meaning: "A literal prop value fails its schema.";
|
|
52
52
|
readonly fix: "Write the value in the shape `props_schema` gives, or bind it with a whole-string `@label.path` reference.";
|
|
53
53
|
};
|
|
54
|
+
readonly HIDE_WHEN_EMPTY_INVALID: {
|
|
55
|
+
readonly meaning: "A cell’s `hide_when_empty` isn’t a list of prop names.";
|
|
56
|
+
readonly fix: "Write `hide_when_empty: [\"title\", \"items\"]`: the props that, all empty once bound (null, blank text, `[]`, `{}`), leave the cell out.";
|
|
57
|
+
};
|
|
54
58
|
readonly CELL_UNKNOWN_CHILD: {
|
|
55
59
|
readonly meaning: "`children` names a cell that is not on the page.";
|
|
56
60
|
readonly fix: "List only ids of cells on this page in `children`.";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
export { CONTENT_FIELDS, hasRef, HYDRATED_CELL_FIELDS, normalizeCell, resolveCell, rootCells, STORE_FIELDS, type CellSource, type ResolvedCell } from './cells.js';
|
|
1
|
+
export { CONTENT_FIELDS, hasRef, HYDRATED_CELL_FIELDS, normalizeCell, resolveCell, RENDER_FIELDS, rootCells, STORE_FIELDS, type CellSource, type ResolvedCell } from './cells.js';
|
|
2
2
|
export { buildDataContext, collectDeclarations, collectDescriptors, collectStatic, readField, resolveDeclarations, type ResolvedDeclaration, type StateRead } from './data-context.js';
|
|
3
3
|
export { mergeStates, needsWalk, readWalk, referencedLabels, RESERVED_LABELS, resolveWalkStart, stateNames, stateValue, systemsFromGraphs, systemsFromProcess, walkKey, walkRequest, type Diagnostic, type GraphSystem, type ProcessSystems, type RawWalk, type WalkBinding, type WalkRequest, type WalkStart, } from './graph.js';
|
|
4
|
+
export { LAYER_ROLES, layerName, type LayerType } from './layers.js';
|
|
4
5
|
export { loadPageData, resolveDataSystem, resolveSystems, type CellData, type CellWalk, type GraphSource, type NodeRecordRow, type PageRuntime, type PageScope, type QueryPage, type ReadContext, type StateRow } from './load-page.js';
|
|
5
6
|
export { descriptorShape, orderByVariable, PAGING_VARIABLES, pageVariables, prepareDocument, queryKey, RENDER_FUNCTIONS, RENDER_FUNCTIONS_AHEAD, resolveDescriptorVariables, selectionShape, shapeAt, UnsafeDocumentError, validateDescriptor, VARIABLE_NAMESPACES, variableLabels, variableReferences, type PreparedDocument, type ResolvedVariables, type SelectionShape, } from './query.js';
|
|
6
7
|
export { selectionIssues } from './selected.js';
|
|
@@ -13,7 +14,7 @@ export { pageRuntimeFromValues } from './values.js';
|
|
|
13
14
|
export { actionBindingKey, actionProblems, actionReferences, declaredActions, normalizeActionDeclaration, projectCellActions, resolveAction, type RunAction } from './actions.js';
|
|
14
15
|
export type { ActionDeclaration } from '@peripheries/runtime';
|
|
15
16
|
export type * from './types.js';
|
|
16
|
-
export { assembleCellProps, projectCellData, type CellStatus } from './cell-props.js';
|
|
17
|
+
export { assembleCellProps, hiddenWhenEmpty, hideWhenEmptyProblem, isEmptyPropValue, projectCellData, type CellStatus } from './cell-props.js';
|
|
17
18
|
export { cellAttributes, cellPlacementStyle, pageContainerStyle } from './layout.js';
|
|
18
19
|
export { deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, mergeSectionReferences, nodePrintStyle, normalizeStructure, numberingFor, PAGE_DOCUMENT, referencesFor, SECTION_KINDS, sectionAnchor, structureIssues, tableOfContents, usesStructureLayout, type ContentsEntry, type LayoutNode, type SectionNumbering, type SectionReference, type SectionReferences, } from './structure.js';
|
|
19
20
|
export { _clearBundleCache, isComponentExport, loadBundle, loadBundles, loadBundlesSettled, projectModule, runtimeReady, type BundleFiles, type BundleRow, type LoadedBundle, type LoadedBundles, } from './bundles/load.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const LAYER_ROLES: {
|
|
2
|
+
readonly answer: null;
|
|
3
|
+
readonly "appraisal-system": "appraisal";
|
|
4
|
+
readonly "data-system": "data";
|
|
5
|
+
readonly edits: null;
|
|
6
|
+
readonly "model-system": "model";
|
|
7
|
+
readonly organisation: null;
|
|
8
|
+
readonly "process-system": "process";
|
|
9
|
+
readonly question: null;
|
|
10
|
+
readonly submission: null;
|
|
11
|
+
};
|
|
12
|
+
export type LayerType = keyof typeof LAYER_ROLES;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DeclaredBinding, PageCell, QueryDescriptor } from '@peripheries/runtime';
|
|
1
|
+
import type { DeclaredBinding, PageCell as RuntimePageCell, QueryDescriptor } from '@peripheries/runtime';
|
|
2
2
|
export type DataPage = {
|
|
3
3
|
hasMore: boolean;
|
|
4
4
|
endCursor: string | null;
|
|
@@ -37,7 +37,10 @@ export type DataOrigin = {
|
|
|
37
37
|
kind: 'reserved';
|
|
38
38
|
};
|
|
39
39
|
export type DataContext = Record<string, DataEntry>;
|
|
40
|
-
export type { CellData, CellLayout, DeclaredBinding,
|
|
40
|
+
export type { CellData, CellLayout, DeclaredBinding, ResponsiveBucket } from '@peripheries/runtime';
|
|
41
|
+
export type PageCell = RuntimePageCell & {
|
|
42
|
+
hide_when_empty?: string[];
|
|
43
|
+
};
|
|
41
44
|
export type PageContent = {
|
|
42
45
|
cells?: PageCell[];
|
|
43
46
|
data?: {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { CONDITION_OPS, evaluateCondition, isConditionOp, normalizeCondition, normalizeOperator, type Condition, type ConditionClause, type ConditionOp } from './conditions.js';
|
|
2
2
|
export { defaultMode, enterAdvances, fromPageSteps, goTo, goToQuestion, isReadOnlyStatus, linkTo, missing, move, positionFromLink, positionsOf, progress, questionsOf, settle, stepKind, visibleSteps, type DisplayMode, type FormChapter, type FormItem, type FormItemKind, type FormLink, type FormModel, type FormQuestion, type FormQuestionDefinition, type FormStep, type Position, type StepKind, type StepProgress, type SubmissionStatus, } from './model.js';
|
|
3
3
|
export type { AnswerToSave, FileToUpload, FormsPort, FormsRefusal, FormsResult } from './port.js';
|
|
4
|
+
export type { FormContentBlock, FormSection } from './section.js';
|
|
@@ -10,10 +10,10 @@ export type FormQuestion = {
|
|
|
10
10
|
};
|
|
11
11
|
export type FormQuestionDefinition = {
|
|
12
12
|
type: string;
|
|
13
|
-
options?: unknown[];
|
|
14
|
-
validation?: Record<string, unknown
|
|
15
|
-
description?: string;
|
|
16
|
-
helpText?: string;
|
|
13
|
+
options?: unknown[] | null;
|
|
14
|
+
validation?: Record<string, unknown> | null;
|
|
15
|
+
description?: string | null;
|
|
16
|
+
helpText?: string | null;
|
|
17
17
|
};
|
|
18
18
|
export type FormItemKind = 'question' | 'content' | 'document' | 'review' | 'upload' | 'other';
|
|
19
19
|
export type FormItem = {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Condition } from './conditions.js';
|
|
2
|
+
import type { FormQuestionDefinition } from './model.js';
|
|
3
|
+
export type FormContentBlock = {
|
|
4
|
+
id: string;
|
|
5
|
+
type: string;
|
|
6
|
+
when?: Condition | null;
|
|
7
|
+
[prop: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
export type FormSection = {
|
|
10
|
+
id: string;
|
|
11
|
+
sectionId: string;
|
|
12
|
+
title: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
sectionType?: string;
|
|
15
|
+
questions: Array<{
|
|
16
|
+
key: string;
|
|
17
|
+
label: string;
|
|
18
|
+
required: boolean;
|
|
19
|
+
definition: FormQuestionDefinition | null;
|
|
20
|
+
}>;
|
|
21
|
+
content: FormContentBlock[];
|
|
22
|
+
};
|
|
@@ -2,10 +2,13 @@ import { Component, type ReactNode } from 'react';
|
|
|
2
2
|
export declare function CellPlaceholder({ state }: {
|
|
3
3
|
state: 'loading' | 'pending';
|
|
4
4
|
}): import("react").JSX.Element;
|
|
5
|
-
export declare function
|
|
5
|
+
export declare function CellHidden(): import("react").JSX.Element;
|
|
6
|
+
export declare function CellNotice({ state, component, onRetry, code, showCode, children }: {
|
|
6
7
|
state: 'not-found' | 'error';
|
|
7
8
|
component?: string;
|
|
8
9
|
onRetry?: () => void;
|
|
10
|
+
code?: string;
|
|
11
|
+
showCode?: boolean;
|
|
9
12
|
children: ReactNode;
|
|
10
13
|
}): import("react").JSX.Element;
|
|
11
14
|
export declare class CellErrorBoundary extends Component<{
|
|
@@ -38,6 +38,8 @@ export type CellEnvironment = {
|
|
|
38
38
|
onDiagnostic?: (d: Diagnostic) => void;
|
|
39
39
|
frameProps?: (cell: PageCell, contract: ComponentContract | undefined) => FrameProps | undefined;
|
|
40
40
|
cellProps?: (cell: PageCell) => Record<string, unknown> | undefined;
|
|
41
|
+
showHiddenCells?: boolean;
|
|
42
|
+
showProblemCodes?: boolean;
|
|
41
43
|
};
|
|
42
44
|
export type FrameProps = {
|
|
43
45
|
attributes?: Record<string, string>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { CellErrorBoundary, CellNotice, CellPlaceholder } from './cell-states.js';
|
|
1
|
+
export { CellErrorBoundary, CellHidden, CellNotice, CellPlaceholder } from './cell-states.js';
|
|
2
2
|
export { CellView, type CellEnvironment, type FrameProps } from './cell-view.js';
|
|
3
3
|
export { PageRenderer, type PageRendererProps, type RendererEnvironment } from './page-renderer.js';
|
|
4
4
|
export { StructureView, useStructureFacts } from './structure-view.js';
|
|
@@ -23,6 +23,8 @@ export type RendererEnvironment = {
|
|
|
23
23
|
retry?: () => void;
|
|
24
24
|
frameProps?: (cell: PageCell, contract: ComponentContract | undefined) => FrameProps | undefined;
|
|
25
25
|
cellProps?: (cell: PageCell) => Record<string, unknown> | undefined;
|
|
26
|
+
showHiddenCells?: boolean;
|
|
27
|
+
showProblemCodes?: boolean;
|
|
26
28
|
};
|
|
27
29
|
export type PageRendererProps = {
|
|
28
30
|
runtime: PageRuntime;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peripheries/renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "The one renderer for pages of federated component bundles: a framework-free core, a React renderer, the runtime a page boots with, and golden pages for testing.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": [
|