@burojs/ui-shadcn 0.8.0 → 0.10.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 (126) hide show
  1. package/dist/{bulk-summary-2HLgz7Il.cjs → bulk-summary-Chc61Pyw.cjs} +9 -7
  2. package/dist/bulk-summary-Chc61Pyw.cjs.map +1 -0
  3. package/dist/{bulk-summary-D6A0ua21.js → bulk-summary-DpSQD2Fq.js} +9 -7
  4. package/dist/bulk-summary-DpSQD2Fq.js.map +1 -0
  5. package/dist/{candidates-relation-picker-CGXItMN0.js → candidates-relation-picker-DRsHKe6N.js} +3 -3
  6. package/dist/{candidates-relation-picker-CGXItMN0.js.map → candidates-relation-picker-DRsHKe6N.js.map} +1 -1
  7. package/dist/{candidates-relation-picker-C47mF260.cjs → candidates-relation-picker-GIxsp7D_.cjs} +3 -3
  8. package/dist/{candidates-relation-picker-C47mF260.cjs.map → candidates-relation-picker-GIxsp7D_.cjs.map} +1 -1
  9. package/dist/{check-confirm-dialog-BT04Mieo.cjs → check-confirm-dialog-BMSb7wFv.cjs} +76 -9
  10. package/dist/check-confirm-dialog-BMSb7wFv.cjs.map +1 -0
  11. package/dist/{check-confirm-dialog-CtiRzOAt.js → check-confirm-dialog-B_u3YVHS.js} +72 -11
  12. package/dist/{check-confirm-dialog-CtiRzOAt.js.map → check-confirm-dialog-B_u3YVHS.js.map} +1 -1
  13. package/dist/{filter-builder-z3Axzf9Y.js → filter-builder-DX-xC3Yd.js} +14 -6
  14. package/dist/filter-builder-DX-xC3Yd.js.map +1 -0
  15. package/dist/{filter-builder-ByGhxLf_.cjs → filter-builder-Dt5E8PSX.cjs} +14 -6
  16. package/dist/filter-builder-Dt5E8PSX.cjs.map +1 -0
  17. package/dist/{flow-runtime-BVFjMU5-.cjs → flow-runtime-CQ4wf8co.cjs} +3 -3
  18. package/dist/{flow-runtime-BVFjMU5-.cjs.map → flow-runtime-CQ4wf8co.cjs.map} +1 -1
  19. package/dist/{flow-runtime-DrUWyTS0.js → flow-runtime-Q2vD7R3c.js} +3 -3
  20. package/dist/{flow-runtime-DrUWyTS0.js.map → flow-runtime-Q2vD7R3c.js.map} +1 -1
  21. package/dist/{flow-screen-3fk6J33y.js → flow-screen-B1y2yizP.js} +68 -29
  22. package/dist/flow-screen-B1y2yizP.js.map +1 -0
  23. package/dist/{flow-screen-6y5E_HT6.cjs → flow-screen-sw2cP70t.cjs} +67 -28
  24. package/dist/flow-screen-sw2cP70t.cjs.map +1 -0
  25. package/dist/index.cjs +2304 -247
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +119 -12
  28. package/dist/index.d.ts +119 -12
  29. package/dist/index.js +2225 -172
  30. package/dist/index.js.map +1 -1
  31. package/dist/{inline-flow-host-C4KmZIYE.cjs → inline-flow-host-CkhoA69R.cjs} +3 -3
  32. package/dist/{inline-flow-host-C4KmZIYE.cjs.map → inline-flow-host-CkhoA69R.cjs.map} +1 -1
  33. package/dist/{inline-flow-host-YnnvWjdU.js → inline-flow-host-DqbXqcPS.js} +3 -3
  34. package/dist/{inline-flow-host-YnnvWjdU.js.map → inline-flow-host-DqbXqcPS.js.map} +1 -1
  35. package/dist/{lazy-relation-picker-dialog-DN4bvQfg.js → lazy-relation-picker-dialog-BaIEWLbF.js} +3 -52
  36. package/dist/lazy-relation-picker-dialog-BaIEWLbF.js.map +1 -0
  37. package/dist/{lazy-relation-picker-dialog-BAKBRn3V.cjs → lazy-relation-picker-dialog-CeRzOAi0.cjs} +3 -52
  38. package/dist/lazy-relation-picker-dialog-CeRzOAi0.cjs.map +1 -0
  39. package/dist/{page-flow-route-CtEfqAvU.js → page-flow-route-CP7cS7FY.js} +7 -7
  40. package/dist/page-flow-route-CP7cS7FY.js.map +1 -0
  41. package/dist/{page-flow-route-DEjAxHe3.cjs → page-flow-route-UDx8qvdM.cjs} +10 -10
  42. package/dist/page-flow-route-UDx8qvdM.cjs.map +1 -0
  43. package/dist/{place-node-Bhl8B3fF.cjs → place-node-C5ZmuHaN.cjs} +208 -55
  44. package/dist/place-node-C5ZmuHaN.cjs.map +1 -0
  45. package/dist/{place-node-BdxT-30h.js → place-node-DwWAigv0.js} +205 -58
  46. package/dist/place-node-DwWAigv0.js.map +1 -0
  47. package/dist/record-trail-store-Cjo9vtod.cjs +126 -0
  48. package/dist/record-trail-store-Cjo9vtod.cjs.map +1 -0
  49. package/dist/record-trail-store-Dn6bVry4.js +91 -0
  50. package/dist/record-trail-store-Dn6bVry4.js.map +1 -0
  51. package/dist/{related-list-cards-Bc_vfCE_.cjs → related-list-cards-BypKfm9t.cjs} +3 -3
  52. package/dist/{related-list-cards-Bc_vfCE_.cjs.map → related-list-cards-BypKfm9t.cjs.map} +1 -1
  53. package/dist/{related-list-cards-BvkD5OcC.js → related-list-cards-Dcmruy09.js} +3 -3
  54. package/dist/{related-list-cards-BvkD5OcC.js.map → related-list-cards-Dcmruy09.js.map} +1 -1
  55. package/dist/{related-list-timeline-k0DtnxTs.cjs → related-list-timeline-D-KClgKb.cjs} +4 -4
  56. package/dist/related-list-timeline-D-KClgKb.cjs.map +1 -0
  57. package/dist/{related-list-timeline-DCrwN9oO.js → related-list-timeline-DZON_qSc.js} +4 -4
  58. package/dist/related-list-timeline-DZON_qSc.js.map +1 -0
  59. package/dist/{related-rows-BW9Jr07T.cjs → related-rows-DgF05ssi.cjs} +4 -4
  60. package/dist/{related-rows-BW9Jr07T.cjs.map → related-rows-DgF05ssi.cjs.map} +1 -1
  61. package/dist/{related-rows-CPE-9FFr.js → related-rows-ETZl5CB9.js} +4 -4
  62. package/dist/{related-rows-CPE-9FFr.js.map → related-rows-ETZl5CB9.js.map} +1 -1
  63. package/dist/{relation-create-DDEYcKfw.cjs → relation-create-B8zngAcA.cjs} +82 -13
  64. package/dist/relation-create-B8zngAcA.cjs.map +1 -0
  65. package/dist/{relation-create-C43cdPQt.js → relation-create-CeCWyxIb.js} +79 -16
  66. package/dist/relation-create-CeCWyxIb.js.map +1 -0
  67. package/dist/{relation-many-picker-BlrGRwMV.js → relation-many-picker-CT7nKfE2.js} +12 -10
  68. package/dist/relation-many-picker-CT7nKfE2.js.map +1 -0
  69. package/dist/{relation-many-picker-Br-zBHxT.cjs → relation-many-picker-Cq0EHY5I.cjs} +12 -10
  70. package/dist/relation-many-picker-Cq0EHY5I.cjs.map +1 -0
  71. package/dist/{relation-picker-x7P5HKie.js → relation-picker-CCyuMeGq.js} +13 -10
  72. package/dist/relation-picker-CCyuMeGq.js.map +1 -0
  73. package/dist/{relation-picker-ADjxI_TI.cjs → relation-picker-DmwTzgsd.cjs} +13 -10
  74. package/dist/relation-picker-DmwTzgsd.cjs.map +1 -0
  75. package/dist/{relation-picker-dialog-CyKliBkN.js → relation-picker-dialog-CoWKjNv8.js} +5 -5
  76. package/dist/relation-picker-dialog-CoWKjNv8.js.map +1 -0
  77. package/dist/{relation-picker-dialog-DimVQF9Y.cjs → relation-picker-dialog-mbwyNK43.cjs} +5 -5
  78. package/dist/relation-picker-dialog-mbwyNK43.cjs.map +1 -0
  79. package/dist/{relation-select-Cr3CfNLy.cjs → relation-select-CguIo2M5.cjs} +2 -2
  80. package/dist/{relation-select-Cr3CfNLy.cjs.map → relation-select-CguIo2M5.cjs.map} +1 -1
  81. package/dist/{relation-select-B8Fq4o-t.js → relation-select-nAYxhopN.js} +2 -2
  82. package/dist/{relation-select-B8Fq4o-t.js.map → relation-select-nAYxhopN.js.map} +1 -1
  83. package/dist/{success-notices-Dl3M1fZP.cjs → success-notices-Cl4b6MLQ.cjs} +3 -2
  84. package/dist/success-notices-Cl4b6MLQ.cjs.map +1 -0
  85. package/dist/{success-notices-LDEgEkc4.js → success-notices-CrcWOGSo.js} +3 -2
  86. package/dist/success-notices-CrcWOGSo.js.map +1 -0
  87. package/dist/{use-dialog-filter-state-tNvqAAjh.cjs → use-dialog-filter-state-CpWblz3C.cjs} +2 -2
  88. package/dist/{use-dialog-filter-state-tNvqAAjh.cjs.map → use-dialog-filter-state-CpWblz3C.cjs.map} +1 -1
  89. package/dist/{use-dialog-filter-state-B_MqzHaT.js → use-dialog-filter-state-ZYxOp5WO.js} +2 -2
  90. package/dist/{use-dialog-filter-state-B_MqzHaT.js.map → use-dialog-filter-state-ZYxOp5WO.js.map} +1 -1
  91. package/dist/{use-record-subtitle-bfwIoUme.cjs → use-record-subtitle-B4lTR7pf.cjs} +5 -8
  92. package/dist/use-record-subtitle-B4lTR7pf.cjs.map +1 -0
  93. package/dist/{use-record-subtitle-gIaCGgbI.js → use-record-subtitle-pWMBqQx9.js} +5 -8
  94. package/dist/use-record-subtitle-pWMBqQx9.js.map +1 -0
  95. package/package.json +9 -9
  96. package/dist/bulk-summary-2HLgz7Il.cjs.map +0 -1
  97. package/dist/bulk-summary-D6A0ua21.js.map +0 -1
  98. package/dist/check-confirm-dialog-BT04Mieo.cjs.map +0 -1
  99. package/dist/filter-builder-ByGhxLf_.cjs.map +0 -1
  100. package/dist/filter-builder-z3Axzf9Y.js.map +0 -1
  101. package/dist/flow-screen-3fk6J33y.js.map +0 -1
  102. package/dist/flow-screen-6y5E_HT6.cjs.map +0 -1
  103. package/dist/lazy-relation-picker-dialog-BAKBRn3V.cjs.map +0 -1
  104. package/dist/lazy-relation-picker-dialog-DN4bvQfg.js.map +0 -1
  105. package/dist/page-flow-route-CtEfqAvU.js.map +0 -1
  106. package/dist/page-flow-route-DEjAxHe3.cjs.map +0 -1
  107. package/dist/place-node-BdxT-30h.js.map +0 -1
  108. package/dist/place-node-Bhl8B3fF.cjs.map +0 -1
  109. package/dist/related-list-timeline-DCrwN9oO.js.map +0 -1
  110. package/dist/related-list-timeline-k0DtnxTs.cjs.map +0 -1
  111. package/dist/relation-create-C43cdPQt.js.map +0 -1
  112. package/dist/relation-create-DDEYcKfw.cjs.map +0 -1
  113. package/dist/relation-many-picker-BlrGRwMV.js.map +0 -1
  114. package/dist/relation-many-picker-Br-zBHxT.cjs.map +0 -1
  115. package/dist/relation-picker-ADjxI_TI.cjs.map +0 -1
  116. package/dist/relation-picker-dialog-CyKliBkN.js.map +0 -1
  117. package/dist/relation-picker-dialog-DimVQF9Y.cjs.map +0 -1
  118. package/dist/relation-picker-x7P5HKie.js.map +0 -1
  119. package/dist/resource-page-router-BRpUnhay.js +0 -1958
  120. package/dist/resource-page-router-BRpUnhay.js.map +0 -1
  121. package/dist/resource-page-router-qEd2xb55.cjs +0 -2167
  122. package/dist/resource-page-router-qEd2xb55.cjs.map +0 -1
  123. package/dist/success-notices-Dl3M1fZP.cjs.map +0 -1
  124. package/dist/success-notices-LDEgEkc4.js.map +0 -1
  125. package/dist/use-record-subtitle-bfwIoUme.cjs.map +0 -1
  126. package/dist/use-record-subtitle-gIaCGgbI.js.map +0 -1
@@ -1,15 +1,15 @@
1
1
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
2
2
  const require_toaster = require("./toaster-BbByOytP.cjs");
3
- const require_check_confirm_dialog = require("./check-confirm-dialog-BT04Mieo.cjs");
3
+ const require_check_confirm_dialog = require("./check-confirm-dialog-BMSb7wFv.cjs");
4
4
  const require_button = require("./button-BxnnE28H.cjs");
5
5
  const require_input = require("./input-BI0czGyI.cjs");
6
6
  const require_dialog = require("./dialog-vmMdfUWs.cjs");
7
- const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
7
+ const require_relation_create = require("./relation-create-B8zngAcA.cjs");
8
8
  const require_skeleton = require("./skeleton-_1gP7wan.cjs");
9
- const require_filter_builder = require("./filter-builder-ByGhxLf_.cjs");
9
+ const require_filter_builder = require("./filter-builder-Dt5E8PSX.cjs");
10
10
  const require_label = require("./label-w6JYf2cF.cjs");
11
- const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BAKBRn3V.cjs");
12
- const require_relation_select = require("./relation-select-Cr3CfNLy.cjs");
11
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-CeRzOAi0.cjs");
12
+ const require_relation_select = require("./relation-select-CguIo2M5.cjs");
13
13
  let _burojs_core = require("@burojs/core");
14
14
  let _burojs_react = require("@burojs/react");
15
15
  let _tabler_icons_react = require("@tabler/icons-react");
@@ -882,6 +882,20 @@ function AppFlowButton({ action, variant = "ghost", size = "sm", className }) {
882
882
  actionName: action.name,
883
883
  surface: "app"
884
884
  });
885
+ if (action.undecided === true) return (0, react_jsx_runtime.jsx)(require_button.Button, {
886
+ type: "button",
887
+ variant,
888
+ size,
889
+ className,
890
+ "data-testid": testid,
891
+ "data-buro-flow-state": "undecided",
892
+ disabled: true,
893
+ "aria-busy": "true",
894
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.ActionInner, {
895
+ icon: action.icon,
896
+ label
897
+ })
898
+ });
885
899
  if (action.hostHref !== void 0) return (0, react_jsx_runtime.jsx)(require_button.Button, {
886
900
  asChild: true,
887
901
  variant,
@@ -1449,14 +1463,15 @@ function useExportRunWatcher() {
1449
1463
  //#endregion
1450
1464
  //#region src/actions/action-overflow.tsx
1451
1465
  const RowActionsCollapseContext = (0, react.createContext)(false);
1452
- function ActionOverflow({ resource: resourceInput, record, surface, className, hideFlows, collapse, sources }) {
1466
+ function ActionOverflow({ resource: resourceInput, record, surface, className, hideFlows, hideActions, collapse, sources }) {
1453
1467
  const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
1454
1468
  const chromeT = (0, _burojs_react.useChromeT)();
1455
1469
  const tid = (0, _burojs_react.useTestIds)();
1456
1470
  const recordKey = String((0, _burojs_react.recordKeyOf)((0, _burojs_react.useApp)().registry.get(resource), record) ?? "");
1457
1471
  const collapsedRows = (0, react.useContext)(RowActionsCollapseContext);
1458
1472
  const [flowFor, setFlowFor] = (0, react.useState)(null);
1459
- const actions = useShownItemActions(resource, record, surface, hideFlows, sources);
1473
+ const shown = useShownItemActions(resource, record, surface, hideFlows, sources);
1474
+ const actions = hideActions === void 0 ? shown : shown.filter((a) => !hideActions(a.name));
1460
1475
  if (actions.length === 0) return null;
1461
1476
  const isRow = surface === "row";
1462
1477
  const folded = isRow && (collapse ?? collapsedRows);
@@ -3045,6 +3060,22 @@ function actionsColumnSize(items) {
3045
3060
  const strip = controls * ROW_ACTION_CONTROL_PX + (controls - 1) * ROW_ACTION_GAP_PX + ACTIONS_CELL_PADDING_PX;
3046
3061
  return Math.max(ACTIONS_COL_MIN_PX, strip);
3047
3062
  }
3063
+ const isNamedEntry = (value) => typeof value === "object" && value !== null;
3064
+ function offered(items, offers) {
3065
+ return offers === void 0 || items === void 0 ? items : items.filter((action) => offers(action.name));
3066
+ }
3067
+ function rowFlowsOf(def, offers) {
3068
+ if (!def) return [];
3069
+ const items = offered(def.actions?.item, offers) ?? [];
3070
+ const out = [];
3071
+ for (const placement of (0, _burojs_core.planItemActions)(items, "row")) {
3072
+ if (items.find((entry) => entry.name === placement.name)?.kind !== "flow") continue;
3073
+ try {
3074
+ out.push((0, _burojs_core.compileFlow)(def, placement.name));
3075
+ } catch {}
3076
+ }
3077
+ return out;
3078
+ }
3048
3079
  const ALIGN_CLASS = {
3049
3080
  start: "text-start",
3050
3081
  center: "text-center",
@@ -3111,25 +3142,72 @@ function ResourceList({ resource: resourceInput, data, total, page = 1, pageSize
3111
3142
  ]);
3112
3143
  const skeletonColumnKeys = accessPending ? declaredColumnKeys : visibleColumnKeys;
3113
3144
  const rows = (0, react.useMemo)(() => data ?? [], [data]);
3114
- const rowFlows = (0, react.useMemo)(() => {
3115
- if (!def) return [];
3116
- const items = def.actions?.item ?? [];
3117
- const out = [];
3118
- for (const placement of (0, _burojs_core.planItemActions)(items, "row")) {
3119
- if (items.find((entry) => entry.name === placement.name)?.kind !== "flow") continue;
3120
- try {
3121
- out.push((0, _burojs_core.compileFlow)(def, placement.name));
3122
- } catch {}
3145
+ const collectionRows = (0, _burojs_react.useCollectionRows)(resource);
3146
+ const rowKinds = (0, react.useMemo)(() => collectionRows === void 0 ? void 0 : rows.map((row) => collectionRows(row)), [collectionRows, rows]);
3147
+ const rowOffers = (0, react.useMemo)(() => {
3148
+ const fact = (0, _burojs_core.memberFactOf)(def);
3149
+ if (fact?.collection === void 0 || def?.rowActions !== "base") return void 0;
3150
+ const declared = app.registry.bases.get(fact.ref)?.actions?.item;
3151
+ const names = new Set(["edit", "delete"]);
3152
+ if (Array.isArray(declared)) {
3153
+ for (const entry of declared) if (isNamedEntry(entry) && typeof entry.name === "string") names.add(entry.name);
3123
3154
  }
3124
- return out;
3125
- }, [def]);
3126
- const pageIds = (0, react.useMemo)(() => rows.map((row) => String(row.id)), [rows]);
3127
- const rowBatch = (0, _burojs_react.useFlowRowBatch)(resource, pageIds, rowFlows);
3128
- const rowBatchState = rowBatch.state;
3129
- const flowRowBatch = (0, react.useMemo)(() => ({
3155
+ return (name) => names.has(name);
3156
+ }, [def, app]);
3157
+ const hideRowAction = (0, react.useMemo)(() => rowOffers === void 0 ? void 0 : (name) => !rowOffers(name), [rowOffers]);
3158
+ const flowsByDef = (0, react.useMemo)(() => {
3159
+ const cache = new WeakMap();
3160
+ return (target) => {
3161
+ if (target === void 0) return [];
3162
+ let flows = cache.get(target);
3163
+ if (flows === void 0) {
3164
+ flows = rowFlowsOf(target, rowOffers);
3165
+ cache.set(target, flows);
3166
+ }
3167
+ return flows;
3168
+ };
3169
+ }, [rowOffers]);
3170
+ const batchGroups = (0, react.useMemo)(() => {
3171
+ if (rowKinds === void 0) return [{
3172
+ resource,
3173
+ ids: rows.map((row) => String(row.id)),
3174
+ flows: flowsByDef(def)
3175
+ }];
3176
+ const idsByMember = new Map();
3177
+ rowKinds.forEach((kind, index) => {
3178
+ if (!("member" in kind)) return;
3179
+ const ids = idsByMember.get(kind.member) ?? [];
3180
+ ids.push(String(rows[index]?.id));
3181
+ idsByMember.set(kind.member, ids);
3182
+ });
3183
+ return [...idsByMember].map(([member, ids]) => ({
3184
+ resource: member,
3185
+ ids,
3186
+ flows: flowsByDef(app.registry.get(member)),
3187
+ list: resource
3188
+ }));
3189
+ }, [
3190
+ rowKinds,
3191
+ rows,
3130
3192
  resource,
3131
- state: rowBatchState
3132
- }), [resource, rowBatchState]);
3193
+ def,
3194
+ flowsByDef,
3195
+ app
3196
+ ]);
3197
+ const rowBatch = (0, _burojs_react.useFlowRowBatches)(batchGroups);
3198
+ const rowBatchState = rowBatch.state;
3199
+ const flowRowBatch = (0, react.useMemo)(() => ({ state: rowBatchState }), [rowBatchState]);
3200
+ const actionsWidth = (0, react.useMemo)(() => {
3201
+ if (rowKinds === void 0) return actionsColumnSize(def?.actions?.item);
3202
+ let widest = ACTIONS_COL_MIN_PX;
3203
+ for (const member of new Set(rowKinds.flatMap((kind) => "member" in kind ? [kind.member] : []))) widest = Math.max(widest, actionsColumnSize(offered(app.registry.get(member)?.actions?.item, rowOffers)));
3204
+ return widest;
3205
+ }, [
3206
+ rowKinds,
3207
+ def,
3208
+ app,
3209
+ rowOffers
3210
+ ]);
3133
3211
  const knownTotal = typeof total === "number";
3134
3212
  const totalPages = knownTotal ? Math.max(1, Math.ceil(total / pageSize)) : void 0;
3135
3213
  const pageIsFull = rows.length >= pageSize;
@@ -3377,7 +3455,7 @@ function ResourceList({ resource: resourceInput, data, total, page = 1, pageSize
3377
3455
  id: ACTIONS_COL_ID,
3378
3456
  enableSorting: false,
3379
3457
  enableResizing: false,
3380
- size: narrow || typeof rowActions === "function" ? 44 : actionsColumnSize(def?.actions?.item),
3458
+ size: narrow || typeof rowActions === "function" ? 44 : actionsWidth,
3381
3459
  enableHiding: false,
3382
3460
  header: () => (0, react_jsx_runtime.jsx)("span", {
3383
3461
  className: "sr-only",
@@ -3388,11 +3466,22 @@ function ResourceList({ resource: resourceInput, data, total, page = 1, pageSize
3388
3466
  noRowNav: true,
3389
3467
  noClip: true
3390
3468
  },
3391
- cell: ({ row }) => typeof rowActions === "function" ? rowActions(row.original) : (0, react_jsx_runtime.jsx)(ActionOverflow, {
3392
- resource,
3393
- record: row.original,
3394
- surface: "row"
3395
- })
3469
+ cell: ({ row }) => {
3470
+ if (typeof rowActions === "function") return rowActions(row.original);
3471
+ if (collectionRows === void 0) return (0, react_jsx_runtime.jsx)(ActionOverflow, {
3472
+ resource,
3473
+ record: row.original,
3474
+ surface: "row"
3475
+ });
3476
+ const kind = collectionRows(row.original);
3477
+ if (!("member" in kind)) return null;
3478
+ return (0, react_jsx_runtime.jsx)(ActionOverflow, {
3479
+ resource: kind.member,
3480
+ record: row.original,
3481
+ surface: "row",
3482
+ ...hideRowAction === void 0 ? {} : { hideActions: hideRowAction }
3483
+ });
3484
+ }
3396
3485
  });
3397
3486
  return cols;
3398
3487
  }, [
@@ -3409,6 +3498,9 @@ function ResourceList({ resource: resourceInput, data, total, page = 1, pageSize
3409
3498
  i18nCaps,
3410
3499
  rowLinkKey,
3411
3500
  narrow,
3501
+ actionsWidth,
3502
+ collectionRows,
3503
+ hideRowAction,
3412
3504
  columnUiOf
3413
3505
  ]);
3414
3506
  const handleSelectionChange = (updater) => {
@@ -3597,7 +3689,7 @@ function ResourceList({ resource: resourceInput, data, total, page = 1, pageSize
3597
3689
  value: flowRowBatch,
3598
3690
  children: (0, react_jsx_runtime.jsxs)(RowActionsCollapseContext.Provider, {
3599
3691
  value: narrow,
3600
- children: [rowBatch.reader, (0, react_jsx_runtime.jsxs)("div", {
3692
+ children: [rowBatch.readers, (0, react_jsx_runtime.jsxs)("div", {
3601
3693
  ref: listRoot,
3602
3694
  className: require_use_theme.cn("space-y-4", className),
3603
3695
  children: [
@@ -4476,7 +4568,7 @@ function issueText(issue, caps, i18nPrefix) {
4476
4568
  }, {
4477
4569
  has: caps.has,
4478
4570
  t: caps.t,
4479
- ...issue.field === "_form" ? {} : { fieldKey: `resources.${i18nPrefix}.fields.${issue.field}` }
4571
+ ...issue.field === "_form" ? {} : { fieldKey: `resources.${i18nPrefix}.${(0, _burojs_core.propertyTextKey)([...issue.field.split("."), ...issue.path])}` }
4480
4572
  });
4481
4573
  }
4482
4574
  const EMPTY_ISSUES = Object.freeze([]);
@@ -4525,9 +4617,10 @@ function DeclarativeForm(props) {
4525
4617
  function DeclarativeFormBody(props) {
4526
4618
  const gate = useDeclarativeCheckGate();
4527
4619
  const prefix = props.i18nPrefix ?? "form";
4620
+ const mode = props.mode ?? "create";
4528
4621
  const form = (0, _burojs_react.useFormController)({
4529
4622
  fields: props.fields,
4530
- mode: "create",
4623
+ mode,
4531
4624
  onConfirmChecks: gate.confirmChecks,
4532
4625
  ...props.body === void 0 ? {} : { body: props.body },
4533
4626
  ...props.formId === void 0 ? {} : { formId: props.formId },
@@ -4592,7 +4685,7 @@ function DeclarativeFormBody(props) {
4592
4685
  children: (0, react_jsx_runtime.jsx)(ScreenTree, {
4593
4686
  region: "form-body",
4594
4687
  resource: prefix,
4595
- mode: "create",
4688
+ mode,
4596
4689
  compiled: form.screen,
4597
4690
  controller: form,
4598
4691
  leafIds,
@@ -4956,10 +5049,12 @@ function BulkSummary(props) {
4956
5049
  children: (0, react_jsx_runtime.jsx)(Summary, { ...props })
4957
5050
  });
4958
5051
  }
4959
- function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
5052
+ function BulkFlowButton({ resource, actionName, ids, records, onSelectionChange }) {
4960
5053
  const app = (0, _burojs_react.useApp)();
4961
5054
  const tid = (0, _burojs_react.useTestIds)();
4962
5055
  const t = (0, _burojs_react.useOptionalT)();
5056
+ const caps = (0, _burojs_react.useI18nCaps)();
5057
+ const gate = (0, _burojs_react.useAvailabilityGate)();
4963
5058
  const control = (0, _burojs_react.useFlowRowResolver)(resource)(actionName, void 0);
4964
5059
  const chrome = require_check_confirm_dialog.useFlowChrome(resource, actionName);
4965
5060
  const def = app.registry.get(resource);
@@ -4978,11 +5073,31 @@ function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
4978
5073
  if (control.state === "absent") return null;
4979
5074
  const variant = chrome.destructive ? "destructive" : "outline";
4980
5075
  const overLimit = each && ids.length > _burojs_core.BULK_EACH_LIMIT;
4981
- if (overLimit || control.state === "disabled") return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DisabledAction, {
5076
+ let membersUndecided = false;
5077
+ const selection = def === void 0 ? void 0 : (0, _burojs_react.collectionBulkState)({
5078
+ registry: app.registry,
5079
+ collection: def,
5080
+ action: actionName,
5081
+ ids,
5082
+ records: records ?? [],
5083
+ available: (member, action) => {
5084
+ const state = gate(member, action).state;
5085
+ if (state === "undecided") membersUndecided = true;
5086
+ return state === "available";
5087
+ }
5088
+ });
5089
+ const refused = membersUndecided || selection?.state !== "disabled" ? void 0 : selection.members.length > 0 ? t("collection.bulkUnavailable", {
5090
+ defaultValue: "Not available for {{types}}.",
5091
+ params: { types: selection.members.map((member) => (0, _burojs_core.resolveResourceLabel)(caps, member, "single", app.registry.get(member))).join(", ") }
5092
+ }) : t("collection.bulkUnknownRows", {
5093
+ defaultValue: "{{count}} selected records are not loaded.",
5094
+ count: selection.missing
5095
+ });
5096
+ if (overLimit || control.state === "disabled" || refused !== void 0) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DisabledAction, {
4982
5097
  reason: overLimit ? t("flow.bulkLimit", {
4983
5098
  defaultValue: `Select at most ${_burojs_core.BULK_EACH_LIMIT}.`,
4984
5099
  count: _burojs_core.BULK_EACH_LIMIT
4985
- }) : control.reason,
5100
+ }) : control.state === "disabled" ? control.reason : refused,
4986
5101
  label: chrome.label,
4987
5102
  icon: chrome.icon,
4988
5103
  testid,
@@ -4992,7 +5107,7 @@ function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
4992
5107
  actionName,
4993
5108
  surface: "bulk"
4994
5109
  });
4995
- const busy = control.state === "undecided" || control.state === "pending" || running;
5110
+ const busy = control.state === "undecided" || control.state === "pending" || membersUndecided || running;
4996
5111
  const finish = (result, progress) => {
4997
5112
  setRunning(false);
4998
5113
  if (progress === void 0) return;
@@ -5054,7 +5169,8 @@ function BulkFlowButton({ resource, actionName, ids, onSelectionChange }) {
5054
5169
  label: chrome.labelText,
5055
5170
  total: summary.total,
5056
5171
  progress: summary.progress,
5057
- texts: compiled?.flow.texts
5172
+ texts: compiled?.flow.texts,
5173
+ ...compiled === void 0 ? {} : { prefixes: compiled.textKeys.prefixes }
5058
5174
  }),
5059
5175
  (0, react_jsx_runtime.jsx)(require_dialog.DialogFooter, { children: (0, react_jsx_runtime.jsx)(require_button.Button, {
5060
5176
  type: "button",
@@ -5120,6 +5236,7 @@ function BulkActionToolbar({ resource: resourceInput, table, selectedRecords, se
5120
5236
  resource,
5121
5237
  actionName: action.name,
5122
5238
  ids,
5239
+ records,
5123
5240
  onSelectionChange: (next) => {
5124
5241
  if (onSelectionChange !== void 0) onSelectionChange(next);
5125
5242
  else if (next.length === 0) handleClear();
@@ -5438,6 +5555,14 @@ function CreateButton({ resource: resourceInput, href, testid, size = "sm", vari
5438
5555
  resource,
5439
5556
  defaultValue: "Create"
5440
5557
  });
5558
+ const undecided = (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.UndecidedAction, {
5559
+ label: text,
5560
+ icon: "Plus",
5561
+ testid,
5562
+ size,
5563
+ variant,
5564
+ className
5565
+ });
5441
5566
  if (onOpen !== void 0) {
5442
5567
  const answer = gate(resource, "create");
5443
5568
  if (answer.state === "disabled") return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DisabledAction, {
@@ -5450,6 +5575,7 @@ function CreateButton({ resource: resourceInput, href, testid, size = "sm", vari
5450
5575
  className,
5451
5576
  resource
5452
5577
  });
5578
+ if (answer.state === "undecided") return undecided;
5453
5579
  if (answer.state !== "open") return null;
5454
5580
  return (0, react_jsx_runtime.jsxs)(require_button.Button, {
5455
5581
  type: "button",
@@ -5465,6 +5591,7 @@ function CreateButton({ resource: resourceInput, href, testid, size = "sm", vari
5465
5591
  });
5466
5592
  }
5467
5593
  if (availability.state === "absent" || availability.state === "hidden") return null;
5594
+ if (availability.state === "undecided") return undecided;
5468
5595
  if (availability.state === "disabled") return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DisabledAction, {
5469
5596
  reason: availability.reason,
5470
5597
  label: text,
@@ -5508,6 +5635,10 @@ const ListCreate = listPiece("ListCreate", ListCreateView);
5508
5635
  //#endregion
5509
5636
  //#region src/export/export-button.tsx
5510
5637
  const warnedProviderQueryResources = new Set();
5638
+ const EXPORT_TARGET = {
5639
+ kind: "action",
5640
+ name: "export"
5641
+ };
5511
5642
  function ExportButton({ resource: resourceInput, className }) {
5512
5643
  const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
5513
5644
  if (!((0, _burojs_react.useOptionalDataRuntime)() !== null)) return null;
@@ -5521,12 +5652,11 @@ function ExportButtonActive({ resource, className }) {
5521
5652
  const { available, prefetch } = (0, _burojs_react.useResourceExport)(resource);
5522
5653
  const capability = (0, _burojs_react.useCapability)("run", {
5523
5654
  resource,
5524
- target: {
5525
- kind: "action",
5526
- name: "export"
5527
- },
5655
+ target: EXPORT_TARGET,
5528
5656
  mode: "list"
5529
5657
  });
5658
+ const app = (0, _burojs_react.useApp)();
5659
+ const undecided = (0, _burojs_react.usePermissionsUndecided)() && (0, _burojs_core.addressesCapability)(app.ruleSource.rules(resource), "run", EXPORT_TARGET);
5530
5660
  const tid = (0, _burojs_react.useTestIds)();
5531
5661
  const t = (0, _burojs_react.useOptionalT)();
5532
5662
  const [open, setOpen] = react.useState(false);
@@ -5544,18 +5674,35 @@ function ExportButtonActive({ resource, className }) {
5544
5674
  if (target !== null) lastTarget.current = target;
5545
5675
  const dialogTarget = target ?? lastTarget.current;
5546
5676
  react.useEffect(() => {
5547
- if (!available || !capability.allowed) return;
5677
+ if (!available || undecided || !capability.allowed) return;
5548
5678
  if (list.providerQuery.value === void 0) return;
5549
5679
  if (warnedProviderQueryResources.has(resource)) return;
5550
5680
  warnedProviderQueryResources.add(resource);
5551
5681
  console.warn(`[buro] ExportButton('${resource}'): this list is narrowed by \`providerQuery\` (a raw provider blob), which an export target cannot carry — the exported file will NOT be narrowed by it. See docs/adopters/data-export.md.`);
5552
5682
  }, [
5553
5683
  available,
5684
+ undecided,
5554
5685
  capability.allowed,
5555
5686
  list.providerQuery.value,
5556
5687
  resource
5557
5688
  ]);
5558
- if (!available || !capability.allowed || list.isForbidden) return null;
5689
+ if (!available || list.isForbidden) return null;
5690
+ if (undecided) return (0, react_jsx_runtime.jsx)(require_button.Button, {
5691
+ type: "button",
5692
+ variant: "outline",
5693
+ size: "icon",
5694
+ "aria-label": t("export.button.label"),
5695
+ title: t("export.button.label"),
5696
+ className: require_use_theme.cn("h-8 w-8", className),
5697
+ "data-testid": tid.exportButton(resource),
5698
+ disabled: true,
5699
+ "aria-busy": "true",
5700
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconDownload, {
5701
+ className: "size-4",
5702
+ "aria-hidden": "true"
5703
+ })
5704
+ });
5705
+ if (!capability.allowed) return null;
5559
5706
  if (target === null && !open) return null;
5560
5707
  if (dialogTarget === null) return null;
5561
5708
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [target === null ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
@@ -6088,6 +6235,7 @@ function BuroPeekFrame({ slots }) {
6088
6235
  //#endregion
6089
6236
  //#region src/record/frame-context.ts
6090
6237
  const FrameChromeContext = (0, react.createContext)(null);
6238
+ const ItemActionsOffContext = (0, react.createContext)(false);
6091
6239
  function useFrameChrome() {
6092
6240
  const chrome = (0, react.useContext)(FrameChromeContext);
6093
6241
  if (chrome === null) throw new Error("[burojs] useRecordFrame() must be called inside <RecordScreen>");
@@ -6125,7 +6273,7 @@ function RecordActionsView() {
6125
6273
  const { extraActions } = useFrameChrome();
6126
6274
  const id = useFrameId();
6127
6275
  const holder = (0, _burojs_react.useScreenState)()?.inline;
6128
- if (mode === "create" || record === void 0 || id === void 0) return null;
6276
+ if ((0, react.useContext)(ItemActionsOffContext) || mode === "create" || record === void 0 || id === void 0) return null;
6129
6277
  const row = (0, _burojs_react.withRecordKeys)((0, _burojs_react.policyRecordOf)(controller) ?? record, { id });
6130
6278
  holder?.declare(inlineFlowNames(controller.screen, controller.plan));
6131
6279
  return (0, react_jsx_runtime.jsxs)("div", {
@@ -6226,7 +6374,7 @@ function FormActionsView() {
6226
6374
  }, {
6227
6375
  has: caps.has,
6228
6376
  t: caps.t,
6229
- ...declared === void 0 ? {} : { fieldKey: `resources.${resource}.fields.${name}` }
6377
+ ...declared === void 0 ? {} : { fieldKey: `resources.${resource}.${(0, _burojs_core.propertyTextKey)(issue.path)}` }
6230
6378
  });
6231
6379
  if (issue.path.length === 0 && message === failure) return [];
6232
6380
  return [{
@@ -6725,8 +6873,8 @@ function declaresDisplay(field) {
6725
6873
  return field !== void 0 && (0, _burojs_core.resolveSurfaceUi)(field, "column").use !== void 0;
6726
6874
  }
6727
6875
  const NO_INITIAL_FILTERS = Object.freeze({});
6728
- const RelatedCards = (0, react.lazy)(async () => ({ default: (await Promise.resolve().then(() => require("./related-list-cards-Bc_vfCE_.cjs"))).RelatedCards }));
6729
- const RelatedTimeline = (0, react.lazy)(async () => ({ default: (await Promise.resolve().then(() => require("./related-list-timeline-k0DtnxTs.cjs"))).RelatedTimeline }));
6876
+ const RelatedCards = (0, react.lazy)(async () => ({ default: (await Promise.resolve().then(() => require("./related-list-cards-BypKfm9t.cjs"))).RelatedCards }));
6877
+ const RelatedTimeline = (0, react.lazy)(async () => ({ default: (await Promise.resolve().then(() => require("./related-list-timeline-D-KClgKb.cjs"))).RelatedTimeline }));
6730
6878
  function discriminatorOptionLabel(field, value) {
6731
6879
  const text = (0, _burojs_core.fieldOptionText)(field, value);
6732
6880
  if (text !== void 0) return text;
@@ -7913,16 +8061,15 @@ function byOf(field) {
7913
8061
  }
7914
8062
  const MAX_TARGET_HOPS = 2;
7915
8063
  function targetColumns(registry, target, def) {
7916
- if (!isRecord(def) || !isRecord(def.fields)) return [];
7917
- const source = def;
8064
+ if (def === void 0) return [];
7918
8065
  const views = isRecord(def.views) ? def.views : void 0;
7919
8066
  const list = views !== void 0 && isRecord(views.list) ? views.list : void 0;
7920
8067
  return (list !== void 0 && Array.isArray(list.columns) ? list.columns.flatMap((entry) => {
7921
8068
  const name = isRecord(entry) ? entry.field : entry;
7922
8069
  return typeof name === "string" ? [name] : [];
7923
- }) : (0, _burojs_core.dtoFields)(source, "list")).filter((name) => {
8070
+ }) : (0, _burojs_core.dtoFields)(def, "list")).filter((name) => {
7924
8071
  if (name.includes(".")) return name.split(".").length - 1 <= MAX_TARGET_HOPS && (0, _burojs_react.resolveColumnField)(registry, target, name) !== void 0;
7925
- const field = peekFieldDefinition(source, name);
8072
+ const field = peekFieldDefinition(def, name);
7926
8073
  return isRecord(field) && !(0, _burojs_core.isRelationField)(field) && (0, _burojs_core.fieldSensitivity)(field) === void 0;
7927
8074
  });
7928
8075
  }
@@ -8117,7 +8264,7 @@ function RelatedListView({ props, empty }) {
8117
8264
  ...route.renderCell === void 0 ? {} : { renderCell: route.renderCell },
8118
8265
  ...route.emptyState === void 0 ? {} : { emptyState: route.emptyState }
8119
8266
  });
8120
- if (own.view !== void 0 && own.view !== "table" && permissions?.status === "loading") return (0, react_jsx_runtime.jsx)("div", {
8267
+ if (own.view !== void 0 && own.view !== "table" && (0, _burojs_core.permissionsUndecided)(permissions)) return (0, react_jsx_runtime.jsx)("div", {
8121
8268
  role: "status",
8122
8269
  "aria-busy": "true",
8123
8270
  "data-testid": `list-undecided:${resource}`,
@@ -8696,6 +8843,12 @@ Object.defineProperty(exports, "HeaderTypeNotice", {
8696
8843
  return HeaderTypeNotice;
8697
8844
  }
8698
8845
  });
8846
+ Object.defineProperty(exports, "ItemActionsOffContext", {
8847
+ enumerable: true,
8848
+ get: function() {
8849
+ return ItemActionsOffContext;
8850
+ }
8851
+ });
8699
8852
  Object.defineProperty(exports, "ListBody", {
8700
8853
  enumerable: true,
8701
8854
  get: function() {
@@ -9087,4 +9240,4 @@ Object.defineProperty(exports, "viewOf", {
9087
9240
  }
9088
9241
  });
9089
9242
 
9090
- //# sourceMappingURL=place-node-Bhl8B3fF.cjs.map
9243
+ //# sourceMappingURL=place-node-C5ZmuHaN.cjs.map