@burojs/ui-shadcn 0.3.0 → 0.5.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 (179) hide show
  1. package/README.md +26 -7
  2. package/dist/bulk-summary-CwSd6Yjb.cjs +108 -0
  3. package/dist/bulk-summary-CwSd6Yjb.cjs.map +1 -0
  4. package/dist/bulk-summary-GxMDP4bw.js +108 -0
  5. package/dist/bulk-summary-GxMDP4bw.js.map +1 -0
  6. package/dist/button-BxnnE28H.cjs +55 -0
  7. package/dist/button-BxnnE28H.cjs.map +1 -0
  8. package/dist/button-MWVeZaqj.js +44 -0
  9. package/dist/button-MWVeZaqj.js.map +1 -0
  10. package/dist/candidates-gate-CX2PBu6l.js +63 -0
  11. package/dist/candidates-gate-CX2PBu6l.js.map +1 -0
  12. package/dist/candidates-gate-DiFI52r7.cjs +70 -0
  13. package/dist/candidates-gate-DiFI52r7.cjs.map +1 -0
  14. package/dist/candidates-relation-picker-CBsVcnPR.js +82 -0
  15. package/dist/candidates-relation-picker-CBsVcnPR.js.map +1 -0
  16. package/dist/candidates-relation-picker-Dd_GVLlu.cjs +84 -0
  17. package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +1 -0
  18. package/dist/check-confirm-dialog-BRByTFpg.cjs +1534 -0
  19. package/dist/check-confirm-dialog-BRByTFpg.cjs.map +1 -0
  20. package/dist/check-confirm-dialog-CkaVTPT9.js +1232 -0
  21. package/dist/check-confirm-dialog-CkaVTPT9.js.map +1 -0
  22. package/dist/dialog-B_rt9S1c.js +63 -0
  23. package/dist/dialog-B_rt9S1c.js.map +1 -0
  24. package/dist/dialog-DRNUq9EA.cjs +112 -0
  25. package/dist/dialog-DRNUq9EA.cjs.map +1 -0
  26. package/dist/filter-builder-B3mZFL-K.cjs +1761 -0
  27. package/dist/filter-builder-B3mZFL-K.cjs.map +1 -0
  28. package/dist/filter-builder-DOnaXNfP.js +1605 -0
  29. package/dist/filter-builder-DOnaXNfP.js.map +1 -0
  30. package/dist/flow-runtime-B6zOHYqI.cjs +255 -0
  31. package/dist/flow-runtime-B6zOHYqI.cjs.map +1 -0
  32. package/dist/flow-runtime-D8h99FSg.js +252 -0
  33. package/dist/flow-runtime-D8h99FSg.js.map +1 -0
  34. package/dist/flow-screen-CX05b3G9.cjs +705 -0
  35. package/dist/flow-screen-CX05b3G9.cjs.map +1 -0
  36. package/dist/flow-screen-CmbARSqg.js +701 -0
  37. package/dist/flow-screen-CmbARSqg.js.map +1 -0
  38. package/dist/index.cjs +6453 -17494
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +3754 -3621
  41. package/dist/index.d.ts +3754 -3621
  42. package/dist/index.js +6217 -17219
  43. package/dist/index.js.map +1 -1
  44. package/dist/inline-flow-host-B7U1OJUe.cjs +112 -0
  45. package/dist/inline-flow-host-B7U1OJUe.cjs.map +1 -0
  46. package/dist/inline-flow-host-C3H2UpSA.js +112 -0
  47. package/dist/inline-flow-host-C3H2UpSA.js.map +1 -0
  48. package/dist/input-BI0czGyI.cjs +23 -0
  49. package/dist/input-BI0czGyI.cjs.map +1 -0
  50. package/dist/input-CUPStzZO.js +17 -0
  51. package/dist/input-CUPStzZO.js.map +1 -0
  52. package/dist/label-66W1qbke.js +29 -0
  53. package/dist/label-66W1qbke.js.map +1 -0
  54. package/dist/label-w6JYf2cF.cjs +36 -0
  55. package/dist/label-w6JYf2cF.cjs.map +1 -0
  56. package/dist/layout/theme-storage-key.cjs +5 -10
  57. package/dist/layout/theme-storage-key.cjs.map +1 -1
  58. package/dist/layout/theme-storage-key.d.cts +2 -23
  59. package/dist/layout/theme-storage-key.d.ts +2 -23
  60. package/dist/layout/theme-storage-key.js +5 -2
  61. package/dist/layout/theme-storage-key.js.map +1 -1
  62. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +14 -0
  63. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +1 -0
  64. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +19 -0
  65. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +1 -0
  66. package/dist/markdown/index.cjs +424 -511
  67. package/dist/markdown/index.cjs.map +1 -1
  68. package/dist/markdown/index.d.cts +1072 -34
  69. package/dist/markdown/index.d.ts +1072 -34
  70. package/dist/markdown/index.js +411 -459
  71. package/dist/markdown/index.js.map +1 -1
  72. package/dist/page-flow-route-CQ7HsbBm.cjs +277 -0
  73. package/dist/page-flow-route-CQ7HsbBm.cjs.map +1 -0
  74. package/dist/page-flow-route-CyXSvXSE.js +277 -0
  75. package/dist/page-flow-route-CyXSvXSE.js.map +1 -0
  76. package/dist/peek-filter-CnqHwTMU.cjs +51 -0
  77. package/dist/peek-filter-CnqHwTMU.cjs.map +1 -0
  78. package/dist/peek-filter-ErLfO153.js +28 -0
  79. package/dist/peek-filter-ErLfO153.js.map +1 -0
  80. package/dist/place-node--GdsP688.js +7315 -0
  81. package/dist/place-node--GdsP688.js.map +1 -0
  82. package/dist/place-node-SIp4XYQH.cjs +7833 -0
  83. package/dist/place-node-SIp4XYQH.cjs.map +1 -0
  84. package/dist/related-list-cards-B6x9HQQp.js +42 -0
  85. package/dist/related-list-cards-B6x9HQQp.js.map +1 -0
  86. package/dist/related-list-cards-nxuODlIA.cjs +42 -0
  87. package/dist/related-list-cards-nxuODlIA.cjs.map +1 -0
  88. package/dist/related-list-timeline-BYJKEbmA.cjs +142 -0
  89. package/dist/related-list-timeline-BYJKEbmA.cjs.map +1 -0
  90. package/dist/related-list-timeline-DEdfd-rr.js +142 -0
  91. package/dist/related-list-timeline-DEdfd-rr.js.map +1 -0
  92. package/dist/related-rows-B4levHcR.js +186 -0
  93. package/dist/related-rows-B4levHcR.js.map +1 -0
  94. package/dist/related-rows-zh5f_4QR.cjs +209 -0
  95. package/dist/related-rows-zh5f_4QR.cjs.map +1 -0
  96. package/dist/relation-create-BOaUe12G.cjs +362 -0
  97. package/dist/relation-create-BOaUe12G.cjs.map +1 -0
  98. package/dist/relation-create-Bg-eEJLs.js +337 -0
  99. package/dist/relation-create-Bg-eEJLs.js.map +1 -0
  100. package/dist/relation-many-picker-B-NCEUgX.cjs +465 -0
  101. package/dist/relation-many-picker-B-NCEUgX.cjs.map +1 -0
  102. package/dist/relation-many-picker-gdAOD-qK.js +464 -0
  103. package/dist/relation-many-picker-gdAOD-qK.js.map +1 -0
  104. package/dist/relation-picker-BAY77ivO.js +462 -0
  105. package/dist/relation-picker-BAY77ivO.js.map +1 -0
  106. package/dist/relation-picker-Da_uhFvA.cjs +479 -0
  107. package/dist/relation-picker-Da_uhFvA.cjs.map +1 -0
  108. package/dist/relation-picker-dialog-M0pQaWlp.cjs +300 -0
  109. package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +1 -0
  110. package/dist/relation-picker-dialog-hA9rYrZB.js +299 -0
  111. package/dist/relation-picker-dialog-hA9rYrZB.js.map +1 -0
  112. package/dist/resource-page-router-OSQyRA5b.cjs +1779 -0
  113. package/dist/resource-page-router-OSQyRA5b.cjs.map +1 -0
  114. package/dist/resource-page-router-T4vS5gbJ.js +1582 -0
  115. package/dist/resource-page-router-T4vS5gbJ.js.map +1 -0
  116. package/dist/rich-text-DFerywgz.js +457 -0
  117. package/dist/rich-text-DFerywgz.js.map +1 -0
  118. package/dist/rich-text-vTyVjDoa.cjs +460 -0
  119. package/dist/rich-text-vTyVjDoa.cjs.map +1 -0
  120. package/dist/search-access-B7G5oR8n.cjs +812 -0
  121. package/dist/search-access-B7G5oR8n.cjs.map +1 -0
  122. package/dist/search-access-CURsWn-U.js +669 -0
  123. package/dist/search-access-CURsWn-U.js.map +1 -0
  124. package/dist/shell-BPlk8hEa.js +205 -0
  125. package/dist/shell-BPlk8hEa.js.map +1 -0
  126. package/dist/shell-DxhlsPwm.cjs +271 -0
  127. package/dist/shell-DxhlsPwm.cjs.map +1 -0
  128. package/dist/skeleton-U2noefj5.js +13 -0
  129. package/dist/skeleton-U2noefj5.js.map +1 -0
  130. package/dist/skeleton-_1gP7wan.cjs +18 -0
  131. package/dist/skeleton-_1gP7wan.cjs.map +1 -0
  132. package/dist/styles.css +255 -17
  133. package/dist/theme/theme-css.cjs +95 -96
  134. package/dist/theme/theme-css.cjs.map +1 -1
  135. package/dist/theme/theme-css.d.cts +10 -8
  136. package/dist/theme/theme-css.d.ts +10 -8
  137. package/dist/theme/theme-css.js +94 -94
  138. package/dist/theme/theme-css.js.map +1 -1
  139. package/dist/theme/theme-storage.cjs +34 -39
  140. package/dist/theme/theme-storage.cjs.map +1 -1
  141. package/dist/theme/theme-storage.d.cts +3 -1
  142. package/dist/theme/theme-storage.d.ts +3 -1
  143. package/dist/theme/theme-storage.js +33 -37
  144. package/dist/theme/theme-storage.js.map +1 -1
  145. package/dist/theme-storage-key-pYlp4aDS.d.cts +31 -0
  146. package/dist/theme-storage-key-pYlp4aDS.d.ts +31 -0
  147. package/dist/toaster-C7CiYA4Z.cjs +248 -0
  148. package/dist/toaster-C7CiYA4Z.cjs.map +1 -0
  149. package/dist/toaster-CfCRLgR-.js +164 -0
  150. package/dist/toaster-CfCRLgR-.js.map +1 -0
  151. package/dist/use-dialog-filter-state-BBCC0OEK.cjs +92 -0
  152. package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +1 -0
  153. package/dist/use-dialog-filter-state-BDcgS5Oz.js +87 -0
  154. package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +1 -0
  155. package/dist/use-theme-DFlpXils.cjs +257 -0
  156. package/dist/use-theme-DFlpXils.cjs.map +1 -0
  157. package/dist/use-theme-dnE3Od3I.js +175 -0
  158. package/dist/use-theme-dnE3Od3I.js.map +1 -0
  159. package/package.json +18 -17
  160. package/dist/chunk-ABUQPOOE.js +0 -11
  161. package/dist/chunk-ABUQPOOE.js.map +0 -1
  162. package/dist/chunk-DBGGWBFG.cjs +0 -199
  163. package/dist/chunk-DBGGWBFG.cjs.map +0 -1
  164. package/dist/chunk-FMX4GLCQ.js +0 -6
  165. package/dist/chunk-FMX4GLCQ.js.map +0 -1
  166. package/dist/chunk-UC57Z243.js +0 -143
  167. package/dist/chunk-UC57Z243.js.map +0 -1
  168. package/dist/chunk-UPGPO75B.js +0 -164
  169. package/dist/chunk-UPGPO75B.js.map +0 -1
  170. package/dist/chunk-VXJAXJ3U.cjs +0 -8
  171. package/dist/chunk-VXJAXJ3U.cjs.map +0 -1
  172. package/dist/chunk-W7AEYE7A.cjs +0 -13
  173. package/dist/chunk-W7AEYE7A.cjs.map +0 -1
  174. package/dist/chunk-YF5IW525.cjs +0 -155
  175. package/dist/chunk-YF5IW525.cjs.map +0 -1
  176. package/dist/rich-text-6V7WZ3WV.cjs +0 -518
  177. package/dist/rich-text-6V7WZ3WV.cjs.map +0 -1
  178. package/dist/rich-text-N2FZEJJV.js +0 -491
  179. package/dist/rich-text-N2FZEJJV.js.map +0 -1
@@ -0,0 +1,209 @@
1
+ const require_toaster = require("./toaster-C7CiYA4Z.cjs");
2
+ const require_search_access = require("./search-access-B7G5oR8n.cjs");
3
+ const require_place_node = require("./place-node-SIp4XYQH.cjs");
4
+ const require_peek_filter = require("./peek-filter-CnqHwTMU.cjs");
5
+ let _burojs_core = require("@burojs/core");
6
+ let _burojs_react = require("@burojs/react");
7
+ let react = require("react");
8
+ let react_jsx_runtime = require("react/jsx-runtime");
9
+ //#region src/blocks/default-item.tsx
10
+ const isNumeric = (field) => field?.kind === "number";
11
+ function DefaultItem({ resource, row, raw, columns, variant = "card" }) {
12
+ const def = (0, _burojs_react.useApp)().registry.get(resource);
13
+ const caps = (0, _burojs_react.useI18nCaps)(resource);
14
+ const access = useRowAccess(resource)(raw);
15
+ const viewVisible = useViewVisible(resource);
16
+ const fields = def === void 0 ? [] : (columns ?? def.views?.list?.columns ?? Object.keys(def.fields)).filter((name, index, names) => name !== def.displayField && names.indexOf(name) === index && require_peek_filter.peekLeafAllowed(def, name, access, viewVisible));
17
+ const ref = def?.ref ?? {
18
+ namespace: "default",
19
+ id: resource
20
+ };
21
+ const definition = (name) => require_peek_filter.peekFieldDefinition(def, name);
22
+ const value = (name) => (0, react_jsx_runtime.jsx)(require_place_node.ResolvedFieldDisplay, {
23
+ resource: ref,
24
+ name,
25
+ field: definition(name),
26
+ value: row[name],
27
+ record: row,
28
+ fallback: require_place_node.toDisplayText(row[name]).text
29
+ });
30
+ const title = (0, react_jsx_runtime.jsx)("p", {
31
+ className: "truncate text-sm font-medium",
32
+ children: require_search_access.recordDisplayName(row, def?.displayField)
33
+ });
34
+ if (variant === "entry") {
35
+ const shown = fields.filter((name) => row[name] != null && row[name] !== "");
36
+ return (0, react_jsx_runtime.jsxs)("div", {
37
+ className: "flex min-w-0 flex-col gap-0.5",
38
+ "data-buro-default-item": "",
39
+ children: [title, shown.length === 0 ? null : (0, react_jsx_runtime.jsx)("div", {
40
+ "data-buro-item-meta": "",
41
+ className: "truncate text-xs text-muted-foreground",
42
+ children: shown.map((name, index) => (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [index > 0 ? " · " : null, value(name)] }, name))
43
+ })]
44
+ });
45
+ }
46
+ const numbers = fields.filter((name) => isNumeric(definition(name)));
47
+ const pairs = fields.filter((name) => !isNumeric(definition(name)));
48
+ return (0, react_jsx_runtime.jsxs)("div", {
49
+ className: "flex min-w-0 items-start gap-3",
50
+ "data-buro-default-item": "",
51
+ children: [(0, react_jsx_runtime.jsxs)("div", {
52
+ className: "flex min-w-0 flex-1 flex-col gap-2",
53
+ children: [title, pairs.length === 0 ? null : (0, react_jsx_runtime.jsx)("dl", {
54
+ className: "grid gap-1.5",
55
+ children: pairs.map((name) => (0, react_jsx_runtime.jsxs)("div", {
56
+ className: "flex min-w-0 items-baseline gap-2 text-sm",
57
+ children: [(0, react_jsx_runtime.jsx)("dt", {
58
+ className: "w-24 shrink-0 truncate text-xs text-muted-foreground",
59
+ children: (0, _burojs_core.resolveFieldLabel)(caps, name, definition(name)?.label)
60
+ }), (0, react_jsx_runtime.jsx)("dd", {
61
+ className: "min-w-0 break-words",
62
+ children: value(name)
63
+ })]
64
+ }, name))
65
+ })]
66
+ }), numbers.length === 0 ? null : (0, react_jsx_runtime.jsx)("div", {
67
+ "data-buro-item-trailing": "",
68
+ className: "flex shrink-0 flex-col items-end gap-1 border-l pl-3 text-sm tabular-nums",
69
+ children: numbers.map((name) => (0, react_jsx_runtime.jsx)("span", {
70
+ title: (0, _burojs_core.resolveFieldLabel)(caps, name, definition(name)?.label),
71
+ children: value(name)
72
+ }, name))
73
+ })]
74
+ });
75
+ }
76
+ //#endregion
77
+ //#region src/blocks/related-rows.tsx
78
+ function useRowAccess(resource) {
79
+ const app = (0, _burojs_react.useApp)();
80
+ const scope = (0, _burojs_react.useCtx)((c) => c.scope);
81
+ const user = (0, _burojs_react.useCtx)((c) => c.user);
82
+ const permissions = (0, _burojs_react.useCtx)((c) => c.permissions);
83
+ return (0, react.useCallback)((row) => (capability, target, defaultAllowed = true) => {
84
+ const rules = app.ruleSource.rules(resource);
85
+ if (rules.length === 0) return { allowed: defaultAllowed };
86
+ const ctx = (0, _burojs_core.ruleContextFor)({
87
+ user,
88
+ scope,
89
+ permissions,
90
+ record: row,
91
+ mode: "show",
92
+ resource
93
+ });
94
+ return (0, _burojs_core.resolveCapability)(rules, capability, target, ctx, defaultAllowed);
95
+ }, [
96
+ app.ruleSource,
97
+ resource,
98
+ scope,
99
+ user,
100
+ permissions
101
+ ]);
102
+ }
103
+ function useViewVisible(resource) {
104
+ const access = (0, _burojs_react.useFieldAccess)(resource, "every");
105
+ return (0, react.useCallback)((field) => {
106
+ const decision = access[field];
107
+ return decision === void 0 || decision.view === "visible";
108
+ }, [access]);
109
+ }
110
+ function useProjectedRows(resource, rows, item) {
111
+ const def = (0, _burojs_react.useApp)().registry.get(resource);
112
+ const accessOf = useRowAccess(resource);
113
+ const viewRow = (0, _burojs_react.useViewRow)(resource);
114
+ const viewVisible = useViewVisible(resource);
115
+ const idField = (def?.data)?.idField ?? "id";
116
+ const project = (0, react.useCallback)((row) => def === void 0 ? viewRow(row) : require_peek_filter.peekRow(def, viewRow(row), idField, accessOf(row), viewVisible), [
117
+ def,
118
+ idField,
119
+ accessOf,
120
+ viewRow,
121
+ viewVisible
122
+ ]);
123
+ const hidden = (0, react.useCallback)((field) => field !== idField && (def === void 0 || !require_peek_filter.peekLeafAllowed(def, field, accessOf(_burojs_core.RECORD_PROBE), viewVisible)), [
124
+ def,
125
+ idField,
126
+ accessOf,
127
+ viewVisible
128
+ ]);
129
+ const probe = (0, react.useMemo)(() => rows[0] === void 0 ? void 0 : project(rows[0]), [rows, project]);
130
+ return {
131
+ def,
132
+ project,
133
+ drawn: require_place_node.useItemDrawn(item, hidden, probe),
134
+ title: (0, react.useCallback)((row) => require_search_access.recordDisplayName(project(row), def?.displayField), [project, def])
135
+ };
136
+ }
137
+ function RowContent({ resource, raw, row, item, drawn, columns, variant }) {
138
+ const fallback = (0, react_jsx_runtime.jsx)(DefaultItem, {
139
+ resource,
140
+ row,
141
+ raw,
142
+ columns,
143
+ ...variant === void 0 ? {} : { variant }
144
+ });
145
+ if (item === void 0 || !drawn) return fallback;
146
+ return (0, react_jsx_runtime.jsx)(require_place_node.RelatedItem, {
147
+ handle: item,
148
+ row,
149
+ fallback
150
+ });
151
+ }
152
+ function RowOpener({ title, href, quick }) {
153
+ const RouterLink = require_toaster.useLinkComponent();
154
+ const className = "outline-none after:absolute after:inset-0 after:rounded-[inherit] focus-visible:after:ring-2 focus-visible:after:ring-ring";
155
+ const name = (0, react_jsx_runtime.jsx)("span", {
156
+ className: "sr-only",
157
+ children: title
158
+ });
159
+ if (quick !== null) return href ? (0, react_jsx_runtime.jsx)(require_search_access.ClaimedQuickLink, {
160
+ href,
161
+ className,
162
+ onOpen: quick,
163
+ children: name
164
+ }) : (0, react_jsx_runtime.jsx)("button", {
165
+ type: "button",
166
+ role: "link",
167
+ [_burojs_react.QUICK_ANCHOR_ATTRIBUTE]: "",
168
+ className: `${className} block size-0 p-0`,
169
+ onClick: (event) => {
170
+ if (!require_search_access.isPlainLeftClick(event)) return;
171
+ quick();
172
+ },
173
+ children: name
174
+ });
175
+ if (href) return (0, react_jsx_runtime.jsx)(RouterLink, {
176
+ href,
177
+ className,
178
+ children: name
179
+ });
180
+ return null;
181
+ }
182
+ const ITEM_LAYER_CLASS = "relative z-[1] pointer-events-none [&_a]:pointer-events-auto [&_button]:pointer-events-auto [&_input]:pointer-events-auto [&_select]:pointer-events-auto [&_textarea]:pointer-events-auto [&_summary]:pointer-events-auto [&_[role=button]]:pointer-events-auto [&_[role=link]]:pointer-events-auto [&_[role=checkbox]]:pointer-events-auto [&_[role=switch]]:pointer-events-auto";
183
+ //#endregion
184
+ Object.defineProperty(exports, "ITEM_LAYER_CLASS", {
185
+ enumerable: true,
186
+ get: function() {
187
+ return ITEM_LAYER_CLASS;
188
+ }
189
+ });
190
+ Object.defineProperty(exports, "RowContent", {
191
+ enumerable: true,
192
+ get: function() {
193
+ return RowContent;
194
+ }
195
+ });
196
+ Object.defineProperty(exports, "RowOpener", {
197
+ enumerable: true,
198
+ get: function() {
199
+ return RowOpener;
200
+ }
201
+ });
202
+ Object.defineProperty(exports, "useProjectedRows", {
203
+ enumerable: true,
204
+ get: function() {
205
+ return useProjectedRows;
206
+ }
207
+ });
208
+
209
+ //# sourceMappingURL=related-rows-zh5f_4QR.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"related-rows-zh5f_4QR.cjs","names":["useApp","useI18nCaps","peekLeafAllowed","peekFieldDefinition","ResolvedFieldDisplay","toDisplayText","recordDisplayName","Fragment","resolveFieldLabel","useApp","useCtx","useCallback","ruleContextFor","resolveCapability","useFieldAccess","useViewRow","peekRow","peekLeafAllowed","RECORD_PROBE","useMemo","useItemDrawn","recordDisplayName","RelatedItem","useLinkComponent","ClaimedQuickLink","QUICK_ANCHOR_ATTRIBUTE","isPlainLeftClick"],"sources":["../src/blocks/default-item.tsx","../src/blocks/related-rows.tsx"],"sourcesContent":["'use client';\nimport { type EntityRef, resolveFieldLabel } from '@burojs/core';\nimport { useApp, useI18nCaps } from '@burojs/react';\nimport { Fragment, type ReactElement } from 'react';\nimport { toDisplayText } from '../fields/display-value.js';\nimport { ResolvedFieldDisplay } from '../fields/resolved-field.js';\nimport {\n type PeekFieldSource,\n peekFieldDefinition,\n peekLeafAllowed,\n} from '../quick/peek-filter.js';\nimport { recordDisplayName } from '../resource/record-display-name.js';\nimport { type ListRow, useRowAccess, useViewVisible } from './related-rows.js';\n\n/** What a default item reads of the target's definition. */\ninterface TargetDefinition extends PeekFieldSource {\n readonly views?: { readonly list?: { readonly columns?: readonly string[] } };\n readonly ref?: EntityRef;\n}\n\n/** A field the default item puts in its trailing part: a number reads best right-aligned. */\nconst isNumeric = (field: { readonly kind?: unknown } | undefined) => field?.kind === 'number';\n\n/**\n * The item of a related list that names none (P6 3.13). As a card: the row's title (weight 500),\n * its other fields as muted label / value pairs, and its numbers in a trailing part set off by a\n * rule. As a timeline entry (`variant: 'entry'`): the title and the field values on one muted\n * meta line. `row` is the projected row, so a field the viewer may not see is already `null` and\n * is not listed.\n */\nexport function DefaultItem({\n resource,\n row,\n raw,\n columns,\n variant = 'card',\n}: {\n readonly resource: string;\n readonly row: Readonly<Record<string, unknown>>;\n /** The row as the list read it: column rules resolve over it. */\n readonly raw: ListRow;\n readonly columns?: readonly string[] | undefined;\n readonly variant?: 'card' | 'entry';\n}): ReactElement {\n const app = useApp();\n const def = app.registry.get(resource) as TargetDefinition | undefined;\n const caps = useI18nCaps(resource);\n const access = useRowAccess(resource)(raw);\n const viewVisible = useViewVisible(resource);\n const fields =\n def === undefined\n ? []\n : (columns ?? def.views?.list?.columns ?? Object.keys(def.fields)).filter(\n (name, index, names) =>\n name !== def.displayField &&\n names.indexOf(name) === index &&\n peekLeafAllowed(def, name, access, viewVisible),\n );\n const ref = def?.ref ?? { namespace: 'default', id: resource };\n const definition = (name: string) =>\n peekFieldDefinition(def!, name) as { readonly label?: string; readonly kind?: unknown };\n const value = (name: string) => (\n <ResolvedFieldDisplay\n resource={ref}\n name={name}\n field={definition(name) as never}\n value={row[name]}\n record={row}\n fallback={toDisplayText(row[name]).text}\n />\n );\n const title = (\n <p className=\"truncate text-sm font-medium\">{recordDisplayName(row, def?.displayField)}</p>\n );\n if (variant === 'entry') {\n const shown = fields.filter((name) => row[name] != null && row[name] !== '');\n return (\n <div className=\"flex min-w-0 flex-col gap-0.5\" data-buro-default-item=\"\">\n {title}\n {shown.length === 0 ? null : (\n <div data-buro-item-meta=\"\" className=\"truncate text-xs text-muted-foreground\">\n {shown.map((name, index) => (\n <Fragment key={name}>\n {index > 0 ? ' · ' : null}\n {value(name)}\n </Fragment>\n ))}\n </div>\n )}\n </div>\n );\n }\n const numbers = fields.filter((name) => isNumeric(definition(name)));\n const pairs = fields.filter((name) => !isNumeric(definition(name)));\n return (\n <div className=\"flex min-w-0 items-start gap-3\" data-buro-default-item=\"\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-2\">\n {title}\n {pairs.length === 0 ? null : (\n <dl className=\"grid gap-1.5\">\n {pairs.map((name) => (\n <div key={name} className=\"flex min-w-0 items-baseline gap-2 text-sm\">\n <dt className=\"w-24 shrink-0 truncate text-xs text-muted-foreground\">\n {resolveFieldLabel(caps, name, definition(name)?.label)}\n </dt>\n <dd className=\"min-w-0 break-words\">{value(name)}</dd>\n </div>\n ))}\n </dl>\n )}\n </div>\n {numbers.length === 0 ? null : (\n <div\n data-buro-item-trailing=\"\"\n className=\"flex shrink-0 flex-col items-end gap-1 border-l pl-3 text-sm tabular-nums\"\n >\n {numbers.map((name) => (\n <span key={name} title={resolveFieldLabel(caps, name, definition(name)?.label)}>\n {value(name)}\n </span>\n ))}\n </div>\n )}\n </div>\n );\n}\n","'use client';\nimport { type AppContext, RECORD_PROBE, resolveCapability, ruleContextFor } from '@burojs/core';\nimport { type CapabilityResolver, useApp, useCtx, useFieldAccess, useViewRow } from '@burojs/react';\nimport { type ReactElement, type ReactNode, useCallback, useMemo } from 'react';\nimport { QUICK_ANCHOR_ATTRIBUTE } from '@burojs/react';\nimport { ClaimedQuickLink, isPlainLeftClick } from '../fields/claimed-quick-link.js';\nimport { useLinkComponent } from '../layout/link-component.js';\nimport { type PeekFieldSource, peekLeafAllowed, peekRow } from '../quick/peek-filter.js';\nimport { recordDisplayName } from '../resource/record-display-name.js';\nimport { DefaultItem } from './default-item.js';\nimport { type ItemHandle, RelatedItem, useItemDrawn } from './related-item.js';\n\nexport type ListRow = { readonly id: string } & Readonly<Record<string, unknown>>;\n\n/** What `related-list` hands a rows view: the list's rows and how a row opens. */\nexport interface RelatedRowsProps {\n /** The target resource. */\n readonly resource: string;\n /** The placement's key (test ids). */\n readonly placementKey: string;\n readonly rows: readonly ListRow[];\n readonly item?: ItemHandle | undefined;\n /** The placement's `columns`, for the default item. */\n readonly columns?: readonly string[] | undefined;\n readonly rowQuick?: ((row: ListRow) => (() => void) | null) | undefined;\n readonly rowHref?: ((row: ListRow) => string | undefined) | undefined;\n}\n\n/**\n * A capability resolver per row: column rules resolve over the row they hide a field of, as the\n * peek's do (P6-B review), so a rule reading the record sees this row.\n */\nexport function useRowAccess(resource: string): (row: ListRow) => CapabilityResolver {\n const app = useApp();\n const scope = useCtx((c: AppContext) => c.scope);\n const user = useCtx((c: AppContext) => c.user);\n const permissions = useCtx((c: AppContext) => c.permissions);\n return useCallback(\n (row) =>\n (capability, target, defaultAllowed = true) => {\n const rules = app.ruleSource.rules(resource);\n if (rules.length === 0) return { allowed: defaultAllowed };\n const ctx = ruleContextFor({\n user,\n scope,\n permissions,\n record: row,\n mode: 'show',\n resource,\n });\n return resolveCapability(rules, capability, target, ctx, defaultAllowed);\n },\n [app.ruleSource, resource, scope, user, permissions],\n );\n}\n\n/**\n * Whether a field may be drawn on every row by its P5 view (P5 spec 3.6.6): a decision that is\n * not `visible` (`hidden`, `restricted`, `failed` and `pending` alike, so nothing is drawn while\n * the permission map loads) withholds it. A field the map does not decide is not withheld here. The decision\n * is the any-record one ({@link RECORD_PROBE}), so a rule reading the record counts as hiding.\n */\nexport function useViewVisible(resource: string): (field: string) => boolean {\n const access = useFieldAccess(resource, 'every');\n return useCallback(\n (field) => {\n const decision = access[field];\n return decision === undefined || decision.view === 'visible';\n },\n [access],\n );\n}\n\ninterface ProjectedRows {\n readonly def:\n | (PeekFieldSource & { readonly displayField?: string; readonly data?: unknown })\n | undefined;\n /** The row a card or an entry sees: the id and what the viewer may see; the rest read `null`. */\n readonly project: (row: ListRow) => ListRow;\n /** Whether the item block is drawn (decided once for the list), else the default item. */\n readonly drawn: boolean;\n readonly title: (row: ListRow) => string;\n}\n\n/**\n * The rows of a cards or timeline view, projected once and the item decided once per list.\n *\n * The rows arrive as the list read them (policy). A row is first projected by P5's field view\n * (`viewRow`: a field its user may not view for every row is left out) and then by the peek's\n * rule ({@link peekRow}): the id field and every field that is not `sensitive`, not withheld by\n * a field `requires.view` and not hidden by a `column` rule keep their values; every other\n * field reads `null`. It is the one place a row's fields are filtered before an item block or\n * the default item sees them (P6-66), and the timeline's axis reads the same row.\n */\nexport function useProjectedRows(\n resource: string,\n rows: readonly ListRow[],\n item: ItemHandle | undefined,\n): ProjectedRows {\n const app = useApp();\n const def = app.registry.get(resource) as ProjectedRows['def'];\n const accessOf = useRowAccess(resource);\n const viewRow = useViewRow(resource);\n const viewVisible = useViewVisible(resource);\n const idField = (def?.data as { readonly idField?: string } | undefined)?.idField ?? 'id';\n const project = useCallback(\n (row: ListRow): ListRow =>\n (def === undefined\n ? viewRow(row)\n : peekRow(def, viewRow(row), idField, accessOf(row), viewVisible)) as ListRow,\n [def, idField, accessOf, viewRow, viewVisible],\n );\n const hidden = useCallback(\n (field: string) =>\n field !== idField &&\n (def === undefined ||\n !peekLeafAllowed(def, field, accessOf(RECORD_PROBE as ListRow), viewVisible)),\n [def, idField, accessOf, viewVisible],\n );\n const probe = useMemo(\n () => (rows[0] === undefined ? undefined : project(rows[0])),\n [rows, project],\n );\n const drawn = useItemDrawn(item, hidden, probe);\n const title = useCallback(\n (row: ListRow) => recordDisplayName(project(row), def?.displayField),\n [project, def],\n );\n return { def, project, drawn, title };\n}\n\n/** The item block (or the default item) of one row. */\nexport function RowContent({\n resource,\n raw,\n row,\n item,\n drawn,\n columns,\n variant,\n}: {\n readonly resource: string;\n /** The row as the list read it (column rules resolve over it). */\n readonly raw: ListRow;\n /** The projected row. */\n readonly row: ListRow;\n readonly item: ItemHandle | undefined;\n readonly drawn: boolean;\n readonly columns?: readonly string[] | undefined;\n /** How the default item lays the row out: a card's, or a timeline entry's. */\n readonly variant?: 'card' | 'entry';\n}): ReactElement {\n const fallback = (\n <DefaultItem\n resource={resource}\n row={row}\n raw={raw}\n columns={columns}\n {...(variant === undefined ? {} : { variant })}\n />\n );\n if (item === undefined || !drawn) return fallback;\n return <RelatedItem handle={item} row={row} fallback={fallback} />;\n}\n\n/**\n * A card's or an entry's one opener (P6-74): the row's title as the accessible name of a single\n * anchor whose `::after` covers the positioned parent. A quick row is the page anchor claimed\n * for the opener (a modified click follows the `href`), or a link-role button without a page.\n * `open: 'none'` draws nothing.\n */\nexport function RowOpener({\n title,\n href,\n quick,\n}: {\n readonly title: string;\n readonly href: string | undefined;\n readonly quick: (() => void) | null;\n}): ReactElement | null {\n const RouterLink = useLinkComponent();\n const className =\n 'outline-none after:absolute after:inset-0 after:rounded-[inherit] focus-visible:after:ring-2 focus-visible:after:ring-ring';\n const name: ReactNode = <span className=\"sr-only\">{title}</span>;\n if (quick !== null)\n return href ? (\n <ClaimedQuickLink href={href} className={className} onOpen={quick}>\n {name}\n </ClaimedQuickLink>\n ) : (\n <button\n type=\"button\"\n role=\"link\"\n {...{ [QUICK_ANCHOR_ATTRIBUTE]: '' }}\n // A button is inline-block, so even with only an `sr-only` name it took a line of the\n // card and pushed the content down (REF-40). Zero-size and unpositioned, its `::after`\n // still covers the card.\n className={`${className} block size-0 p-0`}\n onClick={(event) => {\n if (!isPlainLeftClick(event)) return;\n quick();\n }}\n >\n {name}\n </button>\n );\n if (href)\n return (\n <RouterLink href={href} className={className}>\n {name}\n </RouterLink>\n );\n return null;\n}\n\n/**\n * The wrapper that raises an item's interactive descendants above the opener's cover (P6-74):\n * the wrapper itself lets clicks through to the opener, its controls take them.\n */\nexport const ITEM_LAYER_CLASS =\n 'relative z-[1] pointer-events-none [&_a]:pointer-events-auto [&_button]:pointer-events-auto [&_input]:pointer-events-auto [&_select]:pointer-events-auto [&_textarea]:pointer-events-auto [&_summary]:pointer-events-auto [&_[role=button]]:pointer-events-auto [&_[role=link]]:pointer-events-auto [&_[role=checkbox]]:pointer-events-auto [&_[role=switch]]:pointer-events-auto';\n"],"mappings":"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"}
@@ -0,0 +1,362 @@
1
+ const require_use_theme = require("./use-theme-DFlpXils.cjs");
2
+ const require_toaster = require("./toaster-C7CiYA4Z.cjs");
3
+ const require_button = require("./button-BxnnE28H.cjs");
4
+ const require_search_access = require("./search-access-B7G5oR8n.cjs");
5
+ let _burojs_core = require("@burojs/core");
6
+ let _burojs_react = require("@burojs/react");
7
+ let _tabler_icons_react = require("@tabler/icons-react");
8
+ let react = require("react");
9
+ react = require_use_theme.__toESM(react, 1);
10
+ let react_jsx_runtime = require("react/jsx-runtime");
11
+ let sonner = require("sonner");
12
+ //#region src/fields/relation-hand-back.tsx
13
+ function createdOptionFilter(input) {
14
+ const own = createdOptionScope(input);
15
+ const byId = {
16
+ field: input.idField,
17
+ op: "eq",
18
+ value: input.id
19
+ };
20
+ return own === void 0 ? byId : { and: [own, byId] };
21
+ }
22
+ function createdOptionScope(input) {
23
+ return (0, _burojs_core.composeListFilter)({
24
+ fixed: (0, _burojs_core.normalizeFixedFilters)(input.fixed),
25
+ search: "",
26
+ ...input.searchDecl === void 0 ? {} : { searchDecl: input.searchDecl },
27
+ ...input.searchContext === void 0 ? {} : { searchContext: input.searchContext }
28
+ });
29
+ }
30
+ function CreatedOptionRead({ to, filter, ignoreScope, by, idField, onSettled }) {
31
+ const query = (0, _burojs_react.useList)(to, {
32
+ filter,
33
+ pagination: {
34
+ kind: "offset",
35
+ page: 1,
36
+ pageSize: 1
37
+ },
38
+ ...ignoreScope ? { providerOptionsOverride: { ignoreScope: true } } : {},
39
+ retry: false
40
+ });
41
+ const settled = react.useRef(false);
42
+ const latest = react.useRef(onSettled);
43
+ latest.current = onSettled;
44
+ const rows = query.data?.data;
45
+ const answered = rows !== void 0 && query.isCurrentData && !query.isFetching;
46
+ const failed = query.isError && !query.isFetching;
47
+ react.useEffect(() => {
48
+ if (settled.current) return;
49
+ if (failed) {
50
+ settled.current = true;
51
+ latest.current({ kind: "failed" });
52
+ return;
53
+ }
54
+ if (!answered) return;
55
+ settled.current = true;
56
+ const value = rows[0]?.[by ?? idField];
57
+ latest.current(typeof value === "string" || typeof value === "number" ? {
58
+ kind: "fits",
59
+ value
60
+ } : { kind: "does-not-fit" });
61
+ }, [
62
+ answered,
63
+ failed,
64
+ rows,
65
+ by,
66
+ idField
67
+ ]);
68
+ return null;
69
+ }
70
+ //#endregion
71
+ //#region src/fields/relation-view-button.tsx
72
+ function selectKey(value) {
73
+ if (typeof value === "string") return value.length === 0 ? null : value;
74
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : null;
75
+ return null;
76
+ }
77
+ const VIEW_CLASS = require_use_theme.cn(require_button.buttonVariants({
78
+ variant: "outline",
79
+ size: "icon"
80
+ }), "shrink-0");
81
+ function RelationViewButton(props) {
82
+ const gate = (0, _burojs_react.useEntryGate)();
83
+ const { to, value, by } = props;
84
+ const access = (0, _burojs_react.useListAccess)(to);
85
+ const key = selectKey(value);
86
+ if (key === null || props.open === "none") return null;
87
+ if (by !== void 0 && !(access.status === "ready" && access.fieldVisible(by))) return null;
88
+ if (gate(to, "show").state !== "open") return null;
89
+ return (0, react_jsx_runtime.jsx)(ViewButton, {
90
+ ...props,
91
+ keyString: key
92
+ }, key);
93
+ }
94
+ function ViewButton({ to, by, ignoreScope, fieldName, keyString, beforeOpen, open: openMode = "quick" }) {
95
+ const app = (0, _burojs_react.useApp)();
96
+ const t = (0, _burojs_react.useOptionalT)();
97
+ const tid = (0, _burojs_react.useTestIds)();
98
+ const quick = (0, _burojs_react.useQuick)();
99
+ const navigate = (0, _burojs_react.useRouteNavigate)();
100
+ const RouterLink = require_toaster.useLinkComponent();
101
+ const [asked, setAsked] = react.useState(false);
102
+ const requested = react.useRef(false);
103
+ const targetDef = app.registry.get(to);
104
+ const rawIdField = (targetDef?.data)?.idField;
105
+ const idField = typeof rawIdField === "string" && rawIdField.length > 0 ? rawIdField : "id";
106
+ const read = (0, _burojs_react.useList)(to, {
107
+ ...asked && by !== void 0 ? {
108
+ filter: {
109
+ field: by,
110
+ op: "eq",
111
+ value: keyString
112
+ },
113
+ pagination: {
114
+ kind: "offset",
115
+ page: 1,
116
+ pageSize: 2
117
+ }
118
+ } : {},
119
+ ...ignoreScope === true ? { providerOptionsOverride: { ignoreScope: true } } : {},
120
+ enabled: asked && by !== void 0,
121
+ retry: false
122
+ });
123
+ const rows = read.isCurrentData && !read.isPlaceholderData && !read.isFetching ? read.data?.data : void 0;
124
+ const open = react.useCallback((id) => {
125
+ beforeOpen();
126
+ if (openMode === "page") {
127
+ if (targetDef !== void 0 && require_search_access.linksToPage(app, targetDef)) navigate((0, _burojs_core.resourceShowHref)(app.registry, targetDef, to, id));
128
+ return;
129
+ }
130
+ quick.show(to, id);
131
+ }, [
132
+ beforeOpen,
133
+ quick,
134
+ to,
135
+ openMode,
136
+ navigate,
137
+ app,
138
+ targetDef
139
+ ]);
140
+ react.useEffect(() => {
141
+ if (by === void 0 || !asked || rows === void 0 || !requested.current) return;
142
+ requested.current = false;
143
+ if (rows.length !== 1) {
144
+ if (rows.length > 1 && process.env.NODE_ENV !== "production") console.error(`[burojs] ${to}: more than one row has ${by} ${keyString}; "view" opened nothing.`);
145
+ return;
146
+ }
147
+ const id = rows[0]?.[idField];
148
+ const next = selectKey(id);
149
+ if (next !== null) open(next);
150
+ }, [
151
+ by,
152
+ asked,
153
+ rows,
154
+ idField,
155
+ keyString,
156
+ to,
157
+ open
158
+ ]);
159
+ const label = t("relationPicker.view", { defaultValue: "View" });
160
+ const icon = (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconEye, {
161
+ className: "h-4 w-4",
162
+ "aria-hidden": true
163
+ });
164
+ const testid = tid.relationView(to, fieldName);
165
+ if (openMode === "page" && (targetDef === void 0 || !require_search_access.linksToPage(app, targetDef))) return null;
166
+ if (openMode === "page" && by === void 0 && targetDef !== void 0) return (0, react_jsx_runtime.jsxs)(RouterLink, {
167
+ href: (0, _burojs_core.resourceShowHref)(app.registry, targetDef, to, keyString),
168
+ "data-testid": testid,
169
+ className: VIEW_CLASS,
170
+ onClick: () => beforeOpen(),
171
+ children: [icon, (0, react_jsx_runtime.jsx)("span", {
172
+ className: "sr-only",
173
+ children: label
174
+ })]
175
+ });
176
+ if (by === void 0 && targetDef !== void 0 && require_search_access.linksToPage(app, targetDef)) return (0, react_jsx_runtime.jsxs)(require_search_access.ClaimedQuickLink, {
177
+ href: (0, _burojs_core.resourceShowHref)(app.registry, targetDef, to, keyString),
178
+ testid,
179
+ className: VIEW_CLASS,
180
+ onOpen: () => open(keyString),
181
+ children: [icon, (0, react_jsx_runtime.jsx)("span", {
182
+ className: "sr-only",
183
+ children: label
184
+ })]
185
+ });
186
+ return (0, react_jsx_runtime.jsx)("button", {
187
+ type: "button",
188
+ className: VIEW_CLASS,
189
+ "data-testid": testid,
190
+ "aria-label": label,
191
+ [_burojs_react.QUICK_ANCHOR_ATTRIBUTE]: "",
192
+ onClick: (event) => {
193
+ event.preventDefault();
194
+ event.stopPropagation();
195
+ if (!require_search_access.isPlainLeftClick(event)) return;
196
+ if (by === void 0) {
197
+ open(keyString);
198
+ return;
199
+ }
200
+ requested.current = true;
201
+ setAsked(true);
202
+ if (rows !== void 0 && rows.length === 1) {
203
+ const next = selectKey(rows[0]?.[idField]);
204
+ requested.current = false;
205
+ if (next !== null) open(next);
206
+ }
207
+ },
208
+ children: icon
209
+ });
210
+ }
211
+ //#endregion
212
+ //#region src/fields/relation-create.tsx
213
+ function useSelectCreate(input) {
214
+ const t = (0, _burojs_react.useOptionalT)();
215
+ const { to: target } = input;
216
+ const [pending, setPending] = react.useState(false);
217
+ const [created, setCreated] = react.useState(null);
218
+ const latch = react.useRef(false);
219
+ const mounted = react.useRef(true);
220
+ react.useEffect(() => {
221
+ mounted.current = true;
222
+ return () => {
223
+ mounted.current = false;
224
+ };
225
+ }, []);
226
+ const latest = react.useRef(input);
227
+ latest.current = input;
228
+ const access = (0, _burojs_react.useListAccess)(target);
229
+ const blocked = input.held === true || access.status !== "ready" || require_search_access.namesHiddenField(createdOptionScope({
230
+ fixed: input.fixedFilters,
231
+ searchDecl: input.searchDecl,
232
+ searchContext: input.searchContext
233
+ }), (name) => access.fieldVisible(name));
234
+ const blockedRef = react.useRef(blocked);
235
+ blockedRef.current = blocked;
236
+ const release = react.useCallback(() => {
237
+ latch.current = false;
238
+ if (mounted.current) {
239
+ setPending(false);
240
+ setCreated(null);
241
+ }
242
+ }, []);
243
+ const start = react.useCallback((open) => {
244
+ if (latch.current || !mounted.current || blockedRef.current) return;
245
+ latch.current = true;
246
+ setPending(true);
247
+ let opened;
248
+ try {
249
+ opened = open();
250
+ } catch (error) {
251
+ release();
252
+ throw error;
253
+ }
254
+ opened.then((row) => {
255
+ if (!mounted.current) {
256
+ latch.current = false;
257
+ return;
258
+ }
259
+ const id = row === null ? null : selectKey(row[latest.current.idField]) ?? selectKey(row.id);
260
+ if (id === null) release();
261
+ else setCreated({ id });
262
+ }, () => release());
263
+ }, [release]);
264
+ const settle = react.useCallback((result) => {
265
+ if (mounted.current) {
266
+ if (result.kind === "fits") latest.current.onValue(result.value);
267
+ else if (result.kind === "does-not-fit") (0, sonner.toast)(t("relationPicker.createdNotFitting", { defaultValue: "The record was created but does not fit this field" }));
268
+ else sonner.toast.error(t("relationPicker.createdNotSelected", { defaultValue: "The record was created but could not be selected" }));
269
+ }
270
+ release();
271
+ }, [release, t]);
272
+ return {
273
+ create: react.useMemo(() => ({
274
+ pending,
275
+ blocked,
276
+ start
277
+ }), [
278
+ pending,
279
+ blocked,
280
+ start
281
+ ]),
282
+ reader: created === null || blocked ? null : (0, react_jsx_runtime.jsx)(CreatedOptionRead, {
283
+ to: target,
284
+ filter: createdOptionFilter({
285
+ fixed: input.fixedFilters,
286
+ idField: input.idField,
287
+ id: created.id,
288
+ searchDecl: input.searchDecl,
289
+ searchContext: input.searchContext
290
+ }),
291
+ ignoreScope: input.fixedFilters !== void 0 && input.fixedFilters.length > 0,
292
+ by: input.by,
293
+ idField: input.idField,
294
+ onSettled: settle
295
+ }, created.id)
296
+ };
297
+ }
298
+ function plainStringField(def) {
299
+ if (def === null || typeof def !== "object") return false;
300
+ const field = def;
301
+ return field.kind === "string" && field.system !== true && field.opts?.system !== true && field.opts?.enum === void 0 && field.opts?.localized !== true;
302
+ }
303
+ function RelationCreateButton(props) {
304
+ const gate = (0, _burojs_react.useEntryGate)();
305
+ const { to } = props;
306
+ if (props.create.blocked || gate(to, "create").state !== "open") return null;
307
+ return (0, react_jsx_runtime.jsx)(CreateButton, { ...props });
308
+ }
309
+ function CreateButton({ to, fieldName, create, seeds, search, beforeOpen, className, testId }) {
310
+ const app = (0, _burojs_react.useApp)();
311
+ const t = (0, _burojs_react.useOptionalT)();
312
+ const tid = (0, _burojs_react.useTestIds)();
313
+ const quick = (0, _burojs_react.useQuick)();
314
+ const label = t("relationPicker.create", { defaultValue: "+ Create" });
315
+ return (0, react_jsx_runtime.jsx)("button", {
316
+ type: "button",
317
+ "data-testid": testId ?? tid.relationCreate(to, fieldName),
318
+ disabled: create.pending,
319
+ className,
320
+ onClick: () => {
321
+ const text = search?.trim() ?? "";
322
+ const displayField = app.registry.get(to)?.displayField;
323
+ const fields = app.registry.get(to)?.fields;
324
+ const prefill = text.length > 0 && typeof displayField === "string" && fields !== void 0 && Object.hasOwn(fields, displayField) && plainStringField(fields[displayField]) ? { [displayField]: text } : void 0;
325
+ create.start(() => {
326
+ beforeOpen();
327
+ return quick.create(to, {
328
+ ...seeds === void 0 || Object.keys(seeds).length === 0 ? {} : { defaults: seeds },
329
+ ...prefill === void 0 ? {} : { input: prefill }
330
+ });
331
+ });
332
+ },
333
+ children: label
334
+ });
335
+ }
336
+ //#endregion
337
+ Object.defineProperty(exports, "RelationCreateButton", {
338
+ enumerable: true,
339
+ get: function() {
340
+ return RelationCreateButton;
341
+ }
342
+ });
343
+ Object.defineProperty(exports, "RelationViewButton", {
344
+ enumerable: true,
345
+ get: function() {
346
+ return RelationViewButton;
347
+ }
348
+ });
349
+ Object.defineProperty(exports, "selectKey", {
350
+ enumerable: true,
351
+ get: function() {
352
+ return selectKey;
353
+ }
354
+ });
355
+ Object.defineProperty(exports, "useSelectCreate", {
356
+ enumerable: true,
357
+ get: function() {
358
+ return useSelectCreate;
359
+ }
360
+ });
361
+
362
+ //# sourceMappingURL=relation-create-BOaUe12G.cjs.map