@burojs/ui-shadcn 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +9 -0
  2. package/dist/bulk-summary-BWSAS7k2.js +143 -0
  3. package/dist/bulk-summary-BWSAS7k2.js.map +1 -0
  4. package/dist/bulk-summary-CrEij5vq.cjs +143 -0
  5. package/dist/bulk-summary-CrEij5vq.cjs.map +1 -0
  6. package/dist/candidates-relation-picker-CS_JZ4Fd.js +31 -0
  7. package/dist/candidates-relation-picker-CS_JZ4Fd.js.map +1 -0
  8. package/dist/candidates-relation-picker-y5M6_oe4.cjs +31 -0
  9. package/dist/candidates-relation-picker-y5M6_oe4.cjs.map +1 -0
  10. package/dist/{check-confirm-dialog-CkaVTPT9.js → check-confirm-dialog-2j0gOd7x.js} +392 -103
  11. package/dist/check-confirm-dialog-2j0gOd7x.js.map +1 -0
  12. package/dist/{check-confirm-dialog-BRByTFpg.cjs → check-confirm-dialog-C-NHgMST.cjs} +476 -102
  13. package/dist/check-confirm-dialog-C-NHgMST.cjs.map +1 -0
  14. package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
  15. package/dist/dialog-C123sVQ8.js.map +1 -0
  16. package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
  17. package/dist/dialog-vmMdfUWs.cjs.map +1 -0
  18. package/dist/{filter-builder-B3mZFL-K.cjs → filter-builder-DFu0JP-1.cjs} +959 -128
  19. package/dist/filter-builder-DFu0JP-1.cjs.map +1 -0
  20. package/dist/{filter-builder-DOnaXNfP.js → filter-builder-DaWHUZuV.js} +863 -116
  21. package/dist/filter-builder-DaWHUZuV.js.map +1 -0
  22. package/dist/{flow-runtime-B6zOHYqI.cjs → flow-runtime-BpmrIUb6.cjs} +61 -29
  23. package/dist/flow-runtime-BpmrIUb6.cjs.map +1 -0
  24. package/dist/{flow-runtime-D8h99FSg.js → flow-runtime-DyqTmK3H.js} +62 -30
  25. package/dist/flow-runtime-DyqTmK3H.js.map +1 -0
  26. package/dist/{flow-screen-CX05b3G9.cjs → flow-screen-Bcz9NF2V.cjs} +132 -88
  27. package/dist/flow-screen-Bcz9NF2V.cjs.map +1 -0
  28. package/dist/{flow-screen-CmbARSqg.js → flow-screen-DCdli6Ha.js} +132 -88
  29. package/dist/flow-screen-DCdli6Ha.js.map +1 -0
  30. package/dist/index.cjs +951 -605
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +618 -332
  33. package/dist/index.d.ts +618 -332
  34. package/dist/index.js +863 -522
  35. package/dist/index.js.map +1 -1
  36. package/dist/{inline-flow-host-B7U1OJUe.cjs → inline-flow-host-3vw7LzzD.cjs} +5 -5
  37. package/dist/inline-flow-host-3vw7LzzD.cjs.map +1 -0
  38. package/dist/{inline-flow-host-C3H2UpSA.js → inline-flow-host-C0rI9B7f.js} +5 -5
  39. package/dist/inline-flow-host-C0rI9B7f.js.map +1 -0
  40. package/dist/label-66W1qbke.js.map +1 -1
  41. package/dist/label-w6JYf2cF.cjs.map +1 -1
  42. package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs +153 -0
  43. package/dist/lazy-relation-picker-dialog-Bt8lrEIu.cjs.map +1 -0
  44. package/dist/lazy-relation-picker-dialog-CAScLPb2.js +135 -0
  45. package/dist/lazy-relation-picker-dialog-CAScLPb2.js.map +1 -0
  46. package/dist/markdown/index.d.cts +2 -3
  47. package/dist/markdown/index.d.ts +2 -3
  48. package/dist/{page-flow-route-CyXSvXSE.js → page-flow-route-BHUEpn0I.js} +36 -23
  49. package/dist/page-flow-route-BHUEpn0I.js.map +1 -0
  50. package/dist/{page-flow-route-CQ7HsbBm.cjs → page-flow-route-DS8IVTVH.cjs} +41 -28
  51. package/dist/page-flow-route-DS8IVTVH.cjs.map +1 -0
  52. package/dist/{place-node-SIp4XYQH.cjs → place-node-CNb3w-c7.cjs} +2227 -999
  53. package/dist/place-node-CNb3w-c7.cjs.map +1 -0
  54. package/dist/{place-node--GdsP688.js → place-node-CfzQvh4Y.js} +2164 -984
  55. package/dist/place-node-CfzQvh4Y.js.map +1 -0
  56. package/dist/{related-list-cards-B6x9HQQp.js → related-list-cards-BIqqY69Y.js} +9 -4
  57. package/dist/{related-list-cards-B6x9HQQp.js.map → related-list-cards-BIqqY69Y.js.map} +1 -1
  58. package/dist/{related-list-cards-nxuODlIA.cjs → related-list-cards-CelMxl4q.cjs} +9 -4
  59. package/dist/{related-list-cards-nxuODlIA.cjs.map → related-list-cards-CelMxl4q.cjs.map} +1 -1
  60. package/dist/{related-list-timeline-DEdfd-rr.js → related-list-timeline-CRh7xwLD.js} +6 -7
  61. package/dist/related-list-timeline-CRh7xwLD.js.map +1 -0
  62. package/dist/{related-list-timeline-BYJKEbmA.cjs → related-list-timeline-DsLdi8sv.cjs} +5 -6
  63. package/dist/related-list-timeline-DsLdi8sv.cjs.map +1 -0
  64. package/dist/{related-rows-B4levHcR.js → related-rows--uP2iKQC.js} +27 -17
  65. package/dist/related-rows--uP2iKQC.js.map +1 -0
  66. package/dist/{related-rows-zh5f_4QR.cjs → related-rows-MPnLCmPF.cjs} +32 -22
  67. package/dist/related-rows-MPnLCmPF.cjs.map +1 -0
  68. package/dist/{search-access-CURsWn-U.js → relation-create-C43cdPQt.js} +596 -29
  69. package/dist/relation-create-C43cdPQt.js.map +1 -0
  70. package/dist/{search-access-B7G5oR8n.cjs → relation-create-DDEYcKfw.cjs} +630 -32
  71. package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
  72. package/dist/{relation-many-picker-gdAOD-qK.js → relation-many-picker-BJhaEqxz.js} +210 -107
  73. package/dist/relation-many-picker-BJhaEqxz.js.map +1 -0
  74. package/dist/{relation-many-picker-B-NCEUgX.cjs → relation-many-picker-DzuGJpEl.cjs} +218 -115
  75. package/dist/relation-many-picker-DzuGJpEl.cjs.map +1 -0
  76. package/dist/{relation-picker-BAY77ivO.js → relation-picker-D-tBBZW_.js} +40 -45
  77. package/dist/relation-picker-D-tBBZW_.js.map +1 -0
  78. package/dist/{relation-picker-Da_uhFvA.cjs → relation-picker-DaIMzf2H.cjs} +45 -50
  79. package/dist/relation-picker-DaIMzf2H.cjs.map +1 -0
  80. package/dist/{relation-picker-dialog-M0pQaWlp.cjs → relation-picker-dialog-9Vg5vvR1.cjs} +142 -40
  81. package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +1 -0
  82. package/dist/{relation-picker-dialog-hA9rYrZB.js → relation-picker-dialog-DoEY8EkH.js} +143 -41
  83. package/dist/relation-picker-dialog-DoEY8EkH.js.map +1 -0
  84. package/dist/relation-select-B8Fq4o-t.js +48 -0
  85. package/dist/relation-select-B8Fq4o-t.js.map +1 -0
  86. package/dist/relation-select-Cr3CfNLy.cjs +55 -0
  87. package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
  88. package/dist/{resource-page-router-OSQyRA5b.cjs → resource-page-router-C_kGW2o_.cjs} +552 -303
  89. package/dist/resource-page-router-C_kGW2o_.cjs.map +1 -0
  90. package/dist/{resource-page-router-T4vS5gbJ.js → resource-page-router-Diw6S6TK.js} +507 -258
  91. package/dist/resource-page-router-Diw6S6TK.js.map +1 -0
  92. package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
  93. package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
  94. package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
  95. package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
  96. package/dist/success-notices-Dl3M1fZP.cjs +46 -0
  97. package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
  98. package/dist/success-notices-LDEgEkc4.js +41 -0
  99. package/dist/success-notices-LDEgEkc4.js.map +1 -0
  100. package/dist/{toaster-C7CiYA4Z.cjs → toaster-BbByOytP.cjs} +72 -80
  101. package/dist/toaster-BbByOytP.cjs.map +1 -0
  102. package/dist/{toaster-CfCRLgR-.js → toaster-Ct_YHGs6.js} +66 -68
  103. package/dist/toaster-Ct_YHGs6.js.map +1 -0
  104. package/dist/{use-dialog-filter-state-BDcgS5Oz.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
  105. package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
  106. package/dist/{use-dialog-filter-state-BBCC0OEK.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
  107. package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
  108. package/dist/use-theme-DFlpXils.cjs.map +1 -1
  109. package/dist/use-theme-dnE3Od3I.js.map +1 -1
  110. package/package.json +11 -11
  111. package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
  112. package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
  113. package/dist/bulk-summary-GxMDP4bw.js +0 -108
  114. package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
  115. package/dist/candidates-gate-CX2PBu6l.js +0 -63
  116. package/dist/candidates-gate-CX2PBu6l.js.map +0 -1
  117. package/dist/candidates-gate-DiFI52r7.cjs +0 -70
  118. package/dist/candidates-gate-DiFI52r7.cjs.map +0 -1
  119. package/dist/candidates-relation-picker-CBsVcnPR.js +0 -82
  120. package/dist/candidates-relation-picker-CBsVcnPR.js.map +0 -1
  121. package/dist/candidates-relation-picker-Dd_GVLlu.cjs +0 -84
  122. package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +0 -1
  123. package/dist/check-confirm-dialog-BRByTFpg.cjs.map +0 -1
  124. package/dist/check-confirm-dialog-CkaVTPT9.js.map +0 -1
  125. package/dist/dialog-B_rt9S1c.js.map +0 -1
  126. package/dist/dialog-DRNUq9EA.cjs.map +0 -1
  127. package/dist/filter-builder-B3mZFL-K.cjs.map +0 -1
  128. package/dist/filter-builder-DOnaXNfP.js.map +0 -1
  129. package/dist/flow-runtime-B6zOHYqI.cjs.map +0 -1
  130. package/dist/flow-runtime-D8h99FSg.js.map +0 -1
  131. package/dist/flow-screen-CX05b3G9.cjs.map +0 -1
  132. package/dist/flow-screen-CmbARSqg.js.map +0 -1
  133. package/dist/inline-flow-host-B7U1OJUe.cjs.map +0 -1
  134. package/dist/inline-flow-host-C3H2UpSA.js.map +0 -1
  135. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +0 -14
  136. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +0 -1
  137. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +0 -19
  138. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +0 -1
  139. package/dist/page-flow-route-CQ7HsbBm.cjs.map +0 -1
  140. package/dist/page-flow-route-CyXSvXSE.js.map +0 -1
  141. package/dist/peek-filter-CnqHwTMU.cjs +0 -51
  142. package/dist/peek-filter-CnqHwTMU.cjs.map +0 -1
  143. package/dist/peek-filter-ErLfO153.js +0 -28
  144. package/dist/peek-filter-ErLfO153.js.map +0 -1
  145. package/dist/place-node--GdsP688.js.map +0 -1
  146. package/dist/place-node-SIp4XYQH.cjs.map +0 -1
  147. package/dist/related-list-timeline-BYJKEbmA.cjs.map +0 -1
  148. package/dist/related-list-timeline-DEdfd-rr.js.map +0 -1
  149. package/dist/related-rows-B4levHcR.js.map +0 -1
  150. package/dist/related-rows-zh5f_4QR.cjs.map +0 -1
  151. package/dist/relation-create-BOaUe12G.cjs +0 -362
  152. package/dist/relation-create-BOaUe12G.cjs.map +0 -1
  153. package/dist/relation-create-Bg-eEJLs.js +0 -337
  154. package/dist/relation-create-Bg-eEJLs.js.map +0 -1
  155. package/dist/relation-many-picker-B-NCEUgX.cjs.map +0 -1
  156. package/dist/relation-many-picker-gdAOD-qK.js.map +0 -1
  157. package/dist/relation-picker-BAY77ivO.js.map +0 -1
  158. package/dist/relation-picker-Da_uhFvA.cjs.map +0 -1
  159. package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +0 -1
  160. package/dist/relation-picker-dialog-hA9rYrZB.js.map +0 -1
  161. package/dist/resource-page-router-OSQyRA5b.cjs.map +0 -1
  162. package/dist/resource-page-router-T4vS5gbJ.js.map +0 -1
  163. package/dist/search-access-B7G5oR8n.cjs.map +0 -1
  164. package/dist/search-access-CURsWn-U.js.map +0 -1
  165. package/dist/shell-BPlk8hEa.js +0 -205
  166. package/dist/shell-BPlk8hEa.js.map +0 -1
  167. package/dist/shell-DxhlsPwm.cjs +0 -271
  168. package/dist/shell-DxhlsPwm.cjs.map +0 -1
  169. package/dist/toaster-C7CiYA4Z.cjs.map +0 -1
  170. package/dist/toaster-CfCRLgR-.js.map +0 -1
  171. package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +0 -1
  172. package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,22 +1,21 @@
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-C7CiYA4Z.cjs");
4
- const require_check_confirm_dialog = require("./check-confirm-dialog-BRByTFpg.cjs");
3
+ const require_toaster = require("./toaster-BbByOytP.cjs");
4
+ const require_check_confirm_dialog = require("./check-confirm-dialog-C-NHgMST.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-B7G5oR8n.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-SIp4XYQH.cjs");
10
+ const require_place_node = require("./place-node-CNb3w-c7.cjs");
12
11
  const require_layout_theme_storage_key = require("./layout/theme-storage-key.cjs");
13
- const require_resource_page_router = require("./resource-page-router-OSQyRA5b.cjs");
12
+ const require_filter_builder = require("./filter-builder-DFu0JP-1.cjs");
13
+ const require_resource_page_router = require("./resource-page-router-C_kGW2o_.cjs");
14
14
  const require_label = require("./label-w6JYf2cF.cjs");
15
- const require_filter_builder = require("./filter-builder-B3mZFL-K.cjs");
16
- const require_relation_picker = require("./relation-picker-Da_uhFvA.cjs");
17
- const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BfAGKzUG.cjs");
18
- const require_use_dialog_filter_state = require("./use-dialog-filter-state-BBCC0OEK.cjs");
19
- const require_peek_filter = require("./peek-filter-CnqHwTMU.cjs");
15
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-Bt8lrEIu.cjs");
16
+ const require_relation_picker = require("./relation-picker-DaIMzf2H.cjs");
17
+ const require_use_dialog_filter_state = require("./use-dialog-filter-state-tNvqAAjh.cjs");
18
+ let _burojs_react_web = require("@burojs/react/web");
20
19
  let _burojs_core = require("@burojs/core");
21
20
  let _burojs_react = require("@burojs/react");
22
21
  let _tabler_icons_react = require("@tabler/icons-react");
@@ -36,6 +35,7 @@ let _radix_ui_react_avatar = require("@radix-ui/react-avatar");
36
35
  _radix_ui_react_avatar = require_use_theme.__toESM(_radix_ui_react_avatar, 1);
37
36
  let _radix_ui_react_collapsible = require("@radix-ui/react-collapsible");
38
37
  _radix_ui_react_collapsible = require_use_theme.__toESM(_radix_ui_react_collapsible, 1);
38
+ let _burojs_core_internal = require("@burojs/core/internal");
39
39
  let react_hook_form = require("react-hook-form");
40
40
  let _hookform_resolvers_zod = require("@hookform/resolvers/zod");
41
41
  let zod = require("zod");
@@ -497,7 +497,7 @@ function ScopeSummary({ scope, summary }) {
497
497
  const caps = (0, _burojs_react.useI18nCaps)();
498
498
  const t = (0, _burojs_react.useOptionalT)();
499
499
  const links = (scope !== void 0 ? (0, _burojs_core.resolveDoc)(caps, scope) : void 0)?.links ?? [];
500
- const newTabNote = t("docPanel.newTab", { defaultValue: "opens in a new tab" });
500
+ const newTabNote = t("docPanel.opensInNewTab", { defaultValue: "(opens in a new tab)" });
501
501
  if (summary === void 0 && links.length === 0) return null;
502
502
  return (0, react_jsx_runtime.jsxs)("div", {
503
503
  className: "mt-2 flex flex-col items-start gap-3",
@@ -633,9 +633,9 @@ function CommandPaletteDocsGroup({ locale, onSelect, heading }) {
633
633
  }];
634
634
  }), [groups, contextOf]);
635
635
  if (hits.length === 0) return null;
636
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
636
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
637
637
  heading: heading ?? t("docPanel.title", { defaultValue: "Help" }),
638
- children: hits.map((hit) => (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
638
+ children: hits.map((hit) => (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
639
639
  value: `doc ${hit.scopeLabel} ${hit.title}`,
640
640
  "data-testid": `command-doc:${hit.scope}${hit.topicId === void 0 ? "" : `:${hit.topicId}`}`,
641
641
  onSelect: () => {
@@ -778,10 +778,10 @@ const Sidebar = react.forwardRef(({ side = "left", variant = "sidebar", collapsi
778
778
  ...props,
779
779
  children
780
780
  });
781
- if (isMobile) return (0, react_jsx_runtime.jsx)(require_shell.Sheet, {
781
+ if (isMobile) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Sheet, {
782
782
  open: openMobile,
783
783
  onOpenChange: setOpenMobile,
784
- children: (0, react_jsx_runtime.jsxs)(require_shell.SheetContent, {
784
+ children: (0, react_jsx_runtime.jsxs)(require_check_confirm_dialog.SheetContent, {
785
785
  "data-sidebar": "sidebar",
786
786
  "data-mobile": "true",
787
787
  className: "w-[var(--sidebar-width)] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden",
@@ -789,11 +789,11 @@ const Sidebar = react.forwardRef(({ side = "left", variant = "sidebar", collapsi
789
789
  side: side === "left" ? "left" : "right",
790
790
  ...props,
791
791
  children: [
792
- (0, react_jsx_runtime.jsx)(require_shell.SheetTitle, {
792
+ (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.SheetTitle, {
793
793
  className: "sr-only",
794
794
  children: t("nav.label", { defaultValue: "Navigation" })
795
795
  }),
796
- (0, react_jsx_runtime.jsx)(require_shell.SheetDescription, {
796
+ (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.SheetDescription, {
797
797
  className: "sr-only",
798
798
  children: t("nav.main", { defaultValue: "Main navigation" })
799
799
  }),
@@ -1119,7 +1119,7 @@ AlertDialogCancel.displayName = _radix_ui_react_alert_dialog.Cancel.displayName;
1119
1119
  function NavigationGuardDialog() {
1120
1120
  const prompt = (0, _burojs_react.useRegisterNavigationGuardDialog)();
1121
1121
  const text = (0, _burojs_react.useNavigationGuardText)();
1122
- const unsavedAction = (0, _burojs_react.useOptionalT)()("navigation.unsavedAction");
1122
+ const unsavedAction = (0, _burojs_react.useOptionalT)()("navigation.unsavedAction", { defaultValue: "An action on this screen has unsaved input" });
1123
1123
  const returnFocus = (0, react.useRef)(null);
1124
1124
  const wasOpen = (0, react.useRef)(false);
1125
1125
  const open = prompt !== null;
@@ -1142,7 +1142,7 @@ function NavigationGuardDialog() {
1142
1142
  event.preventDefault();
1143
1143
  element.focus();
1144
1144
  },
1145
- 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, {
1145
+ 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, {
1146
1146
  "data-testid": "nav-guard-stay",
1147
1147
  children: text.stay
1148
1148
  }), (0, react_jsx_runtime.jsx)(AlertDialogAction, {
@@ -1309,7 +1309,7 @@ function useLanguageSwitch() {
1309
1309
  locale,
1310
1310
  locales: (0, react.useMemo)(() => i18n?.locales?.() ?? [locale], [i18n, locale]),
1311
1311
  change: (0, react.useCallback)((code) => {
1312
- require_toaster.saveLocale(code, storageKey);
1312
+ require_filter_builder.saveLocale(code, storageKey);
1313
1313
  changeLocale(code);
1314
1314
  }, [changeLocale, storageKey])
1315
1315
  };
@@ -1702,14 +1702,14 @@ const CollapsibleTrigger = _radix_ui_react_collapsible.CollapsibleTrigger;
1702
1702
  const CollapsibleContent = _radix_ui_react_collapsible.CollapsibleContent;
1703
1703
  //#endregion
1704
1704
  //#region src/shell/use-nav-icon.tsx
1705
- const warned = new Set();
1705
+ const warned$1 = new Set();
1706
1706
  function resolveNavIcon(name, components) {
1707
1707
  if (name === void 0 || name === "") return void 0;
1708
1708
  const slot = components(name);
1709
1709
  if (typeof slot === "function" || typeof slot === "object" && slot !== null) return (0, react_jsx_runtime.jsx)(slot, { className: "h-4 w-4" });
1710
1710
  if (require_check_confirm_dialog.hasIcon(name)) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, { name });
1711
- if (process.env.NODE_ENV !== "production" && !warned.has(name)) {
1712
- warned.add(name);
1711
+ if (process.env.NODE_ENV !== "production" && !warned$1.has(name)) {
1712
+ warned$1.add(name);
1713
1713
  console.warn(`[buro] unknown nav icon "${name}"`);
1714
1714
  }
1715
1715
  }
@@ -1718,6 +1718,53 @@ function useNavIcon() {
1718
1718
  return (0, react.useCallback)((name) => resolveNavIcon(name, (key) => components[key]), [components]);
1719
1719
  }
1720
1720
  //#endregion
1721
+ //#region src/layout/build-nav-items.ts
1722
+ function buildNavItems(args) {
1723
+ const { registry, caps, groupName, match, isVisible, entryFilter, icons } = args;
1724
+ const chain = match?.groupChain ?? [];
1725
+ const qualifiedMatch = match;
1726
+ const activeLeaf = qualifiedMatch == null ? void 0 : qualifiedMatch.kind === "group-index" ? require_resource_page_router.canonicalNavKey({
1727
+ name: qualifiedMatch.target ?? qualifiedMatch.name,
1728
+ ref: qualifiedMatch.targetRef
1729
+ }) : require_resource_page_router.canonicalNavKey(qualifiedMatch);
1730
+ const isEligible = (node) => isVisible(node) && (entryFilter ? entryFilter(node) : true);
1731
+ const out = [];
1732
+ for (const child of registry.groups.childrenOf(groupName)) {
1733
+ if (!isEligible(child)) continue;
1734
+ const kind = (0, _burojs_core.nodeKind)(child);
1735
+ const childKey = require_resource_page_router.canonicalNavKey(child);
1736
+ const href = (0, _burojs_core.navHrefFor)(registry, childKey, { isVisible: isEligible });
1737
+ if (kind === "group") {
1738
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label"));
1739
+ const active = chain.some((g) => require_resource_page_router.canonicalNavKey(g) === childKey);
1740
+ out.push({
1741
+ kind: "group",
1742
+ name: childKey,
1743
+ label,
1744
+ href,
1745
+ icon: icons?.group?.(childKey),
1746
+ active
1747
+ });
1748
+ } else if (kind === "custom-page") out.push({
1749
+ kind: "custom-page",
1750
+ name: childKey,
1751
+ label: (0, _burojs_core.resolveNavLabel)(caps, `pages.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label")),
1752
+ href,
1753
+ icon: icons?.page?.(childKey),
1754
+ active: activeLeaf === childKey
1755
+ });
1756
+ else out.push({
1757
+ kind: "resource",
1758
+ name: childKey,
1759
+ label: (0, _burojs_core.resolveResourceNavLabel)(caps, childKey, child),
1760
+ href,
1761
+ icon: icons?.resource?.(childKey),
1762
+ active: activeLeaf === childKey
1763
+ });
1764
+ }
1765
+ return out;
1766
+ }
1767
+ //#endregion
1721
1768
  //#region src/layout/use-nav-tree.ts
1722
1769
  function isActiveHref(href, currentPath) {
1723
1770
  if (!currentPath) return false;
@@ -1731,8 +1778,7 @@ function useNavTree(opts = {}) {
1731
1778
  const passesEntryFilter = (entry) => entryFilter ? entryFilter(entry) : true;
1732
1779
  const app = (0, _burojs_react.useApp)();
1733
1780
  const caps = (0, _burojs_react.useI18nCaps)();
1734
- const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
1735
- const isResourceVisible = (r) => (0, _burojs_core.evaluateVisible)(r.visible, visibilityCtx);
1781
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
1736
1782
  const resolveLayout = require_resource_page_router.useLayoutResolver();
1737
1783
  const match = require_resource_page_router.useMatch();
1738
1784
  const isVisible = require_resource_page_router.useNavVisible();
@@ -1742,6 +1788,7 @@ function useNavTree(opts = {}) {
1742
1788
  const allCustomPages = app.registry.customPages.list();
1743
1789
  const sections = app.registry.sections.list();
1744
1790
  const groups = app.registry.groups.rootNodes().filter((n) => (0, _burojs_core.nodeKind)(n) === "group");
1791
+ require_resource_page_router.useReportUnresolvedLayouts(app.registry.groups.list(), resolveLayout);
1745
1792
  const topLevelResources = allResources.filter((r) => (0, _burojs_core.hasListPage)(r)).filter(isResourceVisible).filter(passesEntryFilter).filter((r) => !r.section && !r.group).map((r, idx) => ({
1746
1793
  r,
1747
1794
  idx
@@ -1753,9 +1800,9 @@ function useNavTree(opts = {}) {
1753
1800
  const topLevelCustomPages = allCustomPages.filter((p) => !p.section && !p.group).filter(pageAllowed).filter(passesEntryFilter);
1754
1801
  const resourceHref = (def) => (0, _burojs_core.hrefFor)(app.registry, require_resource_page_router.canonicalResourceKey(def));
1755
1802
  const resourceLabel = (def) => (0, _burojs_core.resolveResourceNavLabel)(caps, require_resource_page_router.canonicalResourceKey(def), def);
1756
- const pageLabel = (page) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(page)}`, page.label);
1757
- const sectionLabel = (section) => (0, _burojs_core.resolveNavLabel)(caps, `sections.${require_resource_page_router.canonicalNavKey(section)}`, section.label);
1758
- const groupLabel = (group) => (0, _burojs_core.resolveNavLabel)(caps, `groups.${require_resource_page_router.canonicalNavKey(group)}`, group.label);
1803
+ const pageLabel = (page) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(page)}`, (0, _burojs_core.declaredText)("chrome", page, "label"));
1804
+ const sectionLabel = (section) => (0, _burojs_core.resolveNavLabel)(caps, `sections.${require_resource_page_router.canonicalNavKey(section)}`, (0, _burojs_core.declaredText)("chrome", section, "label"));
1805
+ const groupLabel = (group) => (0, _burojs_core.resolveNavLabel)(caps, `groups.${require_resource_page_router.canonicalNavKey(group)}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
1759
1806
  const pageEntry = (page) => {
1760
1807
  const href = page.path;
1761
1808
  return {
@@ -1779,7 +1826,7 @@ function useNavTree(opts = {}) {
1779
1826
  };
1780
1827
  };
1781
1828
  const layoutOf = (group) => resolveLayout(group.layout) ? group.layout : group.collapsible ? "collapsible" : "flat";
1782
- const groupChildren = (groupKey) => require_resource_page_router.buildNavItems({
1829
+ const groupChildren = (groupKey) => buildNavItems({
1783
1830
  registry: app.registry,
1784
1831
  caps,
1785
1832
  groupName: groupKey,
@@ -1979,7 +2026,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1979
2026
  })
1980
2027
  }) }, entry.key);
1981
2028
  const [top, ...blocks] = tree;
1982
- 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) => {
2029
+ 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) => {
1983
2030
  const key = block.key ?? "";
1984
2031
  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);
1985
2032
  if (block.collapsible) return (0, react_jsx_runtime.jsx)(CollapsibleNavSection, {
@@ -2023,127 +2070,32 @@ function AppSidebar({ header, filters, nav, footer }) {
2023
2070
  });
2024
2071
  }
2025
2072
  //#endregion
2026
- //#region src/layout/layouts/secondary-sidebar-layout.tsx
2027
- function Row({ it }) {
2028
- const RouterLink = require_toaster.useLinkComponent();
2029
- return (0, react_jsx_runtime.jsx)("li", { children: (0, react_jsx_runtime.jsxs)(RouterLink, {
2030
- href: it.href,
2031
- "data-testid": `nav-secondary-item:${it.name}`,
2032
- "aria-current": it.active ? "page" : void 0,
2033
- 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"),
2034
- children: [it.icon != null && (0, react_jsx_runtime.jsx)("span", {
2035
- className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
2036
- "aria-hidden": "true",
2037
- children: it.icon
2038
- }), (0, react_jsx_runtime.jsx)("span", {
2039
- className: "truncate",
2040
- title: it.label,
2041
- children: it.label
2042
- })]
2043
- }) });
2044
- }
2045
- function SecondarySidebarLayout({ group, groupKey, items, children }) {
2046
- const RouterLink = require_toaster.useLinkComponent();
2047
- const caps = (0, _burojs_react.useI18nCaps)();
2048
- const id = groupKey ?? group.name;
2049
- const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, group.label);
2050
- return (0, react_jsx_runtime.jsxs)("div", {
2051
- className: "md:-m-6 md:flex md:min-h-[calc(100%+3rem)]",
2052
- "data-testid": `nav-secondary:${id}`,
2053
- children: [
2054
- (0, react_jsx_runtime.jsx)("aside", {
2055
- className: "hidden w-64 shrink-0 border-r bg-background text-foreground md:block",
2056
- children: (0, react_jsx_runtime.jsxs)("div", {
2057
- className: "space-y-4 p-4",
2058
- children: [(0, react_jsx_runtime.jsx)("p", {
2059
- className: "px-3 text-base font-semibold tracking-tight",
2060
- children: label
2061
- }), (0, react_jsx_runtime.jsx)("nav", {
2062
- "aria-label": label,
2063
- children: (0, react_jsx_runtime.jsx)("ul", {
2064
- className: "space-y-0.5",
2065
- children: items.map((it) => (0, react_jsx_runtime.jsx)(Row, { it }, it.name))
2066
- })
2067
- })]
2068
- })
2069
- }),
2070
- (0, react_jsx_runtime.jsx)("nav", {
2071
- "aria-label": label,
2072
- "data-testid": `nav-secondary-select:${id}`,
2073
- 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",
2074
- children: items.map((it) => (0, react_jsx_runtime.jsx)(RouterLink, {
2075
- href: it.href,
2076
- "aria-current": it.active ? "page" : void 0,
2077
- 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"),
2078
- children: it.label
2079
- }, it.name))
2080
- }),
2081
- (0, react_jsx_runtime.jsx)("div", {
2082
- className: "min-w-0 flex-1 md:overflow-x-hidden md:p-6",
2083
- children
2084
- })
2085
- ]
2086
- });
2087
- }
2088
- //#endregion
2089
- //#region src/layout/layouts/tabs-layout.tsx
2090
- function TabsLayout({ group, groupKey, items, children }) {
2091
- const RouterLink = require_toaster.useLinkComponent();
2092
- const caps = (0, _burojs_react.useI18nCaps)();
2093
- const id = groupKey ?? group.name;
2094
- const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, group.label);
2095
- return (0, react_jsx_runtime.jsxs)("div", {
2096
- className: "flex flex-col gap-4",
2097
- "data-testid": `nav-tabs:${id}`,
2098
- children: [(0, react_jsx_runtime.jsx)("nav", {
2099
- "aria-label": label,
2100
- 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",
2101
- children: items.map((it) => (0, react_jsx_runtime.jsxs)(RouterLink, {
2102
- href: it.href,
2103
- "aria-current": it.active ? "page" : void 0,
2104
- "data-testid": `nav-tab:${it.name}`,
2105
- 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"),
2106
- children: [
2107
- it.icon != null && (0, react_jsx_runtime.jsx)("span", {
2108
- className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
2109
- "aria-hidden": "true",
2110
- children: it.icon
2111
- }),
2112
- it.label,
2113
- (0, react_jsx_runtime.jsx)("span", {
2114
- "aria-hidden": "true",
2115
- 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")
2116
- })
2117
- ]
2118
- }, it.name))
2119
- }), (0, react_jsx_runtime.jsx)("div", {
2120
- className: "min-w-0",
2121
- children
2122
- })]
2123
- });
2124
- }
2125
- //#endregion
2126
- //#region src/layout/nav-area-layout.tsx
2073
+ //#region src/layout/nav-chrome.tsx
2127
2074
  const DETAIL_ACTIONS = new Set([
2128
2075
  "show",
2129
2076
  "edit",
2130
2077
  "create"
2131
2078
  ]);
2132
- function NavAreaLayout({ groupName, children, entryFilter, icons }) {
2079
+ function NavChrome({ children, entryFilter, icons }) {
2133
2080
  const app = (0, _burojs_react.useApp)();
2134
2081
  const caps = (0, _burojs_react.useI18nCaps)();
2135
2082
  const isVisible = require_resource_page_router.useNavVisible();
2136
2083
  const match = require_resource_page_router.useMatch();
2137
2084
  const resolveLayout = require_resource_page_router.useLayoutResolver();
2138
- const group = app.registry.groups.get(groupName);
2139
- if (!group) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
2140
- const groupKey = require_resource_page_router.canonicalNavKey(group);
2141
- const claimed = [groupKey, ...(0, _burojs_core.groupChain)(app.registry, group).map(require_resource_page_router.canonicalNavKey)];
2142
- const collapse = group.chromeOn === "list" && match?.kind === "resource" && DETAIL_ACTIONS.has(match.action);
2143
- const Layout = resolveLayout(group.layout);
2085
+ require_resource_page_router.useReportUnresolvedLayouts(match?.groupChain ?? [], resolveLayout);
2086
+ if (!match) return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeMountedProvider, {
2087
+ value: true,
2088
+ children
2089
+ });
2144
2090
  let content = children;
2145
- if (Layout && !collapse) {
2146
- const items = require_resource_page_router.buildNavItems({
2091
+ for (let i = match.groupChain.length - 1; i >= 0; i--) {
2092
+ const group = match.groupChain[i];
2093
+ if (!group) continue;
2094
+ const groupKey = require_resource_page_router.canonicalNavKey(group);
2095
+ if (group.chromeOn === "list" && match.kind === "resource" && DETAIL_ACTIONS.has(match.action)) continue;
2096
+ const Layout = resolveLayout(group.layout);
2097
+ if (!Layout) continue;
2098
+ const items = buildNavItems({
2147
2099
  registry: app.registry,
2148
2100
  caps,
2149
2101
  groupName: groupKey,
@@ -2156,11 +2108,11 @@ function NavAreaLayout({ groupName, children, entryFilter, icons }) {
2156
2108
  group,
2157
2109
  groupKey,
2158
2110
  items,
2159
- children
2111
+ children: content
2160
2112
  });
2161
2113
  }
2162
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeBoundaryProvider, {
2163
- claim: claimed,
2114
+ return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeMountedProvider, {
2115
+ value: true,
2164
2116
  children: content
2165
2117
  });
2166
2118
  }
@@ -2173,10 +2125,12 @@ function Chevron() {
2173
2125
  "aria-hidden": "true"
2174
2126
  });
2175
2127
  }
2176
- function Breadcrumbs(props) {
2128
+ function Breadcrumbs(input) {
2129
+ const props = input;
2177
2130
  const { leadingSegments, className, docScopes, "data-testid": testId } = props;
2178
2131
  const app = (0, _burojs_react.useApp)();
2179
- const def = props.resource === void 0 ? void 0 : app.registry.get(props.resource);
2132
+ const resource = props.resource === void 0 ? void 0 : (0, _burojs_core.routeResourceKey)(props.resource);
2133
+ const def = resource === void 0 ? void 0 : app.registry.get(resource);
2180
2134
  const tid = (0, _burojs_react.useTestIds)();
2181
2135
  const t = (0, _burojs_react.useOptionalT)();
2182
2136
  const RouterLink = require_toaster.useLinkComponent();
@@ -2231,7 +2185,12 @@ function Breadcrumbs(props) {
2231
2185
  "data-testid": testId,
2232
2186
  children: [
2233
2187
  leading(resourceKey),
2234
- resourceIsCurrent ? current(tid.navBreadcrumb(resourceKey), resourceLabel) : (0, react_jsx_runtime.jsx)(RouterLink, {
2188
+ resourceIsCurrent ? current(tid.navBreadcrumb(resourceKey), resourceLabel) : !(0, _burojs_core.hasListPage)(def) ? (0, react_jsx_runtime.jsx)("span", {
2189
+ "data-testid": tid.navBreadcrumb(resourceKey),
2190
+ className: "truncate",
2191
+ title: resourceLabel,
2192
+ children: resourceLabel
2193
+ }) : (0, react_jsx_runtime.jsx)(RouterLink, {
2235
2194
  href: listHref,
2236
2195
  "data-testid": tid.navBreadcrumb(resourceKey),
2237
2196
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
@@ -2307,15 +2266,15 @@ function RecordBreadcrumbs() {
2307
2266
  }
2308
2267
  //#endregion
2309
2268
  //#region src/layout/default-nav-layouts.ts
2310
- const defaultNavLayouts = {
2311
- [require_resource_page_router.layoutSlot("secondary-sidebar")]: SecondarySidebarLayout,
2312
- [require_resource_page_router.layoutSlot("tabs")]: TabsLayout
2313
- };
2269
+ const defaultNavLayouts = { ...require_resource_page_router.BUILTIN_LAYOUTS };
2314
2270
  //#endregion
2315
2271
  //#region src/layout/context-picker.tsx
2316
- function ContextPicker({ sliceName, label, options, value, onChange, placeholder, disabled, className, hideLabel }) {
2272
+ const ALL = "\0all";
2273
+ function ContextPicker({ sliceName, label, options, value, onChange, placeholder, disabled, className, hideLabel, allOption }) {
2317
2274
  const tid = (0, _burojs_react.useTestIds)();
2318
2275
  const t = (0, _burojs_react.useOptionalT)();
2276
+ const chromeT = (0, _burojs_react.useChromeT)();
2277
+ const allLabel = typeof allOption === "string" ? allOption : chromeT("scope.all", { defaultValue: "All" });
2319
2278
  const displayLabel = label ?? (0, _burojs_core.humanizeKey)(sliceName);
2320
2279
  return (0, react_jsx_runtime.jsxs)("div", {
2321
2280
  className: require_use_theme.cn("space-y-1", className),
@@ -2324,23 +2283,114 @@ function ContextPicker({ sliceName, label, options, value, onChange, placeholder
2324
2283
  className: hideLabel ? "sr-only" : "text-xs font-medium text-muted-foreground uppercase tracking-wide",
2325
2284
  children: displayLabel
2326
2285
  }), (0, react_jsx_runtime.jsxs)(require_filter_builder.Select, {
2327
- value: value ?? "",
2328
- onValueChange: onChange,
2286
+ value: value ?? (allOption === void 0 ? "" : ALL),
2287
+ onValueChange: (next) => {
2288
+ if (allOption === void 0) onChange(next);
2289
+ else onChange(next === ALL ? null : next);
2290
+ },
2329
2291
  disabled,
2330
2292
  children: [(0, react_jsx_runtime.jsx)(require_filter_builder.SelectTrigger, {
2331
2293
  id: `context-picker:${sliceName}`,
2332
2294
  "data-testid": tid.contextPicker(sliceName),
2333
2295
  className: require_use_theme.cn("w-full", hideLabel ? "h-8 text-xs" : void 0),
2334
2296
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
2335
- }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: options.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
2297
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [allOption === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
2298
+ value: ALL,
2299
+ "data-testid": tid.contextPickerOption(sliceName, "all"),
2300
+ children: allLabel
2301
+ }), options.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
2336
2302
  value: o.value,
2337
2303
  "data-testid": tid.contextPickerOption(sliceName, o.value),
2338
2304
  children: o.label
2339
- }, o.value)) })]
2305
+ }, o.value))] })]
2340
2306
  })]
2341
2307
  });
2342
2308
  }
2343
2309
  //#endregion
2310
+ //#region src/layout/scope-dimension-picker.tsx
2311
+ function ScopeDimensionPicker(props) {
2312
+ const scope = (0, _burojs_react.useScope)();
2313
+ const definition = scope.definition?.dimensions[props.dimension];
2314
+ if (definition === void 0) throw new Error(`ScopeDimensionPicker: '${props.dimension}' is not a dimension of the app's defineScope(...)`);
2315
+ if (definition.select === "none") return null;
2316
+ const source = definition.values;
2317
+ if (source === void 0) throw new Error(`ScopeDimensionPicker: dimension '${props.dimension}' declares no values; add values: { resource } or a { value, label } list`);
2318
+ const allowed = scope.access[props.dimension]?.allowed;
2319
+ const permitted = Array.isArray(allowed) ? allowed : void 0;
2320
+ const common = {
2321
+ ...props,
2322
+ multiple: definition.select === "multiple",
2323
+ all: definition.all,
2324
+ selected: scope.selection[props.dimension] ?? null,
2325
+ select: (value) => scope.select(props.dimension, value)
2326
+ };
2327
+ if (Array.isArray(source)) {
2328
+ const options = source.filter((option) => permitted === void 0 || permitted.includes(option.value));
2329
+ return (0, react_jsx_runtime.jsx)(DimensionControl, {
2330
+ ...common,
2331
+ options
2332
+ });
2333
+ }
2334
+ const { resource, label } = source;
2335
+ return (0, react_jsx_runtime.jsx)(ResourceDimension, {
2336
+ ...common,
2337
+ resource,
2338
+ ...label ? { labelField: label } : {}
2339
+ });
2340
+ }
2341
+ function ResourceDimension({ resource, labelField, ...rest }) {
2342
+ const options = require_resource_page_router.useResourceDimensionOptions(rest.dimension, resource, labelField);
2343
+ return (0, react_jsx_runtime.jsx)(DimensionControl, {
2344
+ ...rest,
2345
+ options
2346
+ });
2347
+ }
2348
+ function DimensionControl({ dimension, label, hideLabel, className, multiple, all, selected, select, options }) {
2349
+ const tid = (0, _burojs_react.useTestIds)();
2350
+ const chromeT = (0, _burojs_react.useChromeT)();
2351
+ const byText = (0, react.useMemo)(() => new Map(options.map((option) => [String(option.value), option.value])), [options]);
2352
+ const textOptions = (0, react.useMemo)(() => options.map((option) => ({
2353
+ value: String(option.value),
2354
+ label: option.label
2355
+ })), [options]);
2356
+ const picked = (Array.isArray(selected) ? selected : selected === null ? [] : [selected]).map(String);
2357
+ const text = label ?? (0, _burojs_core.humanizeKey)(dimension);
2358
+ if (multiple) return (0, react_jsx_runtime.jsxs)("div", {
2359
+ className: require_use_theme.cn("space-y-1", className),
2360
+ children: [(0, react_jsx_runtime.jsx)("span", {
2361
+ className: hideLabel ? "sr-only" : "text-xs font-medium text-muted-foreground uppercase tracking-wide",
2362
+ children: text
2363
+ }), (0, react_jsx_runtime.jsx)(require_filter_builder.FacetedFilterPicker, {
2364
+ title: text,
2365
+ options: textOptions,
2366
+ selected: picked,
2367
+ ...all ? { emptyLabel: chromeT("scope.all", { defaultValue: "All" }) } : { clearable: false },
2368
+ onChange: (next) => {
2369
+ if (next.length === 0 && !all) return;
2370
+ select(next.length === 0 ? null : next.map((value) => byText.get(value) ?? value));
2371
+ },
2372
+ getTestId: (role, value) => role === "trigger" ? tid.contextPicker(dimension) : role === "option" ? tid.contextPickerOption(dimension, value ?? "") : role === "clear" ? tid.contextPickerOption(dimension, "all") : void 0
2373
+ })]
2374
+ });
2375
+ const common = {
2376
+ sliceName: dimension,
2377
+ ...label === void 0 ? {} : { label },
2378
+ options: textOptions,
2379
+ value: picked[0] ?? null,
2380
+ ...hideLabel === void 0 ? {} : { hideLabel },
2381
+ ...className === void 0 ? {} : { className }
2382
+ };
2383
+ const choose = (value) => select(value === null ? null : byText.get(value) ?? value);
2384
+ return all ? (0, react_jsx_runtime.jsx)(ContextPicker, {
2385
+ ...common,
2386
+ allOption: true,
2387
+ onChange: choose
2388
+ }) : (0, react_jsx_runtime.jsx)(ContextPicker, {
2389
+ ...common,
2390
+ onChange: choose
2391
+ });
2392
+ }
2393
+ //#endregion
2344
2394
  //#region src/layout/language-switch.tsx
2345
2395
  function LanguageSwitch({ onChange, className }) {
2346
2396
  const t = (0, _burojs_react.useOptionalT)();
@@ -2469,20 +2519,20 @@ function CommandPalette({ open, onOpenChange, children, placeholder, emptyState,
2469
2519
  }
2470
2520
  onOpenChange(next);
2471
2521
  }, [onOpenChange]);
2472
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandDialog, {
2522
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandDialog, {
2473
2523
  open,
2474
2524
  onOpenChange: handleOpenChange,
2475
2525
  className,
2476
2526
  title: t("commandPalette.title", { defaultValue: "Command Palette" }),
2477
2527
  description: t("commandPalette.description", { defaultValue: "Search and run actions." }),
2478
2528
  children: [
2479
- (0, react_jsx_runtime.jsx)(require_search_access.CommandInput, {
2529
+ (0, react_jsx_runtime.jsx)(require_relation_create.CommandInput, {
2480
2530
  placeholder: resolvedPlaceholder,
2481
2531
  "data-testid": inputTestId
2482
2532
  }),
2483
- (0, react_jsx_runtime.jsxs)(require_search_access.CommandList, {
2533
+ (0, react_jsx_runtime.jsxs)(require_relation_create.CommandList, {
2484
2534
  "data-testid": dialogTestId,
2485
- children: [resolvedEmpty !== null && !hasAsyncResults && (0, react_jsx_runtime.jsx)(require_search_access.CommandEmpty, {
2535
+ children: [resolvedEmpty !== null && !hasAsyncResults && (0, react_jsx_runtime.jsx)(require_relation_create.CommandEmpty, {
2486
2536
  "data-testid": emptyTestId,
2487
2537
  children: resolvedEmpty
2488
2538
  }), (0, react_jsx_runtime.jsx)(CommandPaletteResultsContext.Provider, {
@@ -2529,7 +2579,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2529
2579
  const navigate = (0, _burojs_react.useRouteNavigate)();
2530
2580
  const isVisible = require_resource_page_router.useNavVisible();
2531
2581
  const resolveLayout = require_resource_page_router.useLayoutResolver();
2532
- const isResourceVisible = (r) => (0, _burojs_core.evaluateVisible)(r.visible, visibilityCtx);
2582
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
2533
2583
  const pageAllowed = require_resource_page_router.usePageAllowed();
2534
2584
  const isPageVisible = (p) => (0, _burojs_core.evaluateVisible)(p.visible, visibilityCtx) && pageAllowed(p);
2535
2585
  const { topLevelResources, topLevelPages, sectionGroups } = (0, react.useMemo)(() => {
@@ -2558,15 +2608,15 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2558
2608
  navigate(href);
2559
2609
  };
2560
2610
  const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "plural", def);
2561
- const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(def)}`, def.label);
2611
+ const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(def)}`, (0, _burojs_core.declaredText)("chrome", def, "label"));
2562
2612
  const groups = [];
2563
- if (topLevelResources.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2613
+ if (topLevelResources.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2564
2614
  heading: t("commandPalette.resources", { defaultValue: "Resources" }),
2565
2615
  children: topLevelResources.map((def) => {
2566
2616
  const resource = require_resource_page_router.canonicalResourceKey(def);
2567
2617
  const label = resourceLabel(def);
2568
2618
  const href = (0, _burojs_core.hrefFor)(app.registry, resource, { isVisible });
2569
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2619
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2570
2620
  value: `resource:${resource}:${label}`,
2571
2621
  onSelect: () => goTo(href),
2572
2622
  "data-testid": getTestId?.("resource", resource),
@@ -2574,13 +2624,13 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2574
2624
  }, `resource:${resource}`);
2575
2625
  })
2576
2626
  }, "resources"));
2577
- if (topLevelPages.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2627
+ if (topLevelPages.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2578
2628
  heading: t("commandPalette.pages", { defaultValue: "Pages" }),
2579
2629
  children: topLevelPages.map((page) => {
2580
2630
  const pageKey = require_resource_page_router.canonicalNavKey(page);
2581
2631
  const label = pageLabel(page);
2582
2632
  const href = page.path;
2583
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2633
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2584
2634
  value: `page:${pageKey}:${page.path}:${label}`,
2585
2635
  onSelect: () => goTo(href),
2586
2636
  "data-testid": getTestId?.("page", pageKey),
@@ -2590,10 +2640,10 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2590
2640
  }, "pages"));
2591
2641
  for (const { section, children } of sectionGroups) {
2592
2642
  const sectionKey = require_resource_page_router.canonicalNavKey(section);
2593
- const sectionLabel = (0, _burojs_core.resolveNavLabel)(caps, `sections.${sectionKey}`, section.label);
2594
- groups.push((0, react_jsx_runtime.jsxs)(require_search_access.CommandGroup, {
2643
+ const sectionLabel = (0, _burojs_core.resolveNavLabel)(caps, `sections.${sectionKey}`, (0, _burojs_core.declaredText)("chrome", section, "label"));
2644
+ groups.push((0, react_jsx_runtime.jsxs)(require_relation_create.CommandGroup, {
2595
2645
  heading: sectionLabel,
2596
- children: [(0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2646
+ children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2597
2647
  value: `section:${sectionKey}:${sectionLabel}`,
2598
2648
  disabled: true,
2599
2649
  className: "font-medium opacity-70",
@@ -2604,7 +2654,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2604
2654
  const pageKey = require_resource_page_router.canonicalNavKey(child);
2605
2655
  const href = child.path;
2606
2656
  const label = pageLabel(child);
2607
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2657
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2608
2658
  value: `section:${sectionKey}:page:${pageKey}:${child.path}:${label}`,
2609
2659
  onSelect: () => goTo(href),
2610
2660
  "data-testid": getTestId?.("page", `${sectionKey}:${pageKey}`),
@@ -2615,7 +2665,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2615
2665
  const resource = require_resource_page_router.canonicalResourceKey(child);
2616
2666
  const label = resourceLabel(child);
2617
2667
  const href = (0, _burojs_core.hrefFor)(app.registry, resource, { isVisible });
2618
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2668
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2619
2669
  value: `section:${sectionKey}:resource:${resource}:${label}`,
2620
2670
  onSelect: () => goTo(href),
2621
2671
  "data-testid": getTestId?.("resource", `${sectionKey}:${resource}`),
@@ -2629,9 +2679,9 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2629
2679
  const items = [];
2630
2680
  if (!!resolveLayout(group.layout)) {
2631
2681
  const groupKey = require_resource_page_router.canonicalNavKey(group);
2632
- const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, group.label);
2682
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2633
2683
  const href = (0, _burojs_core.navHrefFor)(app.registry, groupKey, { isVisible });
2634
- items.push((0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2684
+ items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2635
2685
  value: `group:${idPath}:${label}`,
2636
2686
  onSelect: () => goTo(href),
2637
2687
  "data-testid": getTestId?.("group", idPath),
@@ -2652,7 +2702,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2652
2702
  const pageKey = require_resource_page_router.canonicalNavKey(page);
2653
2703
  const label = pageLabel(page);
2654
2704
  const href = page.path;
2655
- items.push((0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2705
+ items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2656
2706
  value: `page:${idPath}:${pageKey}:${label}`,
2657
2707
  onSelect: () => goTo(href),
2658
2708
  "data-testid": getTestId?.("page", `${idPath}:${pageKey}`),
@@ -2667,7 +2717,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2667
2717
  const resourceId = require_resource_page_router.canonicalResourceKey(resource);
2668
2718
  const label = resourceLabel(resource);
2669
2719
  const href = (0, _burojs_core.hrefFor)(app.registry, resourceId, { isVisible });
2670
- items.push((0, react_jsx_runtime.jsx)(require_search_access.CommandItem, {
2720
+ items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2671
2721
  value: `resource:${idPath}:${resourceId}:${label}`,
2672
2722
  onSelect: () => goTo(href),
2673
2723
  "data-testid": getTestId?.("resource", `${idPath}:${resourceId}`),
@@ -2683,14 +2733,14 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2683
2733
  const groupKey = require_resource_page_router.canonicalNavKey(group);
2684
2734
  const items = collectGroupItems(group, groupKey, 0);
2685
2735
  if (items.length === 0) continue;
2686
- const heading = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, group.label);
2687
- groups.push((0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2736
+ const heading = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2737
+ groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2688
2738
  heading,
2689
2739
  children: items
2690
2740
  }, `group:${groupKey}`));
2691
2741
  }
2692
2742
  if (groups.length === 0) return null;
2693
- 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}`)) });
2743
+ 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}`)) });
2694
2744
  }
2695
2745
  //#endregion
2696
2746
  //#region src/layout/quick-targets.ts
@@ -2703,10 +2753,10 @@ function opensInQuick(registry, resource, mode) {
2703
2753
  }
2704
2754
  //#endregion
2705
2755
  //#region src/layout/command-palette-recent-group.tsx
2706
- function entryHref(registry, entry, visibilityCtx) {
2756
+ function entryHref(registry, entry, isResourceVisible) {
2707
2757
  const def = registry.get(entry.canonicalRef);
2708
2758
  if (def === void 0) return void 0;
2709
- if (!(0, _burojs_core.evaluateVisible)(def.visible, visibilityCtx)) return void 0;
2759
+ if (!isResourceVisible(def)) return void 0;
2710
2760
  for (const action of ["show", "edit"]) if (require_place_node.recordRouteAvailable(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2711
2761
  action,
2712
2762
  id: entry.id
@@ -2720,27 +2770,39 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2720
2770
  const navigate = (0, _burojs_react.useRouteNavigate)();
2721
2771
  const quick = (0, _burojs_react.useQuick)();
2722
2772
  const userId = (0, _burojs_react.useCurrentUserId)();
2723
- const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
2773
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
2724
2774
  const resolvedHeading = heading ?? t("commandPalette.recent", { defaultValue: "Recent" });
2725
- const [hydrated, setHydrated] = (0, react.useState)(false);
2775
+ const store = (0, _burojs_react.usePlatformStorage)().local;
2776
+ const [stored, setStored] = (0, react.useState)([]);
2726
2777
  (0, react.useEffect)(() => {
2727
- setHydrated(true);
2728
- }, []);
2729
- const recents = (0, react.useMemo)(() => {
2730
- if (!hydrated || userId === null) return [];
2731
- return require_resource_page_router.readRecentRecords(userId).flatMap((entry) => {
2732
- const href = entryHref(app.registry, entry, visibilityCtx);
2733
- return href === void 0 ? [] : [{
2734
- entry,
2735
- href
2736
- }];
2737
- });
2778
+ if (userId === null) {
2779
+ setStored([]);
2780
+ return;
2781
+ }
2782
+ let current = true;
2783
+ const read = require_resource_page_router.readRecentRecords(store, userId);
2784
+ if (Array.isArray(read)) setStored(read);
2785
+ else read.then((entries) => {
2786
+ if (current) setStored(entries);
2787
+ }, () => void 0);
2788
+ return () => {
2789
+ current = false;
2790
+ };
2738
2791
  }, [
2739
- hydrated,
2792
+ store,
2740
2793
  userId,
2741
- refreshKey,
2794
+ refreshKey
2795
+ ]);
2796
+ const recents = (0, react.useMemo)(() => stored.flatMap((entry) => {
2797
+ const href = entryHref(app.registry, entry, isResourceVisible);
2798
+ return href === void 0 ? [] : [{
2799
+ entry,
2800
+ href
2801
+ }];
2802
+ }), [
2803
+ stored,
2742
2804
  app.registry,
2743
- visibilityCtx
2805
+ isResourceVisible
2744
2806
  ]);
2745
2807
  if (((0, cmdk.useCommandState)((state) => state.search) ?? "").length > 0) return null;
2746
2808
  if (recents.length === 0) return null;
@@ -2749,7 +2811,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2749
2811
  if (href === null) quick.show(entry.canonicalRef, entry.id);
2750
2812
  else navigate(href);
2751
2813
  };
2752
- return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2814
+ return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2753
2815
  heading: resolvedHeading,
2754
2816
  children: recents.map(({ entry, href }) => (0, react_jsx_runtime.jsx)(RecentItem, {
2755
2817
  entry,
@@ -2757,7 +2819,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2757
2819
  onGo: goTo,
2758
2820
  ...getTestId === void 0 ? {} : { getTestId }
2759
2821
  }, `recent:${entry.canonicalRef}:${entry.id}`))
2760
- }, "recent"), withSeparator && (0, react_jsx_runtime.jsx)(require_search_access.CommandSeparator, {})] });
2822
+ }, "recent"), withSeparator && (0, react_jsx_runtime.jsx)(require_relation_create.CommandSeparator, {})] });
2761
2823
  }
2762
2824
  function RecentItem({ entry, href, onGo, getTestId }) {
2763
2825
  const app = (0, _burojs_react.useApp)();
@@ -2770,7 +2832,7 @@ function RecentItem({ entry, href, onGo, getTestId }) {
2770
2832
  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;
2771
2833
  const legacyTrusted = entry.label === entry.id || access.status === "ready" && candidates.every((name) => access.fieldVisible(name));
2772
2834
  const shown = entry.labelField === void 0 ? legacyTrusted ? entry.label : entry.id : access.status === "ready" && access.fieldVisible(entry.labelField) ? entry.label : entry.id;
2773
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
2835
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2774
2836
  value: `recent:${key}:${resourceLabel}:${shown}`,
2775
2837
  onSelect: () => onGo(href, entry),
2776
2838
  "data-testid": getTestId?.("recent", key),
@@ -2793,7 +2855,7 @@ function resolveDisplayField(def) {
2793
2855
  const isSearchable = (fieldName) => {
2794
2856
  const fieldDef = fields[fieldName];
2795
2857
  if (!fieldDef) return false;
2796
- const canonical = require_place_node.lowerLegacyField(fieldDef);
2858
+ const canonical = require_filter_builder.lowerLegacyField(fieldDef);
2797
2859
  return canonical.type === "string" && canonical.format !== "enum";
2798
2860
  };
2799
2861
  if (def.displayField && isSearchable(def.displayField)) return def.displayField;
@@ -2805,25 +2867,26 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2805
2867
  const t = (0, _burojs_react.useOptionalT)();
2806
2868
  const navigate = (0, _burojs_react.useRouteNavigate)();
2807
2869
  const quick = (0, _burojs_react.useQuick)();
2870
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
2808
2871
  const resolvedHeading = heading ?? t("commandPalette.records", { defaultValue: "Records" });
2809
2872
  const liveQuery = (0, cmdk.useCommandState)((state) => state.search) ?? "";
2810
2873
  const debouncedQuery = (0, _burojs_react.useDebouncedValue)(liveQuery, debounceMs);
2811
2874
  const searchableResources = (0, react.useMemo)(() => {
2812
- 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) => {
2875
+ 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")).filter(isResourceVisible).map((def) => {
2813
2876
  const displayField = resolveDisplayField(def);
2814
2877
  return displayField ? {
2815
2878
  def,
2816
2879
  displayField
2817
2880
  } : null;
2818
2881
  }).filter((entry) => entry !== null);
2819
- }, [app.registry]);
2882
+ }, [app.registry, isResourceVisible]);
2820
2883
  if (!(enabled && debouncedQuery.length >= minQueryLength && searchableResources.length > 0)) return null;
2821
2884
  const goTo = (href, resource, id) => {
2822
2885
  onSelect?.();
2823
2886
  if (href === null) quick.show(resource, id);
2824
2887
  else navigate(href);
2825
2888
  };
2826
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
2889
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2827
2890
  heading: resolvedHeading,
2828
2891
  forceMount: true,
2829
2892
  children: searchableResources.map(({ def, displayField }) => (0, react_jsx_runtime.jsx)(PerResourceSearchHits, {
@@ -2855,6 +2918,7 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2855
2918
  page: 1,
2856
2919
  pageSize
2857
2920
  },
2921
+ scope: "session",
2858
2922
  enabled: shouldFetch
2859
2923
  });
2860
2924
  const report = useCommandPaletteResults(`records:${resource}`);
@@ -2864,14 +2928,16 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2864
2928
  }, [report, rows.length]);
2865
2929
  if (rows.length === 0) return null;
2866
2930
  const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "single", def);
2931
+ const declaredIdField = def.data?.idField;
2932
+ const idField = typeof declaredIdField === "string" && declaredIdField.length > 0 ? declaredIdField : "id";
2867
2933
  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;
2934
+ const idVal = row[idField] ?? row.id ?? row.event_id ?? row.job_id;
2869
2935
  const id = idVal == null ? "" : String(idVal);
2870
2936
  if (!id) return null;
2871
2937
  const display = titleVisible ? row[displayField] : void 0;
2872
2938
  const labelText = typeof display === "string" && display.length > 0 ? display : id;
2873
2939
  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, {
2940
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2875
2941
  value: `record:${resource}:${id}:${labelText}`,
2876
2942
  forceMount: true,
2877
2943
  onSelect: () => goTo(href, resource, id),
@@ -2973,7 +3039,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
2973
3039
  onSelect?.();
2974
3040
  }
2975
3041
  };
2976
- return (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, {
3042
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2977
3043
  heading: resolvedHeading,
2978
3044
  children: items.map((item) => {
2979
3045
  const value = [
@@ -2983,7 +3049,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
2983
3049
  item.label,
2984
3050
  item.keywords ?? ""
2985
3051
  ].filter((s) => s.length > 0).join(":");
2986
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
3052
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2987
3053
  value,
2988
3054
  className: require_use_theme.cn(item.disabled && "opacity-60"),
2989
3055
  onSelect: () => {
@@ -3010,7 +3076,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
3010
3076
  function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, heading, createHref, prefix }) {
3011
3077
  const caps = (0, _burojs_react.useI18nCaps)();
3012
3078
  const app = (0, _burojs_react.useApp)();
3013
- const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
3079
+ const isResourceVisible = require_resource_page_router.useResourceVisible();
3014
3080
  const gate = (0, _burojs_react.useAvailabilityGate)();
3015
3081
  const t = (0, _burojs_react.useOptionalT)();
3016
3082
  const navigate = (0, _burojs_react.useRouteNavigate)();
@@ -3018,11 +3084,11 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3018
3084
  const resolvedHeading = heading ?? t("commandPalette.create", { defaultValue: "Create" });
3019
3085
  const resolvedPrefix = prefix ?? t("commandPalette.createNew", { defaultValue: "Create new" });
3020
3086
  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);
3087
+ 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
3088
  }, [
3023
3089
  app,
3024
3090
  gate,
3025
- visibilityCtx,
3091
+ isResourceVisible,
3026
3092
  resourceFilter
3027
3093
  ]);
3028
3094
  if (visibleResources.length === 0) return null;
@@ -3039,14 +3105,14 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3039
3105
  quick.create(require_resource_page_router.canonicalResourceKey(def));
3040
3106
  };
3041
3107
  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, {
3108
+ return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
3043
3109
  heading: resolvedHeading,
3044
3110
  children: visibleResources.map((def) => {
3045
3111
  const resource = require_resource_page_router.canonicalResourceKey(def);
3046
3112
  const label = resourceLabel(def);
3047
3113
  const href = createHref?.(def) ?? (0, _burojs_core.resourceCreateHref)(app.registry, def, resource);
3048
3114
  const value = `create:${resource}:${resolvedPrefix}:${label}`;
3049
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
3115
+ return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
3050
3116
  value,
3051
3117
  onSelect: () => createIn(def, href),
3052
3118
  "data-testid": getTestId?.("create", resource),
@@ -3104,7 +3170,7 @@ function AppActions() {
3104
3170
  variant: "outline",
3105
3171
  size: "sm",
3106
3172
  disabled: action.disabledReason !== void 0,
3107
- title: action.disabledReason,
3173
+ title: action.disabledReason === void 0 ? void 0 : require_check_confirm_dialog.reasonText(caps, action.disabledReason),
3108
3174
  "data-testid": `app-action:${action.name}`,
3109
3175
  children: action.disabledReason === void 0 ? (0, react_jsx_runtime.jsx)(RouterLink, {
3110
3176
  href,
@@ -3226,7 +3292,7 @@ function localizedSchema(t) {
3226
3292
  function LoginForm({ onSubmit, title, description, className }) {
3227
3293
  const tid = (0, _burojs_react.useTestIds)();
3228
3294
  const t = (0, _burojs_react.useOptionalT)();
3229
- const locale = (0, _burojs_react.useLocale)();
3295
+ const caps = (0, _burojs_react.useI18nCaps)();
3230
3296
  const resolvedTitle = title ?? t("auth.signIn", { defaultValue: "Sign in" });
3231
3297
  const { register, handleSubmit, formState: { errors, isSubmitting } } = (0, react_hook_form.useForm)({
3232
3298
  resolver: (0, _hookform_resolvers_zod.zodResolver)(localizedSchema(t)),
@@ -3241,9 +3307,11 @@ function LoginForm({ onSubmit, title, description, className }) {
3241
3307
  try {
3242
3308
  await onSubmit(values);
3243
3309
  } catch (e) {
3244
- const raw = e instanceof Error ? e.message : String(e);
3245
- const friendly = require_toaster.toFriendlyError(raw, "", locale);
3246
- setSubmitError(friendly.replaced ? `${friendly.title}. ${friendly.detail}` : credentialsMessage(raw, t));
3310
+ const dataCode = e !== null && typeof e === "object" && !(e instanceof Error) ? e.code : void 0;
3311
+ const raw = e instanceof Error ? e.message : require_toaster.technicalText(e) ?? (dataCode === void 0 ? String(e) : "");
3312
+ const friendly = require_toaster.toFriendlyError(raw, "", require_toaster.friendlyStringsFrom(t));
3313
+ const credentials = credentialsMessage(raw, t);
3314
+ setSubmitError(friendly.replaced ? `${friendly.title}. ${friendly.detail}` : typeof dataCode === "string" && credentials === raw ? (0, _burojs_react.resolveErrorText)(e, caps) : credentials);
3247
3315
  }
3248
3316
  });
3249
3317
  return (0, react_jsx_runtime.jsxs)(Card, {
@@ -3368,9 +3436,108 @@ function AuthPage({ children, brand, footer, className }) {
3368
3436
  });
3369
3437
  }
3370
3438
  //#endregion
3439
+ //#region src/enum/enum-choice-group.tsx
3440
+ const NONE = "__none__";
3441
+ function isEmpty$1(value) {
3442
+ return value === null || value === void 0 || value === "";
3443
+ }
3444
+ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3445
+ const t = (0, _burojs_react.useOptionalT)();
3446
+ const generatedName = react.useId();
3447
+ const groupName = name ?? generatedName;
3448
+ const empty = isEmpty$1(value);
3449
+ const noneLabel = t("field.none", { defaultValue: "None" });
3450
+ const pick = (next) => {
3451
+ if (!disabled) onChange(next);
3452
+ };
3453
+ const ariaProps = {
3454
+ "aria-invalid": ariaInvalid || void 0,
3455
+ "aria-describedby": ariaDescribedBy,
3456
+ ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3457
+ };
3458
+ if (control === "segmented") {
3459
+ const segment = (key, label, active, select) => (0, react_jsx_runtime.jsx)("button", {
3460
+ type: "button",
3461
+ "aria-pressed": active,
3462
+ "data-state": active ? "active" : "inactive",
3463
+ "data-testid": `${testid}:option:${key}`,
3464
+ disabled,
3465
+ onClick: select,
3466
+ 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"),
3467
+ children: label
3468
+ }, key);
3469
+ return (0, react_jsx_runtime.jsxs)("div", {
3470
+ role: "group",
3471
+ id,
3472
+ "aria-labelledby": ariaLabelledBy,
3473
+ "data-testid": testid,
3474
+ className: require_use_theme.cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3475
+ ...ariaProps,
3476
+ children: [required ? null : segment(NONE, noneLabel, empty, () => pick(void 0)), options.map((option) => segment(option.value, (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [option.icon ? (0, react_jsx_runtime.jsx)("span", {
3477
+ "data-testid": `${testid}:option:${option.value}:icon`,
3478
+ className: "contents",
3479
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3480
+ name: option.icon,
3481
+ className: "size-3.5 shrink-0"
3482
+ })
3483
+ }) : null, option.label] }), value === option.value, () => pick(option.value)))]
3484
+ });
3485
+ }
3486
+ const cards = control === "cards";
3487
+ const choice = (key, option, label, checked, select) => {
3488
+ const inputId = `${id ?? groupName}:${key}`;
3489
+ return (0, react_jsx_runtime.jsxs)("label", {
3490
+ htmlFor: inputId,
3491
+ 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"), disabled && "cursor-not-allowed opacity-60"),
3492
+ children: [(0, react_jsx_runtime.jsx)("input", {
3493
+ type: "radio",
3494
+ id: inputId,
3495
+ name: groupName,
3496
+ value: key,
3497
+ checked,
3498
+ onChange: select,
3499
+ disabled,
3500
+ ...ariaProps,
3501
+ "data-testid": `${testid}:option:${key}`,
3502
+ className: require_use_theme.cn("h-4 w-4 shrink-0 accent-primary", cards ? "mt-0.5" : "mt-1")
3503
+ }), (0, react_jsx_runtime.jsxs)("span", {
3504
+ className: "flex min-w-0 flex-col gap-0.5",
3505
+ children: [(0, react_jsx_runtime.jsxs)("span", {
3506
+ className: require_use_theme.cn("flex items-center gap-1.5", cards && "font-medium"),
3507
+ children: [option?.icon ? (0, react_jsx_runtime.jsx)("span", {
3508
+ "data-testid": `${testid}:option:${key}:icon`,
3509
+ className: "contents",
3510
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3511
+ name: option.icon,
3512
+ className: "size-4 shrink-0"
3513
+ })
3514
+ }) : null, (0, react_jsx_runtime.jsx)("span", { children: label })]
3515
+ }), option?.summary === void 0 || option.summary === "" ? null : (0, react_jsx_runtime.jsx)("span", {
3516
+ "data-testid": `${testid}:option:${key}:doc`,
3517
+ className: "text-sm text-muted-foreground",
3518
+ children: option.summary
3519
+ })]
3520
+ })]
3521
+ }, key);
3522
+ };
3523
+ return (0, react_jsx_runtime.jsxs)("div", {
3524
+ role: "radiogroup",
3525
+ id,
3526
+ "aria-labelledby": ariaLabelledBy,
3527
+ "data-testid": testid,
3528
+ "aria-required": required,
3529
+ className: require_use_theme.cn("flex flex-col", cards ? "gap-2" : "gap-1.5", className),
3530
+ children: [required ? null : choice(NONE, void 0, noneLabel, empty, () => pick(void 0)), options.map((option) => choice(option.value, option, option.label, value === option.value, () => pick(option.value)))]
3531
+ });
3532
+ }
3533
+ //#endregion
3371
3534
  //#region src/enum/enum-picker.tsx
3372
3535
  const ENUM_PICKER_CLEAR_SENTINEL = "__buro_clear__";
3373
- function EnumPicker({ enumName, value, onChange, renderAs = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, className, clearable = false, clearLabel = "All" }) {
3536
+ function withSummary(summary) {
3537
+ return summary === void 0 ? {} : { summary };
3538
+ }
3539
+ function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All" }) {
3540
+ const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
3374
3541
  const app = (0, _burojs_react.useApp)();
3375
3542
  const t = (0, _burojs_react.useOptionalT)();
3376
3543
  const def = app.registry.enums.get(enumName);
@@ -3401,63 +3568,43 @@ function EnumPicker({ enumName, value, onChange, renderAs = "select", name, id,
3401
3568
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: t("field.loading", { defaultValue: "Loading…" }) })
3402
3569
  }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, {})]
3403
3570
  });
3404
- if (error || !values) return (0, react_jsx_runtime.jsxs)("span", {
3405
- "data-testid": `${tid}:error`,
3571
+ if (error || !values) return (0, react_jsx_runtime.jsxs)(require_relation_create.LoadError, {
3572
+ surface: "picker",
3573
+ error,
3574
+ testId: `${tid}:error`,
3406
3575
  className: "text-muted-foreground",
3407
- title: error?.message,
3576
+ fallback: {
3577
+ key: "relation.failed",
3578
+ default: "Failed to load options."
3579
+ },
3408
3580
  children: [
3409
3581
  "(failed to load enum ‘",
3410
3582
  enumName,
3411
3583
  "’)"
3412
3584
  ]
3413
3585
  });
3414
- if (renderAs === "radio") return (0, react_jsx_runtime.jsx)("div", {
3415
- role: "radiogroup",
3416
- "data-testid": tid,
3417
- className: require_use_theme.cn("flex flex-col gap-2", className),
3418
- "aria-required": required,
3419
- children: values.map((entry) => {
3420
- const inputId = `${id ?? tid}:${entry.value}`;
3421
- return (0, react_jsx_runtime.jsxs)("label", {
3422
- htmlFor: inputId,
3423
- className: "flex items-center gap-2",
3424
- children: [(0, react_jsx_runtime.jsx)("input", {
3425
- type: "radio",
3426
- id: inputId,
3427
- name: name ?? tid,
3428
- value: entry.value,
3429
- checked: value === entry.value,
3430
- onChange: (e) => onChange(e.target.value),
3431
- disabled,
3432
- "aria-invalid": ariaInvalid || void 0,
3433
- "aria-describedby": ariaDescribedBy,
3434
- ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3435
- "data-testid": `${tid}:option:${entry.value}`,
3436
- className: "h-4 w-4"
3437
- }), (0, react_jsx_runtime.jsx)("span", { children: (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, entry.label) })]
3438
- }, entry.value);
3439
- })
3440
- });
3441
- if (renderAs === "segmented") return (0, react_jsx_runtime.jsx)("div", {
3442
- role: "group",
3443
- "data-testid": tid,
3444
- className: require_use_theme.cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3445
- "aria-invalid": ariaInvalid || void 0,
3446
- "aria-describedby": ariaDescribedBy,
3447
- ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3448
- children: values.map((entry) => {
3449
- const isActive = value === entry.value;
3450
- return (0, react_jsx_runtime.jsx)("button", {
3451
- type: "button",
3452
- "aria-pressed": isActive,
3453
- "data-state": isActive ? "active" : "inactive",
3454
- "data-testid": `${tid}:option:${entry.value}`,
3455
- disabled,
3456
- onClick: () => onChange(entry.value),
3457
- 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"),
3458
- children: (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, entry.label)
3459
- }, entry.value);
3460
- })
3586
+ const labelOf = (entry) => (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label);
3587
+ const summaryOf = (entry) => (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${entry.value}`)?.summary || void 0;
3588
+ if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3589
+ control,
3590
+ options: values.map((entry) => ({
3591
+ value: entry.value,
3592
+ label: labelOf(entry),
3593
+ ...entry.icon === void 0 ? {} : { icon: entry.icon },
3594
+ ...withSummary(summaryOf(entry))
3595
+ })),
3596
+ value,
3597
+ onChange,
3598
+ testid: tid,
3599
+ name,
3600
+ id,
3601
+ required,
3602
+ disabled,
3603
+ ariaInvalid,
3604
+ ariaDescribedBy,
3605
+ ariaErrorMessage,
3606
+ ariaLabelledBy,
3607
+ className
3461
3608
  });
3462
3609
  const selectValue = value == null ? clearable ? ENUM_PICKER_CLEAR_SENTINEL : "" : value;
3463
3610
  const handleValueChange = (next) => {
@@ -3487,36 +3634,49 @@ function EnumPicker({ enumName, value, onChange, renderAs = "select", name, id,
3487
3634
  "data-testid": `${tid}:option:__clear__`,
3488
3635
  children: clearLabel
3489
3636
  }), values.map((entry) => {
3490
- const optionLabel = (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, entry.label);
3491
- const optionDoc = (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${entry.value}`)?.summary;
3637
+ const optionLabel = labelOf(entry);
3638
+ const optionDoc = summaryOf(entry);
3492
3639
  return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3493
3640
  value: entry.value,
3494
3641
  "data-testid": `${tid}:option:${entry.value}`,
3495
- children: optionDoc === void 0 ? optionLabel : (0, react_jsx_runtime.jsxs)("span", {
3496
- className: "flex flex-col gap-0.5",
3497
- children: [(0, react_jsx_runtime.jsx)("span", { children: optionLabel }), (0, react_jsx_runtime.jsx)("span", {
3498
- className: "text-xs leading-snug text-muted-foreground",
3499
- "data-testid": `${tid}:option:${entry.value}:doc`,
3500
- children: optionDoc
3501
- })]
3502
- })
3642
+ description: optionDoc === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3643
+ "data-testid": `${tid}:option:${entry.value}:doc`,
3644
+ children: optionDoc
3645
+ }),
3646
+ children: optionLabel
3503
3647
  }, entry.value);
3504
3648
  })] })]
3505
3649
  });
3506
3650
  }
3507
3651
  //#endregion
3652
+ //#region src/enum/resolve-enum-control.ts
3653
+ const warned = new Set();
3654
+ function resolveEnumControl(fieldControl, enumDef, where) {
3655
+ if ((0, _burojs_core.isEnumControl)(fieldControl)) return fieldControl;
3656
+ if (fieldControl !== void 0) {
3657
+ const shown = typeof fieldControl === "string" ? `'${fieldControl}'` : String(fieldControl);
3658
+ const key = `${where}\u0000${shown}`;
3659
+ if (!warned.has(key)) {
3660
+ warned.add(key);
3661
+ 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'.`);
3662
+ }
3663
+ }
3664
+ return enumDef?.control ?? "select";
3665
+ }
3666
+ //#endregion
3508
3667
  //#region src/forms/issue-severity.ts
3509
3668
  function isErrorIssue(issue) {
3510
3669
  return issue.severity === "error";
3511
3670
  }
3512
3671
  //#endregion
3513
3672
  //#region src/fields/boolean.tsx
3514
- function BooleanDisplay({ value }) {
3673
+ function BooleanDisplay({ value, text }) {
3515
3674
  const t = (0, _burojs_react.useOptionalT)();
3516
3675
  if (value == null) return (0, react_jsx_runtime.jsx)("span", {
3517
3676
  className: "text-muted-foreground",
3518
3677
  children: "—"
3519
3678
  });
3679
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
3520
3680
  return (0, react_jsx_runtime.jsx)("span", { children: value ? t("boolean.yes", { defaultValue: "Yes" }) : t("boolean.no", { defaultValue: "No" }) });
3521
3681
  }
3522
3682
  function BooleanInput({ name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
@@ -3535,17 +3695,32 @@ function BooleanInput({ name, id, value, onChange, testid, disabled, required, a
3535
3695
  }
3536
3696
  //#endregion
3537
3697
  //#region src/fields/date.tsx
3538
- function DateDisplay({ value }) {
3698
+ function DateDisplay({ value, text }) {
3699
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3700
+ value,
3701
+ text,
3702
+ format: require_filter_builder.formatDate
3703
+ });
3704
+ }
3705
+ function DateTimeDisplay({ value, text }) {
3706
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3707
+ value,
3708
+ text,
3709
+ format: require_filter_builder.formatDateTime
3710
+ });
3711
+ }
3712
+ function TemporalDisplay({ value, text, format }) {
3539
3713
  const locale = (0, _burojs_react.useOptionalLocale)();
3540
3714
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
3541
3715
  className: "text-muted-foreground",
3542
3716
  children: "—"
3543
3717
  });
3718
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
3544
3719
  const d = new Date(String(value));
3545
3720
  if (Number.isNaN(d.getTime())) return (0, react_jsx_runtime.jsx)("span", { children: String(value) });
3546
3721
  return (0, react_jsx_runtime.jsx)("span", {
3547
3722
  className: "whitespace-nowrap",
3548
- children: require_filter_builder.formatDate(d, locale)
3723
+ children: format(d, locale)
3549
3724
  });
3550
3725
  }
3551
3726
  function toIsoDate(v) {
@@ -3556,13 +3731,29 @@ function toIsoDate(v) {
3556
3731
  if (Number.isNaN(d.getTime())) return "";
3557
3732
  return d.toISOString().slice(0, 10);
3558
3733
  }
3559
- function DateInput({ name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
3734
+ function DateInput(props) {
3735
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3736
+ ...props,
3737
+ type: "date",
3738
+ toText: toIsoDate,
3739
+ fromText: (text) => text || null
3740
+ });
3741
+ }
3742
+ function DateTimeInput(props) {
3743
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3744
+ ...props,
3745
+ type: "datetime-local",
3746
+ toText: require_filter_builder.toLocalDateTimeText,
3747
+ fromText: (text) => require_filter_builder.fromLocalDateTimeText(text) ?? null
3748
+ });
3749
+ }
3750
+ function TemporalInput({ type, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
3560
3751
  return (0, react_jsx_runtime.jsx)(require_input.Input, {
3561
3752
  name,
3562
3753
  id,
3563
- type: "date",
3564
- value: toIsoDate(value),
3565
- onChange: (e) => onChange(e.target.value || null),
3754
+ type,
3755
+ value: toText(value),
3756
+ onChange: (e) => onChange(fromText(e.target.value)),
3566
3757
  "data-testid": testid,
3567
3758
  disabled,
3568
3759
  required,
@@ -3574,23 +3765,15 @@ function DateInput({ name, id, value, onChange, testid, disabled, required, aria
3574
3765
  }
3575
3766
  //#endregion
3576
3767
  //#region src/fields/enum.tsx
3577
- function optionLabel(caps, field, value, inline) {
3578
- const ns = (0, _burojs_core.enumNamespaceOf)(field);
3579
- if (ns) return (0, _burojs_core.resolveEnumLabel)(caps, ns, value, inline);
3580
- return field ? (0, _burojs_core.resolveContentSlot)(caps, [(0, _burojs_core.fieldOptionKey)(field.name, value)], { default: inline }) : inline;
3581
- }
3582
- function useOptionCaps(resource) {
3583
- return (0, _burojs_react.useI18nCaps)((0, react.useContext)(_burojs_react.ResourceContext).resource ?? resource);
3584
- }
3585
3768
  function EnumDisplay({ value, options, field, resource }) {
3586
- const caps = useOptionCaps(resource);
3769
+ const caps = (0, _burojs_react.useOptionCaps)(resource);
3770
+ const enumDef = (0, _burojs_react.useBoundEnum)(field);
3587
3771
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
3588
3772
  className: "text-muted-foreground",
3589
3773
  children: "—"
3590
3774
  });
3591
3775
  const opt = options?.find((o) => o.value === String(value));
3592
- const inline = typeof opt?.label === "string" ? opt.label : String(value);
3593
- const label = optionLabel(caps, field, String(value), inline);
3776
+ const label = (0, _burojs_react.resolveOptionLabel)(caps, field, String(value), opt, enumDef);
3594
3777
  return (0, react_jsx_runtime.jsxs)("span", {
3595
3778
  className: "inline-flex items-center gap-1",
3596
3779
  children: [opt?.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
@@ -3599,9 +3782,36 @@ function EnumDisplay({ value, options, field, resource }) {
3599
3782
  }) : null, label]
3600
3783
  });
3601
3784
  }
3602
- function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, resource }) {
3785
+ function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource }) {
3603
3786
  const t = (0, _burojs_react.useOptionalT)();
3604
- const caps = useOptionCaps(resource);
3787
+ const caps = (0, _burojs_react.useOptionCaps)(resource);
3788
+ const enumDef = (0, _burojs_react.useBoundEnum)(field);
3789
+ const ns = (0, _burojs_core.enumNamespaceOf)(field);
3790
+ const control = resolveEnumControl(field?.ui?.control, enumDef, `field ${field?.name ?? name}`);
3791
+ const resolved = (options ?? []).map((o) => {
3792
+ const summary = ns === void 0 ? void 0 : (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${o.value}`)?.summary;
3793
+ return {
3794
+ value: o.value,
3795
+ label: (0, _burojs_react.resolveOptionLabel)(caps, field, o.value, o, enumDef),
3796
+ ...o.icon === void 0 ? {} : { icon: o.icon },
3797
+ ...summary === void 0 ? {} : { summary }
3798
+ };
3799
+ });
3800
+ if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3801
+ control,
3802
+ options: resolved,
3803
+ value,
3804
+ onChange,
3805
+ testid: testid ?? name,
3806
+ name,
3807
+ id,
3808
+ required,
3809
+ disabled,
3810
+ ariaInvalid,
3811
+ ariaDescribedBy,
3812
+ ariaErrorMessage,
3813
+ ariaLabelledBy
3814
+ });
3605
3815
  return (0, react_jsx_runtime.jsxs)(require_filter_builder.Select, {
3606
3816
  value: value ?? "",
3607
3817
  onValueChange: onChange,
@@ -3616,14 +3826,19 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3616
3826
  "aria-describedby": ariaDescribedBy,
3617
3827
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3618
3828
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3619
- }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: options?.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3829
+ }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: resolved.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3620
3830
  value: o.value,
3831
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
3832
+ description: o.summary === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3833
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
3834
+ children: o.summary
3835
+ }),
3621
3836
  children: (0, react_jsx_runtime.jsxs)("span", {
3622
3837
  className: "inline-flex items-center gap-1.5",
3623
3838
  children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3624
3839
  name: o.icon,
3625
3840
  className: "size-3.5 shrink-0 text-muted-foreground"
3626
- }) : null, optionLabel(caps, field, o.value, typeof o.label === "string" ? o.label : o.value)]
3841
+ }) : null, o.label]
3627
3842
  })
3628
3843
  }, o.value)) })]
3629
3844
  });
@@ -3996,6 +4211,7 @@ function JsonDisplay({ value, presentation, testid }) {
3996
4211
  });
3997
4212
  }
3998
4213
  function JsonInput({ name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
4214
+ const t = (0, _burojs_react.useOptionalT)();
3999
4215
  const seed = react.useMemo(() => {
4000
4216
  if (value == null || value === "") return "";
4001
4217
  return require_place_node.toDisplayText(value).text;
@@ -4039,13 +4255,13 @@ function JsonInput({ name, id, value, onChange, testid, disabled, required, aria
4039
4255
  }), invalid && (0, react_jsx_runtime.jsx)("p", {
4040
4256
  className: "text-[13px] leading-snug text-destructive",
4041
4257
  "data-testid": `${testid}-json-error`,
4042
- children: "Некорректный JSON — изменения не будут сохранены, пока он не станет валидным."
4258
+ children: t("field.jsonInvalid", { defaultValue: "Invalid JSON. Changes will not be saved until it is valid." })
4043
4259
  })]
4044
4260
  });
4045
4261
  }
4046
4262
  //#endregion
4047
4263
  //#region src/fields/lazy-relation-many.tsx
4048
- const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-B-NCEUgX.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4264
+ const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-DzuGJpEl.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4049
4265
  function LazyRelationManyInput(props) {
4050
4266
  return (0, react_jsx_runtime.jsx)(react.Suspense, {
4051
4267
  fallback: (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
@@ -4058,8 +4274,8 @@ function LazyRelationManyInput(props) {
4058
4274
  }
4059
4275
  //#endregion
4060
4276
  //#region src/fields/lazy-rich-text.tsx
4061
- const RichTextDisplay = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-vTyVjDoa.cjs")).then((module) => ({ default: module.RichTextDisplay })));
4062
- const RichTextInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-vTyVjDoa.cjs")).then((module) => ({ default: module.RichTextInput })));
4277
+ const RichTextDisplay = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-C_7JCvRo.cjs")).then((module) => ({ default: module.RichTextDisplay })));
4278
+ const RichTextInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./rich-text-C_7JCvRo.cjs")).then((module) => ({ default: module.RichTextInput })));
4063
4279
  function RichTextDisplayLoading() {
4064
4280
  const t = (0, _burojs_react.useOptionalT)();
4065
4281
  return (0, react_jsx_runtime.jsx)("div", {
@@ -4116,12 +4332,13 @@ function isIdentifier(field) {
4116
4332
  const n = field?.name;
4117
4333
  return n === "id" || typeof n === "string" && n.endsWith("_id");
4118
4334
  }
4119
- function NumberDisplay({ value, field }) {
4335
+ function NumberDisplay({ value, field, text }) {
4120
4336
  const locale = (0, _burojs_react.useOptionalLocale)();
4121
4337
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4122
4338
  className: "text-muted-foreground",
4123
4339
  children: "—"
4124
4340
  });
4341
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
4125
4342
  let raw = value;
4126
4343
  if (typeof raw === "string") raw = unquote(raw);
4127
4344
  const n = typeof raw === "number" ? raw : Number(raw);
@@ -4156,6 +4373,196 @@ function NumberInput({ name, id, value, onChange, testid, placeholder, disabled,
4156
4373
  });
4157
4374
  }
4158
4375
  //#endregion
4376
+ //#region src/fields/link-keys-display.tsx
4377
+ const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4378
+ function qualify(name) {
4379
+ try {
4380
+ const ref = (0, _burojs_core.normalizeEntityRef)(name);
4381
+ return ref.namespace === "default" ? ref.id : `${ref.namespace}:${ref.id}`;
4382
+ } catch {
4383
+ return;
4384
+ }
4385
+ }
4386
+ function idFieldOf(def) {
4387
+ const declared = (def?.data)?.idField;
4388
+ return typeof declared === "string" && declared.length > 0 ? declared : "id";
4389
+ }
4390
+ function byOf(field) {
4391
+ const by = isRecord$1(field) && isRecord$1(field.meta) ? field.meta.by : void 0;
4392
+ return typeof by === "string" && by.length > 0 ? by : void 0;
4393
+ }
4394
+ const chipClassName = "inline-flex items-center rounded-md border border-border bg-muted/40 px-1.5 py-0.5 text-xs";
4395
+ function LinkKeysDisplay(props) {
4396
+ const { field, record } = props;
4397
+ const owner = props.owner ?? props.resource ?? "";
4398
+ const name = field?.name ?? "";
4399
+ const app = (0, _burojs_react.useApp)();
4400
+ const t = (0, _burojs_react.useOptionalT)();
4401
+ const tid = (0, _burojs_react.useTestIds)();
4402
+ const ownerDef = owner === "" ? void 0 : app.registry.get(owner);
4403
+ const declaration = ownerDef === void 0 ? void 0 : (0, _burojs_core.declaredField)(ownerDef, name);
4404
+ const link = isRecord$1(declaration) ? (0, _burojs_core.linkOf)(declaration) : void 0;
4405
+ const junctionName = link === void 0 ? void 0 : qualify(link.junction);
4406
+ const junctionDef = junctionName === void 0 ? void 0 : app.registry.get(junctionName);
4407
+ const junctionField = (key) => junctionDef === void 0 ? void 0 : (0, _burojs_core.declaredField)(junctionDef, key);
4408
+ const ownerField = link === void 0 ? idFieldOf(ownerDef) : byOf(junctionField(link.sourceKey)) ?? idFieldOf(ownerDef);
4409
+ const targetBy = link === void 0 ? void 0 : byOf(junctionField(link.targetKey));
4410
+ const ownerKey = record?.[ownerField];
4411
+ const { keys, complete, isLoading, error } = (0, _burojs_react.useLinkKeys)(owner, name, ownerKey);
4412
+ const [missed, setMissed] = (0, react.useState)(() => new Set());
4413
+ const onMiss = (0, react.useCallback)((key, isMiss) => {
4414
+ setMissed((current) => {
4415
+ if (current.has(key) === isMiss) return current;
4416
+ const next = new Set(current);
4417
+ if (isMiss) next.add(key);
4418
+ else next.delete(key);
4419
+ return next;
4420
+ });
4421
+ }, []);
4422
+ const target = (isRecord$1(declaration) && isRecord$1(declaration.meta) ? declaration.meta.to : void 0) ?? field?.meta?.to;
4423
+ const chipField = (0, react.useMemo)(() => ({
4424
+ name,
4425
+ meta: {
4426
+ ...target === void 0 ? {} : { to: target },
4427
+ ...targetBy === void 0 ? {} : { by: targetBy }
4428
+ },
4429
+ ...field?.ui === void 0 ? {} : { ui: field.ui }
4430
+ }), [
4431
+ name,
4432
+ target,
4433
+ field?.ui,
4434
+ targetBy
4435
+ ]);
4436
+ const chipsId = tid.linkChips(owner, name);
4437
+ if (error) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
4438
+ surface: "relation",
4439
+ error,
4440
+ ...typeof target === "string" ? { resource: target } : {},
4441
+ testId: tid.linkError(owner, name),
4442
+ className: "text-destructive text-xs",
4443
+ attributes: { role: "status" },
4444
+ fallback: {
4445
+ key: "field.link.failed",
4446
+ default: "Links could not be loaded"
4447
+ }
4448
+ });
4449
+ if (keys === void 0) {
4450
+ if (!isLoading) return (0, react_jsx_runtime.jsx)("span", {
4451
+ "data-testid": "relation-many-display:empty",
4452
+ className: "text-muted-foreground",
4453
+ children: "—"
4454
+ });
4455
+ return (0, react_jsx_runtime.jsx)("span", {
4456
+ "data-testid": `${chipsId}:loading`,
4457
+ className: "inline-block h-5 w-20 animate-pulse rounded bg-muted",
4458
+ "aria-busy": "true"
4459
+ });
4460
+ }
4461
+ if (!complete) return (0, react_jsx_runtime.jsx)("span", {
4462
+ "data-testid": chipsId,
4463
+ className: "inline-flex flex-wrap gap-1",
4464
+ children: (0, react_jsx_runtime.jsx)("span", {
4465
+ "data-testid": tid.linkIncomplete(owner, name),
4466
+ className: "text-muted-foreground",
4467
+ children: t("field.link.incomplete", {
4468
+ count: keys.length,
4469
+ defaultValue: "More than {{count}} links"
4470
+ })
4471
+ })
4472
+ });
4473
+ if (keys.length === 0) return (0, react_jsx_runtime.jsx)("span", {
4474
+ "data-testid": "relation-many-display:empty",
4475
+ className: "text-muted-foreground",
4476
+ children: "—"
4477
+ });
4478
+ const hidden = keys.filter((key) => missed.has(String(key))).length;
4479
+ return (0, react_jsx_runtime.jsxs)("span", {
4480
+ "data-testid": chipsId,
4481
+ className: "inline-flex flex-wrap gap-1",
4482
+ children: [keys.map((key) => (0, react_jsx_runtime.jsx)(LinkChip, {
4483
+ value: key,
4484
+ field: chipField,
4485
+ onMiss
4486
+ }, String(key))), hidden > 0 ? (0, react_jsx_runtime.jsx)("span", {
4487
+ "data-testid": tid.linkHidden(owner, name),
4488
+ className: `${chipClassName} text-muted-foreground`,
4489
+ children: t("field.link.hidden", {
4490
+ count: hidden,
4491
+ defaultValue: "{{count}} not visible"
4492
+ })
4493
+ }) : null]
4494
+ });
4495
+ }
4496
+ function LinkChip({ value, field, onMiss }) {
4497
+ const gate = (0, _burojs_react.useEntryGate)();
4498
+ const meta = field.meta;
4499
+ let to;
4500
+ try {
4501
+ to = meta?.to === void 0 ? void 0 : (0, _burojs_core.resourceKey)(meta.to);
4502
+ } catch {
4503
+ to = void 0;
4504
+ }
4505
+ const answer = to === void 0 ? void 0 : gate(to, "show");
4506
+ if (!(to !== void 0 && answer !== void 0 && answer.state !== "undecided" && answer.state !== "hidden" && answer.state !== "disabled")) return (0, react_jsx_runtime.jsx)("span", {
4507
+ className: chipClassName,
4508
+ children: (0, react_jsx_runtime.jsx)(require_relation_create.RelationDisplay, {
4509
+ value,
4510
+ field
4511
+ })
4512
+ });
4513
+ return (0, react_jsx_runtime.jsx)(ReadChip, {
4514
+ to,
4515
+ value,
4516
+ field,
4517
+ onMiss
4518
+ });
4519
+ }
4520
+ function ReadChip({ to, value, field, onMiss }) {
4521
+ const app = (0, _burojs_react.useApp)();
4522
+ const by = field.meta?.by;
4523
+ const { record, isLoading, error, ambiguous } = (0, _burojs_react.useRelatedRecord)(to, value, typeof by === "string" ? { by } : void 0);
4524
+ const miss = app.registry.get(to) !== void 0 && !isLoading && !error && !ambiguous && !record;
4525
+ const key = String(value);
4526
+ (0, react.useEffect)(() => {
4527
+ onMiss(key, miss);
4528
+ }, [
4529
+ onMiss,
4530
+ key,
4531
+ miss
4532
+ ]);
4533
+ (0, react.useEffect)(() => () => onMiss(key, false), [onMiss, key]);
4534
+ if (miss) return null;
4535
+ return (0, react_jsx_runtime.jsx)("span", {
4536
+ className: chipClassName,
4537
+ children: (0, react_jsx_runtime.jsx)(require_relation_create.RelationDisplay, {
4538
+ value,
4539
+ field
4540
+ })
4541
+ });
4542
+ }
4543
+ function RelationManyDisplay(props) {
4544
+ const app = (0, _burojs_react.useApp)();
4545
+ const owner = props.owner ?? props.resource ?? "";
4546
+ const ownerDef = owner === "" ? void 0 : app.registry.get(owner);
4547
+ const declared = ownerDef === void 0 || props.field?.name === void 0 ? void 0 : (0, _burojs_core.declaredField)(ownerDef, props.field.name);
4548
+ if (isRecord$1(declared) && (0, _burojs_core.linkOf)(declared) !== void 0) return (0, react_jsx_runtime.jsx)(LinkKeysDisplay, { ...props });
4549
+ const { value, field } = props;
4550
+ const keys = Array.isArray(value) ? value : [];
4551
+ if (keys.length === 0) return (0, react_jsx_runtime.jsx)("span", {
4552
+ "data-testid": "relation-many-display:empty",
4553
+ className: "text-muted-foreground",
4554
+ children: "—"
4555
+ });
4556
+ return (0, react_jsx_runtime.jsx)("span", {
4557
+ className: "inline-flex flex-wrap gap-x-2",
4558
+ "data-testid": "relation-many-display",
4559
+ children: keys.map((key, index) => (0, react_jsx_runtime.jsx)(require_relation_create.RelationDisplay, {
4560
+ value: key,
4561
+ field
4562
+ }, `${String(key)}:${index}`))
4563
+ });
4564
+ }
4565
+ //#endregion
4159
4566
  //#region src/fields/relation-meta-schema.ts
4160
4567
  const isRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4161
4568
  const relationMetaSchema = Object.freeze({ "~standard": Object.freeze({
@@ -4167,7 +4574,7 @@ const relationMetaSchema = Object.freeze({ "~standard": Object.freeze({
4167
4574
  path: []
4168
4575
  }] };
4169
4576
  const issues = [];
4170
- const { to, by, resolve, searchField, candidates } = value;
4577
+ const { to, by, resolve, searchField, candidates, scope } = value;
4171
4578
  if (to !== void 0 && !(typeof to === "string" && to.length > 0) && !(isRecord(to) && (typeof to.id === "string" || isRecord(to.ref)))) issues.push({
4172
4579
  message: "must be a resource name or reference",
4173
4580
  path: ["to"]
@@ -4188,16 +4595,21 @@ const relationMetaSchema = Object.freeze({ "~standard": Object.freeze({
4188
4595
  message: "must be an array of conditions",
4189
4596
  path: ["candidates"]
4190
4597
  });
4598
+ if (scope !== void 0 && scope !== "context" && scope !== "session" && scope !== "none") issues.push({
4599
+ message: "must be 'context', 'session' or 'none'",
4600
+ path: ["scope"]
4601
+ });
4191
4602
  return issues.length > 0 ? { issues } : { value };
4192
4603
  }
4193
4604
  }) });
4194
4605
  //#endregion
4195
4606
  //#region src/fields/text.tsx
4196
- function TextDisplay({ value }) {
4607
+ function TextDisplay({ value, text: formatted }) {
4197
4608
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4198
4609
  className: "text-muted-foreground",
4199
4610
  children: "—"
4200
4611
  });
4612
+ if (formatted !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: formatted });
4201
4613
  const { text, isStructured } = require_place_node.toDisplayText(value);
4202
4614
  return isStructured ? (0, react_jsx_runtime.jsx)("span", {
4203
4615
  className: "font-mono text-xs break-all",
@@ -4226,23 +4638,26 @@ function TextInput({ name, id, value, onChange, testid, placeholder, disabled, r
4226
4638
  }
4227
4639
  //#endregion
4228
4640
  //#region src/fields/textarea.tsx
4229
- function TextareaDisplay({ value }) {
4641
+ function TextareaDisplay({ value, text: formatted }) {
4230
4642
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4231
4643
  className: "text-muted-foreground",
4232
4644
  children: "—"
4233
4645
  });
4234
- const { text, isStructured } = require_place_node.toDisplayText(value);
4646
+ const { text, isStructured } = formatted === void 0 ? require_place_node.toDisplayText(value) : {
4647
+ text: formatted,
4648
+ isStructured: false
4649
+ };
4235
4650
  return (0, react_jsx_runtime.jsx)("pre", {
4236
4651
  className: isStructured ? "whitespace-pre-wrap break-all font-mono text-xs" : "whitespace-pre-wrap font-sans text-sm",
4237
4652
  children: text
4238
4653
  });
4239
4654
  }
4240
- function CodeDisplay({ value, presentation, testid }) {
4655
+ function CodeDisplay({ value, text: formatted, presentation, testid }) {
4241
4656
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
4242
4657
  className: "text-muted-foreground",
4243
4658
  children: "—"
4244
4659
  });
4245
- const { text } = require_place_node.toDisplayText(value);
4660
+ const text = formatted ?? require_place_node.toDisplayText(value).text;
4246
4661
  return (0, react_jsx_runtime.jsx)("pre", {
4247
4662
  "data-testid": testid,
4248
4663
  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",
@@ -4286,30 +4701,39 @@ function TextareaInput({ name, id, value, onChange, testid, placeholder, disable
4286
4701
  //#endregion
4287
4702
  //#region src/fields/default-renderers.ts
4288
4703
  function legacyField(props) {
4289
- const name = typeof props.path.at(-1) === "string" ? props.path.at(-1) : "field";
4704
+ const name = (0, _burojs_react.optionFieldName)(props.path);
4705
+ const texts = props.field.texts;
4290
4706
  return Object.freeze({
4291
4707
  name,
4292
4708
  meta: props.meta,
4293
4709
  ui: props.ui,
4294
- codec: props.field.codec
4710
+ ...texts === void 0 ? {} : { texts }
4295
4711
  });
4296
4712
  }
4297
- function legacyOptions(options) {
4713
+ function legacyOptions(options, field) {
4298
4714
  if (options.length === 0) return void 0;
4299
- return options.map((option) => Object.freeze({
4300
- value: String(option.value ?? ""),
4301
- label: option.label,
4302
- ...typeof option.meta?.icon === "string" ? { icon: option.meta.icon } : {}
4303
- }));
4715
+ return options.map((option) => {
4716
+ const value = String(option.value ?? "");
4717
+ return Object.freeze({
4718
+ value,
4719
+ label: (0, _burojs_core.fieldOptionText)(field, value) ?? value,
4720
+ ...typeof option.meta?.icon === "string" ? { icon: option.meta.icon } : {}
4721
+ });
4722
+ });
4723
+ }
4724
+ function registryKey(ref) {
4725
+ return ref.namespace === "default" ? ref.id : (0, _burojs_core.formatEntityRef)(ref);
4304
4726
  }
4305
4727
  function display(renderer) {
4306
4728
  return function ShadcnDisplay(props) {
4307
4729
  return (0, react.createElement)(renderer, {
4308
4730
  value: props.value,
4731
+ ...props.text === void 0 ? {} : { text: props.text },
4309
4732
  multiple: props.multiple,
4310
4733
  field: legacyField(props),
4311
- options: legacyOptions(props.options),
4734
+ options: legacyOptions(props.options, props.field),
4312
4735
  resource: props.resource.id,
4736
+ owner: registryKey(props.resource),
4313
4737
  record: props.record,
4314
4738
  presentation: props.presentation,
4315
4739
  testid: props.testIds.display
@@ -4334,7 +4758,7 @@ function input(renderer) {
4334
4758
  multiple: props.multiple,
4335
4759
  onChange: props.onChange ?? (() => void 0),
4336
4760
  testid: props.testIds.input,
4337
- options: legacyOptions(props.options),
4761
+ options: legacyOptions(props.options, props.field),
4338
4762
  placeholder: typeof props.ui.placeholder === "string" ? props.ui.placeholder : void 0,
4339
4763
  disabled: props.disabled,
4340
4764
  required: props.field.required === true,
@@ -4342,12 +4766,14 @@ function input(renderer) {
4342
4766
  ariaInvalid: props.issues.some(isErrorIssue),
4343
4767
  ariaDescribedBy: props.accessibility.description,
4344
4768
  ariaErrorMessage: props.accessibility.error,
4769
+ ariaLabelledBy: props.accessibility.label,
4345
4770
  field: legacyField(props),
4346
4771
  resource: props.resource.id,
4347
4772
  record: props.record,
4348
4773
  relationSeeds: props.relationSeeds,
4349
4774
  fixedFilters: props.fixedFilters,
4350
- metaSources: props.metaSources
4775
+ metaSources: props.metaSources,
4776
+ link: props.link
4351
4777
  });
4352
4778
  };
4353
4779
  }
@@ -4395,9 +4821,27 @@ function scalarOrCollection(renderer, layout) {
4395
4821
  });
4396
4822
  }
4397
4823
  function enumName(ui) {
4398
- const value = ui.enum;
4399
- if (typeof value === "string" && value.length > 0) return value;
4400
- if (value !== null && typeof value === "object" && typeof value.id === "string") return value.id;
4824
+ return (0, _burojs_core_internal.enumBindingKey)(ui.enum);
4825
+ }
4826
+ function RegistryEnumInput(props) {
4827
+ const app = (0, _burojs_react.useOptionalApp)();
4828
+ 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}`);
4829
+ return (0, react.createElement)(EnumPicker, {
4830
+ enumName: props.enumName,
4831
+ control,
4832
+ value: props.value == null ? void 0 : String(props.value),
4833
+ onChange: props.onChange ?? (() => void 0),
4834
+ name: props.accessibility.input,
4835
+ id: props.accessibility.input,
4836
+ testid: props.testIds.input,
4837
+ placeholder: typeof props.ui.placeholder === "string" ? props.ui.placeholder : void 0,
4838
+ disabled: props.disabled,
4839
+ required: props.field.required === true,
4840
+ ariaInvalid: props.issues.some(isErrorIssue),
4841
+ ariaDescribedBy: props.accessibility.description,
4842
+ ariaErrorMessage: props.accessibility.error,
4843
+ ariaLabelledBy: props.accessibility.label
4844
+ });
4401
4845
  }
4402
4846
  function enumAware(renderer, layout) {
4403
4847
  const FallbackInput = input(renderer.Input);
@@ -4407,19 +4851,9 @@ function enumAware(renderer, layout) {
4407
4851
  return Object.freeze({
4408
4852
  Input: (props) => {
4409
4853
  const name = enumName(props.ui);
4410
- if (name !== void 0) return (0, react.createElement)(EnumPicker, {
4411
- enumName: name,
4412
- value: props.value == null ? void 0 : String(props.value),
4413
- onChange: props.onChange ?? (() => void 0),
4414
- name: props.accessibility.input,
4415
- id: props.accessibility.input,
4416
- testid: props.testIds.input,
4417
- placeholder: typeof props.ui.placeholder === "string" ? props.ui.placeholder : void 0,
4418
- disabled: props.disabled,
4419
- required: props.field.required === true,
4420
- ariaInvalid: props.issues.some(isErrorIssue),
4421
- ariaDescribedBy: props.accessibility.description,
4422
- ariaErrorMessage: props.accessibility.error
4854
+ if (name !== void 0) return (0, react.createElement)(RegistryEnumInput, {
4855
+ ...props,
4856
+ enumName: name
4423
4857
  });
4424
4858
  if (props.options.length > 0) return (0, react.createElement)(OptionedInput, props);
4425
4859
  return (0, react.createElement)(FallbackInput, props);
@@ -4454,6 +4888,10 @@ const date = {
4454
4888
  Display: DateDisplay,
4455
4889
  Input: DateInput
4456
4890
  };
4891
+ const dateTime = {
4892
+ Display: DateTimeDisplay,
4893
+ Input: DateTimeInput
4894
+ };
4457
4895
  const en = {
4458
4896
  Display: EnumDisplay,
4459
4897
  Input: EnumInput
@@ -4463,7 +4901,7 @@ const ta = {
4463
4901
  Input: TextareaInput
4464
4902
  };
4465
4903
  const rel = {
4466
- Display: require_search_access.RelationDisplay,
4904
+ Display: require_relation_create.RelationDisplay,
4467
4905
  Input: require_relation_picker.RelationPickerInput
4468
4906
  };
4469
4907
  const file = {
@@ -4475,7 +4913,7 @@ const rich = {
4475
4913
  Input: LazyRichTextInput
4476
4914
  };
4477
4915
  const relationMany = collection({
4478
- Display: require_search_access.RelationManyDisplay,
4916
+ Display: RelationManyDisplay,
4479
4917
  Input: LazyRelationManyInput
4480
4918
  });
4481
4919
  const shadcnFieldImplementations = Object.freeze({
@@ -4489,9 +4927,9 @@ const shadcnFieldImplementations = Object.freeze({
4489
4927
  number: scalar(num),
4490
4928
  boolean: scalar(bool),
4491
4929
  date: scalar(date),
4492
- dateTime: scalar(date),
4493
- "date-time": scalar(date),
4494
- "default:date-time": scalar(date),
4930
+ dateTime: scalar(dateTime),
4931
+ "date-time": scalar(dateTime),
4932
+ "default:date-time": scalar(dateTime),
4495
4933
  enum: enumAware(en),
4496
4934
  json: scalar({
4497
4935
  Display: JsonDisplay,
@@ -4533,7 +4971,8 @@ function DisplayBody(props) {
4533
4971
  }
4534
4972
  //#endregion
4535
4973
  //#region src/enum/enum-display.tsx
4536
- function EnumDisplay$1({ enumName, value, variant = "badge", testid, className }) {
4974
+ function EnumDisplay$1({ enumName: enumInput, value, variant = "badge", testid, className }) {
4975
+ const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
4537
4976
  const app = (0, _burojs_react.useApp)();
4538
4977
  const caps = (0, _burojs_react.useI18nCaps)();
4539
4978
  const def = app.registry.enums.get(enumName);
@@ -4563,7 +5002,7 @@ function EnumDisplay$1({ enumName, value, variant = "badge", testid, className }
4563
5002
  children: value
4564
5003
  });
4565
5004
  const entry = values?.find((v) => v.value === value);
4566
- const label = entry === void 0 && def?.fallback ? (0, _burojs_core.resolveContentSlot)(caps, [(0, _burojs_core.enumFallbackKey)(ns)], { default: def.fallback.label }) ?? value : (0, _burojs_core.resolveEnumLabel)(caps, ns, value, entry?.label);
5005
+ const label = entry === void 0 && (def?.fallback !== void 0 || (0, _burojs_core.enumFallbackText)(def) !== void 0) ? (0, _burojs_core.resolveContentSlot)(caps, [(0, _burojs_core.enumFallbackKey)(ns)], { default: (0, _burojs_core.enumFallbackText)(def) }) ?? value : (0, _burojs_core.resolveEnumLabel)(caps, ns, value, (0, _burojs_core.enumValueText)(def, value) ?? entry?.label);
4567
5006
  const icon = entry?.icon;
4568
5007
  if (variant === "icon-label") return (0, react_jsx_runtime.jsxs)("span", {
4569
5008
  "data-testid": id,
@@ -4581,159 +5020,6 @@ function EnumDisplay$1({ enumName, value, variant = "badge", testid, className }
4581
5020
  });
4582
5021
  }
4583
5022
  //#endregion
4584
- //#region src/data-table/data-table-faceted-filter.tsx
4585
- function DataTableFacetedFilter({ column, title, options = [], loadOptions, selectedLabelFor, searchPlaceholder, emptyText, getTestId, className }) {
4586
- const t = (0, _burojs_react.useOptionalT)();
4587
- const filterValue = column.getFilterValue();
4588
- const selected = (0, react.useMemo)(() => {
4589
- if (Array.isArray(filterValue)) return new Set(filterValue.map(String));
4590
- return new Set();
4591
- }, [filterValue]);
4592
- const [search, setSearch] = (0, react.useState)("");
4593
- const [asyncOptions, setAsyncOptions] = (0, react.useState)([]);
4594
- const [loading, setLoading] = (0, react.useState)(false);
4595
- const debounceRef = (0, react.useRef)(null);
4596
- const loadOptionsRef = (0, react.useRef)(loadOptions);
4597
- (0, react.useEffect)(() => {
4598
- loadOptionsRef.current = loadOptions;
4599
- });
4600
- (0, react.useEffect)(() => {
4601
- if (!loadOptionsRef.current) return;
4602
- setLoading(true);
4603
- if (debounceRef.current !== null) clearTimeout(debounceRef.current);
4604
- let cancelled = false;
4605
- debounceRef.current = setTimeout(() => {
4606
- const loader = loadOptionsRef.current;
4607
- if (!loader) return;
4608
- loader(search).then((results) => {
4609
- if (!cancelled) {
4610
- setAsyncOptions(results);
4611
- setLoading(false);
4612
- }
4613
- }).catch(() => {
4614
- if (!cancelled) setLoading(false);
4615
- });
4616
- }, 250);
4617
- return () => {
4618
- cancelled = true;
4619
- if (debounceRef.current !== null) clearTimeout(debounceRef.current);
4620
- };
4621
- }, [search]);
4622
- const effectiveOptions = loadOptions ? asyncOptions : options;
4623
- const labelFor = (value) => {
4624
- const opt = effectiveOptions.find((o) => o.value === value);
4625
- if (opt) return opt.label;
4626
- return selectedLabelFor?.(value) ?? value;
4627
- };
4628
- const toggle = (value) => {
4629
- const next = new Set(selected);
4630
- if (next.has(value)) next.delete(value);
4631
- else next.add(value);
4632
- column.setFilterValue(next.size === 0 ? void 0 : Array.from(next));
4633
- };
4634
- const selectedValues = Array.from(selected);
4635
- return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, { children: [(0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
4636
- asChild: true,
4637
- children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
4638
- type: "button",
4639
- variant: "outline",
4640
- size: "sm",
4641
- "data-testid": getTestId?.("trigger"),
4642
- className: require_use_theme.cn("h-8 border-dashed", className),
4643
- children: [
4644
- (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCirclePlus, {
4645
- className: "mr-2 h-4 w-4",
4646
- "aria-hidden": "true"
4647
- }),
4648
- title,
4649
- selected.size > 0 && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
4650
- (0, react_jsx_runtime.jsx)("span", {
4651
- className: "mx-2 h-4 w-px bg-border",
4652
- "aria-hidden": "true"
4653
- }),
4654
- (0, react_jsx_runtime.jsx)(require_filter_builder.Badge, {
4655
- variant: "secondary",
4656
- className: "rounded-sm px-1 font-normal lg:hidden",
4657
- children: selected.size
4658
- }),
4659
- (0, react_jsx_runtime.jsx)("div", {
4660
- className: "hidden gap-1 lg:flex",
4661
- children: selected.size > 2 ? (0, react_jsx_runtime.jsx)(require_filter_builder.Badge, {
4662
- variant: "secondary",
4663
- className: "rounded-sm px-1 font-normal",
4664
- children: t("table.selectedCount", {
4665
- count: selected.size,
4666
- defaultValue: "{{count}} selected"
4667
- })
4668
- }) : selectedValues.map((value) => (0, react_jsx_runtime.jsx)(require_filter_builder.Badge, {
4669
- variant: "secondary",
4670
- className: "rounded-sm px-1 font-normal",
4671
- children: labelFor(value)
4672
- }, value))
4673
- })
4674
- ] })
4675
- ]
4676
- })
4677
- }), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
4678
- className: "w-[220px] p-0",
4679
- align: "start",
4680
- children: (0, react_jsx_runtime.jsxs)(require_search_access.Command, {
4681
- shouldFilter: !loadOptions,
4682
- children: [
4683
- (0, react_jsx_runtime.jsx)(require_search_access.CommandInput, {
4684
- placeholder: searchPlaceholder ?? title,
4685
- "data-testid": getTestId?.("search"),
4686
- ...loadOptions ? {
4687
- value: search,
4688
- onValueChange: setSearch
4689
- } : {}
4690
- }),
4691
- (0, react_jsx_runtime.jsxs)(require_search_access.CommandList, { children: [
4692
- loading && (0, react_jsx_runtime.jsx)("div", {
4693
- className: "py-6 text-center text-sm text-muted-foreground",
4694
- children: t("list.loadingShort", { defaultValue: "Loading…" })
4695
- }),
4696
- (0, react_jsx_runtime.jsx)(require_search_access.CommandEmpty, { children: emptyText ?? t("relation.noResults", { defaultValue: "No results." }) }),
4697
- (0, react_jsx_runtime.jsx)(require_search_access.CommandGroup, { children: effectiveOptions.map((opt) => {
4698
- const isSelected = selected.has(opt.value);
4699
- const Icon = opt.icon;
4700
- return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
4701
- value: opt.label,
4702
- "data-testid": getTestId?.("option", opt.value),
4703
- role: "option",
4704
- "aria-selected": isSelected,
4705
- "aria-checked": isSelected,
4706
- onSelect: () => toggle(opt.value),
4707
- children: [
4708
- (0, react_jsx_runtime.jsx)("span", {
4709
- 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"),
4710
- "aria-hidden": "true",
4711
- children: isSelected && (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, { className: "h-3.5 w-3.5" })
4712
- }),
4713
- Icon && (0, react_jsx_runtime.jsx)(Icon, {
4714
- className: "mr-2 h-4 w-4 text-muted-foreground",
4715
- "aria-hidden": "true"
4716
- }),
4717
- (0, react_jsx_runtime.jsx)("span", {
4718
- className: "flex-1 text-left",
4719
- children: opt.label
4720
- })
4721
- ]
4722
- }, opt.value);
4723
- }) })
4724
- ] }),
4725
- selected.size > 0 && (0, react_jsx_runtime.jsx)("button", {
4726
- type: "button",
4727
- "data-testid": getTestId?.("clear"),
4728
- onClick: () => column.setFilterValue(void 0),
4729
- className: "flex w-full items-center justify-center border-t px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
4730
- children: t("filters.clearAll", { defaultValue: "Clear filters" })
4731
- })
4732
- ]
4733
- })
4734
- })] });
4735
- }
4736
- //#endregion
4737
5023
  //#region src/data-table/data-table-text-filter.tsx
4738
5024
  function DataTableTextFilter({ column, placeholder, testid, className }) {
4739
5025
  const external = column.getFilterValue() ?? "";
@@ -4769,7 +5055,7 @@ function DataTableTextFilter({ column, placeholder, testid, className }) {
4769
5055
  //#endregion
4770
5056
  //#region src/data-table/data-table-enum-filter.tsx
4771
5057
  function DataTableEnumFilter({ column, title, options, getTestId, className }) {
4772
- return (0, react_jsx_runtime.jsx)(DataTableFacetedFilter, {
5058
+ return (0, react_jsx_runtime.jsx)(require_filter_builder.DataTableFacetedFilter, {
4773
5059
  column,
4774
5060
  title,
4775
5061
  options,
@@ -4883,14 +5169,18 @@ const OPERATOR_LABELS = {
4883
5169
  null: "is null",
4884
5170
  nnull: "is not null",
4885
5171
  startswith: "starts with",
4886
- endswith: "ends with"
5172
+ endswith: "ends with",
5173
+ has: "has",
5174
+ hasAny: "has any of",
5175
+ hasAll: "has all of",
5176
+ hasNone: "has none of"
4887
5177
  };
4888
- function formatOperatorLabel(op, t) {
4889
- return t ? t(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
5178
+ function formatOperatorLabel(op, chromeT) {
5179
+ return chromeT ? chromeT(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
4890
5180
  }
4891
5181
  function useOperatorLabel() {
4892
- const t = (0, _burojs_react.useOptionalT)();
4893
- return (op) => formatOperatorLabel(op, t);
5182
+ const chromeT = (0, _burojs_react.useChromeT)();
5183
+ return (op) => formatOperatorLabel(op, chromeT);
4894
5184
  }
4895
5185
  function isEmpty(v) {
4896
5186
  return v === void 0 || v === null || v === "";
@@ -4984,7 +5274,7 @@ function DataTableOperatorFilter({ column, operators, defaultOperator, valueKind
4984
5274
  //#region src/data-table/data-table-row-actions.tsx
4985
5275
  function DataTableRowActions({ row, actions, getTestId, className }) {
4986
5276
  const [open, setOpen] = (0, react.useState)(false);
4987
- const t = (0, _burojs_react.useOptionalT)();
5277
+ const chromeT = (0, _burojs_react.useChromeT)();
4988
5278
  if (actions.length === 0) return null;
4989
5279
  return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, {
4990
5280
  open,
@@ -5002,7 +5292,7 @@ function DataTableRowActions({ row, actions, getTestId, className }) {
5002
5292
  "aria-hidden": "true"
5003
5293
  }), (0, react_jsx_runtime.jsx)("span", {
5004
5294
  className: "sr-only",
5005
- children: t("actions.openMenu", { defaultValue: "Open row actions menu" })
5295
+ children: chromeT("actions.openMenu", { defaultValue: "Open row actions menu" })
5006
5296
  })]
5007
5297
  })
5008
5298
  }), (0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
@@ -5114,7 +5404,7 @@ function BlockScreen({ block, props, resource, record, label }) {
5114
5404
  snapshot
5115
5405
  ]);
5116
5406
  if (compiled === void 0) return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, { className: "h-24 w-full" });
5117
- if ((0, _burojs_core.isScreenFailure)(compiled)) return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "error" });
5407
+ if ((0, _burojs_core.isScreenFailure)(compiled)) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "error" });
5118
5408
  return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
5119
5409
  value: null,
5120
5410
  children: (0, react_jsx_runtime.jsx)("div", {
@@ -5123,7 +5413,8 @@ function BlockScreen({ block, props, resource, record, label }) {
5123
5413
  children: (0, react_jsx_runtime.jsx)(require_resource_page_router.PlannedBody, {
5124
5414
  screen: compiled,
5125
5415
  name: "modal",
5126
- label: label ?? ""
5416
+ label: label ?? "",
5417
+ ...needsRow && row !== null ? { record: row } : {}
5127
5418
  })
5128
5419
  })
5129
5420
  });
@@ -5132,13 +5423,20 @@ function relation(field) {
5132
5423
  if (field === null || typeof field !== "object") return false;
5133
5424
  return (0, _burojs_core.isRelationField)(field);
5134
5425
  }
5426
+ const resolveOf = (bag) => bag !== null && typeof bag === "object" ? bag.resolve : void 0;
5427
+ function lazyToOne(field) {
5428
+ const entry = field;
5429
+ if (entry.kind === "relationMany" || entry.type === "array") return false;
5430
+ return (resolveOf(entry.meta) ?? resolveOf(entry.opts)) === "lazy";
5431
+ }
5135
5432
  function peekFields(def, columns, capabilityFor, fieldVisible = () => true) {
5136
5433
  const record = new Set((0, _burojs_core.dtoFields)(def, "record"));
5137
5434
  const out = [];
5138
5435
  for (const name of columns) {
5139
5436
  if (out.length === 5) break;
5140
5437
  if (name === def.displayField || out.includes(name) || !record.has(name)) continue;
5141
- if (!require_peek_filter.peekLeafAllowed(def, name, capabilityFor, fieldVisible) || relation(require_peek_filter.peekFieldDefinition(def, name))) continue;
5438
+ const field = require_place_node.peekFieldDefinition(def, name);
5439
+ if (!require_place_node.peekLeafAllowed(def, name, capabilityFor, fieldVisible) || relation(field) && !lazyToOne(field)) continue;
5142
5440
  out.push(name);
5143
5441
  }
5144
5442
  return Object.freeze(out);
@@ -5154,7 +5452,7 @@ function failure(error, retry) {
5154
5452
  };
5155
5453
  }
5156
5454
  function PeekScreen(props) {
5157
- return (0, react_jsx_runtime.jsx)(require_search_access.PeekContext.Provider, {
5455
+ return (0, react_jsx_runtime.jsx)(require_relation_create.PeekContext.Provider, {
5158
5456
  value: true,
5159
5457
  children: props.by !== void 0 ? (0, react_jsx_runtime.jsx)(PeekByKey, {
5160
5458
  target: props.target,
@@ -5205,6 +5503,7 @@ function PeekByKey({ target, by }) {
5205
5503
  page: 1,
5206
5504
  pageSize: 2
5207
5505
  },
5506
+ scope: "none",
5208
5507
  enabled: by.key !== "",
5209
5508
  retry: false
5210
5509
  });
@@ -5220,7 +5519,7 @@ function PeekByKey({ target, by }) {
5220
5519
  } else if (query.error != null) read = failure(query.error, () => void query.refetch());
5221
5520
  else read = { state: "pending" };
5222
5521
  (0, react.useEffect)(() => {
5223
- if (read.state === "ambiguous" && process.env.NODE_ENV !== "production") console.error(`[burojs] ${(0, _burojs_core.relationAmbiguousError)(target, by.field, by.key).message}`);
5522
+ if (read.state === "ambiguous" && process.env.NODE_ENV !== "production") console.error(`[burojs] ${require_toaster.technicalText((0, _burojs_core.relationAmbiguousError)(target, by.field, by.key))}`);
5224
5523
  }, [
5225
5524
  read.state,
5226
5525
  target,
@@ -5236,6 +5535,7 @@ function PeekByKey({ target, by }) {
5236
5535
  function PeekBody({ target, peekKey, read }) {
5237
5536
  const tid = (0, _burojs_react.useTestIds)();
5238
5537
  const t = (0, _burojs_react.useOptionalT)();
5538
+ const chromeT = (0, _burojs_react.useChromeT)();
5239
5539
  const testid = tid.peek(target, peekKey);
5240
5540
  if (read.state === "pending") return (0, react_jsx_runtime.jsx)("div", {
5241
5541
  "data-testid": testid,
@@ -5263,7 +5563,7 @@ function PeekBody({ target, peekKey, read }) {
5263
5563
  variant: "outline",
5264
5564
  "data-testid": `${testid}:retry`,
5265
5565
  onClick: read.retry,
5266
- children: t("actions.retry", { defaultValue: "Retry" })
5566
+ children: chromeT("actions.retry", { defaultValue: "Retry" })
5267
5567
  })]
5268
5568
  });
5269
5569
  if (read.state === "unavailable") return (0, react_jsx_runtime.jsx)("p", {
@@ -5325,7 +5625,7 @@ function PeekRecord({ target, testid, row }) {
5325
5625
  ]);
5326
5626
  const access = (0, _burojs_react.useFieldAccess)(target, "record", dto);
5327
5627
  const fieldVisible = (0, react.useCallback)((name) => access[name]?.view === "visible", [access]);
5328
- const record = (0, react.useMemo)(() => require_peek_filter.peekRecord(def, dto, idField, capabilityFor, fieldVisible), [
5628
+ const record = (0, react.useMemo)(() => require_place_node.peekRecord(def, dto, idField, capabilityFor, fieldVisible), [
5329
5629
  dto,
5330
5630
  def,
5331
5631
  idField,
@@ -5336,7 +5636,7 @@ function PeekRecord({ target, testid, row }) {
5336
5636
  if (def === void 0 || screen === void 0) return record;
5337
5637
  const drawn = new Set();
5338
5638
  for (const node of screen.nodes) if (node.kind === "field" && node.field !== void 0) drawn.add(node.field);
5339
- return require_peek_filter.peekRow(def, dto, idField, capabilityFor, fieldVisible, drawn);
5639
+ return require_place_node.peekRow(def, dto, idField, capabilityFor, fieldVisible, drawn);
5340
5640
  }, [
5341
5641
  def,
5342
5642
  screen,
@@ -5346,7 +5646,7 @@ function PeekRecord({ target, testid, row }) {
5346
5646
  capabilityFor,
5347
5647
  fieldVisible
5348
5648
  ]);
5349
- const host = (0, react.useContext)(require_search_access.PeekHostContext);
5649
+ const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5350
5650
  const instance = (0, _burojs_react.useUIInstance)();
5351
5651
  const quickOpen = (0, _burojs_react.useQuickOpener)();
5352
5652
  const rowId = rowIdOf(def, row);
@@ -5354,9 +5654,9 @@ function PeekRecord({ target, testid, row }) {
5354
5654
  const open = (0, react.useCallback)(() => {
5355
5655
  if (!openable) return;
5356
5656
  const anchor = host?.anchor ?? null;
5357
- const anchorOpen = require_search_access.peekAnchorOpener(anchor);
5657
+ const anchorOpen = require_relation_create.peekAnchorOpener(anchor);
5358
5658
  instance.dismiss();
5359
- if (anchor?.isConnected) require_search_access.focusWithoutPeek(anchor);
5659
+ if (anchor?.isConnected) require_relation_create.focusWithoutPeek(anchor);
5360
5660
  if (anchorOpen !== void 0) anchorOpen(target, String(rowId));
5361
5661
  else quickOpen(target, String(rowId));
5362
5662
  }, [
@@ -5405,8 +5705,8 @@ function PeekRecord({ target, testid, row }) {
5405
5705
  });
5406
5706
  }
5407
5707
  function DeclaredPeekBody({ target, testid, record, frameRecord, def, capabilityFor, fieldVisible, view: View, builtin, open, openable, t }) {
5408
- const host = (0, react.useContext)(require_search_access.PeekHostContext);
5409
- const title = require_search_access.recordDisplayName(record, def?.displayField);
5708
+ const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5709
+ const title = require_relation_create.recordDisplayName(record, def?.displayField);
5410
5710
  const setLabel = host?.setLabel;
5411
5711
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5412
5712
  const controller = (0, _burojs_react.useFormController)({
@@ -5418,7 +5718,7 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5418
5718
  const compiled = controller.screen;
5419
5719
  const hidden = (0, react.useMemo)(() => {
5420
5720
  const out = new Set();
5421
- for (const entry of compiled?.fields ?? []) if (def === void 0 || !require_peek_filter.peekLeafAllowed(def, entry.name, capabilityFor, fieldVisible)) out.add(entry.name);
5721
+ for (const entry of compiled?.fields ?? []) if (def === void 0 || !require_place_node.peekLeafAllowed(def, entry.name, capabilityFor, fieldVisible)) out.add(entry.name);
5422
5722
  return out;
5423
5723
  }, [
5424
5724
  compiled,
@@ -5477,7 +5777,7 @@ function DefaultPeekBody({ target, testid, row, open }) {
5477
5777
  namespace: "default",
5478
5778
  id: target
5479
5779
  };
5480
- const host = (0, react.useContext)(require_search_access.PeekHostContext);
5780
+ const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5481
5781
  const caps = (0, _burojs_react.useI18nCaps)(target);
5482
5782
  const capabilityFor = (0, _burojs_react.useCapabilityResolver)(target, row, "show");
5483
5783
  const projection = useRecordProjection(target);
@@ -5485,13 +5785,13 @@ function DefaultPeekBody({ target, testid, row, open }) {
5485
5785
  const access = (0, _burojs_react.useFieldAccess)(target, "record", dtoRow);
5486
5786
  const projected = (0, _burojs_react.useProjectedRecord)(target, dtoRow);
5487
5787
  const record = projected.value ?? {};
5488
- const title = require_search_access.recordDisplayName(record, def?.displayField);
5788
+ const title = require_relation_create.recordDisplayName(record, def?.displayField);
5489
5789
  const setLabel = host?.setLabel;
5490
5790
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5491
5791
  const columns = (0, react.useMemo)(() => {
5492
5792
  if (def === void 0) return [];
5493
5793
  const listed = def.views?.list?.columns;
5494
- return peekFields(def, listed ?? Object.keys(def.fields), capabilityFor, (name) => access[name]?.view === "visible");
5794
+ return peekFields(def, listed?.map(_burojs_core.columnName) ?? Object.keys(def.fields), capabilityFor, (name) => access[name]?.view === "visible");
5495
5795
  }, [
5496
5796
  def,
5497
5797
  capabilityFor,
@@ -5521,23 +5821,31 @@ function DefaultPeekBody({ target, testid, row, open }) {
5521
5821
  }), columns.length === 0 ? null : (0, react_jsx_runtime.jsx)("dl", {
5522
5822
  className: "grid gap-1.5",
5523
5823
  children: columns.map((name) => {
5524
- const field = require_peek_filter.peekFieldDefinition(def, name);
5824
+ const field = require_place_node.peekFieldDefinition(def, name);
5525
5825
  const value = record[name];
5526
5826
  return (0, react_jsx_runtime.jsxs)("div", {
5527
5827
  "data-testid": `${testid}:field:${name}`,
5528
5828
  className: "flex min-w-0 items-baseline gap-2 text-sm",
5529
5829
  children: [(0, react_jsx_runtime.jsx)("dt", {
5530
5830
  className: "w-24 shrink-0 truncate text-xs text-muted-foreground",
5531
- children: (0, _burojs_core.resolveFieldLabel)(caps, name, field?.label)
5831
+ children: (0, _burojs_core.resolveFieldLabel)(caps, name, (0, _burojs_core.declaredText)("field", field, "label"))
5532
5832
  }), (0, react_jsx_runtime.jsx)("dd", {
5533
5833
  className: "min-w-0 break-words",
5534
- children: (0, react_jsx_runtime.jsx)(require_place_node.ResolvedFieldDisplay, {
5535
- resource: ref,
5536
- name,
5537
- field,
5834
+ children: (0, react_jsx_runtime.jsx)(require_place_node.FieldValueFrame, {
5835
+ field: {
5836
+ ...field,
5837
+ name
5838
+ },
5538
5839
  value,
5539
- record,
5540
- fallback: require_place_node.toDisplayText(value).text
5840
+ surface: "display",
5841
+ children: (0, react_jsx_runtime.jsx)(require_filter_builder.ResolvedFieldDisplay, {
5842
+ resource: ref,
5843
+ name,
5844
+ field,
5845
+ value,
5846
+ record,
5847
+ fallback: require_place_node.toDisplayText(value).text
5848
+ })
5541
5849
  })
5542
5850
  })]
5543
5851
  }, name);
@@ -5549,45 +5857,60 @@ function DefaultPeekBody({ target, testid, row, open }) {
5549
5857
  //#region src/quick/quick-body.tsx
5550
5858
  const EMPTY_ROUTE = Object.freeze({});
5551
5859
  function QuickBody({ entry }) {
5860
+ return (0, react_jsx_runtime.jsx)(_burojs_react.RecordScopeChain, {
5861
+ frames: entry.scopeFrames ?? _burojs_react.NO_RECORD_SCOPE_FRAMES,
5862
+ children: (0, react_jsx_runtime.jsx)(QuickBodyOf, { entry })
5863
+ });
5864
+ }
5865
+ function QuickBodyOf({ entry }) {
5552
5866
  if (entry.mode === "create") return (0, react_jsx_runtime.jsx)(QuickScreenOf, {
5553
5867
  entry,
5554
5868
  route: EMPTY_ROUTE
5555
5869
  });
5556
- if (entry.recordId === void 0 || entry.recordId === "") return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "not-found" });
5557
- return (0, react_jsx_runtime.jsx)(QuickRead, {
5870
+ if (entry.recordId === void 0 || entry.recordId === "") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
5871
+ return (0, react_jsx_runtime.jsx)(QuickReadRoute, {
5558
5872
  entry,
5559
5873
  recordId: entry.recordId
5560
5874
  });
5561
5875
  }
5562
- function QuickRead({ entry, recordId }) {
5876
+ function QuickReadRoute({ entry, recordId }) {
5877
+ const typed = (0, _burojs_react.useRouteRecordId)(entry.resource, recordId);
5878
+ if (typed === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.InvalidRouteId, { resource: entry.resource });
5879
+ return (0, react_jsx_runtime.jsx)(QuickRead, {
5880
+ entry,
5881
+ recordId,
5882
+ typedId: typed
5883
+ });
5884
+ }
5885
+ function QuickRead({ entry, recordId, typedId }) {
5563
5886
  const def = (0, _burojs_react.useApp)().registry.get(entry.resource);
5564
5887
  const projection = (0, react.useMemo)(() => def === void 0 ? void 0 : (0, _burojs_core.dtoFields)(def, "record"), [def]);
5565
5888
  const query = (0, _burojs_react.useOne)(entry.resource, {
5566
- id: recordId,
5889
+ id: typedId,
5567
5890
  retry: _burojs_react.retryRecordRead,
5568
5891
  ...projection === void 0 ? {} : { projection }
5569
5892
  });
5570
5893
  const result = query.data;
5571
5894
  if (result !== void 0) {
5572
5895
  const row = result.data;
5573
- if (row === null || typeof row !== "object") return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "not-found" });
5896
+ if (row === null || typeof row !== "object") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
5574
5897
  return (0, react_jsx_runtime.jsx)(QuickLoaded, {
5575
5898
  entry,
5576
5899
  recordId,
5900
+ typedId,
5577
5901
  row,
5578
5902
  isCurrentData: !query.isPlaceholderData
5579
5903
  });
5580
5904
  }
5581
- if (query.error != null) {
5582
- const state = require_resource_page_router.recordErrorState(query.error);
5583
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, {
5584
- state,
5585
- ...state === "error" ? { onRetry: () => void query.refetch() } : {}
5586
- });
5587
- }
5588
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "loading" });
5905
+ if (query.error != null) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
5906
+ surface: "record",
5907
+ resource: entry.resource,
5908
+ error: query.error,
5909
+ retry: () => void query.refetch()
5910
+ });
5911
+ return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
5589
5912
  }
5590
- function QuickLoaded({ entry, recordId, row, isCurrentData }) {
5913
+ function QuickLoaded({ entry, recordId, typedId, row, isCurrentData }) {
5591
5914
  const gate = (0, _burojs_react.useEntryGate)();
5592
5915
  const quick = (0, _burojs_react.useQuickEntry)();
5593
5916
  const answer = gate(entry.resource, entry.mode === "edit" ? "edit" : "show", row);
@@ -5603,20 +5926,20 @@ function QuickLoaded({ entry, recordId, row, isCurrentData }) {
5603
5926
  title
5604
5927
  ]);
5605
5928
  const route = (0, react.useMemo)(() => Object.freeze({ id: recordId }), [recordId]);
5606
- if (answer.state === "undecided") return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "loading" });
5607
- if (!open) return (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordState, { state: "not-found" });
5929
+ if (answer.state === "undecided") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
5930
+ if (!open) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
5608
5931
  return (0, react_jsx_runtime.jsx)(QuickScreenOf, {
5609
5932
  entry,
5610
- route
5933
+ route,
5934
+ recordId: typedId
5611
5935
  });
5612
5936
  }
5613
5937
  function canonicalOrNull(name) {
5614
- if (typeof name !== "string") return null;
5615
5938
  try {
5616
- return require_check_confirm_dialog.canonicalResourceName(name);
5617
- } catch {
5618
- return null;
5619
- }
5939
+ if (typeof name === "string") return require_check_confirm_dialog.canonicalResourceName(name);
5940
+ if (name !== null && typeof name === "object") return (0, _burojs_core.routeResourceKey)(name);
5941
+ } catch {}
5942
+ return null;
5620
5943
  }
5621
5944
  function absorbedRedirect(to, entry) {
5622
5945
  if (typeof to !== "object" || to === null) return null;
@@ -5630,7 +5953,7 @@ function closeEntry(quick, dismiss) {
5630
5953
  if (quick.stack.entries.length > 1) quick.stack.pop();
5631
5954
  else dismiss(quick.presentationId);
5632
5955
  }
5633
- function QuickScreenOf({ entry, route }) {
5956
+ function QuickScreenOf({ entry, route, recordId }) {
5634
5957
  const quick = (0, _burojs_react.useQuickEntry)();
5635
5958
  const instance = (0, _burojs_react.useUIInstance)();
5636
5959
  const runtime = (0, _burojs_react.useUIPresentationRuntime)();
@@ -5682,7 +6005,7 @@ function QuickScreenOf({ entry, route }) {
5682
6005
  children: (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordScreen, {
5683
6006
  resource: entry.resource,
5684
6007
  mode: entry.mode,
5685
- ...entry.recordId === void 0 ? {} : { recordId: entry.recordId },
6008
+ ...recordId === void 0 ? {} : { recordId },
5686
6009
  ...entry.defaults === void 0 ? {} : { defaults: entry.defaults },
5687
6010
  ...entry.input === void 0 ? {} : { input: entry.input },
5688
6011
  ...callbacks
@@ -5704,7 +6027,7 @@ function useEntryTitle(entry) {
5704
6027
  const caps = (0, _burojs_react.useI18nCaps)(entry.resource);
5705
6028
  const t = (0, _burojs_react.useOptionalT)();
5706
6029
  if (entry.mode !== "create") return entry.title ?? "";
5707
- return t("pageHeader.createTitle", { params: { label: (0, _burojs_core.resolveResourceLabel)(caps, entry.resource, "single", app.registry.get(entry.resource)) } });
6030
+ return require_place_node.resolveResourceTitle(caps, t, entry.resource, "createTitle", { label: (0, _burojs_core.resolveResourceLabel)(caps, entry.resource, "single", app.registry.get(entry.resource)) });
5708
6031
  }
5709
6032
  const HEADING_CLASS = "min-w-0 flex-1 break-words text-lg font-semibold tracking-tight focus-visible:outline-hidden";
5710
6033
  function QuickHeader({ entries }) {
@@ -5714,7 +6037,7 @@ function QuickHeader({ entries }) {
5714
6037
  const t = (0, _burojs_react.useOptionalT)();
5715
6038
  const tid = (0, _burojs_react.useTestIds)();
5716
6039
  const RouterLink = require_toaster.useLinkComponent();
5717
- const ownTitle = (0, react.useContext)(require_shell.OwnTitleContext);
6040
+ const ownTitle = (0, react.useContext)(require_check_confirm_dialog.OwnTitleContext);
5718
6041
  const top = entries[entries.length - 1];
5719
6042
  const previous = entries.length > 1 ? entries[entries.length - 2] : void 0;
5720
6043
  const title = useEntryTitle(top);
@@ -5850,7 +6173,7 @@ function wrapperEnabled(options) {
5850
6173
  //#region src/ui-presentations/dialog-host.tsx
5851
6174
  function DialogPresentationHost({ component: Component, props, options }) {
5852
6175
  const instance = (0, _burojs_react.useUIInstance)();
5853
- return (0, react_jsx_runtime.jsx)(require_shell.DialogPresentationShell, {
6176
+ return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.DialogPresentationShell, {
5854
6177
  dismiss: instance.dismiss,
5855
6178
  wrapper: wrapperEnabled(options),
5856
6179
  ownTitle: options.ownTitle === true,
@@ -5931,7 +6254,7 @@ function PopoverPresentationHost({ component: Component, props, options, anchor
5931
6254
  onCloseAutoFocus: (event) => event.preventDefault(),
5932
6255
  onPointerEnter: hold,
5933
6256
  onPointerLeave: release,
5934
- children: (0, react_jsx_runtime.jsx)(require_search_access.PeekHostContext.Provider, {
6257
+ children: (0, react_jsx_runtime.jsx)(require_relation_create.PeekHostContext.Provider, {
5935
6258
  value: host,
5936
6259
  children: (0, react_jsx_runtime.jsx)(Component, { ...props })
5937
6260
  })
@@ -5943,7 +6266,7 @@ PopoverPresentationHost.optionsSchema = Object.freeze({ title: "string" });
5943
6266
  //#region src/ui-presentations/sheet-host.tsx
5944
6267
  function SheetPresentationHost({ component: Component, props, options }) {
5945
6268
  const instance = (0, _burojs_react.useUIInstance)();
5946
- return (0, react_jsx_runtime.jsx)(require_shell.SheetPresentationShell, {
6269
+ return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.SheetPresentationShell, {
5947
6270
  dismiss: instance.dismiss,
5948
6271
  wrapper: wrapperEnabled(options),
5949
6272
  ownTitle: options.ownTitle === true,
@@ -5961,11 +6284,25 @@ SheetPresentationHost.optionsSchema = Object.freeze({
5961
6284
  //#region src/ui-presentations/index.tsx
5962
6285
  function FlowScreen(props) {
5963
6286
  const loaded = require_check_confirm_dialog.useLoaded(require_check_confirm_dialog.loadFlowScreen);
5964
- if (loaded.error !== void 0) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, { onRetry: loaded.retry });
5965
- if (loaded.module === void 0) return null;
6287
+ if (loaded.error !== void 0) return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, {
6288
+ label: props.label,
6289
+ onRetry: loaded.retry
6290
+ });
6291
+ if (loaded.module === void 0) return (0, react_jsx_runtime.jsxs)("div", {
6292
+ "data-buro-flow-step": "loading",
6293
+ "aria-busy": "true",
6294
+ className: "flex flex-col gap-4",
6295
+ children: [(0, react_jsx_runtime.jsx)(require_check_confirm_dialog.OwnTitleHeading, { label: props.label }), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
6296
+ className: "h-5 w-5 animate-spin self-center",
6297
+ "aria-hidden": "true"
6298
+ })]
6299
+ });
5966
6300
  const Screen = loaded.module.FlowScreen;
5967
6301
  return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowBoundary, {
5968
- fallback: (_error, reset) => (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, { onRetry: reset }),
6302
+ fallback: (_error, reset) => (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowLoadFailed, {
6303
+ label: props.label,
6304
+ onRetry: reset
6305
+ }),
5969
6306
  children: (0, react_jsx_runtime.jsx)(Screen, { ...props })
5970
6307
  });
5971
6308
  }
@@ -6240,9 +6577,13 @@ function DefaultCommandPalette({ open, onOpenChange, actions, children }) {
6240
6577
  }
6241
6578
  //#endregion
6242
6579
  //#region src/shell/app-shell.tsx
6243
- function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel, children }) {
6580
+ function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel, navChrome, children }) {
6244
6581
  const enabled = palette !== false;
6245
- const { open, setOpen } = (0, _burojs_react.useCommandPalette)({ disableShortcut: !enabled });
6582
+ const { open, setOpen, toggle } = (0, _burojs_react.useCommandPalette)();
6583
+ (0, _burojs_react_web.useGlobalShortcut)({
6584
+ key: "k",
6585
+ mod: true
6586
+ }, toggle, { enabled });
6246
6587
  const paletteState = (0, react.useMemo)(() => ({
6247
6588
  open,
6248
6589
  setOpen
@@ -6260,7 +6601,7 @@ function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel,
6260
6601
  sidebar: fill(sidebar, () => (0, react_jsx_runtime.jsx)(AppSidebar, {})),
6261
6602
  header: fill(header, () => (0, react_jsx_runtime.jsx)(AppHeader, {})),
6262
6603
  ...docPanel !== void 0 ? { docPanel } : {},
6263
- children
6604
+ children: navChrome === false ? children : (0, react_jsx_runtime.jsx)(NavChrome, { children })
6264
6605
  }), paletteNode]
6265
6606
  });
6266
6607
  }
@@ -6410,14 +6751,14 @@ exports.Collapsible = Collapsible;
6410
6751
  exports.CollapsibleContent = CollapsibleContent;
6411
6752
  exports.CollapsibleTrigger = CollapsibleTrigger;
6412
6753
  exports.ColumnsToggle = require_place_node.ColumnsToggle;
6413
- exports.Command = require_search_access.Command;
6414
- exports.CommandDialog = require_search_access.CommandDialog;
6415
- exports.CommandEmpty = require_search_access.CommandEmpty;
6416
- exports.CommandGroup = require_search_access.CommandGroup;
6417
- exports.CommandInput = require_search_access.CommandInput;
6418
- exports.CommandItem = require_search_access.CommandItem;
6419
- exports.CommandList = require_search_access.CommandList;
6420
- exports.CommandLoading = require_search_access.CommandLoading;
6754
+ exports.Command = require_relation_create.Command;
6755
+ exports.CommandDialog = require_relation_create.CommandDialog;
6756
+ exports.CommandEmpty = require_relation_create.CommandEmpty;
6757
+ exports.CommandGroup = require_relation_create.CommandGroup;
6758
+ exports.CommandInput = require_relation_create.CommandInput;
6759
+ exports.CommandItem = require_relation_create.CommandItem;
6760
+ exports.CommandList = require_relation_create.CommandList;
6761
+ exports.CommandLoading = require_relation_create.CommandLoading;
6421
6762
  exports.CommandPalette = CommandPalette;
6422
6763
  exports.CommandPaletteActionsGroup = CommandPaletteActionsGroup;
6423
6764
  exports.CommandPaletteCreateGroup = CommandPaletteCreateGroup;
@@ -6426,17 +6767,16 @@ exports.CommandPaletteNavigationGroups = CommandPaletteNavigationGroups;
6426
6767
  exports.CommandPaletteRecentGroup = CommandPaletteRecentGroup;
6427
6768
  exports.CommandPaletteRecordsGroup = CommandPaletteRecordsGroup;
6428
6769
  exports.CommandPaletteTrigger = CommandPaletteTrigger;
6429
- exports.CommandSeparator = require_search_access.CommandSeparator;
6770
+ exports.CommandSeparator = require_relation_create.CommandSeparator;
6430
6771
  exports.ContextPicker = ContextPicker;
6431
6772
  exports.CopyId = require_place_node.CopyId;
6432
6773
  exports.CreateButton = require_place_node.CreateButton;
6433
6774
  exports.CursorLoadMore = require_place_node.CursorLoadMore;
6434
- exports.DEFAULT_LANGUAGE = require_toaster.DEFAULT_LANGUAGE;
6435
6775
  exports.DEFAULT_LANGUAGE_STORAGE_KEY = _burojs_react.DEFAULT_LANGUAGE_STORAGE_KEY;
6436
6776
  exports.DataTable = require_place_node.DataTable;
6437
6777
  exports.DataTableDateRangeFilter = DataTableDateRangeFilter;
6438
6778
  exports.DataTableEnumFilter = DataTableEnumFilter;
6439
- exports.DataTableFacetedFilter = DataTableFacetedFilter;
6779
+ exports.DataTableFacetedFilter = require_filter_builder.DataTableFacetedFilter;
6440
6780
  exports.DataTableNumRangeFilter = DataTableNumRangeFilter;
6441
6781
  exports.DataTableOperatorFilter = DataTableOperatorFilter;
6442
6782
  exports.DataTableRowActions = DataTableRowActions;
@@ -6455,7 +6795,7 @@ exports.DialogDescription = require_dialog.DialogDescription;
6455
6795
  exports.DialogFooter = require_dialog.DialogFooter;
6456
6796
  exports.DialogHeader = require_dialog.DialogHeader;
6457
6797
  exports.DialogPresentationHost = DialogPresentationHost;
6458
- exports.DialogPresentationShell = require_shell.DialogPresentationShell;
6798
+ exports.DialogPresentationShell = require_check_confirm_dialog.DialogPresentationShell;
6459
6799
  exports.DialogTitle = require_dialog.DialogTitle;
6460
6800
  exports.DialogTrigger = require_dialog.DialogTrigger;
6461
6801
  exports.DisabledAction = require_check_confirm_dialog.DisabledAction;
@@ -6488,6 +6828,7 @@ exports.EnumPicker = EnumPicker;
6488
6828
  exports.EnumValueDisplay = EnumDisplay$1;
6489
6829
  exports.ExportButton = require_place_node.ExportButton;
6490
6830
  exports.ExportDialog = require_place_node.ExportDialog;
6831
+ exports.FacetedFilterPicker = require_filter_builder.FacetedFilterPicker;
6491
6832
  exports.Field = require_place_node.Field;
6492
6833
  exports.FieldDisplay = require_place_node.FieldDisplay;
6493
6834
  exports.FileDisplay = FileDisplay;
@@ -6515,6 +6856,7 @@ exports.Label = require_label.Label;
6515
6856
  exports.LanguageSubmenu = LanguageSubmenu;
6516
6857
  exports.LanguageSwitch = LanguageSwitch;
6517
6858
  exports.LinkComponentProvider = require_toaster.LinkComponentProvider;
6859
+ exports.LinkKeysDisplay = LinkKeysDisplay;
6518
6860
  exports.ListBody = require_place_node.ListBody;
6519
6861
  exports.ListBulkBar = require_place_node.ListBulkBar;
6520
6862
  exports.ListColumns = require_place_node.ListColumns;
@@ -6528,10 +6870,8 @@ exports.ListLive = require_place_node.ListLive;
6528
6870
  exports.ListSavedViews = require_place_node.ListSavedViews;
6529
6871
  exports.ListSearchInput = require_place_node.ListSearchInput;
6530
6872
  exports.LoginForm = LoginForm;
6531
- exports.NavAreaLayout = NavAreaLayout;
6532
6873
  exports.NavAreaPage = require_resource_page_router.NavAreaPage;
6533
- exports.NavChrome = require_resource_page_router.NavChrome;
6534
- exports.NavChromeBoundaryProvider = require_resource_page_router.NavChromeBoundaryProvider;
6874
+ exports.NavChrome = NavChrome;
6535
6875
  exports.NavMain = NavMain;
6536
6876
  exports.NavigationGuardDialog = NavigationGuardDialog;
6537
6877
  exports.NumberDisplay = NumberDisplay;
@@ -6546,6 +6886,7 @@ exports.PopoverClose = require_toaster.PopoverClose;
6546
6886
  exports.PopoverContent = require_toaster.PopoverContent;
6547
6887
  exports.PopoverPresentationHost = PopoverPresentationHost;
6548
6888
  exports.PopoverTrigger = require_toaster.PopoverTrigger;
6889
+ exports.PresetFilterControls = require_filter_builder.PresetFilterControls;
6549
6890
  exports.Progress = Progress;
6550
6891
  exports.RecordActions = require_place_node.RecordActions;
6551
6892
  exports.RecordBreadcrumbs = RecordBreadcrumbs;
@@ -6553,9 +6894,9 @@ exports.RecordPage = require_resource_page_router.RecordPage;
6553
6894
  exports.RecordScreen = require_resource_page_router.RecordScreen;
6554
6895
  exports.RecordTitle = require_place_node.RecordTitle;
6555
6896
  exports.RefreshButton = RefreshButton;
6556
- exports.RelationDisplay = require_search_access.RelationDisplay;
6557
- exports.RelationField = require_search_access.RelationField;
6558
- exports.RelationManyDisplay = require_search_access.RelationManyDisplay;
6897
+ exports.RelationDisplay = require_relation_create.RelationDisplay;
6898
+ exports.RelationField = require_relation_create.RelationField;
6899
+ exports.RelationManyDisplay = RelationManyDisplay;
6559
6900
  exports.RelationPicker = require_relation_picker.RelationPicker;
6560
6901
  exports.RelationPickerDialog = require_lazy_relation_picker_dialog.LazyRelationPickerDialog;
6561
6902
  exports.RelationPickerInput = require_relation_picker.RelationPickerInput;
@@ -6563,8 +6904,9 @@ exports.ResourceList = require_place_node.ResourceList;
6563
6904
  exports.ResourceListPage = require_resource_page_router.ResourceListPage;
6564
6905
  exports.ResourcePageRouter = require_resource_page_router.ResourcePageRouter;
6565
6906
  exports.SavedViewsDropdown = require_place_node.SavedViewsDropdown;
6907
+ exports.ScopeDimensionPicker = ScopeDimensionPicker;
6566
6908
  exports.ScopeSwitcher = ScopeSwitcher;
6567
- exports.SecondarySidebarLayout = SecondarySidebarLayout;
6909
+ exports.SecondarySidebarLayout = require_resource_page_router.SecondarySidebarLayout;
6568
6910
  exports.Select = require_filter_builder.Select;
6569
6911
  exports.SelectContent = require_filter_builder.SelectContent;
6570
6912
  exports.SelectGroup = require_filter_builder.SelectGroup;
@@ -6576,16 +6918,16 @@ exports.SelectSeparator = require_filter_builder.SelectSeparator;
6576
6918
  exports.SelectTrigger = require_filter_builder.SelectTrigger;
6577
6919
  exports.SelectValue = require_filter_builder.SelectValue;
6578
6920
  exports.Separator = Separator;
6579
- exports.Sheet = require_shell.Sheet;
6580
- exports.SheetClose = require_shell.SheetClose;
6581
- exports.SheetContent = require_shell.SheetContent;
6582
- exports.SheetDescription = require_shell.SheetDescription;
6583
- exports.SheetFooter = require_shell.SheetFooter;
6584
- exports.SheetHeader = require_shell.SheetHeader;
6921
+ exports.Sheet = require_check_confirm_dialog.Sheet;
6922
+ exports.SheetClose = require_check_confirm_dialog.SheetClose;
6923
+ exports.SheetContent = require_check_confirm_dialog.SheetContent;
6924
+ exports.SheetDescription = require_check_confirm_dialog.SheetDescription;
6925
+ exports.SheetFooter = require_check_confirm_dialog.SheetFooter;
6926
+ exports.SheetHeader = require_check_confirm_dialog.SheetHeader;
6585
6927
  exports.SheetPresentationHost = SheetPresentationHost;
6586
- exports.SheetPresentationShell = require_shell.SheetPresentationShell;
6587
- exports.SheetTitle = require_shell.SheetTitle;
6588
- exports.SheetTrigger = require_shell.SheetTrigger;
6928
+ exports.SheetPresentationShell = require_check_confirm_dialog.SheetPresentationShell;
6929
+ exports.SheetTitle = require_check_confirm_dialog.SheetTitle;
6930
+ exports.SheetTrigger = require_check_confirm_dialog.SheetTrigger;
6589
6931
  exports.ShellProvider = require_place_node.ShellProvider;
6590
6932
  exports.ShowPageHeader = require_place_node.ShowPageHeader;
6591
6933
  exports.Sidebar = Sidebar;
@@ -6624,7 +6966,7 @@ exports.TableHeader = require_filter_builder.TableHeader;
6624
6966
  exports.TableRow = require_filter_builder.TableRow;
6625
6967
  exports.Tabs = require_place_node.Tabs;
6626
6968
  exports.TabsContent = require_place_node.TabsContent;
6627
- exports.TabsLayout = TabsLayout;
6969
+ exports.TabsLayout = require_resource_page_router.TabsLayout;
6628
6970
  exports.TabsList = require_place_node.TabsList;
6629
6971
  exports.TabsTrigger = require_place_node.TabsTrigger;
6630
6972
  exports.TaskRunPanel = TaskRunPanel;
@@ -6642,7 +6984,7 @@ exports.TooltipProvider = require_check_confirm_dialog.TooltipProvider;
6642
6984
  exports.TooltipTrigger = require_check_confirm_dialog.TooltipTrigger;
6643
6985
  exports.UserMenu = UserMenu;
6644
6986
  exports.badgeVariants = require_filter_builder.badgeVariants;
6645
- exports.buildNavItems = require_resource_page_router.buildNavItems;
6987
+ exports.buildNavItems = buildNavItems;
6646
6988
  exports.buroSortingToTanStack = require_place_node.buroSortingToTanStack;
6647
6989
  exports.buttonVariants = require_button.buttonVariants;
6648
6990
  exports.cn = require_use_theme.cn;
@@ -6655,8 +6997,7 @@ exports.i18nPrefixToRef = _burojs_core.i18nPrefixToRef;
6655
6997
  exports.isImage = _burojs_file_storage.isImage;
6656
6998
  exports.layoutSlot = require_resource_page_router.layoutSlot;
6657
6999
  exports.listSlot = require_check_confirm_dialog.listSlot;
6658
- exports.loadLanguage = require_toaster.loadLanguage;
6659
- exports.loadLocale = require_toaster.loadLocale;
7000
+ exports.loadLocale = require_filter_builder.loadLocale;
6660
7001
  exports.localeLabel = localeLabel;
6661
7002
  Object.defineProperty(exports, "modeForSurface", {
6662
7003
  enumerable: true,
@@ -6664,13 +7005,12 @@ Object.defineProperty(exports, "modeForSurface", {
6664
7005
  return _burojs_react.modeForSurface;
6665
7006
  }
6666
7007
  });
6667
- exports.recordDisplayName = require_search_access.recordDisplayName;
7008
+ exports.recordDisplayName = require_relation_create.recordDisplayName;
6668
7009
  exports.registerIcons = require_check_confirm_dialog.registerIcons;
6669
- exports.relationLinkClassName = require_search_access.relationLinkClassName;
7010
+ exports.relationLinkClassName = require_relation_create.relationLinkClassName;
6670
7011
  exports.resolveNavIcon = resolveNavIcon;
6671
7012
  exports.resolveUpdater = require_place_node.resolveUpdater;
6672
- exports.saveLanguage = require_toaster.saveLanguage;
6673
- exports.saveLocale = require_toaster.saveLocale;
7013
+ exports.saveLocale = require_filter_builder.saveLocale;
6674
7014
  exports.shadcnBlockImplementations = require_place_node.shadcnBlockImplementations;
6675
7015
  exports.shadcnFieldImplementations = shadcnFieldImplementations;
6676
7016
  exports.shadcnPresentationHosts = shadcnPresentationHosts;
@@ -6683,7 +7023,7 @@ exports.useCurrentUser = useCurrentUser;
6683
7023
  exports.useDialogFilterState = require_use_dialog_filter_state.useDialogFilterState;
6684
7024
  exports.useDocumentTitle = require_place_node.useDocumentTitle;
6685
7025
  exports.useExportRunWatcher = require_place_node.useExportRunWatcher;
6686
- exports.useFormControl = require_resource_page_router.useFormControl;
7026
+ exports.useFormControl = require_place_node.useFormControl;
6687
7027
  exports.useFormField = useFormField;
6688
7028
  exports.useHref = require_resource_page_router.useHref;
6689
7029
  exports.useIsMobile = useIsMobile;
@@ -6694,17 +7034,23 @@ exports.useLayoutResolver = require_resource_page_router.useLayoutResolver;
6694
7034
  exports.useLinkComponent = require_toaster.useLinkComponent;
6695
7035
  exports.useListSlot = require_check_confirm_dialog.useListSlot;
6696
7036
  exports.useMatch = require_resource_page_router.useMatch;
6697
- exports.useNavChromeBoundary = require_resource_page_router.useNavChromeBoundary;
6698
7037
  exports.useNavIcon = useNavIcon;
6699
7038
  exports.useNavTree = useNavTree;
6700
7039
  exports.useNavVisible = require_resource_page_router.useNavVisible;
6701
7040
  exports.useOptionalSidebar = useOptionalSidebar;
6702
7041
  exports.usePaletteState = require_place_node.usePaletteState;
6703
7042
  exports.usePresentationCopy = usePresentationCopy;
7043
+ exports.useRelationPicker = require_place_node.useRelationPicker;
6704
7044
  exports.useShell = require_place_node.useShell;
6705
7045
  exports.useSidebar = useSidebar;
6706
7046
  exports.useTheme = require_use_theme.useTheme;
6707
7047
  exports.useThemePaletteActions = useThemePaletteActions;
7048
+ Object.defineProperty(exports, "webPlatform", {
7049
+ enumerable: true,
7050
+ get: function() {
7051
+ return _burojs_react_web.webPlatform;
7052
+ }
7053
+ });
6708
7054
  exports.wrapperEnabled = wrapperEnabled;
6709
7055
 
6710
7056
  //# sourceMappingURL=index.cjs.map