@burojs/ui-shadcn 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -0
- package/dist/bulk-summary-BWSAS7k2.js +143 -0
- package/dist/bulk-summary-BWSAS7k2.js.map +1 -0
- package/dist/bulk-summary-CrEij5vq.cjs +143 -0
- package/dist/bulk-summary-CrEij5vq.cjs.map +1 -0
- package/dist/candidates-relation-picker-CS_JZ4Fd.js +31 -0
- package/dist/candidates-relation-picker-CS_JZ4Fd.js.map +1 -0
- package/dist/candidates-relation-picker-y5M6_oe4.cjs +31 -0
- package/dist/candidates-relation-picker-y5M6_oe4.cjs.map +1 -0
- package/dist/{check-confirm-dialog-CkaVTPT9.js → check-confirm-dialog-2j0gOd7x.js} +392 -103
- package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
- package/dist/{check-confirm-dialog-BRByTFpg.cjs → check-confirm-dialog-C-NHgMST.cjs} +476 -102
- package/dist/check-confirm-dialog-C-NHgMST.cjs.map +1 -0
- package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
- package/dist/dialog-C123sVQ8.js.map +1 -0
- package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
- package/dist/dialog-vmMdfUWs.cjs.map +1 -0
- package/dist/{filter-builder-B3mZFL-K.cjs → filter-builder-DFu0JP-1.cjs} +959 -128
- package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
- package/dist/{filter-builder-DOnaXNfP.js → filter-builder-DaWHUZuV.js} +863 -116
- package/dist/filter-builder-DaWHUZuV.js.map +1 -0
- package/dist/{flow-runtime-B6zOHYqI.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
- package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
- package/dist/{flow-runtime-D8h99FSg.js → flow-runtime-DyqTmK3H.js} +62 -30
- package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
- package/dist/{flow-screen-CX05b3G9.cjs → flow-screen-Bcz9NF2V.cjs} +132 -88
- package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
- package/dist/{flow-screen-CmbARSqg.js → flow-screen-DCdli6Ha.js} +132 -88
- package/dist/flow-screen-DCdli6Ha.js.map +1 -0
- package/dist/index.cjs +951 -605
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +618 -332
- package/dist/index.d.ts +618 -332
- package/dist/index.js +863 -522
- package/dist/index.js.map +1 -1
- package/dist/{inline-flow-host-B7U1OJUe.cjs → inline-flow-host-3vw7LzzD.cjs} +5 -5
- package/dist/inline-flow-host-3vw7LzzD.cjs.map +1 -0
- package/dist/{inline-flow-host-C3H2UpSA.js → inline-flow-host-C0rI9B7f.js} +5 -5
- package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
- package/dist/label-66W1qbke.js.map +1 -1
- package/dist/label-w6JYf2cF.cjs.map +1 -1
- package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs +153 -0
- package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
- package/dist/lazy-relation-picker-dialog-CAScLPb2.js +135 -0
- package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
- package/dist/markdown/index.d.cts +2 -3
- package/dist/markdown/index.d.ts +2 -3
- package/dist/{page-flow-route-CyXSvXSE.js → page-flow-route-BHUEpn0I.js} +36 -23
- package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
- package/dist/{page-flow-route-CQ7HsbBm.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
- package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
- package/dist/{place-node-SIp4XYQH.cjs → place-node-CNb3w-c7.cjs} +2227 -999
- package/dist/place-node-CNb3w-c7.cjs.map +1 -0
- package/dist/{place-node--GdsP688.js → place-node-CfzQvh4Y.js} +2164 -984
- package/dist/place-node-CfzQvh4Y.js.map +1 -0
- package/dist/{related-list-cards-B6x9HQQp.js → related-list-cards-BIqqY69Y.js} +9 -4
- package/dist/{related-list-cards-B6x9HQQp.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
- package/dist/{related-list-cards-nxuODlIA.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
- package/dist/{related-list-cards-nxuODlIA.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
- package/dist/{related-list-timeline-DEdfd-rr.js → related-list-timeline-CRh7xwLD.js} +6 -7
- package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
- package/dist/{related-list-timeline-BYJKEbmA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
- package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
- package/dist/{related-rows-B4levHcR.js → related-rows--uP2iKQC.js} +27 -17
- package/dist/related-rows--uP2iKQC.js.map +1 -0
- package/dist/{related-rows-zh5f_4QR.cjs → related-rows-MPnLCmPF.cjs} +32 -22
- package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
- package/dist/{search-access-CURsWn-U.js → relation-create-C43cdPQt.js} +596 -29
- package/dist/relation-create-C43cdPQt.js.map +1 -0
- package/dist/{search-access-B7G5oR8n.cjs → relation-create-DDEYcKfw.cjs} +630 -32
- package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
- package/dist/{relation-many-picker-gdAOD-qK.js → relation-many-picker-BJhaEqxz.js} +210 -107
- package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
- package/dist/{relation-many-picker-B-NCEUgX.cjs → relation-many-picker-DzuGJpEl.cjs} +218 -115
- package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
- package/dist/{relation-picker-BAY77ivO.js → relation-picker-D-tBBZW_.js} +40 -45
- package/dist/relation-picker-D-tBBZW_.js.map +1 -0
- package/dist/{relation-picker-Da_uhFvA.cjs → relation-picker-DaIMzf2H.cjs} +45 -50
- package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
- package/dist/{relation-picker-dialog-M0pQaWlp.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +142 -40
- package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
- package/dist/{relation-picker-dialog-hA9rYrZB.js → relation-picker-dialog-DoEY8EkH.js} +143 -41
- package/dist/relation-picker-dialog-DoEY8EkH.js.map +1 -0
- package/dist/relation-select-B8Fq4o-t.js +48 -0
- package/dist/relation-select-B8Fq4o-t.js.map +1 -0
- package/dist/relation-select-Cr3CfNLy.cjs +55 -0
- package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
- package/dist/{resource-page-router-OSQyRA5b.cjs → resource-page-router-C_kGW2o_.cjs} +552 -303
- package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
- package/dist/{resource-page-router-T4vS5gbJ.js → resource-page-router-Diw6S6TK.js} +507 -258
- package/dist/resource-page-router-Diw6S6TK.js.map +1 -0
- package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
- package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
- package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
- package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
- package/dist/success-notices-Dl3M1fZP.cjs +46 -0
- package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
- package/dist/success-notices-LDEgEkc4.js +41 -0
- package/dist/success-notices-LDEgEkc4.js.map +1 -0
- package/dist/{toaster-C7CiYA4Z.cjs → toaster-BbByOytP.cjs} +72 -80
- package/dist/toaster-BbByOytP.cjs.map +1 -0
- package/dist/{toaster-CfCRLgR-.js → toaster-Ct_YHGs6.js} +66 -68
- package/dist/toaster-Ct_YHGs6.js.map +1 -0
- package/dist/{use-dialog-filter-state-BDcgS5Oz.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
- package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
- package/dist/{use-dialog-filter-state-BBCC0OEK.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
- package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
- package/dist/use-theme-DFlpXils.cjs.map +1 -1
- package/dist/use-theme-dnE3Od3I.js.map +1 -1
- package/package.json +11 -11
- package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
- package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
- package/dist/bulk-summary-GxMDP4bw.js +0 -108
- package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
- package/dist/candidates-gate-CX2PBu6l.js +0 -63
- package/dist/candidates-gate-CX2PBu6l.js.map +0 -1
- package/dist/candidates-gate-DiFI52r7.cjs +0 -70
- package/dist/candidates-gate-DiFI52r7.cjs.map +0 -1
- package/dist/candidates-relation-picker-CBsVcnPR.js +0 -82
- package/dist/candidates-relation-picker-CBsVcnPR.js.map +0 -1
- package/dist/candidates-relation-picker-Dd_GVLlu.cjs +0 -84
- package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +0 -1
- package/dist/check-confirm-dialog-BRByTFpg.cjs.map +0 -1
- package/dist/check-confirm-dialog-CkaVTPT9.js.map +0 -1
- package/dist/dialog-B_rt9S1c.js.map +0 -1
- package/dist/dialog-DRNUq9EA.cjs.map +0 -1
- package/dist/filter-builder-B3mZFL-K.cjs.map +0 -1
- package/dist/filter-builder-DOnaXNfP.js.map +0 -1
- package/dist/flow-runtime-B6zOHYqI.cjs.map +0 -1
- package/dist/flow-runtime-D8h99FSg.js.map +0 -1
- package/dist/flow-screen-CX05b3G9.cjs.map +0 -1
- package/dist/flow-screen-CmbARSqg.js.map +0 -1
- package/dist/inline-flow-host-B7U1OJUe.cjs.map +0 -1
- package/dist/inline-flow-host-C3H2UpSA.js.map +0 -1
- package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +0 -14
- package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +0 -1
- package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +0 -19
- package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +0 -1
- package/dist/page-flow-route-CQ7HsbBm.cjs.map +0 -1
- package/dist/page-flow-route-CyXSvXSE.js.map +0 -1
- package/dist/peek-filter-CnqHwTMU.cjs +0 -51
- package/dist/peek-filter-CnqHwTMU.cjs.map +0 -1
- package/dist/peek-filter-ErLfO153.js +0 -28
- package/dist/peek-filter-ErLfO153.js.map +0 -1
- package/dist/place-node--GdsP688.js.map +0 -1
- package/dist/place-node-SIp4XYQH.cjs.map +0 -1
- package/dist/related-list-timeline-BYJKEbmA.cjs.map +0 -1
- package/dist/related-list-timeline-DEdfd-rr.js.map +0 -1
- package/dist/related-rows-B4levHcR.js.map +0 -1
- package/dist/related-rows-zh5f_4QR.cjs.map +0 -1
- package/dist/relation-create-BOaUe12G.cjs +0 -362
- package/dist/relation-create-BOaUe12G.cjs.map +0 -1
- package/dist/relation-create-Bg-eEJLs.js +0 -337
- package/dist/relation-create-Bg-eEJLs.js.map +0 -1
- package/dist/relation-many-picker-B-NCEUgX.cjs.map +0 -1
- package/dist/relation-many-picker-gdAOD-qK.js.map +0 -1
- package/dist/relation-picker-BAY77ivO.js.map +0 -1
- package/dist/relation-picker-Da_uhFvA.cjs.map +0 -1
- package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +0 -1
- package/dist/relation-picker-dialog-hA9rYrZB.js.map +0 -1
- package/dist/resource-page-router-OSQyRA5b.cjs.map +0 -1
- package/dist/resource-page-router-T4vS5gbJ.js.map +0 -1
- package/dist/search-access-B7G5oR8n.cjs.map +0 -1
- package/dist/search-access-CURsWn-U.js.map +0 -1
- package/dist/shell-BPlk8hEa.js +0 -205
- package/dist/shell-BPlk8hEa.js.map +0 -1
- package/dist/shell-DxhlsPwm.cjs +0 -271
- package/dist/shell-DxhlsPwm.cjs.map +0 -1
- package/dist/toaster-C7CiYA4Z.cjs.map +0 -1
- package/dist/toaster-CfCRLgR-.js.map +0 -1
- package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +0 -1
- package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { l as useLinkComponent } from "./toaster-Ct_YHGs6.js";
|
|
2
|
+
import { _ as reasonText, m as useFlowChrome } from "./check-confirm-dialog-2j0gOd7x.js";
|
|
3
3
|
import { t as Button } from "./button-MWVeZaqj.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
4
|
+
import { b as RecordState, v as InvalidRouteId, y as LoadError } from "./relation-create-C43cdPQt.js";
|
|
5
|
+
import { wt as recordRouteAvailable } from "./place-node-CfzQvh4Y.js";
|
|
6
|
+
import { M as canonicalNavKey, f as recordTrailKey, p as usePublishRecordTrail, t as NavAreaNotFound } from "./resource-page-router-Diw6S6TK.js";
|
|
7
|
+
import { FlowHostBindingContext, FlowScreen } from "./flow-screen-DCdli6Ha.js";
|
|
7
8
|
import { compileFlow, dtoFields, effectiveFlow, hrefFor } from "@burojs/core";
|
|
8
|
-
import { retryRecordRead, useApp, useApplicationSnapshot, useDispatcherEffects, useFlowRowResolver, useOne, useOptionalT, usePermissions, useProjectedTitle, useRouteNavigate, useTestIds } from "@burojs/react";
|
|
9
|
+
import { retryRecordRead, useApp, useApplicationSnapshot, useDispatcherEffects, useFlowRowResolver, useI18nCaps, useOne, useOptionalT, usePermissions, useProjectedTitle, useRouteNavigate, useRouteRecordId, useTestIds } from "@burojs/react";
|
|
9
10
|
import { IconLoader2 } from "@tabler/icons-react";
|
|
10
11
|
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
11
12
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -31,10 +32,19 @@ function PageFlowRoute({ match }) {
|
|
|
31
32
|
}
|
|
32
33
|
function PageFlowRecord(props) {
|
|
33
34
|
const { resource, id } = props;
|
|
35
|
+
const recordId = useRouteRecordId(resource, id);
|
|
36
|
+
if (recordId === void 0) return jsx(InvalidRouteId, { resource });
|
|
37
|
+
return jsx(PageFlowRead, {
|
|
38
|
+
...props,
|
|
39
|
+
recordId
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function PageFlowRead(props) {
|
|
43
|
+
const { resource, recordId } = props;
|
|
34
44
|
const def = useApp().registry.get(resource);
|
|
35
45
|
const projection = useMemo(() => def === void 0 ? void 0 : dtoFields(def, "record"), [def]);
|
|
36
46
|
const query = useOne(resource, {
|
|
37
|
-
id,
|
|
47
|
+
id: recordId,
|
|
38
48
|
retry: retryRecordRead,
|
|
39
49
|
...projection === void 0 ? {} : { projection }
|
|
40
50
|
});
|
|
@@ -43,17 +53,18 @@ function PageFlowRecord(props) {
|
|
|
43
53
|
const record = result.data;
|
|
44
54
|
if (record === null || typeof record !== "object") return jsx(RecordState, { state: "not-found" });
|
|
45
55
|
return jsx(PageFlowGate, {
|
|
46
|
-
|
|
56
|
+
resource,
|
|
57
|
+
id: props.id,
|
|
58
|
+
name: props.name,
|
|
47
59
|
record
|
|
48
60
|
});
|
|
49
61
|
}
|
|
50
|
-
if (query.error != null) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
62
|
+
if (query.error != null) return jsx(LoadError, {
|
|
63
|
+
surface: "record",
|
|
64
|
+
resource,
|
|
65
|
+
error: query.error,
|
|
66
|
+
retry: () => void query.refetch()
|
|
67
|
+
});
|
|
57
68
|
return jsx(RecordState, { state: "loading" });
|
|
58
69
|
}
|
|
59
70
|
function PageFlowGate(props) {
|
|
@@ -110,6 +121,7 @@ function usePageFlowFrame(props) {
|
|
|
110
121
|
}
|
|
111
122
|
function PageFlowUnavailable(props) {
|
|
112
123
|
const t = useOptionalT();
|
|
124
|
+
const caps = useI18nCaps(props.resource);
|
|
113
125
|
const tid = useTestIds();
|
|
114
126
|
const { recordHref } = usePageFlowFrame(props);
|
|
115
127
|
const Link = useLinkComponent();
|
|
@@ -121,16 +133,16 @@ function PageFlowUnavailable(props) {
|
|
|
121
133
|
children: [
|
|
122
134
|
jsx("p", {
|
|
123
135
|
className: "font-medium",
|
|
124
|
-
children:
|
|
136
|
+
children: t("flow.notAvailable", { defaultValue: "This action is not available" })
|
|
125
137
|
}),
|
|
126
138
|
props.reason === void 0 ? null : jsx("p", {
|
|
127
139
|
className: "text-muted-foreground",
|
|
128
|
-
children: props.reason
|
|
140
|
+
children: reasonText(caps, props.reason, props.resource)
|
|
129
141
|
}),
|
|
130
142
|
jsx(Link, {
|
|
131
143
|
href: recordHref,
|
|
132
144
|
className: "underline",
|
|
133
|
-
children:
|
|
145
|
+
children: t("flow.back", { defaultValue: "Back" })
|
|
134
146
|
})
|
|
135
147
|
]
|
|
136
148
|
}) });
|
|
@@ -153,6 +165,7 @@ function PageFlowRun(props) {
|
|
|
153
165
|
const { resource, name, stale = false, onDirty, onMounted } = props;
|
|
154
166
|
const [record] = useState(props.record);
|
|
155
167
|
const t = useOptionalT();
|
|
168
|
+
const caps = useI18nCaps(resource);
|
|
156
169
|
const tid = useTestIds();
|
|
157
170
|
const navigate = useRouteNavigate();
|
|
158
171
|
const Link = useLinkComponent();
|
|
@@ -228,14 +241,14 @@ function PageFlowRun(props) {
|
|
|
228
241
|
href: recordHref,
|
|
229
242
|
className: "ml-auto text-sm underline",
|
|
230
243
|
"data-testid": `${tid.pageFlow(compiled?.flowId ?? name)}:back`,
|
|
231
|
-
children:
|
|
244
|
+
children: t("flow.back", { defaultValue: "Back" })
|
|
232
245
|
})
|
|
233
246
|
}),
|
|
234
247
|
stale ? jsxs("div", {
|
|
235
248
|
role: "status",
|
|
236
249
|
"data-buro-flow-state": "stale",
|
|
237
250
|
className: "flex flex-wrap items-center gap-2 text-sm text-muted-foreground",
|
|
238
|
-
children: [jsx("span", { children:
|
|
251
|
+
children: [jsx("span", { children: t("flow.noLongerApplies", { defaultValue: "This action no longer applies" }) }), jsx(Button, {
|
|
239
252
|
type: "button",
|
|
240
253
|
size: "sm",
|
|
241
254
|
variant: "outline",
|
|
@@ -243,7 +256,7 @@ function PageFlowRun(props) {
|
|
|
243
256
|
flow.reset();
|
|
244
257
|
setDiscarded(true);
|
|
245
258
|
},
|
|
246
|
-
children:
|
|
259
|
+
children: t("flow.discard", { defaultValue: "Discard" })
|
|
247
260
|
})]
|
|
248
261
|
}) : null,
|
|
249
262
|
opened ? jsx(FlowHostBindingContext.Provider, {
|
|
@@ -263,7 +276,7 @@ function PageFlowRun(props) {
|
|
|
263
276
|
}) : refused ? jsx("p", {
|
|
264
277
|
role: "alert",
|
|
265
278
|
className: "text-sm",
|
|
266
|
-
children: snapshot.reason
|
|
279
|
+
children: snapshot.reason === void 0 ? t("flow.unavailable", { defaultValue: "Not allowed." }) : reasonText(caps, snapshot.reason, resource)
|
|
267
280
|
}) : jsx(IconLoader2, {
|
|
268
281
|
className: "h-5 w-5 animate-spin self-center",
|
|
269
282
|
"aria-hidden": "true"
|
|
@@ -274,4 +287,4 @@ function PageFlowRun(props) {
|
|
|
274
287
|
//#endregion
|
|
275
288
|
export { PageFlowRoute };
|
|
276
289
|
|
|
277
|
-
//# sourceMappingURL=page-flow-route-
|
|
290
|
+
//# sourceMappingURL=page-flow-route-BHUEpn0I.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-flow-route-BHUEpn0I.js","names":[],"sources":["../src/flows/page-flow-route.tsx"],"sourcesContent":["'use client';\n/**\n * A page-hosted flow's route (P6 3.11): `<record route>/<flow name>`. It owns the whole gate in\n * order, so a user who may not run the flow never sees a trace of it:\n *\n * 1. the permission map is decided, else the record route's loading state and nothing is read;\n * 2. static: the resource has a record page, the flow is an item flow and, in the published\n * snapshot, its `host` is `page`; else the record route's not-found;\n * 3. the record is read by id with the record DTO;\n * 4. the flow's gate over that row (`requires`, the mutation's `requires`, `action/run` rules):\n * hidden, absent, or a missing or forbidden row is the same not-found as `/articles/missing`;\n * a false `when` or a blocking pre-click check is \"not available\" and the way back;\n * 5. only then the run (`useFlowRun`) and its sources.\n */\nimport {\n type RecordId,\n type RouteMatch,\n compileFlow,\n dtoFields,\n effectiveFlow,\n hrefFor,\n} from '@burojs/core';\nimport {\n retryRecordRead,\n useApp,\n useApplicationSnapshot,\n useDispatcherEffects,\n useFlowRowResolver,\n useOne,\n useI18nCaps,\n useOptionalT,\n usePermissions,\n useProjectedTitle,\n useRouteNavigate,\n useRouteRecordId,\n useTestIds,\n} from '@burojs/react';\nimport { useFlowRun } from '@burojs/react/flows';\nimport { IconLoader2 } from '@tabler/icons-react';\nimport { type ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useLinkComponent } from '../layout/link-component.js';\nimport { reasonText } from '../lib/reason-text.js';\nimport { InvalidRouteId, LoadError } from '../load-error/load-error-view.js';\nimport { recordRouteAvailable } from '../layout/record-targets.js';\nimport { recordTrailKey, usePublishRecordTrail } from '../layout/record-trail-store.js';\nimport { RecordState } from '../record/record-state.js';\nimport { NavAreaNotFound } from '../layout/resource-page-router.js';\nimport { canonicalNavKey } from '../resource-key.js';\nimport { Button } from '../primitives/button.js';\nimport { useFlowChrome } from './chrome.js';\nimport { type FlowHostBinding, FlowHostBindingContext, FlowScreen } from './flow-screen.js';\n\ntype Row = { id: string } & Record<string, unknown>;\n\ninterface PageFlowProps {\n readonly resource: string;\n readonly id: string;\n readonly name: string;\n}\n\nexport interface PageFlowRouteProps {\n readonly match: RouteMatch;\n}\n\n/** The route: the static gate, then the record, then the flow's own gate. */\nexport function PageFlowRoute({ match }: PageFlowRouteProps): ReactElement {\n const app = useApp();\n const snapshot = useApplicationSnapshot();\n const permissions = usePermissions();\n const resource = canonicalNavKey(match as never);\n const id = match.id ?? '';\n const name = match.flow ?? '';\n // (1) Decided before anything is read.\n if (permissions?.status === 'loading') return <RecordState state=\"loading\" />;\n // (2) Static: a record page to hang the route on, and an item flow whose effective host is page.\n const flow = effectiveFlow(snapshot, match.ref, name);\n const hasRecordPage =\n recordRouteAvailable(app.registry, resource, 'show') ||\n recordRouteAvailable(app.registry, resource, 'edit');\n // A name no item flow answers to is no route at all (`/orders/x/segments`): the framework 404,\n // as for any unmatched URL. A flow that exists but is not page-hosted, or a record page that is\n // missing, keeps the record route's not-found, so a denied flow reads like a missing record.\n if (flow === undefined) return <NavAreaNotFound />;\n if (!hasRecordPage || flow.host !== 'page' || id === '') return <RecordState state=\"not-found\" />;\n return <PageFlowRecord key={`${resource}:${id}:${name}`} {...{ resource, id, name }} />;\n}\n\n/** (3) The record by id, with the record DTO: the same read the record route makes. */\nfunction PageFlowRecord(props: PageFlowProps): ReactElement {\n const { resource, id } = props;\n // The URL's id as the id field types it (spec 4.19); an invalid one names no record.\n const recordId = useRouteRecordId(resource, id);\n if (recordId === undefined) return <InvalidRouteId resource={resource} />;\n return <PageFlowRead {...props} recordId={recordId} />;\n}\n\n/** The record by its typed id. */\nfunction PageFlowRead(props: PageFlowProps & { readonly recordId: RecordId }): ReactElement {\n const { resource, recordId } = props;\n const app = useApp();\n const def = app.registry.get(resource);\n const projection = useMemo(\n () => (def === undefined ? undefined : dtoFields(def, 'record')),\n [def],\n );\n const query = useOne(resource, {\n id: recordId,\n retry: retryRecordRead,\n ...(projection === undefined ? {} : { projection }),\n });\n const result = query.data as { readonly data?: unknown } | undefined;\n if (result !== undefined) {\n const record = result.data;\n if (record === null || typeof record !== 'object') return <RecordState state=\"not-found\" />;\n return (\n <PageFlowGate resource={resource} id={props.id} name={props.name} record={record as Row} />\n );\n }\n if (query.error != null) {\n return (\n <LoadError\n surface=\"record\"\n resource={resource}\n error={query.error}\n retry={() => void query.refetch()}\n />\n );\n }\n return <RecordState state=\"loading\" />;\n}\n\n/** (4) The flow's gate over the row, as its button decides it: no second rule here. */\nfunction PageFlowGate(props: PageFlowProps & { readonly record: Row }): ReactElement {\n const { resource, name, record } = props;\n const resolve = useFlowRowResolver(resource);\n const control = resolve(name, record);\n // Someone else's change can take the flow away under a form that holds input: the page keeps\n // the form, read-only, with the \"no longer applies\" notice and Discard (3.12), instead of\n // unmounting it silently. `useRef` here, `PageFlowRun` mounted from the first available render.\n const dirty = useRef(false);\n const running = useRef(false);\n const goneNow =\n (control.state === 'absent' && control.cause === 'when') || control.state === 'disabled';\n const keep = goneNow && running.current && dirty.current;\n const track = (value: boolean) => {\n dirty.current = value;\n };\n if (keep)\n return (\n <PageFlowRun {...props} stale onDirty={track} onMounted={(on) => (running.current = on)} />\n );\n switch (control.state) {\n case 'undecided':\n case 'pending':\n return <RecordState state=\"loading\" />;\n case 'absent':\n return control.cause === 'when' ? (\n <PageFlowUnavailable {...props} />\n ) : (\n <RecordState state=\"not-found\" />\n );\n case 'disabled':\n return (\n <PageFlowUnavailable\n {...props}\n {...(control.reason === undefined ? {} : { reason: control.reason })}\n />\n );\n default:\n return (\n <PageFlowRun\n {...props}\n record={(control.record ?? record) as Row}\n onDirty={track}\n onMounted={(on) => (running.current = on)}\n />\n );\n }\n}\n\n/**\n * The flow's name, the record's title and the record's way back, shared by every state of the\n * page that shows the record. It also tells the header's trail (`<HeaderBreadcrumbs>`) the\n * record's title and the flow's label, which the trail ends with: only these states do, so a\n * loading or not-found flow route never names its flow.\n */\nfunction usePageFlowFrame(props: PageFlowProps & { readonly record: Row }) {\n const { resource, id, name, record } = props;\n const app = useApp();\n const chrome = useFlowChrome(resource, name);\n const title = useProjectedTitle(resource, id, record);\n const showable = recordRouteAvailable(app.registry, resource, 'show');\n const recordHref = hrefFor(app.registry, resource, {\n action: showable ? 'show' : 'edit',\n id,\n });\n usePublishRecordTrail({\n key: recordTrailKey(resource, id, `flow:${name}`),\n title,\n flowLabel: chrome.labelText,\n });\n return { chrome, title, recordHref };\n}\n\n/** `when` false, or a blocking check: the reason and the way back, no form. */\nfunction PageFlowUnavailable(\n props: PageFlowProps & { readonly record: Row; readonly reason?: string },\n): ReactElement {\n const t = useOptionalT();\n const caps = useI18nCaps(props.resource);\n const tid = useTestIds();\n const { recordHref } = usePageFlowFrame(props);\n const Link = useLinkComponent();\n const flowId = usePageFlowId(props.resource, props.name);\n return (\n <div>\n <div\n role=\"status\"\n data-testid={`${tid.pageFlow(flowId)}:unavailable`}\n className=\"flex flex-col gap-2 px-1 py-6 text-sm\"\n >\n <p className=\"font-medium\">\n {t('flow.notAvailable', { defaultValue: 'This action is not available' })}\n </p>\n {props.reason === undefined ? null : (\n <p className=\"text-muted-foreground\">{reasonText(caps, props.reason, props.resource)}</p>\n )}\n <Link href={recordHref} className=\"underline\">\n {t('flow.back', { defaultValue: 'Back' })}\n </Link>\n </div>\n </div>\n );\n}\n\n/** The flow's identity (`default:articles/actions/rename`), for test ids; stable when compiled. */\nfunction usePageFlowId(resource: string, name: string): string {\n const app = useApp();\n const def = app.registry.get(resource);\n return useMemo(() => {\n try {\n return def === undefined\n ? `${resource}/actions/${name}`\n : compileFlow(def as never, name).flowId;\n } catch {\n return `${resource}/actions/${name}`;\n }\n }, [def, resource, name]);\n}\n\n/** (5) The run and its host. */\nfunction PageFlowRun(\n props: PageFlowProps & {\n readonly record: Row;\n /** The flow no longer applies: the form stays, read-only, with a notice and Discard. */\n readonly stale?: boolean;\n readonly onDirty?: (dirty: boolean) => void;\n readonly onMounted?: (mounted: boolean) => void;\n },\n): ReactElement {\n const { resource, name, stale = false, onDirty, onMounted } = props;\n // The run belongs to the record as it was opened: the refetch after the write must not build\n // a new run (and lose the outcome `then` is about to run on). Display reads the fresh one.\n const [record] = useState(props.record);\n const t = useOptionalT();\n const caps = useI18nCaps(resource);\n const tid = useTestIds();\n const navigate = useRouteNavigate();\n const Link = useLinkComponent();\n const scopeEffects = useDispatcherEffects();\n const { chrome, title, recordHref } = usePageFlowFrame(props);\n const navigateRef = useRef(navigate);\n navigateRef.current = navigate;\n // `redirect` replaces the page: Back cannot reach a form that has been submitted.\n const thenEffects = useCallback(\n () => ({\n ...scopeEffects(),\n redirect: (to: Parameters<typeof navigate>[0]) => navigateRef.current(to, { replace: true }),\n }),\n [scopeEffects],\n );\n const target = useMemo(() => ({ resource, action: name }), [resource, name]);\n const flow = useFlowRun(target, { record, surface: 'page', thenEffects });\n // `then` is the page's to run, once it left the form (4.13).\n flow.holdThen(true);\n const { run, snapshot, compiled } = flow;\n const flowRef = useRef(flow);\n flowRef.current = flow;\n\n // The page leaves the form behind: after the form below it reset (a clean form asks the guard\n // nothing), replace the page by the destination, then run `then` over it.\n const [finished, setFinished] = useState(false);\n useEffect(() => {\n if (!finished) return;\n const current = flowRef.current;\n if (current.compiled?.flow.then?.redirect === undefined)\n navigateRef.current(recordHref, { replace: true });\n // After the route committed: an overlay opened by `then` belongs to the destination, and a\n // route change in flight would close it again.\n setTimeout(() => current.runThen(), 0);\n }, [finished, recordHref]);\n const binding = useMemo<FlowHostBinding>(\n () => ({\n kind: 'page',\n close: () => navigateRef.current(recordHref),\n finish: () => setFinished(true),\n }),\n [recordHref],\n );\n\n useEffect(() => {\n onMounted?.(true);\n return () => onMounted?.(false);\n }, [onMounted]);\n // Unsaved input or an unresolved attempt: what the gate must not unmount silently.\n useEffect(() => {\n if (run === null) return;\n let initial: string | undefined;\n const sync = () => {\n const now = run.getSnapshot();\n if (initial === undefined && now.history.includes('open'))\n initial = JSON.stringify(now.values);\n onDirty?.(\n now.outcome?.outcome !== 'success' &&\n (now.outcome?.outcome === 'unknown' ||\n (initial !== undefined && JSON.stringify(now.values) !== initial)),\n );\n };\n sync();\n return run.subscribe(sync);\n }, [run, onDirty]);\n // Discard: the input is dropped first, so the guard has nothing to ask, then the page leaves.\n const [discarded, setDiscarded] = useState(false);\n useEffect(() => {\n if (discarded) navigateRef.current(recordHref, { replace: true });\n }, [discarded, recordHref]);\n\n const documentTitle = `${chrome.labelText}${title === '' ? '' : ` · ${title}`}`;\n useEffect(() => {\n const previous = document.title;\n document.title = documentTitle;\n return () => {\n document.title = previous;\n };\n }, [documentTitle]);\n\n const opened =\n run !== null &&\n compiled !== null &&\n (snapshot.history.includes('open') || snapshot.step === 'outcome');\n const refused = snapshot.control === 'disabled' || snapshot.control === 'absent';\n return (\n <div\n data-testid={compiled === null ? undefined : tid.pageFlow(compiled.flowId)}\n className=\"flex min-h-0 flex-col gap-4\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <Link\n href={recordHref}\n className=\"ml-auto text-sm underline\"\n data-testid={`${tid.pageFlow(compiled?.flowId ?? name)}:back`}\n >\n {t('flow.back', { defaultValue: 'Back' })}\n </Link>\n </div>\n {stale ? (\n <div\n role=\"status\"\n data-buro-flow-state=\"stale\"\n className=\"flex flex-wrap items-center gap-2 text-sm text-muted-foreground\"\n >\n <span>\n {t('flow.noLongerApplies', { defaultValue: 'This action no longer applies' })}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n flow.reset();\n setDiscarded(true);\n }}\n >\n {t('flow.discard', { defaultValue: 'Discard' })}\n </Button>\n </div>\n ) : null}\n {opened ? (\n <FlowHostBindingContext.Provider value={binding}>\n <fieldset disabled={stale} className=\"m-0 min-w-0 border-0 p-0\">\n <FlowScreen\n host=\"page\"\n run={run}\n compiled={compiled}\n label={chrome.labelText}\n {...(title === '' ? {} : { title })}\n record={record}\n />\n </fieldset>\n </FlowHostBindingContext.Provider>\n ) : refused ? (\n <p role=\"alert\" className=\"text-sm\">\n {snapshot.reason === undefined\n ? t('flow.unavailable', { defaultValue: 'Not allowed.' })\n : reasonText(caps, snapshot.reason, resource)}\n </p>\n ) : (\n <IconLoader2 className=\"h-5 w-5 animate-spin self-center\" aria-hidden=\"true\" />\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;AAiEA,SAAgB,cAAc,EAAE,SAA2C;CACzE,MAAM,MAAM,OAAO;CACnB,MAAM,WAAW,uBAAuB;CACxC,MAAM,cAAc,eAAe;CACnC,MAAM,WAAW,gBAAgB,KAAc;CAC/C,MAAM,KAAK,MAAM,MAAM;CACvB,MAAM,OAAO,MAAM,QAAQ;CAE3B,IAAI,aAAa,WAAW,WAAW,OAAO,IAAC,aAAD,EAAa,OAAM,UAAW,CAAA;CAE5E,MAAM,OAAO,cAAc,UAAU,MAAM,KAAK,IAAI;CACpD,MAAM,gBACJ,qBAAqB,IAAI,UAAU,UAAU,MAAM,KACnD,qBAAqB,IAAI,UAAU,UAAU,MAAM;CAIrD,IAAI,SAAS,KAAA,GAAW,OAAO,IAAC,iBAAD,CAAkB,CAAA;CACjD,IAAI,CAAC,iBAAiB,KAAK,SAAS,UAAU,OAAO,IAAI,OAAO,IAAC,aAAD,EAAa,OAAM,YAAa,CAAA;CAChG,OAAO,IAAC,gBAAD;EAAwD;EAAU;EAAI;CAAS,GAA1D,GAAG,SAAS,GAAG,GAAG,GAAG,MAAqC;AACxF;AAGA,SAAS,eAAe,OAAoC;CAC1D,MAAM,EAAE,UAAU,OAAO;CAEzB,MAAM,WAAW,iBAAiB,UAAU,EAAE;CAC9C,IAAI,aAAa,KAAA,GAAW,OAAO,IAAC,gBAAD,EAA0B,SAAW,CAAA;CACxE,OAAO,IAAC,cAAD;EAAc,GAAI;EAAiB;CAAW,CAAA;AACvD;AAGA,SAAS,aAAa,OAAsE;CAC1F,MAAM,EAAE,UAAU,aAAa;CAE/B,MAAM,MADM,OACE,CAAC,CAAC,SAAS,IAAI,QAAQ;CACrC,MAAM,aAAa,cACV,QAAQ,KAAA,IAAY,KAAA,IAAY,UAAU,KAAK,QAAQ,GAC9D,CAAC,GAAG,CACN;CACA,MAAM,QAAQ,OAAO,UAAU;EAC7B,IAAI;EACJ,OAAO;EACP,GAAI,eAAe,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW;CACnD,CAAC;CACD,MAAM,SAAS,MAAM;CACrB,IAAI,WAAW,KAAA,GAAW;EACxB,MAAM,SAAS,OAAO;EACtB,IAAI,WAAW,QAAQ,OAAO,WAAW,UAAU,OAAO,IAAC,aAAD,EAAa,OAAM,YAAa,CAAA;EAC1F,OACE,IAAC,cAAD;GAAwB;GAAU,IAAI,MAAM;GAAI,MAAM,MAAM;GAAc;EAAgB,CAAA;CAE9F;CACA,IAAI,MAAM,SAAS,MACjB,OACE,IAAC,WAAD;EACE,SAAQ;EACE;EACV,OAAO,MAAM;EACb,aAAa,KAAK,MAAM,QAAQ;CACjC,CAAA;CAGL,OAAO,IAAC,aAAD,EAAa,OAAM,UAAW,CAAA;AACvC;AAGA,SAAS,aAAa,OAA+D;CACnF,MAAM,EAAE,UAAU,MAAM,WAAW;CAEnC,MAAM,UADU,mBAAmB,QACb,CAAC,CAAC,MAAM,MAAM;CAIpC,MAAM,QAAQ,OAAO,KAAK;CAC1B,MAAM,UAAU,OAAO,KAAK;CAG5B,MAAM,QADH,QAAQ,UAAU,YAAY,QAAQ,UAAU,UAAW,QAAQ,UAAU,eACxD,QAAQ,WAAW,MAAM;CACjD,MAAM,SAAS,UAAmB;EAChC,MAAM,UAAU;CAClB;CACA,IAAI,MACF,OACE,IAAC,aAAD;EAAa,GAAI;EAAO,OAAA;EAAM,SAAS;EAAO,YAAY,OAAQ,QAAQ,UAAU;CAAM,CAAA;CAE9F,QAAQ,QAAQ,OAAhB;EACE,KAAK;EACL,KAAK,WACH,OAAO,IAAC,aAAD,EAAa,OAAM,UAAW,CAAA;EACvC,KAAK,UACH,OAAO,QAAQ,UAAU,SACvB,IAAC,qBAAD,EAAqB,GAAI,MAAQ,CAAA,IAEjC,IAAC,aAAD,EAAa,OAAM,YAAa,CAAA;EAEpC,KAAK,YACH,OACE,IAAC,qBAAD;GACE,GAAI;GACJ,GAAK,QAAQ,WAAW,KAAA,IAAY,CAAC,IAAI,EAAE,QAAQ,QAAQ,OAAO;EACnE,CAAA;EAEL,SACE,OACE,IAAC,aAAD;GACE,GAAI;GACJ,QAAS,QAAQ,UAAU;GAC3B,SAAS;GACT,YAAY,OAAQ,QAAQ,UAAU;EACvC,CAAA;CAEP;AACF;AAQA,SAAS,iBAAiB,OAAiD;CACzE,MAAM,EAAE,UAAU,IAAI,MAAM,WAAW;CACvC,MAAM,MAAM,OAAO;CACnB,MAAM,SAAS,cAAc,UAAU,IAAI;CAC3C,MAAM,QAAQ,kBAAkB,UAAU,IAAI,MAAM;CACpD,MAAM,WAAW,qBAAqB,IAAI,UAAU,UAAU,MAAM;CACpE,MAAM,aAAa,QAAQ,IAAI,UAAU,UAAU;EACjD,QAAQ,WAAW,SAAS;EAC5B;CACF,CAAC;CACD,sBAAsB;EACpB,KAAK,eAAe,UAAU,IAAI,QAAQ,MAAM;EAChD;EACA,WAAW,OAAO;CACpB,CAAC;CACD,OAAO;EAAE;EAAQ;EAAO;CAAW;AACrC;AAGA,SAAS,oBACP,OACc;CACd,MAAM,IAAI,aAAa;CACvB,MAAM,OAAO,YAAY,MAAM,QAAQ;CACvC,MAAM,MAAM,WAAW;CACvB,MAAM,EAAE,eAAe,iBAAiB,KAAK;CAC7C,MAAM,OAAO,iBAAiB;CAC9B,MAAM,SAAS,cAAc,MAAM,UAAU,MAAM,IAAI;CACvD,OACE,IAAC,OAAD,EAAA,UACE,KAAC,OAAD;EACE,MAAK;EACL,eAAa,GAAG,IAAI,SAAS,MAAM,EAAE;EACrC,WAAU;EAHZ,UAAA;GAKE,IAAC,KAAD;IAAG,WAAU;IACV,UAAA,EAAE,qBAAqB,EAAE,cAAc,+BAA+B,CAAC;GACvE,CAAA;GACF,MAAM,WAAW,KAAA,IAAY,OAC5B,IAAC,KAAD;IAAG,WAAU;IAAyB,UAAA,WAAW,MAAM,MAAM,QAAQ,MAAM,QAAQ;GAAK,CAAA;GAE1F,IAAC,MAAD;IAAM,MAAM;IAAY,WAAU;IAC/B,UAAA,EAAE,aAAa,EAAE,cAAc,OAAO,CAAC;GACpC,CAAA;EACH;CACF,CAAA,EAAA,CAAA;AAET;AAGA,SAAS,cAAc,UAAkB,MAAsB;CAE7D,MAAM,MADM,OACE,CAAC,CAAC,SAAS,IAAI,QAAQ;CACrC,OAAO,cAAc;EACnB,IAAI;GACF,OAAO,QAAQ,KAAA,IACX,GAAG,SAAS,WAAW,SACvB,YAAY,KAAc,IAAI,CAAC,CAAC;EACtC,QAAQ;GACN,OAAO,GAAG,SAAS,WAAW;EAChC;CACF,GAAG;EAAC;EAAK;EAAU;CAAI,CAAC;AAC1B;AAGA,SAAS,YACP,OAOc;CACd,MAAM,EAAE,UAAU,MAAM,QAAQ,OAAO,SAAS,cAAc;CAG9D,MAAM,CAAC,UAAU,SAAS,MAAM,MAAM;CACtC,MAAM,IAAI,aAAa;CACvB,MAAM,OAAO,YAAY,QAAQ;CACjC,MAAM,MAAM,WAAW;CACvB,MAAM,WAAW,iBAAiB;CAClC,MAAM,OAAO,iBAAiB;CAC9B,MAAM,eAAe,qBAAqB;CAC1C,MAAM,EAAE,QAAQ,OAAO,eAAe,iBAAiB,KAAK;CAC5D,MAAM,cAAc,OAAO,QAAQ;CACnC,YAAY,UAAU;CAEtB,MAAM,cAAc,mBACX;EACL,GAAG,aAAa;EAChB,WAAW,OAAuC,YAAY,QAAQ,IAAI,EAAE,SAAS,KAAK,CAAC;CAC7F,IACA,CAAC,YAAY,CACf;CACA,MAAM,SAAS,eAAe;EAAE;EAAU,QAAQ;CAAK,IAAI,CAAC,UAAU,IAAI,CAAC;CAC3E,MAAM,OAAO,WAAW,QAAQ;EAAE;EAAQ,SAAS;EAAQ;CAAY,CAAC;CAExE,KAAK,SAAS,IAAI;CAClB,MAAM,EAAE,KAAK,UAAU,aAAa;CACpC,MAAM,UAAU,OAAO,IAAI;CAC3B,QAAQ,UAAU;CAIlB,MAAM,CAAC,UAAU,eAAe,SAAS,KAAK;CAC9C,gBAAgB;EACd,IAAI,CAAC,UAAU;EACf,MAAM,UAAU,QAAQ;EACxB,IAAI,QAAQ,UAAU,KAAK,MAAM,aAAa,KAAA,GAC5C,YAAY,QAAQ,YAAY,EAAE,SAAS,KAAK,CAAC;EAGnD,iBAAiB,QAAQ,QAAQ,GAAG,CAAC;CACvC,GAAG,CAAC,UAAU,UAAU,CAAC;CACzB,MAAM,UAAU,eACP;EACL,MAAM;EACN,aAAa,YAAY,QAAQ,UAAU;EAC3C,cAAc,YAAY,IAAI;CAChC,IACA,CAAC,UAAU,CACb;CAEA,gBAAgB;EACd,YAAY,IAAI;EAChB,aAAa,YAAY,KAAK;CAChC,GAAG,CAAC,SAAS,CAAC;CAEd,gBAAgB;EACd,IAAI,QAAQ,MAAM;EAClB,IAAI;EACJ,MAAM,aAAa;GACjB,MAAM,MAAM,IAAI,YAAY;GAC5B,IAAI,YAAY,KAAA,KAAa,IAAI,QAAQ,SAAS,MAAM,GACtD,UAAU,KAAK,UAAU,IAAI,MAAM;GACrC,UACE,IAAI,SAAS,YAAY,cACtB,IAAI,SAAS,YAAY,aACvB,YAAY,KAAA,KAAa,KAAK,UAAU,IAAI,MAAM,MAAM,QAC/D;EACF;EACA,KAAK;EACL,OAAO,IAAI,UAAU,IAAI;CAC3B,GAAG,CAAC,KAAK,OAAO,CAAC;CAEjB,MAAM,CAAC,WAAW,gBAAgB,SAAS,KAAK;CAChD,gBAAgB;EACd,IAAI,WAAW,YAAY,QAAQ,YAAY,EAAE,SAAS,KAAK,CAAC;CAClE,GAAG,CAAC,WAAW,UAAU,CAAC;CAE1B,MAAM,gBAAgB,GAAG,OAAO,YAAY,UAAU,KAAK,KAAK,MAAM;CACtE,gBAAgB;EACd,MAAM,WAAW,SAAS;EAC1B,SAAS,QAAQ;EACjB,aAAa;GACX,SAAS,QAAQ;EACnB;CACF,GAAG,CAAC,aAAa,CAAC;CAElB,MAAM,SACJ,QAAQ,QACR,aAAa,SACZ,SAAS,QAAQ,SAAS,MAAM,KAAK,SAAS,SAAS;CAC1D,MAAM,UAAU,SAAS,YAAY,cAAc,SAAS,YAAY;CACxE,OACE,KAAC,OAAD;EACE,eAAa,aAAa,OAAO,KAAA,IAAY,IAAI,SAAS,SAAS,MAAM;EACzE,WAAU;EAFZ,UAAA;GAIE,IAAC,OAAD;IAAK,WAAU;IACb,UAAA,IAAC,MAAD;KACE,MAAM;KACN,WAAU;KACV,eAAa,GAAG,IAAI,SAAS,UAAU,UAAU,IAAI,EAAE;KAEtD,UAAA,EAAE,aAAa,EAAE,cAAc,OAAO,CAAC;IACpC,CAAA;GACH,CAAA;GACJ,QACC,KAAC,OAAD;IACE,MAAK;IACL,wBAAqB;IACrB,WAAU;IAHZ,UAAA,CAKE,IAAC,QAAD,EAAA,UACG,EAAE,wBAAwB,EAAE,cAAc,gCAAgC,CAAC,EACxE,CAAA,GACN,IAAC,QAAD;KACE,MAAK;KACL,MAAK;KACL,SAAQ;KACR,eAAe;MACb,KAAK,MAAM;MACX,aAAa,IAAI;KACnB;KAEC,UAAA,EAAE,gBAAgB,EAAE,cAAc,UAAU,CAAC;IACxC,CAAA,CACL;GACH,CAAA,IAAA;GACH,SACC,IAAC,uBAAuB,UAAxB;IAAiC,OAAO;IACtC,UAAA,IAAC,YAAD;KAAU,UAAU;KAAO,WAAU;KACnC,UAAA,IAAC,YAAD;MACE,MAAK;MACA;MACK;MACV,OAAO,OAAO;MACd,GAAK,UAAU,KAAK,CAAC,IAAI,EAAE,MAAM;MACzB;KACT,CAAA;IACO,CAAA;GACqB,CAAA,IAC/B,UACF,IAAC,KAAD;IAAG,MAAK;IAAQ,WAAU;IACvB,UAAA,SAAS,WAAW,KAAA,IACjB,EAAE,oBAAoB,EAAE,cAAc,eAAe,CAAC,IACtD,WAAW,MAAM,SAAS,QAAQ,QAAQ;GAC7C,CAAA,IAEH,IAAC,aAAD;IAAa,WAAU;IAAmC,eAAY;GAAQ,CAAA;EAE7E;;AAET"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
const require_toaster = require("./toaster-
|
|
2
|
-
const require_check_confirm_dialog = require("./check-confirm-dialog-
|
|
1
|
+
const require_toaster = require("./toaster-BbByOytP.cjs");
|
|
2
|
+
const require_check_confirm_dialog = require("./check-confirm-dialog-C-NHgMST.cjs");
|
|
3
3
|
const require_button = require("./button-BxnnE28H.cjs");
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
4
|
+
const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
|
|
5
|
+
const require_place_node = require("./place-node-CNb3w-c7.cjs");
|
|
6
|
+
const require_resource_page_router = require("./resource-page-router-C_kGW2o_.cjs");
|
|
7
|
+
const require_flow_screen = require("./flow-screen-Bcz9NF2V.cjs");
|
|
7
8
|
let _burojs_core = require("@burojs/core");
|
|
8
9
|
let _burojs_react = require("@burojs/react");
|
|
9
10
|
let _tabler_icons_react = require("@tabler/icons-react");
|
|
@@ -18,11 +19,11 @@ function PageFlowRoute({ match }) {
|
|
|
18
19
|
const resource = require_resource_page_router.canonicalNavKey(match);
|
|
19
20
|
const id = match.id ?? "";
|
|
20
21
|
const name = match.flow ?? "";
|
|
21
|
-
if (permissions?.status === "loading") return (0, react_jsx_runtime.jsx)(
|
|
22
|
+
if (permissions?.status === "loading") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
|
|
22
23
|
const flow = (0, _burojs_core.effectiveFlow)(snapshot, match.ref, name);
|
|
23
24
|
const hasRecordPage = require_place_node.recordRouteAvailable(app.registry, resource, "show") || require_place_node.recordRouteAvailable(app.registry, resource, "edit");
|
|
24
25
|
if (flow === void 0) return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavAreaNotFound, {});
|
|
25
|
-
if (!hasRecordPage || flow.host !== "page" || id === "") return (0, react_jsx_runtime.jsx)(
|
|
26
|
+
if (!hasRecordPage || flow.host !== "page" || id === "") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
|
|
26
27
|
return (0, react_jsx_runtime.jsx)(PageFlowRecord, {
|
|
27
28
|
resource,
|
|
28
29
|
id,
|
|
@@ -31,30 +32,40 @@ function PageFlowRoute({ match }) {
|
|
|
31
32
|
}
|
|
32
33
|
function PageFlowRecord(props) {
|
|
33
34
|
const { resource, id } = props;
|
|
35
|
+
const recordId = (0, _burojs_react.useRouteRecordId)(resource, id);
|
|
36
|
+
if (recordId === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.InvalidRouteId, { resource });
|
|
37
|
+
return (0, react_jsx_runtime.jsx)(PageFlowRead, {
|
|
38
|
+
...props,
|
|
39
|
+
recordId
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function PageFlowRead(props) {
|
|
43
|
+
const { resource, recordId } = props;
|
|
34
44
|
const def = (0, _burojs_react.useApp)().registry.get(resource);
|
|
35
45
|
const projection = (0, react.useMemo)(() => def === void 0 ? void 0 : (0, _burojs_core.dtoFields)(def, "record"), [def]);
|
|
36
46
|
const query = (0, _burojs_react.useOne)(resource, {
|
|
37
|
-
id,
|
|
47
|
+
id: recordId,
|
|
38
48
|
retry: _burojs_react.retryRecordRead,
|
|
39
49
|
...projection === void 0 ? {} : { projection }
|
|
40
50
|
});
|
|
41
51
|
const result = query.data;
|
|
42
52
|
if (result !== void 0) {
|
|
43
53
|
const record = result.data;
|
|
44
|
-
if (record === null || typeof record !== "object") return (0, react_jsx_runtime.jsx)(
|
|
54
|
+
if (record === null || typeof record !== "object") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
|
|
45
55
|
return (0, react_jsx_runtime.jsx)(PageFlowGate, {
|
|
46
|
-
|
|
56
|
+
resource,
|
|
57
|
+
id: props.id,
|
|
58
|
+
name: props.name,
|
|
47
59
|
record
|
|
48
60
|
});
|
|
49
61
|
}
|
|
50
|
-
if (query.error != null) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "loading" });
|
|
62
|
+
if (query.error != null) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
|
|
63
|
+
surface: "record",
|
|
64
|
+
resource,
|
|
65
|
+
error: query.error,
|
|
66
|
+
retry: () => void query.refetch()
|
|
67
|
+
});
|
|
68
|
+
return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
|
|
58
69
|
}
|
|
59
70
|
function PageFlowGate(props) {
|
|
60
71
|
const { resource, name, record } = props;
|
|
@@ -73,8 +84,8 @@ function PageFlowGate(props) {
|
|
|
73
84
|
});
|
|
74
85
|
switch (control.state) {
|
|
75
86
|
case "undecided":
|
|
76
|
-
case "pending": return (0, react_jsx_runtime.jsx)(
|
|
77
|
-
case "absent": return control.cause === "when" ? (0, react_jsx_runtime.jsx)(PageFlowUnavailable, { ...props }) : (0, react_jsx_runtime.jsx)(
|
|
87
|
+
case "pending": return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
|
|
88
|
+
case "absent": return control.cause === "when" ? (0, react_jsx_runtime.jsx)(PageFlowUnavailable, { ...props }) : (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
|
|
78
89
|
case "disabled": return (0, react_jsx_runtime.jsx)(PageFlowUnavailable, {
|
|
79
90
|
...props,
|
|
80
91
|
...control.reason === void 0 ? {} : { reason: control.reason }
|
|
@@ -110,6 +121,7 @@ function usePageFlowFrame(props) {
|
|
|
110
121
|
}
|
|
111
122
|
function PageFlowUnavailable(props) {
|
|
112
123
|
const t = (0, _burojs_react.useOptionalT)();
|
|
124
|
+
const caps = (0, _burojs_react.useI18nCaps)(props.resource);
|
|
113
125
|
const tid = (0, _burojs_react.useTestIds)();
|
|
114
126
|
const { recordHref } = usePageFlowFrame(props);
|
|
115
127
|
const Link = require_toaster.useLinkComponent();
|
|
@@ -121,16 +133,16 @@ function PageFlowUnavailable(props) {
|
|
|
121
133
|
children: [
|
|
122
134
|
(0, react_jsx_runtime.jsx)("p", {
|
|
123
135
|
className: "font-medium",
|
|
124
|
-
children:
|
|
136
|
+
children: t("flow.notAvailable", { defaultValue: "This action is not available" })
|
|
125
137
|
}),
|
|
126
138
|
props.reason === void 0 ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
127
139
|
className: "text-muted-foreground",
|
|
128
|
-
children: props.reason
|
|
140
|
+
children: require_check_confirm_dialog.reasonText(caps, props.reason, props.resource)
|
|
129
141
|
}),
|
|
130
142
|
(0, react_jsx_runtime.jsx)(Link, {
|
|
131
143
|
href: recordHref,
|
|
132
144
|
className: "underline",
|
|
133
|
-
children:
|
|
145
|
+
children: t("flow.back", { defaultValue: "Back" })
|
|
134
146
|
})
|
|
135
147
|
]
|
|
136
148
|
}) });
|
|
@@ -153,6 +165,7 @@ function PageFlowRun(props) {
|
|
|
153
165
|
const { resource, name, stale = false, onDirty, onMounted } = props;
|
|
154
166
|
const [record] = (0, react.useState)(props.record);
|
|
155
167
|
const t = (0, _burojs_react.useOptionalT)();
|
|
168
|
+
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
156
169
|
const tid = (0, _burojs_react.useTestIds)();
|
|
157
170
|
const navigate = (0, _burojs_react.useRouteNavigate)();
|
|
158
171
|
const Link = require_toaster.useLinkComponent();
|
|
@@ -228,14 +241,14 @@ function PageFlowRun(props) {
|
|
|
228
241
|
href: recordHref,
|
|
229
242
|
className: "ml-auto text-sm underline",
|
|
230
243
|
"data-testid": `${tid.pageFlow(compiled?.flowId ?? name)}:back`,
|
|
231
|
-
children:
|
|
244
|
+
children: t("flow.back", { defaultValue: "Back" })
|
|
232
245
|
})
|
|
233
246
|
}),
|
|
234
247
|
stale ? (0, react_jsx_runtime.jsxs)("div", {
|
|
235
248
|
role: "status",
|
|
236
249
|
"data-buro-flow-state": "stale",
|
|
237
250
|
className: "flex flex-wrap items-center gap-2 text-sm text-muted-foreground",
|
|
238
|
-
children: [(0, react_jsx_runtime.jsx)("span", { children:
|
|
251
|
+
children: [(0, react_jsx_runtime.jsx)("span", { children: t("flow.noLongerApplies", { defaultValue: "This action no longer applies" }) }), (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
239
252
|
type: "button",
|
|
240
253
|
size: "sm",
|
|
241
254
|
variant: "outline",
|
|
@@ -243,7 +256,7 @@ function PageFlowRun(props) {
|
|
|
243
256
|
flow.reset();
|
|
244
257
|
setDiscarded(true);
|
|
245
258
|
},
|
|
246
|
-
children:
|
|
259
|
+
children: t("flow.discard", { defaultValue: "Discard" })
|
|
247
260
|
})]
|
|
248
261
|
}) : null,
|
|
249
262
|
opened ? (0, react_jsx_runtime.jsx)(require_flow_screen.FlowHostBindingContext.Provider, {
|
|
@@ -263,7 +276,7 @@ function PageFlowRun(props) {
|
|
|
263
276
|
}) : refused ? (0, react_jsx_runtime.jsx)("p", {
|
|
264
277
|
role: "alert",
|
|
265
278
|
className: "text-sm",
|
|
266
|
-
children: snapshot.reason
|
|
279
|
+
children: snapshot.reason === void 0 ? t("flow.unavailable", { defaultValue: "Not allowed." }) : require_check_confirm_dialog.reasonText(caps, snapshot.reason, resource)
|
|
267
280
|
}) : (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
|
|
268
281
|
className: "h-5 w-5 animate-spin self-center",
|
|
269
282
|
"aria-hidden": "true"
|
|
@@ -274,4 +287,4 @@ function PageFlowRun(props) {
|
|
|
274
287
|
//#endregion
|
|
275
288
|
exports.PageFlowRoute = PageFlowRoute;
|
|
276
289
|
|
|
277
|
-
//# sourceMappingURL=page-flow-route-
|
|
290
|
+
//# sourceMappingURL=page-flow-route-DS8IVTVH.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-flow-route-DS8IVTVH.cjs","names":["useApp","useApplicationSnapshot","usePermissions","canonicalNavKey","RecordState","effectiveFlow","recordRouteAvailable","NavAreaNotFound","useRouteRecordId","InvalidRouteId","useMemo","dtoFields","useOne","retryRecordRead","LoadError","useFlowRowResolver","useRef","useFlowChrome","useProjectedTitle","hrefFor","recordTrailKey","useOptionalT","useI18nCaps","useTestIds","useLinkComponent","reasonText","compileFlow","useState","useRouteNavigate","useDispatcherEffects","useCallback","useFlowRun","Button","FlowHostBindingContext","FlowScreen","IconLoader2"],"sources":["../src/flows/page-flow-route.tsx"],"sourcesContent":["'use client';\n/**\n * A page-hosted flow's route (P6 3.11): `<record route>/<flow name>`. It owns the whole gate in\n * order, so a user who may not run the flow never sees a trace of it:\n *\n * 1. the permission map is decided, else the record route's loading state and nothing is read;\n * 2. static: the resource has a record page, the flow is an item flow and, in the published\n * snapshot, its `host` is `page`; else the record route's not-found;\n * 3. the record is read by id with the record DTO;\n * 4. the flow's gate over that row (`requires`, the mutation's `requires`, `action/run` rules):\n * hidden, absent, or a missing or forbidden row is the same not-found as `/articles/missing`;\n * a false `when` or a blocking pre-click check is \"not available\" and the way back;\n * 5. only then the run (`useFlowRun`) and its sources.\n */\nimport {\n type RecordId,\n type RouteMatch,\n compileFlow,\n dtoFields,\n effectiveFlow,\n hrefFor,\n} from '@burojs/core';\nimport {\n retryRecordRead,\n useApp,\n useApplicationSnapshot,\n useDispatcherEffects,\n useFlowRowResolver,\n useOne,\n useI18nCaps,\n useOptionalT,\n usePermissions,\n useProjectedTitle,\n useRouteNavigate,\n useRouteRecordId,\n useTestIds,\n} from '@burojs/react';\nimport { useFlowRun } from '@burojs/react/flows';\nimport { IconLoader2 } from '@tabler/icons-react';\nimport { type ReactElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { useLinkComponent } from '../layout/link-component.js';\nimport { reasonText } from '../lib/reason-text.js';\nimport { InvalidRouteId, LoadError } from '../load-error/load-error-view.js';\nimport { recordRouteAvailable } from '../layout/record-targets.js';\nimport { recordTrailKey, usePublishRecordTrail } from '../layout/record-trail-store.js';\nimport { RecordState } from '../record/record-state.js';\nimport { NavAreaNotFound } from '../layout/resource-page-router.js';\nimport { canonicalNavKey } from '../resource-key.js';\nimport { Button } from '../primitives/button.js';\nimport { useFlowChrome } from './chrome.js';\nimport { type FlowHostBinding, FlowHostBindingContext, FlowScreen } from './flow-screen.js';\n\ntype Row = { id: string } & Record<string, unknown>;\n\ninterface PageFlowProps {\n readonly resource: string;\n readonly id: string;\n readonly name: string;\n}\n\nexport interface PageFlowRouteProps {\n readonly match: RouteMatch;\n}\n\n/** The route: the static gate, then the record, then the flow's own gate. */\nexport function PageFlowRoute({ match }: PageFlowRouteProps): ReactElement {\n const app = useApp();\n const snapshot = useApplicationSnapshot();\n const permissions = usePermissions();\n const resource = canonicalNavKey(match as never);\n const id = match.id ?? '';\n const name = match.flow ?? '';\n // (1) Decided before anything is read.\n if (permissions?.status === 'loading') return <RecordState state=\"loading\" />;\n // (2) Static: a record page to hang the route on, and an item flow whose effective host is page.\n const flow = effectiveFlow(snapshot, match.ref, name);\n const hasRecordPage =\n recordRouteAvailable(app.registry, resource, 'show') ||\n recordRouteAvailable(app.registry, resource, 'edit');\n // A name no item flow answers to is no route at all (`/orders/x/segments`): the framework 404,\n // as for any unmatched URL. A flow that exists but is not page-hosted, or a record page that is\n // missing, keeps the record route's not-found, so a denied flow reads like a missing record.\n if (flow === undefined) return <NavAreaNotFound />;\n if (!hasRecordPage || flow.host !== 'page' || id === '') return <RecordState state=\"not-found\" />;\n return <PageFlowRecord key={`${resource}:${id}:${name}`} {...{ resource, id, name }} />;\n}\n\n/** (3) The record by id, with the record DTO: the same read the record route makes. */\nfunction PageFlowRecord(props: PageFlowProps): ReactElement {\n const { resource, id } = props;\n // The URL's id as the id field types it (spec 4.19); an invalid one names no record.\n const recordId = useRouteRecordId(resource, id);\n if (recordId === undefined) return <InvalidRouteId resource={resource} />;\n return <PageFlowRead {...props} recordId={recordId} />;\n}\n\n/** The record by its typed id. */\nfunction PageFlowRead(props: PageFlowProps & { readonly recordId: RecordId }): ReactElement {\n const { resource, recordId } = props;\n const app = useApp();\n const def = app.registry.get(resource);\n const projection = useMemo(\n () => (def === undefined ? undefined : dtoFields(def, 'record')),\n [def],\n );\n const query = useOne(resource, {\n id: recordId,\n retry: retryRecordRead,\n ...(projection === undefined ? {} : { projection }),\n });\n const result = query.data as { readonly data?: unknown } | undefined;\n if (result !== undefined) {\n const record = result.data;\n if (record === null || typeof record !== 'object') return <RecordState state=\"not-found\" />;\n return (\n <PageFlowGate resource={resource} id={props.id} name={props.name} record={record as Row} />\n );\n }\n if (query.error != null) {\n return (\n <LoadError\n surface=\"record\"\n resource={resource}\n error={query.error}\n retry={() => void query.refetch()}\n />\n );\n }\n return <RecordState state=\"loading\" />;\n}\n\n/** (4) The flow's gate over the row, as its button decides it: no second rule here. */\nfunction PageFlowGate(props: PageFlowProps & { readonly record: Row }): ReactElement {\n const { resource, name, record } = props;\n const resolve = useFlowRowResolver(resource);\n const control = resolve(name, record);\n // Someone else's change can take the flow away under a form that holds input: the page keeps\n // the form, read-only, with the \"no longer applies\" notice and Discard (3.12), instead of\n // unmounting it silently. `useRef` here, `PageFlowRun` mounted from the first available render.\n const dirty = useRef(false);\n const running = useRef(false);\n const goneNow =\n (control.state === 'absent' && control.cause === 'when') || control.state === 'disabled';\n const keep = goneNow && running.current && dirty.current;\n const track = (value: boolean) => {\n dirty.current = value;\n };\n if (keep)\n return (\n <PageFlowRun {...props} stale onDirty={track} onMounted={(on) => (running.current = on)} />\n );\n switch (control.state) {\n case 'undecided':\n case 'pending':\n return <RecordState state=\"loading\" />;\n case 'absent':\n return control.cause === 'when' ? (\n <PageFlowUnavailable {...props} />\n ) : (\n <RecordState state=\"not-found\" />\n );\n case 'disabled':\n return (\n <PageFlowUnavailable\n {...props}\n {...(control.reason === undefined ? {} : { reason: control.reason })}\n />\n );\n default:\n return (\n <PageFlowRun\n {...props}\n record={(control.record ?? record) as Row}\n onDirty={track}\n onMounted={(on) => (running.current = on)}\n />\n );\n }\n}\n\n/**\n * The flow's name, the record's title and the record's way back, shared by every state of the\n * page that shows the record. It also tells the header's trail (`<HeaderBreadcrumbs>`) the\n * record's title and the flow's label, which the trail ends with: only these states do, so a\n * loading or not-found flow route never names its flow.\n */\nfunction usePageFlowFrame(props: PageFlowProps & { readonly record: Row }) {\n const { resource, id, name, record } = props;\n const app = useApp();\n const chrome = useFlowChrome(resource, name);\n const title = useProjectedTitle(resource, id, record);\n const showable = recordRouteAvailable(app.registry, resource, 'show');\n const recordHref = hrefFor(app.registry, resource, {\n action: showable ? 'show' : 'edit',\n id,\n });\n usePublishRecordTrail({\n key: recordTrailKey(resource, id, `flow:${name}`),\n title,\n flowLabel: chrome.labelText,\n });\n return { chrome, title, recordHref };\n}\n\n/** `when` false, or a blocking check: the reason and the way back, no form. */\nfunction PageFlowUnavailable(\n props: PageFlowProps & { readonly record: Row; readonly reason?: string },\n): ReactElement {\n const t = useOptionalT();\n const caps = useI18nCaps(props.resource);\n const tid = useTestIds();\n const { recordHref } = usePageFlowFrame(props);\n const Link = useLinkComponent();\n const flowId = usePageFlowId(props.resource, props.name);\n return (\n <div>\n <div\n role=\"status\"\n data-testid={`${tid.pageFlow(flowId)}:unavailable`}\n className=\"flex flex-col gap-2 px-1 py-6 text-sm\"\n >\n <p className=\"font-medium\">\n {t('flow.notAvailable', { defaultValue: 'This action is not available' })}\n </p>\n {props.reason === undefined ? null : (\n <p className=\"text-muted-foreground\">{reasonText(caps, props.reason, props.resource)}</p>\n )}\n <Link href={recordHref} className=\"underline\">\n {t('flow.back', { defaultValue: 'Back' })}\n </Link>\n </div>\n </div>\n );\n}\n\n/** The flow's identity (`default:articles/actions/rename`), for test ids; stable when compiled. */\nfunction usePageFlowId(resource: string, name: string): string {\n const app = useApp();\n const def = app.registry.get(resource);\n return useMemo(() => {\n try {\n return def === undefined\n ? `${resource}/actions/${name}`\n : compileFlow(def as never, name).flowId;\n } catch {\n return `${resource}/actions/${name}`;\n }\n }, [def, resource, name]);\n}\n\n/** (5) The run and its host. */\nfunction PageFlowRun(\n props: PageFlowProps & {\n readonly record: Row;\n /** The flow no longer applies: the form stays, read-only, with a notice and Discard. */\n readonly stale?: boolean;\n readonly onDirty?: (dirty: boolean) => void;\n readonly onMounted?: (mounted: boolean) => void;\n },\n): ReactElement {\n const { resource, name, stale = false, onDirty, onMounted } = props;\n // The run belongs to the record as it was opened: the refetch after the write must not build\n // a new run (and lose the outcome `then` is about to run on). Display reads the fresh one.\n const [record] = useState(props.record);\n const t = useOptionalT();\n const caps = useI18nCaps(resource);\n const tid = useTestIds();\n const navigate = useRouteNavigate();\n const Link = useLinkComponent();\n const scopeEffects = useDispatcherEffects();\n const { chrome, title, recordHref } = usePageFlowFrame(props);\n const navigateRef = useRef(navigate);\n navigateRef.current = navigate;\n // `redirect` replaces the page: Back cannot reach a form that has been submitted.\n const thenEffects = useCallback(\n () => ({\n ...scopeEffects(),\n redirect: (to: Parameters<typeof navigate>[0]) => navigateRef.current(to, { replace: true }),\n }),\n [scopeEffects],\n );\n const target = useMemo(() => ({ resource, action: name }), [resource, name]);\n const flow = useFlowRun(target, { record, surface: 'page', thenEffects });\n // `then` is the page's to run, once it left the form (4.13).\n flow.holdThen(true);\n const { run, snapshot, compiled } = flow;\n const flowRef = useRef(flow);\n flowRef.current = flow;\n\n // The page leaves the form behind: after the form below it reset (a clean form asks the guard\n // nothing), replace the page by the destination, then run `then` over it.\n const [finished, setFinished] = useState(false);\n useEffect(() => {\n if (!finished) return;\n const current = flowRef.current;\n if (current.compiled?.flow.then?.redirect === undefined)\n navigateRef.current(recordHref, { replace: true });\n // After the route committed: an overlay opened by `then` belongs to the destination, and a\n // route change in flight would close it again.\n setTimeout(() => current.runThen(), 0);\n }, [finished, recordHref]);\n const binding = useMemo<FlowHostBinding>(\n () => ({\n kind: 'page',\n close: () => navigateRef.current(recordHref),\n finish: () => setFinished(true),\n }),\n [recordHref],\n );\n\n useEffect(() => {\n onMounted?.(true);\n return () => onMounted?.(false);\n }, [onMounted]);\n // Unsaved input or an unresolved attempt: what the gate must not unmount silently.\n useEffect(() => {\n if (run === null) return;\n let initial: string | undefined;\n const sync = () => {\n const now = run.getSnapshot();\n if (initial === undefined && now.history.includes('open'))\n initial = JSON.stringify(now.values);\n onDirty?.(\n now.outcome?.outcome !== 'success' &&\n (now.outcome?.outcome === 'unknown' ||\n (initial !== undefined && JSON.stringify(now.values) !== initial)),\n );\n };\n sync();\n return run.subscribe(sync);\n }, [run, onDirty]);\n // Discard: the input is dropped first, so the guard has nothing to ask, then the page leaves.\n const [discarded, setDiscarded] = useState(false);\n useEffect(() => {\n if (discarded) navigateRef.current(recordHref, { replace: true });\n }, [discarded, recordHref]);\n\n const documentTitle = `${chrome.labelText}${title === '' ? '' : ` · ${title}`}`;\n useEffect(() => {\n const previous = document.title;\n document.title = documentTitle;\n return () => {\n document.title = previous;\n };\n }, [documentTitle]);\n\n const opened =\n run !== null &&\n compiled !== null &&\n (snapshot.history.includes('open') || snapshot.step === 'outcome');\n const refused = snapshot.control === 'disabled' || snapshot.control === 'absent';\n return (\n <div\n data-testid={compiled === null ? undefined : tid.pageFlow(compiled.flowId)}\n className=\"flex min-h-0 flex-col gap-4\"\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <Link\n href={recordHref}\n className=\"ml-auto text-sm underline\"\n data-testid={`${tid.pageFlow(compiled?.flowId ?? name)}:back`}\n >\n {t('flow.back', { defaultValue: 'Back' })}\n </Link>\n </div>\n {stale ? (\n <div\n role=\"status\"\n data-buro-flow-state=\"stale\"\n className=\"flex flex-wrap items-center gap-2 text-sm text-muted-foreground\"\n >\n <span>\n {t('flow.noLongerApplies', { defaultValue: 'This action no longer applies' })}\n </span>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"outline\"\n onClick={() => {\n flow.reset();\n setDiscarded(true);\n }}\n >\n {t('flow.discard', { defaultValue: 'Discard' })}\n </Button>\n </div>\n ) : null}\n {opened ? (\n <FlowHostBindingContext.Provider value={binding}>\n <fieldset disabled={stale} className=\"m-0 min-w-0 border-0 p-0\">\n <FlowScreen\n host=\"page\"\n run={run}\n compiled={compiled}\n label={chrome.labelText}\n {...(title === '' ? {} : { title })}\n record={record}\n />\n </fieldset>\n </FlowHostBindingContext.Provider>\n ) : refused ? (\n <p role=\"alert\" className=\"text-sm\">\n {snapshot.reason === undefined\n ? t('flow.unavailable', { defaultValue: 'Not allowed.' })\n : reasonText(caps, snapshot.reason, resource)}\n </p>\n ) : (\n <IconLoader2 className=\"h-5 w-5 animate-spin self-center\" aria-hidden=\"true\" />\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|