@burojs/ui-shadcn 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/{bulk-summary-2HLgz7Il.cjs → bulk-summary-Chc61Pyw.cjs} +9 -7
  2. package/dist/bulk-summary-Chc61Pyw.cjs.map +1 -0
  3. package/dist/{bulk-summary-D6A0ua21.js → bulk-summary-DpSQD2Fq.js} +9 -7
  4. package/dist/bulk-summary-DpSQD2Fq.js.map +1 -0
  5. package/dist/{candidates-relation-picker-QvoY2bOQ.js → candidates-relation-picker-DRsHKe6N.js} +3 -3
  6. package/dist/{candidates-relation-picker-QvoY2bOQ.js.map → candidates-relation-picker-DRsHKe6N.js.map} +1 -1
  7. package/dist/{candidates-relation-picker-pEAWKQEY.cjs → candidates-relation-picker-GIxsp7D_.cjs} +3 -3
  8. package/dist/{candidates-relation-picker-pEAWKQEY.cjs.map → candidates-relation-picker-GIxsp7D_.cjs.map} +1 -1
  9. package/dist/{check-confirm-dialog-W-8WOmGh.cjs → check-confirm-dialog-BMSb7wFv.cjs} +17 -9
  10. package/dist/check-confirm-dialog-BMSb7wFv.cjs.map +1 -0
  11. package/dist/{check-confirm-dialog-B-CbJTln.js → check-confirm-dialog-B_u3YVHS.js} +18 -10
  12. package/dist/{check-confirm-dialog-B-CbJTln.js.map → check-confirm-dialog-B_u3YVHS.js.map} +1 -1
  13. package/dist/{filter-builder-04nas3eq.js → filter-builder-DX-xC3Yd.js} +2 -2
  14. package/dist/{filter-builder-04nas3eq.js.map → filter-builder-DX-xC3Yd.js.map} +1 -1
  15. package/dist/{filter-builder-DQX-TMFh.cjs → filter-builder-Dt5E8PSX.cjs} +2 -2
  16. package/dist/{filter-builder-DQX-TMFh.cjs.map → filter-builder-Dt5E8PSX.cjs.map} +1 -1
  17. package/dist/{flow-runtime-DyNIYfUP.cjs → flow-runtime-CQ4wf8co.cjs} +2 -2
  18. package/dist/{flow-runtime-DyNIYfUP.cjs.map → flow-runtime-CQ4wf8co.cjs.map} +1 -1
  19. package/dist/{flow-runtime-BEIyym7d.js → flow-runtime-Q2vD7R3c.js} +2 -2
  20. package/dist/{flow-runtime-BEIyym7d.js.map → flow-runtime-Q2vD7R3c.js.map} +1 -1
  21. package/dist/{flow-screen-DY1Z9PbG.js → flow-screen-B1y2yizP.js} +18 -18
  22. package/dist/flow-screen-B1y2yizP.js.map +1 -0
  23. package/dist/{flow-screen-FE5Xhb3t.cjs → flow-screen-sw2cP70t.cjs} +18 -18
  24. package/dist/flow-screen-sw2cP70t.cjs.map +1 -0
  25. package/dist/index.cjs +2183 -109
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +76 -8
  28. package/dist/index.d.ts +76 -8
  29. package/dist/index.js +2095 -24
  30. package/dist/index.js.map +1 -1
  31. package/dist/{inline-flow-host-yVLo6-sM.cjs → inline-flow-host-CkhoA69R.cjs} +3 -3
  32. package/dist/{inline-flow-host-yVLo6-sM.cjs.map → inline-flow-host-CkhoA69R.cjs.map} +1 -1
  33. package/dist/{inline-flow-host-D6u-RlsV.js → inline-flow-host-DqbXqcPS.js} +3 -3
  34. package/dist/{inline-flow-host-D6u-RlsV.js.map → inline-flow-host-DqbXqcPS.js.map} +1 -1
  35. package/dist/{lazy-relation-picker-dialog-BaORufxQ.js → lazy-relation-picker-dialog-BaIEWLbF.js} +3 -52
  36. package/dist/lazy-relation-picker-dialog-BaIEWLbF.js.map +1 -0
  37. package/dist/{lazy-relation-picker-dialog-C_VlGlDz.cjs → lazy-relation-picker-dialog-CeRzOAi0.cjs} +3 -52
  38. package/dist/lazy-relation-picker-dialog-CeRzOAi0.cjs.map +1 -0
  39. package/dist/{page-flow-route-CyMzUidK.js → page-flow-route-CP7cS7FY.js} +5 -5
  40. package/dist/page-flow-route-CP7cS7FY.js.map +1 -0
  41. package/dist/{page-flow-route-OFx7h7Ja.cjs → page-flow-route-UDx8qvdM.cjs} +9 -9
  42. package/dist/page-flow-route-UDx8qvdM.cjs.map +1 -0
  43. package/dist/{place-node-BZF5Af6x.cjs → place-node-C5ZmuHaN.cjs} +149 -40
  44. package/dist/place-node-C5ZmuHaN.cjs.map +1 -0
  45. package/dist/{place-node-DRjmJGQ_.js → place-node-DwWAigv0.js} +146 -43
  46. package/dist/place-node-DwWAigv0.js.map +1 -0
  47. package/dist/record-trail-store-Cjo9vtod.cjs +126 -0
  48. package/dist/record-trail-store-Cjo9vtod.cjs.map +1 -0
  49. package/dist/record-trail-store-Dn6bVry4.js +91 -0
  50. package/dist/record-trail-store-Dn6bVry4.js.map +1 -0
  51. package/dist/{related-list-cards-xVvgSlu-.cjs → related-list-cards-BypKfm9t.cjs} +3 -3
  52. package/dist/{related-list-cards-xVvgSlu-.cjs.map → related-list-cards-BypKfm9t.cjs.map} +1 -1
  53. package/dist/{related-list-cards-2hLitVkg.js → related-list-cards-Dcmruy09.js} +3 -3
  54. package/dist/{related-list-cards-2hLitVkg.js.map → related-list-cards-Dcmruy09.js.map} +1 -1
  55. package/dist/{related-list-timeline-Dsf5WewG.cjs → related-list-timeline-D-KClgKb.cjs} +4 -4
  56. package/dist/{related-list-timeline-Dsf5WewG.cjs.map → related-list-timeline-D-KClgKb.cjs.map} +1 -1
  57. package/dist/{related-list-timeline-CxJqe6eK.js → related-list-timeline-DZON_qSc.js} +4 -4
  58. package/dist/{related-list-timeline-CxJqe6eK.js.map → related-list-timeline-DZON_qSc.js.map} +1 -1
  59. package/dist/{related-rows-DDhp9axl.cjs → related-rows-DgF05ssi.cjs} +4 -4
  60. package/dist/{related-rows-DDhp9axl.cjs.map → related-rows-DgF05ssi.cjs.map} +1 -1
  61. package/dist/{related-rows-DL6CWsrj.js → related-rows-ETZl5CB9.js} +4 -4
  62. package/dist/{related-rows-DL6CWsrj.js.map → related-rows-ETZl5CB9.js.map} +1 -1
  63. package/dist/{relation-create-_SFuPQGM.cjs → relation-create-B8zngAcA.cjs} +46 -11
  64. package/dist/relation-create-B8zngAcA.cjs.map +1 -0
  65. package/dist/{relation-create-6WicROWA.js → relation-create-CeCWyxIb.js} +47 -12
  66. package/dist/relation-create-CeCWyxIb.js.map +1 -0
  67. package/dist/{relation-many-picker-mGEQDWo2.js → relation-many-picker-CT7nKfE2.js} +4 -4
  68. package/dist/{relation-many-picker-mGEQDWo2.js.map → relation-many-picker-CT7nKfE2.js.map} +1 -1
  69. package/dist/{relation-many-picker-BBNsmkaX.cjs → relation-many-picker-Cq0EHY5I.cjs} +4 -4
  70. package/dist/{relation-many-picker-BBNsmkaX.cjs.map → relation-many-picker-Cq0EHY5I.cjs.map} +1 -1
  71. package/dist/{relation-picker-BbO41cFV.js → relation-picker-CCyuMeGq.js} +6 -6
  72. package/dist/{relation-picker-BbO41cFV.js.map → relation-picker-CCyuMeGq.js.map} +1 -1
  73. package/dist/{relation-picker-jk9D_uwn.cjs → relation-picker-DmwTzgsd.cjs} +6 -6
  74. package/dist/{relation-picker-jk9D_uwn.cjs.map → relation-picker-DmwTzgsd.cjs.map} +1 -1
  75. package/dist/{relation-picker-dialog-BgSG_8bU.js → relation-picker-dialog-CoWKjNv8.js} +4 -4
  76. package/dist/{relation-picker-dialog-BgSG_8bU.js.map → relation-picker-dialog-CoWKjNv8.js.map} +1 -1
  77. package/dist/{relation-picker-dialog-Duqy2r0n.cjs → relation-picker-dialog-mbwyNK43.cjs} +4 -4
  78. package/dist/{relation-picker-dialog-Duqy2r0n.cjs.map → relation-picker-dialog-mbwyNK43.cjs.map} +1 -1
  79. package/dist/{relation-select-C3aV18kT.cjs → relation-select-CguIo2M5.cjs} +2 -2
  80. package/dist/{relation-select-C3aV18kT.cjs.map → relation-select-CguIo2M5.cjs.map} +1 -1
  81. package/dist/{relation-select-CjQT9LpS.js → relation-select-nAYxhopN.js} +2 -2
  82. package/dist/{relation-select-CjQT9LpS.js.map → relation-select-nAYxhopN.js.map} +1 -1
  83. package/dist/{use-dialog-filter-state-lsTJxrB4.cjs → use-dialog-filter-state-CpWblz3C.cjs} +2 -2
  84. package/dist/{use-dialog-filter-state-lsTJxrB4.cjs.map → use-dialog-filter-state-CpWblz3C.cjs.map} +1 -1
  85. package/dist/{use-dialog-filter-state-CJoeY-1j.js → use-dialog-filter-state-ZYxOp5WO.js} +2 -2
  86. package/dist/{use-dialog-filter-state-CJoeY-1j.js.map → use-dialog-filter-state-ZYxOp5WO.js.map} +1 -1
  87. package/dist/{use-record-subtitle-BJ9rnj6F.cjs → use-record-subtitle-B4lTR7pf.cjs} +2 -2
  88. package/dist/{use-record-subtitle-BJ9rnj6F.cjs.map → use-record-subtitle-B4lTR7pf.cjs.map} +1 -1
  89. package/dist/{use-record-subtitle-w3ZhXNlf.js → use-record-subtitle-pWMBqQx9.js} +2 -2
  90. package/dist/{use-record-subtitle-w3ZhXNlf.js.map → use-record-subtitle-pWMBqQx9.js.map} +1 -1
  91. package/package.json +9 -9
  92. package/dist/bulk-summary-2HLgz7Il.cjs.map +0 -1
  93. package/dist/bulk-summary-D6A0ua21.js.map +0 -1
  94. package/dist/check-confirm-dialog-W-8WOmGh.cjs.map +0 -1
  95. package/dist/flow-screen-DY1Z9PbG.js.map +0 -1
  96. package/dist/flow-screen-FE5Xhb3t.cjs.map +0 -1
  97. package/dist/lazy-relation-picker-dialog-BaORufxQ.js.map +0 -1
  98. package/dist/lazy-relation-picker-dialog-C_VlGlDz.cjs.map +0 -1
  99. package/dist/page-flow-route-CyMzUidK.js.map +0 -1
  100. package/dist/page-flow-route-OFx7h7Ja.cjs.map +0 -1
  101. package/dist/place-node-BZF5Af6x.cjs.map +0 -1
  102. package/dist/place-node-DRjmJGQ_.js.map +0 -1
  103. package/dist/relation-create-6WicROWA.js.map +0 -1
  104. package/dist/relation-create-_SFuPQGM.cjs.map +0 -1
  105. package/dist/resource-page-router-CzaNATSp.js +0 -2010
  106. package/dist/resource-page-router-CzaNATSp.js.map +0 -1
  107. package/dist/resource-page-router-dmVIeu5s.cjs +0 -2231
  108. package/dist/resource-page-router-dmVIeu5s.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,21 +1,22 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
3
3
  const require_toaster = require("./toaster-BbByOytP.cjs");
4
- const require_check_confirm_dialog = require("./check-confirm-dialog-W-8WOmGh.cjs");
4
+ const require_check_confirm_dialog = require("./check-confirm-dialog-BMSb7wFv.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-_SFuPQGM.cjs");
8
+ const require_relation_create = require("./relation-create-B8zngAcA.cjs");
9
9
  const require_skeleton = require("./skeleton-_1gP7wan.cjs");
10
- const require_place_node = require("./place-node-BZF5Af6x.cjs");
10
+ const require_place_node = require("./place-node-C5ZmuHaN.cjs");
11
11
  const require_layout_theme_storage_key = require("./layout/theme-storage-key.cjs");
12
- const require_filter_builder = require("./filter-builder-DQX-TMFh.cjs");
13
- const require_resource_page_router = require("./resource-page-router-dmVIeu5s.cjs");
12
+ const require_filter_builder = require("./filter-builder-Dt5E8PSX.cjs");
13
+ const require_record_trail_store = require("./record-trail-store-Cjo9vtod.cjs");
14
14
  const require_label = require("./label-w6JYf2cF.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");
15
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-CeRzOAi0.cjs");
16
+ const require_success_notices = require("./success-notices-Cl4b6MLQ.cjs");
17
+ const require_use_record_subtitle = require("./use-record-subtitle-B4lTR7pf.cjs");
18
+ const require_relation_picker = require("./relation-picker-DmwTzgsd.cjs");
19
+ const require_use_dialog_filter_state = require("./use-dialog-filter-state-CpWblz3C.cjs");
19
20
  let _burojs_react_web = require("@burojs/react/web");
20
21
  let _burojs_core = require("@burojs/core");
21
22
  let _burojs_react = require("@burojs/react");
@@ -303,7 +304,7 @@ function DocBrowser({ className }) {
303
304
  label,
304
305
  summary: (0, _burojs_core.resolveDoc)(caps, entry.scope)?.summary,
305
306
  nested: entry.kind === "variant",
306
- group: entry.kind === "concept" ? glossaryLabel : entry.kind === "resource" ? areasLabel : void 0
307
+ group: entry.kind === "concept" ? glossaryLabel : entry.kind === "resource" || entry.kind === "base" ? areasLabel : void 0
307
308
  };
308
309
  }), [
309
310
  app,
@@ -1724,6 +1725,231 @@ function useShellWaiting() {
1724
1725
  return (0, _burojs_react.usePermissionsUndecided)();
1725
1726
  }
1726
1727
  //#endregion
1728
+ //#region src/layout/build-nav-items.ts
1729
+ function groupNavHref(registry, group, isVisible) {
1730
+ let href;
1731
+ try {
1732
+ href = (0, _burojs_core.navHrefFor)(registry, group, { isVisible });
1733
+ } catch {
1734
+ return;
1735
+ }
1736
+ return (0, _burojs_core.matchPath)(registry, href, { isVisible }) === null ? void 0 : href;
1737
+ }
1738
+ function buildNavItems(args) {
1739
+ const { registry, caps, groupName, match, isVisible, entryFilter, icons } = args;
1740
+ const chain = match?.groupChain ?? [];
1741
+ const qualifiedMatch = match;
1742
+ const activeLeaf = qualifiedMatch == null ? void 0 : qualifiedMatch.kind === "group-index" ? require_record_trail_store.canonicalNavKey({
1743
+ name: qualifiedMatch.target ?? qualifiedMatch.name,
1744
+ ref: qualifiedMatch.targetRef
1745
+ }) : require_record_trail_store.canonicalNavKey(qualifiedMatch);
1746
+ const isEligible = (node) => isVisible(node) && (entryFilter ? entryFilter(node) : true);
1747
+ const out = [];
1748
+ for (const child of registry.groups.childrenOf(groupName)) {
1749
+ if (!isEligible(child)) continue;
1750
+ const kind = (0, _burojs_core.nodeKind)(child);
1751
+ const childKey = require_record_trail_store.canonicalNavKey(child);
1752
+ if (kind === "group") {
1753
+ const href = groupNavHref(registry, childKey, isEligible);
1754
+ if (href === void 0) continue;
1755
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label"));
1756
+ const active = chain.some((g) => require_record_trail_store.canonicalNavKey(g) === childKey);
1757
+ out.push({
1758
+ kind: "group",
1759
+ name: childKey,
1760
+ label,
1761
+ href,
1762
+ icon: icons?.group?.(childKey),
1763
+ active
1764
+ });
1765
+ continue;
1766
+ }
1767
+ const href = (0, _burojs_core.navHrefFor)(registry, childKey, { isVisible: isEligible });
1768
+ if (kind === "custom-page") out.push({
1769
+ kind: "custom-page",
1770
+ name: childKey,
1771
+ label: (0, _burojs_core.resolveNavLabel)(caps, `pages.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label")),
1772
+ href,
1773
+ icon: icons?.page?.(childKey),
1774
+ active: activeLeaf === childKey
1775
+ });
1776
+ else out.push({
1777
+ kind: "resource",
1778
+ name: childKey,
1779
+ label: (0, _burojs_core.resolveResourceNavLabel)(caps, childKey, child),
1780
+ href,
1781
+ icon: icons?.resource?.(childKey),
1782
+ active: activeLeaf === childKey
1783
+ });
1784
+ }
1785
+ return out;
1786
+ }
1787
+ //#endregion
1788
+ //#region src/layout/layouts/secondary-sidebar-layout.tsx
1789
+ function Row({ it }) {
1790
+ const RouterLink = require_toaster.useLinkComponent();
1791
+ return (0, react_jsx_runtime.jsx)("li", { children: (0, react_jsx_runtime.jsxs)(RouterLink, {
1792
+ href: it.href,
1793
+ "data-testid": `nav-secondary-item:${it.name}`,
1794
+ "aria-current": it.active ? "page" : void 0,
1795
+ 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"),
1796
+ children: [it.icon != null && (0, react_jsx_runtime.jsx)("span", {
1797
+ className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
1798
+ "aria-hidden": "true",
1799
+ children: it.icon
1800
+ }), (0, react_jsx_runtime.jsx)("span", {
1801
+ className: "truncate",
1802
+ title: it.label,
1803
+ children: it.label
1804
+ })]
1805
+ }) });
1806
+ }
1807
+ function SecondarySidebarLayout({ group, groupKey, items, children }) {
1808
+ const RouterLink = require_toaster.useLinkComponent();
1809
+ const caps = (0, _burojs_react.useI18nCaps)();
1810
+ const id = groupKey ?? group.name;
1811
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
1812
+ return (0, react_jsx_runtime.jsxs)("div", {
1813
+ className: "md:-m-6 md:flex md:min-h-[calc(100%+3rem)]",
1814
+ "data-testid": `nav-secondary:${id}`,
1815
+ children: [
1816
+ (0, react_jsx_runtime.jsx)("aside", {
1817
+ className: "hidden w-64 shrink-0 border-r bg-background text-foreground md:block",
1818
+ children: (0, react_jsx_runtime.jsxs)("div", {
1819
+ className: "space-y-4 p-4",
1820
+ children: [(0, react_jsx_runtime.jsx)("p", {
1821
+ className: "px-3 text-base font-semibold tracking-tight",
1822
+ children: label
1823
+ }), (0, react_jsx_runtime.jsx)("nav", {
1824
+ "aria-label": label,
1825
+ children: (0, react_jsx_runtime.jsx)("ul", {
1826
+ className: "space-y-0.5",
1827
+ children: items.map((it) => (0, react_jsx_runtime.jsx)(Row, { it }, it.name))
1828
+ })
1829
+ })]
1830
+ })
1831
+ }),
1832
+ (0, react_jsx_runtime.jsx)("nav", {
1833
+ "aria-label": label,
1834
+ "data-testid": `nav-secondary-select:${id}`,
1835
+ 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",
1836
+ children: items.map((it) => (0, react_jsx_runtime.jsx)(RouterLink, {
1837
+ href: it.href,
1838
+ "aria-current": it.active ? "page" : void 0,
1839
+ 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"),
1840
+ children: it.label
1841
+ }, it.name))
1842
+ }),
1843
+ (0, react_jsx_runtime.jsx)("div", {
1844
+ className: "min-w-0 flex-1 md:overflow-x-hidden md:p-6",
1845
+ children
1846
+ })
1847
+ ]
1848
+ });
1849
+ }
1850
+ //#endregion
1851
+ //#region src/layout/layouts/tabs-layout.tsx
1852
+ function TabsLayout({ group, groupKey, items, children }) {
1853
+ const RouterLink = require_toaster.useLinkComponent();
1854
+ const caps = (0, _burojs_react.useI18nCaps)();
1855
+ const id = groupKey ?? group.name;
1856
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
1857
+ return (0, react_jsx_runtime.jsxs)("div", {
1858
+ className: "flex flex-col gap-4",
1859
+ "data-testid": `nav-tabs:${id}`,
1860
+ children: [(0, react_jsx_runtime.jsx)("nav", {
1861
+ "aria-label": label,
1862
+ 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",
1863
+ children: items.map((it) => (0, react_jsx_runtime.jsxs)(RouterLink, {
1864
+ href: it.href,
1865
+ "aria-current": it.active ? "page" : void 0,
1866
+ "data-testid": `nav-tab:${it.name}`,
1867
+ 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"),
1868
+ children: [
1869
+ it.icon != null && (0, react_jsx_runtime.jsx)("span", {
1870
+ className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
1871
+ "aria-hidden": "true",
1872
+ children: it.icon
1873
+ }),
1874
+ it.label,
1875
+ (0, react_jsx_runtime.jsx)("span", {
1876
+ "aria-hidden": "true",
1877
+ 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")
1878
+ })
1879
+ ]
1880
+ }, it.name))
1881
+ }), (0, react_jsx_runtime.jsx)("div", {
1882
+ className: "min-w-0",
1883
+ children
1884
+ })]
1885
+ });
1886
+ }
1887
+ //#endregion
1888
+ //#region src/layout/nav-slots.ts
1889
+ function layoutSlot(key) {
1890
+ return `layout.${key}`;
1891
+ }
1892
+ function useLayout(key) {
1893
+ return (0, _burojs_react.useComponent)(layoutSlot(key));
1894
+ }
1895
+ const BUILTIN_LAYOUTS = {
1896
+ [layoutSlot("secondary-sidebar")]: SecondarySidebarLayout,
1897
+ [layoutSlot("tabs")]: TabsLayout
1898
+ };
1899
+ function useLayoutResolver() {
1900
+ const components = (0, react.useContext)(_burojs_react.ComponentsContext);
1901
+ return (key) => components[layoutSlot(key)] ?? BUILTIN_LAYOUTS[layoutSlot(key)];
1902
+ }
1903
+ const unresolvedLayoutReported = new WeakMap();
1904
+ function useReportUnresolvedLayouts(groups, resolve) {
1905
+ const app = (0, _burojs_react.useApp)();
1906
+ (0, react.useEffect)(() => {
1907
+ if (process.env.NODE_ENV === "production") return;
1908
+ for (const group of groups) {
1909
+ const layout = group.layout;
1910
+ if (layout === "flat" || layout === "collapsible" || resolve(layout)) continue;
1911
+ const key = require_record_trail_store.canonicalNavKey(group);
1912
+ let seen = unresolvedLayoutReported.get(app);
1913
+ if (!seen) {
1914
+ seen = new Set();
1915
+ unresolvedLayoutReported.set(app, seen);
1916
+ }
1917
+ if (seen.has(key)) continue;
1918
+ seen.add(key);
1919
+ console.error(`[burojs] Nav group "${key}" declares layout "${layout}", and no renderer is registered for it. Register one as components["layout.${layout}"] on <BuroProvider>, or use a built-in layout: "secondary-sidebar", "tabs", "flat", "collapsible".`);
1920
+ }
1921
+ });
1922
+ }
1923
+ //#endregion
1924
+ //#region src/layout/use-nav-routing.ts
1925
+ function useNavVisible() {
1926
+ const ctx = (0, _burojs_react.useVisibilityCtx)();
1927
+ const allowed = usePageAllowed();
1928
+ return (0, react.useCallback)((node) => (0, _burojs_core.evaluateVisible)(node.visible, ctx) && (!(0, _burojs_core.isCustomPageDef)(node) || allowed(node)), [ctx, allowed]);
1929
+ }
1930
+ function useResourceVisible() {
1931
+ const ctx = (0, _burojs_react.useVisibilityCtx)();
1932
+ return (0, react.useCallback)((def) => (0, _burojs_core.evaluateVisible)(def.visible, ctx), [ctx]);
1933
+ }
1934
+ function usePageAllowed() {
1935
+ const permissions = (0, _burojs_react.usePermissions)();
1936
+ return (0, react.useCallback)((page) => (0, _burojs_react.pageAccessFor)(page, permissions) === "allowed", [permissions]);
1937
+ }
1938
+ function useHref(name, opts) {
1939
+ const app = (0, _burojs_react.useApp)();
1940
+ const isVisible = useNavVisible();
1941
+ return (0, _burojs_core.hrefFor)(app.registry, name, {
1942
+ ...opts,
1943
+ isVisible
1944
+ });
1945
+ }
1946
+ function useMatch() {
1947
+ const app = (0, _burojs_react.useApp)();
1948
+ const isVisible = useNavVisible();
1949
+ const path = (0, _burojs_react.useOptionalRouterAdapter)()?.pathname;
1950
+ return path === void 0 ? null : (0, _burojs_core.matchPath)(app.registry, path, { isVisible });
1951
+ }
1952
+ //#endregion
1727
1953
  //#region src/layout/use-nav-tree.ts
1728
1954
  function isActiveHref(href, currentPath) {
1729
1955
  if (!currentPath) return false;
@@ -1737,18 +1963,18 @@ function useNavTree(opts = {}) {
1737
1963
  const passesEntryFilter = (entry) => entryFilter ? entryFilter(entry) : true;
1738
1964
  const app = (0, _burojs_react.useApp)();
1739
1965
  const caps = (0, _burojs_react.useI18nCaps)();
1740
- const isResourceVisible = require_resource_page_router.useResourceVisible();
1741
- const resolveLayout = require_resource_page_router.useLayoutResolver();
1742
- const match = require_resource_page_router.useMatch();
1743
- const isVisible = require_resource_page_router.useNavVisible();
1744
- const pageAllowed = require_resource_page_router.usePageAllowed();
1966
+ const isResourceVisible = useResourceVisible();
1967
+ const resolveLayout = useLayoutResolver();
1968
+ const match = useMatch();
1969
+ const isVisible = useNavVisible();
1970
+ const pageAllowed = usePageAllowed();
1745
1971
  const isNavEligible = (node) => isVisible(node) && passesEntryFilter(node);
1746
1972
  const allResources = app.registry.list();
1747
1973
  const allCustomPages = app.registry.customPages.list();
1748
1974
  const sections = app.registry.sections.list();
1749
1975
  const groups = app.registry.groups.rootNodes().filter((n) => (0, _burojs_core.nodeKind)(n) === "group");
1750
- require_resource_page_router.useReportUnresolvedLayouts(app.registry.groups.list(), resolveLayout);
1751
- const topLevelResources = allResources.filter((r) => (0, _burojs_core.hasListPage)(r)).filter(isResourceVisible).filter(passesEntryFilter).filter((r) => !r.section && !r.group).map((r, idx) => ({
1976
+ useReportUnresolvedLayouts(app.registry.groups.list(), resolveLayout);
1977
+ const topLevelResources = allResources.filter((r) => (0, _burojs_core.hasMenuEntry)(r)).filter(isResourceVisible).filter(passesEntryFilter).filter((r) => !r.section && !r.group).map((r, idx) => ({
1752
1978
  r,
1753
1979
  idx
1754
1980
  })).sort((a, b) => {
@@ -1757,16 +1983,16 @@ function useNavTree(opts = {}) {
1757
1983
  return ao !== bo ? ao - bo : a.idx - b.idx;
1758
1984
  }).map((x) => x.r);
1759
1985
  const topLevelCustomPages = allCustomPages.filter((p) => !p.section && !p.group).filter(pageAllowed).filter(passesEntryFilter);
1760
- const resourceHref = (def) => (0, _burojs_core.hrefFor)(app.registry, require_resource_page_router.canonicalResourceKey(def));
1761
- const resourceLabel = (def) => (0, _burojs_core.resolveResourceNavLabel)(caps, require_resource_page_router.canonicalResourceKey(def), def);
1762
- const pageLabel = (page) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(page)}`, (0, _burojs_core.declaredText)("chrome", page, "label"));
1763
- const sectionLabel = (section) => (0, _burojs_core.resolveNavLabel)(caps, `sections.${require_resource_page_router.canonicalNavKey(section)}`, (0, _burojs_core.declaredText)("chrome", section, "label"));
1764
- const groupLabel = (group) => (0, _burojs_core.resolveNavLabel)(caps, `groups.${require_resource_page_router.canonicalNavKey(group)}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
1986
+ const resourceHref = (def) => (0, _burojs_core.hrefFor)(app.registry, require_record_trail_store.canonicalResourceKey(def));
1987
+ const resourceLabel = (def) => (0, _burojs_core.resolveResourceNavLabel)(caps, require_record_trail_store.canonicalResourceKey(def), def);
1988
+ const pageLabel = (page) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_record_trail_store.canonicalNavKey(page)}`, (0, _burojs_core.declaredText)("chrome", page, "label"));
1989
+ const sectionLabel = (section) => (0, _burojs_core.resolveNavLabel)(caps, `sections.${require_record_trail_store.canonicalNavKey(section)}`, (0, _burojs_core.declaredText)("chrome", section, "label"));
1990
+ const groupLabel = (group) => (0, _burojs_core.resolveNavLabel)(caps, `groups.${require_record_trail_store.canonicalNavKey(group)}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
1765
1991
  const pageEntry = (page) => {
1766
1992
  const href = page.path;
1767
1993
  return {
1768
1994
  kind: "page",
1769
- key: require_resource_page_router.canonicalNavKey(page),
1995
+ key: require_record_trail_store.canonicalNavKey(page),
1770
1996
  label: pageLabel(page),
1771
1997
  href,
1772
1998
  icon: page.icon,
@@ -1777,7 +2003,7 @@ function useNavTree(opts = {}) {
1777
2003
  const href = resourceHref(def);
1778
2004
  return {
1779
2005
  kind: "resource",
1780
- key: require_resource_page_router.canonicalResourceKey(def),
2006
+ key: require_record_trail_store.canonicalResourceKey(def),
1781
2007
  label: resourceLabel(def),
1782
2008
  href,
1783
2009
  icon: def.icon,
@@ -1785,7 +2011,7 @@ function useNavTree(opts = {}) {
1785
2011
  };
1786
2012
  };
1787
2013
  const layoutOf = (group) => resolveLayout(group.layout) ? group.layout : group.collapsible ? "collapsible" : "flat";
1788
- const groupChildren = (groupKey) => require_resource_page_router.buildNavItems({
2014
+ const groupChildren = (groupKey) => buildNavItems({
1789
2015
  registry: app.registry,
1790
2016
  caps,
1791
2017
  groupName: groupKey,
@@ -1794,7 +2020,7 @@ function useNavTree(opts = {}) {
1794
2020
  entryFilter
1795
2021
  }).map(itemEntry);
1796
2022
  const groupEntry = (group, label, href, active) => {
1797
- const key = require_resource_page_router.canonicalNavKey(group);
2023
+ const key = require_record_trail_store.canonicalNavKey(group);
1798
2024
  return {
1799
2025
  kind: "group",
1800
2026
  key,
@@ -1832,8 +2058,8 @@ function useNavTree(opts = {}) {
1832
2058
  entries: topEntries
1833
2059
  }];
1834
2060
  for (const section of sections) {
1835
- const sectionKey = require_resource_page_router.canonicalNavKey(section);
1836
- const entries = app.registry.sections.childrenOf(sectionKey).filter((c) => !("parent" in c) || (0, _burojs_core.hasListPage)(c)).filter((c) => (0, _burojs_core.isCustomPageDef)(c) ? pageAllowed(c) : isResourceVisible(c)).filter(passesEntryFilter).map((c) => (0, _burojs_core.isCustomPageDef)(c) ? pageEntry(c) : resourceEntry(c));
2061
+ const sectionKey = require_record_trail_store.canonicalNavKey(section);
2062
+ const entries = app.registry.sections.childrenOf(sectionKey).filter((c) => !("parent" in c) || (0, _burojs_core.hasMenuEntry)(c)).filter((c) => (0, _burojs_core.isCustomPageDef)(c) ? pageAllowed(c) : isResourceVisible(c)).filter(passesEntryFilter).map((c) => (0, _burojs_core.isCustomPageDef)(c) ? pageEntry(c) : resourceEntry(c));
1837
2063
  if (entries.length === 0) continue;
1838
2064
  const active = entries.some((e) => e.active);
1839
2065
  out.push({
@@ -1847,11 +2073,11 @@ function useNavTree(opts = {}) {
1847
2073
  });
1848
2074
  }
1849
2075
  for (const group of groups) {
1850
- const groupKey = require_resource_page_router.canonicalNavKey(group);
2076
+ const groupKey = require_record_trail_store.canonicalNavKey(group);
1851
2077
  if (!isNavEligible(group)) continue;
1852
2078
  const gLabel = groupLabel(group);
1853
2079
  if (resolveLayout(group.layout)) {
1854
- const href = require_resource_page_router.groupNavHref(app.registry, groupKey, isNavEligible);
2080
+ const href = groupNavHref(app.registry, groupKey, isNavEligible);
1855
2081
  if (href === void 0) continue;
1856
2082
  const entry = groupEntry(group, gLabel, href, isActiveHref(href, currentPath));
1857
2083
  out.push({
@@ -2047,6 +2273,13 @@ function AppSidebar({ header, filters, nav, footer }) {
2047
2273
  });
2048
2274
  }
2049
2275
  //#endregion
2276
+ //#region src/layout/nav-chrome-mounted.ts
2277
+ const NavChromeMountedContext = (0, react.createContext)(false);
2278
+ const NavChromeMountedProvider = NavChromeMountedContext.Provider;
2279
+ function useNavChromeMounted() {
2280
+ return (0, react.useContext)(NavChromeMountedContext);
2281
+ }
2282
+ //#endregion
2050
2283
  //#region src/layout/nav-chrome.tsx
2051
2284
  const DETAIL_ACTIONS = new Set([
2052
2285
  "show",
@@ -2056,11 +2289,11 @@ const DETAIL_ACTIONS = new Set([
2056
2289
  function NavChrome({ children, entryFilter, icons }) {
2057
2290
  const app = (0, _burojs_react.useApp)();
2058
2291
  const caps = (0, _burojs_react.useI18nCaps)();
2059
- const isVisible = require_resource_page_router.useNavVisible();
2060
- const match = require_resource_page_router.useMatch();
2061
- const resolveLayout = require_resource_page_router.useLayoutResolver();
2062
- require_resource_page_router.useReportUnresolvedLayouts(match?.groupChain ?? [], resolveLayout);
2063
- if (!match) return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeMountedProvider, {
2292
+ const isVisible = useNavVisible();
2293
+ const match = useMatch();
2294
+ const resolveLayout = useLayoutResolver();
2295
+ useReportUnresolvedLayouts(match?.groupChain ?? [], resolveLayout);
2296
+ if (!match) return (0, react_jsx_runtime.jsx)(NavChromeMountedProvider, {
2064
2297
  value: true,
2065
2298
  children
2066
2299
  });
@@ -2068,11 +2301,11 @@ function NavChrome({ children, entryFilter, icons }) {
2068
2301
  for (let i = match.groupChain.length - 1; i >= 0; i--) {
2069
2302
  const group = match.groupChain[i];
2070
2303
  if (!group) continue;
2071
- const groupKey = require_resource_page_router.canonicalNavKey(group);
2304
+ const groupKey = require_record_trail_store.canonicalNavKey(group);
2072
2305
  if (group.chromeOn === "list" && match.kind === "resource" && DETAIL_ACTIONS.has(match.action)) continue;
2073
2306
  const Layout = resolveLayout(group.layout);
2074
2307
  if (!Layout) continue;
2075
- const items = require_resource_page_router.buildNavItems({
2308
+ const items = buildNavItems({
2076
2309
  registry: app.registry,
2077
2310
  caps,
2078
2311
  groupName: groupKey,
@@ -2088,12 +2321,1847 @@ function NavChrome({ children, entryFilter, icons }) {
2088
2321
  children: content
2089
2322
  });
2090
2323
  }
2091
- return (0, react_jsx_runtime.jsx)(require_resource_page_router.NavChromeMountedProvider, {
2324
+ return (0, react_jsx_runtime.jsx)(NavChromeMountedProvider, {
2092
2325
  value: true,
2093
2326
  children: content
2094
2327
  });
2095
2328
  }
2096
2329
  //#endregion
2330
+ //#region src/flows/page-flow-loader.tsx
2331
+ function PageFlowRouteLoader({ match }) {
2332
+ const t = (0, _burojs_react.useOptionalT)();
2333
+ const chromeT = (0, _burojs_react.useChromeT)();
2334
+ const loaded = require_check_confirm_dialog.useLoaded(require_check_confirm_dialog.loadPageFlowRoute);
2335
+ const failed = (retry) => (0, react_jsx_runtime.jsxs)("div", {
2336
+ role: "alert",
2337
+ "data-buro-flow-load": "failed",
2338
+ className: "flex flex-col gap-3 p-6 text-sm",
2339
+ children: [(0, react_jsx_runtime.jsx)("p", { children: require_check_confirm_dialog.loadFailedText(t) }), (0, react_jsx_runtime.jsx)("div", { children: (0, react_jsx_runtime.jsx)(require_button.Button, {
2340
+ type: "button",
2341
+ onClick: retry,
2342
+ children: chromeT("actions.retry", { defaultValue: "Retry" })
2343
+ }) })]
2344
+ });
2345
+ if (loaded.error !== void 0) return failed(loaded.retry);
2346
+ if (loaded.module === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
2347
+ const Route = loaded.module.PageFlowRoute;
2348
+ return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowBoundary, {
2349
+ fallback: (_error, reset) => failed(reset),
2350
+ children: (0, react_jsx_runtime.jsx)(Route, { match })
2351
+ });
2352
+ }
2353
+ //#endregion
2354
+ //#region src/list-kit/resource-list-page.tsx
2355
+ function ResourceListPage({ resource: resourceInput, meta, renderCell, emptyState }) {
2356
+ const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
2357
+ const app = (0, _burojs_react.useRouteListImplementation)();
2358
+ const implementation = require_place_node.selectImplementation("buro:related-list", app);
2359
+ const View = implementation === void 0 ? void 0 : require_place_node.viewOf(implementation);
2360
+ const translate = (0, _burojs_react.useTranslate)();
2361
+ const route = (0, react.useMemo)(() => ({
2362
+ meta,
2363
+ renderCell,
2364
+ emptyState
2365
+ }), [
2366
+ meta,
2367
+ renderCell,
2368
+ emptyState
2369
+ ]);
2370
+ const viewProps = (0, react.useMemo)(() => ({
2371
+ props: { resource: (0, _burojs_core.normalizeEntityRef)(resource) },
2372
+ data: {},
2373
+ t: (key, options) => translate(`blocks.buro:related-list.${key}`, options)
2374
+ }), [resource, translate]);
2375
+ return (0, react_jsx_runtime.jsx)("div", {
2376
+ "data-buro-node": "place",
2377
+ "data-buro-size": "full",
2378
+ className: "min-w-0",
2379
+ children: (0, react_jsx_runtime.jsx)(require_place_node.RouteListContext.Provider, {
2380
+ value: route,
2381
+ children: (0, react_jsx_runtime.jsx)(react.Suspense, {
2382
+ fallback: null,
2383
+ children: View === void 0 ? null : (0, react_jsx_runtime.jsx)(View, { ...viewProps })
2384
+ })
2385
+ })
2386
+ });
2387
+ }
2388
+ //#endregion
2389
+ //#region src/resource/collection-create-picker.tsx
2390
+ function CollectionCreatePicker({ collection }) {
2391
+ const app = (0, _burojs_react.useApp)();
2392
+ const t = (0, _burojs_react.useOptionalT)();
2393
+ const caps = (0, _burojs_react.useI18nCaps)();
2394
+ const gate = (0, _burojs_react.useAvailabilityGate)("create");
2395
+ const Link = require_toaster.useLinkComponent();
2396
+ const key = (0, _burojs_core.routeResourceKey)(collection);
2397
+ const testid = `collection-create-picker:${key}`;
2398
+ let undecided = false;
2399
+ const members = ((0, _burojs_core.collectionFactOf)(app.registry.get(key))?.members ?? []).flatMap((entry) => {
2400
+ const def = app.registry.get(entry.ref);
2401
+ if (def === void 0 || !(0, _burojs_core.hasRecordPage)(def, "create")) return [];
2402
+ const member = (0, _burojs_core.routeResourceKey)(entry.ref);
2403
+ const state = gate(member, "create").state;
2404
+ if (state === "undecided") undecided = true;
2405
+ if (state !== "available") return [];
2406
+ return [{
2407
+ member,
2408
+ href: (0, _burojs_core.resourceCreateHref)(app.registry, def, member),
2409
+ label: (0, _burojs_core.resolveResourceLabel)(caps, member, "single", def)
2410
+ }];
2411
+ });
2412
+ return (0, react_jsx_runtime.jsxs)("div", {
2413
+ "data-testid": testid,
2414
+ className: "mx-auto flex max-w-md flex-col gap-3 px-6 py-12",
2415
+ children: [(0, react_jsx_runtime.jsx)("h2", {
2416
+ className: "text-base font-semibold tracking-tight",
2417
+ children: t("collection.createTitle", { defaultValue: "What do you want to create?" })
2418
+ }), members.length > 0 ? (0, react_jsx_runtime.jsx)("ul", {
2419
+ className: "flex flex-col gap-2",
2420
+ children: members.map((entry) => (0, react_jsx_runtime.jsx)("li", { children: (0, react_jsx_runtime.jsx)(require_button.Button, {
2421
+ asChild: true,
2422
+ variant: "outline",
2423
+ className: "w-full justify-start",
2424
+ "data-testid": `${testid}:${entry.member}`,
2425
+ children: (0, react_jsx_runtime.jsxs)(Link, {
2426
+ href: entry.href,
2427
+ children: [(0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
2428
+ name: "Plus",
2429
+ className: "mr-1 h-4 w-4"
2430
+ }), entry.label]
2431
+ })
2432
+ }) }, entry.member))
2433
+ }) : undecided ? (0, react_jsx_runtime.jsx)("div", {
2434
+ role: "status",
2435
+ "aria-busy": "true",
2436
+ className: "h-9 w-full animate-pulse rounded bg-muted/40"
2437
+ }) : (0, react_jsx_runtime.jsx)("p", {
2438
+ className: "text-sm text-muted-foreground",
2439
+ children: t("collection.createNone", { defaultValue: "There is nothing here you can create." })
2440
+ })]
2441
+ });
2442
+ }
2443
+ //#endregion
2444
+ //#region src/frames/obligations.tsx
2445
+ const SlotMountsContext = (0, react.createContext)(null);
2446
+ function useSlotOnce(slot) {
2447
+ const mounts = (0, react.useContext)(SlotMountsContext);
2448
+ const token = (0, react.useId)();
2449
+ const first = mounts === null || mounts.claim(slot, token);
2450
+ (0, react.useEffect)(() => {
2451
+ if (mounts === null) return;
2452
+ mounts.claim(slot, token);
2453
+ return () => mounts.release(slot, token);
2454
+ }, [
2455
+ mounts,
2456
+ slot,
2457
+ token
2458
+ ]);
2459
+ (0, react.useEffect)(() => {
2460
+ if (!first) mounts?.twice(slot);
2461
+ }, [
2462
+ first,
2463
+ mounts,
2464
+ slot
2465
+ ]);
2466
+ return first;
2467
+ }
2468
+ function FrameObligations({ id, mode, showActions, root, children }) {
2469
+ const told = (0, react.useRef)(new Set());
2470
+ const counts = (0, react.useRef)(new Map());
2471
+ const owners = (0, react.useRef)(new Map());
2472
+ const tell = (key, write) => {
2473
+ if (told.current.has(key) || process.env.NODE_ENV === "production") return;
2474
+ told.current.add(key);
2475
+ write();
2476
+ };
2477
+ const latestId = (0, react.useRef)(id);
2478
+ latestId.current = id;
2479
+ const slotMounts = (0, react.useMemo)(() => ({
2480
+ claim(slot, token) {
2481
+ const owner = owners.current.get(slot);
2482
+ if (owner === void 0) {
2483
+ owners.current.set(slot, token);
2484
+ return true;
2485
+ }
2486
+ return owner === token;
2487
+ },
2488
+ release(slot, token) {
2489
+ if (owners.current.get(slot) === token) owners.current.delete(slot);
2490
+ },
2491
+ twice(slot) {
2492
+ tell(`slot-twice:${slot}`, () => console.error(`[burojs] frame.slot-twice: ${latestId.current} renders slots.${slot} twice; a slot renders at most once (body twice would mount every field twice under one form).`));
2493
+ }
2494
+ }), []);
2495
+ const pieces = (0, react.useMemo)(() => ({
2496
+ stub: false,
2497
+ mount(piece) {
2498
+ counts.current.set(piece, (counts.current.get(piece) ?? 0) + 1);
2499
+ return () => counts.current.set(piece, (counts.current.get(piece) ?? 1) - 1);
2500
+ }
2501
+ }), []);
2502
+ return (0, react_jsx_runtime.jsx)(SlotMountsContext.Provider, {
2503
+ value: slotMounts,
2504
+ children: (0, react_jsx_runtime.jsxs)(_burojs_react.FrameCheckContext.Provider, {
2505
+ value: pieces,
2506
+ children: [children, (0, react_jsx_runtime.jsx)(ObligationCheck, { check: () => {
2507
+ const mounted = (piece) => (counts.current.get(piece) ?? 0) > 0;
2508
+ if (mode !== "show" && !mounted("FormActions")) tell("no-form-actions", () => console.error(`[burojs] frame.no-form-actions: ${id} renders no <FormActions/> in ${mode}; nothing can submit or cancel the form.`));
2509
+ if (mode === "show" && showActions && !mounted("RecordActions")) tell("no-actions", () => console.warn(`[burojs] screen.no-actions: ${id} renders no <RecordActions/> in show, and the resource has item actions there.`));
2510
+ if (root.current?.querySelector("h1") != null) tell("h1", () => console.error(`[burojs] ${id} renders an h1; the route draws the screen's one h1.`));
2511
+ } })]
2512
+ })
2513
+ });
2514
+ }
2515
+ function ObligationCheck({ check }) {
2516
+ (0, react.useEffect)(() => {
2517
+ check();
2518
+ });
2519
+ return null;
2520
+ }
2521
+ //#endregion
2522
+ //#region src/frames/slot-wrapper.tsx
2523
+ function DraftBanner() {
2524
+ const { resource, mode, controller } = (0, _burojs_react.useRecordFrame)();
2525
+ const t = (0, _burojs_react.useOptionalT)();
2526
+ const tid = (0, _burojs_react.useTestIds)();
2527
+ const { draft } = controller;
2528
+ if (mode === "show" || draft.pending === null) return null;
2529
+ return (0, react_jsx_runtime.jsxs)("div", {
2530
+ "data-testid": tid.formDraftBanner(resource, mode),
2531
+ role: "status",
2532
+ "aria-live": "polite",
2533
+ className: "flex flex-wrap items-center gap-2 rounded-md border border-warning/50 bg-warning/10 px-3 py-2 text-sm",
2534
+ children: [
2535
+ (0, react_jsx_runtime.jsx)("span", {
2536
+ className: "font-medium",
2537
+ children: draft.recordChanged ? t("draft.recordChanged") : t("draft.found", { params: { time: timeAgo(draft.pending.savedAt, t) } })
2538
+ }),
2539
+ draft.recordChanged ? null : (0, react_jsx_runtime.jsx)("span", {
2540
+ className: "text-muted-foreground",
2541
+ children: t("draft.restorePrompt")
2542
+ }),
2543
+ (0, react_jsx_runtime.jsxs)("div", {
2544
+ className: "ml-auto flex gap-2",
2545
+ children: [draft.recordChanged ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
2546
+ type: "button",
2547
+ size: "sm",
2548
+ variant: "outline",
2549
+ "data-testid": tid.formDraftRestore(resource, mode),
2550
+ onClick: draft.restore,
2551
+ children: t("draft.restore")
2552
+ }), (0, react_jsx_runtime.jsx)(require_button.Button, {
2553
+ type: "button",
2554
+ size: "sm",
2555
+ variant: "ghost",
2556
+ "data-testid": tid.formDraftDiscard(resource, mode),
2557
+ onClick: draft.discard,
2558
+ children: t("draft.discard")
2559
+ })]
2560
+ })
2561
+ ]
2562
+ });
2563
+ }
2564
+ function timeAgo(savedAt, t) {
2565
+ const then = new Date(savedAt).getTime();
2566
+ if (!Number.isFinite(then)) return t("draft.timeAgoRecently");
2567
+ const diff = Date.now() - then;
2568
+ if (diff < 6e4) return t("draft.timeAgoMoment");
2569
+ if (diff < 36e5) return t("draft.timeAgoMinutes", { count: Math.round(diff / 6e4) });
2570
+ if (diff < 864e5) return t("draft.timeAgoHours", { count: Math.round(diff / 36e5) });
2571
+ return t("draft.timeAgoDays", { count: Math.round(diff / 864e5) });
2572
+ }
2573
+ function frameRecordId(frame, def) {
2574
+ if (frame.recordId !== void 0) return frame.recordId;
2575
+ const id = (0, _burojs_react.recordKeyOf)(def, frame.record);
2576
+ return typeof id === "string" || typeof id === "number" ? String(id) : void 0;
2577
+ }
2578
+ function BodySlot() {
2579
+ const frame = (0, _burojs_react.useRecordFrame)();
2580
+ const { resource, mode, controller } = frame;
2581
+ const chrome = require_place_node.useFrameChrome();
2582
+ const tid = (0, _burojs_react.useTestIds)();
2583
+ const id = frameRecordId(frame, (0, _burojs_react.useApp)().registry.get(resource));
2584
+ const tree = (0, react_jsx_runtime.jsx)("div", {
2585
+ "data-buro-region": "record-body",
2586
+ "data-buro-slot": _burojs_core.FORM_SLOT,
2587
+ children: (0, react_jsx_runtime.jsx)(require_place_node.ScreenTree, {
2588
+ region: "record",
2589
+ slot: _burojs_core.FORM_SLOT,
2590
+ resource,
2591
+ mode,
2592
+ compiled: controller.screen,
2593
+ controller
2594
+ })
2595
+ });
2596
+ if (mode === "show") return tree;
2597
+ return (0, react_jsx_runtime.jsxs)("form", {
2598
+ id: chrome.formId,
2599
+ noValidate: true,
2600
+ "data-testid": tid.form(resource, mode, id),
2601
+ onSubmit: (event) => {
2602
+ event.preventDefault();
2603
+ const steps = controller.steps;
2604
+ if (steps !== null && steps.current !== void 0 && steps.current !== steps.ids[steps.ids.length - 1]) steps.next();
2605
+ else chrome.submit();
2606
+ },
2607
+ className: "flex flex-col gap-4",
2608
+ children: [(0, react_jsx_runtime.jsx)(DraftBanner, {}), tree]
2609
+ });
2610
+ }
2611
+ function DisplaySlot({ name }) {
2612
+ const { resource, mode, controller } = (0, _burojs_react.useRecordFrame)();
2613
+ return (0, react_jsx_runtime.jsx)(require_place_node.ScreenTree, {
2614
+ region: "record",
2615
+ slot: name,
2616
+ resource,
2617
+ mode,
2618
+ compiled: controller.screen,
2619
+ controller
2620
+ });
2621
+ }
2622
+ function SlotWrapper({ name }) {
2623
+ if (!useSlotOnce(name)) return null;
2624
+ return name === _burojs_core.FORM_SLOT ? (0, react_jsx_runtime.jsx)(BodySlot, {}) : (0, react_jsx_runtime.jsx)(DisplaySlot, { name });
2625
+ }
2626
+ //#endregion
2627
+ //#region src/frames/record-frame-host.tsx
2628
+ const NO_ROOT = { current: null };
2629
+ function drawnFields(roots, compiled, out) {
2630
+ for (const node of roots) {
2631
+ if (node.state === "absent") continue;
2632
+ const field = node.field ?? compiled.nodes[node.index]?.field;
2633
+ if (node.kind === "field" && field !== void 0 && node.state === "ready") out.add(field);
2634
+ drawnFields(node.children, compiled, out);
2635
+ }
2636
+ }
2637
+ function frameRecord(record, compiled, slots, idField, visible = () => true) {
2638
+ if (record === void 0 || compiled === null || slots === void 0) return void 0;
2639
+ const drawn = new Set();
2640
+ for (const roots of Object.values(slots)) drawnFields(roots, compiled, drawn);
2641
+ const declarations = new Map(compiled.fields.map((entry) => [entry.name, entry.declaration]));
2642
+ const out = {};
2643
+ if (Object.hasOwn(record, idField)) out[idField] = record[idField];
2644
+ for (const name of drawn) {
2645
+ if (!Object.hasOwn(record, name) || !visible(name)) continue;
2646
+ if ((0, _burojs_core.fieldSensitivity)(declarations.get(name)) !== void 0) continue;
2647
+ out[name] = record[name];
2648
+ }
2649
+ return Object.freeze(out);
2650
+ }
2651
+ function declaredSlots(compiled) {
2652
+ if (compiled === null) return [];
2653
+ return Object.entries(compiled.slots).filter(([, nodes]) => nodes.length > 0).map(([name]) => name);
2654
+ }
2655
+ function useEffectiveFrame(instance) {
2656
+ const { resource, mode, controller } = (0, _burojs_react.useRecordFrame)();
2657
+ const compiled = controller.screen;
2658
+ const missing = (0, react.useMemo)(() => {
2659
+ if (instance === void 0 || instance.for !== "record") return void 0;
2660
+ const own = new Set(Object.keys(instance.slots));
2661
+ return declaredSlots(compiled).find((slot) => !own.has(slot));
2662
+ }, [instance, compiled]);
2663
+ const told = (0, react.useRef)(false);
2664
+ const instanceId = instance === void 0 ? void 0 : (0, _burojs_core.formatEntityRef)(instance.ref);
2665
+ (0, react.useEffect)(() => {
2666
+ if (missing === void 0 || told.current || process.env.NODE_ENV === "production") return;
2667
+ told.current = true;
2668
+ console.error(`[burojs] <RecordScreen frame={${instanceId}}> lacks the slot ${missing} that ${resource}'s ${mode} screen fills; the screen's own frame draws it.`);
2669
+ }, [
2670
+ missing,
2671
+ instanceId,
2672
+ resource,
2673
+ mode
2674
+ ]);
2675
+ if (instance !== void 0 && instance.for === "record" && missing === void 0 && compiled !== null) return {
2676
+ ref: instance.ref,
2677
+ slotNames: Object.keys(instance.slots)
2678
+ };
2679
+ return {
2680
+ ref: compiled?.frame ?? _burojs_core.builtinFrames.record.ref,
2681
+ slotNames: compiled === null ? ["header", _burojs_core.FORM_SLOT] : Object.keys(compiled.slots)
2682
+ };
2683
+ }
2684
+ function RecordFrameView({ frame: instance }) {
2685
+ const { resource, mode, controller, record } = (0, _burojs_react.useRecordFrame)();
2686
+ const chrome = require_place_node.useFrameChrome();
2687
+ const quick = (0, _burojs_react.useQuickEntry)();
2688
+ const app = (0, _burojs_react.useApp)();
2689
+ const catalog = (0, _burojs_react.useFrameImplementations)();
2690
+ const { ref, slotNames } = useEffectiveFrame(instance);
2691
+ const id = (0, _burojs_core.formatEntityRef)(ref);
2692
+ const resolved = (0, react.useMemo)(() => require_place_node.resolveFrameView(ref, catalog, "record"), [ref, catalog]);
2693
+ const t = (0, _burojs_react.useFrameT)(id);
2694
+ const compiled = controller.screen;
2695
+ const plan = controller.plan;
2696
+ const slots = {};
2697
+ for (const name of slotNames) {
2698
+ if (name === _burojs_core.FORM_SLOT) {
2699
+ slots[name] = (0, react_jsx_runtime.jsx)(SlotWrapper, { name }, name);
2700
+ continue;
2701
+ }
2702
+ slots[name] = (plan?.slots[name] ?? []).every((node) => node.state === "absent") ? null : (0, react_jsx_runtime.jsx)(SlotWrapper, { name }, name);
2703
+ }
2704
+ slots[_burojs_core.FORM_SLOT] ??= (0, react_jsx_runtime.jsx)(SlotWrapper, { name: _burojs_core.FORM_SLOT });
2705
+ const idField = app.registry.get(resource)?.data?.idField ?? "id";
2706
+ const access = (0, _burojs_react.useFieldAccess)(resource, "record", record === void 0 ? void 0 : (0, _burojs_react.policyRecordOf)(controller, record));
2707
+ const projected = (0, react.useMemo)(() => frameRecord(record, compiled, plan?.slots, idField, (name) => access[name]?.view === "visible"), [
2708
+ record,
2709
+ compiled,
2710
+ plan,
2711
+ idField,
2712
+ access
2713
+ ]);
2714
+ const quickHost = chrome.hostTitle === true && quick !== null;
2715
+ const props = {
2716
+ slots,
2717
+ host: quickHost ? quick.host : "page",
2718
+ mode,
2719
+ screen: {
2720
+ resource,
2721
+ entry: quickHost ? "quick" : "route"
2722
+ },
2723
+ record: mode === "create" ? void 0 : projected,
2724
+ t
2725
+ };
2726
+ const policyRecord = (0, _burojs_react.policyRecordOf)(controller, record);
2727
+ const rowId = record?.[idField];
2728
+ const actionRow = (0, react.useMemo)(() => ({
2729
+ ...policyRecord ?? {},
2730
+ id: typeof rowId === "string" || typeof rowId === "number" ? String(rowId) : ""
2731
+ }), [policyRecord, rowId]);
2732
+ const showItemActions = require_place_node.useShownItemActions(resource, actionRow, "show", void 0, controller.sources);
2733
+ const showActions = mode === "show" && record !== void 0 && showItemActions.length > 0;
2734
+ const View = resolved.view;
2735
+ const builtin = require_place_node.isBuiltinRecordView(resolved);
2736
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [builtin ? null : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_place_node.HeaderTypeNotice, { resource }), (0, react_jsx_runtime.jsx)(require_place_node.ChangeTypeButton, {})] }), (0, react_jsx_runtime.jsx)(require_place_node.TypeChromeDrawnContext.Provider, {
2737
+ value: !builtin,
2738
+ children: (0, react_jsx_runtime.jsx)(react.Suspense, {
2739
+ fallback: (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" }),
2740
+ children: (0, react_jsx_runtime.jsx)(FrameObligations, {
2741
+ id,
2742
+ mode,
2743
+ showActions,
2744
+ root: chrome.root ?? NO_ROOT,
2745
+ children: (0, react_jsx_runtime.jsx)(View, { ...props })
2746
+ })
2747
+ })
2748
+ })] });
2749
+ }
2750
+ function useResourceDimensionOptions(dimension, resource, labelField) {
2751
+ const def = (0, _burojs_react.useApp)().registry.get(resource);
2752
+ const rowTitle = require_relation_create.useRowTitle(resource, labelField ?? def?.displayField);
2753
+ const rows = (0, _burojs_react.useList)(resource, {
2754
+ pagination: {
2755
+ kind: "offset",
2756
+ page: 1,
2757
+ pageSize: 100
2758
+ },
2759
+ total: false,
2760
+ scope: {
2761
+ default: "session",
2762
+ dimensions: { [dimension]: "none" }
2763
+ }
2764
+ }).data?.data;
2765
+ return (0, react.useMemo)(() => (rows ?? []).flatMap((row) => {
2766
+ const key = (0, _burojs_react.recordKeyOf)(def, row);
2767
+ return key === null || key === void 0 ? [] : [{
2768
+ value: key,
2769
+ label: rowTitle(row)
2770
+ }];
2771
+ }), [
2772
+ rows,
2773
+ def,
2774
+ rowTitle
2775
+ ]);
2776
+ }
2777
+ //#endregion
2778
+ //#region src/record/scope-mismatch-banner.tsx
2779
+ const asList = (value) => value === null ? [] : Array.isArray(value) ? value : [value];
2780
+ const isScalar = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
2781
+ function ScopeMismatchBanner(props) {
2782
+ const app = (0, _burojs_react.useApp)();
2783
+ const mapping = app.registry.get(props.resource)?.data?.scope;
2784
+ if (app.scope === void 0 || mapping === void 0 || props.record === void 0) return null;
2785
+ return (0, react_jsx_runtime.jsx)(Banner, {
2786
+ ...props,
2787
+ record: props.record,
2788
+ mapping
2789
+ });
2790
+ }
2791
+ function Banner({ record, mapping, kind = "record" }) {
2792
+ const scope = (0, _burojs_react.useScope)();
2793
+ const chromeT = (0, _burojs_react.useChromeT)();
2794
+ const differences = (0, react.useMemo)(() => {
2795
+ const out = [];
2796
+ for (const [dimension, target] of Object.entries(mapping)) {
2797
+ const definition = scope.definition?.dimensions[dimension];
2798
+ if (definition === void 0 || definition.select === "none") continue;
2799
+ const selected = asList(scope.selection[dimension] ?? null);
2800
+ if (selected.length === 0) continue;
2801
+ const column = (0, _burojs_core.scopeColumnOf)(target);
2802
+ if (!Object.hasOwn(record, column)) continue;
2803
+ const held = record[column];
2804
+ if (held === null || held === void 0 || held === "") {
2805
+ if (kind === "created" || "field" in target && target.empty === "shared") continue;
2806
+ out.push({
2807
+ dimension,
2808
+ value: null,
2809
+ selected,
2810
+ select: definition.select
2811
+ });
2812
+ continue;
2813
+ }
2814
+ if (!isScalar(held)) continue;
2815
+ if (selected.some((value) => String(value) === String(held))) continue;
2816
+ out.push({
2817
+ dimension,
2818
+ value: held,
2819
+ selected,
2820
+ select: definition.select
2821
+ });
2822
+ }
2823
+ return out;
2824
+ }, [
2825
+ mapping,
2826
+ record,
2827
+ scope.definition,
2828
+ scope.selection,
2829
+ kind
2830
+ ]);
2831
+ if (differences.length === 0) return null;
2832
+ const apply = () => {
2833
+ for (const difference of differences) scope.select(difference.dimension, difference.value === null ? null : difference.select === "multiple" ? [difference.value] : difference.value);
2834
+ };
2835
+ return (0, react_jsx_runtime.jsxs)("div", {
2836
+ role: "status",
2837
+ "data-testid": "scope-mismatch:banner",
2838
+ className: "flex flex-wrap items-center justify-between gap-3 rounded-md border bg-muted/50 px-3 py-2 text-sm",
2839
+ children: [(0, react_jsx_runtime.jsxs)("div", {
2840
+ className: "space-y-1",
2841
+ children: [(0, react_jsx_runtime.jsx)("p", {
2842
+ className: "font-medium",
2843
+ children: kind === "created" ? chromeT("scope.mismatch.createdOutside", { defaultValue: "Created outside the current scope" }) : chromeT("scope.mismatch.title", { defaultValue: "This record is outside the current scope" })
2844
+ }), (0, react_jsx_runtime.jsx)("ul", {
2845
+ className: "text-muted-foreground",
2846
+ children: differences.map((difference) => (0, react_jsx_runtime.jsx)(DifferenceLine, {
2847
+ difference,
2848
+ definition: scope.definition.dimensions[difference.dimension]
2849
+ }, difference.dimension))
2850
+ })]
2851
+ }), (0, react_jsx_runtime.jsx)(require_button.Button, {
2852
+ type: "button",
2853
+ size: "sm",
2854
+ "data-testid": "scope-mismatch:switch",
2855
+ onClick: apply,
2856
+ children: chromeT("scope.mismatch.switch", { defaultValue: "Switch" })
2857
+ })]
2858
+ });
2859
+ }
2860
+ function DifferenceLine(props) {
2861
+ const source = props.definition.values;
2862
+ if (source !== void 0 && !Array.isArray(source)) {
2863
+ const { resource, label } = source;
2864
+ return (0, react_jsx_runtime.jsx)(ResourceLine, {
2865
+ ...props,
2866
+ resource,
2867
+ ...label ? { labelField: label } : {}
2868
+ });
2869
+ }
2870
+ return (0, react_jsx_runtime.jsx)(LineText, {
2871
+ difference: props.difference,
2872
+ options: source ?? []
2873
+ });
2874
+ }
2875
+ function ResourceLine({ difference, resource, labelField }) {
2876
+ const options = useResourceDimensionOptions(difference.dimension, resource, labelField);
2877
+ return (0, react_jsx_runtime.jsx)(LineText, {
2878
+ difference,
2879
+ options
2880
+ });
2881
+ }
2882
+ function LineText({ difference, options }) {
2883
+ const chromeT = (0, _burojs_react.useChromeT)();
2884
+ const labelOf = (value) => options.find((option) => String(option.value) === String(value))?.label ?? String(value);
2885
+ const field = (0, _burojs_core.humanizeKey)(difference.dimension);
2886
+ const item = difference.value === null ? chromeT("scope.mismatch.empty", { defaultValue: "not set" }) : labelOf(difference.value);
2887
+ const items = difference.selected.map(labelOf).join(", ");
2888
+ return (0, react_jsx_runtime.jsx)("li", {
2889
+ "data-testid": `scope-mismatch:line:${difference.dimension}`,
2890
+ children: chromeT("scope.mismatch.line", {
2891
+ params: {
2892
+ field,
2893
+ item,
2894
+ items
2895
+ },
2896
+ defaultValue: `${field}: ${item} (selected: ${items})`
2897
+ })
2898
+ });
2899
+ }
2900
+ //#endregion
2901
+ //#region src/record/type-offer.tsx
2902
+ function TypeOffer({ resource, offer, onChoose }) {
2903
+ const app = (0, _burojs_react.useApp)();
2904
+ const t = (0, _burojs_react.useOptionalT)();
2905
+ const tid = (0, _burojs_react.useTestIds)();
2906
+ const def = app.registry.get(resource);
2907
+ const by = def?.types?.by;
2908
+ const field = by === void 0 ? void 0 : def?.fields[by];
2909
+ const ref = def?.ref ?? {
2910
+ namespace: "default",
2911
+ id: resource
2912
+ };
2913
+ return (0, react_jsx_runtime.jsxs)("section", {
2914
+ "aria-labelledby": "type-offer-title",
2915
+ className: "flex flex-col gap-3",
2916
+ children: [(0, react_jsx_runtime.jsxs)("div", {
2917
+ className: "flex flex-col gap-1",
2918
+ children: [(0, react_jsx_runtime.jsx)("h2", {
2919
+ id: "type-offer-title",
2920
+ className: "text-base font-semibold",
2921
+ children: t("create.typeOffer.title", { defaultValue: "Choose a type" })
2922
+ }), (0, react_jsx_runtime.jsx)("p", {
2923
+ className: "text-sm text-muted-foreground",
2924
+ children: t("create.typeOffer.hint", { defaultValue: "The type decides which fields the record has." })
2925
+ })]
2926
+ }), offer.status === "pending" ? (0, react_jsx_runtime.jsxs)("div", {
2927
+ "aria-busy": "true",
2928
+ className: "flex flex-col gap-2",
2929
+ children: [(0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, { className: "h-10 w-full" }), (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, { className: "h-10 w-full" })]
2930
+ }) : offer.types.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
2931
+ role: "status",
2932
+ className: "text-sm text-muted-foreground",
2933
+ children: t("create.typeOffer.empty", { defaultValue: "No type can be created here." })
2934
+ }) : (0, react_jsx_runtime.jsx)("ul", {
2935
+ className: "grid grid-cols-1 gap-2 sm:grid-cols-2",
2936
+ children: offer.types.map((type) => (0, react_jsx_runtime.jsx)("li", { children: (0, react_jsx_runtime.jsx)("button", {
2937
+ type: "button",
2938
+ "data-testid": tid.typeOffer(resource, type),
2939
+ onClick: () => onChoose(type),
2940
+ className: "flex w-full items-center gap-2 rounded-md border px-3 py-2 text-left text-sm hover:bg-muted focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
2941
+ children: by === void 0 || field === void 0 ? type : (0, react_jsx_runtime.jsx)(require_place_node.FieldDisplay, {
2942
+ resource: ref,
2943
+ name: by,
2944
+ field,
2945
+ value: type,
2946
+ fallback: (0, react_jsx_runtime.jsx)("span", { children: type })
2947
+ })
2948
+ }) }, type))
2949
+ })]
2950
+ });
2951
+ }
2952
+ //#endregion
2953
+ //#region src/record/record-screen.tsx
2954
+ function isAbort(error) {
2955
+ if (error === null || typeof error !== "object" && typeof error !== "function") return false;
2956
+ try {
2957
+ return error.name === "AbortError";
2958
+ } catch {
2959
+ return false;
2960
+ }
2961
+ }
2962
+ const NO_ISSUES = Object.freeze([]);
2963
+ const APPLIED_UNREADABLE = Object.freeze({
2964
+ code: "applied-unreadable",
2965
+ message: Object.freeze({
2966
+ key: "errors.appliedUnreadable",
2967
+ default: "Saved. The server's answer could not be read, so the screen may not show the latest values."
2968
+ }),
2969
+ path: Object.freeze([]),
2970
+ source: "server",
2971
+ severity: "info"
2972
+ });
2973
+ function issuesOf(error) {
2974
+ if (error === null || typeof error !== "object") return void 0;
2975
+ try {
2976
+ const descriptor = Object.getOwnPropertyDescriptor(error, "issues");
2977
+ return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
2978
+ } catch {
2979
+ return;
2980
+ }
2981
+ }
2982
+ const NO_EDITED = new Set();
2983
+ function sameValue(a, b) {
2984
+ if (Object.is(a, b)) return true;
2985
+ try {
2986
+ return JSON.stringify(a) === JSON.stringify(b);
2987
+ } catch {
2988
+ return false;
2989
+ }
2990
+ }
2991
+ function RecordFrameHost(props) {
2992
+ const { resource, mode } = props;
2993
+ const [failed, setFailed] = (0, react.useState)(NO_ISSUES);
2994
+ const named = (0, react.useMemo)(() => failed.length === 0 ? NO_ISSUES : (0, _burojs_core.routeServerIssues)({ issues: failed }, (segment) => segment, (field) => field !== "_form").fields, [failed]);
2995
+ const atFailure = (0, react.useRef)({});
2996
+ const [edited, setEdited] = (0, react.useState)(NO_EDITED);
2997
+ const controller = (0, _burojs_react.useFormController)({
2998
+ resource,
2999
+ mode,
3000
+ ...props.recordId === void 0 ? {} : { recordId: props.recordId },
3001
+ ...props.type === void 0 ? {} : { type: props.type },
3002
+ ...props.record === void 0 ? {} : { record: props.record },
3003
+ ...props.defaults === void 0 ? {} : { defaults: props.defaults },
3004
+ ...props.onSubmit === void 0 ? {} : { onSubmit: props.onSubmit },
3005
+ ...props.hostTitle ? { entry: "quick" } : {},
3006
+ serverIssues: named
3007
+ });
3008
+ const inputApplied = (0, react.useRef)(false);
3009
+ const { input } = props;
3010
+ const plan = controller.plan;
3011
+ (0, react.useEffect)(() => {
3012
+ if (inputApplied.current || input === void 0 || mode !== "create" || plan === null) return;
3013
+ inputApplied.current = true;
3014
+ for (const [key, value] of Object.entries(input)) if (plan.fields[key] === "active") controller.setValue(key, value);
3015
+ }, [
3016
+ input,
3017
+ mode,
3018
+ plan,
3019
+ controller
3020
+ ]);
3021
+ const tid = (0, _burojs_react.useTestIds)();
3022
+ const formId = `record-form-${(0, react.useId)()}`;
3023
+ const root = (0, react.useRef)(null);
3024
+ const [submitError, setSubmitError] = (0, react.useState)(void 0);
3025
+ const [submitApplied, setSubmitApplied] = (0, react.useState)(void 0);
3026
+ (0, react.useEffect)(() => {
3027
+ if (plan === null) return;
3028
+ const now = Object.keys(atFailure.current).filter((name) => !edited.has(name) && plan.fields[name] === "active" && !sameValue(controller.field(name).value, atFailure.current[name]));
3029
+ if (now.length > 0) setEdited((previous) => new Set([...previous, ...now]));
3030
+ }, [
3031
+ plan,
3032
+ controller,
3033
+ edited
3034
+ ]);
3035
+ const notify = require_success_notices.useNoticeSink(resource);
3036
+ const routeScreen = require_place_node.useIsRouteScreen();
3037
+ const leavesOnCreate = mode === "create" && routeScreen;
3038
+ const [created, setCreated] = (0, react.useState)(false);
3039
+ const createdRef = (0, react.useRef)(false);
3040
+ const latest = (0, react.useRef)({
3041
+ controller,
3042
+ onSuccess: props.onSuccess,
3043
+ notify,
3044
+ leavesOnCreate
3045
+ });
3046
+ latest.current = {
3047
+ controller,
3048
+ onSuccess: props.onSuccess,
3049
+ notify,
3050
+ leavesOnCreate
3051
+ };
3052
+ const mounted = (0, react.useRef)(true);
3053
+ (0, react.useEffect)(() => {
3054
+ mounted.current = true;
3055
+ return () => {
3056
+ mounted.current = false;
3057
+ };
3058
+ }, []);
3059
+ const submit = (0, react.useCallback)(async () => {
3060
+ if (createdRef.current) return;
3061
+ setSubmitError(void 0);
3062
+ setSubmitApplied(void 0);
3063
+ setFailed(NO_ISSUES);
3064
+ setEdited(NO_EDITED);
3065
+ atFailure.current = {};
3066
+ const outcome = await latest.current.controller.submit();
3067
+ if (!mounted.current) return;
3068
+ if (latest.current.leavesOnCreate && (outcome.status === "submitted" || outcome.status === "failed" && outcome.applied === "yes")) {
3069
+ createdRef.current = true;
3070
+ setCreated(true);
3071
+ }
3072
+ if (outcome.status === "submitted") {
3073
+ const notices = (0, _burojs_core.successNoticesOf)(outcome.result);
3074
+ if (notices.length > 0) latest.current.notify(notices);
3075
+ latest.current.onSuccess?.(outcome.result);
3076
+ } else if (outcome.status === "failed" && outcome.applied === "yes") {
3077
+ latest.current.notify([APPLIED_UNREADABLE]);
3078
+ latest.current.onSuccess?.(void 0);
3079
+ } else if (outcome.status === "failed" && !isAbort(outcome.error)) {
3080
+ setSubmitError(outcome.error ?? null);
3081
+ setSubmitApplied(outcome.applied);
3082
+ const issues = (0, _burojs_core.normalizeIssueInputs)(issuesOf(outcome.error)).issues;
3083
+ const next = issues.length === 0 ? NO_ISSUES : Object.freeze(issues.map(_burojs_core.issueOfInput));
3084
+ const held = {};
3085
+ const now = latest.current.controller;
3086
+ for (const issue of next) {
3087
+ const head = issue.path[0];
3088
+ if (typeof head === "string" && head !== "_form" && now.plan?.fields[head] === "active") held[head] = now.field(head).value;
3089
+ }
3090
+ atFailure.current = held;
3091
+ setFailed(next);
3092
+ }
3093
+ }, []);
3094
+ const record = controller.record;
3095
+ const recordText = props.recordId === void 0 ? void 0 : String(props.recordId);
3096
+ const frame = (0, react.useMemo)(() => ({
3097
+ resource,
3098
+ recordId: recordText,
3099
+ mode,
3100
+ record,
3101
+ controller
3102
+ }), [
3103
+ resource,
3104
+ recordText,
3105
+ mode,
3106
+ record,
3107
+ controller
3108
+ ]);
3109
+ const { chooseType } = props;
3110
+ const typedAndAccepted = mode === "create" && controller.typeOffer !== null && controller.failure === null;
3111
+ const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
3112
+ const hostRouter = routeScreen ? adapter : null;
3113
+ const guardText = (0, _burojs_react.useNavigationGuardText)();
3114
+ const changeType = (0, react.useMemo)(() => typedAndAccepted ? () => {
3115
+ if (hostRouter === null && latest.current.controller.isDirty && !window.confirm(`${guardText.title}\n\n${guardText.body}`)) return;
3116
+ chooseType(void 0);
3117
+ } : void 0, [
3118
+ typedAndAccepted,
3119
+ chooseType,
3120
+ hostRouter,
3121
+ guardText.title,
3122
+ guardText.body
3123
+ ]);
3124
+ const app = (0, _burojs_react.useApp)();
3125
+ const typesDecl = app.registry.get(resource)?.types;
3126
+ const loaded = controller.record;
3127
+ const unsupportedType = (0, react.useMemo)(() => {
3128
+ if (mode === "create" || typesDecl === void 0 || loaded === void 0) return void 0;
3129
+ const value = loaded[typesDecl.by];
3130
+ const name = typeof value === "string" && value !== "" ? value : null;
3131
+ return name !== null && typesDecl.items.some((item) => item.name === name) ? void 0 : name;
3132
+ }, [
3133
+ mode,
3134
+ typesDecl,
3135
+ loaded
3136
+ ]);
3137
+ const shownFailed = (0, react.useMemo)(() => edited.size === 0 ? failed : Object.freeze(failed.filter((issue) => {
3138
+ const head = issue.path[0];
3139
+ return typeof head !== "string" || !edited.has(head);
3140
+ })), [failed, edited]);
3141
+ const chrome = (0, react.useMemo)(() => ({
3142
+ ...props.onCancel === void 0 ? {} : { onCancel: props.onCancel },
3143
+ ...props.submitLabel === void 0 ? {} : { submitLabel: props.submitLabel },
3144
+ ...props.extraActions === void 0 ? {} : { extraActions: props.extraActions },
3145
+ ...changeType === void 0 ? {} : { changeType },
3146
+ ...unsupportedType === void 0 ? {} : { unsupportedType },
3147
+ ...props.hostTitle ? { hostTitle: true } : {},
3148
+ formId,
3149
+ submitError,
3150
+ ...submitApplied === void 0 ? {} : { submitApplied },
3151
+ serverIssues: shownFailed,
3152
+ ...created ? { created: true } : {},
3153
+ submit,
3154
+ root
3155
+ }), [
3156
+ props.onCancel,
3157
+ props.submitLabel,
3158
+ props.extraActions,
3159
+ changeType,
3160
+ unsupportedType,
3161
+ props.hostTitle,
3162
+ formId,
3163
+ submitError,
3164
+ submitApplied,
3165
+ shownFailed,
3166
+ created,
3167
+ submit
3168
+ ]);
3169
+ (0, _burojs_react.usePublishDocVariant)(mode === "show" ? resource : void 0, record);
3170
+ const failure = controller.failure;
3171
+ const offering = failure?.kind === "type-required" && controller.typeOffer !== null;
3172
+ (0, react.useEffect)(() => {
3173
+ if (failure === null || offering || process.env.NODE_ENV === "production") return;
3174
+ console.error(`[burojs] <RecordScreen resource="${resource}" mode="${mode}"> cannot render its screen: ${failure.kind === "screen" ? `${failure.failure.code} at ${failure.failure.path.join(".")}: ${failure.failure.message}` : "a typed create needs an accepted type"}.`);
3175
+ }, [
3176
+ failure,
3177
+ offering,
3178
+ resource,
3179
+ mode
3180
+ ]);
3181
+ const formControl = require_place_node.useFormControlOf(controller);
3182
+ const id = frameRecordId(frame, app.registry.get(frame.resource));
3183
+ const rootId = mode === "show" ? tid.pageShow(resource, id ?? "") : mode === "edit" ? tid.pageEdit(resource, id ?? "") : tid.pageCreate(resource);
3184
+ const claimedRoute = (0, react.useContext)(_burojs_react.RouteSourceContext);
3185
+ const scopeValues = mode === "show" ? controller.record : controller.values;
3186
+ return (0, react_jsx_runtime.jsx)(_burojs_react.RecordScopeProvider, {
3187
+ resource,
3188
+ ...recordText === void 0 ? {} : { recordId: recordText },
3189
+ values: scopeValues,
3190
+ create: mode === "create",
3191
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
3192
+ value: null,
3193
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ActionRouteContext.Provider, {
3194
+ value: claimedRoute,
3195
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.RecordFrameContext.Provider, {
3196
+ value: frame,
3197
+ children: (0, react_jsx_runtime.jsx)(require_place_node.FrameChromeContext.Provider, {
3198
+ value: chrome,
3199
+ children: (0, react_jsx_runtime.jsxs)(require_place_node.FormControlProvider, {
3200
+ value: formControl,
3201
+ children: [(0, react_jsx_runtime.jsx)(require_place_node.DeepLinkScope, {
3202
+ plan: controller.plan,
3203
+ enabled: routeScreen && mode !== "create",
3204
+ children: (0, react_jsx_runtime.jsx)("div", {
3205
+ ref: root,
3206
+ "data-testid": rootId,
3207
+ className: "flex flex-col gap-[var(--buro-section-gap)]",
3208
+ children: offering && controller.typeOffer !== null ? (0, react_jsx_runtime.jsx)(TypeOffer, {
3209
+ resource,
3210
+ offer: controller.typeOffer,
3211
+ onChoose: (type) => chooseType(type)
3212
+ }) : failure !== null ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "error" }), (0, react_jsx_runtime.jsx)(require_place_node.FormActions, {})] }) : mode === "edit" && unsupportedType !== void 0 ? (0, react_jsx_runtime.jsx)(require_place_node.UndeclaredTypeNotice, {
3213
+ resource,
3214
+ typeValue: unsupportedType
3215
+ }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(ScopeMismatchBanner, {
3216
+ resource,
3217
+ record: mode === "create" ? controller.trustedSeeds : controller.record,
3218
+ kind: mode === "create" ? "created" : "record"
3219
+ }), (0, react_jsx_runtime.jsx)(RecordFrameView, { ...props.frame === void 0 ? {} : { frame: props.frame } })] })
3220
+ })
3221
+ }), controller.checkGate === null ? null : (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.CheckConfirmDialog, {
3222
+ state: controller.checkGate,
3223
+ testid: `${tid.form(resource, mode, id)}:checks`
3224
+ })]
3225
+ })
3226
+ })
3227
+ })
3228
+ })
3229
+ })
3230
+ });
3231
+ }
3232
+ function RecordScreen(props) {
3233
+ const app = (0, _burojs_react.useApp)();
3234
+ const routeScreen = (0, react.useContext)(require_place_node.RouteScreenClaimContext);
3235
+ const quickScreen = (0, react.useContext)(require_place_node.QuickScreenClaimContext);
3236
+ const route = (0, react.useContext)(_burojs_react.RouteSourceContext);
3237
+ const resourceInput = props.resource;
3238
+ const resource = (0, _burojs_core.resourceKey)(resourceInput);
3239
+ const tabs = require_place_node.useTabsUrlState(props.mode, routeScreen);
3240
+ const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
3241
+ const router = routeScreen ? adapter : null;
3242
+ const navigate = (0, _burojs_react.useRouteNavigate)();
3243
+ const [local, setLocal] = (0, react.useState)(props.type);
3244
+ const [typeProp, setTypeProp] = (0, react.useState)(props.type);
3245
+ if (props.type !== typeProp) {
3246
+ setTypeProp(props.type);
3247
+ setLocal(props.type);
3248
+ }
3249
+ const [chose, setChose] = (0, react.useState)(false);
3250
+ const fromUrl = router?.searchParams.get("type") ?? void 0;
3251
+ const type = props.mode !== "create" ? props.type : router === null ? local : chose ? fromUrl : props.type ?? fromUrl;
3252
+ const chooseType = (0, react.useCallback)((next) => {
3253
+ if (router === null) {
3254
+ setLocal(next);
3255
+ return;
3256
+ }
3257
+ setChose(true);
3258
+ const params = new URLSearchParams(router.searchParams);
3259
+ if (next === void 0) params.delete("type");
3260
+ else params.set("type", next);
3261
+ const query = params.toString();
3262
+ navigate(query === "" ? router.pathname : `${router.pathname}?${query}`);
3263
+ }, [router, navigate]);
3264
+ if (app.registry.get(resource) === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3265
+ const { type: _declared, ...rest } = props;
3266
+ return (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenClaimContext.Provider, {
3267
+ value: false,
3268
+ children: (0, react_jsx_runtime.jsx)(require_place_node.QuickScreenClaimContext.Provider, {
3269
+ value: false,
3270
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
3271
+ value: routeScreen || quickScreen ? route : null,
3272
+ children: (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenContext.Provider, {
3273
+ value: routeScreen,
3274
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ResourceContext.Provider, {
3275
+ value: { resource },
3276
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ScreenStateProvider, {
3277
+ open: tabs.open,
3278
+ onOpenChange: tabs.onOpenChange,
3279
+ children: (0, react_jsx_runtime.jsx)(RecordFrameHost, {
3280
+ ...rest,
3281
+ ...type === void 0 ? {} : { type },
3282
+ resource,
3283
+ chooseType,
3284
+ hostTitle: quickScreen
3285
+ }, type ?? "")
3286
+ })
3287
+ })
3288
+ })
3289
+ })
3290
+ })
3291
+ });
3292
+ }
3293
+ //#endregion
3294
+ //#region src/layout/record-targets.ts
3295
+ function isShowAvailable(registry, resource) {
3296
+ return (0, _burojs_react.recordRouteAvailable)(registry, resource, "show");
3297
+ }
3298
+ function showTarget(resource, id) {
3299
+ return {
3300
+ resource,
3301
+ action: "show",
3302
+ params: { id }
3303
+ };
3304
+ }
3305
+ function listTarget(resource) {
3306
+ return {
3307
+ resource,
3308
+ action: "list"
3309
+ };
3310
+ }
3311
+ //#endregion
3312
+ //#region src/layout/route-trail.ts
3313
+ function useTrailContext() {
3314
+ const app = (0, _burojs_react.useApp)();
3315
+ const caps = (0, _burojs_react.useI18nCaps)();
3316
+ const isVisible = useNavVisible();
3317
+ const t = (0, _burojs_react.useT)();
3318
+ return {
3319
+ registry: app.registry,
3320
+ caps,
3321
+ isVisible,
3322
+ t
3323
+ };
3324
+ }
3325
+ function groupCrumbs(ctx, chain) {
3326
+ return chain.map((group) => {
3327
+ const key = require_record_trail_store.canonicalNavKey(group);
3328
+ return {
3329
+ label: (0, _burojs_core.resolveNavLabel)(ctx.caps, `groups.${key}`, (0, _burojs_core.declaredText)("chrome", group, "label")),
3330
+ href: groupNavHref(ctx.registry, key, ctx.isVisible),
3331
+ jump: true
3332
+ };
3333
+ });
3334
+ }
3335
+ function nonEmpty(crumbs) {
3336
+ return crumbs.length > 0 ? crumbs : void 0;
3337
+ }
3338
+ function recordActionOf(match) {
3339
+ if (match === null || match.kind !== "resource") return void 0;
3340
+ switch (match.action) {
3341
+ case "show":
3342
+ case "edit":
3343
+ case "create": return match.action;
3344
+ default: return;
3345
+ }
3346
+ }
3347
+ function pathOf(href) {
3348
+ const path = href.split(/[?#]/, 1)[0] ?? "";
3349
+ return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
3350
+ }
3351
+ function originTrail(ctx, origin, depth = _burojs_react.ORIGIN_DEPTH) {
3352
+ const match = (0, _burojs_core.matchPath)(ctx.registry, pathOf(origin.href), { isVisible: ctx.isVisible });
3353
+ if (match === null) return void 0;
3354
+ switch (match.kind) {
3355
+ case "resource": {
3356
+ const key = require_record_trail_store.canonicalNavKey(match);
3357
+ if (match.action === "list") return {
3358
+ leading: groupCrumbs(ctx, match.groupChain),
3359
+ resource: key,
3360
+ resourceHref: origin.href,
3361
+ segments: []
3362
+ };
3363
+ const def = ctx.registry.get(key);
3364
+ const crumb = {
3365
+ label: match.action === "create" ? ctx.t("breadcrumbs.create") : origin.title || (match.id === void 0 ? "" : `#${match.id}`),
3366
+ href: origin.href
3367
+ };
3368
+ const parent = depth > 1 && origin.origin !== void 0 ? originTrail(ctx, origin.origin, depth - 1) : void 0;
3369
+ if (parent !== void 0) return {
3370
+ ...parent,
3371
+ segments: [...parent.segments, crumb]
3372
+ };
3373
+ return {
3374
+ leading: groupCrumbs(ctx, match.groupChain),
3375
+ resource: key,
3376
+ ...def !== void 0 && (0, _burojs_core.hasListPage)(def) ? { resourceHref: (0, _burojs_core.hrefFor)(ctx.registry, key) } : {},
3377
+ segments: [crumb]
3378
+ };
3379
+ }
3380
+ case "custom-page": {
3381
+ const trail = headerTrail(ctx, match);
3382
+ if (trail === null || trail.pageLabel === void 0) return void 0;
3383
+ return {
3384
+ leading: trail.leadingSegments ?? [],
3385
+ segments: [{
3386
+ label: trail.pageLabel,
3387
+ href: origin.href
3388
+ }]
3389
+ };
3390
+ }
3391
+ case "group-index": {
3392
+ const crumbs = groupCrumbs(ctx, match.groupChain);
3393
+ const own = crumbs[crumbs.length - 1];
3394
+ if (own === void 0) return void 0;
3395
+ return {
3396
+ leading: crumbs.slice(0, -1),
3397
+ segments: [{
3398
+ label: own.label,
3399
+ href: origin.href
3400
+ }]
3401
+ };
3402
+ }
3403
+ default: return;
3404
+ }
3405
+ }
3406
+ function recordTrail(ctx, input) {
3407
+ const { resource, action, id, origin } = input;
3408
+ if (origin !== void 0 && (action === "create" || id !== "")) return originRooted(ctx, input, origin);
3409
+ const leadingSegments = nonEmpty(groupCrumbs(ctx, input.groupChain));
3410
+ if (action !== "create" && id === "") return {
3411
+ resource,
3412
+ leadingSegments
3413
+ };
3414
+ const recordLabel = input.title || id;
3415
+ const middleSegments = action === "edit" ? [isShowAvailable(ctx.registry, resource) ? {
3416
+ label: recordLabel,
3417
+ href: (0, _burojs_react.resolveRoute)(showTarget(resource, id), ctx.registry)
3418
+ } : { label: recordLabel }] : void 0;
3419
+ const pageLabel = action === "create" ? ctx.t("breadcrumbs.create") : action === "edit" ? ctx.t("breadcrumbs.edit") : recordLabel;
3420
+ return {
3421
+ resource,
3422
+ recordId: action === "create" ? void 0 : id,
3423
+ pageLabel,
3424
+ leadingSegments,
3425
+ middleSegments
3426
+ };
3427
+ }
3428
+ function originRooted(ctx, input, origin) {
3429
+ const { resource, action, id } = input;
3430
+ const recordLabel = input.title || id;
3431
+ const drawn = new Set(origin.segments.flatMap((crumb) => crumb.href === void 0 ? [] : [pathOf(crumb.href)]));
3432
+ const own = action === "edit" ? [isShowAvailable(ctx.registry, resource) ? {
3433
+ label: recordLabel,
3434
+ href: (0, _burojs_react.resolveRoute)(showTarget(resource, id), ctx.registry)
3435
+ } : { label: recordLabel }].filter((crumb) => crumb.href === void 0 || !drawn.has(pathOf(crumb.href))) : [];
3436
+ const pageLabel = action === "create" ? ctx.t("breadcrumbs.create") : action === "edit" ? ctx.t("breadcrumbs.edit") : recordLabel;
3437
+ const recordId = action === "create" ? void 0 : id;
3438
+ const middleSegments = nonEmpty([...origin.segments, ...own]);
3439
+ if (origin.resource !== void 0 && ctx.registry.get(origin.resource) === ctx.registry.get(resource)) return {
3440
+ resource,
3441
+ recordId,
3442
+ pageLabel,
3443
+ leadingSegments: nonEmpty([...origin.leading]),
3444
+ ...origin.resourceHref === void 0 ? {} : { resourceHref: origin.resourceHref },
3445
+ middleSegments
3446
+ };
3447
+ const def = origin.resource === void 0 ? void 0 : ctx.registry.get(origin.resource);
3448
+ const resourceCrumb = origin.resource === void 0 ? [] : [{
3449
+ label: (0, _burojs_core.resolveResourceLabel)(ctx.caps, origin.resource, "plural", def),
3450
+ ...origin.resourceHref === void 0 ? {} : { href: origin.resourceHref }
3451
+ }];
3452
+ return {
3453
+ resource,
3454
+ recordId,
3455
+ pageLabel,
3456
+ rootSegments: [
3457
+ ...origin.leading,
3458
+ ...resourceCrumb,
3459
+ ...origin.segments,
3460
+ ...own
3461
+ ]
3462
+ };
3463
+ }
3464
+ function recordTrailRoute(registry, match) {
3465
+ if (match === null || match.kind !== "resource") return null;
3466
+ const resource = require_record_trail_store.canonicalNavKey(match);
3467
+ const { groupChain } = match;
3468
+ if (match.action === "flow") return {
3469
+ resource,
3470
+ action: "show",
3471
+ id: match.id ?? "",
3472
+ flow: match.flow ?? "",
3473
+ groupChain
3474
+ };
3475
+ const action = recordActionOf(match);
3476
+ if (action === void 0 || !(0, _burojs_react.recordRouteAvailable)(registry, resource, action)) return null;
3477
+ return {
3478
+ resource,
3479
+ action,
3480
+ id: action === "create" ? "" : match.id ?? "",
3481
+ groupChain
3482
+ };
3483
+ }
3484
+ function headerTrail(ctx, match) {
3485
+ if (match === null) return null;
3486
+ const key = require_record_trail_store.canonicalNavKey(match);
3487
+ switch (match.kind) {
3488
+ case "resource": {
3489
+ const leadingSegments = nonEmpty(groupCrumbs(ctx, match.groupChain));
3490
+ const action = recordActionOf(match);
3491
+ if (recordTrailRoute(ctx.registry, match) !== null) return null;
3492
+ if (action === void 0) return {
3493
+ resource: key,
3494
+ leadingSegments
3495
+ };
3496
+ return {
3497
+ resource: key,
3498
+ recordId: match.id,
3499
+ pageLabel: ctx.t("router.notFoundTitle"),
3500
+ leadingSegments
3501
+ };
3502
+ }
3503
+ case "custom-page": {
3504
+ const page = ctx.registry.customPages.get(match.name);
3505
+ if (page === void 0 || !ctx.isVisible(page)) return null;
3506
+ return {
3507
+ name: key,
3508
+ pageLabel: (0, _burojs_core.resolveNavLabel)(ctx.caps, `pages.${key}`, (0, _burojs_core.declaredText)("chrome", page, "label")),
3509
+ leadingSegments: nonEmpty(groupCrumbs(ctx, match.groupChain))
3510
+ };
3511
+ }
3512
+ case "group-index": {
3513
+ const own = match.groupChain[match.groupChain.length - 1];
3514
+ if (own === void 0) return null;
3515
+ const crumbs = groupCrumbs(ctx, match.groupChain);
3516
+ const current = crumbs[crumbs.length - 1];
3517
+ return {
3518
+ name: require_record_trail_store.canonicalNavKey(own),
3519
+ pageLabel: current.label,
3520
+ leadingSegments: nonEmpty(crumbs.slice(0, -1))
3521
+ };
3522
+ }
3523
+ default: return null;
3524
+ }
3525
+ }
3526
+ function recentStorageKey(userId) {
3527
+ return `buro:recent:v2:${userId}`;
3528
+ }
3529
+ function isRecent(value) {
3530
+ if (typeof value !== "object" || value === null) return false;
3531
+ const entry = value;
3532
+ return typeof entry.canonicalRef === "string" && typeof entry.id === "string" && typeof entry.label === "string" && (entry.labelField === void 0 || typeof entry.labelField === "string") && typeof entry.at === "string";
3533
+ }
3534
+ function parse(raw) {
3535
+ if (raw === null) return [];
3536
+ try {
3537
+ const parsed = JSON.parse(raw);
3538
+ if (typeof parsed !== "object" || parsed === null) return [];
3539
+ const envelope = parsed;
3540
+ if (envelope.version !== 2 || !Array.isArray(envelope.items)) return [];
3541
+ return envelope.items.filter(isRecent);
3542
+ } catch {
3543
+ return [];
3544
+ }
3545
+ }
3546
+ function readRecentRecords(store, userId) {
3547
+ return (0, _burojs_react.maybeThen)((0, _burojs_react.settle)(() => store.get(recentStorageKey(userId)), null), parse);
3548
+ }
3549
+ function writeRecentRecord(store, userId, entry) {
3550
+ const key = recentStorageKey(userId);
3551
+ return (0, _burojs_react.maybeThen)((0, _burojs_react.settle)(() => store.get(key), null), (raw) => {
3552
+ const envelope = {
3553
+ version: 2,
3554
+ items: [entry, ...parse(raw).filter((item) => !(item.canonicalRef === entry.canonicalRef && item.id === entry.id))].slice(0, 5)
3555
+ };
3556
+ return (0, _burojs_react.settle)(() => store.set(key, JSON.stringify(envelope)), void 0);
3557
+ });
3558
+ }
3559
+ function text$1(value) {
3560
+ return typeof value === "string" && value.length > 0 ? value : void 0;
3561
+ }
3562
+ const RECENT_LABEL_KEYS = [
3563
+ "alias",
3564
+ "name",
3565
+ "title",
3566
+ "label"
3567
+ ];
3568
+ function recentLabel(record, id, isGuarded = () => false) {
3569
+ for (const key of RECENT_LABEL_KEYS) {
3570
+ if (isGuarded(key)) continue;
3571
+ const value = text$1(record[key]);
3572
+ if (value !== void 0) return {
3573
+ label: value,
3574
+ field: key
3575
+ };
3576
+ }
3577
+ return { label: id };
3578
+ }
3579
+ //#endregion
3580
+ //#region src/layout/use-record-visit.ts
3581
+ function useRecordVisit(resource, record, opts) {
3582
+ const userId = (0, _burojs_react.useCurrentUserId)();
3583
+ const store = (0, _burojs_react.usePlatformStorage)().local;
3584
+ const app = (0, _burojs_react.useApp)();
3585
+ const def = app.registry.get(resource);
3586
+ const raw = (0, _burojs_react.recordKeyOf)(def, record);
3587
+ const id = typeof raw === "string" || typeof raw === "number" ? String(raw) : void 0;
3588
+ const fields = def?.fields;
3589
+ const rules = app.ruleSource?.rules(resource) ?? [];
3590
+ const isGuarded = (field) => fields !== void 0 && Object.hasOwn(fields, field) && (0, _burojs_core.fieldSensitivity)(fields[field]) !== void 0 || (0, _burojs_core.addressesCapability)(rules, "view", {
3591
+ kind: "field",
3592
+ name: field
3593
+ });
3594
+ const picked = record != null && id !== void 0 ? recentLabel(record, id, isGuarded) : void 0;
3595
+ const label = picked?.label;
3596
+ const labelField = picked?.field;
3597
+ const canonicalRef = require_check_confirm_dialog.canonicalResourceName(resource);
3598
+ const { isCurrentData } = opts;
3599
+ (0, react.useEffect)(() => {
3600
+ if (userId === null || !isCurrentData || id === void 0 || id === "") return;
3601
+ if (label === void 0) return;
3602
+ writeRecentRecord(store, userId, {
3603
+ canonicalRef,
3604
+ id,
3605
+ label,
3606
+ ...labelField === void 0 ? {} : { labelField },
3607
+ at: new Date().toISOString()
3608
+ });
3609
+ }, [
3610
+ store,
3611
+ userId,
3612
+ isCurrentData,
3613
+ canonicalRef,
3614
+ id,
3615
+ label,
3616
+ labelField
3617
+ ]);
3618
+ }
3619
+ //#endregion
3620
+ //#region src/layout/record-page.tsx
3621
+ function useMountedRef() {
3622
+ const mounted = (0, react.useRef)(true);
3623
+ (0, react.useEffect)(() => {
3624
+ mounted.current = true;
3625
+ return () => {
3626
+ mounted.current = false;
3627
+ };
3628
+ }, []);
3629
+ return mounted;
3630
+ }
3631
+ function RecordRouteHeader({ resource, action, id, record }) {
3632
+ const recordName = (0, _burojs_react.useRecordTitle)(resource, action === "create" ? void 0 : id, record);
3633
+ require_record_trail_store.usePublishRecordTrail(action === "create" ? null : {
3634
+ key: require_record_trail_store.recordTrailKey(resource, id, action),
3635
+ title: recordName
3636
+ });
3637
+ return (0, react_jsx_runtime.jsx)(require_place_node.PageHeader, {
3638
+ resource,
3639
+ mode: action,
3640
+ ...action === "create" ? {} : { recordName }
3641
+ });
3642
+ }
3643
+ function RecordShow({ resource, id, recordId, record, shown }) {
3644
+ return (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(RecordRouteHeader, {
3645
+ resource,
3646
+ action: "show",
3647
+ id,
3648
+ record: shown
3649
+ }), (0, react_jsx_runtime.jsx)(RecordScreen, {
3650
+ resource,
3651
+ mode: "show",
3652
+ recordId,
3653
+ record
3654
+ })] });
3655
+ }
3656
+ function RecordEdit({ resource, id, recordId, record, shown }) {
3657
+ const navigate = (0, _burojs_react.useRouteNavigate)();
3658
+ const mounted = useMountedRef();
3659
+ const back = (0, _burojs_react.useReturnTarget)(resource, "edit", id);
3660
+ return (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(RecordRouteHeader, {
3661
+ resource,
3662
+ action: "edit",
3663
+ id,
3664
+ record: shown
3665
+ }), (0, react_jsx_runtime.jsx)(RecordScreen, {
3666
+ resource,
3667
+ mode: "edit",
3668
+ recordId,
3669
+ record,
3670
+ onCancel: () => navigate(back, { origin: "inherit" }),
3671
+ onSuccess: () => {
3672
+ if (mounted.current) navigate(back, { origin: "inherit" });
3673
+ }
3674
+ })] });
3675
+ }
3676
+ function createdId(result) {
3677
+ const id = result?.id;
3678
+ return typeof id === "string" || typeof id === "number" ? String(id) : void 0;
3679
+ }
3680
+ function RecordCreate({ resource, defaults }) {
3681
+ const app = (0, _burojs_react.useApp)();
3682
+ const navigate = (0, _burojs_react.useRouteNavigate)();
3683
+ const mounted = useMountedRef();
3684
+ const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
3685
+ const list = listTarget(resource);
3686
+ const back = (0, _burojs_react.useReturnTarget)(resource, "create");
3687
+ const type = adapter?.searchParams.get("type") ?? void 0;
3688
+ return (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(RecordRouteHeader, {
3689
+ resource,
3690
+ action: "create",
3691
+ id: ""
3692
+ }), (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenClaimContext.Provider, {
3693
+ value: true,
3694
+ children: (0, react_jsx_runtime.jsx)(RecordScreen, {
3695
+ resource,
3696
+ mode: "create",
3697
+ ...type === void 0 ? {} : { type },
3698
+ ...defaults === void 0 ? {} : { defaults },
3699
+ onCancel: () => navigate(back, { origin: "inherit" }),
3700
+ onSuccess: (result) => {
3701
+ if (!mounted.current) return;
3702
+ const id = createdId(result);
3703
+ navigate(id !== void 0 && isShowAvailable(app.registry, resource) ? showTarget(resource, id) : list, { origin: "inherit" });
3704
+ }
3705
+ })
3706
+ })] });
3707
+ }
3708
+ function RecordRead({ resource, action, id, recordId }) {
3709
+ const app = (0, _burojs_react.useApp)();
3710
+ const def = app.registry.get(resource);
3711
+ const projection = (0, react.useMemo)(() => def === void 0 ? void 0 : (0, _burojs_core.dtoFields)(def, "record"), [def]);
3712
+ const query = (0, _burojs_react.useOne)(resource, {
3713
+ id: recordId,
3714
+ retry: _burojs_react.retryRecordRead,
3715
+ ...projection === void 0 ? {} : { projection }
3716
+ });
3717
+ const result = query.data;
3718
+ const read = result?.data;
3719
+ const projected = (0, _burojs_react.useProjectedRecord)(resource, read, { placeholder: query.isPlaceholderData });
3720
+ const showAvailability = (0, _burojs_react.useAvailabilityResolver)(resource, "show");
3721
+ const permissions = (0, _burojs_react.useCtx)((c) => c.permissions);
3722
+ const showRuled = (0, _burojs_core.addressesCapability)(app.ruleSource.rules(resource), "run", {
3723
+ kind: "action",
3724
+ name: "show"
3725
+ });
3726
+ const showHidden = showRuled && read !== null && typeof read === "object" && showAvailability("show", read).state !== "available";
3727
+ const showSettled = !showRuled || !query.isPlaceholderData && !(0, _burojs_core.permissionsUndecided)(permissions) && permissions?.status !== "error";
3728
+ useRecordVisit(resource, projected.status === "ready" && showSettled && !showHidden ? projected.value : null, { isCurrentData: !query.isPlaceholderData });
3729
+ const route = (0, react.useMemo)(() => Object.freeze({ id }), [id]);
3730
+ const availability = (0, _burojs_react.useAvailabilityResolver)(resource, "edit");
3731
+ if (result !== void 0) {
3732
+ const record = result.data;
3733
+ if (record === null || typeof record !== "object") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3734
+ const loaded = record;
3735
+ if (showRuled) {
3736
+ if (query.isPlaceholderData || (0, _burojs_core.permissionsUndecided)(permissions)) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
3737
+ if (permissions?.status === "error") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3738
+ if (showHidden) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3739
+ }
3740
+ if (projected.status === "pending" || projected.value === null) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
3741
+ const shown = projected.value;
3742
+ if (action === "edit") {
3743
+ const edit = availability("edit", loaded).state;
3744
+ if (edit === "hidden" || edit === "absent") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3745
+ if (edit === "undecided") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
3746
+ }
3747
+ return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
3748
+ value: route,
3749
+ children: (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenClaimContext.Provider, {
3750
+ value: true,
3751
+ children: action === "edit" ? (0, react_jsx_runtime.jsx)(RecordEdit, {
3752
+ resource,
3753
+ id,
3754
+ recordId,
3755
+ record: loaded,
3756
+ shown
3757
+ }) : (0, react_jsx_runtime.jsx)(RecordShow, {
3758
+ resource,
3759
+ id,
3760
+ recordId,
3761
+ record: loaded,
3762
+ shown
3763
+ })
3764
+ })
3765
+ });
3766
+ }
3767
+ if (query.error != null) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
3768
+ surface: "record",
3769
+ resource,
3770
+ error: query.error,
3771
+ retry: () => void query.refetch()
3772
+ });
3773
+ return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
3774
+ }
3775
+ function RecordRouteBody(props) {
3776
+ if (props.action === "create") return (0, react_jsx_runtime.jsx)(RecordCreate, { ...props });
3777
+ if (props.id === "") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3778
+ return (0, react_jsx_runtime.jsx)(RecordReadRoute, { ...props });
3779
+ }
3780
+ function RecordReadRoute(props) {
3781
+ const recordId = (0, _burojs_react.useRouteRecordId)(props.resource, props.id);
3782
+ if (recordId === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.InvalidRouteId, { resource: props.resource });
3783
+ return (0, react_jsx_runtime.jsx)(RecordRead, {
3784
+ ...props,
3785
+ recordId
3786
+ });
3787
+ }
3788
+ function RecordRoute(props) {
3789
+ const missingRuntime = (0, _burojs_react.useOptionalDataRuntime)() === null;
3790
+ (0, react.useEffect)(() => {
3791
+ if (!missingRuntime || process.env.NODE_ENV === "production") return;
3792
+ console.error(`[burojs] The '${props.resource}' record page has no data runtime to read or write with: BuroProvider.dataRuntime is not set. Pass <BuroProvider dataRuntime={…}> (createDataRuntime from @burojs/react); until then record routes render the error state.`);
3793
+ }, [missingRuntime, props.resource]);
3794
+ if (missingRuntime) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "error" });
3795
+ return (0, react_jsx_runtime.jsx)(RecordRouteBody, { ...props }, `${props.resource}:${props.id}`);
3796
+ }
3797
+ function recordPageProblem(input) {
3798
+ const { props, resource, action } = input;
3799
+ if (resource === void 0 || action === void 0) return "[burojs] <RecordPage> needs both `resource` and `action`. Pass them; until then it renders not-found.";
3800
+ if (!input.onRecordRoute) return `[burojs] <RecordPage resource="${resource}" action="${action}"> is not on a record route (show, edit or create), so it has no record to read: render it on one, under a RouterAdapterProvider. Until then it renders not-found.`;
3801
+ if (props.defaults !== void 0 && action !== "create") return `[burojs] <RecordPage defaults> applies to create only; on this '${action}' route it is ignored.`;
3802
+ return null;
3803
+ }
3804
+ const recordPageProblemsLogged = new WeakMap();
3805
+ function RecordPage(props) {
3806
+ const app = (0, _burojs_react.useApp)();
3807
+ const match = useMatch();
3808
+ const id = match === null ? null : match.id ?? "";
3809
+ const { action } = props;
3810
+ const resource = props.resource === void 0 ? void 0 : (0, _burojs_core.routeResourceKey)(props.resource);
3811
+ const onRecordRoute = recordActionOf(match) !== void 0;
3812
+ const problem = recordPageProblem({
3813
+ props,
3814
+ resource,
3815
+ action,
3816
+ onRecordRoute
3817
+ });
3818
+ (0, react.useEffect)(() => {
3819
+ if (problem === null || process.env.NODE_ENV === "production") return;
3820
+ let logged = recordPageProblemsLogged.get(app);
3821
+ if (logged === void 0) {
3822
+ logged = new Set();
3823
+ recordPageProblemsLogged.set(app, logged);
3824
+ }
3825
+ if (logged.has(problem)) return;
3826
+ logged.add(problem);
3827
+ console.error(problem);
3828
+ }, [app, problem]);
3829
+ if (resource === void 0 || action === void 0 || id === null || !onRecordRoute) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
3830
+ const route = action === "create" ? {
3831
+ resource,
3832
+ action,
3833
+ defaults: props.defaults
3834
+ } : {
3835
+ resource,
3836
+ action
3837
+ };
3838
+ return (0, react_jsx_runtime.jsx)(RecordRoute, {
3839
+ ...route,
3840
+ id
3841
+ });
3842
+ }
3843
+ //#endregion
3844
+ //#region src/layout/collection-record-route.tsx
3845
+ function addressTail(searchParams, routerHash) {
3846
+ const query = searchParams?.toString() ?? "";
3847
+ const hash = routerHash ?? (typeof window === "undefined" ? "" : window.location.hash);
3848
+ return `${query === "" ? "" : `?${query}`}${hash === "#" ? "" : hash}`;
3849
+ }
3850
+ function CollectionRecordRoute(props) {
3851
+ const { collection, action, id } = props;
3852
+ const app = (0, _burojs_react.useApp)();
3853
+ const navigate = (0, _burojs_react.useRouteNavigate)();
3854
+ const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
3855
+ const state = (0, _burojs_react.useCollectionMember)(collection, id);
3856
+ const flow = props.action === "flow" ? props.flow : void 0;
3857
+ const target = state.status === "member" ? (0, _burojs_core.hrefFor)(app.registry, state.member, {
3858
+ action,
3859
+ id,
3860
+ ...flow === void 0 ? {} : { flow }
3861
+ }) : void 0;
3862
+ const current = (0, react.useRef)(adapter);
3863
+ current.current = adapter;
3864
+ const sent = (0, react.useRef)(void 0);
3865
+ (0, react.useEffect)(() => {
3866
+ if (target === void 0 || sent.current === target) return;
3867
+ sent.current = target;
3868
+ navigate(`${target}${addressTail(current.current?.searchParams, current.current?.hash)}`, { replace: true });
3869
+ }, [target, navigate]);
3870
+ if (state.status === "unknown") return (0, react_jsx_runtime.jsx)(UnknownMemberCard, {
3871
+ collection,
3872
+ id,
3873
+ value: state.value
3874
+ });
3875
+ if (state.status === "not-found") return (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {});
3876
+ if (state.status === "error") return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
3877
+ surface: "record",
3878
+ resource: (0, _burojs_core.routeResourceKey)(collection),
3879
+ error: state.error
3880
+ });
3881
+ return null;
3882
+ }
3883
+ function UnknownMemberCard({ collection, id, value }) {
3884
+ const app = (0, _burojs_react.useApp)();
3885
+ const t = (0, _burojs_react.useOptionalT)();
3886
+ const key = (0, _burojs_core.routeResourceKey)(collection);
3887
+ const fact = (0, _burojs_core.memberFactOf)(app.registry.get(key));
3888
+ const shown = value === void 0 || value === null ? "" : String(value);
3889
+ const known = (fact?.collection?.members ?? []).flatMap((member) => member.values).join(", ");
3890
+ return (0, react_jsx_runtime.jsxs)("div", {
3891
+ "data-testid": `unknown-member-card:${key}:${id}`,
3892
+ className: "flex flex-col gap-2",
3893
+ children: [
3894
+ process.env.NODE_ENV === "production" ? null : (0, react_jsx_runtime.jsx)("div", {
3895
+ role: "note",
3896
+ "data-testid": "unknown-member-notice",
3897
+ className: "mx-6 mt-4 rounded-md border border-dashed border-amber-500/60 bg-amber-500/10 px-3 py-2 text-sm",
3898
+ children: t("collection.unknownMemberNotice", {
3899
+ params: {
3900
+ base: fact === void 0 ? key : (0, _burojs_core.formatEntityRef)(fact.ref),
3901
+ value: shown,
3902
+ known
3903
+ },
3904
+ defaultValue: "No member of {{base}} claims the type “{{value}}”. Known types: {{known}}."
3905
+ })
3906
+ }),
3907
+ (0, react_jsx_runtime.jsx)("p", {
3908
+ "data-testid": "unknown-member-type",
3909
+ className: "mx-6 text-sm text-muted-foreground",
3910
+ children: t("collection.unknownType", {
3911
+ params: { value: shown },
3912
+ defaultValue: "Unknown type: {{value}}"
3913
+ })
3914
+ }),
3915
+ (0, react_jsx_runtime.jsx)(require_place_node.ItemActionsOffContext.Provider, {
3916
+ value: true,
3917
+ children: (0, react_jsx_runtime.jsx)(RecordRoute, {
3918
+ resource: key,
3919
+ action: "show",
3920
+ id
3921
+ })
3922
+ })
3923
+ ]
3924
+ });
3925
+ }
3926
+ //#endregion
3927
+ //#region src/layout/page-host.tsx
3928
+ function PageHost({ page, match, notFound }) {
3929
+ const isVisible = useNavVisible();
3930
+ const ctx = (0, _burojs_react.useVisibilityCtx)();
3931
+ const access = (0, _burojs_react.usePageAccess)(page);
3932
+ if (!((0, _burojs_core.evaluateVisible)(page.visible, ctx) && match.groupChain.every((group) => isVisible(group)))) return notFound;
3933
+ if (access === "pending") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
3934
+ if (access === "denied") return notFound;
3935
+ return (0, react_jsx_runtime.jsx)(PageParams, {
3936
+ page,
3937
+ notFound
3938
+ });
3939
+ }
3940
+ const NO_SEARCH = new URLSearchParams();
3941
+ function PageParams({ page, notFound }) {
3942
+ const search = (0, _burojs_react.useOptionalRouterAdapter)()?.searchParams ?? (typeof window === "undefined" ? NO_SEARCH : new URLSearchParams(window.location.search));
3943
+ const raw = JSON.stringify((0, _burojs_core.pageParamNames)(page.params).map((name) => search.get(name)));
3944
+ const parsed = (0, react.useMemo)(() => (0, _burojs_core.parsePageParams)(page, search), [page, raw]);
3945
+ if (!parsed.ok) return notFound;
3946
+ return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
3947
+ value: parsed.route,
3948
+ children: (0, react_jsx_runtime.jsx)(PageBody, { page })
3949
+ });
3950
+ }
3951
+ function PageBody({ page }) {
3952
+ const snapshot = (0, _burojs_react.useApplicationSnapshot)();
3953
+ const compiled = (0, react.useMemo)(() => (0, _burojs_core.compilePageScreen)(page, {
3954
+ blocks: (0, _burojs_core.snapshotBlockLookup)(snapshot),
3955
+ frames: (0, _burojs_core.snapshotFrameLookup)(snapshot),
3956
+ appFrames: (0, _burojs_core.snapshotAppFrames)(snapshot)
3957
+ }), [page, snapshot]);
3958
+ const failure = (0, _burojs_core.isScreenFailure)(compiled) ? compiled : null;
3959
+ const screen = failure === null && !(0, _burojs_core.isScreenFailure)(compiled) ? compiled : null;
3960
+ const caps = (0, _burojs_react.useI18nCaps)();
3961
+ const name = require_record_trail_store.canonicalNavKey(page);
3962
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `pages.${name}`, (0, _burojs_core.declaredText)("chrome", page, "label"));
3963
+ (0, react.useEffect)(() => {
3964
+ if (failure === null || process.env.NODE_ENV === "production") return;
3965
+ console.error(`[burojs] The page "${name}" cannot render its body: ${failure.code} at ${failure.path.join(".")}: ${failure.message}.`);
3966
+ }, [failure, name]);
3967
+ return (0, react_jsx_runtime.jsxs)("div", {
3968
+ className: "flex flex-col gap-4",
3969
+ children: [(0, react_jsx_runtime.jsx)("h1", {
3970
+ className: "text-2xl font-semibold tracking-tight",
3971
+ children: label
3972
+ }), screen === null ? (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "error" }) : (0, react_jsx_runtime.jsx)(PageRouteScreen, { children: (0, react_jsx_runtime.jsx)(PlannedBody, {
3973
+ screen,
3974
+ name,
3975
+ label
3976
+ }) })]
3977
+ });
3978
+ }
3979
+ function PageRouteScreen({ children }) {
3980
+ const tabs = require_place_node.useTabsUrlState("show", true);
3981
+ return (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenClaimContext.Provider, {
3982
+ value: false,
3983
+ children: (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenContext.Provider, {
3984
+ value: true,
3985
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ScreenStateProvider, {
3986
+ open: tabs.open,
3987
+ onOpenChange: tabs.onOpenChange,
3988
+ children
3989
+ })
3990
+ })
3991
+ });
3992
+ }
3993
+ function PlannedBody({ screen, name, label, record }) {
3994
+ const pageOptions = (0, react.useMemo)(() => record === void 0 ? {} : { record }, [record]);
3995
+ const page = (0, _burojs_react.usePageScreen)(screen, pageOptions);
3996
+ const { PlacementScope } = page;
3997
+ const route = (0, react.useContext)(_burojs_react.RouteSourceContext);
3998
+ const catalog = (0, _burojs_react.useFrameImplementations)();
3999
+ const id = (0, _burojs_core.formatEntityRef)(screen.frame);
4000
+ const resolved = (0, react.useMemo)(() => require_place_node.resolveFrameView(screen.frame, catalog, "page"), [screen.frame, catalog]);
4001
+ const t = (0, _burojs_react.useFrameT)(id);
4002
+ const slots = {};
4003
+ for (const slot of Object.keys(screen.slots)) slots[slot] = (page.plan.slots[slot] ?? []).every((node) => node.state === "absent") ? null : (0, react_jsx_runtime.jsx)(require_place_node.ScreenTree, {
4004
+ region: slot === "body" ? "page-body" : "record",
4005
+ slot,
4006
+ resource: name,
4007
+ mode: "show",
4008
+ compiled: screen,
4009
+ page
4010
+ }, slot);
4011
+ const View = resolved.view;
4012
+ const viewProps = {
4013
+ slots,
4014
+ label,
4015
+ params: route ?? {},
4016
+ t
4017
+ };
4018
+ return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
4019
+ value: null,
4020
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ActionRouteContext.Provider, {
4021
+ value: route,
4022
+ children: (0, react_jsx_runtime.jsx)(PlacementScope, { children: (0, react_jsx_runtime.jsx)(require_place_node.DeepLinkScope, {
4023
+ plan: page.plan,
4024
+ enabled: true,
4025
+ children: (0, react_jsx_runtime.jsx)("div", {
4026
+ "data-buro-region": "page-body",
4027
+ children: (0, react_jsx_runtime.jsx)(react.Suspense, {
4028
+ fallback: null,
4029
+ children: (0, react_jsx_runtime.jsx)(View, { ...viewProps })
4030
+ })
4031
+ })
4032
+ }) })
4033
+ })
4034
+ });
4035
+ }
4036
+ //#endregion
4037
+ //#region src/layout/resource-page-router.tsx
4038
+ function ResourcePageRouterEmpty() {
4039
+ const t = (0, _burojs_react.useT)();
4040
+ return (0, react_jsx_runtime.jsxs)("div", {
4041
+ "data-testid": "resource-page-router-empty",
4042
+ className: "flex flex-col items-center justify-center gap-1 px-6 py-24 text-center",
4043
+ children: [(0, react_jsx_runtime.jsx)("h2", {
4044
+ className: "text-base font-semibold tracking-tight",
4045
+ children: t("router.emptyTitle")
4046
+ }), (0, react_jsx_runtime.jsx)("p", {
4047
+ className: "max-w-sm text-sm text-muted-foreground",
4048
+ children: t("router.emptyBody")
4049
+ })]
4050
+ });
4051
+ }
4052
+ function ResourcePageRouter({ match }) {
4053
+ const app = (0, _burojs_react.useApp)();
4054
+ const qualifiedMatch = match;
4055
+ const resource = require_record_trail_store.canonicalNavKey(qualifiedMatch);
4056
+ const target = require_record_trail_store.canonicalNavKey({
4057
+ name: match.target ?? match.name,
4058
+ ref: qualifiedMatch.targetRef
4059
+ });
4060
+ const recordAction = recordActionOf(match);
4061
+ switch (match.kind) {
4062
+ case "resource": {
4063
+ if (match.action === "list") {
4064
+ const def = app.registry.get(resource);
4065
+ return def !== void 0 && !(0, _burojs_core.hasListPage)(def) ? (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {}) : (0, react_jsx_runtime.jsx)(ResourceListPage, { resource });
4066
+ }
4067
+ const collection = (0, _burojs_core.collectionFactOf)(app.registry.get(resource)) !== void 0;
4068
+ if (collection && match.id !== void 0 && (match.action === "show" || match.action === "edit" || match.action === "flow")) {
4069
+ if (!(0, _burojs_react.recordRouteAvailable)(app.registry, resource, "show")) return (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {});
4070
+ return match.action === "flow" ? (0, react_jsx_runtime.jsx)(CollectionRecordRoute, {
4071
+ collection: resource,
4072
+ action: "flow",
4073
+ id: match.id,
4074
+ flow: match.flow ?? ""
4075
+ }) : (0, react_jsx_runtime.jsx)(CollectionRecordRoute, {
4076
+ collection: resource,
4077
+ action: match.action,
4078
+ id: match.id
4079
+ });
4080
+ }
4081
+ if (match.action === "flow") return (0, react_jsx_runtime.jsx)(PageFlowRouteLoader, { match });
4082
+ if (recordAction === void 0) return (0, react_jsx_runtime.jsx)(ResourcePageRouterEmpty, {});
4083
+ if (!(0, _burojs_react.recordRouteAvailable)(app.registry, resource, recordAction)) return (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {});
4084
+ if (collection && recordAction === "create") return (0, react_jsx_runtime.jsx)(CollectionCreatePicker, { collection: resource });
4085
+ return (0, react_jsx_runtime.jsx)(RecordRoute, {
4086
+ resource,
4087
+ action: recordAction,
4088
+ id: match.id ?? ""
4089
+ });
4090
+ }
4091
+ case "custom-page": {
4092
+ const page = app.registry.customPages.get(resource);
4093
+ if (page === void 0) return (0, react_jsx_runtime.jsx)(ResourcePageRouterEmpty, {});
4094
+ if (!page.body?.length) return (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {});
4095
+ return (0, react_jsx_runtime.jsx)(PageHost, {
4096
+ page,
4097
+ match,
4098
+ notFound: (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {})
4099
+ }, resource);
4100
+ }
4101
+ case "group-index": {
4102
+ const indexPage = app.registry.customPages.get(target);
4103
+ if (indexPage?.body?.length) return (0, react_jsx_runtime.jsx)(PageHost, {
4104
+ page: indexPage,
4105
+ match,
4106
+ notFound: (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {})
4107
+ }, target);
4108
+ const targetDef = app.registry.get(target);
4109
+ if (targetDef !== void 0) return (0, _burojs_core.hasListPage)(targetDef) ? (0, react_jsx_runtime.jsx)(ResourceListPage, { resource: target }) : (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {});
4110
+ return (0, react_jsx_runtime.jsx)(ResourcePageRouterEmpty, {});
4111
+ }
4112
+ default: return (0, react_jsx_runtime.jsx)(ResourcePageRouterEmpty, {});
4113
+ }
4114
+ }
4115
+ function NavAreaPageSkeleton() {
4116
+ return (0, react_jsx_runtime.jsxs)("div", {
4117
+ className: "space-y-3 p-6",
4118
+ role: "status",
4119
+ "aria-busy": "true",
4120
+ "aria-live": "polite",
4121
+ "data-testid": "nav-area-skeleton",
4122
+ children: [
4123
+ (0, react_jsx_runtime.jsx)("span", {
4124
+ className: "sr-only",
4125
+ children: "Loading…"
4126
+ }),
4127
+ (0, react_jsx_runtime.jsx)("div", { className: "h-6 w-48 animate-pulse rounded bg-muted/60" }),
4128
+ (0, react_jsx_runtime.jsx)("div", { className: "h-4 w-full animate-pulse rounded bg-muted/40" }),
4129
+ (0, react_jsx_runtime.jsx)("div", { className: "h-4 w-5/6 animate-pulse rounded bg-muted/40" }),
4130
+ (0, react_jsx_runtime.jsx)("div", { className: "h-4 w-2/3 animate-pulse rounded bg-muted/40" })
4131
+ ]
4132
+ });
4133
+ }
4134
+ const adapterNoticeGiven = new WeakSet();
4135
+ const chromeNoticeGiven = new WeakSet();
4136
+ function NavAreaPage() {
4137
+ const match = useMatch();
4138
+ const app = (0, _burojs_react.useApp)();
4139
+ const noAdapter = (0, _burojs_react.useOptionalRouterAdapter)() === null;
4140
+ const chromeMounted = useNavChromeMounted();
4141
+ const resolveLayout = useLayoutResolver();
4142
+ const chromeGroup = match?.groupChain.find((g) => resolveLayout(g.layout)) ?? null;
4143
+ (0, react.useEffect)(() => {
4144
+ if (process.env.NODE_ENV === "production") return;
4145
+ if (chromeMounted || !chromeGroup || chromeNoticeGiven.has(app)) return;
4146
+ chromeNoticeGiven.add(app);
4147
+ console.error(`[burojs] <NavAreaPage> is inside the nav group "${require_record_trail_store.canonicalNavKey(chromeGroup)}" whose layout "${chromeGroup.layout}" draws area chrome, and no <NavChrome> is mounted above it. <AppShell> mounts one by default; with your own frame, wrap your routes in <NavChrome>.`);
4148
+ }, [
4149
+ app,
4150
+ chromeMounted,
4151
+ chromeGroup
4152
+ ]);
4153
+ (0, react.useEffect)(() => {
4154
+ if (!noAdapter || process.env.NODE_ENV === "production") return;
4155
+ if (adapterNoticeGiven.has(app)) return;
4156
+ adapterNoticeGiven.add(app);
4157
+ console.error("[burojs] <NavAreaPage> has no location to match: no RouterAdapterProvider is mounted. Mount your router’s adapter (RouterAdapterProvider from @burojs/react) above <BuroProvider>; until then every route renders not-found.");
4158
+ }, [app, noAdapter]);
4159
+ return (0, react_jsx_runtime.jsx)(react.Suspense, {
4160
+ fallback: (0, react_jsx_runtime.jsx)(NavAreaPageSkeleton, {}),
4161
+ children: match ? (0, react_jsx_runtime.jsx)(ResourcePageRouter, { match }) : (0, react_jsx_runtime.jsx)(require_record_trail_store.NavAreaNotFound, {})
4162
+ });
4163
+ }
4164
+ //#endregion
2097
4165
  //#region src/layout/breadcrumbs.tsx
2098
4166
  const LINK_CLASS = "rounded hover:text-foreground transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2";
2099
4167
  function Chevron() {
@@ -2158,7 +4226,7 @@ function Breadcrumbs(input) {
2158
4226
  });
2159
4227
  if (!def) return null;
2160
4228
  const { recordId, pageLabel, middleSegments, rootSegments } = props;
2161
- const resourceKey = require_resource_page_router.canonicalResourceKey(def);
4229
+ const resourceKey = require_record_trail_store.canonicalResourceKey(def);
2162
4230
  if (rootSegments !== void 0 && rootSegments.length > 0) return (0, react_jsx_runtime.jsxs)("nav", {
2163
4231
  className: navClass,
2164
4232
  "aria-label": ariaLabel,
@@ -2229,20 +4297,23 @@ function Breadcrumbs(input) {
2229
4297
  //#region src/layout/record-breadcrumbs.tsx
2230
4298
  function viewOrigin(ctx, trail, resource) {
2231
4299
  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;
4300
+ const def = ctx.registry.get(trail.resource);
4301
+ const target = def?.routesTo?.show;
4302
+ if (target !== void 0 && ctx.registry.get(target) === ctx.registry.get(resource)) return trail.resource;
4303
+ const collected = (0, _burojs_core.collectionFactOf)(def) === void 0 ? void 0 : (0, _burojs_core.memberFactOf)(def)?.ref;
4304
+ const memberBase = (0, _burojs_core.memberFactOf)(ctx.registry.get(resource))?.ref;
4305
+ if (collected !== void 0 && memberBase !== void 0 && (0, _burojs_core.sameEntityRef)(collected, memberBase)) return trail.resource;
2235
4306
  }
2236
4307
  function RecordBreadcrumbs() {
2237
- const ctx = require_resource_page_router.useTrailContext();
2238
- const match = require_resource_page_router.useMatch();
4308
+ const ctx = useTrailContext();
4309
+ const match = useMatch();
2239
4310
  const snapshot = (0, _burojs_react.useApplicationSnapshot)();
2240
- const route = require_resource_page_router.recordTrailRoute(ctx.registry, match);
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}`));
4311
+ const route = recordTrailRoute(ctx.registry, match);
4312
+ const published = require_record_trail_store.usePublishedRecordTrail(route === null ? "" : require_record_trail_store.recordTrailKey(route.resource, route.id, route.flow === void 0 ? route.action : `flow:${route.flow}`));
2242
4313
  const idTitle = (0, _burojs_react.useRecordTitle)(route?.resource, route?.id);
2243
4314
  (0, _burojs_react.usePublishOriginTitle)(published?.title || void 0);
2244
4315
  const origin = (0, _burojs_react.useNavigationOrigin)();
2245
- const rooted = origin === null ? void 0 : require_resource_page_router.originTrail(ctx, origin);
4316
+ const rooted = origin === null ? void 0 : originTrail(ctx, origin);
2246
4317
  const view = route === null ? void 0 : viewOrigin(ctx, rooted, route.resource);
2247
4318
  const viewScopes = (0, _burojs_react.useDocTrailScopes)(view);
2248
4319
  const ownScopes = (0, _burojs_react.useDocTrailScopes)(view === void 0 ? void 0 : route?.resource);
@@ -2255,7 +4326,7 @@ function RecordBreadcrumbs() {
2255
4326
  if ((0, _burojs_core.effectiveFlow)(snapshot, match.ref, route.flow) === void 0) return null;
2256
4327
  const flowLabel = published?.flowLabel;
2257
4328
  if (flowLabel === void 0) return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
2258
- ...require_resource_page_router.recordTrail(ctx, {
4329
+ ...recordTrail(ctx, {
2259
4330
  resource,
2260
4331
  action: "show",
2261
4332
  id,
@@ -2267,7 +4338,7 @@ function RecordBreadcrumbs() {
2267
4338
  "data-testid": "record-breadcrumbs"
2268
4339
  });
2269
4340
  return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
2270
- ...require_resource_page_router.recordTrail(ctx, {
4341
+ ...recordTrail(ctx, {
2271
4342
  resource,
2272
4343
  action: "edit",
2273
4344
  id,
@@ -2281,7 +4352,7 @@ function RecordBreadcrumbs() {
2281
4352
  });
2282
4353
  }
2283
4354
  return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
2284
- ...require_resource_page_router.recordTrail(ctx, {
4355
+ ...recordTrail(ctx, {
2285
4356
  resource,
2286
4357
  action: route.action,
2287
4358
  id,
@@ -2295,7 +4366,7 @@ function RecordBreadcrumbs() {
2295
4366
  }
2296
4367
  //#endregion
2297
4368
  //#region src/layout/default-nav-layouts.ts
2298
- const defaultNavLayouts = { ...require_resource_page_router.BUILTIN_LAYOUTS };
4369
+ const defaultNavLayouts = { ...BUILTIN_LAYOUTS };
2299
4370
  //#endregion
2300
4371
  //#region src/layout/context-picker.tsx
2301
4372
  const ALL = "\0all";
@@ -2368,7 +4439,7 @@ function ScopeDimensionPicker(props) {
2368
4439
  });
2369
4440
  }
2370
4441
  function ResourceDimension({ resource, labelField, ...rest }) {
2371
- const options = require_resource_page_router.useResourceDimensionOptions(rest.dimension, resource, labelField);
4442
+ const options = useResourceDimensionOptions(rest.dimension, resource, labelField);
2372
4443
  return (0, react_jsx_runtime.jsx)(DimensionControl, {
2373
4444
  ...rest,
2374
4445
  options
@@ -2455,10 +4526,10 @@ function LanguageSwitch({ onChange, className }) {
2455
4526
  //#endregion
2456
4527
  //#region src/layout/header-breadcrumbs.tsx
2457
4528
  function HeaderBreadcrumbs() {
2458
- const ctx = require_resource_page_router.useTrailContext();
2459
- const match = require_resource_page_router.useMatch();
2460
- if (require_resource_page_router.recordTrailRoute(ctx.registry, match) !== null) return (0, react_jsx_runtime.jsx)(RecordBreadcrumbs, {});
2461
- const trail = require_resource_page_router.headerTrail(ctx, match);
4529
+ const ctx = useTrailContext();
4530
+ const match = useMatch();
4531
+ if (recordTrailRoute(ctx.registry, match) !== null) return (0, react_jsx_runtime.jsx)(RecordBreadcrumbs, {});
4532
+ const trail = headerTrail(ctx, match);
2462
4533
  if (trail === null) return null;
2463
4534
  return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
2464
4535
  ...trail,
@@ -2606,20 +4677,20 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2606
4677
  const visibilityCtx = (0, _burojs_react.useVisibilityCtx)();
2607
4678
  const t = (0, _burojs_react.useOptionalT)();
2608
4679
  const navigate = (0, _burojs_react.useRouteNavigate)();
2609
- const isVisible = require_resource_page_router.useNavVisible();
2610
- const resolveLayout = require_resource_page_router.useLayoutResolver();
2611
- const isResourceVisible = require_resource_page_router.useResourceVisible();
2612
- const pageAllowed = require_resource_page_router.usePageAllowed();
4680
+ const isVisible = useNavVisible();
4681
+ const resolveLayout = useLayoutResolver();
4682
+ const isResourceVisible = useResourceVisible();
4683
+ const pageAllowed = usePageAllowed();
2613
4684
  const isPageVisible = (p) => (0, _burojs_core.evaluateVisible)(p.visible, visibilityCtx) && pageAllowed(p);
2614
4685
  const { topLevelResources, topLevelPages, sectionGroups } = (0, react.useMemo)(() => {
2615
4686
  const allResources = app.registry.list();
2616
4687
  const allPages = app.registry.customPages.list();
2617
4688
  const allSections = app.registry.sections.list();
2618
- const tlResources = allResources.filter((r) => (0, _burojs_core.hasListPage)(r)).filter(isResourceVisible).filter((r) => !r.section && !r.group);
4689
+ const tlResources = allResources.filter((r) => (0, _burojs_core.hasMenuEntry)(r)).filter(isResourceVisible).filter((r) => !r.section && !r.group);
2619
4690
  const tlPages = allPages.filter((p) => !p.section && !p.group).filter(isPageVisible);
2620
4691
  const groups = [];
2621
4692
  for (const section of allSections) {
2622
- const children = app.registry.sections.childrenOf(require_resource_page_router.canonicalNavKey(section)).filter((c) => !c.group).filter((c) => !("parent" in c) || (0, _burojs_core.hasListPage)(c)).filter((c) => (0, _burojs_core.isCustomPageDef)(c) ? isPageVisible(c) : isResourceVisible(c));
4693
+ const children = app.registry.sections.childrenOf(require_record_trail_store.canonicalNavKey(section)).filter((c) => !c.group).filter((c) => !("parent" in c) || (0, _burojs_core.hasMenuEntry)(c)).filter((c) => (0, _burojs_core.isCustomPageDef)(c) ? isPageVisible(c) : isResourceVisible(c));
2623
4694
  if (children.length === 0) continue;
2624
4695
  groups.push({
2625
4696
  section,
@@ -2636,13 +4707,13 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2636
4707
  onSelect?.();
2637
4708
  navigate(href, { origin: "jump" });
2638
4709
  };
2639
- const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "plural", def);
2640
- const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(def)}`, (0, _burojs_core.declaredText)("chrome", def, "label"));
4710
+ const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_record_trail_store.canonicalResourceKey(def), "plural", def);
4711
+ const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_record_trail_store.canonicalNavKey(def)}`, (0, _burojs_core.declaredText)("chrome", def, "label"));
2641
4712
  const groups = [];
2642
4713
  if (topLevelResources.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2643
4714
  heading: t("commandPalette.resources", { defaultValue: "Resources" }),
2644
4715
  children: topLevelResources.map((def) => {
2645
- const resource = require_resource_page_router.canonicalResourceKey(def);
4716
+ const resource = require_record_trail_store.canonicalResourceKey(def);
2646
4717
  const label = resourceLabel(def);
2647
4718
  const href = (0, _burojs_core.hrefFor)(app.registry, resource, { isVisible });
2648
4719
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
@@ -2656,7 +4727,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2656
4727
  if (topLevelPages.length > 0) groups.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2657
4728
  heading: t("commandPalette.pages", { defaultValue: "Pages" }),
2658
4729
  children: topLevelPages.map((page) => {
2659
- const pageKey = require_resource_page_router.canonicalNavKey(page);
4730
+ const pageKey = require_record_trail_store.canonicalNavKey(page);
2660
4731
  const label = pageLabel(page);
2661
4732
  const href = page.path;
2662
4733
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
@@ -2668,7 +4739,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2668
4739
  })
2669
4740
  }, "pages"));
2670
4741
  for (const { section, children } of sectionGroups) {
2671
- const sectionKey = require_resource_page_router.canonicalNavKey(section);
4742
+ const sectionKey = require_record_trail_store.canonicalNavKey(section);
2672
4743
  const sectionLabel = (0, _burojs_core.resolveNavLabel)(caps, `sections.${sectionKey}`, (0, _burojs_core.declaredText)("chrome", section, "label"));
2673
4744
  groups.push((0, react_jsx_runtime.jsxs)(require_relation_create.CommandGroup, {
2674
4745
  heading: sectionLabel,
@@ -2680,7 +4751,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2680
4751
  children: sectionLabel
2681
4752
  }, `__section_header_${sectionKey}`), children.map((child) => {
2682
4753
  if ((0, _burojs_core.isCustomPageDef)(child)) {
2683
- const pageKey = require_resource_page_router.canonicalNavKey(child);
4754
+ const pageKey = require_record_trail_store.canonicalNavKey(child);
2684
4755
  const href = child.path;
2685
4756
  const label = pageLabel(child);
2686
4757
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
@@ -2691,7 +4762,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2691
4762
  children: label
2692
4763
  }, `section:${sectionKey}:page:${pageKey}`);
2693
4764
  }
2694
- const resource = require_resource_page_router.canonicalResourceKey(child);
4765
+ const resource = require_record_trail_store.canonicalResourceKey(child);
2695
4766
  const label = resourceLabel(child);
2696
4767
  const href = (0, _burojs_core.hrefFor)(app.registry, resource, { isVisible });
2697
4768
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
@@ -2706,9 +4777,9 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2706
4777
  }
2707
4778
  const collectGroupItems = (group, idPath, depth) => {
2708
4779
  const items = [];
2709
- const href = !!resolveLayout(group.layout) ? require_resource_page_router.groupNavHref(app.registry, require_resource_page_router.canonicalNavKey(group), isVisible) : void 0;
4780
+ const href = !!resolveLayout(group.layout) ? groupNavHref(app.registry, require_record_trail_store.canonicalNavKey(group), isVisible) : void 0;
2710
4781
  if (href !== void 0) {
2711
- const groupKey = require_resource_page_router.canonicalNavKey(group);
4782
+ const groupKey = require_record_trail_store.canonicalNavKey(group);
2712
4783
  const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
2713
4784
  items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
2714
4785
  value: `group:${idPath}:${label}`,
@@ -2718,18 +4789,18 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2718
4789
  children: label
2719
4790
  }, `group:${idPath}`));
2720
4791
  }
2721
- for (const child of app.registry.groups.childrenOf(require_resource_page_router.canonicalNavKey(group))) {
4792
+ for (const child of app.registry.groups.childrenOf(require_record_trail_store.canonicalNavKey(group))) {
2722
4793
  const kind = (0, _burojs_core.nodeKind)(child);
2723
4794
  if (kind === "group") {
2724
4795
  const sub = child;
2725
4796
  if (!isVisible(sub)) continue;
2726
- items.push(...collectGroupItems(sub, `${idPath}:${require_resource_page_router.canonicalNavKey(sub)}`, depth + 1));
4797
+ items.push(...collectGroupItems(sub, `${idPath}:${require_record_trail_store.canonicalNavKey(sub)}`, depth + 1));
2727
4798
  continue;
2728
4799
  }
2729
4800
  if (kind === "custom-page") {
2730
4801
  const page = child;
2731
4802
  if (!isPageVisible(page)) continue;
2732
- const pageKey = require_resource_page_router.canonicalNavKey(page);
4803
+ const pageKey = require_record_trail_store.canonicalNavKey(page);
2733
4804
  const label = pageLabel(page);
2734
4805
  const href = page.path;
2735
4806
  items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
@@ -2744,7 +4815,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2744
4815
  const resource = child;
2745
4816
  if (!(0, _burojs_core.hasListPage)(resource)) continue;
2746
4817
  if (!isResourceVisible(resource)) continue;
2747
- const resourceId = require_resource_page_router.canonicalResourceKey(resource);
4818
+ const resourceId = require_record_trail_store.canonicalResourceKey(resource);
2748
4819
  const label = resourceLabel(resource);
2749
4820
  const href = (0, _burojs_core.hrefFor)(app.registry, resourceId, { isVisible });
2750
4821
  items.push((0, react_jsx_runtime.jsx)(require_relation_create.CommandItem, {
@@ -2760,7 +4831,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2760
4831
  const rootGroups = app.registry.groups.rootNodes().filter((n) => (0, _burojs_core.nodeKind)(n) === "group");
2761
4832
  for (const group of rootGroups) {
2762
4833
  if (!isVisible(group)) continue;
2763
- const groupKey = require_resource_page_router.canonicalNavKey(group);
4834
+ const groupKey = require_record_trail_store.canonicalNavKey(group);
2764
4835
  const items = collectGroupItems(group, groupKey, 0);
2765
4836
  if (items.length === 0) continue;
2766
4837
  const heading = (0, _burojs_core.resolveNavLabel)(caps, `groups.${groupKey}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
@@ -2800,7 +4871,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2800
4871
  const navigate = (0, _burojs_react.useRouteNavigate)();
2801
4872
  const quick = (0, _burojs_react.useQuick)();
2802
4873
  const userId = (0, _burojs_react.useCurrentUserId)();
2803
- const isResourceVisible = require_resource_page_router.useResourceVisible();
4874
+ const isResourceVisible = useResourceVisible();
2804
4875
  const resolvedHeading = heading ?? t("commandPalette.recent", { defaultValue: "Recent" });
2805
4876
  const store = (0, _burojs_react.usePlatformStorage)().local;
2806
4877
  const [stored, setStored] = (0, react.useState)([]);
@@ -2810,7 +4881,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2810
4881
  return;
2811
4882
  }
2812
4883
  let current = true;
2813
- const read = require_resource_page_router.readRecentRecords(store, userId);
4884
+ const read = readRecentRecords(store, userId);
2814
4885
  if (Array.isArray(read)) setStored(read);
2815
4886
  else read.then((entries) => {
2816
4887
  if (current) setStored(entries);
@@ -2859,7 +4930,7 @@ function RecentItem({ entry, href, onGo, getTestId }) {
2859
4930
  const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, entry.canonicalRef, "single", def);
2860
4931
  const key = `${entry.canonicalRef}:${entry.id}`;
2861
4932
  const declared = Object.keys(def?.fields ?? {});
2862
- 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;
4933
+ const candidates = def?.recordTitle === void 0 ? [...declared.filter((name) => RECENT_LABEL_KEYS.includes(name)), ...def?.displayField === void 0 ? [] : [def.displayField]] : declared;
2863
4934
  const legacyTrusted = entry.label === entry.id || access.status === "ready" && candidates.every((name) => access.fieldVisible(name));
2864
4935
  const shown = entry.labelField === void 0 ? legacyTrusted ? entry.label : entry.id : access.status === "ready" && access.fieldVisible(entry.labelField) ? entry.label : entry.id;
2865
4936
  return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
@@ -2897,12 +4968,12 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2897
4968
  const t = (0, _burojs_react.useOptionalT)();
2898
4969
  const navigate = (0, _burojs_react.useRouteNavigate)();
2899
4970
  const quick = (0, _burojs_react.useQuick)();
2900
- const isResourceVisible = require_resource_page_router.useResourceVisible();
4971
+ const isResourceVisible = useResourceVisible();
2901
4972
  const resolvedHeading = heading ?? t("commandPalette.records", { defaultValue: "Records" });
2902
4973
  const liveQuery = (0, cmdk.useCommandState)((state) => state.search) ?? "";
2903
4974
  const debouncedQuery = (0, _burojs_react.useDebouncedValue)(liveQuery, debounceMs);
2904
4975
  const searchableResources = (0, react.useMemo)(() => {
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) => {
4976
+ return app.registry.list().filter((r) => isShowAvailable(app.registry, require_record_trail_store.canonicalResourceKey(r)) || opensInQuick(app.registry, require_record_trail_store.canonicalResourceKey(r), "show")).filter(isResourceVisible).map((def) => {
2906
4977
  const displayField = resolveDisplayField(def);
2907
4978
  return displayField ? {
2908
4979
  def,
@@ -2928,12 +4999,12 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2928
4999
  recordHref,
2929
5000
  registry: app.registry,
2930
5001
  getTestId
2931
- }, require_resource_page_router.canonicalResourceKey(def)))
5002
+ }, require_record_trail_store.canonicalResourceKey(def)))
2932
5003
  }, "records");
2933
5004
  }
2934
5005
  function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recordHref, registry, getTestId }) {
2935
5006
  const caps = (0, _burojs_react.useI18nCaps)();
2936
- const resource = require_resource_page_router.canonicalResourceKey(def);
5007
+ const resource = require_record_trail_store.canonicalResourceKey(def);
2937
5008
  const access = (0, _burojs_react.useListAccess)(resource);
2938
5009
  const titleVisible = access.status === "ready" && access.fieldVisible(displayField);
2939
5010
  const shouldFetch = query.length > 0 && titleVisible;
@@ -2958,7 +5029,7 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2958
5029
  report(rows.length);
2959
5030
  }, [report, rows.length]);
2960
5031
  if (rows.length === 0) return null;
2961
- const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "single", def);
5032
+ const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, require_record_trail_store.canonicalResourceKey(def), "single", def);
2962
5033
  const declaredIdField = def.data?.idField;
2963
5034
  const idField = typeof declaredIdField === "string" && declaredIdField.length > 0 ? declaredIdField : "id";
2964
5035
  return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: rows.map((row) => {
@@ -2968,7 +5039,7 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2968
5039
  const display = titleVisible ? row[displayField] : void 0;
2969
5040
  const labelText = typeof display === "string" && display.length > 0 ? display : id;
2970
5041
  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;
5042
+ const href = recordHref ? recordHref(resource, id) : isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id, row) : null;
2972
5043
  return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2973
5044
  value: `record:${resource}:${id}:${labelText}`,
2974
5045
  forceMount: true,
@@ -3116,7 +5187,7 @@ function CommandPaletteActionsGroup({ actions, onSelect, getTestId, heading }) {
3116
5187
  function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, heading, createHref, prefix }) {
3117
5188
  const caps = (0, _burojs_react.useI18nCaps)();
3118
5189
  const app = (0, _burojs_react.useApp)();
3119
- const isResourceVisible = require_resource_page_router.useResourceVisible();
5190
+ const isResourceVisible = useResourceVisible();
3120
5191
  const gate = (0, _burojs_react.useAvailabilityGate)();
3121
5192
  const t = (0, _burojs_react.useOptionalT)();
3122
5193
  const navigate = (0, _burojs_react.useRouteNavigate)();
@@ -3124,7 +5195,7 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3124
5195
  const resolvedHeading = heading ?? t("commandPalette.create", { defaultValue: "Create" });
3125
5196
  const resolvedPrefix = prefix ?? t("commandPalette.createNew", { defaultValue: "Create new" });
3126
5197
  const visibleResources = (0, react.useMemo)(() => {
3127
- 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);
5198
+ return app.registry.list().filter((r) => (0, _burojs_core.hasListPage)(r)).filter((r) => (0, _burojs_core.collectionFactOf)(r) === void 0).filter((r) => gate(require_record_trail_store.canonicalResourceKey(r), "create").state === "available").filter((r) => (0, _burojs_core.hasRecordPage)(r, "create") || opensInQuick(app.registry, require_record_trail_store.canonicalResourceKey(r), "create")).filter(isResourceVisible).filter((r) => resourceFilter ? resourceFilter(r) : true);
3128
5199
  }, [
3129
5200
  app,
3130
5201
  gate,
@@ -3142,13 +5213,13 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3142
5213
  return;
3143
5214
  }
3144
5215
  onSelect?.();
3145
- quick.create(require_resource_page_router.canonicalResourceKey(def));
5216
+ quick.create(require_record_trail_store.canonicalResourceKey(def));
3146
5217
  };
3147
- const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "single", def);
5218
+ const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_record_trail_store.canonicalResourceKey(def), "single", def);
3148
5219
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
3149
5220
  heading: resolvedHeading,
3150
5221
  children: visibleResources.map((def) => {
3151
- const resource = require_resource_page_router.canonicalResourceKey(def);
5222
+ const resource = require_record_trail_store.canonicalResourceKey(def);
3152
5223
  const label = resourceLabel(def);
3153
5224
  const href = createHref?.(def) ?? (0, _burojs_core.resourceCreateHref)(app.registry, def, resource);
3154
5225
  const value = `create:${resource}:${resolvedPrefix}:${label}`;
@@ -4457,7 +6528,7 @@ function JsonInput({ name, id, value, onChange, testid, disabled, required, aria
4457
6528
  }
4458
6529
  //#endregion
4459
6530
  //#region src/fields/lazy-relation-many.tsx
4460
- const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-BBNsmkaX.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
6531
+ const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-Cq0EHY5I.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4461
6532
  function LazyRelationManyInput(props) {
4462
6533
  return (0, react_jsx_runtime.jsx)(react.Suspense, {
4463
6534
  fallback: (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
@@ -5778,7 +7849,7 @@ function BlockScreen({ block, props, resource, record, label }) {
5778
7849
  children: (0, react_jsx_runtime.jsx)("div", {
5779
7850
  "data-testid": "modal-block",
5780
7851
  className: "min-w-0",
5781
- children: (0, react_jsx_runtime.jsx)(require_resource_page_router.PlannedBody, {
7852
+ children: (0, react_jsx_runtime.jsx)(PlannedBody, {
5782
7853
  screen: compiled,
5783
7854
  name: "modal",
5784
7855
  label: label ?? "",
@@ -6304,7 +8375,7 @@ function QuickLoaded({ entry, recordId, typedId, row, isCurrentData }) {
6304
8375
  const answer = gate(entry.resource, entry.mode === "edit" ? "edit" : "show", row);
6305
8376
  const open = answer.state === "open";
6306
8377
  const title = (0, _burojs_react.useProjectedTitle)(entry.resource, recordId, row, { placeholder: !isCurrentData });
6307
- require_resource_page_router.useRecordVisit(entry.resource, open && entry.mode === "show" ? row : null, { isCurrentData });
8378
+ useRecordVisit(entry.resource, open && entry.mode === "show" ? row : null, { isCurrentData });
6308
8379
  const stack = quick?.stack;
6309
8380
  (0, react.useEffect)(() => {
6310
8381
  if (open && stack !== void 0) stack.nameTop(title);
@@ -6390,7 +8461,7 @@ function QuickScreenOf({ entry, route, recordId }) {
6390
8461
  value: route,
6391
8462
  children: (0, react_jsx_runtime.jsx)(require_place_node.QuickScreenClaimContext.Provider, {
6392
8463
  value: true,
6393
- children: (0, react_jsx_runtime.jsx)(require_resource_page_router.RecordScreen, {
8464
+ children: (0, react_jsx_runtime.jsx)(RecordScreen, {
6394
8465
  resource: entry.resource,
6395
8466
  mode: entry.mode,
6396
8467
  ...recordId === void 0 ? {} : { recordId },
@@ -7143,6 +9214,8 @@ exports.Checkbox = require_place_node.Checkbox;
7143
9214
  exports.Collapsible = Collapsible;
7144
9215
  exports.CollapsibleContent = CollapsibleContent;
7145
9216
  exports.CollapsibleTrigger = CollapsibleTrigger;
9217
+ exports.CollectionCreatePicker = CollectionCreatePicker;
9218
+ exports.CollectionRecordRoute = CollectionRecordRoute;
7146
9219
  exports.ColumnsToggle = require_place_node.ColumnsToggle;
7147
9220
  exports.Command = require_relation_create.Command;
7148
9221
  exports.CommandDialog = require_relation_create.CommandDialog;
@@ -7263,8 +9336,8 @@ exports.ListLive = require_place_node.ListLive;
7263
9336
  exports.ListSavedViews = require_place_node.ListSavedViews;
7264
9337
  exports.ListSearchInput = require_place_node.ListSearchInput;
7265
9338
  exports.LoginForm = LoginForm;
7266
- exports.NavAreaNotFound = require_resource_page_router.NavAreaNotFound;
7267
- exports.NavAreaPage = require_resource_page_router.NavAreaPage;
9339
+ exports.NavAreaNotFound = require_record_trail_store.NavAreaNotFound;
9340
+ exports.NavAreaPage = NavAreaPage;
7268
9341
  exports.NavChrome = NavChrome;
7269
9342
  exports.NavMain = NavMain;
7270
9343
  exports.NavigationGuardDialog = NavigationGuardDialog;
@@ -7284,8 +9357,8 @@ exports.PresetFilterControls = require_filter_builder.PresetFilterControls;
7284
9357
  exports.Progress = Progress;
7285
9358
  exports.RecordActions = require_place_node.RecordActions;
7286
9359
  exports.RecordBreadcrumbs = RecordBreadcrumbs;
7287
- exports.RecordPage = require_resource_page_router.RecordPage;
7288
- exports.RecordScreen = require_resource_page_router.RecordScreen;
9360
+ exports.RecordPage = RecordPage;
9361
+ exports.RecordScreen = RecordScreen;
7289
9362
  exports.RecordTitle = require_place_node.RecordTitle;
7290
9363
  exports.RefreshButton = RefreshButton;
7291
9364
  exports.RelationDisplay = require_relation_create.RelationDisplay;
@@ -7295,12 +9368,12 @@ exports.RelationPicker = require_relation_picker.RelationPicker;
7295
9368
  exports.RelationPickerDialog = require_lazy_relation_picker_dialog.LazyRelationPickerDialog;
7296
9369
  exports.RelationPickerInput = require_relation_picker.RelationPickerInput;
7297
9370
  exports.ResourceList = require_place_node.ResourceList;
7298
- exports.ResourceListPage = require_resource_page_router.ResourceListPage;
7299
- exports.ResourcePageRouter = require_resource_page_router.ResourcePageRouter;
9371
+ exports.ResourceListPage = ResourceListPage;
9372
+ exports.ResourcePageRouter = ResourcePageRouter;
7300
9373
  exports.SavedViewsDropdown = require_place_node.SavedViewsDropdown;
7301
9374
  exports.ScopeDimensionPicker = ScopeDimensionPicker;
7302
9375
  exports.ScopeSwitcher = ScopeSwitcher;
7303
- exports.SecondarySidebarLayout = require_resource_page_router.SecondarySidebarLayout;
9376
+ exports.SecondarySidebarLayout = SecondarySidebarLayout;
7304
9377
  exports.Select = require_filter_builder.Select;
7305
9378
  exports.SelectContent = require_filter_builder.SelectContent;
7306
9379
  exports.SelectGroup = require_filter_builder.SelectGroup;
@@ -7360,7 +9433,7 @@ exports.TableHeader = require_filter_builder.TableHeader;
7360
9433
  exports.TableRow = require_filter_builder.TableRow;
7361
9434
  exports.Tabs = require_place_node.Tabs;
7362
9435
  exports.TabsContent = require_place_node.TabsContent;
7363
- exports.TabsLayout = require_resource_page_router.TabsLayout;
9436
+ exports.TabsLayout = TabsLayout;
7364
9437
  exports.TabsList = require_place_node.TabsList;
7365
9438
  exports.TabsTrigger = require_place_node.TabsTrigger;
7366
9439
  exports.TaskRunPanel = TaskRunPanel;
@@ -7376,9 +9449,10 @@ exports.Tooltip = require_check_confirm_dialog.Tooltip;
7376
9449
  exports.TooltipContent = require_check_confirm_dialog.TooltipContent;
7377
9450
  exports.TooltipProvider = require_check_confirm_dialog.TooltipProvider;
7378
9451
  exports.TooltipTrigger = require_check_confirm_dialog.TooltipTrigger;
9452
+ exports.UnknownMemberCard = UnknownMemberCard;
7379
9453
  exports.UserMenu = UserMenu;
7380
9454
  exports.badgeVariants = require_filter_builder.badgeVariants;
7381
- exports.buildNavItems = require_resource_page_router.buildNavItems;
9455
+ exports.buildNavItems = buildNavItems;
7382
9456
  exports.buroSortingToTanStack = require_place_node.buroSortingToTanStack;
7383
9457
  exports.buttonVariants = require_button.buttonVariants;
7384
9458
  exports.cn = require_use_theme.cn;
@@ -7389,7 +9463,7 @@ exports.formatOperatorLabel = formatOperatorLabel;
7389
9463
  exports.hasIcon = require_check_confirm_dialog.hasIcon;
7390
9464
  exports.i18nPrefixToRef = _burojs_core.i18nPrefixToRef;
7391
9465
  exports.isImage = _burojs_file_storage.isImage;
7392
- exports.layoutSlot = require_resource_page_router.layoutSlot;
9466
+ exports.layoutSlot = layoutSlot;
7393
9467
  exports.listSlot = require_check_confirm_dialog.listSlot;
7394
9468
  exports.loadLocale = require_filter_builder.loadLocale;
7395
9469
  exports.localeLabel = localeLabel;
@@ -7419,18 +9493,18 @@ exports.useDocumentTitle = require_place_node.useDocumentTitle;
7419
9493
  exports.useExportRunWatcher = require_place_node.useExportRunWatcher;
7420
9494
  exports.useFormControl = require_place_node.useFormControl;
7421
9495
  exports.useFormField = useFormField;
7422
- exports.useHref = require_resource_page_router.useHref;
9496
+ exports.useHref = useHref;
7423
9497
  exports.useIsMobile = useIsMobile;
7424
9498
  exports.useLanguagePaletteActions = useLanguagePaletteActions;
7425
9499
  exports.useLanguageSwitch = useLanguageSwitch;
7426
- exports.useLayout = require_resource_page_router.useLayout;
7427
- exports.useLayoutResolver = require_resource_page_router.useLayoutResolver;
9500
+ exports.useLayout = useLayout;
9501
+ exports.useLayoutResolver = useLayoutResolver;
7428
9502
  exports.useLinkComponent = require_toaster.useLinkComponent;
7429
9503
  exports.useListSlot = require_check_confirm_dialog.useListSlot;
7430
- exports.useMatch = require_resource_page_router.useMatch;
9504
+ exports.useMatch = useMatch;
7431
9505
  exports.useNavIcon = useNavIcon;
7432
9506
  exports.useNavTree = useNavTree;
7433
- exports.useNavVisible = require_resource_page_router.useNavVisible;
9507
+ exports.useNavVisible = useNavVisible;
7434
9508
  exports.useOptionalSidebar = useOptionalSidebar;
7435
9509
  exports.usePaletteState = require_place_node.usePaletteState;
7436
9510
  exports.usePresentationCopy = usePresentationCopy;