@peripheries/renderer 0.25.0 → 0.27.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
@@ -83,6 +83,14 @@ bundle's `ThemeProvider` export.
83
83
 
84
84
  ## Versions
85
85
 
86
+ - **Unreleased:** `RENDER_FUNCTIONS` adds `advisor_add_allowed(p_org_id)`: whether the viewer may
87
+ add advisors (a bare Boolean; bind it with `result.path: 'advisor_add_allowed'`). It also adds
88
+ `pages_awaiting_release(p_project_id)`:
89
+ a project's pages whose newest main page-state is newer than the one their
90
+ client channel's release holds, for staff (an empty array for anyone else).
91
+ - **Removable in the next minor:** `GraphSource.processSystems` (the process's cached system
92
+ columns, read only by a source without `graphSystems`). The host no longer implements it;
93
+ `graphSystems` is the way, and the process columns it reads are being dropped.
86
94
  - **0.25.0** (2026-10-24): `hide_when_empty`, a cell-level list of prop names.
87
95
  - **A cell with `hide_when_empty: ["title", "items"]`** renders nothing, and leaves no gap,
88
96
  when every prop it names is empty once bound: null, undefined, text that is blank once
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-CrHGlwey.js";
1
+ import { x as isEach } from "./chunks/query-DOXxGTO2.js";
2
+ import { a as eachFormProblems, c as validatePage, i as componentsFor } from "./chunks/validate-y5_6ws0s.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}`;
@@ -43,15 +43,51 @@ function loadBundle(row, files) {
43
43
  }
44
44
  return pending;
45
45
  }
46
+ var escapeRe = (v) => v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
47
+ async function sharedDependencies(rows, files) {
48
+ const get = files.fetch ?? ((u) => fetch(u));
49
+ const bySpecifier = new Map(rows.map((r) => [r.specifier, r.id]));
50
+ const deps = new Map();
51
+ try {
52
+ await Promise.all(rows.map(async (r) => {
53
+ if (r.requires) return void deps.set(r.id, r.requires.map((s) => bySpecifier.get(s)).filter((id) => !!id && id !== r.id));
54
+ const url = files.url(r, "index.js");
55
+ const res = url ? await get(url) : null;
56
+ if (!res?.ok) throw new Error("unreadable");
57
+ const source = await res.text();
58
+ deps.set(r.id, rows.filter((o) => o.id !== r.id && new RegExp(`(?:from|import)\\s*\\(?\\s*(["'\`])${escapeRe(o.specifier)}\\1`).test(source)).map((o) => o.id));
59
+ }));
60
+ } catch {
61
+ return null;
62
+ }
63
+ return deps;
64
+ }
65
+ async function loadWaves(rows, files) {
66
+ const shared = rows.filter((r) => r.specifier);
67
+ const rest = rows.filter((r) => !r.specifier);
68
+ const waves = [];
69
+ const deps = shared.length > 1 ? await sharedDependencies(shared, files) : null;
70
+ if (!deps) return [rows];
71
+ const done = new Set();
72
+ let left = shared;
73
+ while (left.length) {
74
+ const wave = left.filter((r) => (deps.get(r.id) ?? []).every((d) => done.has(d)));
75
+ if (!wave.length) return [rows];
76
+ waves.push(wave);
77
+ wave.forEach((r) => done.add(r.id));
78
+ left = left.filter((r) => !done.has(r.id));
79
+ }
80
+ if (rest.length) waves.push(rest);
81
+ return waves;
82
+ }
46
83
  async function loadBundlesSettled(rows, files) {
47
- const settled = await Promise.allSettled(rows.map((r) => loadBundle(r, files)));
48
84
  const loaded = [];
49
85
  const failed = [];
50
- settled.forEach((s, i) => {
86
+ for (const wave of await loadWaves(rows, files)) (await Promise.allSettled(wave.map((r) => loadBundle(r, files)))).forEach((s, i) => {
51
87
  if (s.status === "fulfilled") loaded.push(s.value);
52
88
  else {
53
- failed.push(rows[i].id);
54
- console.warn(`[bundles] ${rows[i].org_slug}/${rows[i].bundle_name} failed to load:`, s.reason);
89
+ failed.push(wave[i].id);
90
+ console.warn(`[bundles] ${wave[i].org_slug}/${wave[i].bundle_name} failed to load:`, s.reason);
55
91
  }
56
92
  });
57
93
  return {
@@ -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 };
@@ -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,102 @@ 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"
420
+ ],
421
+ advisor_add_allowed: [
422
+ "advisor",
423
+ "organization",
424
+ "org_member",
425
+ "client"
319
426
  ]
320
427
  };
321
428
  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-DOXxGTO2.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-DOXxGTO2.js";
2
+ import { S as actionProblems, b as isHostRead, g as usesStructureLayout, m as structureIssues, y as hostReadProblem } from "./structure-B1PsD-AJ.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",
@@ -694,6 +715,7 @@ function validateCell(cell, catalog, path = "cell", ids, options = {}) {
694
715
  });
695
716
  checkBindings(cell.data?.queries, `${path}.data.queries`, push, cellId, options.template);
696
717
  checkActions(cell, path, push);
718
+ checkHostReads(cell.props, `${path}.props`, push, cellId);
697
719
  checkProjections(cell.props, `${path}.props`, push, cellId);
698
720
  checkProjections(cell.conditions, `${path}.conditions`, push, cellId);
699
721
  checkTraversal(cell.traversal, `${path}.traversal`, push, cellId);
@@ -793,7 +815,7 @@ function slotIssues(cells, catalog) {
793
815
  cells.forEach((parent) => {
794
816
  if (!parent?.component) return;
795
817
  const kids = parent.children ?? [];
796
- const entry = catalog.components[parent.component];
818
+ const entry = componentsFor(catalog, parent)[parent.component];
797
819
  if (!entry) return;
798
820
  const slots = declaredSlots(entry.props_schema);
799
821
  const filled = new Map();
@@ -844,4 +866,4 @@ function slotIssues(cells, catalog) {
844
866
  });
845
867
  return out;
846
868
  }
847
- 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
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-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-CrHGlwey.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";
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";
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-DOXxGTO2.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-y5_6ws0s.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-B1PsD-AJ.js";
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-H7hUCwPc.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,14 @@ 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
+ },
804
812
  HIDE_WHEN_EMPTY_INVALID: {
805
813
  meaning: "A cell’s `hide_when_empty` isn’t a list of prop names.",
806
814
  fix: "Write `hide_when_empty: [\"title\", \"items\"]`: the props that, all empty once bound (null, blank text, `[]`, `{}`), leave the cell out."
@@ -1136,4 +1144,4 @@ function manifestPageFrom(graphNodeId, data) {
1136
1144
  }
1137
1145
  };
1138
1146
  }
1139
- export { CONTENT_FIELDS, CORE_SPECIFIER, DIAGNOSTICS, EACH, EACH_DEFAULT_AS, HYDRATED_CELL_FIELDS, LAYER_ROLES, LAYOUT_TYPES, MAIN, PAGE_DOCUMENT, PAGE_RULES, PAGING_VARIABLES, PUBLIC, RENDER_FIELDS, RENDER_FUNCTIONS, RENDER_FUNCTIONS_AHEAD, RESERVED_LABELS, RESPONSIVE_BUCKETS, SECTION_KINDS, STORE_FIELDS, STORE_SCOPES, STRUCTURE_FIELDS, TOOL_OWNED_KEYS, UnsafeDocumentError, VARIABLE_NAMESPACES, WALK_DIRECTIONS, _clearBundleCache, actionBindingKey, actionProblems, actionReferences, assembleCellProps, attachSelectionSetters, attachViewStateSetters, buildDataContext, bundleScope, cellAttributes, cellContext, cellPlacementStyle, cellPropSources, cellResolutionContext, clearScope, collectDeclarations, collectDescriptors, collectScopeIds, collectStatic, createStackStore, declaredActions, deriveElementReferences, deriveSectionNumbering, deriveSectionReferences, descriptorShape, eachFormProblems, editTarget, hasRef, hiddenWhenEmpty, hideWhenEmptyProblem, isComponentExport, isEach, isEmptyPropValue, layerName, loadBundle, loadBundles, loadBundlesSettled, loadPageData, loadScope, manifestPageFrom, mergeSectionReferences, mergeStates, nearestNames, needsWalk, nodePrintStyle, normalizeActionDeclaration, normalizeCell, normalizeRef, normalizeStructure, numberingFor, orderByVariable, pageBundleRefs, pageBundles, pageContainerStyle, pageContext, pageRuntimeFromValues, pageScopeKey, pageVariables, passesConditions, patchAt, prepareDocument, projectCellActions, projectCellData, projectLive, projectModule, projectScopeKey, projectSelections, projectViewState, queryKey, readField, readWalk, refKey, referencedLabels, referencesFor, resolveAction, resolveCell, resolveComponent, resolveDataSystem, resolveDeclarations, resolveDescriptorVariables, resolveReferences, resolveScopeId, resolveSystems, resolveWalkStart, rootCells, runtimeReady, saveScope, sectionAnchor, selectionIssues, selectionShape, settled, shallowEqualBundle, shapeAt, stateNames, stateValue, structureIssues, systemsFromGraphs, systemsFromProcess, tableOfContents, usesStructureLayout, validateCell, validateDescriptor, validateManifest, validatePage, variableLabels, variableReferences, walkKey, walkRequest };
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
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-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";
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-DOXxGTO2.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-B1PsD-AJ.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";
@@ -236,7 +236,7 @@ function mergeActions(a, b) {
236
236
  } : void 0;
237
237
  }
238
238
  function boundProps(cell, ctx, env, injectedProps) {
239
- const out = { ...resolveReferences(cell.props ?? {}, ctx) };
239
+ const out = { ...bindHostReads(resolveReferences(cell.props ?? {}, ctx), env.hostReads) };
240
240
  for (const id of cell.children ?? []) {
241
241
  const child = env.cellsById.get(id);
242
242
  if (!child) continue;
@@ -252,6 +252,14 @@ function boundProps(cell, ctx, env, injectedProps) {
252
252
  ...env.cellProps?.(cell)
253
253
  };
254
254
  }
255
+ var reportedMissing = new Set();
256
+ function reportMissing(component) {
257
+ if (!reportedMissing.has(component)) {
258
+ reportedMissing.add(component);
259
+ console.warn(`[render] no bundle holds the component "${component}"`);
260
+ }
261
+ return null;
262
+ }
255
263
  function CellView({ cell, env, nested = false, injectedProps }) {
256
264
  const frame = useRef(null);
257
265
  const store = useCellStore(cell, env.scope, env.store);
@@ -370,7 +378,7 @@ function CellView({ cell, env, nested = false, injectedProps }) {
370
378
  else if (!resolved) body = jsxs(CellNotice, {
371
379
  state: "not-found",
372
380
  component: cell.component,
373
- children: [cell.component, " isn't available here."]
381
+ children: [reportMissing(cell.component), "This section isn't available right now."]
374
382
  });
375
383
  else {
376
384
  const slotted = {};
@@ -426,7 +434,13 @@ function CellView({ cell, env, nested = false, injectedProps }) {
426
434
  source
427
435
  }) } : {}
428
436
  };
429
- const resolvedProps = resolveReferences(cell.props ?? {}, propsCtx);
437
+ const resolvedProps = bindHostReads(resolveReferences(cell.props ?? {}, propsCtx), env.hostReads, (prop, why) => env.onDiagnostic?.({
438
+ severity: "warning",
439
+ code: "HOST_READ_UNKNOWN",
440
+ cellId: cell.id,
441
+ path: `props.${prop}`,
442
+ message: `${cell.component ?? cell.id}.${prop}: ${why}`
443
+ }));
430
444
  if (found) env.onPropSources({
431
445
  id: cell.id,
432
446
  source: cell.source
@@ -572,7 +586,7 @@ var warn = (d) => console.warn(`[render] ${d.code}${d.cellId ? ` (cell ${d.cellI
572
586
  function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, environment }) {
573
587
  const { page, cells } = runtime;
574
588
  const declared = useMemo(() => new Set(runtime.declared), [runtime.declared]);
575
- const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, cellProps, retry, showHiddenCells, showProblemCodes } = environment;
589
+ const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, cellProps, hostReads, retry, showHiddenCells, showProblemCodes } = environment;
576
590
  useEffect(() => {
577
591
  for (const d of runtime.diagnostics) onDiagnostic(d);
578
592
  }, [runtime.diagnostics, onDiagnostic]);
@@ -600,6 +614,7 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
600
614
  onDiagnostic,
601
615
  frameProps,
602
616
  cellProps,
617
+ hostReads,
603
618
  showHiddenCells,
604
619
  showProblemCodes,
605
620
  renderEmbed: (cellId) => {
@@ -652,6 +667,7 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
652
667
  onDiagnostic,
653
668
  frameProps,
654
669
  cellProps,
670
+ hostReads,
655
671
  retry,
656
672
  showHiddenCells,
657
673
  showProblemCodes,
package/dist/runtime.js CHANGED
@@ -1,4 +1,4 @@
1
- import { s as runtimeReady } from "./chunks/load-b38vUiZM.js";
1
+ import { s as runtimeReady } from "./chunks/load-H7hUCwPc.js";
2
2
  import { a as createStackStore, t as clearAllScopes } from "./chunks/persistence-hurkUUQ0.js";
3
3
  import { PINNED_RUNTIMES, READY_GLOBAL, RESOLVE_GLOBAL, RUNTIME_GLOBAL, buildImportMap } from "@peripheries/runtime";
4
4
  import * as React from "react";
@@ -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/testing.js CHANGED
@@ -1,7 +1,7 @@
1
- import { l as prepareDocument } from "./chunks/query-D6xQbTFK.js";
2
- import { o as projectModule } from "./chunks/load-b38vUiZM.js";
1
+ import { l as prepareDocument } from "./chunks/query-DOXxGTO2.js";
2
+ import { o as projectModule } from "./chunks/load-H7hUCwPc.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;
@@ -13,6 +13,7 @@ export type BundleRow = {
13
13
  exposed_export: string | null;
14
14
  }>;
15
15
  specifier?: string | null;
16
+ requires?: readonly string[] | null;
16
17
  };
17
18
  export type LoadedBundle = {
18
19
  id: string;
@@ -36,6 +37,7 @@ export type LoadedBundles = {
36
37
  loaded: LoadedBundle[];
37
38
  failed: string[];
38
39
  };
40
+ export declare function loadWaves(rows: BundleRow[], files: BundleFiles): Promise<BundleRow[][]>;
39
41
  export declare function loadBundlesSettled(rows: BundleRow[], files: BundleFiles): Promise<LoadedBundles>;
40
42
  export declare function loadBundles(rows: BundleRow[], files: BundleFiles): Promise<LoadedBundle[]>;
41
43
  export declare function _clearBundleCache(): void;
@@ -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;
@@ -51,6 +51,14 @@ 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
+ };
54
62
  readonly HIDE_WHEN_EMPTY_INVALID: {
55
63
  readonly meaning: "A cell’s `hide_when_empty` isn’t a list of prop names.";
56
64
  readonly fix: "Write `hide_when_empty: [\"title\", \"items\"]`: the props that, all empty once bound (null, blank text, `[]`, `{}`), leave the cell out.";
@@ -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>;
@@ -6,8 +6,9 @@ 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';
@@ -18,7 +19,7 @@ export { assembleCellProps, hiddenWhenEmpty, hideWhenEmptyProblem, isEmptyPropVa
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,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 {};
@@ -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,6 +36,7 @@ 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;
@@ -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,6 +18,7 @@ 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;
@@ -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.25.0",
3
+ "version": "0.27.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
  },