@burojs/ui-shadcn 0.7.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 (100) hide show
  1. package/dist/{bulk-summary-CrEij5vq.cjs → bulk-summary-2HLgz7Il.cjs} +31 -5
  2. package/dist/bulk-summary-2HLgz7Il.cjs.map +1 -0
  3. package/dist/{bulk-summary-BWSAS7k2.js → bulk-summary-D6A0ua21.js} +32 -6
  4. package/dist/bulk-summary-D6A0ua21.js.map +1 -0
  5. package/dist/{candidates-relation-picker-y5M6_oe4.cjs → candidates-relation-picker-C47mF260.cjs} +3 -3
  6. package/dist/{candidates-relation-picker-y5M6_oe4.cjs.map → candidates-relation-picker-C47mF260.cjs.map} +1 -1
  7. package/dist/{candidates-relation-picker-CS_JZ4Fd.js → candidates-relation-picker-CGXItMN0.js} +3 -3
  8. package/dist/{candidates-relation-picker-CS_JZ4Fd.js.map → candidates-relation-picker-CGXItMN0.js.map} +1 -1
  9. package/dist/{check-confirm-dialog-C-NHgMST.cjs → check-confirm-dialog-BT04Mieo.cjs} +13 -6
  10. package/dist/check-confirm-dialog-BT04Mieo.cjs.map +1 -0
  11. package/dist/{check-confirm-dialog-2j0gOd7x.js → check-confirm-dialog-CtiRzOAt.js} +14 -7
  12. package/dist/{check-confirm-dialog-2j0gOd7x.js.map → check-confirm-dialog-CtiRzOAt.js.map} +1 -1
  13. package/dist/{filter-builder-DFu0JP-1.cjs → filter-builder-ByGhxLf_.cjs} +127 -63
  14. package/dist/filter-builder-ByGhxLf_.cjs.map +1 -0
  15. package/dist/{filter-builder-DaWHUZuV.js → filter-builder-z3Axzf9Y.js} +114 -56
  16. package/dist/filter-builder-z3Axzf9Y.js.map +1 -0
  17. package/dist/{flow-runtime-BpmrIUb6.cjs → flow-runtime-BVFjMU5-.cjs} +6 -3
  18. package/dist/{flow-runtime-BpmrIUb6.cjs.map → flow-runtime-BVFjMU5-.cjs.map} +1 -1
  19. package/dist/{flow-runtime-DyqTmK3H.js → flow-runtime-DrUWyTS0.js} +6 -3
  20. package/dist/{flow-runtime-DyqTmK3H.js.map → flow-runtime-DrUWyTS0.js.map} +1 -1
  21. package/dist/{flow-screen-DCdli6Ha.js → flow-screen-3fk6J33y.js} +6 -4
  22. package/dist/flow-screen-3fk6J33y.js.map +1 -0
  23. package/dist/{flow-screen-Bcz9NF2V.cjs → flow-screen-6y5E_HT6.cjs} +5 -3
  24. package/dist/flow-screen-6y5E_HT6.cjs.map +1 -0
  25. package/dist/index.cjs +518 -107
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +187 -86
  28. package/dist/index.d.ts +187 -86
  29. package/dist/index.js +519 -108
  30. package/dist/index.js.map +1 -1
  31. package/dist/{inline-flow-host-3vw7LzzD.cjs → inline-flow-host-C4KmZIYE.cjs} +3 -3
  32. package/dist/{inline-flow-host-3vw7LzzD.cjs.map → inline-flow-host-C4KmZIYE.cjs.map} +1 -1
  33. package/dist/{inline-flow-host-C0rI9B7f.js → inline-flow-host-YnnvWjdU.js} +3 -3
  34. package/dist/{inline-flow-host-C0rI9B7f.js.map → inline-flow-host-YnnvWjdU.js.map} +1 -1
  35. package/dist/{lazy-relation-picker-dialog-Bt8lrEIu.cjs → lazy-relation-picker-dialog-BAKBRn3V.cjs} +2 -2
  36. package/dist/{lazy-relation-picker-dialog-Bt8lrEIu.cjs.map → lazy-relation-picker-dialog-BAKBRn3V.cjs.map} +1 -1
  37. package/dist/{lazy-relation-picker-dialog-CAScLPb2.js → lazy-relation-picker-dialog-DN4bvQfg.js} +2 -2
  38. package/dist/{lazy-relation-picker-dialog-CAScLPb2.js.map → lazy-relation-picker-dialog-DN4bvQfg.js.map} +1 -1
  39. package/dist/{page-flow-route-BHUEpn0I.js → page-flow-route-CtEfqAvU.js} +5 -6
  40. package/dist/page-flow-route-CtEfqAvU.js.map +1 -0
  41. package/dist/{page-flow-route-DS8IVTVH.cjs → page-flow-route-DEjAxHe3.cjs} +6 -7
  42. package/dist/page-flow-route-DEjAxHe3.cjs.map +1 -0
  43. package/dist/{place-node-CfzQvh4Y.js → place-node-BdxT-30h.js} +149 -108
  44. package/dist/place-node-BdxT-30h.js.map +1 -0
  45. package/dist/{place-node-CNb3w-c7.cjs → place-node-Bhl8B3fF.cjs} +163 -134
  46. package/dist/place-node-Bhl8B3fF.cjs.map +1 -0
  47. package/dist/{related-list-cards-CelMxl4q.cjs → related-list-cards-Bc_vfCE_.cjs} +3 -3
  48. package/dist/{related-list-cards-CelMxl4q.cjs.map → related-list-cards-Bc_vfCE_.cjs.map} +1 -1
  49. package/dist/{related-list-cards-BIqqY69Y.js → related-list-cards-BvkD5OcC.js} +3 -3
  50. package/dist/{related-list-cards-BIqqY69Y.js.map → related-list-cards-BvkD5OcC.js.map} +1 -1
  51. package/dist/related-list-timeline-DCrwN9oO.js +167 -0
  52. package/dist/related-list-timeline-DCrwN9oO.js.map +1 -0
  53. package/dist/related-list-timeline-k0DtnxTs.cjs +167 -0
  54. package/dist/related-list-timeline-k0DtnxTs.cjs.map +1 -0
  55. package/dist/{related-rows-MPnLCmPF.cjs → related-rows-BW9Jr07T.cjs} +3 -3
  56. package/dist/{related-rows-MPnLCmPF.cjs.map → related-rows-BW9Jr07T.cjs.map} +1 -1
  57. package/dist/{related-rows--uP2iKQC.js → related-rows-CPE-9FFr.js} +3 -3
  58. package/dist/{related-rows--uP2iKQC.js.map → related-rows-CPE-9FFr.js.map} +1 -1
  59. package/dist/{relation-many-picker-BJhaEqxz.js → relation-many-picker-BlrGRwMV.js} +10 -5
  60. package/dist/relation-many-picker-BlrGRwMV.js.map +1 -0
  61. package/dist/{relation-many-picker-DzuGJpEl.cjs → relation-many-picker-Br-zBHxT.cjs} +10 -5
  62. package/dist/relation-many-picker-Br-zBHxT.cjs.map +1 -0
  63. package/dist/{relation-picker-DaIMzf2H.cjs → relation-picker-ADjxI_TI.cjs} +11 -6
  64. package/dist/relation-picker-ADjxI_TI.cjs.map +1 -0
  65. package/dist/{relation-picker-dialog-DoEY8EkH.js → relation-picker-dialog-CyKliBkN.js} +2 -2
  66. package/dist/{relation-picker-dialog-DoEY8EkH.js.map → relation-picker-dialog-CyKliBkN.js.map} +1 -1
  67. package/dist/{relation-picker-dialog-9Vg5vvR1.cjs → relation-picker-dialog-DimVQF9Y.cjs} +2 -2
  68. package/dist/{relation-picker-dialog-9Vg5vvR1.cjs.map → relation-picker-dialog-DimVQF9Y.cjs.map} +1 -1
  69. package/dist/{relation-picker-D-tBBZW_.js → relation-picker-x7P5HKie.js} +11 -6
  70. package/dist/relation-picker-x7P5HKie.js.map +1 -0
  71. package/dist/{resource-page-router-Diw6S6TK.js → resource-page-router-BRpUnhay.js} +144 -17
  72. package/dist/resource-page-router-BRpUnhay.js.map +1 -0
  73. package/dist/{resource-page-router-C_kGW2o_.cjs → resource-page-router-qEd2xb55.cjs} +158 -19
  74. package/dist/resource-page-router-qEd2xb55.cjs.map +1 -0
  75. package/dist/use-record-subtitle-bfwIoUme.cjs +70 -0
  76. package/dist/use-record-subtitle-bfwIoUme.cjs.map +1 -0
  77. package/dist/use-record-subtitle-gIaCGgbI.js +53 -0
  78. package/dist/use-record-subtitle-gIaCGgbI.js.map +1 -0
  79. package/package.json +9 -9
  80. package/dist/bulk-summary-BWSAS7k2.js.map +0 -1
  81. package/dist/bulk-summary-CrEij5vq.cjs.map +0 -1
  82. package/dist/check-confirm-dialog-C-NHgMST.cjs.map +0 -1
  83. package/dist/filter-builder-DFu0JP-1.cjs.map +0 -1
  84. package/dist/filter-builder-DaWHUZuV.js.map +0 -1
  85. package/dist/flow-screen-Bcz9NF2V.cjs.map +0 -1
  86. package/dist/flow-screen-DCdli6Ha.js.map +0 -1
  87. package/dist/page-flow-route-BHUEpn0I.js.map +0 -1
  88. package/dist/page-flow-route-DS8IVTVH.cjs.map +0 -1
  89. package/dist/place-node-CNb3w-c7.cjs.map +0 -1
  90. package/dist/place-node-CfzQvh4Y.js.map +0 -1
  91. package/dist/related-list-timeline-CRh7xwLD.js +0 -141
  92. package/dist/related-list-timeline-CRh7xwLD.js.map +0 -1
  93. package/dist/related-list-timeline-DsLdi8sv.cjs +0 -141
  94. package/dist/related-list-timeline-DsLdi8sv.cjs.map +0 -1
  95. package/dist/relation-many-picker-BJhaEqxz.js.map +0 -1
  96. package/dist/relation-many-picker-DzuGJpEl.cjs.map +0 -1
  97. package/dist/relation-picker-D-tBBZW_.js.map +0 -1
  98. package/dist/relation-picker-DaIMzf2H.cjs.map +0 -1
  99. package/dist/resource-page-router-C_kGW2o_.cjs.map +0 -1
  100. package/dist/resource-page-router-Diw6S6TK.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,19 +1,20 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_use_theme = require("./use-theme-DFlpXils.cjs");
3
3
  const require_toaster = require("./toaster-BbByOytP.cjs");
4
- const require_check_confirm_dialog = require("./check-confirm-dialog-C-NHgMST.cjs");
4
+ const require_check_confirm_dialog = require("./check-confirm-dialog-BT04Mieo.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
8
  const require_relation_create = require("./relation-create-DDEYcKfw.cjs");
9
9
  const require_skeleton = require("./skeleton-_1gP7wan.cjs");
10
- const require_place_node = require("./place-node-CNb3w-c7.cjs");
10
+ const require_place_node = require("./place-node-Bhl8B3fF.cjs");
11
11
  const require_layout_theme_storage_key = require("./layout/theme-storage-key.cjs");
12
- const require_filter_builder = require("./filter-builder-DFu0JP-1.cjs");
13
- const require_resource_page_router = require("./resource-page-router-C_kGW2o_.cjs");
12
+ const require_filter_builder = require("./filter-builder-ByGhxLf_.cjs");
13
+ const require_resource_page_router = require("./resource-page-router-qEd2xb55.cjs");
14
14
  const require_label = require("./label-w6JYf2cF.cjs");
15
- const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-Bt8lrEIu.cjs");
16
- const require_relation_picker = require("./relation-picker-DaIMzf2H.cjs");
15
+ const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BAKBRn3V.cjs");
16
+ const require_use_record_subtitle = require("./use-record-subtitle-bfwIoUme.cjs");
17
+ const require_relation_picker = require("./relation-picker-ADjxI_TI.cjs");
17
18
  const require_use_dialog_filter_state = require("./use-dialog-filter-state-tNvqAAjh.cjs");
18
19
  let _burojs_react_web = require("@burojs/react/web");
19
20
  let _burojs_core = require("@burojs/core");
@@ -1981,6 +1982,10 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1981
1982
  const t = (0, _burojs_react.useT)();
1982
1983
  const RouterLink = require_toaster.useLinkComponent();
1983
1984
  const navIcon = useNavIcon();
1985
+ const intent = (0, _burojs_react.useOriginIntent)();
1986
+ const jump = (entry) => () => {
1987
+ if (entry.href !== void 0) intent(entry.href, "jump");
1988
+ };
1984
1989
  const ownOr = (own, name) => own !== void 0 ? own : navIcon(name);
1985
1990
  const groupAsSection = (key) => app.registry.sections.get(key) ?? app.registry.groups.get(key);
1986
1991
  const sectionIcon = (key, name) => {
@@ -2007,6 +2012,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
2007
2012
  href: entry.href ?? "",
2008
2013
  "aria-current": entry.active ? "page" : void 0,
2009
2014
  "data-testid": entryTestId(entry),
2015
+ onClick: jump(entry),
2010
2016
  children: [icon != null && (0, react_jsx_runtime.jsx)("span", {
2011
2017
  className: "inline-flex h-4 w-4 items-center justify-center",
2012
2018
  "aria-hidden": "true",
@@ -2022,6 +2028,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
2022
2028
  href: entry.href ?? "",
2023
2029
  "aria-current": entry.active ? "page" : void 0,
2024
2030
  "data-testid": entryTestId(entry),
2031
+ onClick: jump(entry),
2025
2032
  children: (0, react_jsx_runtime.jsx)("span", { children: entry.label })
2026
2033
  })
2027
2034
  }) }, entry.key);
@@ -2135,11 +2142,17 @@ function Breadcrumbs(input) {
2135
2142
  const t = (0, _burojs_react.useOptionalT)();
2136
2143
  const RouterLink = require_toaster.useLinkComponent();
2137
2144
  const caps = (0, _burojs_react.useI18nCaps)(def?.name);
2145
+ const intent = (0, _burojs_react.useOriginIntent)();
2146
+ const onJump = (seg) => {
2147
+ const href = seg.href;
2148
+ return seg.jump === true && href !== void 0 ? () => intent(href, "jump") : void 0;
2149
+ };
2138
2150
  const trailScopes = (0, _burojs_react.useDocTrailScopes)(def?.name);
2139
2151
  const leading = (name) => leadingSegments?.map((seg, i) => (0, react_jsx_runtime.jsxs)("span", {
2140
2152
  className: "flex min-w-0 items-center gap-1",
2141
2153
  children: [seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2142
2154
  href: seg.href,
2155
+ onClick: onJump(seg),
2143
2156
  "data-testid": `${tid.navBreadcrumb(name)}:lead:${i}`,
2144
2157
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
2145
2158
  title: seg.label,
@@ -2174,9 +2187,34 @@ function Breadcrumbs(input) {
2174
2187
  ]
2175
2188
  });
2176
2189
  if (!def) return null;
2177
- const { recordId, pageLabel, middleSegments } = props;
2190
+ const { recordId, pageLabel, middleSegments, rootSegments } = props;
2178
2191
  const resourceKey = require_resource_page_router.canonicalResourceKey(def);
2179
- const listHref = (0, _burojs_core.hrefFor)(app.registry, resourceKey);
2192
+ if (rootSegments !== void 0 && rootSegments.length > 0) return (0, react_jsx_runtime.jsxs)("nav", {
2193
+ className: navClass,
2194
+ "aria-label": ariaLabel,
2195
+ "data-testid": testId,
2196
+ children: [
2197
+ rootSegments.map((seg, i) => (0, react_jsx_runtime.jsxs)("span", {
2198
+ className: "flex min-w-0 items-center gap-1",
2199
+ children: [i > 0 && (0, react_jsx_runtime.jsx)(Chevron, {}), seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2200
+ href: seg.href,
2201
+ onClick: onJump(seg),
2202
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2203
+ className: require_use_theme.cn(LINK_CLASS, "truncate"),
2204
+ title: seg.label,
2205
+ children: seg.label
2206
+ }) : (0, react_jsx_runtime.jsx)("span", {
2207
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2208
+ className: "truncate",
2209
+ title: seg.label,
2210
+ children: seg.label
2211
+ })]
2212
+ }, `root:${i}:${seg.label}`)),
2213
+ pageLabel && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(Chevron, {}), current(tid.navBreadcrumb(resourceKey, recordId), pageLabel)] }),
2214
+ help
2215
+ ]
2216
+ });
2217
+ const listHref = props.resourceHref ?? (0, _burojs_core.hrefFor)(app.registry, resourceKey);
2180
2218
  const resourceLabel = (0, _burojs_core.resolveResourceLabel)(caps, resourceKey, "plural", def);
2181
2219
  const resourceIsCurrent = !pageLabel && !(middleSegments && middleSegments.length > 0);
2182
2220
  return (0, react_jsx_runtime.jsxs)("nav", {
@@ -2201,6 +2239,7 @@ function Breadcrumbs(input) {
2201
2239
  className: "flex min-w-0 items-center gap-1",
2202
2240
  children: [(0, react_jsx_runtime.jsx)(Chevron, {}), seg.href ? (0, react_jsx_runtime.jsx)(RouterLink, {
2203
2241
  href: seg.href,
2242
+ onClick: onJump(seg),
2204
2243
  "data-testid": `${tid.navBreadcrumb(resourceKey)}:mid:${i}`,
2205
2244
  className: require_use_theme.cn(LINK_CLASS, "truncate"),
2206
2245
  title: seg.label,
@@ -2218,6 +2257,12 @@ function Breadcrumbs(input) {
2218
2257
  }
2219
2258
  //#endregion
2220
2259
  //#region src/layout/record-breadcrumbs.tsx
2260
+ function viewOrigin(ctx, trail, resource) {
2261
+ if (trail === void 0 || trail.resource === void 0 || trail.segments.length > 0) return void 0;
2262
+ const target = ctx.registry.get(trail.resource)?.routesTo?.show;
2263
+ if (target === void 0 || ctx.registry.get(target) !== ctx.registry.get(resource)) return void 0;
2264
+ return trail.resource;
2265
+ }
2221
2266
  function RecordBreadcrumbs() {
2222
2267
  const ctx = require_resource_page_router.useTrailContext();
2223
2268
  const match = require_resource_page_router.useMatch();
@@ -2225,9 +2270,17 @@ function RecordBreadcrumbs() {
2225
2270
  const route = require_resource_page_router.recordTrailRoute(ctx.registry, match);
2226
2271
  const published = require_resource_page_router.usePublishedRecordTrail(route === null ? "" : require_resource_page_router.recordTrailKey(route.resource, route.id, route.flow === void 0 ? route.action : `flow:${route.flow}`));
2227
2272
  const idTitle = (0, _burojs_react.useRecordTitle)(route?.resource, route?.id);
2273
+ (0, _burojs_react.usePublishOriginTitle)(published?.title || void 0);
2274
+ const origin = (0, _burojs_react.useNavigationOrigin)();
2275
+ const rooted = origin === null ? void 0 : require_resource_page_router.originTrail(ctx, origin);
2276
+ const view = route === null ? void 0 : viewOrigin(ctx, rooted, route.resource);
2277
+ const viewScopes = (0, _burojs_react.useDocTrailScopes)(view);
2278
+ const ownScopes = (0, _burojs_react.useDocTrailScopes)(view === void 0 ? void 0 : route?.resource);
2279
+ const docScopes = view === void 0 ? {} : { docScopes: [...new Set([...viewScopes, ...ownScopes])] };
2228
2280
  if (route === null || match === null) return null;
2229
2281
  const { resource, id, groupChain } = route;
2230
2282
  const title = published?.title ?? idTitle;
2283
+ const withOrigin = rooted === void 0 ? {} : { origin: rooted };
2231
2284
  if (route.flow !== void 0) {
2232
2285
  if ((0, _burojs_core.effectiveFlow)(snapshot, match.ref, route.flow) === void 0) return null;
2233
2286
  const flowLabel = published?.flowLabel;
@@ -2237,8 +2290,10 @@ function RecordBreadcrumbs() {
2237
2290
  action: "show",
2238
2291
  id,
2239
2292
  title: idTitle,
2240
- groupChain
2293
+ groupChain,
2294
+ ...withOrigin
2241
2295
  }),
2296
+ ...docScopes,
2242
2297
  "data-testid": "record-breadcrumbs"
2243
2298
  });
2244
2299
  return (0, react_jsx_runtime.jsx)(Breadcrumbs, {
@@ -2247,8 +2302,10 @@ function RecordBreadcrumbs() {
2247
2302
  action: "edit",
2248
2303
  id,
2249
2304
  title,
2250
- groupChain
2305
+ groupChain,
2306
+ ...withOrigin
2251
2307
  }),
2308
+ ...docScopes,
2252
2309
  pageLabel: flowLabel,
2253
2310
  "data-testid": "record-breadcrumbs"
2254
2311
  });
@@ -2259,8 +2316,10 @@ function RecordBreadcrumbs() {
2259
2316
  action: route.action,
2260
2317
  id,
2261
2318
  title,
2262
- groupChain
2319
+ groupChain,
2320
+ ...withOrigin
2263
2321
  }),
2322
+ ...docScopes,
2264
2323
  "data-testid": "record-breadcrumbs"
2265
2324
  });
2266
2325
  }
@@ -2605,7 +2664,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2605
2664
  }, [app, visibilityCtx]);
2606
2665
  const goTo = (href) => {
2607
2666
  onSelect?.();
2608
- navigate(href);
2667
+ navigate(href, { origin: "jump" });
2609
2668
  };
2610
2669
  const resourceLabel = (def) => (0, _burojs_core.resolveResourceLabel)(caps, require_resource_page_router.canonicalResourceKey(def), "plural", def);
2611
2670
  const pageLabel = (def) => (0, _burojs_core.resolveNavLabel)(caps, `pages.${require_resource_page_router.canonicalNavKey(def)}`, (0, _burojs_core.declaredText)("chrome", def, "label"));
@@ -2757,7 +2816,7 @@ function entryHref(registry, entry, isResourceVisible) {
2757
2816
  const def = registry.get(entry.canonicalRef);
2758
2817
  if (def === void 0) return void 0;
2759
2818
  if (!isResourceVisible(def)) return void 0;
2760
- for (const action of ["show", "edit"]) if (require_place_node.recordRouteAvailable(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2819
+ for (const action of ["show", "edit"]) if ((0, _burojs_react.recordRouteAvailable)(registry, entry.canonicalRef, action)) return (0, _burojs_core.hrefFor)(registry, entry.canonicalRef, {
2761
2820
  action,
2762
2821
  id: entry.id
2763
2822
  });
@@ -2809,7 +2868,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2809
2868
  const goTo = (href, entry) => {
2810
2869
  onSelect?.();
2811
2870
  if (href === null) quick.show(entry.canonicalRef, entry.id);
2812
- else navigate(href);
2871
+ else navigate(href, { origin: "jump" });
2813
2872
  };
2814
2873
  return (0, react_jsx_runtime.jsxs)(react.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2815
2874
  heading: resolvedHeading,
@@ -2872,7 +2931,7 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2872
2931
  const liveQuery = (0, cmdk.useCommandState)((state) => state.search) ?? "";
2873
2932
  const debouncedQuery = (0, _burojs_react.useDebouncedValue)(liveQuery, debounceMs);
2874
2933
  const searchableResources = (0, react.useMemo)(() => {
2875
- return app.registry.list().filter((r) => require_place_node.isShowAvailable(app.registry, require_resource_page_router.canonicalResourceKey(r)) || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "show")).filter(isResourceVisible).map((def) => {
2934
+ return app.registry.list().filter((r) => require_resource_page_router.isShowAvailable(app.registry, require_resource_page_router.canonicalResourceKey(r)) || opensInQuick(app.registry, require_resource_page_router.canonicalResourceKey(r), "show")).filter(isResourceVisible).map((def) => {
2876
2935
  const displayField = resolveDisplayField(def);
2877
2936
  return displayField ? {
2878
2937
  def,
@@ -2884,7 +2943,7 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2884
2943
  const goTo = (href, resource, id) => {
2885
2944
  onSelect?.();
2886
2945
  if (href === null) quick.show(resource, id);
2887
- else navigate(href);
2946
+ else navigate(href, { origin: "jump" });
2888
2947
  };
2889
2948
  return (0, react_jsx_runtime.jsx)(require_relation_create.CommandGroup, {
2890
2949
  heading: resolvedHeading,
@@ -2922,6 +2981,7 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2922
2981
  enabled: shouldFetch
2923
2982
  });
2924
2983
  const report = useCommandPaletteResults(`records:${resource}`);
2984
+ const rowSubtitle = require_use_record_subtitle.useRowSubtitle(resource);
2925
2985
  const rows = !shouldFetch || q.isLoading || q.isError ? [] : q.data?.data ?? [];
2926
2986
  (0, react.useEffect)(() => {
2927
2987
  report(rows.length);
@@ -2936,16 +2996,25 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2936
2996
  if (!id) return null;
2937
2997
  const display = titleVisible ? row[displayField] : void 0;
2938
2998
  const labelText = typeof display === "string" && display.length > 0 ? display : id;
2939
- const href = recordHref ? recordHref(resource, id) : require_place_node.isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id) : null;
2999
+ const subtitle = rowSubtitle(row) ?? null;
3000
+ const href = recordHref ? recordHref(resource, id) : require_resource_page_router.isShowAvailable(registry, resource) ? (0, _burojs_core.resourceShowHref)(registry, def, resource, id) : null;
2940
3001
  return (0, react_jsx_runtime.jsxs)(require_relation_create.CommandItem, {
2941
3002
  value: `record:${resource}:${id}:${labelText}`,
2942
3003
  forceMount: true,
2943
3004
  onSelect: () => goTo(href, resource, id),
2944
3005
  "data-testid": getTestId?.("records-record", `${resource}:${id}`),
2945
- children: [(0, react_jsx_runtime.jsxs)("span", {
2946
- className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
2947
- children: [resourceLabel, ":"]
2948
- }), labelText]
3006
+ children: [
3007
+ (0, react_jsx_runtime.jsxs)("span", {
3008
+ className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
3009
+ children: [resourceLabel, ":"]
3010
+ }),
3011
+ labelText,
3012
+ subtitle === null ? null : (0, react_jsx_runtime.jsx)("span", {
3013
+ "data-buro-region": "record-subtitle",
3014
+ className: "ml-auto truncate pl-2 text-xs text-muted-foreground group-data-[selected=true]:text-accent-foreground",
3015
+ children: subtitle
3016
+ })
3017
+ ]
2949
3018
  }, `record:${resource}:${id}`);
2950
3019
  }) });
2951
3020
  }
@@ -3093,7 +3162,7 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3093
3162
  ]);
3094
3163
  if (visibleResources.length === 0) return null;
3095
3164
  const goTo = (href) => {
3096
- navigate(href);
3165
+ navigate(href, { origin: "jump" });
3097
3166
  onSelect?.();
3098
3167
  };
3099
3168
  const createIn = (def, href) => {
@@ -3441,7 +3510,7 @@ const NONE = "__none__";
3441
3510
  function isEmpty$1(value) {
3442
3511
  return value === null || value === void 0 || value === "";
3443
3512
  }
3444
- function EnumChoiceGroup({ control, options, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3513
+ function EnumChoiceGroup({ control, options, current, settling, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3445
3514
  const t = (0, _burojs_react.useOptionalT)();
3446
3515
  const generatedName = react.useId();
3447
3516
  const groupName = name ?? generatedName;
@@ -3456,16 +3525,25 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3456
3525
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3457
3526
  };
3458
3527
  if (control === "segmented") {
3459
- const segment = (key, label, active, select) => (0, react_jsx_runtime.jsx)("button", {
3528
+ const segmentLabel = (option) => (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [option.icon ? (0, react_jsx_runtime.jsx)("span", {
3529
+ "data-testid": `${testid}:option:${option.value}:icon`,
3530
+ className: "contents",
3531
+ children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3532
+ name: option.icon,
3533
+ className: "size-3.5 shrink-0"
3534
+ })
3535
+ }) : null, option.label] });
3536
+ const segment = (key, label, active, select, currentItem = false) => (0, react_jsx_runtime.jsx)("button", {
3460
3537
  type: "button",
3461
3538
  "aria-pressed": active,
3462
3539
  "data-state": active ? "active" : "inactive",
3463
- "data-testid": `${testid}:option:${key}`,
3464
- disabled,
3540
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3541
+ ...currentItem ? { "data-current": "" } : {},
3542
+ disabled: disabled || currentItem,
3465
3543
  onClick: select,
3466
3544
  className: require_use_theme.cn("inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all", "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-xs", "disabled:pointer-events-none disabled:opacity-50", "focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring"),
3467
3545
  children: label
3468
- }, key);
3546
+ }, currentItem ? `current:${key}` : key);
3469
3547
  return (0, react_jsx_runtime.jsxs)("div", {
3470
3548
  role: "group",
3471
3549
  id,
@@ -3473,22 +3551,24 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3473
3551
  "data-testid": testid,
3474
3552
  className: require_use_theme.cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3475
3553
  ...ariaProps,
3476
- children: [required ? null : segment(NONE, noneLabel, empty, () => pick(void 0)), options.map((option) => segment(option.value, (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [option.icon ? (0, react_jsx_runtime.jsx)("span", {
3477
- "data-testid": `${testid}:option:${option.value}:icon`,
3478
- className: "contents",
3479
- children: (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3480
- name: option.icon,
3481
- className: "size-3.5 shrink-0"
3482
- })
3483
- }) : null, option.label] }), value === option.value, () => pick(option.value)))]
3554
+ children: [
3555
+ current === void 0 ? null : segment(current.value, segmentLabel(current), true, () => void 0, true),
3556
+ required || settling !== void 0 ? null : segment(NONE, noneLabel, empty, () => pick(void 0)),
3557
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3558
+ status: settling,
3559
+ testid
3560
+ }),
3561
+ options.map((option) => segment(option.value, segmentLabel(option), value === option.value, () => pick(option.value)))
3562
+ ]
3484
3563
  });
3485
3564
  }
3486
3565
  const cards = control === "cards";
3487
- const choice = (key, option, label, checked, select) => {
3488
- const inputId = `${id ?? groupName}:${key}`;
3566
+ const choice = (key, option, label, checked, select, currentItem = false) => {
3567
+ const inputId = `${id ?? groupName}:${currentItem ? "current:" : ""}${key}`;
3568
+ const inert = disabled || currentItem;
3489
3569
  return (0, react_jsx_runtime.jsxs)("label", {
3490
3570
  htmlFor: inputId,
3491
- className: require_use_theme.cn("flex items-start gap-2.5", cards && "cursor-pointer rounded-lg border px-3 py-2.5 transition-colors hover:bg-accent/50 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring", cards && (checked ? "border-primary" : "border-input"), disabled && "cursor-not-allowed opacity-60"),
3571
+ className: require_use_theme.cn("flex items-start gap-2.5", cards && "cursor-pointer rounded-lg border px-3 py-2.5 transition-colors hover:bg-accent/50 has-[:focus-visible]:ring-2 has-[:focus-visible]:ring-ring", cards && (checked ? "border-primary" : "border-input"), inert && "cursor-not-allowed opacity-60"),
3492
3572
  children: [(0, react_jsx_runtime.jsx)("input", {
3493
3573
  type: "radio",
3494
3574
  id: inputId,
@@ -3496,9 +3576,10 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3496
3576
  value: key,
3497
3577
  checked,
3498
3578
  onChange: select,
3499
- disabled,
3579
+ disabled: inert,
3500
3580
  ...ariaProps,
3501
- "data-testid": `${testid}:option:${key}`,
3581
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3582
+ ...currentItem ? { "data-current": "" } : {},
3502
3583
  className: require_use_theme.cn("h-4 w-4 shrink-0 accent-primary", cards ? "mt-0.5" : "mt-1")
3503
3584
  }), (0, react_jsx_runtime.jsxs)("span", {
3504
3585
  className: "flex min-w-0 flex-col gap-0.5",
@@ -3518,7 +3599,7 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3518
3599
  children: option.summary
3519
3600
  })]
3520
3601
  })]
3521
- }, key);
3602
+ }, currentItem ? `current:${key}` : key);
3522
3603
  };
3523
3604
  return (0, react_jsx_runtime.jsxs)("div", {
3524
3605
  role: "radiogroup",
@@ -3527,7 +3608,15 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3527
3608
  "data-testid": testid,
3528
3609
  "aria-required": required,
3529
3610
  className: require_use_theme.cn("flex flex-col", cards ? "gap-2" : "gap-1.5", className),
3530
- children: [required ? null : choice(NONE, void 0, noneLabel, empty, () => pick(void 0)), options.map((option) => choice(option.value, option, option.label, value === option.value, () => pick(option.value)))]
3611
+ children: [
3612
+ current === void 0 ? null : choice(current.value, current, current.label, true, () => void 0, true),
3613
+ required || settling !== void 0 ? null : choice(NONE, void 0, noneLabel, empty, () => pick(void 0)),
3614
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3615
+ status: settling,
3616
+ testid
3617
+ }),
3618
+ options.map((option) => choice(option.value, option, option.label, value === option.value, () => pick(option.value)))
3619
+ ]
3531
3620
  });
3532
3621
  }
3533
3622
  //#endregion
@@ -3536,7 +3625,7 @@ const ENUM_PICKER_CLEAR_SENTINEL = "__buro_clear__";
3536
3625
  function withSummary(summary) {
3537
3626
  return summary === void 0 ? {} : { summary };
3538
3627
  }
3539
- function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All" }) {
3628
+ function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All", use }) {
3540
3629
  const enumName = (0, _burojs_core_internal.enumBindingKey)(enumInput) ?? "";
3541
3630
  const app = (0, _burojs_react.useApp)();
3542
3631
  const t = (0, _burojs_react.useOptionalT)();
@@ -3544,6 +3633,11 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3544
3633
  const caps = (0, _burojs_react.useI18nCaps)();
3545
3634
  const ns = def?.i18nNamespace ?? enumName;
3546
3635
  const { values, isLoading, error } = (0, _burojs_react.useEnumValues)(enumName);
3636
+ const available = (0, _burojs_react.useAvailableEnumValues)({
3637
+ values: isLoading || values === void 0 ? "pending" : values,
3638
+ ...def === void 0 ? {} : { enum: def },
3639
+ ...use === void 0 ? {} : { use }
3640
+ });
3547
3641
  const tid = testid ?? `enum-picker:${enumName}`;
3548
3642
  if (!def) return (0, react_jsx_runtime.jsxs)("span", {
3549
3643
  "data-testid": `${tid}:unregistered`,
@@ -3585,9 +3679,22 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3585
3679
  });
3586
3680
  const labelOf = (entry) => (0, _burojs_core.resolveEnumLabel)(caps, ns, entry.value, (0, _burojs_core.enumValueText)(def, entry.value) ?? entry.label);
3587
3681
  const summaryOf = (entry) => (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${entry.value}`)?.summary || void 0;
3682
+ const settling = available.status === "ready" ? void 0 : available.status;
3683
+ const offered = settling === void 0 ? available.values : [];
3684
+ const known = value == null ? void 0 : values.find((entry) => entry.value === value);
3685
+ const current = value == null || value === "" || offered.some((entry) => entry.value === value) ? void 0 : known === void 0 ? {
3686
+ value,
3687
+ label: require_place_node.unknownEnumValueLabel(caps, def, ns, value).label
3688
+ } : {
3689
+ value,
3690
+ label: labelOf(known),
3691
+ ...known.icon === void 0 ? {} : { icon: known.icon }
3692
+ };
3588
3693
  if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3589
3694
  control,
3590
- options: values.map((entry) => ({
3695
+ ...current === void 0 ? {} : { current },
3696
+ ...settling === void 0 ? {} : { settling },
3697
+ options: offered.map((entry) => ({
3591
3698
  value: entry.value,
3592
3699
  label: labelOf(entry),
3593
3700
  ...entry.icon === void 0 ? {} : { icon: entry.icon },
@@ -3624,28 +3731,43 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3624
3731
  name,
3625
3732
  id,
3626
3733
  "aria-required": required,
3734
+ "aria-busy": settling === "pending" || void 0,
3627
3735
  "aria-invalid": ariaInvalid || void 0,
3628
3736
  "aria-describedby": ariaDescribedBy,
3629
3737
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3630
3738
  className,
3631
3739
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3632
- }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [clearable && (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3633
- value: "__buro_clear__",
3634
- "data-testid": `${tid}:option:__clear__`,
3635
- children: clearLabel
3636
- }), values.map((entry) => {
3637
- const optionLabel = labelOf(entry);
3638
- const optionDoc = summaryOf(entry);
3639
- return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3640
- value: entry.value,
3641
- "data-testid": `${tid}:option:${entry.value}`,
3642
- description: optionDoc === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3643
- "data-testid": `${tid}:option:${entry.value}:doc`,
3644
- children: optionDoc
3645
- }),
3646
- children: optionLabel
3647
- }, entry.value);
3648
- })] })]
3740
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [
3741
+ clearable && (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3742
+ value: "__buro_clear__",
3743
+ "data-testid": `${tid}:option:__clear__`,
3744
+ children: clearLabel
3745
+ }),
3746
+ current === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3747
+ value: current.value,
3748
+ disabled: true,
3749
+ "data-current": "",
3750
+ "data-testid": `${tid}:current`,
3751
+ children: current.label
3752
+ }),
3753
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
3754
+ status: settling,
3755
+ testid: tid
3756
+ }),
3757
+ offered.map((entry) => {
3758
+ const optionLabel = labelOf(entry);
3759
+ const optionDoc = summaryOf(entry);
3760
+ return (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3761
+ value: entry.value,
3762
+ "data-testid": `${tid}:option:${entry.value}`,
3763
+ description: optionDoc === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3764
+ "data-testid": `${tid}:option:${entry.value}:doc`,
3765
+ children: optionDoc
3766
+ }),
3767
+ children: optionLabel
3768
+ }, entry.value);
3769
+ })
3770
+ ] })]
3649
3771
  });
3650
3772
  }
3651
3773
  //#endregion
@@ -3695,41 +3817,63 @@ function BooleanInput({ name, id, value, onChange, testid, disabled, required, a
3695
3817
  }
3696
3818
  //#endregion
3697
3819
  //#region src/fields/date.tsx
3698
- function DateDisplay({ value, text }) {
3820
+ function DateDisplay(props) {
3699
3821
  return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3700
- value,
3701
- text,
3702
- format: require_filter_builder.formatDate
3822
+ kind: "date",
3823
+ ...props
3703
3824
  });
3704
3825
  }
3705
- function DateTimeDisplay({ value, text }) {
3826
+ function DateTimeDisplay(props) {
3706
3827
  return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3707
- value,
3708
- text,
3709
- format: require_filter_builder.formatDateTime
3828
+ kind: "dateTime",
3829
+ ...props
3830
+ });
3831
+ }
3832
+ function TimeDisplay(props) {
3833
+ return (0, react_jsx_runtime.jsx)(TemporalDisplay, {
3834
+ kind: "time",
3835
+ ...props
3710
3836
  });
3711
3837
  }
3712
- function TemporalDisplay({ value, text, format }) {
3838
+ function storedText(value) {
3839
+ return value instanceof Date && !Number.isNaN(value.getTime()) ? value.toISOString() : String(value);
3840
+ }
3841
+ function TemporalDisplay({ kind, value, text, field, record }) {
3713
3842
  const locale = (0, _burojs_react.useOptionalLocale)();
3843
+ const zone = require_filter_builder.useFieldTimeZone(field?.zone, record);
3844
+ const viewer = (0, _burojs_react.useTimeZone)();
3714
3845
  if (value == null || value === "") return (0, react_jsx_runtime.jsx)("span", {
3715
3846
  className: "text-muted-foreground",
3716
3847
  children: "—"
3717
3848
  });
3718
- if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", { children: text });
3719
- const d = new Date(String(value));
3720
- if (Number.isNaN(d.getTime())) return (0, react_jsx_runtime.jsx)("span", { children: String(value) });
3849
+ if (zone.status === "pending" || viewer.status === "pending") return (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
3850
+ className: "h-4 w-24",
3851
+ "aria-busy": "true"
3852
+ });
3853
+ const raw = storedText(value);
3854
+ const formatted = (0, _burojs_core.formatTimeValue)(kind, raw, {
3855
+ zone: zone.zone,
3856
+ viewerZone: viewer.zone,
3857
+ locale: require_filter_builder.localeTag(locale),
3858
+ params: {
3859
+ ...kind === "time" && field?.ui?.seconds === true ? { timeStyle: "medium" } : {},
3860
+ ...require_filter_builder.dateDisplayParams(field?.ui)
3861
+ }
3862
+ });
3863
+ if (text !== void 0) return (0, react_jsx_runtime.jsx)("span", {
3864
+ title: formatted,
3865
+ children: text
3866
+ });
3867
+ if (formatted === void 0) return (0, react_jsx_runtime.jsx)("span", { children: raw });
3721
3868
  return (0, react_jsx_runtime.jsx)("span", {
3722
3869
  className: "whitespace-nowrap",
3723
- children: format(d, locale)
3870
+ children: formatted
3724
3871
  });
3725
3872
  }
3726
3873
  function toIsoDate(v) {
3727
3874
  if (v == null || v === "") return "";
3728
3875
  const s = String(v);
3729
- if (/^\d{4}-\d{2}-\d{2}/.test(s)) return s.slice(0, 10);
3730
- const d = new Date(s);
3731
- if (Number.isNaN(d.getTime())) return "";
3732
- return d.toISOString().slice(0, 10);
3876
+ return (0, _burojs_core.isCalendarDate)(s) ? s : "";
3733
3877
  }
3734
3878
  function DateInput(props) {
3735
3879
  return (0, react_jsx_runtime.jsx)(TemporalInput, {
@@ -3740,18 +3884,44 @@ function DateInput(props) {
3740
3884
  });
3741
3885
  }
3742
3886
  function DateTimeInput(props) {
3887
+ const locale = (0, _burojs_react.useOptionalLocale)();
3888
+ const zone = require_filter_builder.useFieldTimeZone(props.field?.zone, props.values === void 0 ? props.record : {
3889
+ ...props.record,
3890
+ ...props.values
3891
+ });
3892
+ const viewer = (0, _burojs_react.useTimeZone)();
3893
+ const pending = zone.status === "pending";
3894
+ const fieldZone = zone.status === "ready" ? zone.zone : void 0;
3895
+ const named = fieldZone !== void 0 && viewer.status === "ready" && fieldZone !== viewer.zone ? (0, _burojs_core.zoneShortName)((0, _burojs_core.canonicalInstant)(String(props.value ?? "")) ?? (0, _burojs_core.epochMsToInstant)(Date.now()), fieldZone, require_filter_builder.localeTag(locale)) : void 0;
3743
3896
  return (0, react_jsx_runtime.jsx)(TemporalInput, {
3744
3897
  ...props,
3745
3898
  type: "datetime-local",
3746
- toText: require_filter_builder.toLocalDateTimeText,
3747
- fromText: (text) => require_filter_builder.fromLocalDateTimeText(text) ?? null
3899
+ disabled: props.disabled || pending,
3900
+ toText: (value) => fieldZone === void 0 ? "" : require_filter_builder.toLocalDateTimeText(value, fieldZone),
3901
+ fromText: (text) => fieldZone === void 0 ? null : require_filter_builder.fromLocalDateTimeText(text, fieldZone) ?? null,
3902
+ ...named === void 0 ? {} : { zoneName: named }
3748
3903
  });
3749
3904
  }
3750
- function TemporalInput({ type, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
3751
- return (0, react_jsx_runtime.jsx)(require_input.Input, {
3905
+ function TimeInput(props) {
3906
+ const seconds = props.field?.ui?.seconds === true;
3907
+ return (0, react_jsx_runtime.jsx)(TemporalInput, {
3908
+ ...props,
3909
+ type: "time",
3910
+ step: seconds ? 1 : 60,
3911
+ toText: (value) => value == null ? "" : String(value),
3912
+ fromText: (text) => {
3913
+ if (text === "") return null;
3914
+ if (seconds) return text.length === 5 ? `${text}:00` : text;
3915
+ return text.slice(0, 5);
3916
+ }
3917
+ });
3918
+ }
3919
+ function TemporalInput({ type, step, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, zoneName }) {
3920
+ const input = (0, react_jsx_runtime.jsx)(require_input.Input, {
3752
3921
  name,
3753
3922
  id,
3754
3923
  type,
3924
+ ...step === void 0 ? {} : { step },
3755
3925
  value: toText(value),
3756
3926
  onChange: (e) => onChange(fromText(e.target.value)),
3757
3927
  "data-testid": testid,
@@ -3762,6 +3932,15 @@ function TemporalInput({ type, toText, fromText, name, id, value, onChange, test
3762
3932
  "aria-describedby": ariaDescribedBy,
3763
3933
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3764
3934
  });
3935
+ if (zoneName === void 0) return input;
3936
+ return (0, react_jsx_runtime.jsxs)("div", {
3937
+ className: "flex items-center gap-2",
3938
+ children: [input, (0, react_jsx_runtime.jsx)("span", {
3939
+ className: "whitespace-nowrap text-xs text-muted-foreground",
3940
+ "data-testid": testid === void 0 ? void 0 : `${testid}:zone`,
3941
+ children: zoneName
3942
+ })]
3943
+ });
3765
3944
  }
3766
3945
  //#endregion
3767
3946
  //#region src/fields/enum.tsx
@@ -3782,13 +3961,30 @@ function EnumDisplay({ value, options, field, resource }) {
3782
3961
  }) : null, label]
3783
3962
  });
3784
3963
  }
3785
- function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource }) {
3964
+ function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource, record, values, metaSources, baseline }) {
3786
3965
  const t = (0, _burojs_react.useOptionalT)();
3787
3966
  const caps = (0, _burojs_react.useOptionCaps)(resource);
3788
3967
  const enumDef = (0, _burojs_react.useBoundEnum)(field);
3789
3968
  const ns = (0, _burojs_core.enumNamespaceOf)(field);
3790
3969
  const control = resolveEnumControl(field?.ui?.control, enumDef, `field ${field?.name ?? name}`);
3791
- const resolved = (options ?? []).map((o) => {
3970
+ const sources = (0, _burojs_react.useFieldMetaSources)({
3971
+ record,
3972
+ values,
3973
+ extra: metaSources
3974
+ });
3975
+ const available = (0, _burojs_react.useAvailableEnumValues)({
3976
+ values: options ?? [],
3977
+ use: {
3978
+ narrow: (0, _burojs_core_internal.narrowEntriesOf)(field?.meta?.narrow),
3979
+ sources,
3980
+ mode: record === void 0 ? "create" : "edit",
3981
+ baseline: baseline ?? record
3982
+ }
3983
+ });
3984
+ const settling = available.status === "ready" ? void 0 : available.status;
3985
+ const offered = settling === void 0 ? available.values : [];
3986
+ const tid = testid ?? name;
3987
+ const resolved = offered.map((o) => {
3792
3988
  const summary = ns === void 0 ? void 0 : (0, _burojs_core.resolveDoc)(caps, `enum/${ns}/${o.value}`)?.summary;
3793
3989
  return {
3794
3990
  value: o.value,
@@ -3797,12 +3993,21 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3797
3993
  ...summary === void 0 ? {} : { summary }
3798
3994
  };
3799
3995
  });
3996
+ const raw = value == null || value === "" ? void 0 : String(value);
3997
+ const known = raw === void 0 ? void 0 : options?.find((o) => o.value === raw);
3998
+ const current = raw === void 0 || resolved.some((o) => o.value === raw) ? void 0 : {
3999
+ value: raw,
4000
+ label: (0, _burojs_react.resolveOptionLabel)(caps, field, raw, known, enumDef),
4001
+ ...known?.icon === void 0 ? {} : { icon: known.icon }
4002
+ };
3800
4003
  if (control !== "select") return (0, react_jsx_runtime.jsx)(EnumChoiceGroup, {
3801
4004
  control,
3802
4005
  options: resolved,
4006
+ ...current === void 0 ? {} : { current },
4007
+ ...settling === void 0 ? {} : { settling },
3803
4008
  value,
3804
4009
  onChange,
3805
- testid: testid ?? name,
4010
+ testid: tid,
3806
4011
  name,
3807
4012
  id,
3808
4013
  required,
@@ -3822,25 +4027,39 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3822
4027
  name,
3823
4028
  id,
3824
4029
  "aria-required": required,
4030
+ "aria-busy": settling === "pending" || void 0,
3825
4031
  "aria-invalid": ariaInvalid || void 0,
3826
4032
  "aria-describedby": ariaDescribedBy,
3827
4033
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3828
4034
  children: (0, react_jsx_runtime.jsx)(require_filter_builder.SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3829
- }), (0, react_jsx_runtime.jsx)(require_filter_builder.SelectContent, { children: resolved.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
3830
- value: o.value,
3831
- "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
3832
- description: o.summary === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
3833
- "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
3834
- children: o.summary
4035
+ }), (0, react_jsx_runtime.jsxs)(require_filter_builder.SelectContent, { children: [
4036
+ current === void 0 ? null : (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
4037
+ value: current.value,
4038
+ disabled: true,
4039
+ "data-current": "",
4040
+ "data-testid": `${tid}:current`,
4041
+ children: current.label
3835
4042
  }),
3836
- children: (0, react_jsx_runtime.jsxs)("span", {
3837
- className: "inline-flex items-center gap-1.5",
3838
- children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
3839
- name: o.icon,
3840
- className: "size-3.5 shrink-0 text-muted-foreground"
3841
- }) : null, o.label]
3842
- })
3843
- }, o.value)) })]
4043
+ settling === void 0 ? null : (0, react_jsx_runtime.jsx)(require_place_node.EnumSettlingRow, {
4044
+ status: settling,
4045
+ testid: tid
4046
+ }),
4047
+ resolved.map((o) => (0, react_jsx_runtime.jsx)(require_filter_builder.SelectItem, {
4048
+ value: o.value,
4049
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
4050
+ description: o.summary === void 0 ? void 0 : (0, react_jsx_runtime.jsx)("span", {
4051
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
4052
+ children: o.summary
4053
+ }),
4054
+ children: (0, react_jsx_runtime.jsxs)("span", {
4055
+ className: "inline-flex items-center gap-1.5",
4056
+ children: [o.icon ? (0, react_jsx_runtime.jsx)(require_check_confirm_dialog.Icon, {
4057
+ name: o.icon,
4058
+ className: "size-3.5 shrink-0 text-muted-foreground"
4059
+ }) : null, o.label]
4060
+ })
4061
+ }, o.value))
4062
+ ] })]
3844
4063
  });
3845
4064
  }
3846
4065
  //#endregion
@@ -4261,7 +4480,7 @@ function JsonInput({ name, id, value, onChange, testid, disabled, required, aria
4261
4480
  }
4262
4481
  //#endregion
4263
4482
  //#region src/fields/lazy-relation-many.tsx
4264
- const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-DzuGJpEl.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4483
+ const RelationManyPickerInput = (0, react.lazy)(() => Promise.resolve().then(() => require("./relation-many-picker-Br-zBHxT.cjs")).then((module) => ({ default: module.RelationManyPickerInput })));
4265
4484
  function LazyRelationManyInput(props) {
4266
4485
  return (0, react_jsx_runtime.jsx)(react.Suspense, {
4267
4486
  fallback: (0, react_jsx_runtime.jsx)(require_skeleton.Skeleton, {
@@ -4373,6 +4592,144 @@ function NumberInput({ name, id, value, onChange, testid, placeholder, disabled,
4373
4592
  });
4374
4593
  }
4375
4594
  //#endregion
4595
+ //#region src/fields/object-group.tsx
4596
+ const GROUP = "rounded-md border border-input p-3";
4597
+ function ObjectGroupInput(props) {
4598
+ const { testIds, accessibility, children } = props;
4599
+ return (0, react_jsx_runtime.jsx)("div", {
4600
+ role: "group",
4601
+ "data-buro-object-group": "input",
4602
+ className: require_use_theme.cn(GROUP, "space-y-3"),
4603
+ "data-testid": testIds.input,
4604
+ id: accessibility.input,
4605
+ "aria-labelledby": accessibility.label,
4606
+ "aria-describedby": accessibility.description,
4607
+ "aria-invalid": props.issues.some((issue) => issue.severity === "error" && issue.path.length === 0) || void 0,
4608
+ "aria-errormessage": accessibility.error,
4609
+ children
4610
+ });
4611
+ }
4612
+ function ObjectGroupDisplay(props) {
4613
+ const { testIds, children } = props;
4614
+ return (0, react_jsx_runtime.jsx)("div", {
4615
+ role: "group",
4616
+ "data-buro-object-group": "display",
4617
+ className: require_use_theme.cn(GROUP, "space-y-2"),
4618
+ "data-testid": testIds.display,
4619
+ children
4620
+ });
4621
+ }
4622
+ //#endregion
4623
+ //#region src/fields/repeater.tsx
4624
+ function useRepeaterTexts() {
4625
+ const t = (0, _burojs_react.useChromeT)();
4626
+ return {
4627
+ add: t("field.repeater.add", { defaultValue: "Add" }),
4628
+ empty: t("field.repeater.empty", { defaultValue: "No items yet" }),
4629
+ remove: (position) => t("field.repeater.remove", {
4630
+ params: { position },
4631
+ defaultValue: "Remove item {{position}}"
4632
+ }),
4633
+ moveUp: (position) => t("field.repeater.moveUp", {
4634
+ params: { position },
4635
+ defaultValue: "Move item {{position}} up"
4636
+ }),
4637
+ moveDown: (position) => t("field.repeater.moveDown", {
4638
+ params: { position },
4639
+ defaultValue: "Move item {{position}} down"
4640
+ })
4641
+ };
4642
+ }
4643
+ function RepeaterInput(props) {
4644
+ const texts = useRepeaterTexts();
4645
+ const { value, renderElement, elementKeys, onAdd, onRemove, onMove, testIds, accessibility } = props;
4646
+ const root = testIds.input;
4647
+ const at = (suffix) => root === void 0 ? void 0 : `${root}:${suffix}`;
4648
+ const editable = props.disabled !== true && props.readOnly !== true;
4649
+ const canAdd = editable && onAdd !== void 0 && props.canAdd !== false;
4650
+ const canRemove = editable && onRemove !== void 0 && props.canRemove !== false;
4651
+ const last = value.length - 1;
4652
+ return (0, react_jsx_runtime.jsxs)("div", {
4653
+ role: "group",
4654
+ className: "space-y-2",
4655
+ "data-testid": root,
4656
+ id: accessibility.input,
4657
+ "aria-labelledby": accessibility.label,
4658
+ "aria-describedby": accessibility.description,
4659
+ "aria-errormessage": accessibility.error,
4660
+ children: [value.length === 0 ? (0, react_jsx_runtime.jsx)("p", {
4661
+ className: "text-sm text-muted-foreground",
4662
+ "data-testid": at("empty"),
4663
+ children: texts.empty
4664
+ }) : (0, react_jsx_runtime.jsx)("ol", {
4665
+ className: "space-y-2",
4666
+ children: value.map((_, index) => (0, react_jsx_runtime.jsxs)("li", {
4667
+ className: "flex items-start gap-2 rounded-md border border-input p-3",
4668
+ "data-testid": at(`item:${index}`),
4669
+ children: [(0, react_jsx_runtime.jsx)("div", {
4670
+ className: "min-w-0 flex-1",
4671
+ children: renderElement?.(index)
4672
+ }), onMove === void 0 && onRemove === void 0 ? null : (0, react_jsx_runtime.jsxs)("div", {
4673
+ className: "flex shrink-0 gap-1",
4674
+ children: [onMove === void 0 ? null : (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(require_button.Button, {
4675
+ type: "button",
4676
+ variant: "ghost",
4677
+ size: "icon",
4678
+ "aria-label": texts.moveUp(index + 1),
4679
+ disabled: !editable || index === 0,
4680
+ "data-testid": at(`up:${index}`),
4681
+ onClick: () => onMove(index, index - 1),
4682
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowUp, { "aria-hidden": "true" })
4683
+ }), (0, react_jsx_runtime.jsx)(require_button.Button, {
4684
+ type: "button",
4685
+ variant: "ghost",
4686
+ size: "icon",
4687
+ "aria-label": texts.moveDown(index + 1),
4688
+ disabled: !editable || index === last,
4689
+ "data-testid": at(`down:${index}`),
4690
+ onClick: () => onMove(index, index + 1),
4691
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconArrowDown, { "aria-hidden": "true" })
4692
+ })] }), onRemove === void 0 ? null : (0, react_jsx_runtime.jsx)(require_button.Button, {
4693
+ type: "button",
4694
+ variant: "ghost",
4695
+ size: "icon",
4696
+ "aria-label": texts.remove(index + 1),
4697
+ disabled: !canRemove,
4698
+ "data-testid": at(`remove:${index}`),
4699
+ onClick: () => onRemove(index),
4700
+ children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconTrash, { "aria-hidden": "true" })
4701
+ })]
4702
+ })]
4703
+ }, elementKeys?.[index] ?? index))
4704
+ }), onAdd === void 0 ? null : (0, react_jsx_runtime.jsxs)(require_button.Button, {
4705
+ type: "button",
4706
+ variant: "outline",
4707
+ size: "sm",
4708
+ disabled: !canAdd,
4709
+ "data-testid": at("add"),
4710
+ onClick: onAdd,
4711
+ children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconPlus, { "aria-hidden": "true" }), texts.add]
4712
+ })]
4713
+ });
4714
+ }
4715
+ function RepeaterDisplay(props) {
4716
+ const texts = useRepeaterTexts();
4717
+ const { value, renderElement, testIds } = props;
4718
+ if (value.length === 0) return (0, react_jsx_runtime.jsx)("span", {
4719
+ className: "text-muted-foreground",
4720
+ "data-testid": testIds.display,
4721
+ children: texts.empty
4722
+ });
4723
+ return (0, react_jsx_runtime.jsx)("ol", {
4724
+ className: "space-y-2",
4725
+ "data-testid": testIds.display,
4726
+ children: value.map((_, index) => (0, react_jsx_runtime.jsx)("li", {
4727
+ className: "rounded-md border border-input p-3",
4728
+ children: renderElement?.(index)
4729
+ }, index))
4730
+ });
4731
+ }
4732
+ //#endregion
4376
4733
  //#region src/fields/link-keys-display.tsx
4377
4734
  const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4378
4735
  function qualify(name) {
@@ -4702,12 +5059,13 @@ function TextareaInput({ name, id, value, onChange, testid, placeholder, disable
4702
5059
  //#region src/fields/default-renderers.ts
4703
5060
  function legacyField(props) {
4704
5061
  const name = (0, _burojs_react.optionFieldName)(props.path);
4705
- const texts = props.field.texts;
5062
+ const { texts, zone } = props.field;
4706
5063
  return Object.freeze({
4707
5064
  name,
4708
5065
  meta: props.meta,
4709
5066
  ui: props.ui,
4710
- ...texts === void 0 ? {} : { texts }
5067
+ ...texts === void 0 ? {} : { texts },
5068
+ ...zone === void 0 ? {} : { zone }
4711
5069
  });
4712
5070
  }
4713
5071
  function legacyOptions(options, field) {
@@ -4770,9 +5128,12 @@ function input(renderer) {
4770
5128
  field: legacyField(props),
4771
5129
  resource: props.resource.id,
4772
5130
  record: props.record,
5131
+ values: props.form,
4773
5132
  relationSeeds: props.relationSeeds,
4774
5133
  fixedFilters: props.fixedFilters,
5134
+ optionSubtitle: props.optionSubtitle,
4775
5135
  metaSources: props.metaSources,
5136
+ ...props.baseline === void 0 ? {} : { baseline: props.baseline },
4776
5137
  link: props.link
4777
5138
  });
4778
5139
  };
@@ -4825,6 +5186,12 @@ function enumName(ui) {
4825
5186
  }
4826
5187
  function RegistryEnumInput(props) {
4827
5188
  const app = (0, _burojs_react.useOptionalApp)();
5189
+ const meta = props.field.meta;
5190
+ const sources = (0, _burojs_react.useFieldMetaSources)({
5191
+ record: props.record,
5192
+ values: props.form,
5193
+ extra: props.metaSources
5194
+ });
4828
5195
  const control = resolveEnumControl(props.ui.control, app?.registry.enums.get(props.enumName), `field ${typeof props.path.at(-1) === "string" ? String(props.path.at(-1)) : props.enumName}`);
4829
5196
  return (0, react.createElement)(EnumPicker, {
4830
5197
  enumName: props.enumName,
@@ -4840,7 +5207,14 @@ function RegistryEnumInput(props) {
4840
5207
  ariaInvalid: props.issues.some(isErrorIssue),
4841
5208
  ariaDescribedBy: props.accessibility.description,
4842
5209
  ariaErrorMessage: props.accessibility.error,
4843
- ariaLabelledBy: props.accessibility.label
5210
+ ariaLabelledBy: props.accessibility.label,
5211
+ use: {
5212
+ params: (0, _burojs_core_internal.enumParamsOf)(meta?.enumParams),
5213
+ narrow: (0, _burojs_core_internal.narrowEntriesOf)(meta?.narrow),
5214
+ sources,
5215
+ mode: props.record === void 0 ? "create" : "edit",
5216
+ baseline: props.baseline ?? props.record
5217
+ }
4844
5218
  });
4845
5219
  }
4846
5220
  function enumAware(renderer, layout) {
@@ -4892,6 +5266,10 @@ const dateTime = {
4892
5266
  Display: DateTimeDisplay,
4893
5267
  Input: DateTimeInput
4894
5268
  };
5269
+ const time = {
5270
+ Display: TimeDisplay,
5271
+ Input: TimeInput
5272
+ };
4895
5273
  const en = {
4896
5274
  Display: EnumDisplay,
4897
5275
  Input: EnumInput
@@ -4930,6 +5308,8 @@ const shadcnFieldImplementations = Object.freeze({
4930
5308
  dateTime: scalar(dateTime),
4931
5309
  "date-time": scalar(dateTime),
4932
5310
  "default:date-time": scalar(dateTime),
5311
+ time: scalar(time),
5312
+ "default:time": scalar(time),
4933
5313
  enum: enumAware(en),
4934
5314
  json: scalar({
4935
5315
  Display: JsonDisplay,
@@ -4943,7 +5323,17 @@ const shadcnFieldImplementations = Object.freeze({
4943
5323
  richText: scalar(rich, { size: "full" }),
4944
5324
  "rich-text": scalar(rich, { size: "full" }),
4945
5325
  "default:rich-text": scalar(rich, { size: "full" }),
4946
- file: scalarOrCollection(file, { size: "full" })
5326
+ file: scalarOrCollection(file, { size: "full" }),
5327
+ object: Object.freeze({
5328
+ Input: ObjectGroupInput,
5329
+ Display: ObjectGroupDisplay,
5330
+ chrome: true
5331
+ }),
5332
+ array: Object.freeze({
5333
+ CollectionInput: RepeaterInput,
5334
+ CollectionDisplay: RepeaterDisplay,
5335
+ chrome: true
5336
+ })
4947
5337
  });
4948
5338
  //#endregion
4949
5339
  //#region src/forms/declarative-display.tsx
@@ -5173,7 +5563,8 @@ const OPERATOR_LABELS = {
5173
5563
  has: "has",
5174
5564
  hasAny: "has any of",
5175
5565
  hasAll: "has all of",
5176
- hasNone: "has none of"
5566
+ hasNone: "has none of",
5567
+ some: "has an item where"
5177
5568
  };
5178
5569
  function formatOperatorLabel(op, chromeT) {
5179
5570
  return chromeT ? chromeT(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
@@ -5707,6 +6098,7 @@ function PeekRecord({ target, testid, row }) {
5707
6098
  function DeclaredPeekBody({ target, testid, record, frameRecord, def, capabilityFor, fieldVisible, view: View, builtin, open, openable, t }) {
5708
6099
  const host = (0, react.useContext)(require_relation_create.PeekHostContext);
5709
6100
  const title = require_relation_create.recordDisplayName(record, def?.displayField);
6101
+ const subtitle = require_use_record_subtitle.useRecordSubtitle(target)(record) ?? void 0;
5710
6102
  const setLabel = host?.setLabel;
5711
6103
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5712
6104
  const controller = (0, _burojs_react.useFormController)({
@@ -5742,6 +6134,7 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5742
6134
  children: [builtin ? (0, react_jsx_runtime.jsx)(PeekTitle, {
5743
6135
  testid,
5744
6136
  title,
6137
+ subtitle,
5745
6138
  open: openable ? open : void 0
5746
6139
  }) : null, (0, react_jsx_runtime.jsx)(react.Suspense, {
5747
6140
  fallback: null,
@@ -5754,11 +6147,26 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5754
6147
  })]
5755
6148
  });
5756
6149
  }
5757
- function PeekTitle({ testid, title, open }) {
5758
- if (open === void 0) return (0, react_jsx_runtime.jsx)("p", {
6150
+ function PeekTitle({ testid, title, subtitle, open }) {
6151
+ const heading = open === void 0 ? (0, react_jsx_runtime.jsx)("p", {
5759
6152
  className: "text-sm font-semibold",
5760
6153
  children: title
6154
+ }) : (0, react_jsx_runtime.jsx)(PeekTitleButton, {
6155
+ testid,
6156
+ title,
6157
+ open
6158
+ });
6159
+ if (subtitle === void 0) return heading;
6160
+ return (0, react_jsx_runtime.jsxs)("div", {
6161
+ className: "flex flex-col gap-0.5",
6162
+ children: [heading, (0, react_jsx_runtime.jsx)("p", {
6163
+ "data-testid": `${testid}:subtitle`,
6164
+ className: "text-xs text-muted-foreground",
6165
+ children: subtitle
6166
+ })]
5761
6167
  });
6168
+ }
6169
+ function PeekTitleButton({ testid, title, open }) {
5762
6170
  return (0, react_jsx_runtime.jsx)("button", {
5763
6171
  type: "button",
5764
6172
  "data-testid": `${testid}:title`,
@@ -5786,6 +6194,8 @@ function DefaultPeekBody({ target, testid, row, open }) {
5786
6194
  const projected = (0, _burojs_react.useProjectedRecord)(target, dtoRow);
5787
6195
  const record = projected.value ?? {};
5788
6196
  const title = require_relation_create.recordDisplayName(record, def?.displayField);
6197
+ const subtitleOf = require_use_record_subtitle.useRecordSubtitle(target);
6198
+ const subtitle = projected.status === "ready" ? subtitleOf(record) ?? void 0 : void 0;
5789
6199
  const setLabel = host?.setLabel;
5790
6200
  (0, react.useEffect)(() => setLabel?.(title), [setLabel, title]);
5791
6201
  const columns = (0, react.useMemo)(() => {
@@ -5817,6 +6227,7 @@ function DefaultPeekBody({ target, testid, row, open }) {
5817
6227
  children: [(0, react_jsx_runtime.jsx)(PeekTitle, {
5818
6228
  testid,
5819
6229
  title,
6230
+ subtitle,
5820
6231
  open
5821
6232
  }), columns.length === 0 ? null : (0, react_jsx_runtime.jsx)("dl", {
5822
6233
  className: "grid gap-1.5",