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