@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,255 @@
1
+ require("./toaster-Cr51X7bz.cjs");
2
+ const require_check_confirm_dialog = require("./check-confirm-dialog--gPFnEeg.cjs");
3
+ let _burojs_core = require("@burojs/core");
4
+ let _burojs_react = require("@burojs/react");
5
+ let react = require("react");
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ let _burojs_core_internal = require("@burojs/core/internal");
8
+ let _burojs_react_flows = require("@burojs/react/flows");
9
+ let sonner = require("sonner");
10
+ //#region src/flows/flow-runtime.tsx
11
+ const NO_ISSUES = Object.freeze([]);
12
+ function useFlowLauncher(flow, host, chrome, resource, testid) {
13
+ const t = (0, _burojs_react.useOptionalT)();
14
+ const [confirming, setConfirming] = (0, react.useState)(false);
15
+ const decide = (0, react.useRef)(null);
16
+ const latest = (0, react.useRef)(flow);
17
+ latest.current = flow;
18
+ (0, react.useEffect)(() => () => {
19
+ decide.current?.(false);
20
+ decide.current = null;
21
+ }, []);
22
+ const launch = (0, react.useCallback)(async () => {
23
+ const { run, compiled } = latest.current;
24
+ if (run === null || compiled === null) return;
25
+ if (compiled.hasHost) {
26
+ await (host.open() ?? Promise.resolve());
27
+ return;
28
+ }
29
+ let result = await run.submit();
30
+ while (result.outcome === "halted" && (result.step === "accept" || result.step === "review")) {
31
+ setConfirming(true);
32
+ const proceed = await new Promise((resolve) => {
33
+ decide.current = resolve;
34
+ });
35
+ decide.current = null;
36
+ setConfirming(false);
37
+ if (!proceed) {
38
+ run.startOver();
39
+ return;
40
+ }
41
+ result = await run.accept();
42
+ }
43
+ if (result.outcome === "failed" && "reason" in result && result.reason === "busy") {
44
+ (0, sonner.toast)(require_check_confirm_dialog.text(t, "flow.busyElsewhere", "This action is running in another tab."));
45
+ return;
46
+ }
47
+ if (result.outcome === "rejected" || result.outcome === "failed" || result.outcome === "unknown" || result.outcome === "halted" && result.step === "outcome") await (host.open("dialog") ?? Promise.resolve());
48
+ }, [host, t]);
49
+ const { snapshot, compiled } = flow;
50
+ const gate = {
51
+ resource,
52
+ open: confirming,
53
+ busy: false,
54
+ header: null,
55
+ blockers: NO_ISSUES,
56
+ confirmable: confirming ? snapshot.warnings.map((warning) => ({
57
+ code: "check.warning",
58
+ message: (0, _burojs_core_internal.toMessageRef)(warning.message, `checks.${warning.id}`),
59
+ path: [],
60
+ params: {
61
+ checkId: warning.id,
62
+ resolved: true
63
+ },
64
+ source: "check",
65
+ severity: "warning"
66
+ })) : NO_ISSUES,
67
+ proceed: () => decide.current?.(true),
68
+ cancel: () => decide.current?.(false)
69
+ };
70
+ return {
71
+ launch,
72
+ dialog: compiled === null || compiled.hasHost ? null : (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.CheckConfirmDialog, {
73
+ state: gate,
74
+ testid: `${testid}:confirm`,
75
+ title: chrome.label,
76
+ proceedLabel: chrome.label,
77
+ tone: chrome.destructive ? "destructive" : "default"
78
+ })
79
+ };
80
+ }
81
+ function FlowRunner({ resource, actionName, record, scope, onClose }) {
82
+ const target = (0, react.useMemo)(() => ({
83
+ resource,
84
+ action: actionName
85
+ }), [resource, actionName]);
86
+ const flow = (0, _burojs_react_flows.useFlowRun)(target, {
87
+ ...record === void 0 ? {} : { record },
88
+ surface: scope === "row" ? "row" : "menu"
89
+ });
90
+ const chrome = require_check_confirm_dialog.useFlowChrome(resource, actionName);
91
+ const title = (0, _burojs_react.useProjectedTitle)(resource, record?.id, record);
92
+ const host = (0, _burojs_react_flows.useFlowHost)(flow, {
93
+ label: chrome.labelText,
94
+ ...record === void 0 || title === "" ? {} : { title },
95
+ ...record === void 0 ? {} : { record }
96
+ });
97
+ const tid = (0, _burojs_react.useTestIds)();
98
+ const t = (0, _burojs_react.useOptionalT)();
99
+ const { launch, dialog } = useFlowLauncher(flow, host, chrome, resource, require_check_confirm_dialog.makeTestId(scope, resource, actionName, String(record?.id ?? ""), tid));
100
+ const started = (0, react.useRef)(false);
101
+ const onCloseRef = (0, react.useRef)(onClose);
102
+ onCloseRef.current = onClose;
103
+ const { snapshot, compiled } = flow;
104
+ const decided = compiled !== null && (snapshot.control === "disabled" || snapshot.control === "absent" || snapshot.control === "ready" && (!compiled.hasHost || snapshot.history.includes("open") || snapshot.step === "outcome"));
105
+ (0, react.useEffect)(() => {
106
+ if (!decided || started.current) return;
107
+ started.current = true;
108
+ if (snapshot.control !== "ready") {
109
+ (0, sonner.toast)(snapshot.reason ?? require_check_confirm_dialog.text(t, "availability.denied", "This action isn't available"));
110
+ onCloseRef.current();
111
+ return;
112
+ }
113
+ launch().finally(() => onCloseRef.current());
114
+ }, [
115
+ decided,
116
+ snapshot.control,
117
+ snapshot.reason,
118
+ launch,
119
+ t
120
+ ]);
121
+ return dialog;
122
+ }
123
+ function AppFlowRunner({ name, label, testid, onClose }) {
124
+ const target = (0, react.useMemo)(() => ({ appAction: name }), [name]);
125
+ const flow = (0, _burojs_react_flows.useFlowRun)(target, { surface: "app" });
126
+ const chrome = {
127
+ label,
128
+ labelText: label,
129
+ icon: void 0,
130
+ destructive: false
131
+ };
132
+ const host = (0, _burojs_react_flows.useFlowHost)(flow, { label });
133
+ const t = (0, _burojs_react.useOptionalT)();
134
+ const { launch, dialog } = useFlowLauncher(flow, host, chrome, _burojs_core.APP_ACTION_RESOURCE, testid);
135
+ const started = (0, react.useRef)(false);
136
+ const onCloseRef = (0, react.useRef)(onClose);
137
+ onCloseRef.current = onClose;
138
+ const { snapshot, compiled } = flow;
139
+ const decided = compiled !== null && (snapshot.control === "disabled" || snapshot.control === "absent" || snapshot.control === "ready" && (!compiled.hasHost || snapshot.history.includes("open") || snapshot.step === "outcome"));
140
+ (0, react.useEffect)(() => {
141
+ if (!decided || started.current) return;
142
+ started.current = true;
143
+ if (snapshot.control !== "ready") {
144
+ (0, sonner.toast)(snapshot.reason ?? require_check_confirm_dialog.text(t, "availability.denied", "This action isn't available"));
145
+ onCloseRef.current();
146
+ return;
147
+ }
148
+ launch().finally(() => onCloseRef.current());
149
+ }, [
150
+ decided,
151
+ snapshot.control,
152
+ snapshot.reason,
153
+ launch,
154
+ t
155
+ ]);
156
+ return dialog;
157
+ }
158
+ function BulkFlowRunner({ resource, actionName, ids, onFinish }) {
159
+ const tid = (0, _burojs_react.useTestIds)();
160
+ const t = (0, _burojs_react.useOptionalT)();
161
+ const idsKey = ids.join("\0");
162
+ const selection = (0, react.useMemo)(() => ({
163
+ ids: [...ids],
164
+ count: ids.length
165
+ }), [idsKey]);
166
+ const target = (0, react.useMemo)(() => ({
167
+ resource,
168
+ action: actionName
169
+ }), [resource, actionName]);
170
+ const flow = (0, _burojs_react_flows.useFlowRun)(target, {
171
+ selection,
172
+ surface: "bulk"
173
+ });
174
+ const chrome = require_check_confirm_dialog.useFlowChrome(resource, actionName);
175
+ const testid = tid.bulkAction(resource, actionName);
176
+ const [confirming, setConfirming] = (0, react.useState)(false);
177
+ const decide = (0, react.useRef)(null);
178
+ const started = (0, react.useRef)(false);
179
+ const onFinishRef = (0, react.useRef)(onFinish);
180
+ onFinishRef.current = onFinish;
181
+ const { run, snapshot } = flow;
182
+ (0, react.useEffect)(() => () => {
183
+ decide.current?.(false);
184
+ decide.current = null;
185
+ }, []);
186
+ const decided = run !== null && snapshot.control !== "undecided" && snapshot.control !== "pending";
187
+ (0, react.useEffect)(() => {
188
+ if (!decided || started.current || run === null) return;
189
+ started.current = true;
190
+ (async () => {
191
+ if (run.getSnapshot().control !== "ready") {
192
+ (0, sonner.toast)(run.getSnapshot().reason ?? require_check_confirm_dialog.text(t, "availability.denied", "This action isn't available"));
193
+ onFinishRef.current(Object.freeze({
194
+ outcome: "unavailable",
195
+ state: "disabled"
196
+ }), void 0);
197
+ return;
198
+ }
199
+ let result = await run.submit();
200
+ while (result.outcome === "halted" && (result.step === "accept" || result.step === "review")) {
201
+ setConfirming(true);
202
+ const proceed = await new Promise((resolve) => {
203
+ decide.current = resolve;
204
+ });
205
+ decide.current = null;
206
+ setConfirming(false);
207
+ if (!proceed) {
208
+ run.startOver();
209
+ onFinishRef.current(result, void 0);
210
+ return;
211
+ }
212
+ result = await run.accept();
213
+ }
214
+ if (result.outcome === "failed" && "reason" in result && result.reason === "busy") (0, sonner.toast)(require_check_confirm_dialog.text(t, "flow.busyElsewhere", "This action is running in another tab."));
215
+ onFinishRef.current(result, run.getSnapshot().bulk);
216
+ })();
217
+ }, [
218
+ decided,
219
+ run,
220
+ t
221
+ ]);
222
+ const gate = {
223
+ resource,
224
+ open: confirming,
225
+ busy: false,
226
+ header: null,
227
+ blockers: NO_ISSUES,
228
+ confirmable: confirming ? snapshot.warnings.map((warning) => ({
229
+ code: "check.warning",
230
+ message: (0, _burojs_core_internal.toMessageRef)(warning.message, `checks.${warning.id}`),
231
+ path: [],
232
+ params: {
233
+ checkId: warning.id,
234
+ resolved: true
235
+ },
236
+ source: "check",
237
+ severity: "warning"
238
+ })) : NO_ISSUES,
239
+ proceed: () => decide.current?.(true),
240
+ cancel: () => decide.current?.(false)
241
+ };
242
+ return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.CheckConfirmDialog, {
243
+ state: gate,
244
+ testid: `${testid}:confirm`,
245
+ title: chrome.label,
246
+ proceedLabel: chrome.label,
247
+ tone: chrome.destructive ? "destructive" : "default"
248
+ });
249
+ }
250
+ //#endregion
251
+ exports.AppFlowRunner = AppFlowRunner;
252
+ exports.BulkFlowRunner = BulkFlowRunner;
253
+ exports.FlowRunner = FlowRunner;
254
+
255
+ //# sourceMappingURL=flow-runtime-D3avVH0I.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-runtime-D3avVH0I.cjs","names":["useOptionalT","useState","useRef","useCallback","text","toMessageRef","CheckConfirmDialog","useMemo","useFlowRun","useFlowChrome","useProjectedTitle","useFlowHost","useTestIds","makeTestId","APP_ACTION_RESOURCE"],"sources":["../src/flows/flow-runtime.tsx"],"sourcesContent":["'use client';\n/**\n * The flow runtime's side of the UI kit (P4, the coordinator's ruling on the bundle): every\n * component that holds a run. It loads on the first sign that a user means to run a flow (a\n * hover, a focus, a menu opening, at the latest the click) through `./load-runtime.js`, and with\n * it `@burojs/react/flows` and `@burojs/core/flows` — the flow machine stays out of an\n * application's first screen.\n */\nimport { toMessageRef } from '@burojs/core/internal';\nimport {\n APP_ACTION_RESOURCE,\n type BulkProgress,\n type FlowControlState,\n type FlowResult,\n type Row,\n type ValidationIssue,\n} from '@burojs/core';\nimport { type CheckGateState, useOptionalT, useProjectedTitle, useTestIds } from '@burojs/react';\nimport {\n type FlowHostControl,\n type UseFlowRunResult,\n useFlowHost,\n useFlowRun,\n} from '@burojs/react/flows';\nimport { type ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { makeTestId } from '../actions/action-button.js';\nimport { CheckConfirmDialog } from '../checks/check-confirm-dialog.js';\nimport { toast } from '../notification/toaster.js';\nimport { type FlowChrome, text, useFlowChrome } from './chrome.js';\n\nconst NO_ISSUES: readonly ValidationIssue[] = Object.freeze([]);\n\n/**\n * Runs a flow from its control (4.15): a flow with a host presents it and the interaction ends\n * when it closes; a `{ label, submit }` flow sends, asks through the confirm dialog when\n * `confirm` or a fired warning asks, and shows `rejected`, `failed` and `unknown` in the flow's\n * screen in a dialog (`success` notifies through the flow's `then`; a lock another tab holds\n * says so). `launch()` settles when the interaction is over.\n */\nfunction useFlowLauncher(\n flow: UseFlowRunResult,\n host: FlowHostControl,\n chrome: FlowChrome,\n resource: string,\n testid: string,\n): { readonly launch: () => Promise<void>; readonly dialog: ReactElement | null } {\n const t = useOptionalT();\n const [confirming, setConfirming] = useState(false);\n const decide = useRef<((proceed: boolean) => void) | null>(null);\n const latest = useRef(flow);\n latest.current = flow;\n useEffect(\n () => () => {\n decide.current?.(false);\n decide.current = null;\n },\n [],\n );\n\n const launch = useCallback(async (): Promise<void> => {\n const { run, compiled } = latest.current;\n if (run === null || compiled === null) return;\n if (compiled.hasHost) {\n await (host.open() ?? Promise.resolve());\n return;\n }\n let result: FlowResult = await run.submit();\n while (result.outcome === 'halted' && (result.step === 'accept' || result.step === 'review')) {\n setConfirming(true);\n const proceed = await new Promise<boolean>((resolve) => {\n decide.current = resolve;\n });\n decide.current = null;\n setConfirming(false);\n if (!proceed) {\n run.startOver();\n return;\n }\n result = await run.accept();\n }\n // Another tab holds the attempt's lock: nothing was sent (4.10).\n if (result.outcome === 'failed' && 'reason' in result && result.reason === 'busy') {\n toast(text(t, 'flow.busyElsewhere', 'This action is running in another tab.'));\n return;\n }\n if (\n result.outcome === 'rejected' ||\n result.outcome === 'failed' ||\n result.outcome === 'unknown' ||\n (result.outcome === 'halted' && result.step === 'outcome')\n )\n await (host.open('dialog') ?? Promise.resolve());\n }, [host, t]);\n\n const { snapshot, compiled } = flow;\n const gate: CheckGateState = {\n resource,\n open: confirming,\n busy: false,\n header: null,\n blockers: NO_ISSUES,\n confirmable: confirming\n ? snapshot.warnings.map(\n (warning): ValidationIssue => ({\n code: 'check.warning',\n // The machine's text (bundle and params resolved); the key is the check's.\n message: toMessageRef(warning.message, `checks.${warning.id}`),\n path: [],\n // The run's text is final (bundle and params resolved): the dialog shows it as is.\n params: { checkId: warning.id, resolved: true },\n source: 'check',\n severity: 'warning',\n }),\n )\n : NO_ISSUES,\n proceed: () => decide.current?.(true),\n cancel: () => decide.current?.(false),\n };\n const dialog =\n compiled === null || compiled.hasHost ? null : (\n <CheckConfirmDialog\n state={gate}\n testid={`${testid}:confirm`}\n title={chrome.label}\n proceedLabel={chrome.label}\n tone={chrome.destructive ? 'destructive' : 'default'}\n />\n );\n return { launch, dialog };\n}\n\nexport interface FlowRunnerProps {\n readonly resource: string;\n readonly actionName: string;\n readonly record?: Row;\n readonly scope: string;\n /** The interaction is over (the host closed, the write answered, the confirm was declined). */\n readonly onClose: () => void;\n}\n\n/**\n * @internal A flow started from a control that holds no run — a row's button, a menu item\n * (4.15: a menu item \"presents its host through the runtime from `onSelect`, so the menu closes\n * normally\"). It renders no control: it starts the run (its `with` sources load now) and, once\n * the run has decided, presents the host or sends; `onClose` reports the end of the\n * interaction. A run that decides against the click (a check over a `with` source fired) says\n * why.\n */\nexport function FlowRunner({\n resource,\n actionName,\n record,\n scope,\n onClose,\n}: FlowRunnerProps): ReactElement | null {\n const target = useMemo(() => ({ resource, action: actionName }), [resource, actionName]);\n const flow = useFlowRun(target, {\n ...(record === undefined ? {} : { record }),\n surface: scope === 'row' ? 'row' : 'menu',\n });\n const chrome = useFlowChrome(resource, actionName);\n const title = useProjectedTitle(resource, record?.id, record);\n const host = useFlowHost(flow, {\n label: chrome.labelText,\n ...(record === undefined || title === '' ? {} : { title }),\n ...(record === undefined ? {} : { record }),\n });\n const tid = useTestIds();\n const t = useOptionalT();\n const testid = makeTestId(scope, resource, actionName, String(record?.id ?? ''), tid);\n const { launch, dialog } = useFlowLauncher(flow, host, chrome, resource, testid);\n const started = useRef(false);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n const { snapshot, compiled } = flow;\n const decided =\n compiled !== null &&\n (snapshot.control === 'disabled' ||\n snapshot.control === 'absent' ||\n (snapshot.control === 'ready' &&\n (!compiled.hasHost || snapshot.history.includes('open') || snapshot.step === 'outcome')));\n useEffect(() => {\n if (!decided || started.current) return;\n started.current = true;\n if (snapshot.control !== 'ready') {\n toast(snapshot.reason ?? text(t, 'availability.denied', \"This action isn't available\"));\n onCloseRef.current();\n return;\n }\n void launch().finally(() => onCloseRef.current());\n }, [decided, snapshot.control, snapshot.reason, launch, t]);\n return dialog;\n}\n\nexport interface AppFlowRunnerProps {\n /** The app action's name (`defineAppAction({ name, kind: 'flow' })`). */\n readonly name: string;\n /** Its label, as the opener resolved it (`appActions.<name>` over the declared default). */\n readonly label: string;\n /** The opener's test id: the confirm dialog's ids suffix it (`<testid>:confirm:…`). */\n readonly testid: string;\n readonly onClose: () => void;\n}\n\n/**\n * @internal An app flow started from its control (`AppFlowButton`, P4-D): the same launcher as a\n * resource flow's — the host when the flow has a form or a review, else the send with the\n * confirm dialog — over the target `{ appAction: name }`, with no record.\n */\nexport function AppFlowRunner({\n name,\n label,\n testid,\n onClose,\n}: AppFlowRunnerProps): ReactElement | null {\n const target = useMemo(() => ({ appAction: name }), [name]);\n const flow = useFlowRun(target, { surface: 'app' });\n const chrome: FlowChrome = { label, labelText: label, icon: undefined, destructive: false };\n const host = useFlowHost(flow, { label });\n const t = useOptionalT();\n const { launch, dialog } = useFlowLauncher(flow, host, chrome, APP_ACTION_RESOURCE, testid);\n const started = useRef(false);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n const { snapshot, compiled } = flow;\n const decided =\n compiled !== null &&\n (snapshot.control === 'disabled' ||\n snapshot.control === 'absent' ||\n (snapshot.control === 'ready' &&\n (!compiled.hasHost || snapshot.history.includes('open') || snapshot.step === 'outcome')));\n useEffect(() => {\n if (!decided || started.current) return;\n started.current = true;\n if (snapshot.control !== 'ready') {\n toast(snapshot.reason ?? text(t, 'availability.denied', \"This action isn't available\"));\n onCloseRef.current();\n return;\n }\n void launch().finally(() => onCloseRef.current());\n }, [decided, snapshot.control, snapshot.reason, launch, t]);\n return dialog;\n}\n\nexport interface BulkFlowRunnerProps {\n readonly resource: string;\n readonly actionName: string;\n readonly ids: readonly string[];\n /** The run is over: its result and its per-id report (absent when nothing was sent). */\n readonly onFinish: (result: FlowResult, progress: BulkProgress | undefined) => void;\n}\n\n/**\n * @internal A bulk flow's run over the selection (4.16), started by the bar's click: the confirm\n * (`confirm` and the fired warnings) asks through the confirm dialog, then the run re-reads the\n * rows and writes each under its own key; `onFinish` reports the result and the per-id report.\n */\nexport function BulkFlowRunner({\n resource,\n actionName,\n ids,\n onFinish,\n}: BulkFlowRunnerProps): ReactElement | null {\n const tid = useTestIds();\n const t = useOptionalT();\n const idsKey = ids.join('\\u0000');\n // biome-ignore lint/correctness/useExhaustiveDependencies: keyed by the ids' values\n const selection = useMemo(() => ({ ids: [...ids], count: ids.length }), [idsKey]);\n const target = useMemo(() => ({ resource, action: actionName }), [resource, actionName]);\n const flow = useFlowRun(target, { selection, surface: 'bulk' });\n const chrome = useFlowChrome(resource, actionName);\n const testid = tid.bulkAction(resource, actionName);\n const [confirming, setConfirming] = useState(false);\n const decide = useRef<((proceed: boolean) => void) | null>(null);\n const started = useRef(false);\n const onFinishRef = useRef(onFinish);\n onFinishRef.current = onFinish;\n const { run, snapshot } = flow;\n useEffect(\n () => () => {\n decide.current?.(false);\n decide.current = null;\n },\n [],\n );\n const decided =\n run !== null && snapshot.control !== 'undecided' && snapshot.control !== 'pending';\n useEffect(() => {\n if (!decided || started.current || run === null) return;\n started.current = true;\n void (async () => {\n if (run.getSnapshot().control !== 'ready') {\n toast(\n run.getSnapshot().reason ?? text(t, 'availability.denied', \"This action isn't available\"),\n );\n onFinishRef.current(\n Object.freeze({ outcome: 'unavailable', state: 'disabled' }),\n undefined,\n );\n return;\n }\n let result = await run.submit();\n while (\n result.outcome === 'halted' &&\n (result.step === 'accept' || result.step === 'review')\n ) {\n setConfirming(true);\n const proceed = await new Promise<boolean>((resolve) => {\n decide.current = resolve;\n });\n decide.current = null;\n setConfirming(false);\n if (!proceed) {\n run.startOver();\n onFinishRef.current(result, undefined);\n return;\n }\n result = await run.accept();\n }\n if (result.outcome === 'failed' && 'reason' in result && result.reason === 'busy')\n toast(text(t, 'flow.busyElsewhere', 'This action is running in another tab.'));\n onFinishRef.current(result, run.getSnapshot().bulk);\n })();\n }, [decided, run, t]);\n const gate: CheckGateState = {\n resource,\n open: confirming,\n busy: false,\n header: null,\n blockers: NO_ISSUES,\n confirmable: confirming\n ? snapshot.warnings.map(\n (warning): ValidationIssue => ({\n code: 'check.warning',\n // The machine's text (bundle and params resolved); the key is the check's.\n message: toMessageRef(warning.message, `checks.${warning.id}`),\n path: [],\n // The run's text is final (bundle and params resolved): the dialog shows it as is.\n params: { checkId: warning.id, resolved: true },\n source: 'check',\n severity: 'warning',\n }),\n )\n : NO_ISSUES,\n proceed: () => decide.current?.(true),\n cancel: () => decide.current?.(false),\n };\n return (\n <CheckConfirmDialog\n state={gate}\n testid={`${testid}:confirm`}\n title={chrome.label}\n proceedLabel={chrome.label}\n tone={chrome.destructive ? 'destructive' : 'default'}\n />\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,252 @@
1
+ import { n as toast } from "./toaster-C02XbB9r.js";
2
+ import { h as useFlowChrome, i as makeTestId, m as text, t as CheckConfirmDialog } from "./check-confirm-dialog-bRT8lt0d.js";
3
+ import { APP_ACTION_RESOURCE } from "@burojs/core";
4
+ import { useOptionalT, useProjectedTitle, useTestIds } from "@burojs/react";
5
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
+ import { jsx } from "react/jsx-runtime";
7
+ import { toMessageRef } from "@burojs/core/internal";
8
+ import { useFlowHost, useFlowRun } from "@burojs/react/flows";
9
+ //#region src/flows/flow-runtime.tsx
10
+ const NO_ISSUES = Object.freeze([]);
11
+ function useFlowLauncher(flow, host, chrome, resource, testid) {
12
+ const t = useOptionalT();
13
+ const [confirming, setConfirming] = useState(false);
14
+ const decide = useRef(null);
15
+ const latest = useRef(flow);
16
+ latest.current = flow;
17
+ useEffect(() => () => {
18
+ decide.current?.(false);
19
+ decide.current = null;
20
+ }, []);
21
+ const launch = useCallback(async () => {
22
+ const { run, compiled } = latest.current;
23
+ if (run === null || compiled === null) return;
24
+ if (compiled.hasHost) {
25
+ await (host.open() ?? Promise.resolve());
26
+ return;
27
+ }
28
+ let result = await run.submit();
29
+ while (result.outcome === "halted" && (result.step === "accept" || result.step === "review")) {
30
+ setConfirming(true);
31
+ const proceed = await new Promise((resolve) => {
32
+ decide.current = resolve;
33
+ });
34
+ decide.current = null;
35
+ setConfirming(false);
36
+ if (!proceed) {
37
+ run.startOver();
38
+ return;
39
+ }
40
+ result = await run.accept();
41
+ }
42
+ if (result.outcome === "failed" && "reason" in result && result.reason === "busy") {
43
+ toast(text(t, "flow.busyElsewhere", "This action is running in another tab."));
44
+ return;
45
+ }
46
+ if (result.outcome === "rejected" || result.outcome === "failed" || result.outcome === "unknown" || result.outcome === "halted" && result.step === "outcome") await (host.open("dialog") ?? Promise.resolve());
47
+ }, [host, t]);
48
+ const { snapshot, compiled } = flow;
49
+ const gate = {
50
+ resource,
51
+ open: confirming,
52
+ busy: false,
53
+ header: null,
54
+ blockers: NO_ISSUES,
55
+ confirmable: confirming ? snapshot.warnings.map((warning) => ({
56
+ code: "check.warning",
57
+ message: toMessageRef(warning.message, `checks.${warning.id}`),
58
+ path: [],
59
+ params: {
60
+ checkId: warning.id,
61
+ resolved: true
62
+ },
63
+ source: "check",
64
+ severity: "warning"
65
+ })) : NO_ISSUES,
66
+ proceed: () => decide.current?.(true),
67
+ cancel: () => decide.current?.(false)
68
+ };
69
+ return {
70
+ launch,
71
+ dialog: compiled === null || compiled.hasHost ? null : jsx(CheckConfirmDialog, {
72
+ state: gate,
73
+ testid: `${testid}:confirm`,
74
+ title: chrome.label,
75
+ proceedLabel: chrome.label,
76
+ tone: chrome.destructive ? "destructive" : "default"
77
+ })
78
+ };
79
+ }
80
+ function FlowRunner({ resource, actionName, record, scope, onClose }) {
81
+ const target = useMemo(() => ({
82
+ resource,
83
+ action: actionName
84
+ }), [resource, actionName]);
85
+ const flow = useFlowRun(target, {
86
+ ...record === void 0 ? {} : { record },
87
+ surface: scope === "row" ? "row" : "menu"
88
+ });
89
+ const chrome = useFlowChrome(resource, actionName);
90
+ const title = useProjectedTitle(resource, record?.id, record);
91
+ const host = useFlowHost(flow, {
92
+ label: chrome.labelText,
93
+ ...record === void 0 || title === "" ? {} : { title },
94
+ ...record === void 0 ? {} : { record }
95
+ });
96
+ const tid = useTestIds();
97
+ const t = useOptionalT();
98
+ const { launch, dialog } = useFlowLauncher(flow, host, chrome, resource, makeTestId(scope, resource, actionName, String(record?.id ?? ""), tid));
99
+ const started = useRef(false);
100
+ const onCloseRef = useRef(onClose);
101
+ onCloseRef.current = onClose;
102
+ const { snapshot, compiled } = flow;
103
+ const decided = compiled !== null && (snapshot.control === "disabled" || snapshot.control === "absent" || snapshot.control === "ready" && (!compiled.hasHost || snapshot.history.includes("open") || snapshot.step === "outcome"));
104
+ useEffect(() => {
105
+ if (!decided || started.current) return;
106
+ started.current = true;
107
+ if (snapshot.control !== "ready") {
108
+ toast(snapshot.reason ?? text(t, "availability.denied", "This action isn't available"));
109
+ onCloseRef.current();
110
+ return;
111
+ }
112
+ launch().finally(() => onCloseRef.current());
113
+ }, [
114
+ decided,
115
+ snapshot.control,
116
+ snapshot.reason,
117
+ launch,
118
+ t
119
+ ]);
120
+ return dialog;
121
+ }
122
+ function AppFlowRunner({ name, label, testid, onClose }) {
123
+ const target = useMemo(() => ({ appAction: name }), [name]);
124
+ const flow = useFlowRun(target, { surface: "app" });
125
+ const chrome = {
126
+ label,
127
+ labelText: label,
128
+ icon: void 0,
129
+ destructive: false
130
+ };
131
+ const host = useFlowHost(flow, { label });
132
+ const t = useOptionalT();
133
+ const { launch, dialog } = useFlowLauncher(flow, host, chrome, APP_ACTION_RESOURCE, testid);
134
+ const started = useRef(false);
135
+ const onCloseRef = useRef(onClose);
136
+ onCloseRef.current = onClose;
137
+ const { snapshot, compiled } = flow;
138
+ const decided = compiled !== null && (snapshot.control === "disabled" || snapshot.control === "absent" || snapshot.control === "ready" && (!compiled.hasHost || snapshot.history.includes("open") || snapshot.step === "outcome"));
139
+ useEffect(() => {
140
+ if (!decided || started.current) return;
141
+ started.current = true;
142
+ if (snapshot.control !== "ready") {
143
+ toast(snapshot.reason ?? text(t, "availability.denied", "This action isn't available"));
144
+ onCloseRef.current();
145
+ return;
146
+ }
147
+ launch().finally(() => onCloseRef.current());
148
+ }, [
149
+ decided,
150
+ snapshot.control,
151
+ snapshot.reason,
152
+ launch,
153
+ t
154
+ ]);
155
+ return dialog;
156
+ }
157
+ function BulkFlowRunner({ resource, actionName, ids, onFinish }) {
158
+ const tid = useTestIds();
159
+ const t = useOptionalT();
160
+ const idsKey = ids.join("\0");
161
+ const selection = useMemo(() => ({
162
+ ids: [...ids],
163
+ count: ids.length
164
+ }), [idsKey]);
165
+ const target = useMemo(() => ({
166
+ resource,
167
+ action: actionName
168
+ }), [resource, actionName]);
169
+ const flow = useFlowRun(target, {
170
+ selection,
171
+ surface: "bulk"
172
+ });
173
+ const chrome = useFlowChrome(resource, actionName);
174
+ const testid = tid.bulkAction(resource, actionName);
175
+ const [confirming, setConfirming] = useState(false);
176
+ const decide = useRef(null);
177
+ const started = useRef(false);
178
+ const onFinishRef = useRef(onFinish);
179
+ onFinishRef.current = onFinish;
180
+ const { run, snapshot } = flow;
181
+ useEffect(() => () => {
182
+ decide.current?.(false);
183
+ decide.current = null;
184
+ }, []);
185
+ const decided = run !== null && snapshot.control !== "undecided" && snapshot.control !== "pending";
186
+ useEffect(() => {
187
+ if (!decided || started.current || run === null) return;
188
+ started.current = true;
189
+ (async () => {
190
+ if (run.getSnapshot().control !== "ready") {
191
+ toast(run.getSnapshot().reason ?? text(t, "availability.denied", "This action isn't available"));
192
+ onFinishRef.current(Object.freeze({
193
+ outcome: "unavailable",
194
+ state: "disabled"
195
+ }), void 0);
196
+ return;
197
+ }
198
+ let result = await run.submit();
199
+ while (result.outcome === "halted" && (result.step === "accept" || result.step === "review")) {
200
+ setConfirming(true);
201
+ const proceed = await new Promise((resolve) => {
202
+ decide.current = resolve;
203
+ });
204
+ decide.current = null;
205
+ setConfirming(false);
206
+ if (!proceed) {
207
+ run.startOver();
208
+ onFinishRef.current(result, void 0);
209
+ return;
210
+ }
211
+ result = await run.accept();
212
+ }
213
+ if (result.outcome === "failed" && "reason" in result && result.reason === "busy") toast(text(t, "flow.busyElsewhere", "This action is running in another tab."));
214
+ onFinishRef.current(result, run.getSnapshot().bulk);
215
+ })();
216
+ }, [
217
+ decided,
218
+ run,
219
+ t
220
+ ]);
221
+ const gate = {
222
+ resource,
223
+ open: confirming,
224
+ busy: false,
225
+ header: null,
226
+ blockers: NO_ISSUES,
227
+ confirmable: confirming ? snapshot.warnings.map((warning) => ({
228
+ code: "check.warning",
229
+ message: toMessageRef(warning.message, `checks.${warning.id}`),
230
+ path: [],
231
+ params: {
232
+ checkId: warning.id,
233
+ resolved: true
234
+ },
235
+ source: "check",
236
+ severity: "warning"
237
+ })) : NO_ISSUES,
238
+ proceed: () => decide.current?.(true),
239
+ cancel: () => decide.current?.(false)
240
+ };
241
+ return jsx(CheckConfirmDialog, {
242
+ state: gate,
243
+ testid: `${testid}:confirm`,
244
+ title: chrome.label,
245
+ proceedLabel: chrome.label,
246
+ tone: chrome.destructive ? "destructive" : "default"
247
+ });
248
+ }
249
+ //#endregion
250
+ export { AppFlowRunner, BulkFlowRunner, FlowRunner };
251
+
252
+ //# sourceMappingURL=flow-runtime-s6lkRPKF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-runtime-s6lkRPKF.js","names":[],"sources":["../src/flows/flow-runtime.tsx"],"sourcesContent":["'use client';\n/**\n * The flow runtime's side of the UI kit (P4, the coordinator's ruling on the bundle): every\n * component that holds a run. It loads on the first sign that a user means to run a flow (a\n * hover, a focus, a menu opening, at the latest the click) through `./load-runtime.js`, and with\n * it `@burojs/react/flows` and `@burojs/core/flows` — the flow machine stays out of an\n * application's first screen.\n */\nimport { toMessageRef } from '@burojs/core/internal';\nimport {\n APP_ACTION_RESOURCE,\n type BulkProgress,\n type FlowControlState,\n type FlowResult,\n type Row,\n type ValidationIssue,\n} from '@burojs/core';\nimport { type CheckGateState, useOptionalT, useProjectedTitle, useTestIds } from '@burojs/react';\nimport {\n type FlowHostControl,\n type UseFlowRunResult,\n useFlowHost,\n useFlowRun,\n} from '@burojs/react/flows';\nimport { type ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { makeTestId } from '../actions/action-button.js';\nimport { CheckConfirmDialog } from '../checks/check-confirm-dialog.js';\nimport { toast } from '../notification/toaster.js';\nimport { type FlowChrome, text, useFlowChrome } from './chrome.js';\n\nconst NO_ISSUES: readonly ValidationIssue[] = Object.freeze([]);\n\n/**\n * Runs a flow from its control (4.15): a flow with a host presents it and the interaction ends\n * when it closes; a `{ label, submit }` flow sends, asks through the confirm dialog when\n * `confirm` or a fired warning asks, and shows `rejected`, `failed` and `unknown` in the flow's\n * screen in a dialog (`success` notifies through the flow's `then`; a lock another tab holds\n * says so). `launch()` settles when the interaction is over.\n */\nfunction useFlowLauncher(\n flow: UseFlowRunResult,\n host: FlowHostControl,\n chrome: FlowChrome,\n resource: string,\n testid: string,\n): { readonly launch: () => Promise<void>; readonly dialog: ReactElement | null } {\n const t = useOptionalT();\n const [confirming, setConfirming] = useState(false);\n const decide = useRef<((proceed: boolean) => void) | null>(null);\n const latest = useRef(flow);\n latest.current = flow;\n useEffect(\n () => () => {\n decide.current?.(false);\n decide.current = null;\n },\n [],\n );\n\n const launch = useCallback(async (): Promise<void> => {\n const { run, compiled } = latest.current;\n if (run === null || compiled === null) return;\n if (compiled.hasHost) {\n await (host.open() ?? Promise.resolve());\n return;\n }\n let result: FlowResult = await run.submit();\n while (result.outcome === 'halted' && (result.step === 'accept' || result.step === 'review')) {\n setConfirming(true);\n const proceed = await new Promise<boolean>((resolve) => {\n decide.current = resolve;\n });\n decide.current = null;\n setConfirming(false);\n if (!proceed) {\n run.startOver();\n return;\n }\n result = await run.accept();\n }\n // Another tab holds the attempt's lock: nothing was sent (4.10).\n if (result.outcome === 'failed' && 'reason' in result && result.reason === 'busy') {\n toast(text(t, 'flow.busyElsewhere', 'This action is running in another tab.'));\n return;\n }\n if (\n result.outcome === 'rejected' ||\n result.outcome === 'failed' ||\n result.outcome === 'unknown' ||\n (result.outcome === 'halted' && result.step === 'outcome')\n )\n await (host.open('dialog') ?? Promise.resolve());\n }, [host, t]);\n\n const { snapshot, compiled } = flow;\n const gate: CheckGateState = {\n resource,\n open: confirming,\n busy: false,\n header: null,\n blockers: NO_ISSUES,\n confirmable: confirming\n ? snapshot.warnings.map(\n (warning): ValidationIssue => ({\n code: 'check.warning',\n // The machine's text (bundle and params resolved); the key is the check's.\n message: toMessageRef(warning.message, `checks.${warning.id}`),\n path: [],\n // The run's text is final (bundle and params resolved): the dialog shows it as is.\n params: { checkId: warning.id, resolved: true },\n source: 'check',\n severity: 'warning',\n }),\n )\n : NO_ISSUES,\n proceed: () => decide.current?.(true),\n cancel: () => decide.current?.(false),\n };\n const dialog =\n compiled === null || compiled.hasHost ? null : (\n <CheckConfirmDialog\n state={gate}\n testid={`${testid}:confirm`}\n title={chrome.label}\n proceedLabel={chrome.label}\n tone={chrome.destructive ? 'destructive' : 'default'}\n />\n );\n return { launch, dialog };\n}\n\nexport interface FlowRunnerProps {\n readonly resource: string;\n readonly actionName: string;\n readonly record?: Row;\n readonly scope: string;\n /** The interaction is over (the host closed, the write answered, the confirm was declined). */\n readonly onClose: () => void;\n}\n\n/**\n * @internal A flow started from a control that holds no run — a row's button, a menu item\n * (4.15: a menu item \"presents its host through the runtime from `onSelect`, so the menu closes\n * normally\"). It renders no control: it starts the run (its `with` sources load now) and, once\n * the run has decided, presents the host or sends; `onClose` reports the end of the\n * interaction. A run that decides against the click (a check over a `with` source fired) says\n * why.\n */\nexport function FlowRunner({\n resource,\n actionName,\n record,\n scope,\n onClose,\n}: FlowRunnerProps): ReactElement | null {\n const target = useMemo(() => ({ resource, action: actionName }), [resource, actionName]);\n const flow = useFlowRun(target, {\n ...(record === undefined ? {} : { record }),\n surface: scope === 'row' ? 'row' : 'menu',\n });\n const chrome = useFlowChrome(resource, actionName);\n const title = useProjectedTitle(resource, record?.id, record);\n const host = useFlowHost(flow, {\n label: chrome.labelText,\n ...(record === undefined || title === '' ? {} : { title }),\n ...(record === undefined ? {} : { record }),\n });\n const tid = useTestIds();\n const t = useOptionalT();\n const testid = makeTestId(scope, resource, actionName, String(record?.id ?? ''), tid);\n const { launch, dialog } = useFlowLauncher(flow, host, chrome, resource, testid);\n const started = useRef(false);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n const { snapshot, compiled } = flow;\n const decided =\n compiled !== null &&\n (snapshot.control === 'disabled' ||\n snapshot.control === 'absent' ||\n (snapshot.control === 'ready' &&\n (!compiled.hasHost || snapshot.history.includes('open') || snapshot.step === 'outcome')));\n useEffect(() => {\n if (!decided || started.current) return;\n started.current = true;\n if (snapshot.control !== 'ready') {\n toast(snapshot.reason ?? text(t, 'availability.denied', \"This action isn't available\"));\n onCloseRef.current();\n return;\n }\n void launch().finally(() => onCloseRef.current());\n }, [decided, snapshot.control, snapshot.reason, launch, t]);\n return dialog;\n}\n\nexport interface AppFlowRunnerProps {\n /** The app action's name (`defineAppAction({ name, kind: 'flow' })`). */\n readonly name: string;\n /** Its label, as the opener resolved it (`appActions.<name>` over the declared default). */\n readonly label: string;\n /** The opener's test id: the confirm dialog's ids suffix it (`<testid>:confirm:…`). */\n readonly testid: string;\n readonly onClose: () => void;\n}\n\n/**\n * @internal An app flow started from its control (`AppFlowButton`, P4-D): the same launcher as a\n * resource flow's — the host when the flow has a form or a review, else the send with the\n * confirm dialog — over the target `{ appAction: name }`, with no record.\n */\nexport function AppFlowRunner({\n name,\n label,\n testid,\n onClose,\n}: AppFlowRunnerProps): ReactElement | null {\n const target = useMemo(() => ({ appAction: name }), [name]);\n const flow = useFlowRun(target, { surface: 'app' });\n const chrome: FlowChrome = { label, labelText: label, icon: undefined, destructive: false };\n const host = useFlowHost(flow, { label });\n const t = useOptionalT();\n const { launch, dialog } = useFlowLauncher(flow, host, chrome, APP_ACTION_RESOURCE, testid);\n const started = useRef(false);\n const onCloseRef = useRef(onClose);\n onCloseRef.current = onClose;\n const { snapshot, compiled } = flow;\n const decided =\n compiled !== null &&\n (snapshot.control === 'disabled' ||\n snapshot.control === 'absent' ||\n (snapshot.control === 'ready' &&\n (!compiled.hasHost || snapshot.history.includes('open') || snapshot.step === 'outcome')));\n useEffect(() => {\n if (!decided || started.current) return;\n started.current = true;\n if (snapshot.control !== 'ready') {\n toast(snapshot.reason ?? text(t, 'availability.denied', \"This action isn't available\"));\n onCloseRef.current();\n return;\n }\n void launch().finally(() => onCloseRef.current());\n }, [decided, snapshot.control, snapshot.reason, launch, t]);\n return dialog;\n}\n\nexport interface BulkFlowRunnerProps {\n readonly resource: string;\n readonly actionName: string;\n readonly ids: readonly string[];\n /** The run is over: its result and its per-id report (absent when nothing was sent). */\n readonly onFinish: (result: FlowResult, progress: BulkProgress | undefined) => void;\n}\n\n/**\n * @internal A bulk flow's run over the selection (4.16), started by the bar's click: the confirm\n * (`confirm` and the fired warnings) asks through the confirm dialog, then the run re-reads the\n * rows and writes each under its own key; `onFinish` reports the result and the per-id report.\n */\nexport function BulkFlowRunner({\n resource,\n actionName,\n ids,\n onFinish,\n}: BulkFlowRunnerProps): ReactElement | null {\n const tid = useTestIds();\n const t = useOptionalT();\n const idsKey = ids.join('\\u0000');\n // biome-ignore lint/correctness/useExhaustiveDependencies: keyed by the ids' values\n const selection = useMemo(() => ({ ids: [...ids], count: ids.length }), [idsKey]);\n const target = useMemo(() => ({ resource, action: actionName }), [resource, actionName]);\n const flow = useFlowRun(target, { selection, surface: 'bulk' });\n const chrome = useFlowChrome(resource, actionName);\n const testid = tid.bulkAction(resource, actionName);\n const [confirming, setConfirming] = useState(false);\n const decide = useRef<((proceed: boolean) => void) | null>(null);\n const started = useRef(false);\n const onFinishRef = useRef(onFinish);\n onFinishRef.current = onFinish;\n const { run, snapshot } = flow;\n useEffect(\n () => () => {\n decide.current?.(false);\n decide.current = null;\n },\n [],\n );\n const decided =\n run !== null && snapshot.control !== 'undecided' && snapshot.control !== 'pending';\n useEffect(() => {\n if (!decided || started.current || run === null) return;\n started.current = true;\n void (async () => {\n if (run.getSnapshot().control !== 'ready') {\n toast(\n run.getSnapshot().reason ?? text(t, 'availability.denied', \"This action isn't available\"),\n );\n onFinishRef.current(\n Object.freeze({ outcome: 'unavailable', state: 'disabled' }),\n undefined,\n );\n return;\n }\n let result = await run.submit();\n while (\n result.outcome === 'halted' &&\n (result.step === 'accept' || result.step === 'review')\n ) {\n setConfirming(true);\n const proceed = await new Promise<boolean>((resolve) => {\n decide.current = resolve;\n });\n decide.current = null;\n setConfirming(false);\n if (!proceed) {\n run.startOver();\n onFinishRef.current(result, undefined);\n return;\n }\n result = await run.accept();\n }\n if (result.outcome === 'failed' && 'reason' in result && result.reason === 'busy')\n toast(text(t, 'flow.busyElsewhere', 'This action is running in another tab.'));\n onFinishRef.current(result, run.getSnapshot().bulk);\n })();\n }, [decided, run, t]);\n const gate: CheckGateState = {\n resource,\n open: confirming,\n busy: false,\n header: null,\n blockers: NO_ISSUES,\n confirmable: confirming\n ? snapshot.warnings.map(\n (warning): ValidationIssue => ({\n code: 'check.warning',\n // The machine's text (bundle and params resolved); the key is the check's.\n message: toMessageRef(warning.message, `checks.${warning.id}`),\n path: [],\n // The run's text is final (bundle and params resolved): the dialog shows it as is.\n params: { checkId: warning.id, resolved: true },\n source: 'check',\n severity: 'warning',\n }),\n )\n : NO_ISSUES,\n proceed: () => decide.current?.(true),\n cancel: () => decide.current?.(false),\n };\n return (\n <CheckConfirmDialog\n state={gate}\n testid={`${testid}:confirm`}\n title={chrome.label}\n proceedLabel={chrome.label}\n tone={chrome.destructive ? 'destructive' : 'default'}\n />\n );\n}\n"],"mappings":";;;;;;;;;AA8BA,MAAM,YAAwC,OAAO,OAAO,CAAC,CAAC;AAS9D,SAAS,gBACP,MACA,MACA,QACA,UACA,QACgF;CAChF,MAAM,IAAI,aAAa;CACvB,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAClD,MAAM,SAAS,OAA4C,IAAI;CAC/D,MAAM,SAAS,OAAO,IAAI;CAC1B,OAAO,UAAU;CACjB,sBACc;EACV,OAAO,UAAU,KAAK;EACtB,OAAO,UAAU;CACnB,GACA,CAAC,CACH;CAEA,MAAM,SAAS,YAAY,YAA2B;EACpD,MAAM,EAAE,KAAK,aAAa,OAAO;EACjC,IAAI,QAAQ,QAAQ,aAAa,MAAM;EACvC,IAAI,SAAS,SAAS;GACpB,OAAO,KAAK,KAAK,KAAK,QAAQ,QAAQ;GACtC;EACF;EACA,IAAI,SAAqB,MAAM,IAAI,OAAO;EAC1C,OAAO,OAAO,YAAY,aAAa,OAAO,SAAS,YAAY,OAAO,SAAS,WAAW;GAC5F,cAAc,IAAI;GAClB,MAAM,UAAU,MAAM,IAAI,SAAkB,YAAY;IACtD,OAAO,UAAU;GACnB,CAAC;GACD,OAAO,UAAU;GACjB,cAAc,KAAK;GACnB,IAAI,CAAC,SAAS;IACZ,IAAI,UAAU;IACd;GACF;GACA,SAAS,MAAM,IAAI,OAAO;EAC5B;EAEA,IAAI,OAAO,YAAY,YAAY,YAAY,UAAU,OAAO,WAAW,QAAQ;GACjF,MAAM,KAAK,GAAG,sBAAsB,wCAAwC,CAAC;GAC7E;EACF;EACA,IACE,OAAO,YAAY,cACnB,OAAO,YAAY,YACnB,OAAO,YAAY,aAClB,OAAO,YAAY,YAAY,OAAO,SAAS,WAEhD,OAAO,KAAK,KAAK,QAAQ,KAAK,QAAQ,QAAQ;CAClD,GAAG,CAAC,MAAM,CAAC,CAAC;CAEZ,MAAM,EAAE,UAAU,aAAa;CAC/B,MAAM,OAAuB;EAC3B;EACA,MAAM;EACN,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa,aACT,SAAS,SAAS,KACf,aAA8B;GAC7B,MAAM;GAEN,SAAS,aAAa,QAAQ,SAAS,UAAU,QAAQ,IAAI;GAC7D,MAAM,CAAC;GAEP,QAAQ;IAAE,SAAS,QAAQ;IAAI,UAAU;GAAK;GAC9C,QAAQ;GACR,UAAU;EACZ,EACF,IACA;EACJ,eAAe,OAAO,UAAU,IAAI;EACpC,cAAc,OAAO,UAAU,KAAK;CACtC;CAWA,OAAO;EAAE;EAAQ,QATf,aAAa,QAAQ,SAAS,UAAU,OACtC,IAAC,oBAAD;GACE,OAAO;GACP,QAAQ,GAAG,OAAO;GAClB,OAAO,OAAO;GACd,cAAc,OAAO;GACrB,MAAM,OAAO,cAAc,gBAAgB;EAC5C,CAAA;CAEmB;AAC1B;AAmBA,SAAgB,WAAW,EACzB,UACA,YACA,QACA,OACA,WACuC;CACvC,MAAM,SAAS,eAAe;EAAE;EAAU,QAAQ;CAAW,IAAI,CAAC,UAAU,UAAU,CAAC;CACvF,MAAM,OAAO,WAAW,QAAQ;EAC9B,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO;EACzC,SAAS,UAAU,QAAQ,QAAQ;CACrC,CAAC;CACD,MAAM,SAAS,cAAc,UAAU,UAAU;CACjD,MAAM,QAAQ,kBAAkB,UAAU,QAAQ,IAAI,MAAM;CAC5D,MAAM,OAAO,YAAY,MAAM;EAC7B,OAAO,OAAO;EACd,GAAI,WAAW,KAAA,KAAa,UAAU,KAAK,CAAC,IAAI,EAAE,MAAM;EACxD,GAAI,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,OAAO;CAC3C,CAAC;CACD,MAAM,MAAM,WAAW;CACvB,MAAM,IAAI,aAAa;CAEvB,MAAM,EAAE,QAAQ,WAAW,gBAAgB,MAAM,MAAM,QAAQ,UADhD,WAAW,OAAO,UAAU,YAAY,OAAO,QAAQ,MAAM,EAAE,GAAG,GACH,CAAC;CAC/E,MAAM,UAAU,OAAO,KAAK;CAC5B,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CACrB,MAAM,EAAE,UAAU,aAAa;CAC/B,MAAM,UACJ,aAAa,SACZ,SAAS,YAAY,cACpB,SAAS,YAAY,YACpB,SAAS,YAAY,YACnB,CAAC,SAAS,WAAW,SAAS,QAAQ,SAAS,MAAM,KAAK,SAAS,SAAS;CACnF,gBAAgB;EACd,IAAI,CAAC,WAAW,QAAQ,SAAS;EACjC,QAAQ,UAAU;EAClB,IAAI,SAAS,YAAY,SAAS;GAChC,MAAM,SAAS,UAAU,KAAK,GAAG,uBAAuB,6BAA6B,CAAC;GACtF,WAAW,QAAQ;GACnB;EACF;EACA,OAAY,CAAC,CAAC,cAAc,WAAW,QAAQ,CAAC;CAClD,GAAG;EAAC;EAAS,SAAS;EAAS,SAAS;EAAQ;EAAQ;CAAC,CAAC;CAC1D,OAAO;AACT;AAiBA,SAAgB,cAAc,EAC5B,MACA,OACA,QACA,WAC0C;CAC1C,MAAM,SAAS,eAAe,EAAE,WAAW,KAAK,IAAI,CAAC,IAAI,CAAC;CAC1D,MAAM,OAAO,WAAW,QAAQ,EAAE,SAAS,MAAM,CAAC;CAClD,MAAM,SAAqB;EAAE;EAAO,WAAW;EAAO,MAAM,KAAA;EAAW,aAAa;CAAM;CAC1F,MAAM,OAAO,YAAY,MAAM,EAAE,MAAM,CAAC;CACxC,MAAM,IAAI,aAAa;CACvB,MAAM,EAAE,QAAQ,WAAW,gBAAgB,MAAM,MAAM,QAAQ,qBAAqB,MAAM;CAC1F,MAAM,UAAU,OAAO,KAAK;CAC5B,MAAM,aAAa,OAAO,OAAO;CACjC,WAAW,UAAU;CACrB,MAAM,EAAE,UAAU,aAAa;CAC/B,MAAM,UACJ,aAAa,SACZ,SAAS,YAAY,cACpB,SAAS,YAAY,YACpB,SAAS,YAAY,YACnB,CAAC,SAAS,WAAW,SAAS,QAAQ,SAAS,MAAM,KAAK,SAAS,SAAS;CACnF,gBAAgB;EACd,IAAI,CAAC,WAAW,QAAQ,SAAS;EACjC,QAAQ,UAAU;EAClB,IAAI,SAAS,YAAY,SAAS;GAChC,MAAM,SAAS,UAAU,KAAK,GAAG,uBAAuB,6BAA6B,CAAC;GACtF,WAAW,QAAQ;GACnB;EACF;EACA,OAAY,CAAC,CAAC,cAAc,WAAW,QAAQ,CAAC;CAClD,GAAG;EAAC;EAAS,SAAS;EAAS,SAAS;EAAQ;EAAQ;CAAC,CAAC;CAC1D,OAAO;AACT;AAeA,SAAgB,eAAe,EAC7B,UACA,YACA,KACA,YAC2C;CAC3C,MAAM,MAAM,WAAW;CACvB,MAAM,IAAI,aAAa;CACvB,MAAM,SAAS,IAAI,KAAK,IAAQ;CAEhC,MAAM,YAAY,eAAe;EAAE,KAAK,CAAC,GAAG,GAAG;EAAG,OAAO,IAAI;CAAO,IAAI,CAAC,MAAM,CAAC;CAChF,MAAM,SAAS,eAAe;EAAE;EAAU,QAAQ;CAAW,IAAI,CAAC,UAAU,UAAU,CAAC;CACvF,MAAM,OAAO,WAAW,QAAQ;EAAE;EAAW,SAAS;CAAO,CAAC;CAC9D,MAAM,SAAS,cAAc,UAAU,UAAU;CACjD,MAAM,SAAS,IAAI,WAAW,UAAU,UAAU;CAClD,MAAM,CAAC,YAAY,iBAAiB,SAAS,KAAK;CAClD,MAAM,SAAS,OAA4C,IAAI;CAC/D,MAAM,UAAU,OAAO,KAAK;CAC5B,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CACtB,MAAM,EAAE,KAAK,aAAa;CAC1B,sBACc;EACV,OAAO,UAAU,KAAK;EACtB,OAAO,UAAU;CACnB,GACA,CAAC,CACH;CACA,MAAM,UACJ,QAAQ,QAAQ,SAAS,YAAY,eAAe,SAAS,YAAY;CAC3E,gBAAgB;EACd,IAAI,CAAC,WAAW,QAAQ,WAAW,QAAQ,MAAM;EACjD,QAAQ,UAAU;EAClB,CAAM,YAAY;GAChB,IAAI,IAAI,YAAY,CAAC,CAAC,YAAY,SAAS;IACzC,MACE,IAAI,YAAY,CAAC,CAAC,UAAU,KAAK,GAAG,uBAAuB,6BAA6B,CAC1F;IACA,YAAY,QACV,OAAO,OAAO;KAAE,SAAS;KAAe,OAAO;IAAW,CAAC,GAC3D,KAAA,CACF;IACA;GACF;GACA,IAAI,SAAS,MAAM,IAAI,OAAO;GAC9B,OACE,OAAO,YAAY,aAClB,OAAO,SAAS,YAAY,OAAO,SAAS,WAC7C;IACA,cAAc,IAAI;IAClB,MAAM,UAAU,MAAM,IAAI,SAAkB,YAAY;KACtD,OAAO,UAAU;IACnB,CAAC;IACD,OAAO,UAAU;IACjB,cAAc,KAAK;IACnB,IAAI,CAAC,SAAS;KACZ,IAAI,UAAU;KACd,YAAY,QAAQ,QAAQ,KAAA,CAAS;KACrC;IACF;IACA,SAAS,MAAM,IAAI,OAAO;GAC5B;GACA,IAAI,OAAO,YAAY,YAAY,YAAY,UAAU,OAAO,WAAW,QACzE,MAAM,KAAK,GAAG,sBAAsB,wCAAwC,CAAC;GAC/E,YAAY,QAAQ,QAAQ,IAAI,YAAY,CAAC,CAAC,IAAI;EACpD,EAAA,CAAG;CACL,GAAG;EAAC;EAAS;EAAK;CAAC,CAAC;CACpB,MAAM,OAAuB;EAC3B;EACA,MAAM;EACN,MAAM;EACN,QAAQ;EACR,UAAU;EACV,aAAa,aACT,SAAS,SAAS,KACf,aAA8B;GAC7B,MAAM;GAEN,SAAS,aAAa,QAAQ,SAAS,UAAU,QAAQ,IAAI;GAC7D,MAAM,CAAC;GAEP,QAAQ;IAAE,SAAS,QAAQ;IAAI,UAAU;GAAK;GAC9C,QAAQ;GACR,UAAU;EACZ,EACF,IACA;EACJ,eAAe,OAAO,UAAU,IAAI;EACpC,cAAc,OAAO,UAAU,KAAK;CACtC;CACA,OACE,IAAC,oBAAD;EACE,OAAO;EACP,QAAQ,GAAG,OAAO;EAClB,OAAO,OAAO;EACd,cAAc,OAAO;EACrB,MAAM,OAAO,cAAc,gBAAgB;CAC5C,CAAA;AAEL"}