@burojs/ui-shadcn 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/README.md +9 -0
  2. package/dist/bulk-summary-BWSAS7k2.js +143 -0
  3. package/dist/bulk-summary-BWSAS7k2.js.map +1 -0
  4. package/dist/bulk-summary-CrEij5vq.cjs +143 -0
  5. package/dist/bulk-summary-CrEij5vq.cjs.map +1 -0
  6. package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CS_JZ4Fd.js} +3 -3
  7. package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CS_JZ4Fd.js.map} +1 -1
  8. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-y5M6_oe4.cjs} +4 -4
  9. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-y5M6_oe4.cjs.map} +1 -1
  10. package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-2j0gOd7x.js} +384 -108
  11. package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
  12. package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-C-NHgMST.cjs} +468 -107
  13. package/dist/check-confirm-dialog-C-NHgMST.cjs.map +1 -0
  14. package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
  15. package/dist/dialog-C123sVQ8.js.map +1 -0
  16. package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
  17. package/dist/dialog-vmMdfUWs.cjs.map +1 -0
  18. package/dist/{filter-builder-nXqtM_h4.cjs → filter-builder-DFu0JP-1.cjs} +923 -120
  19. package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
  20. package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-DaWHUZuV.js} +839 -108
  21. package/dist/filter-builder-DaWHUZuV.js.map +1 -0
  22. package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
  23. package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
  24. package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DyqTmK3H.js} +62 -30
  25. package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
  26. package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-Bcz9NF2V.cjs} +128 -87
  27. package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
  28. package/dist/{flow-screen-CCvgDI9G.js → flow-screen-DCdli6Ha.js} +128 -87
  29. package/dist/flow-screen-DCdli6Ha.js.map +1 -0
  30. package/dist/index.cjs +731 -906
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +455 -247
  33. package/dist/index.d.ts +455 -247
  34. package/dist/index.js +647 -828
  35. package/dist/index.js.map +1 -1
  36. package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-3vw7LzzD.cjs} +5 -5
  37. package/dist/inline-flow-host-3vw7LzzD.cjs.map +1 -0
  38. package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-C0rI9B7f.js} +5 -5
  39. package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
  40. package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-Bt8lrEIu.cjs} +10 -10
  41. package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
  42. package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-CAScLPb2.js} +11 -11
  43. package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
  44. package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-BHUEpn0I.js} +36 -23
  45. package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
  46. package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
  47. package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
  48. package/dist/{place-node-C5SmIAYU.cjs → place-node-CNb3w-c7.cjs} +1869 -947
  49. package/dist/place-node-CNb3w-c7.cjs.map +1 -0
  50. package/dist/{place-node-NraNYKPx.js → place-node-CfzQvh4Y.js} +1824 -926
  51. package/dist/place-node-CfzQvh4Y.js.map +1 -0
  52. package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BIqqY69Y.js} +9 -4
  53. package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
  54. package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
  55. package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
  56. package/dist/{related-list-timeline-yrPsjA3F.js → related-list-timeline-CRh7xwLD.js} +6 -7
  57. package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
  58. package/dist/{related-list-timeline-CCzl71aA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
  59. package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
  60. package/dist/{related-rows-o0_t-Yce.js → related-rows--uP2iKQC.js} +25 -14
  61. package/dist/related-rows--uP2iKQC.js.map +1 -0
  62. package/dist/{related-rows-ea43qhhy.cjs → related-rows-MPnLCmPF.cjs} +27 -16
  63. package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
  64. package/dist/{search-access-CPPmfuvy.js → relation-create-C43cdPQt.js} +595 -13
  65. package/dist/relation-create-C43cdPQt.js.map +1 -0
  66. package/dist/{search-access-Dugvttlg.cjs → relation-create-DDEYcKfw.cjs} +633 -14
  67. package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
  68. package/dist/{relation-many-picker-bvkjkv-k.js → relation-many-picker-BJhaEqxz.js} +203 -102
  69. package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
  70. package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-DzuGJpEl.cjs} +211 -110
  71. package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
  72. package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-D-tBBZW_.js} +23 -59
  73. package/dist/relation-picker-D-tBBZW_.js.map +1 -0
  74. package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-DaIMzf2H.cjs} +29 -71
  75. package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
  76. package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +133 -35
  77. package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
  78. package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-DoEY8EkH.js} +134 -36
  79. package/dist/relation-picker-dialog-DoEY8EkH.js.map +1 -0
  80. package/dist/relation-select-B8Fq4o-t.js +48 -0
  81. package/dist/relation-select-B8Fq4o-t.js.map +1 -0
  82. package/dist/relation-select-Cr3CfNLy.cjs +55 -0
  83. package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
  84. package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-C_kGW2o_.cjs} +543 -300
  85. package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
  86. package/dist/{resource-page-router-3RUf9d1j.js → resource-page-router-Diw6S6TK.js} +498 -255
  87. package/dist/resource-page-router-Diw6S6TK.js.map +1 -0
  88. package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
  89. package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
  90. package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
  91. package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
  92. package/dist/success-notices-Dl3M1fZP.cjs +46 -0
  93. package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
  94. package/dist/success-notices-LDEgEkc4.js +41 -0
  95. package/dist/success-notices-LDEgEkc4.js.map +1 -0
  96. package/dist/{toaster-Cr51X7bz.cjs → toaster-BbByOytP.cjs} +60 -15
  97. package/dist/toaster-BbByOytP.cjs.map +1 -0
  98. package/dist/{toaster-C02XbB9r.js → toaster-Ct_YHGs6.js} +43 -16
  99. package/dist/toaster-Ct_YHGs6.js.map +1 -0
  100. package/dist/{use-dialog-filter-state-C--oMAZG.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
  101. package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
  102. package/dist/{use-dialog-filter-state-Dhe8PcB5.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
  103. package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
  104. package/package.json +11 -11
  105. package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
  106. package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
  107. package/dist/bulk-summary-GxMDP4bw.js +0 -108
  108. package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
  109. package/dist/candidates-gate-Bb70LPAy.js.map +0 -1
  110. package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
  111. package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
  112. package/dist/check-confirm-dialog-bRT8lt0d.js.map +0 -1
  113. package/dist/dialog-B_rt9S1c.js.map +0 -1
  114. package/dist/dialog-DRNUq9EA.cjs.map +0 -1
  115. package/dist/filter-builder-Bhn-dhZV.js.map +0 -1
  116. package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
  117. package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
  118. package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
  119. package/dist/flow-screen-CCvgDI9G.js.map +0 -1
  120. package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
  121. package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
  122. package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
  123. package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
  124. package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
  125. package/dist/place-node-C5SmIAYU.cjs.map +0 -1
  126. package/dist/place-node-NraNYKPx.js.map +0 -1
  127. package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
  128. package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
  129. package/dist/related-rows-ea43qhhy.cjs.map +0 -1
  130. package/dist/related-rows-o0_t-Yce.js.map +0 -1
  131. package/dist/relation-create-IA40t1hi.cjs +0 -364
  132. package/dist/relation-create-IA40t1hi.cjs.map +0 -1
  133. package/dist/relation-create-h6F9B4C4.js +0 -339
  134. package/dist/relation-create-h6F9B4C4.js.map +0 -1
  135. package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
  136. package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
  137. package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
  138. package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
  139. package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
  140. package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
  141. package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
  142. package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
  143. package/dist/search-access-CPPmfuvy.js.map +0 -1
  144. package/dist/search-access-Dugvttlg.cjs.map +0 -1
  145. package/dist/shell-BPlk8hEa.js +0 -205
  146. package/dist/shell-BPlk8hEa.js.map +0 -1
  147. package/dist/shell-DxhlsPwm.cjs +0 -271
  148. package/dist/shell-DxhlsPwm.cjs.map +0 -1
  149. package/dist/toaster-C02XbB9r.js.map +0 -1
  150. package/dist/toaster-Cr51X7bz.cjs.map +0 -1
  151. package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
  152. package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +0 -1
@@ -1,6 +1,7 @@
1
1
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
2
- const require_toaster = require("./toaster-Cr51X7bz.cjs");
3
- const require_dialog = require("./dialog-DRNUq9EA.cjs");
2
+ const require_toaster = require("./toaster-BbByOytP.cjs");
3
+ const require_button = require("./button-BxnnE28H.cjs");
4
+ const require_dialog = require("./dialog-vmMdfUWs.cjs");
4
5
  let _burojs_core = require("@burojs/core");
5
6
  let _burojs_react = require("@burojs/react");
6
7
  let _tabler_icons_react = require("@tabler/icons-react");
@@ -8,6 +9,7 @@ let react = require("react");
8
9
  react = require_use_theme.__toESM(react, 1);
9
10
  let react_jsx_runtime = require("react/jsx-runtime");
10
11
  let cmdk = require("cmdk");
12
+ let sonner = require("sonner");
11
13
  //#region src/primitives/command.tsx
12
14
  const Command = react.forwardRef(({ className, ...props }, ref) => (0, react_jsx_runtime.jsx)(cmdk.Command, {
13
15
  ref,
@@ -92,6 +94,243 @@ function CommandDialog({ open, onOpenChange, defaultOpen, modal, title = "Comman
92
94
  }
93
95
  CommandDialog.displayName = "CommandDialog";
94
96
  //#endregion
97
+ //#region src/record/record-state.tsx
98
+ function RecordState({ state, onRetry, message: given }) {
99
+ const t = (0, _burojs_react.useT)();
100
+ const chromeT = (0, _burojs_react.useChromeT)();
101
+ if (state === "loading") return (0, react_jsx_runtime.jsx)("div", {
102
+ role: "status",
103
+ "aria-busy": "true",
104
+ "data-testid": "record-page:loading",
105
+ className: "p-6 text-sm text-muted-foreground",
106
+ children: t("router.recordLoading")
107
+ });
108
+ const message = given ?? (state === "not-found" ? t("record.notFoundOrNoAccess") : state === "session-expired" ? t("router.recordSessionExpired") : t("router.recordError"));
109
+ return (0, react_jsx_runtime.jsxs)("div", {
110
+ role: "alert",
111
+ "data-testid": `record-page:${state}`,
112
+ className: "flex flex-col items-center justify-center gap-3 px-6 py-24 text-center",
113
+ children: [(0, react_jsx_runtime.jsx)("p", {
114
+ className: "max-w-sm text-sm text-muted-foreground",
115
+ children: message
116
+ }), onRetry ? (0, react_jsx_runtime.jsx)(require_button.Button, {
117
+ type: "button",
118
+ variant: "outline",
119
+ size: "sm",
120
+ "data-testid": "record-page:retry",
121
+ onClick: onRetry,
122
+ children: chromeT("actions.retry")
123
+ }) : null]
124
+ });
125
+ }
126
+ //#endregion
127
+ //#region src/load-error/list-error-panel.tsx
128
+ function ListErrorPanel({ text, technical, onRetry, resource, title, className }) {
129
+ (0, _burojs_react.useT)();
130
+ const t = (0, _burojs_react.useOptionalT)();
131
+ const chromeT = (0, _burojs_react.useChromeT)();
132
+ const raw = process.env.NODE_ENV === "production" ? void 0 : technical;
133
+ return (0, react_jsx_runtime.jsxs)("div", {
134
+ role: "alert",
135
+ className: require_use_theme.cn("flex flex-col items-center justify-center gap-3 px-6 py-16 rounded-lg border border-destructive/40 bg-destructive/5 text-center", className),
136
+ "data-testid": "error",
137
+ children: [
138
+ (0, react_jsx_runtime.jsx)("div", {
139
+ className: "rounded-full bg-destructive/10 p-3 text-destructive",
140
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconAlertCircle, {
141
+ className: "size-6",
142
+ "aria-hidden": "true"
143
+ })
144
+ }),
145
+ (0, react_jsx_runtime.jsxs)("div", {
146
+ className: "space-y-1",
147
+ children: [(0, react_jsx_runtime.jsx)("h3", {
148
+ className: "text-base font-semibold tracking-tight text-destructive",
149
+ children: title ?? t("list.errorTitle")
150
+ }), (0, react_jsx_runtime.jsx)("p", {
151
+ className: "max-w-md text-sm text-muted-foreground",
152
+ children: text
153
+ })]
154
+ }),
155
+ raw && raw !== text ? (0, react_jsx_runtime.jsxs)("details", {
156
+ className: "max-w-md text-left",
157
+ children: [(0, react_jsx_runtime.jsx)("summary", {
158
+ className: "cursor-pointer text-xs text-muted-foreground hover:text-foreground",
159
+ children: t("list.errorDetails")
160
+ }), (0, react_jsx_runtime.jsx)("p", {
161
+ className: "mt-1.5 break-all font-mono text-xs text-muted-foreground",
162
+ "data-testid": "list-error-detail",
163
+ children: raw
164
+ })]
165
+ }) : null,
166
+ onRetry && (0, react_jsx_runtime.jsx)("div", {
167
+ className: "flex justify-center pt-2",
168
+ children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
169
+ type: "button",
170
+ variant: "outline",
171
+ size: "sm",
172
+ "data-testid": resource ? `list-error-retry:${resource}` : "list-error-retry",
173
+ onClick: onRetry,
174
+ className: "gap-1.5",
175
+ children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconRefresh, {
176
+ className: "size-3.5",
177
+ "aria-hidden": "true"
178
+ }), chromeT("actions.retry")]
179
+ })
180
+ })
181
+ ]
182
+ });
183
+ }
184
+ //#endregion
185
+ //#region src/load-error/state.ts
186
+ function recordErrorState(error) {
187
+ const { kind } = (0, _burojs_core.normalizeDataError)(error);
188
+ if (kind === "not-found" || kind === "forbidden") return "not-found";
189
+ if (kind === "auth") return "session-expired";
190
+ return "error";
191
+ }
192
+ //#endregion
193
+ //#region src/load-error/load-error-view.tsx
194
+ const RECORD_KEYS = {
195
+ "not-found": "record.notFoundOrNoAccess",
196
+ "session-expired": "router.recordSessionExpired",
197
+ error: "router.recordError"
198
+ };
199
+ const LIST_FALLBACK = {
200
+ key: "list.errorBody",
201
+ default: "Failed to load data. Please try again."
202
+ };
203
+ function loadErrorTechnicalTexts(error, original) {
204
+ const out = [...require_toaster.technicalTexts(error), ...require_toaster.technicalTexts(original)];
205
+ if (original !== null && typeof original === "object" && !(original instanceof Error)) {
206
+ const message = original.message;
207
+ if (typeof message === "string") out.push(message);
208
+ }
209
+ return out.filter((text, index) => text.length > 0 && out.indexOf(text) === index);
210
+ }
211
+ function useLoadErrorText(error, original, state, surface, fallback) {
212
+ const t = (0, _burojs_react.useOptionalT)();
213
+ const caps = (0, _burojs_react.useI18nCaps)();
214
+ if (state !== "error") return t(RECORD_KEYS[state]);
215
+ const own = (0, _burojs_react.specificErrorText)(error, caps);
216
+ if (own !== void 0) return own;
217
+ const strings = require_toaster.friendlyStringsFrom(t);
218
+ for (const text of loadErrorTechnicalTexts(error, original)) {
219
+ const friendly = require_toaster.toFriendlyError(text, "", strings);
220
+ if (friendly.replaced && friendly.detail !== strings.generic) return friendly.detail;
221
+ }
222
+ const generic = surface === "list" ? fallback ?? LIST_FALLBACK : fallback;
223
+ if (surface === "record" || generic === void 0) return t(RECORD_KEYS.error);
224
+ return t(generic.key, { defaultValue: generic.default });
225
+ }
226
+ function DefaultLoadErrorView(props) {
227
+ const { error, surface, state, retry, original, fallback, testId, className, children, attributes } = props;
228
+ const text = useLoadErrorText(error, original, state, surface, fallback);
229
+ const chromeT = (0, _burojs_react.useChromeT)();
230
+ if (surface === "record") return (0, react_jsx_runtime.jsx)(RecordState, {
231
+ state,
232
+ message: text,
233
+ ...retry === void 0 ? {} : { onRetry: retry }
234
+ });
235
+ if (surface === "list") return (0, react_jsx_runtime.jsx)(ListErrorPanel, {
236
+ text,
237
+ technical: loadErrorTechnicalTexts(error, original)[0],
238
+ ...retry === void 0 ? {} : { onRetry: retry },
239
+ ...props.resource === void 0 ? {} : { resource: props.resource },
240
+ ...props.title === void 0 ? {} : { title: props.title },
241
+ ...className === void 0 ? {} : { className }
242
+ });
243
+ if (surface === "relation" || surface === "picker") {
244
+ const technical = process.env.NODE_ENV === "production" ? void 0 : loadErrorTechnicalTexts(error, original)[0];
245
+ return (0, react_jsx_runtime.jsx)("span", {
246
+ ...attributes,
247
+ ...testId === void 0 ? {} : { "data-testid": testId },
248
+ className,
249
+ title: technical === void 0 ? text : `${text} (${technical})`,
250
+ children: children ?? text
251
+ });
252
+ }
253
+ return (0, react_jsx_runtime.jsxs)("div", {
254
+ ...attributes,
255
+ role: "alert",
256
+ ...testId === void 0 ? {} : { "data-testid": testId },
257
+ className: require_use_theme.cn("flex flex-wrap items-center gap-2 rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground", className),
258
+ children: [(0, react_jsx_runtime.jsx)("span", { children: text }), retry === void 0 ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
259
+ type: "button",
260
+ variant: "outline",
261
+ size: "sm",
262
+ onClick: retry,
263
+ children: chromeT("actions.retry", { defaultValue: "Retry" })
264
+ })]
265
+ });
266
+ }
267
+ const UNSET = Symbol("unset");
268
+ var AppViewBoundary = class extends react.Component {
269
+ state = {
270
+ failedFor: UNSET,
271
+ failed: false
272
+ };
273
+ static getDerivedStateFromError() {
274
+ return { failed: true };
275
+ }
276
+ static getDerivedStateFromProps(props, state) {
277
+ if (state.failed && state.failedFor !== UNSET && state.failedFor !== props.error) return {
278
+ failedFor: UNSET,
279
+ failed: false
280
+ };
281
+ return null;
282
+ }
283
+ componentDidCatch(error, _info) {
284
+ this.setState({ failedFor: this.props.error });
285
+ if (process.env.NODE_ENV !== "production") console.error("[burojs] load-error.view-threw: the app's views.loadError threw while rendering; the kit's view is shown instead.", error);
286
+ }
287
+ render() {
288
+ return this.state.failed ? this.props.fallback : this.props.children;
289
+ }
290
+ };
291
+ function LoadError(props) {
292
+ const App = (0, _burojs_react.useLoadErrorView)();
293
+ const { error: original, surface, resource } = props;
294
+ const error = (0, react.useMemo)(() => (0, _burojs_core.normalizeDataError)(original), [original]);
295
+ const state = props.state ?? recordErrorState(error);
296
+ const retry = state === "error" ? props.retry : void 0;
297
+ const viewProps = {
298
+ error,
299
+ surface,
300
+ state,
301
+ ...resource === void 0 ? {} : { resource },
302
+ ...retry === void 0 ? {} : { retry }
303
+ };
304
+ const standard = (0, react_jsx_runtime.jsx)(DefaultLoadErrorView, {
305
+ ...viewProps,
306
+ original,
307
+ fallback: props.fallback,
308
+ testId: props.testId,
309
+ className: props.className,
310
+ title: props.title,
311
+ attributes: props.attributes,
312
+ children: props.children
313
+ });
314
+ if (App === void 0) return standard;
315
+ return (0, react_jsx_runtime.jsx)(AppViewBoundary, {
316
+ error: original,
317
+ fallback: standard,
318
+ children: (0, react_jsx_runtime.jsx)(App, { ...viewProps })
319
+ });
320
+ }
321
+ const INVALID_ROUTE_ID = Object.freeze({
322
+ kind: "not-found",
323
+ code: "invalid-record-id"
324
+ });
325
+ function InvalidRouteId({ resource }) {
326
+ return (0, react_jsx_runtime.jsx)(LoadError, {
327
+ surface: "record",
328
+ resource,
329
+ state: "not-found",
330
+ error: INVALID_ROUTE_ID
331
+ });
332
+ }
333
+ //#endregion
95
334
  //#region src/fields/claimed-quick-link.tsx
96
335
  function isPlainLeftClick(event) {
97
336
  return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
@@ -330,7 +569,8 @@ function RelationDisplay({ value, field }) {
330
569
  open
331
570
  });
332
571
  }
333
- function RelationField({ to, value }) {
572
+ function RelationField({ to: toInput, value }) {
573
+ const to = (0, _burojs_core.routeResourceKey)(toInput);
334
574
  return (0, react_jsx_runtime.jsx)(RelationDisplay, {
335
575
  value,
336
576
  field: {
@@ -484,7 +724,7 @@ function LazyByOpener({ to, by, idStr, target }) {
484
724
  if (!asked || rows === void 0 || !requested.current) return;
485
725
  if (rows.length > 1) {
486
726
  requested.current = false;
487
- if (process.env.NODE_ENV !== "production") console.error(`[burojs] ${(0, _burojs_core.relationAmbiguousError)(to, by, idStr).message}`);
727
+ if (process.env.NODE_ENV !== "production") console.error(`[burojs] ${require_toaster.technicalText((0, _burojs_core.relationAmbiguousError)(to, by, idStr))}`);
488
728
  return;
489
729
  }
490
730
  requested.current = false;
@@ -572,10 +812,16 @@ function RelationDisplayBody({ to, by, id, idStr, app, open: openMode, quickTarg
572
812
  title: `${to}: more than one row has ${by ?? "id"} ${idStr}`,
573
813
  children: idStr
574
814
  });
575
- if (error) return (0, react_jsx_runtime.jsx)("span", {
576
- "data-testid": `${baseId}:error`,
815
+ if (error) return (0, react_jsx_runtime.jsx)(LoadError, {
816
+ surface: "relation",
817
+ error,
818
+ resource: to,
819
+ testId: `${baseId}:error`,
577
820
  className: "text-muted-foreground",
578
- title: error.message,
821
+ fallback: {
822
+ key: "relation.failed",
823
+ default: "Failed to load options."
824
+ },
579
825
  children: idStr
580
826
  });
581
827
  if (!record) return (0, react_jsx_runtime.jsx)("span", {
@@ -649,6 +895,343 @@ function namesHiddenField(filter, visible) {
649
895
  return filter !== void 0 && (0, _burojs_react.filterFields)(filter).some((field) => !visible(field));
650
896
  }
651
897
  //#endregion
898
+ //#region src/fields/relation-hand-back.tsx
899
+ function createdOptionFilter(input) {
900
+ const own = createdOptionScope(input);
901
+ const byId = {
902
+ field: input.idField,
903
+ op: "eq",
904
+ value: input.id
905
+ };
906
+ return own === void 0 ? byId : { and: [own, byId] };
907
+ }
908
+ function createdOptionScope(input) {
909
+ return (0, _burojs_core.composeListFilter)({
910
+ fixed: (0, _burojs_core.normalizeFixedFilters)(input.fixed),
911
+ search: "",
912
+ ...input.searchDecl === void 0 ? {} : { searchDecl: input.searchDecl },
913
+ ...input.searchContext === void 0 ? {} : { searchContext: input.searchContext }
914
+ });
915
+ }
916
+ function CreatedOptionRead({ to, filter, scope, scopeField, by, idField, onSettled }) {
917
+ const query = (0, _burojs_react.useList)(to, {
918
+ filter,
919
+ pagination: {
920
+ kind: "offset",
921
+ page: 1,
922
+ pageSize: 1
923
+ },
924
+ scope,
925
+ ...scopeField === void 0 ? {} : { scopeField },
926
+ retry: false
927
+ });
928
+ const settled = react.useRef(false);
929
+ const latest = react.useRef(onSettled);
930
+ latest.current = onSettled;
931
+ const rows = query.data?.data;
932
+ const answered = rows !== void 0 && query.isCurrentData && !query.isFetching;
933
+ const failed = query.isError && !query.isFetching;
934
+ react.useEffect(() => {
935
+ if (settled.current) return;
936
+ if (failed) {
937
+ settled.current = true;
938
+ latest.current({ kind: "failed" });
939
+ return;
940
+ }
941
+ if (!answered) return;
942
+ settled.current = true;
943
+ const value = rows[0]?.[by ?? idField];
944
+ latest.current(typeof value === "string" || typeof value === "number" ? {
945
+ kind: "fits",
946
+ value
947
+ } : { kind: "does-not-fit" });
948
+ }, [
949
+ answered,
950
+ failed,
951
+ rows,
952
+ by,
953
+ idField
954
+ ]);
955
+ return null;
956
+ }
957
+ //#endregion
958
+ //#region src/fields/relation-view-button.tsx
959
+ function selectKey(value) {
960
+ if (typeof value === "string") return value.length === 0 ? null : value;
961
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : null;
962
+ return null;
963
+ }
964
+ const VIEW_CLASS = require_use_theme.cn(require_button.buttonVariants({
965
+ variant: "outline",
966
+ size: "icon"
967
+ }), "shrink-0");
968
+ const TITLE_CLASS = "min-w-0 max-w-[16rem] truncate";
969
+ const TITLE_VIEW_CLASS = require_use_theme.cn(TITLE_CLASS, "cursor-pointer rounded-sm text-left hover:underline focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring");
970
+ function RelationViewButton(props) {
971
+ const gate = (0, _burojs_react.useEntryGate)();
972
+ const { to, value, by } = props;
973
+ const access = (0, _burojs_react.useListAccess)(to);
974
+ const key = selectKey(value);
975
+ const plain = plainTitle(props.title);
976
+ if (key === null || props.open === "none") return plain;
977
+ if (by !== void 0 && !(access.status === "ready" && access.fieldVisible(by))) return plain;
978
+ if (gate(to, "show").state !== "open") return plain;
979
+ return (0, react_jsx_runtime.jsx)(ViewButton, {
980
+ ...props,
981
+ keyString: key
982
+ }, key);
983
+ }
984
+ function plainTitle(title) {
985
+ return title === void 0 ? null : (0, react_jsx_runtime.jsx)("span", {
986
+ className: TITLE_CLASS,
987
+ children: title
988
+ });
989
+ }
990
+ function ViewButton({ to, by, fieldName, keyString, beforeOpen, open: openMode = "quick", title }) {
991
+ const app = (0, _burojs_react.useApp)();
992
+ const t = (0, _burojs_react.useOptionalT)();
993
+ const tid = (0, _burojs_react.useTestIds)();
994
+ const quick = (0, _burojs_react.useQuick)();
995
+ const navigate = (0, _burojs_react.useRouteNavigate)();
996
+ const RouterLink = require_toaster.useLinkComponent();
997
+ const [asked, setAsked] = react.useState(false);
998
+ const requested = react.useRef(false);
999
+ const targetDef = app.registry.get(to);
1000
+ const rawIdField = (targetDef?.data)?.idField;
1001
+ const idField = typeof rawIdField === "string" && rawIdField.length > 0 ? rawIdField : "id";
1002
+ const read = (0, _burojs_react.useList)(to, {
1003
+ ...asked && by !== void 0 ? {
1004
+ filter: {
1005
+ field: by,
1006
+ op: "eq",
1007
+ value: keyString
1008
+ },
1009
+ pagination: {
1010
+ kind: "offset",
1011
+ page: 1,
1012
+ pageSize: 2
1013
+ }
1014
+ } : {},
1015
+ scope: "none",
1016
+ enabled: asked && by !== void 0,
1017
+ retry: false
1018
+ });
1019
+ const rows = read.isCurrentData && !read.isPlaceholderData && !read.isFetching ? read.data?.data : void 0;
1020
+ const open = react.useCallback((id) => {
1021
+ beforeOpen();
1022
+ if (openMode === "page") {
1023
+ if (targetDef !== void 0 && linksToPage(app, targetDef)) navigate((0, _burojs_core.resourceShowHref)(app.registry, targetDef, to, id));
1024
+ return;
1025
+ }
1026
+ quick.show(to, id);
1027
+ }, [
1028
+ beforeOpen,
1029
+ quick,
1030
+ to,
1031
+ openMode,
1032
+ navigate,
1033
+ app,
1034
+ targetDef
1035
+ ]);
1036
+ react.useEffect(() => {
1037
+ if (by === void 0 || !asked || rows === void 0 || !requested.current) return;
1038
+ requested.current = false;
1039
+ if (rows.length !== 1) {
1040
+ if (rows.length > 1 && process.env.NODE_ENV !== "production") console.error(`[burojs] ${to}: more than one row has ${by} ${keyString}; "view" opened nothing.`);
1041
+ return;
1042
+ }
1043
+ const id = rows[0]?.[idField];
1044
+ const next = selectKey(id);
1045
+ if (next !== null) open(next);
1046
+ }, [
1047
+ by,
1048
+ asked,
1049
+ rows,
1050
+ idField,
1051
+ keyString,
1052
+ to,
1053
+ open
1054
+ ]);
1055
+ const label = t("relationPicker.view", { defaultValue: "View" });
1056
+ const content = title === void 0 ? (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconEye, {
1057
+ className: "h-4 w-4",
1058
+ "aria-hidden": true
1059
+ }) : title;
1060
+ const className = title === void 0 ? VIEW_CLASS : TITLE_VIEW_CLASS;
1061
+ const testid = tid.relationView(to, fieldName);
1062
+ if (openMode === "page" && (targetDef === void 0 || !linksToPage(app, targetDef))) return plainTitle(title);
1063
+ if (openMode === "page" && by === void 0 && targetDef !== void 0) return (0, react_jsx_runtime.jsxs)(RouterLink, {
1064
+ href: (0, _burojs_core.resourceShowHref)(app.registry, targetDef, to, keyString),
1065
+ "data-testid": testid,
1066
+ className,
1067
+ onClick: () => beforeOpen(),
1068
+ children: [(0, react_jsx_runtime.jsxs)("span", {
1069
+ className: "sr-only",
1070
+ children: [label, " "]
1071
+ }), content]
1072
+ });
1073
+ if (by === void 0 && targetDef !== void 0 && linksToPage(app, targetDef)) return (0, react_jsx_runtime.jsxs)(ClaimedQuickLink, {
1074
+ href: (0, _burojs_core.resourceShowHref)(app.registry, targetDef, to, keyString),
1075
+ testid,
1076
+ className,
1077
+ onOpen: () => open(keyString),
1078
+ children: [(0, react_jsx_runtime.jsxs)("span", {
1079
+ className: "sr-only",
1080
+ children: [label, " "]
1081
+ }), content]
1082
+ });
1083
+ return (0, react_jsx_runtime.jsx)("button", {
1084
+ type: "button",
1085
+ className,
1086
+ "data-testid": testid,
1087
+ "aria-label": title === void 0 ? label : `${label} ${title}`,
1088
+ [_burojs_react.QUICK_ANCHOR_ATTRIBUTE]: "",
1089
+ onClick: (event) => {
1090
+ event.preventDefault();
1091
+ event.stopPropagation();
1092
+ if (!isPlainLeftClick(event)) return;
1093
+ if (by === void 0) {
1094
+ open(keyString);
1095
+ return;
1096
+ }
1097
+ requested.current = true;
1098
+ setAsked(true);
1099
+ if (rows !== void 0 && rows.length === 1) {
1100
+ const next = selectKey(rows[0]?.[idField]);
1101
+ requested.current = false;
1102
+ if (next !== null) open(next);
1103
+ }
1104
+ },
1105
+ children: content
1106
+ });
1107
+ }
1108
+ //#endregion
1109
+ //#region src/fields/relation-create.tsx
1110
+ function useSelectCreate(input) {
1111
+ const t = (0, _burojs_react.useOptionalT)();
1112
+ const { to: target } = input;
1113
+ const [pending, setPending] = react.useState(false);
1114
+ const [created, setCreated] = react.useState(null);
1115
+ const latch = react.useRef(false);
1116
+ const mounted = react.useRef(true);
1117
+ react.useEffect(() => {
1118
+ mounted.current = true;
1119
+ return () => {
1120
+ mounted.current = false;
1121
+ };
1122
+ }, []);
1123
+ const latest = react.useRef(input);
1124
+ latest.current = input;
1125
+ const access = (0, _burojs_react.useListAccess)(target);
1126
+ const blocked = input.held === true || access.status !== "ready" || namesHiddenField(createdOptionScope({
1127
+ fixed: input.fixedFilters,
1128
+ searchDecl: input.searchDecl,
1129
+ searchContext: input.searchContext
1130
+ }), (name) => access.fieldVisible(name));
1131
+ const blockedRef = react.useRef(blocked);
1132
+ blockedRef.current = blocked;
1133
+ const release = react.useCallback(() => {
1134
+ latch.current = false;
1135
+ if (mounted.current) {
1136
+ setPending(false);
1137
+ setCreated(null);
1138
+ }
1139
+ }, []);
1140
+ const start = react.useCallback((open) => {
1141
+ if (latch.current || !mounted.current || blockedRef.current) return;
1142
+ latch.current = true;
1143
+ setPending(true);
1144
+ let opened;
1145
+ try {
1146
+ opened = open();
1147
+ } catch (error) {
1148
+ release();
1149
+ throw error;
1150
+ }
1151
+ opened.then((row) => {
1152
+ if (!mounted.current) {
1153
+ latch.current = false;
1154
+ return;
1155
+ }
1156
+ const id = row === null ? null : selectKey(row[latest.current.idField]) ?? selectKey(row.id);
1157
+ if (id === null) release();
1158
+ else setCreated({ id });
1159
+ }, () => release());
1160
+ }, [release]);
1161
+ const settle = react.useCallback((result) => {
1162
+ if (mounted.current) {
1163
+ if (result.kind === "fits") latest.current.onValue(result.value);
1164
+ else if (result.kind === "does-not-fit") (0, sonner.toast)(t("relationPicker.createdNotFitting", { defaultValue: "The record was created but does not fit this field" }));
1165
+ else sonner.toast.error(t("relationPicker.createdNotSelected", { defaultValue: "The record was created but could not be selected" }));
1166
+ }
1167
+ release();
1168
+ }, [release, t]);
1169
+ return {
1170
+ create: react.useMemo(() => ({
1171
+ pending,
1172
+ blocked,
1173
+ start
1174
+ }), [
1175
+ pending,
1176
+ blocked,
1177
+ start
1178
+ ]),
1179
+ reader: created === null || blocked ? null : (0, react_jsx_runtime.jsx)(CreatedOptionRead, {
1180
+ to: target,
1181
+ filter: createdOptionFilter({
1182
+ fixed: input.fixedFilters,
1183
+ idField: input.idField,
1184
+ id: created.id,
1185
+ searchDecl: input.searchDecl,
1186
+ searchContext: input.searchContext
1187
+ }),
1188
+ scope: input.scope,
1189
+ ...input.scopeField === void 0 ? {} : { scopeField: input.scopeField },
1190
+ by: input.by,
1191
+ idField: input.idField,
1192
+ onSettled: settle
1193
+ }, created.id)
1194
+ };
1195
+ }
1196
+ function plainStringField(def) {
1197
+ if (def === null || typeof def !== "object") return false;
1198
+ const field = def;
1199
+ return field.kind === "string" && field.system !== true && field.opts?.system !== true && field.opts?.enum === void 0 && field.opts?.localized !== true;
1200
+ }
1201
+ function RelationCreateButton(props) {
1202
+ const gate = (0, _burojs_react.useEntryGate)();
1203
+ const { to } = props;
1204
+ if (props.create.blocked || gate(to, "create").state !== "open") return null;
1205
+ return (0, react_jsx_runtime.jsx)(CreateButton, { ...props });
1206
+ }
1207
+ function CreateButton({ to, fieldName, create, seeds, search, beforeOpen, className, testId }) {
1208
+ const app = (0, _burojs_react.useApp)();
1209
+ const t = (0, _burojs_react.useOptionalT)();
1210
+ const tid = (0, _burojs_react.useTestIds)();
1211
+ const quick = (0, _burojs_react.useQuick)();
1212
+ const label = t("relationPicker.create", { defaultValue: "+ Create" });
1213
+ return (0, react_jsx_runtime.jsx)("button", {
1214
+ type: "button",
1215
+ "data-testid": testId ?? tid.relationCreate(to, fieldName),
1216
+ disabled: create.pending,
1217
+ className,
1218
+ onClick: () => {
1219
+ const text = search?.trim() ?? "";
1220
+ const displayField = app.registry.get(to)?.displayField;
1221
+ const fields = app.registry.get(to)?.fields;
1222
+ const prefill = text.length > 0 && typeof displayField === "string" && fields !== void 0 && Object.hasOwn(fields, displayField) && plainStringField(fields[displayField]) ? { [displayField]: text } : void 0;
1223
+ create.start(() => {
1224
+ beforeOpen();
1225
+ return quick.create(to, {
1226
+ ...seeds === void 0 || Object.keys(seeds).length === 0 ? {} : { defaults: seeds },
1227
+ ...prefill === void 0 ? {} : { input: prefill }
1228
+ });
1229
+ });
1230
+ },
1231
+ children: label
1232
+ });
1233
+ }
1234
+ //#endregion
652
1235
  Object.defineProperty(exports, "ClaimedQuickLink", {
653
1236
  enumerable: true,
654
1237
  get: function() {
@@ -709,6 +1292,18 @@ Object.defineProperty(exports, "CommandSeparator", {
709
1292
  return CommandSeparator;
710
1293
  }
711
1294
  });
1295
+ Object.defineProperty(exports, "InvalidRouteId", {
1296
+ enumerable: true,
1297
+ get: function() {
1298
+ return InvalidRouteId;
1299
+ }
1300
+ });
1301
+ Object.defineProperty(exports, "LoadError", {
1302
+ enumerable: true,
1303
+ get: function() {
1304
+ return LoadError;
1305
+ }
1306
+ });
712
1307
  Object.defineProperty(exports, "PeekContext", {
713
1308
  enumerable: true,
714
1309
  get: function() {
@@ -721,6 +1316,18 @@ Object.defineProperty(exports, "PeekHostContext", {
721
1316
  return PeekHostContext;
722
1317
  }
723
1318
  });
1319
+ Object.defineProperty(exports, "RecordState", {
1320
+ enumerable: true,
1321
+ get: function() {
1322
+ return RecordState;
1323
+ }
1324
+ });
1325
+ Object.defineProperty(exports, "RelationCreateButton", {
1326
+ enumerable: true,
1327
+ get: function() {
1328
+ return RelationCreateButton;
1329
+ }
1330
+ });
724
1331
  Object.defineProperty(exports, "RelationDisplay", {
725
1332
  enumerable: true,
726
1333
  get: function() {
@@ -733,22 +1340,22 @@ Object.defineProperty(exports, "RelationField", {
733
1340
  return RelationField;
734
1341
  }
735
1342
  });
736
- Object.defineProperty(exports, "focusWithoutPeek", {
1343
+ Object.defineProperty(exports, "RelationViewButton", {
737
1344
  enumerable: true,
738
1345
  get: function() {
739
- return focusWithoutPeek;
1346
+ return RelationViewButton;
740
1347
  }
741
1348
  });
742
- Object.defineProperty(exports, "isPlainLeftClick", {
1349
+ Object.defineProperty(exports, "focusWithoutPeek", {
743
1350
  enumerable: true,
744
1351
  get: function() {
745
- return isPlainLeftClick;
1352
+ return focusWithoutPeek;
746
1353
  }
747
1354
  });
748
- Object.defineProperty(exports, "linksToPage", {
1355
+ Object.defineProperty(exports, "isPlainLeftClick", {
749
1356
  enumerable: true,
750
1357
  get: function() {
751
- return linksToPage;
1358
+ return isPlainLeftClick;
752
1359
  }
753
1360
  });
754
1361
  Object.defineProperty(exports, "namesHiddenField", {
@@ -781,11 +1388,23 @@ Object.defineProperty(exports, "relationLinkClassName", {
781
1388
  return relationLinkClassName;
782
1389
  }
783
1390
  });
1391
+ Object.defineProperty(exports, "selectKey", {
1392
+ enumerable: true,
1393
+ get: function() {
1394
+ return selectKey;
1395
+ }
1396
+ });
784
1397
  Object.defineProperty(exports, "useRowTitle", {
785
1398
  enumerable: true,
786
1399
  get: function() {
787
1400
  return useRowTitle;
788
1401
  }
789
1402
  });
1403
+ Object.defineProperty(exports, "useSelectCreate", {
1404
+ enumerable: true,
1405
+ get: function() {
1406
+ return useSelectCreate;
1407
+ }
1408
+ });
790
1409
 
791
- //# sourceMappingURL=search-access-Dugvttlg.cjs.map
1410
+ //# sourceMappingURL=relation-create-DDEYcKfw.cjs.map