@burojs/ui-shadcn 0.6.0 → 0.8.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 (158) hide show
  1. package/README.md +9 -0
  2. package/dist/bulk-summary-2HLgz7Il.cjs +169 -0
  3. package/dist/bulk-summary-2HLgz7Il.cjs.map +1 -0
  4. package/dist/bulk-summary-D6A0ua21.js +169 -0
  5. package/dist/bulk-summary-D6A0ua21.js.map +1 -0
  6. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-C47mF260.cjs} +4 -4
  7. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-C47mF260.cjs.map} +1 -1
  8. package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CGXItMN0.js} +3 -3
  9. package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CGXItMN0.js.map} +1 -1
  10. package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-BT04Mieo.cjs} +475 -107
  11. package/dist/check-confirm-dialog-BT04Mieo.cjs.map +1 -0
  12. package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-CtiRzOAt.js} +391 -108
  13. package/dist/check-confirm-dialog-CtiRzOAt.js.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-ByGhxLf_.cjs} +1021 -154
  19. package/dist/filter-builder-ByGhxLf_.cjs.map +1 -0
  20. package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-z3Axzf9Y.js} +929 -140
  21. package/dist/filter-builder-z3Axzf9Y.js.map +1 -0
  22. package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BVFjMU5-.cjs} +64 -29
  23. package/dist/flow-runtime-BVFjMU5-.cjs.map +1 -0
  24. package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DrUWyTS0.js} +65 -30
  25. package/dist/flow-runtime-DrUWyTS0.js.map +1 -0
  26. package/dist/{flow-screen-CCvgDI9G.js → flow-screen-3fk6J33y.js} +130 -87
  27. package/dist/flow-screen-3fk6J33y.js.map +1 -0
  28. package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-6y5E_HT6.cjs} +130 -87
  29. package/dist/flow-screen-6y5E_HT6.cjs.map +1 -0
  30. package/dist/index.cjs +1186 -950
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +631 -322
  33. package/dist/index.d.ts +631 -322
  34. package/dist/index.js +1100 -870
  35. package/dist/index.js.map +1 -1
  36. package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-C4KmZIYE.cjs} +5 -5
  37. package/dist/inline-flow-host-C4KmZIYE.cjs.map +1 -0
  38. package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-YnnvWjdU.js} +5 -5
  39. package/dist/inline-flow-host-YnnvWjdU.js.map +1 -0
  40. package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-BAKBRn3V.cjs} +10 -10
  41. package/dist/lazy-relation-picker-dialog-BAKBRn3V.cjs.map +1 -0
  42. package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-DN4bvQfg.js} +11 -11
  43. package/dist/lazy-relation-picker-dialog-DN4bvQfg.js.map +1 -0
  44. package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-CtEfqAvU.js} +35 -23
  45. package/dist/page-flow-route-CtEfqAvU.js.map +1 -0
  46. package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DEjAxHe3.cjs} +42 -30
  47. package/dist/page-flow-route-DEjAxHe3.cjs.map +1 -0
  48. package/dist/{place-node-NraNYKPx.js → place-node-BdxT-30h.js} +1980 -1041
  49. package/dist/place-node-BdxT-30h.js.map +1 -0
  50. package/dist/{place-node-C5SmIAYU.cjs → place-node-Bhl8B3fF.cjs} +2038 -1087
  51. package/dist/place-node-Bhl8B3fF.cjs.map +1 -0
  52. package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-Bc_vfCE_.cjs} +9 -4
  53. package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-Bc_vfCE_.cjs.map} +1 -1
  54. package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BvkD5OcC.js} +9 -4
  55. package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BvkD5OcC.js.map} +1 -1
  56. package/dist/related-list-timeline-DCrwN9oO.js +167 -0
  57. package/dist/related-list-timeline-DCrwN9oO.js.map +1 -0
  58. package/dist/related-list-timeline-k0DtnxTs.cjs +167 -0
  59. package/dist/related-list-timeline-k0DtnxTs.cjs.map +1 -0
  60. package/dist/{related-rows-ea43qhhy.cjs → related-rows-BW9Jr07T.cjs} +27 -16
  61. package/dist/related-rows-BW9Jr07T.cjs.map +1 -0
  62. package/dist/{related-rows-o0_t-Yce.js → related-rows-CPE-9FFr.js} +25 -14
  63. package/dist/related-rows-CPE-9FFr.js.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-BlrGRwMV.js} +210 -104
  69. package/dist/relation-many-picker-BlrGRwMV.js.map +1 -0
  70. package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-Br-zBHxT.cjs} +218 -112
  71. package/dist/relation-many-picker-Br-zBHxT.cjs.map +1 -0
  72. package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-ADjxI_TI.cjs} +36 -73
  73. package/dist/relation-picker-ADjxI_TI.cjs.map +1 -0
  74. package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-CyKliBkN.js} +134 -36
  75. package/dist/relation-picker-dialog-CyKliBkN.js.map +1 -0
  76. package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-DimVQF9Y.cjs} +133 -35
  77. package/dist/relation-picker-dialog-DimVQF9Y.cjs.map +1 -0
  78. package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-x7P5HKie.js} +30 -61
  79. package/dist/relation-picker-x7P5HKie.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-3RUf9d1j.js → resource-page-router-BRpUnhay.js} +634 -264
  85. package/dist/resource-page-router-BRpUnhay.js.map +1 -0
  86. package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-qEd2xb55.cjs} +694 -312
  87. package/dist/resource-page-router-qEd2xb55.cjs.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/dist/use-record-subtitle-bfwIoUme.cjs +70 -0
  105. package/dist/use-record-subtitle-bfwIoUme.cjs.map +1 -0
  106. package/dist/use-record-subtitle-gIaCGgbI.js +53 -0
  107. package/dist/use-record-subtitle-gIaCGgbI.js.map +1 -0
  108. package/package.json +11 -11
  109. package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
  110. package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
  111. package/dist/bulk-summary-GxMDP4bw.js +0 -108
  112. package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
  113. package/dist/candidates-gate-Bb70LPAy.js.map +0 -1
  114. package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
  115. package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
  116. package/dist/check-confirm-dialog-bRT8lt0d.js.map +0 -1
  117. package/dist/dialog-B_rt9S1c.js.map +0 -1
  118. package/dist/dialog-DRNUq9EA.cjs.map +0 -1
  119. package/dist/filter-builder-Bhn-dhZV.js.map +0 -1
  120. package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
  121. package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
  122. package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
  123. package/dist/flow-screen-CCvgDI9G.js.map +0 -1
  124. package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
  125. package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
  126. package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
  127. package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
  128. package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
  129. package/dist/place-node-C5SmIAYU.cjs.map +0 -1
  130. package/dist/place-node-NraNYKPx.js.map +0 -1
  131. package/dist/related-list-timeline-CCzl71aA.cjs +0 -142
  132. package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
  133. package/dist/related-list-timeline-yrPsjA3F.js +0 -142
  134. package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
  135. package/dist/related-rows-ea43qhhy.cjs.map +0 -1
  136. package/dist/related-rows-o0_t-Yce.js.map +0 -1
  137. package/dist/relation-create-IA40t1hi.cjs +0 -364
  138. package/dist/relation-create-IA40t1hi.cjs.map +0 -1
  139. package/dist/relation-create-h6F9B4C4.js +0 -339
  140. package/dist/relation-create-h6F9B4C4.js.map +0 -1
  141. package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
  142. package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
  143. package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
  144. package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
  145. package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
  146. package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
  147. package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
  148. package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
  149. package/dist/search-access-CPPmfuvy.js.map +0 -1
  150. package/dist/search-access-Dugvttlg.cjs.map +0 -1
  151. package/dist/shell-BPlk8hEa.js +0 -205
  152. package/dist/shell-BPlk8hEa.js.map +0 -1
  153. package/dist/shell-DxhlsPwm.cjs +0 -271
  154. package/dist/shell-DxhlsPwm.cjs.map +0 -1
  155. package/dist/toaster-C02XbB9r.js.map +0 -1
  156. package/dist/toaster-Cr51X7bz.cjs.map +0 -1
  157. package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
  158. package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,21 +1,22 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
3
- const require_toaster = require("./toaster-Cr51X7bz.cjs");
4
- const require_check_confirm_dialog = require("./check-confirm-dialog--gPFnEeg.cjs");
3
+ const require_toaster = require("./toaster-BbByOytP.cjs");
4
+ const require_check_confirm_dialog = require("./check-confirm-dialog-BT04Mieo.cjs");
5
5
  const require_button = require("./button-BxnnE28H.cjs");
6
6
  const require_input = require("./input-BI0czGyI.cjs");
7
- const require_dialog = require("./dialog-DRNUq9EA.cjs");
8
- const require_search_access = require("./search-access-Dugvttlg.cjs");
9
- const require_shell = require("./shell-DxhlsPwm.cjs");
7
+ const require_dialog = require("./dialog-vmMdfUWs.cjs");
8
+ const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
10
9
  const require_skeleton = require("./skeleton-_1gP7wan.cjs");
11
- const require_place_node = require("./place-node-C5SmIAYU.cjs");
10
+ const require_place_node = require("./place-node-Bhl8B3fF.cjs");
12
11
  const require_layout_theme_storage_key = require("./layout/theme-storage-key.cjs");
13
- const require_filter_builder = require("./filter-builder-nXqtM_h4.cjs");
14
- const require_resource_page_router = require("./resource-page-router-PXfMW9nh.cjs");
12
+ const require_filter_builder = require("./filter-builder-ByGhxLf_.cjs");
13
+ const require_resource_page_router = require("./resource-page-router-qEd2xb55.cjs");
15
14
  const require_label = require("./label-w6JYf2cF.cjs");
16
- const require_relation_picker = require("./relation-picker-gag0qSR5.cjs");
17
- const require_candidates_gate = require("./candidates-gate-D33jXLHO.cjs");
18
- const require_use_dialog_filter_state = require("./use-dialog-filter-state-Dhe8PcB5.cjs");
15
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BAKBRn3V.cjs");
16
+ const require_use_record_subtitle = require("./use-record-subtitle-bfwIoUme.cjs");
17
+ const require_relation_picker = require("./relation-picker-ADjxI_TI.cjs");
18
+ const require_use_dialog_filter_state = require("./use-dialog-filter-state-tNvqAAjh.cjs");
19
+ let _burojs_react_web = require("@burojs/react/web");
19
20
  let _burojs_core = require("@burojs/core");
20
21
  let _burojs_react = require("@burojs/react");
21
22
  let _tabler_icons_react = require("@tabler/icons-react");
@@ -35,6 +36,7 @@ let _radix_ui_react_avatar = require("@radix-ui/react-avatar");
35
36
  _radix_ui_react_avatar = require_use_theme.__toESM(_radix_ui_react_avatar, 1);
36
37
  let _radix_ui_react_collapsible = require("@radix-ui/react-collapsible");
37
38
  _radix_ui_react_collapsible = require_use_theme.__toESM(_radix_ui_react_collapsible, 1);
39
+ let _burojs_core_internal = require("@burojs/core/internal");
38
40
  let react_hook_form = require("react-hook-form");
39
41
  let _hookform_resolvers_zod = require("@hookform/resolvers/zod");
40
42
  let zod = require("zod");
@@ -496,7 +498,7 @@ function ScopeSummary({ scope, summary }) {
496
498
  const caps = (0, _burojs_react.useI18nCaps)();
497
499
  const t = (0, _burojs_react.useOptionalT)();
498
500
  const links = (scope !== void 0 ? (0, _burojs_core.resolveDoc)(caps, scope) : void 0)?.links ?? [];
499
- const newTabNote = t("docPanel.newTab", { defaultValue: "opens in a new tab" });
501
+ const newTabNote = t("docPanel.opensInNewTab", { defaultValue: "(opens in a new tab)" });
500
502
  if (summary === void 0 && links.length === 0) return null;
501
503
  return (0, react_jsx_runtime.jsxs)("div", {
502
504
  className: "mt-2 flex flex-col items-start gap-3",
@@ -632,9 +634,9 @@ function CommandPaletteDocsGroup({ locale, onSelect, heading }) {
632
634
  }];
633
635
  }), [groups, contextOf]);
634
636
  if (hits.length === 0) return null;
635
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
637
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
636
638
  heading: heading ?? t("docPanel.title", { defaultValue: "Help" }),
637
- children: hits.map((hit) => (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
639
+ children: hits.map((hit) => (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
638
640
  value: `doc ${hit.scopeLabel} ${hit.title}`,
639
641
  "data-testid": `command-doc:${hit.scope}${hit.topicId === void 0 ? "" : `:${hit.topicId}`}`,
640
642
  onSelect: () => {
@@ -777,10 +779,10 @@ const Sidebar = react.forwardRef(({ side = "left", variant = "sidebar", collapsi
777
779
  ...props,
778
780
  children
779
781
  });
780
- if (isMobile) return (0, react_jsx_runtime.jsx)(require_shell.Sheet, {
782
+ if (isMobile) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Sheet, {
781
783
  open: openMobile,
782
784
  onOpenChange: setOpenMobile,
783
- children: (0, react_jsx_runtime.jsxs)(require_shell.SheetContent, {
785
+ children: (0, react_jsx_runtime.jsxs)(require_check_confirm_dialog.SheetContent, {
784
786
  "data-sidebar": "sidebar",
785
787
  "data-mobile": "true",
786
788
  className: "w-[var(--sidebar-width)] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden",
@@ -788,11 +790,11 @@ const Sidebar = react.forwardRef(({ side = "left", variant = "sidebar", collapsi
788
790
  side: side === "left" ? "left" : "right",
789
791
  ...props,
790
792
  children: [
791
- (0, react_jsx_runtime.jsx)(require_shell.SheetTitle, {
793
+ (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.SheetTitle, {
792
794
  className: "sr-only",
793
795
  children: t("nav.label", { defaultValue: "Navigation" })
794
796
  }),
795
- (0, react_jsx_runtime.jsx)(require_shell.SheetDescription, {
797
+ (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.SheetDescription, {
796
798
  className: "sr-only",
797
799
  children: t("nav.main", { defaultValue: "Main navigation" })
798
800
  }),
@@ -1118,7 +1120,7 @@ AlertDialogCancel.displayName = _radix_ui_react_alert_dialog.Cancel.displayName;
1118
1120
  function NavigationGuardDialog() {
1119
1121
  const prompt = (0, _burojs_react.useRegisterNavigationGuardDialog)();
1120
1122
  const text = (0, _burojs_react.useNavigationGuardText)();
1121
- const unsavedAction = (0, _burojs_react.useOptionalT)()("navigation.unsavedAction");
1123
+ const unsavedAction = (0, _burojs_react.useOptionalT)()("navigation.unsavedAction", { defaultValue: "An action on this screen has unsaved input" });
1122
1124
  const returnFocus = (0, react.useRef)(null);
1123
1125
  const wasOpen = (0, react.useRef)(false);
1124
1126
  const open = prompt !== null;
@@ -1141,7 +1143,7 @@ function NavigationGuardDialog() {
1141
1143
  event.preventDefault();
1142
1144
  element.focus();
1143
1145
  },
1144
- children: [(0, react_jsx_runtime.jsxs)(AlertDialogHeader, { children: [(0, react_jsx_runtime.jsx)(AlertDialogTitle, { children: text.title }), (0, react_jsx_runtime.jsxs)(AlertDialogDescription, { children: [text.body, prompt !== null && prompt.labels.length > 0 ? ` ${unsavedAction === "navigation.unsavedAction" ? "An action on this screen has unsaved input" : unsavedAction}: ${prompt.labels.join(", ")}.` : null] })] }), (0, react_jsx_runtime.jsxs)(AlertDialogFooter, { children: [(0, react_jsx_runtime.jsx)(AlertDialogCancel, {
1146
+ children: [(0, react_jsx_runtime.jsxs)(AlertDialogHeader, { children: [(0, react_jsx_runtime.jsx)(AlertDialogTitle, { children: text.title }), (0, react_jsx_runtime.jsxs)(AlertDialogDescription, { children: [text.body, prompt !== null && prompt.labels.length > 0 ? ` ${unsavedAction}: ${prompt.labels.join(", ")}.` : null] })] }), (0, react_jsx_runtime.jsxs)(AlertDialogFooter, { children: [(0, react_jsx_runtime.jsx)(AlertDialogCancel, {
1145
1147
  "data-testid": "nav-guard-stay",
1146
1148
  children: text.stay
1147
1149
  }), (0, react_jsx_runtime.jsx)(AlertDialogAction, {
@@ -1701,14 +1703,14 @@ const CollapsibleTrigger = _radix_ui_react_collapsible.CollapsibleTrigger;
1701
1703
  const CollapsibleContent = _radix_ui_react_collapsible.CollapsibleContent;
1702
1704
  //#endregion
1703
1705
  //#region src/shell/use-nav-icon.tsx
1704
- const warned = new Set();
1706
+ const warned$1 = new Set();
1705
1707
  function resolveNavIcon(name, components) {
1706
1708
  if (name === void 0 || name === "") return void 0;
1707
1709
  const slot = components(name);
1708
1710
  if (typeof slot === "function" || typeof slot === "object" && slot !== null) return (0, react_jsx_runtime.jsx)(slot, { className: "h-4 w-4" });
1709
1711
  if (require_check_confirm_dialog.hasIcon(name)) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, { name });
1710
- if (process.env.NODE_ENV !== "production" && !warned.has(name)) {
1711
- warned.add(name);
1712
+ if (process.env.NODE_ENV !== "production" && !warned$1.has(name)) {
1713
+ warned$1.add(name);
1712
1714
  console.warn(`[buro] unknown nav icon "${name}"`);
1713
1715
  }
1714
1716
  }
@@ -1717,6 +1719,53 @@ function useNavIcon() {
1717
1719
  return (0, react.useCallback)((name) => resolveNavIcon(name, (key) => components[key]), [components]);
1718
1720
  }
1719
1721
  //#endregion
1722
+ //#region src/layout/build-nav-items.ts
1723
+ function buildNavItems(args) {
1724
+ const { registry, caps, groupName, match, isVisible, entryFilter, icons } = args;
1725
+ const chain = match?.groupChain ?? [];
1726
+ const qualifiedMatch = match;
1727
+ const activeLeaf = qualifiedMatch == null ? void 0 : qualifiedMatch.kind === "group-index" ? require_resource_page_router.canonicalNavKey({
1728
+ name: qualifiedMatch.target ?? qualifiedMatch.name,
1729
+ ref: qualifiedMatch.targetRef
1730
+ }) : require_resource_page_router.canonicalNavKey(qualifiedMatch);
1731
+ const isEligible = (node) => isVisible(node) && (entryFilter ? entryFilter(node) : true);
1732
+ const out = [];
1733
+ for (const child of registry.groups.childrenOf(groupName)) {
1734
+ if (!isEligible(child)) continue;
1735
+ const kind = (0, _burojs_core.nodeKind)(child);
1736
+ const childKey = require_resource_page_router.canonicalNavKey(child);
1737
+ const href = (0, _burojs_core.navHrefFor)(registry, childKey, { isVisible: isEligible });
1738
+ if (kind === "group") {
1739
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label"));
1740
+ const active = chain.some((g) => require_resource_page_router.canonicalNavKey(g) === childKey);
1741
+ out.push({
1742
+ kind: "group",
1743
+ name: childKey,
1744
+ label,
1745
+ href,
1746
+ icon: icons?.group?.(childKey),
1747
+ active
1748
+ });
1749
+ } else if (kind === "custom-page") out.push({
1750
+ kind: "custom-page",
1751
+ name: childKey,
1752
+ label: (0, _burojs_core.resolveNavLabel)(caps, `pages.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label")),
1753
+ href,
1754
+ icon: icons?.page?.(childKey),
1755
+ active: activeLeaf === childKey
1756
+ });
1757
+ else out.push({
1758
+ kind: "resource",
1759
+ name: childKey,
1760
+ label: (0, _burojs_core.resolveResourceNavLabel)(caps, childKey, child),
1761
+ href,
1762
+ icon: icons?.resource?.(childKey),
1763
+ active: activeLeaf === childKey
1764
+ });
1765
+ }
1766
+ return out;
1767
+ }
1768
+ //#endregion
1720
1769
  //#region src/layout/use-nav-tree.ts
1721
1770
  function isActiveHref(href, currentPath) {
1722
1771
  if (!currentPath) return false;
@@ -1730,8 +1779,7 @@ function useNavTree(opts = {}) {
1730
1779
  const passesEntryFilter = (entry) => entryFilter ? entryFilter(entry) : true;
1731
1780
  const app = (0, _burojs_react.useApp)();
1732
1781
  const caps = (0, _burojs_react.useI18nCaps)();
1733
- const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
1734
- const isResourceVisible = (r) => (0, _burojs_core.evaluateVisible)(r.visible, visibilityCtx);
1782
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
1735
1783
  const resolveLayout = require_resource_page_router.useLayoutResolver();
1736
1784
  const match = require_resource_page_router.useMatch();
1737
1785
  const isVisible = require_resource_page_router.useNavVisible();
@@ -1741,6 +1789,7 @@ function useNavTree(opts = {}) {
1741
1789
  const allCustomPages = app.registry.customPages.list();
1742
1790
  const sections = app.registry.sections.list();
1743
1791
  const groups = app.registry.groups.rootNodes().filter((n) => (0, _burojs_core.nodeKind)(n) === "group");
1792
+ require_resource_page_router.useReportUnresolvedLayouts(app.registry.groups.list(), resolveLayout);
1744
1793
  const topLevelResources = allResources.filter((r) => (0, _burojs_core.hasListPage)(r)).filter(isResourceVisible).filter(passesEntryFilter).filter((r) => !r.section && !r.group).map((r, idx) => ({
1745
1794
  r,
1746
1795
  idx
@@ -1778,7 +1827,7 @@ function useNavTree(opts = {}) {
1778
1827
  };
1779
1828
  };
1780
1829
  const layoutOf = (group) => resolveLayout(group.layout) ? group.layout : group.collapsible ? "collapsible" : "flat";
1781
- const groupChildren = (groupKey) => require_resource_page_router.buildNavItems({
1830
+ const groupChildren = (groupKey) => buildNavItems({
1782
1831
  registry: app.registry,
1783
1832
  caps,
1784
1833
  groupName: groupKey,
@@ -1933,6 +1982,10 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1933
1982
  const t = (0, _burojs_react.useT)();
1934
1983
  const RouterLink = require_toaster.useLinkComponent();
1935
1984
  const navIcon = useNavIcon();
1985
+ const intent = (0, _burojs_react.useOriginIntent)();
1986
+ const jump = (entry) => () => {
1987
+ if (entry.href !== void 0) intent(entry.href, "jump");
1988
+ };
1936
1989
  const ownOr = (own, name) => own !== void 0 ? own : navIcon(name);
1937
1990
  const groupAsSection = (key) => app.registry.sections.get(key) ?? app.registry.groups.get(key);
1938
1991
  const sectionIcon = (key, name) => {
@@ -1959,6 +2012,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1959
2012
  href: entry.href ?? "",
1960
2013
  "aria-current": entry.active ? "page" : void 0,
1961
2014
  "data-testid": entryTestId(entry),
2015
+ onClick: jump(entry),
1962
2016
  children: [icon != null && (0, react_jsx_runtime.jsx)("span", {
1963
2017
  className: "inline-flex h-4 w-4 items-center justify-center",
1964
2018
  "aria-hidden": "true",
@@ -1974,11 +2028,12 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1974
2028
  href: entry.href ?? "",
1975
2029
  "aria-current": entry.active ? "page" : void 0,
1976
2030
  "data-testid": entryTestId(entry),
2031
+ onClick: jump(entry),
1977
2032
  children: (0, react_jsx_runtime.jsx)("span", { children: entry.label })
1978
2033
  })
1979
2034
  }) }, entry.key);
1980
2035
  const [top, ...blocks] = tree;
1981
- return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)(SidebarGroup, { children: [topLabel !== null && (0, react_jsx_runtime.jsx)(SidebarGroupLabel, { children: topLabel ?? t("nav.resources") }), (0, react_jsx_runtime.jsx)(SidebarGroupContent, { children: (0, react_jsx_runtime.jsx)(SidebarMenu, { children: top?.entries.map(menuItem) }) })] }), blocks.map((block) => {
2036
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [top !== void 0 && top.entries.length > 0 && (0, react_jsx_runtime.jsxs)(SidebarGroup, { children: [topLabel !== null && (0, react_jsx_runtime.jsx)(SidebarGroupLabel, { children: topLabel ?? t("nav.resources") }), (0, react_jsx_runtime.jsx)(SidebarGroupContent, { children: (0, react_jsx_runtime.jsx)(SidebarMenu, { children: top.entries.map(menuItem) }) })] }), blocks.map((block) => {
1982
2037
  const key = block.key ?? "";
1983
2038
  if (block.label === null) return (0, react_jsx_runtime.jsx)(SidebarGroup, { children: (0, react_jsx_runtime.jsx)(SidebarGroupContent, { children: (0, react_jsx_runtime.jsx)(SidebarMenu, { children: block.entries.map(menuItem) }) }) }, key);
1984
2039
  if (block.collapsible) return (0, react_jsx_runtime.jsx)(CollapsibleNavSection, {
@@ -2022,127 +2077,32 @@ function AppSidebar({ header, filters, nav, footer }) {
2022
2077
  });
2023
2078
  }
2024
2079
  //#endregion
2025
- //#region src/layout/layouts/secondary-sidebar-layout.tsx
2026
- function Row({ it }) {
2027
- const RouterLink = require_toaster.useLinkComponent();
2028
- return (0, react_jsx_runtime.jsx)("li", { children: (0, react_jsx_runtime.jsxs)(RouterLink, {
2029
- href: it.href,
2030
- "data-testid": `nav-secondary-item:${it.name}`,
2031
- "aria-current": it.active ? "page" : void 0,
2032
- className: require_use_theme.cn("flex items-center gap-3 rounded-lg px-3 py-2 text-sm font-medium outline-hidden ring-offset-background transition-colors", "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", it.active ? "bg-secondary text-secondary-foreground" : "text-muted-foreground hover:bg-secondary/50 hover:text-foreground"),
2033
- children: [it.icon != null && (0, react_jsx_runtime.jsx)("span", {
2034
- className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
2035
- "aria-hidden": "true",
2036
- children: it.icon
2037
- }), (0, react_jsx_runtime.jsx)("span", {
2038
- className: "truncate",
2039
- title: it.label,
2040
- children: it.label
2041
- })]
2042
- }) });
2043
- }
2044
- function SecondarySidebarLayout({ group, groupKey, items, children }) {
2045
- const RouterLink = require_toaster.useLinkComponent();
2046
- const caps = (0, _burojs_react.useI18nCaps)();
2047
- const id = groupKey ?? group.name;
2048
- const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2049
- return (0, react_jsx_runtime.jsxs)("div", {
2050
- className: "md:-m-6 md:flex md:min-h-[calc(100%+3rem)]",
2051
- "data-testid": `nav-secondary:${id}`,
2052
- children: [
2053
- (0, react_jsx_runtime.jsx)("aside", {
2054
- className: "hidden w-64 shrink-0 border-r bg-background text-foreground md:block",
2055
- children: (0, react_jsx_runtime.jsxs)("div", {
2056
- className: "space-y-4 p-4",
2057
- children: [(0, react_jsx_runtime.jsx)("p", {
2058
- className: "px-3 text-base font-semibold tracking-tight",
2059
- children: label
2060
- }), (0, react_jsx_runtime.jsx)("nav", {
2061
- "aria-label": label,
2062
- children: (0, react_jsx_runtime.jsx)("ul", {
2063
- className: "space-y-0.5",
2064
- children: items.map((it) => (0, react_jsx_runtime.jsx)(Row, { it }, it.name))
2065
- })
2066
- })]
2067
- })
2068
- }),
2069
- (0, react_jsx_runtime.jsx)("nav", {
2070
- "aria-label": label,
2071
- "data-testid": `nav-secondary-select:${id}`,
2072
- className: "-mx-1 mb-4 flex snap-x snap-proximity gap-1.5 overflow-x-auto scroll-smooth px-1 pb-1 [-ms-overflow-style:none] [mask-image:linear-gradient(to_right,transparent,black_8px,black_calc(100%-8px),transparent)] [scrollbar-width:none] md:hidden [&::-webkit-scrollbar]:hidden",
2073
- children: items.map((it) => (0, react_jsx_runtime.jsx)(RouterLink, {
2074
- href: it.href,
2075
- "aria-current": it.active ? "page" : void 0,
2076
- className: require_use_theme.cn("snap-start whitespace-nowrap rounded-full border px-3 py-1.5 text-sm outline-hidden ring-offset-background transition-colors duration-150", "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", it.active ? "border-primary/40 bg-primary/10 font-medium text-foreground" : "border-border text-muted-foreground hover:bg-accent/60 hover:text-accent-foreground"),
2077
- children: it.label
2078
- }, it.name))
2079
- }),
2080
- (0, react_jsx_runtime.jsx)("div", {
2081
- className: "min-w-0 flex-1 md:overflow-x-hidden md:p-6",
2082
- children
2083
- })
2084
- ]
2085
- });
2086
- }
2087
- //#endregion
2088
- //#region src/layout/layouts/tabs-layout.tsx
2089
- function TabsLayout({ group, groupKey, items, children }) {
2090
- const RouterLink = require_toaster.useLinkComponent();
2091
- const caps = (0, _burojs_react.useI18nCaps)();
2092
- const id = groupKey ?? group.name;
2093
- const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2094
- return (0, react_jsx_runtime.jsxs)("div", {
2095
- className: "flex flex-col gap-4",
2096
- "data-testid": `nav-tabs:${id}`,
2097
- children: [(0, react_jsx_runtime.jsx)("nav", {
2098
- "aria-label": label,
2099
- className: "flex gap-1 overflow-x-auto scroll-smooth border-b border-border [-ms-overflow-style:none] [mask-image:linear-gradient(to_right,transparent,black_8px,black_calc(100%-8px),transparent)] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
2100
- children: items.map((it) => (0, react_jsx_runtime.jsxs)(RouterLink, {
2101
- href: it.href,
2102
- "aria-current": it.active ? "page" : void 0,
2103
- "data-testid": `nav-tab:${it.name}`,
2104
- className: require_use_theme.cn("group/tab relative flex shrink-0 items-center gap-1.5 whitespace-nowrap rounded-t-sm px-3 py-2.5 text-sm outline-hidden ring-offset-background transition-colors duration-150", "focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", it.active ? "font-medium text-foreground" : "text-muted-foreground hover:text-foreground"),
2105
- children: [
2106
- it.icon != null && (0, react_jsx_runtime.jsx)("span", {
2107
- className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
2108
- "aria-hidden": "true",
2109
- children: it.icon
2110
- }),
2111
- it.label,
2112
- (0, react_jsx_runtime.jsx)("span", {
2113
- "aria-hidden": "true",
2114
- className: require_use_theme.cn("pointer-events-none absolute inset-x-2 -bottom-px h-0.5 origin-center scale-x-0 rounded-full bg-primary opacity-0 transition-all duration-300 ease-out", it.active ? "scale-x-100 opacity-100" : "group-hover/tab:scale-x-100 group-hover/tab:opacity-30")
2115
- })
2116
- ]
2117
- }, it.name))
2118
- }), (0, react_jsx_runtime.jsx)("div", {
2119
- className: "min-w-0",
2120
- children
2121
- })]
2122
- });
2123
- }
2124
- //#endregion
2125
- //#region src/layout/nav-area-layout.tsx
2080
+ //#region src/layout/nav-chrome.tsx
2126
2081
  const DETAIL_ACTIONS = new Set([
2127
2082
  "show",
2128
2083
  "edit",
2129
2084
  "create"
2130
2085
  ]);
2131
- function NavAreaLayout({ groupName, children, entryFilter, icons }) {
2086
+ function NavChrome({ children, entryFilter, icons }) {
2132
2087
  const app = (0, _burojs_react.useApp)();
2133
2088
  const caps = (0, _burojs_react.useI18nCaps)();
2134
2089
  const isVisible = require_resource_page_router.useNavVisible();
2135
2090
  const match = require_resource_page_router.useMatch();
2136
2091
  const resolveLayout = require_resource_page_router.useLayoutResolver();
2137
- const group = app.registry.groups.get(groupName);
2138
- if (!group) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
2139
- const groupKey = require_resource_page_router.canonicalNavKey(group);
2140
- const claimed = [groupKey, ...(0, _burojs_core.groupChain)(app.registry, group).map(require_resource_page_router.canonicalNavKey)];
2141
- const collapse = group.chromeOn === "list" && match?.kind === "resource" && DETAIL_ACTIONS.has(match.action);
2142
- const Layout = resolveLayout(group.layout);
2092
+ require_resource_page_router.useReportUnresolvedLayouts(match?.groupChain ?? [], resolveLayout);
2093
+ if (!match) return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeMountedProvider, {
2094
+ value: true,
2095
+ children
2096
+ });
2143
2097
  let content = children;
2144
- if (Layout && !collapse) {
2145
- const items = require_resource_page_router.buildNavItems({
2098
+ for (let i = match.groupChain.length - 1; i >= 0; i--) {
2099
+ const group = match.groupChain[i];
2100
+ if (!group) continue;
2101
+ const groupKey = require_resource_page_router.canonicalNavKey(group);
2102
+ if (group.chromeOn === "list" && match.kind === "resource" && DETAIL_ACTIONS.has(match.action)) continue;
2103
+ const Layout = resolveLayout(group.layout);
2104
+ if (!Layout) continue;
2105
+ const items = buildNavItems({
2146
2106
  registry: app.registry,
2147
2107
  caps,
2148
2108
  groupName: groupKey,
@@ -2155,11 +2115,11 @@ function NavAreaLayout({ groupName, children, entryFilter, icons }) {
2155
2115
  group,
2156
2116
  groupKey,
2157
2117
  items,
2158
- children
2118
+ children: content
2159
2119
  });
2160
2120
  }
2161
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeBoundaryProvider, {
2162
- claim: claimed,
2121
+ return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeMountedProvider, {
2122
+ value: true,
2163
2123
  children: content
2164
2124
  });
2165
2125
  }
@@ -2172,19 +2132,27 @@ function Chevron() {
2172
2132
  "aria-hidden": "true"
2173
2133
  });
2174
2134
  }
2175
- function Breadcrumbs(props) {
2135
+ function Breadcrumbs(input) {
2136
+ const props = input;
2176
2137
  const { leadingSegments, className, docScopes, "data-testid": testId } = props;
2177
2138
  const app = (0, _burojs_react.useApp)();
2178
- const def = props.resource === void 0 ? void 0 : app.registry.get(props.resource);
2139
+ const resource = props.resource === void 0 ? void 0 : (0, _burojs_core.routeResourceKey)(props.resource);
2140
+ const def = resource === void 0 ? void 0 : app.registry.get(resource);
2179
2141
  const tid = (0, _burojs_react.useTestIds)();
2180
2142
  const t = (0, _burojs_react.useOptionalT)();
2181
2143
  const RouterLink = require_toaster.useLinkComponent();
2182
2144
  const caps = (0, _burojs_react.useI18nCaps)(def?.name);
2145
+ const intent = (0, _burojs_react.useOriginIntent)();
2146
+ const onJump = (seg) => {
2147
+ const href = seg.href;
2148
+ return seg.jump === true && href !== void 0 ? () => intent(href, "jump") : void 0;
2149
+ };
2183
2150
  const trailScopes = (0, _burojs_react.useDocTrailScopes)(def?.name);
2184
2151
  const leading = (name) => leadingSegments?.map((seg, i) => (0, react_jsx_runtime.jsxs)("span", {
2185
2152
  className: "flex min-w-0 items-center gap-1",
2186
2153
  children: [seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2187
2154
  href: seg.href,
2155
+ onClick: onJump(seg),
2188
2156
  "data-testid": `${tid.navBreadcrumb(name)}:lead:${i}`,
2189
2157
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
2190
2158
  title: seg.label,
@@ -2219,9 +2187,34 @@ function Breadcrumbs(props) {
2219
2187
  ]
2220
2188
  });
2221
2189
  if (!def) return null;
2222
- const { recordId, pageLabel, middleSegments } = props;
2190
+ const { recordId, pageLabel, middleSegments, rootSegments } = props;
2223
2191
  const resourceKey = require_resource_page_router.canonicalResourceKey(def);
2224
- const listHref = (0, _burojs_core.hrefFor)(app.registry, resourceKey);
2192
+ if (rootSegments !== void 0 && rootSegments.length > 0) return (0, react_jsx_runtime.jsxs)("nav", {
2193
+ className: navClass,
2194
+ "aria-label": ariaLabel,
2195
+ "data-testid": testId,
2196
+ children: [
2197
+ rootSegments.map((seg, i) => (0, react_jsx_runtime.jsxs)("span", {
2198
+ className: "flex min-w-0 items-center gap-1",
2199
+ children: [i > 0 && (0, react_jsx_runtime.jsx)(Chevron, {}), seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2200
+ href: seg.href,
2201
+ onClick: onJump(seg),
2202
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2203
+ className: require_use_theme.cn(LINK_CLASS, "truncate"),
2204
+ title: seg.label,
2205
+ children: seg.label
2206
+ }) : (0, react_jsx_runtime.jsx)("span", {
2207
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2208
+ className: "truncate",
2209
+ title: seg.label,
2210
+ children: seg.label
2211
+ })]
2212
+ }, `root:${i}:${seg.label}`)),
2213
+ pageLabel && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(Chevron, {}), current(tid.navBreadcrumb(resourceKey, recordId), pageLabel)] }),
2214
+ help
2215
+ ]
2216
+ });
2217
+ const listHref = props.resourceHref ?? (0, _burojs_core.hrefFor)(app.registry, resourceKey);
2225
2218
  const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, resourceKey, "plural", def);
2226
2219
  const resourceIsCurrent = !pageLabel && !(middleSegments && middleSegments.length > 0);
2227
2220
  return (0, react_jsx_runtime.jsxs)("nav", {
@@ -2230,7 +2223,12 @@ function Breadcrumbs(props) {
2230
2223
  "data-testid": testId,
2231
2224
  children: [
2232
2225
  leading(resourceKey),
2233
- resourceIsCurrent ? current(tid.navBreadcrumb(resourceKey), resourceLabel) : (0, react_jsx_runtime.jsx)(RouterLink, {
2226
+ resourceIsCurrent ? current(tid.navBreadcrumb(resourceKey), resourceLabel) : !(0, _burojs_core.hasListPage)(def) ? (0, react_jsx_runtime.jsx)("span", {
2227
+ "data-testid": tid.navBreadcrumb(resourceKey),
2228
+ className: "truncate",
2229
+ title: resourceLabel,
2230
+ children: resourceLabel
2231
+ }) : (0, react_jsx_runtime.jsx)(RouterLink, {
2234
2232
  href: listHref,
2235
2233
  "data-testid": tid.navBreadcrumb(resourceKey),
2236
2234
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
@@ -2241,6 +2239,7 @@ function Breadcrumbs(props) {
2241
2239
  className: "flex min-w-0 items-center gap-1",
2242
2240
  children: [(0, react_jsx_runtime.jsx)(Chevron, {}), seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2243
2241
  href: seg.href,
2242
+ onClick: onJump(seg),
2244
2243
  "data-testid": `${tid.navBreadcrumb(resourceKey)}:mid:${i}`,
2245
2244
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
2246
2245
  title: seg.label,
@@ -2258,6 +2257,12 @@ function Breadcrumbs(props) {
2258
2257
  }
2259
2258
  //#endregion
2260
2259
  //#region src/layout/record-breadcrumbs.tsx
2260
+ function viewOrigin(ctx, trail, resource) {
2261
+ if (trail === void 0 || trail.resource === void 0 || trail.segments.length > 0) return void 0;
2262
+ const target = ctx.registry.get(trail.resource)?.routesTo?.show;
2263
+ if (target === void 0 || ctx.registry.get(target) !== ctx.registry.get(resource)) return void 0;
2264
+ return trail.resource;
2265
+ }
2261
2266
  function RecordBreadcrumbs() {
2262
2267
  const ctx = require_resource_page_router.useTrailContext();
2263
2268
  const match = require_resource_page_router.useMatch();
@@ -2265,9 +2270,17 @@ function RecordBreadcrumbs() {
2265
2270
  const route = require_resource_page_router.recordTrailRoute(ctx.registry, match);
2266
2271
  const published = require_resource_page_router.usePublishedRecordTrail(route === null ? "" : require_resource_page_router.recordTrailKey(route.resource, route.id, route.flow === void 0 ? route.action : `flow:${route.flow}`));
2267
2272
  const idTitle = (0, _burojs_react.useRecordTitle)(route?.resource, route?.id);
2273
+ (0, _burojs_react.usePublishOriginTitle)(published?.title || void 0);
2274
+ const origin = (0, _burojs_react.useNavigationOrigin)();
2275
+ const rooted = origin === null ? void 0 : require_resource_page_router.originTrail(ctx, origin);
2276
+ const view = route === null ? void 0 : viewOrigin(ctx, rooted, route.resource);
2277
+ const viewScopes = (0, _burojs_react.useDocTrailScopes)(view);
2278
+ const ownScopes = (0, _burojs_react.useDocTrailScopes)(view === void 0 ? void 0 : route?.resource);
2279
+ const docScopes = view === void 0 ? {} : { docScopes: [...new Set([...viewScopes, ...ownScopes])] };
2268
2280
  if (route === null || match === null) return null;
2269
2281
  const { resource, id, groupChain } = route;
2270
2282
  const title = published?.title ?? idTitle;
2283
+ const withOrigin = rooted === void 0 ? {} : { origin: rooted };
2271
2284
  if (route.flow !== void 0) {
2272
2285
  if ((0, _burojs_core.effectiveFlow)(snapshot, match.ref, route.flow) === void 0) return null;
2273
2286
  const flowLabel = published?.flowLabel;
@@ -2277,8 +2290,10 @@ function RecordBreadcrumbs() {
2277
2290
  action: "show",
2278
2291
  id,
2279
2292
  title: idTitle,
2280
- groupChain
2293
+ groupChain,
2294
+ ...withOrigin
2281
2295
  }),
2296
+ ...docScopes,
2282
2297
  "data-testid": "record-breadcrumbs"
2283
2298
  });
2284
2299
  return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
@@ -2287,8 +2302,10 @@ function RecordBreadcrumbs() {
2287
2302
  action: "edit",
2288
2303
  id,
2289
2304
  title,
2290
- groupChain
2305
+ groupChain,
2306
+ ...withOrigin
2291
2307
  }),
2308
+ ...docScopes,
2292
2309
  pageLabel: flowLabel,
2293
2310
  "data-testid": "record-breadcrumbs"
2294
2311
  });
@@ -2299,22 +2316,24 @@ function RecordBreadcrumbs() {
2299
2316
  action: route.action,
2300
2317
  id,
2301
2318
  title,
2302
- groupChain
2319
+ groupChain,
2320
+ ...withOrigin
2303
2321
  }),
2322
+ ...docScopes,
2304
2323
  "data-testid": "record-breadcrumbs"
2305
2324
  });
2306
2325
  }
2307
2326
  //#endregion
2308
2327
  //#region src/layout/default-nav-layouts.ts
2309
- const defaultNavLayouts = {
2310
- [require_resource_page_router.layoutSlot("secondary-sidebar")]: SecondarySidebarLayout,
2311
- [require_resource_page_router.layoutSlot("tabs")]: TabsLayout
2312
- };
2328
+ const defaultNavLayouts = { ...require_resource_page_router.BUILTIN_LAYOUTS };
2313
2329
  //#endregion
2314
2330
  //#region src/layout/context-picker.tsx
2315
- function ContextPicker({ sliceName, label, options, value, onChange, placeholder, disabled, className, hideLabel }) {
2331
+ const ALL = "\0all";
2332
+ function ContextPicker({ sliceName, label, options, value, onChange, placeholder, disabled, className, hideLabel, allOption }) {
2316
2333
  const tid = (0, _burojs_react.useTestIds)();
2317
2334
  const t = (0, _burojs_react.useOptionalT)();
2335
+ const chromeT = (0, _burojs_react.useChromeT)();
2336
+ const allLabel = typeof allOption === "string" ? allOption : chromeT("scope.all", { defaultValue: "All" });
2318
2337
  const displayLabel = label ?? (0, _burojs_core.humanizeKey)(sliceName);
2319
2338
  return (0, react_jsx_runtime.jsxs)("div", {
2320
2339
  className: require_use_theme.cn("space-y-1", className),
@@ -2323,21 +2342,112 @@ function ContextPicker({ sliceName, label, options, value, onChange, placeholder
2323
2342
  className: hideLabel ? "sr-only" : "text-xs font-medium text-muted-foreground uppercase tracking-wide",
2324
2343
  children: displayLabel
2325
2344
  }), (0, react_jsx_runtime.jsxs)(require_filter_builder.Select, {
2326
- value: value ?? "",
2327
- onValueChange: onChange,
2345
+ value: value ?? (allOption === void 0 ? "" : ALL),
2346
+ onValueChange: (next) => {
2347
+ if (allOption === void 0) onChange(next);
2348
+ else onChange(next === ALL ? null : next);
2349
+ },
2328
2350
  disabled,
2329
2351
  children: [(0, react_jsx_runtime.jsx)(require_filter_builder.SelectTrigger, {
2330
2352
  id: `context-picker:${sliceName}`,
2331
2353
  "data-testid": tid.contextPicker(sliceName),
2332
2354
  className: require_use_theme.cn("w-full", hideLabel ? "h-8 text-xs" : void 0),
2333
2355
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
2334
- }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: options.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
2356
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [allOption === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
2357
+ value: ALL,
2358
+ "data-testid": tid.contextPickerOption(sliceName, "all"),
2359
+ children: allLabel
2360
+ }), options.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
2335
2361
  value: o.value,
2336
2362
  "data-testid": tid.contextPickerOption(sliceName, o.value),
2337
2363
  children: o.label
2338
- }, o.value)) })]
2364
+ }, o.value))] })]
2365
+ })]
2366
+ });
2367
+ }
2368
+ //#endregion
2369
+ //#region src/layout/scope-dimension-picker.tsx
2370
+ function ScopeDimensionPicker(props) {
2371
+ const scope = (0, _burojs_react.useScope)();
2372
+ const definition = scope.definition?.dimensions[props.dimension];
2373
+ if (definition === void 0) throw new Error(`ScopeDimensionPicker: '${props.dimension}' is not a dimension of the app's defineScope(...)`);
2374
+ if (definition.select === "none") return null;
2375
+ const source = definition.values;
2376
+ if (source === void 0) throw new Error(`ScopeDimensionPicker: dimension '${props.dimension}' declares no values; add values: { resource } or a { value, label } list`);
2377
+ const allowed = scope.access[props.dimension]?.allowed;
2378
+ const permitted = Array.isArray(allowed) ? allowed : void 0;
2379
+ const common = {
2380
+ ...props,
2381
+ multiple: definition.select === "multiple",
2382
+ all: definition.all,
2383
+ selected: scope.selection[props.dimension] ?? null,
2384
+ select: (value) => scope.select(props.dimension, value)
2385
+ };
2386
+ if (Array.isArray(source)) {
2387
+ const options = source.filter((option) => permitted === void 0 || permitted.includes(option.value));
2388
+ return (0, react_jsx_runtime.jsx)(DimensionControl, {
2389
+ ...common,
2390
+ options
2391
+ });
2392
+ }
2393
+ const { resource, label } = source;
2394
+ return (0, react_jsx_runtime.jsx)(ResourceDimension, {
2395
+ ...common,
2396
+ resource,
2397
+ ...label ? { labelField: label } : {}
2398
+ });
2399
+ }
2400
+ function ResourceDimension({ resource, labelField, ...rest }) {
2401
+ const options = require_resource_page_router.useResourceDimensionOptions(rest.dimension, resource, labelField);
2402
+ return (0, react_jsx_runtime.jsx)(DimensionControl, {
2403
+ ...rest,
2404
+ options
2405
+ });
2406
+ }
2407
+ function DimensionControl({ dimension, label, hideLabel, className, multiple, all, selected, select, options }) {
2408
+ const tid = (0, _burojs_react.useTestIds)();
2409
+ const chromeT = (0, _burojs_react.useChromeT)();
2410
+ const byText = (0, react.useMemo)(() => new Map(options.map((option) => [String(option.value), option.value])), [options]);
2411
+ const textOptions = (0, react.useMemo)(() => options.map((option) => ({
2412
+ value: String(option.value),
2413
+ label: option.label
2414
+ })), [options]);
2415
+ const picked = (Array.isArray(selected) ? selected : selected === null ? [] : [selected]).map(String);
2416
+ const text = label ?? (0, _burojs_core.humanizeKey)(dimension);
2417
+ if (multiple) return (0, react_jsx_runtime.jsxs)("div", {
2418
+ className: require_use_theme.cn("space-y-1", className),
2419
+ children: [(0, react_jsx_runtime.jsx)("span", {
2420
+ className: hideLabel ? "sr-only" : "text-xs font-medium text-muted-foreground uppercase tracking-wide",
2421
+ children: text
2422
+ }), (0, react_jsx_runtime.jsx)(require_filter_builder.FacetedFilterPicker, {
2423
+ title: text,
2424
+ options: textOptions,
2425
+ selected: picked,
2426
+ ...all ? { emptyLabel: chromeT("scope.all", { defaultValue: "All" }) } : { clearable: false },
2427
+ onChange: (next) => {
2428
+ if (next.length === 0 && !all) return;
2429
+ select(next.length === 0 ? null : next.map((value) => byText.get(value) ?? value));
2430
+ },
2431
+ getTestId: (role, value) => role === "trigger" ? tid.contextPicker(dimension) : role === "option" ? tid.contextPickerOption(dimension, value ?? "") : role === "clear" ? tid.contextPickerOption(dimension, "all") : void 0
2339
2432
  })]
2340
2433
  });
2434
+ const common = {
2435
+ sliceName: dimension,
2436
+ ...label === void 0 ? {} : { label },
2437
+ options: textOptions,
2438
+ value: picked[0] ?? null,
2439
+ ...hideLabel === void 0 ? {} : { hideLabel },
2440
+ ...className === void 0 ? {} : { className }
2441
+ };
2442
+ const choose = (value) => select(value === null ? null : byText.get(value) ?? value);
2443
+ return all ? (0, react_jsx_runtime.jsx)(ContextPicker, {
2444
+ ...common,
2445
+ allOption: true,
2446
+ onChange: choose
2447
+ }) : (0, react_jsx_runtime.jsx)(ContextPicker, {
2448
+ ...common,
2449
+ onChange: choose
2450
+ });
2341
2451
  }
2342
2452
  //#endregion
2343
2453
  //#region src/layout/language-switch.tsx
@@ -2468,20 +2578,20 @@ function CommandPalette({ open, onOpenChange, children, placeholder, emptyState,
2468
2578
  }
2469
2579
  onOpenChange(next);
2470
2580
  }, [onOpenChange]);
2471
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandDialog, {
2581
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandDialog, {
2472
2582
  open,
2473
2583
  onOpenChange: handleOpenChange,
2474
2584
  className,
2475
2585
  title: t("commandPalette.title", { defaultValue: "Command Palette" }),
2476
2586
  description: t("commandPalette.description", { defaultValue: "Search and run actions." }),
2477
2587
  children: [
2478
- (0, react_jsx_runtime.jsx)(require_search_access.CommandInput, {
2588
+ (0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
2479
2589
  placeholder: resolvedPlaceholder,
2480
2590
  "data-testid": inputTestId
2481
2591
  }),
2482
- (0, react_jsx_runtime.jsxs)(require_search_access.CommandList, {
2592
+ (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, {
2483
2593
  "data-testid": dialogTestId,
2484
- children: [resolvedEmpty !== null && !hasAsyncResults && (0, react_jsx_runtime.jsx)(require_search_access.CommandEmpty, {
2594
+ children: [resolvedEmpty !== null && !hasAsyncResults && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, {
2485
2595
  "data-testid": emptyTestId,
2486
2596
  children: resolvedEmpty
2487
2597
  }), (0, react_jsx_runtime.jsx)(CommandPaletteResultsContext.Provider, {
@@ -2528,7 +2638,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2528
2638
  const navigate = (0, _burojs_react.useRouteNavigate)();
2529
2639
  const isVisible = require_resource_page_router.useNavVisible();
2530
2640
  const resolveLayout = require_resource_page_router.useLayoutResolver();
2531
- const isResourceVisible = (r) => (0, _burojs_core.evaluateVisible)(r.visible, visibilityCtx);
2641
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
2532
2642
  const pageAllowed = require_resource_page_router.usePageAllowed();
2533
2643
  const isPageVisible = (p) => (0, _burojs_core.evaluateVisible)(p.visible, visibilityCtx) && pageAllowed(p);
2534
2644
  const { topLevelResources, topLevelPages, sectionGroups } = (0, react.useMemo)(() => {
@@ -2554,18 +2664,18 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2554
2664
  }, [app, visibilityCtx]);
2555
2665
  const goTo = (href) => {
2556
2666
  onSelect?.();
2557
- navigate(href);
2667
+ navigate(href, { origin: "jump" });
2558
2668
  };
2559
2669
  const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "plural", def);
2560
2670
  const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(def)}`, (0, _burojs_core.declaredText)("chrome", def, "label"));
2561
2671
  const groups = [];
2562
- if (topLevelResources.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2672
+ if (topLevelResources.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2563
2673
  heading: t("commandPalette.resources", { defaultValue: "Resources" }),
2564
2674
  children: topLevelResources.map((def) => {
2565
2675
  const resource = require_resource_page_router.canonicalResourceKey(def);
2566
2676
  const label = resourceLabel(def);
2567
2677
  const href = (0, _burojs_core.hrefFor)(app.registry, resource, { isVisible });
2568
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2678
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2569
2679
  value: `resource:${resource}:${label}`,
2570
2680
  onSelect: () => goTo(href),
2571
2681
  "data-testid": getTestId?.("resource", resource),
@@ -2573,13 +2683,13 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2573
2683
  }, `resource:${resource}`);
2574
2684
  })
2575
2685
  }, "resources"));
2576
- if (topLevelPages.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2686
+ if (topLevelPages.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2577
2687
  heading: t("commandPalette.pages", { defaultValue: "Pages" }),
2578
2688
  children: topLevelPages.map((page) => {
2579
2689
  const pageKey = require_resource_page_router.canonicalNavKey(page);
2580
2690
  const label = pageLabel(page);
2581
2691
  const href = page.path;
2582
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2692
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2583
2693
  value: `page:${pageKey}:${page.path}:${label}`,
2584
2694
  onSelect: () => goTo(href),
2585
2695
  "data-testid": getTestId?.("page", pageKey),
@@ -2590,9 +2700,9 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2590
2700
  for (const { section, children } of sectionGroups) {
2591
2701
  const sectionKey = require_resource_page_router.canonicalNavKey(section);
2592
2702
  const sectionLabel = (0, _burojs_core.resolveNavLabel)(caps, `sections.${sectionKey}`, (0, _burojs_core.declaredText)("chrome", section, "label"));
2593
- groups.push((0, react_jsx_runtime.jsxs)(require_search_access.CommandGroup, {
2703
+ groups.push((0, react_jsx_runtime.jsxs)(require_relation_create.CommandGroup, {
2594
2704
  heading: sectionLabel,
2595
- children: [(0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2705
+ children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2596
2706
  value: `section:${sectionKey}:${sectionLabel}`,
2597
2707
  disabled: true,
2598
2708
  className: "font-medium opacity-70",
@@ -2603,7 +2713,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2603
2713
  const pageKey = require_resource_page_router.canonicalNavKey(child);
2604
2714
  const href = child.path;
2605
2715
  const label = pageLabel(child);
2606
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2716
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2607
2717
  value: `section:${sectionKey}:page:${pageKey}:${child.path}:${label}`,
2608
2718
  onSelect: () => goTo(href),
2609
2719
  "data-testid": getTestId?.("page", `${sectionKey}:${pageKey}`),
@@ -2614,7 +2724,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2614
2724
  const resource = require_resource_page_router.canonicalResourceKey(child);
2615
2725
  const label = resourceLabel(child);
2616
2726
  const href = (0, _burojs_core.hrefFor)(app.registry, resource, { isVisible });
2617
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2727
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2618
2728
  value: `section:${sectionKey}:resource:${resource}:${label}`,
2619
2729
  onSelect: () => goTo(href),
2620
2730
  "data-testid": getTestId?.("resource", `${sectionKey}:${resource}`),
@@ -2630,7 +2740,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2630
2740
  const groupKey = require_resource_page_router.canonicalNavKey(group);
2631
2741
  const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2632
2742
  const href = (0, _burojs_core.navHrefFor)(app.registry, groupKey, { isVisible });
2633
- items.push((0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2743
+ items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2634
2744
  value: `group:${idPath}:${label}`,
2635
2745
  onSelect: () => goTo(href),
2636
2746
  "data-testid": getTestId?.("group", idPath),
@@ -2651,7 +2761,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2651
2761
  const pageKey = require_resource_page_router.canonicalNavKey(page);
2652
2762
  const label = pageLabel(page);
2653
2763
  const href = page.path;
2654
- items.push((0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2764
+ items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2655
2765
  value: `page:${idPath}:${pageKey}:${label}`,
2656
2766
  onSelect: () => goTo(href),
2657
2767
  "data-testid": getTestId?.("page", `${idPath}:${pageKey}`),
@@ -2666,7 +2776,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2666
2776
  const resourceId = require_resource_page_router.canonicalResourceKey(resource);
2667
2777
  const label = resourceLabel(resource);
2668
2778
  const href = (0, _burojs_core.hrefFor)(app.registry, resourceId, { isVisible });
2669
- items.push((0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2779
+ items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2670
2780
  value: `resource:${idPath}:${resourceId}:${label}`,
2671
2781
  onSelect: () => goTo(href),
2672
2782
  "data-testid": getTestId?.("resource", `${idPath}:${resourceId}`),
@@ -2683,13 +2793,13 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2683
2793
  const items = collectGroupItems(group, groupKey, 0);
2684
2794
  if (items.length === 0) continue;
2685
2795
  const heading = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2686
- groups.push((0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2796
+ groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2687
2797
  heading,
2688
2798
  children: items
2689
2799
  }, `group:${groupKey}`));
2690
2800
  }
2691
2801
  if (groups.length === 0) return null;
2692
- return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: groups.map((group, idx) => (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [idx > 0 && (0, react_jsx_runtime.jsx)(require_search_access.CommandSeparator, {}), group] }, `navgrp-${idx}`)) });
2802
+ return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: groups.map((group, idx) => (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [idx > 0 && (0, react_jsx_runtime.jsx)(require_relation_create.CommandSeparator, {}), group] }, `navgrp-${idx}`)) });
2693
2803
  }
2694
2804
  //#endregion
2695
2805
  //#region src/layout/quick-targets.ts
@@ -2702,11 +2812,11 @@ function opensInQuick(registry, resource, mode) {
2702
2812
  }
2703
2813
  //#endregion
2704
2814
  //#region src/layout/command-palette-recent-group.tsx
2705
- function entryHref(registry, entry, visibilityCtx) {
2815
+ function entryHref(registry, entry, isResourceVisible) {
2706
2816
  const def = registry.get(entry.canonicalRef);
2707
2817
  if (def === void 0) return void 0;
2708
- if (!(0, _burojs_core.evaluateVisible)(def.visible, visibilityCtx)) return void 0;
2709
- for (const action of ["show", "edit"]) if (require_place_node.recordRouteAvailable(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2818
+ if (!isResourceVisible(def)) return void 0;
2819
+ for (const action of ["show", "edit"]) if ((0, _burojs_react.recordRouteAvailable)(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2710
2820
  action,
2711
2821
  id: entry.id
2712
2822
  });
@@ -2719,36 +2829,48 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2719
2829
  const navigate = (0, _burojs_react.useRouteNavigate)();
2720
2830
  const quick = (0, _burojs_react.useQuick)();
2721
2831
  const userId = (0, _burojs_react.useCurrentUserId)();
2722
- const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
2832
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
2723
2833
  const resolvedHeading = heading ?? t("commandPalette.recent", { defaultValue: "Recent" });
2724
- const [hydrated, setHydrated] = (0, react.useState)(false);
2834
+ const store = (0, _burojs_react.usePlatformStorage)().local;
2835
+ const [stored, setStored] = (0, react.useState)([]);
2725
2836
  (0, react.useEffect)(() => {
2726
- setHydrated(true);
2727
- }, []);
2728
- const recents = (0, react.useMemo)(() => {
2729
- if (!hydrated || userId === null) return [];
2730
- return require_resource_page_router.readRecentRecords(userId).flatMap((entry) => {
2731
- const href = entryHref(app.registry, entry, visibilityCtx);
2732
- return href === void 0 ? [] : [{
2733
- entry,
2734
- href
2735
- }];
2736
- });
2837
+ if (userId === null) {
2838
+ setStored([]);
2839
+ return;
2840
+ }
2841
+ let current = true;
2842
+ const read = require_resource_page_router.readRecentRecords(store, userId);
2843
+ if (Array.isArray(read)) setStored(read);
2844
+ else read.then((entries) => {
2845
+ if (current) setStored(entries);
2846
+ }, () => void 0);
2847
+ return () => {
2848
+ current = false;
2849
+ };
2737
2850
  }, [
2738
- hydrated,
2851
+ store,
2739
2852
  userId,
2740
- refreshKey,
2853
+ refreshKey
2854
+ ]);
2855
+ const recents = (0, react.useMemo)(() => stored.flatMap((entry) => {
2856
+ const href = entryHref(app.registry, entry, isResourceVisible);
2857
+ return href === void 0 ? [] : [{
2858
+ entry,
2859
+ href
2860
+ }];
2861
+ }), [
2862
+ stored,
2741
2863
  app.registry,
2742
- visibilityCtx
2864
+ isResourceVisible
2743
2865
  ]);
2744
2866
  if (((0, cmdk.useCommandState)((state) => state.search) ?? "").length > 0) return null;
2745
2867
  if (recents.length === 0) return null;
2746
2868
  const goTo = (href, entry) => {
2747
2869
  onSelect?.();
2748
2870
  if (href === null) quick.show(entry.canonicalRef, entry.id);
2749
- else navigate(href);
2871
+ else navigate(href, { origin: "jump" });
2750
2872
  };
2751
- return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2873
+ return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2752
2874
  heading: resolvedHeading,
2753
2875
  children: recents.map(({ entry, href }) => (0, react_jsx_runtime.jsx)(RecentItem, {
2754
2876
  entry,
@@ -2756,7 +2878,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2756
2878
  onGo: goTo,
2757
2879
  ...getTestId === void 0 ? {} : { getTestId }
2758
2880
  }, `recent:${entry.canonicalRef}:${entry.id}`))
2759
- }, "recent"), withSeparator && (0, react_jsx_runtime.jsx)(require_search_access.CommandSeparator, {})] });
2881
+ }, "recent"), withSeparator && (0, react_jsx_runtime.jsx)(require_relation_create.CommandSeparator, {})] });
2760
2882
  }
2761
2883
  function RecentItem({ entry, href, onGo, getTestId }) {
2762
2884
  const app = (0, _burojs_react.useApp)();
@@ -2769,7 +2891,7 @@ function RecentItem({ entry, href, onGo, getTestId }) {
2769
2891
  const candidates = def?.recordTitle === void 0 ? [...declared.filter((name) => require_resource_page_router.RECENT_LABEL_KEYS.includes(name)), ...def?.displayField === void 0 ? [] : [def.displayField]] : declared;
2770
2892
  const legacyTrusted = entry.label === entry.id || access.status === "ready" && candidates.every((name) => access.fieldVisible(name));
2771
2893
  const shown = entry.labelField === void 0 ? legacyTrusted ? entry.label : entry.id : access.status === "ready" && access.fieldVisible(entry.labelField) ? entry.label : entry.id;
2772
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
2894
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2773
2895
  value: `recent:${key}:${resourceLabel}:${shown}`,
2774
2896
  onSelect: () => onGo(href, entry),
2775
2897
  "data-testid": getTestId?.("recent", key),
@@ -2792,7 +2914,7 @@ function resolveDisplayField(def) {
2792
2914
  const isSearchable = (fieldName) => {
2793
2915
  const fieldDef = fields[fieldName];
2794
2916
  if (!fieldDef) return false;
2795
- const canonical = require_place_node.lowerLegacyField(fieldDef);
2917
+ const canonical = require_filter_builder.lowerLegacyField(fieldDef);
2796
2918
  return canonical.type === "string" && canonical.format !== "enum";
2797
2919
  };
2798
2920
  if (def.displayField && isSearchable(def.displayField)) return def.displayField;
@@ -2804,25 +2926,26 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2804
2926
  const t = (0, _burojs_react.useOptionalT)();
2805
2927
  const navigate = (0, _burojs_react.useRouteNavigate)();
2806
2928
  const quick = (0, _burojs_react.useQuick)();
2929
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
2807
2930
  const resolvedHeading = heading ?? t("commandPalette.records", { defaultValue: "Records" });
2808
2931
  const liveQuery = (0, cmdk.useCommandState)((state) => state.search) ?? "";
2809
2932
  const debouncedQuery = (0, _burojs_react.useDebouncedValue)(liveQuery, debounceMs);
2810
2933
  const searchableResources = (0, react.useMemo)(() => {
2811
- return app.registry.list().filter((r) => require_place_node.isShowAvailable(app.registry, require_resource_page_router.canonicalResourceKey(r)) || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "show")).map((def) => {
2934
+ return app.registry.list().filter((r) => require_resource_page_router.isShowAvailable(app.registry, require_resource_page_router.canonicalResourceKey(r)) || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "show")).filter(isResourceVisible).map((def) => {
2812
2935
  const displayField = resolveDisplayField(def);
2813
2936
  return displayField ? {
2814
2937
  def,
2815
2938
  displayField
2816
2939
  } : null;
2817
2940
  }).filter((entry) => entry !== null);
2818
- }, [app.registry]);
2941
+ }, [app.registry, isResourceVisible]);
2819
2942
  if (!(enabled && debouncedQuery.length >= minQueryLength && searchableResources.length > 0)) return null;
2820
2943
  const goTo = (href, resource, id) => {
2821
2944
  onSelect?.();
2822
2945
  if (href === null) quick.show(resource, id);
2823
- else navigate(href);
2946
+ else navigate(href, { origin: "jump" });
2824
2947
  };
2825
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2948
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2826
2949
  heading: resolvedHeading,
2827
2950
  forceMount: true,
2828
2951
  children: searchableResources.map(({ def, displayField }) => (0, react_jsx_runtime.jsx)(PerResourceSearchHits, {
@@ -2858,28 +2981,40 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2858
2981
  enabled: shouldFetch
2859
2982
  });
2860
2983
  const report = useCommandPaletteResults(`records:${resource}`);
2984
+ const rowSubtitle = require_use_record_subtitle.useRowSubtitle(resource);
2861
2985
  const rows = !shouldFetch || q.isLoading || q.isError ? [] : q.data?.data ?? [];
2862
2986
  (0, react.useEffect)(() => {
2863
2987
  report(rows.length);
2864
2988
  }, [report, rows.length]);
2865
2989
  if (rows.length === 0) return null;
2866
2990
  const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "single", def);
2991
+ const declaredIdField = def.data?.idField;
2992
+ const idField = typeof declaredIdField === "string" && declaredIdField.length > 0 ? declaredIdField : "id";
2867
2993
  return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: rows.map((row) => {
2868
- const idVal = row.id ?? row.event_id ?? row.job_id;
2994
+ const idVal = row[idField] ?? row.id ?? row.event_id ?? row.job_id;
2869
2995
  const id = idVal == null ? "" : String(idVal);
2870
2996
  if (!id) return null;
2871
2997
  const display = titleVisible ? row[displayField] : void 0;
2872
2998
  const labelText = typeof display === "string" && display.length > 0 ? display : id;
2873
- const href = recordHref ? recordHref(resource, id) : require_place_node.isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id) : null;
2874
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
2999
+ const subtitle = rowSubtitle(row) ?? null;
3000
+ const href = recordHref ? recordHref(resource, id) : require_resource_page_router.isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id) : null;
3001
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2875
3002
  value: `record:${resource}:${id}:${labelText}`,
2876
3003
  forceMount: true,
2877
3004
  onSelect: () => goTo(href, resource, id),
2878
3005
  "data-testid": getTestId?.("records-record", `${resource}:${id}`),
2879
- children: [(0, react_jsx_runtime.jsxs)("span", {
2880
- className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
2881
- children: [resourceLabel, ":"]
2882
- }), labelText]
3006
+ children: [
3007
+ (0, react_jsx_runtime.jsxs)("span", {
3008
+ className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
3009
+ children: [resourceLabel, ":"]
3010
+ }),
3011
+ labelText,
3012
+ subtitle === null ? null : (0, react_jsx_runtime.jsx)("span", {
3013
+ "data-buro-region": "record-subtitle",
3014
+ className: "ml-auto truncate pl-2 text-xs text-muted-foreground group-data-[selected=true]:text-accent-foreground",
3015
+ children: subtitle
3016
+ })
3017
+ ]
2883
3018
  }, `record:${resource}:${id}`);
2884
3019
  }) });
2885
3020
  }
@@ -2973,7 +3108,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
2973
3108
  onSelect?.();
2974
3109
  }
2975
3110
  };
2976
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
3111
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2977
3112
  heading: resolvedHeading,
2978
3113
  children: items.map((item) => {
2979
3114
  const value = [
@@ -2983,7 +3118,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
2983
3118
  item.label,
2984
3119
  item.keywords ?? ""
2985
3120
  ].filter((s) => s.length > 0).join(":");
2986
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
3121
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2987
3122
  value,
2988
3123
  className: require_use_theme.cn(item.disabled && "opacity-60"),
2989
3124
  onSelect: () => {
@@ -3010,7 +3145,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
3010
3145
  function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, heading, createHref, prefix }) {
3011
3146
  const caps = (0, _burojs_react.useI18nCaps)();
3012
3147
  const app = (0, _burojs_react.useApp)();
3013
- const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
3148
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
3014
3149
  const gate = (0, _burojs_react.useAvailabilityGate)();
3015
3150
  const t = (0, _burojs_react.useOptionalT)();
3016
3151
  const navigate = (0, _burojs_react.useRouteNavigate)();
@@ -3018,16 +3153,16 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3018
3153
  const resolvedHeading = heading ?? t("commandPalette.create", { defaultValue: "Create" });
3019
3154
  const resolvedPrefix = prefix ?? t("commandPalette.createNew", { defaultValue: "Create new" });
3020
3155
  const visibleResources = (0, react.useMemo)(() => {
3021
- return app.registry.list().filter((r) => (0, _burojs_core.hasListPage)(r)).filter((r) => gate(require_resource_page_router.canonicalResourceKey(r), "create").state === "available").filter((r) => (0, _burojs_core.hasRecordPage)(r, "create") || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "create")).filter((r) => (0, _burojs_core.evaluateVisible)(r.visible, visibilityCtx)).filter((r) => resourceFilter ? resourceFilter(r) : true);
3156
+ return app.registry.list().filter((r) => (0, _burojs_core.hasListPage)(r)).filter((r) => gate(require_resource_page_router.canonicalResourceKey(r), "create").state === "available").filter((r) => (0, _burojs_core.hasRecordPage)(r, "create") || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "create")).filter(isResourceVisible).filter((r) => resourceFilter ? resourceFilter(r) : true);
3022
3157
  }, [
3023
3158
  app,
3024
3159
  gate,
3025
- visibilityCtx,
3160
+ isResourceVisible,
3026
3161
  resourceFilter
3027
3162
  ]);
3028
3163
  if (visibleResources.length === 0) return null;
3029
3164
  const goTo = (href) => {
3030
- navigate(href);
3165
+ navigate(href, { origin: "jump" });
3031
3166
  onSelect?.();
3032
3167
  };
3033
3168
  const createIn = (def, href) => {
@@ -3039,14 +3174,14 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3039
3174
  quick.create(require_resource_page_router.canonicalResourceKey(def));
3040
3175
  };
3041
3176
  const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "single", def);
3042
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
3177
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
3043
3178
  heading: resolvedHeading,
3044
3179
  children: visibleResources.map((def) => {
3045
3180
  const resource = require_resource_page_router.canonicalResourceKey(def);
3046
3181
  const label = resourceLabel(def);
3047
3182
  const href = createHref?.(def) ?? (0, _burojs_core.resourceCreateHref)(app.registry, def, resource);
3048
3183
  const value = `create:${resource}:${resolvedPrefix}:${label}`;
3049
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
3184
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
3050
3185
  value,
3051
3186
  onSelect: () => createIn(def, href),
3052
3187
  "data-testid": getTestId?.("create", resource),
@@ -3104,7 +3239,7 @@ function AppActions() {
3104
3239
  variant: "outline",
3105
3240
  size: "sm",
3106
3241
  disabled: action.disabledReason !== void 0,
3107
- title: action.disabledReason,
3242
+ title: action.disabledReason === void 0 ? void 0 : require_check_confirm_dialog.reasonText(caps, action.disabledReason),
3108
3243
  "data-testid": `app-action:${action.name}`,
3109
3244
  children: action.disabledReason === void 0 ? (0, react_jsx_runtime.jsx)(RouterLink, {
3110
3245
  href,
@@ -3226,6 +3361,7 @@ function localizedSchema(t) {
3226
3361
  function LoginForm({ onSubmit, title, description, className }) {
3227
3362
  const tid = (0, _burojs_react.useTestIds)();
3228
3363
  const t = (0, _burojs_react.useOptionalT)();
3364
+ const caps = (0, _burojs_react.useI18nCaps)();
3229
3365
  const resolvedTitle = title ?? t("auth.signIn", { defaultValue: "Sign in" });
3230
3366
  const { register, handleSubmit, formState: { errors, isSubmitting } } = (0, react_hook_form.useForm)({
3231
3367
  resolver: (0, _hookform_resolvers_zod.zodResolver)(localizedSchema(t)),
@@ -3240,9 +3376,11 @@ function LoginForm({ onSubmit, title, description, className }) {
3240
3376
  try {
3241
3377
  await onSubmit(values);
3242
3378
  } catch (e) {
3243
- const raw = e instanceof Error ? e.message : String(e);
3379
+ const dataCode = e !== null && typeof e === "object" && !(e instanceof Error) ? e.code : void 0;
3380
+ const raw = e instanceof Error ? e.message : require_toaster.technicalText(e) ?? (dataCode === void 0 ? String(e) : "");
3244
3381
  const friendly = require_toaster.toFriendlyError(raw, "", require_toaster.friendlyStringsFrom(t));
3245
- setSubmitError(friendly.replaced ? `${friendly.title}. ${friendly.detail}` : credentialsMessage(raw, t));
3382
+ const credentials = credentialsMessage(raw, t);
3383
+ setSubmitError(friendly.replaced ? `${friendly.title}. ${friendly.detail}` : typeof dataCode === "string" && credentials === raw ? (0, _burojs_react.resolveErrorText)(e, caps) : credentials);
3246
3384
  }
3247
3385
  });
3248
3386
  return (0, react_jsx_runtime.jsxs)(Card, {
@@ -3367,15 +3505,139 @@ function AuthPage({ children, brand, footer, className }) {
3367
3505
  });
3368
3506
  }
3369
3507
  //#endregion
3508
+ //#region src/enum/enum-choice-group.tsx
3509
+ const NONE = "__none__";
3510
+ function isEmpty$1(value) {
3511
+ return value === null || value === void 0 || value === "";
3512
+ }
3513
+ function EnumChoiceGroup({ control, options, current, settling, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3514
+ const t = (0, _burojs_react.useOptionalT)();
3515
+ const generatedName = react.useId();
3516
+ const groupName = name ?? generatedName;
3517
+ const empty = isEmpty$1(value);
3518
+ const noneLabel = t("field.none", { defaultValue: "None" });
3519
+ const pick = (next) => {
3520
+ if (!disabled) onChange(next);
3521
+ };
3522
+ const ariaProps = {
3523
+ "aria-invalid": ariaInvalid || void 0,
3524
+ "aria-describedby": ariaDescribedBy,
3525
+ ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3526
+ };
3527
+ if (control === "segmented") {
3528
+ const segmentLabel = (option) => (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [option.icon ? (0, react_jsx_runtime.jsx)("span", {
3529
+ "data-testid": `${testid}:option:${option.value}:icon`,
3530
+ className: "contents",
3531
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3532
+ name: option.icon,
3533
+ className: "size-3.5 shrink-0"
3534
+ })
3535
+ }) : null, option.label] });
3536
+ const segment = (key, label, active, select, currentItem = false) => (0, react_jsx_runtime.jsx)("button", {
3537
+ type: "button",
3538
+ "aria-pressed": active,
3539
+ "data-state": active ? "active" : "inactive",
3540
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3541
+ ...currentItem ? { "data-current": "" } : {},
3542
+ disabled: disabled || currentItem,
3543
+ onClick: select,
3544
+ className: require_use_theme.cn("inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all", "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs", "disabled:pointer-events-none disabled:opacity-50", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"),
3545
+ children: label
3546
+ }, currentItem ? `current:${key}` : key);
3547
+ return (0, react_jsx_runtime.jsxs)("div", {
3548
+ role: "group",
3549
+ id,
3550
+ "aria-labelledby": ariaLabelledBy,
3551
+ "data-testid": testid,
3552
+ className: require_use_theme.cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3553
+ ...ariaProps,
3554
+ children: [
3555
+ current === void 0 ? null : segment(current.value, segmentLabel(current), true, () => void 0, true),
3556
+ required || settling !== void 0 ? null : segment(NONE, noneLabel, empty, () => pick(void 0)),
3557
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3558
+ status: settling,
3559
+ testid
3560
+ }),
3561
+ options.map((option) => segment(option.value, segmentLabel(option), value === option.value, () => pick(option.value)))
3562
+ ]
3563
+ });
3564
+ }
3565
+ const cards = control === "cards";
3566
+ const choice = (key, option, label, checked, select, currentItem = false) => {
3567
+ const inputId = `${id ?? groupName}:${currentItem ? "current:" : ""}${key}`;
3568
+ const inert = disabled || currentItem;
3569
+ return (0, react_jsx_runtime.jsxs)("label", {
3570
+ htmlFor: inputId,
3571
+ className: require_use_theme.cn("flex items-start gap-2.5", cards && "cursor-pointer rounded-lg border px-3 py-2.5 transition-colors hover:bg-accent/50 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring", cards && (checked ? "border-primary" : "border-input"), inert && "cursor-not-allowed opacity-60"),
3572
+ children: [(0, react_jsx_runtime.jsx)("input", {
3573
+ type: "radio",
3574
+ id: inputId,
3575
+ name: groupName,
3576
+ value: key,
3577
+ checked,
3578
+ onChange: select,
3579
+ disabled: inert,
3580
+ ...ariaProps,
3581
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3582
+ ...currentItem ? { "data-current": "" } : {},
3583
+ className: require_use_theme.cn("h-4 w-4 shrink-0 accent-primary", cards ? "mt-0.5" : "mt-1")
3584
+ }), (0, react_jsx_runtime.jsxs)("span", {
3585
+ className: "flex min-w-0 flex-col gap-0.5",
3586
+ children: [(0, react_jsx_runtime.jsxs)("span", {
3587
+ className: require_use_theme.cn("flex items-center gap-1.5", cards && "font-medium"),
3588
+ children: [option?.icon ? (0, react_jsx_runtime.jsx)("span", {
3589
+ "data-testid": `${testid}:option:${key}:icon`,
3590
+ className: "contents",
3591
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3592
+ name: option.icon,
3593
+ className: "size-4 shrink-0"
3594
+ })
3595
+ }) : null, (0, react_jsx_runtime.jsx)("span", { children: label })]
3596
+ }), option?.summary === void 0 || option.summary === "" ? null : (0, react_jsx_runtime.jsx)("span", {
3597
+ "data-testid": `${testid}:option:${key}:doc`,
3598
+ className: "text-sm text-muted-foreground",
3599
+ children: option.summary
3600
+ })]
3601
+ })]
3602
+ }, currentItem ? `current:${key}` : key);
3603
+ };
3604
+ return (0, react_jsx_runtime.jsxs)("div", {
3605
+ role: "radiogroup",
3606
+ id,
3607
+ "aria-labelledby": ariaLabelledBy,
3608
+ "data-testid": testid,
3609
+ "aria-required": required,
3610
+ className: require_use_theme.cn("flex flex-col", cards ? "gap-2" : "gap-1.5", className),
3611
+ children: [
3612
+ current === void 0 ? null : choice(current.value, current, current.label, true, () => void 0, true),
3613
+ required || settling !== void 0 ? null : choice(NONE, void 0, noneLabel, empty, () => pick(void 0)),
3614
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3615
+ status: settling,
3616
+ testid
3617
+ }),
3618
+ options.map((option) => choice(option.value, option, option.label, value === option.value, () => pick(option.value)))
3619
+ ]
3620
+ });
3621
+ }
3622
+ //#endregion
3370
3623
  //#region src/enum/enum-picker.tsx
3371
3624
  const ENUM_PICKER_CLEAR_SENTINEL = "__buro_clear__";
3372
- function EnumPicker({ enumName, value, onChange, renderAs = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, className, clearable = false, clearLabel = "All" }) {
3625
+ function withSummary(summary) {
3626
+ return summary === void 0 ? {} : { summary };
3627
+ }
3628
+ function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All", use }) {
3629
+ const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
3373
3630
  const app = (0, _burojs_react.useApp)();
3374
3631
  const t = (0, _burojs_react.useOptionalT)();
3375
3632
  const def = app.registry.enums.get(enumName);
3376
3633
  const caps = (0, _burojs_react.useI18nCaps)();
3377
3634
  const ns = def?.i18nNamespace ?? enumName;
3378
3635
  const { values, isLoading, error } = (0, _burojs_react.useEnumValues)(enumName);
3636
+ const available = (0, _burojs_react.useAvailableEnumValues)({
3637
+ values: isLoading || values === void 0 ? "pending" : values,
3638
+ ...def === void 0 ? {} : { enum: def },
3639
+ ...use === void 0 ? {} : { use }
3640
+ });
3379
3641
  const tid = testid ?? `enum-picker:${enumName}`;
3380
3642
  if (!def) return (0, react_jsx_runtime.jsxs)("span", {
3381
3643
  "data-testid": `${tid}:unregistered`,
@@ -3400,63 +3662,56 @@ function EnumPicker({ enumName, value, onChange, renderAs = "select", name, id,
3400
3662
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: t("field.loading", { defaultValue: "Loading…" }) })
3401
3663
  }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, {})]
3402
3664
  });
3403
- if (error || !values) return (0, react_jsx_runtime.jsxs)("span", {
3404
- "data-testid": `${tid}:error`,
3665
+ if (error || !values) return (0, react_jsx_runtime.jsxs)(require_relation_create.LoadError, {
3666
+ surface: "picker",
3667
+ error,
3668
+ testId: `${tid}:error`,
3405
3669
  className: "text-muted-foreground",
3406
- title: error?.message,
3670
+ fallback: {
3671
+ key: "relation.failed",
3672
+ default: "Failed to load options."
3673
+ },
3407
3674
  children: [
3408
3675
  "(failed to load enum ‘",
3409
3676
  enumName,
3410
3677
  "’)"
3411
3678
  ]
3412
3679
  });
3413
- if (renderAs === "radio") return (0, react_jsx_runtime.jsx)("div", {
3414
- role: "radiogroup",
3415
- "data-testid": tid,
3416
- className: require_use_theme.cn("flex flex-col gap-2", className),
3417
- "aria-required": required,
3418
- children: values.map((entry) => {
3419
- const inputId = `${id ?? tid}:${entry.value}`;
3420
- return (0, react_jsx_runtime.jsxs)("label", {
3421
- htmlFor: inputId,
3422
- className: "flex items-center gap-2",
3423
- children: [(0, react_jsx_runtime.jsx)("input", {
3424
- type: "radio",
3425
- id: inputId,
3426
- name: name ?? tid,
3427
- value: entry.value,
3428
- checked: value === entry.value,
3429
- onChange: (e) => onChange(e.target.value),
3430
- disabled,
3431
- "aria-invalid": ariaInvalid || void 0,
3432
- "aria-describedby": ariaDescribedBy,
3433
- ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3434
- "data-testid": `${tid}:option:${entry.value}`,
3435
- className: "h-4 w-4"
3436
- }), (0, react_jsx_runtime.jsx)("span", { children: (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label) })]
3437
- }, entry.value);
3438
- })
3439
- });
3440
- if (renderAs === "segmented") return (0, react_jsx_runtime.jsx)("div", {
3441
- role: "group",
3442
- "data-testid": tid,
3443
- className: require_use_theme.cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3444
- "aria-invalid": ariaInvalid || void 0,
3445
- "aria-describedby": ariaDescribedBy,
3446
- ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3447
- children: values.map((entry) => {
3448
- const isActive = value === entry.value;
3449
- return (0, react_jsx_runtime.jsx)("button", {
3450
- type: "button",
3451
- "aria-pressed": isActive,
3452
- "data-state": isActive ? "active" : "inactive",
3453
- "data-testid": `${tid}:option:${entry.value}`,
3454
- disabled,
3455
- onClick: () => onChange(entry.value),
3456
- className: require_use_theme.cn("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all", "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs", "disabled:pointer-events-none disabled:opacity-50", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"),
3457
- children: (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label)
3458
- }, entry.value);
3459
- })
3680
+ const labelOf = (entry) => (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label);
3681
+ const summaryOf = (entry) => (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${entry.value}`)?.summary || void 0;
3682
+ const settling = available.status === "ready" ? void 0 : available.status;
3683
+ const offered = settling === void 0 ? available.values : [];
3684
+ const known = value == null ? void 0 : values.find((entry) => entry.value === value);
3685
+ const current = value == null || value === "" || offered.some((entry) => entry.value === value) ? void 0 : known === void 0 ? {
3686
+ value,
3687
+ label: require_place_node.unknownEnumValueLabel(caps, def, ns, value).label
3688
+ } : {
3689
+ value,
3690
+ label: labelOf(known),
3691
+ ...known.icon === void 0 ? {} : { icon: known.icon }
3692
+ };
3693
+ if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3694
+ control,
3695
+ ...current === void 0 ? {} : { current },
3696
+ ...settling === void 0 ? {} : { settling },
3697
+ options: offered.map((entry) => ({
3698
+ value: entry.value,
3699
+ label: labelOf(entry),
3700
+ ...entry.icon === void 0 ? {} : { icon: entry.icon },
3701
+ ...withSummary(summaryOf(entry))
3702
+ })),
3703
+ value,
3704
+ onChange,
3705
+ testid: tid,
3706
+ name,
3707
+ id,
3708
+ required,
3709
+ disabled,
3710
+ ariaInvalid,
3711
+ ariaDescribedBy,
3712
+ ariaErrorMessage,
3713
+ ariaLabelledBy,
3714
+ className
3460
3715
  });
3461
3716
  const selectValue = value == null ? clearable ? ENUM_PICKER_CLEAR_SENTINEL : "" : value;
3462
3717
  const handleValueChange = (next) => {
@@ -3476,46 +3731,74 @@ function EnumPicker({ enumName, value, onChange, renderAs = "select", name, id,
3476
3731
  name,
3477
3732
  id,
3478
3733
  "aria-required": required,
3734
+ "aria-busy": settling === "pending" || void 0,
3479
3735
  "aria-invalid": ariaInvalid || void 0,
3480
3736
  "aria-describedby": ariaDescribedBy,
3481
3737
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3482
3738
  className,
3483
3739
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3484
- }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [clearable && (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3485
- value: "__buro_clear__",
3486
- "data-testid": `${tid}:option:__clear__`,
3487
- children: clearLabel
3488
- }), values.map((entry) => {
3489
- const optionLabel = (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label);
3490
- const optionDoc = (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${entry.value}`)?.summary;
3491
- return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3492
- value: entry.value,
3493
- "data-testid": `${tid}:option:${entry.value}`,
3494
- children: optionDoc === void 0 ? optionLabel : (0, react_jsx_runtime.jsxs)("span", {
3495
- className: "flex flex-col gap-0.5",
3496
- children: [(0, react_jsx_runtime.jsx)("span", { children: optionLabel }), (0, react_jsx_runtime.jsx)("span", {
3497
- className: "text-xs leading-snug text-muted-foreground",
3740
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [
3741
+ clearable && (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3742
+ value: "__buro_clear__",
3743
+ "data-testid": `${tid}:option:__clear__`,
3744
+ children: clearLabel
3745
+ }),
3746
+ current === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3747
+ value: current.value,
3748
+ disabled: true,
3749
+ "data-current": "",
3750
+ "data-testid": `${tid}:current`,
3751
+ children: current.label
3752
+ }),
3753
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3754
+ status: settling,
3755
+ testid: tid
3756
+ }),
3757
+ offered.map((entry) => {
3758
+ const optionLabel = labelOf(entry);
3759
+ const optionDoc = summaryOf(entry);
3760
+ return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3761
+ value: entry.value,
3762
+ "data-testid": `${tid}:option:${entry.value}`,
3763
+ description: optionDoc === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3498
3764
  "data-testid": `${tid}:option:${entry.value}:doc`,
3499
3765
  children: optionDoc
3500
- })]
3501
- })
3502
- }, entry.value);
3503
- })] })]
3766
+ }),
3767
+ children: optionLabel
3768
+ }, entry.value);
3769
+ })
3770
+ ] })]
3504
3771
  });
3505
3772
  }
3506
3773
  //#endregion
3774
+ //#region src/enum/resolve-enum-control.ts
3775
+ const warned = new Set();
3776
+ function resolveEnumControl(fieldControl, enumDef, where) {
3777
+ if ((0, _burojs_core.isEnumControl)(fieldControl)) return fieldControl;
3778
+ if (fieldControl !== void 0) {
3779
+ const shown = typeof fieldControl === "string" ? `'${fieldControl}'` : String(fieldControl);
3780
+ const key = `${where}\u0000${shown}`;
3781
+ if (!warned.has(key)) {
3782
+ warned.add(key);
3783
+ console.warn(`[buro/ui-shadcn] ${where}: unknown enum control ${shown}; expected one of ${_burojs_core.ENUM_CONTROLS.map((control) => `'${control}'`).join(", ")}. Using the enum's control, else 'select'.`);
3784
+ }
3785
+ }
3786
+ return enumDef?.control ?? "select";
3787
+ }
3788
+ //#endregion
3507
3789
  //#region src/forms/issue-severity.ts
3508
3790
  function isErrorIssue(issue) {
3509
3791
  return issue.severity === "error";
3510
3792
  }
3511
3793
  //#endregion
3512
3794
  //#region src/fields/boolean.tsx
3513
- function BooleanDisplay({ value }) {
3795
+ function BooleanDisplay({ value, text }) {
3514
3796
  const t = (0, _burojs_react.useOptionalT)();
3515
3797
  if (value == null) return (0, react_jsx_runtime.jsx)("span", {
3516
3798
  className: "text-muted-foreground",
3517
3799
  children: "—"
3518
3800
  });
3801
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
3519
3802
  return (0, react_jsx_runtime.jsx)("span", { children: value ? t("boolean.yes", { defaultValue: "Yes" }) : t("boolean.no", { defaultValue: "No" }) });
3520
3803
  }
3521
3804
  function BooleanInput({ name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
@@ -3534,34 +3817,113 @@ function BooleanInput({ name, id, value, onChange, testid, disabled, required, a
3534
3817
  }
3535
3818
  //#endregion
3536
3819
  //#region src/fields/date.tsx
3537
- function DateDisplay({ value }) {
3820
+ function DateDisplay(props) {
3821
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3822
+ kind: "date",
3823
+ ...props
3824
+ });
3825
+ }
3826
+ function DateTimeDisplay(props) {
3827
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3828
+ kind: "dateTime",
3829
+ ...props
3830
+ });
3831
+ }
3832
+ function TimeDisplay(props) {
3833
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3834
+ kind: "time",
3835
+ ...props
3836
+ });
3837
+ }
3838
+ function storedText(value) {
3839
+ return value instanceof Date && !Number.isNaN(value.getTime()) ? value.toISOString() : String(value);
3840
+ }
3841
+ function TemporalDisplay({ kind, value, text, field, record }) {
3538
3842
  const locale = (0, _burojs_react.useOptionalLocale)();
3843
+ const zone = require_filter_builder.useFieldTimeZone(field?.zone, record);
3844
+ const viewer = (0, _burojs_react.useTimeZone)();
3539
3845
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
3540
3846
  className: "text-muted-foreground",
3541
3847
  children: "—"
3542
3848
  });
3543
- const d = new Date(String(value));
3544
- if (Number.isNaN(d.getTime())) return (0, react_jsx_runtime.jsx)("span", { children: String(value) });
3849
+ if (zone.status === "pending" || viewer.status === "pending") return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
3850
+ className: "h-4 w-24",
3851
+ "aria-busy": "true"
3852
+ });
3853
+ const raw = storedText(value);
3854
+ const formatted = (0, _burojs_core.formatTimeValue)(kind, raw, {
3855
+ zone: zone.zone,
3856
+ viewerZone: viewer.zone,
3857
+ locale: require_filter_builder.localeTag(locale),
3858
+ params: {
3859
+ ...kind === "time" && field?.ui?.seconds === true ? { timeStyle: "medium" } : {},
3860
+ ...require_filter_builder.dateDisplayParams(field?.ui)
3861
+ }
3862
+ });
3863
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", {
3864
+ title: formatted,
3865
+ children: text
3866
+ });
3867
+ if (formatted === void 0) return (0, react_jsx_runtime.jsx)("span", { children: raw });
3545
3868
  return (0, react_jsx_runtime.jsx)("span", {
3546
3869
  className: "whitespace-nowrap",
3547
- children: require_filter_builder.formatDate(d, locale)
3870
+ children: formatted
3548
3871
  });
3549
3872
  }
3550
3873
  function toIsoDate(v) {
3551
3874
  if (v == null || v === "") return "";
3552
3875
  const s = String(v);
3553
- if (/^\d{4}-\d{2}-\d{2}/.test(s)) return s.slice(0, 10);
3554
- const d = new Date(s);
3555
- if (Number.isNaN(d.getTime())) return "";
3556
- return d.toISOString().slice(0, 10);
3876
+ return (0, _burojs_core.isCalendarDate)(s) ? s : "";
3557
3877
  }
3558
- function DateInput({ name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
3559
- return (0, react_jsx_runtime.jsx)(require_input.Input, {
3878
+ function DateInput(props) {
3879
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3880
+ ...props,
3881
+ type: "date",
3882
+ toText: toIsoDate,
3883
+ fromText: (text) => text || null
3884
+ });
3885
+ }
3886
+ function DateTimeInput(props) {
3887
+ const locale = (0, _burojs_react.useOptionalLocale)();
3888
+ const zone = require_filter_builder.useFieldTimeZone(props.field?.zone, props.values === void 0 ? props.record : {
3889
+ ...props.record,
3890
+ ...props.values
3891
+ });
3892
+ const viewer = (0, _burojs_react.useTimeZone)();
3893
+ const pending = zone.status === "pending";
3894
+ const fieldZone = zone.status === "ready" ? zone.zone : void 0;
3895
+ const named = fieldZone !== void 0 && viewer.status === "ready" && fieldZone !== viewer.zone ? (0, _burojs_core.zoneShortName)((0, _burojs_core.canonicalInstant)(String(props.value ?? "")) ?? (0, _burojs_core.epochMsToInstant)(Date.now()), fieldZone, require_filter_builder.localeTag(locale)) : void 0;
3896
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3897
+ ...props,
3898
+ type: "datetime-local",
3899
+ disabled: props.disabled || pending,
3900
+ toText: (value) => fieldZone === void 0 ? "" : require_filter_builder.toLocalDateTimeText(value, fieldZone),
3901
+ fromText: (text) => fieldZone === void 0 ? null : require_filter_builder.fromLocalDateTimeText(text, fieldZone) ?? null,
3902
+ ...named === void 0 ? {} : { zoneName: named }
3903
+ });
3904
+ }
3905
+ function TimeInput(props) {
3906
+ const seconds = props.field?.ui?.seconds === true;
3907
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3908
+ ...props,
3909
+ type: "time",
3910
+ step: seconds ? 1 : 60,
3911
+ toText: (value) => value == null ? "" : String(value),
3912
+ fromText: (text) => {
3913
+ if (text === "") return null;
3914
+ if (seconds) return text.length === 5 ? `${text}:00` : text;
3915
+ return text.slice(0, 5);
3916
+ }
3917
+ });
3918
+ }
3919
+ function TemporalInput({ type, step, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, zoneName }) {
3920
+ const input = (0, react_jsx_runtime.jsx)(require_input.Input, {
3560
3921
  name,
3561
3922
  id,
3562
- type: "date",
3563
- value: toIsoDate(value),
3564
- onChange: (e) => onChange(e.target.value || null),
3923
+ type,
3924
+ ...step === void 0 ? {} : { step },
3925
+ value: toText(value),
3926
+ onChange: (e) => onChange(fromText(e.target.value)),
3565
3927
  "data-testid": testid,
3566
3928
  disabled,
3567
3929
  required,
@@ -3570,34 +3932,27 @@ function DateInput({ name, id, value, onChange, testid, disabled, required, aria
3570
3932
  "aria-describedby": ariaDescribedBy,
3571
3933
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3572
3934
  });
3935
+ if (zoneName === void 0) return input;
3936
+ return (0, react_jsx_runtime.jsxs)("div", {
3937
+ className: "flex items-center gap-2",
3938
+ children: [input, (0, react_jsx_runtime.jsx)("span", {
3939
+ className: "whitespace-nowrap text-xs text-muted-foreground",
3940
+ "data-testid": testid === void 0 ? void 0 : `${testid}:zone`,
3941
+ children: zoneName
3942
+ })]
3943
+ });
3573
3944
  }
3574
3945
  //#endregion
3575
3946
  //#region src/fields/enum.tsx
3576
- function optionLabel(caps, field, value, inline) {
3577
- const ns = (0, _burojs_core.enumNamespaceOf)(field);
3578
- if (ns) return (0, _burojs_core.resolveEnumLabel)(caps, ns, value, inline);
3579
- return field ? (0, _burojs_core.resolveFieldOptionLabel)(caps, field.name, value, inline) : inline;
3580
- }
3581
- function declaredOptionLabel(option, value, enumDef) {
3582
- return (enumDef === void 0 ? void 0 : (0, _burojs_core.enumValueText)(enumDef, value)) ?? (typeof option?.label === "string" ? option.label : value);
3583
- }
3584
- function useBoundEnum(field) {
3585
- const app = (0, _burojs_react.useOptionalApp)();
3586
- const namespace = (0, _burojs_core.enumNamespaceOf)(field);
3587
- return namespace === void 0 ? void 0 : app?.registry.enums.get(namespace);
3588
- }
3589
- function useOptionCaps(resource) {
3590
- return (0, _burojs_react.useI18nCaps)((0, react.useContext)(_burojs_react.ResourceContext).resource ?? resource);
3591
- }
3592
3947
  function EnumDisplay({ value, options, field, resource }) {
3593
- const caps = useOptionCaps(resource);
3594
- const enumDef = useBoundEnum(field);
3948
+ const caps = (0, _burojs_react.useOptionCaps)(resource);
3949
+ const enumDef = (0, _burojs_react.useBoundEnum)(field);
3595
3950
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
3596
3951
  className: "text-muted-foreground",
3597
3952
  children: "—"
3598
3953
  });
3599
3954
  const opt = options?.find((o) => o.value === String(value));
3600
- const label = optionLabel(caps, field, String(value), declaredOptionLabel(opt, String(value), enumDef));
3955
+ const label = (0, _burojs_react.resolveOptionLabel)(caps, field, String(value), opt, enumDef);
3601
3956
  return (0, react_jsx_runtime.jsxs)("span", {
3602
3957
  className: "inline-flex items-center gap-1",
3603
3958
  children: [opt?.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
@@ -3606,10 +3961,62 @@ function EnumDisplay({ value, options, field, resource }) {
3606
3961
  }) : null, label]
3607
3962
  });
3608
3963
  }
3609
- function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, resource }) {
3964
+ function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource, record, values, metaSources, baseline }) {
3610
3965
  const t = (0, _burojs_react.useOptionalT)();
3611
- const caps = useOptionCaps(resource);
3612
- const enumDef = useBoundEnum(field);
3966
+ const caps = (0, _burojs_react.useOptionCaps)(resource);
3967
+ const enumDef = (0, _burojs_react.useBoundEnum)(field);
3968
+ const ns = (0, _burojs_core.enumNamespaceOf)(field);
3969
+ const control = resolveEnumControl(field?.ui?.control, enumDef, `field ${field?.name ?? name}`);
3970
+ const sources = (0, _burojs_react.useFieldMetaSources)({
3971
+ record,
3972
+ values,
3973
+ extra: metaSources
3974
+ });
3975
+ const available = (0, _burojs_react.useAvailableEnumValues)({
3976
+ values: options ?? [],
3977
+ use: {
3978
+ narrow: (0, _burojs_core_internal.narrowEntriesOf)(field?.meta?.narrow),
3979
+ sources,
3980
+ mode: record === void 0 ? "create" : "edit",
3981
+ baseline: baseline ?? record
3982
+ }
3983
+ });
3984
+ const settling = available.status === "ready" ? void 0 : available.status;
3985
+ const offered = settling === void 0 ? available.values : [];
3986
+ const tid = testid ?? name;
3987
+ const resolved = offered.map((o) => {
3988
+ const summary = ns === void 0 ? void 0 : (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${o.value}`)?.summary;
3989
+ return {
3990
+ value: o.value,
3991
+ label: (0, _burojs_react.resolveOptionLabel)(caps, field, o.value, o, enumDef),
3992
+ ...o.icon === void 0 ? {} : { icon: o.icon },
3993
+ ...summary === void 0 ? {} : { summary }
3994
+ };
3995
+ });
3996
+ const raw = value == null || value === "" ? void 0 : String(value);
3997
+ const known = raw === void 0 ? void 0 : options?.find((o) => o.value === raw);
3998
+ const current = raw === void 0 || resolved.some((o) => o.value === raw) ? void 0 : {
3999
+ value: raw,
4000
+ label: (0, _burojs_react.resolveOptionLabel)(caps, field, raw, known, enumDef),
4001
+ ...known?.icon === void 0 ? {} : { icon: known.icon }
4002
+ };
4003
+ if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
4004
+ control,
4005
+ options: resolved,
4006
+ ...current === void 0 ? {} : { current },
4007
+ ...settling === void 0 ? {} : { settling },
4008
+ value,
4009
+ onChange,
4010
+ testid: tid,
4011
+ name,
4012
+ id,
4013
+ required,
4014
+ disabled,
4015
+ ariaInvalid,
4016
+ ariaDescribedBy,
4017
+ ariaErrorMessage,
4018
+ ariaLabelledBy
4019
+ });
3613
4020
  return (0, react_jsx_runtime.jsxs)(require_filter_builder.Select, {
3614
4021
  value: value ?? "",
3615
4022
  onValueChange: onChange,
@@ -3620,20 +4027,39 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3620
4027
  name,
3621
4028
  id,
3622
4029
  "aria-required": required,
4030
+ "aria-busy": settling === "pending" || void 0,
3623
4031
  "aria-invalid": ariaInvalid || void 0,
3624
4032
  "aria-describedby": ariaDescribedBy,
3625
4033
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3626
4034
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3627
- }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: options?.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3628
- value: o.value,
3629
- children: (0, react_jsx_runtime.jsxs)("span", {
3630
- className: "inline-flex items-center gap-1.5",
3631
- children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3632
- name: o.icon,
3633
- className: "size-3.5 shrink-0 text-muted-foreground"
3634
- }) : null, optionLabel(caps, field, o.value, declaredOptionLabel(o, o.value, enumDef))]
3635
- })
3636
- }, o.value)) })]
4035
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [
4036
+ current === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
4037
+ value: current.value,
4038
+ disabled: true,
4039
+ "data-current": "",
4040
+ "data-testid": `${tid}:current`,
4041
+ children: current.label
4042
+ }),
4043
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
4044
+ status: settling,
4045
+ testid: tid
4046
+ }),
4047
+ resolved.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
4048
+ value: o.value,
4049
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
4050
+ description: o.summary === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
4051
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
4052
+ children: o.summary
4053
+ }),
4054
+ children: (0, react_jsx_runtime.jsxs)("span", {
4055
+ className: "inline-flex items-center gap-1.5",
4056
+ children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
4057
+ name: o.icon,
4058
+ className: "size-3.5 shrink-0 text-muted-foreground"
4059
+ }) : null, o.label]
4060
+ })
4061
+ }, o.value))
4062
+ ] })]
3637
4063
  });
3638
4064
  }
3639
4065
  //#endregion
@@ -4054,7 +4480,7 @@ function JsonInput({ name, id, value, onChange, testid, disabled, required, aria
4054
4480
  }
4055
4481
  //#endregion
4056
4482
  //#region src/fields/lazy-relation-many.tsx
4057
- const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-C8zFEjwd.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4483
+ const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-Br-zBHxT.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4058
4484
  function LazyRelationManyInput(props) {
4059
4485
  return (0, react_jsx_runtime.jsx)(react.Suspense, {
4060
4486
  fallback: (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
@@ -4067,8 +4493,8 @@ function LazyRelationManyInput(props) {
4067
4493
  }
4068
4494
  //#endregion
4069
4495
  //#region src/fields/lazy-rich-text.tsx
4070
- const RichTextDisplay = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-vTyVjDoa.cjs")).then((module) => ({ default: module.RichTextDisplay })));
4071
- const RichTextInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-vTyVjDoa.cjs")).then((module) => ({ default: module.RichTextInput })));
4496
+ const RichTextDisplay = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-C_7JCvRo.cjs")).then((module) => ({ default: module.RichTextDisplay })));
4497
+ const RichTextInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-C_7JCvRo.cjs")).then((module) => ({ default: module.RichTextInput })));
4072
4498
  function RichTextDisplayLoading() {
4073
4499
  const t = (0, _burojs_react.useOptionalT)();
4074
4500
  return (0, react_jsx_runtime.jsx)("div", {
@@ -4125,12 +4551,13 @@ function isIdentifier(field) {
4125
4551
  const n = field?.name;
4126
4552
  return n === "id" || typeof n === "string" && n.endsWith("_id");
4127
4553
  }
4128
- function NumberDisplay({ value, field }) {
4554
+ function NumberDisplay({ value, field, text }) {
4129
4555
  const locale = (0, _burojs_react.useOptionalLocale)();
4130
4556
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4131
4557
  className: "text-muted-foreground",
4132
4558
  children: "—"
4133
4559
  });
4560
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
4134
4561
  let raw = value;
4135
4562
  if (typeof raw === "string") raw = unquote(raw);
4136
4563
  const n = typeof raw === "number" ? raw : Number(raw);
@@ -4165,12 +4592,149 @@ function NumberInput({ name, id, value, onChange, testid, placeholder, disabled,
4165
4592
  });
4166
4593
  }
4167
4594
  //#endregion
4595
+ //#region src/fields/object-group.tsx
4596
+ const GROUP = "rounded-md border border-input p-3";
4597
+ function ObjectGroupInput(props) {
4598
+ const { testIds, accessibility, children } = props;
4599
+ return (0, react_jsx_runtime.jsx)("div", {
4600
+ role: "group",
4601
+ "data-buro-object-group": "input",
4602
+ className: require_use_theme.cn(GROUP, "space-y-3"),
4603
+ "data-testid": testIds.input,
4604
+ id: accessibility.input,
4605
+ "aria-labelledby": accessibility.label,
4606
+ "aria-describedby": accessibility.description,
4607
+ "aria-invalid": props.issues.some((issue) => issue.severity === "error" && issue.path.length === 0) || void 0,
4608
+ "aria-errormessage": accessibility.error,
4609
+ children
4610
+ });
4611
+ }
4612
+ function ObjectGroupDisplay(props) {
4613
+ const { testIds, children } = props;
4614
+ return (0, react_jsx_runtime.jsx)("div", {
4615
+ role: "group",
4616
+ "data-buro-object-group": "display",
4617
+ className: require_use_theme.cn(GROUP, "space-y-2"),
4618
+ "data-testid": testIds.display,
4619
+ children
4620
+ });
4621
+ }
4622
+ //#endregion
4623
+ //#region src/fields/repeater.tsx
4624
+ function useRepeaterTexts() {
4625
+ const t = (0, _burojs_react.useChromeT)();
4626
+ return {
4627
+ add: t("field.repeater.add", { defaultValue: "Add" }),
4628
+ empty: t("field.repeater.empty", { defaultValue: "No items yet" }),
4629
+ remove: (position) => t("field.repeater.remove", {
4630
+ params: { position },
4631
+ defaultValue: "Remove item {{position}}"
4632
+ }),
4633
+ moveUp: (position) => t("field.repeater.moveUp", {
4634
+ params: { position },
4635
+ defaultValue: "Move item {{position}} up"
4636
+ }),
4637
+ moveDown: (position) => t("field.repeater.moveDown", {
4638
+ params: { position },
4639
+ defaultValue: "Move item {{position}} down"
4640
+ })
4641
+ };
4642
+ }
4643
+ function RepeaterInput(props) {
4644
+ const texts = useRepeaterTexts();
4645
+ const { value, renderElement, elementKeys, onAdd, onRemove, onMove, testIds, accessibility } = props;
4646
+ const root = testIds.input;
4647
+ const at = (suffix) => root === void 0 ? void 0 : `${root}:${suffix}`;
4648
+ const editable = props.disabled !== true && props.readOnly !== true;
4649
+ const canAdd = editable && onAdd !== void 0 && props.canAdd !== false;
4650
+ const canRemove = editable && onRemove !== void 0 && props.canRemove !== false;
4651
+ const last = value.length - 1;
4652
+ return (0, react_jsx_runtime.jsxs)("div", {
4653
+ role: "group",
4654
+ className: "space-y-2",
4655
+ "data-testid": root,
4656
+ id: accessibility.input,
4657
+ "aria-labelledby": accessibility.label,
4658
+ "aria-describedby": accessibility.description,
4659
+ "aria-errormessage": accessibility.error,
4660
+ children: [value.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
4661
+ className: "text-sm text-muted-foreground",
4662
+ "data-testid": at("empty"),
4663
+ children: texts.empty
4664
+ }) : (0, react_jsx_runtime.jsx)("ol", {
4665
+ className: "space-y-2",
4666
+ children: value.map((_, index) => (0, react_jsx_runtime.jsxs)("li", {
4667
+ className: "flex items-start gap-2 rounded-md border border-input p-3",
4668
+ "data-testid": at(`item:${index}`),
4669
+ children: [(0, react_jsx_runtime.jsx)("div", {
4670
+ className: "min-w-0 flex-1",
4671
+ children: renderElement?.(index)
4672
+ }), onMove === void 0 && onRemove === void 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
4673
+ className: "flex shrink-0 gap-1",
4674
+ children: [onMove === void 0 ? null : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_button.Button, {
4675
+ type: "button",
4676
+ variant: "ghost",
4677
+ size: "icon",
4678
+ "aria-label": texts.moveUp(index + 1),
4679
+ disabled: !editable || index === 0,
4680
+ "data-testid": at(`up:${index}`),
4681
+ onClick: () => onMove(index, index - 1),
4682
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowUp, { "aria-hidden": "true" })
4683
+ }), (0, react_jsx_runtime.jsx)(require_button.Button, {
4684
+ type: "button",
4685
+ variant: "ghost",
4686
+ size: "icon",
4687
+ "aria-label": texts.moveDown(index + 1),
4688
+ disabled: !editable || index === last,
4689
+ "data-testid": at(`down:${index}`),
4690
+ onClick: () => onMove(index, index + 1),
4691
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowDown, { "aria-hidden": "true" })
4692
+ })] }), onRemove === void 0 ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
4693
+ type: "button",
4694
+ variant: "ghost",
4695
+ size: "icon",
4696
+ "aria-label": texts.remove(index + 1),
4697
+ disabled: !canRemove,
4698
+ "data-testid": at(`remove:${index}`),
4699
+ onClick: () => onRemove(index),
4700
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconTrash, { "aria-hidden": "true" })
4701
+ })]
4702
+ })]
4703
+ }, elementKeys?.[index] ?? index))
4704
+ }), onAdd === void 0 ? null : (0, react_jsx_runtime.jsxs)(require_button.Button, {
4705
+ type: "button",
4706
+ variant: "outline",
4707
+ size: "sm",
4708
+ disabled: !canAdd,
4709
+ "data-testid": at("add"),
4710
+ onClick: onAdd,
4711
+ children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconPlus, { "aria-hidden": "true" }), texts.add]
4712
+ })]
4713
+ });
4714
+ }
4715
+ function RepeaterDisplay(props) {
4716
+ const texts = useRepeaterTexts();
4717
+ const { value, renderElement, testIds } = props;
4718
+ if (value.length === 0) return (0, react_jsx_runtime.jsx)("span", {
4719
+ className: "text-muted-foreground",
4720
+ "data-testid": testIds.display,
4721
+ children: texts.empty
4722
+ });
4723
+ return (0, react_jsx_runtime.jsx)("ol", {
4724
+ className: "space-y-2",
4725
+ "data-testid": testIds.display,
4726
+ children: value.map((_, index) => (0, react_jsx_runtime.jsx)("li", {
4727
+ className: "rounded-md border border-input p-3",
4728
+ children: renderElement?.(index)
4729
+ }, index))
4730
+ });
4731
+ }
4732
+ //#endregion
4168
4733
  //#region src/fields/link-keys-display.tsx
4169
4734
  const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4170
- function qualify(name, owner) {
4735
+ function qualify(name) {
4171
4736
  try {
4172
- const namespace = (0, _burojs_core.normalizeEntityRef)(owner).namespace;
4173
- const ref = (0, _burojs_core.normalizeEntityRef)(name, { defaultNamespace: namespace });
4737
+ const ref = (0, _burojs_core.normalizeEntityRef)(name);
4174
4738
  return ref.namespace === "default" ? ref.id : `${ref.namespace}:${ref.id}`;
4175
4739
  } catch {
4176
4740
  return;
@@ -4195,7 +4759,7 @@ function LinkKeysDisplay(props) {
4195
4759
  const ownerDef = owner === "" ? void 0 : app.registry.get(owner);
4196
4760
  const declaration = ownerDef === void 0 ? void 0 : (0, _burojs_core.declaredField)(ownerDef, name);
4197
4761
  const link = isRecord$1(declaration) ? (0, _burojs_core.linkOf)(declaration) : void 0;
4198
- const junctionName = link === void 0 ? void 0 : qualify(link.junction, owner);
4762
+ const junctionName = link === void 0 ? void 0 : qualify(link.junction);
4199
4763
  const junctionDef = junctionName === void 0 ? void 0 : app.registry.get(junctionName);
4200
4764
  const junctionField = (key) => junctionDef === void 0 ? void 0 : (0, _burojs_core.declaredField)(junctionDef, key);
4201
4765
  const ownerField = link === void 0 ? idFieldOf(ownerDef) : byOf(junctionField(link.sourceKey)) ?? idFieldOf(ownerDef);
@@ -4203,11 +4767,11 @@ function LinkKeysDisplay(props) {
4203
4767
  const ownerKey = record?.[ownerField];
4204
4768
  const { keys, complete, isLoading, error } = (0, _burojs_react.useLinkKeys)(owner, name, ownerKey);
4205
4769
  const [missed, setMissed] = (0, react.useState)(() => new Set());
4206
- const onMiss = (0, react.useCallback)((key, miss) => {
4770
+ const onMiss = (0, react.useCallback)((key, isMiss) => {
4207
4771
  setMissed((current) => {
4208
- if (current.has(key) === miss) return current;
4772
+ if (current.has(key) === isMiss) return current;
4209
4773
  const next = new Set(current);
4210
- if (miss) next.add(key);
4774
+ if (isMiss) next.add(key);
4211
4775
  else next.delete(key);
4212
4776
  return next;
4213
4777
  });
@@ -4227,12 +4791,17 @@ function LinkKeysDisplay(props) {
4227
4791
  targetBy
4228
4792
  ]);
4229
4793
  const chipsId = tid.linkChips(owner, name);
4230
- if (error) return (0, react_jsx_runtime.jsx)("span", {
4231
- "data-testid": tid.linkError(owner, name),
4232
- role: "status",
4794
+ if (error) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
4795
+ surface: "relation",
4796
+ error,
4797
+ ...typeof target === "string" ? { resource: target } : {},
4798
+ testId: tid.linkError(owner, name),
4233
4799
  className: "text-destructive text-xs",
4234
- title: error.message,
4235
- children: t("fields.link.failed", { defaultValue: "Links could not be loaded" })
4800
+ attributes: { role: "status" },
4801
+ fallback: {
4802
+ key: "field.link.failed",
4803
+ default: "Links could not be loaded"
4804
+ }
4236
4805
  });
4237
4806
  if (keys === void 0) {
4238
4807
  if (!isLoading) return (0, react_jsx_runtime.jsx)("span", {
@@ -4252,7 +4821,7 @@ function LinkKeysDisplay(props) {
4252
4821
  children: (0, react_jsx_runtime.jsx)("span", {
4253
4822
  "data-testid": tid.linkIncomplete(owner, name),
4254
4823
  className: "text-muted-foreground",
4255
- children: t("fields.link.incomplete", {
4824
+ children: t("field.link.incomplete", {
4256
4825
  count: keys.length,
4257
4826
  defaultValue: "More than {{count}} links"
4258
4827
  })
@@ -4274,7 +4843,7 @@ function LinkKeysDisplay(props) {
4274
4843
  }, String(key))), hidden > 0 ? (0, react_jsx_runtime.jsx)("span", {
4275
4844
  "data-testid": tid.linkHidden(owner, name),
4276
4845
  className: `${chipClassName} text-muted-foreground`,
4277
- children: t("fields.link.hidden", {
4846
+ children: t("field.link.hidden", {
4278
4847
  count: hidden,
4279
4848
  defaultValue: "{{count}} not visible"
4280
4849
  })
@@ -4293,7 +4862,7 @@ function LinkChip({ value, field, onMiss }) {
4293
4862
  const answer = to === void 0 ? void 0 : gate(to, "show");
4294
4863
  if (!(to !== void 0 && answer !== void 0 && answer.state !== "undecided" && answer.state !== "hidden" && answer.state !== "disabled")) return (0, react_jsx_runtime.jsx)("span", {
4295
4864
  className: chipClassName,
4296
- children: (0, react_jsx_runtime.jsx)(require_search_access.RelationDisplay, {
4865
+ children: (0, react_jsx_runtime.jsx)(require_relation_create.RelationDisplay, {
4297
4866
  value,
4298
4867
  field
4299
4868
  })
@@ -4322,7 +4891,7 @@ function ReadChip({ to, value, field, onMiss }) {
4322
4891
  if (miss) return null;
4323
4892
  return (0, react_jsx_runtime.jsx)("span", {
4324
4893
  className: chipClassName,
4325
- children: (0, react_jsx_runtime.jsx)(require_search_access.RelationDisplay, {
4894
+ children: (0, react_jsx_runtime.jsx)(require_relation_create.RelationDisplay, {
4326
4895
  value,
4327
4896
  field
4328
4897
  })
@@ -4344,7 +4913,7 @@ function RelationManyDisplay(props) {
4344
4913
  return (0, react_jsx_runtime.jsx)("span", {
4345
4914
  className: "inline-flex flex-wrap gap-x-2",
4346
4915
  "data-testid": "relation-many-display",
4347
- children: keys.map((key, index) => (0, react_jsx_runtime.jsx)(require_search_access.RelationDisplay, {
4916
+ children: keys.map((key, index) => (0, react_jsx_runtime.jsx)(require_relation_create.RelationDisplay, {
4348
4917
  value: key,
4349
4918
  field
4350
4919
  }, `${String(key)}:${index}`))
@@ -4362,7 +4931,7 @@ const relationMetaSchema = Object.freeze({ "~standard": Object.freeze({
4362
4931
  path: []
4363
4932
  }] };
4364
4933
  const issues = [];
4365
- const { to, by, resolve, searchField, candidates } = value;
4934
+ const { to, by, resolve, searchField, candidates, scope } = value;
4366
4935
  if (to !== void 0 && !(typeof to === "string" && to.length > 0) && !(isRecord(to) && (typeof to.id === "string" || isRecord(to.ref)))) issues.push({
4367
4936
  message: "must be a resource name or reference",
4368
4937
  path: ["to"]
@@ -4383,16 +4952,21 @@ const relationMetaSchema = Object.freeze({ "~standard": Object.freeze({
4383
4952
  message: "must be an array of conditions",
4384
4953
  path: ["candidates"]
4385
4954
  });
4955
+ if (scope !== void 0 && scope !== "context" && scope !== "session" && scope !== "none") issues.push({
4956
+ message: "must be 'context', 'session' or 'none'",
4957
+ path: ["scope"]
4958
+ });
4386
4959
  return issues.length > 0 ? { issues } : { value };
4387
4960
  }
4388
4961
  }) });
4389
4962
  //#endregion
4390
4963
  //#region src/fields/text.tsx
4391
- function TextDisplay({ value }) {
4964
+ function TextDisplay({ value, text: formatted }) {
4392
4965
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4393
4966
  className: "text-muted-foreground",
4394
4967
  children: "—"
4395
4968
  });
4969
+ if (formatted !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: formatted });
4396
4970
  const { text, isStructured } = require_place_node.toDisplayText(value);
4397
4971
  return isStructured ? (0, react_jsx_runtime.jsx)("span", {
4398
4972
  className: "font-mono text-xs break-all",
@@ -4421,23 +4995,26 @@ function TextInput({ name, id, value, onChange, testid, placeholder, disabled, r
4421
4995
  }
4422
4996
  //#endregion
4423
4997
  //#region src/fields/textarea.tsx
4424
- function TextareaDisplay({ value }) {
4998
+ function TextareaDisplay({ value, text: formatted }) {
4425
4999
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4426
5000
  className: "text-muted-foreground",
4427
5001
  children: "—"
4428
5002
  });
4429
- const { text, isStructured } = require_place_node.toDisplayText(value);
5003
+ const { text, isStructured } = formatted === void 0 ? require_place_node.toDisplayText(value) : {
5004
+ text: formatted,
5005
+ isStructured: false
5006
+ };
4430
5007
  return (0, react_jsx_runtime.jsx)("pre", {
4431
5008
  className: isStructured ? "whitespace-pre-wrap break-all font-mono text-xs" : "whitespace-pre-wrap font-sans text-sm",
4432
5009
  children: text
4433
5010
  });
4434
5011
  }
4435
- function CodeDisplay({ value, presentation, testid }) {
5012
+ function CodeDisplay({ value, text: formatted, presentation, testid }) {
4436
5013
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4437
5014
  className: "text-muted-foreground",
4438
5015
  children: "—"
4439
5016
  });
4440
- const { text } = require_place_node.toDisplayText(value);
5017
+ const text = formatted ?? require_place_node.toDisplayText(value).text;
4441
5018
  return (0, react_jsx_runtime.jsx)("pre", {
4442
5019
  "data-testid": testid,
4443
5020
  className: presentation === "plain" ? "overflow-x-auto whitespace-pre font-mono text-xs leading-relaxed" : "overflow-x-auto whitespace-pre rounded-md border bg-muted/40 p-3 font-mono text-xs leading-relaxed",
@@ -4481,14 +5058,14 @@ function TextareaInput({ name, id, value, onChange, testid, placeholder, disable
4481
5058
  //#endregion
4482
5059
  //#region src/fields/default-renderers.ts
4483
5060
  function legacyField(props) {
4484
- const name = typeof props.path.at(-1) === "string" ? props.path.at(-1) : "field";
4485
- const texts = props.field.texts;
5061
+ const name = (0, _burojs_react.optionFieldName)(props.path);
5062
+ const { texts, zone } = props.field;
4486
5063
  return Object.freeze({
4487
5064
  name,
4488
5065
  meta: props.meta,
4489
5066
  ui: props.ui,
4490
- codec: props.field.codec,
4491
- ...texts === void 0 ? {} : { texts }
5067
+ ...texts === void 0 ? {} : { texts },
5068
+ ...zone === void 0 ? {} : { zone }
4492
5069
  });
4493
5070
  }
4494
5071
  function legacyOptions(options, field) {
@@ -4509,6 +5086,7 @@ function display(renderer) {
4509
5086
  return function ShadcnDisplay(props) {
4510
5087
  return (0, react.createElement)(renderer, {
4511
5088
  value: props.value,
5089
+ ...props.text === void 0 ? {} : { text: props.text },
4512
5090
  multiple: props.multiple,
4513
5091
  field: legacyField(props),
4514
5092
  options: legacyOptions(props.options, props.field),
@@ -4546,12 +5124,17 @@ function input(renderer) {
4546
5124
  ariaInvalid: props.issues.some(isErrorIssue),
4547
5125
  ariaDescribedBy: props.accessibility.description,
4548
5126
  ariaErrorMessage: props.accessibility.error,
5127
+ ariaLabelledBy: props.accessibility.label,
4549
5128
  field: legacyField(props),
4550
5129
  resource: props.resource.id,
4551
5130
  record: props.record,
5131
+ values: props.form,
4552
5132
  relationSeeds: props.relationSeeds,
4553
5133
  fixedFilters: props.fixedFilters,
4554
- metaSources: props.metaSources
5134
+ optionSubtitle: props.optionSubtitle,
5135
+ metaSources: props.metaSources,
5136
+ ...props.baseline === void 0 ? {} : { baseline: props.baseline },
5137
+ link: props.link
4555
5138
  });
4556
5139
  };
4557
5140
  }
@@ -4599,9 +5182,40 @@ function scalarOrCollection(renderer, layout) {
4599
5182
  });
4600
5183
  }
4601
5184
  function enumName(ui) {
4602
- const value = ui.enum;
4603
- if (typeof value === "string" && value.length > 0) return value;
4604
- if (value !== null && typeof value === "object" && typeof value.id === "string") return value.id;
5185
+ return (0, _burojs_core_internal.enumBindingKey)(ui.enum);
5186
+ }
5187
+ function RegistryEnumInput(props) {
5188
+ const app = (0, _burojs_react.useOptionalApp)();
5189
+ const meta = props.field.meta;
5190
+ const sources = (0, _burojs_react.useFieldMetaSources)({
5191
+ record: props.record,
5192
+ values: props.form,
5193
+ extra: props.metaSources
5194
+ });
5195
+ const control = resolveEnumControl(props.ui.control, app?.registry.enums.get(props.enumName), `field ${typeof props.path.at(-1) === "string" ? String(props.path.at(-1)) : props.enumName}`);
5196
+ return (0, react.createElement)(EnumPicker, {
5197
+ enumName: props.enumName,
5198
+ control,
5199
+ value: props.value == null ? void 0 : String(props.value),
5200
+ onChange: props.onChange ?? (() => void 0),
5201
+ name: props.accessibility.input,
5202
+ id: props.accessibility.input,
5203
+ testid: props.testIds.input,
5204
+ placeholder: typeof props.ui.placeholder === "string" ? props.ui.placeholder : void 0,
5205
+ disabled: props.disabled,
5206
+ required: props.field.required === true,
5207
+ ariaInvalid: props.issues.some(isErrorIssue),
5208
+ ariaDescribedBy: props.accessibility.description,
5209
+ ariaErrorMessage: props.accessibility.error,
5210
+ ariaLabelledBy: props.accessibility.label,
5211
+ use: {
5212
+ params: (0, _burojs_core_internal.enumParamsOf)(meta?.enumParams),
5213
+ narrow: (0, _burojs_core_internal.narrowEntriesOf)(meta?.narrow),
5214
+ sources,
5215
+ mode: props.record === void 0 ? "create" : "edit",
5216
+ baseline: props.baseline ?? props.record
5217
+ }
5218
+ });
4605
5219
  }
4606
5220
  function enumAware(renderer, layout) {
4607
5221
  const FallbackInput = input(renderer.Input);
@@ -4611,19 +5225,9 @@ function enumAware(renderer, layout) {
4611
5225
  return Object.freeze({
4612
5226
  Input: (props) => {
4613
5227
  const name = enumName(props.ui);
4614
- if (name !== void 0) return (0, react.createElement)(EnumPicker, {
4615
- enumName: name,
4616
- value: props.value == null ? void 0 : String(props.value),
4617
- onChange: props.onChange ?? (() => void 0),
4618
- name: props.accessibility.input,
4619
- id: props.accessibility.input,
4620
- testid: props.testIds.input,
4621
- placeholder: typeof props.ui.placeholder === "string" ? props.ui.placeholder : void 0,
4622
- disabled: props.disabled,
4623
- required: props.field.required === true,
4624
- ariaInvalid: props.issues.some(isErrorIssue),
4625
- ariaDescribedBy: props.accessibility.description,
4626
- ariaErrorMessage: props.accessibility.error
5228
+ if (name !== void 0) return (0, react.createElement)(RegistryEnumInput, {
5229
+ ...props,
5230
+ enumName: name
4627
5231
  });
4628
5232
  if (props.options.length > 0) return (0, react.createElement)(OptionedInput, props);
4629
5233
  return (0, react.createElement)(FallbackInput, props);
@@ -4658,6 +5262,14 @@ const date = {
4658
5262
  Display: DateDisplay,
4659
5263
  Input: DateInput
4660
5264
  };
5265
+ const dateTime = {
5266
+ Display: DateTimeDisplay,
5267
+ Input: DateTimeInput
5268
+ };
5269
+ const time = {
5270
+ Display: TimeDisplay,
5271
+ Input: TimeInput
5272
+ };
4661
5273
  const en = {
4662
5274
  Display: EnumDisplay,
4663
5275
  Input: EnumInput
@@ -4667,7 +5279,7 @@ const ta = {
4667
5279
  Input: TextareaInput
4668
5280
  };
4669
5281
  const rel = {
4670
- Display: require_search_access.RelationDisplay,
5282
+ Display: require_relation_create.RelationDisplay,
4671
5283
  Input: require_relation_picker.RelationPickerInput
4672
5284
  };
4673
5285
  const file = {
@@ -4693,9 +5305,11 @@ const shadcnFieldImplementations = Object.freeze({
4693
5305
  number: scalar(num),
4694
5306
  boolean: scalar(bool),
4695
5307
  date: scalar(date),
4696
- dateTime: scalar(date),
4697
- "date-time": scalar(date),
4698
- "default:date-time": scalar(date),
5308
+ dateTime: scalar(dateTime),
5309
+ "date-time": scalar(dateTime),
5310
+ "default:date-time": scalar(dateTime),
5311
+ time: scalar(time),
5312
+ "default:time": scalar(time),
4699
5313
  enum: enumAware(en),
4700
5314
  json: scalar({
4701
5315
  Display: JsonDisplay,
@@ -4709,316 +5323,19 @@ const shadcnFieldImplementations = Object.freeze({
4709
5323
  richText: scalar(rich, { size: "full" }),
4710
5324
  "rich-text": scalar(rich, { size: "full" }),
4711
5325
  "default:rich-text": scalar(rich, { size: "full" }),
4712
- file: scalarOrCollection(file, { size: "full" })
5326
+ file: scalarOrCollection(file, { size: "full" }),
5327
+ object: Object.freeze({
5328
+ Input: ObjectGroupInput,
5329
+ Display: ObjectGroupDisplay,
5330
+ chrome: true
5331
+ }),
5332
+ array: Object.freeze({
5333
+ CollectionInput: RepeaterInput,
5334
+ CollectionDisplay: RepeaterDisplay,
5335
+ chrome: true
5336
+ })
4713
5337
  });
4714
5338
  //#endregion
4715
- //#region src/fields/use-relation-picker.tsx
4716
- const noop = () => void 0;
4717
- function safeKey(input) {
4718
- if (input === void 0 || input === null) return void 0;
4719
- try {
4720
- return (0, _burojs_core.resourceKey)(input);
4721
- } catch {
4722
- return;
4723
- }
4724
- }
4725
- function sessionIdentity(runtime) {
4726
- const state = runtime.dataSession.getState();
4727
- const snapshot = state.status === "ready" ? state.snapshot : state.target;
4728
- let scopeKey;
4729
- try {
4730
- scopeKey = JSON.stringify(snapshot.scopeKey) ?? "";
4731
- } catch {
4732
- scopeKey = String(snapshot.scopeKey);
4733
- }
4734
- return {
4735
- sessionKey: snapshot.sessionKey,
4736
- scopeKey
4737
- };
4738
- }
4739
- function PickerHost(props) {
4740
- const { register } = props;
4741
- react.useEffect(() => register(), [register]);
4742
- return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: props.children });
4743
- }
4744
- function useRelationPicker(options) {
4745
- const app = (0, _burojs_react.useApp)();
4746
- const runtime = (0, _burojs_react.useDataRuntime)();
4747
- const frame = (0, _burojs_react.useOptionalRecordFrame)();
4748
- const frames = (0, _burojs_react.useRecordScopeFrames)();
4749
- const multiple = options.multiple === true;
4750
- const fieldName = options.field;
4751
- let to;
4752
- let declaredBy;
4753
- let declaredCandidates;
4754
- if (fieldName !== void 0) {
4755
- const meta = ((frame === null ? void 0 : app.registry.get(frame.resource)?.fields)?.[fieldName])?.meta;
4756
- to = safeKey(meta?.to);
4757
- declaredBy = typeof meta?.by === "string" ? meta.by : void 0;
4758
- declaredCandidates = Array.isArray(meta?.candidates) ? meta.candidates : void 0;
4759
- } else to = safeKey(options.to);
4760
- const target = to ?? "";
4761
- const by = options.valueField ?? declaredBy;
4762
- const scope = options.scope ?? "context";
4763
- const selection = require_candidates_gate.useCandidateSelection({
4764
- to,
4765
- candidates: options.candidates ?? declaredCandidates,
4766
- sources: frame?.controller.sources,
4767
- resource: frame?.resource ?? "",
4768
- fieldName: fieldName ?? target,
4769
- fixedFilters: options.fixedFilters
4770
- });
4771
- const held = selection.gate !== void 0;
4772
- const pendingRef = react.useRef(null);
4773
- const [active, setActive] = react.useState(null);
4774
- const activeRef = react.useRef(null);
4775
- activeRef.current = active;
4776
- const rowsRef = react.useRef(new Map());
4777
- const createdRowRef = react.useRef(void 0);
4778
- const alive = react.useRef(true);
4779
- const mounts = react.useRef(0);
4780
- const sequence = react.useRef(0);
4781
- const latest = react.useRef({
4782
- multiple,
4783
- select: options.select,
4784
- idField: "id",
4785
- valueField: "id",
4786
- available: false,
4787
- frames
4788
- });
4789
- const project = react.useCallback((row) => {
4790
- const select = latest.current.select;
4791
- if (select === void 0) return { ...row };
4792
- const out = {};
4793
- const key = row.id !== void 0 ? row.id : row[latest.current.idField];
4794
- if (key !== void 0) out.id = key;
4795
- const { valueField } = latest.current;
4796
- if (Object.hasOwn(row, valueField)) out[valueField] = row[valueField];
4797
- for (const name of select) if (Object.hasOwn(row, name)) out[name] = row[name];
4798
- return out;
4799
- }, []);
4800
- const settle = react.useCallback((result) => {
4801
- const pending = pendingRef.current;
4802
- if (pending === null) return;
4803
- pendingRef.current = null;
4804
- pending.detach();
4805
- if (alive.current) setActive(null);
4806
- pending.resolve(result);
4807
- }, []);
4808
- const toggle = react.useCallback((key, row) => {
4809
- setActive((current) => {
4810
- if (current === null) return current;
4811
- const has = current.selected.some((k) => String(k) === String(key));
4812
- if (has) rowsRef.current.delete(String(key));
4813
- else if (row !== void 0) rowsRef.current.set(String(key), row);
4814
- const selected = has ? current.selected.filter((k) => String(k) !== String(key)) : [...current.selected, key];
4815
- const next = {
4816
- ...current,
4817
- selected
4818
- };
4819
- activeRef.current = next;
4820
- return next;
4821
- });
4822
- }, []);
4823
- const onValue = react.useCallback((value) => {
4824
- const row = createdRowRef.current;
4825
- createdRowRef.current = void 0;
4826
- if (latest.current.multiple) {
4827
- const current = activeRef.current;
4828
- if (current !== null && !current.selected.some((k) => String(k) === String(value))) toggle(value, row);
4829
- return;
4830
- }
4831
- settle({
4832
- kind: "selected",
4833
- keys: [value],
4834
- rows: row === void 0 ? [] : [project(row)]
4835
- });
4836
- }, [
4837
- project,
4838
- settle,
4839
- toggle
4840
- ]);
4841
- const wiring = require_relation_picker.useRelationSelect({
4842
- to: target,
4843
- by,
4844
- fixedFilters: selection.fixedFilters,
4845
- scope,
4846
- ...fieldName === void 0 ? {} : { scopeField: fieldName },
4847
- held,
4848
- onValue
4849
- });
4850
- latest.current = {
4851
- multiple,
4852
- select: options.select,
4853
- idField: wiring.idField,
4854
- valueField: wiring.valueField,
4855
- available: to !== void 0 && wiring.targetDef !== void 0 && !held,
4856
- frames
4857
- };
4858
- const { create: shared } = wiring;
4859
- const create = react.useMemo(() => ({
4860
- ...shared,
4861
- start: (openCreate) => shared.start(() => {
4862
- const opened = openCreate();
4863
- opened.then((row) => {
4864
- createdRowRef.current = row === null ? void 0 : { ...row };
4865
- }, noop);
4866
- return opened;
4867
- })
4868
- }), [shared]);
4869
- react.useEffect(() => runtime.dataSession.subscribe(() => {
4870
- const pending = pendingRef.current;
4871
- if (pending === null) return;
4872
- const now = sessionIdentity(runtime);
4873
- if (now.sessionKey !== pending.sessionKey || now.scopeKey !== pending.scopeKey) settle({
4874
- kind: "cancelled",
4875
- reason: "session-changed"
4876
- });
4877
- }), [runtime, settle]);
4878
- react.useEffect(() => {
4879
- alive.current = true;
4880
- return () => {
4881
- alive.current = false;
4882
- settle({
4883
- kind: "cancelled",
4884
- reason: "unmounted"
4885
- });
4886
- };
4887
- }, [settle]);
4888
- react.useEffect(() => {
4889
- if (held) settle({
4890
- kind: "cancelled",
4891
- reason: "unavailable"
4892
- });
4893
- }, [held, settle]);
4894
- const register = react.useCallback(() => {
4895
- mounts.current += 1;
4896
- return () => {
4897
- mounts.current -= 1;
4898
- if (mounts.current === 0) settle({
4899
- kind: "cancelled",
4900
- reason: "unmounted"
4901
- });
4902
- };
4903
- }, [settle]);
4904
- const open = react.useCallback((opts = {}) => new Promise((resolve) => {
4905
- settle({
4906
- kind: "cancelled",
4907
- reason: "superseded"
4908
- });
4909
- if (mounts.current === 0) {
4910
- if (process.env.NODE_ENV !== "production") console.error("[burojs] useRelationPicker: open() was called but its element is not rendered — render `handle.element` once in your tree.");
4911
- resolve({
4912
- kind: "cancelled",
4913
- reason: "not-mounted"
4914
- });
4915
- return;
4916
- }
4917
- const { signal } = opts;
4918
- if (signal?.aborted === true) {
4919
- resolve({
4920
- kind: "cancelled",
4921
- reason: "aborted"
4922
- });
4923
- return;
4924
- }
4925
- if (!latest.current.available) {
4926
- resolve({
4927
- kind: "cancelled",
4928
- reason: "unavailable"
4929
- });
4930
- return;
4931
- }
4932
- sequence.current += 1;
4933
- const id = sequence.current;
4934
- const onAbort = () => {
4935
- if (pendingRef.current?.id === id) settle({
4936
- kind: "cancelled",
4937
- reason: "aborted"
4938
- });
4939
- };
4940
- signal?.addEventListener("abort", onAbort, { once: true });
4941
- pendingRef.current = {
4942
- id,
4943
- ...sessionIdentity(runtime),
4944
- resolve,
4945
- detach: () => signal?.removeEventListener("abort", onAbort)
4946
- };
4947
- rowsRef.current = new Map();
4948
- createdRowRef.current = void 0;
4949
- const next = {
4950
- id,
4951
- frames: latest.current.frames,
4952
- selected: opts.selected ?? []
4953
- };
4954
- activeRef.current = next;
4955
- setActive(next);
4956
- }), [runtime, settle]);
4957
- const onSelectRow = react.useCallback((row) => {
4958
- const field = wiring.valueField;
4959
- const value = field === "id" ? row.id : row[field];
4960
- if (typeof value !== "string" && typeof value !== "number") return;
4961
- settle({
4962
- kind: "selected",
4963
- keys: [value],
4964
- rows: [project(row)]
4965
- });
4966
- }, [
4967
- wiring.valueField,
4968
- settle,
4969
- project
4970
- ]);
4971
- const onDone = react.useCallback(() => {
4972
- const keys = activeRef.current?.selected ?? [];
4973
- const rows = keys.flatMap((key) => {
4974
- const row = rowsRef.current.get(String(key));
4975
- return row === void 0 ? [] : [project(row)];
4976
- });
4977
- settle({
4978
- kind: "selected",
4979
- keys,
4980
- rows
4981
- });
4982
- }, [settle, project]);
4983
- const onOpenChange = react.useCallback((next) => {
4984
- if (!next) settle({
4985
- kind: "cancelled",
4986
- reason: "dismissed"
4987
- });
4988
- }, [settle]);
4989
- return {
4990
- open,
4991
- element: (0, react_jsx_runtime.jsx)(PickerHost, {
4992
- register,
4993
- children: active === null || held ? null : (0, react_jsx_runtime.jsxs)(_burojs_react.RecordScopeChain, {
4994
- frames: active.frames,
4995
- children: [(0, react_jsx_runtime.jsx)(require_candidates_gate.LazyRelationPickerDialog, {
4996
- to: target,
4997
- open: true,
4998
- onOpenChange,
4999
- onSelect: noop,
5000
- onSelectRow,
5001
- valueField: wiring.valueField,
5002
- ...selection.fixedFilters === void 0 ? {} : { fixedFilters: selection.fixedFilters },
5003
- scope,
5004
- ...fieldName === void 0 ? {} : { scopeField: fieldName },
5005
- ...options.create === void 0 ? {} : {
5006
- create,
5007
- ...options.create.seeds === void 0 ? {} : { createSeeds: options.create.seeds }
5008
- },
5009
- fieldName: fieldName ?? target,
5010
- ...multiple ? {
5011
- multiple: true,
5012
- selected: active.selected,
5013
- onToggle: (value, row) => toggle(value, row),
5014
- onDone
5015
- } : {}
5016
- }), wiring.reader]
5017
- }, active.id)
5018
- })
5019
- };
5020
- }
5021
- //#endregion
5022
5339
  //#region src/forms/declarative-display.tsx
5023
5340
  function DeclarativeDisplay(props) {
5024
5341
  return (0, react_jsx_runtime.jsx)(_burojs_react.ScreenStateProvider, { children: (0, react_jsx_runtime.jsx)(DisplayBody, { ...props }) });
@@ -5044,7 +5361,8 @@ function DisplayBody(props) {
5044
5361
  }
5045
5362
  //#endregion
5046
5363
  //#region src/enum/enum-display.tsx
5047
- function EnumDisplay$1({ enumName, value, variant = "badge", testid, className }) {
5364
+ function EnumDisplay$1({ enumName: enumInput, value, variant = "badge", testid, className }) {
5365
+ const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
5048
5366
  const app = (0, _burojs_react.useApp)();
5049
5367
  const caps = (0, _burojs_react.useI18nCaps)();
5050
5368
  const def = app.registry.enums.get(enumName);
@@ -5092,159 +5410,6 @@ function EnumDisplay$1({ enumName, value, variant = "badge", testid, className }
5092
5410
  });
5093
5411
  }
5094
5412
  //#endregion
5095
- //#region src/data-table/data-table-faceted-filter.tsx
5096
- function DataTableFacetedFilter({ column, title, options = [], loadOptions, selectedLabelFor, searchPlaceholder, emptyText, getTestId, className }) {
5097
- const t = (0, _burojs_react.useOptionalT)();
5098
- const filterValue = column.getFilterValue();
5099
- const selected = (0, react.useMemo)(() => {
5100
- if (Array.isArray(filterValue)) return new Set(filterValue.map(String));
5101
- return new Set();
5102
- }, [filterValue]);
5103
- const [search, setSearch] = (0, react.useState)("");
5104
- const [asyncOptions, setAsyncOptions] = (0, react.useState)([]);
5105
- const [loading, setLoading] = (0, react.useState)(false);
5106
- const debounceRef = (0, react.useRef)(null);
5107
- const loadOptionsRef = (0, react.useRef)(loadOptions);
5108
- (0, react.useEffect)(() => {
5109
- loadOptionsRef.current = loadOptions;
5110
- });
5111
- (0, react.useEffect)(() => {
5112
- if (!loadOptionsRef.current) return;
5113
- setLoading(true);
5114
- if (debounceRef.current !== null) clearTimeout(debounceRef.current);
5115
- let cancelled = false;
5116
- debounceRef.current = setTimeout(() => {
5117
- const loader = loadOptionsRef.current;
5118
- if (!loader) return;
5119
- loader(search).then((results) => {
5120
- if (!cancelled) {
5121
- setAsyncOptions(results);
5122
- setLoading(false);
5123
- }
5124
- }).catch(() => {
5125
- if (!cancelled) setLoading(false);
5126
- });
5127
- }, 250);
5128
- return () => {
5129
- cancelled = true;
5130
- if (debounceRef.current !== null) clearTimeout(debounceRef.current);
5131
- };
5132
- }, [search]);
5133
- const effectiveOptions = loadOptions ? asyncOptions : options;
5134
- const labelFor = (value) => {
5135
- const opt = effectiveOptions.find((o) => o.value === value);
5136
- if (opt) return opt.label;
5137
- return selectedLabelFor?.(value) ?? value;
5138
- };
5139
- const toggle = (value) => {
5140
- const next = new Set(selected);
5141
- if (next.has(value)) next.delete(value);
5142
- else next.add(value);
5143
- column.setFilterValue(next.size === 0 ? void 0 : Array.from(next));
5144
- };
5145
- const selectedValues = Array.from(selected);
5146
- return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, { children: [(0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
5147
- asChild: true,
5148
- children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
5149
- type: "button",
5150
- variant: "outline",
5151
- size: "sm",
5152
- "data-testid": getTestId?.("trigger"),
5153
- className: require_use_theme.cn("h-8 border-dashed", className),
5154
- children: [
5155
- (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCirclePlus, {
5156
- className: "mr-2 h-4 w-4",
5157
- "aria-hidden": "true"
5158
- }),
5159
- title,
5160
- selected.size > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
5161
- (0, react_jsx_runtime.jsx)("span", {
5162
- className: "mx-2 h-4 w-px bg-border",
5163
- "aria-hidden": "true"
5164
- }),
5165
- (0, react_jsx_runtime.jsx)(require_filter_builder.Badge, {
5166
- variant: "secondary",
5167
- className: "rounded-sm px-1 font-normal lg:hidden",
5168
- children: selected.size
5169
- }),
5170
- (0, react_jsx_runtime.jsx)("div", {
5171
- className: "hidden gap-1 lg:flex",
5172
- children: selected.size > 2 ? (0, react_jsx_runtime.jsx)(require_filter_builder.Badge, {
5173
- variant: "secondary",
5174
- className: "rounded-sm px-1 font-normal",
5175
- children: t("table.selectedCount", {
5176
- count: selected.size,
5177
- defaultValue: "{{count}} selected"
5178
- })
5179
- }) : selectedValues.map((value) => (0, react_jsx_runtime.jsx)(require_filter_builder.Badge, {
5180
- variant: "secondary",
5181
- className: "rounded-sm px-1 font-normal",
5182
- children: labelFor(value)
5183
- }, value))
5184
- })
5185
- ] })
5186
- ]
5187
- })
5188
- }), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
5189
- className: "w-[220px] p-0",
5190
- align: "start",
5191
- children: (0, react_jsx_runtime.jsxs)(require_search_access.Command, {
5192
- shouldFilter: !loadOptions,
5193
- children: [
5194
- (0, react_jsx_runtime.jsx)(require_search_access.CommandInput, {
5195
- placeholder: searchPlaceholder ?? title,
5196
- "data-testid": getTestId?.("search"),
5197
- ...loadOptions ? {
5198
- value: search,
5199
- onValueChange: setSearch
5200
- } : {}
5201
- }),
5202
- (0, react_jsx_runtime.jsxs)(require_search_access.CommandList, { children: [
5203
- loading && (0, react_jsx_runtime.jsx)("div", {
5204
- className: "py-6 text-center text-sm text-muted-foreground",
5205
- children: t("list.loadingShort", { defaultValue: "Loading…" })
5206
- }),
5207
- (0, react_jsx_runtime.jsx)(require_search_access.CommandEmpty, { children: emptyText ?? t("relation.noResults", { defaultValue: "No results." }) }),
5208
- (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, { children: effectiveOptions.map((opt) => {
5209
- const isSelected = selected.has(opt.value);
5210
- const Icon = opt.icon;
5211
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
5212
- value: opt.label,
5213
- "data-testid": getTestId?.("option", opt.value),
5214
- role: "option",
5215
- "aria-selected": isSelected,
5216
- "aria-checked": isSelected,
5217
- onSelect: () => toggle(opt.value),
5218
- children: [
5219
- (0, react_jsx_runtime.jsx)("span", {
5220
- className: require_use_theme.cn("mr-2 flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border", isSelected ? "border-primary bg-primary text-primary-foreground" : "border-input opacity-50"),
5221
- "aria-hidden": "true",
5222
- children: isSelected && (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, { className: "h-3.5 w-3.5" })
5223
- }),
5224
- Icon && (0, react_jsx_runtime.jsx)(Icon, {
5225
- className: "mr-2 h-4 w-4 text-muted-foreground",
5226
- "aria-hidden": "true"
5227
- }),
5228
- (0, react_jsx_runtime.jsx)("span", {
5229
- className: "flex-1 text-left",
5230
- children: opt.label
5231
- })
5232
- ]
5233
- }, opt.value);
5234
- }) })
5235
- ] }),
5236
- selected.size > 0 && (0, react_jsx_runtime.jsx)("button", {
5237
- type: "button",
5238
- "data-testid": getTestId?.("clear"),
5239
- onClick: () => column.setFilterValue(void 0),
5240
- className: "flex w-full items-center justify-center border-t px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
5241
- children: t("filters.clearAll", { defaultValue: "Clear filters" })
5242
- })
5243
- ]
5244
- })
5245
- })] });
5246
- }
5247
- //#endregion
5248
5413
  //#region src/data-table/data-table-text-filter.tsx
5249
5414
  function DataTableTextFilter({ column, placeholder, testid, className }) {
5250
5415
  const external = column.getFilterValue() ?? "";
@@ -5280,7 +5445,7 @@ function DataTableTextFilter({ column, placeholder, testid, className }) {
5280
5445
  //#endregion
5281
5446
  //#region src/data-table/data-table-enum-filter.tsx
5282
5447
  function DataTableEnumFilter({ column, title, options, getTestId, className }) {
5283
- return (0, react_jsx_runtime.jsx)(DataTableFacetedFilter, {
5448
+ return (0, react_jsx_runtime.jsx)(require_filter_builder.DataTableFacetedFilter, {
5284
5449
  column,
5285
5450
  title,
5286
5451
  options,
@@ -5398,14 +5563,15 @@ const OPERATOR_LABELS = {
5398
5563
  has: "has",
5399
5564
  hasAny: "has any of",
5400
5565
  hasAll: "has all of",
5401
- hasNone: "has none of"
5566
+ hasNone: "has none of",
5567
+ some: "has an item where"
5402
5568
  };
5403
- function formatOperatorLabel(op, t) {
5404
- return t ? t(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
5569
+ function formatOperatorLabel(op, chromeT) {
5570
+ return chromeT ? chromeT(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
5405
5571
  }
5406
5572
  function useOperatorLabel() {
5407
- const t = (0, _burojs_react.useOptionalT)();
5408
- return (op) => formatOperatorLabel(op, t);
5573
+ const chromeT = (0, _burojs_react.useChromeT)();
5574
+ return (op) => formatOperatorLabel(op, chromeT);
5409
5575
  }
5410
5576
  function isEmpty(v) {
5411
5577
  return v === void 0 || v === null || v === "";
@@ -5499,7 +5665,7 @@ function DataTableOperatorFilter({ column, operators, defaultOperator, valueKind
5499
5665
  //#region src/data-table/data-table-row-actions.tsx
5500
5666
  function DataTableRowActions({ row, actions, getTestId, className }) {
5501
5667
  const [open, setOpen] = (0, react.useState)(false);
5502
- const t = (0, _burojs_react.useOptionalT)();
5668
+ const chromeT = (0, _burojs_react.useChromeT)();
5503
5669
  if (actions.length === 0) return null;
5504
5670
  return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, {
5505
5671
  open,
@@ -5517,7 +5683,7 @@ function DataTableRowActions({ row, actions, getTestId, className }) {
5517
5683
  "aria-hidden": "true"
5518
5684
  }), (0, react_jsx_runtime.jsx)("span", {
5519
5685
  className: "sr-only",
5520
- children: t("actions.openMenu", { defaultValue: "Open row actions menu" })
5686
+ children: chromeT("actions.openMenu", { defaultValue: "Open row actions menu" })
5521
5687
  })]
5522
5688
  })
5523
5689
  }), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
@@ -5629,7 +5795,7 @@ function BlockScreen({ block, props, resource, record, label }) {
5629
5795
  snapshot
5630
5796
  ]);
5631
5797
  if (compiled === void 0) return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, { className: "h-24 w-full" });
5632
- if ((0, _burojs_core.isScreenFailure)(compiled)) return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "error" });
5798
+ if ((0, _burojs_core.isScreenFailure)(compiled)) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "error" });
5633
5799
  return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
5634
5800
  value: null,
5635
5801
  children: (0, react_jsx_runtime.jsx)("div", {
@@ -5638,7 +5804,8 @@ function BlockScreen({ block, props, resource, record, label }) {
5638
5804
  children: (0, react_jsx_runtime.jsx)(require_resource_page_router.PlannedBody, {
5639
5805
  screen: compiled,
5640
5806
  name: "modal",
5641
- label: label ?? ""
5807
+ label: label ?? "",
5808
+ ...needsRow && row !== null ? { record: row } : {}
5642
5809
  })
5643
5810
  })
5644
5811
  });
@@ -5647,13 +5814,20 @@ function relation(field) {
5647
5814
  if (field === null || typeof field !== "object") return false;
5648
5815
  return (0, _burojs_core.isRelationField)(field);
5649
5816
  }
5817
+ const resolveOf = (bag) => bag !== null && typeof bag === "object" ? bag.resolve : void 0;
5818
+ function lazyToOne(field) {
5819
+ const entry = field;
5820
+ if (entry.kind === "relationMany" || entry.type === "array") return false;
5821
+ return (resolveOf(entry.meta) ?? resolveOf(entry.opts)) === "lazy";
5822
+ }
5650
5823
  function peekFields(def, columns, capabilityFor, fieldVisible = () => true) {
5651
5824
  const record = new Set((0, _burojs_core.dtoFields)(def, "record"));
5652
5825
  const out = [];
5653
5826
  for (const name of columns) {
5654
5827
  if (out.length === 5) break;
5655
5828
  if (name === def.displayField || out.includes(name) || !record.has(name)) continue;
5656
- if (!require_place_node.peekLeafAllowed(def, name, capabilityFor, fieldVisible) || relation(require_place_node.peekFieldDefinition(def, name))) continue;
5829
+ const field = require_place_node.peekFieldDefinition(def, name);
5830
+ if (!require_place_node.peekLeafAllowed(def, name, capabilityFor, fieldVisible) || relation(field) && !lazyToOne(field)) continue;
5657
5831
  out.push(name);
5658
5832
  }
5659
5833
  return Object.freeze(out);
@@ -5669,7 +5843,7 @@ function failure(error, retry) {
5669
5843
  };
5670
5844
  }
5671
5845
  function PeekScreen(props) {
5672
- return (0, react_jsx_runtime.jsx)(require_search_access.PeekContext.Provider, {
5846
+ return (0, react_jsx_runtime.jsx)(require_relation_create.PeekContext.Provider, {
5673
5847
  value: true,
5674
5848
  children: props.by !== void 0 ? (0, react_jsx_runtime.jsx)(PeekByKey, {
5675
5849
  target: props.target,
@@ -5736,7 +5910,7 @@ function PeekByKey({ target, by }) {
5736
5910
  } else if (query.error != null) read = failure(query.error, () => void query.refetch());
5737
5911
  else read = { state: "pending" };
5738
5912
  (0, react.useEffect)(() => {
5739
- if (read.state === "ambiguous" && process.env.NODE_ENV !== "production") console.error(`[burojs] ${(0, _burojs_core.relationAmbiguousError)(target, by.field, by.key).message}`);
5913
+ if (read.state === "ambiguous" && process.env.NODE_ENV !== "production") console.error(`[burojs] ${require_toaster.technicalText((0, _burojs_core.relationAmbiguousError)(target, by.field, by.key))}`);
5740
5914
  }, [
5741
5915
  read.state,
5742
5916
  target,
@@ -5752,6 +5926,7 @@ function PeekByKey({ target, by }) {
5752
5926
  function PeekBody({ target, peekKey, read }) {
5753
5927
  const tid = (0, _burojs_react.useTestIds)();
5754
5928
  const t = (0, _burojs_react.useOptionalT)();
5929
+ const chromeT = (0, _burojs_react.useChromeT)();
5755
5930
  const testid = tid.peek(target, peekKey);
5756
5931
  if (read.state === "pending") return (0, react_jsx_runtime.jsx)("div", {
5757
5932
  "data-testid": testid,
@@ -5779,7 +5954,7 @@ function PeekBody({ target, peekKey, read }) {
5779
5954
  variant: "outline",
5780
5955
  "data-testid": `${testid}:retry`,
5781
5956
  onClick: read.retry,
5782
- children: t("actions.retry", { defaultValue: "Retry" })
5957
+ children: chromeT("actions.retry", { defaultValue: "Retry" })
5783
5958
  })]
5784
5959
  });
5785
5960
  if (read.state === "unavailable") return (0, react_jsx_runtime.jsx)("p", {
@@ -5862,7 +6037,7 @@ function PeekRecord({ target, testid, row }) {
5862
6037
  capabilityFor,
5863
6038
  fieldVisible
5864
6039
  ]);
5865
- const host = (0, react.useContext)(require_search_access.PeekHostContext);
6040
+ const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5866
6041
  const instance = (0, _burojs_react.useUIInstance)();
5867
6042
  const quickOpen = (0, _burojs_react.useQuickOpener)();
5868
6043
  const rowId = rowIdOf(def, row);
@@ -5870,9 +6045,9 @@ function PeekRecord({ target, testid, row }) {
5870
6045
  const open = (0, react.useCallback)(() => {
5871
6046
  if (!openable) return;
5872
6047
  const anchor = host?.anchor ?? null;
5873
- const anchorOpen = require_search_access.peekAnchorOpener(anchor);
6048
+ const anchorOpen = require_relation_create.peekAnchorOpener(anchor);
5874
6049
  instance.dismiss();
5875
- if (anchor?.isConnected) require_search_access.focusWithoutPeek(anchor);
6050
+ if (anchor?.isConnected) require_relation_create.focusWithoutPeek(anchor);
5876
6051
  if (anchorOpen !== void 0) anchorOpen(target, String(rowId));
5877
6052
  else quickOpen(target, String(rowId));
5878
6053
  }, [
@@ -5921,8 +6096,9 @@ function PeekRecord({ target, testid, row }) {
5921
6096
  });
5922
6097
  }
5923
6098
  function DeclaredPeekBody({ target, testid, record, frameRecord, def, capabilityFor, fieldVisible, view: View, builtin, open, openable, t }) {
5924
- const host = (0, react.useContext)(require_search_access.PeekHostContext);
5925
- const title = require_search_access.recordDisplayName(record, def?.displayField);
6099
+ const host = (0, react.useContext)(require_relation_create.PeekHostContext);
6100
+ const title = require_relation_create.recordDisplayName(record, def?.displayField);
6101
+ const subtitle = require_use_record_subtitle.useRecordSubtitle(target)(record) ?? void 0;
5926
6102
  const setLabel = host?.setLabel;
5927
6103
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5928
6104
  const controller = (0, _burojs_react.useFormController)({
@@ -5958,6 +6134,7 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5958
6134
  children: [builtin ? (0, react_jsx_runtime.jsx)(PeekTitle, {
5959
6135
  testid,
5960
6136
  title,
6137
+ subtitle,
5961
6138
  open: openable ? open : void 0
5962
6139
  }) : null, (0, react_jsx_runtime.jsx)(react.Suspense, {
5963
6140
  fallback: null,
@@ -5970,11 +6147,26 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5970
6147
  })]
5971
6148
  });
5972
6149
  }
5973
- function PeekTitle({ testid, title, open }) {
5974
- if (open === void 0) return (0, react_jsx_runtime.jsx)("p", {
6150
+ function PeekTitle({ testid, title, subtitle, open }) {
6151
+ const heading = open === void 0 ? (0, react_jsx_runtime.jsx)("p", {
5975
6152
  className: "text-sm font-semibold",
5976
6153
  children: title
6154
+ }) : (0, react_jsx_runtime.jsx)(PeekTitleButton, {
6155
+ testid,
6156
+ title,
6157
+ open
5977
6158
  });
6159
+ if (subtitle === void 0) return heading;
6160
+ return (0, react_jsx_runtime.jsxs)("div", {
6161
+ className: "flex flex-col gap-0.5",
6162
+ children: [heading, (0, react_jsx_runtime.jsx)("p", {
6163
+ "data-testid": `${testid}:subtitle`,
6164
+ className: "text-xs text-muted-foreground",
6165
+ children: subtitle
6166
+ })]
6167
+ });
6168
+ }
6169
+ function PeekTitleButton({ testid, title, open }) {
5978
6170
  return (0, react_jsx_runtime.jsx)("button", {
5979
6171
  type: "button",
5980
6172
  "data-testid": `${testid}:title`,
@@ -5993,7 +6185,7 @@ function DefaultPeekBody({ target, testid, row, open }) {
5993
6185
  namespace: "default",
5994
6186
  id: target
5995
6187
  };
5996
- const host = (0, react.useContext)(require_search_access.PeekHostContext);
6188
+ const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5997
6189
  const caps = (0, _burojs_react.useI18nCaps)(target);
5998
6190
  const capabilityFor = (0, _burojs_react.useCapabilityResolver)(target, row, "show");
5999
6191
  const projection = useRecordProjection(target);
@@ -6001,13 +6193,15 @@ function DefaultPeekBody({ target, testid, row, open }) {
6001
6193
  const access = (0, _burojs_react.useFieldAccess)(target, "record", dtoRow);
6002
6194
  const projected = (0, _burojs_react.useProjectedRecord)(target, dtoRow);
6003
6195
  const record = projected.value ?? {};
6004
- const title = require_search_access.recordDisplayName(record, def?.displayField);
6196
+ const title = require_relation_create.recordDisplayName(record, def?.displayField);
6197
+ const subtitleOf = require_use_record_subtitle.useRecordSubtitle(target);
6198
+ const subtitle = projected.status === "ready" ? subtitleOf(record) ?? void 0 : void 0;
6005
6199
  const setLabel = host?.setLabel;
6006
6200
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
6007
6201
  const columns = (0, react.useMemo)(() => {
6008
6202
  if (def === void 0) return [];
6009
6203
  const listed = def.views?.list?.columns;
6010
- return peekFields(def, listed ?? Object.keys(def.fields), capabilityFor, (name) => access[name]?.view === "visible");
6204
+ return peekFields(def, listed?.map(_burojs_core.columnName) ?? Object.keys(def.fields), capabilityFor, (name) => access[name]?.view === "visible");
6011
6205
  }, [
6012
6206
  def,
6013
6207
  capabilityFor,
@@ -6033,6 +6227,7 @@ function DefaultPeekBody({ target, testid, row, open }) {
6033
6227
  children: [(0, react_jsx_runtime.jsx)(PeekTitle, {
6034
6228
  testid,
6035
6229
  title,
6230
+ subtitle,
6036
6231
  open
6037
6232
  }), columns.length === 0 ? null : (0, react_jsx_runtime.jsx)("dl", {
6038
6233
  className: "grid gap-1.5",
@@ -6047,13 +6242,21 @@ function DefaultPeekBody({ target, testid, row, open }) {
6047
6242
  children: (0, _burojs_core.resolveFieldLabel)(caps, name, (0, _burojs_core.declaredText)("field", field, "label"))
6048
6243
  }), (0, react_jsx_runtime.jsx)("dd", {
6049
6244
  className: "min-w-0 break-words",
6050
- children: (0, react_jsx_runtime.jsx)(require_place_node.ResolvedFieldDisplay, {
6051
- resource: ref,
6052
- name,
6053
- field,
6245
+ children: (0, react_jsx_runtime.jsx)(require_place_node.FieldValueFrame, {
6246
+ field: {
6247
+ ...field,
6248
+ name
6249
+ },
6054
6250
  value,
6055
- record,
6056
- fallback: require_place_node.toDisplayText(value).text
6251
+ surface: "display",
6252
+ children: (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldDisplay, {
6253
+ resource: ref,
6254
+ name,
6255
+ field,
6256
+ value,
6257
+ record,
6258
+ fallback: require_place_node.toDisplayText(value).text
6259
+ })
6057
6260
  })
6058
6261
  })]
6059
6262
  }, name);
@@ -6075,41 +6278,50 @@ function QuickBodyOf({ entry }) {
6075
6278
  entry,
6076
6279
  route: EMPTY_ROUTE
6077
6280
  });
6078
- if (entry.recordId === void 0 || entry.recordId === "") return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "not-found" });
6079
- return (0, react_jsx_runtime.jsx)(QuickRead, {
6281
+ if (entry.recordId === void 0 || entry.recordId === "") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
6282
+ return (0, react_jsx_runtime.jsx)(QuickReadRoute, {
6080
6283
  entry,
6081
6284
  recordId: entry.recordId
6082
6285
  });
6083
6286
  }
6084
- function QuickRead({ entry, recordId }) {
6287
+ function QuickReadRoute({ entry, recordId }) {
6288
+ const typed = (0, _burojs_react.useRouteRecordId)(entry.resource, recordId);
6289
+ if (typed === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.InvalidRouteId, { resource: entry.resource });
6290
+ return (0, react_jsx_runtime.jsx)(QuickRead, {
6291
+ entry,
6292
+ recordId,
6293
+ typedId: typed
6294
+ });
6295
+ }
6296
+ function QuickRead({ entry, recordId, typedId }) {
6085
6297
  const def = (0, _burojs_react.useApp)().registry.get(entry.resource);
6086
6298
  const projection = (0, react.useMemo)(() => def === void 0 ? void 0 : (0, _burojs_core.dtoFields)(def, "record"), [def]);
6087
6299
  const query = (0, _burojs_react.useOne)(entry.resource, {
6088
- id: recordId,
6300
+ id: typedId,
6089
6301
  retry: _burojs_react.retryRecordRead,
6090
6302
  ...projection === void 0 ? {} : { projection }
6091
6303
  });
6092
6304
  const result = query.data;
6093
6305
  if (result !== void 0) {
6094
6306
  const row = result.data;
6095
- if (row === null || typeof row !== "object") return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "not-found" });
6307
+ if (row === null || typeof row !== "object") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
6096
6308
  return (0, react_jsx_runtime.jsx)(QuickLoaded, {
6097
6309
  entry,
6098
6310
  recordId,
6311
+ typedId,
6099
6312
  row,
6100
6313
  isCurrentData: !query.isPlaceholderData
6101
6314
  });
6102
6315
  }
6103
- if (query.error != null) {
6104
- const state = require_resource_page_router.recordErrorState(query.error);
6105
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, {
6106
- state,
6107
- ...state === "error" ? { onRetry: () => void query.refetch() } : {}
6108
- });
6109
- }
6110
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "loading" });
6316
+ if (query.error != null) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
6317
+ surface: "record",
6318
+ resource: entry.resource,
6319
+ error: query.error,
6320
+ retry: () => void query.refetch()
6321
+ });
6322
+ return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
6111
6323
  }
6112
- function QuickLoaded({ entry, recordId, row, isCurrentData }) {
6324
+ function QuickLoaded({ entry, recordId, typedId, row, isCurrentData }) {
6113
6325
  const gate = (0, _burojs_react.useEntryGate)();
6114
6326
  const quick = (0, _burojs_react.useQuickEntry)();
6115
6327
  const answer = gate(entry.resource, entry.mode === "edit" ? "edit" : "show", row);
@@ -6125,20 +6337,20 @@ function QuickLoaded({ entry, recordId, row, isCurrentData }) {
6125
6337
  title
6126
6338
  ]);
6127
6339
  const route = (0, react.useMemo)(() => Object.freeze({ id: recordId }), [recordId]);
6128
- if (answer.state === "undecided") return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "loading" });
6129
- if (!open) return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "not-found" });
6340
+ if (answer.state === "undecided") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
6341
+ if (!open) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
6130
6342
  return (0, react_jsx_runtime.jsx)(QuickScreenOf, {
6131
6343
  entry,
6132
- route
6344
+ route,
6345
+ recordId: typedId
6133
6346
  });
6134
6347
  }
6135
6348
  function canonicalOrNull(name) {
6136
- if (typeof name !== "string") return null;
6137
6349
  try {
6138
- return require_check_confirm_dialog.canonicalResourceName(name);
6139
- } catch {
6140
- return null;
6141
- }
6350
+ if (typeof name === "string") return require_check_confirm_dialog.canonicalResourceName(name);
6351
+ if (name !== null && typeof name === "object") return (0, _burojs_core.routeResourceKey)(name);
6352
+ } catch {}
6353
+ return null;
6142
6354
  }
6143
6355
  function absorbedRedirect(to, entry) {
6144
6356
  if (typeof to !== "object" || to === null) return null;
@@ -6152,7 +6364,7 @@ function closeEntry(quick, dismiss) {
6152
6364
  if (quick.stack.entries.length > 1) quick.stack.pop();
6153
6365
  else dismiss(quick.presentationId);
6154
6366
  }
6155
- function QuickScreenOf({ entry, route }) {
6367
+ function QuickScreenOf({ entry, route, recordId }) {
6156
6368
  const quick = (0, _burojs_react.useQuickEntry)();
6157
6369
  const instance = (0, _burojs_react.useUIInstance)();
6158
6370
  const runtime = (0, _burojs_react.useUIPresentationRuntime)();
@@ -6204,7 +6416,7 @@ function QuickScreenOf({ entry, route }) {
6204
6416
  children: (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordScreen, {
6205
6417
  resource: entry.resource,
6206
6418
  mode: entry.mode,
6207
- ...entry.recordId === void 0 ? {} : { recordId: entry.recordId },
6419
+ ...recordId === void 0 ? {} : { recordId },
6208
6420
  ...entry.defaults === void 0 ? {} : { defaults: entry.defaults },
6209
6421
  ...entry.input === void 0 ? {} : { input: entry.input },
6210
6422
  ...callbacks
@@ -6226,7 +6438,7 @@ function useEntryTitle(entry) {
6226
6438
  const caps = (0, _burojs_react.useI18nCaps)(entry.resource);
6227
6439
  const t = (0, _burojs_react.useOptionalT)();
6228
6440
  if (entry.mode !== "create") return entry.title ?? "";
6229
- return t("pageHeader.createTitle", { params: { label: (0, _burojs_core.resolveResourceLabel)(caps, entry.resource, "single", app.registry.get(entry.resource)) } });
6441
+ return require_place_node.resolveResourceTitle(caps, t, entry.resource, "createTitle", { label: (0, _burojs_core.resolveResourceLabel)(caps, entry.resource, "single", app.registry.get(entry.resource)) });
6230
6442
  }
6231
6443
  const HEADING_CLASS = "min-w-0 flex-1 break-words text-lg font-semibold tracking-tight focus-visible:outline-hidden";
6232
6444
  function QuickHeader({ entries }) {
@@ -6236,7 +6448,7 @@ function QuickHeader({ entries }) {
6236
6448
  const t = (0, _burojs_react.useOptionalT)();
6237
6449
  const tid = (0, _burojs_react.useTestIds)();
6238
6450
  const RouterLink = require_toaster.useLinkComponent();
6239
- const ownTitle = (0, react.useContext)(require_shell.OwnTitleContext);
6451
+ const ownTitle = (0, react.useContext)(require_check_confirm_dialog.OwnTitleContext);
6240
6452
  const top = entries[entries.length - 1];
6241
6453
  const previous = entries.length > 1 ? entries[entries.length - 2] : void 0;
6242
6454
  const title = useEntryTitle(top);
@@ -6372,7 +6584,7 @@ function wrapperEnabled(options) {
6372
6584
  //#region src/ui-presentations/dialog-host.tsx
6373
6585
  function DialogPresentationHost({ component: Component, props, options }) {
6374
6586
  const instance = (0, _burojs_react.useUIInstance)();
6375
- return (0, react_jsx_runtime.jsx)(require_shell.DialogPresentationShell, {
6587
+ return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DialogPresentationShell, {
6376
6588
  dismiss: instance.dismiss,
6377
6589
  wrapper: wrapperEnabled(options),
6378
6590
  ownTitle: options.ownTitle === true,
@@ -6453,7 +6665,7 @@ function PopoverPresentationHost({ component: Component, props, options, anchor
6453
6665
  onCloseAutoFocus: (event) => event.preventDefault(),
6454
6666
  onPointerEnter: hold,
6455
6667
  onPointerLeave: release,
6456
- children: (0, react_jsx_runtime.jsx)(require_search_access.PeekHostContext.Provider, {
6668
+ children: (0, react_jsx_runtime.jsx)(require_relation_create.PeekHostContext.Provider, {
6457
6669
  value: host,
6458
6670
  children: (0, react_jsx_runtime.jsx)(Component, { ...props })
6459
6671
  })
@@ -6465,7 +6677,7 @@ PopoverPresentationHost.optionsSchema = Object.freeze({ title: "string" });
6465
6677
  //#region src/ui-presentations/sheet-host.tsx
6466
6678
  function SheetPresentationHost({ component: Component, props, options }) {
6467
6679
  const instance = (0, _burojs_react.useUIInstance)();
6468
- return (0, react_jsx_runtime.jsx)(require_shell.SheetPresentationShell, {
6680
+ return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.SheetPresentationShell, {
6469
6681
  dismiss: instance.dismiss,
6470
6682
  wrapper: wrapperEnabled(options),
6471
6683
  ownTitle: options.ownTitle === true,
@@ -6483,11 +6695,25 @@ SheetPresentationHost.optionsSchema = Object.freeze({
6483
6695
  //#region src/ui-presentations/index.tsx
6484
6696
  function FlowScreen(props) {
6485
6697
  const loaded = require_check_confirm_dialog.useLoaded(require_check_confirm_dialog.loadFlowScreen);
6486
- if (loaded.error !== void 0) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, { onRetry: loaded.retry });
6487
- if (loaded.module === void 0) return null;
6698
+ if (loaded.error !== void 0) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, {
6699
+ label: props.label,
6700
+ onRetry: loaded.retry
6701
+ });
6702
+ if (loaded.module === void 0) return (0, react_jsx_runtime.jsxs)("div", {
6703
+ "data-buro-flow-step": "loading",
6704
+ "aria-busy": "true",
6705
+ className: "flex flex-col gap-4",
6706
+ children: [(0, react_jsx_runtime.jsx)(require_check_confirm_dialog.OwnTitleHeading, { label: props.label }), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
6707
+ className: "h-5 w-5 animate-spin self-center",
6708
+ "aria-hidden": "true"
6709
+ })]
6710
+ });
6488
6711
  const Screen = loaded.module.FlowScreen;
6489
6712
  return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowBoundary, {
6490
- fallback: (_error, reset) => (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, { onRetry: reset }),
6713
+ fallback: (_error, reset) => (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, {
6714
+ label: props.label,
6715
+ onRetry: reset
6716
+ }),
6491
6717
  children: (0, react_jsx_runtime.jsx)(Screen, { ...props })
6492
6718
  });
6493
6719
  }
@@ -6762,9 +6988,13 @@ function DefaultCommandPalette({ open, onOpenChange, actions, children }) {
6762
6988
  }
6763
6989
  //#endregion
6764
6990
  //#region src/shell/app-shell.tsx
6765
- function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel, children }) {
6991
+ function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel, navChrome, children }) {
6766
6992
  const enabled = palette !== false;
6767
- const { open, setOpen } = (0, _burojs_react.useCommandPalette)({ disableShortcut: !enabled });
6993
+ const { open, setOpen, toggle } = (0, _burojs_react.useCommandPalette)();
6994
+ (0, _burojs_react_web.useGlobalShortcut)({
6995
+ key: "k",
6996
+ mod: true
6997
+ }, toggle, { enabled });
6768
6998
  const paletteState = (0, react.useMemo)(() => ({
6769
6999
  open,
6770
7000
  setOpen
@@ -6782,7 +7012,7 @@ function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel,
6782
7012
  sidebar: fill(sidebar, () => (0, react_jsx_runtime.jsx)(AppSidebar, {})),
6783
7013
  header: fill(header, () => (0, react_jsx_runtime.jsx)(AppHeader, {})),
6784
7014
  ...docPanel !== void 0 ? { docPanel } : {},
6785
- children
7015
+ children: navChrome === false ? children : (0, react_jsx_runtime.jsx)(NavChrome, { children })
6786
7016
  }), paletteNode]
6787
7017
  });
6788
7018
  }
@@ -6932,14 +7162,14 @@ exports.Collapsible = Collapsible;
6932
7162
  exports.CollapsibleContent = CollapsibleContent;
6933
7163
  exports.CollapsibleTrigger = CollapsibleTrigger;
6934
7164
  exports.ColumnsToggle = require_place_node.ColumnsToggle;
6935
- exports.Command = require_search_access.Command;
6936
- exports.CommandDialog = require_search_access.CommandDialog;
6937
- exports.CommandEmpty = require_search_access.CommandEmpty;
6938
- exports.CommandGroup = require_search_access.CommandGroup;
6939
- exports.CommandInput = require_search_access.CommandInput;
6940
- exports.CommandItem = require_search_access.CommandItem;
6941
- exports.CommandList = require_search_access.CommandList;
6942
- exports.CommandLoading = require_search_access.CommandLoading;
7165
+ exports.Command = require_relation_create.Command;
7166
+ exports.CommandDialog = require_relation_create.CommandDialog;
7167
+ exports.CommandEmpty = require_relation_create.CommandEmpty;
7168
+ exports.CommandGroup = require_relation_create.CommandGroup;
7169
+ exports.CommandInput = require_relation_create.CommandInput;
7170
+ exports.CommandItem = require_relation_create.CommandItem;
7171
+ exports.CommandList = require_relation_create.CommandList;
7172
+ exports.CommandLoading = require_relation_create.CommandLoading;
6943
7173
  exports.CommandPalette = CommandPalette;
6944
7174
  exports.CommandPaletteActionsGroup = CommandPaletteActionsGroup;
6945
7175
  exports.CommandPaletteCreateGroup = CommandPaletteCreateGroup;
@@ -6948,7 +7178,7 @@ exports.CommandPaletteNavigationGroups = CommandPaletteNavigationGroups;
6948
7178
  exports.CommandPaletteRecentGroup = CommandPaletteRecentGroup;
6949
7179
  exports.CommandPaletteRecordsGroup = CommandPaletteRecordsGroup;
6950
7180
  exports.CommandPaletteTrigger = CommandPaletteTrigger;
6951
- exports.CommandSeparator = require_search_access.CommandSeparator;
7181
+ exports.CommandSeparator = require_relation_create.CommandSeparator;
6952
7182
  exports.ContextPicker = ContextPicker;
6953
7183
  exports.CopyId = require_place_node.CopyId;
6954
7184
  exports.CreateButton = require_place_node.CreateButton;
@@ -6957,7 +7187,7 @@ exports.DEFAULT_LANGUAGE_STORAGE_KEY = _burojs_react.DEFAULT_LANGUAGE_STORAGE_KE
6957
7187
  exports.DataTable = require_place_node.DataTable;
6958
7188
  exports.DataTableDateRangeFilter = DataTableDateRangeFilter;
6959
7189
  exports.DataTableEnumFilter = DataTableEnumFilter;
6960
- exports.DataTableFacetedFilter = DataTableFacetedFilter;
7190
+ exports.DataTableFacetedFilter = require_filter_builder.DataTableFacetedFilter;
6961
7191
  exports.DataTableNumRangeFilter = DataTableNumRangeFilter;
6962
7192
  exports.DataTableOperatorFilter = DataTableOperatorFilter;
6963
7193
  exports.DataTableRowActions = DataTableRowActions;
@@ -6976,7 +7206,7 @@ exports.DialogDescription = require_dialog.DialogDescription;
6976
7206
  exports.DialogFooter = require_dialog.DialogFooter;
6977
7207
  exports.DialogHeader = require_dialog.DialogHeader;
6978
7208
  exports.DialogPresentationHost = DialogPresentationHost;
6979
- exports.DialogPresentationShell = require_shell.DialogPresentationShell;
7209
+ exports.DialogPresentationShell = require_check_confirm_dialog.DialogPresentationShell;
6980
7210
  exports.DialogTitle = require_dialog.DialogTitle;
6981
7211
  exports.DialogTrigger = require_dialog.DialogTrigger;
6982
7212
  exports.DisabledAction = require_check_confirm_dialog.DisabledAction;
@@ -7009,6 +7239,7 @@ exports.EnumPicker = EnumPicker;
7009
7239
  exports.EnumValueDisplay = EnumDisplay$1;
7010
7240
  exports.ExportButton = require_place_node.ExportButton;
7011
7241
  exports.ExportDialog = require_place_node.ExportDialog;
7242
+ exports.FacetedFilterPicker = require_filter_builder.FacetedFilterPicker;
7012
7243
  exports.Field = require_place_node.Field;
7013
7244
  exports.FieldDisplay = require_place_node.FieldDisplay;
7014
7245
  exports.FileDisplay = FileDisplay;
@@ -7050,10 +7281,8 @@ exports.ListLive = require_place_node.ListLive;
7050
7281
  exports.ListSavedViews = require_place_node.ListSavedViews;
7051
7282
  exports.ListSearchInput = require_place_node.ListSearchInput;
7052
7283
  exports.LoginForm = LoginForm;
7053
- exports.NavAreaLayout = NavAreaLayout;
7054
7284
  exports.NavAreaPage = require_resource_page_router.NavAreaPage;
7055
- exports.NavChrome = require_resource_page_router.NavChrome;
7056
- exports.NavChromeBoundaryProvider = require_resource_page_router.NavChromeBoundaryProvider;
7285
+ exports.NavChrome = NavChrome;
7057
7286
  exports.NavMain = NavMain;
7058
7287
  exports.NavigationGuardDialog = NavigationGuardDialog;
7059
7288
  exports.NumberDisplay = NumberDisplay;
@@ -7068,6 +7297,7 @@ exports.PopoverClose = require_toaster.PopoverClose;
7068
7297
  exports.PopoverContent = require_toaster.PopoverContent;
7069
7298
  exports.PopoverPresentationHost = PopoverPresentationHost;
7070
7299
  exports.PopoverTrigger = require_toaster.PopoverTrigger;
7300
+ exports.PresetFilterControls = require_filter_builder.PresetFilterControls;
7071
7301
  exports.Progress = Progress;
7072
7302
  exports.RecordActions = require_place_node.RecordActions;
7073
7303
  exports.RecordBreadcrumbs = RecordBreadcrumbs;
@@ -7075,18 +7305,19 @@ exports.RecordPage = require_resource_page_router.RecordPage;
7075
7305
  exports.RecordScreen = require_resource_page_router.RecordScreen;
7076
7306
  exports.RecordTitle = require_place_node.RecordTitle;
7077
7307
  exports.RefreshButton = RefreshButton;
7078
- exports.RelationDisplay = require_search_access.RelationDisplay;
7079
- exports.RelationField = require_search_access.RelationField;
7308
+ exports.RelationDisplay = require_relation_create.RelationDisplay;
7309
+ exports.RelationField = require_relation_create.RelationField;
7080
7310
  exports.RelationManyDisplay = RelationManyDisplay;
7081
7311
  exports.RelationPicker = require_relation_picker.RelationPicker;
7082
- exports.RelationPickerDialog = require_candidates_gate.LazyRelationPickerDialog;
7312
+ exports.RelationPickerDialog = require_lazy_relation_picker_dialog.LazyRelationPickerDialog;
7083
7313
  exports.RelationPickerInput = require_relation_picker.RelationPickerInput;
7084
7314
  exports.ResourceList = require_place_node.ResourceList;
7085
7315
  exports.ResourceListPage = require_resource_page_router.ResourceListPage;
7086
7316
  exports.ResourcePageRouter = require_resource_page_router.ResourcePageRouter;
7087
7317
  exports.SavedViewsDropdown = require_place_node.SavedViewsDropdown;
7318
+ exports.ScopeDimensionPicker = ScopeDimensionPicker;
7088
7319
  exports.ScopeSwitcher = ScopeSwitcher;
7089
- exports.SecondarySidebarLayout = SecondarySidebarLayout;
7320
+ exports.SecondarySidebarLayout = require_resource_page_router.SecondarySidebarLayout;
7090
7321
  exports.Select = require_filter_builder.Select;
7091
7322
  exports.SelectContent = require_filter_builder.SelectContent;
7092
7323
  exports.SelectGroup = require_filter_builder.SelectGroup;
@@ -7098,16 +7329,16 @@ exports.SelectSeparator = require_filter_builder.SelectSeparator;
7098
7329
  exports.SelectTrigger = require_filter_builder.SelectTrigger;
7099
7330
  exports.SelectValue = require_filter_builder.SelectValue;
7100
7331
  exports.Separator = Separator;
7101
- exports.Sheet = require_shell.Sheet;
7102
- exports.SheetClose = require_shell.SheetClose;
7103
- exports.SheetContent = require_shell.SheetContent;
7104
- exports.SheetDescription = require_shell.SheetDescription;
7105
- exports.SheetFooter = require_shell.SheetFooter;
7106
- exports.SheetHeader = require_shell.SheetHeader;
7332
+ exports.Sheet = require_check_confirm_dialog.Sheet;
7333
+ exports.SheetClose = require_check_confirm_dialog.SheetClose;
7334
+ exports.SheetContent = require_check_confirm_dialog.SheetContent;
7335
+ exports.SheetDescription = require_check_confirm_dialog.SheetDescription;
7336
+ exports.SheetFooter = require_check_confirm_dialog.SheetFooter;
7337
+ exports.SheetHeader = require_check_confirm_dialog.SheetHeader;
7107
7338
  exports.SheetPresentationHost = SheetPresentationHost;
7108
- exports.SheetPresentationShell = require_shell.SheetPresentationShell;
7109
- exports.SheetTitle = require_shell.SheetTitle;
7110
- exports.SheetTrigger = require_shell.SheetTrigger;
7339
+ exports.SheetPresentationShell = require_check_confirm_dialog.SheetPresentationShell;
7340
+ exports.SheetTitle = require_check_confirm_dialog.SheetTitle;
7341
+ exports.SheetTrigger = require_check_confirm_dialog.SheetTrigger;
7111
7342
  exports.ShellProvider = require_place_node.ShellProvider;
7112
7343
  exports.ShowPageHeader = require_place_node.ShowPageHeader;
7113
7344
  exports.Sidebar = Sidebar;
@@ -7146,7 +7377,7 @@ exports.TableHeader = require_filter_builder.TableHeader;
7146
7377
  exports.TableRow = require_filter_builder.TableRow;
7147
7378
  exports.Tabs = require_place_node.Tabs;
7148
7379
  exports.TabsContent = require_place_node.TabsContent;
7149
- exports.TabsLayout = TabsLayout;
7380
+ exports.TabsLayout = require_resource_page_router.TabsLayout;
7150
7381
  exports.TabsList = require_place_node.TabsList;
7151
7382
  exports.TabsTrigger = require_place_node.TabsTrigger;
7152
7383
  exports.TaskRunPanel = TaskRunPanel;
@@ -7164,7 +7395,7 @@ exports.TooltipProvider = require_check_confirm_dialog.TooltipProvider;
7164
7395
  exports.TooltipTrigger = require_check_confirm_dialog.TooltipTrigger;
7165
7396
  exports.UserMenu = UserMenu;
7166
7397
  exports.badgeVariants = require_filter_builder.badgeVariants;
7167
- exports.buildNavItems = require_resource_page_router.buildNavItems;
7398
+ exports.buildNavItems = buildNavItems;
7168
7399
  exports.buroSortingToTanStack = require_place_node.buroSortingToTanStack;
7169
7400
  exports.buttonVariants = require_button.buttonVariants;
7170
7401
  exports.cn = require_use_theme.cn;
@@ -7185,9 +7416,9 @@ Object.defineProperty(exports, "modeForSurface", {
7185
7416
  return _burojs_react.modeForSurface;
7186
7417
  }
7187
7418
  });
7188
- exports.recordDisplayName = require_search_access.recordDisplayName;
7419
+ exports.recordDisplayName = require_relation_create.recordDisplayName;
7189
7420
  exports.registerIcons = require_check_confirm_dialog.registerIcons;
7190
- exports.relationLinkClassName = require_search_access.relationLinkClassName;
7421
+ exports.relationLinkClassName = require_relation_create.relationLinkClassName;
7191
7422
  exports.resolveNavIcon = resolveNavIcon;
7192
7423
  exports.resolveUpdater = require_place_node.resolveUpdater;
7193
7424
  exports.saveLocale = require_filter_builder.saveLocale;
@@ -7203,7 +7434,7 @@ exports.useCurrentUser = useCurrentUser;
7203
7434
  exports.useDialogFilterState = require_use_dialog_filter_state.useDialogFilterState;
7204
7435
  exports.useDocumentTitle = require_place_node.useDocumentTitle;
7205
7436
  exports.useExportRunWatcher = require_place_node.useExportRunWatcher;
7206
- exports.useFormControl = require_resource_page_router.useFormControl;
7437
+ exports.useFormControl = require_place_node.useFormControl;
7207
7438
  exports.useFormField = useFormField;
7208
7439
  exports.useHref = require_resource_page_router.useHref;
7209
7440
  exports.useIsMobile = useIsMobile;
@@ -7214,18 +7445,23 @@ exports.useLayoutResolver = require_resource_page_router.useLayoutResolver;
7214
7445
  exports.useLinkComponent = require_toaster.useLinkComponent;
7215
7446
  exports.useListSlot = require_check_confirm_dialog.useListSlot;
7216
7447
  exports.useMatch = require_resource_page_router.useMatch;
7217
- exports.useNavChromeBoundary = require_resource_page_router.useNavChromeBoundary;
7218
7448
  exports.useNavIcon = useNavIcon;
7219
7449
  exports.useNavTree = useNavTree;
7220
7450
  exports.useNavVisible = require_resource_page_router.useNavVisible;
7221
7451
  exports.useOptionalSidebar = useOptionalSidebar;
7222
7452
  exports.usePaletteState = require_place_node.usePaletteState;
7223
7453
  exports.usePresentationCopy = usePresentationCopy;
7224
- exports.useRelationPicker = useRelationPicker;
7454
+ exports.useRelationPicker = require_place_node.useRelationPicker;
7225
7455
  exports.useShell = require_place_node.useShell;
7226
7456
  exports.useSidebar = useSidebar;
7227
7457
  exports.useTheme = require_use_theme.useTheme;
7228
7458
  exports.useThemePaletteActions = useThemePaletteActions;
7459
+ Object.defineProperty(exports, "webPlatform", {
7460
+ enumerable: true,
7461
+ get: function() {
7462
+ return _burojs_react_web.webPlatform;
7463
+ }
7464
+ });
7229
7465
  exports.wrapperEnabled = wrapperEnabled;
7230
7466
 
7231
7467
  //# sourceMappingURL=index.cjs.map