@burojs/ui-shadcn 0.4.0 → 0.6.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 +22 -5
- package/dist/bulk-summary-CwSd6Yjb.cjs +108 -0
- package/dist/bulk-summary-CwSd6Yjb.cjs.map +1 -0
- package/dist/bulk-summary-GxMDP4bw.js +108 -0
- package/dist/bulk-summary-GxMDP4bw.js.map +1 -0
- package/dist/button-BxnnE28H.cjs +55 -0
- package/dist/button-BxnnE28H.cjs.map +1 -0
- package/dist/button-MWVeZaqj.js +44 -0
- package/dist/button-MWVeZaqj.js.map +1 -0
- package/dist/candidates-gate-Bb70LPAy.js +135 -0
- package/dist/candidates-gate-Bb70LPAy.js.map +1 -0
- package/dist/candidates-gate-D33jXLHO.cjs +153 -0
- package/dist/candidates-gate-D33jXLHO.cjs.map +1 -0
- package/dist/candidates-relation-picker-B116Bmqi.js +31 -0
- package/dist/candidates-relation-picker-B116Bmqi.js.map +1 -0
- package/dist/candidates-relation-picker-Cy0rTxvI.cjs +31 -0
- package/dist/candidates-relation-picker-Cy0rTxvI.cjs.map +1 -0
- package/dist/check-confirm-dialog--gPFnEeg.cjs +1547 -0
- package/dist/check-confirm-dialog--gPFnEeg.cjs.map +1 -0
- package/dist/check-confirm-dialog-bRT8lt0d.js +1245 -0
- package/dist/check-confirm-dialog-bRT8lt0d.js.map +1 -0
- package/dist/dialog-B_rt9S1c.js +63 -0
- package/dist/dialog-B_rt9S1c.js.map +1 -0
- package/dist/dialog-DRNUq9EA.cjs +112 -0
- package/dist/dialog-DRNUq9EA.cjs.map +1 -0
- package/dist/filter-builder-Bhn-dhZV.js +1621 -0
- package/dist/filter-builder-Bhn-dhZV.js.map +1 -0
- package/dist/filter-builder-nXqtM_h4.cjs +1789 -0
- package/dist/filter-builder-nXqtM_h4.cjs.map +1 -0
- package/dist/flow-runtime-D3avVH0I.cjs +255 -0
- package/dist/flow-runtime-D3avVH0I.cjs.map +1 -0
- package/dist/flow-runtime-s6lkRPKF.js +252 -0
- package/dist/flow-runtime-s6lkRPKF.js.map +1 -0
- package/dist/flow-screen-CCvgDI9G.js +704 -0
- package/dist/flow-screen-CCvgDI9G.js.map +1 -0
- package/dist/flow-screen-Ci_Sik4Y.cjs +708 -0
- package/dist/flow-screen-Ci_Sik4Y.cjs.map +1 -0
- package/dist/index.cjs +3420 -11986
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1843 -2015
- package/dist/index.d.ts +1849 -2021
- package/dist/index.js +3090 -11675
- package/dist/index.js.map +1 -1
- package/dist/inline-flow-host-B6FI0ctQ.js +112 -0
- package/dist/inline-flow-host-B6FI0ctQ.js.map +1 -0
- package/dist/inline-flow-host-DV1et3c6.cjs +112 -0
- package/dist/inline-flow-host-DV1et3c6.cjs.map +1 -0
- package/dist/input-BI0czGyI.cjs +23 -0
- package/dist/input-BI0czGyI.cjs.map +1 -0
- package/dist/input-CUPStzZO.js +17 -0
- package/dist/input-CUPStzZO.js.map +1 -0
- package/dist/label-66W1qbke.js +29 -0
- package/dist/label-66W1qbke.js.map +1 -0
- package/dist/label-w6JYf2cF.cjs +36 -0
- package/dist/label-w6JYf2cF.cjs.map +1 -0
- package/dist/markdown/index.cjs +1 -1
- package/dist/markdown/index.d.cts +2 -3
- package/dist/markdown/index.d.ts +2 -3
- package/dist/markdown/index.js +1 -1
- package/dist/page-flow-route-hdnULWqd.cjs +277 -0
- package/dist/page-flow-route-hdnULWqd.cjs.map +1 -0
- package/dist/page-flow-route-i3ZfJ1sd.js +277 -0
- package/dist/page-flow-route-i3ZfJ1sd.js.map +1 -0
- package/dist/place-node-C5SmIAYU.cjs +8139 -0
- package/dist/place-node-C5SmIAYU.cjs.map +1 -0
- package/dist/place-node-NraNYKPx.js +7597 -0
- package/dist/place-node-NraNYKPx.js.map +1 -0
- package/dist/related-list-cards-BWZ9GfOG.js +42 -0
- package/dist/related-list-cards-BWZ9GfOG.js.map +1 -0
- package/dist/related-list-cards-CFq3meUn.cjs +42 -0
- package/dist/related-list-cards-CFq3meUn.cjs.map +1 -0
- package/dist/related-list-timeline-CCzl71aA.cjs +142 -0
- package/dist/related-list-timeline-CCzl71aA.cjs.map +1 -0
- package/dist/related-list-timeline-yrPsjA3F.js +142 -0
- package/dist/related-list-timeline-yrPsjA3F.js.map +1 -0
- package/dist/related-rows-ea43qhhy.cjs +208 -0
- package/dist/related-rows-ea43qhhy.cjs.map +1 -0
- package/dist/related-rows-o0_t-Yce.js +185 -0
- package/dist/related-rows-o0_t-Yce.js.map +1 -0
- package/dist/relation-create-IA40t1hi.cjs +364 -0
- package/dist/relation-create-IA40t1hi.cjs.map +1 -0
- package/dist/relation-create-h6F9B4C4.js +339 -0
- package/dist/relation-create-h6F9B4C4.js.map +1 -0
- package/dist/relation-many-picker-C8zFEjwd.cjs +467 -0
- package/dist/relation-many-picker-C8zFEjwd.cjs.map +1 -0
- package/dist/relation-many-picker-bvkjkv-k.js +466 -0
- package/dist/relation-many-picker-bvkjkv-k.js.map +1 -0
- package/dist/relation-picker-Z0ZJJ5uS.js +493 -0
- package/dist/relation-picker-Z0ZJJ5uS.js.map +1 -0
- package/dist/relation-picker-dialog-0IzkjmiA.cjs +304 -0
- package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +1 -0
- package/dist/relation-picker-dialog-B6nIiJBf.js +303 -0
- package/dist/relation-picker-dialog-B6nIiJBf.js.map +1 -0
- package/dist/relation-picker-gag0qSR5.cjs +516 -0
- package/dist/relation-picker-gag0qSR5.cjs.map +1 -0
- package/dist/resource-page-router-3RUf9d1j.js +1588 -0
- package/dist/resource-page-router-3RUf9d1j.js.map +1 -0
- package/dist/resource-page-router-PXfMW9nh.cjs +1785 -0
- package/dist/resource-page-router-PXfMW9nh.cjs.map +1 -0
- package/dist/{rich-text-IDFvyvRE.js → rich-text-DFerywgz.js} +7 -4
- package/dist/{rich-text-IDFvyvRE.js.map → rich-text-DFerywgz.js.map} +1 -1
- package/dist/{rich-text-lndbYqzR.cjs → rich-text-vTyVjDoa.cjs} +25 -22
- package/dist/{rich-text-lndbYqzR.cjs.map → rich-text-vTyVjDoa.cjs.map} +1 -1
- package/dist/search-access-CPPmfuvy.js +654 -0
- package/dist/search-access-CPPmfuvy.js.map +1 -0
- package/dist/search-access-Dugvttlg.cjs +791 -0
- package/dist/search-access-Dugvttlg.cjs.map +1 -0
- package/dist/shell-BPlk8hEa.js +205 -0
- package/dist/shell-BPlk8hEa.js.map +1 -0
- package/dist/shell-DxhlsPwm.cjs +271 -0
- package/dist/shell-DxhlsPwm.cjs.map +1 -0
- package/dist/skeleton-U2noefj5.js +13 -0
- package/dist/skeleton-U2noefj5.js.map +1 -0
- package/dist/skeleton-_1gP7wan.cjs +18 -0
- package/dist/skeleton-_1gP7wan.cjs.map +1 -0
- package/dist/styles.css +241 -9
- package/dist/toaster-C02XbB9r.js +135 -0
- package/dist/toaster-C02XbB9r.js.map +1 -0
- package/dist/toaster-Cr51X7bz.cjs +195 -0
- package/dist/toaster-Cr51X7bz.cjs.map +1 -0
- package/dist/use-dialog-filter-state-C--oMAZG.js +87 -0
- package/dist/use-dialog-filter-state-C--oMAZG.js.map +1 -0
- package/dist/use-dialog-filter-state-Dhe8PcB5.cjs +92 -0
- package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +1 -0
- package/dist/{use-theme-BwPWinB2.cjs → use-theme-DFlpXils.cjs} +12 -1
- package/dist/use-theme-DFlpXils.cjs.map +1 -0
- package/dist/{use-theme-IHmtrhEt.js → use-theme-dnE3Od3I.js} +7 -2
- package/dist/use-theme-dnE3Od3I.js.map +1 -0
- package/package.json +16 -14
- package/dist/use-theme-BwPWinB2.cjs.map +0 -1
- package/dist/use-theme-IHmtrhEt.js.map +0 -1
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
import { Z as DocInfo } from "./check-confirm-dialog-bRT8lt0d.js";
|
|
2
|
+
import { t as Button } from "./button-MWVeZaqj.js";
|
|
3
|
+
import { n as OwnTitleContext } from "./shell-BPlk8hEa.js";
|
|
4
|
+
import { V as ScreenTree, kt as FieldDisplay, n as viewOf, t as selectImplementation } from "./place-node-NraNYKPx.js";
|
|
5
|
+
import { fieldSensitivity, humanizeKey, validatePlacementProps } from "@burojs/core";
|
|
6
|
+
import { ScreenStateProvider, resolveValidationMessage, useDismissPending, useFlowFormCatalog, useFlowOpenImplementation, useFormController, useI18nCaps, useOptionalT, useProjectedTitle, useTestIds, useUIInstance, useUIPresentationRuntime } from "@burojs/react";
|
|
7
|
+
import { IconLoader2, IconX } from "@tabler/icons-react";
|
|
8
|
+
import { Suspense, createContext, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
|
|
9
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
11
|
+
import { fieldEntriesToMap } from "@burojs/core/internal";
|
|
12
|
+
import { FlowTextsScope, useFlowForm, useFlowRun } from "@burojs/react/flows";
|
|
13
|
+
//#region src/flows/review-diff.tsx
|
|
14
|
+
const REVIEW_DIFF_BLOCK = "buro:review-diff";
|
|
15
|
+
function sensitive(definition) {
|
|
16
|
+
if (fieldSensitivity(definition) !== void 0) return true;
|
|
17
|
+
if (definition === null || typeof definition !== "object") return false;
|
|
18
|
+
const opts = definition.opts;
|
|
19
|
+
const marked = opts !== null && typeof opts === "object" ? opts.sensitive : void 0;
|
|
20
|
+
return marked !== void 0 && marked !== false && marked !== null;
|
|
21
|
+
}
|
|
22
|
+
const same = (a, b) => {
|
|
23
|
+
if (Object.is(a, b)) return true;
|
|
24
|
+
const empty = (value) => value === void 0 || value === null || value === "";
|
|
25
|
+
if (empty(a) && empty(b)) return true;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
28
|
+
} catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
function ReviewDiff({ form, initial, values, i18nPrefix, testid }) {
|
|
33
|
+
const t = useOptionalT();
|
|
34
|
+
const changedText = (() => {
|
|
35
|
+
const value = t("review.changed");
|
|
36
|
+
return value === "review.changed" ? "changed" : value;
|
|
37
|
+
})();
|
|
38
|
+
const rows = form.fields.filter((binding) => !same(initial[binding.name], values[binding.name]));
|
|
39
|
+
return jsx("dl", {
|
|
40
|
+
"data-testid": `${testid}:review`,
|
|
41
|
+
"data-buro-block": REVIEW_DIFF_BLOCK,
|
|
42
|
+
className: "grid gap-2",
|
|
43
|
+
children: rows.map((binding) => {
|
|
44
|
+
const definition = binding.field;
|
|
45
|
+
const label = typeof definition.label === "string" ? definition.label : humanizeKey(binding.name);
|
|
46
|
+
const hidden = sensitive(binding.field);
|
|
47
|
+
return jsxs("div", {
|
|
48
|
+
"data-testid": `${testid}:review:${binding.name}`,
|
|
49
|
+
className: "grid grid-cols-[minmax(0,1fr)_minmax(0,2fr)] gap-2 text-sm",
|
|
50
|
+
children: [jsx("dt", {
|
|
51
|
+
className: "font-medium",
|
|
52
|
+
children: label
|
|
53
|
+
}), jsx("dd", {
|
|
54
|
+
className: "flex flex-wrap items-center gap-2",
|
|
55
|
+
children: hidden ? jsx("span", {
|
|
56
|
+
className: "text-muted-foreground",
|
|
57
|
+
children: changedText
|
|
58
|
+
}) : jsxs(Fragment$1, { children: [
|
|
59
|
+
jsx("span", {
|
|
60
|
+
"data-buro-review": "old",
|
|
61
|
+
className: "text-muted-foreground line-through",
|
|
62
|
+
children: jsx(FieldDisplay, {
|
|
63
|
+
i18nPrefix,
|
|
64
|
+
name: binding.name,
|
|
65
|
+
field: binding.field,
|
|
66
|
+
value: initial[binding.name],
|
|
67
|
+
fallback: jsx("span", { children: display(initial[binding.name]) })
|
|
68
|
+
})
|
|
69
|
+
}),
|
|
70
|
+
jsx("span", {
|
|
71
|
+
"aria-hidden": "true",
|
|
72
|
+
children: "→"
|
|
73
|
+
}),
|
|
74
|
+
jsx("span", {
|
|
75
|
+
"data-buro-review": "new",
|
|
76
|
+
children: jsx(FieldDisplay, {
|
|
77
|
+
i18nPrefix,
|
|
78
|
+
name: binding.name,
|
|
79
|
+
field: binding.field,
|
|
80
|
+
value: values[binding.name],
|
|
81
|
+
fallback: jsx("span", { children: display(values[binding.name]) })
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
] })
|
|
85
|
+
})]
|
|
86
|
+
}, binding.name);
|
|
87
|
+
})
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const display = (value) => value === void 0 || value === null || value === "" ? "—" : String(value);
|
|
91
|
+
//#endregion
|
|
92
|
+
//#region src/flows/flow-screen.tsx
|
|
93
|
+
const HELD = Object.freeze({
|
|
94
|
+
name: "AbortError",
|
|
95
|
+
message: "The flow run sends the values."
|
|
96
|
+
});
|
|
97
|
+
function HostedFlowScreen(props) {
|
|
98
|
+
const { binding, ...rest } = props;
|
|
99
|
+
return jsx(FlowHostBindingContext.Provider, {
|
|
100
|
+
value: binding,
|
|
101
|
+
children: jsx(FlowScreen, { ...rest })
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const FlowHostBindingContext = createContext(null);
|
|
105
|
+
function OverlayBinding({ children }) {
|
|
106
|
+
const instance = useUIInstance();
|
|
107
|
+
const runtime = useUIPresentationRuntime();
|
|
108
|
+
const binding = useMemo(() => ({
|
|
109
|
+
kind: "overlay",
|
|
110
|
+
close: () => instance.dismiss(),
|
|
111
|
+
finish: () => runtime.dismiss(instance.id)
|
|
112
|
+
}), [instance, runtime]);
|
|
113
|
+
return jsx(FlowHostBindingContext.Provider, {
|
|
114
|
+
value: binding,
|
|
115
|
+
children
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function WithBinding({ children }) {
|
|
119
|
+
return useContext(FlowHostBindingContext) !== null ? jsx(Fragment$1, { children }) : jsx(OverlayBinding, { children });
|
|
120
|
+
}
|
|
121
|
+
function text(t, key, fallback, params) {
|
|
122
|
+
const value = t(key, params === void 0 ? void 0 : { params });
|
|
123
|
+
return value === key ? fallback : value;
|
|
124
|
+
}
|
|
125
|
+
const REJECTED_KEYS = {
|
|
126
|
+
validation: "validation",
|
|
127
|
+
conflict: "conflict",
|
|
128
|
+
forbidden: "forbidden",
|
|
129
|
+
"not-found": "notFound"
|
|
130
|
+
};
|
|
131
|
+
function outcomeMessage(snapshot, busy, t) {
|
|
132
|
+
if (busy) return text(t, "flow.busyElsewhere", "This action is running in another tab.");
|
|
133
|
+
const outcome = snapshot.outcome;
|
|
134
|
+
if (outcome === void 0 || outcome.outcome === "success") {
|
|
135
|
+
if (snapshot.control === "disabled" && snapshot.reason !== void 0) return snapshot.reason;
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
if (outcome.outcome === "unknown") return [text(t, "flow.unknown", "The request timed out. It may have been applied. Nothing was resent."), ...snapshot.reason === void 0 ? [] : [snapshot.reason]].join(" ");
|
|
139
|
+
if (outcome.outcome === "rejected") {
|
|
140
|
+
if (snapshot.reason !== void 0) return snapshot.reason;
|
|
141
|
+
const kind = "errorKind" in outcome ? outcome.errorKind : void 0;
|
|
142
|
+
const key = kind === void 0 ? void 0 : REJECTED_KEYS[kind];
|
|
143
|
+
if (key !== void 0) return text(t, `flow.rejected.${key}`, "Nothing was saved.");
|
|
144
|
+
return text(t, "flow.rejected.precondition", "The record changed. Nothing was sent.");
|
|
145
|
+
}
|
|
146
|
+
if (outcome.outcome === "failed") return snapshot.reason ?? text(t, "flow.failed", "The request could not be sent. Nothing was saved.");
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
149
|
+
function FlowScreen(props) {
|
|
150
|
+
if (props.run !== void 0 && props.compiled !== void 0) return jsx(HeldFlowScreen, {
|
|
151
|
+
...props,
|
|
152
|
+
run: props.run,
|
|
153
|
+
compiled: props.compiled
|
|
154
|
+
});
|
|
155
|
+
if (props.start !== void 0) return jsx(OwnedFlowScreen, {
|
|
156
|
+
...props,
|
|
157
|
+
start: props.start
|
|
158
|
+
});
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function HeldFlowScreen(props) {
|
|
162
|
+
const [generation, setGeneration] = useState(0);
|
|
163
|
+
return jsx(FlowTextsScope, {
|
|
164
|
+
compiled: props.compiled,
|
|
165
|
+
children: jsx(WithBinding, { children: jsx(ScreenStateProvider, { children: jsx(FlowScreenBody, {
|
|
166
|
+
...props,
|
|
167
|
+
onFreshForm: () => setGeneration((value) => value + 1)
|
|
168
|
+
}) }, generation) })
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
function OwnedFlowScreen(props) {
|
|
172
|
+
const { start, effects, onSettle } = props;
|
|
173
|
+
const flow = useFlowRun(start.target, {
|
|
174
|
+
...start.record === void 0 ? {} : { record: start.record },
|
|
175
|
+
...start.args === void 0 ? {} : { args: start.args },
|
|
176
|
+
...start.selection === void 0 ? {} : { selection: start.selection },
|
|
177
|
+
surface: "host",
|
|
178
|
+
...effects === void 0 ? {} : { thenEffects: effects }
|
|
179
|
+
});
|
|
180
|
+
flow.holdThen(true);
|
|
181
|
+
const latest = useRef(flow);
|
|
182
|
+
latest.current = flow;
|
|
183
|
+
useEffect(() => () => {
|
|
184
|
+
setTimeout(() => {
|
|
185
|
+
latest.current.holdThen(false);
|
|
186
|
+
latest.current.runThen();
|
|
187
|
+
}, 0);
|
|
188
|
+
}, []);
|
|
189
|
+
const { run, snapshot, compiled } = flow;
|
|
190
|
+
const outcome = snapshot.outcome;
|
|
191
|
+
useEffect(() => {
|
|
192
|
+
if (outcome !== void 0) onSettle?.(outcome);
|
|
193
|
+
}, [outcome, onSettle]);
|
|
194
|
+
const instance = useUIInstance();
|
|
195
|
+
const t = useOptionalT();
|
|
196
|
+
const tid = useTestIds();
|
|
197
|
+
if (run !== null && compiled !== null && (snapshot.history.includes("open") || snapshot.step === "outcome")) return jsx(HeldFlowScreen, {
|
|
198
|
+
...props,
|
|
199
|
+
run,
|
|
200
|
+
compiled
|
|
201
|
+
});
|
|
202
|
+
const refused = snapshot.control === "disabled" || snapshot.control === "absent";
|
|
203
|
+
return jsxs("div", {
|
|
204
|
+
"data-testid": compiled === null ? void 0 : `${tid.flowHost(compiled.flowId)}:opening`,
|
|
205
|
+
"data-buro-host": props.host,
|
|
206
|
+
"data-buro-flow-step": refused ? "refused" : "opening",
|
|
207
|
+
"aria-busy": refused ? void 0 : "true",
|
|
208
|
+
className: "flex min-h-0 flex-1 flex-col gap-4",
|
|
209
|
+
children: [
|
|
210
|
+
jsx(OwnTitleHeading, { label: props.label }),
|
|
211
|
+
refused ? jsx("p", {
|
|
212
|
+
role: "alert",
|
|
213
|
+
className: "text-sm",
|
|
214
|
+
children: snapshot.reason ?? text(t, "flow.unavailable", "Not allowed.")
|
|
215
|
+
}) : jsx(IconLoader2, {
|
|
216
|
+
className: "h-5 w-5 animate-spin self-center",
|
|
217
|
+
"aria-hidden": "true"
|
|
218
|
+
}),
|
|
219
|
+
jsx("div", {
|
|
220
|
+
className: "flex justify-end",
|
|
221
|
+
children: jsx(Button, {
|
|
222
|
+
type: "button",
|
|
223
|
+
variant: "ghost",
|
|
224
|
+
onClick: () => instance.dismiss(),
|
|
225
|
+
children: text(t, "flow.close", "Close")
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
]
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
function OwnTitleHeading({ label }) {
|
|
232
|
+
const ownTitle = useContext(OwnTitleContext);
|
|
233
|
+
const heading = jsx("h2", {
|
|
234
|
+
tabIndex: -1,
|
|
235
|
+
"data-buro-overlay-heading": "",
|
|
236
|
+
className: "text-lg font-semibold",
|
|
237
|
+
children: label
|
|
238
|
+
});
|
|
239
|
+
return ownTitle ? jsx(DialogPrimitive.Title, {
|
|
240
|
+
asChild: true,
|
|
241
|
+
children: heading
|
|
242
|
+
}) : heading;
|
|
243
|
+
}
|
|
244
|
+
function FlowScreenBody({ run, host, label, title: givenTitle, compiled, record, args, selection, onFreshForm }) {
|
|
245
|
+
const snapshot = useSyncSnapshot(run);
|
|
246
|
+
const binding = useContext(FlowHostBindingContext);
|
|
247
|
+
const tid = useTestIds();
|
|
248
|
+
const t = useOptionalT();
|
|
249
|
+
const resource = compiled.resource ?? void 0;
|
|
250
|
+
const caps = useI18nCaps(resource);
|
|
251
|
+
const ownTitle = useContext(OwnTitleContext);
|
|
252
|
+
const flowId = compiled.flowId;
|
|
253
|
+
const recordId = record?.[compiled.idField] ?? record?.id;
|
|
254
|
+
const recordTitle = useProjectedTitle(resource, recordId, record);
|
|
255
|
+
const title = givenTitle ?? (record === void 0 || recordTitle === "" ? void 0 : recordTitle);
|
|
256
|
+
const form = useFlowForm(run, compiled, snapshot, {
|
|
257
|
+
...record === void 0 ? {} : { record },
|
|
258
|
+
...args === void 0 ? {} : { args },
|
|
259
|
+
...selection === void 0 ? {} : { selection: selection.ids }
|
|
260
|
+
});
|
|
261
|
+
const hasForm = compiled.flow.form !== void 0;
|
|
262
|
+
const [busy, setBusy] = useState(false);
|
|
263
|
+
const [initial] = useState(() => run.getSnapshot().values);
|
|
264
|
+
const formErrors = form.errors.filter((issue) => issue.field === "_form");
|
|
265
|
+
const locked = snapshot.control === "running";
|
|
266
|
+
useDismissPending(locked);
|
|
267
|
+
const outcome = snapshot.outcome?.outcome;
|
|
268
|
+
const unknown = outcome === "unknown";
|
|
269
|
+
const succeeded = outcome === "success";
|
|
270
|
+
const finalStep = snapshot.step === "review" || snapshot.step === "accept";
|
|
271
|
+
const openBlock = succeeded ? blockOpen(snapshot.effects?.open) : null;
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
if (succeeded && !locked && openBlock === null) binding.finish();
|
|
274
|
+
}, [
|
|
275
|
+
succeeded,
|
|
276
|
+
locked,
|
|
277
|
+
openBlock,
|
|
278
|
+
binding
|
|
279
|
+
]);
|
|
280
|
+
const prefix = compiled.resource === null ? `appActions.${compiled.name}` : `${compiled.resource}.actions.${compiled.name}`;
|
|
281
|
+
const settle = (result) => {
|
|
282
|
+
setBusy(result.outcome === "failed" && "reason" in result && result.reason === "busy");
|
|
283
|
+
};
|
|
284
|
+
const submit = async () => {
|
|
285
|
+
if (locked) return;
|
|
286
|
+
setBusy(false);
|
|
287
|
+
if (finalStep) {
|
|
288
|
+
settle(await run.accept());
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (unknown && editingNew) {
|
|
292
|
+
let valid = false;
|
|
293
|
+
await form.handleSubmit(() => {
|
|
294
|
+
valid = true;
|
|
295
|
+
throw HELD;
|
|
296
|
+
})();
|
|
297
|
+
if (valid) setConfirmingNew(true);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (unknown) return;
|
|
301
|
+
if (hasForm) {
|
|
302
|
+
let validated = false;
|
|
303
|
+
await form.handleSubmit(() => {
|
|
304
|
+
validated = true;
|
|
305
|
+
throw HELD;
|
|
306
|
+
})();
|
|
307
|
+
if (!validated) return;
|
|
308
|
+
}
|
|
309
|
+
settle(await run.submit());
|
|
310
|
+
};
|
|
311
|
+
const pendingKey = compiled.resource === null ? `appActions.${compiled.name}.pending` : `resources.${compiled.resource}.actions.${compiled.name}.pending`;
|
|
312
|
+
const pendingLabel = caps.has(pendingKey) ? caps.t(pendingKey) : `${label}…`;
|
|
313
|
+
const message = outcomeMessage(snapshot, busy, t);
|
|
314
|
+
const couldNotCheck = snapshot.control === "disabled" && snapshot.reason !== void 0 && snapshot.reason === text(t, "flow.couldNotCheck", "Couldn't check");
|
|
315
|
+
const steps = form.steps;
|
|
316
|
+
const lastStep = steps === null || steps.ids.length === 0 || steps.current === steps.ids[steps.ids.length - 1];
|
|
317
|
+
const showSubmit = !unknown && !succeeded && (!hasForm || finalStep || lastStep);
|
|
318
|
+
const [confirmingNew, setConfirmingNew] = useState(false);
|
|
319
|
+
const [editingNew, setEditingNew] = useState(false);
|
|
320
|
+
const checkable = compiled.flow.submit.onUnknown !== void 0;
|
|
321
|
+
const unhandled = unknown && !checkable && !snapshot.canResend;
|
|
322
|
+
const exit = (action) => () => {
|
|
323
|
+
if (!locked) action().then(settle);
|
|
324
|
+
};
|
|
325
|
+
const close = () => {
|
|
326
|
+
if (binding.kind === "inline" && hasForm && !unknown) form.draft.discard();
|
|
327
|
+
binding.close();
|
|
328
|
+
};
|
|
329
|
+
const heading = jsxs("h2", {
|
|
330
|
+
tabIndex: -1,
|
|
331
|
+
"data-buro-overlay-heading": "",
|
|
332
|
+
className: "min-w-0 flex-1 break-words text-lg font-semibold tracking-tight focus-visible:outline-hidden",
|
|
333
|
+
children: [label, title === void 0 ? null : jsx("span", {
|
|
334
|
+
className: "ml-2 font-normal text-muted-foreground",
|
|
335
|
+
children: title
|
|
336
|
+
})]
|
|
337
|
+
});
|
|
338
|
+
return jsxs("div", {
|
|
339
|
+
"data-testid": tid.flowHost(flowId),
|
|
340
|
+
"data-buro-host": host,
|
|
341
|
+
"data-buro-flow-step": snapshot.step,
|
|
342
|
+
"aria-busy": locked ? "true" : void 0,
|
|
343
|
+
className: "flex min-h-0 flex-1 flex-col gap-4",
|
|
344
|
+
children: [
|
|
345
|
+
binding.kind === "inline" ? null : jsxs("div", {
|
|
346
|
+
"data-buro-region": "flow-header",
|
|
347
|
+
className: "flex items-center gap-2 pr-1",
|
|
348
|
+
children: [
|
|
349
|
+
ownTitle ? jsx(DialogPrimitive.Title, {
|
|
350
|
+
asChild: true,
|
|
351
|
+
children: heading
|
|
352
|
+
}) : heading,
|
|
353
|
+
compiled.resource === null ? null : jsx(DocInfo, {
|
|
354
|
+
address: `${compiled.resource}/actions/${compiled.name}`,
|
|
355
|
+
name: label,
|
|
356
|
+
testId: `${tid.flowHost(flowId)}:info`
|
|
357
|
+
}),
|
|
358
|
+
binding.kind === "overlay" ? jsx(Button, {
|
|
359
|
+
type: "button",
|
|
360
|
+
variant: "ghost",
|
|
361
|
+
size: "icon",
|
|
362
|
+
className: "h-8 w-8 shrink-0",
|
|
363
|
+
"data-testid": tid.flowClose(flowId),
|
|
364
|
+
"aria-label": text(t, "flow.close", "Close"),
|
|
365
|
+
onClick: close,
|
|
366
|
+
children: jsx(IconX, {
|
|
367
|
+
className: "h-4 w-4",
|
|
368
|
+
"aria-hidden": "true"
|
|
369
|
+
})
|
|
370
|
+
}) : null
|
|
371
|
+
]
|
|
372
|
+
}),
|
|
373
|
+
openBlock !== null ? jsx(FlowOpenBlock, {
|
|
374
|
+
open: openBlock,
|
|
375
|
+
prefix,
|
|
376
|
+
testid: tid.flowHost(flowId)
|
|
377
|
+
}) : null,
|
|
378
|
+
openBlock !== null && binding.kind !== "overlay" ? jsx("div", {
|
|
379
|
+
className: "flex justify-end",
|
|
380
|
+
children: jsx(Button, {
|
|
381
|
+
type: "button",
|
|
382
|
+
variant: "outline",
|
|
383
|
+
"data-testid": tid.flowClose(flowId),
|
|
384
|
+
onClick: close,
|
|
385
|
+
children: text(t, "flow.done", "Done")
|
|
386
|
+
})
|
|
387
|
+
}) : null,
|
|
388
|
+
jsxs("form", {
|
|
389
|
+
hidden: openBlock !== null,
|
|
390
|
+
noValidate: true,
|
|
391
|
+
className: openBlock === null ? "flex min-h-0 flex-1 flex-col gap-4" : "hidden",
|
|
392
|
+
onSubmit: (event) => {
|
|
393
|
+
event.preventDefault();
|
|
394
|
+
submit();
|
|
395
|
+
},
|
|
396
|
+
children: [
|
|
397
|
+
jsxs("div", {
|
|
398
|
+
className: "-mx-1 flex min-h-0 flex-1 flex-col gap-4 overflow-y-auto px-1",
|
|
399
|
+
children: [
|
|
400
|
+
message === null ? null : jsxs("div", {
|
|
401
|
+
role: unknown || outcome === "rejected" || outcome === "failed" ? "alert" : "status",
|
|
402
|
+
"data-testid": tid.flowOutcome(flowId),
|
|
403
|
+
"data-buro-flow-outcome": busy ? "busy" : outcome ?? snapshot.control,
|
|
404
|
+
className: "flex flex-wrap items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
|
405
|
+
children: [jsx("span", { children: message }), couldNotCheck ? jsx(Button, {
|
|
406
|
+
type: "button",
|
|
407
|
+
size: "sm",
|
|
408
|
+
variant: "outline",
|
|
409
|
+
className: "ml-auto",
|
|
410
|
+
onClick: () => run.retryChecks(),
|
|
411
|
+
children: text(t, "actions.retry", "Retry")
|
|
412
|
+
}) : null]
|
|
413
|
+
}),
|
|
414
|
+
hasForm && form.draft.pending !== null && (!unknown || editingNew) ? jsxs("div", {
|
|
415
|
+
"data-testid": tid.flowDraft(flowId),
|
|
416
|
+
role: "status",
|
|
417
|
+
"aria-live": "polite",
|
|
418
|
+
className: "flex flex-wrap items-center gap-2 rounded-md border border-warning/50 bg-warning/10 px-3 py-2 text-sm",
|
|
419
|
+
children: [jsx("span", {
|
|
420
|
+
className: "font-medium",
|
|
421
|
+
children: text(t, "draft.restorePrompt", "Restore draft?")
|
|
422
|
+
}), jsxs("div", {
|
|
423
|
+
className: "ml-auto flex gap-2",
|
|
424
|
+
children: [jsx(Button, {
|
|
425
|
+
type: "button",
|
|
426
|
+
size: "sm",
|
|
427
|
+
variant: "outline",
|
|
428
|
+
"data-testid": `${tid.flowDraft(flowId)}:restore`,
|
|
429
|
+
onClick: form.draft.restore,
|
|
430
|
+
children: text(t, "draft.restore", "Restore")
|
|
431
|
+
}), jsx(Button, {
|
|
432
|
+
type: "button",
|
|
433
|
+
size: "sm",
|
|
434
|
+
variant: "ghost",
|
|
435
|
+
"data-testid": `${tid.flowDraft(flowId)}:discard`,
|
|
436
|
+
onClick: form.draft.discard,
|
|
437
|
+
children: text(t, "draft.discard", "Discard")
|
|
438
|
+
})]
|
|
439
|
+
})]
|
|
440
|
+
}) : null,
|
|
441
|
+
formErrors.length > 0 ? jsx("div", {
|
|
442
|
+
role: "alert",
|
|
443
|
+
"data-testid": `${tid.flowHost(flowId)}:form-errors`,
|
|
444
|
+
className: "flex flex-col gap-1 rounded-md border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive",
|
|
445
|
+
children: formErrors.map((issue, index) => jsx("p", { children: resolveValidationMessage({
|
|
446
|
+
code: issue.code ?? "",
|
|
447
|
+
message: issue.message,
|
|
448
|
+
...issue.params === void 0 ? {} : { params: issue.params }
|
|
449
|
+
}, { t }) }, index))
|
|
450
|
+
}) : null,
|
|
451
|
+
finalStep && compiled.flow.review === true ? jsx(ReviewDiff, {
|
|
452
|
+
form,
|
|
453
|
+
initial,
|
|
454
|
+
values: snapshot.values,
|
|
455
|
+
i18nPrefix: prefix,
|
|
456
|
+
testid: tid.flowHost(flowId)
|
|
457
|
+
}) : finalStep && Array.isArray(compiled.flow.review) ? jsx(ReviewTree, {
|
|
458
|
+
compiled,
|
|
459
|
+
tree: compiled.flow.review,
|
|
460
|
+
values: snapshot.values,
|
|
461
|
+
prefix
|
|
462
|
+
}) : hasForm ? jsx(ScreenTree, {
|
|
463
|
+
region: "form-body",
|
|
464
|
+
resource: prefix,
|
|
465
|
+
mode: "create",
|
|
466
|
+
compiled: form.screen,
|
|
467
|
+
controller: form,
|
|
468
|
+
leafIds: "record",
|
|
469
|
+
disabled: locked || unknown && !editingNew || finalStep || succeeded
|
|
470
|
+
}) : null,
|
|
471
|
+
finalStep && snapshot.warnings.length > 0 ? jsx("ul", {
|
|
472
|
+
role: "status",
|
|
473
|
+
"data-buro-region": "flow-warnings",
|
|
474
|
+
className: "flex flex-col gap-1 rounded-md border border-warning/50 bg-warning/10 px-3 py-2 text-sm text-warning-emphasis",
|
|
475
|
+
children: snapshot.warnings.map((warning) => jsx("li", {
|
|
476
|
+
"data-testid": `${tid.flowHost(flowId)}:warning:${warning.id}`,
|
|
477
|
+
children: warning.message
|
|
478
|
+
}, warning.id))
|
|
479
|
+
}) : null
|
|
480
|
+
]
|
|
481
|
+
}),
|
|
482
|
+
unhandled ? jsx("p", {
|
|
483
|
+
"data-testid": `${tid.flowOutcome(flowId)}:unhandled`,
|
|
484
|
+
className: "text-sm",
|
|
485
|
+
children: text(t, "flow.unknownUnhandled", "Check the record before trying again.")
|
|
486
|
+
}) : null,
|
|
487
|
+
unknown && confirmingNew ? jsxs("div", {
|
|
488
|
+
role: "alertdialog",
|
|
489
|
+
"aria-label": text(t, "flow.sendAsNew", "Send as new"),
|
|
490
|
+
"data-testid": `${tid.flowSendAsNew(flowId)}:confirm`,
|
|
491
|
+
className: "flex flex-wrap items-center gap-2 rounded-md border border-warning/50 bg-warning/10 px-3 py-2 text-sm",
|
|
492
|
+
children: [jsx("span", { children: text(t, "flow.sendAsNewConfirm", "This may apply the change twice. Send it as a new request?") }), jsxs("div", {
|
|
493
|
+
className: "ml-auto flex gap-2",
|
|
494
|
+
children: [jsx(Button, {
|
|
495
|
+
type: "button",
|
|
496
|
+
size: "sm",
|
|
497
|
+
variant: "ghost",
|
|
498
|
+
"data-testid": `${tid.flowSendAsNew(flowId)}:cancel`,
|
|
499
|
+
onClick: () => setConfirmingNew(false),
|
|
500
|
+
children: text(t, "actions.cancel", "Cancel")
|
|
501
|
+
}), jsx(Button, {
|
|
502
|
+
type: "button",
|
|
503
|
+
size: "sm",
|
|
504
|
+
variant: "destructive",
|
|
505
|
+
"data-testid": `${tid.flowSendAsNew(flowId)}:ok`,
|
|
506
|
+
onClick: () => {
|
|
507
|
+
setConfirmingNew(false);
|
|
508
|
+
exit(() => run.sendAsNew({ confirmed: true }))();
|
|
509
|
+
},
|
|
510
|
+
children: text(t, "flow.sendAsNew", "Send as new")
|
|
511
|
+
})]
|
|
512
|
+
})]
|
|
513
|
+
}) : null,
|
|
514
|
+
unknown ? jsxs("div", {
|
|
515
|
+
"data-buro-region": "flow-unknown-exits",
|
|
516
|
+
className: "flex flex-wrap gap-2",
|
|
517
|
+
children: [
|
|
518
|
+
checkable ? jsx(Button, {
|
|
519
|
+
type: "button",
|
|
520
|
+
variant: "default",
|
|
521
|
+
"data-testid": tid.flowCheckAgain(flowId),
|
|
522
|
+
disabled: locked,
|
|
523
|
+
onClick: exit(() => run.checkAgain()),
|
|
524
|
+
children: text(t, "flow.checkAgain", "Check again")
|
|
525
|
+
}) : null,
|
|
526
|
+
snapshot.canResend ? jsx(Button, {
|
|
527
|
+
type: "button",
|
|
528
|
+
variant: "outline",
|
|
529
|
+
"data-testid": tid.flowResend(flowId),
|
|
530
|
+
disabled: locked,
|
|
531
|
+
onClick: exit(() => run.resend()),
|
|
532
|
+
children: text(t, "flow.resend", "Resend")
|
|
533
|
+
}) : null,
|
|
534
|
+
jsx(Button, {
|
|
535
|
+
type: "button",
|
|
536
|
+
variant: "outline",
|
|
537
|
+
"data-testid": tid.flowSendAsNew(flowId),
|
|
538
|
+
disabled: locked || confirmingNew || editingNew,
|
|
539
|
+
onClick: () => {
|
|
540
|
+
if (hasForm) setEditingNew(true);
|
|
541
|
+
else setConfirmingNew(true);
|
|
542
|
+
},
|
|
543
|
+
children: text(t, "flow.sendAsNew", "Send as new")
|
|
544
|
+
}),
|
|
545
|
+
jsx(Button, {
|
|
546
|
+
type: "button",
|
|
547
|
+
variant: "outline",
|
|
548
|
+
"data-testid": tid.flowStartOver(flowId),
|
|
549
|
+
disabled: locked,
|
|
550
|
+
onClick: () => {
|
|
551
|
+
run.startOver();
|
|
552
|
+
onFreshForm();
|
|
553
|
+
},
|
|
554
|
+
children: text(t, "flow.startOver", "I've checked — start over")
|
|
555
|
+
})
|
|
556
|
+
]
|
|
557
|
+
}) : null,
|
|
558
|
+
jsxs("div", {
|
|
559
|
+
"data-buro-region": "flow-footer",
|
|
560
|
+
className: "flex flex-wrap items-center gap-2",
|
|
561
|
+
children: [finalStep && hasForm && !locked ? jsx(Button, {
|
|
562
|
+
type: "button",
|
|
563
|
+
variant: "outline",
|
|
564
|
+
"data-testid": tid.flowBack(flowId),
|
|
565
|
+
onClick: () => run.back(),
|
|
566
|
+
children: text(t, "flow.back", "Back")
|
|
567
|
+
}) : null, jsxs("div", {
|
|
568
|
+
className: "ml-auto flex gap-2",
|
|
569
|
+
children: [
|
|
570
|
+
jsx(Button, {
|
|
571
|
+
type: "button",
|
|
572
|
+
variant: "ghost",
|
|
573
|
+
"data-testid": tid.flowCancel(flowId),
|
|
574
|
+
disabled: locked,
|
|
575
|
+
onClick: close,
|
|
576
|
+
children: unknown ? text(t, "flow.close", "Close") : binding.kind === "inline" ? text(t, "flow.reset", "Reset") : text(t, "actions.cancel", "Cancel")
|
|
577
|
+
}),
|
|
578
|
+
unknown && editingNew ? jsx(Button, {
|
|
579
|
+
type: "submit",
|
|
580
|
+
variant: "destructive",
|
|
581
|
+
"data-testid": `${tid.flowSendAsNew(flowId)}:submit`,
|
|
582
|
+
disabled: locked || confirmingNew,
|
|
583
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
584
|
+
children: text(t, "flow.sendAsNew", "Send as new")
|
|
585
|
+
}) : null,
|
|
586
|
+
showSubmit ? jsxs(Button, {
|
|
587
|
+
type: "submit",
|
|
588
|
+
variant: compiled.flow.variant === "destructive" ? "destructive" : "default",
|
|
589
|
+
"data-testid": tid.flowSubmit(flowId),
|
|
590
|
+
disabled: locked || couldNotCheck,
|
|
591
|
+
"aria-busy": locked ? "true" : void 0,
|
|
592
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
593
|
+
children: [locked ? jsx(IconLoader2, {
|
|
594
|
+
className: "h-4 w-4 animate-spin",
|
|
595
|
+
"aria-hidden": "true"
|
|
596
|
+
}) : null, locked ? pendingLabel : label]
|
|
597
|
+
}) : null
|
|
598
|
+
]
|
|
599
|
+
})]
|
|
600
|
+
})
|
|
601
|
+
]
|
|
602
|
+
})
|
|
603
|
+
]
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
function useSyncSnapshot(run) {
|
|
607
|
+
return useSyncExternalStore(run.subscribe, run.getSnapshot, run.getSnapshot);
|
|
608
|
+
}
|
|
609
|
+
const NO_FIELDS = Object.freeze({});
|
|
610
|
+
function ReviewTree({ compiled, tree, values, prefix }) {
|
|
611
|
+
const fields = compiled.flow.form?.fields;
|
|
612
|
+
const map = useState(() => {
|
|
613
|
+
if (fields === void 0) return NO_FIELDS;
|
|
614
|
+
const placed = placedLeaves(tree);
|
|
615
|
+
return fieldEntriesToMap(fields.map((field) => placed.has(String(field.name)) ? field : {
|
|
616
|
+
...field,
|
|
617
|
+
in: ["create"]
|
|
618
|
+
}));
|
|
619
|
+
})[0];
|
|
620
|
+
const body = useState(() => () => tree)[0];
|
|
621
|
+
const blocks = useFlowFormCatalog();
|
|
622
|
+
const review = useFormController({
|
|
623
|
+
blocks,
|
|
624
|
+
fields: map,
|
|
625
|
+
body,
|
|
626
|
+
mode: "show",
|
|
627
|
+
i18nPrefix: prefix,
|
|
628
|
+
value: values
|
|
629
|
+
});
|
|
630
|
+
return jsx(ScreenTree, {
|
|
631
|
+
region: "form-body",
|
|
632
|
+
resource: prefix,
|
|
633
|
+
mode: "show",
|
|
634
|
+
compiled: review.screen,
|
|
635
|
+
controller: review,
|
|
636
|
+
leafIds: "record"
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
function placedLeaves(tree) {
|
|
640
|
+
const out = new Set();
|
|
641
|
+
const walk = (node) => {
|
|
642
|
+
if (typeof node === "string") {
|
|
643
|
+
out.add(node);
|
|
644
|
+
return;
|
|
645
|
+
}
|
|
646
|
+
if (node === null || typeof node !== "object") return;
|
|
647
|
+
const children = node.children;
|
|
648
|
+
if (Array.isArray(children)) for (const child of children) walk(child);
|
|
649
|
+
};
|
|
650
|
+
for (const node of tree) walk(node);
|
|
651
|
+
return out;
|
|
652
|
+
}
|
|
653
|
+
function blockOpen(open) {
|
|
654
|
+
if (open === null || typeof open !== "object" || !Object.hasOwn(open, "block")) return null;
|
|
655
|
+
const { block, props } = open;
|
|
656
|
+
const ref = block !== null && typeof block === "object" && "ref" in block ? block.ref : block;
|
|
657
|
+
if (ref === null || typeof ref !== "object" || typeof ref.namespace !== "string" || typeof ref.id !== "string") return null;
|
|
658
|
+
return {
|
|
659
|
+
block: ref,
|
|
660
|
+
props: props !== null && typeof props === "object" ? props : {}
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
function FlowOpenBlock({ open, testid }) {
|
|
664
|
+
const t = useOptionalT();
|
|
665
|
+
const id = `${open.block.namespace}:${open.block.id}`;
|
|
666
|
+
const implementation = selectImplementation(id, useFlowOpenImplementation(id));
|
|
667
|
+
const [validation, setValidation] = useState(() => implementation === void 0 ? null : validatePlacementProps(implementation.definition, open.props));
|
|
668
|
+
useEffect(() => {
|
|
669
|
+
if (validation?.status !== "pending") return;
|
|
670
|
+
let live = true;
|
|
671
|
+
validation.settled.then((settled) => {
|
|
672
|
+
if (live) setValidation(settled);
|
|
673
|
+
});
|
|
674
|
+
return () => {
|
|
675
|
+
live = false;
|
|
676
|
+
};
|
|
677
|
+
}, [validation]);
|
|
678
|
+
const failed = implementation === void 0 || validation?.status === "failed";
|
|
679
|
+
const View = implementation === void 0 ? null : viewOf(implementation);
|
|
680
|
+
return jsx("div", {
|
|
681
|
+
"data-testid": `${testid}:open`,
|
|
682
|
+
"data-buro-block": id,
|
|
683
|
+
className: "min-h-0 flex-1 overflow-y-auto",
|
|
684
|
+
children: failed ? jsx("p", {
|
|
685
|
+
role: "alert",
|
|
686
|
+
className: "text-sm text-muted-foreground",
|
|
687
|
+
children: text(t, "block.notImplemented", "This section is not available.")
|
|
688
|
+
}) : View === null || validation?.status !== "ready" ? null : jsx(Suspense, {
|
|
689
|
+
fallback: null,
|
|
690
|
+
children: jsx(View, {
|
|
691
|
+
props: validation.props,
|
|
692
|
+
data: NO_FIELDS,
|
|
693
|
+
t: (key, options) => t(`blocks.${id}.${key}`, {
|
|
694
|
+
...options?.params === void 0 ? {} : { params: options.params },
|
|
695
|
+
...options?.count === void 0 ? {} : { count: options.count }
|
|
696
|
+
})
|
|
697
|
+
})
|
|
698
|
+
})
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
//#endregion
|
|
702
|
+
export { FlowHostBindingContext, FlowScreen, HostedFlowScreen };
|
|
703
|
+
|
|
704
|
+
//# sourceMappingURL=flow-screen-CCvgDI9G.js.map
|