@burojs/ui-shadcn 0.7.0 → 0.9.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 (122) hide show
  1. package/dist/{bulk-summary-CrEij5vq.cjs → bulk-summary-2HLgz7Il.cjs} +31 -5
  2. package/dist/bulk-summary-2HLgz7Il.cjs.map +1 -0
  3. package/dist/{bulk-summary-BWSAS7k2.js → bulk-summary-D6A0ua21.js} +32 -6
  4. package/dist/bulk-summary-D6A0ua21.js.map +1 -0
  5. package/dist/{candidates-relation-picker-CS_JZ4Fd.js → candidates-relation-picker-QvoY2bOQ.js} +3 -3
  6. package/dist/{candidates-relation-picker-CS_JZ4Fd.js.map → candidates-relation-picker-QvoY2bOQ.js.map} +1 -1
  7. package/dist/{candidates-relation-picker-y5M6_oe4.cjs → candidates-relation-picker-pEAWKQEY.cjs} +3 -3
  8. package/dist/{candidates-relation-picker-y5M6_oe4.cjs.map → candidates-relation-picker-pEAWKQEY.cjs.map} +1 -1
  9. package/dist/{check-confirm-dialog-2j0gOd7x.js → check-confirm-dialog-B-CbJTln.js} +68 -8
  10. package/dist/{check-confirm-dialog-2j0gOd7x.js.map → check-confirm-dialog-B-CbJTln.js.map} +1 -1
  11. package/dist/{check-confirm-dialog-C-NHgMST.cjs → check-confirm-dialog-W-8WOmGh.cjs} +72 -6
  12. package/dist/check-confirm-dialog-W-8WOmGh.cjs.map +1 -0
  13. package/dist/{filter-builder-DaWHUZuV.js → filter-builder-04nas3eq.js} +127 -61
  14. package/dist/filter-builder-04nas3eq.js.map +1 -0
  15. package/dist/{filter-builder-DFu0JP-1.cjs → filter-builder-DQX-TMFh.cjs} +140 -68
  16. package/dist/filter-builder-DQX-TMFh.cjs.map +1 -0
  17. package/dist/{flow-runtime-DyqTmK3H.js → flow-runtime-BEIyym7d.js} +7 -4
  18. package/dist/{flow-runtime-DyqTmK3H.js.map → flow-runtime-BEIyym7d.js.map} +1 -1
  19. package/dist/{flow-runtime-BpmrIUb6.cjs → flow-runtime-DyNIYfUP.cjs} +7 -4
  20. package/dist/{flow-runtime-BpmrIUb6.cjs.map → flow-runtime-DyNIYfUP.cjs.map} +1 -1
  21. package/dist/{flow-screen-DCdli6Ha.js → flow-screen-DY1Z9PbG.js} +56 -15
  22. package/dist/flow-screen-DY1Z9PbG.js.map +1 -0
  23. package/dist/{flow-screen-Bcz9NF2V.cjs → flow-screen-FE5Xhb3t.cjs} +54 -13
  24. package/dist/flow-screen-FE5Xhb3t.cjs.map +1 -0
  25. package/dist/index.cjs +564 -170
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +235 -95
  28. package/dist/index.d.ts +235 -95
  29. package/dist/index.js +562 -169
  30. package/dist/index.js.map +1 -1
  31. package/dist/{inline-flow-host-C0rI9B7f.js → inline-flow-host-D6u-RlsV.js} +3 -3
  32. package/dist/{inline-flow-host-C0rI9B7f.js.map → inline-flow-host-D6u-RlsV.js.map} +1 -1
  33. package/dist/{inline-flow-host-3vw7LzzD.cjs → inline-flow-host-yVLo6-sM.cjs} +3 -3
  34. package/dist/{inline-flow-host-3vw7LzzD.cjs.map → inline-flow-host-yVLo6-sM.cjs.map} +1 -1
  35. package/dist/{lazy-relation-picker-dialog-CAScLPb2.js → lazy-relation-picker-dialog-BaORufxQ.js} +2 -2
  36. package/dist/{lazy-relation-picker-dialog-CAScLPb2.js.map → lazy-relation-picker-dialog-BaORufxQ.js.map} +1 -1
  37. package/dist/{lazy-relation-picker-dialog-Bt8lrEIu.cjs → lazy-relation-picker-dialog-C_VlGlDz.cjs} +2 -2
  38. package/dist/{lazy-relation-picker-dialog-Bt8lrEIu.cjs.map → lazy-relation-picker-dialog-C_VlGlDz.cjs.map} +1 -1
  39. package/dist/{page-flow-route-BHUEpn0I.js → page-flow-route-CyMzUidK.js} +8 -9
  40. package/dist/page-flow-route-CyMzUidK.js.map +1 -0
  41. package/dist/{page-flow-route-DS8IVTVH.cjs → page-flow-route-OFx7h7Ja.cjs} +8 -9
  42. package/dist/page-flow-route-OFx7h7Ja.cjs.map +1 -0
  43. package/dist/{place-node-CNb3w-c7.cjs → place-node-BZF5Af6x.cjs} +224 -151
  44. package/dist/place-node-BZF5Af6x.cjs.map +1 -0
  45. package/dist/{place-node-CfzQvh4Y.js → place-node-DRjmJGQ_.js} +210 -125
  46. package/dist/place-node-DRjmJGQ_.js.map +1 -0
  47. package/dist/{related-list-cards-BIqqY69Y.js → related-list-cards-2hLitVkg.js} +3 -3
  48. package/dist/{related-list-cards-BIqqY69Y.js.map → related-list-cards-2hLitVkg.js.map} +1 -1
  49. package/dist/{related-list-cards-CelMxl4q.cjs → related-list-cards-xVvgSlu-.cjs} +3 -3
  50. package/dist/{related-list-cards-CelMxl4q.cjs.map → related-list-cards-xVvgSlu-.cjs.map} +1 -1
  51. package/dist/related-list-timeline-CxJqe6eK.js +167 -0
  52. package/dist/related-list-timeline-CxJqe6eK.js.map +1 -0
  53. package/dist/related-list-timeline-Dsf5WewG.cjs +167 -0
  54. package/dist/related-list-timeline-Dsf5WewG.cjs.map +1 -0
  55. package/dist/{related-rows-MPnLCmPF.cjs → related-rows-DDhp9axl.cjs} +4 -4
  56. package/dist/{related-rows-MPnLCmPF.cjs.map → related-rows-DDhp9axl.cjs.map} +1 -1
  57. package/dist/{related-rows--uP2iKQC.js → related-rows-DL6CWsrj.js} +4 -4
  58. package/dist/{related-rows--uP2iKQC.js.map → related-rows-DL6CWsrj.js.map} +1 -1
  59. package/dist/{relation-create-C43cdPQt.js → relation-create-6WicROWA.js} +33 -5
  60. package/dist/relation-create-6WicROWA.js.map +1 -0
  61. package/dist/{relation-create-DDEYcKfw.cjs → relation-create-_SFuPQGM.cjs} +37 -3
  62. package/dist/relation-create-_SFuPQGM.cjs.map +1 -0
  63. package/dist/{relation-many-picker-DzuGJpEl.cjs → relation-many-picker-BBNsmkaX.cjs} +18 -11
  64. package/dist/relation-many-picker-BBNsmkaX.cjs.map +1 -0
  65. package/dist/{relation-many-picker-BJhaEqxz.js → relation-many-picker-mGEQDWo2.js} +18 -11
  66. package/dist/relation-many-picker-mGEQDWo2.js.map +1 -0
  67. package/dist/{relation-picker-D-tBBZW_.js → relation-picker-BbO41cFV.js} +19 -11
  68. package/dist/relation-picker-BbO41cFV.js.map +1 -0
  69. package/dist/{relation-picker-dialog-DoEY8EkH.js → relation-picker-dialog-BgSG_8bU.js} +5 -5
  70. package/dist/relation-picker-dialog-BgSG_8bU.js.map +1 -0
  71. package/dist/{relation-picker-dialog-9Vg5vvR1.cjs → relation-picker-dialog-Duqy2r0n.cjs} +5 -5
  72. package/dist/relation-picker-dialog-Duqy2r0n.cjs.map +1 -0
  73. package/dist/{relation-picker-DaIMzf2H.cjs → relation-picker-jk9D_uwn.cjs} +19 -11
  74. package/dist/relation-picker-jk9D_uwn.cjs.map +1 -0
  75. package/dist/{relation-select-Cr3CfNLy.cjs → relation-select-C3aV18kT.cjs} +2 -2
  76. package/dist/{relation-select-Cr3CfNLy.cjs.map → relation-select-C3aV18kT.cjs.map} +1 -1
  77. package/dist/{relation-select-B8Fq4o-t.js → relation-select-CjQT9LpS.js} +2 -2
  78. package/dist/{relation-select-B8Fq4o-t.js.map → relation-select-CjQT9LpS.js.map} +1 -1
  79. package/dist/{resource-page-router-Diw6S6TK.js → resource-page-router-CzaNATSp.js} +209 -30
  80. package/dist/resource-page-router-CzaNATSp.js.map +1 -0
  81. package/dist/{resource-page-router-C_kGW2o_.cjs → resource-page-router-dmVIeu5s.cjs} +235 -32
  82. package/dist/resource-page-router-dmVIeu5s.cjs.map +1 -0
  83. package/dist/{success-notices-Dl3M1fZP.cjs → success-notices-Cl4b6MLQ.cjs} +3 -2
  84. package/dist/success-notices-Cl4b6MLQ.cjs.map +1 -0
  85. package/dist/{success-notices-LDEgEkc4.js → success-notices-CrcWOGSo.js} +3 -2
  86. package/dist/success-notices-CrcWOGSo.js.map +1 -0
  87. package/dist/{use-dialog-filter-state-B_MqzHaT.js → use-dialog-filter-state-CJoeY-1j.js} +2 -2
  88. package/dist/{use-dialog-filter-state-B_MqzHaT.js.map → use-dialog-filter-state-CJoeY-1j.js.map} +1 -1
  89. package/dist/{use-dialog-filter-state-tNvqAAjh.cjs → use-dialog-filter-state-lsTJxrB4.cjs} +2 -2
  90. package/dist/{use-dialog-filter-state-tNvqAAjh.cjs.map → use-dialog-filter-state-lsTJxrB4.cjs.map} +1 -1
  91. package/dist/use-record-subtitle-BJ9rnj6F.cjs +67 -0
  92. package/dist/use-record-subtitle-BJ9rnj6F.cjs.map +1 -0
  93. package/dist/use-record-subtitle-w3ZhXNlf.js +50 -0
  94. package/dist/use-record-subtitle-w3ZhXNlf.js.map +1 -0
  95. package/package.json +9 -9
  96. package/dist/bulk-summary-BWSAS7k2.js.map +0 -1
  97. package/dist/bulk-summary-CrEij5vq.cjs.map +0 -1
  98. package/dist/check-confirm-dialog-C-NHgMST.cjs.map +0 -1
  99. package/dist/filter-builder-DFu0JP-1.cjs.map +0 -1
  100. package/dist/filter-builder-DaWHUZuV.js.map +0 -1
  101. package/dist/flow-screen-Bcz9NF2V.cjs.map +0 -1
  102. package/dist/flow-screen-DCdli6Ha.js.map +0 -1
  103. package/dist/page-flow-route-BHUEpn0I.js.map +0 -1
  104. package/dist/page-flow-route-DS8IVTVH.cjs.map +0 -1
  105. package/dist/place-node-CNb3w-c7.cjs.map +0 -1
  106. package/dist/place-node-CfzQvh4Y.js.map +0 -1
  107. package/dist/related-list-timeline-CRh7xwLD.js +0 -141
  108. package/dist/related-list-timeline-CRh7xwLD.js.map +0 -1
  109. package/dist/related-list-timeline-DsLdi8sv.cjs +0 -141
  110. package/dist/related-list-timeline-DsLdi8sv.cjs.map +0 -1
  111. package/dist/relation-create-C43cdPQt.js.map +0 -1
  112. package/dist/relation-create-DDEYcKfw.cjs.map +0 -1
  113. package/dist/relation-many-picker-BJhaEqxz.js.map +0 -1
  114. package/dist/relation-many-picker-DzuGJpEl.cjs.map +0 -1
  115. package/dist/relation-picker-D-tBBZW_.js.map +0 -1
  116. package/dist/relation-picker-DaIMzf2H.cjs.map +0 -1
  117. package/dist/relation-picker-dialog-9Vg5vvR1.cjs.map +0 -1
  118. package/dist/relation-picker-dialog-DoEY8EkH.js.map +0 -1
  119. package/dist/resource-page-router-C_kGW2o_.cjs.map +0 -1
  120. package/dist/resource-page-router-Diw6S6TK.js.map +0 -1
  121. package/dist/success-notices-Dl3M1fZP.cjs.map +0 -1
  122. package/dist/success-notices-LDEgEkc4.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,20 +1,21 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
3
3
  const require_toaster = require("./toaster-BbByOytP.cjs");
4
- const require_check_confirm_dialog = require("./check-confirm-dialog-C-NHgMST.cjs");
4
+ const require_check_confirm_dialog = require("./check-confirm-dialog-W-8WOmGh.cjs");
5
5
  const require_button = require("./button-BxnnE28H.cjs");
6
6
  const require_input = require("./input-BI0czGyI.cjs");
7
7
  const require_dialog = require("./dialog-vmMdfUWs.cjs");
8
- const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
8
+ const require_relation_create = require("./relation-create-_SFuPQGM.cjs");
9
9
  const require_skeleton = require("./skeleton-_1gP7wan.cjs");
10
- const require_place_node = require("./place-node-CNb3w-c7.cjs");
10
+ const require_place_node = require("./place-node-BZF5Af6x.cjs");
11
11
  const require_layout_theme_storage_key = require("./layout/theme-storage-key.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");
12
+ const require_filter_builder = require("./filter-builder-DQX-TMFh.cjs");
13
+ const require_resource_page_router = require("./resource-page-router-dmVIeu5s.cjs");
14
14
  const require_label = require("./label-w6JYf2cF.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");
15
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-C_VlGlDz.cjs");
16
+ const require_use_record_subtitle = require("./use-record-subtitle-BJ9rnj6F.cjs");
17
+ const require_relation_picker = require("./relation-picker-jk9D_uwn.cjs");
18
+ const require_use_dialog_filter_state = require("./use-dialog-filter-state-lsTJxrB4.cjs");
18
19
  let _burojs_react_web = require("@burojs/react/web");
19
20
  let _burojs_core = require("@burojs/core");
20
21
  let _burojs_react = require("@burojs/react");
@@ -1718,51 +1719,9 @@ function useNavIcon() {
1718
1719
  return (0, react.useCallback)((name) => resolveNavIcon(name, (key) => components[key]), [components]);
1719
1720
  }
1720
1721
  //#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;
1722
+ //#region src/shell/use-shell-waiting.ts
1723
+ function useShellWaiting() {
1724
+ return (0, _burojs_react.usePermissionsUndecided)();
1766
1725
  }
1767
1726
  //#endregion
1768
1727
  //#region src/layout/use-nav-tree.ts
@@ -1826,7 +1785,7 @@ function useNavTree(opts = {}) {
1826
1785
  };
1827
1786
  };
1828
1787
  const layoutOf = (group) => resolveLayout(group.layout) ? group.layout : group.collapsible ? "collapsible" : "flat";
1829
- const groupChildren = (groupKey) => buildNavItems({
1788
+ const groupChildren = (groupKey) => require_resource_page_router.buildNavItems({
1830
1789
  registry: app.registry,
1831
1790
  caps,
1832
1791
  groupName: groupKey,
@@ -1892,7 +1851,8 @@ function useNavTree(opts = {}) {
1892
1851
  if (!isNavEligible(group)) continue;
1893
1852
  const gLabel = groupLabel(group);
1894
1853
  if (resolveLayout(group.layout)) {
1895
- const href = (0, _burojs_core.navHrefFor)(app.registry, groupKey, { isVisible: isNavEligible });
1854
+ const href = require_resource_page_router.groupNavHref(app.registry, groupKey, isNavEligible);
1855
+ if (href === void 0) continue;
1896
1856
  const entry = groupEntry(group, gLabel, href, isActiveHref(href, currentPath));
1897
1857
  out.push({
1898
1858
  key: groupKey,
@@ -1981,6 +1941,11 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1981
1941
  const t = (0, _burojs_react.useT)();
1982
1942
  const RouterLink = require_toaster.useLinkComponent();
1983
1943
  const navIcon = useNavIcon();
1944
+ const waiting = useShellWaiting();
1945
+ const intent = (0, _burojs_react.useOriginIntent)();
1946
+ const jump = (entry) => () => {
1947
+ if (entry.href !== void 0) intent(entry.href, "jump");
1948
+ };
1984
1949
  const ownOr = (own, name) => own !== void 0 ? own : navIcon(name);
1985
1950
  const groupAsSection = (key) => app.registry.sections.get(key) ?? app.registry.groups.get(key);
1986
1951
  const sectionIcon = (key, name) => {
@@ -2007,6 +1972,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
2007
1972
  href: entry.href ?? "",
2008
1973
  "aria-current": entry.active ? "page" : void 0,
2009
1974
  "data-testid": entryTestId(entry),
1975
+ onClick: jump(entry),
2010
1976
  children: [icon != null && (0, react_jsx_runtime.jsx)("span", {
2011
1977
  className: "inline-flex h-4 w-4 items-center justify-center",
2012
1978
  "aria-hidden": "true",
@@ -2022,9 +1988,20 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
2022
1988
  href: entry.href ?? "",
2023
1989
  "aria-current": entry.active ? "page" : void 0,
2024
1990
  "data-testid": entryTestId(entry),
1991
+ onClick: jump(entry),
2025
1992
  children: (0, react_jsx_runtime.jsx)("span", { children: entry.label })
2026
1993
  })
2027
1994
  }) }, entry.key);
1995
+ if (waiting) return (0, react_jsx_runtime.jsx)(SidebarGroup, {
1996
+ "data-testid": "sidebar-nav-loading",
1997
+ "aria-busy": "true",
1998
+ children: (0, react_jsx_runtime.jsx)(SidebarGroupContent, { children: (0, react_jsx_runtime.jsx)(SidebarMenu, { children: [
1999
+ 0,
2000
+ 1,
2001
+ 2,
2002
+ 3
2003
+ ].map((i) => (0, react_jsx_runtime.jsx)(SidebarMenuItem, { children: (0, react_jsx_runtime.jsx)(SidebarMenuSkeleton, { showIcon: true }) }, i)) }) })
2004
+ });
2028
2005
  const [top, ...blocks] = tree;
2029
2006
  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) => {
2030
2007
  const key = block.key ?? "";
@@ -2095,7 +2072,7 @@ function NavChrome({ children, entryFilter, icons }) {
2095
2072
  if (group.chromeOn === "list" && match.kind === "resource" && DETAIL_ACTIONS.has(match.action)) continue;
2096
2073
  const Layout = resolveLayout(group.layout);
2097
2074
  if (!Layout) continue;
2098
- const items = buildNavItems({
2075
+ const items = require_resource_page_router.buildNavItems({
2099
2076
  registry: app.registry,
2100
2077
  caps,
2101
2078
  groupName: groupKey,
@@ -2135,11 +2112,17 @@ function Breadcrumbs(input) {
2135
2112
  const t = (0, _burojs_react.useOptionalT)();
2136
2113
  const RouterLink = require_toaster.useLinkComponent();
2137
2114
  const caps = (0, _burojs_react.useI18nCaps)(def?.name);
2115
+ const intent = (0, _burojs_react.useOriginIntent)();
2116
+ const onJump = (seg) => {
2117
+ const href = seg.href;
2118
+ return seg.jump === true && href !== void 0 ? () => intent(href, "jump") : void 0;
2119
+ };
2138
2120
  const trailScopes = (0, _burojs_react.useDocTrailScopes)(def?.name);
2139
2121
  const leading = (name) => leadingSegments?.map((seg, i) => (0, react_jsx_runtime.jsxs)("span", {
2140
2122
  className: "flex min-w-0 items-center gap-1",
2141
2123
  children: [seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2142
2124
  href: seg.href,
2125
+ onClick: onJump(seg),
2143
2126
  "data-testid": `${tid.navBreadcrumb(name)}:lead:${i}`,
2144
2127
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
2145
2128
  title: seg.label,
@@ -2174,9 +2157,34 @@ function Breadcrumbs(input) {
2174
2157
  ]
2175
2158
  });
2176
2159
  if (!def) return null;
2177
- const { recordId, pageLabel, middleSegments } = props;
2160
+ const { recordId, pageLabel, middleSegments, rootSegments } = props;
2178
2161
  const resourceKey = require_resource_page_router.canonicalResourceKey(def);
2179
- const listHref = (0, _burojs_core.hrefFor)(app.registry, resourceKey);
2162
+ if (rootSegments !== void 0 && rootSegments.length > 0) return (0, react_jsx_runtime.jsxs)("nav", {
2163
+ className: navClass,
2164
+ "aria-label": ariaLabel,
2165
+ "data-testid": testId,
2166
+ children: [
2167
+ rootSegments.map((seg, i) => (0, react_jsx_runtime.jsxs)("span", {
2168
+ className: "flex min-w-0 items-center gap-1",
2169
+ children: [i > 0 && (0, react_jsx_runtime.jsx)(Chevron, {}), seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2170
+ href: seg.href,
2171
+ onClick: onJump(seg),
2172
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2173
+ className: require_use_theme.cn(LINK_CLASS, "truncate"),
2174
+ title: seg.label,
2175
+ children: seg.label
2176
+ }) : (0, react_jsx_runtime.jsx)("span", {
2177
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2178
+ className: "truncate",
2179
+ title: seg.label,
2180
+ children: seg.label
2181
+ })]
2182
+ }, `root:${i}:${seg.label}`)),
2183
+ pageLabel && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(Chevron, {}), current(tid.navBreadcrumb(resourceKey, recordId), pageLabel)] }),
2184
+ help
2185
+ ]
2186
+ });
2187
+ const listHref = props.resourceHref ?? (0, _burojs_core.hrefFor)(app.registry, resourceKey);
2180
2188
  const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, resourceKey, "plural", def);
2181
2189
  const resourceIsCurrent = !pageLabel && !(middleSegments && middleSegments.length > 0);
2182
2190
  return (0, react_jsx_runtime.jsxs)("nav", {
@@ -2201,6 +2209,7 @@ function Breadcrumbs(input) {
2201
2209
  className: "flex min-w-0 items-center gap-1",
2202
2210
  children: [(0, react_jsx_runtime.jsx)(Chevron, {}), seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2203
2211
  href: seg.href,
2212
+ onClick: onJump(seg),
2204
2213
  "data-testid": `${tid.navBreadcrumb(resourceKey)}:mid:${i}`,
2205
2214
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
2206
2215
  title: seg.label,
@@ -2218,6 +2227,12 @@ function Breadcrumbs(input) {
2218
2227
  }
2219
2228
  //#endregion
2220
2229
  //#region src/layout/record-breadcrumbs.tsx
2230
+ function viewOrigin(ctx, trail, resource) {
2231
+ if (trail === void 0 || trail.resource === void 0 || trail.segments.length > 0) return void 0;
2232
+ const target = ctx.registry.get(trail.resource)?.routesTo?.show;
2233
+ if (target === void 0 || ctx.registry.get(target) !== ctx.registry.get(resource)) return void 0;
2234
+ return trail.resource;
2235
+ }
2221
2236
  function RecordBreadcrumbs() {
2222
2237
  const ctx = require_resource_page_router.useTrailContext();
2223
2238
  const match = require_resource_page_router.useMatch();
@@ -2225,9 +2240,17 @@ function RecordBreadcrumbs() {
2225
2240
  const route = require_resource_page_router.recordTrailRoute(ctx.registry, match);
2226
2241
  const published = require_resource_page_router.usePublishedRecordTrail(route === null ? "" : require_resource_page_router.recordTrailKey(route.resource, route.id, route.flow === void 0 ? route.action : `flow:${route.flow}`));
2227
2242
  const idTitle = (0, _burojs_react.useRecordTitle)(route?.resource, route?.id);
2243
+ (0, _burojs_react.usePublishOriginTitle)(published?.title || void 0);
2244
+ const origin = (0, _burojs_react.useNavigationOrigin)();
2245
+ const rooted = origin === null ? void 0 : require_resource_page_router.originTrail(ctx, origin);
2246
+ const view = route === null ? void 0 : viewOrigin(ctx, rooted, route.resource);
2247
+ const viewScopes = (0, _burojs_react.useDocTrailScopes)(view);
2248
+ const ownScopes = (0, _burojs_react.useDocTrailScopes)(view === void 0 ? void 0 : route?.resource);
2249
+ const docScopes = view === void 0 ? {} : { docScopes: [...new Set([...viewScopes, ...ownScopes])] };
2228
2250
  if (route === null || match === null) return null;
2229
2251
  const { resource, id, groupChain } = route;
2230
2252
  const title = published?.title ?? idTitle;
2253
+ const withOrigin = rooted === void 0 ? {} : { origin: rooted };
2231
2254
  if (route.flow !== void 0) {
2232
2255
  if ((0, _burojs_core.effectiveFlow)(snapshot, match.ref, route.flow) === void 0) return null;
2233
2256
  const flowLabel = published?.flowLabel;
@@ -2237,8 +2260,10 @@ function RecordBreadcrumbs() {
2237
2260
  action: "show",
2238
2261
  id,
2239
2262
  title: idTitle,
2240
- groupChain
2263
+ groupChain,
2264
+ ...withOrigin
2241
2265
  }),
2266
+ ...docScopes,
2242
2267
  "data-testid": "record-breadcrumbs"
2243
2268
  });
2244
2269
  return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
@@ -2247,8 +2272,10 @@ function RecordBreadcrumbs() {
2247
2272
  action: "edit",
2248
2273
  id,
2249
2274
  title,
2250
- groupChain
2275
+ groupChain,
2276
+ ...withOrigin
2251
2277
  }),
2278
+ ...docScopes,
2252
2279
  pageLabel: flowLabel,
2253
2280
  "data-testid": "record-breadcrumbs"
2254
2281
  });
@@ -2259,8 +2286,10 @@ function RecordBreadcrumbs() {
2259
2286
  action: route.action,
2260
2287
  id,
2261
2288
  title,
2262
- groupChain
2289
+ groupChain,
2290
+ ...withOrigin
2263
2291
  }),
2292
+ ...docScopes,
2264
2293
  "data-testid": "record-breadcrumbs"
2265
2294
  });
2266
2295
  }
@@ -2605,7 +2634,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2605
2634
  }, [app, visibilityCtx]);
2606
2635
  const goTo = (href) => {
2607
2636
  onSelect?.();
2608
- navigate(href);
2637
+ navigate(href, { origin: "jump" });
2609
2638
  };
2610
2639
  const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "plural", def);
2611
2640
  const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(def)}`, (0, _burojs_core.declaredText)("chrome", def, "label"));
@@ -2677,10 +2706,10 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2677
2706
  }
2678
2707
  const collectGroupItems = (group, idPath, depth) => {
2679
2708
  const items = [];
2680
- if (!!resolveLayout(group.layout)) {
2709
+ const href = !!resolveLayout(group.layout) ? require_resource_page_router.groupNavHref(app.registry, require_resource_page_router.canonicalNavKey(group), isVisible) : void 0;
2710
+ if (href !== void 0) {
2681
2711
  const groupKey = require_resource_page_router.canonicalNavKey(group);
2682
2712
  const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2683
- const href = (0, _burojs_core.navHrefFor)(app.registry, groupKey, { isVisible });
2684
2713
  items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2685
2714
  value: `group:${idPath}:${label}`,
2686
2715
  onSelect: () => goTo(href),
@@ -2699,6 +2728,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2699
2728
  }
2700
2729
  if (kind === "custom-page") {
2701
2730
  const page = child;
2731
+ if (!isPageVisible(page)) continue;
2702
2732
  const pageKey = require_resource_page_router.canonicalNavKey(page);
2703
2733
  const label = pageLabel(page);
2704
2734
  const href = page.path;
@@ -2757,7 +2787,7 @@ function entryHref(registry, entry, isResourceVisible) {
2757
2787
  const def = registry.get(entry.canonicalRef);
2758
2788
  if (def === void 0) return void 0;
2759
2789
  if (!isResourceVisible(def)) return void 0;
2760
- for (const action of ["show", "edit"]) if (require_place_node.recordRouteAvailable(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2790
+ for (const action of ["show", "edit"]) if ((0, _burojs_react.recordRouteAvailable)(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2761
2791
  action,
2762
2792
  id: entry.id
2763
2793
  });
@@ -2809,7 +2839,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2809
2839
  const goTo = (href, entry) => {
2810
2840
  onSelect?.();
2811
2841
  if (href === null) quick.show(entry.canonicalRef, entry.id);
2812
- else navigate(href);
2842
+ else navigate(href, { origin: "jump" });
2813
2843
  };
2814
2844
  return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2815
2845
  heading: resolvedHeading,
@@ -2872,7 +2902,7 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2872
2902
  const liveQuery = (0, cmdk.useCommandState)((state) => state.search) ?? "";
2873
2903
  const debouncedQuery = (0, _burojs_react.useDebouncedValue)(liveQuery, debounceMs);
2874
2904
  const searchableResources = (0, react.useMemo)(() => {
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) => {
2905
+ return app.registry.list().filter((r) => require_resource_page_router.isShowAvailable(app.registry, require_resource_page_router.canonicalResourceKey(r)) || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "show")).filter(isResourceVisible).map((def) => {
2876
2906
  const displayField = resolveDisplayField(def);
2877
2907
  return displayField ? {
2878
2908
  def,
@@ -2884,7 +2914,7 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2884
2914
  const goTo = (href, resource, id) => {
2885
2915
  onSelect?.();
2886
2916
  if (href === null) quick.show(resource, id);
2887
- else navigate(href);
2917
+ else navigate(href, { origin: "jump" });
2888
2918
  };
2889
2919
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2890
2920
  heading: resolvedHeading,
@@ -2922,6 +2952,7 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2922
2952
  enabled: shouldFetch
2923
2953
  });
2924
2954
  const report = useCommandPaletteResults(`records:${resource}`);
2955
+ const rowSubtitle = require_use_record_subtitle.useRowSubtitle(resource);
2925
2956
  const rows = !shouldFetch || q.isLoading || q.isError ? [] : q.data?.data ?? [];
2926
2957
  (0, react.useEffect)(() => {
2927
2958
  report(rows.length);
@@ -2936,16 +2967,25 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2936
2967
  if (!id) return null;
2937
2968
  const display = titleVisible ? row[displayField] : void 0;
2938
2969
  const labelText = typeof display === "string" && display.length > 0 ? display : id;
2939
- const href = recordHref ? recordHref(resource, id) : require_place_node.isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id) : null;
2970
+ const subtitle = rowSubtitle(row) ?? null;
2971
+ const href = recordHref ? recordHref(resource, id) : require_resource_page_router.isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id) : null;
2940
2972
  return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2941
2973
  value: `record:${resource}:${id}:${labelText}`,
2942
2974
  forceMount: true,
2943
2975
  onSelect: () => goTo(href, resource, id),
2944
2976
  "data-testid": getTestId?.("records-record", `${resource}:${id}`),
2945
- children: [(0, react_jsx_runtime.jsxs)("span", {
2946
- className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
2947
- children: [resourceLabel, ":"]
2948
- }), labelText]
2977
+ children: [
2978
+ (0, react_jsx_runtime.jsxs)("span", {
2979
+ className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
2980
+ children: [resourceLabel, ":"]
2981
+ }),
2982
+ labelText,
2983
+ subtitle === null ? null : (0, react_jsx_runtime.jsx)("span", {
2984
+ "data-buro-region": "record-subtitle",
2985
+ className: "ml-auto truncate pl-2 text-xs text-muted-foreground group-data-[selected=true]:text-accent-foreground",
2986
+ children: subtitle
2987
+ })
2988
+ ]
2949
2989
  }, `record:${resource}:${id}`);
2950
2990
  }) });
2951
2991
  }
@@ -3007,7 +3047,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
3007
3047
  const propActions = actions ?? EMPTY_ACTIONS;
3008
3048
  const resolvedHeading = heading ?? t("commandPalette.actions", { defaultValue: "Actions" });
3009
3049
  const { items, collidingIds } = (0, react.useMemo)(() => {
3010
- return mergeActions(registryEntries.map((entry) => appActionToItem(entry, present, caps)), propActions);
3050
+ return mergeActions(registryEntries.filter((entry) => entry.undecided !== true).map((entry) => appActionToItem(entry, present, caps)), propActions);
3011
3051
  }, [
3012
3052
  registryEntries,
3013
3053
  propActions,
@@ -3093,7 +3133,7 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3093
3133
  ]);
3094
3134
  if (visibleResources.length === 0) return null;
3095
3135
  const goTo = (href) => {
3096
- navigate(href);
3136
+ navigate(href, { origin: "jump" });
3097
3137
  onSelect?.();
3098
3138
  };
3099
3139
  const createIn = (def, href) => {
@@ -3160,19 +3200,21 @@ function AppActions() {
3160
3200
  className: "flex items-center gap-1",
3161
3201
  "data-testid": "app-actions",
3162
3202
  children: links.map(({ action, href }) => {
3203
+ const inert = action.disabledReason !== void 0 || action.undecided === true;
3163
3204
  const label = (0, _burojs_core.resolveNavLabel)(caps, `appActions.${action.name}`, action.label);
3164
3205
  const content = action.icon === void 0 ? label : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, { name: action.icon }), (0, react_jsx_runtime.jsx)("span", {
3165
3206
  className: "max-md:sr-only",
3166
3207
  children: label
3167
3208
  })] });
3168
3209
  return (0, react_jsx_runtime.jsx)(require_button.Button, {
3169
- asChild: action.disabledReason === void 0,
3210
+ asChild: !inert,
3170
3211
  variant: "outline",
3171
3212
  size: "sm",
3172
- disabled: action.disabledReason !== void 0,
3213
+ disabled: inert,
3214
+ "aria-busy": action.undecided === true ? "true" : void 0,
3173
3215
  title: action.disabledReason === void 0 ? void 0 : require_check_confirm_dialog.reasonText(caps, action.disabledReason),
3174
3216
  "data-testid": `app-action:${action.name}`,
3175
- children: action.disabledReason === void 0 ? (0, react_jsx_runtime.jsx)(RouterLink, {
3217
+ children: !inert ? (0, react_jsx_runtime.jsx)(RouterLink, {
3176
3218
  href,
3177
3219
  children: content
3178
3220
  }) : (0, react_jsx_runtime.jsx)("span", { children: content })
@@ -3441,7 +3483,7 @@ const NONE = "__none__";
3441
3483
  function isEmpty$1(value) {
3442
3484
  return value === null || value === void 0 || value === "";
3443
3485
  }
3444
- function EnumChoiceGroup({ control, options, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3486
+ function EnumChoiceGroup({ control, options, current, settling, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3445
3487
  const t = (0, _burojs_react.useOptionalT)();
3446
3488
  const generatedName = react.useId();
3447
3489
  const groupName = name ?? generatedName;
@@ -3456,16 +3498,25 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3456
3498
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3457
3499
  };
3458
3500
  if (control === "segmented") {
3459
- const segment = (key, label, active, select) => (0, react_jsx_runtime.jsx)("button", {
3501
+ const segmentLabel = (option) => (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [option.icon ? (0, react_jsx_runtime.jsx)("span", {
3502
+ "data-testid": `${testid}:option:${option.value}:icon`,
3503
+ className: "contents",
3504
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3505
+ name: option.icon,
3506
+ className: "size-3.5 shrink-0"
3507
+ })
3508
+ }) : null, option.label] });
3509
+ const segment = (key, label, active, select, currentItem = false) => (0, react_jsx_runtime.jsx)("button", {
3460
3510
  type: "button",
3461
3511
  "aria-pressed": active,
3462
3512
  "data-state": active ? "active" : "inactive",
3463
- "data-testid": `${testid}:option:${key}`,
3464
- disabled,
3513
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3514
+ ...currentItem ? { "data-current": "" } : {},
3515
+ disabled: disabled || currentItem,
3465
3516
  onClick: select,
3466
3517
  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
3518
  children: label
3468
- }, key);
3519
+ }, currentItem ? `current:${key}` : key);
3469
3520
  return (0, react_jsx_runtime.jsxs)("div", {
3470
3521
  role: "group",
3471
3522
  id,
@@ -3473,22 +3524,24 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3473
3524
  "data-testid": testid,
3474
3525
  className: require_use_theme.cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3475
3526
  ...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)))]
3527
+ children: [
3528
+ current === void 0 ? null : segment(current.value, segmentLabel(current), true, () => void 0, true),
3529
+ required || settling !== void 0 ? null : segment(NONE, noneLabel, empty, () => pick(void 0)),
3530
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3531
+ status: settling,
3532
+ testid
3533
+ }),
3534
+ options.map((option) => segment(option.value, segmentLabel(option), value === option.value, () => pick(option.value)))
3535
+ ]
3484
3536
  });
3485
3537
  }
3486
3538
  const cards = control === "cards";
3487
- const choice = (key, option, label, checked, select) => {
3488
- const inputId = `${id ?? groupName}:${key}`;
3539
+ const choice = (key, option, label, checked, select, currentItem = false) => {
3540
+ const inputId = `${id ?? groupName}:${currentItem ? "current:" : ""}${key}`;
3541
+ const inert = disabled || currentItem;
3489
3542
  return (0, react_jsx_runtime.jsxs)("label", {
3490
3543
  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"),
3544
+ className: require_use_theme.cn("flex items-start gap-2.5", cards && "cursor-pointer rounded-lg border px-3 py-2.5 transition-colors hover:bg-accent/50 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring", cards && (checked ? "border-primary" : "border-input"), inert && "cursor-not-allowed opacity-60"),
3492
3545
  children: [(0, react_jsx_runtime.jsx)("input", {
3493
3546
  type: "radio",
3494
3547
  id: inputId,
@@ -3496,9 +3549,10 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3496
3549
  value: key,
3497
3550
  checked,
3498
3551
  onChange: select,
3499
- disabled,
3552
+ disabled: inert,
3500
3553
  ...ariaProps,
3501
- "data-testid": `${testid}:option:${key}`,
3554
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3555
+ ...currentItem ? { "data-current": "" } : {},
3502
3556
  className: require_use_theme.cn("h-4 w-4 shrink-0 accent-primary", cards ? "mt-0.5" : "mt-1")
3503
3557
  }), (0, react_jsx_runtime.jsxs)("span", {
3504
3558
  className: "flex min-w-0 flex-col gap-0.5",
@@ -3518,7 +3572,7 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3518
3572
  children: option.summary
3519
3573
  })]
3520
3574
  })]
3521
- }, key);
3575
+ }, currentItem ? `current:${key}` : key);
3522
3576
  };
3523
3577
  return (0, react_jsx_runtime.jsxs)("div", {
3524
3578
  role: "radiogroup",
@@ -3527,23 +3581,40 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3527
3581
  "data-testid": testid,
3528
3582
  "aria-required": required,
3529
3583
  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)))]
3584
+ children: [
3585
+ current === void 0 ? null : choice(current.value, current, current.label, true, () => void 0, true),
3586
+ required || settling !== void 0 ? null : choice(NONE, void 0, noneLabel, empty, () => pick(void 0)),
3587
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3588
+ status: settling,
3589
+ testid
3590
+ }),
3591
+ options.map((option) => choice(option.value, option, option.label, value === option.value, () => pick(option.value)))
3592
+ ]
3531
3593
  });
3532
3594
  }
3533
3595
  //#endregion
3534
3596
  //#region src/enum/enum-picker.tsx
3535
3597
  const ENUM_PICKER_CLEAR_SENTINEL = "__buro_clear__";
3598
+ const NO_VALUES = Object.freeze([]);
3536
3599
  function withSummary(summary) {
3537
3600
  return summary === void 0 ? {} : { summary };
3538
3601
  }
3539
- function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All" }) {
3602
+ function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All", use }) {
3540
3603
  const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
3541
3604
  const app = (0, _burojs_react.useApp)();
3542
3605
  const t = (0, _burojs_react.useOptionalT)();
3543
3606
  const def = app.registry.enums.get(enumName);
3544
3607
  const caps = (0, _burojs_react.useI18nCaps)();
3545
3608
  const ns = def?.i18nNamespace ?? enumName;
3546
- const { values, isLoading, error } = (0, _burojs_react.useEnumValues)(enumName);
3609
+ const loaderParams = def !== void 0 && def.values === void 0 && use !== void 0 ? (0, _burojs_core_internal.resolveEnumParams)(def.params, use.params, use.sources) : void 0;
3610
+ const unsettledParams = loaderParams !== void 0 && loaderParams.status !== "ready";
3611
+ const { values: loadedValues, isLoading, error } = (0, _burojs_react.useEnumValues)(enumName, loaderParams?.status === "ready" ? loaderParams.params : void 0, { enabled: !unsettledParams });
3612
+ const values = unsettledParams ? NO_VALUES : loadedValues;
3613
+ const available = (0, _burojs_react.useAvailableEnumValues)({
3614
+ values: isLoading || values === void 0 ? "pending" : values,
3615
+ ...def === void 0 ? {} : { enum: def },
3616
+ ...use === void 0 ? {} : { use }
3617
+ });
3547
3618
  const tid = testid ?? `enum-picker:${enumName}`;
3548
3619
  if (!def) return (0, react_jsx_runtime.jsxs)("span", {
3549
3620
  "data-testid": `${tid}:unregistered`,
@@ -3585,9 +3656,22 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3585
3656
  });
3586
3657
  const labelOf = (entry) => (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label);
3587
3658
  const summaryOf = (entry) => (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${entry.value}`)?.summary || void 0;
3659
+ const settling = available.status === "ready" ? void 0 : available.status;
3660
+ const offered = settling === void 0 ? available.values : [];
3661
+ const known = value == null ? void 0 : values.find((entry) => entry.value === value);
3662
+ const current = value == null || value === "" || offered.some((entry) => entry.value === value) ? void 0 : known === void 0 ? {
3663
+ value,
3664
+ label: require_place_node.unknownEnumValueLabel(caps, def, ns, value).label
3665
+ } : {
3666
+ value,
3667
+ label: labelOf(known),
3668
+ ...known.icon === void 0 ? {} : { icon: known.icon }
3669
+ };
3588
3670
  if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3589
3671
  control,
3590
- options: values.map((entry) => ({
3672
+ ...current === void 0 ? {} : { current },
3673
+ ...settling === void 0 ? {} : { settling },
3674
+ options: offered.map((entry) => ({
3591
3675
  value: entry.value,
3592
3676
  label: labelOf(entry),
3593
3677
  ...entry.icon === void 0 ? {} : { icon: entry.icon },
@@ -3624,28 +3708,43 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3624
3708
  name,
3625
3709
  id,
3626
3710
  "aria-required": required,
3711
+ "aria-busy": settling === "pending" || void 0,
3627
3712
  "aria-invalid": ariaInvalid || void 0,
3628
3713
  "aria-describedby": ariaDescribedBy,
3629
3714
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3630
3715
  className,
3631
3716
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3632
- }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [clearable && (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3633
- value: "__buro_clear__",
3634
- "data-testid": `${tid}:option:__clear__`,
3635
- children: clearLabel
3636
- }), values.map((entry) => {
3637
- const optionLabel = labelOf(entry);
3638
- const optionDoc = summaryOf(entry);
3639
- return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3640
- value: entry.value,
3641
- "data-testid": `${tid}:option:${entry.value}`,
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
3647
- }, entry.value);
3648
- })] })]
3717
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [
3718
+ clearable && (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3719
+ value: "__buro_clear__",
3720
+ "data-testid": `${tid}:option:__clear__`,
3721
+ children: clearLabel
3722
+ }),
3723
+ current === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3724
+ value: current.value,
3725
+ disabled: true,
3726
+ "data-current": "",
3727
+ "data-testid": `${tid}:current`,
3728
+ children: current.label
3729
+ }),
3730
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3731
+ status: settling,
3732
+ testid: tid
3733
+ }),
3734
+ offered.map((entry) => {
3735
+ const optionLabel = labelOf(entry);
3736
+ const optionDoc = summaryOf(entry);
3737
+ return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3738
+ value: entry.value,
3739
+ "data-testid": `${tid}:option:${entry.value}`,
3740
+ description: optionDoc === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3741
+ "data-testid": `${tid}:option:${entry.value}:doc`,
3742
+ children: optionDoc
3743
+ }),
3744
+ children: optionLabel
3745
+ }, entry.value);
3746
+ })
3747
+ ] })]
3649
3748
  });
3650
3749
  }
3651
3750
  //#endregion
@@ -3695,41 +3794,63 @@ function BooleanInput({ name, id, value, onChange, testid, disabled, required, a
3695
3794
  }
3696
3795
  //#endregion
3697
3796
  //#region src/fields/date.tsx
3698
- function DateDisplay({ value, text }) {
3797
+ function DateDisplay(props) {
3699
3798
  return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3700
- value,
3701
- text,
3702
- format: require_filter_builder.formatDate
3799
+ kind: "date",
3800
+ ...props
3703
3801
  });
3704
3802
  }
3705
- function DateTimeDisplay({ value, text }) {
3803
+ function DateTimeDisplay(props) {
3706
3804
  return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3707
- value,
3708
- text,
3709
- format: require_filter_builder.formatDateTime
3805
+ kind: "dateTime",
3806
+ ...props
3807
+ });
3808
+ }
3809
+ function TimeDisplay(props) {
3810
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3811
+ kind: "time",
3812
+ ...props
3710
3813
  });
3711
3814
  }
3712
- function TemporalDisplay({ value, text, format }) {
3815
+ function storedText(value) {
3816
+ return value instanceof Date && !Number.isNaN(value.getTime()) ? value.toISOString() : String(value);
3817
+ }
3818
+ function TemporalDisplay({ kind, value, text, field, record }) {
3713
3819
  const locale = (0, _burojs_react.useOptionalLocale)();
3820
+ const zone = require_filter_builder.useFieldTimeZone(field?.zone, record);
3821
+ const viewer = (0, _burojs_react.useTimeZone)();
3714
3822
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
3715
3823
  className: "text-muted-foreground",
3716
3824
  children: "—"
3717
3825
  });
3718
- if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
3719
- const d = new Date(String(value));
3720
- if (Number.isNaN(d.getTime())) return (0, react_jsx_runtime.jsx)("span", { children: String(value) });
3826
+ if (zone.status === "pending" || viewer.status === "pending") return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
3827
+ className: "h-4 w-24",
3828
+ "aria-busy": "true"
3829
+ });
3830
+ const raw = storedText(value);
3831
+ const formatted = (0, _burojs_core.formatTimeValue)(kind, raw, {
3832
+ zone: zone.zone,
3833
+ viewerZone: viewer.zone,
3834
+ locale: require_filter_builder.localeTag(locale),
3835
+ params: {
3836
+ ...kind === "time" && field?.ui?.seconds === true ? { timeStyle: "medium" } : {},
3837
+ ...require_filter_builder.dateDisplayParams(field?.ui)
3838
+ }
3839
+ });
3840
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", {
3841
+ title: formatted,
3842
+ children: text
3843
+ });
3844
+ if (formatted === void 0) return (0, react_jsx_runtime.jsx)("span", { children: raw });
3721
3845
  return (0, react_jsx_runtime.jsx)("span", {
3722
3846
  className: "whitespace-nowrap",
3723
- children: format(d, locale)
3847
+ children: formatted
3724
3848
  });
3725
3849
  }
3726
3850
  function toIsoDate(v) {
3727
3851
  if (v == null || v === "") return "";
3728
3852
  const s = String(v);
3729
- if (/^\d{4}-\d{2}-\d{2}/.test(s)) return s.slice(0, 10);
3730
- const d = new Date(s);
3731
- if (Number.isNaN(d.getTime())) return "";
3732
- return d.toISOString().slice(0, 10);
3853
+ return (0, _burojs_core.isCalendarDate)(s) ? s : "";
3733
3854
  }
3734
3855
  function DateInput(props) {
3735
3856
  return (0, react_jsx_runtime.jsx)(TemporalInput, {
@@ -3740,18 +3861,44 @@ function DateInput(props) {
3740
3861
  });
3741
3862
  }
3742
3863
  function DateTimeInput(props) {
3864
+ const locale = (0, _burojs_react.useOptionalLocale)();
3865
+ const zone = require_filter_builder.useFieldTimeZone(props.field?.zone, props.values === void 0 ? props.record : {
3866
+ ...props.record,
3867
+ ...props.values
3868
+ });
3869
+ const viewer = (0, _burojs_react.useTimeZone)();
3870
+ const pending = zone.status === "pending";
3871
+ const fieldZone = zone.status === "ready" ? zone.zone : void 0;
3872
+ const named = fieldZone !== void 0 && viewer.status === "ready" && fieldZone !== viewer.zone ? (0, _burojs_core.zoneShortName)((0, _burojs_core.canonicalInstant)(String(props.value ?? "")) ?? (0, _burojs_core.epochMsToInstant)(Date.now()), fieldZone, require_filter_builder.localeTag(locale)) : void 0;
3743
3873
  return (0, react_jsx_runtime.jsx)(TemporalInput, {
3744
3874
  ...props,
3745
3875
  type: "datetime-local",
3746
- toText: require_filter_builder.toLocalDateTimeText,
3747
- fromText: (text) => require_filter_builder.fromLocalDateTimeText(text) ?? null
3876
+ disabled: props.disabled || pending,
3877
+ toText: (value) => fieldZone === void 0 ? "" : require_filter_builder.toLocalDateTimeText(value, fieldZone),
3878
+ fromText: (text) => fieldZone === void 0 ? null : require_filter_builder.fromLocalDateTimeText(text, fieldZone) ?? null,
3879
+ ...named === void 0 ? {} : { zoneName: named }
3748
3880
  });
3749
3881
  }
3750
- function TemporalInput({ type, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
3751
- return (0, react_jsx_runtime.jsx)(require_input.Input, {
3882
+ function TimeInput(props) {
3883
+ const seconds = props.field?.ui?.seconds === true;
3884
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3885
+ ...props,
3886
+ type: "time",
3887
+ step: seconds ? 1 : 60,
3888
+ toText: (value) => value == null ? "" : String(value),
3889
+ fromText: (text) => {
3890
+ if (text === "") return null;
3891
+ if (seconds) return text.length === 5 ? `${text}:00` : text;
3892
+ return text.slice(0, 5);
3893
+ }
3894
+ });
3895
+ }
3896
+ function TemporalInput({ type, step, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, zoneName }) {
3897
+ const input = (0, react_jsx_runtime.jsx)(require_input.Input, {
3752
3898
  name,
3753
3899
  id,
3754
3900
  type,
3901
+ ...step === void 0 ? {} : { step },
3755
3902
  value: toText(value),
3756
3903
  onChange: (e) => onChange(fromText(e.target.value)),
3757
3904
  "data-testid": testid,
@@ -3762,6 +3909,15 @@ function TemporalInput({ type, toText, fromText, name, id, value, onChange, test
3762
3909
  "aria-describedby": ariaDescribedBy,
3763
3910
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3764
3911
  });
3912
+ if (zoneName === void 0) return input;
3913
+ return (0, react_jsx_runtime.jsxs)("div", {
3914
+ className: "flex items-center gap-2",
3915
+ children: [input, (0, react_jsx_runtime.jsx)("span", {
3916
+ className: "whitespace-nowrap text-xs text-muted-foreground",
3917
+ "data-testid": testid === void 0 ? void 0 : `${testid}:zone`,
3918
+ children: zoneName
3919
+ })]
3920
+ });
3765
3921
  }
3766
3922
  //#endregion
3767
3923
  //#region src/fields/enum.tsx
@@ -3782,13 +3938,30 @@ function EnumDisplay({ value, options, field, resource }) {
3782
3938
  }) : null, label]
3783
3939
  });
3784
3940
  }
3785
- function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource }) {
3941
+ function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource, record, values, metaSources, baseline }) {
3786
3942
  const t = (0, _burojs_react.useOptionalT)();
3787
3943
  const caps = (0, _burojs_react.useOptionCaps)(resource);
3788
3944
  const enumDef = (0, _burojs_react.useBoundEnum)(field);
3789
3945
  const ns = (0, _burojs_core.enumNamespaceOf)(field);
3790
3946
  const control = resolveEnumControl(field?.ui?.control, enumDef, `field ${field?.name ?? name}`);
3791
- const resolved = (options ?? []).map((o) => {
3947
+ const sources = (0, _burojs_react.useFieldMetaSources)({
3948
+ record,
3949
+ values,
3950
+ extra: metaSources
3951
+ });
3952
+ const available = (0, _burojs_react.useAvailableEnumValues)({
3953
+ values: options ?? [],
3954
+ use: {
3955
+ narrow: (0, _burojs_core_internal.narrowEntriesOf)(field?.meta?.narrow),
3956
+ sources,
3957
+ mode: record === void 0 ? "create" : "edit",
3958
+ baseline: baseline ?? record
3959
+ }
3960
+ });
3961
+ const settling = available.status === "ready" ? void 0 : available.status;
3962
+ const offered = settling === void 0 ? available.values : [];
3963
+ const tid = testid ?? name;
3964
+ const resolved = offered.map((o) => {
3792
3965
  const summary = ns === void 0 ? void 0 : (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${o.value}`)?.summary;
3793
3966
  return {
3794
3967
  value: o.value,
@@ -3797,12 +3970,21 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3797
3970
  ...summary === void 0 ? {} : { summary }
3798
3971
  };
3799
3972
  });
3973
+ const raw = value == null || value === "" ? void 0 : String(value);
3974
+ const known = raw === void 0 ? void 0 : options?.find((o) => o.value === raw);
3975
+ const current = raw === void 0 || resolved.some((o) => o.value === raw) ? void 0 : {
3976
+ value: raw,
3977
+ label: (0, _burojs_react.resolveOptionLabel)(caps, field, raw, known, enumDef),
3978
+ ...known?.icon === void 0 ? {} : { icon: known.icon }
3979
+ };
3800
3980
  if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3801
3981
  control,
3802
3982
  options: resolved,
3983
+ ...current === void 0 ? {} : { current },
3984
+ ...settling === void 0 ? {} : { settling },
3803
3985
  value,
3804
3986
  onChange,
3805
- testid: testid ?? name,
3987
+ testid: tid,
3806
3988
  name,
3807
3989
  id,
3808
3990
  required,
@@ -3822,25 +4004,39 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3822
4004
  name,
3823
4005
  id,
3824
4006
  "aria-required": required,
4007
+ "aria-busy": settling === "pending" || void 0,
3825
4008
  "aria-invalid": ariaInvalid || void 0,
3826
4009
  "aria-describedby": ariaDescribedBy,
3827
4010
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3828
4011
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3829
- }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: resolved.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
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
4012
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [
4013
+ current === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
4014
+ value: current.value,
4015
+ disabled: true,
4016
+ "data-current": "",
4017
+ "data-testid": `${tid}:current`,
4018
+ children: current.label
3835
4019
  }),
3836
- children: (0, react_jsx_runtime.jsxs)("span", {
3837
- className: "inline-flex items-center gap-1.5",
3838
- children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3839
- name: o.icon,
3840
- className: "size-3.5 shrink-0 text-muted-foreground"
3841
- }) : null, o.label]
3842
- })
3843
- }, o.value)) })]
4020
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
4021
+ status: settling,
4022
+ testid: tid
4023
+ }),
4024
+ resolved.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
4025
+ value: o.value,
4026
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
4027
+ description: o.summary === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
4028
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
4029
+ children: o.summary
4030
+ }),
4031
+ children: (0, react_jsx_runtime.jsxs)("span", {
4032
+ className: "inline-flex items-center gap-1.5",
4033
+ children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
4034
+ name: o.icon,
4035
+ className: "size-3.5 shrink-0 text-muted-foreground"
4036
+ }) : null, o.label]
4037
+ })
4038
+ }, o.value))
4039
+ ] })]
3844
4040
  });
3845
4041
  }
3846
4042
  //#endregion
@@ -4261,7 +4457,7 @@ function JsonInput({ name, id, value, onChange, testid, disabled, required, aria
4261
4457
  }
4262
4458
  //#endregion
4263
4459
  //#region src/fields/lazy-relation-many.tsx
4264
- const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-DzuGJpEl.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4460
+ const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-BBNsmkaX.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4265
4461
  function LazyRelationManyInput(props) {
4266
4462
  return (0, react_jsx_runtime.jsx)(react.Suspense, {
4267
4463
  fallback: (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
@@ -4373,6 +4569,144 @@ function NumberInput({ name, id, value, onChange, testid, placeholder, disabled,
4373
4569
  });
4374
4570
  }
4375
4571
  //#endregion
4572
+ //#region src/fields/object-group.tsx
4573
+ const GROUP = "rounded-md border border-input p-3";
4574
+ function ObjectGroupInput(props) {
4575
+ const { testIds, accessibility, children } = props;
4576
+ return (0, react_jsx_runtime.jsx)("div", {
4577
+ role: "group",
4578
+ "data-buro-object-group": "input",
4579
+ className: require_use_theme.cn(GROUP, "space-y-3"),
4580
+ "data-testid": testIds.input,
4581
+ id: accessibility.input,
4582
+ "aria-labelledby": accessibility.label,
4583
+ "aria-describedby": accessibility.description,
4584
+ "aria-invalid": props.issues.some((issue) => issue.severity === "error" && issue.path.length === 0) || void 0,
4585
+ "aria-errormessage": accessibility.error,
4586
+ children
4587
+ });
4588
+ }
4589
+ function ObjectGroupDisplay(props) {
4590
+ const { testIds, children } = props;
4591
+ return (0, react_jsx_runtime.jsx)("div", {
4592
+ role: "group",
4593
+ "data-buro-object-group": "display",
4594
+ className: require_use_theme.cn(GROUP, "space-y-2"),
4595
+ "data-testid": testIds.display,
4596
+ children
4597
+ });
4598
+ }
4599
+ //#endregion
4600
+ //#region src/fields/repeater.tsx
4601
+ function useRepeaterTexts() {
4602
+ const t = (0, _burojs_react.useChromeT)();
4603
+ return {
4604
+ add: t("field.repeater.add", { defaultValue: "Add" }),
4605
+ empty: t("field.repeater.empty", { defaultValue: "No items yet" }),
4606
+ remove: (position) => t("field.repeater.remove", {
4607
+ params: { position },
4608
+ defaultValue: "Remove item {{position}}"
4609
+ }),
4610
+ moveUp: (position) => t("field.repeater.moveUp", {
4611
+ params: { position },
4612
+ defaultValue: "Move item {{position}} up"
4613
+ }),
4614
+ moveDown: (position) => t("field.repeater.moveDown", {
4615
+ params: { position },
4616
+ defaultValue: "Move item {{position}} down"
4617
+ })
4618
+ };
4619
+ }
4620
+ function RepeaterInput(props) {
4621
+ const texts = useRepeaterTexts();
4622
+ const { value, renderElement, elementKeys, onAdd, onRemove, onMove, testIds, accessibility } = props;
4623
+ const root = testIds.input;
4624
+ const at = (suffix) => root === void 0 ? void 0 : `${root}:${suffix}`;
4625
+ const editable = props.disabled !== true && props.readOnly !== true;
4626
+ const canAdd = editable && onAdd !== void 0 && props.canAdd !== false;
4627
+ const canRemove = editable && onRemove !== void 0 && props.canRemove !== false;
4628
+ const last = value.length - 1;
4629
+ return (0, react_jsx_runtime.jsxs)("div", {
4630
+ role: "group",
4631
+ className: "space-y-2",
4632
+ "data-testid": root,
4633
+ id: accessibility.input,
4634
+ "aria-labelledby": accessibility.label,
4635
+ "aria-describedby": accessibility.description,
4636
+ "aria-errormessage": accessibility.error,
4637
+ children: [value.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
4638
+ className: "text-sm text-muted-foreground",
4639
+ "data-testid": at("empty"),
4640
+ children: texts.empty
4641
+ }) : (0, react_jsx_runtime.jsx)("ol", {
4642
+ className: "space-y-2",
4643
+ children: value.map((_, index) => (0, react_jsx_runtime.jsxs)("li", {
4644
+ className: "flex items-start gap-2 rounded-md border border-input p-3",
4645
+ "data-testid": at(`item:${index}`),
4646
+ children: [(0, react_jsx_runtime.jsx)("div", {
4647
+ className: "min-w-0 flex-1",
4648
+ children: renderElement?.(index)
4649
+ }), onMove === void 0 && onRemove === void 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
4650
+ className: "flex shrink-0 gap-1",
4651
+ children: [onMove === void 0 ? null : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_button.Button, {
4652
+ type: "button",
4653
+ variant: "ghost",
4654
+ size: "icon",
4655
+ "aria-label": texts.moveUp(index + 1),
4656
+ disabled: !editable || index === 0,
4657
+ "data-testid": at(`up:${index}`),
4658
+ onClick: () => onMove(index, index - 1),
4659
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowUp, { "aria-hidden": "true" })
4660
+ }), (0, react_jsx_runtime.jsx)(require_button.Button, {
4661
+ type: "button",
4662
+ variant: "ghost",
4663
+ size: "icon",
4664
+ "aria-label": texts.moveDown(index + 1),
4665
+ disabled: !editable || index === last,
4666
+ "data-testid": at(`down:${index}`),
4667
+ onClick: () => onMove(index, index + 1),
4668
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowDown, { "aria-hidden": "true" })
4669
+ })] }), onRemove === void 0 ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
4670
+ type: "button",
4671
+ variant: "ghost",
4672
+ size: "icon",
4673
+ "aria-label": texts.remove(index + 1),
4674
+ disabled: !canRemove,
4675
+ "data-testid": at(`remove:${index}`),
4676
+ onClick: () => onRemove(index),
4677
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconTrash, { "aria-hidden": "true" })
4678
+ })]
4679
+ })]
4680
+ }, elementKeys?.[index] ?? index))
4681
+ }), onAdd === void 0 ? null : (0, react_jsx_runtime.jsxs)(require_button.Button, {
4682
+ type: "button",
4683
+ variant: "outline",
4684
+ size: "sm",
4685
+ disabled: !canAdd,
4686
+ "data-testid": at("add"),
4687
+ onClick: onAdd,
4688
+ children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconPlus, { "aria-hidden": "true" }), texts.add]
4689
+ })]
4690
+ });
4691
+ }
4692
+ function RepeaterDisplay(props) {
4693
+ const texts = useRepeaterTexts();
4694
+ const { value, renderElement, testIds } = props;
4695
+ if (value.length === 0) return (0, react_jsx_runtime.jsx)("span", {
4696
+ className: "text-muted-foreground",
4697
+ "data-testid": testIds.display,
4698
+ children: texts.empty
4699
+ });
4700
+ return (0, react_jsx_runtime.jsx)("ol", {
4701
+ className: "space-y-2",
4702
+ "data-testid": testIds.display,
4703
+ children: value.map((_, index) => (0, react_jsx_runtime.jsx)("li", {
4704
+ className: "rounded-md border border-input p-3",
4705
+ children: renderElement?.(index)
4706
+ }, index))
4707
+ });
4708
+ }
4709
+ //#endregion
4376
4710
  //#region src/fields/link-keys-display.tsx
4377
4711
  const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4378
4712
  function qualify(name) {
@@ -4702,12 +5036,13 @@ function TextareaInput({ name, id, value, onChange, testid, placeholder, disable
4702
5036
  //#region src/fields/default-renderers.ts
4703
5037
  function legacyField(props) {
4704
5038
  const name = (0, _burojs_react.optionFieldName)(props.path);
4705
- const texts = props.field.texts;
5039
+ const { texts, zone } = props.field;
4706
5040
  return Object.freeze({
4707
5041
  name,
4708
5042
  meta: props.meta,
4709
5043
  ui: props.ui,
4710
- ...texts === void 0 ? {} : { texts }
5044
+ ...texts === void 0 ? {} : { texts },
5045
+ ...zone === void 0 ? {} : { zone }
4711
5046
  });
4712
5047
  }
4713
5048
  function legacyOptions(options, field) {
@@ -4770,9 +5105,12 @@ function input(renderer) {
4770
5105
  field: legacyField(props),
4771
5106
  resource: props.resource.id,
4772
5107
  record: props.record,
5108
+ values: props.form,
4773
5109
  relationSeeds: props.relationSeeds,
4774
5110
  fixedFilters: props.fixedFilters,
5111
+ optionSubtitle: props.optionSubtitle,
4775
5112
  metaSources: props.metaSources,
5113
+ ...props.baseline === void 0 ? {} : { baseline: props.baseline },
4776
5114
  link: props.link
4777
5115
  });
4778
5116
  };
@@ -4825,6 +5163,12 @@ function enumName(ui) {
4825
5163
  }
4826
5164
  function RegistryEnumInput(props) {
4827
5165
  const app = (0, _burojs_react.useOptionalApp)();
5166
+ const meta = props.field.meta;
5167
+ const sources = (0, _burojs_react.useFieldMetaSources)({
5168
+ record: props.record,
5169
+ values: props.form,
5170
+ extra: props.metaSources
5171
+ });
4828
5172
  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
5173
  return (0, react.createElement)(EnumPicker, {
4830
5174
  enumName: props.enumName,
@@ -4840,7 +5184,14 @@ function RegistryEnumInput(props) {
4840
5184
  ariaInvalid: props.issues.some(isErrorIssue),
4841
5185
  ariaDescribedBy: props.accessibility.description,
4842
5186
  ariaErrorMessage: props.accessibility.error,
4843
- ariaLabelledBy: props.accessibility.label
5187
+ ariaLabelledBy: props.accessibility.label,
5188
+ use: {
5189
+ params: (0, _burojs_core_internal.enumParamsOf)(meta?.enumParams),
5190
+ narrow: (0, _burojs_core_internal.narrowEntriesOf)(meta?.narrow),
5191
+ sources,
5192
+ mode: props.record === void 0 ? "create" : "edit",
5193
+ baseline: props.baseline ?? props.record
5194
+ }
4844
5195
  });
4845
5196
  }
4846
5197
  function enumAware(renderer, layout) {
@@ -4892,6 +5243,10 @@ const dateTime = {
4892
5243
  Display: DateTimeDisplay,
4893
5244
  Input: DateTimeInput
4894
5245
  };
5246
+ const time = {
5247
+ Display: TimeDisplay,
5248
+ Input: TimeInput
5249
+ };
4895
5250
  const en = {
4896
5251
  Display: EnumDisplay,
4897
5252
  Input: EnumInput
@@ -4930,6 +5285,8 @@ const shadcnFieldImplementations = Object.freeze({
4930
5285
  dateTime: scalar(dateTime),
4931
5286
  "date-time": scalar(dateTime),
4932
5287
  "default:date-time": scalar(dateTime),
5288
+ time: scalar(time),
5289
+ "default:time": scalar(time),
4933
5290
  enum: enumAware(en),
4934
5291
  json: scalar({
4935
5292
  Display: JsonDisplay,
@@ -4943,7 +5300,17 @@ const shadcnFieldImplementations = Object.freeze({
4943
5300
  richText: scalar(rich, { size: "full" }),
4944
5301
  "rich-text": scalar(rich, { size: "full" }),
4945
5302
  "default:rich-text": scalar(rich, { size: "full" }),
4946
- file: scalarOrCollection(file, { size: "full" })
5303
+ file: scalarOrCollection(file, { size: "full" }),
5304
+ object: Object.freeze({
5305
+ Input: ObjectGroupInput,
5306
+ Display: ObjectGroupDisplay,
5307
+ chrome: true
5308
+ }),
5309
+ array: Object.freeze({
5310
+ CollectionInput: RepeaterInput,
5311
+ CollectionDisplay: RepeaterDisplay,
5312
+ chrome: true
5313
+ })
4947
5314
  });
4948
5315
  //#endregion
4949
5316
  //#region src/forms/declarative-display.tsx
@@ -5173,7 +5540,8 @@ const OPERATOR_LABELS = {
5173
5540
  has: "has",
5174
5541
  hasAny: "has any of",
5175
5542
  hasAll: "has all of",
5176
- hasNone: "has none of"
5543
+ hasNone: "has none of",
5544
+ some: "has an item where"
5177
5545
  };
5178
5546
  function formatOperatorLabel(op, chromeT) {
5179
5547
  return chromeT ? chromeT(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
@@ -5707,6 +6075,7 @@ function PeekRecord({ target, testid, row }) {
5707
6075
  function DeclaredPeekBody({ target, testid, record, frameRecord, def, capabilityFor, fieldVisible, view: View, builtin, open, openable, t }) {
5708
6076
  const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5709
6077
  const title = require_relation_create.recordDisplayName(record, def?.displayField);
6078
+ const subtitle = require_use_record_subtitle.useRecordSubtitle(target)(record) ?? void 0;
5710
6079
  const setLabel = host?.setLabel;
5711
6080
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5712
6081
  const controller = (0, _burojs_react.useFormController)({
@@ -5742,6 +6111,7 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5742
6111
  children: [builtin ? (0, react_jsx_runtime.jsx)(PeekTitle, {
5743
6112
  testid,
5744
6113
  title,
6114
+ subtitle,
5745
6115
  open: openable ? open : void 0
5746
6116
  }) : null, (0, react_jsx_runtime.jsx)(react.Suspense, {
5747
6117
  fallback: null,
@@ -5754,11 +6124,26 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5754
6124
  })]
5755
6125
  });
5756
6126
  }
5757
- function PeekTitle({ testid, title, open }) {
5758
- if (open === void 0) return (0, react_jsx_runtime.jsx)("p", {
6127
+ function PeekTitle({ testid, title, subtitle, open }) {
6128
+ const heading = open === void 0 ? (0, react_jsx_runtime.jsx)("p", {
5759
6129
  className: "text-sm font-semibold",
5760
6130
  children: title
6131
+ }) : (0, react_jsx_runtime.jsx)(PeekTitleButton, {
6132
+ testid,
6133
+ title,
6134
+ open
5761
6135
  });
6136
+ if (subtitle === void 0) return heading;
6137
+ return (0, react_jsx_runtime.jsxs)("div", {
6138
+ className: "flex flex-col gap-0.5",
6139
+ children: [heading, (0, react_jsx_runtime.jsx)("p", {
6140
+ "data-testid": `${testid}:subtitle`,
6141
+ className: "text-xs text-muted-foreground",
6142
+ children: subtitle
6143
+ })]
6144
+ });
6145
+ }
6146
+ function PeekTitleButton({ testid, title, open }) {
5762
6147
  return (0, react_jsx_runtime.jsx)("button", {
5763
6148
  type: "button",
5764
6149
  "data-testid": `${testid}:title`,
@@ -5786,6 +6171,8 @@ function DefaultPeekBody({ target, testid, row, open }) {
5786
6171
  const projected = (0, _burojs_react.useProjectedRecord)(target, dtoRow);
5787
6172
  const record = projected.value ?? {};
5788
6173
  const title = require_relation_create.recordDisplayName(record, def?.displayField);
6174
+ const subtitleOf = require_use_record_subtitle.useRecordSubtitle(target);
6175
+ const subtitle = projected.status === "ready" ? subtitleOf(record) ?? void 0 : void 0;
5789
6176
  const setLabel = host?.setLabel;
5790
6177
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5791
6178
  const columns = (0, react.useMemo)(() => {
@@ -5817,6 +6204,7 @@ function DefaultPeekBody({ target, testid, row, open }) {
5817
6204
  children: [(0, react_jsx_runtime.jsx)(PeekTitle, {
5818
6205
  testid,
5819
6206
  title,
6207
+ subtitle,
5820
6208
  open
5821
6209
  }), columns.length === 0 ? null : (0, react_jsx_runtime.jsx)("dl", {
5822
6210
  className: "grid gap-1.5",
@@ -6511,6 +6899,7 @@ const spacing = {
6511
6899
  const groupTestId = (role, id) => `command-palette:${role}:${id}`;
6512
6900
  function DefaultCommandPalette({ open, onOpenChange, actions, children }) {
6513
6901
  const t = (0, _burojs_react.useOptionalT)();
6902
+ const waiting = useShellWaiting();
6514
6903
  const locale = (0, _burojs_react.useLocale)();
6515
6904
  const canSearchRecords = (0, _burojs_react.useOptionalDataRuntime)() !== null;
6516
6905
  const close = () => onOpenChange(false);
@@ -6549,21 +6938,21 @@ function DefaultCommandPalette({ open, onOpenChange, actions, children }) {
6549
6938
  locale,
6550
6939
  onSelect: close
6551
6940
  }),
6552
- (0, react_jsx_runtime.jsx)(CommandPaletteRecentGroup, {
6941
+ waiting ? null : (0, react_jsx_runtime.jsx)(CommandPaletteRecentGroup, {
6553
6942
  onSelect: close,
6554
6943
  refreshKey: open,
6555
6944
  getTestId: groupTestId
6556
6945
  }),
6557
- canSearchRecords ? (0, react_jsx_runtime.jsx)(CommandPaletteRecordsGroup, {
6946
+ canSearchRecords && !waiting ? (0, react_jsx_runtime.jsx)(CommandPaletteRecordsGroup, {
6558
6947
  enabled: open,
6559
6948
  onSelect: close,
6560
6949
  getTestId: groupTestId
6561
6950
  }) : null,
6562
- (0, react_jsx_runtime.jsx)(CommandPaletteNavigationGroups, {
6951
+ waiting ? null : (0, react_jsx_runtime.jsx)(CommandPaletteNavigationGroups, {
6563
6952
  onSelect: close,
6564
6953
  getTestId: (role, id) => `command-palette:nav:${role}:${id}`
6565
6954
  }),
6566
- (0, react_jsx_runtime.jsx)(CommandPaletteCreateGroup, {
6955
+ waiting ? null : (0, react_jsx_runtime.jsx)(CommandPaletteCreateGroup, {
6567
6956
  onSelect: close,
6568
6957
  getTestId: groupTestId
6569
6958
  }),
@@ -6579,6 +6968,10 @@ function DefaultCommandPalette({ open, onOpenChange, actions, children }) {
6579
6968
  //#region src/shell/app-shell.tsx
6580
6969
  function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel, navChrome, children }) {
6581
6970
  const enabled = palette !== false;
6971
+ const waiting = useShellWaiting();
6972
+ const decidedOnce = (0, react.useRef)(false);
6973
+ if (!waiting) decidedOnce.current = true;
6974
+ const holding = waiting && !decidedOnce.current;
6582
6975
  const { open, setOpen, toggle } = (0, _burojs_react.useCommandPalette)();
6583
6976
  (0, _burojs_react_web.useGlobalShortcut)({
6584
6977
  key: "k",
@@ -6601,7 +6994,7 @@ function AppShell({ brand, user, loginPath, sidebar, header, palette, docPanel,
6601
6994
  sidebar: fill(sidebar, () => (0, react_jsx_runtime.jsx)(AppSidebar, {})),
6602
6995
  header: fill(header, () => (0, react_jsx_runtime.jsx)(AppHeader, {})),
6603
6996
  ...docPanel !== void 0 ? { docPanel } : {},
6604
- children: navChrome === false ? children : (0, react_jsx_runtime.jsx)(NavChrome, { children })
6997
+ children: holding ? (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" }) : navChrome === false ? children : (0, react_jsx_runtime.jsx)(NavChrome, { children })
6605
6998
  }), paletteNode]
6606
6999
  });
6607
7000
  }
@@ -6870,6 +7263,7 @@ exports.ListLive = require_place_node.ListLive;
6870
7263
  exports.ListSavedViews = require_place_node.ListSavedViews;
6871
7264
  exports.ListSearchInput = require_place_node.ListSearchInput;
6872
7265
  exports.LoginForm = LoginForm;
7266
+ exports.NavAreaNotFound = require_resource_page_router.NavAreaNotFound;
6873
7267
  exports.NavAreaPage = require_resource_page_router.NavAreaPage;
6874
7268
  exports.NavChrome = NavChrome;
6875
7269
  exports.NavMain = NavMain;
@@ -6984,7 +7378,7 @@ exports.TooltipProvider = require_check_confirm_dialog.TooltipProvider;
6984
7378
  exports.TooltipTrigger = require_check_confirm_dialog.TooltipTrigger;
6985
7379
  exports.UserMenu = UserMenu;
6986
7380
  exports.badgeVariants = require_filter_builder.badgeVariants;
6987
- exports.buildNavItems = buildNavItems;
7381
+ exports.buildNavItems = require_resource_page_router.buildNavItems;
6988
7382
  exports.buroSortingToTanStack = require_place_node.buroSortingToTanStack;
6989
7383
  exports.buttonVariants = require_button.buttonVariants;
6990
7384
  exports.cn = require_use_theme.cn;