@peripheries/renderer 0.24.0 → 0.26.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 +36 -0
- package/dist/catalog.js +3 -3
- package/dist/chunks/{page-bundles-CPj_vx-J.js → page-bundles-_wsGO9WU.js} +10 -4
- package/dist/chunks/{projection-zhu32_KJ.js → projection-e8MHn6Bt.js} +40 -2
- package/dist/chunks/{query-D6xQbTFK.js → query-CNaB25jE.js} +101 -0
- package/dist/chunks/{structure-CKBtQHJq.js → structure-B3ikc0oD.js} +27 -2
- package/dist/chunks/{validate-BcB_PA1k.js → validate-DRkCpQaY.js} +46 -6
- package/dist/core.js +19 -7
- package/dist/react.js +70 -14
- package/dist/runtime.js +20 -1
- package/dist/styles.css +6 -0
- package/dist/testing.js +2 -2
- package/dist/types/core/bundles/page-bundles.d.ts +2 -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 +12 -0
- package/dist/types/core/host-reads.d.ts +6 -0
- package/dist/types/core/index.d.ts +5 -4
- package/dist/types/core/types.d.ts +5 -2
- package/dist/types/core/validate.d.ts +11 -7
- package/dist/types/react/cell-states.d.ts +4 -1
- package/dist/types/react/cell-view.d.ts +4 -0
- package/dist/types/react/index.d.ts +1 -1
- package/dist/types/react/page-renderer.d.ts +4 -0
- package/dist/types/runtime/install.d.ts +3 -1
- package/dist/types/runtime/load-global.d.ts +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -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,36 @@ bundle's `ThemeProvider` export.
|
|
|
77
83
|
|
|
78
84
|
## Versions
|
|
79
85
|
|
|
86
|
+
- **Unreleased:** `RENDER_FUNCTIONS` adds `pages_awaiting_release(p_project_id)`:
|
|
87
|
+
a project's pages whose newest main page-state is newer than the one their
|
|
88
|
+
client channel's release holds, for staff (an empty array for anyone else).
|
|
89
|
+
- **Removable in the next minor:** `GraphSource.processSystems` (the process's cached system
|
|
90
|
+
columns, read only by a source without `graphSystems`). The host no longer implements it;
|
|
91
|
+
`graphSystems` is the way, and the process columns it reads are being dropped.
|
|
92
|
+
- **0.25.0** (2026-10-24): `hide_when_empty`, a cell-level list of prop names.
|
|
93
|
+
- **A cell with `hide_when_empty: ["title", "items"]`** renders nothing, and leaves no gap,
|
|
94
|
+
when every prop it names is empty once bound: null, undefined, text that is blank once
|
|
95
|
+
trimmed, `[]` or `{}`. `0` and `false` are content. A slot or `children` filled by child
|
|
96
|
+
cells is content. Print follows the screen. The check runs before the bundles load, so a
|
|
97
|
+
server render and the browser agree.
|
|
98
|
+
- **A refused, failed or unresolved read is not empty.** A named prop that reads a label whose
|
|
99
|
+
read was refused or failed keeps the cell's error notice. One whose query never ran because
|
|
100
|
+
its own reference resolved to nothing (`QUERY_UNRESOLVED`) shows the same notice instead of
|
|
101
|
+
hiding (`hideWhenEmptyProblem`). A label still loading isn't decided yet (the cell renders).
|
|
102
|
+
- **`RendererEnvironment.showProblemCodes`**: a problem notice adds its diagnostic code
|
|
103
|
+
(`data-cell-code`, `.cell-notice__code`) for staff and editors; a client reads only "This
|
|
104
|
+
part of the page couldn't load." The host sets it in the platform environment and in a
|
|
105
|
+
proposal preview.
|
|
106
|
+
- **`RendererEnvironment.showHiddenCells`**: an editor, a harness or a preview shows a hidden
|
|
107
|
+
cell as a small "hidden (empty)" placeholder (`CellHidden`, `.cell-hidden`).
|
|
108
|
+
- **Validation:** `validatePage` reports `PROP_UNKNOWN` (warning) at
|
|
109
|
+
`content.cells[i].hide_when_empty[j]` for a name the component's `props_schema` doesn't
|
|
110
|
+
declare, and `HIDE_WHEN_EMPTY_INVALID` (error) for anything but a non-empty list of names.
|
|
111
|
+
- A ref cell's node owns `hide_when_empty` (`CONTENT_FIELDS`, via `RENDER_FIELDS`). `/core`
|
|
112
|
+
exports `hiddenWhenEmpty`, `hideWhenEmptyProblem` and `isEmptyPropValue`. `PAGE_RULES` names the key.
|
|
113
|
+
- The renderer's `PageCell` type adds `hide_when_empty?: string[]`; `@peripheries/runtime`'s
|
|
114
|
+
`PageCell` gains it at its next release.
|
|
115
|
+
|
|
80
116
|
- **0.24.0** (2026-10-20): one renderer batch (CX).
|
|
81
117
|
- **`layerName(system)` and `LAYER_ROLES`** in `/core`: a system's state name (its layer's role,
|
|
82
118
|
else a registered layer's own type, `question`, `answer`, …) from the layer catalog, which is
|
package/dist/catalog.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { x as isEach } from "./chunks/query-
|
|
2
|
-
import {
|
|
1
|
+
import { x as isEach } from "./chunks/query-CNaB25jE.js";
|
|
2
|
+
import { a as eachFormProblems, c as validatePage, i as componentsFor } from "./chunks/validate-DRkCpQaY.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}`;
|
|
@@ -216,7 +216,7 @@ var asNode = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : void 0
|
|
|
216
216
|
function propsAgainstSchemas(page, catalog, ajv) {
|
|
217
217
|
const out = [];
|
|
218
218
|
(Array.isArray(page.content?.cells) ? page.content.cells : []).forEach((cell, i) => {
|
|
219
|
-
const properties = cell?.component ? catalog
|
|
219
|
+
const properties = cell?.component ? componentsFor(catalog, cell)[cell.component]?.props_schema?.properties : void 0;
|
|
220
220
|
for (const [prop, value] of Object.entries(cell.props ?? {})) {
|
|
221
221
|
const schema = properties?.[prop];
|
|
222
222
|
const path = `content.cells[${i}].props.${prop}`;
|
|
@@ -15,16 +15,22 @@ function rowMatches(ref, row) {
|
|
|
15
15
|
if (ref.kind === "pinned") return row.id === ref.bundleId;
|
|
16
16
|
return row.bundle_name === ref.bundle && (ref.kind === "lineage-in-org" ? row.org_id === ref.orgId : row.org_slug === ref.orgSlug);
|
|
17
17
|
}
|
|
18
|
+
function rowsInScope(rows, scope) {
|
|
19
|
+
return rows.filter((row) => scope.some((r) => rowMatches(r, row)));
|
|
20
|
+
}
|
|
21
|
+
function rowForCell(rows, cell, pageOrgId) {
|
|
22
|
+
const ref = normalizeRef(cell.bundle_ref, pageOrgId);
|
|
23
|
+
return ref && rows.find((r) => rowMatches(ref, r)) || null;
|
|
24
|
+
}
|
|
18
25
|
function pageBundles(scope, rows, loaded, pageOrgId, failed = false) {
|
|
19
26
|
const byRow = new Map((loaded ?? []).map((b) => [b.id, b]));
|
|
20
27
|
return {
|
|
21
28
|
failed,
|
|
22
|
-
scope: loaded ? rows
|
|
29
|
+
scope: loaded ? rowsInScope(rows, scope).flatMap((row) => byRow.get(row.id) ?? []) : null,
|
|
23
30
|
forCell: (cell) => {
|
|
24
|
-
const
|
|
25
|
-
const row = ref && rows.find((r) => rowMatches(ref, r));
|
|
31
|
+
const row = rowForCell(rows, cell, pageOrgId);
|
|
26
32
|
return (row && byRow.get(row.id)) ?? null;
|
|
27
33
|
}
|
|
28
34
|
};
|
|
29
35
|
}
|
|
30
|
-
export { pageBundles as n, pageBundleRefs as t };
|
|
36
|
+
export { rowsInScope as i, pageBundles as n, rowForCell as r, pageBundleRefs as t };
|
|
@@ -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 };
|
|
@@ -299,6 +299,17 @@ var RENDER_FUNCTIONS = {
|
|
|
299
299
|
"edge",
|
|
300
300
|
"graph"
|
|
301
301
|
],
|
|
302
|
+
pages_awaiting_release: [
|
|
303
|
+
"graph",
|
|
304
|
+
"graph_node",
|
|
305
|
+
"node",
|
|
306
|
+
"process",
|
|
307
|
+
"system",
|
|
308
|
+
"edge",
|
|
309
|
+
"system_version",
|
|
310
|
+
"system_node_version",
|
|
311
|
+
"system_node_state"
|
|
312
|
+
],
|
|
302
313
|
versions_for: ["system_version"],
|
|
303
314
|
version_diff: [
|
|
304
315
|
"system_version",
|
|
@@ -316,6 +327,96 @@ var RENDER_FUNCTIONS = {
|
|
|
316
327
|
"system_node_state",
|
|
317
328
|
"graph_node",
|
|
318
329
|
"edge"
|
|
330
|
+
],
|
|
331
|
+
page_read: [
|
|
332
|
+
"edge",
|
|
333
|
+
"graph",
|
|
334
|
+
"graph_node",
|
|
335
|
+
"node",
|
|
336
|
+
"process",
|
|
337
|
+
"system_node_state",
|
|
338
|
+
"system_node_version",
|
|
339
|
+
"system_version"
|
|
340
|
+
],
|
|
341
|
+
page_by_type: [
|
|
342
|
+
"edge",
|
|
343
|
+
"graph",
|
|
344
|
+
"graph_node",
|
|
345
|
+
"node",
|
|
346
|
+
"process",
|
|
347
|
+
"system_node_state",
|
|
348
|
+
"system_node_version",
|
|
349
|
+
"system_version"
|
|
350
|
+
],
|
|
351
|
+
page_list: [
|
|
352
|
+
"edge",
|
|
353
|
+
"graph",
|
|
354
|
+
"graph_node",
|
|
355
|
+
"node",
|
|
356
|
+
"process",
|
|
357
|
+
"system_node_state",
|
|
358
|
+
"system_node_version",
|
|
359
|
+
"system_version"
|
|
360
|
+
],
|
|
361
|
+
form_status_read: [
|
|
362
|
+
"client_project",
|
|
363
|
+
"edge",
|
|
364
|
+
"graph",
|
|
365
|
+
"graph_edge",
|
|
366
|
+
"graph_node",
|
|
367
|
+
"node",
|
|
368
|
+
"process",
|
|
369
|
+
"system",
|
|
370
|
+
"system_node_state",
|
|
371
|
+
"system_version"
|
|
372
|
+
],
|
|
373
|
+
page_read_many: [
|
|
374
|
+
"edge",
|
|
375
|
+
"graph",
|
|
376
|
+
"graph_node",
|
|
377
|
+
"node",
|
|
378
|
+
"process",
|
|
379
|
+
"system_node_state",
|
|
380
|
+
"system_node_version",
|
|
381
|
+
"system_version"
|
|
382
|
+
],
|
|
383
|
+
page_list_recent: [
|
|
384
|
+
"edge",
|
|
385
|
+
"graph",
|
|
386
|
+
"graph_node",
|
|
387
|
+
"node",
|
|
388
|
+
"process",
|
|
389
|
+
"system_node_state",
|
|
390
|
+
"system_node_version",
|
|
391
|
+
"system_version"
|
|
392
|
+
],
|
|
393
|
+
page_anchor_of_scope: [
|
|
394
|
+
"edge",
|
|
395
|
+
"graph",
|
|
396
|
+
"graph_node",
|
|
397
|
+
"node",
|
|
398
|
+
"process",
|
|
399
|
+
"system_node_state",
|
|
400
|
+
"system_node_version",
|
|
401
|
+
"system_version"
|
|
402
|
+
],
|
|
403
|
+
page_summaries: [
|
|
404
|
+
"edge",
|
|
405
|
+
"graph",
|
|
406
|
+
"graph_node",
|
|
407
|
+
"node",
|
|
408
|
+
"process",
|
|
409
|
+
"system_node_state",
|
|
410
|
+
"system_node_version",
|
|
411
|
+
"system_version"
|
|
412
|
+
],
|
|
413
|
+
edit_proposal_rows: ["system_node_state"],
|
|
414
|
+
graph_list_items: [
|
|
415
|
+
"edge",
|
|
416
|
+
"edge_type",
|
|
417
|
+
"graph_edge",
|
|
418
|
+
"graph_node",
|
|
419
|
+
"node"
|
|
319
420
|
]
|
|
320
421
|
};
|
|
321
422
|
var RENDER_FUNCTIONS_AHEAD = { form_answers: "SCH M3b" };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { T as settled, w as resolveReferences, x as isEach } from "./query-
|
|
1
|
+
import { T as settled, w as resolveReferences, x as isEach } from "./query-CNaB25jE.js";
|
|
2
2
|
import { ACTION_FIELDS, ACTION_KINDS, SECTION_KINDS as SECTION_KINDS$1, isGraphAction } from "@peripheries/runtime";
|
|
3
3
|
var actionBindingKey = (registry, entityKey) => entityKey ? `${registry}#${entityKey}` : registry;
|
|
4
4
|
function normalizeActionDeclaration(decl) {
|
|
@@ -147,6 +147,31 @@ function declaredActions(cell, ctx, runAction) {
|
|
|
147
147
|
}
|
|
148
148
|
return Object.keys(out).length ? out : void 0;
|
|
149
149
|
}
|
|
150
|
+
var HOST_READ_KEY = "@host";
|
|
151
|
+
var NAME = /^[a-z][a-z0-9_]{0,63}$/;
|
|
152
|
+
var isHostRead = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && "@host" in value;
|
|
153
|
+
function hostReadProblem(value) {
|
|
154
|
+
const keys = Object.keys(value);
|
|
155
|
+
if (keys.length !== 1) return `a host read takes only "@host", not ${keys.filter((k) => k !== HOST_READ_KEY).map((k) => `"${k}"`).join(", ")}`;
|
|
156
|
+
const name = value[HOST_READ_KEY];
|
|
157
|
+
if (typeof name !== "string" || !NAME.test(name)) return "\"@host\" must be a name of lowercase letters, digits and underscores, starting with a letter";
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
function bindHostReads(props, reads, onUnknown) {
|
|
161
|
+
let out = null;
|
|
162
|
+
for (const [prop, value] of Object.entries(props)) {
|
|
163
|
+
if (!isHostRead(value)) continue;
|
|
164
|
+
out ??= { ...props };
|
|
165
|
+
const problem = hostReadProblem(value);
|
|
166
|
+
const name = value[HOST_READ_KEY];
|
|
167
|
+
if (!problem && reads && Object.hasOwn(reads, name) && typeof reads[name] === "function") out[prop] = reads[name];
|
|
168
|
+
else {
|
|
169
|
+
delete out[prop];
|
|
170
|
+
onUnknown?.(prop, problem ?? `the host lists no read named "${name}"`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return out ?? props;
|
|
174
|
+
}
|
|
150
175
|
var PAGE_DOCUMENT = "__page__";
|
|
151
176
|
function normalizeStructure(nodes) {
|
|
152
177
|
if (!Array.isArray(nodes)) return [];
|
|
@@ -380,4 +405,4 @@ function tableOfContents(structure, cells = []) {
|
|
|
380
405
|
});
|
|
381
406
|
return walk(normalizeStructure(structure), 1, PAGE_DOCUMENT);
|
|
382
407
|
}
|
|
383
|
-
export {
|
|
408
|
+
export { actionReferences as C, resolveAction as D, projectCellActions as E, actionProblems as S, normalizeActionDeclaration as T, HOST_READ_KEY as _, deriveSectionReferences as a, isHostRead as b, nodePrintStyle as c, referencesFor as d, sectionAnchor as f, usesStructureLayout as g, tableOfContents as h, deriveSectionNumbering as i, normalizeStructure as l, structureIssues as m, SECTION_KINDS$1 as n, isSectionNode as o, sortByOrder as p, deriveElementReferences as r, mergeSectionReferences as s, PAGE_DOCUMENT as t, numberingFor as u, bindHostReads as v, declaredActions as w, actionBindingKey as x, hostReadProblem as y };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as EACH, h as variableLabels, m as validateDescriptor, o as descriptorShape, p as shapeAt, v as EACH_DEFAULT_AS, x as isEach } from "./query-
|
|
2
|
-
import { g as usesStructureLayout, m as structureIssues,
|
|
1
|
+
import { _ as EACH, h as variableLabels, m as validateDescriptor, o as descriptorShape, p as shapeAt, v as EACH_DEFAULT_AS, x as isEach } from "./query-CNaB25jE.js";
|
|
2
|
+
import { S as actionProblems, b as isHostRead, g as usesStructureLayout, m as structureIssues, y as hostReadProblem } from "./structure-B3ikc0oD.js";
|
|
3
3
|
import { DEFAULT_STATE, STATE_NAMES, WALK_DEFAULTS, isDescriptorBinding, isGraphAction, isStateName } from "@peripheries/runtime";
|
|
4
4
|
var TIER_OF_GRAPH_TYPE = {
|
|
5
5
|
"meta-process": "meta",
|
|
@@ -270,6 +270,7 @@ function selectionIssues(cell, queries, at) {
|
|
|
270
270
|
visit(cell.conditions, `${at}.conditions`, top);
|
|
271
271
|
return out;
|
|
272
272
|
}
|
|
273
|
+
var componentsFor = (catalog, cell) => catalog.forCell?.(cell) ?? catalog.components;
|
|
273
274
|
var words = (name) => name.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().split(/[\s_-]+/).filter(Boolean);
|
|
274
275
|
function editDistance(a, b) {
|
|
275
276
|
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
@@ -491,6 +492,25 @@ function checkProjections(value, path, push, cellId) {
|
|
|
491
492
|
});
|
|
492
493
|
checkProjections(value.map, `${path}.map`, push, cellId);
|
|
493
494
|
}
|
|
495
|
+
function checkHostReads(props, path, push, cellId) {
|
|
496
|
+
if (!props || typeof props !== "object" || Array.isArray(props)) return;
|
|
497
|
+
for (const [key, value] of Object.entries(props)) if (isHostRead(value)) {
|
|
498
|
+
const problem = hostReadProblem(value);
|
|
499
|
+
if (problem) push({
|
|
500
|
+
severity: "error",
|
|
501
|
+
code: "HOST_READ_INVALID",
|
|
502
|
+
cellId,
|
|
503
|
+
path: `${path}.${key}`,
|
|
504
|
+
message: problem
|
|
505
|
+
});
|
|
506
|
+
} else if (value && typeof value === "object" && JSON.stringify(value).includes(`"@host"`)) push({
|
|
507
|
+
severity: "error",
|
|
508
|
+
code: "HOST_READ_INVALID",
|
|
509
|
+
cellId,
|
|
510
|
+
path: `${path}.${key}`,
|
|
511
|
+
message: "a host read is a prop of its own: it is not read inside another value"
|
|
512
|
+
});
|
|
513
|
+
}
|
|
494
514
|
function checkActions(cell, path, push) {
|
|
495
515
|
if (cell.actions === void 0) return;
|
|
496
516
|
if (!cell.actions || typeof cell.actions !== "object" || Array.isArray(cell.actions)) {
|
|
@@ -617,9 +637,10 @@ function validateCell(cell, catalog, path = "cell", ids, options = {}) {
|
|
|
617
637
|
message: "an inline cell needs a component"
|
|
618
638
|
});
|
|
619
639
|
if (cell.component && catalog && !cell.component.startsWith("@core/")) {
|
|
620
|
-
const
|
|
640
|
+
const components = componentsFor(catalog, cell);
|
|
641
|
+
const entry = components[cell.component];
|
|
621
642
|
if (!entry) {
|
|
622
|
-
const suggestions = nearestNames(cell.component, Object.keys(
|
|
643
|
+
const suggestions = nearestNames(cell.component, Object.keys(components));
|
|
623
644
|
push({
|
|
624
645
|
severity: nodeManaged ? "warning" : "error",
|
|
625
646
|
code: "CELL_UNKNOWN_COMPONENT",
|
|
@@ -641,6 +662,16 @@ function validateCell(cell, catalog, path = "cell", ids, options = {}) {
|
|
|
641
662
|
message: `${cell.component} requires ${prop}`
|
|
642
663
|
});
|
|
643
664
|
}
|
|
665
|
+
const listed = schema?.properties;
|
|
666
|
+
if (listed && Array.isArray(cell.hide_when_empty)) cell.hide_when_empty.forEach((prop, i) => {
|
|
667
|
+
if (typeof prop === "string" && prop !== "children" && !(prop in listed)) push({
|
|
668
|
+
severity: "warning",
|
|
669
|
+
code: "PROP_UNKNOWN",
|
|
670
|
+
cellId,
|
|
671
|
+
path: `${path}.hide_when_empty[${i}]`,
|
|
672
|
+
message: `hide_when_empty names ${prop}, which ${cell.component} doesn’t declare`
|
|
673
|
+
});
|
|
674
|
+
});
|
|
644
675
|
const declared = schema?.properties;
|
|
645
676
|
if (declared && schema?.additionalProperties !== true && typeof schema?.additionalProperties !== "object") {
|
|
646
677
|
for (const prop of Object.keys(cell.props ?? {})) if (prop !== "children" && prop !== "style" && !(prop in declared)) push({
|
|
@@ -674,8 +705,17 @@ function validateCell(cell, catalog, path = "cell", ids, options = {}) {
|
|
|
674
705
|
path: `${path}.children`,
|
|
675
706
|
message: `child cell "${child}" is not on the page`
|
|
676
707
|
});
|
|
708
|
+
const hide = cell.hide_when_empty;
|
|
709
|
+
if (hide !== void 0 && (!Array.isArray(hide) || hide.length === 0 || hide.some((p) => typeof p !== "string" || !p))) push({
|
|
710
|
+
severity: "error",
|
|
711
|
+
code: "HIDE_WHEN_EMPTY_INVALID",
|
|
712
|
+
cellId,
|
|
713
|
+
path: `${path}.hide_when_empty`,
|
|
714
|
+
message: "hide_when_empty takes a non-empty list of prop names"
|
|
715
|
+
});
|
|
677
716
|
checkBindings(cell.data?.queries, `${path}.data.queries`, push, cellId, options.template);
|
|
678
717
|
checkActions(cell, path, push);
|
|
718
|
+
checkHostReads(cell.props, `${path}.props`, push, cellId);
|
|
679
719
|
checkProjections(cell.props, `${path}.props`, push, cellId);
|
|
680
720
|
checkProjections(cell.conditions, `${path}.conditions`, push, cellId);
|
|
681
721
|
checkTraversal(cell.traversal, `${path}.traversal`, push, cellId);
|
|
@@ -775,7 +815,7 @@ function slotIssues(cells, catalog) {
|
|
|
775
815
|
cells.forEach((parent) => {
|
|
776
816
|
if (!parent?.component) return;
|
|
777
817
|
const kids = parent.children ?? [];
|
|
778
|
-
const entry = catalog
|
|
818
|
+
const entry = componentsFor(catalog, parent)[parent.component];
|
|
779
819
|
if (!entry) return;
|
|
780
820
|
const slots = declaredSlots(entry.props_schema);
|
|
781
821
|
const filled = new Map();
|
|
@@ -826,4 +866,4 @@ function slotIssues(cells, catalog) {
|
|
|
826
866
|
});
|
|
827
867
|
return out;
|
|
828
868
|
}
|
|
829
|
-
export {
|
|
869
|
+
export { walkRequest as S, stateNames as _, eachFormProblems as a, systemsFromProcess as b, validatePage as c, mergeStates as d, needsWalk as f, resolveWalkStart as g, referencedLabels as h, componentsFor as i, selectionIssues as l, readWalk as m, STORE_SCOPES as n, nearestNames as o, readField as p, WALK_DIRECTIONS as r, validateCell as s, RESPONSIVE_BUCKETS as t, RESERVED_LABELS as u, stateValue as v, walkKey as x, systemsFromGraphs as y };
|
package/dist/core.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { C as normalizeCell,
|
|
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-
|
|
3
|
-
import { _ as
|
|
4
|
-
import { C as resolveAction,
|
|
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
|
+
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-CNaB25jE.js";
|
|
3
|
+
import { S as walkRequest, _ as stateNames, a as eachFormProblems, b as systemsFromProcess, c as validatePage, d as mergeStates, f as needsWalk, g as resolveWalkStart, h as referencedLabels, i as componentsFor, l as selectionIssues, m as readWalk, n as STORE_SCOPES, o as nearestNames, p as readField, r as WALK_DIRECTIONS, s as validateCell, t as RESPONSIVE_BUCKETS, u as RESERVED_LABELS, v as stateValue, x as walkKey, y as systemsFromGraphs } from "./chunks/validate-DRkCpQaY.js";
|
|
4
|
+
import { C as actionReferences, D as resolveAction, E as projectCellActions, S as actionProblems, T as normalizeActionDeclaration, _ as HOST_READ_KEY, a as deriveSectionReferences, b as isHostRead, 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 bindHostReads, w as declaredActions, x as actionBindingKey, y as hostReadProblem } from "./chunks/structure-B3ikc0oD.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";
|
|
7
|
-
import { n as pageBundles, t as pageBundleRefs } from "./chunks/page-bundles-
|
|
7
|
+
import { i as rowsInScope, n as pageBundles, r as rowForCell, t as pageBundleRefs } from "./chunks/page-bundles-_wsGO9WU.js";
|
|
8
8
|
import { a as createStackStore, i as saveScope, n as clearScope, r as loadScope } from "./chunks/persistence-hurkUUQ0.js";
|
|
9
9
|
import { ACTION_KINDS, QUERY_DESCRIPTOR_KEY, SECTION_KINDS as SECTION_KINDS$1, STATE_ROLES, STATE_TIERS, WALK_DEFAULTS, isDescriptorBinding, isLiveQueryState, isReadOnlyVersion } from "@peripheries/runtime";
|
|
10
10
|
function resolveDeclarations(queries, systems, diagnostics = [], cellId) {
|
|
@@ -801,6 +801,18 @@ var DIAGNOSTICS = {
|
|
|
801
801
|
meaning: "A literal prop value fails its schema.",
|
|
802
802
|
fix: "Write the value in the shape `props_schema` gives, or bind it with a whole-string `@label.path` reference."
|
|
803
803
|
},
|
|
804
|
+
HOST_READ_INVALID: {
|
|
805
|
+
meaning: "A `{ \"@host\": … }` prop value is malformed.",
|
|
806
|
+
fix: "Write exactly `{ \"@host\": \"<name>\" }`, a name of lowercase letters, digits and underscores, as a top-level prop."
|
|
807
|
+
},
|
|
808
|
+
HOST_READ_UNKNOWN: {
|
|
809
|
+
meaning: "A `{ \"@host\": \"<name>\" }` prop names a read the host does not list, so the prop is dropped and the component runs without it.",
|
|
810
|
+
fix: "Use a name the host lists in `hostReads`, or remove the prop."
|
|
811
|
+
},
|
|
812
|
+
HIDE_WHEN_EMPTY_INVALID: {
|
|
813
|
+
meaning: "A cell’s `hide_when_empty` isn’t a list of prop names.",
|
|
814
|
+
fix: "Write `hide_when_empty: [\"title\", \"items\"]`: the props that, all empty once bound (null, blank text, `[]`, `{}`), leave the cell out."
|
|
815
|
+
},
|
|
804
816
|
CELL_UNKNOWN_CHILD: {
|
|
805
817
|
meaning: "`children` names a cell that is not on the page.",
|
|
806
818
|
fix: "List only ids of cells on this page in `children`."
|
|
@@ -1054,7 +1066,7 @@ The host's rules for every page. Components, kits and patterns are in the catalo
|
|
|
1054
1066
|
- 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.
|
|
1055
1067
|
- \`children\` lists child cell ids, rendered inside the cell in place of \`props.children\`.
|
|
1056
1068
|
- A child with \`slot\` fills that \`x-slot\` of its parent; others are \`children\`.
|
|
1057
|
-
- \`conditions.showIf\` / \`hideIf\` test a value
|
|
1069
|
+
- \`conditions.showIf\` / \`hideIf\` test a value for truthiness; \`hide_when_empty: [props]\` hides the cell if all are empty.
|
|
1058
1070
|
- An embed cell \`{ id, embed: { page_id } | { page_type, project_id?, process_id? } }\` renders another published page, one level deep.
|
|
1059
1071
|
|
|
1060
1072
|
## Data and references
|
|
@@ -1132,4 +1144,4 @@ function manifestPageFrom(graphNodeId, data) {
|
|
|
1132
1144
|
}
|
|
1133
1145
|
};
|
|
1134
1146
|
}
|
|
1135
|
-
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_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, 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 };
|
|
1147
|
+
export { CONTENT_FIELDS, CORE_SPECIFIER, DIAGNOSTICS, EACH, EACH_DEFAULT_AS, HOST_READ_KEY, 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, bindHostReads, buildDataContext, bundleScope, cellAttributes, cellContext, cellPlacementStyle, cellPropSources, cellResolutionContext, clearScope, collectDeclarations, collectDescriptors, collectScopeIds, collectStatic, componentsFor, createStackStore, declaredActions, deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, descriptorShape, eachFormProblems, editTarget, hasRef, hiddenWhenEmpty, hideWhenEmptyProblem, hostReadProblem, isComponentExport, isEach, isEmptyPropValue, isHostRead, 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, rowForCell, rowsInScope, 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,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
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-
|
|
3
|
-
import { a as deriveSectionReferences,
|
|
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
|
+
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-CNaB25jE.js";
|
|
3
|
+
import { a as deriveSectionReferences, 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, v as bindHostReads, w as declaredActions } from "./chunks/structure-B3ikc0oD.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";
|
|
5
5
|
import { Component, Fragment, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
6
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -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 = { ...bindHostReads(resolveReferences(cell.props ?? {}, ctx), env.hostReads) };
|
|
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",
|
|
@@ -382,7 +426,13 @@ function CellView({ cell, env, nested = false, injectedProps }) {
|
|
|
382
426
|
source
|
|
383
427
|
}) } : {}
|
|
384
428
|
};
|
|
385
|
-
const resolvedProps = resolveReferences(cell.props ?? {}, propsCtx)
|
|
429
|
+
const resolvedProps = bindHostReads(resolveReferences(cell.props ?? {}, propsCtx), env.hostReads, (prop, why) => env.onDiagnostic?.({
|
|
430
|
+
severity: "warning",
|
|
431
|
+
code: "HOST_READ_UNKNOWN",
|
|
432
|
+
cellId: cell.id,
|
|
433
|
+
path: `props.${prop}`,
|
|
434
|
+
message: `${cell.component ?? cell.id}.${prop}: ${why}`
|
|
435
|
+
}));
|
|
386
436
|
if (found) env.onPropSources({
|
|
387
437
|
id: cell.id,
|
|
388
438
|
source: cell.source
|
|
@@ -528,7 +578,7 @@ var warn = (d) => console.warn(`[render] ${d.code}${d.cellId ? ` (cell ${d.cellI
|
|
|
528
578
|
function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, environment }) {
|
|
529
579
|
const { page, cells } = runtime;
|
|
530
580
|
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;
|
|
581
|
+
const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, cellProps, hostReads, retry, showHiddenCells, showProblemCodes } = environment;
|
|
532
582
|
useEffect(() => {
|
|
533
583
|
for (const d of runtime.diagnostics) onDiagnostic(d);
|
|
534
584
|
}, [runtime.diagnostics, onDiagnostic]);
|
|
@@ -556,6 +606,9 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
556
606
|
onDiagnostic,
|
|
557
607
|
frameProps,
|
|
558
608
|
cellProps,
|
|
609
|
+
hostReads,
|
|
610
|
+
showHiddenCells,
|
|
611
|
+
showProblemCodes,
|
|
559
612
|
renderEmbed: (cellId) => {
|
|
560
613
|
const embedded = runtime.embeds?.[cellId];
|
|
561
614
|
if (!embedded) return jsx(CellNotice, {
|
|
@@ -606,7 +659,10 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
606
659
|
onDiagnostic,
|
|
607
660
|
frameProps,
|
|
608
661
|
cellProps,
|
|
662
|
+
hostReads,
|
|
609
663
|
retry,
|
|
664
|
+
showHiddenCells,
|
|
665
|
+
showProblemCodes,
|
|
610
666
|
environment
|
|
611
667
|
]);
|
|
612
668
|
const structured = usesStructureLayout(page.layout);
|
|
@@ -980,4 +1036,4 @@ function bindActions(v, path, latest) {
|
|
|
980
1036
|
if (v && typeof v === "object") return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, bindActions(x, [...path, k], latest)]));
|
|
981
1037
|
return v;
|
|
982
1038
|
}
|
|
983
|
-
export { CellErrorBoundary, CellNotice, CellPlaceholder, CellView, FORM_SAVE_DEBOUNCE_MS, PageRenderer, StructureView, answerInputId, cellLabels, useCellStore, useContainerSize, useFormsRuntime, usePaging, useStructureFacts };
|
|
1039
|
+
export { CellErrorBoundary, CellHidden, CellNotice, CellPlaceholder, CellView, FORM_SAVE_DEBOUNCE_MS, PageRenderer, StructureView, answerInputId, cellLabels, useCellStore, useContainerSize, useFormsRuntime, usePaging, useStructureFacts };
|
package/dist/runtime.js
CHANGED
|
@@ -16,6 +16,7 @@ function importMapJson(shared = []) {
|
|
|
16
16
|
return JSON.stringify(importMapFor(shared)).replace(/</g, "\\u003c");
|
|
17
17
|
}
|
|
18
18
|
var IMPORT_MAP_JSON = importMapJson();
|
|
19
|
+
var LOAD_GLOBAL = "__STACK_RUNTIME_LOAD__";
|
|
19
20
|
var singleton = null;
|
|
20
21
|
function getStackStore() {
|
|
21
22
|
return singleton ??= createStackStore();
|
|
@@ -52,11 +53,28 @@ function buildRuntime(extra = {}) {
|
|
|
52
53
|
...extra
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
|
-
function installRuntime(g = globalThis, extra = {}) {
|
|
56
|
+
function installRuntime(g = globalThis, extra = {}, lazy = {}) {
|
|
56
57
|
const runtime = g[RUNTIME_GLOBAL] ?? buildRuntime(extra);
|
|
57
58
|
g[RUNTIME_GLOBAL] = runtime;
|
|
59
|
+
if (typeof g["__STACK_RUNTIME_LOAD__"] !== "function") {
|
|
60
|
+
const loading = new Map();
|
|
61
|
+
g[LOAD_GLOBAL] = (specifier) => {
|
|
62
|
+
const load = lazy[specifier];
|
|
63
|
+
if (!load || specifier in runtime) return void 0;
|
|
64
|
+
let pending = loading.get(specifier);
|
|
65
|
+
if (!pending) {
|
|
66
|
+
pending = load().then((mod) => void (runtime[specifier] = mod), (error) => {
|
|
67
|
+
loading.delete(specifier);
|
|
68
|
+
throw error;
|
|
69
|
+
});
|
|
70
|
+
loading.set(specifier, pending);
|
|
71
|
+
}
|
|
72
|
+
return pending;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
58
75
|
if (typeof g.require !== "function") g.require = (specifier) => {
|
|
59
76
|
if (specifier in runtime) return runtime[specifier];
|
|
77
|
+
if (specifier in lazy) throw new Error(`[runtime] "${specifier}" is lent lazily by the host and is not loaded yet: import it as an ES module, not with require().`);
|
|
60
78
|
throw new Error(`[runtime] No host module for require("${specifier}"). Add it to PINNED_RUNTIMES or bundle it.`);
|
|
61
79
|
};
|
|
62
80
|
if (!g[READY_GLOBAL]) g[READY_GLOBAL] = Promise.resolve();
|
|
@@ -75,6 +93,7 @@ function renderShim(specifier, names, hasDefault) {
|
|
|
75
93
|
"// Generated by scripts/build-shims.ts. Do not edit.",
|
|
76
94
|
`// Forwards ${key} to globalThis.${RUNTIME_GLOBAL}[${key}].`,
|
|
77
95
|
`await globalThis.${READY_GLOBAL};`,
|
|
96
|
+
`await globalThis.${LOAD_GLOBAL}?.(${key});`,
|
|
78
97
|
`const R = globalThis.${RUNTIME_GLOBAL}?.[${key}];`,
|
|
79
98
|
`if (!R) throw new Error('[runtime] ${RUNTIME_GLOBAL}[${key}] is not installed; the host has not booted.');`
|
|
80
99
|
];
|
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
|
|
package/dist/testing.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { l as prepareDocument } from "./chunks/query-
|
|
1
|
+
import { l as prepareDocument } from "./chunks/query-CNaB25jE.js";
|
|
2
2
|
import { o as projectModule } from "./chunks/load-b38vUiZM.js";
|
|
3
3
|
import { i as bundleScope } from "./chunks/refs-Csgh6rXq.js";
|
|
4
|
-
import { n as pageBundles, t as pageBundleRefs } from "./chunks/page-bundles-
|
|
4
|
+
import { n as pageBundles, t as pageBundleRefs } from "./chunks/page-bundles-_wsGO9WU.js";
|
|
5
5
|
import { r as fromPageSteps } from "./chunks/forms-DxA9WzCt.js";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
var __defProp = Object.defineProperty;
|
|
@@ -2,6 +2,8 @@ import type { PageCell } from '../types.js';
|
|
|
2
2
|
import type { BundleRow, LoadedBundle } from './load.js';
|
|
3
3
|
import { type LineageRef } from './refs.js';
|
|
4
4
|
export declare function pageBundleRefs(scope: LineageRef[], cells: PageCell[], pageOrgId: string | null): LineageRef[];
|
|
5
|
+
export declare function rowsInScope<R extends Pick<BundleRow, 'id' | 'bundle_name' | 'org_slug' | 'org_id'>>(rows: readonly R[], scope: LineageRef[]): R[];
|
|
6
|
+
export declare function rowForCell<R extends Pick<BundleRow, 'id' | 'bundle_name' | 'org_slug' | 'org_id'>>(rows: readonly R[], cell: PageCell, pageOrgId: string | null): R | null;
|
|
5
7
|
export type PageBundles = {
|
|
6
8
|
scope: LoadedBundle[] | null;
|
|
7
9
|
forCell: (cell: PageCell) => LoadedBundle | null;
|
|
@@ -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,18 @@ 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 HOST_READ_INVALID: {
|
|
55
|
+
readonly meaning: "A `{ \"@host\": … }` prop value is malformed.";
|
|
56
|
+
readonly fix: "Write exactly `{ \"@host\": \"<name>\" }`, a name of lowercase letters, digits and underscores, as a top-level prop.";
|
|
57
|
+
};
|
|
58
|
+
readonly HOST_READ_UNKNOWN: {
|
|
59
|
+
readonly meaning: "A `{ \"@host\": \"<name>\" }` prop names a read the host does not list, so the prop is dropped and the component runs without it.";
|
|
60
|
+
readonly fix: "Use a name the host lists in `hostReads`, or remove the prop.";
|
|
61
|
+
};
|
|
62
|
+
readonly HIDE_WHEN_EMPTY_INVALID: {
|
|
63
|
+
readonly meaning: "A cell’s `hide_when_empty` isn’t a list of prop names.";
|
|
64
|
+
readonly fix: "Write `hide_when_empty: [\"title\", \"items\"]`: the props that, all empty once bound (null, blank text, `[]`, `{}`), leave the cell out.";
|
|
65
|
+
};
|
|
54
66
|
readonly CELL_UNKNOWN_CHILD: {
|
|
55
67
|
readonly meaning: "`children` names a cell that is not on the page.";
|
|
56
68
|
readonly fix: "List only ids of cells on this page in `children`.";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const HOST_READ_KEY = "@host";
|
|
2
|
+
export type HostRead = (...args: never[]) => unknown;
|
|
3
|
+
export type HostReads = Readonly<Record<string, HostRead>>;
|
|
4
|
+
export declare const isHostRead: (value: unknown) => value is Record<string, unknown>;
|
|
5
|
+
export declare function hostReadProblem(value: Record<string, unknown>): string | null;
|
|
6
|
+
export declare function bindHostReads(props: Record<string, unknown>, reads: HostReads | undefined, onUnknown?: (prop: string, why: string) => void): Record<string, unknown>;
|
|
@@ -1,4 +1,4 @@
|
|
|
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
4
|
export { LAYER_ROLES, layerName, type LayerType } from './layers.js';
|
|
@@ -6,19 +6,20 @@ export { loadPageData, resolveDataSystem, resolveSystems, type CellData, type Ce
|
|
|
6
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';
|
|
7
7
|
export { selectionIssues } from './selected.js';
|
|
8
8
|
export { cellPropSources, editTarget, patchAt, STRUCTURE_FIELDS, TOOL_OWNED_KEYS, type EditCell, type EditRefusal, type EditTarget, type OnSource, type PropSource, type PropSourceEntry } from './sources.js';
|
|
9
|
+
export { bindHostReads, HOST_READ_KEY, hostReadProblem, isHostRead, type HostRead, type HostReads } from './host-reads.js';
|
|
9
10
|
export { cellContext, cellResolutionContext, EACH, pageContext, EACH_DEFAULT_AS, isEach, passesConditions, resolveReferences, settled, type CellScope, type Each, type ResolutionContext } from './references.js';
|
|
10
|
-
export { eachFormProblems, nearestNames, RESPONSIVE_BUCKETS, STORE_SCOPES, validateCell, validatePage, WALK_DIRECTIONS, type Catalog, type ValidateOptions } from './validate.js';
|
|
11
|
+
export { componentsFor, eachFormProblems, nearestNames, RESPONSIVE_BUCKETS, STORE_SCOPES, validateCell, validatePage, WALK_DIRECTIONS, type Catalog, type ValidateOptions } from './validate.js';
|
|
11
12
|
export { DIAGNOSTICS, type DiagnosticCode, type DiagnosticEntry } from './diagnostics.js';
|
|
12
13
|
export { LAYOUT_TYPES, PAGE_RULES } from './rules.js';
|
|
13
14
|
export { pageRuntimeFromValues } from './values.js';
|
|
14
15
|
export { actionBindingKey, actionProblems, actionReferences, declaredActions, normalizeActionDeclaration, projectCellActions, resolveAction, type RunAction } from './actions.js';
|
|
15
16
|
export type { ActionDeclaration } from '@peripheries/runtime';
|
|
16
17
|
export type * from './types.js';
|
|
17
|
-
export { assembleCellProps, projectCellData, type CellStatus } from './cell-props.js';
|
|
18
|
+
export { assembleCellProps, hiddenWhenEmpty, hideWhenEmptyProblem, isEmptyPropValue, projectCellData, type CellStatus } from './cell-props.js';
|
|
18
19
|
export { cellAttributes, cellPlacementStyle, pageContainerStyle } from './layout.js';
|
|
19
20
|
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';
|
|
20
21
|
export { _clearBundleCache, isComponentExport, loadBundle, loadBundles, loadBundlesSettled, projectModule, runtimeReady, type BundleFiles, type BundleRow, type LoadedBundle, type LoadedBundles, } from './bundles/load.js';
|
|
21
|
-
export { pageBundleRefs, pageBundles, type PageBundles } from './bundles/page-bundles.js';
|
|
22
|
+
export { pageBundleRefs, pageBundles, rowForCell, rowsInScope, type PageBundles } from './bundles/page-bundles.js';
|
|
22
23
|
export { bundleScope, CORE_SPECIFIER, MAIN, normalizeRef, PUBLIC, refKey, type BundleRef, type BundleScopeInput, type LineageRef, type SharedLineage } from './bundles/refs.js';
|
|
23
24
|
export { resolveComponent, type CoreRegistry, type ResolvedComponent } from './bundles/resolve.js';
|
|
24
25
|
export { createStackStore, type StackStoreApi } from './store/create-store.js';
|
|
@@ -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,15 +1,18 @@
|
|
|
1
1
|
import { type Diagnostic } from './graph.js';
|
|
2
2
|
import { type Each } from './references.js';
|
|
3
3
|
import type { PageCell, ProjectPage } from './types.js';
|
|
4
|
+
type CatalogEntries = Record<string, {
|
|
5
|
+
props_schema?: {
|
|
6
|
+
required?: readonly string[];
|
|
7
|
+
properties?: Record<string, unknown>;
|
|
8
|
+
additionalProperties?: unknown;
|
|
9
|
+
} | null;
|
|
10
|
+
} | undefined>;
|
|
4
11
|
export type Catalog = {
|
|
5
|
-
components:
|
|
6
|
-
|
|
7
|
-
required?: readonly string[];
|
|
8
|
-
properties?: Record<string, unknown>;
|
|
9
|
-
additionalProperties?: unknown;
|
|
10
|
-
} | null;
|
|
11
|
-
} | undefined>;
|
|
12
|
+
components: CatalogEntries;
|
|
13
|
+
forCell?: (cell: PageCell) => CatalogEntries | undefined;
|
|
12
14
|
};
|
|
15
|
+
export declare const componentsFor: (catalog: Catalog, cell: PageCell) => CatalogEntries;
|
|
13
16
|
export declare function nearestNames(name: string, names: Iterable<string>, limit?: number): string[];
|
|
14
17
|
export declare const RESPONSIVE_BUCKETS: readonly ["narrow", "compact", "wide"];
|
|
15
18
|
export declare const STORE_SCOPES: readonly ["page", "project"];
|
|
@@ -30,3 +33,4 @@ export type SlotDeclaration = {
|
|
|
30
33
|
export declare function declaredSlots(schema: {
|
|
31
34
|
properties?: Record<string, unknown>;
|
|
32
35
|
} | null | undefined): Map<string, SlotDeclaration>;
|
|
36
|
+
export {};
|
|
@@ -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<{
|
|
@@ -4,6 +4,7 @@ import type { LoadedBundle } from '../core/bundles/load.js';
|
|
|
4
4
|
import type { Diagnostic } from '../core/graph.js';
|
|
5
5
|
import { type CoreRegistry } from '../core/bundles/resolve.js';
|
|
6
6
|
import { type RunAction } from '../core/actions.js';
|
|
7
|
+
import { type HostReads } from '../core/host-reads.js';
|
|
7
8
|
import type { CellData } from '../core/load-page.js';
|
|
8
9
|
import { type ResolutionContext } from '../core/references.js';
|
|
9
10
|
import type { StackStoreApi } from '../core/store/create-store.js';
|
|
@@ -35,9 +36,12 @@ export type CellEnvironment = {
|
|
|
35
36
|
onUnresolvedReference?: (cellId: string, ref: string) => void;
|
|
36
37
|
onPropSources?: (cell: EditCell, sources: PropSourceEntry[]) => void;
|
|
37
38
|
renderEmbed?: (cellId: string) => ReactNode;
|
|
39
|
+
hostReads?: HostReads;
|
|
38
40
|
onDiagnostic?: (d: Diagnostic) => void;
|
|
39
41
|
frameProps?: (cell: PageCell, contract: ComponentContract | undefined) => FrameProps | undefined;
|
|
40
42
|
cellProps?: (cell: PageCell) => Record<string, unknown> | undefined;
|
|
43
|
+
showHiddenCells?: boolean;
|
|
44
|
+
showProblemCodes?: boolean;
|
|
41
45
|
};
|
|
42
46
|
export type FrameProps = {
|
|
43
47
|
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';
|
|
@@ -2,6 +2,7 @@ import type { CellAction, ComponentContract } from '@peripheries/runtime';
|
|
|
2
2
|
import type { RunAction } from '../core/actions.js';
|
|
3
3
|
import type { PageBundles } from '../core/bundles/page-bundles.js';
|
|
4
4
|
import type { CoreRegistry } from '../core/bundles/resolve.js';
|
|
5
|
+
import type { HostReads } from '../core/host-reads.js';
|
|
5
6
|
import type { Diagnostic } from '../core/graph.js';
|
|
6
7
|
import type { PageRuntime } from '../core/load-page.js';
|
|
7
8
|
import type { EditCell, PropSourceEntry } from '../core/sources.js';
|
|
@@ -17,12 +18,15 @@ export type RendererEnvironment = {
|
|
|
17
18
|
actionsFor?: (cell: PageCell) => Record<string, CellAction> | undefined;
|
|
18
19
|
runAction?: RunAction;
|
|
19
20
|
loadPage?: LoadPage;
|
|
21
|
+
hostReads?: HostReads;
|
|
20
22
|
onCellError?: (cellId: string, error: Error) => void;
|
|
21
23
|
onUnresolvedReference?: (cellId: string, ref: string) => void;
|
|
22
24
|
onPropSources?: (cell: EditCell, sources: PropSourceEntry[]) => void;
|
|
23
25
|
retry?: () => void;
|
|
24
26
|
frameProps?: (cell: PageCell, contract: ComponentContract | undefined) => FrameProps | undefined;
|
|
25
27
|
cellProps?: (cell: PageCell) => Record<string, unknown> | undefined;
|
|
28
|
+
showHiddenCells?: boolean;
|
|
29
|
+
showProblemCodes?: boolean;
|
|
26
30
|
};
|
|
27
31
|
export type PageRendererProps = {
|
|
28
32
|
runtime: PageRuntime;
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { READY_GLOBAL, RESOLVE_GLOBAL, RUNTIME_GLOBAL, type RuntimeSpecifier } from '@peripheries/runtime';
|
|
2
|
+
import { LOAD_GLOBAL } from './load-global.js';
|
|
2
3
|
export type StackRuntime = Record<Exclude<RuntimeSpecifier, '@peripheries/ui'>, unknown> & Record<string, unknown>;
|
|
3
4
|
type RuntimeGlobals = {
|
|
4
5
|
[RUNTIME_GLOBAL]?: StackRuntime;
|
|
5
6
|
[READY_GLOBAL]?: Promise<void>;
|
|
6
7
|
[RESOLVE_GLOBAL]?: () => void;
|
|
8
|
+
[LOAD_GLOBAL]?: (specifier: string) => Promise<void> | undefined;
|
|
7
9
|
require?: (specifier: string) => unknown;
|
|
8
10
|
};
|
|
9
11
|
export declare function buildRuntime(extra?: Record<string, unknown>): StackRuntime;
|
|
10
|
-
export declare function installRuntime(g?: RuntimeGlobals, extra?: Record<string, unknown
|
|
12
|
+
export declare function installRuntime(g?: RuntimeGlobals, extra?: Record<string, unknown>, lazy?: Record<string, () => Promise<unknown>>): StackRuntime;
|
|
11
13
|
export { runtimeReady } from '../core/bundles/load.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const LOAD_GLOBAL = "__STACK_RUNTIME_LOAD__";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peripheries/renderer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.26.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": [
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"LICENSE"
|
|
48
48
|
],
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@peripheries/runtime": "0.
|
|
50
|
+
"@peripheries/runtime": "0.25.0",
|
|
51
51
|
"ajv": "8.20.0",
|
|
52
52
|
"graphql": "17.0.2"
|
|
53
53
|
},
|