@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 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-D6xQbTFK.js";
2
- import { i as eachFormProblems, s as validatePage } from "./chunks/validate-BcB_PA1k.js";
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.components[cell.component]?.props_schema?.properties : void 0;
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.filter((row) => scope.some((r) => rowMatches(r, row))).flatMap((row) => byRow.get(row.id) ?? []) : null,
29
+ scope: loaded ? rowsInScope(rows, scope).flatMap((row) => byRow.get(row.id) ?? []) : null,
23
30
  forCell: (cell) => {
24
- const ref = normalizeRef(cell.bundle_ref, pageOrgId);
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 CONTENT_FIELDS = [...HYDRATED_CELL_FIELDS.filter((f) => f !== "layout"), ...STORE_FIELDS];
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 { normalizeCell as C, hasRef as S, rootCells as T, failedLabels as _, projectSelections as a, HYDRATED_CELL_FIELDS as b, pageScopeKey as c, resolveComponent as d, cellAttributes as f, assembleCellProps as g, pageContainerStyle as h, projectLive as i, 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, projectCellData as v, resolveCell as w, STORE_FIELDS as x, CONTENT_FIELDS as y };
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-D6xQbTFK.js";
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 { resolveAction as C, projectCellActions as S, actionBindingKey as _, deriveSectionReferences as a, declaredActions 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, actionProblems as v, normalizeActionDeclaration as x, actionReferences as y };
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-D6xQbTFK.js";
2
- import { g as usesStructureLayout, m as structureIssues, v as actionProblems } from "./structure-CKBtQHJq.js";
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 entry = catalog.components[cell.component];
640
+ const components = componentsFor(catalog, cell);
641
+ const entry = components[cell.component];
621
642
  if (!entry) {
622
- const suggestions = nearestNames(cell.component, Object.keys(catalog.components));
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.components[parent.component];
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 { stateValue as _, nearestNames as a, walkKey as b, selectionIssues as c, needsWalk as d, readField as f, stateNames as g, resolveWalkStart as h, eachFormProblems as i, RESERVED_LABELS as l, referencedLabels as m, STORE_SCOPES as n, validateCell as o, readWalk as p, WALK_DIRECTIONS as r, validatePage as s, RESPONSIVE_BUCKETS as t, mergeStates as u, systemsFromGraphs as v, walkRequest as x, systemsFromProcess as y };
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, S as hasRef, T as rootCells, a as projectSelections, b as HYDRATED_CELL_FIELDS, c as pageScopeKey, d as resolveComponent, f as cellAttributes, g as assembleCellProps, h as pageContainerStyle, i as projectLive, 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 projectCellData, w as resolveCell, x as STORE_FIELDS, y as CONTENT_FIELDS } from "./chunks/projection-zhu32_KJ.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-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-BcB_PA1k.js";
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";
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-CPj_vx-J.js";
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, usually a reference, for truthiness.
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 { T as rootCells, _ as failedLabels, a as projectSelections, d as resolveComponent, f as cellAttributes, g as assembleCellProps, h as pageContainerStyle, i as projectLive, m as documentProfile, n as attachViewStateSetters, o as projectViewState, p as cellPlacementStyle, s as shallowEqualBundle, t as attachSelectionSetters, u as resolveScopeId, v as projectCellData } from "./chunks/projection-zhu32_KJ.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-D6xQbTFK.js";
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";
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 CellNotice({ state, component, onRetry, children }) {
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: [children, onRetry && jsxs(Fragment$1, { children: [" ", jsx("button", {
22
- type: "button",
23
- className: "cell-notice__retry",
24
- onClick: onRetry,
25
- children: "Try again"
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 (cell.embed) body = env.renderEmbed?.(cell.id) ?? null;
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-D6xQbTFK.js";
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-CPj_vx-J.js";
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 CONTENT_FIELDS: readonly [...("data" | "component" | "props" | "conditions" | "children" | "traversal" | "bundle_ref" | "actions" | "embed")[], "selections", "viewState", "live"];
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, PageCell, ResponsiveBucket } from '@peripheries/runtime';
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: Record<string, {
6
- props_schema?: {
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 CellNotice({ state, component, onRetry, children }: {
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>): StackRuntime;
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.24.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.23.1",
50
+ "@peripheries/runtime": "0.25.0",
51
51
  "ajv": "8.20.0",
52
52
  "graphql": "17.0.2"
53
53
  },