@burojs/ui-shadcn 0.6.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.
Files changed (152) hide show
  1. package/README.md +9 -0
  2. package/dist/bulk-summary-BWSAS7k2.js +143 -0
  3. package/dist/bulk-summary-BWSAS7k2.js.map +1 -0
  4. package/dist/bulk-summary-CrEij5vq.cjs +143 -0
  5. package/dist/bulk-summary-CrEij5vq.cjs.map +1 -0
  6. package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CS_JZ4Fd.js} +3 -3
  7. package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CS_JZ4Fd.js.map} +1 -1
  8. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-y5M6_oe4.cjs} +4 -4
  9. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-y5M6_oe4.cjs.map} +1 -1
  10. package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-2j0gOd7x.js} +384 -108
  11. package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
  12. package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-C-NHgMST.cjs} +468 -107
  13. package/dist/check-confirm-dialog-C-NHgMST.cjs.map +1 -0
  14. package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
  15. package/dist/dialog-C123sVQ8.js.map +1 -0
  16. package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
  17. package/dist/dialog-vmMdfUWs.cjs.map +1 -0
  18. package/dist/{filter-builder-nXqtM_h4.cjs → filter-builder-DFu0JP-1.cjs} +923 -120
  19. package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
  20. package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-DaWHUZuV.js} +839 -108
  21. package/dist/filter-builder-DaWHUZuV.js.map +1 -0
  22. package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
  23. package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
  24. package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DyqTmK3H.js} +62 -30
  25. package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
  26. package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-Bcz9NF2V.cjs} +128 -87
  27. package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
  28. package/dist/{flow-screen-CCvgDI9G.js → flow-screen-DCdli6Ha.js} +128 -87
  29. package/dist/flow-screen-DCdli6Ha.js.map +1 -0
  30. package/dist/index.cjs +731 -906
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +455 -247
  33. package/dist/index.d.ts +455 -247
  34. package/dist/index.js +647 -828
  35. package/dist/index.js.map +1 -1
  36. package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-3vw7LzzD.cjs} +5 -5
  37. package/dist/inline-flow-host-3vw7LzzD.cjs.map +1 -0
  38. package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-C0rI9B7f.js} +5 -5
  39. package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
  40. package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-Bt8lrEIu.cjs} +10 -10
  41. package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
  42. package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-CAScLPb2.js} +11 -11
  43. package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
  44. package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-BHUEpn0I.js} +36 -23
  45. package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
  46. package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
  47. package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
  48. package/dist/{place-node-C5SmIAYU.cjs → place-node-CNb3w-c7.cjs} +1869 -947
  49. package/dist/place-node-CNb3w-c7.cjs.map +1 -0
  50. package/dist/{place-node-NraNYKPx.js → place-node-CfzQvh4Y.js} +1824 -926
  51. package/dist/place-node-CfzQvh4Y.js.map +1 -0
  52. package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BIqqY69Y.js} +9 -4
  53. package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
  54. package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
  55. package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
  56. package/dist/{related-list-timeline-yrPsjA3F.js → related-list-timeline-CRh7xwLD.js} +6 -7
  57. package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
  58. package/dist/{related-list-timeline-CCzl71aA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
  59. package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
  60. package/dist/{related-rows-o0_t-Yce.js → related-rows--uP2iKQC.js} +25 -14
  61. package/dist/related-rows--uP2iKQC.js.map +1 -0
  62. package/dist/{related-rows-ea43qhhy.cjs → related-rows-MPnLCmPF.cjs} +27 -16
  63. package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
  64. package/dist/{search-access-CPPmfuvy.js → relation-create-C43cdPQt.js} +595 -13
  65. package/dist/relation-create-C43cdPQt.js.map +1 -0
  66. package/dist/{search-access-Dugvttlg.cjs → relation-create-DDEYcKfw.cjs} +633 -14
  67. package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
  68. package/dist/{relation-many-picker-bvkjkv-k.js → relation-many-picker-BJhaEqxz.js} +203 -102
  69. package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
  70. package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-DzuGJpEl.cjs} +211 -110
  71. package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
  72. package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-D-tBBZW_.js} +23 -59
  73. package/dist/relation-picker-D-tBBZW_.js.map +1 -0
  74. package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-DaIMzf2H.cjs} +29 -71
  75. package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
  76. package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +133 -35
  77. package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
  78. package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-DoEY8EkH.js} +134 -36
  79. package/dist/relation-picker-dialog-DoEY8EkH.js.map +1 -0
  80. package/dist/relation-select-B8Fq4o-t.js +48 -0
  81. package/dist/relation-select-B8Fq4o-t.js.map +1 -0
  82. package/dist/relation-select-Cr3CfNLy.cjs +55 -0
  83. package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
  84. package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-C_kGW2o_.cjs} +543 -300
  85. package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
  86. package/dist/{resource-page-router-3RUf9d1j.js → resource-page-router-Diw6S6TK.js} +498 -255
  87. package/dist/resource-page-router-Diw6S6TK.js.map +1 -0
  88. package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
  89. package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
  90. package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
  91. package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
  92. package/dist/success-notices-Dl3M1fZP.cjs +46 -0
  93. package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
  94. package/dist/success-notices-LDEgEkc4.js +41 -0
  95. package/dist/success-notices-LDEgEkc4.js.map +1 -0
  96. package/dist/{toaster-Cr51X7bz.cjs → toaster-BbByOytP.cjs} +60 -15
  97. package/dist/toaster-BbByOytP.cjs.map +1 -0
  98. package/dist/{toaster-C02XbB9r.js → toaster-Ct_YHGs6.js} +43 -16
  99. package/dist/toaster-Ct_YHGs6.js.map +1 -0
  100. package/dist/{use-dialog-filter-state-C--oMAZG.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
  101. package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
  102. package/dist/{use-dialog-filter-state-Dhe8PcB5.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
  103. package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
  104. package/package.json +11 -11
  105. package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
  106. package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
  107. package/dist/bulk-summary-GxMDP4bw.js +0 -108
  108. package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
  109. package/dist/candidates-gate-Bb70LPAy.js.map +0 -1
  110. package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
  111. package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
  112. package/dist/check-confirm-dialog-bRT8lt0d.js.map +0 -1
  113. package/dist/dialog-B_rt9S1c.js.map +0 -1
  114. package/dist/dialog-DRNUq9EA.cjs.map +0 -1
  115. package/dist/filter-builder-Bhn-dhZV.js.map +0 -1
  116. package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
  117. package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
  118. package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
  119. package/dist/flow-screen-CCvgDI9G.js.map +0 -1
  120. package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
  121. package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
  122. package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
  123. package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
  124. package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
  125. package/dist/place-node-C5SmIAYU.cjs.map +0 -1
  126. package/dist/place-node-NraNYKPx.js.map +0 -1
  127. package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
  128. package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
  129. package/dist/related-rows-ea43qhhy.cjs.map +0 -1
  130. package/dist/related-rows-o0_t-Yce.js.map +0 -1
  131. package/dist/relation-create-IA40t1hi.cjs +0 -364
  132. package/dist/relation-create-IA40t1hi.cjs.map +0 -1
  133. package/dist/relation-create-h6F9B4C4.js +0 -339
  134. package/dist/relation-create-h6F9B4C4.js.map +0 -1
  135. package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
  136. package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
  137. package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
  138. package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
  139. package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
  140. package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
  141. package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
  142. package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
  143. package/dist/search-access-CPPmfuvy.js.map +0 -1
  144. package/dist/search-access-Dugvttlg.cjs.map +0 -1
  145. package/dist/shell-BPlk8hEa.js +0 -205
  146. package/dist/shell-BPlk8hEa.js.map +0 -1
  147. package/dist/shell-DxhlsPwm.cjs +0 -271
  148. package/dist/shell-DxhlsPwm.cjs.map +0 -1
  149. package/dist/toaster-C02XbB9r.js.map +0 -1
  150. package/dist/toaster-Cr51X7bz.cjs.map +0 -1
  151. package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
  152. 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,143 @@
1
+ import { t as Button } from "./button-MWVeZaqj.js";
2
+ import { BULK_SUMMARY_IDS } 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 notProcessed = progress.rejected.filter((entry) => entry.reason !== "server");
51
+ const notApplied = [...progress.rejected.filter((entry) => entry.reason === "server").map((entry) => ({
52
+ id: entry.id,
53
+ text: textOf(entry.error, neutral)
54
+ })), ...progress.failed.map((entry) => ({
55
+ id: entry.id,
56
+ 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." }))
57
+ }))];
58
+ const unknown = progress.unknown.filter((entry) => !forgotten.has(entry.id)).map((entry) => ({
59
+ id: entry.id,
60
+ 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." }))
61
+ }));
62
+ const groups = [
63
+ {
64
+ key: "not-processed",
65
+ title: t("flow.rejected.precondition", { defaultValue: "The record changed. Nothing was sent." }),
66
+ lines: [{ ids: notProcessed.map((entry) => entry.id) }]
67
+ },
68
+ {
69
+ key: "not-applied",
70
+ title: t("flow.bulkNotApplied", { defaultValue: "Not applied" }),
71
+ lines: linesByText(notApplied)
72
+ },
73
+ {
74
+ key: "unknown",
75
+ title: t("flow.bulkMayHaveBeenApplied", { defaultValue: "May have been applied" }),
76
+ lines: linesByText(unknown)
77
+ },
78
+ {
79
+ key: "unresolved",
80
+ title: t("flow.bulkUnresolved", { defaultValue: "Skipped: an earlier request for it may have been applied." }),
81
+ lines: [{ ids: progress.unresolved.filter((id) => !forgotten.has(id)) }]
82
+ },
83
+ {
84
+ key: "not-attempted",
85
+ title: t("flow.bulkNotAttempted", { defaultValue: "Not attempted." }),
86
+ lines: [{ ids: progress.notAttempted }]
87
+ }
88
+ ];
89
+ const sizeOf = (group) => group.lines.reduce((sum, line) => sum + line.ids.length, 0);
90
+ return jsxs("div", {
91
+ "data-testid": testid,
92
+ className: "flex flex-col gap-3 text-sm",
93
+ children: [jsx("p", {
94
+ "data-testid": `${testid}:heading`,
95
+ className: "font-medium",
96
+ children: heading
97
+ }), groups.filter((group) => sizeOf(group) > 0).map((group) => jsxs("section", {
98
+ "data-testid": `${testid}:${group.key}`,
99
+ children: [jsxs("h3", {
100
+ className: "font-medium",
101
+ children: [
102
+ group.title,
103
+ " ",
104
+ jsxs("span", {
105
+ "data-testid": `${testid}:${group.key}:count`,
106
+ className: "tabular-nums",
107
+ children: [
108
+ "(",
109
+ sizeOf(group),
110
+ ")"
111
+ ]
112
+ })
113
+ ]
114
+ }), group.lines.map((line, index) => jsxs("div", {
115
+ "data-testid": line.text === void 0 ? void 0 : `${testid}:${group.key}:line`,
116
+ children: [line.text === void 0 ? null : jsx("p", { children: t("flow.bulkLine", {
117
+ defaultValue: `${line.ids.length}: ${line.text}`,
118
+ params: { message: line.text },
119
+ count: line.ids.length
120
+ }) }), jsxs("ul", {
121
+ className: "flex flex-wrap gap-1 text-muted-foreground",
122
+ children: [line.ids.slice(0, BULK_SUMMARY_IDS).map((id) => jsxs("li", {
123
+ "data-testid": `${testid}:${group.key}:${id}`,
124
+ className: "flex items-center gap-1",
125
+ children: [id, group.key === "unknown" || group.key === "unresolved" ? jsx(Button, {
126
+ type: "button",
127
+ size: "sm",
128
+ variant: "ghost",
129
+ className: "h-6 px-1.5 text-xs",
130
+ "data-testid": `${testid}:forget:${id}`,
131
+ onClick: () => void forget(id).then(() => setForgotten((previous) => new Set([...previous, id]))),
132
+ children: forgetText
133
+ }) : null]
134
+ }, id)), line.ids.length > BULK_SUMMARY_IDS ? jsxs("li", { children: ["+", line.ids.length - BULK_SUMMARY_IDS] }) : null]
135
+ })]
136
+ }, line.text ?? index))]
137
+ }, group.key))]
138
+ });
139
+ }
140
+ //#endregion
141
+ export { FlowBulkSummary };
142
+
143
+ //# sourceMappingURL=bulk-summary-BWSAS7k2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-summary-BWSAS7k2.js","names":[],"sources":["../src/flows/bulk-summary.tsx"],"sourcesContent":["'use client';\nimport { BULK_SUMMARY_IDS, type BulkProgress, type DataError } 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. Not processed\n * (gone or its precondition failed), unresolved from an earlier run and not attempted keep their\n * own groups. 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 notProcessed = progress.rejected.filter((entry) => entry.reason !== 'server');\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 {\n key: 'not-processed',\n title: t('flow.rejected.precondition', {\n defaultValue: 'The record changed. Nothing was sent.',\n }),\n lines: [{ ids: notProcessed.map((entry) => entry.id) }],\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,143 @@
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 notProcessed = progress.rejected.filter((entry) => entry.reason !== "server");
51
+ const notApplied = [...progress.rejected.filter((entry) => entry.reason === "server").map((entry) => ({
52
+ id: entry.id,
53
+ text: textOf(entry.error, neutral)
54
+ })), ...progress.failed.map((entry) => ({
55
+ id: entry.id,
56
+ 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." }))
57
+ }))];
58
+ const unknown = progress.unknown.filter((entry) => !forgotten.has(entry.id)).map((entry) => ({
59
+ id: entry.id,
60
+ 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." }))
61
+ }));
62
+ const groups = [
63
+ {
64
+ key: "not-processed",
65
+ title: t("flow.rejected.precondition", { defaultValue: "The record changed. Nothing was sent." }),
66
+ lines: [{ ids: notProcessed.map((entry) => entry.id) }]
67
+ },
68
+ {
69
+ key: "not-applied",
70
+ title: t("flow.bulkNotApplied", { defaultValue: "Not applied" }),
71
+ lines: linesByText(notApplied)
72
+ },
73
+ {
74
+ key: "unknown",
75
+ title: t("flow.bulkMayHaveBeenApplied", { defaultValue: "May have been applied" }),
76
+ lines: linesByText(unknown)
77
+ },
78
+ {
79
+ key: "unresolved",
80
+ title: t("flow.bulkUnresolved", { defaultValue: "Skipped: an earlier request for it may have been applied." }),
81
+ lines: [{ ids: progress.unresolved.filter((id) => !forgotten.has(id)) }]
82
+ },
83
+ {
84
+ key: "not-attempted",
85
+ title: t("flow.bulkNotAttempted", { defaultValue: "Not attempted." }),
86
+ lines: [{ ids: progress.notAttempted }]
87
+ }
88
+ ];
89
+ const sizeOf = (group) => group.lines.reduce((sum, line) => sum + line.ids.length, 0);
90
+ return (0, react_jsx_runtime.jsxs)("div", {
91
+ "data-testid": testid,
92
+ className: "flex flex-col gap-3 text-sm",
93
+ children: [(0, react_jsx_runtime.jsx)("p", {
94
+ "data-testid": `${testid}:heading`,
95
+ className: "font-medium",
96
+ children: heading
97
+ }), groups.filter((group) => sizeOf(group) > 0).map((group) => (0, react_jsx_runtime.jsxs)("section", {
98
+ "data-testid": `${testid}:${group.key}`,
99
+ children: [(0, react_jsx_runtime.jsxs)("h3", {
100
+ className: "font-medium",
101
+ children: [
102
+ group.title,
103
+ " ",
104
+ (0, react_jsx_runtime.jsxs)("span", {
105
+ "data-testid": `${testid}:${group.key}:count`,
106
+ className: "tabular-nums",
107
+ children: [
108
+ "(",
109
+ sizeOf(group),
110
+ ")"
111
+ ]
112
+ })
113
+ ]
114
+ }), group.lines.map((line, index) => (0, react_jsx_runtime.jsxs)("div", {
115
+ "data-testid": line.text === void 0 ? void 0 : `${testid}:${group.key}:line`,
116
+ children: [line.text === void 0 ? null : (0, react_jsx_runtime.jsx)("p", { children: t("flow.bulkLine", {
117
+ defaultValue: `${line.ids.length}: ${line.text}`,
118
+ params: { message: line.text },
119
+ count: line.ids.length
120
+ }) }), (0, react_jsx_runtime.jsxs)("ul", {
121
+ className: "flex flex-wrap gap-1 text-muted-foreground",
122
+ children: [line.ids.slice(0, _burojs_core.BULK_SUMMARY_IDS).map((id) => (0, react_jsx_runtime.jsxs)("li", {
123
+ "data-testid": `${testid}:${group.key}:${id}`,
124
+ className: "flex items-center gap-1",
125
+ children: [id, group.key === "unknown" || group.key === "unresolved" ? (0, react_jsx_runtime.jsx)(require_button.Button, {
126
+ type: "button",
127
+ size: "sm",
128
+ variant: "ghost",
129
+ className: "h-6 px-1.5 text-xs",
130
+ "data-testid": `${testid}:forget:${id}`,
131
+ onClick: () => void forget(id).then(() => setForgotten((previous) => new Set([...previous, id]))),
132
+ children: forgetText
133
+ }) : null]
134
+ }, 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]
135
+ })]
136
+ }, line.text ?? index))]
137
+ }, group.key))]
138
+ });
139
+ }
140
+ //#endregion
141
+ exports.FlowBulkSummary = FlowBulkSummary;
142
+
143
+ //# sourceMappingURL=bulk-summary-CrEij5vq.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-summary-CrEij5vq.cjs","names":["useOptionalT","useI18nCaps","useForgetEachAttempt","useState","useTestIds","specificErrorText","kindErrorText","BULK_SUMMARY_IDS","Button"],"sources":["../src/flows/bulk-summary.tsx"],"sourcesContent":["'use client';\nimport { BULK_SUMMARY_IDS, type BulkProgress, type DataError } 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. Not processed\n * (gone or its precondition failed), unresolved from an earlier run and not attempted keep their\n * own groups. 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 notProcessed = progress.rejected.filter((entry) => entry.reason !== 'server');\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 {\n key: 'not-processed',\n title: t('flow.rejected.precondition', {\n defaultValue: 'The record changed. Nothing was sent.',\n }),\n lines: [{ ids: notProcessed.map((entry) => entry.id) }],\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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"}
@@ -1,5 +1,5 @@
1
- import { t as FieldRelationPicker } from "./relation-picker-Z0ZJJ5uS.js";
2
- import { t as useCandidateSelection } from "./candidates-gate-Bb70LPAy.js";
1
+ import { n as useCandidateSelection } from "./lazy-relation-picker-dialog-CAScLPb2.js";
2
+ import { t as FieldRelationPicker } from "./relation-picker-D-tBBZW_.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-B116Bmqi.js.map
31
+ //# sourceMappingURL=candidates-relation-picker-CS_JZ4Fd.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"candidates-relation-picker-B116Bmqi.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"}
1
+ {"version":3,"file":"candidates-relation-picker-CS_JZ4Fd.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"}
@@ -1,5 +1,5 @@
1
- const require_relation_picker = require("./relation-picker-gag0qSR5.cjs");
2
- const require_candidates_gate = require("./candidates-gate-D33jXLHO.cjs");
1
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-Bt8lrEIu.cjs");
2
+ const require_relation_picker = require("./relation-picker-DaIMzf2H.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 = require_candidates_gate.useCandidateSelection({
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-Cy0rTxvI.cjs.map
31
+ //# sourceMappingURL=candidates-relation-picker-y5M6_oe4.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"candidates-relation-picker-Cy0rTxvI.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,wBAAAA,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"}
1
+ {"version":3,"file":"candidates-relation-picker-y5M6_oe4.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"}