@burojs/ui-shadcn 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/README.md +9 -0
  2. package/dist/bulk-summary-2HLgz7Il.cjs +169 -0
  3. package/dist/bulk-summary-2HLgz7Il.cjs.map +1 -0
  4. package/dist/bulk-summary-D6A0ua21.js +169 -0
  5. package/dist/bulk-summary-D6A0ua21.js.map +1 -0
  6. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs → candidates-relation-picker-C47mF260.cjs} +4 -4
  7. package/dist/{candidates-relation-picker-Cy0rTxvI.cjs.map → candidates-relation-picker-C47mF260.cjs.map} +1 -1
  8. package/dist/{candidates-relation-picker-B116Bmqi.js → candidates-relation-picker-CGXItMN0.js} +3 -3
  9. package/dist/{candidates-relation-picker-B116Bmqi.js.map → candidates-relation-picker-CGXItMN0.js.map} +1 -1
  10. package/dist/{check-confirm-dialog--gPFnEeg.cjs → check-confirm-dialog-BT04Mieo.cjs} +475 -107
  11. package/dist/check-confirm-dialog-BT04Mieo.cjs.map +1 -0
  12. package/dist/{check-confirm-dialog-bRT8lt0d.js → check-confirm-dialog-CtiRzOAt.js} +391 -108
  13. package/dist/check-confirm-dialog-CtiRzOAt.js.map +1 -0
  14. package/dist/{dialog-B_rt9S1c.js → dialog-C123sVQ8.js} +4 -4
  15. package/dist/dialog-C123sVQ8.js.map +1 -0
  16. package/dist/{dialog-DRNUq9EA.cjs → dialog-vmMdfUWs.cjs} +3 -3
  17. package/dist/dialog-vmMdfUWs.cjs.map +1 -0
  18. package/dist/{filter-builder-nXqtM_h4.cjs → filter-builder-ByGhxLf_.cjs} +1021 -154
  19. package/dist/filter-builder-ByGhxLf_.cjs.map +1 -0
  20. package/dist/{filter-builder-Bhn-dhZV.js → filter-builder-z3Axzf9Y.js} +929 -140
  21. package/dist/filter-builder-z3Axzf9Y.js.map +1 -0
  22. package/dist/{flow-runtime-D3avVH0I.cjs → flow-runtime-BVFjMU5-.cjs} +64 -29
  23. package/dist/flow-runtime-BVFjMU5-.cjs.map +1 -0
  24. package/dist/{flow-runtime-s6lkRPKF.js → flow-runtime-DrUWyTS0.js} +65 -30
  25. package/dist/flow-runtime-DrUWyTS0.js.map +1 -0
  26. package/dist/{flow-screen-CCvgDI9G.js → flow-screen-3fk6J33y.js} +130 -87
  27. package/dist/flow-screen-3fk6J33y.js.map +1 -0
  28. package/dist/{flow-screen-Ci_Sik4Y.cjs → flow-screen-6y5E_HT6.cjs} +130 -87
  29. package/dist/flow-screen-6y5E_HT6.cjs.map +1 -0
  30. package/dist/index.cjs +1186 -950
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +631 -322
  33. package/dist/index.d.ts +631 -322
  34. package/dist/index.js +1100 -870
  35. package/dist/index.js.map +1 -1
  36. package/dist/{inline-flow-host-DV1et3c6.cjs → inline-flow-host-C4KmZIYE.cjs} +5 -5
  37. package/dist/inline-flow-host-C4KmZIYE.cjs.map +1 -0
  38. package/dist/{inline-flow-host-B6FI0ctQ.js → inline-flow-host-YnnvWjdU.js} +5 -5
  39. package/dist/inline-flow-host-YnnvWjdU.js.map +1 -0
  40. package/dist/{candidates-gate-D33jXLHO.cjs → lazy-relation-picker-dialog-BAKBRn3V.cjs} +10 -10
  41. package/dist/lazy-relation-picker-dialog-BAKBRn3V.cjs.map +1 -0
  42. package/dist/{candidates-gate-Bb70LPAy.js → lazy-relation-picker-dialog-DN4bvQfg.js} +11 -11
  43. package/dist/lazy-relation-picker-dialog-DN4bvQfg.js.map +1 -0
  44. package/dist/{page-flow-route-i3ZfJ1sd.js → page-flow-route-CtEfqAvU.js} +35 -23
  45. package/dist/page-flow-route-CtEfqAvU.js.map +1 -0
  46. package/dist/{page-flow-route-hdnULWqd.cjs → page-flow-route-DEjAxHe3.cjs} +42 -30
  47. package/dist/page-flow-route-DEjAxHe3.cjs.map +1 -0
  48. package/dist/{place-node-NraNYKPx.js → place-node-BdxT-30h.js} +1980 -1041
  49. package/dist/place-node-BdxT-30h.js.map +1 -0
  50. package/dist/{place-node-C5SmIAYU.cjs → place-node-Bhl8B3fF.cjs} +2038 -1087
  51. package/dist/place-node-Bhl8B3fF.cjs.map +1 -0
  52. package/dist/{related-list-cards-CFq3meUn.cjs → related-list-cards-Bc_vfCE_.cjs} +9 -4
  53. package/dist/{related-list-cards-CFq3meUn.cjs.map → related-list-cards-Bc_vfCE_.cjs.map} +1 -1
  54. package/dist/{related-list-cards-BWZ9GfOG.js → related-list-cards-BvkD5OcC.js} +9 -4
  55. package/dist/{related-list-cards-BWZ9GfOG.js.map → related-list-cards-BvkD5OcC.js.map} +1 -1
  56. package/dist/related-list-timeline-DCrwN9oO.js +167 -0
  57. package/dist/related-list-timeline-DCrwN9oO.js.map +1 -0
  58. package/dist/related-list-timeline-k0DtnxTs.cjs +167 -0
  59. package/dist/related-list-timeline-k0DtnxTs.cjs.map +1 -0
  60. package/dist/{related-rows-ea43qhhy.cjs → related-rows-BW9Jr07T.cjs} +27 -16
  61. package/dist/related-rows-BW9Jr07T.cjs.map +1 -0
  62. package/dist/{related-rows-o0_t-Yce.js → related-rows-CPE-9FFr.js} +25 -14
  63. package/dist/related-rows-CPE-9FFr.js.map +1 -0
  64. package/dist/{search-access-CPPmfuvy.js → relation-create-C43cdPQt.js} +595 -13
  65. package/dist/relation-create-C43cdPQt.js.map +1 -0
  66. package/dist/{search-access-Dugvttlg.cjs → relation-create-DDEYcKfw.cjs} +633 -14
  67. package/dist/relation-create-DDEYcKfw.cjs.map +1 -0
  68. package/dist/{relation-many-picker-bvkjkv-k.js → relation-many-picker-BlrGRwMV.js} +210 -104
  69. package/dist/relation-many-picker-BlrGRwMV.js.map +1 -0
  70. package/dist/{relation-many-picker-C8zFEjwd.cjs → relation-many-picker-Br-zBHxT.cjs} +218 -112
  71. package/dist/relation-many-picker-Br-zBHxT.cjs.map +1 -0
  72. package/dist/{relation-picker-gag0qSR5.cjs → relation-picker-ADjxI_TI.cjs} +36 -73
  73. package/dist/relation-picker-ADjxI_TI.cjs.map +1 -0
  74. package/dist/{relation-picker-dialog-B6nIiJBf.js → relation-picker-dialog-CyKliBkN.js} +134 -36
  75. package/dist/relation-picker-dialog-CyKliBkN.js.map +1 -0
  76. package/dist/{relation-picker-dialog-0IzkjmiA.cjs → relation-picker-dialog-DimVQF9Y.cjs} +133 -35
  77. package/dist/relation-picker-dialog-DimVQF9Y.cjs.map +1 -0
  78. package/dist/{relation-picker-Z0ZJJ5uS.js → relation-picker-x7P5HKie.js} +30 -61
  79. package/dist/relation-picker-x7P5HKie.js.map +1 -0
  80. package/dist/relation-select-B8Fq4o-t.js +48 -0
  81. package/dist/relation-select-B8Fq4o-t.js.map +1 -0
  82. package/dist/relation-select-Cr3CfNLy.cjs +55 -0
  83. package/dist/relation-select-Cr3CfNLy.cjs.map +1 -0
  84. package/dist/{resource-page-router-3RUf9d1j.js → resource-page-router-BRpUnhay.js} +634 -264
  85. package/dist/resource-page-router-BRpUnhay.js.map +1 -0
  86. package/dist/{resource-page-router-PXfMW9nh.cjs → resource-page-router-qEd2xb55.cjs} +694 -312
  87. package/dist/resource-page-router-qEd2xb55.cjs.map +1 -0
  88. package/dist/{rich-text-vTyVjDoa.cjs → rich-text-C_7JCvRo.cjs} +2 -2
  89. package/dist/{rich-text-vTyVjDoa.cjs.map → rich-text-C_7JCvRo.cjs.map} +1 -1
  90. package/dist/{rich-text-DFerywgz.js → rich-text-RcPBf6hr.js} +2 -2
  91. package/dist/{rich-text-DFerywgz.js.map → rich-text-RcPBf6hr.js.map} +1 -1
  92. package/dist/success-notices-Dl3M1fZP.cjs +46 -0
  93. package/dist/success-notices-Dl3M1fZP.cjs.map +1 -0
  94. package/dist/success-notices-LDEgEkc4.js +41 -0
  95. package/dist/success-notices-LDEgEkc4.js.map +1 -0
  96. package/dist/{toaster-Cr51X7bz.cjs → toaster-BbByOytP.cjs} +60 -15
  97. package/dist/toaster-BbByOytP.cjs.map +1 -0
  98. package/dist/{toaster-C02XbB9r.js → toaster-Ct_YHGs6.js} +43 -16
  99. package/dist/toaster-Ct_YHGs6.js.map +1 -0
  100. package/dist/{use-dialog-filter-state-C--oMAZG.js → use-dialog-filter-state-B_MqzHaT.js} +5 -4
  101. package/dist/use-dialog-filter-state-B_MqzHaT.js.map +1 -0
  102. package/dist/{use-dialog-filter-state-Dhe8PcB5.cjs → use-dialog-filter-state-tNvqAAjh.cjs} +6 -5
  103. package/dist/use-dialog-filter-state-tNvqAAjh.cjs.map +1 -0
  104. package/dist/use-record-subtitle-bfwIoUme.cjs +70 -0
  105. package/dist/use-record-subtitle-bfwIoUme.cjs.map +1 -0
  106. package/dist/use-record-subtitle-gIaCGgbI.js +53 -0
  107. package/dist/use-record-subtitle-gIaCGgbI.js.map +1 -0
  108. package/package.json +11 -11
  109. package/dist/bulk-summary-CwSd6Yjb.cjs +0 -108
  110. package/dist/bulk-summary-CwSd6Yjb.cjs.map +0 -1
  111. package/dist/bulk-summary-GxMDP4bw.js +0 -108
  112. package/dist/bulk-summary-GxMDP4bw.js.map +0 -1
  113. package/dist/candidates-gate-Bb70LPAy.js.map +0 -1
  114. package/dist/candidates-gate-D33jXLHO.cjs.map +0 -1
  115. package/dist/check-confirm-dialog--gPFnEeg.cjs.map +0 -1
  116. package/dist/check-confirm-dialog-bRT8lt0d.js.map +0 -1
  117. package/dist/dialog-B_rt9S1c.js.map +0 -1
  118. package/dist/dialog-DRNUq9EA.cjs.map +0 -1
  119. package/dist/filter-builder-Bhn-dhZV.js.map +0 -1
  120. package/dist/filter-builder-nXqtM_h4.cjs.map +0 -1
  121. package/dist/flow-runtime-D3avVH0I.cjs.map +0 -1
  122. package/dist/flow-runtime-s6lkRPKF.js.map +0 -1
  123. package/dist/flow-screen-CCvgDI9G.js.map +0 -1
  124. package/dist/flow-screen-Ci_Sik4Y.cjs.map +0 -1
  125. package/dist/inline-flow-host-B6FI0ctQ.js.map +0 -1
  126. package/dist/inline-flow-host-DV1et3c6.cjs.map +0 -1
  127. package/dist/page-flow-route-hdnULWqd.cjs.map +0 -1
  128. package/dist/page-flow-route-i3ZfJ1sd.js.map +0 -1
  129. package/dist/place-node-C5SmIAYU.cjs.map +0 -1
  130. package/dist/place-node-NraNYKPx.js.map +0 -1
  131. package/dist/related-list-timeline-CCzl71aA.cjs +0 -142
  132. package/dist/related-list-timeline-CCzl71aA.cjs.map +0 -1
  133. package/dist/related-list-timeline-yrPsjA3F.js +0 -142
  134. package/dist/related-list-timeline-yrPsjA3F.js.map +0 -1
  135. package/dist/related-rows-ea43qhhy.cjs.map +0 -1
  136. package/dist/related-rows-o0_t-Yce.js.map +0 -1
  137. package/dist/relation-create-IA40t1hi.cjs +0 -364
  138. package/dist/relation-create-IA40t1hi.cjs.map +0 -1
  139. package/dist/relation-create-h6F9B4C4.js +0 -339
  140. package/dist/relation-create-h6F9B4C4.js.map +0 -1
  141. package/dist/relation-many-picker-C8zFEjwd.cjs.map +0 -1
  142. package/dist/relation-many-picker-bvkjkv-k.js.map +0 -1
  143. package/dist/relation-picker-Z0ZJJ5uS.js.map +0 -1
  144. package/dist/relation-picker-dialog-0IzkjmiA.cjs.map +0 -1
  145. package/dist/relation-picker-dialog-B6nIiJBf.js.map +0 -1
  146. package/dist/relation-picker-gag0qSR5.cjs.map +0 -1
  147. package/dist/resource-page-router-3RUf9d1j.js.map +0 -1
  148. package/dist/resource-page-router-PXfMW9nh.cjs.map +0 -1
  149. package/dist/search-access-CPPmfuvy.js.map +0 -1
  150. package/dist/search-access-Dugvttlg.cjs.map +0 -1
  151. package/dist/shell-BPlk8hEa.js +0 -205
  152. package/dist/shell-BPlk8hEa.js.map +0 -1
  153. package/dist/shell-DxhlsPwm.cjs +0 -271
  154. package/dist/shell-DxhlsPwm.cjs.map +0 -1
  155. package/dist/toaster-C02XbB9r.js.map +0 -1
  156. package/dist/toaster-Cr51X7bz.cjs.map +0 -1
  157. package/dist/use-dialog-filter-state-C--oMAZG.js.map +0 -1
  158. package/dist/use-dialog-filter-state-Dhe8PcB5.cjs.map +0 -1
@@ -1,7 +1,11 @@
1
- const require_check_confirm_dialog = require("./check-confirm-dialog--gPFnEeg.cjs");
1
+ const require_use_theme = require("./use-theme-DFlpXils.cjs");
2
+ const require_toaster = require("./toaster-BbByOytP.cjs");
3
+ const require_check_confirm_dialog = require("./check-confirm-dialog-BT04Mieo.cjs");
2
4
  const require_button = require("./button-BxnnE28H.cjs");
5
+ const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
3
6
  const require_skeleton = require("./skeleton-_1gP7wan.cjs");
4
- const require_place_node = require("./place-node-C5SmIAYU.cjs");
7
+ const require_place_node = require("./place-node-Bhl8B3fF.cjs");
8
+ const require_success_notices = require("./success-notices-Dl3M1fZP.cjs");
5
9
  let _burojs_core = require("@burojs/core");
6
10
  let _burojs_react = require("@burojs/react");
7
11
  let react = require("react");
@@ -14,51 +18,104 @@ function canonicalResourceKey(def) {
14
18
  return canonicalNavKey(def);
15
19
  }
16
20
  //#endregion
17
- //#region src/layout/build-nav-items.ts
18
- function buildNavItems(args) {
19
- const { registry, caps, groupName, match, isVisible, entryFilter, icons } = args;
20
- const chain = match?.groupChain ?? [];
21
- const qualifiedMatch = match;
22
- const activeLeaf = qualifiedMatch == null ? void 0 : qualifiedMatch.kind === "group-index" ? canonicalNavKey({
23
- name: qualifiedMatch.target ?? qualifiedMatch.name,
24
- ref: qualifiedMatch.targetRef
25
- }) : canonicalNavKey(qualifiedMatch);
26
- const isEligible = (node) => isVisible(node) && (entryFilter ? entryFilter(node) : true);
27
- const out = [];
28
- for (const child of registry.groups.childrenOf(groupName)) {
29
- if (!isEligible(child)) continue;
30
- const kind = (0, _burojs_core.nodeKind)(child);
31
- const childKey = canonicalNavKey(child);
32
- const href = (0, _burojs_core.navHrefFor)(registry, childKey, { isVisible: isEligible });
33
- if (kind === "group") {
34
- const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label"));
35
- const active = chain.some((g) => canonicalNavKey(g) === childKey);
36
- out.push({
37
- kind: "group",
38
- name: childKey,
39
- label,
40
- href,
41
- icon: icons?.group?.(childKey),
42
- active
43
- });
44
- } else if (kind === "custom-page") out.push({
45
- kind: "custom-page",
46
- name: childKey,
47
- label: (0, _burojs_core.resolveNavLabel)(caps, `pages.${childKey}`, (0, _burojs_core.declaredText)("chrome", child, "label")),
48
- href,
49
- icon: icons?.page?.(childKey),
50
- active: activeLeaf === childKey
51
- });
52
- else out.push({
53
- kind: "resource",
54
- name: childKey,
55
- label: (0, _burojs_core.resolveResourceNavLabel)(caps, childKey, child),
56
- href,
57
- icon: icons?.resource?.(childKey),
58
- active: activeLeaf === childKey
59
- });
60
- }
61
- return out;
21
+ //#region src/layout/layouts/secondary-sidebar-layout.tsx
22
+ function Row({ it }) {
23
+ const RouterLink = require_toaster.useLinkComponent();
24
+ return (0, react_jsx_runtime.jsx)("li", { children: (0, react_jsx_runtime.jsxs)(RouterLink, {
25
+ href: it.href,
26
+ "data-testid": `nav-secondary-item:${it.name}`,
27
+ "aria-current": it.active ? "page" : void 0,
28
+ 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"),
29
+ children: [it.icon != null && (0, react_jsx_runtime.jsx)("span", {
30
+ className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
31
+ "aria-hidden": "true",
32
+ children: it.icon
33
+ }), (0, react_jsx_runtime.jsx)("span", {
34
+ className: "truncate",
35
+ title: it.label,
36
+ children: it.label
37
+ })]
38
+ }) });
39
+ }
40
+ function SecondarySidebarLayout({ group, groupKey, items, children }) {
41
+ const RouterLink = require_toaster.useLinkComponent();
42
+ const caps = (0, _burojs_react.useI18nCaps)();
43
+ const id = groupKey ?? group.name;
44
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
45
+ return (0, react_jsx_runtime.jsxs)("div", {
46
+ className: "md:-m-6 md:flex md:min-h-[calc(100%+3rem)]",
47
+ "data-testid": `nav-secondary:${id}`,
48
+ children: [
49
+ (0, react_jsx_runtime.jsx)("aside", {
50
+ className: "hidden w-64 shrink-0 border-r bg-background text-foreground md:block",
51
+ children: (0, react_jsx_runtime.jsxs)("div", {
52
+ className: "space-y-4 p-4",
53
+ children: [(0, react_jsx_runtime.jsx)("p", {
54
+ className: "px-3 text-base font-semibold tracking-tight",
55
+ children: label
56
+ }), (0, react_jsx_runtime.jsx)("nav", {
57
+ "aria-label": label,
58
+ children: (0, react_jsx_runtime.jsx)("ul", {
59
+ className: "space-y-0.5",
60
+ children: items.map((it) => (0, react_jsx_runtime.jsx)(Row, { it }, it.name))
61
+ })
62
+ })]
63
+ })
64
+ }),
65
+ (0, react_jsx_runtime.jsx)("nav", {
66
+ "aria-label": label,
67
+ "data-testid": `nav-secondary-select:${id}`,
68
+ 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",
69
+ children: items.map((it) => (0, react_jsx_runtime.jsx)(RouterLink, {
70
+ href: it.href,
71
+ "aria-current": it.active ? "page" : void 0,
72
+ 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"),
73
+ children: it.label
74
+ }, it.name))
75
+ }),
76
+ (0, react_jsx_runtime.jsx)("div", {
77
+ className: "min-w-0 flex-1 md:overflow-x-hidden md:p-6",
78
+ children
79
+ })
80
+ ]
81
+ });
82
+ }
83
+ //#endregion
84
+ //#region src/layout/layouts/tabs-layout.tsx
85
+ function TabsLayout({ group, groupKey, items, children }) {
86
+ const RouterLink = require_toaster.useLinkComponent();
87
+ const caps = (0, _burojs_react.useI18nCaps)();
88
+ const id = groupKey ?? group.name;
89
+ const label = (0, _burojs_core.resolveNavLabel)(caps, `groups.${id}`, (0, _burojs_core.declaredText)("chrome", group, "label"));
90
+ return (0, react_jsx_runtime.jsxs)("div", {
91
+ className: "flex flex-col gap-4",
92
+ "data-testid": `nav-tabs:${id}`,
93
+ children: [(0, react_jsx_runtime.jsx)("nav", {
94
+ "aria-label": label,
95
+ 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",
96
+ children: items.map((it) => (0, react_jsx_runtime.jsxs)(RouterLink, {
97
+ href: it.href,
98
+ "aria-current": it.active ? "page" : void 0,
99
+ "data-testid": `nav-tab:${it.name}`,
100
+ 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"),
101
+ children: [
102
+ it.icon != null && (0, react_jsx_runtime.jsx)("span", {
103
+ className: "inline-flex h-4 w-4 shrink-0 items-center justify-center",
104
+ "aria-hidden": "true",
105
+ children: it.icon
106
+ }),
107
+ it.label,
108
+ (0, react_jsx_runtime.jsx)("span", {
109
+ "aria-hidden": "true",
110
+ 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")
111
+ })
112
+ ]
113
+ }, it.name))
114
+ }), (0, react_jsx_runtime.jsx)("div", {
115
+ className: "min-w-0",
116
+ children
117
+ })]
118
+ });
62
119
  }
63
120
  //#endregion
64
121
  //#region src/layout/nav-slots.ts
@@ -68,9 +125,33 @@ function layoutSlot(key) {
68
125
  function useLayout(key) {
69
126
  return (0, _burojs_react.useComponent)(layoutSlot(key));
70
127
  }
128
+ const BUILTIN_LAYOUTS = {
129
+ [layoutSlot("secondary-sidebar")]: SecondarySidebarLayout,
130
+ [layoutSlot("tabs")]: TabsLayout
131
+ };
71
132
  function useLayoutResolver() {
72
133
  const components = (0, react.useContext)(_burojs_react.ComponentsContext);
73
- return (key) => components[layoutSlot(key)];
134
+ return (key) => components[layoutSlot(key)] ?? BUILTIN_LAYOUTS[layoutSlot(key)];
135
+ }
136
+ const unresolvedLayoutReported = new WeakMap();
137
+ function useReportUnresolvedLayouts(groups, resolve) {
138
+ const app = (0, _burojs_react.useApp)();
139
+ (0, react.useEffect)(() => {
140
+ if (process.env.NODE_ENV === "production") return;
141
+ for (const group of groups) {
142
+ const layout = group.layout;
143
+ if (layout === "flat" || layout === "collapsible" || resolve(layout)) continue;
144
+ const key = canonicalNavKey(group);
145
+ let seen = unresolvedLayoutReported.get(app);
146
+ if (!seen) {
147
+ seen = new Set();
148
+ unresolvedLayoutReported.set(app, seen);
149
+ }
150
+ if (seen.has(key)) continue;
151
+ seen.add(key);
152
+ 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".`);
153
+ }
154
+ });
74
155
  }
75
156
  //#endregion
76
157
  //#region src/layout/use-nav-routing.ts
@@ -79,6 +160,10 @@ function useNavVisible() {
79
160
  const allowed = usePageAllowed();
80
161
  return (0, react.useCallback)((node) => (0, _burojs_core.evaluateVisible)(node.visible, ctx) && (!(0, _burojs_core.isCustomPageDef)(node) || allowed(node)), [ctx, allowed]);
81
162
  }
163
+ function useResourceVisible() {
164
+ const ctx = (0, _burojs_react.useVisibilityCtx)();
165
+ return (0, react.useCallback)((def) => (0, _burojs_core.evaluateVisible)(def.visible, ctx), [ctx]);
166
+ }
82
167
  function usePageAllowed() {
83
168
  const permissions = (0, _burojs_react.usePermissions)();
84
169
  return (0, react.useCallback)((page) => (0, _burojs_react.pageAccessFor)(page, permissions) === "allowed", [permissions]);
@@ -98,99 +183,17 @@ function useMatch() {
98
183
  return path === void 0 ? null : (0, _burojs_core.matchPath)(app.registry, path, { isVisible });
99
184
  }
100
185
  //#endregion
101
- //#region src/layout/nav-chrome-boundary.tsx
102
- const NavChromeBoundaryContext = (0, react.createContext)(new Set());
103
- function useNavChromeBoundary() {
104
- return (0, react.useContext)(NavChromeBoundaryContext);
105
- }
106
- function NavChromeBoundaryProvider({ claim, children }) {
107
- const parent = (0, react.useContext)(NavChromeBoundaryContext);
108
- const key = claim.join(" ");
109
- const merged = (0, react.useMemo)(() => {
110
- const s = new Set(parent);
111
- for (const n of claim) s.add(n);
112
- return s;
113
- }, [parent, key]);
114
- return (0, react_jsx_runtime.jsx)(NavChromeBoundaryContext.Provider, {
115
- value: merged,
116
- children
117
- });
118
- }
119
- //#endregion
120
- //#region src/layout/nav-chrome.tsx
121
- const DETAIL_ACTIONS = new Set([
122
- "show",
123
- "edit",
124
- "create"
125
- ]);
126
- function NavChrome({ children, entryFilter, icons }) {
127
- const app = (0, _burojs_react.useApp)();
128
- const caps = (0, _burojs_react.useI18nCaps)();
129
- const isVisible = useNavVisible();
130
- const match = useMatch();
131
- const resolveLayout = useLayoutResolver();
132
- const boundary = useNavChromeBoundary();
133
- if (!match) return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
134
- let content = children;
135
- for (let i = match.groupChain.length - 1; i >= 0; i--) {
136
- const group = match.groupChain[i];
137
- if (!group) continue;
138
- const groupKey = canonicalNavKey(group);
139
- if (boundary.has(groupKey)) continue;
140
- if (group.chromeOn === "list" && match.kind === "resource" && DETAIL_ACTIONS.has(match.action)) continue;
141
- const Layout = resolveLayout(group.layout);
142
- if (!Layout) continue;
143
- const items = buildNavItems({
144
- registry: app.registry,
145
- caps,
146
- groupName: groupKey,
147
- match,
148
- isVisible,
149
- entryFilter,
150
- icons
151
- });
152
- content = (0, react_jsx_runtime.jsx)(Layout, {
153
- group,
154
- groupKey,
155
- items,
156
- children: content
157
- });
158
- }
159
- return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: content });
160
- }
161
- //#endregion
162
- //#region src/record/record-state.tsx
163
- function RecordState({ state, onRetry }) {
164
- const t = (0, _burojs_react.useT)();
165
- if (state === "loading") return (0, react_jsx_runtime.jsx)("div", {
166
- role: "status",
167
- "aria-busy": "true",
168
- "data-testid": "record-page:loading",
169
- className: "p-6 text-sm text-muted-foreground",
170
- children: t("router.recordLoading")
171
- });
172
- const message = state === "not-found" ? t("router.recordNotFound") : state === "session-expired" ? t("router.recordSessionExpired") : t("router.recordError");
173
- return (0, react_jsx_runtime.jsxs)("div", {
174
- role: "alert",
175
- "data-testid": `record-page:${state}`,
176
- className: "flex flex-col items-center justify-center gap-3 px-6 py-24 text-center",
177
- children: [(0, react_jsx_runtime.jsx)("p", {
178
- className: "max-w-sm text-sm text-muted-foreground",
179
- children: message
180
- }), onRetry ? (0, react_jsx_runtime.jsx)(require_button.Button, {
181
- type: "button",
182
- variant: "outline",
183
- size: "sm",
184
- "data-testid": "record-page:retry",
185
- onClick: onRetry,
186
- children: t("actions.retry")
187
- }) : null]
188
- });
186
+ //#region src/layout/nav-chrome-mounted.ts
187
+ const NavChromeMountedContext = (0, react.createContext)(false);
188
+ const NavChromeMountedProvider = NavChromeMountedContext.Provider;
189
+ function useNavChromeMounted() {
190
+ return (0, react.useContext)(NavChromeMountedContext);
189
191
  }
190
192
  //#endregion
191
193
  //#region src/flows/page-flow-loader.tsx
192
194
  function PageFlowRouteLoader({ match }) {
193
195
  const t = (0, _burojs_react.useOptionalT)();
196
+ const chromeT = (0, _burojs_react.useChromeT)();
194
197
  const loaded = require_check_confirm_dialog.useLoaded(require_check_confirm_dialog.loadPageFlowRoute);
195
198
  const failed = (retry) => (0, react_jsx_runtime.jsxs)("div", {
196
199
  role: "alert",
@@ -199,11 +202,11 @@ function PageFlowRouteLoader({ match }) {
199
202
  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, {
200
203
  type: "button",
201
204
  onClick: retry,
202
- children: t("actions.retry") === "actions.retry" ? "Retry" : t("actions.retry")
205
+ children: chromeT("actions.retry", { defaultValue: "Retry" })
203
206
  }) })]
204
207
  });
205
208
  if (loaded.error !== void 0) return failed(loaded.retry);
206
- if (loaded.module === void 0) return (0, react_jsx_runtime.jsx)(RecordState, { state: "loading" });
209
+ if (loaded.module === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
207
210
  const Route = loaded.module.PageFlowRoute;
208
211
  return (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.FlowBoundary, {
209
212
  fallback: (_error, reset) => failed(reset),
@@ -212,7 +215,8 @@ function PageFlowRouteLoader({ match }) {
212
215
  }
213
216
  //#endregion
214
217
  //#region src/list-kit/resource-list-page.tsx
215
- function ResourceListPage({ resource, meta, renderCell, emptyState }) {
218
+ function ResourceListPage({ resource: resourceInput, meta, renderCell, emptyState }) {
219
+ const resource = (0, _burojs_core.routeResourceKey)(resourceInput);
216
220
  const app = (0, _burojs_react.useRouteListImplementation)();
217
221
  const implementation = require_place_node.selectImplementation("buro:related-list", app);
218
222
  const View = implementation === void 0 ? void 0 : require_place_node.viewOf(implementation);
@@ -251,7 +255,7 @@ function PageHost({ page, match, notFound }) {
251
255
  const ctx = (0, _burojs_react.useVisibilityCtx)();
252
256
  const access = (0, _burojs_react.usePageAccess)(page);
253
257
  if (!((0, _burojs_core.evaluateVisible)(page.visible, ctx) && match.groupChain.every((group) => isVisible(group)))) return notFound;
254
- if (access === "pending") return (0, react_jsx_runtime.jsx)(RecordState, { state: "loading" });
258
+ if (access === "pending") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
255
259
  if (access === "denied") return notFound;
256
260
  return (0, react_jsx_runtime.jsx)(PageParams, {
257
261
  page,
@@ -290,7 +294,7 @@ function PageBody({ page }) {
290
294
  children: [(0, react_jsx_runtime.jsx)("h1", {
291
295
  className: "text-2xl font-semibold tracking-tight",
292
296
  children: label
293
- }), screen === null ? (0, react_jsx_runtime.jsx)(RecordState, { state: "error" }) : (0, react_jsx_runtime.jsx)(PageRouteScreen, { children: (0, react_jsx_runtime.jsx)(PlannedBody, {
297
+ }), 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, {
294
298
  screen,
295
299
  name,
296
300
  label
@@ -311,8 +315,9 @@ function PageRouteScreen({ children }) {
311
315
  })
312
316
  });
313
317
  }
314
- function PlannedBody({ screen, name, label }) {
315
- const page = (0, _burojs_react.usePageScreen)(screen);
318
+ function PlannedBody({ screen, name, label, record }) {
319
+ const pageOptions = (0, react.useMemo)(() => record === void 0 ? {} : { record }, [record]);
320
+ const page = (0, _burojs_react.usePageScreen)(screen, pageOptions);
316
321
  const { PlacementScope } = page;
317
322
  const route = (0, react.useContext)(_burojs_react.RouteSourceContext);
318
323
  const catalog = (0, _burojs_react.useFrameImplementations)();
@@ -337,27 +342,23 @@ function PlannedBody({ screen, name, label }) {
337
342
  };
338
343
  return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
339
344
  value: null,
340
- children: (0, react_jsx_runtime.jsx)(PlacementScope, { children: (0, react_jsx_runtime.jsx)(require_place_node.DeepLinkScope, {
341
- plan: page.plan,
342
- enabled: true,
343
- children: (0, react_jsx_runtime.jsx)("div", {
344
- "data-buro-region": "page-body",
345
- children: (0, react_jsx_runtime.jsx)(react.Suspense, {
346
- fallback: null,
347
- children: (0, react_jsx_runtime.jsx)(View, { ...viewProps })
345
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ActionRouteContext.Provider, {
346
+ value: route,
347
+ children: (0, react_jsx_runtime.jsx)(PlacementScope, { children: (0, react_jsx_runtime.jsx)(require_place_node.DeepLinkScope, {
348
+ plan: page.plan,
349
+ enabled: true,
350
+ children: (0, react_jsx_runtime.jsx)("div", {
351
+ "data-buro-region": "page-body",
352
+ children: (0, react_jsx_runtime.jsx)(react.Suspense, {
353
+ fallback: null,
354
+ children: (0, react_jsx_runtime.jsx)(View, { ...viewProps })
355
+ })
348
356
  })
349
- })
350
- }) })
357
+ }) })
358
+ })
351
359
  });
352
360
  }
353
361
  //#endregion
354
- //#region src/resource/form-context.tsx
355
- const FormControlContext = (0, react.createContext)(null);
356
- const FormControlProvider = FormControlContext.Provider;
357
- function useFormControl() {
358
- return (0, react.useContext)(FormControlContext);
359
- }
360
- //#endregion
361
362
  //#region src/frames/obligations.tsx
362
363
  const SlotMountsContext = (0, react.createContext)(null);
363
364
  function useSlotOnce(slot) {
@@ -487,9 +488,9 @@ function timeAgo(savedAt, t) {
487
488
  if (diff < 864e5) return t("draft.timeAgoHours", { count: Math.round(diff / 36e5) });
488
489
  return t("draft.timeAgoDays", { count: Math.round(diff / 864e5) });
489
490
  }
490
- function frameRecordId(frame) {
491
+ function frameRecordId(frame, def) {
491
492
  if (frame.recordId !== void 0) return frame.recordId;
492
- const id = frame.record?.id;
493
+ const id = (0, _burojs_react.recordKeyOf)(def, frame.record);
493
494
  return typeof id === "string" || typeof id === "number" ? String(id) : void 0;
494
495
  }
495
496
  function BodySlot() {
@@ -497,7 +498,7 @@ function BodySlot() {
497
498
  const { resource, mode, controller } = frame;
498
499
  const chrome = require_place_node.useFrameChrome();
499
500
  const tid = (0, _burojs_react.useTestIds)();
500
- const id = frameRecordId(frame);
501
+ const id = frameRecordId(frame, (0, _burojs_react.useApp)().registry.get(resource));
501
502
  const tree = (0, react_jsx_runtime.jsx)("div", {
502
503
  "data-buro-region": "record-body",
503
504
  "data-buro-slot": _burojs_core.FORM_SLOT,
@@ -646,14 +647,14 @@ function RecordFrameView({ frame: instance }) {
646
647
  ...policyRecord ?? {},
647
648
  id: typeof rowId === "string" || typeof rowId === "number" ? String(rowId) : ""
648
649
  }), [policyRecord, rowId]);
649
- const showItemActions = require_place_node.useShownItemActions(resource, actionRow, "show");
650
+ const showItemActions = require_place_node.useShownItemActions(resource, actionRow, "show", void 0, controller.sources);
650
651
  const showActions = mode === "show" && record !== void 0 && showItemActions.length > 0;
651
652
  const View = resolved.view;
652
653
  const builtin = require_place_node.isBuiltinRecordView(resolved);
653
654
  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, {
654
655
  value: !builtin,
655
656
  children: (0, react_jsx_runtime.jsx)(react.Suspense, {
656
- fallback: (0, react_jsx_runtime.jsx)(RecordState, { state: "loading" }),
657
+ fallback: (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" }),
657
658
  children: (0, react_jsx_runtime.jsx)(FrameObligations, {
658
659
  id,
659
660
  mode,
@@ -664,6 +665,156 @@ function RecordFrameView({ frame: instance }) {
664
665
  })
665
666
  })] });
666
667
  }
668
+ function useResourceDimensionOptions(dimension, resource, labelField) {
669
+ const def = (0, _burojs_react.useApp)().registry.get(resource);
670
+ const rowTitle = require_relation_create.useRowTitle(resource, labelField ?? def?.displayField);
671
+ const rows = (0, _burojs_react.useList)(resource, {
672
+ pagination: {
673
+ kind: "offset",
674
+ page: 1,
675
+ pageSize: 100
676
+ },
677
+ total: false,
678
+ scope: {
679
+ default: "session",
680
+ dimensions: { [dimension]: "none" }
681
+ }
682
+ }).data?.data;
683
+ return (0, react.useMemo)(() => (rows ?? []).flatMap((row) => {
684
+ const key = (0, _burojs_react.recordKeyOf)(def, row);
685
+ return key === null || key === void 0 ? [] : [{
686
+ value: key,
687
+ label: rowTitle(row)
688
+ }];
689
+ }), [
690
+ rows,
691
+ def,
692
+ rowTitle
693
+ ]);
694
+ }
695
+ //#endregion
696
+ //#region src/record/scope-mismatch-banner.tsx
697
+ const asList = (value) => value === null ? [] : Array.isArray(value) ? value : [value];
698
+ const isScalar = (value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean";
699
+ function ScopeMismatchBanner(props) {
700
+ const app = (0, _burojs_react.useApp)();
701
+ const mapping = app.registry.get(props.resource)?.data?.scope;
702
+ if (app.scope === void 0 || mapping === void 0 || props.record === void 0) return null;
703
+ return (0, react_jsx_runtime.jsx)(Banner, {
704
+ ...props,
705
+ record: props.record,
706
+ mapping
707
+ });
708
+ }
709
+ function Banner({ record, mapping, kind = "record" }) {
710
+ const scope = (0, _burojs_react.useScope)();
711
+ const chromeT = (0, _burojs_react.useChromeT)();
712
+ const differences = (0, react.useMemo)(() => {
713
+ const out = [];
714
+ for (const [dimension, target] of Object.entries(mapping)) {
715
+ const definition = scope.definition?.dimensions[dimension];
716
+ if (definition === void 0 || definition.select === "none") continue;
717
+ const selected = asList(scope.selection[dimension] ?? null);
718
+ if (selected.length === 0) continue;
719
+ const column = (0, _burojs_core.scopeColumnOf)(target);
720
+ if (!Object.hasOwn(record, column)) continue;
721
+ const held = record[column];
722
+ if (held === null || held === void 0 || held === "") {
723
+ if (kind === "created" || "field" in target && target.empty === "shared") continue;
724
+ out.push({
725
+ dimension,
726
+ value: null,
727
+ selected,
728
+ select: definition.select
729
+ });
730
+ continue;
731
+ }
732
+ if (!isScalar(held)) continue;
733
+ if (selected.some((value) => String(value) === String(held))) continue;
734
+ out.push({
735
+ dimension,
736
+ value: held,
737
+ selected,
738
+ select: definition.select
739
+ });
740
+ }
741
+ return out;
742
+ }, [
743
+ mapping,
744
+ record,
745
+ scope.definition,
746
+ scope.selection,
747
+ kind
748
+ ]);
749
+ if (differences.length === 0) return null;
750
+ const apply = () => {
751
+ for (const difference of differences) scope.select(difference.dimension, difference.value === null ? null : difference.select === "multiple" ? [difference.value] : difference.value);
752
+ };
753
+ return (0, react_jsx_runtime.jsxs)("div", {
754
+ role: "status",
755
+ "data-testid": "scope-mismatch:banner",
756
+ className: "flex flex-wrap items-center justify-between gap-3 rounded-md border bg-muted/50 px-3 py-2 text-sm",
757
+ children: [(0, react_jsx_runtime.jsxs)("div", {
758
+ className: "space-y-1",
759
+ children: [(0, react_jsx_runtime.jsx)("p", {
760
+ className: "font-medium",
761
+ 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" })
762
+ }), (0, react_jsx_runtime.jsx)("ul", {
763
+ className: "text-muted-foreground",
764
+ children: differences.map((difference) => (0, react_jsx_runtime.jsx)(DifferenceLine, {
765
+ difference,
766
+ definition: scope.definition.dimensions[difference.dimension]
767
+ }, difference.dimension))
768
+ })]
769
+ }), (0, react_jsx_runtime.jsx)(require_button.Button, {
770
+ type: "button",
771
+ size: "sm",
772
+ "data-testid": "scope-mismatch:switch",
773
+ onClick: apply,
774
+ children: chromeT("scope.mismatch.switch", { defaultValue: "Switch" })
775
+ })]
776
+ });
777
+ }
778
+ function DifferenceLine(props) {
779
+ const source = props.definition.values;
780
+ if (source !== void 0 && !Array.isArray(source)) {
781
+ const { resource, label } = source;
782
+ return (0, react_jsx_runtime.jsx)(ResourceLine, {
783
+ ...props,
784
+ resource,
785
+ ...label ? { labelField: label } : {}
786
+ });
787
+ }
788
+ return (0, react_jsx_runtime.jsx)(LineText, {
789
+ difference: props.difference,
790
+ options: source ?? []
791
+ });
792
+ }
793
+ function ResourceLine({ difference, resource, labelField }) {
794
+ const options = useResourceDimensionOptions(difference.dimension, resource, labelField);
795
+ return (0, react_jsx_runtime.jsx)(LineText, {
796
+ difference,
797
+ options
798
+ });
799
+ }
800
+ function LineText({ difference, options }) {
801
+ const chromeT = (0, _burojs_react.useChromeT)();
802
+ const labelOf = (value) => options.find((option) => String(option.value) === String(value))?.label ?? String(value);
803
+ const field = (0, _burojs_core.humanizeKey)(difference.dimension);
804
+ const item = difference.value === null ? chromeT("scope.mismatch.empty", { defaultValue: "not set" }) : labelOf(difference.value);
805
+ const items = difference.selected.map(labelOf).join(", ");
806
+ return (0, react_jsx_runtime.jsx)("li", {
807
+ "data-testid": `scope-mismatch:line:${difference.dimension}`,
808
+ children: chromeT("scope.mismatch.line", {
809
+ params: {
810
+ field,
811
+ item,
812
+ items
813
+ },
814
+ defaultValue: `${field}: ${item} (selected: ${items})`
815
+ })
816
+ });
817
+ }
667
818
  //#endregion
668
819
  //#region src/record/type-offer.tsx
669
820
  function TypeOffer({ resource, offer, onChoose }) {
@@ -726,18 +877,41 @@ function isAbort(error) {
726
877
  return false;
727
878
  }
728
879
  }
729
- function canonicalName(resource) {
730
- const ref = (0, _burojs_core.normalizeEntityRef)(typeof resource === "string" ? resource : resource.ref);
731
- return (0, _burojs_core.canonicalEntityNodeKey)({
732
- name: ref.id,
733
- ref
734
- });
880
+ const NO_ISSUES = Object.freeze([]);
881
+ const APPLIED_UNREADABLE = Object.freeze({
882
+ code: "applied-unreadable",
883
+ message: Object.freeze({
884
+ key: "errors.appliedUnreadable",
885
+ default: "Saved. The server's answer could not be read, so the screen may not show the latest values."
886
+ }),
887
+ path: Object.freeze([]),
888
+ source: "server",
889
+ severity: "info"
890
+ });
891
+ function issuesOf(error) {
892
+ if (error === null || typeof error !== "object") return void 0;
893
+ try {
894
+ const descriptor = Object.getOwnPropertyDescriptor(error, "issues");
895
+ return descriptor !== void 0 && "value" in descriptor ? descriptor.value : void 0;
896
+ } catch {
897
+ return;
898
+ }
735
899
  }
736
- function frameId(frame) {
737
- return frameRecordId(frame);
900
+ const NO_EDITED = new Set();
901
+ function sameValue(a, b) {
902
+ if (Object.is(a, b)) return true;
903
+ try {
904
+ return JSON.stringify(a) === JSON.stringify(b);
905
+ } catch {
906
+ return false;
907
+ }
738
908
  }
739
909
  function RecordFrameHost(props) {
740
910
  const { resource, mode } = props;
911
+ const [failed, setFailed] = (0, react.useState)(NO_ISSUES);
912
+ const named = (0, react.useMemo)(() => failed.length === 0 ? NO_ISSUES : (0, _burojs_core.routeServerIssues)({ issues: failed }, (segment) => segment, (field) => field !== "_form").fields, [failed]);
913
+ const atFailure = (0, react.useRef)({});
914
+ const [edited, setEdited] = (0, react.useState)(NO_EDITED);
741
915
  const controller = (0, _burojs_react.useFormController)({
742
916
  resource,
743
917
  mode,
@@ -746,7 +920,8 @@ function RecordFrameHost(props) {
746
920
  ...props.record === void 0 ? {} : { record: props.record },
747
921
  ...props.defaults === void 0 ? {} : { defaults: props.defaults },
748
922
  ...props.onSubmit === void 0 ? {} : { onSubmit: props.onSubmit },
749
- ...props.hostTitle ? { entry: "quick" } : {}
923
+ ...props.hostTitle ? { entry: "quick" } : {},
924
+ serverIssues: named
750
925
  });
751
926
  const inputApplied = (0, react.useRef)(false);
752
927
  const { input } = props;
@@ -765,13 +940,32 @@ function RecordFrameHost(props) {
765
940
  const formId = `record-form-${(0, react.useId)()}`;
766
941
  const root = (0, react.useRef)(null);
767
942
  const [submitError, setSubmitError] = (0, react.useState)(void 0);
943
+ const [submitApplied, setSubmitApplied] = (0, react.useState)(void 0);
944
+ (0, react.useEffect)(() => {
945
+ if (plan === null) return;
946
+ const now = Object.keys(atFailure.current).filter((name) => !edited.has(name) && plan.fields[name] === "active" && !sameValue(controller.field(name).value, atFailure.current[name]));
947
+ if (now.length > 0) setEdited((previous) => new Set([...previous, ...now]));
948
+ }, [
949
+ plan,
950
+ controller,
951
+ edited
952
+ ]);
953
+ const notify = require_success_notices.useNoticeSink(resource);
954
+ const routeScreen = require_place_node.useIsRouteScreen();
955
+ const leavesOnCreate = mode === "create" && routeScreen;
956
+ const [created, setCreated] = (0, react.useState)(false);
957
+ const createdRef = (0, react.useRef)(false);
768
958
  const latest = (0, react.useRef)({
769
959
  controller,
770
- onSuccess: props.onSuccess
960
+ onSuccess: props.onSuccess,
961
+ notify,
962
+ leavesOnCreate
771
963
  });
772
964
  latest.current = {
773
965
  controller,
774
- onSuccess: props.onSuccess
966
+ onSuccess: props.onSuccess,
967
+ notify,
968
+ leavesOnCreate
775
969
  };
776
970
  const mounted = (0, react.useRef)(true);
777
971
  (0, react.useEffect)(() => {
@@ -781,29 +975,57 @@ function RecordFrameHost(props) {
781
975
  };
782
976
  }, []);
783
977
  const submit = (0, react.useCallback)(async () => {
978
+ if (createdRef.current) return;
784
979
  setSubmitError(void 0);
980
+ setSubmitApplied(void 0);
981
+ setFailed(NO_ISSUES);
982
+ setEdited(NO_EDITED);
983
+ atFailure.current = {};
785
984
  const outcome = await latest.current.controller.submit();
786
985
  if (!mounted.current) return;
787
- if (outcome.status === "submitted") latest.current.onSuccess?.(outcome.result);
788
- else if (outcome.status === "failed" && !isAbort(outcome.error)) setSubmitError(outcome.error ?? null);
986
+ if (latest.current.leavesOnCreate && (outcome.status === "submitted" || outcome.status === "failed" && outcome.applied === "yes")) {
987
+ createdRef.current = true;
988
+ setCreated(true);
989
+ }
990
+ if (outcome.status === "submitted") {
991
+ const notices = (0, _burojs_core.successNoticesOf)(outcome.result);
992
+ if (notices.length > 0) latest.current.notify(notices);
993
+ latest.current.onSuccess?.(outcome.result);
994
+ } else if (outcome.status === "failed" && outcome.applied === "yes") {
995
+ latest.current.notify([APPLIED_UNREADABLE]);
996
+ latest.current.onSuccess?.(void 0);
997
+ } else if (outcome.status === "failed" && !isAbort(outcome.error)) {
998
+ setSubmitError(outcome.error ?? null);
999
+ setSubmitApplied(outcome.applied);
1000
+ const issues = (0, _burojs_core.normalizeIssueInputs)(issuesOf(outcome.error)).issues;
1001
+ const next = issues.length === 0 ? NO_ISSUES : Object.freeze(issues.map(_burojs_core.issueOfInput));
1002
+ const held = {};
1003
+ const now = latest.current.controller;
1004
+ for (const issue of next) {
1005
+ const head = issue.path[0];
1006
+ if (typeof head === "string" && head !== "_form" && now.plan?.fields[head] === "active") held[head] = now.field(head).value;
1007
+ }
1008
+ atFailure.current = held;
1009
+ setFailed(next);
1010
+ }
789
1011
  }, []);
790
1012
  const record = controller.record;
1013
+ const recordText = props.recordId === void 0 ? void 0 : String(props.recordId);
791
1014
  const frame = (0, react.useMemo)(() => ({
792
1015
  resource,
793
- recordId: props.recordId,
1016
+ recordId: recordText,
794
1017
  mode,
795
1018
  record,
796
1019
  controller
797
1020
  }), [
798
1021
  resource,
799
- props.recordId,
1022
+ recordText,
800
1023
  mode,
801
1024
  record,
802
1025
  controller
803
1026
  ]);
804
1027
  const { chooseType } = props;
805
1028
  const typedAndAccepted = mode === "create" && controller.typeOffer !== null && controller.failure === null;
806
- const routeScreen = require_place_node.useIsRouteScreen();
807
1029
  const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
808
1030
  const hostRouter = routeScreen ? adapter : null;
809
1031
  const guardText = (0, _burojs_react.useNavigationGuardText)();
@@ -817,7 +1039,8 @@ function RecordFrameHost(props) {
817
1039
  guardText.title,
818
1040
  guardText.body
819
1041
  ]);
820
- const typesDecl = (0, _burojs_react.useApp)().registry.get(resource)?.types;
1042
+ const app = (0, _burojs_react.useApp)();
1043
+ const typesDecl = app.registry.get(resource)?.types;
821
1044
  const loaded = controller.record;
822
1045
  const unsupportedType = (0, react.useMemo)(() => {
823
1046
  if (mode === "create" || typesDecl === void 0 || loaded === void 0) return void 0;
@@ -829,6 +1052,10 @@ function RecordFrameHost(props) {
829
1052
  typesDecl,
830
1053
  loaded
831
1054
  ]);
1055
+ const shownFailed = (0, react.useMemo)(() => edited.size === 0 ? failed : Object.freeze(failed.filter((issue) => {
1056
+ const head = issue.path[0];
1057
+ return typeof head !== "string" || !edited.has(head);
1058
+ })), [failed, edited]);
832
1059
  const chrome = (0, react.useMemo)(() => ({
833
1060
  ...props.onCancel === void 0 ? {} : { onCancel: props.onCancel },
834
1061
  ...props.submitLabel === void 0 ? {} : { submitLabel: props.submitLabel },
@@ -838,6 +1065,9 @@ function RecordFrameHost(props) {
838
1065
  ...props.hostTitle ? { hostTitle: true } : {},
839
1066
  formId,
840
1067
  submitError,
1068
+ ...submitApplied === void 0 ? {} : { submitApplied },
1069
+ serverIssues: shownFailed,
1070
+ ...created ? { created: true } : {},
841
1071
  submit,
842
1072
  root
843
1073
  }), [
@@ -849,6 +1079,9 @@ function RecordFrameHost(props) {
849
1079
  props.hostTitle,
850
1080
  formId,
851
1081
  submitError,
1082
+ submitApplied,
1083
+ shownFailed,
1084
+ created,
852
1085
  submit
853
1086
  ]);
854
1087
  (0, _burojs_react.usePublishDocVariant)(mode === "show" ? resource : void 0, record);
@@ -863,45 +1096,51 @@ function RecordFrameHost(props) {
863
1096
  resource,
864
1097
  mode
865
1098
  ]);
866
- const setValues = (0, react.useCallback)((patch) => {
867
- for (const [name, value] of Object.entries(patch)) latest.current.controller.setValue(name, value);
868
- }, []);
869
- const formControl = (0, react.useMemo)(() => ({ setValues }), [setValues]);
870
- const id = frameId(frame);
1099
+ const formControl = require_place_node.useFormControlOf(controller);
1100
+ const id = frameRecordId(frame, app.registry.get(frame.resource));
871
1101
  const rootId = mode === "show" ? tid.pageShow(resource, id ?? "") : mode === "edit" ? tid.pageEdit(resource, id ?? "") : tid.pageCreate(resource);
1102
+ const claimedRoute = (0, react.useContext)(_burojs_react.RouteSourceContext);
872
1103
  const scopeValues = mode === "show" ? controller.record : controller.values;
873
1104
  return (0, react_jsx_runtime.jsx)(_burojs_react.RecordScopeProvider, {
874
1105
  resource,
875
- ...props.recordId === void 0 ? {} : { recordId: props.recordId },
1106
+ ...recordText === void 0 ? {} : { recordId: recordText },
876
1107
  values: scopeValues,
1108
+ create: mode === "create",
877
1109
  children: (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
878
1110
  value: null,
879
- children: (0, react_jsx_runtime.jsx)(_burojs_react.RecordFrameContext.Provider, {
880
- value: frame,
881
- children: (0, react_jsx_runtime.jsx)(require_place_node.FrameChromeContext.Provider, {
882
- value: chrome,
883
- children: (0, react_jsx_runtime.jsxs)(FormControlProvider, {
884
- value: formControl,
885
- children: [(0, react_jsx_runtime.jsx)(require_place_node.DeepLinkScope, {
886
- plan: controller.plan,
887
- enabled: routeScreen && mode !== "create",
888
- children: (0, react_jsx_runtime.jsx)("div", {
889
- ref: root,
890
- "data-testid": rootId,
891
- className: "flex flex-col gap-[var(--buro-section-gap)]",
892
- children: offering && controller.typeOffer !== null ? (0, react_jsx_runtime.jsx)(TypeOffer, {
893
- resource,
894
- offer: controller.typeOffer,
895
- onChoose: (type) => chooseType(type)
896
- }) : failure !== null ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(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, {
897
- resource,
898
- typeValue: unsupportedType
899
- }) : (0, react_jsx_runtime.jsx)(RecordFrameView, { ...props.frame === void 0 ? {} : { frame: props.frame } })
900
- })
901
- }), controller.checkGate === null ? null : (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.CheckConfirmDialog, {
902
- state: controller.checkGate,
903
- testid: `${tid.form(resource, mode, id)}:checks`
904
- })]
1111
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.ActionRouteContext.Provider, {
1112
+ value: claimedRoute,
1113
+ children: (0, react_jsx_runtime.jsx)(_burojs_react.RecordFrameContext.Provider, {
1114
+ value: frame,
1115
+ children: (0, react_jsx_runtime.jsx)(require_place_node.FrameChromeContext.Provider, {
1116
+ value: chrome,
1117
+ children: (0, react_jsx_runtime.jsxs)(require_place_node.FormControlProvider, {
1118
+ value: formControl,
1119
+ children: [(0, react_jsx_runtime.jsx)(require_place_node.DeepLinkScope, {
1120
+ plan: controller.plan,
1121
+ enabled: routeScreen && mode !== "create",
1122
+ children: (0, react_jsx_runtime.jsx)("div", {
1123
+ ref: root,
1124
+ "data-testid": rootId,
1125
+ className: "flex flex-col gap-[var(--buro-section-gap)]",
1126
+ children: offering && controller.typeOffer !== null ? (0, react_jsx_runtime.jsx)(TypeOffer, {
1127
+ resource,
1128
+ offer: controller.typeOffer,
1129
+ onChoose: (type) => chooseType(type)
1130
+ }) : 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, {
1131
+ resource,
1132
+ typeValue: unsupportedType
1133
+ }) : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(ScopeMismatchBanner, {
1134
+ resource,
1135
+ record: mode === "create" ? controller.trustedSeeds : controller.record,
1136
+ kind: mode === "create" ? "created" : "record"
1137
+ }), (0, react_jsx_runtime.jsx)(RecordFrameView, { ...props.frame === void 0 ? {} : { frame: props.frame } })] })
1138
+ })
1139
+ }), controller.checkGate === null ? null : (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.CheckConfirmDialog, {
1140
+ state: controller.checkGate,
1141
+ testid: `${tid.form(resource, mode, id)}:checks`
1142
+ })]
1143
+ })
905
1144
  })
906
1145
  })
907
1146
  })
@@ -913,7 +1152,8 @@ function RecordScreen(props) {
913
1152
  const routeScreen = (0, react.useContext)(require_place_node.RouteScreenClaimContext);
914
1153
  const quickScreen = (0, react.useContext)(require_place_node.QuickScreenClaimContext);
915
1154
  const route = (0, react.useContext)(_burojs_react.RouteSourceContext);
916
- const resource = canonicalName(props.resource);
1155
+ const resourceInput = props.resource;
1156
+ const resource = (0, _burojs_core.resourceKey)(resourceInput);
917
1157
  const tabs = require_place_node.useTabsUrlState(props.mode, routeScreen);
918
1158
  const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
919
1159
  const router = routeScreen ? adapter : null;
@@ -939,7 +1179,7 @@ function RecordScreen(props) {
939
1179
  const query = params.toString();
940
1180
  navigate(query === "" ? router.pathname : `${router.pathname}?${query}`);
941
1181
  }, [router, navigate]);
942
- if (app.registry.get(resource) === void 0) return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1182
+ if (app.registry.get(resource) === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
943
1183
  const { type: _declared, ...rest } = props;
944
1184
  return (0, react_jsx_runtime.jsx)(require_place_node.RouteScreenClaimContext.Provider, {
945
1185
  value: false,
@@ -1029,6 +1269,24 @@ function usePublishedRecordTrail(key) {
1029
1269
  return current !== null && current.key === key ? current : null;
1030
1270
  }
1031
1271
  //#endregion
1272
+ //#region src/layout/record-targets.ts
1273
+ function isShowAvailable(registry, resource) {
1274
+ return (0, _burojs_react.recordRouteAvailable)(registry, resource, "show");
1275
+ }
1276
+ function showTarget(resource, id) {
1277
+ return {
1278
+ resource,
1279
+ action: "show",
1280
+ params: { id }
1281
+ };
1282
+ }
1283
+ function listTarget(resource) {
1284
+ return {
1285
+ resource,
1286
+ action: "list"
1287
+ };
1288
+ }
1289
+ //#endregion
1032
1290
  //#region src/layout/route-trail.ts
1033
1291
  function useTrailContext() {
1034
1292
  const app = (0, _burojs_react.useApp)();
@@ -1056,7 +1314,8 @@ function groupCrumbs(ctx, chain) {
1056
1314
  const key = canonicalNavKey(group);
1057
1315
  return {
1058
1316
  label: (0, _burojs_core.resolveNavLabel)(ctx.caps, `groups.${key}`, (0, _burojs_core.declaredText)("chrome", group, "label")),
1059
- href: groupCrumbHref(ctx.registry, key, ctx.isVisible)
1317
+ href: groupCrumbHref(ctx.registry, key, ctx.isVisible),
1318
+ jump: true
1060
1319
  };
1061
1320
  });
1062
1321
  }
@@ -1072,17 +1331,77 @@ function recordActionOf(match) {
1072
1331
  default: return;
1073
1332
  }
1074
1333
  }
1334
+ function pathOf(href) {
1335
+ const path = href.split(/[?#]/, 1)[0] ?? "";
1336
+ return path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path;
1337
+ }
1338
+ function originTrail(ctx, origin, depth = _burojs_react.ORIGIN_DEPTH) {
1339
+ const match = (0, _burojs_core.matchPath)(ctx.registry, pathOf(origin.href), { isVisible: ctx.isVisible });
1340
+ if (match === null) return void 0;
1341
+ switch (match.kind) {
1342
+ case "resource": {
1343
+ const key = canonicalNavKey(match);
1344
+ if (match.action === "list") return {
1345
+ leading: groupCrumbs(ctx, match.groupChain),
1346
+ resource: key,
1347
+ resourceHref: origin.href,
1348
+ segments: []
1349
+ };
1350
+ const def = ctx.registry.get(key);
1351
+ const crumb = {
1352
+ label: match.action === "create" ? ctx.t("breadcrumbs.create") : origin.title || (match.id === void 0 ? "" : `#${match.id}`),
1353
+ href: origin.href
1354
+ };
1355
+ const parent = depth > 1 && origin.origin !== void 0 ? originTrail(ctx, origin.origin, depth - 1) : void 0;
1356
+ if (parent !== void 0) return {
1357
+ ...parent,
1358
+ segments: [...parent.segments, crumb]
1359
+ };
1360
+ return {
1361
+ leading: groupCrumbs(ctx, match.groupChain),
1362
+ resource: key,
1363
+ ...def !== void 0 && (0, _burojs_core.hasListPage)(def) ? { resourceHref: (0, _burojs_core.hrefFor)(ctx.registry, key) } : {},
1364
+ segments: [crumb]
1365
+ };
1366
+ }
1367
+ case "custom-page": {
1368
+ const trail = headerTrail(ctx, match);
1369
+ if (trail === null || trail.pageLabel === void 0) return void 0;
1370
+ return {
1371
+ leading: trail.leadingSegments ?? [],
1372
+ segments: [{
1373
+ label: trail.pageLabel,
1374
+ href: origin.href
1375
+ }]
1376
+ };
1377
+ }
1378
+ case "group-index": {
1379
+ const crumbs = groupCrumbs(ctx, match.groupChain);
1380
+ const own = crumbs[crumbs.length - 1];
1381
+ if (own === void 0) return void 0;
1382
+ return {
1383
+ leading: crumbs.slice(0, -1),
1384
+ segments: [{
1385
+ label: own.label,
1386
+ href: origin.href
1387
+ }]
1388
+ };
1389
+ }
1390
+ default: return;
1391
+ }
1392
+ }
1075
1393
  function recordTrail(ctx, input) {
1076
- const { resource, action, id } = input;
1394
+ const { resource, action, id, origin } = input;
1395
+ if (origin !== void 0 && (action === "create" || id !== "")) return originRooted(ctx, input, origin);
1077
1396
  const leadingSegments = nonEmpty(groupCrumbs(ctx, input.groupChain));
1078
1397
  if (action !== "create" && id === "") return {
1079
1398
  resource,
1080
1399
  leadingSegments
1081
1400
  };
1082
1401
  const recordLabel = input.title || id;
1083
- const middleSegments = action === "edit" ? [require_place_node.isShowAvailable(ctx.registry, resource) ? {
1402
+ const middleSegments = action === "edit" ? [isShowAvailable(ctx.registry, resource) ? {
1084
1403
  label: recordLabel,
1085
- href: (0, _burojs_react.resolveRoute)(require_place_node.showTarget(resource, id), ctx.registry)
1404
+ href: (0, _burojs_react.resolveRoute)(showTarget(resource, id), ctx.registry)
1086
1405
  } : { label: recordLabel }] : void 0;
1087
1406
  const pageLabel = action === "create" ? ctx.t("breadcrumbs.create") : action === "edit" ? ctx.t("breadcrumbs.edit") : recordLabel;
1088
1407
  return {
@@ -1093,6 +1412,42 @@ function recordTrail(ctx, input) {
1093
1412
  middleSegments
1094
1413
  };
1095
1414
  }
1415
+ function originRooted(ctx, input, origin) {
1416
+ const { resource, action, id } = input;
1417
+ const recordLabel = input.title || id;
1418
+ const drawn = new Set(origin.segments.flatMap((crumb) => crumb.href === void 0 ? [] : [pathOf(crumb.href)]));
1419
+ const own = action === "edit" ? [isShowAvailable(ctx.registry, resource) ? {
1420
+ label: recordLabel,
1421
+ href: (0, _burojs_react.resolveRoute)(showTarget(resource, id), ctx.registry)
1422
+ } : { label: recordLabel }].filter((crumb) => crumb.href === void 0 || !drawn.has(pathOf(crumb.href))) : [];
1423
+ const pageLabel = action === "create" ? ctx.t("breadcrumbs.create") : action === "edit" ? ctx.t("breadcrumbs.edit") : recordLabel;
1424
+ const recordId = action === "create" ? void 0 : id;
1425
+ const middleSegments = nonEmpty([...origin.segments, ...own]);
1426
+ if (origin.resource !== void 0 && ctx.registry.get(origin.resource) === ctx.registry.get(resource)) return {
1427
+ resource,
1428
+ recordId,
1429
+ pageLabel,
1430
+ leadingSegments: nonEmpty([...origin.leading]),
1431
+ ...origin.resourceHref === void 0 ? {} : { resourceHref: origin.resourceHref },
1432
+ middleSegments
1433
+ };
1434
+ const def = origin.resource === void 0 ? void 0 : ctx.registry.get(origin.resource);
1435
+ const resourceCrumb = origin.resource === void 0 ? [] : [{
1436
+ label: (0, _burojs_core.resolveResourceLabel)(ctx.caps, origin.resource, "plural", def),
1437
+ ...origin.resourceHref === void 0 ? {} : { href: origin.resourceHref }
1438
+ }];
1439
+ return {
1440
+ resource,
1441
+ recordId,
1442
+ pageLabel,
1443
+ rootSegments: [
1444
+ ...origin.leading,
1445
+ ...resourceCrumb,
1446
+ ...origin.segments,
1447
+ ...own
1448
+ ]
1449
+ };
1450
+ }
1096
1451
  function recordTrailRoute(registry, match) {
1097
1452
  if (match === null || match.kind !== "resource") return null;
1098
1453
  const resource = canonicalNavKey(match);
@@ -1105,7 +1460,7 @@ function recordTrailRoute(registry, match) {
1105
1460
  groupChain
1106
1461
  };
1107
1462
  const action = recordActionOf(match);
1108
- if (action === void 0 || !require_place_node.recordRouteAvailable(registry, resource, action)) return null;
1463
+ if (action === void 0 || !(0, _burojs_react.recordRouteAvailable)(registry, resource, action)) return null;
1109
1464
  return {
1110
1465
  resource,
1111
1466
  action,
@@ -1175,24 +1530,18 @@ function parse(raw) {
1175
1530
  return [];
1176
1531
  }
1177
1532
  }
1178
- function readRecentRecords(userId) {
1179
- if (typeof window === "undefined") return [];
1180
- try {
1181
- return parse(window.localStorage.getItem(recentStorageKey(userId)));
1182
- } catch {
1183
- return [];
1184
- }
1533
+ function readRecentRecords(store, userId) {
1534
+ return (0, _burojs_react.maybeThen)((0, _burojs_react.settle)(() => store.get(recentStorageKey(userId)), null), parse);
1185
1535
  }
1186
- function writeRecentRecord(userId, entry) {
1187
- if (typeof window === "undefined") return;
1188
- try {
1189
- const key = recentStorageKey(userId);
1536
+ function writeRecentRecord(store, userId, entry) {
1537
+ const key = recentStorageKey(userId);
1538
+ return (0, _burojs_react.maybeThen)((0, _burojs_react.settle)(() => store.get(key), null), (raw) => {
1190
1539
  const envelope = {
1191
1540
  version: 2,
1192
- items: [entry, ...parse(window.localStorage.getItem(key)).filter((item) => !(item.canonicalRef === entry.canonicalRef && item.id === entry.id))].slice(0, 5)
1541
+ items: [entry, ...parse(raw).filter((item) => !(item.canonicalRef === entry.canonicalRef && item.id === entry.id))].slice(0, 5)
1193
1542
  };
1194
- window.localStorage.setItem(key, JSON.stringify(envelope));
1195
- } catch {}
1543
+ return (0, _burojs_react.settle)(() => store.set(key, JSON.stringify(envelope)), void 0);
1544
+ });
1196
1545
  }
1197
1546
  function text(value) {
1198
1547
  return typeof value === "string" && value.length > 0 ? value : void 0;
@@ -1218,10 +1567,12 @@ function recentLabel(record, id, isGuarded = () => false) {
1218
1567
  //#region src/layout/use-record-visit.ts
1219
1568
  function useRecordVisit(resource, record, opts) {
1220
1569
  const userId = (0, _burojs_react.useCurrentUserId)();
1221
- const raw = record?.id;
1222
- const id = typeof raw === "string" || typeof raw === "number" ? String(raw) : void 0;
1570
+ const store = (0, _burojs_react.usePlatformStorage)().local;
1223
1571
  const app = (0, _burojs_react.useApp)();
1224
- const fields = app.registry.get(resource)?.fields;
1572
+ const def = app.registry.get(resource);
1573
+ const raw = (0, _burojs_react.recordKeyOf)(def, record);
1574
+ const id = typeof raw === "string" || typeof raw === "number" ? String(raw) : void 0;
1575
+ const fields = def?.fields;
1225
1576
  const rules = app.ruleSource?.rules(resource) ?? [];
1226
1577
  const isGuarded = (field) => fields !== void 0 && Object.hasOwn(fields, field) && (0, _burojs_core.fieldSensitivity)(fields[field]) !== void 0 || (0, _burojs_core.addressesCapability)(rules, "view", {
1227
1578
  kind: "field",
@@ -1235,7 +1586,7 @@ function useRecordVisit(resource, record, opts) {
1235
1586
  (0, react.useEffect)(() => {
1236
1587
  if (userId === null || !isCurrentData || id === void 0 || id === "") return;
1237
1588
  if (label === void 0) return;
1238
- writeRecentRecord(userId, {
1589
+ writeRecentRecord(store, userId, {
1239
1590
  canonicalRef,
1240
1591
  id,
1241
1592
  label,
@@ -1243,6 +1594,7 @@ function useRecordVisit(resource, record, opts) {
1243
1594
  at: new Date().toISOString()
1244
1595
  });
1245
1596
  }, [
1597
+ store,
1246
1598
  userId,
1247
1599
  isCurrentData,
1248
1600
  canonicalRef,
@@ -1253,12 +1605,6 @@ function useRecordVisit(resource, record, opts) {
1253
1605
  }
1254
1606
  //#endregion
1255
1607
  //#region src/layout/record-page.tsx
1256
- function recordErrorState(error) {
1257
- const { kind } = (0, _burojs_core.normalizeDataError)(error);
1258
- if (kind === "not-found" || kind === "forbidden") return "not-found";
1259
- if (kind === "auth") return "session-expired";
1260
- return "error";
1261
- }
1262
1608
  function useMountedRef() {
1263
1609
  const mounted = (0, react.useRef)(true);
1264
1610
  (0, react.useEffect)(() => {
@@ -1281,7 +1627,7 @@ function RecordRouteHeader({ resource, action, id, record }) {
1281
1627
  ...action === "create" ? {} : { recordName }
1282
1628
  });
1283
1629
  }
1284
- function RecordShow({ resource, id, record, shown }) {
1630
+ function RecordShow({ resource, id, recordId, record, shown }) {
1285
1631
  return (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(RecordRouteHeader, {
1286
1632
  resource,
1287
1633
  action: "show",
@@ -1290,15 +1636,14 @@ function RecordShow({ resource, id, record, shown }) {
1290
1636
  }), (0, react_jsx_runtime.jsx)(RecordScreen, {
1291
1637
  resource,
1292
1638
  mode: "show",
1293
- recordId: id,
1639
+ recordId,
1294
1640
  record
1295
1641
  })] });
1296
1642
  }
1297
- function RecordEdit({ resource, id, record, shown }) {
1298
- const app = (0, _burojs_react.useApp)();
1643
+ function RecordEdit({ resource, id, recordId, record, shown }) {
1299
1644
  const navigate = (0, _burojs_react.useRouteNavigate)();
1300
1645
  const mounted = useMountedRef();
1301
- const back = require_place_node.recordReturnTarget(app.registry, resource, id);
1646
+ const back = (0, _burojs_react.useReturnTarget)(resource, "edit", id);
1302
1647
  return (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(RecordRouteHeader, {
1303
1648
  resource,
1304
1649
  action: "edit",
@@ -1307,11 +1652,11 @@ function RecordEdit({ resource, id, record, shown }) {
1307
1652
  }), (0, react_jsx_runtime.jsx)(RecordScreen, {
1308
1653
  resource,
1309
1654
  mode: "edit",
1310
- recordId: id,
1655
+ recordId,
1311
1656
  record,
1312
- onCancel: () => navigate(back),
1657
+ onCancel: () => navigate(back, { origin: "inherit" }),
1313
1658
  onSuccess: () => {
1314
- if (mounted.current) navigate(back);
1659
+ if (mounted.current) navigate(back, { origin: "inherit" });
1315
1660
  }
1316
1661
  })] });
1317
1662
  }
@@ -1324,7 +1669,8 @@ function RecordCreate({ resource, defaults }) {
1324
1669
  const navigate = (0, _burojs_react.useRouteNavigate)();
1325
1670
  const mounted = useMountedRef();
1326
1671
  const adapter = (0, _burojs_react.useOptionalRouterAdapter)();
1327
- const list = require_place_node.listTarget(resource);
1672
+ const list = listTarget(resource);
1673
+ const back = (0, _burojs_react.useReturnTarget)(resource, "create");
1328
1674
  const type = adapter?.searchParams.get("type") ?? void 0;
1329
1675
  return (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(RecordRouteHeader, {
1330
1676
  resource,
@@ -1337,21 +1683,21 @@ function RecordCreate({ resource, defaults }) {
1337
1683
  mode: "create",
1338
1684
  ...type === void 0 ? {} : { type },
1339
1685
  ...defaults === void 0 ? {} : { defaults },
1340
- onCancel: () => navigate(list),
1686
+ onCancel: () => navigate(back, { origin: "inherit" }),
1341
1687
  onSuccess: (result) => {
1342
1688
  if (!mounted.current) return;
1343
1689
  const id = createdId(result);
1344
- navigate(id === void 0 ? list : require_place_node.recordReturnTarget(app.registry, resource, id));
1690
+ navigate(id !== void 0 && isShowAvailable(app.registry, resource) ? showTarget(resource, id) : list, { origin: "inherit" });
1345
1691
  }
1346
1692
  })
1347
1693
  })] });
1348
1694
  }
1349
- function RecordRead({ resource, action, id }) {
1695
+ function RecordRead({ resource, action, id, recordId }) {
1350
1696
  const app = (0, _burojs_react.useApp)();
1351
1697
  const def = app.registry.get(resource);
1352
1698
  const projection = (0, react.useMemo)(() => def === void 0 ? void 0 : (0, _burojs_core.dtoFields)(def, "record"), [def]);
1353
1699
  const query = (0, _burojs_react.useOne)(resource, {
1354
- id,
1700
+ id: recordId,
1355
1701
  retry: _burojs_react.retryRecordRead,
1356
1702
  ...projection === void 0 ? {} : { projection }
1357
1703
  });
@@ -1371,18 +1717,18 @@ function RecordRead({ resource, action, id }) {
1371
1717
  const availability = (0, _burojs_react.useAvailabilityResolver)(resource, "edit");
1372
1718
  if (result !== void 0) {
1373
1719
  const record = result.data;
1374
- if (record === null || typeof record !== "object") return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1720
+ if (record === null || typeof record !== "object") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
1375
1721
  const loaded = record;
1376
1722
  if (showRuled) {
1377
- if (query.isPlaceholderData || permissions?.status === "loading") return (0, react_jsx_runtime.jsx)(RecordState, { state: "loading" });
1378
- if (permissions?.status === "error") return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1379
- if (showHidden) return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1723
+ if (query.isPlaceholderData || permissions?.status === "loading") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
1724
+ if (permissions?.status === "error") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
1725
+ if (showHidden) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
1380
1726
  }
1381
- if (projected.status === "pending" || projected.value === null) return (0, react_jsx_runtime.jsx)(RecordState, { state: "loading" });
1727
+ if (projected.status === "pending" || projected.value === null) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
1382
1728
  const shown = projected.value;
1383
1729
  if (action === "edit") {
1384
1730
  const edit = availability("edit", loaded).state;
1385
- if (edit === "hidden" || edit === "absent") return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1731
+ if (edit === "hidden" || edit === "absent") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
1386
1732
  }
1387
1733
  return (0, react_jsx_runtime.jsx)(_burojs_react.RouteSourceContext.Provider, {
1388
1734
  value: route,
@@ -1391,30 +1737,39 @@ function RecordRead({ resource, action, id }) {
1391
1737
  children: action === "edit" ? (0, react_jsx_runtime.jsx)(RecordEdit, {
1392
1738
  resource,
1393
1739
  id,
1740
+ recordId,
1394
1741
  record: loaded,
1395
1742
  shown
1396
1743
  }) : (0, react_jsx_runtime.jsx)(RecordShow, {
1397
1744
  resource,
1398
1745
  id,
1746
+ recordId,
1399
1747
  record: loaded,
1400
1748
  shown
1401
1749
  })
1402
1750
  })
1403
1751
  });
1404
1752
  }
1405
- if (query.error != null) {
1406
- const state = recordErrorState(query.error);
1407
- return (0, react_jsx_runtime.jsx)(RecordState, {
1408
- state,
1409
- onRetry: state === "error" ? () => void query.refetch() : void 0
1410
- });
1411
- }
1412
- return (0, react_jsx_runtime.jsx)(RecordState, { state: "loading" });
1753
+ if (query.error != null) return (0, react_jsx_runtime.jsx)(require_relation_create.LoadError, {
1754
+ surface: "record",
1755
+ resource,
1756
+ error: query.error,
1757
+ retry: () => void query.refetch()
1758
+ });
1759
+ return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "loading" });
1413
1760
  }
1414
1761
  function RecordRouteBody(props) {
1415
1762
  if (props.action === "create") return (0, react_jsx_runtime.jsx)(RecordCreate, { ...props });
1416
- if (props.id === "") return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1417
- return (0, react_jsx_runtime.jsx)(RecordRead, { ...props });
1763
+ if (props.id === "") return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
1764
+ return (0, react_jsx_runtime.jsx)(RecordReadRoute, { ...props });
1765
+ }
1766
+ function RecordReadRoute(props) {
1767
+ const recordId = (0, _burojs_react.useRouteRecordId)(props.resource, props.id);
1768
+ if (recordId === void 0) return (0, react_jsx_runtime.jsx)(require_relation_create.InvalidRouteId, { resource: props.resource });
1769
+ return (0, react_jsx_runtime.jsx)(RecordRead, {
1770
+ ...props,
1771
+ recordId
1772
+ });
1418
1773
  }
1419
1774
  function RecordRoute(props) {
1420
1775
  const missingRuntime = (0, _burojs_react.useOptionalDataRuntime)() === null;
@@ -1422,7 +1777,7 @@ function RecordRoute(props) {
1422
1777
  if (!missingRuntime || process.env.NODE_ENV === "production") return;
1423
1778
  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.`);
1424
1779
  }, [missingRuntime, props.resource]);
1425
- if (missingRuntime) return (0, react_jsx_runtime.jsx)(RecordState, { state: "error" });
1780
+ if (missingRuntime) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "error" });
1426
1781
  return (0, react_jsx_runtime.jsx)(RecordRouteBody, { ...props }, `${props.resource}:${props.id}`);
1427
1782
  }
1428
1783
  function recordPageProblem(input) {
@@ -1437,7 +1792,8 @@ function RecordPage(props) {
1437
1792
  const app = (0, _burojs_react.useApp)();
1438
1793
  const match = useMatch();
1439
1794
  const id = match === null ? null : match.id ?? "";
1440
- const { resource, action } = props;
1795
+ const { action } = props;
1796
+ const resource = props.resource === void 0 ? void 0 : (0, _burojs_core.routeResourceKey)(props.resource);
1441
1797
  const onRecordRoute = recordActionOf(match) !== void 0;
1442
1798
  const problem = recordPageProblem({
1443
1799
  props,
@@ -1456,7 +1812,7 @@ function RecordPage(props) {
1456
1812
  logged.add(problem);
1457
1813
  console.error(problem);
1458
1814
  }, [app, problem]);
1459
- if (resource === void 0 || action === void 0 || id === null || !onRecordRoute) return (0, react_jsx_runtime.jsx)(RecordState, { state: "not-found" });
1815
+ if (resource === void 0 || action === void 0 || id === null || !onRecordRoute) return (0, react_jsx_runtime.jsx)(require_relation_create.RecordState, { state: "not-found" });
1460
1816
  const route = action === "create" ? {
1461
1817
  resource,
1462
1818
  action,
@@ -1503,7 +1859,7 @@ function ResourcePageRouter({ match }) {
1503
1859
  }
1504
1860
  if (match.action === "flow") return (0, react_jsx_runtime.jsx)(PageFlowRouteLoader, { match });
1505
1861
  if (recordAction === void 0) return (0, react_jsx_runtime.jsx)(ResourcePageRouterEmpty, {});
1506
- if (!require_place_node.recordRouteAvailable(app.registry, resource, recordAction)) return (0, react_jsx_runtime.jsx)(NavAreaNotFound, {});
1862
+ if (!(0, _burojs_react.recordRouteAvailable)(app.registry, resource, recordAction)) return (0, react_jsx_runtime.jsx)(NavAreaNotFound, {});
1507
1863
  return (0, react_jsx_runtime.jsx)(RecordRoute, {
1508
1864
  resource,
1509
1865
  action: recordAction,
@@ -1567,10 +1923,24 @@ function NavAreaNotFound() {
1567
1923
  });
1568
1924
  }
1569
1925
  const adapterNoticeGiven = new WeakSet();
1926
+ const chromeNoticeGiven = new WeakSet();
1570
1927
  function NavAreaPage() {
1571
1928
  const match = useMatch();
1572
1929
  const app = (0, _burojs_react.useApp)();
1573
1930
  const noAdapter = (0, _burojs_react.useOptionalRouterAdapter)() === null;
1931
+ const chromeMounted = useNavChromeMounted();
1932
+ const resolveLayout = useLayoutResolver();
1933
+ const chromeGroup = match?.groupChain.find((g) => resolveLayout(g.layout)) ?? null;
1934
+ (0, react.useEffect)(() => {
1935
+ if (process.env.NODE_ENV === "production") return;
1936
+ if (chromeMounted || !chromeGroup || chromeNoticeGiven.has(app)) return;
1937
+ chromeNoticeGiven.add(app);
1938
+ console.error(`[burojs] <NavAreaPage> is inside the nav group "${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>.`);
1939
+ }, [
1940
+ app,
1941
+ chromeMounted,
1942
+ chromeGroup
1943
+ ]);
1574
1944
  (0, react.useEffect)(() => {
1575
1945
  if (!noAdapter || process.env.NODE_ENV === "production") return;
1576
1946
  if (adapterNoticeGiven.has(app)) return;
@@ -1579,32 +1949,32 @@ function NavAreaPage() {
1579
1949
  }, [app, noAdapter]);
1580
1950
  return (0, react_jsx_runtime.jsx)(react.Suspense, {
1581
1951
  fallback: (0, react_jsx_runtime.jsx)(NavAreaPageSkeleton, {}),
1582
- children: match ? (0, react_jsx_runtime.jsx)(NavChrome, { children: (0, react_jsx_runtime.jsx)(ResourcePageRouter, { match }) }) : (0, react_jsx_runtime.jsx)(NavAreaNotFound, {})
1952
+ children: match ? (0, react_jsx_runtime.jsx)(ResourcePageRouter, { match }) : (0, react_jsx_runtime.jsx)(NavAreaNotFound, {})
1583
1953
  });
1584
1954
  }
1585
1955
  //#endregion
1586
- Object.defineProperty(exports, "NavAreaNotFound", {
1956
+ Object.defineProperty(exports, "BUILTIN_LAYOUTS", {
1587
1957
  enumerable: true,
1588
1958
  get: function() {
1589
- return NavAreaNotFound;
1959
+ return BUILTIN_LAYOUTS;
1590
1960
  }
1591
1961
  });
1592
- Object.defineProperty(exports, "NavAreaPage", {
1962
+ Object.defineProperty(exports, "NavAreaNotFound", {
1593
1963
  enumerable: true,
1594
1964
  get: function() {
1595
- return NavAreaPage;
1965
+ return NavAreaNotFound;
1596
1966
  }
1597
1967
  });
1598
- Object.defineProperty(exports, "NavChrome", {
1968
+ Object.defineProperty(exports, "NavAreaPage", {
1599
1969
  enumerable: true,
1600
1970
  get: function() {
1601
- return NavChrome;
1971
+ return NavAreaPage;
1602
1972
  }
1603
1973
  });
1604
- Object.defineProperty(exports, "NavChromeBoundaryProvider", {
1974
+ Object.defineProperty(exports, "NavChromeMountedProvider", {
1605
1975
  enumerable: true,
1606
1976
  get: function() {
1607
- return NavChromeBoundaryProvider;
1977
+ return NavChromeMountedProvider;
1608
1978
  }
1609
1979
  });
1610
1980
  Object.defineProperty(exports, "PlannedBody", {
@@ -1631,12 +2001,6 @@ Object.defineProperty(exports, "RecordScreen", {
1631
2001
  return RecordScreen;
1632
2002
  }
1633
2003
  });
1634
- Object.defineProperty(exports, "RecordState", {
1635
- enumerable: true,
1636
- get: function() {
1637
- return RecordState;
1638
- }
1639
- });
1640
2004
  Object.defineProperty(exports, "ResourceListPage", {
1641
2005
  enumerable: true,
1642
2006
  get: function() {
@@ -1649,10 +2013,16 @@ Object.defineProperty(exports, "ResourcePageRouter", {
1649
2013
  return ResourcePageRouter;
1650
2014
  }
1651
2015
  });
1652
- Object.defineProperty(exports, "buildNavItems", {
2016
+ Object.defineProperty(exports, "SecondarySidebarLayout", {
2017
+ enumerable: true,
2018
+ get: function() {
2019
+ return SecondarySidebarLayout;
2020
+ }
2021
+ });
2022
+ Object.defineProperty(exports, "TabsLayout", {
1653
2023
  enumerable: true,
1654
2024
  get: function() {
1655
- return buildNavItems;
2025
+ return TabsLayout;
1656
2026
  }
1657
2027
  });
1658
2028
  Object.defineProperty(exports, "canonicalNavKey", {
@@ -1673,22 +2043,28 @@ Object.defineProperty(exports, "headerTrail", {
1673
2043
  return headerTrail;
1674
2044
  }
1675
2045
  });
2046
+ Object.defineProperty(exports, "isShowAvailable", {
2047
+ enumerable: true,
2048
+ get: function() {
2049
+ return isShowAvailable;
2050
+ }
2051
+ });
1676
2052
  Object.defineProperty(exports, "layoutSlot", {
1677
2053
  enumerable: true,
1678
2054
  get: function() {
1679
2055
  return layoutSlot;
1680
2056
  }
1681
2057
  });
1682
- Object.defineProperty(exports, "readRecentRecords", {
2058
+ Object.defineProperty(exports, "originTrail", {
1683
2059
  enumerable: true,
1684
2060
  get: function() {
1685
- return readRecentRecords;
2061
+ return originTrail;
1686
2062
  }
1687
2063
  });
1688
- Object.defineProperty(exports, "recordErrorState", {
2064
+ Object.defineProperty(exports, "readRecentRecords", {
1689
2065
  enumerable: true,
1690
2066
  get: function() {
1691
- return recordErrorState;
2067
+ return readRecentRecords;
1692
2068
  }
1693
2069
  });
1694
2070
  Object.defineProperty(exports, "recordTrail", {
@@ -1709,12 +2085,6 @@ Object.defineProperty(exports, "recordTrailRoute", {
1709
2085
  return recordTrailRoute;
1710
2086
  }
1711
2087
  });
1712
- Object.defineProperty(exports, "useFormControl", {
1713
- enumerable: true,
1714
- get: function() {
1715
- return useFormControl;
1716
- }
1717
- });
1718
2088
  Object.defineProperty(exports, "useHref", {
1719
2089
  enumerable: true,
1720
2090
  get: function() {
@@ -1739,12 +2109,6 @@ Object.defineProperty(exports, "useMatch", {
1739
2109
  return useMatch;
1740
2110
  }
1741
2111
  });
1742
- Object.defineProperty(exports, "useNavChromeBoundary", {
1743
- enumerable: true,
1744
- get: function() {
1745
- return useNavChromeBoundary;
1746
- }
1747
- });
1748
2112
  Object.defineProperty(exports, "useNavVisible", {
1749
2113
  enumerable: true,
1750
2114
  get: function() {
@@ -1775,6 +2139,24 @@ Object.defineProperty(exports, "useRecordVisit", {
1775
2139
  return useRecordVisit;
1776
2140
  }
1777
2141
  });
2142
+ Object.defineProperty(exports, "useReportUnresolvedLayouts", {
2143
+ enumerable: true,
2144
+ get: function() {
2145
+ return useReportUnresolvedLayouts;
2146
+ }
2147
+ });
2148
+ Object.defineProperty(exports, "useResourceDimensionOptions", {
2149
+ enumerable: true,
2150
+ get: function() {
2151
+ return useResourceDimensionOptions;
2152
+ }
2153
+ });
2154
+ Object.defineProperty(exports, "useResourceVisible", {
2155
+ enumerable: true,
2156
+ get: function() {
2157
+ return useResourceVisible;
2158
+ }
2159
+ });
1778
2160
  Object.defineProperty(exports, "useTrailContext", {
1779
2161
  enumerable: true,
1780
2162
  get: function() {
@@ -1782,4 +2164,4 @@ Object.defineProperty(exports, "useTrailContext", {
1782
2164
  }
1783
2165
  });
1784
2166
 
1785
- //# sourceMappingURL=resource-page-router-PXfMW9nh.cjs.map
2167
+ //# sourceMappingURL=resource-page-router-qEd2xb55.cjs.map