@burojs/ui-shadcn 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) 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-CS_JZ4Fd.js +31 -0
  7. package/dist/candidates-relation-picker-CS_JZ4Fd.js.map +1 -0
  8. package/dist/candidates-relation-picker-y5M6_oe4.cjs +31 -0
  9. package/dist/candidates-relation-picker-y5M6_oe4.cjs.map +1 -0
  10. package/dist/{check-confirm-dialog-CkaVTPT9.js → check-confirm-dialog-2j0gOd7x.js} +392 -103
  11. package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
  12. package/dist/{check-confirm-dialog-BRByTFpg.cjs → check-confirm-dialog-C-NHgMST.cjs} +476 -102
  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-B3mZFL-K.cjs → filter-builder-DFu0JP-1.cjs} +959 -128
  19. package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
  20. package/dist/{filter-builder-DOnaXNfP.js → filter-builder-DaWHUZuV.js} +863 -116
  21. package/dist/filter-builder-DaWHUZuV.js.map +1 -0
  22. package/dist/{flow-runtime-B6zOHYqI.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
  23. package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
  24. package/dist/{flow-runtime-D8h99FSg.js → flow-runtime-DyqTmK3H.js} +62 -30
  25. package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
  26. package/dist/{flow-screen-CX05b3G9.cjs → flow-screen-Bcz9NF2V.cjs} +132 -88
  27. package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
  28. package/dist/{flow-screen-CmbARSqg.js → flow-screen-DCdli6Ha.js} +132 -88
  29. package/dist/flow-screen-DCdli6Ha.js.map +1 -0
  30. package/dist/index.cjs +951 -605
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +618 -332
  33. package/dist/index.d.ts +618 -332
  34. package/dist/index.js +863 -522
  35. package/dist/index.js.map +1 -1
  36. package/dist/{inline-flow-host-B7U1OJUe.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-C3H2UpSA.js → inline-flow-host-C0rI9B7f.js} +5 -5
  39. package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
  40. package/dist/label-66W1qbke.js.map +1 -1
  41. package/dist/label-w6JYf2cF.cjs.map +1 -1
  42. package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs +153 -0
  43. package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
  44. package/dist/lazy-relation-picker-dialog-CAScLPb2.js +135 -0
  45. package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
  46. package/dist/markdown/index.d.cts +2 -3
  47. package/dist/markdown/index.d.ts +2 -3
  48. package/dist/{page-flow-route-CyXSvXSE.js → page-flow-route-BHUEpn0I.js} +36 -23
  49. package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
  50. package/dist/{page-flow-route-CQ7HsbBm.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
  51. package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
  52. package/dist/{place-node-SIp4XYQH.cjs → place-node-CNb3w-c7.cjs} +2227 -999
  53. package/dist/place-node-CNb3w-c7.cjs.map +1 -0
  54. package/dist/{place-node--GdsP688.js → place-node-CfzQvh4Y.js} +2164 -984
  55. package/dist/place-node-CfzQvh4Y.js.map +1 -0
  56. package/dist/{related-list-cards-B6x9HQQp.js → related-list-cards-BIqqY69Y.js} +9 -4
  57. package/dist/{related-list-cards-B6x9HQQp.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
  58. package/dist/{related-list-cards-nxuODlIA.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
  59. package/dist/{related-list-cards-nxuODlIA.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
  60. package/dist/{related-list-timeline-DEdfd-rr.js → related-list-timeline-CRh7xwLD.js} +6 -7
  61. package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
  62. package/dist/{related-list-timeline-BYJKEbmA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
  63. package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
  64. package/dist/{related-rows-B4levHcR.js → related-rows--uP2iKQC.js} +27 -17
  65. package/dist/related-rows--uP2iKQC.js.map +1 -0
  66. package/dist/{related-rows-zh5f_4QR.cjs → related-rows-MPnLCmPF.cjs} +32 -22
  67. package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
  68. package/dist/{search-access-CURsWn-U.js → relation-create-C43cdPQt.js} +596 -29
  69. package/dist/relation-create-C43cdPQt.js.map +1 -0
  70. package/dist/{search-access-B7G5oR8n.cjs → relation-create-DDEYcKfw.cjs} +630 -32
  71. package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
  72. package/dist/{relation-many-picker-gdAOD-qK.js → relation-many-picker-BJhaEqxz.js} +210 -107
  73. package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
  74. package/dist/{relation-many-picker-B-NCEUgX.cjs → relation-many-picker-DzuGJpEl.cjs} +218 -115
  75. package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
  76. package/dist/{relation-picker-BAY77ivO.js → relation-picker-D-tBBZW_.js} +40 -45
  77. package/dist/relation-picker-D-tBBZW_.js.map +1 -0
  78. package/dist/{relation-picker-Da_uhFvA.cjs → relation-picker-DaIMzf2H.cjs} +45 -50
  79. package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
  80. package/dist/{relation-picker-dialog-M0pQaWlp.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +142 -40
  81. package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
  82. package/dist/{relation-picker-dialog-hA9rYrZB.js → relation-picker-dialog-DoEY8EkH.js} +143 -41
  83. package/dist/relation-picker-dialog-DoEY8EkH.js.map +1 -0
  84. package/dist/relation-select-B8Fq4o-t.js +48 -0
  85. package/dist/relation-select-B8Fq4o-t.js.map +1 -0
  86. package/dist/relation-select-Cr3CfNLy.cjs +55 -0
  87. package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
  88. package/dist/{resource-page-router-OSQyRA5b.cjs → resource-page-router-C_kGW2o_.cjs} +552 -303
  89. package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
  90. package/dist/{resource-page-router-T4vS5gbJ.js → resource-page-router-Diw6S6TK.js} +507 -258
  91. package/dist/resource-page-router-Diw6S6TK.js.map +1 -0
  92. package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
  93. package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
  94. package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
  95. package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
  96. package/dist/success-notices-Dl3M1fZP.cjs +46 -0
  97. package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
  98. package/dist/success-notices-LDEgEkc4.js +41 -0
  99. package/dist/success-notices-LDEgEkc4.js.map +1 -0
  100. package/dist/{toaster-C7CiYA4Z.cjs → toaster-BbByOytP.cjs} +72 -80
  101. package/dist/toaster-BbByOytP.cjs.map +1 -0
  102. package/dist/{toaster-CfCRLgR-.js → toaster-Ct_YHGs6.js} +66 -68
  103. package/dist/toaster-Ct_YHGs6.js.map +1 -0
  104. package/dist/{use-dialog-filter-state-BDcgS5Oz.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
  105. package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
  106. package/dist/{use-dialog-filter-state-BBCC0OEK.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
  107. package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
  108. package/dist/use-theme-DFlpXils.cjs.map +1 -1
  109. package/dist/use-theme-dnE3Od3I.js.map +1 -1
  110. package/package.json +11 -11
  111. package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
  112. package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
  113. package/dist/bulk-summary-GxMDP4bw.js +0 -108
  114. package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
  115. package/dist/candidates-gate-CX2PBu6l.js +0 -63
  116. package/dist/candidates-gate-CX2PBu6l.js.map +0 -1
  117. package/dist/candidates-gate-DiFI52r7.cjs +0 -70
  118. package/dist/candidates-gate-DiFI52r7.cjs.map +0 -1
  119. package/dist/candidates-relation-picker-CBsVcnPR.js +0 -82
  120. package/dist/candidates-relation-picker-CBsVcnPR.js.map +0 -1
  121. package/dist/candidates-relation-picker-Dd_GVLlu.cjs +0 -84
  122. package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +0 -1
  123. package/dist/check-confirm-dialog-BRByTFpg.cjs.map +0 -1
  124. package/dist/check-confirm-dialog-CkaVTPT9.js.map +0 -1
  125. package/dist/dialog-B_rt9S1c.js.map +0 -1
  126. package/dist/dialog-DRNUq9EA.cjs.map +0 -1
  127. package/dist/filter-builder-B3mZFL-K.cjs.map +0 -1
  128. package/dist/filter-builder-DOnaXNfP.js.map +0 -1
  129. package/dist/flow-runtime-B6zOHYqI.cjs.map +0 -1
  130. package/dist/flow-runtime-D8h99FSg.js.map +0 -1
  131. package/dist/flow-screen-CX05b3G9.cjs.map +0 -1
  132. package/dist/flow-screen-CmbARSqg.js.map +0 -1
  133. package/dist/inline-flow-host-B7U1OJUe.cjs.map +0 -1
  134. package/dist/inline-flow-host-C3H2UpSA.js.map +0 -1
  135. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +0 -14
  136. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +0 -1
  137. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +0 -19
  138. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +0 -1
  139. package/dist/page-flow-route-CQ7HsbBm.cjs.map +0 -1
  140. package/dist/page-flow-route-CyXSvXSE.js.map +0 -1
  141. package/dist/peek-filter-CnqHwTMU.cjs +0 -51
  142. package/dist/peek-filter-CnqHwTMU.cjs.map +0 -1
  143. package/dist/peek-filter-ErLfO153.js +0 -28
  144. package/dist/peek-filter-ErLfO153.js.map +0 -1
  145. package/dist/place-node--GdsP688.js.map +0 -1
  146. package/dist/place-node-SIp4XYQH.cjs.map +0 -1
  147. package/dist/related-list-timeline-BYJKEbmA.cjs.map +0 -1
  148. package/dist/related-list-timeline-DEdfd-rr.js.map +0 -1
  149. package/dist/related-rows-B4levHcR.js.map +0 -1
  150. package/dist/related-rows-zh5f_4QR.cjs.map +0 -1
  151. package/dist/relation-create-BOaUe12G.cjs +0 -362
  152. package/dist/relation-create-BOaUe12G.cjs.map +0 -1
  153. package/dist/relation-create-Bg-eEJLs.js +0 -337
  154. package/dist/relation-create-Bg-eEJLs.js.map +0 -1
  155. package/dist/relation-many-picker-B-NCEUgX.cjs.map +0 -1
  156. package/dist/relation-many-picker-gdAOD-qK.js.map +0 -1
  157. package/dist/relation-picker-BAY77ivO.js.map +0 -1
  158. package/dist/relation-picker-Da_uhFvA.cjs.map +0 -1
  159. package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +0 -1
  160. package/dist/relation-picker-dialog-hA9rYrZB.js.map +0 -1
  161. package/dist/resource-page-router-OSQyRA5b.cjs.map +0 -1
  162. package/dist/resource-page-router-T4vS5gbJ.js.map +0 -1
  163. package/dist/search-access-B7G5oR8n.cjs.map +0 -1
  164. package/dist/search-access-CURsWn-U.js.map +0 -1
  165. package/dist/shell-BPlk8hEa.js +0 -205
  166. package/dist/shell-BPlk8hEa.js.map +0 -1
  167. package/dist/shell-DxhlsPwm.cjs +0 -271
  168. package/dist/shell-DxhlsPwm.cjs.map +0 -1
  169. package/dist/toaster-C7CiYA4Z.cjs.map +0 -1
  170. package/dist/toaster-CfCRLgR-.js.map +0 -1
  171. package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +0 -1
  172. package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +0 -1
@@ -1,18 +1,29 @@
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-BbByOytP.cjs");
3
3
  const require_button = require("./button-BxnnE28H.cjs");
4
- const require_search_access = require("./search-access-B7G5oR8n.cjs");
5
- const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BfAGKzUG.cjs");
6
- const require_relation_create = require("./relation-create-BOaUe12G.cjs");
7
- const require_candidates_gate = require("./candidates-gate-DiFI52r7.cjs");
4
+ const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
5
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-Bt8lrEIu.cjs");
8
6
  let _burojs_core = require("@burojs/core");
9
7
  let _burojs_react = require("@burojs/react");
10
8
  let _tabler_icons_react = require("@tabler/icons-react");
11
9
  let react = require("react");
12
10
  react = require_use_theme.__toESM(react, 1);
13
11
  let react_jsx_runtime = require("react/jsx-runtime");
12
+ //#region src/lib/error-title.ts
13
+ function errorTitle(error, caps) {
14
+ if (error instanceof Error) return error.message;
15
+ if (error !== null && typeof error === "object") {
16
+ const { code, message } = error;
17
+ if (typeof code === "string") return (0, _burojs_react.resolveErrorText)({
18
+ code,
19
+ ...message !== null && typeof message === "object" ? { message } : {}
20
+ }, caps);
21
+ }
22
+ }
23
+ //#endregion
14
24
  //#region src/fields/relation-many-picker.tsx
15
25
  const DEBOUNCE_MS = 250;
26
+ const NO_KEYS = Object.freeze([]);
16
27
  function keysOf(value) {
17
28
  if (!Array.isArray(value)) return [];
18
29
  const seen = new Set();
@@ -26,7 +37,7 @@ function keysOf(value) {
26
37
  return out;
27
38
  }
28
39
  function RelationManyPickerInput(props) {
29
- const { name, id, value, onChange, testid, field, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, relationSeeds, fixedFilters, metaSources, resource } = props;
40
+ const { name, id, value, onChange, testid, field, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, relationSeeds, fixedFilters, metaSources, resource, link } = props;
30
41
  const meta = field?.meta;
31
42
  let to;
32
43
  try {
@@ -34,7 +45,7 @@ function RelationManyPickerInput(props) {
34
45
  } catch {
35
46
  to = void 0;
36
47
  }
37
- const gate = require_candidates_gate.useCandidatesGate({
48
+ const gate = require_lazy_relation_picker_dialog.useCandidatesGate({
38
49
  to,
39
50
  candidates: Array.isArray(meta?.candidates) ? meta.candidates : void 0,
40
51
  sources: metaSources,
@@ -54,6 +65,25 @@ function RelationManyPickerInput(props) {
54
65
  children: "—"
55
66
  })
56
67
  });
68
+ const linkRights = link?.rights;
69
+ const notAtomic = linkRights !== void 0 && [
70
+ linkRights.edit,
71
+ linkRights.attach,
72
+ linkRights.detach
73
+ ].some((right) => !right.allowed && right.reason === "not-atomic");
74
+ const denied = linkRights !== void 0 && !notAtomic && !linkRights.edit.allowed && [
75
+ "field-readonly",
76
+ "rule-denied",
77
+ "operation-absent"
78
+ ].includes(linkRights.edit.reason);
79
+ const keyRead = link?.keys;
80
+ const keyNotice = link === void 0 ? void 0 : keyRead?.error ? {
81
+ kind: "error",
82
+ error: keyRead.error
83
+ } : keyRead !== void 0 && !keyRead.isLoading && keyRead.keys !== void 0 && !keyRead.complete ? {
84
+ kind: "incomplete",
85
+ count: keyRead.keys.length
86
+ } : !link.ready ? { kind: "pending" } : void 0;
57
87
  const filters = gate.filters.length === 0 ? fixedFilters : [...gate.filters, ...fixedFilters ?? []];
58
88
  return (0, react_jsx_runtime.jsx)(ManyPicker, {
59
89
  to,
@@ -61,6 +91,7 @@ function RelationManyPickerInput(props) {
61
91
  onChange: (next) => onChange(next),
62
92
  ...typeof meta?.by === "string" ? { by: meta.by } : {},
63
93
  searchField: meta?.searchField,
94
+ ...meta?.scope === void 0 ? {} : { scope: meta.scope },
64
95
  fixedFilters: filters,
65
96
  ...gate.gate === void 0 ? {} : { gate: gate.gate },
66
97
  createSeeds: relationSeeds,
@@ -70,6 +101,14 @@ function RelationManyPickerInput(props) {
70
101
  resource: resource ?? "",
71
102
  fieldName: field?.name ?? name,
72
103
  open: (0, _burojs_core.relationOpenOf)(field ?? {}),
104
+ ...linkRights === void 0 ? {} : {
105
+ canAdd: linkRights.attach.allowed,
106
+ canRemove: linkRights.detach.allowed,
107
+ hidden: link?.hidden ?? [],
108
+ notAtomic,
109
+ readOnly: denied,
110
+ ...keyNotice === void 0 ? {} : { keyNotice }
111
+ },
73
112
  disabled,
74
113
  required,
75
114
  ariaInvalid,
@@ -77,13 +116,13 @@ function RelationManyPickerInput(props) {
77
116
  ariaErrorMessage
78
117
  });
79
118
  }
80
- function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, createSeeds, name, id, testid, resource, fieldName, open: openMode, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
119
+ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, createSeeds, name, id, testid, resource, fieldName, open: openMode, canAdd = true, canRemove = true, hidden = NO_KEYS, notAtomic = false, readOnly = false, keyNotice, scope = "context", disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
81
120
  const app = (0, _burojs_react.useApp)();
82
121
  const caps = (0, _burojs_react.useI18nCaps)();
83
122
  const t = (0, _burojs_react.useOptionalT)();
84
123
  const tid = (0, _burojs_react.useTestIds)();
85
124
  const targetDef = app.registry.get(to);
86
- const rowTitle = require_search_access.useRowTitle(to, targetDef?.displayField);
125
+ const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
87
126
  const targetLabel = (0, _burojs_core.resolveResourceLabel)(caps, to, "single", targetDef).toLowerCase();
88
127
  const childPrefix = `relation-picker:${to}`;
89
128
  const effectiveSearchField = searchField ?? targetDef?.displayField ?? "name";
@@ -116,7 +155,7 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
116
155
  const valueField = by ?? idField;
117
156
  const access = (0, _burojs_react.useListAccess)(to);
118
157
  const accessReady = access.status === "ready";
119
- const searchDecl = react.useMemo(() => require_search_access.narrowSearchDecl(targetDef?.views?.list?.search ?? { fields: [effectiveSearchField] }, (field) => access.fieldVisible(field)), [
158
+ const searchDecl = react.useMemo(() => require_relation_create.narrowSearchDecl(targetDef?.views?.list?.search ?? { fields: [effectiveSearchField] }, (field) => access.fieldVisible(field)), [
120
159
  targetDef,
121
160
  effectiveSearchField,
122
161
  access
@@ -136,20 +175,37 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
136
175
  to,
137
176
  targetDef
138
177
  ]);
139
- const blocked = !accessReady || gate !== void 0 || require_search_access.namesHiddenField(filter, (field) => access.fieldVisible(field));
178
+ const blocked = !accessReady || gate !== void 0 || require_relation_create.namesHiddenField(filter, (field) => access.fieldVisible(field));
179
+ const hiddenSet = react.useMemo(() => new Set(hidden.map(String)), [hidden]);
180
+ const visibleKeys = react.useMemo(() => keys.filter((key) => !hiddenSet.has(String(key))), [keys, hiddenSet]);
181
+ const hiddenHeld = keys.length - visibleKeys.length;
140
182
  const append = react.useCallback((next) => {
141
- if (keys.some((key) => String(key) === String(next))) return;
183
+ if (!canAdd || keys.some((key) => String(key) === String(next))) return;
142
184
  onChange([...keys, next]);
143
- }, [keys, onChange]);
185
+ }, [
186
+ keys,
187
+ onChange,
188
+ canAdd
189
+ ]);
144
190
  const toggle = react.useCallback((next) => {
145
- onChange(keys.some((key) => String(key) === String(next)) ? keys.filter((key) => String(key) !== String(next)) : [...keys, next]);
146
- }, [keys, onChange]);
191
+ const held = keys.some((key) => String(key) === String(next));
192
+ if (held ? !canRemove || hiddenSet.has(String(next)) : !canAdd) return;
193
+ onChange(held ? keys.filter((key) => String(key) !== String(next)) : [...keys, next]);
194
+ }, [
195
+ keys,
196
+ onChange,
197
+ canAdd,
198
+ canRemove,
199
+ hiddenSet
200
+ ]);
147
201
  const { create, reader: createReader } = require_relation_create.useSelectCreate({
148
202
  to,
149
203
  by,
150
204
  valueField,
151
205
  idField,
152
206
  fixedFilters,
207
+ scope,
208
+ scopeField: fieldName,
153
209
  held: gated,
154
210
  searchDecl,
155
211
  searchContext: {
@@ -168,7 +224,8 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
168
224
  page: 1,
169
225
  pageSize: 10
170
226
  },
171
- ...fixedFilters && fixedFilters.length > 0 ? { providerOptionsOverride: { ignoreScope: true } } : {},
227
+ scope,
228
+ scopeField: fieldName,
172
229
  enabled: open && targetDef != null && !blocked
173
230
  });
174
231
  const rows = listQuery.data?.data ?? [];
@@ -191,46 +248,87 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
191
248
  params: { name: targetLabel },
192
249
  defaultValue: `Select ${targetLabel}…`
193
250
  });
194
- const chips = (0, react_jsx_runtime.jsx)("div", {
251
+ const chips = visibleKeys.length === 0 && hiddenHeld === 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
195
252
  className: "flex flex-wrap items-center gap-1",
196
253
  "data-testid": `${testid}:chips`,
197
- children: keys.map((key) => (0, react_jsx_runtime.jsx)(Chip, {
198
- to,
199
- keyValue: key,
200
- by,
201
- resource,
202
- fieldName,
203
- open: openMode,
204
- testId: tid.relationManyChip(resource, fieldName, String(key)),
205
- disabled: disabled === true,
206
- ignoreScope: fixedFilters !== void 0 && fixedFilters.length > 0,
207
- focusTrigger,
208
- onRemove: () => onChange(keys.filter((entry) => String(entry) !== String(key)))
209
- }, String(key)))
254
+ children: [
255
+ visibleKeys.map((key) => (0, react_jsx_runtime.jsx)(Chip, {
256
+ to,
257
+ keyValue: key,
258
+ by,
259
+ resource,
260
+ fieldName,
261
+ open: openMode,
262
+ testId: tid.relationManyChip(resource, fieldName, String(key)),
263
+ disabled: disabled === true || !canRemove,
264
+ focusTrigger,
265
+ onRemove: () => onChange(keys.filter((entry) => String(entry) !== String(key)))
266
+ }, String(key))),
267
+ hiddenHeld > 0 ? (0, react_jsx_runtime.jsx)("span", {
268
+ "data-testid": tid.linkHidden(resource, fieldName),
269
+ className: "inline-flex items-center rounded-md border bg-secondary px-2 py-0.5 text-sm text-muted-foreground",
270
+ children: t("field.link.hidden", {
271
+ count: hiddenHeld,
272
+ defaultValue: "{{count}} not visible"
273
+ })
274
+ }) : null,
275
+ canRemove && disabled !== true && visibleKeys.length > 0 ? (0, react_jsx_runtime.jsx)("button", {
276
+ type: "button",
277
+ onClick: () => {
278
+ focusTrigger();
279
+ onChange(keys.filter((key) => hiddenSet.has(String(key))));
280
+ },
281
+ "data-testid": `${testid}:clear-all`,
282
+ className: "rounded-sm px-1 text-xs text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
283
+ children: t("relationPicker.clearAll", { defaultValue: "Clear all" })
284
+ }) : null
285
+ ]
210
286
  });
287
+ const notice = keyNotice ? (0, react_jsx_runtime.jsx)("p", {
288
+ "data-testid": `${testid}:keys-${keyNotice.kind}`,
289
+ role: keyNotice.kind === "error" ? "status" : void 0,
290
+ className: require_use_theme.cn("text-xs", keyNotice.kind === "error" ? "text-destructive" : "text-muted-foreground"),
291
+ children: keyNotice.kind === "error" ? `${t("field.link.failed", { defaultValue: "Links could not be loaded" })}: ${errorTitle(keyNotice.error, caps) ?? ""}` : keyNotice.kind === "incomplete" ? t("field.link.incomplete", {
292
+ count: keyNotice.count,
293
+ defaultValue: "More than {{count}} links"
294
+ }) : t("table.loading", { defaultValue: "Loading…" })
295
+ }) : readOnly ? (0, react_jsx_runtime.jsx)("p", {
296
+ "data-testid": `${testid}:read-only`,
297
+ className: "text-xs text-muted-foreground",
298
+ children: t("field.link.readOnly", { defaultValue: "You cannot change this link." })
299
+ }) : notAtomic ? (0, react_jsx_runtime.jsx)("p", {
300
+ "data-testid": `${testid}:not-atomic`,
301
+ className: "text-xs text-muted-foreground",
302
+ children: t("field.link.notAtomic", { defaultValue: "This link cannot be edited here: its data source does not save it with the record." })
303
+ }) : null;
211
304
  if (gate?.kind === "pending") return (0, react_jsx_runtime.jsxs)("div", {
212
305
  className: "flex flex-col gap-1.5",
213
- children: [chips, (0, react_jsx_runtime.jsxs)(require_button.Button, {
214
- type: "button",
215
- variant: "outline",
216
- disabled: true,
217
- "aria-busy": "true",
218
- "data-testid": testid,
219
- "data-buro-candidates": "pending",
220
- className: "w-full justify-between font-normal",
221
- children: [(0, react_jsx_runtime.jsx)("span", {
222
- className: "truncate text-muted-foreground",
223
- children: placeholder
224
- }), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
225
- className: "h-4 w-4 shrink-0 animate-spin opacity-50",
226
- "aria-hidden": true
227
- })]
228
- })]
306
+ children: [
307
+ chips,
308
+ notice,
309
+ (0, react_jsx_runtime.jsxs)(require_button.Button, {
310
+ type: "button",
311
+ variant: "outline",
312
+ disabled: true,
313
+ "aria-busy": "true",
314
+ "data-testid": testid,
315
+ "data-buro-candidates": "pending",
316
+ className: "w-full justify-between font-normal",
317
+ children: [(0, react_jsx_runtime.jsx)("span", {
318
+ className: "truncate text-muted-foreground",
319
+ children: placeholder
320
+ }), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
321
+ className: "h-4 w-4 shrink-0 animate-spin opacity-50",
322
+ "aria-hidden": true
323
+ })]
324
+ })
325
+ ]
229
326
  });
230
327
  if (gate?.kind === "forbidden") return (0, react_jsx_runtime.jsxs)("div", {
231
328
  className: "flex flex-col gap-1.5",
232
329
  children: [
233
330
  chips,
331
+ notice,
234
332
  (0, react_jsx_runtime.jsxs)(require_button.Button, {
235
333
  type: "button",
236
334
  variant: "outline",
@@ -261,33 +359,37 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
261
359
  children: [
262
360
  (0, react_jsx_runtime.jsxs)("div", {
263
361
  className: "flex flex-col gap-1.5",
264
- children: [chips, (0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
265
- asChild: true,
266
- children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
267
- ref: triggerRef,
268
- type: "button",
269
- variant: "outline",
270
- role: "combobox",
271
- "aria-expanded": open,
272
- "aria-haspopup": "listbox",
273
- "aria-required": required,
274
- "aria-invalid": ariaInvalid || void 0,
275
- "aria-describedby": ariaDescribedBy,
276
- ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
277
- disabled,
278
- "data-testid": testid,
279
- name,
280
- id,
281
- className: "w-full justify-between font-normal",
282
- children: [(0, react_jsx_runtime.jsx)("span", {
283
- className: "truncate text-left text-muted-foreground",
284
- children: placeholder
285
- }), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, {
286
- className: "h-4 w-4 shrink-0 opacity-50",
287
- "aria-hidden": true
288
- })]
362
+ children: [
363
+ chips,
364
+ notice,
365
+ (0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
366
+ asChild: true,
367
+ children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
368
+ ref: triggerRef,
369
+ type: "button",
370
+ variant: "outline",
371
+ role: "combobox",
372
+ "aria-expanded": open,
373
+ "aria-haspopup": "listbox",
374
+ "aria-required": required,
375
+ "aria-invalid": ariaInvalid || void 0,
376
+ "aria-describedby": ariaDescribedBy,
377
+ ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
378
+ disabled,
379
+ "data-testid": testid,
380
+ name,
381
+ id,
382
+ className: "w-full justify-between font-normal",
383
+ children: [(0, react_jsx_runtime.jsx)("span", {
384
+ className: "truncate text-left text-muted-foreground",
385
+ children: placeholder
386
+ }), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, {
387
+ className: "h-4 w-4 shrink-0 opacity-50",
388
+ "aria-hidden": true
389
+ })]
390
+ })
289
391
  })
290
- })]
392
+ ]
291
393
  }),
292
394
  (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
293
395
  className: "w-[var(--radix-popover-trigger-width)] p-0",
@@ -296,10 +398,10 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
296
398
  className: "px-3 py-6 text-center text-sm text-muted-foreground",
297
399
  "data-testid": gate.testId,
298
400
  children: gate.message
299
- }) : (0, react_jsx_runtime.jsxs)(require_search_access.Command, {
401
+ }) : (0, react_jsx_runtime.jsxs)(require_relation_create.Command, {
300
402
  shouldFilter: false,
301
403
  children: [
302
- searchDecl !== void 0 && (0, react_jsx_runtime.jsx)(require_search_access.CommandInput, {
404
+ searchDecl !== void 0 && canAdd && (0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
303
405
  value: search,
304
406
  onValueChange: setSearch,
305
407
  placeholder: t("toolbar.search", {
@@ -312,9 +414,10 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
312
414
  defaultValue: `Search ${targetLabel}`
313
415
  }),
314
416
  onKeyDown: (event) => {
315
- if (event.key === "Backspace" && search === "" && keys.length > 0) {
417
+ if (event.key === "Backspace" && search === "" && canRemove) {
316
418
  event.preventDefault();
317
- onChange(keys.slice(0, -1));
419
+ const last = visibleKeys.at(-1);
420
+ if (last !== void 0) onChange(keys.filter((key) => String(key) !== String(last)));
318
421
  }
319
422
  if (event.key === " " && search === "") {
320
423
  event.preventDefault();
@@ -322,7 +425,7 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
322
425
  }
323
426
  }
324
427
  }),
325
- (0, react_jsx_runtime.jsxs)(require_search_access.CommandList, {
428
+ (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, {
326
429
  "data-testid": `${childPrefix}:list`,
327
430
  "aria-multiselectable": "true",
328
431
  "aria-label": targetLabel,
@@ -335,13 +438,17 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
335
438
  "aria-hidden": true
336
439
  }), (0, react_jsx_runtime.jsx)("span", { children: t("table.loading", { defaultValue: "Loading…" }) })]
337
440
  }),
338
- !isLoading && error && (0, react_jsx_runtime.jsx)("div", {
339
- className: "px-3 py-6 text-center text-sm text-muted-foreground",
340
- "data-testid": `${childPrefix}:error`,
341
- title: error.message,
342
- children: t("relation.failed", { defaultValue: "Failed to load options." })
441
+ !isLoading && error && (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
442
+ surface: "picker",
443
+ error,
444
+ testId: `${childPrefix}:error`,
445
+ className: "block px-3 py-6 text-center text-sm text-muted-foreground",
446
+ fallback: {
447
+ key: "relation.failed",
448
+ default: "Failed to load options."
449
+ }
343
450
  }),
344
- !isLoading && !error && rows.length === 0 && (0, react_jsx_runtime.jsx)(require_search_access.CommandEmpty, {
451
+ !isLoading && !error && rows.length === 0 && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, {
345
452
  "data-testid": `${childPrefix}:empty`,
346
453
  children: t("relation.noResults", { defaultValue: "No results." })
347
454
  }),
@@ -351,10 +458,11 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
351
458
  const idStr = String(rowValue);
352
459
  const label = rowTitle(row);
353
460
  const chosen = keys.some((key) => String(key) === idStr);
354
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
461
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
355
462
  value: `${label} ${idStr}`,
356
463
  "data-testid": `${childPrefix}:option:${idStr}`,
357
464
  "aria-checked": chosen,
465
+ disabled: chosen ? !canRemove : !canAdd,
358
466
  onSelect: () => toggle(rowValue),
359
467
  children: [
360
468
  (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, {
@@ -376,7 +484,7 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
376
484
  }),
377
485
  (0, react_jsx_runtime.jsxs)("div", {
378
486
  className: "flex items-center justify-between gap-2 border-t px-3 py-2 text-sm",
379
- children: [(0, react_jsx_runtime.jsx)("button", {
487
+ children: [canAdd ? (0, react_jsx_runtime.jsx)("button", {
380
488
  type: "button",
381
489
  onClick: () => {
382
490
  setOpen(false);
@@ -385,7 +493,7 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
385
493
  "data-testid": `${childPrefix}:advanced`,
386
494
  className: "text-foreground hover:underline focus:outline-hidden focus-visible:underline",
387
495
  children: t("relationPicker.advancedSearch", { defaultValue: "Advanced search" })
388
- }), !disabled && (0, react_jsx_runtime.jsx)(require_relation_create.RelationCreateButton, {
496
+ }) : (0, react_jsx_runtime.jsx)("span", {}), !disabled && canAdd && (0, react_jsx_runtime.jsx)(require_relation_create.RelationCreateButton, {
389
497
  to,
390
498
  fieldName,
391
499
  create,
@@ -401,7 +509,7 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
401
509
  ]
402
510
  })
403
511
  }),
404
- dialogMounted && !gated && (0, react_jsx_runtime.jsx)(require_lazy_relation_picker_dialog.LazyRelationPickerDialog, {
512
+ dialogMounted && !gated && canAdd && (0, react_jsx_runtime.jsx)(require_lazy_relation_picker_dialog.LazyRelationPickerDialog, {
405
513
  to,
406
514
  open: dialogOpen,
407
515
  onOpenChange: setDialogOpen,
@@ -412,6 +520,8 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
412
520
  valueField,
413
521
  searchField,
414
522
  fixedFilters,
523
+ scope,
524
+ scopeField: fieldName,
415
525
  ...disabled ? {} : { create },
416
526
  createSeeds,
417
527
  fieldName,
@@ -421,45 +531,38 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
421
531
  ]
422
532
  });
423
533
  }
424
- function Chip({ to, keyValue, by, resource, fieldName, testId, open: openMode, disabled, ignoreScope, focusTrigger, onRemove }) {
534
+ function Chip({ to, keyValue, by, resource, fieldName, testId, open: openMode, disabled, focusTrigger, onRemove }) {
425
535
  const t = (0, _burojs_react.useOptionalT)();
426
536
  const targetDef = (0, _burojs_react.useApp)().registry.get(to);
427
- const rowTitle = require_search_access.useRowTitle(to, targetDef?.displayField);
537
+ const rowTitle = require_relation_create.useRowTitle(to, targetDef?.displayField);
428
538
  const { record, isLoading } = (0, _burojs_react.useRelatedRecord)(to, keyValue, by === void 0 ? void 0 : { by });
429
539
  const title = record ? rowTitle(record) : String(keyValue);
430
540
  return (0, react_jsx_runtime.jsxs)("span", {
431
541
  "data-testid": testId,
432
542
  "data-resource": resource,
433
543
  className: "inline-flex items-center gap-0.5 rounded-md border bg-secondary pl-2 text-sm text-secondary-foreground",
434
- children: [
435
- (0, react_jsx_runtime.jsx)("span", {
436
- className: "max-w-[16rem] truncate",
437
- children: isLoading ? t("table.loading", { defaultValue: "Loading…" }) : title
438
- }),
439
- (0, react_jsx_runtime.jsx)(require_relation_create.RelationViewButton, {
440
- to,
441
- value: keyValue,
442
- by,
443
- ignoreScope,
444
- fieldName: `${fieldName}:${String(keyValue)}`,
445
- beforeOpen: focusTrigger,
446
- open: openMode
447
- }),
448
- !disabled && (0, react_jsx_runtime.jsx)("button", {
449
- type: "button",
450
- onClick: onRemove,
451
- "data-testid": `${testId}:remove`,
452
- "aria-label": `${t("relationPicker.clear", { defaultValue: "Clear" })} ${title}`,
453
- className: "inline-flex size-6 items-center justify-center rounded-sm text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
454
- children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
455
- className: "size-3.5",
456
- "aria-hidden": true
457
- })
544
+ children: [(0, react_jsx_runtime.jsx)(require_relation_create.RelationViewButton, {
545
+ to,
546
+ value: keyValue,
547
+ by,
548
+ fieldName: `${fieldName}:${String(keyValue)}`,
549
+ beforeOpen: focusTrigger,
550
+ open: openMode,
551
+ title: isLoading ? t("table.loading", { defaultValue: "Loading…" }) : title
552
+ }), !disabled && (0, react_jsx_runtime.jsx)("button", {
553
+ type: "button",
554
+ onClick: onRemove,
555
+ "data-testid": `${testId}:remove`,
556
+ "aria-label": `${t("relationPicker.clear", { defaultValue: "Clear" })} ${title}`,
557
+ className: "inline-flex size-6 items-center justify-center rounded-sm text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
558
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
559
+ className: "size-3.5",
560
+ "aria-hidden": true
458
561
  })
459
- ]
562
+ })]
460
563
  });
461
564
  }
462
565
  //#endregion
463
566
  exports.RelationManyPickerInput = RelationManyPickerInput;
464
567
 
465
- //# sourceMappingURL=relation-many-picker-B-NCEUgX.cjs.map
568
+ //# sourceMappingURL=relation-many-picker-DzuGJpEl.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-many-picker-DzuGJpEl.cjs","names":["resolveErrorText","selectKey","resourceKey","useCandidatesGate","Button","relationOpenOf","useApp","useI18nCaps","useOptionalT","useTestIds","useRowTitle","resolveResourceLabel","React","useListAccess","narrowSearchDecl","composeListFilter","normalizeFixedFilters","namesHiddenField","useSelectCreate","useList","cn","IconLoader2","IconChevronDown","Popover","PopoverTrigger","PopoverContent","Command","CommandInput","CommandList","LoadError","CommandEmpty","CommandItem","IconCheck","RelationCreateButton","LazyRelationPickerDialog","useRelatedRecord","RelationViewButton","IconX"],"sources":["../src/lib/error-title.ts","../src/fields/relation-many-picker.tsx"],"sourcesContent":["import { type ErrorTextCaps, resolveErrorText } from '@burojs/react';\n\n/**\n * The text a user may read for a failure a hook handed to the kit as an `Error`-typed value.\n * The value is a `DataError` at runtime when it came from a data provider (its `message` is a\n * reference, so it is resolved through the bundle) and a plain `Error` when the framework raised\n * it (its `message` is already a sentence). Anything else has nothing to show.\n */\nexport function errorTitle(error: unknown, caps: ErrorTextCaps): string | undefined {\n if (error instanceof Error) return error.message;\n if (error !== null && typeof error === 'object') {\n const { code, message } = error as { readonly code?: unknown; readonly message?: unknown };\n if (typeof code === 'string') {\n return resolveErrorText(\n {\n code,\n ...(message !== null && typeof message === 'object' ? { message } : {}),\n } as Parameters<typeof resolveErrorText>[0],\n caps,\n );\n }\n }\n return undefined;\n}\n","'use client';\n\nimport {\n type ErasedResourceHandle,\n type FilterExpression,\n type FixedFilterInput,\n type RelationCandidate,\n type RelationOpen,\n relationOpenOf,\n type ResourceRefInput,\n type ScopeSource,\n type SearchDecl,\n composeListFilter,\n normalizeFixedFilters,\n resolveResourceLabel,\n resourceKey,\n} from '@burojs/core';\nimport {\n useApp,\n useI18nCaps,\n useList,\n useListAccess,\n useOptionalT,\n useRelatedRecord,\n useTestIds,\n} from '@burojs/react';\nimport { errorTitle } from '../lib/error-title.js';\nimport { LoadError } from '../load-error/load-error-view.js';\nimport { IconCheck, IconChevronDown, IconLoader2, IconX } from '@tabler/icons-react';\nimport * as React from 'react';\nimport { cn } from '../lib/cn.js';\nimport { Button } from '../primitives/button.js';\nimport {\n Command,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n} from '../primitives/command.js';\nimport { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover.js';\nimport { useRowTitle } from '../resource/use-row-title.js';\nimport { useCandidatesGate } from './candidates-gate.js';\nimport { RelationCreateButton, useSelectCreate } from './relation-create.js';\nimport { LazyRelationPickerDialog } from './lazy-relation-picker-dialog.js';\nimport { RelationViewButton, selectKey } from './relation-view-button.js';\nimport type { FieldInputProps } from './registry.js';\nimport { namesHiddenField, narrowSearchDecl } from './search-access.js';\n\ntype ErasedExpression = FilterExpression<ErasedResourceHandle>;\ntype Key = string | number;\n\nconst DEBOUNCE_MS = 250;\nconst NO_KEYS: readonly Key[] = Object.freeze([]);\n\n/** The keys a to-many field holds: strings and finite numbers, the user's order, no repeats. */\nfunction keysOf(value: unknown): readonly Key[] {\n if (!Array.isArray(value)) return [];\n const seen = new Set<string>();\n const out: Key[] = [];\n for (const entry of value) {\n const key = selectKey(entry);\n if (key === null || seen.has(key)) continue;\n seen.add(key);\n out.push(entry as Key);\n }\n return out;\n}\n\n/**\n * Form input of `f.relationMany` (P7 3.5): the chosen rows as chips (titles through the relation\n * aggregator, one batched read), a popover that searches the same option query a single select\n * does (candidates, field access and the create hand-back included), \"Advanced search\" in a\n * multiple-choice dialog, a \"view\" on every chip and \"+ create\" that appends what it created.\n * The value is `row[by ?? id]` for each chosen row. Loaded lazily: it is not on any screen's\n * first paint.\n */\nexport function RelationManyPickerInput(props: FieldInputProps): React.ReactElement {\n const {\n name,\n id,\n value,\n onChange,\n testid,\n field,\n disabled,\n required,\n ariaInvalid,\n ariaDescribedBy,\n ariaErrorMessage,\n relationSeeds,\n fixedFilters,\n metaSources,\n resource,\n link,\n } = props;\n const meta = field?.meta as\n | {\n to?: ResourceRefInput;\n by?: unknown;\n searchField?: string;\n candidates?: unknown;\n scope?: ScopeSource;\n }\n | undefined;\n let to: string | undefined;\n try {\n to = meta?.to === undefined ? undefined : resourceKey(meta.to);\n } catch {\n to = undefined;\n }\n const gate = useCandidatesGate({\n to,\n candidates: Array.isArray(meta?.candidates)\n ? (meta.candidates as readonly RelationCandidate[])\n : undefined,\n sources: metaSources,\n resource: resource ?? '',\n fieldName: field?.name ?? name,\n });\n if (!to) {\n return (\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n data-testid={`${testid ?? `relation-many:${name}`}:no-target`}\n className=\"w-full justify-between font-normal\"\n name={name}\n id={id}\n >\n <span className=\"truncate text-muted-foreground\">—</span>\n </Button>\n );\n }\n // An inline link: the form controller's rights decide what the select offers, and the keys the\n // user cannot see ride along in the value. A link denied `not-atomic` is read-only with a notice.\n const linkRights = link?.rights;\n const notAtomic =\n linkRights !== undefined &&\n [linkRights.edit, linkRights.attach, linkRights.detach].some(\n (right) => !right.allowed && right.reason === 'not-atomic',\n );\n const denied =\n linkRights !== undefined &&\n !notAtomic &&\n !linkRights.edit.allowed &&\n ['field-readonly', 'rule-denied', 'operation-absent'].includes(linkRights.edit.reason);\n // The form holds a link's keys only once they are read whole: a failed or capped read, or one\n // still running, leaves the field read-only, and the user is told why.\n const keyRead = link?.keys;\n const keyNotice: KeyNotice | undefined =\n link === undefined\n ? undefined\n : keyRead?.error\n ? { kind: 'error', error: keyRead.error }\n : keyRead !== undefined &&\n !keyRead.isLoading &&\n keyRead.keys !== undefined &&\n !keyRead.complete\n ? { kind: 'incomplete', count: keyRead.keys.length }\n : !link.ready\n ? { kind: 'pending' }\n : undefined;\n const filters =\n gate.filters.length === 0 ? fixedFilters : [...gate.filters, ...(fixedFilters ?? [])];\n return (\n <ManyPicker\n to={to}\n keys={keysOf(value)}\n onChange={(next) => onChange(next)}\n {...(typeof meta?.by === 'string' ? { by: meta.by } : {})}\n searchField={meta?.searchField}\n {...(meta?.scope === undefined ? {} : { scope: meta.scope })}\n fixedFilters={filters}\n {...(gate.gate === undefined ? {} : { gate: gate.gate })}\n createSeeds={relationSeeds}\n name={name}\n id={id}\n testid={testid ?? `relation-many:${to}`}\n resource={resource ?? ''}\n fieldName={field?.name ?? name}\n open={relationOpenOf(field ?? {})}\n {...(linkRights === undefined\n ? {}\n : {\n canAdd: linkRights.attach.allowed,\n canRemove: linkRights.detach.allowed,\n hidden: link?.hidden ?? [],\n notAtomic,\n readOnly: denied,\n ...(keyNotice === undefined ? {} : { keyNotice }),\n })}\n disabled={disabled}\n required={required}\n ariaInvalid={ariaInvalid}\n ariaDescribedBy={ariaDescribedBy}\n ariaErrorMessage={ariaErrorMessage}\n />\n );\n}\n\n/** Why a link whose keys the form does not hold whole is read-only. */\ntype KeyNotice =\n | { readonly kind: 'error'; readonly error: unknown }\n | { readonly kind: 'incomplete'; readonly count: number }\n | { readonly kind: 'pending' };\n\ninterface ManyPickerProps {\n readonly to: string;\n readonly keys: readonly Key[];\n readonly onChange: (next: readonly Key[]) => void;\n readonly by?: string;\n readonly searchField?: string | undefined;\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n readonly gate?: import('./candidates-gate.js').CandidatesGate;\n readonly createSeeds: Readonly<Record<string, unknown>> | undefined;\n readonly name: string;\n readonly id: string | undefined;\n readonly testid: string;\n readonly resource: string;\n readonly fieldName: string;\n readonly open: RelationOpen;\n /** False: no search box, no \"Advanced search\", no create, and no key can be added. Default true. */\n readonly canAdd?: boolean;\n /** False: no chip remove button, no Backspace removal, no clear-all. Default true. */\n readonly canRemove?: boolean;\n /**\n * Keys of `keys` whose target the user cannot see: one \"N not visible\" chip stands for them, it\n * has no remove button, and neither Backspace nor clear-all drops them.\n */\n readonly hidden?: readonly Key[];\n /** The link is edited with the record but its provider does not write it so: read-only, say so. */\n readonly notAtomic?: boolean;\n /** The user may see the link but not change it: say so. */\n readonly readOnly?: boolean;\n /** The link's keys are not held whole (failed, cut at the read cap, or still loading). */\n readonly keyNotice?: KeyNotice;\n /**\n * The read scope of the option reads (popover, dialog, create hand-back). Default `'context'`:\n * the record around the select narrows them, except by the field the select writes.\n */\n readonly scope?: ScopeSource;\n readonly disabled: boolean | undefined;\n readonly required: boolean | undefined;\n readonly ariaInvalid: boolean | undefined;\n readonly ariaDescribedBy: string | undefined;\n readonly ariaErrorMessage: string | undefined;\n}\n\nfunction ManyPicker({\n to,\n keys,\n onChange,\n by,\n searchField,\n fixedFilters,\n gate,\n createSeeds,\n name,\n id,\n testid,\n resource,\n fieldName,\n open: openMode,\n canAdd = true,\n canRemove = true,\n hidden = NO_KEYS,\n notAtomic = false,\n readOnly = false,\n keyNotice,\n scope = 'context',\n disabled,\n required,\n ariaInvalid,\n ariaDescribedBy,\n ariaErrorMessage,\n}: ManyPickerProps): React.ReactElement {\n const app = useApp();\n const caps = useI18nCaps();\n const t = useOptionalT();\n const tid = useTestIds();\n const targetDef = app.registry.get(to);\n const rowTitle = useRowTitle(to, targetDef?.displayField);\n const targetLabel = resolveResourceLabel(caps, to, 'single', targetDef).toLowerCase();\n const childPrefix = `relation-picker:${to}`;\n const effectiveSearchField = searchField ?? targetDef?.displayField ?? 'name';\n const [open, setOpen] = React.useState(false);\n const [dialogOpen, setDialogOpen] = React.useState(false);\n // Mounted on the first open, and only while no candidates gate holds the read: without the\n // candidate filters the dialog would list rows the field must not offer.\n const gated = gate !== undefined;\n const [dialogMounted, setDialogMounted] = React.useState(false);\n React.useEffect(() => {\n if (gated) setDialogOpen(false);\n }, [gated]);\n React.useEffect(() => {\n if (dialogOpen) setDialogMounted(true);\n }, [dialogOpen]);\n const [search, setSearch] = React.useState('');\n const [debouncedSearch, setDebouncedSearch] = React.useState('');\n const triggerRef = React.useRef<HTMLButtonElement | null>(null);\n const focusTrigger = React.useCallback(() => triggerRef.current?.focus(), []);\n\n React.useEffect(() => {\n const handle = setTimeout(() => setDebouncedSearch(search), DEBOUNCE_MS);\n return () => clearTimeout(handle);\n }, [search]);\n React.useEffect(() => {\n if (!open) {\n setSearch('');\n setDebouncedSearch('');\n }\n }, [open]);\n\n const targetIdField = (targetDef?.data as { readonly idField?: unknown } | undefined)?.idField;\n const idField =\n typeof targetIdField === 'string' && targetIdField.length > 0 ? targetIdField : 'id';\n const valueField = by ?? idField;\n const access = useListAccess(to);\n const accessReady = access.status === 'ready';\n const searchDecl = React.useMemo<SearchDecl | undefined>(\n () =>\n narrowSearchDecl(\n targetDef?.views?.list?.search ?? { fields: [effectiveSearchField] },\n (field) => access.fieldVisible(field),\n ),\n [targetDef, effectiveSearchField, access],\n );\n const filter = React.useMemo<ErasedExpression | undefined>(\n () =>\n composeListFilter({\n fixed: normalizeFixedFilters(fixedFilters),\n search: debouncedSearch,\n searchDecl,\n searchContext: { resource: to, def: targetDef },\n }),\n [fixedFilters, debouncedSearch, searchDecl, to, targetDef],\n );\n const blocked =\n !accessReady ||\n gate !== undefined ||\n namesHiddenField(filter, (field) => access.fieldVisible(field));\n\n const hiddenSet = React.useMemo(() => new Set(hidden.map(String)), [hidden]);\n const visibleKeys = React.useMemo(\n () => keys.filter((key) => !hiddenSet.has(String(key))),\n [keys, hiddenSet],\n );\n const hiddenHeld = keys.length - visibleKeys.length;\n const append = React.useCallback(\n (next: Key) => {\n if (!canAdd || keys.some((key) => String(key) === String(next))) return;\n onChange([...keys, next]);\n },\n [keys, onChange, canAdd],\n );\n const toggle = React.useCallback(\n (next: Key) => {\n const held = keys.some((key) => String(key) === String(next));\n if (held ? !canRemove || hiddenSet.has(String(next)) : !canAdd) return;\n onChange(held ? keys.filter((key) => String(key) !== String(next)) : [...keys, next]);\n },\n [keys, onChange, canAdd, canRemove, hiddenSet],\n );\n const { create, reader: createReader } = useSelectCreate({\n to,\n by,\n valueField,\n idField,\n fixedFilters,\n scope,\n scopeField: fieldName,\n held: gated,\n searchDecl,\n searchContext: { resource: to, def: targetDef },\n // What was created and fits is appended, as a pick would be; the dialog it came from is done.\n onValue: (picked) => {\n append(picked);\n setDialogOpen(false);\n },\n });\n\n const listQuery = useList(to, {\n ...(filter ? { filter } : {}),\n pagination: { kind: 'offset', page: 1, pageSize: 10 },\n scope,\n scopeField: fieldName,\n enabled: open && targetDef != null && !blocked,\n });\n const rows = (listQuery.data?.data ?? []) as Array<Record<string, unknown>>;\n const isLoading = listQuery.isLoading || listQuery.isFetching;\n const error = listQuery.isError ? (listQuery.error as unknown as Error) : null;\n\n if (!targetDef) {\n return (\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n data-testid={`${childPrefix}:unregistered`}\n className=\"w-full justify-between font-normal\"\n name={name}\n id={id}\n >\n <span className=\"truncate text-muted-foreground\">{keys.map(String).join(', ') || '—'}</span>\n </Button>\n );\n }\n\n const placeholder = t('relation.select', {\n params: { name: targetLabel },\n defaultValue: `Select ${targetLabel}…`,\n });\n // Nothing held, nothing drawn: an empty row would still take the column's gap above the trigger.\n const chips =\n visibleKeys.length === 0 && hiddenHeld === 0 ? null : (\n <div className=\"flex flex-wrap items-center gap-1\" data-testid={`${testid}:chips`}>\n {visibleKeys.map((key) => (\n <Chip\n key={String(key)}\n to={to}\n keyValue={key}\n by={by}\n resource={resource}\n fieldName={fieldName}\n open={openMode}\n testId={tid.relationManyChip(resource, fieldName, String(key))}\n disabled={disabled === true || !canRemove}\n focusTrigger={focusTrigger}\n onRemove={() => onChange(keys.filter((entry) => String(entry) !== String(key)))}\n />\n ))}\n {hiddenHeld > 0 ? (\n <span\n data-testid={tid.linkHidden(resource, fieldName)}\n className=\"inline-flex items-center rounded-md border bg-secondary px-2 py-0.5 text-sm text-muted-foreground\"\n >\n {t('field.link.hidden', {\n count: hiddenHeld,\n defaultValue: '{{count}} not visible',\n })}\n </span>\n ) : null}\n {canRemove && disabled !== true && visibleKeys.length > 0 ? (\n <button\n type=\"button\"\n onClick={() => {\n // The button leaves with the chips it clears: focus goes where chip removal sends it.\n focusTrigger();\n onChange(keys.filter((key) => hiddenSet.has(String(key))));\n }}\n data-testid={`${testid}:clear-all`}\n className=\"rounded-sm px-1 text-xs text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\"\n >\n {t('relationPicker.clearAll', { defaultValue: 'Clear all' })}\n </button>\n ) : null}\n </div>\n );\n const notice = keyNotice ? (\n <p\n data-testid={`${testid}:keys-${keyNotice.kind}`}\n role={keyNotice.kind === 'error' ? 'status' : undefined}\n className={cn(\n 'text-xs',\n keyNotice.kind === 'error' ? 'text-destructive' : 'text-muted-foreground',\n )}\n >\n {keyNotice.kind === 'error'\n ? `${t('field.link.failed', { defaultValue: 'Links could not be loaded' })}: ${errorTitle(keyNotice.error, caps) ?? ''}`\n : keyNotice.kind === 'incomplete'\n ? t('field.link.incomplete', {\n count: keyNotice.count,\n defaultValue: 'More than {{count}} links',\n })\n : t('table.loading', { defaultValue: 'Loading…' })}\n </p>\n ) : readOnly ? (\n <p data-testid={`${testid}:read-only`} className=\"text-xs text-muted-foreground\">\n {t('field.link.readOnly', { defaultValue: 'You cannot change this link.' })}\n </p>\n ) : notAtomic ? (\n <p data-testid={`${testid}:not-atomic`} className=\"text-xs text-muted-foreground\">\n {t('field.link.notAtomic', {\n defaultValue:\n 'This link cannot be edited here: its data source does not save it with the record.',\n })}\n </p>\n ) : null;\n\n if (gate?.kind === 'pending')\n return (\n <div className=\"flex flex-col gap-1.5\">\n {chips}\n {notice}\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n aria-busy=\"true\"\n data-testid={testid}\n data-buro-candidates=\"pending\"\n className=\"w-full justify-between font-normal\"\n >\n <span className=\"truncate text-muted-foreground\">{placeholder}</span>\n <IconLoader2 className=\"h-4 w-4 shrink-0 animate-spin opacity-50\" aria-hidden />\n </Button>\n </div>\n );\n if (gate?.kind === 'forbidden')\n return (\n <div className=\"flex flex-col gap-1.5\">\n {chips}\n {notice}\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n data-testid={testid}\n data-buro-candidates=\"forbidden\"\n aria-describedby={gate.testId}\n className=\"w-full justify-between font-normal\"\n >\n <span className=\"truncate text-muted-foreground\">{placeholder}</span>\n <IconChevronDown className=\"h-4 w-4 shrink-0 opacity-50\" aria-hidden />\n </Button>\n <p id={gate.testId} data-testid={gate.testId} className=\"text-xs text-muted-foreground\">\n {gate.message}\n </p>\n </div>\n );\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <div className=\"flex flex-col gap-1.5\">\n {chips}\n {notice}\n <PopoverTrigger asChild>\n <Button\n ref={triggerRef}\n type=\"button\"\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-required={required}\n aria-invalid={ariaInvalid || undefined}\n aria-describedby={ariaDescribedBy}\n {...(ariaErrorMessage ? { 'aria-errormessage': ariaErrorMessage } : {})}\n disabled={disabled}\n data-testid={testid}\n name={name}\n id={id}\n className=\"w-full justify-between font-normal\"\n >\n <span className=\"truncate text-left text-muted-foreground\">{placeholder}</span>\n <IconChevronDown className=\"h-4 w-4 shrink-0 opacity-50\" aria-hidden />\n </Button>\n </PopoverTrigger>\n </div>\n <PopoverContent className=\"w-[var(--radix-popover-trigger-width)] p-0\" align=\"start\">\n {gate?.kind === 'empty' ? (\n <p\n className=\"px-3 py-6 text-center text-sm text-muted-foreground\"\n data-testid={gate.testId}\n >\n {gate.message}\n </p>\n ) : (\n <Command shouldFilter={false}>\n {searchDecl !== undefined && canAdd && (\n <CommandInput\n value={search}\n onValueChange={setSearch}\n placeholder={t('toolbar.search', {\n params: { name: targetLabel },\n defaultValue: `Search ${targetLabel}…`,\n })}\n data-testid={`${childPrefix}:search`}\n aria-label={t('toolbar.search', {\n params: { name: targetLabel },\n defaultValue: `Search ${targetLabel}`,\n })}\n onKeyDown={(event) => {\n // Backspace in an empty search takes the last chip off.\n if (event.key === 'Backspace' && search === '' && canRemove) {\n event.preventDefault();\n const last = visibleKeys.at(-1);\n if (last !== undefined)\n onChange(keys.filter((key) => String(key) !== String(last)));\n }\n // Space toggles the highlighted option while nothing is typed.\n if (event.key === ' ' && search === '') {\n event.preventDefault();\n document\n .querySelector<HTMLElement>(\n `[data-testid=\"${childPrefix}:list\"] [aria-selected=\"true\"]`,\n )\n ?.click();\n }\n }}\n />\n )}\n <CommandList\n data-testid={`${childPrefix}:list`}\n aria-multiselectable=\"true\"\n aria-label={targetLabel}\n >\n {isLoading && (\n <div\n className=\"flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground\"\n data-testid={`${childPrefix}:loading`}\n >\n <IconLoader2 className=\"h-4 w-4 animate-spin\" aria-hidden />\n <span>{t('table.loading', { defaultValue: 'Loading…' })}</span>\n </div>\n )}\n {!isLoading && error && (\n <LoadError\n surface=\"picker\"\n error={error}\n testId={`${childPrefix}:error`}\n className=\"block px-3 py-6 text-center text-sm text-muted-foreground\"\n fallback={{ key: 'relation.failed', default: 'Failed to load options.' }}\n />\n )}\n {!isLoading && !error && rows.length === 0 && (\n <CommandEmpty data-testid={`${childPrefix}:empty`}>\n {t('relation.noResults', { defaultValue: 'No results.' })}\n </CommandEmpty>\n )}\n {!isLoading &&\n !error &&\n rows.map((row) => {\n const rowValue = row[valueField];\n if (rowValue === null || rowValue === undefined || rowValue === '') return null;\n const idStr = String(rowValue);\n const label = rowTitle(row);\n const chosen = keys.some((key) => String(key) === idStr);\n return (\n <CommandItem\n key={idStr}\n value={`${label} ${idStr}`}\n data-testid={`${childPrefix}:option:${idStr}`}\n aria-checked={chosen}\n disabled={chosen ? !canRemove : !canAdd}\n onSelect={() => toggle(rowValue as Key)}\n >\n <IconCheck\n className={cn(\n 'mr-2 h-4 w-4 shrink-0',\n chosen ? 'opacity-100' : 'opacity-0',\n )}\n aria-hidden\n />\n <span className=\"truncate\">{label}</span>\n {/* A label that already is the id would print it twice (REF-40). */}\n {label === idStr ? null : (\n <span className=\"ml-auto shrink-0 pl-2 text-xs text-muted-foreground\">\n #{idStr}\n </span>\n )}\n </CommandItem>\n );\n })}\n </CommandList>\n <div className=\"flex items-center justify-between gap-2 border-t px-3 py-2 text-sm\">\n {canAdd ? (\n <button\n type=\"button\"\n onClick={() => {\n setOpen(false);\n setDialogOpen(true);\n }}\n data-testid={`${childPrefix}:advanced`}\n className=\"text-foreground hover:underline focus:outline-hidden focus-visible:underline\"\n >\n {t('relationPicker.advancedSearch', { defaultValue: 'Advanced search' })}\n </button>\n ) : (\n <span />\n )}\n {!disabled && canAdd && (\n <RelationCreateButton\n to={to}\n fieldName={fieldName}\n create={create}\n seeds={createSeeds}\n search={search}\n beforeOpen={() => {\n setOpen(false);\n focusTrigger();\n }}\n className=\"text-foreground hover:underline focus:outline-hidden focus-visible:underline disabled:opacity-50\"\n />\n )}\n </div>\n </Command>\n )}\n </PopoverContent>\n {dialogMounted && !gated && canAdd && (\n <LazyRelationPickerDialog\n to={to}\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSelect={() => undefined}\n multiple\n selected={keys}\n onToggle={toggle}\n valueField={valueField}\n searchField={searchField}\n fixedFilters={fixedFilters}\n scope={scope}\n scopeField={fieldName}\n {...(disabled ? {} : { create })}\n createSeeds={createSeeds}\n fieldName={fieldName}\n onBeforeCreate={focusTrigger}\n />\n )}\n {createReader}\n </Popover>\n );\n}\n\n/** One chosen row: its title (the aggregator batches every chip's read), which views it, and remove. */\nfunction Chip({\n to,\n keyValue,\n by,\n resource,\n fieldName,\n testId,\n open: openMode,\n disabled,\n focusTrigger,\n onRemove,\n}: {\n readonly to: string;\n readonly keyValue: Key;\n readonly by: string | undefined;\n readonly resource: string;\n readonly fieldName: string;\n readonly testId: string;\n readonly open: RelationOpen;\n readonly disabled: boolean;\n readonly focusTrigger: () => void;\n readonly onRemove: () => void;\n}): React.ReactElement {\n const t = useOptionalT();\n const app = useApp();\n const targetDef = app.registry.get(to);\n const rowTitle = useRowTitle(to, targetDef?.displayField);\n const { record, isLoading } = useRelatedRecord(\n to,\n keyValue,\n by === undefined ? undefined : { by },\n );\n const title = record ? rowTitle(record as Record<string, unknown>) : String(keyValue);\n return (\n <span\n data-testid={testId}\n data-resource={resource}\n className=\"inline-flex items-center gap-0.5 rounded-md border bg-secondary pl-2 text-sm text-secondary-foreground\"\n >\n <RelationViewButton\n to={to}\n value={keyValue}\n by={by}\n fieldName={`${fieldName}:${String(keyValue)}`}\n beforeOpen={focusTrigger}\n open={openMode}\n title={isLoading ? t('table.loading', { defaultValue: 'Loading…' }) : title}\n />\n {!disabled && (\n <button\n type=\"button\"\n onClick={onRemove}\n data-testid={`${testId}:remove`}\n aria-label={`${t('relationPicker.clear', { defaultValue: 'Clear' })} ${title}`}\n className=\"inline-flex size-6 items-center justify-center rounded-sm text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <IconX className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </span>\n );\n}\n"],"mappings":"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"}