@peripheries/renderer 0.22.0 → 0.23.1
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 +125 -23
- package/dist/catalog.js +2 -6
- package/dist/chunks/forms-DxA9WzCt.js +336 -0
- package/dist/chunks/{load-CjPvISzH.js → load-b38vUiZM.js} +0 -4
- package/dist/chunks/{page-bundles-DLRIBP8g.js → page-bundles-CPj_vx-J.js} +1 -5
- package/dist/chunks/{persistence-DCMakM9H.js → persistence-hurkUUQ0.js} +0 -6
- package/dist/chunks/{projection-yvYKzMOS.js → projection-zhu32_KJ.js} +1 -15
- package/dist/chunks/{query-BPuCJC1C.js → query-D6xQbTFK.js} +166 -12
- package/dist/chunks/{refs-BLUokra5.js → refs-Csgh6rXq.js} +0 -4
- package/dist/chunks/{structure-o9pYoDjD.js → structure-CKBtQHJq.js} +1 -7
- package/dist/chunks/{validate-4LgH8QMJ.js → validate-BcB_PA1k.js} +20 -13
- package/dist/core.js +138 -47
- package/dist/forms.js +2 -0
- package/dist/print.js +0 -24
- package/dist/react.js +352 -22
- package/dist/runtime.js +2 -12
- package/dist/styles.css +9 -15
- package/dist/testing.js +214 -19
- package/dist/theme.js +0 -10
- package/dist/types/catalog/check.d.ts +0 -13
- package/dist/types/core/actions.d.ts +0 -24
- package/dist/types/core/bundles/load.d.ts +0 -23
- package/dist/types/core/bundles/page-bundles.d.ts +0 -9
- package/dist/types/core/bundles/refs.d.ts +1 -28
- package/dist/types/core/bundles/resolve.d.ts +0 -10
- package/dist/types/core/cell-props.d.ts +0 -20
- package/dist/types/core/cells.d.ts +0 -21
- package/dist/types/core/data-context.d.ts +4 -21
- package/dist/types/core/diagnostics.d.ts +20 -6
- package/dist/types/core/graph.d.ts +6 -44
- package/dist/types/core/index.d.ts +4 -3
- package/dist/types/core/layout.d.ts +0 -9
- package/dist/types/core/load-page.d.ts +30 -88
- package/dist/types/core/query.d.ts +6 -52
- package/dist/types/core/references.d.ts +0 -21
- package/dist/types/core/release.d.ts +11 -0
- package/dist/types/core/rules.d.ts +0 -1
- package/dist/types/core/selected.d.ts +0 -5
- package/dist/types/core/sources.d.ts +10 -63
- package/dist/types/core/store/create-store.d.ts +0 -6
- package/dist/types/core/store/persistence.d.ts +0 -1
- package/dist/types/core/store/projection.d.ts +0 -5
- package/dist/types/core/store/scope-keys.d.ts +0 -1
- package/dist/types/core/store/types.d.ts +0 -6
- package/dist/types/core/structure.d.ts +0 -33
- package/dist/types/core/types.d.ts +2 -13
- package/dist/types/core/validate.d.ts +0 -12
- package/dist/types/core/values.d.ts +0 -6
- package/dist/types/forms/conditions.d.ts +18 -0
- package/dist/types/forms/index.d.ts +3 -0
- package/dist/types/forms/model.d.ts +90 -0
- package/dist/types/forms/port.d.ts +47 -0
- package/dist/types/print/document-bindings.d.ts +0 -61
- package/dist/types/print/document-profile.d.ts +0 -137
- package/dist/types/print/map-staleness.d.ts +0 -66
- package/dist/types/print/page-map.d.ts +1 -334
- package/dist/types/print/paginate.d.ts +0 -190
- package/dist/types/print/print-layout.d.ts +0 -161
- package/dist/types/print/print-lint.d.ts +0 -109
- package/dist/types/print/print-policy.d.ts +0 -184
- package/dist/types/print/print-stylesheet.d.ts +0 -135
- package/dist/types/print/running-header.d.ts +0 -86
- package/dist/types/print/structure-print.d.ts +1 -243
- package/dist/types/react/cell-states.d.ts +0 -2
- package/dist/types/react/cell-view.d.ts +1 -15
- package/dist/types/react/index.d.ts +1 -0
- package/dist/types/react/page-renderer.d.ts +1 -33
- package/dist/types/react/structure-view.d.ts +0 -12
- package/dist/types/react/use-cell-store.d.ts +0 -5
- package/dist/types/react/use-container-size.d.ts +0 -5
- package/dist/types/react/use-forms-runtime.d.ts +147 -0
- package/dist/types/react/use-paging.d.ts +0 -9
- package/dist/types/runtime/boot.d.ts +0 -11
- package/dist/types/runtime/install.d.ts +0 -15
- package/dist/types/runtime/shims.d.ts +0 -8
- package/dist/types/runtime/store-export.d.ts +0 -7
- package/dist/types/testing/base-props.d.ts +0 -1
- package/dist/types/testing/components.d.ts +0 -8
- package/dist/types/testing/form-workbook.d.ts +103 -0
- package/dist/types/testing/golden.d.ts +0 -16
- package/dist/types/testing/ids.d.ts +0 -2
- package/dist/types/testing/index.d.ts +1 -0
- package/dist/types/testing/sources.d.ts +0 -7
- package/dist/types/theme/check.d.ts +0 -2
- package/dist/types/theme/color.d.ts +0 -12
- package/dist/types/theme/derive.d.ts +0 -12
- package/dist/types/theme/parse.d.ts +0 -7
- package/package.json +6 -2
- package/dist/catalog.js.map +0 -1
- package/dist/chunks/load-CjPvISzH.js.map +0 -1
- package/dist/chunks/page-bundles-DLRIBP8g.js.map +0 -1
- package/dist/chunks/persistence-DCMakM9H.js.map +0 -1
- package/dist/chunks/projection-yvYKzMOS.js.map +0 -1
- package/dist/chunks/query-BPuCJC1C.js.map +0 -1
- package/dist/chunks/refs-BLUokra5.js.map +0 -1
- package/dist/chunks/structure-o9pYoDjD.js.map +0 -1
- package/dist/chunks/validate-4LgH8QMJ.js.map +0 -1
- package/dist/core.js.map +0 -1
- package/dist/print.js.map +0 -1
- package/dist/react.js.map +0 -1
- package/dist/runtime.js.map +0 -1
- package/dist/testing.js.map +0 -1
- package/dist/theme.js.map +0 -1
package/dist/react.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
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-
|
|
2
|
-
import { C as
|
|
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-
|
|
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";
|
|
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";
|
|
4
5
|
import { Component, Fragment, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
5
6
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { useSelector } from "@tanstack/react-store";
|
|
7
|
-
//#region packages/renderer/src/react/cell-states.tsx
|
|
8
8
|
function CellPlaceholder({ state }) {
|
|
9
9
|
return jsx("div", {
|
|
10
10
|
className: "cell-placeholder",
|
|
@@ -42,8 +42,6 @@ var CellErrorBoundary = class extends Component {
|
|
|
42
42
|
}) : this.props.children;
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
-
//#endregion
|
|
46
|
-
//#region packages/renderer/src/react/use-cell-store.ts
|
|
47
45
|
function useCellStore(cell, scope, api) {
|
|
48
46
|
const selections = useSelector(api.store, (s) => projectSelections(cell.selections, s, scope), { compare: shallowEqualBundle });
|
|
49
47
|
const viewState = useSelector(api.store, (s) => projectViewState(cell.viewState, s, scope), { compare: shallowEqualBundle });
|
|
@@ -80,8 +78,6 @@ function useCellStore(cell, scope, api) {
|
|
|
80
78
|
scope.projectId
|
|
81
79
|
]);
|
|
82
80
|
}
|
|
83
|
-
//#endregion
|
|
84
|
-
//#region packages/renderer/src/react/use-container-size.ts
|
|
85
81
|
function useContainerSize(ref, enabled) {
|
|
86
82
|
const [size, setSize] = useState();
|
|
87
83
|
useEffect(() => {
|
|
@@ -106,8 +102,6 @@ function useContainerSize(ref, enabled) {
|
|
|
106
102
|
}, [ref, enabled]);
|
|
107
103
|
return size;
|
|
108
104
|
}
|
|
109
|
-
//#endregion
|
|
110
|
-
//#region packages/renderer/src/react/use-paging.ts
|
|
111
105
|
var LABEL_REF = /@([A-Za-z0-9_$-]+)/g;
|
|
112
106
|
function cellLabels(cell) {
|
|
113
107
|
const out = new Set(Object.keys(cell.data?.queries ?? {}));
|
|
@@ -207,8 +201,6 @@ function usePaging(cell, entries, loadPage) {
|
|
|
207
201
|
loadPage
|
|
208
202
|
]);
|
|
209
203
|
}
|
|
210
|
-
//#endregion
|
|
211
|
-
//#region packages/renderer/src/react/cell-view.tsx
|
|
212
204
|
var REPEAT_SLOT = "item";
|
|
213
205
|
function useSoftNavigation(navigate) {
|
|
214
206
|
return useCallback((e) => {
|
|
@@ -399,7 +391,8 @@ function CellView({ cell, env, nested = false, injectedProps }) {
|
|
|
399
391
|
resolvedProps: {
|
|
400
392
|
...resolvedProps,
|
|
401
393
|
...slots,
|
|
402
|
-
...injectedProps
|
|
394
|
+
...injectedProps,
|
|
395
|
+
...env.cellProps?.(cell)
|
|
403
396
|
},
|
|
404
397
|
children,
|
|
405
398
|
baseProps: env.baseProps,
|
|
@@ -437,8 +430,6 @@ function CellView({ cell, env, nested = false, injectedProps }) {
|
|
|
437
430
|
children: body
|
|
438
431
|
});
|
|
439
432
|
}
|
|
440
|
-
//#endregion
|
|
441
|
-
//#region packages/renderer/src/react/structure-view.tsx
|
|
442
433
|
function useStructureFacts(structure, cells, env, documents) {
|
|
443
434
|
return useMemo(() => {
|
|
444
435
|
const numbering = deriveSectionNumbering(structure);
|
|
@@ -533,13 +524,11 @@ function StructureView({ nodes, env, facts, level = 0, documentId = PAGE_DOCUMEN
|
|
|
533
524
|
}, `${node.sectionId ?? ""}\u0000${node.cellId ?? index}`);
|
|
534
525
|
}) });
|
|
535
526
|
}
|
|
536
|
-
//#endregion
|
|
537
|
-
//#region packages/renderer/src/react/page-renderer.tsx
|
|
538
527
|
var warn = (d) => console.warn(`[render] ${d.code}${d.cellId ? ` (cell ${d.cellId})` : ""}: ${d.message}`);
|
|
539
528
|
function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, environment }) {
|
|
540
529
|
const { page, cells } = runtime;
|
|
541
530
|
const declared = useMemo(() => new Set(runtime.declared), [runtime.declared]);
|
|
542
|
-
const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, retry } = environment;
|
|
531
|
+
const { core, navigate, store, onDiagnostic = warn, actionsFor, runAction, loadPage, onCellError, onUnresolvedReference, onPropSources, frameProps, cellProps, retry } = environment;
|
|
543
532
|
useEffect(() => {
|
|
544
533
|
for (const d of runtime.diagnostics) onDiagnostic(d);
|
|
545
534
|
}, [runtime.diagnostics, onDiagnostic]);
|
|
@@ -566,6 +555,7 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
566
555
|
onPropSources,
|
|
567
556
|
onDiagnostic,
|
|
568
557
|
frameProps,
|
|
558
|
+
cellProps,
|
|
569
559
|
renderEmbed: (cellId) => {
|
|
570
560
|
const embedded = runtime.embeds?.[cellId];
|
|
571
561
|
if (!embedded) return jsx(CellNotice, {
|
|
@@ -615,6 +605,7 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
615
605
|
onPropSources,
|
|
616
606
|
onDiagnostic,
|
|
617
607
|
frameProps,
|
|
608
|
+
cellProps,
|
|
618
609
|
retry,
|
|
619
610
|
environment
|
|
620
611
|
]);
|
|
@@ -647,7 +638,346 @@ function PageRenderer({ runtime, bundles, params, baseProps, context, viewer, en
|
|
|
647
638
|
}, cell.id))
|
|
648
639
|
});
|
|
649
640
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
641
|
+
var FORM_SAVE_DEBOUNCE_MS = 3e3;
|
|
642
|
+
var answerInputId = (key) => `form-answer-${key.replace(/[^\w-]/g, "_")}`;
|
|
643
|
+
var reviewOf = (notes) => {
|
|
644
|
+
const last = [...notes ?? []].reverse().find((n) => n.status);
|
|
645
|
+
return last ? {
|
|
646
|
+
status: last.status,
|
|
647
|
+
note: last.text,
|
|
648
|
+
at: last.at,
|
|
649
|
+
by: last.by ?? null
|
|
650
|
+
} : null;
|
|
651
|
+
};
|
|
652
|
+
var answeredOf = (v) => Object.fromEntries(Object.entries(v).map(([k, a]) => [k, a.value]));
|
|
653
|
+
function useFormsRuntime(o) {
|
|
654
|
+
const [values, setValues] = useState(() => answeredOf(o.initial));
|
|
655
|
+
const [mode, setMode] = useState(() => o.link?.mode === "question" ? "question" : defaultMode(!!o.phone));
|
|
656
|
+
const [status, setStatus] = useState(o.status);
|
|
657
|
+
const [visited, setVisited] = useState(() => new Set(o.visited ?? []));
|
|
658
|
+
const [save, setSave] = useState({ state: "idle" });
|
|
659
|
+
const [refusals, setRefusals] = useState({});
|
|
660
|
+
const [submitTried, setSubmitTried] = useState(false);
|
|
661
|
+
const focusKey = useRef(null);
|
|
662
|
+
const steps = useMemo(() => visibleSteps(o.model, values), [o.model, values]);
|
|
663
|
+
const [at, setAt] = useState(() => positionFromLink(visibleSteps(o.model, answeredOf(o.initial)), mode, o.link ?? {}));
|
|
664
|
+
const here = settle(steps, mode, at);
|
|
665
|
+
const readOnly = isReadOnlyStatus(status);
|
|
666
|
+
const opts = useRef(o);
|
|
667
|
+
opts.current = o;
|
|
668
|
+
const expected = useRef(new Map(Object.entries(o.initial).map(([k, a]) => [k, a.stateId ?? null])));
|
|
669
|
+
const pending = useRef(new Map());
|
|
670
|
+
const timer = useRef(null);
|
|
671
|
+
const chain = useRef(Promise.resolve());
|
|
672
|
+
const words = (code, message) => opts.current.describe?.(code) ?? message ?? code;
|
|
673
|
+
const flush = useCallback(() => {
|
|
674
|
+
if (timer.current) clearTimeout(timer.current);
|
|
675
|
+
timer.current = null;
|
|
676
|
+
const batch = [...pending.current];
|
|
677
|
+
pending.current.clear();
|
|
678
|
+
if (!batch.length) return chain.current;
|
|
679
|
+
chain.current = chain.current.then(async () => {
|
|
680
|
+
setSave({ state: "saving" });
|
|
681
|
+
for (const [key, value] of batch) {
|
|
682
|
+
const q = opts.current.model.steps.flatMap(questionsOf).find((x) => x.key === key);
|
|
683
|
+
const r = await opts.current.port.save({
|
|
684
|
+
key,
|
|
685
|
+
value,
|
|
686
|
+
expectedStateId: expected.current.get(key) ?? null,
|
|
687
|
+
...q?.node ? { node: q.node } : {}
|
|
688
|
+
}).catch(() => ({
|
|
689
|
+
ok: false,
|
|
690
|
+
code: "NETWORK"
|
|
691
|
+
}));
|
|
692
|
+
if (!r.ok) {
|
|
693
|
+
if (!pending.current.has(key)) pending.current.set(key, value);
|
|
694
|
+
const said = words(r.code, "message" in r ? r.message : void 0);
|
|
695
|
+
setRefusals((x) => ({
|
|
696
|
+
...x,
|
|
697
|
+
[key]: said
|
|
698
|
+
}));
|
|
699
|
+
setSave({
|
|
700
|
+
state: "error",
|
|
701
|
+
error: said
|
|
702
|
+
});
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
expected.current.set(key, r.stateId ?? null);
|
|
706
|
+
setRefusals((x) => key in x ? Object.fromEntries(Object.entries(x).filter(([k]) => k !== key)) : x);
|
|
707
|
+
}
|
|
708
|
+
setSave({
|
|
709
|
+
state: "saved",
|
|
710
|
+
at: new Date().toISOString()
|
|
711
|
+
});
|
|
712
|
+
});
|
|
713
|
+
return chain.current;
|
|
714
|
+
}, []);
|
|
715
|
+
const change = useCallback((key, value) => {
|
|
716
|
+
if (isReadOnlyStatus(status)) return;
|
|
717
|
+
setValues((v) => ({
|
|
718
|
+
...v,
|
|
719
|
+
[key]: value
|
|
720
|
+
}));
|
|
721
|
+
pending.current.set(key, value);
|
|
722
|
+
if (timer.current) clearTimeout(timer.current);
|
|
723
|
+
timer.current = setTimeout(() => void flush(), FORM_SAVE_DEBOUNCE_MS);
|
|
724
|
+
}, [flush, status]);
|
|
725
|
+
useEffect(() => {
|
|
726
|
+
const onLeave = () => void flush();
|
|
727
|
+
window.addEventListener("pagehide", onLeave);
|
|
728
|
+
return () => {
|
|
729
|
+
window.removeEventListener("pagehide", onLeave);
|
|
730
|
+
flush();
|
|
731
|
+
};
|
|
732
|
+
}, [flush]);
|
|
733
|
+
const headingRef = useRef(null);
|
|
734
|
+
const contentRef = useRef(null);
|
|
735
|
+
const go = useCallback((to) => {
|
|
736
|
+
if (!to) return;
|
|
737
|
+
flush();
|
|
738
|
+
const stepChanged = to.step !== here?.step;
|
|
739
|
+
setAt(to);
|
|
740
|
+
opts.current.onNavigate?.(linkTo(steps, mode, to), { replace: !stepChanged });
|
|
741
|
+
}, [
|
|
742
|
+
flush,
|
|
743
|
+
here?.step,
|
|
744
|
+
steps,
|
|
745
|
+
mode
|
|
746
|
+
]);
|
|
747
|
+
useEffect(() => {
|
|
748
|
+
if (!here) return;
|
|
749
|
+
contentRef.current?.scrollTo?.({ top: 0 });
|
|
750
|
+
headingRef.current?.focus({ preventScroll: true });
|
|
751
|
+
if (!visited.has(here.step)) {
|
|
752
|
+
setVisited((v) => new Set(v).add(here.step));
|
|
753
|
+
opts.current.port.visit(here.step).catch(() => void 0);
|
|
754
|
+
}
|
|
755
|
+
}, [here?.step]);
|
|
756
|
+
useEffect(() => {
|
|
757
|
+
const key = focusKey.current;
|
|
758
|
+
if (!key) return;
|
|
759
|
+
const el = typeof document === "undefined" ? null : document.getElementById(answerInputId(key));
|
|
760
|
+
if (el) {
|
|
761
|
+
focusKey.current = null;
|
|
762
|
+
el.focus({ preventScroll: false });
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
const index = here ? steps.findIndex((s) => s.id === here.step) : -1;
|
|
766
|
+
const step = steps[index];
|
|
767
|
+
const isLast = index === steps.length - 1;
|
|
768
|
+
const nextPos = here ? move(steps, mode, here, 1) : null;
|
|
769
|
+
const p = progress(steps, values, visited);
|
|
770
|
+
const allMissing = missing(steps, values);
|
|
771
|
+
const advance = useCallback(() => go(nextPos), [go, nextPos]);
|
|
772
|
+
const back = useCallback(() => here && go(move(steps, mode, here, -1)), [
|
|
773
|
+
go,
|
|
774
|
+
here,
|
|
775
|
+
steps,
|
|
776
|
+
mode
|
|
777
|
+
]);
|
|
778
|
+
const runSubmit = useCallback(async () => {
|
|
779
|
+
setSubmitTried(true);
|
|
780
|
+
if (o.model.submitRequired === "block" && allMissing.length) return;
|
|
781
|
+
await flush();
|
|
782
|
+
const r = await opts.current.port.submit({ missing: allMissing.map((q) => q.key) }).catch(() => ({
|
|
783
|
+
ok: false,
|
|
784
|
+
code: "NETWORK"
|
|
785
|
+
}));
|
|
786
|
+
if (r.ok) setStatus("submitted");
|
|
787
|
+
else setSave({
|
|
788
|
+
state: "error",
|
|
789
|
+
error: words(r.code, "message" in r ? r.message : void 0)
|
|
790
|
+
});
|
|
791
|
+
}, [
|
|
792
|
+
o.model.submitRequired,
|
|
793
|
+
allMissing,
|
|
794
|
+
flush
|
|
795
|
+
]);
|
|
796
|
+
const runReopen = useCallback(async () => {
|
|
797
|
+
const r = await opts.current.port.reopen().catch(() => ({
|
|
798
|
+
ok: false,
|
|
799
|
+
code: "NETWORK"
|
|
800
|
+
}));
|
|
801
|
+
if (r.ok) setStatus("in_progress");
|
|
802
|
+
else setSave({
|
|
803
|
+
state: "error",
|
|
804
|
+
error: words(r.code, "message" in r ? r.message : void 0)
|
|
805
|
+
});
|
|
806
|
+
}, []);
|
|
807
|
+
const onKeyDown = useCallback((e) => {
|
|
808
|
+
if (e.key !== "Enter" || e.shiftKey || e.nativeEvent.isComposing || !step) return;
|
|
809
|
+
if (e.target.tagName === "TEXTAREA") return;
|
|
810
|
+
if (!enterAdvances(step, mode, here?.question)) return;
|
|
811
|
+
e.preventDefault();
|
|
812
|
+
advance();
|
|
813
|
+
}, [
|
|
814
|
+
step,
|
|
815
|
+
mode,
|
|
816
|
+
here?.question,
|
|
817
|
+
advance
|
|
818
|
+
]);
|
|
819
|
+
const nextStep = nextPos && nextPos.step !== here?.step ? steps.find((s) => s.id === nextPos.step) : null;
|
|
820
|
+
const stepQuestions = step ? questionsOf(step) : [];
|
|
821
|
+
const qIndex = mode === "question" && here?.question ? stepQuestions.findIndex((q) => q.key === here.question) : -1;
|
|
822
|
+
const questionHere = qIndex >= 0 ? {
|
|
823
|
+
index: qIndex,
|
|
824
|
+
count: stepQuestions.length,
|
|
825
|
+
key: stepQuestions[qIndex].key,
|
|
826
|
+
next: stepQuestions[qIndex + 1] ? { label: stepQuestions[qIndex + 1].label } : null
|
|
827
|
+
} : null;
|
|
828
|
+
const passed = new Set(steps.slice(0, Math.max(index, 0)).map((s) => s.id).filter((id) => visited.has(id)));
|
|
829
|
+
const missingKeys = new Set(allMissing.map((q) => q.key));
|
|
830
|
+
const answerOf = (q, stepId) => {
|
|
831
|
+
const port = o.port;
|
|
832
|
+
return {
|
|
833
|
+
key: q.key,
|
|
834
|
+
label: q.label,
|
|
835
|
+
question: q.definition ?? null,
|
|
836
|
+
value: values[q.key],
|
|
837
|
+
change: (v) => change(q.key, v),
|
|
838
|
+
readOnly,
|
|
839
|
+
required: q.required,
|
|
840
|
+
missing: missingKeys.has(q.key) && (submitTried || passed.has(stepId)),
|
|
841
|
+
refusal: refusals[q.key] ?? null,
|
|
842
|
+
inputId: answerInputId(q.key),
|
|
843
|
+
...port.upload ? { upload: async (file) => {
|
|
844
|
+
if (isReadOnlyStatus(status)) return {
|
|
845
|
+
ok: false,
|
|
846
|
+
refusal: words("FORM_NOT_OPEN")
|
|
847
|
+
};
|
|
848
|
+
const r = await port.upload({
|
|
849
|
+
key: q.key,
|
|
850
|
+
file,
|
|
851
|
+
...q.node ? { node: q.node } : {}
|
|
852
|
+
}).catch(() => ({
|
|
853
|
+
ok: false,
|
|
854
|
+
code: "NETWORK"
|
|
855
|
+
}));
|
|
856
|
+
if (!r.ok) return {
|
|
857
|
+
ok: false,
|
|
858
|
+
refusal: words(r.code, "message" in r ? r.message : void 0)
|
|
859
|
+
};
|
|
860
|
+
change(q.key, r.answer);
|
|
861
|
+
await flush();
|
|
862
|
+
return { ok: true };
|
|
863
|
+
} } : {},
|
|
864
|
+
...port.openFile ? { openFile: async () => {
|
|
865
|
+
const v = values[q.key];
|
|
866
|
+
if (!v?.file) return null;
|
|
867
|
+
const r = await port.openFile(v.file).catch(() => null);
|
|
868
|
+
return r && r.ok ? r.url : null;
|
|
869
|
+
} } : {}
|
|
870
|
+
};
|
|
871
|
+
};
|
|
872
|
+
const questionAnswer = questionHere && step ? stepQuestions.find((q) => q.key === questionHere.key) : void 0;
|
|
873
|
+
const stable = useStableSlots(step ? {
|
|
874
|
+
title: o.model.title,
|
|
875
|
+
chapter: step.chapter && o.model.chapters.find((c) => c.id === step.chapter) || null,
|
|
876
|
+
step: {
|
|
877
|
+
id: step.id,
|
|
878
|
+
title: step.title,
|
|
879
|
+
index,
|
|
880
|
+
count: steps.length,
|
|
881
|
+
kind: stepKind(step, isLast),
|
|
882
|
+
...step.label ? { label: step.label } : {}
|
|
883
|
+
},
|
|
884
|
+
sections: steps.map((s, i) => ({
|
|
885
|
+
id: s.id,
|
|
886
|
+
title: s.title,
|
|
887
|
+
...s.chapter ? { chapter: s.chapter } : {},
|
|
888
|
+
kind: stepKind(s, i === steps.length - 1),
|
|
889
|
+
...s.label ? { label: s.label } : {},
|
|
890
|
+
...p.perStep[s.id],
|
|
891
|
+
current: s.id === step.id
|
|
892
|
+
})),
|
|
893
|
+
progress: {
|
|
894
|
+
answered: p.answered,
|
|
895
|
+
required: p.required,
|
|
896
|
+
ratio: p.ratio,
|
|
897
|
+
total: p.total
|
|
898
|
+
},
|
|
899
|
+
question: questionHere && questionAnswer ? {
|
|
900
|
+
...questionHere,
|
|
901
|
+
answer: answerOf(questionAnswer, step.id)
|
|
902
|
+
} : questionHere,
|
|
903
|
+
goToQuestion: (key) => {
|
|
904
|
+
focusKey.current = key;
|
|
905
|
+
go(goToQuestion(steps, mode, key));
|
|
906
|
+
},
|
|
907
|
+
displayMode: mode,
|
|
908
|
+
setDisplayMode: (m) => {
|
|
909
|
+
setMode(m);
|
|
910
|
+
if (here) setAt(settle(steps, m, here));
|
|
911
|
+
},
|
|
912
|
+
goToSection: (id) => go(goTo(steps, mode, id, values)),
|
|
913
|
+
advance,
|
|
914
|
+
back,
|
|
915
|
+
canBack: o.model.allowBack && index > 0,
|
|
916
|
+
next: nextStep ? { title: nextStep.title } : null,
|
|
917
|
+
submit: isLast && !readOnly && o.model.submittable !== false ? {
|
|
918
|
+
label: "Submit",
|
|
919
|
+
run: () => void runSubmit(),
|
|
920
|
+
blocked: o.model.submitRequired === "block" && allMissing.length > 0
|
|
921
|
+
} : null,
|
|
922
|
+
reopen: status === "submitted" && o.model.submittable !== false ? {
|
|
923
|
+
label: "Edit answers",
|
|
924
|
+
run: () => void runReopen()
|
|
925
|
+
} : null,
|
|
926
|
+
save,
|
|
927
|
+
missing: missing(steps, values, step.id).map((q) => ({
|
|
928
|
+
key: q.key,
|
|
929
|
+
label: q.label
|
|
930
|
+
})),
|
|
931
|
+
chapters: o.model.chapters.map((c) => ({
|
|
932
|
+
id: c.id,
|
|
933
|
+
title: c.title
|
|
934
|
+
})),
|
|
935
|
+
status,
|
|
936
|
+
readOnly,
|
|
937
|
+
review: reviewOf(o.notes)
|
|
938
|
+
} : null);
|
|
939
|
+
const cellProps = (cell) => {
|
|
940
|
+
for (const s of steps) {
|
|
941
|
+
const item = s.items.find((i) => i.id === cell.id);
|
|
942
|
+
if (!item) continue;
|
|
943
|
+
const answers = Object.fromEntries(item.questions.map((q) => [q.key, answerOf(q, s.id)]));
|
|
944
|
+
const list = Object.values(answers);
|
|
945
|
+
return {
|
|
946
|
+
form: stable,
|
|
947
|
+
answers,
|
|
948
|
+
...list.length === 1 ? { answer: list[0] } : {}
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
};
|
|
952
|
+
return {
|
|
953
|
+
slots: stable,
|
|
954
|
+
cellProps,
|
|
955
|
+
steps,
|
|
956
|
+
step: step ?? null,
|
|
957
|
+
position: here,
|
|
958
|
+
values,
|
|
959
|
+
change,
|
|
960
|
+
flush,
|
|
961
|
+
readOnly,
|
|
962
|
+
status,
|
|
963
|
+
headingRef,
|
|
964
|
+
contentRef,
|
|
965
|
+
onKeyDown
|
|
966
|
+
};
|
|
967
|
+
}
|
|
968
|
+
function useStableSlots(slots) {
|
|
969
|
+
const latest = useRef(slots);
|
|
970
|
+
latest.current = slots;
|
|
971
|
+
const shown = JSON.stringify(slots);
|
|
972
|
+
return useMemo(() => slots ? bindActions(slots, [], latest) : null, [shown]);
|
|
973
|
+
}
|
|
974
|
+
function bindActions(v, path, latest) {
|
|
975
|
+
if (typeof v === "function") return (...args) => {
|
|
976
|
+
const fn = path.reduce((o, k) => o?.[k], latest.current);
|
|
977
|
+
return typeof fn === "function" ? fn(...args) : void 0;
|
|
978
|
+
};
|
|
979
|
+
if (Array.isArray(v)) return v.map((x, i) => bindActions(x, [...path, String(i)], latest));
|
|
980
|
+
if (v && typeof v === "object") return Object.fromEntries(Object.entries(v).map(([k, x]) => [k, bindActions(x, [...path, k], latest)]));
|
|
981
|
+
return v;
|
|
982
|
+
}
|
|
983
|
+
export { CellErrorBoundary, CellNotice, CellPlaceholder, CellView, FORM_SAVE_DEBOUNCE_MS, PageRenderer, StructureView, answerInputId, cellLabels, useCellStore, useContainerSize, useFormsRuntime, usePaging, useStructureFacts };
|
package/dist/runtime.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { s as runtimeReady } from "./chunks/load-
|
|
2
|
-
import { a as createStackStore, t as clearAllScopes } from "./chunks/persistence-
|
|
1
|
+
import { s as runtimeReady } from "./chunks/load-b38vUiZM.js";
|
|
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";
|
|
5
5
|
import * as JsxRuntime from "react/jsx-runtime";
|
|
@@ -8,7 +8,6 @@ import * as ReactDOM from "react-dom";
|
|
|
8
8
|
import * as ReactDOMClient from "react-dom/client";
|
|
9
9
|
import * as JsxDevRuntime from "react/jsx-dev-runtime";
|
|
10
10
|
import * as zustand from "zustand";
|
|
11
|
-
//#region packages/renderer/src/runtime/boot.ts
|
|
12
11
|
var RUNTIME_BOOT_SCRIPT = `(function(g){if(g.${READY_GLOBAL})return;g.${READY_GLOBAL}=new Promise(function(r){g.${RESOLVE_GLOBAL}=r;});})(globalThis);`;
|
|
13
12
|
function importMapFor(shared = []) {
|
|
14
13
|
return { imports: buildImportMap(shared).imports };
|
|
@@ -17,8 +16,6 @@ function importMapJson(shared = []) {
|
|
|
17
16
|
return JSON.stringify(importMapFor(shared)).replace(/</g, "\\u003c");
|
|
18
17
|
}
|
|
19
18
|
var IMPORT_MAP_JSON = importMapJson();
|
|
20
|
-
//#endregion
|
|
21
|
-
//#region packages/renderer/src/runtime/store-export.ts
|
|
22
19
|
var singleton = null;
|
|
23
20
|
function getStackStore() {
|
|
24
21
|
return singleton ??= createStackStore();
|
|
@@ -43,8 +40,6 @@ function buildStoreRuntime() {
|
|
|
43
40
|
selectors
|
|
44
41
|
};
|
|
45
42
|
}
|
|
46
|
-
//#endregion
|
|
47
|
-
//#region packages/renderer/src/runtime/install.ts
|
|
48
43
|
function buildRuntime(extra = {}) {
|
|
49
44
|
return {
|
|
50
45
|
react: React,
|
|
@@ -68,8 +63,6 @@ function installRuntime(g = globalThis, extra = {}) {
|
|
|
68
63
|
g[RESOLVE_GLOBAL]?.();
|
|
69
64
|
return runtime;
|
|
70
65
|
}
|
|
71
|
-
//#endregion
|
|
72
|
-
//#region packages/renderer/src/runtime/shims.ts
|
|
73
66
|
function shimFileName(specifier) {
|
|
74
67
|
const base = PINNED_RUNTIMES[specifier].url.split("/").pop();
|
|
75
68
|
if (!base?.endsWith(".js")) throw new Error(`[runtime] ${specifier}: url is not a .js file`);
|
|
@@ -92,7 +85,4 @@ function renderShim(specifier, names, hasDefault) {
|
|
|
92
85
|
}
|
|
93
86
|
return lines.join("\n") + "\n";
|
|
94
87
|
}
|
|
95
|
-
//#endregion
|
|
96
88
|
export { IMPORT_MAP_JSON, RUNTIME_BOOT_SCRIPT, buildRuntime, getStackStore, importMapFor, importMapJson, installRuntime, renderShim, resetStackStore, runtimeReady, selectors, shimFileName, useStackStore };
|
|
97
|
-
|
|
98
|
-
//# sourceMappingURL=runtime.js.map
|
package/dist/styles.css
CHANGED
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
Import it once per app. Everything is in the `renderer` layer (design/core-and-tokens.md §7.2):
|
|
3
|
-
above the reset and the tokens, below every bundle and the org's theme. */
|
|
1
|
+
|
|
4
2
|
|
|
5
3
|
@layer renderer {
|
|
6
|
-
|
|
7
|
-
The page and every cell are size containers, so layout responds to the
|
|
8
|
-
space a component actually has, not the viewport. */
|
|
4
|
+
|
|
9
5
|
:root {
|
|
10
6
|
--cell-placeholder-bg: var(--color-surface-sunken, #f1f1f1);
|
|
11
7
|
--cell-notice-bg: var(--color-warning-surface, #fff4d6);
|
|
12
8
|
--cell-notice-fg: var(--color-warning, #6b4e00);
|
|
13
9
|
}
|
|
14
|
-
|
|
10
|
+
|
|
15
11
|
[data-page-container] { font-family: var(--font-body, system-ui, sans-serif); color: var(--color-text, inherit); }
|
|
16
12
|
[data-page-container] { container: page / inline-size; }
|
|
17
13
|
.cell { container: cell / inline-size; min-width: 0; }
|
|
18
|
-
|
|
19
|
-
Inline) an inline-size container would have no width of its own and collapse to nothing. Its
|
|
20
|
-
`@container cell` queries read the parent cell's width instead. */
|
|
14
|
+
|
|
21
15
|
.cell[data-nested] { container: none; }
|
|
22
16
|
.cell-placeholder { min-height: 6rem; border-radius: 0.5rem; background: var(--cell-placeholder-bg); }
|
|
23
17
|
.cell-placeholder[aria-busy='true'] { animation: cell-pulse 1.5s ease-in-out infinite; }
|
|
@@ -25,24 +19,24 @@
|
|
|
25
19
|
@media (prefers-reduced-motion: reduce) { .cell-placeholder[aria-busy='true'] { animation: none; } }
|
|
26
20
|
.cell-notice { padding: 0.75rem 1rem; border-radius: 0.5rem; background: var(--cell-notice-bg); color: var(--cell-notice-fg); }
|
|
27
21
|
|
|
28
|
-
|
|
22
|
+
|
|
29
23
|
[data-show-when] { display: none; }
|
|
30
24
|
@container page (max-width: 1024px) {
|
|
31
25
|
[data-hide-when='wide'] { display: none; }
|
|
32
26
|
[data-show-when='wide'] { display: revert; }
|
|
33
|
-
[data-stack-when='wide'] { grid-column: 1 / -1 !important; }
|
|
27
|
+
[data-stack-when='wide'] { grid-column: 1 / -1 !important; }
|
|
34
28
|
[data-truncate-when='wide'] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
35
29
|
}
|
|
36
30
|
@container page (max-width: 720px) {
|
|
37
31
|
[data-hide-when='compact'] { display: none; }
|
|
38
32
|
[data-show-when='compact'] { display: revert; }
|
|
39
|
-
[data-stack-when='compact'] { grid-column: 1 / -1 !important; }
|
|
33
|
+
[data-stack-when='compact'] { grid-column: 1 / -1 !important; }
|
|
40
34
|
[data-truncate-when='compact'] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
41
35
|
}
|
|
42
36
|
@container page (max-width: 480px) {
|
|
43
37
|
[data-hide-when='narrow'] { display: none; }
|
|
44
38
|
[data-show-when='narrow'] { display: revert; }
|
|
45
|
-
[data-stack-when='narrow'] { grid-column: 1 / -1 !important; }
|
|
39
|
+
[data-stack-when='narrow'] { grid-column: 1 / -1 !important; }
|
|
46
40
|
[data-truncate-when='narrow'] { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
47
41
|
}
|
|
48
42
|
|
|
@@ -54,6 +48,6 @@
|
|
|
54
48
|
}
|
|
55
49
|
}
|
|
56
50
|
|
|
57
|
-
|
|
51
|
+
|
|
58
52
|
.structure-section { grid-column: 1 / -1; display: flex; flex-direction: column; gap: inherit; }
|
|
59
53
|
}
|