@burojs/ui-shadcn 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (133) hide show
  1. package/dist/candidates-gate-Bb70LPAy.js +135 -0
  2. package/dist/candidates-gate-Bb70LPAy.js.map +1 -0
  3. package/dist/candidates-gate-D33jXLHO.cjs +153 -0
  4. package/dist/candidates-gate-D33jXLHO.cjs.map +1 -0
  5. package/dist/candidates-relation-picker-B116Bmqi.js +31 -0
  6. package/dist/candidates-relation-picker-B116Bmqi.js.map +1 -0
  7. package/dist/candidates-relation-picker-Cy0rTxvI.cjs +31 -0
  8. package/dist/candidates-relation-picker-Cy0rTxvI.cjs.map +1 -0
  9. package/dist/{check-confirm-dialog-BRByTFpg.cjs → check-confirm-dialog--gPFnEeg.cjs} +27 -14
  10. package/dist/check-confirm-dialog--gPFnEeg.cjs.map +1 -0
  11. package/dist/{check-confirm-dialog-CkaVTPT9.js → check-confirm-dialog-bRT8lt0d.js} +28 -15
  12. package/dist/check-confirm-dialog-bRT8lt0d.js.map +1 -0
  13. package/dist/{filter-builder-DOnaXNfP.js → filter-builder-Bhn-dhZV.js} +30 -14
  14. package/dist/filter-builder-Bhn-dhZV.js.map +1 -0
  15. package/dist/{filter-builder-B3mZFL-K.cjs → filter-builder-nXqtM_h4.cjs} +39 -11
  16. package/dist/filter-builder-nXqtM_h4.cjs.map +1 -0
  17. package/dist/{flow-runtime-B6zOHYqI.cjs → flow-runtime-D3avVH0I.cjs} +3 -3
  18. package/dist/{flow-runtime-B6zOHYqI.cjs.map → flow-runtime-D3avVH0I.cjs.map} +1 -1
  19. package/dist/{flow-runtime-D8h99FSg.js → flow-runtime-s6lkRPKF.js} +3 -3
  20. package/dist/{flow-runtime-D8h99FSg.js.map → flow-runtime-s6lkRPKF.js.map} +1 -1
  21. package/dist/{flow-screen-CmbARSqg.js → flow-screen-CCvgDI9G.js} +11 -8
  22. package/dist/flow-screen-CCvgDI9G.js.map +1 -0
  23. package/dist/{flow-screen-CX05b3G9.cjs → flow-screen-Ci_Sik4Y.cjs} +10 -7
  24. package/dist/flow-screen-Ci_Sik4Y.cjs.map +1 -0
  25. package/dist/index.cjs +577 -56
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +181 -103
  28. package/dist/index.d.ts +181 -103
  29. package/dist/index.js +567 -45
  30. package/dist/index.js.map +1 -1
  31. package/dist/{inline-flow-host-C3H2UpSA.js → inline-flow-host-B6FI0ctQ.js} +3 -3
  32. package/dist/{inline-flow-host-C3H2UpSA.js.map → inline-flow-host-B6FI0ctQ.js.map} +1 -1
  33. package/dist/{inline-flow-host-B7U1OJUe.cjs → inline-flow-host-DV1et3c6.cjs} +3 -3
  34. package/dist/{inline-flow-host-B7U1OJUe.cjs.map → inline-flow-host-DV1et3c6.cjs.map} +1 -1
  35. package/dist/label-66W1qbke.js.map +1 -1
  36. package/dist/label-w6JYf2cF.cjs.map +1 -1
  37. package/dist/markdown/index.d.cts +2 -3
  38. package/dist/markdown/index.d.ts +2 -3
  39. package/dist/{page-flow-route-CQ7HsbBm.cjs → page-flow-route-hdnULWqd.cjs} +6 -6
  40. package/dist/{page-flow-route-CQ7HsbBm.cjs.map → page-flow-route-hdnULWqd.cjs.map} +1 -1
  41. package/dist/{page-flow-route-CyXSvXSE.js → page-flow-route-i3ZfJ1sd.js} +6 -6
  42. package/dist/{page-flow-route-CyXSvXSE.js.map → page-flow-route-i3ZfJ1sd.js.map} +1 -1
  43. package/dist/{place-node-SIp4XYQH.cjs → place-node-C5SmIAYU.cjs} +441 -135
  44. package/dist/place-node-C5SmIAYU.cjs.map +1 -0
  45. package/dist/{place-node--GdsP688.js → place-node-NraNYKPx.js} +420 -138
  46. package/dist/place-node-NraNYKPx.js.map +1 -0
  47. package/dist/{related-list-cards-B6x9HQQp.js → related-list-cards-BWZ9GfOG.js} +3 -3
  48. package/dist/{related-list-cards-B6x9HQQp.js.map → related-list-cards-BWZ9GfOG.js.map} +1 -1
  49. package/dist/{related-list-cards-nxuODlIA.cjs → related-list-cards-CFq3meUn.cjs} +3 -3
  50. package/dist/{related-list-cards-nxuODlIA.cjs.map → related-list-cards-CFq3meUn.cjs.map} +1 -1
  51. package/dist/{related-list-timeline-BYJKEbmA.cjs → related-list-timeline-CCzl71aA.cjs} +2 -2
  52. package/dist/{related-list-timeline-BYJKEbmA.cjs.map → related-list-timeline-CCzl71aA.cjs.map} +1 -1
  53. package/dist/{related-list-timeline-DEdfd-rr.js → related-list-timeline-yrPsjA3F.js} +2 -2
  54. package/dist/{related-list-timeline-DEdfd-rr.js.map → related-list-timeline-yrPsjA3F.js.map} +1 -1
  55. package/dist/{related-rows-zh5f_4QR.cjs → related-rows-ea43qhhy.cjs} +10 -11
  56. package/dist/related-rows-ea43qhhy.cjs.map +1 -0
  57. package/dist/{related-rows-B4levHcR.js → related-rows-o0_t-Yce.js} +7 -8
  58. package/dist/related-rows-o0_t-Yce.js.map +1 -0
  59. package/dist/{relation-create-BOaUe12G.cjs → relation-create-IA40t1hi.cjs} +10 -8
  60. package/dist/relation-create-IA40t1hi.cjs.map +1 -0
  61. package/dist/{relation-create-Bg-eEJLs.js → relation-create-h6F9B4C4.js} +10 -8
  62. package/dist/relation-create-h6F9B4C4.js.map +1 -0
  63. package/dist/{relation-many-picker-B-NCEUgX.cjs → relation-many-picker-C8zFEjwd.cjs} +14 -12
  64. package/dist/relation-many-picker-C8zFEjwd.cjs.map +1 -0
  65. package/dist/{relation-many-picker-gdAOD-qK.js → relation-many-picker-bvkjkv-k.js} +13 -11
  66. package/dist/relation-many-picker-bvkjkv-k.js.map +1 -0
  67. package/dist/{relation-picker-BAY77ivO.js → relation-picker-Z0ZJJ5uS.js} +68 -37
  68. package/dist/relation-picker-Z0ZJJ5uS.js.map +1 -0
  69. package/dist/{relation-picker-dialog-M0pQaWlp.cjs → relation-picker-dialog-0IzkjmiA.cjs} +17 -13
  70. package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +1 -0
  71. package/dist/{relation-picker-dialog-hA9rYrZB.js → relation-picker-dialog-B6nIiJBf.js} +18 -14
  72. package/dist/relation-picker-dialog-B6nIiJBf.js.map +1 -0
  73. package/dist/{relation-picker-Da_uhFvA.cjs → relation-picker-gag0qSR5.cjs} +74 -37
  74. package/dist/relation-picker-gag0qSR5.cjs.map +1 -0
  75. package/dist/{resource-page-router-T4vS5gbJ.js → resource-page-router-3RUf9d1j.js} +44 -38
  76. package/dist/resource-page-router-3RUf9d1j.js.map +1 -0
  77. package/dist/{resource-page-router-OSQyRA5b.cjs → resource-page-router-PXfMW9nh.cjs} +42 -36
  78. package/dist/resource-page-router-PXfMW9nh.cjs.map +1 -0
  79. package/dist/{search-access-CURsWn-U.js → search-access-CPPmfuvy.js} +4 -19
  80. package/dist/search-access-CPPmfuvy.js.map +1 -0
  81. package/dist/{search-access-B7G5oR8n.cjs → search-access-Dugvttlg.cjs} +3 -24
  82. package/dist/search-access-Dugvttlg.cjs.map +1 -0
  83. package/dist/{toaster-CfCRLgR-.js → toaster-C02XbB9r.js} +30 -59
  84. package/dist/toaster-C02XbB9r.js.map +1 -0
  85. package/dist/{toaster-C7CiYA4Z.cjs → toaster-Cr51X7bz.cjs} +30 -83
  86. package/dist/toaster-Cr51X7bz.cjs.map +1 -0
  87. package/dist/{use-dialog-filter-state-BDcgS5Oz.js → use-dialog-filter-state-C--oMAZG.js} +2 -2
  88. package/dist/{use-dialog-filter-state-BDcgS5Oz.js.map → use-dialog-filter-state-C--oMAZG.js.map} +1 -1
  89. package/dist/{use-dialog-filter-state-BBCC0OEK.cjs → use-dialog-filter-state-Dhe8PcB5.cjs} +2 -2
  90. package/dist/{use-dialog-filter-state-BBCC0OEK.cjs.map → use-dialog-filter-state-Dhe8PcB5.cjs.map} +1 -1
  91. package/dist/use-theme-DFlpXils.cjs.map +1 -1
  92. package/dist/use-theme-dnE3Od3I.js.map +1 -1
  93. package/package.json +9 -9
  94. package/dist/candidates-gate-CX2PBu6l.js +0 -63
  95. package/dist/candidates-gate-CX2PBu6l.js.map +0 -1
  96. package/dist/candidates-gate-DiFI52r7.cjs +0 -70
  97. package/dist/candidates-gate-DiFI52r7.cjs.map +0 -1
  98. package/dist/candidates-relation-picker-CBsVcnPR.js +0 -82
  99. package/dist/candidates-relation-picker-CBsVcnPR.js.map +0 -1
  100. package/dist/candidates-relation-picker-Dd_GVLlu.cjs +0 -84
  101. package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +0 -1
  102. package/dist/check-confirm-dialog-BRByTFpg.cjs.map +0 -1
  103. package/dist/check-confirm-dialog-CkaVTPT9.js.map +0 -1
  104. package/dist/filter-builder-B3mZFL-K.cjs.map +0 -1
  105. package/dist/filter-builder-DOnaXNfP.js.map +0 -1
  106. package/dist/flow-screen-CX05b3G9.cjs.map +0 -1
  107. package/dist/flow-screen-CmbARSqg.js.map +0 -1
  108. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +0 -14
  109. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +0 -1
  110. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +0 -19
  111. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +0 -1
  112. package/dist/peek-filter-CnqHwTMU.cjs +0 -51
  113. package/dist/peek-filter-CnqHwTMU.cjs.map +0 -1
  114. package/dist/peek-filter-ErLfO153.js +0 -28
  115. package/dist/peek-filter-ErLfO153.js.map +0 -1
  116. package/dist/place-node--GdsP688.js.map +0 -1
  117. package/dist/place-node-SIp4XYQH.cjs.map +0 -1
  118. package/dist/related-rows-B4levHcR.js.map +0 -1
  119. package/dist/related-rows-zh5f_4QR.cjs.map +0 -1
  120. package/dist/relation-create-BOaUe12G.cjs.map +0 -1
  121. package/dist/relation-create-Bg-eEJLs.js.map +0 -1
  122. package/dist/relation-many-picker-B-NCEUgX.cjs.map +0 -1
  123. package/dist/relation-many-picker-gdAOD-qK.js.map +0 -1
  124. package/dist/relation-picker-BAY77ivO.js.map +0 -1
  125. package/dist/relation-picker-Da_uhFvA.cjs.map +0 -1
  126. package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +0 -1
  127. package/dist/relation-picker-dialog-hA9rYrZB.js.map +0 -1
  128. package/dist/resource-page-router-OSQyRA5b.cjs.map +0 -1
  129. package/dist/resource-page-router-T4vS5gbJ.js.map +0 -1
  130. package/dist/search-access-B7G5oR8n.cjs.map +0 -1
  131. package/dist/search-access-CURsWn-U.js.map +0 -1
  132. package/dist/toaster-C7CiYA4Z.cjs.map +0 -1
  133. package/dist/toaster-CfCRLgR-.js.map +0 -1
@@ -0,0 +1,135 @@
1
+ import { declaredText, resolveCandidates, resolveFieldLabel } from "@burojs/core";
2
+ import { useApp, useCandidatesAccess, useI18nCaps, useOptionalT, useTestIds } from "@burojs/react";
3
+ import * as React from "react";
4
+ import { Suspense, lazy } from "react";
5
+ import { jsx } from "react/jsx-runtime";
6
+ //#region src/fields/lazy-relation-picker-dialog.tsx
7
+ const Dialog = lazy(() => import("./relation-picker-dialog-B6nIiJBf.js").then((module) => ({ default: module.RelationPickerDialog })));
8
+ function LazyRelationPickerDialog(props) {
9
+ return jsx(Suspense, {
10
+ fallback: null,
11
+ children: jsx(Dialog, { ...props })
12
+ });
13
+ }
14
+ //#endregion
15
+ //#region src/fields/candidates-match.ts
16
+ function rowMatches(row, filters) {
17
+ let unknown = false;
18
+ for (const filter of filters) {
19
+ const group = filter;
20
+ if (Array.isArray(group.and) || Array.isArray(group.or)) {
21
+ const answers = (Array.isArray(group.and) ? group.and : group.or).map((part) => rowMatches(row, [part]));
22
+ const all = Array.isArray(group.and);
23
+ const decided = answers.filter((answer) => answer !== void 0);
24
+ if (all ? decided.includes(false) : decided.length > 0 && !decided.includes(true)) return false;
25
+ if (decided.length < answers.length && !(all ? false : decided.includes(true))) unknown = true;
26
+ continue;
27
+ }
28
+ const { field, op, value } = filter;
29
+ if (typeof field !== "string" || typeof op !== "string") continue;
30
+ if (!Object.hasOwn(row, field)) {
31
+ unknown = true;
32
+ continue;
33
+ }
34
+ const held = holds(row[field], op, value);
35
+ if (held === false) return false;
36
+ if (held === void 0) unknown = true;
37
+ }
38
+ return unknown ? void 0 : true;
39
+ }
40
+ function holds(actual, op, expected) {
41
+ const list = Array.isArray(expected) ? expected : void 0;
42
+ const text = (value) => String(value ?? "").toLowerCase();
43
+ switch (op) {
44
+ case "eq": return Object.is(actual, expected) || String(actual) === String(expected);
45
+ case "neq": return !(Object.is(actual, expected) || String(actual) === String(expected));
46
+ case "in": return list === void 0 ? void 0 : list.some((entry) => String(entry) === String(actual));
47
+ case "notIn": return list === void 0 ? void 0 : !list.some((entry) => String(entry) === String(actual));
48
+ case "gt": return compare(actual, expected, (a, b) => a > b);
49
+ case "gte": return compare(actual, expected, (a, b) => a >= b);
50
+ case "lt": return compare(actual, expected, (a, b) => a < b);
51
+ case "lte": return compare(actual, expected, (a, b) => a <= b);
52
+ case "contains": return text(actual).includes(text(expected));
53
+ case "startsWith": return text(actual).startsWith(text(expected));
54
+ case "endsWith": return text(actual).endsWith(text(expected));
55
+ case "isNull": return actual === null || actual === void 0;
56
+ case "isNotNull": return actual !== null && actual !== void 0;
57
+ default: return;
58
+ }
59
+ }
60
+ function compare(actual, expected, test) {
61
+ return typeof actual === "number" && typeof expected === "number" || typeof actual === "string" && typeof expected === "string" ? test(actual, expected) : void 0;
62
+ }
63
+ //#endregion
64
+ //#region src/fields/candidates-gate.ts
65
+ const NO_SOURCES = Object.freeze({});
66
+ const NO_FILTERS = Object.freeze([]);
67
+ function useCandidatesGate(input) {
68
+ const { to, candidates, sources, resource, fieldName } = input;
69
+ const t = useOptionalT();
70
+ const app = useApp();
71
+ const tid = useTestIds();
72
+ const ownerCaps = useI18nCaps(resource);
73
+ const targetCaps = useI18nCaps(to ?? resource);
74
+ const access = useCandidatesAccess(to ?? "", candidates);
75
+ const resolution = React.useMemo(() => resolveCandidates(candidates, sources ?? NO_SOURCES), [candidates, sources]);
76
+ if (candidates === void 0 || candidates.length === 0) return { filters: NO_FILTERS };
77
+ const testId = tid.relationCandidatesHint(resource, fieldName);
78
+ if (access.status === "pending") return {
79
+ filters: NO_FILTERS,
80
+ gate: { kind: "pending" }
81
+ };
82
+ if (access.status === "forbidden") {
83
+ const declared = declaredText("field", (app.registry.get(to ?? "")?.fields)?.[access.field], "label");
84
+ const label = resolveFieldLabel(targetCaps, access.field, declared);
85
+ return {
86
+ filters: NO_FILTERS,
87
+ gate: {
88
+ kind: "forbidden",
89
+ testId,
90
+ message: t("relationPicker.cannotSearchBy", {
91
+ params: { label },
92
+ defaultValue: `You cannot search by ${label}`
93
+ })
94
+ }
95
+ };
96
+ }
97
+ if (resolution.status === "pending") return {
98
+ filters: NO_FILTERS,
99
+ gate: { kind: "pending" }
100
+ };
101
+ if (resolution.status === "empty") {
102
+ const { source, path } = resolution.hint;
103
+ const head = path[0];
104
+ const declared = (source === "values" || source === "record") && head !== void 0 ? declaredText("field", (app.registry.get(resource)?.fields)?.[head], "label") : void 0;
105
+ const label = resolveFieldLabel(ownerCaps, head ?? source, declared);
106
+ return {
107
+ filters: NO_FILTERS,
108
+ gate: {
109
+ kind: "empty",
110
+ testId,
111
+ message: t("relationPicker.chooseFirst", {
112
+ params: { label },
113
+ defaultValue: `Choose ${label} first`
114
+ })
115
+ }
116
+ };
117
+ }
118
+ return { filters: resolution.filters };
119
+ }
120
+ function useCandidateSelection(input) {
121
+ const { fixedFilters } = input;
122
+ const gate = useCandidatesGate(input);
123
+ const filters = gate.filters;
124
+ const combined = React.useMemo(() => filters.length === 0 ? fixedFilters : [...filters, ...fixedFilters ?? []], [filters, fixedFilters]);
125
+ const rowFits = React.useMemo(() => filters.length === 0 ? void 0 : (row) => rowMatches(row, filters), [filters]);
126
+ return {
127
+ fixedFilters: combined,
128
+ ...gate.gate === void 0 ? {} : { gate: gate.gate },
129
+ ...rowFits === void 0 ? {} : { rowFits }
130
+ };
131
+ }
132
+ //#endregion
133
+ export { useCandidatesGate as n, LazyRelationPickerDialog as r, useCandidateSelection as t };
134
+
135
+ //# sourceMappingURL=candidates-gate-Bb70LPAy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidates-gate-Bb70LPAy.js","names":[],"sources":["../src/fields/lazy-relation-picker-dialog.tsx","../src/fields/candidates-match.ts","../src/fields/candidates-gate.ts"],"sourcesContent":["import { type ComponentProps, type ReactElement, Suspense, lazy } from 'react';\nimport type { RelationPickerDialog } from './relation-picker-dialog.js';\n\nconst Dialog = lazy(() =>\n import('./relation-picker-dialog.js').then((module) => ({\n default: module.RelationPickerDialog,\n })),\n);\n\n/** The \"Advanced search\" dialog, loaded on the first open: nothing is drawn until it arrives. */\nexport function LazyRelationPickerDialog(\n props: ComponentProps<typeof RelationPickerDialog>,\n): ReactElement {\n return (\n <Suspense fallback={null}>\n <Dialog {...props} />\n </Suspense>\n );\n}\n","import type { FixedFilterInput } from '@burojs/core';\n\ntype Entry = { readonly field?: unknown; readonly op?: unknown; readonly value?: unknown };\n\n/**\n * Whether `row` meets every candidate filter (P7 3.4): `true`, `false`, or `undefined` when the\n * row does not carry a field a filter names (a narrower projection), so nothing can be said.\n * Only the flat `{ field, op, value }` entries candidates resolve to are evaluated; this is what\n * \"does not match the current filter\" is decided on, never what is sent.\n */\nexport function rowMatches(\n row: Readonly<Record<string, unknown>>,\n filters: readonly FixedFilterInput[],\n): boolean | undefined {\n let unknown = false;\n for (const filter of filters) {\n const group = filter as { readonly and?: unknown; readonly or?: unknown };\n if (Array.isArray(group.and) || Array.isArray(group.or)) {\n const parts = (\n Array.isArray(group.and) ? group.and : group.or\n ) as readonly FixedFilterInput[];\n const answers = parts.map((part) => rowMatches(row, [part]));\n const all = Array.isArray(group.and);\n const decided = answers.filter((answer) => answer !== undefined);\n if (all ? decided.includes(false) : decided.length > 0 && !decided.includes(true))\n return false;\n if (decided.length < answers.length && !(all ? false : decided.includes(true)))\n unknown = true;\n continue;\n }\n const { field, op, value } = filter as Entry;\n if (typeof field !== 'string' || typeof op !== 'string') continue;\n if (!Object.hasOwn(row, field)) {\n unknown = true;\n continue;\n }\n const held = holds(row[field], op, value);\n if (held === false) return false;\n if (held === undefined) unknown = true;\n }\n return unknown ? undefined : true;\n}\n\nfunction holds(actual: unknown, op: string, expected: unknown): boolean | undefined {\n const list = Array.isArray(expected) ? (expected as readonly unknown[]) : undefined;\n const text = (value: unknown) => String(value ?? '').toLowerCase();\n switch (op) {\n case 'eq':\n return Object.is(actual, expected) || String(actual) === String(expected);\n case 'neq':\n return !(Object.is(actual, expected) || String(actual) === String(expected));\n case 'in':\n return list === undefined\n ? undefined\n : list.some((entry) => String(entry) === String(actual));\n case 'notIn':\n return list === undefined\n ? undefined\n : !list.some((entry) => String(entry) === String(actual));\n case 'gt':\n return compare(actual, expected, (a, b) => a > b);\n case 'gte':\n return compare(actual, expected, (a, b) => a >= b);\n case 'lt':\n return compare(actual, expected, (a, b) => a < b);\n case 'lte':\n return compare(actual, expected, (a, b) => a <= b);\n case 'contains':\n return text(actual).includes(text(expected));\n case 'startsWith':\n return text(actual).startsWith(text(expected));\n case 'endsWith':\n return text(actual).endsWith(text(expected));\n case 'isNull':\n return actual === null || actual === undefined;\n case 'isNotNull':\n return actual !== null && actual !== undefined;\n default:\n return undefined;\n }\n}\n\nfunction compare(\n actual: unknown,\n expected: unknown,\n test: (a: number | string, b: number | string) => boolean,\n): boolean | undefined {\n const both =\n (typeof actual === 'number' && typeof expected === 'number') ||\n (typeof actual === 'string' && typeof expected === 'string');\n return both ? test(actual as number | string, expected as number | string) : undefined;\n}\n","import {\n type FixedFilterInput,\n type RelationCandidate,\n type ScreenSources,\n resolveCandidates,\n resolveFieldLabel,\n declaredText,\n} from '@burojs/core';\nimport { useApp, useCandidatesAccess, useI18nCaps, useOptionalT, useTestIds } from '@burojs/react';\nimport * as React from 'react';\nimport { rowMatches } from './candidates-match.js';\n\n/** A select that must not read its target now (P7 3.4): why, and what it tells the user. */\nexport type CandidatesGate =\n | { readonly kind: 'pending' }\n | { readonly kind: 'empty'; readonly message: string; readonly testId: string }\n | { readonly kind: 'forbidden'; readonly message: string; readonly testId: string };\n\nconst NO_SOURCES: ScreenSources = Object.freeze({});\nconst NO_FILTERS: readonly FixedFilterInput[] = Object.freeze([]);\n\n/**\n * A relation field's `candidates` as the select applies them (P7 3.4): the filters to send and,\n * when they say the target must not be read yet, the gate that tells the user why. The refs are\n * read from the owner's projected sources, so a field P5 hides reads `null` (the select asks for\n * it first, and sends nothing); a candidate on a target field the user may not view forbids the\n * read; an undecided source or permission map keeps the select disabled.\n */\nexport function useCandidatesGate(input: {\n readonly to: string | undefined;\n readonly candidates: readonly RelationCandidate[] | undefined;\n readonly sources: ScreenSources | undefined;\n readonly resource: string;\n readonly fieldName: string;\n}): { readonly filters: readonly FixedFilterInput[]; readonly gate?: CandidatesGate } {\n const { to, candidates, sources, resource, fieldName } = input;\n const t = useOptionalT();\n const app = useApp();\n const tid = useTestIds();\n const ownerCaps = useI18nCaps(resource);\n const targetCaps = useI18nCaps(to ?? resource);\n const access = useCandidatesAccess(to ?? '', candidates);\n const resolution = React.useMemo(\n () => resolveCandidates(candidates, sources ?? NO_SOURCES),\n [candidates, sources],\n );\n if (candidates === undefined || candidates.length === 0) return { filters: NO_FILTERS };\n const testId = tid.relationCandidatesHint(resource, fieldName);\n if (access.status === 'pending') return { filters: NO_FILTERS, gate: { kind: 'pending' } };\n if (access.status === 'forbidden') {\n const declared = declaredText(\n 'field',\n (app.registry.get(to ?? '')?.fields as Record<string, unknown> | undefined)?.[access.field],\n 'label',\n );\n const label = resolveFieldLabel(targetCaps, access.field, declared);\n return {\n filters: NO_FILTERS,\n gate: {\n kind: 'forbidden',\n testId,\n message: t('relationPicker.cannotSearchBy', {\n params: { label },\n defaultValue: `You cannot search by ${label}`,\n }),\n },\n };\n }\n if (resolution.status === 'pending') return { filters: NO_FILTERS, gate: { kind: 'pending' } };\n if (resolution.status === 'empty') {\n const { source, path } = resolution.hint;\n const head = path[0];\n // The field a `values` / `record` ref reads is labelled as the owner labels it; any other\n // source (`scope`, `user`) names the key it reads, humanised.\n const own = source === 'values' || source === 'record';\n const declared =\n own && head !== undefined\n ? declaredText(\n 'field',\n (app.registry.get(resource)?.fields as Record<string, unknown> | undefined)?.[head],\n 'label',\n )\n : undefined;\n const label = resolveFieldLabel(ownerCaps, head ?? source, declared);\n return {\n filters: NO_FILTERS,\n gate: {\n kind: 'empty',\n testId,\n message: t('relationPicker.chooseFirst', {\n params: { label },\n defaultValue: `Choose ${label} first`,\n }),\n },\n };\n }\n return { filters: resolution.filters };\n}\n\n/**\n * A select's declared candidates as the shared select wiring applies them (`CandidatesRelationPicker`\n * and `useRelationPicker`): the gate, the resolved candidate filters prepended to the caller's\n * `fixedFilters`, and whether a loaded row fits them (`undefined` when no candidate filter applies).\n */\nexport function useCandidateSelection(input: {\n readonly to: string | undefined;\n readonly candidates: readonly RelationCandidate[] | undefined;\n readonly sources: ScreenSources | undefined;\n readonly resource: string;\n readonly fieldName: string;\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n}): {\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n readonly gate?: CandidatesGate;\n readonly rowFits?: (row: Record<string, unknown>) => boolean | undefined;\n} {\n const { fixedFilters } = input;\n const gate = useCandidatesGate(input);\n const filters = gate.filters;\n const combined = React.useMemo(\n () => (filters.length === 0 ? fixedFilters : [...filters, ...(fixedFilters ?? [])]),\n [filters, fixedFilters],\n );\n const rowFits = React.useMemo(\n () =>\n filters.length === 0 ? undefined : (row: Record<string, unknown>) => rowMatches(row, filters),\n [filters],\n );\n return {\n fixedFilters: combined,\n ...(gate.gate === undefined ? {} : { gate: gate.gate }),\n ...(rowFits === undefined ? {} : { rowFits }),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,153 @@
1
+ const require_use_theme = require("./use-theme-DFlpXils.cjs");
2
+ let _burojs_core = require("@burojs/core");
3
+ let _burojs_react = require("@burojs/react");
4
+ let react = require("react");
5
+ react = require_use_theme.__toESM(react, 1);
6
+ let react_jsx_runtime = require("react/jsx-runtime");
7
+ //#region src/fields/lazy-relation-picker-dialog.tsx
8
+ const Dialog = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-picker-dialog-0IzkjmiA.cjs")).then((module) => ({ default: module.RelationPickerDialog })));
9
+ function LazyRelationPickerDialog(props) {
10
+ return (0, react_jsx_runtime.jsx)(react.Suspense, {
11
+ fallback: null,
12
+ children: (0, react_jsx_runtime.jsx)(Dialog, { ...props })
13
+ });
14
+ }
15
+ //#endregion
16
+ //#region src/fields/candidates-match.ts
17
+ function rowMatches(row, filters) {
18
+ let unknown = false;
19
+ for (const filter of filters) {
20
+ const group = filter;
21
+ if (Array.isArray(group.and) || Array.isArray(group.or)) {
22
+ const answers = (Array.isArray(group.and) ? group.and : group.or).map((part) => rowMatches(row, [part]));
23
+ const all = Array.isArray(group.and);
24
+ const decided = answers.filter((answer) => answer !== void 0);
25
+ if (all ? decided.includes(false) : decided.length > 0 && !decided.includes(true)) return false;
26
+ if (decided.length < answers.length && !(all ? false : decided.includes(true))) unknown = true;
27
+ continue;
28
+ }
29
+ const { field, op, value } = filter;
30
+ if (typeof field !== "string" || typeof op !== "string") continue;
31
+ if (!Object.hasOwn(row, field)) {
32
+ unknown = true;
33
+ continue;
34
+ }
35
+ const held = holds(row[field], op, value);
36
+ if (held === false) return false;
37
+ if (held === void 0) unknown = true;
38
+ }
39
+ return unknown ? void 0 : true;
40
+ }
41
+ function holds(actual, op, expected) {
42
+ const list = Array.isArray(expected) ? expected : void 0;
43
+ const text = (value) => String(value ?? "").toLowerCase();
44
+ switch (op) {
45
+ case "eq": return Object.is(actual, expected) || String(actual) === String(expected);
46
+ case "neq": return !(Object.is(actual, expected) || String(actual) === String(expected));
47
+ case "in": return list === void 0 ? void 0 : list.some((entry) => String(entry) === String(actual));
48
+ case "notIn": return list === void 0 ? void 0 : !list.some((entry) => String(entry) === String(actual));
49
+ case "gt": return compare(actual, expected, (a, b) => a > b);
50
+ case "gte": return compare(actual, expected, (a, b) => a >= b);
51
+ case "lt": return compare(actual, expected, (a, b) => a < b);
52
+ case "lte": return compare(actual, expected, (a, b) => a <= b);
53
+ case "contains": return text(actual).includes(text(expected));
54
+ case "startsWith": return text(actual).startsWith(text(expected));
55
+ case "endsWith": return text(actual).endsWith(text(expected));
56
+ case "isNull": return actual === null || actual === void 0;
57
+ case "isNotNull": return actual !== null && actual !== void 0;
58
+ default: return;
59
+ }
60
+ }
61
+ function compare(actual, expected, test) {
62
+ return typeof actual === "number" && typeof expected === "number" || typeof actual === "string" && typeof expected === "string" ? test(actual, expected) : void 0;
63
+ }
64
+ //#endregion
65
+ //#region src/fields/candidates-gate.ts
66
+ const NO_SOURCES = Object.freeze({});
67
+ const NO_FILTERS = Object.freeze([]);
68
+ function useCandidatesGate(input) {
69
+ const { to, candidates, sources, resource, fieldName } = input;
70
+ const t = (0, _burojs_react.useOptionalT)();
71
+ const app = (0, _burojs_react.useApp)();
72
+ const tid = (0, _burojs_react.useTestIds)();
73
+ const ownerCaps = (0, _burojs_react.useI18nCaps)(resource);
74
+ const targetCaps = (0, _burojs_react.useI18nCaps)(to ?? resource);
75
+ const access = (0, _burojs_react.useCandidatesAccess)(to ?? "", candidates);
76
+ const resolution = react.useMemo(() => (0, _burojs_core.resolveCandidates)(candidates, sources ?? NO_SOURCES), [candidates, sources]);
77
+ if (candidates === void 0 || candidates.length === 0) return { filters: NO_FILTERS };
78
+ const testId = tid.relationCandidatesHint(resource, fieldName);
79
+ if (access.status === "pending") return {
80
+ filters: NO_FILTERS,
81
+ gate: { kind: "pending" }
82
+ };
83
+ if (access.status === "forbidden") {
84
+ const declared = (0, _burojs_core.declaredText)("field", (app.registry.get(to ?? "")?.fields)?.[access.field], "label");
85
+ const label = (0, _burojs_core.resolveFieldLabel)(targetCaps, access.field, declared);
86
+ return {
87
+ filters: NO_FILTERS,
88
+ gate: {
89
+ kind: "forbidden",
90
+ testId,
91
+ message: t("relationPicker.cannotSearchBy", {
92
+ params: { label },
93
+ defaultValue: `You cannot search by ${label}`
94
+ })
95
+ }
96
+ };
97
+ }
98
+ if (resolution.status === "pending") return {
99
+ filters: NO_FILTERS,
100
+ gate: { kind: "pending" }
101
+ };
102
+ if (resolution.status === "empty") {
103
+ const { source, path } = resolution.hint;
104
+ const head = path[0];
105
+ const declared = (source === "values" || source === "record") && head !== void 0 ? (0, _burojs_core.declaredText)("field", (app.registry.get(resource)?.fields)?.[head], "label") : void 0;
106
+ const label = (0, _burojs_core.resolveFieldLabel)(ownerCaps, head ?? source, declared);
107
+ return {
108
+ filters: NO_FILTERS,
109
+ gate: {
110
+ kind: "empty",
111
+ testId,
112
+ message: t("relationPicker.chooseFirst", {
113
+ params: { label },
114
+ defaultValue: `Choose ${label} first`
115
+ })
116
+ }
117
+ };
118
+ }
119
+ return { filters: resolution.filters };
120
+ }
121
+ function useCandidateSelection(input) {
122
+ const { fixedFilters } = input;
123
+ const gate = useCandidatesGate(input);
124
+ const filters = gate.filters;
125
+ const combined = react.useMemo(() => filters.length === 0 ? fixedFilters : [...filters, ...fixedFilters ?? []], [filters, fixedFilters]);
126
+ const rowFits = react.useMemo(() => filters.length === 0 ? void 0 : (row) => rowMatches(row, filters), [filters]);
127
+ return {
128
+ fixedFilters: combined,
129
+ ...gate.gate === void 0 ? {} : { gate: gate.gate },
130
+ ...rowFits === void 0 ? {} : { rowFits }
131
+ };
132
+ }
133
+ //#endregion
134
+ Object.defineProperty(exports, "LazyRelationPickerDialog", {
135
+ enumerable: true,
136
+ get: function() {
137
+ return LazyRelationPickerDialog;
138
+ }
139
+ });
140
+ Object.defineProperty(exports, "useCandidateSelection", {
141
+ enumerable: true,
142
+ get: function() {
143
+ return useCandidateSelection;
144
+ }
145
+ });
146
+ Object.defineProperty(exports, "useCandidatesGate", {
147
+ enumerable: true,
148
+ get: function() {
149
+ return useCandidatesGate;
150
+ }
151
+ });
152
+
153
+ //# sourceMappingURL=candidates-gate-D33jXLHO.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"candidates-gate-D33jXLHO.cjs","names":["lazy","Suspense","useOptionalT","useApp","useTestIds","useI18nCaps","useCandidatesAccess","React","resolveCandidates","declaredText","resolveFieldLabel"],"sources":["../src/fields/lazy-relation-picker-dialog.tsx","../src/fields/candidates-match.ts","../src/fields/candidates-gate.ts"],"sourcesContent":["import { type ComponentProps, type ReactElement, Suspense, lazy } from 'react';\nimport type { RelationPickerDialog } from './relation-picker-dialog.js';\n\nconst Dialog = lazy(() =>\n import('./relation-picker-dialog.js').then((module) => ({\n default: module.RelationPickerDialog,\n })),\n);\n\n/** The \"Advanced search\" dialog, loaded on the first open: nothing is drawn until it arrives. */\nexport function LazyRelationPickerDialog(\n props: ComponentProps<typeof RelationPickerDialog>,\n): ReactElement {\n return (\n <Suspense fallback={null}>\n <Dialog {...props} />\n </Suspense>\n );\n}\n","import type { FixedFilterInput } from '@burojs/core';\n\ntype Entry = { readonly field?: unknown; readonly op?: unknown; readonly value?: unknown };\n\n/**\n * Whether `row` meets every candidate filter (P7 3.4): `true`, `false`, or `undefined` when the\n * row does not carry a field a filter names (a narrower projection), so nothing can be said.\n * Only the flat `{ field, op, value }` entries candidates resolve to are evaluated; this is what\n * \"does not match the current filter\" is decided on, never what is sent.\n */\nexport function rowMatches(\n row: Readonly<Record<string, unknown>>,\n filters: readonly FixedFilterInput[],\n): boolean | undefined {\n let unknown = false;\n for (const filter of filters) {\n const group = filter as { readonly and?: unknown; readonly or?: unknown };\n if (Array.isArray(group.and) || Array.isArray(group.or)) {\n const parts = (\n Array.isArray(group.and) ? group.and : group.or\n ) as readonly FixedFilterInput[];\n const answers = parts.map((part) => rowMatches(row, [part]));\n const all = Array.isArray(group.and);\n const decided = answers.filter((answer) => answer !== undefined);\n if (all ? decided.includes(false) : decided.length > 0 && !decided.includes(true))\n return false;\n if (decided.length < answers.length && !(all ? false : decided.includes(true)))\n unknown = true;\n continue;\n }\n const { field, op, value } = filter as Entry;\n if (typeof field !== 'string' || typeof op !== 'string') continue;\n if (!Object.hasOwn(row, field)) {\n unknown = true;\n continue;\n }\n const held = holds(row[field], op, value);\n if (held === false) return false;\n if (held === undefined) unknown = true;\n }\n return unknown ? undefined : true;\n}\n\nfunction holds(actual: unknown, op: string, expected: unknown): boolean | undefined {\n const list = Array.isArray(expected) ? (expected as readonly unknown[]) : undefined;\n const text = (value: unknown) => String(value ?? '').toLowerCase();\n switch (op) {\n case 'eq':\n return Object.is(actual, expected) || String(actual) === String(expected);\n case 'neq':\n return !(Object.is(actual, expected) || String(actual) === String(expected));\n case 'in':\n return list === undefined\n ? undefined\n : list.some((entry) => String(entry) === String(actual));\n case 'notIn':\n return list === undefined\n ? undefined\n : !list.some((entry) => String(entry) === String(actual));\n case 'gt':\n return compare(actual, expected, (a, b) => a > b);\n case 'gte':\n return compare(actual, expected, (a, b) => a >= b);\n case 'lt':\n return compare(actual, expected, (a, b) => a < b);\n case 'lte':\n return compare(actual, expected, (a, b) => a <= b);\n case 'contains':\n return text(actual).includes(text(expected));\n case 'startsWith':\n return text(actual).startsWith(text(expected));\n case 'endsWith':\n return text(actual).endsWith(text(expected));\n case 'isNull':\n return actual === null || actual === undefined;\n case 'isNotNull':\n return actual !== null && actual !== undefined;\n default:\n return undefined;\n }\n}\n\nfunction compare(\n actual: unknown,\n expected: unknown,\n test: (a: number | string, b: number | string) => boolean,\n): boolean | undefined {\n const both =\n (typeof actual === 'number' && typeof expected === 'number') ||\n (typeof actual === 'string' && typeof expected === 'string');\n return both ? test(actual as number | string, expected as number | string) : undefined;\n}\n","import {\n type FixedFilterInput,\n type RelationCandidate,\n type ScreenSources,\n resolveCandidates,\n resolveFieldLabel,\n declaredText,\n} from '@burojs/core';\nimport { useApp, useCandidatesAccess, useI18nCaps, useOptionalT, useTestIds } from '@burojs/react';\nimport * as React from 'react';\nimport { rowMatches } from './candidates-match.js';\n\n/** A select that must not read its target now (P7 3.4): why, and what it tells the user. */\nexport type CandidatesGate =\n | { readonly kind: 'pending' }\n | { readonly kind: 'empty'; readonly message: string; readonly testId: string }\n | { readonly kind: 'forbidden'; readonly message: string; readonly testId: string };\n\nconst NO_SOURCES: ScreenSources = Object.freeze({});\nconst NO_FILTERS: readonly FixedFilterInput[] = Object.freeze([]);\n\n/**\n * A relation field's `candidates` as the select applies them (P7 3.4): the filters to send and,\n * when they say the target must not be read yet, the gate that tells the user why. The refs are\n * read from the owner's projected sources, so a field P5 hides reads `null` (the select asks for\n * it first, and sends nothing); a candidate on a target field the user may not view forbids the\n * read; an undecided source or permission map keeps the select disabled.\n */\nexport function useCandidatesGate(input: {\n readonly to: string | undefined;\n readonly candidates: readonly RelationCandidate[] | undefined;\n readonly sources: ScreenSources | undefined;\n readonly resource: string;\n readonly fieldName: string;\n}): { readonly filters: readonly FixedFilterInput[]; readonly gate?: CandidatesGate } {\n const { to, candidates, sources, resource, fieldName } = input;\n const t = useOptionalT();\n const app = useApp();\n const tid = useTestIds();\n const ownerCaps = useI18nCaps(resource);\n const targetCaps = useI18nCaps(to ?? resource);\n const access = useCandidatesAccess(to ?? '', candidates);\n const resolution = React.useMemo(\n () => resolveCandidates(candidates, sources ?? NO_SOURCES),\n [candidates, sources],\n );\n if (candidates === undefined || candidates.length === 0) return { filters: NO_FILTERS };\n const testId = tid.relationCandidatesHint(resource, fieldName);\n if (access.status === 'pending') return { filters: NO_FILTERS, gate: { kind: 'pending' } };\n if (access.status === 'forbidden') {\n const declared = declaredText(\n 'field',\n (app.registry.get(to ?? '')?.fields as Record<string, unknown> | undefined)?.[access.field],\n 'label',\n );\n const label = resolveFieldLabel(targetCaps, access.field, declared);\n return {\n filters: NO_FILTERS,\n gate: {\n kind: 'forbidden',\n testId,\n message: t('relationPicker.cannotSearchBy', {\n params: { label },\n defaultValue: `You cannot search by ${label}`,\n }),\n },\n };\n }\n if (resolution.status === 'pending') return { filters: NO_FILTERS, gate: { kind: 'pending' } };\n if (resolution.status === 'empty') {\n const { source, path } = resolution.hint;\n const head = path[0];\n // The field a `values` / `record` ref reads is labelled as the owner labels it; any other\n // source (`scope`, `user`) names the key it reads, humanised.\n const own = source === 'values' || source === 'record';\n const declared =\n own && head !== undefined\n ? declaredText(\n 'field',\n (app.registry.get(resource)?.fields as Record<string, unknown> | undefined)?.[head],\n 'label',\n )\n : undefined;\n const label = resolveFieldLabel(ownerCaps, head ?? source, declared);\n return {\n filters: NO_FILTERS,\n gate: {\n kind: 'empty',\n testId,\n message: t('relationPicker.chooseFirst', {\n params: { label },\n defaultValue: `Choose ${label} first`,\n }),\n },\n };\n }\n return { filters: resolution.filters };\n}\n\n/**\n * A select's declared candidates as the shared select wiring applies them (`CandidatesRelationPicker`\n * and `useRelationPicker`): the gate, the resolved candidate filters prepended to the caller's\n * `fixedFilters`, and whether a loaded row fits them (`undefined` when no candidate filter applies).\n */\nexport function useCandidateSelection(input: {\n readonly to: string | undefined;\n readonly candidates: readonly RelationCandidate[] | undefined;\n readonly sources: ScreenSources | undefined;\n readonly resource: string;\n readonly fieldName: string;\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n}): {\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n readonly gate?: CandidatesGate;\n readonly rowFits?: (row: Record<string, unknown>) => boolean | undefined;\n} {\n const { fixedFilters } = input;\n const gate = useCandidatesGate(input);\n const filters = gate.filters;\n const combined = React.useMemo(\n () => (filters.length === 0 ? fixedFilters : [...filters, ...(fixedFilters ?? [])]),\n [filters, fixedFilters],\n );\n const rowFits = React.useMemo(\n () =>\n filters.length === 0 ? undefined : (row: Record<string, unknown>) => rowMatches(row, filters),\n [filters],\n );\n return {\n fixedFilters: combined,\n ...(gate.gate === undefined ? {} : { gate: gate.gate }),\n ...(rowFits === undefined ? {} : { rowFits }),\n };\n}\n"],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { t as FieldRelationPicker } from "./relation-picker-Z0ZJJ5uS.js";
2
+ import { t as useCandidateSelection } from "./candidates-gate-Bb70LPAy.js";
3
+ import { resourceKey } from "@burojs/core";
4
+ import { jsx } from "react/jsx-runtime";
5
+ //#region src/fields/candidates-relation-picker.tsx
6
+ function CandidatesRelationPicker(props) {
7
+ const { name, field, metaSources, resource, fixedFilters } = props;
8
+ const meta = field?.meta;
9
+ const to = resourceKey(meta.to);
10
+ const selection = useCandidateSelection({
11
+ to,
12
+ candidates: meta.candidates,
13
+ sources: metaSources,
14
+ resource: resource ?? "",
15
+ fieldName: field?.name ?? name,
16
+ fixedFilters
17
+ });
18
+ return jsx(FieldRelationPicker, {
19
+ props,
20
+ to,
21
+ extra: {
22
+ fixedFilters: selection.fixedFilters,
23
+ ...selection.gate === void 0 ? {} : { candidatesGate: selection.gate },
24
+ ...selection.rowFits === void 0 ? {} : { rowFits: selection.rowFits }
25
+ }
26
+ });
27
+ }
28
+ //#endregion
29
+ export { CandidatesRelationPicker };
30
+
31
+ //# sourceMappingURL=candidates-relation-picker-B116Bmqi.js.map
@@ -0,0 +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"}
@@ -0,0 +1,31 @@
1
+ const require_relation_picker = require("./relation-picker-gag0qSR5.cjs");
2
+ const require_candidates_gate = require("./candidates-gate-D33jXLHO.cjs");
3
+ let _burojs_core = require("@burojs/core");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ //#region src/fields/candidates-relation-picker.tsx
6
+ function CandidatesRelationPicker(props) {
7
+ const { name, field, metaSources, resource, fixedFilters } = props;
8
+ const meta = field?.meta;
9
+ const to = (0, _burojs_core.resourceKey)(meta.to);
10
+ const selection = require_candidates_gate.useCandidateSelection({
11
+ to,
12
+ candidates: meta.candidates,
13
+ sources: metaSources,
14
+ resource: resource ?? "",
15
+ fieldName: field?.name ?? name,
16
+ fixedFilters
17
+ });
18
+ return (0, react_jsx_runtime.jsx)(require_relation_picker.FieldRelationPicker, {
19
+ props,
20
+ to,
21
+ extra: {
22
+ fixedFilters: selection.fixedFilters,
23
+ ...selection.gate === void 0 ? {} : { candidatesGate: selection.gate },
24
+ ...selection.rowFits === void 0 ? {} : { rowFits: selection.rowFits }
25
+ }
26
+ });
27
+ }
28
+ //#endregion
29
+ exports.CandidatesRelationPicker = CandidatesRelationPicker;
30
+
31
+ //# sourceMappingURL=candidates-relation-picker-Cy0rTxvI.cjs.map
@@ -0,0 +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,5 +1,5 @@
1
1
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
2
- const require_toaster = require("./toaster-C7CiYA4Z.cjs");
2
+ const require_toaster = require("./toaster-Cr51X7bz.cjs");
3
3
  const require_button = require("./button-BxnnE28H.cjs");
4
4
  const require_dialog = require("./dialog-DRNUq9EA.cjs");
5
5
  let _burojs_core = require("@burojs/core");
@@ -270,10 +270,10 @@ function retrying(importer) {
270
270
  return loading;
271
271
  };
272
272
  }
273
- const loadFlowRuntime = retrying(() => Promise.resolve().then(() => require("./flow-runtime-B6zOHYqI.cjs")));
274
- const loadFlowScreen = retrying(() => Promise.resolve().then(() => require("./flow-screen-CX05b3G9.cjs")));
275
- const loadPageFlowRoute = retrying(() => Promise.resolve().then(() => require("./page-flow-route-CQ7HsbBm.cjs")));
276
- const loadInlineFlowHost = retrying(() => Promise.resolve().then(() => require("./inline-flow-host-B7U1OJUe.cjs")));
273
+ const loadFlowRuntime = retrying(() => Promise.resolve().then(() => require("./flow-runtime-D3avVH0I.cjs")));
274
+ const loadFlowScreen = retrying(() => Promise.resolve().then(() => require("./flow-screen-Ci_Sik4Y.cjs")));
275
+ const loadPageFlowRoute = retrying(() => Promise.resolve().then(() => require("./page-flow-route-hdnULWqd.cjs")));
276
+ const loadInlineFlowHost = retrying(() => Promise.resolve().then(() => require("./inline-flow-host-DV1et3c6.cjs")));
277
277
  const loadBulkSummary = retrying(() => Promise.resolve().then(() => require("./bulk-summary-CwSd6Yjb.cjs")));
278
278
  function preloadFlowRuntime() {
279
279
  loadFlowRuntime().catch(() => void 0);
@@ -824,11 +824,12 @@ function useResolvedLabel(action, actionName, children, resource) {
824
824
  if (children != null) return children;
825
825
  const raw = `actions.${actionName}`;
826
826
  const own = `resources.${resource}.${raw}`;
827
- if (caps.has(`${own}.label`)) return caps.t(`${own}.label`);
828
- if (caps.has(own)) return caps.t(own);
829
- if (action.label != null) return action.label;
830
- if (caps.has(`${raw}.label`)) return caps.t(`${raw}.label`);
831
- if (caps.has(raw)) return caps.t(raw);
827
+ const ownLabel = (0, _burojs_core.resolveContentSlot)(caps, [[`${own}.label`, own]]);
828
+ if (ownLabel !== void 0) return ownLabel;
829
+ const declared = (0, _burojs_core.declaredText)(action.kind === "flow" ? "flow" : "action", action, "label");
830
+ if (declared !== void 0) return declared;
831
+ const sharedLabel = (0, _burojs_core.resolveContentSlot)(caps, [[`${raw}.label`, raw]]);
832
+ if (sharedLabel !== void 0) return sharedLabel;
832
833
  const camel = `actions.${camelizeActionName(actionName)}`;
833
834
  if (caps.has(camel)) return caps.t(camel);
834
835
  return (0, _burojs_core.humanizeKey)(actionName);
@@ -1106,9 +1107,21 @@ function translateOrFallback(t, key, fallback, params, resource) {
1106
1107
  return translated === key ? fallback : translated;
1107
1108
  }
1108
1109
  function issueText(issue, t, resource) {
1109
- const declared = typeof issue.message.default === "string" ? issue.message.default : issue.message.key;
1110
- if (issue.params?.resolved === true) return declared;
1111
- return translateOrFallback(t, issue.message.key, declared, issue.params, resource);
1110
+ const params = issue.params;
1111
+ const checkId = params?.checkId;
1112
+ const ownCheck = typeof checkId === "string" && issue.message.key === `checks.${checkId}`;
1113
+ const declared = typeof issue.message.default === "string" ? issue.message.default : ownCheck ? void 0 : issue.message.key;
1114
+ if (issue.params?.resolved === true) return declared ?? issue.message.key;
1115
+ if (!ownCheck) return translateOrFallback(t, issue.message.key, declared ?? "", params, resource);
1116
+ const miss = "\0";
1117
+ const bundled = [`${issue.message.key}.message`, issue.message.key].map((key) => translateOrFallback(t, key, miss, params, resource)).find((text) => text !== miss);
1118
+ if (bundled !== void 0) return bundled;
1119
+ if (declared !== void 0) return declared;
1120
+ const name = String(params?.name ?? checkId);
1121
+ return translateOrFallback(t, _burojs_core.FRAMEWORK_TEXT_KEYS.checkFailed, (0, _burojs_core.checkFailedDefault)(name), {
1122
+ ...params,
1123
+ name
1124
+ }, void 0);
1112
1125
  }
1113
1126
  function checkIdOf(issue, index) {
1114
1127
  const id = issue.params?.checkId;
@@ -1531,4 +1544,4 @@ Object.defineProperty(exports, "useToBrowserHref", {
1531
1544
  }
1532
1545
  });
1533
1546
 
1534
- //# sourceMappingURL=check-confirm-dialog-BRByTFpg.cjs.map
1547
+ //# sourceMappingURL=check-confirm-dialog--gPFnEeg.cjs.map