@burojs/ui-shadcn 0.6.0 → 0.8.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-2HLgz7Il.cjs +169 -0
- package/dist/bulk-summary-2HLgz7Il.cjs.map +1 -0
- package/dist/bulk-summary-D6A0ua21.js +169 -0
- package/dist/bulk-summary-D6A0ua21.js.map +1 -0
- package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-C47mF260.cjs} +4 -4
- package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-C47mF260.cjs.map} +1 -1
- package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CGXItMN0.js} +3 -3
- package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CGXItMN0.js.map} +1 -1
- package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-BT04Mieo.cjs} +475 -107
- package/dist/check-confirm-dialog-BT04Mieo.cjs.map +1 -0
- package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-CtiRzOAt.js} +391 -108
- package/dist/check-confirm-dialog-CtiRzOAt.js.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-nXqtM_h4.cjs → filter-builder-ByGhxLf_.cjs} +1021 -154
- package/dist/filter-builder-ByGhxLf_.cjs.map +1 -0
- package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-z3Axzf9Y.js} +929 -140
- package/dist/filter-builder-z3Axzf9Y.js.map +1 -0
- package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BVFjMU5-.cjs} +64 -29
- package/dist/flow-runtime-BVFjMU5-.cjs.map +1 -0
- package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DrUWyTS0.js} +65 -30
- package/dist/flow-runtime-DrUWyTS0.js.map +1 -0
- package/dist/{flow-screen-CCvgDI9G.js → flow-screen-3fk6J33y.js} +130 -87
- package/dist/flow-screen-3fk6J33y.js.map +1 -0
- package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-6y5E_HT6.cjs} +130 -87
- package/dist/flow-screen-6y5E_HT6.cjs.map +1 -0
- package/dist/index.cjs +1186 -950
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +631 -322
- package/dist/index.d.ts +631 -322
- package/dist/index.js +1100 -870
- package/dist/index.js.map +1 -1
- package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-C4KmZIYE.cjs} +5 -5
- package/dist/inline-flow-host-C4KmZIYE.cjs.map +1 -0
- package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-YnnvWjdU.js} +5 -5
- package/dist/inline-flow-host-YnnvWjdU.js.map +1 -0
- package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-BAKBRn3V.cjs} +10 -10
- package/dist/lazy-relation-picker-dialog-BAKBRn3V.cjs.map +1 -0
- package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-DN4bvQfg.js} +11 -11
- package/dist/lazy-relation-picker-dialog-DN4bvQfg.js.map +1 -0
- package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-CtEfqAvU.js} +35 -23
- package/dist/page-flow-route-CtEfqAvU.js.map +1 -0
- package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DEjAxHe3.cjs} +42 -30
- package/dist/page-flow-route-DEjAxHe3.cjs.map +1 -0
- package/dist/{place-node-NraNYKPx.js → place-node-BdxT-30h.js} +1980 -1041
- package/dist/place-node-BdxT-30h.js.map +1 -0
- package/dist/{place-node-C5SmIAYU.cjs → place-node-Bhl8B3fF.cjs} +2038 -1087
- package/dist/place-node-Bhl8B3fF.cjs.map +1 -0
- package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-Bc_vfCE_.cjs} +9 -4
- package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-Bc_vfCE_.cjs.map} +1 -1
- package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BvkD5OcC.js} +9 -4
- package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BvkD5OcC.js.map} +1 -1
- package/dist/related-list-timeline-DCrwN9oO.js +167 -0
- package/dist/related-list-timeline-DCrwN9oO.js.map +1 -0
- package/dist/related-list-timeline-k0DtnxTs.cjs +167 -0
- package/dist/related-list-timeline-k0DtnxTs.cjs.map +1 -0
- package/dist/{related-rows-ea43qhhy.cjs → related-rows-BW9Jr07T.cjs} +27 -16
- package/dist/related-rows-BW9Jr07T.cjs.map +1 -0
- package/dist/{related-rows-o0_t-Yce.js → related-rows-CPE-9FFr.js} +25 -14
- package/dist/related-rows-CPE-9FFr.js.map +1 -0
- package/dist/{search-access-CPPmfuvy.js → relation-create-C43cdPQt.js} +595 -13
- package/dist/relation-create-C43cdPQt.js.map +1 -0
- package/dist/{search-access-Dugvttlg.cjs → relation-create-DDEYcKfw.cjs} +633 -14
- package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
- package/dist/{relation-many-picker-bvkjkv-k.js → relation-many-picker-BlrGRwMV.js} +210 -104
- package/dist/relation-many-picker-BlrGRwMV.js.map +1 -0
- package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-Br-zBHxT.cjs} +218 -112
- package/dist/relation-many-picker-Br-zBHxT.cjs.map +1 -0
- package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-ADjxI_TI.cjs} +36 -73
- package/dist/relation-picker-ADjxI_TI.cjs.map +1 -0
- package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-CyKliBkN.js} +134 -36
- package/dist/relation-picker-dialog-CyKliBkN.js.map +1 -0
- package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-DimVQF9Y.cjs} +133 -35
- package/dist/relation-picker-dialog-DimVQF9Y.cjs.map +1 -0
- package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-x7P5HKie.js} +30 -61
- package/dist/relation-picker-x7P5HKie.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-3RUf9d1j.js → resource-page-router-BRpUnhay.js} +634 -264
- package/dist/resource-page-router-BRpUnhay.js.map +1 -0
- package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-qEd2xb55.cjs} +694 -312
- package/dist/resource-page-router-qEd2xb55.cjs.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-Cr51X7bz.cjs → toaster-BbByOytP.cjs} +60 -15
- package/dist/toaster-BbByOytP.cjs.map +1 -0
- package/dist/{toaster-C02XbB9r.js → toaster-Ct_YHGs6.js} +43 -16
- package/dist/toaster-Ct_YHGs6.js.map +1 -0
- package/dist/{use-dialog-filter-state-C--oMAZG.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-Dhe8PcB5.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
- package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
- package/dist/use-record-subtitle-bfwIoUme.cjs +70 -0
- package/dist/use-record-subtitle-bfwIoUme.cjs.map +1 -0
- package/dist/use-record-subtitle-gIaCGgbI.js +53 -0
- package/dist/use-record-subtitle-gIaCGgbI.js.map +1 -0
- 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-Bb70LPAy.js.map +0 -1
- package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
- package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
- package/dist/check-confirm-dialog-bRT8lt0d.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-Bhn-dhZV.js.map +0 -1
- package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
- package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
- package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
- package/dist/flow-screen-CCvgDI9G.js.map +0 -1
- package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
- package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
- package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
- package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
- package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
- package/dist/place-node-C5SmIAYU.cjs.map +0 -1
- package/dist/place-node-NraNYKPx.js.map +0 -1
- package/dist/related-list-timeline-CCzl71aA.cjs +0 -142
- package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
- package/dist/related-list-timeline-yrPsjA3F.js +0 -142
- package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
- package/dist/related-rows-ea43qhhy.cjs.map +0 -1
- package/dist/related-rows-o0_t-Yce.js.map +0 -1
- package/dist/relation-create-IA40t1hi.cjs +0 -364
- package/dist/relation-create-IA40t1hi.cjs.map +0 -1
- package/dist/relation-create-h6F9B4C4.js +0 -339
- package/dist/relation-create-h6F9B4C4.js.map +0 -1
- package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
- package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
- package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
- package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
- package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
- package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
- package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
- package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
- package/dist/search-access-CPPmfuvy.js.map +0 -1
- package/dist/search-access-Dugvttlg.cjs.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-C02XbB9r.js.map +0 -1
- package/dist/toaster-Cr51X7bz.cjs.map +0 -1
- package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
- package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -60,6 +60,14 @@ nav item, breadcrumb and framework navigation goes through it. Then give
|
|
|
60
60
|
only renders anchors. `RouterAdapterProvider`'s docblock has the react-router and
|
|
61
61
|
Next App Router adapters; `examples/vite` and `examples/next` mount them.
|
|
62
62
|
|
|
63
|
+
## Platform
|
|
64
|
+
|
|
65
|
+
`BuroProvider` takes the browser's behaviour (persistent storage, drafts, download, clipboard, the
|
|
66
|
+
⌘K shortcut, the leave-page guard) from one prop. This package re-exports the factory, so a web app
|
|
67
|
+
adds one line: `<BuroProvider app={app} platform={webPlatform()}>` with
|
|
68
|
+
`import { webPlatform } from '@burojs/ui-shadcn'`. See
|
|
69
|
+
[docs/platform-guide.md](../../docs/platform-guide.md).
|
|
70
|
+
|
|
63
71
|
## App shell
|
|
64
72
|
|
|
65
73
|
**→ [docs/app-shell-guide.md](../../docs/app-shell-guide.md)** covers
|
|
@@ -67,6 +75,7 @@ Next App Router adapters; `examples/vite` and `examples/next` mount them.
|
|
|
67
75
|
|
|
68
76
|
## What's included
|
|
69
77
|
|
|
78
|
+
- Navigation areas: `secondary-sidebar` and `tabs` groups work with no layout registration; `<AppShell>` mounts `<NavChrome>` (opt out with `navChrome={false}`), `<NavAreaPage>` renders the content, `defaultNavLayouts` is the optional table of the built-ins. See the [navigation guide](../../docs/navigation-guide.md)
|
|
70
79
|
- Layout: AppLayout, AppSidebar and AppHeader (each slot you omit gets its default — brand, `<NavMain />` and `<UserMenu />`; `<HeaderBreadcrumbs />`, the palette chip, app actions and refresh — and `false` empties it), Sidebar, Breadcrumbs, HeaderBreadcrumbs (the header trail of the current route)
|
|
71
80
|
- Auth: LoginForm
|
|
72
81
|
- Resource views: ResourceList, and `<RecordScreen resource mode recordId? …>` — a record's show, edit or create screen outside a route, in the built-in frame or in your own layout of its pieces (`RecordTitle`, `RecordActions`, `CopyId`, `FormActions`)
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const require_button = require("./button-BxnnE28H.cjs");
|
|
2
|
+
let _burojs_core = require("@burojs/core");
|
|
3
|
+
let _burojs_react = require("@burojs/react");
|
|
4
|
+
let react = require("react");
|
|
5
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
6
|
+
let _burojs_react_flows = require("@burojs/react/flows");
|
|
7
|
+
//#region src/flows/bulk-summary.tsx
|
|
8
|
+
function linesByText(entries) {
|
|
9
|
+
const lines = new Map();
|
|
10
|
+
for (const { id, text } of entries) {
|
|
11
|
+
const ids = lines.get(text);
|
|
12
|
+
if (ids === void 0) lines.set(text, [id]);
|
|
13
|
+
else ids.push(id);
|
|
14
|
+
}
|
|
15
|
+
return [...lines].map(([text, ids]) => ({
|
|
16
|
+
text,
|
|
17
|
+
ids
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
function FlowBulkSummary({ resource, actionName, label, total, progress, texts }) {
|
|
21
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
22
|
+
const caps = (0, _burojs_react.useI18nCaps)(resource);
|
|
23
|
+
const forget = (0, _burojs_react_flows.useForgetEachAttempt)({
|
|
24
|
+
resource,
|
|
25
|
+
action: actionName
|
|
26
|
+
});
|
|
27
|
+
const [forgotten, setForgotten] = (0, react.useState)(() => new Set());
|
|
28
|
+
const forgetText = t("flow.forget", { defaultValue: "I've checked — forget it" });
|
|
29
|
+
const testid = (0, _burojs_react.useTestIds)().bulkSummary(resource, actionName);
|
|
30
|
+
const own = `resources.${resource}.actions.${actionName}.summary`;
|
|
31
|
+
const count = progress.success.length;
|
|
32
|
+
const heading = caps.has(own, { count }) ? caps.t(own, {
|
|
33
|
+
params: { total },
|
|
34
|
+
count
|
|
35
|
+
}) : `${label}: ${t("flow.bulkSummary", {
|
|
36
|
+
defaultValue: `${count} processed`,
|
|
37
|
+
params: { total },
|
|
38
|
+
count
|
|
39
|
+
})} / ${total}`;
|
|
40
|
+
const place = { action: {
|
|
41
|
+
prefix: `resources.${resource}.actions.${actionName}`,
|
|
42
|
+
texts
|
|
43
|
+
} };
|
|
44
|
+
const textCaps = {
|
|
45
|
+
has: (key) => caps.has(key),
|
|
46
|
+
t: caps.t
|
|
47
|
+
};
|
|
48
|
+
const textOf = (error, fallback) => (error === void 0 ? void 0 : (0, _burojs_react.specificErrorText)(error, textCaps, place) ?? (0, _burojs_react.kindErrorText)(error.kind, textCaps, place)) ?? fallback();
|
|
49
|
+
const neutral = () => t("flow.rejected.validation", { defaultValue: "Not accepted. Nothing was saved." });
|
|
50
|
+
const gone = progress.rejected.filter((entry) => entry.reason === "gone");
|
|
51
|
+
const byCheck = new Map();
|
|
52
|
+
for (const entry of progress.rejected) {
|
|
53
|
+
if (entry.reason !== "check" || entry.check === void 0) continue;
|
|
54
|
+
const own = `checks.${entry.check}`;
|
|
55
|
+
const title = entry.message ?? (caps.has(own) ? caps.t(own) : entry.check);
|
|
56
|
+
const group = byCheck.get(entry.check);
|
|
57
|
+
if (group === void 0) byCheck.set(entry.check, {
|
|
58
|
+
check: entry.check,
|
|
59
|
+
title,
|
|
60
|
+
ids: [entry.id]
|
|
61
|
+
});
|
|
62
|
+
else group.ids.push(entry.id);
|
|
63
|
+
}
|
|
64
|
+
const checkGroups = [...byCheck.values()].map(({ check, title, ids }) => ({
|
|
65
|
+
key: `check:${check}`,
|
|
66
|
+
title,
|
|
67
|
+
lines: [{ ids }]
|
|
68
|
+
}));
|
|
69
|
+
const ownGone = `resources.${resource}.actions.${actionName}.rereadGone`;
|
|
70
|
+
const goneTitle = caps.has(ownGone) ? caps.t(ownGone) : (0, _burojs_core.declaredText)("flow", { texts }, "rereadGone") ?? t("flow.bulkGone", { defaultValue: "No longer available" });
|
|
71
|
+
const notApplied = [...progress.rejected.filter((entry) => entry.reason === "server").map((entry) => ({
|
|
72
|
+
id: entry.id,
|
|
73
|
+
text: textOf(entry.error, neutral)
|
|
74
|
+
})), ...progress.failed.map((entry) => ({
|
|
75
|
+
id: entry.id,
|
|
76
|
+
text: textOf(entry.error, () => entry.reason === "reread" ? t("flow.couldNotReread", { defaultValue: "Couldn't re-read the record. Nothing was sent." }) : t("flow.failed", { defaultValue: "The request could not be sent. Nothing was saved." }))
|
|
77
|
+
}))];
|
|
78
|
+
const unknown = progress.unknown.filter((entry) => !forgotten.has(entry.id)).map((entry) => ({
|
|
79
|
+
id: entry.id,
|
|
80
|
+
text: textOf(entry.error, () => entry.error?.applied === "partial" ? t("flow.unknownPartial", { defaultValue: "Part of this may have been applied. Nothing was resent." }) : t("flow.unknown", { defaultValue: "It may have been applied. Nothing was resent." }))
|
|
81
|
+
}));
|
|
82
|
+
const groups = [
|
|
83
|
+
...checkGroups,
|
|
84
|
+
{
|
|
85
|
+
key: "gone",
|
|
86
|
+
title: goneTitle,
|
|
87
|
+
lines: [{ ids: gone.map((entry) => entry.id) }]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
key: "reread-skipped",
|
|
91
|
+
title: t("flow.bulkSentWithoutReread", { defaultValue: "Sent without a current record" }),
|
|
92
|
+
lines: [{ ids: progress.rereadSkipped.filter((entry) => entry.policy === "warn").map((entry) => entry.id) }]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
key: "not-applied",
|
|
96
|
+
title: t("flow.bulkNotApplied", { defaultValue: "Not applied" }),
|
|
97
|
+
lines: linesByText(notApplied)
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
key: "unknown",
|
|
101
|
+
title: t("flow.bulkMayHaveBeenApplied", { defaultValue: "May have been applied" }),
|
|
102
|
+
lines: linesByText(unknown)
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: "unresolved",
|
|
106
|
+
title: t("flow.bulkUnresolved", { defaultValue: "Skipped: an earlier request for it may have been applied." }),
|
|
107
|
+
lines: [{ ids: progress.unresolved.filter((id) => !forgotten.has(id)) }]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
key: "not-attempted",
|
|
111
|
+
title: t("flow.bulkNotAttempted", { defaultValue: "Not attempted." }),
|
|
112
|
+
lines: [{ ids: progress.notAttempted }]
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
const sizeOf = (group) => group.lines.reduce((sum, line) => sum + line.ids.length, 0);
|
|
116
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
117
|
+
"data-testid": testid,
|
|
118
|
+
className: "flex flex-col gap-3 text-sm",
|
|
119
|
+
children: [(0, react_jsx_runtime.jsx)("p", {
|
|
120
|
+
"data-testid": `${testid}:heading`,
|
|
121
|
+
className: "font-medium",
|
|
122
|
+
children: heading
|
|
123
|
+
}), groups.filter((group) => sizeOf(group) > 0).map((group) => (0, react_jsx_runtime.jsxs)("section", {
|
|
124
|
+
"data-testid": `${testid}:${group.key}`,
|
|
125
|
+
children: [(0, react_jsx_runtime.jsxs)("h3", {
|
|
126
|
+
className: "font-medium",
|
|
127
|
+
children: [
|
|
128
|
+
group.title,
|
|
129
|
+
" ",
|
|
130
|
+
(0, react_jsx_runtime.jsxs)("span", {
|
|
131
|
+
"data-testid": `${testid}:${group.key}:count`,
|
|
132
|
+
className: "tabular-nums",
|
|
133
|
+
children: [
|
|
134
|
+
"(",
|
|
135
|
+
sizeOf(group),
|
|
136
|
+
")"
|
|
137
|
+
]
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
}), group.lines.map((line, index) => (0, react_jsx_runtime.jsxs)("div", {
|
|
141
|
+
"data-testid": line.text === void 0 ? void 0 : `${testid}:${group.key}:line`,
|
|
142
|
+
children: [line.text === void 0 ? null : (0, react_jsx_runtime.jsx)("p", { children: t("flow.bulkLine", {
|
|
143
|
+
defaultValue: `${line.ids.length}: ${line.text}`,
|
|
144
|
+
params: { message: line.text },
|
|
145
|
+
count: line.ids.length
|
|
146
|
+
}) }), (0, react_jsx_runtime.jsxs)("ul", {
|
|
147
|
+
className: "flex flex-wrap gap-1 text-muted-foreground",
|
|
148
|
+
children: [line.ids.slice(0, _burojs_core.BULK_SUMMARY_IDS).map((id) => (0, react_jsx_runtime.jsxs)("li", {
|
|
149
|
+
"data-testid": `${testid}:${group.key}:${id}`,
|
|
150
|
+
className: "flex items-center gap-1",
|
|
151
|
+
children: [id, group.key === "unknown" || group.key === "unresolved" ? (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
152
|
+
type: "button",
|
|
153
|
+
size: "sm",
|
|
154
|
+
variant: "ghost",
|
|
155
|
+
className: "h-6 px-1.5 text-xs",
|
|
156
|
+
"data-testid": `${testid}:forget:${id}`,
|
|
157
|
+
onClick: () => void forget(id).then(() => setForgotten((previous) => new Set([...previous, id]))),
|
|
158
|
+
children: forgetText
|
|
159
|
+
}) : null]
|
|
160
|
+
}, id)), line.ids.length > _burojs_core.BULK_SUMMARY_IDS ? (0, react_jsx_runtime.jsxs)("li", { children: ["+", line.ids.length - _burojs_core.BULK_SUMMARY_IDS] }) : null]
|
|
161
|
+
})]
|
|
162
|
+
}, line.text ?? index))]
|
|
163
|
+
}, group.key))]
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
exports.FlowBulkSummary = FlowBulkSummary;
|
|
168
|
+
|
|
169
|
+
//# sourceMappingURL=bulk-summary-2HLgz7Il.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulk-summary-2HLgz7Il.cjs","names":["useOptionalT","useI18nCaps","useForgetEachAttempt","useState","useTestIds","specificErrorText","kindErrorText","declaredText","BULK_SUMMARY_IDS","Button"],"sources":["../src/flows/bulk-summary.tsx"],"sourcesContent":["'use client';\nimport { BULK_SUMMARY_IDS, type BulkProgress, type DataError, declaredText } from '@burojs/core';\nimport {\n type ErrorTextPlace,\n kindErrorText,\n specificErrorText,\n useI18nCaps,\n useOptionalT,\n useTestIds,\n} from '@burojs/react';\nimport { useForgetEachAttempt } from '@burojs/react/flows';\nimport { type ReactElement, useState } from 'react';\nimport { Button } from '../primitives/button.js';\n\nexport interface FlowBulkSummaryProps {\n readonly resource: string;\n readonly actionName: string;\n /** The action's label. */\n readonly label: string;\n /** How many ids the run was given. */\n readonly total: number;\n readonly progress: BulkProgress;\n /** The action's declared texts (`texts.validation`, `texts.rejected`): the resolver's action place. */\n readonly texts?: unknown;\n}\n\n/** One line of a group: the ids that read the same text; `text` absent for a group without lines. */\ninterface SummaryLine {\n readonly text?: string;\n readonly ids: readonly string[];\n}\n\ninterface SummaryGroup {\n readonly key: string;\n readonly title: string;\n readonly lines: readonly SummaryLine[];\n}\n\n/** The ids by their text, in the order each text first appears. */\nfunction linesByText(entries: readonly { readonly id: string; readonly text: string }[]) {\n const lines = new Map<string, string[]>();\n for (const { id, text } of entries) {\n const ids = lines.get(text);\n if (ids === undefined) lines.set(text, [id]);\n else ids.push(id);\n }\n return [...lines].map(([text, ids]): SummaryLine => ({ text, ids }));\n}\n\n/**\n * A bulk flow's summary (P4 spec 4.16, T1 spec 4.17): the count that succeeded of the ids given\n * (the flow's own `resources.<r>.actions.<name>.summary`, `{{count}}` of `{{total}}`, else the\n * framework's count text), then one group per other outcome with its count and up to\n * `BULK_SUMMARY_IDS` ids per line. The ids the server answered for are grouped first by\n * `applied` — not applied (refused or failed) and may have been applied (unknown) — and then by\n * the text each one's error resolves to (spec 4.15, with the action as the place), so\n * \"3 records: Already linked\" and \"2 records: Not allowed\" are separate lines. A row a check\n * rejected is grouped under that check's resolved text (`checks.<id>`), a row that was gone under\n * the flow's `texts.rereadGone` else \"No longer available\", and a row sent without a re-read\n * (`rereadSkipped` under `warn`, even when every row succeeded) under its own group (REF-135 §2.3).\n * Unresolved from an earlier run and not attempted keep their own groups.\n * Every text resolves at render, so a language switch re-renders it.\n */\nexport function FlowBulkSummary({\n resource,\n actionName,\n label,\n total,\n progress,\n texts,\n}: FlowBulkSummaryProps): ReactElement {\n const t = useOptionalT();\n const caps = useI18nCaps(resource);\n // An id the run left unknown, or found unresolved, has its exit here (P4-C review I3): the user\n // checked the record, and the id's attempt is forgotten — the next run sends it again.\n const forget = useForgetEachAttempt({ resource, action: actionName });\n const [forgotten, setForgotten] = useState<ReadonlySet<string>>(() => new Set());\n const forgetText = t('flow.forget', { defaultValue: \"I've checked — forget it\" });\n const tid = useTestIds();\n const testid = tid.bulkSummary(resource, actionName);\n const own = `resources.${resource}.actions.${actionName}.summary`;\n const count = progress.success.length;\n const heading = caps.has(own, { count })\n ? caps.t(own, { params: { total }, count })\n : `${label}: ${t('flow.bulkSummary', { defaultValue: `${count} processed`, params: { total }, count })} / ${total}`;\n // A bulk flow is a resource's action: its texts live under `resources.<r>.actions.<name>`.\n const place: ErrorTextPlace = {\n action: { prefix: `resources.${resource}.actions.${actionName}`, texts },\n };\n const textCaps = { has: (key: string) => caps.has(key), t: caps.t };\n // Steps 1 to 5 of spec 4.15; the fallback is the outcome's own sentence.\n const textOf = (error: DataError | undefined, fallback: () => string): string =>\n (error === undefined\n ? undefined\n : (specificErrorText(error, textCaps, place) ??\n kindErrorText(error.kind, textCaps, place))) ?? fallback();\n const neutral = () =>\n t('flow.rejected.validation', { defaultValue: 'Not accepted. Nothing was saved.' });\n const gone = progress.rejected.filter((entry) => entry.reason === 'gone');\n // One group per check, in the order each first appears, headed by the first entry's text. The machine resolved the\n // text (bundle entry, the check's declared `texts`, the framework's sentence); an entry without\n // it reads the check's `checks.<id>` bundle entry, else names the check.\n const byCheck = new Map<string, { check: string; title: string; ids: string[] }>();\n for (const entry of progress.rejected) {\n if (entry.reason !== 'check' || entry.check === undefined) continue;\n const own = `checks.${entry.check}`;\n const title = entry.message ?? (caps.has(own) ? caps.t(own) : entry.check);\n const group = byCheck.get(entry.check);\n if (group === undefined)\n byCheck.set(entry.check, { check: entry.check, title, ids: [entry.id] });\n else group.ids.push(entry.id);\n }\n const checkGroups = [...byCheck.values()].map(\n ({ check, title, ids }): SummaryGroup => ({ key: `check:${check}`, title, lines: [{ ids }] }),\n );\n const ownGone = `resources.${resource}.actions.${actionName}.rereadGone`;\n const goneTitle = caps.has(ownGone)\n ? caps.t(ownGone)\n : (declaredText('flow', { texts }, 'rereadGone') ??\n t('flow.bulkGone', { defaultValue: 'No longer available' }));\n const notApplied = [\n ...progress.rejected\n .filter((entry) => entry.reason === 'server')\n .map((entry) => ({ id: entry.id, text: textOf(entry.error, neutral) })),\n ...progress.failed.map((entry) => ({\n id: entry.id,\n text: textOf(entry.error, () =>\n entry.reason === 'reread'\n ? t('flow.couldNotReread', {\n defaultValue: \"Couldn't re-read the record. Nothing was sent.\",\n })\n : t('flow.failed', {\n defaultValue: 'The request could not be sent. Nothing was saved.',\n }),\n ),\n })),\n ];\n const unknown = progress.unknown\n .filter((entry) => !forgotten.has(entry.id))\n .map((entry) => ({\n id: entry.id,\n text: textOf(entry.error, () =>\n entry.error?.applied === 'partial'\n ? t('flow.unknownPartial', {\n defaultValue: 'Part of this may have been applied. Nothing was resent.',\n })\n : t('flow.unknown', { defaultValue: 'It may have been applied. Nothing was resent.' }),\n ),\n }));\n const groups: readonly SummaryGroup[] = [\n ...checkGroups,\n { key: 'gone', title: goneTitle, lines: [{ ids: gone.map((entry) => entry.id) }] },\n {\n key: 'reread-skipped',\n title: t('flow.bulkSentWithoutReread', { defaultValue: 'Sent without a current record' }),\n lines: [\n {\n ids: progress.rereadSkipped\n .filter((entry) => entry.policy === 'warn')\n .map((entry) => entry.id),\n },\n ],\n },\n {\n key: 'not-applied',\n title: t('flow.bulkNotApplied', { defaultValue: 'Not applied' }),\n lines: linesByText(notApplied),\n },\n {\n key: 'unknown',\n title: t('flow.bulkMayHaveBeenApplied', { defaultValue: 'May have been applied' }),\n lines: linesByText(unknown),\n },\n {\n key: 'unresolved',\n title: t('flow.bulkUnresolved', {\n defaultValue: 'Skipped: an earlier request for it may have been applied.',\n }),\n lines: [{ ids: progress.unresolved.filter((id) => !forgotten.has(id)) }],\n },\n {\n key: 'not-attempted',\n title: t('flow.bulkNotAttempted', { defaultValue: 'Not attempted.' }),\n lines: [{ ids: progress.notAttempted }],\n },\n ];\n const sizeOf = (group: SummaryGroup) =>\n group.lines.reduce((sum, line) => sum + line.ids.length, 0);\n return (\n <div data-testid={testid} className=\"flex flex-col gap-3 text-sm\">\n <p data-testid={`${testid}:heading`} className=\"font-medium\">\n {heading}\n </p>\n {groups\n .filter((group) => sizeOf(group) > 0)\n .map((group) => (\n <section key={group.key} data-testid={`${testid}:${group.key}`}>\n <h3 className=\"font-medium\">\n {group.title}{' '}\n <span data-testid={`${testid}:${group.key}:count`} className=\"tabular-nums\">\n ({sizeOf(group)})\n </span>\n </h3>\n {group.lines.map((line, index) => (\n <div\n key={line.text ?? index}\n data-testid={line.text === undefined ? undefined : `${testid}:${group.key}:line`}\n >\n {line.text === undefined ? null : (\n <p>\n {t('flow.bulkLine', {\n defaultValue: `${line.ids.length}: ${line.text}`,\n params: { message: line.text },\n count: line.ids.length,\n })}\n </p>\n )}\n <ul className=\"flex flex-wrap gap-1 text-muted-foreground\">\n {line.ids.slice(0, BULK_SUMMARY_IDS).map((id) => (\n <li\n key={id}\n data-testid={`${testid}:${group.key}:${id}`}\n className=\"flex items-center gap-1\"\n >\n {id}\n {group.key === 'unknown' || group.key === 'unresolved' ? (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-6 px-1.5 text-xs\"\n data-testid={`${testid}:forget:${id}`}\n onClick={() =>\n void forget(id).then(() =>\n setForgotten((previous) => new Set([...previous, id])),\n )\n }\n >\n {forgetText}\n </Button>\n ) : null}\n </li>\n ))}\n {line.ids.length > BULK_SUMMARY_IDS ? (\n <li>+{line.ids.length - BULK_SUMMARY_IDS}</li>\n ) : null}\n </ul>\n </div>\n ))}\n </section>\n ))}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { t as Button } from "./button-MWVeZaqj.js";
|
|
2
|
+
import { BULK_SUMMARY_IDS, declaredText } from "@burojs/core";
|
|
3
|
+
import { kindErrorText, specificErrorText, useI18nCaps, useOptionalT, useTestIds } from "@burojs/react";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { useForgetEachAttempt } from "@burojs/react/flows";
|
|
7
|
+
//#region src/flows/bulk-summary.tsx
|
|
8
|
+
function linesByText(entries) {
|
|
9
|
+
const lines = new Map();
|
|
10
|
+
for (const { id, text } of entries) {
|
|
11
|
+
const ids = lines.get(text);
|
|
12
|
+
if (ids === void 0) lines.set(text, [id]);
|
|
13
|
+
else ids.push(id);
|
|
14
|
+
}
|
|
15
|
+
return [...lines].map(([text, ids]) => ({
|
|
16
|
+
text,
|
|
17
|
+
ids
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
function FlowBulkSummary({ resource, actionName, label, total, progress, texts }) {
|
|
21
|
+
const t = useOptionalT();
|
|
22
|
+
const caps = useI18nCaps(resource);
|
|
23
|
+
const forget = useForgetEachAttempt({
|
|
24
|
+
resource,
|
|
25
|
+
action: actionName
|
|
26
|
+
});
|
|
27
|
+
const [forgotten, setForgotten] = useState(() => new Set());
|
|
28
|
+
const forgetText = t("flow.forget", { defaultValue: "I've checked — forget it" });
|
|
29
|
+
const testid = useTestIds().bulkSummary(resource, actionName);
|
|
30
|
+
const own = `resources.${resource}.actions.${actionName}.summary`;
|
|
31
|
+
const count = progress.success.length;
|
|
32
|
+
const heading = caps.has(own, { count }) ? caps.t(own, {
|
|
33
|
+
params: { total },
|
|
34
|
+
count
|
|
35
|
+
}) : `${label}: ${t("flow.bulkSummary", {
|
|
36
|
+
defaultValue: `${count} processed`,
|
|
37
|
+
params: { total },
|
|
38
|
+
count
|
|
39
|
+
})} / ${total}`;
|
|
40
|
+
const place = { action: {
|
|
41
|
+
prefix: `resources.${resource}.actions.${actionName}`,
|
|
42
|
+
texts
|
|
43
|
+
} };
|
|
44
|
+
const textCaps = {
|
|
45
|
+
has: (key) => caps.has(key),
|
|
46
|
+
t: caps.t
|
|
47
|
+
};
|
|
48
|
+
const textOf = (error, fallback) => (error === void 0 ? void 0 : specificErrorText(error, textCaps, place) ?? kindErrorText(error.kind, textCaps, place)) ?? fallback();
|
|
49
|
+
const neutral = () => t("flow.rejected.validation", { defaultValue: "Not accepted. Nothing was saved." });
|
|
50
|
+
const gone = progress.rejected.filter((entry) => entry.reason === "gone");
|
|
51
|
+
const byCheck = new Map();
|
|
52
|
+
for (const entry of progress.rejected) {
|
|
53
|
+
if (entry.reason !== "check" || entry.check === void 0) continue;
|
|
54
|
+
const own = `checks.${entry.check}`;
|
|
55
|
+
const title = entry.message ?? (caps.has(own) ? caps.t(own) : entry.check);
|
|
56
|
+
const group = byCheck.get(entry.check);
|
|
57
|
+
if (group === void 0) byCheck.set(entry.check, {
|
|
58
|
+
check: entry.check,
|
|
59
|
+
title,
|
|
60
|
+
ids: [entry.id]
|
|
61
|
+
});
|
|
62
|
+
else group.ids.push(entry.id);
|
|
63
|
+
}
|
|
64
|
+
const checkGroups = [...byCheck.values()].map(({ check, title, ids }) => ({
|
|
65
|
+
key: `check:${check}`,
|
|
66
|
+
title,
|
|
67
|
+
lines: [{ ids }]
|
|
68
|
+
}));
|
|
69
|
+
const ownGone = `resources.${resource}.actions.${actionName}.rereadGone`;
|
|
70
|
+
const goneTitle = caps.has(ownGone) ? caps.t(ownGone) : declaredText("flow", { texts }, "rereadGone") ?? t("flow.bulkGone", { defaultValue: "No longer available" });
|
|
71
|
+
const notApplied = [...progress.rejected.filter((entry) => entry.reason === "server").map((entry) => ({
|
|
72
|
+
id: entry.id,
|
|
73
|
+
text: textOf(entry.error, neutral)
|
|
74
|
+
})), ...progress.failed.map((entry) => ({
|
|
75
|
+
id: entry.id,
|
|
76
|
+
text: textOf(entry.error, () => entry.reason === "reread" ? t("flow.couldNotReread", { defaultValue: "Couldn't re-read the record. Nothing was sent." }) : t("flow.failed", { defaultValue: "The request could not be sent. Nothing was saved." }))
|
|
77
|
+
}))];
|
|
78
|
+
const unknown = progress.unknown.filter((entry) => !forgotten.has(entry.id)).map((entry) => ({
|
|
79
|
+
id: entry.id,
|
|
80
|
+
text: textOf(entry.error, () => entry.error?.applied === "partial" ? t("flow.unknownPartial", { defaultValue: "Part of this may have been applied. Nothing was resent." }) : t("flow.unknown", { defaultValue: "It may have been applied. Nothing was resent." }))
|
|
81
|
+
}));
|
|
82
|
+
const groups = [
|
|
83
|
+
...checkGroups,
|
|
84
|
+
{
|
|
85
|
+
key: "gone",
|
|
86
|
+
title: goneTitle,
|
|
87
|
+
lines: [{ ids: gone.map((entry) => entry.id) }]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
key: "reread-skipped",
|
|
91
|
+
title: t("flow.bulkSentWithoutReread", { defaultValue: "Sent without a current record" }),
|
|
92
|
+
lines: [{ ids: progress.rereadSkipped.filter((entry) => entry.policy === "warn").map((entry) => entry.id) }]
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
key: "not-applied",
|
|
96
|
+
title: t("flow.bulkNotApplied", { defaultValue: "Not applied" }),
|
|
97
|
+
lines: linesByText(notApplied)
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
key: "unknown",
|
|
101
|
+
title: t("flow.bulkMayHaveBeenApplied", { defaultValue: "May have been applied" }),
|
|
102
|
+
lines: linesByText(unknown)
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: "unresolved",
|
|
106
|
+
title: t("flow.bulkUnresolved", { defaultValue: "Skipped: an earlier request for it may have been applied." }),
|
|
107
|
+
lines: [{ ids: progress.unresolved.filter((id) => !forgotten.has(id)) }]
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
key: "not-attempted",
|
|
111
|
+
title: t("flow.bulkNotAttempted", { defaultValue: "Not attempted." }),
|
|
112
|
+
lines: [{ ids: progress.notAttempted }]
|
|
113
|
+
}
|
|
114
|
+
];
|
|
115
|
+
const sizeOf = (group) => group.lines.reduce((sum, line) => sum + line.ids.length, 0);
|
|
116
|
+
return jsxs("div", {
|
|
117
|
+
"data-testid": testid,
|
|
118
|
+
className: "flex flex-col gap-3 text-sm",
|
|
119
|
+
children: [jsx("p", {
|
|
120
|
+
"data-testid": `${testid}:heading`,
|
|
121
|
+
className: "font-medium",
|
|
122
|
+
children: heading
|
|
123
|
+
}), groups.filter((group) => sizeOf(group) > 0).map((group) => jsxs("section", {
|
|
124
|
+
"data-testid": `${testid}:${group.key}`,
|
|
125
|
+
children: [jsxs("h3", {
|
|
126
|
+
className: "font-medium",
|
|
127
|
+
children: [
|
|
128
|
+
group.title,
|
|
129
|
+
" ",
|
|
130
|
+
jsxs("span", {
|
|
131
|
+
"data-testid": `${testid}:${group.key}:count`,
|
|
132
|
+
className: "tabular-nums",
|
|
133
|
+
children: [
|
|
134
|
+
"(",
|
|
135
|
+
sizeOf(group),
|
|
136
|
+
")"
|
|
137
|
+
]
|
|
138
|
+
})
|
|
139
|
+
]
|
|
140
|
+
}), group.lines.map((line, index) => jsxs("div", {
|
|
141
|
+
"data-testid": line.text === void 0 ? void 0 : `${testid}:${group.key}:line`,
|
|
142
|
+
children: [line.text === void 0 ? null : jsx("p", { children: t("flow.bulkLine", {
|
|
143
|
+
defaultValue: `${line.ids.length}: ${line.text}`,
|
|
144
|
+
params: { message: line.text },
|
|
145
|
+
count: line.ids.length
|
|
146
|
+
}) }), jsxs("ul", {
|
|
147
|
+
className: "flex flex-wrap gap-1 text-muted-foreground",
|
|
148
|
+
children: [line.ids.slice(0, BULK_SUMMARY_IDS).map((id) => jsxs("li", {
|
|
149
|
+
"data-testid": `${testid}:${group.key}:${id}`,
|
|
150
|
+
className: "flex items-center gap-1",
|
|
151
|
+
children: [id, group.key === "unknown" || group.key === "unresolved" ? jsx(Button, {
|
|
152
|
+
type: "button",
|
|
153
|
+
size: "sm",
|
|
154
|
+
variant: "ghost",
|
|
155
|
+
className: "h-6 px-1.5 text-xs",
|
|
156
|
+
"data-testid": `${testid}:forget:${id}`,
|
|
157
|
+
onClick: () => void forget(id).then(() => setForgotten((previous) => new Set([...previous, id]))),
|
|
158
|
+
children: forgetText
|
|
159
|
+
}) : null]
|
|
160
|
+
}, id)), line.ids.length > BULK_SUMMARY_IDS ? jsxs("li", { children: ["+", line.ids.length - BULK_SUMMARY_IDS] }) : null]
|
|
161
|
+
})]
|
|
162
|
+
}, line.text ?? index))]
|
|
163
|
+
}, group.key))]
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
//#endregion
|
|
167
|
+
export { FlowBulkSummary };
|
|
168
|
+
|
|
169
|
+
//# sourceMappingURL=bulk-summary-D6A0ua21.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bulk-summary-D6A0ua21.js","names":[],"sources":["../src/flows/bulk-summary.tsx"],"sourcesContent":["'use client';\nimport { BULK_SUMMARY_IDS, type BulkProgress, type DataError, declaredText } from '@burojs/core';\nimport {\n type ErrorTextPlace,\n kindErrorText,\n specificErrorText,\n useI18nCaps,\n useOptionalT,\n useTestIds,\n} from '@burojs/react';\nimport { useForgetEachAttempt } from '@burojs/react/flows';\nimport { type ReactElement, useState } from 'react';\nimport { Button } from '../primitives/button.js';\n\nexport interface FlowBulkSummaryProps {\n readonly resource: string;\n readonly actionName: string;\n /** The action's label. */\n readonly label: string;\n /** How many ids the run was given. */\n readonly total: number;\n readonly progress: BulkProgress;\n /** The action's declared texts (`texts.validation`, `texts.rejected`): the resolver's action place. */\n readonly texts?: unknown;\n}\n\n/** One line of a group: the ids that read the same text; `text` absent for a group without lines. */\ninterface SummaryLine {\n readonly text?: string;\n readonly ids: readonly string[];\n}\n\ninterface SummaryGroup {\n readonly key: string;\n readonly title: string;\n readonly lines: readonly SummaryLine[];\n}\n\n/** The ids by their text, in the order each text first appears. */\nfunction linesByText(entries: readonly { readonly id: string; readonly text: string }[]) {\n const lines = new Map<string, string[]>();\n for (const { id, text } of entries) {\n const ids = lines.get(text);\n if (ids === undefined) lines.set(text, [id]);\n else ids.push(id);\n }\n return [...lines].map(([text, ids]): SummaryLine => ({ text, ids }));\n}\n\n/**\n * A bulk flow's summary (P4 spec 4.16, T1 spec 4.17): the count that succeeded of the ids given\n * (the flow's own `resources.<r>.actions.<name>.summary`, `{{count}}` of `{{total}}`, else the\n * framework's count text), then one group per other outcome with its count and up to\n * `BULK_SUMMARY_IDS` ids per line. The ids the server answered for are grouped first by\n * `applied` — not applied (refused or failed) and may have been applied (unknown) — and then by\n * the text each one's error resolves to (spec 4.15, with the action as the place), so\n * \"3 records: Already linked\" and \"2 records: Not allowed\" are separate lines. A row a check\n * rejected is grouped under that check's resolved text (`checks.<id>`), a row that was gone under\n * the flow's `texts.rereadGone` else \"No longer available\", and a row sent without a re-read\n * (`rereadSkipped` under `warn`, even when every row succeeded) under its own group (REF-135 §2.3).\n * Unresolved from an earlier run and not attempted keep their own groups.\n * Every text resolves at render, so a language switch re-renders it.\n */\nexport function FlowBulkSummary({\n resource,\n actionName,\n label,\n total,\n progress,\n texts,\n}: FlowBulkSummaryProps): ReactElement {\n const t = useOptionalT();\n const caps = useI18nCaps(resource);\n // An id the run left unknown, or found unresolved, has its exit here (P4-C review I3): the user\n // checked the record, and the id's attempt is forgotten — the next run sends it again.\n const forget = useForgetEachAttempt({ resource, action: actionName });\n const [forgotten, setForgotten] = useState<ReadonlySet<string>>(() => new Set());\n const forgetText = t('flow.forget', { defaultValue: \"I've checked — forget it\" });\n const tid = useTestIds();\n const testid = tid.bulkSummary(resource, actionName);\n const own = `resources.${resource}.actions.${actionName}.summary`;\n const count = progress.success.length;\n const heading = caps.has(own, { count })\n ? caps.t(own, { params: { total }, count })\n : `${label}: ${t('flow.bulkSummary', { defaultValue: `${count} processed`, params: { total }, count })} / ${total}`;\n // A bulk flow is a resource's action: its texts live under `resources.<r>.actions.<name>`.\n const place: ErrorTextPlace = {\n action: { prefix: `resources.${resource}.actions.${actionName}`, texts },\n };\n const textCaps = { has: (key: string) => caps.has(key), t: caps.t };\n // Steps 1 to 5 of spec 4.15; the fallback is the outcome's own sentence.\n const textOf = (error: DataError | undefined, fallback: () => string): string =>\n (error === undefined\n ? undefined\n : (specificErrorText(error, textCaps, place) ??\n kindErrorText(error.kind, textCaps, place))) ?? fallback();\n const neutral = () =>\n t('flow.rejected.validation', { defaultValue: 'Not accepted. Nothing was saved.' });\n const gone = progress.rejected.filter((entry) => entry.reason === 'gone');\n // One group per check, in the order each first appears, headed by the first entry's text. The machine resolved the\n // text (bundle entry, the check's declared `texts`, the framework's sentence); an entry without\n // it reads the check's `checks.<id>` bundle entry, else names the check.\n const byCheck = new Map<string, { check: string; title: string; ids: string[] }>();\n for (const entry of progress.rejected) {\n if (entry.reason !== 'check' || entry.check === undefined) continue;\n const own = `checks.${entry.check}`;\n const title = entry.message ?? (caps.has(own) ? caps.t(own) : entry.check);\n const group = byCheck.get(entry.check);\n if (group === undefined)\n byCheck.set(entry.check, { check: entry.check, title, ids: [entry.id] });\n else group.ids.push(entry.id);\n }\n const checkGroups = [...byCheck.values()].map(\n ({ check, title, ids }): SummaryGroup => ({ key: `check:${check}`, title, lines: [{ ids }] }),\n );\n const ownGone = `resources.${resource}.actions.${actionName}.rereadGone`;\n const goneTitle = caps.has(ownGone)\n ? caps.t(ownGone)\n : (declaredText('flow', { texts }, 'rereadGone') ??\n t('flow.bulkGone', { defaultValue: 'No longer available' }));\n const notApplied = [\n ...progress.rejected\n .filter((entry) => entry.reason === 'server')\n .map((entry) => ({ id: entry.id, text: textOf(entry.error, neutral) })),\n ...progress.failed.map((entry) => ({\n id: entry.id,\n text: textOf(entry.error, () =>\n entry.reason === 'reread'\n ? t('flow.couldNotReread', {\n defaultValue: \"Couldn't re-read the record. Nothing was sent.\",\n })\n : t('flow.failed', {\n defaultValue: 'The request could not be sent. Nothing was saved.',\n }),\n ),\n })),\n ];\n const unknown = progress.unknown\n .filter((entry) => !forgotten.has(entry.id))\n .map((entry) => ({\n id: entry.id,\n text: textOf(entry.error, () =>\n entry.error?.applied === 'partial'\n ? t('flow.unknownPartial', {\n defaultValue: 'Part of this may have been applied. Nothing was resent.',\n })\n : t('flow.unknown', { defaultValue: 'It may have been applied. Nothing was resent.' }),\n ),\n }));\n const groups: readonly SummaryGroup[] = [\n ...checkGroups,\n { key: 'gone', title: goneTitle, lines: [{ ids: gone.map((entry) => entry.id) }] },\n {\n key: 'reread-skipped',\n title: t('flow.bulkSentWithoutReread', { defaultValue: 'Sent without a current record' }),\n lines: [\n {\n ids: progress.rereadSkipped\n .filter((entry) => entry.policy === 'warn')\n .map((entry) => entry.id),\n },\n ],\n },\n {\n key: 'not-applied',\n title: t('flow.bulkNotApplied', { defaultValue: 'Not applied' }),\n lines: linesByText(notApplied),\n },\n {\n key: 'unknown',\n title: t('flow.bulkMayHaveBeenApplied', { defaultValue: 'May have been applied' }),\n lines: linesByText(unknown),\n },\n {\n key: 'unresolved',\n title: t('flow.bulkUnresolved', {\n defaultValue: 'Skipped: an earlier request for it may have been applied.',\n }),\n lines: [{ ids: progress.unresolved.filter((id) => !forgotten.has(id)) }],\n },\n {\n key: 'not-attempted',\n title: t('flow.bulkNotAttempted', { defaultValue: 'Not attempted.' }),\n lines: [{ ids: progress.notAttempted }],\n },\n ];\n const sizeOf = (group: SummaryGroup) =>\n group.lines.reduce((sum, line) => sum + line.ids.length, 0);\n return (\n <div data-testid={testid} className=\"flex flex-col gap-3 text-sm\">\n <p data-testid={`${testid}:heading`} className=\"font-medium\">\n {heading}\n </p>\n {groups\n .filter((group) => sizeOf(group) > 0)\n .map((group) => (\n <section key={group.key} data-testid={`${testid}:${group.key}`}>\n <h3 className=\"font-medium\">\n {group.title}{' '}\n <span data-testid={`${testid}:${group.key}:count`} className=\"tabular-nums\">\n ({sizeOf(group)})\n </span>\n </h3>\n {group.lines.map((line, index) => (\n <div\n key={line.text ?? index}\n data-testid={line.text === undefined ? undefined : `${testid}:${group.key}:line`}\n >\n {line.text === undefined ? null : (\n <p>\n {t('flow.bulkLine', {\n defaultValue: `${line.ids.length}: ${line.text}`,\n params: { message: line.text },\n count: line.ids.length,\n })}\n </p>\n )}\n <ul className=\"flex flex-wrap gap-1 text-muted-foreground\">\n {line.ids.slice(0, BULK_SUMMARY_IDS).map((id) => (\n <li\n key={id}\n data-testid={`${testid}:${group.key}:${id}`}\n className=\"flex items-center gap-1\"\n >\n {id}\n {group.key === 'unknown' || group.key === 'unresolved' ? (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n className=\"h-6 px-1.5 text-xs\"\n data-testid={`${testid}:forget:${id}`}\n onClick={() =>\n void forget(id).then(() =>\n setForgotten((previous) => new Set([...previous, id])),\n )\n }\n >\n {forgetText}\n </Button>\n ) : null}\n </li>\n ))}\n {line.ids.length > BULK_SUMMARY_IDS ? (\n <li>+{line.ids.length - BULK_SUMMARY_IDS}</li>\n ) : null}\n </ul>\n </div>\n ))}\n </section>\n ))}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAuCA,SAAS,YAAY,SAAoE;CACvF,MAAM,QAAQ,IAAI,IAAsB;CACxC,KAAK,MAAM,EAAE,IAAI,UAAU,SAAS;EAClC,MAAM,MAAM,MAAM,IAAI,IAAI;EAC1B,IAAI,QAAQ,KAAA,GAAW,MAAM,IAAI,MAAM,CAAC,EAAE,CAAC;OACtC,IAAI,KAAK,EAAE;CAClB;CACA,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,UAAuB;EAAE;EAAM;CAAI,EAAE;AACrE;AAgBA,SAAgB,gBAAgB,EAC9B,UACA,YACA,OACA,OACA,UACA,SACqC;CACrC,MAAM,IAAI,aAAa;CACvB,MAAM,OAAO,YAAY,QAAQ;CAGjC,MAAM,SAAS,qBAAqB;EAAE;EAAU,QAAQ;CAAW,CAAC;CACpE,MAAM,CAAC,WAAW,gBAAgB,eAAoC,IAAI,IAAI,CAAC;CAC/E,MAAM,aAAa,EAAE,eAAe,EAAE,cAAc,2BAA2B,CAAC;CAEhF,MAAM,SADM,WACK,CAAC,CAAC,YAAY,UAAU,UAAU;CACnD,MAAM,MAAM,aAAa,SAAS,WAAW,WAAW;CACxD,MAAM,QAAQ,SAAS,QAAQ;CAC/B,MAAM,UAAU,KAAK,IAAI,KAAK,EAAE,MAAM,CAAC,IACnC,KAAK,EAAE,KAAK;EAAE,QAAQ,EAAE,MAAM;EAAG;CAAM,CAAC,IACxC,GAAG,MAAM,IAAI,EAAE,oBAAoB;EAAE,cAAc,GAAG,MAAM;EAAa,QAAQ,EAAE,MAAM;EAAG;CAAM,CAAC,EAAE,KAAK;CAE9G,MAAM,QAAwB,EAC5B,QAAQ;EAAE,QAAQ,aAAa,SAAS,WAAW;EAAc;CAAM,EACzE;CACA,MAAM,WAAW;EAAE,MAAM,QAAgB,KAAK,IAAI,GAAG;EAAG,GAAG,KAAK;CAAE;CAElE,MAAM,UAAU,OAA8B,cAC3C,UAAU,KAAA,IACP,KAAA,IACC,kBAAkB,OAAO,UAAU,KAAK,KACzC,cAAc,MAAM,MAAM,UAAU,KAAK,MAAO,SAAS;CAC/D,MAAM,gBACJ,EAAE,4BAA4B,EAAE,cAAc,mCAAmC,CAAC;CACpF,MAAM,OAAO,SAAS,SAAS,QAAQ,UAAU,MAAM,WAAW,MAAM;CAIxE,MAAM,UAAU,IAAI,IAA6D;CACjF,KAAK,MAAM,SAAS,SAAS,UAAU;EACrC,IAAI,MAAM,WAAW,WAAW,MAAM,UAAU,KAAA,GAAW;EAC3D,MAAM,MAAM,UAAU,MAAM;EAC5B,MAAM,QAAQ,MAAM,YAAY,KAAK,IAAI,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,MAAM;EACpE,MAAM,QAAQ,QAAQ,IAAI,MAAM,KAAK;EACrC,IAAI,UAAU,KAAA,GACZ,QAAQ,IAAI,MAAM,OAAO;GAAE,OAAO,MAAM;GAAO;GAAO,KAAK,CAAC,MAAM,EAAE;EAAE,CAAC;OACpE,MAAM,IAAI,KAAK,MAAM,EAAE;CAC9B;CACA,MAAM,cAAc,CAAC,GAAG,QAAQ,OAAO,CAAC,CAAC,CAAC,KACvC,EAAE,OAAO,OAAO,WAAyB;EAAE,KAAK,SAAS;EAAS;EAAO,OAAO,CAAC,EAAE,IAAI,CAAC;CAAE,EAC7F;CACA,MAAM,UAAU,aAAa,SAAS,WAAW,WAAW;CAC5D,MAAM,YAAY,KAAK,IAAI,OAAO,IAC9B,KAAK,EAAE,OAAO,IACb,aAAa,QAAQ,EAAE,MAAM,GAAG,YAAY,KAC7C,EAAE,iBAAiB,EAAE,cAAc,sBAAsB,CAAC;CAC9D,MAAM,aAAa,CACjB,GAAG,SAAS,SACT,QAAQ,UAAU,MAAM,WAAW,QAAQ,CAAC,CAC5C,KAAK,WAAW;EAAE,IAAI,MAAM;EAAI,MAAM,OAAO,MAAM,OAAO,OAAO;CAAE,EAAE,GACxE,GAAG,SAAS,OAAO,KAAK,WAAW;EACjC,IAAI,MAAM;EACV,MAAM,OAAO,MAAM,aACjB,MAAM,WAAW,WACb,EAAE,uBAAuB,EACvB,cAAc,iDAChB,CAAC,IACD,EAAE,eAAe,EACf,cAAc,oDAChB,CAAC,CACP;CACF,EAAE,CACJ;CACA,MAAM,UAAU,SAAS,QACtB,QAAQ,UAAU,CAAC,UAAU,IAAI,MAAM,EAAE,CAAC,CAAC,CAC3C,KAAK,WAAW;EACf,IAAI,MAAM;EACV,MAAM,OAAO,MAAM,aACjB,MAAM,OAAO,YAAY,YACrB,EAAE,uBAAuB,EACvB,cAAc,0DAChB,CAAC,IACD,EAAE,gBAAgB,EAAE,cAAc,gDAAgD,CAAC,CACzF;CACF,EAAE;CACJ,MAAM,SAAkC;EACtC,GAAG;EACH;GAAE,KAAK;GAAQ,OAAO;GAAW,OAAO,CAAC,EAAE,KAAK,KAAK,KAAK,UAAU,MAAM,EAAE,EAAE,CAAC;EAAE;EACjF;GACE,KAAK;GACL,OAAO,EAAE,8BAA8B,EAAE,cAAc,gCAAgC,CAAC;GACxF,OAAO,CACL,EACE,KAAK,SAAS,cACX,QAAQ,UAAU,MAAM,WAAW,MAAM,CAAC,CAC1C,KAAK,UAAU,MAAM,EAAE,EAC5B,CACF;EACF;EACA;GACE,KAAK;GACL,OAAO,EAAE,uBAAuB,EAAE,cAAc,cAAc,CAAC;GAC/D,OAAO,YAAY,UAAU;EAC/B;EACA;GACE,KAAK;GACL,OAAO,EAAE,+BAA+B,EAAE,cAAc,wBAAwB,CAAC;GACjF,OAAO,YAAY,OAAO;EAC5B;EACA;GACE,KAAK;GACL,OAAO,EAAE,uBAAuB,EAC9B,cAAc,4DAChB,CAAC;GACD,OAAO,CAAC,EAAE,KAAK,SAAS,WAAW,QAAQ,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC,EAAE,CAAC;EACzE;EACA;GACE,KAAK;GACL,OAAO,EAAE,yBAAyB,EAAE,cAAc,iBAAiB,CAAC;GACpE,OAAO,CAAC,EAAE,KAAK,SAAS,aAAa,CAAC;EACxC;CACF;CACA,MAAM,UAAU,UACd,MAAM,MAAM,QAAQ,KAAK,SAAS,MAAM,KAAK,IAAI,QAAQ,CAAC;CAC5D,OACE,KAAC,OAAD;EAAK,eAAa;EAAQ,WAAU;EAApC,UAAA,CACE,IAAC,KAAD;GAAG,eAAa,GAAG,OAAO;GAAW,WAAU;GAC5C,UAAA;EACA,CAAA,GACF,OACE,QAAQ,UAAU,OAAO,KAAK,IAAI,CAAC,CAAC,CACpC,KAAK,UACJ,KAAC,WAAD;GAAyB,eAAa,GAAG,OAAO,GAAG,MAAM;GAAzD,UAAA,CACE,KAAC,MAAD;IAAI,WAAU;IAAd,UAAA;KACG,MAAM;KAAO;KACd,KAAC,QAAD;MAAM,eAAa,GAAG,OAAO,GAAG,MAAM,IAAI;MAAS,WAAU;MAA7D,UAAA;OAA4E;OACxE,OAAO,KAAK;OAAE;MACZ;;IACJ;GACH,CAAA,GAAA,MAAM,MAAM,KAAK,MAAM,UACtB,KAAC,OAAD;IAEE,eAAa,KAAK,SAAS,KAAA,IAAY,KAAA,IAAY,GAAG,OAAO,GAAG,MAAM,IAAI;IAF5E,UAAA,CAIG,KAAK,SAAS,KAAA,IAAY,OACzB,IAAC,KAAD,EAAA,UACG,EAAE,iBAAiB;KAClB,cAAc,GAAG,KAAK,IAAI,OAAO,IAAI,KAAK;KAC1C,QAAQ,EAAE,SAAS,KAAK,KAAK;KAC7B,OAAO,KAAK,IAAI;IAClB,CAAC,EACA,CAAA,GAEL,KAAC,MAAD;KAAI,WAAU;KAAd,UAAA,CACG,KAAK,IAAI,MAAM,GAAG,gBAAgB,CAAC,CAAC,KAAK,OACxC,KAAC,MAAD;MAEE,eAAa,GAAG,OAAO,GAAG,MAAM,IAAI,GAAG;MACvC,WAAU;MAHZ,UAAA,CAKG,IACA,MAAM,QAAQ,aAAa,MAAM,QAAQ,eACxC,IAAC,QAAD;OACE,MAAK;OACL,MAAK;OACL,SAAQ;OACR,WAAU;OACV,eAAa,GAAG,OAAO,UAAU;OACjC,eACE,KAAK,OAAO,EAAE,CAAC,CAAC,WACd,cAAc,aAAa,IAAI,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,CAAC,CACvD;OAGD,UAAA;MACK,CAAA,IACN,IACF;KArBG,GAAA,EAqBH,CACL,GACA,KAAK,IAAI,SAAS,mBACjB,KAAC,MAAD,EAAA,UAAA,CAAI,KAAE,KAAK,IAAI,SAAS,gBAAqB,EAAA,CAAA,IAC3C,IACF;IACD,CAAA,CAAA;GA1CE,GAAA,KAAK,QAAQ,KA0Cf,CACN,CACM;EArDK,GAAA,MAAM,GAqDX,CACV,CACA;;AAET"}
|
package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-C47mF260.cjs}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BAKBRn3V.cjs");
|
|
2
|
+
const require_relation_picker = require("./relation-picker-ADjxI_TI.cjs");
|
|
3
3
|
let _burojs_core = require("@burojs/core");
|
|
4
4
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
5
|
//#region src/fields/candidates-relation-picker.tsx
|
|
@@ -7,7 +7,7 @@ function CandidatesRelationPicker(props) {
|
|
|
7
7
|
const { name, field, metaSources, resource, fixedFilters } = props;
|
|
8
8
|
const meta = field?.meta;
|
|
9
9
|
const to = (0, _burojs_core.resourceKey)(meta.to);
|
|
10
|
-
const selection =
|
|
10
|
+
const selection = require_lazy_relation_picker_dialog.useCandidateSelection({
|
|
11
11
|
to,
|
|
12
12
|
candidates: meta.candidates,
|
|
13
13
|
sources: metaSources,
|
|
@@ -28,4 +28,4 @@ function CandidatesRelationPicker(props) {
|
|
|
28
28
|
//#endregion
|
|
29
29
|
exports.CandidatesRelationPicker = CandidatesRelationPicker;
|
|
30
30
|
|
|
31
|
-
//# sourceMappingURL=candidates-relation-picker-
|
|
31
|
+
//# sourceMappingURL=candidates-relation-picker-C47mF260.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candidates-relation-picker-
|
|
1
|
+
{"version":3,"file":"candidates-relation-picker-C47mF260.cjs","names":["resourceKey","useCandidateSelection","FieldRelationPicker"],"sources":["../src/fields/candidates-relation-picker.tsx"],"sourcesContent":["import { type RelationCandidate, type ResourceRefInput, resourceKey } from '@burojs/core';\nimport type * as React from 'react';\nimport { useCandidateSelection } from './candidates-gate.js';\nimport { FieldRelationPicker } from './relation-picker.js';\nimport type { FieldInputProps } from './registry.js';\n\n/** The select of a field that declares `candidates`: the gate and the filters it resolves. */\nexport function CandidatesRelationPicker(props: FieldInputProps): React.ReactElement {\n const { name, field, metaSources, resource, fixedFilters } = props;\n const meta = field?.meta as { to?: ResourceRefInput; candidates?: unknown };\n const to = resourceKey(meta.to as ResourceRefInput);\n const selection = useCandidateSelection({\n to,\n candidates: meta.candidates as readonly RelationCandidate[],\n sources: metaSources,\n resource: resource ?? '',\n fieldName: field?.name ?? name,\n fixedFilters,\n });\n return (\n <FieldRelationPicker\n props={props}\n to={to}\n extra={{\n fixedFilters: selection.fixedFilters,\n ...(selection.gate === undefined ? {} : { candidatesGate: selection.gate }),\n ...(selection.rowFits === undefined ? {} : { rowFits: selection.rowFits }),\n }}\n />\n );\n}\n"],"mappings":";;;;;AAOA,SAAgB,yBAAyB,OAA4C;CACnF,MAAM,EAAE,MAAM,OAAO,aAAa,UAAU,iBAAiB;CAC7D,MAAM,OAAO,OAAO;CACpB,MAAM,MAAA,GAAKA,aAAAA,YAAAA,CAAY,KAAK,EAAsB;CAClD,MAAM,YAAYC,oCAAAA,sBAAsB;EACtC;EACA,YAAY,KAAK;EACjB,SAAS;EACT,UAAU,YAAY;EACtB,WAAW,OAAO,QAAQ;EAC1B;CACF,CAAC;CACD,QACE,GAAA,kBAAA,IAAA,CAACC,wBAAAA,qBAAD;EACS;EACH;EACJ,OAAO;GACL,cAAc,UAAU;GACxB,GAAI,UAAU,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,UAAU,KAAK;GACzE,GAAI,UAAU,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,UAAU,QAAQ;EAC1E;CACD,CAAA;AAEL"}
|
package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CGXItMN0.js}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
1
|
+
import { n as useCandidateSelection } from "./lazy-relation-picker-dialog-DN4bvQfg.js";
|
|
2
|
+
import { t as FieldRelationPicker } from "./relation-picker-x7P5HKie.js";
|
|
3
3
|
import { resourceKey } from "@burojs/core";
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/fields/candidates-relation-picker.tsx
|
|
@@ -28,4 +28,4 @@ function CandidatesRelationPicker(props) {
|
|
|
28
28
|
//#endregion
|
|
29
29
|
export { CandidatesRelationPicker };
|
|
30
30
|
|
|
31
|
-
//# sourceMappingURL=candidates-relation-picker-
|
|
31
|
+
//# sourceMappingURL=candidates-relation-picker-CGXItMN0.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"candidates-relation-picker-
|
|
1
|
+
{"version":3,"file":"candidates-relation-picker-CGXItMN0.js","names":[],"sources":["../src/fields/candidates-relation-picker.tsx"],"sourcesContent":["import { type RelationCandidate, type ResourceRefInput, resourceKey } from '@burojs/core';\nimport type * as React from 'react';\nimport { useCandidateSelection } from './candidates-gate.js';\nimport { FieldRelationPicker } from './relation-picker.js';\nimport type { FieldInputProps } from './registry.js';\n\n/** The select of a field that declares `candidates`: the gate and the filters it resolves. */\nexport function CandidatesRelationPicker(props: FieldInputProps): React.ReactElement {\n const { name, field, metaSources, resource, fixedFilters } = props;\n const meta = field?.meta as { to?: ResourceRefInput; candidates?: unknown };\n const to = resourceKey(meta.to as ResourceRefInput);\n const selection = useCandidateSelection({\n to,\n candidates: meta.candidates as readonly RelationCandidate[],\n sources: metaSources,\n resource: resource ?? '',\n fieldName: field?.name ?? name,\n fixedFilters,\n });\n return (\n <FieldRelationPicker\n props={props}\n to={to}\n extra={{\n fixedFilters: selection.fixedFilters,\n ...(selection.gate === undefined ? {} : { candidatesGate: selection.gate }),\n ...(selection.rowFits === undefined ? {} : { rowFits: selection.rowFits }),\n }}\n />\n );\n}\n"],"mappings":";;;;;AAOA,SAAgB,yBAAyB,OAA4C;CACnF,MAAM,EAAE,MAAM,OAAO,aAAa,UAAU,iBAAiB;CAC7D,MAAM,OAAO,OAAO;CACpB,MAAM,KAAK,YAAY,KAAK,EAAsB;CAClD,MAAM,YAAY,sBAAsB;EACtC;EACA,YAAY,KAAK;EACjB,SAAS;EACT,UAAU,YAAY;EACtB,WAAW,OAAO,QAAQ;EAC1B;CACF,CAAC;CACD,OACE,IAAC,qBAAD;EACS;EACH;EACJ,OAAO;GACL,cAAc,UAAU;GACxB,GAAI,UAAU,SAAS,KAAA,IAAY,CAAC,IAAI,EAAE,gBAAgB,UAAU,KAAK;GACzE,GAAI,UAAU,YAAY,KAAA,IAAY,CAAC,IAAI,EAAE,SAAS,UAAU,QAAQ;EAC1E;CACD,CAAA;AAEL"}
|