@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.js CHANGED
@@ -1,23 +1,24 @@
1
1
  import { c as scrollToDocAnchor, l as cn, n as useTheme, s as readDocHash, t as THEME_CHOICES } from "./use-theme-dnE3Od3I.js";
2
2
  import { a as technicalText, c as LinkComponentProvider, d as PopoverAnchor, f as PopoverClose, l as useLinkComponent, m as PopoverTrigger, n as toast, p as PopoverContent, r as friendlyStringsFrom, s as toFriendlyError, t as Toaster, u as Popover } from "./toaster-Ct_YHGs6.js";
3
- import { $ as Tooltip, A as OwnTitleHeading, B as DropdownMenuContent, F as Icon, G as DropdownMenuRadioGroup, H as DropdownMenuItem, I as hasIcon, J as DropdownMenuShortcut, K as DropdownMenuRadioItem, L as registerIcons, M as DialogPresentationShell, N as OwnTitleContext, P as SheetPresentationShell, Q as DropdownMenuTrigger, R as DropdownMenu, T as loadFlowScreen, U as DropdownMenuLabel, V as DropdownMenuGroup, W as DropdownMenuPortal, X as DropdownMenuSubContent, Y as DropdownMenuSub, Z as DropdownMenuSubTrigger, _ as reasonText, a as modeForSurface, at as SheetContent, c as useListSlot, ct as SheetHeader, dt as DocInfo, et as TooltipContent, f as FlowActionButton, it as SheetClose, k as useLoaded, l as isExternalHref, lt as SheetTitle, n as ActionButton, nt as TooltipTrigger, o as canonicalResourceName, ot as SheetDescription, q as DropdownMenuSeparator, r as DisabledAction, rt as Sheet, s as listSlot, st as SheetFooter, t as CheckConfirmDialog, tt as TooltipProvider, u as openExternal, ut as SheetTrigger, v as FlowBoundary, y as FlowLoadFailed, z as DropdownMenuCheckboxItem } from "./check-confirm-dialog-2j0gOd7x.js";
3
+ import { $ as Tooltip, A as OwnTitleHeading, B as DropdownMenuContent, F as Icon, G as DropdownMenuRadioGroup, H as DropdownMenuItem, I as hasIcon, J as DropdownMenuShortcut, K as DropdownMenuRadioItem, L as registerIcons, M as DialogPresentationShell, N as OwnTitleContext, P as SheetPresentationShell, Q as DropdownMenuTrigger, R as DropdownMenu, T as loadFlowScreen, U as DropdownMenuLabel, V as DropdownMenuGroup, W as DropdownMenuPortal, X as DropdownMenuSubContent, Y as DropdownMenuSub, Z as DropdownMenuSubTrigger, _ as reasonText, a as modeForSurface, at as SheetContent, c as useListSlot, ct as SheetHeader, dt as DocInfo, et as TooltipContent, f as FlowActionButton, it as SheetClose, k as useLoaded, l as isExternalHref, lt as SheetTitle, n as ActionButton, nt as TooltipTrigger, o as canonicalResourceName, ot as SheetDescription, q as DropdownMenuSeparator, r as DisabledAction, rt as Sheet, s as listSlot, st as SheetFooter, t as CheckConfirmDialog, tt as TooltipProvider, u as openExternal, ut as SheetTrigger, v as FlowBoundary, y as FlowLoadFailed, z as DropdownMenuCheckboxItem } from "./check-confirm-dialog-CtiRzOAt.js";
4
4
  import { n as buttonVariants, t as Button } from "./button-MWVeZaqj.js";
5
5
  import { t as Input } from "./input-CUPStzZO.js";
6
6
  import { a as DialogFooter, c as DialogTrigger, i as DialogDescription, n as DialogClose, o as DialogHeader, r as DialogContent, s as DialogTitle, t as Dialog } from "./dialog-C123sVQ8.js";
7
7
  import { C as CommandEmpty, D as CommandList, E as CommandItem, O as CommandLoading, S as CommandDialog, T as CommandInput, b as RecordState, c as RelationField, d as peekAnchorOpener, f as PeekContext, h as recordDisplayName, k as CommandSeparator, l as relationLinkClassName, p as PeekHostContext, s as RelationDisplay, u as focusWithoutPeek, v as InvalidRouteId, w as CommandGroup, x as Command, y as LoadError } from "./relation-create-C43cdPQt.js";
8
8
  import { t as Skeleton } from "./skeleton-U2noefj5.js";
9
- import { $ as CursorLoadMore, A as ListSearchInput, At as EnumBadge, B as ExportDialog, Bt as usePaletteState, C as ListControls, D as ListFlows, E as ListLive, Et as ActionOverflow, F as ListColumns, Ft as i18nPrefixToRef, H as ScreenTree, I as ColumnsToggle, It as FieldValueFrame, L as DataTableViewOptions, Lt as toDisplayText, M as ExportButton, Mt as AppFlowButton, N as ListCreate, Nt as Field, O as ListFilters, Ot as useExportRunWatcher, P as CreateButton, Pt as FieldDisplay, Q as ResourceList, R as ListBulkBar, Rt as ShellProvider, T as SavedViewsDropdown, V as DeclarativeForm, Vt as useShell, W as QuickScreenClaimContext, Y as useFormControl, Z as ListBody, _ as CopyId, _t as resolveResourceTitle, a as peekFieldDefinition, at as DataTable, b as RecordTitle, bt as typography, c as peekRow, ct as TabsContent, d as resolveFrameView, et as ListErrorState, f as shadcnFrameViews, gt as ShowPageHeader, ht as PageHeader, it as useBuroDataTable, j as ListExport, k as FilterRegion, kt as downloadArtifact, l as useRelationPicker, lt as TabsList, mt as EditPageHeader, nt as resolveUpdater, o as peekLeafAllowed, ot as Checkbox, r as shadcnBlockImplementations, rt as tanStackSortingToBuro, s as peekRecord, st as Tabs, tt as buroSortingToTanStack, ut as TabsTrigger, v as FormActions, vt as DocumentTitleProvider, w as ListSavedViews, wt as recordRouteAvailable, xt as isShowAvailable, y as RecordActions, yt as useDocumentTitle, z as BulkActionToolbar, zt as defaultUserMapper } from "./place-node-CfzQvh4Y.js";
9
+ import { $ as CursorLoadMore, A as ListSearchInput, At as AppFlowButton, B as ExportDialog, C as ListControls, D as ListFlows, Dt as EnumSettlingRow, E as ListLive, Et as EnumBadge, F as ListColumns, Ft as toDisplayText, H as ScreenTree, I as ColumnsToggle, It as ShellProvider, L as DataTableViewOptions, Lt as defaultUserMapper, M as ExportButton, Mt as FieldDisplay, N as ListCreate, Nt as i18nPrefixToRef, O as ListFilters, Ot as unknownEnumValueLabel, P as CreateButton, Pt as FieldValueFrame, Q as ResourceList, R as ListBulkBar, Rt as usePaletteState, St as ActionOverflow, T as SavedViewsDropdown, Tt as downloadArtifact, V as DeclarativeForm, W as QuickScreenClaimContext, Y as useFormControl, Z as ListBody, _ as CopyId, _t as ShowPageHeader, a as peekFieldDefinition, at as DataTable, b as RecordTitle, bt as useDocumentTitle, c as peekRow, ct as TabsContent, d as resolveFrameView, et as ListErrorState, f as shadcnFrameViews, gt as PageHeader, ht as EditPageHeader, it as useBuroDataTable, j as ListExport, jt as Field, k as FilterRegion, l as useRelationPicker, lt as TabsList, nt as resolveUpdater, o as peekLeafAllowed, ot as Checkbox, r as shadcnBlockImplementations, rt as tanStackSortingToBuro, s as peekRecord, st as Tabs, tt as buroSortingToTanStack, ut as TabsTrigger, v as FormActions, vt as resolveResourceTitle, w as ListSavedViews, wt as useExportRunWatcher, xt as typography, y as RecordActions, yt as DocumentTitleProvider, z as BulkActionToolbar, zt as useShell } from "./place-node-BdxT-30h.js";
10
10
  import { THEME_STORAGE_KEY } from "./layout/theme-storage-key.js";
11
- import { A as TableRow, B as loadLocale, C as SelectValue, D as TableCell, E as TableCaption, M as badgeVariants, O as TableHead, P as ResolvedFieldDisplay, R as lowerLegacyField, S as SelectTrigger, T as TableBody, V as saveLocale, _ as SelectItem, a as PinnedFilterControls, b as SelectScrollUpButton, c as fromLocalDateTimeText, d as formatDate, f as formatDateTime, g as SelectGroup, h as SelectContent, i as FacetedFilterPicker, j as Badge, k as TableHeader, l as toLocalDateTimeText, m as Select, n as PresetFilterControls, o as FilterPanel, p as formatNumber, r as DataTableFacetedFilter, s as FilterValueControl, t as FilterBuilder, u as FilterBadges, v as SelectLabel, w as Table, x as SelectSeparator, y as SelectScrollDownButton, z as DEFAULT_LANGUAGE_STORAGE_KEY } from "./filter-builder-DaWHUZuV.js";
12
- import { A as TabsLayout, C as usePageAllowed, D as useLayout, E as layoutSlot, M as canonicalNavKey, N as canonicalResourceKey$1, O as useLayoutResolver, S as useNavVisible, T as BUILTIN_LAYOUTS, _ as PlannedBody, a as useRecordVisit, b as useHref, c as headerTrail, d as useTrailContext, f as recordTrailKey, g as useResourceDimensionOptions, h as RecordScreen, i as RecordPage, j as SecondarySidebarLayout, k as useReportUnresolvedLayouts, l as recordTrail, m as usePublishedRecordTrail, n as NavAreaPage, o as RECENT_LABEL_KEYS, r as ResourcePageRouter, s as readRecentRecords, u as recordTrailRoute, v as ResourceListPage, w as useResourceVisible, x as useMatch, y as NavChromeMountedProvider } from "./resource-page-router-Diw6S6TK.js";
11
+ import { A as TableHeader, B as DEFAULT_LANGUAGE_STORAGE_KEY, C as SelectTrigger, D as TableCaption, E as TableBody, F as ResolvedFieldDisplay, H as saveLocale, M as Badge, N as badgeVariants, O as TableCell, S as SelectSeparator, T as Table, V as loadLocale, _ as SelectGroup, a as PinnedFilterControls, b as SelectScrollDownButton, c as fromLocalDateTimeText, d as useFieldTimeZone, f as FilterBadges, g as SelectContent, h as Select, i as FacetedFilterPicker, j as TableRow, k as TableHead, l as toLocalDateTimeText, m as localeTag, n as PresetFilterControls, o as FilterPanel, p as formatNumber, r as DataTableFacetedFilter, s as FilterValueControl, t as FilterBuilder, u as dateDisplayParams, v as SelectItem, w as SelectValue, x as SelectScrollUpButton, y as SelectLabel, z as lowerLegacyField } from "./filter-builder-z3Axzf9Y.js";
12
+ import { A as useLayoutResolver, C as useMatch, D as BUILTIN_LAYOUTS, E as useResourceVisible, F as canonicalResourceKey$1, M as TabsLayout, N as SecondarySidebarLayout, O as layoutSlot, P as canonicalNavKey, S as useHref, T as usePageAllowed, _ as RecordScreen, a as useRecordVisit, b as ResourceListPage, c as headerTrail, d as recordTrailRoute, f as useTrailContext, g as usePublishedRecordTrail, i as RecordPage, j as useReportUnresolvedLayouts, k as useLayout, l as originTrail, m as recordTrailKey, n as NavAreaPage, o as RECENT_LABEL_KEYS, p as isShowAvailable, r as ResourcePageRouter, s as readRecentRecords, u as recordTrail, v as useResourceDimensionOptions, w as useNavVisible, x as NavChromeMountedProvider, y as PlannedBody } from "./resource-page-router-BRpUnhay.js";
13
13
  import { t as Label } from "./label-66W1qbke.js";
14
- import { t as LazyRelationPickerDialog } from "./lazy-relation-picker-dialog-CAScLPb2.js";
15
- import { n as RelationPicker, r as RelationPickerInput } from "./relation-picker-D-tBBZW_.js";
14
+ import { t as LazyRelationPickerDialog } from "./lazy-relation-picker-dialog-DN4bvQfg.js";
15
+ import { n as useRecordSubtitle, r as useRowSubtitle } from "./use-record-subtitle-gIaCGgbI.js";
16
+ import { n as RelationPicker, r as RelationPickerInput } from "./relation-picker-x7P5HKie.js";
16
17
  import { t as useDialogFilterState } from "./use-dialog-filter-state-B_MqzHaT.js";
17
18
  import { useGlobalShortcut, webPlatform } from "@burojs/react/web";
18
- import { ENUM_CONTROLS, builtinFrames, columnName, compilePageScreen, compiledScreenFor, declaredField, declaredText, dtoFields, effectiveFlow, enumFallbackKey, enumFallbackText, enumNamespaceOf, enumValueText, evaluateVisible, fieldOptionText, formatEntityRef, hasListPage, hasRecordPage, hrefFor, humanizeKey, isCustomPageDef, isEnumControl, isRelationField, isScreenFailure, linkOf, navHrefFor, nodeKind, normalizeDataError, normalizeEntityRef, projectDto, recordEntries, relationAmbiguousError, resolveConceptLabel, resolveContentSlot, resolveDoc, resolveEnumLabel, resolveFieldLabel, resolveNavLabel, resolveResourceLabel, resolveResourceNavLabel, resolveStaticAvailability, resourceCreateHref, resourceKey, resourceShowHref, routeResourceKey, snapshotAppFrames, snapshotBlockLookup, snapshotFrameLookup, taskRunFraction, taskRunOutcome } from "@burojs/core";
19
- import { ComponentsContext, DispatcherProvider, I18nContext, NO_RECORD_SCOPE_FRAMES, QUICK_ANCHOR_ATTRIBUTE, QuickEntryContext, RecordScopeChain, RouteSourceContext, ScreenStateProvider, formatBytes, optionFieldName, resolveErrorText, resolveOptionLabel, retryRecordRead, useApp, useAppActions, useApplicationSnapshot, useAvailabilityGate, useBoundEnum, useCapabilityResolver, useChangeLocale, useChromeT, useCommandPalette, useCurrentUserId, useDebouncedValue, useDispatcherEffects, useDocPanel, useDocScopes, useDocTopics, useDocTrailScopes, useDocsConfig, useDocumentedScopes, useEntryGate, useEnumValues, useFieldAccess, useFileField, useFileUrls, useFormController, useFrameImplementations, useFrameT, useI18nCaps, useIdentity, useLanguageStorageKey, useLinkKeys, useList, useListAccess, useLocale, useLogout, useNavigationGuardText, useOne, useOptionCaps, useOptionalApp, useOptionalAuthController, useOptionalDataRuntime, useOptionalFileStorage, useOptionalLocale, useOptionalRouterAdapter, useOptionalT, usePlatformStorage, usePresentBlock, useProjectedRecord, useProjectedTitle, useQuick, useQuickEntry, useQuickEntryValue, useQuickOpener, useRecordTitle, useRefresh, useRegisterNavigationGuardDialog, useRelatedRecord, useRouteNavigate, useRouteRecordId, useRouterAdapter, useScope, useT, useTestIds, useUIInstance, useUIPresentationRuntime, useVisibilityCtx } from "@burojs/react";
20
- import { IconAlertCircle, IconArrowLeft, IconArrowUpRight, IconBook2, IconCheck, IconChevronDown, IconChevronRight, IconDeviceDesktop, IconDots, IconExternalLink, IconHelp, IconHelpHexagon, IconLayoutSidebar, IconLoader2, IconLogin, IconLogout, IconMaximize, IconMinimize, IconMoon, IconRefresh, IconRotate, IconSearch, IconSelector, IconSun, IconUpload, IconUser, IconX } from "@tabler/icons-react";
19
+ import { ENUM_CONTROLS, builtinFrames, canonicalInstant, columnName, compilePageScreen, compiledScreenFor, declaredField, declaredText, dtoFields, effectiveFlow, enumFallbackKey, enumFallbackText, enumNamespaceOf, enumValueText, epochMsToInstant, evaluateVisible, fieldOptionText, formatEntityRef, formatTimeValue, hasListPage, hasRecordPage, hrefFor, humanizeKey, isCalendarDate, isCustomPageDef, isEnumControl, isRelationField, isScreenFailure, linkOf, navHrefFor, nodeKind, normalizeDataError, normalizeEntityRef, projectDto, recordEntries, relationAmbiguousError, resolveConceptLabel, resolveContentSlot, resolveDoc, resolveEnumLabel, resolveFieldLabel, resolveNavLabel, resolveResourceLabel, resolveResourceNavLabel, resolveStaticAvailability, resourceCreateHref, resourceKey, resourceShowHref, routeResourceKey, snapshotAppFrames, snapshotBlockLookup, snapshotFrameLookup, taskRunFraction, taskRunOutcome, zoneShortName } from "@burojs/core";
20
+ import { ComponentsContext, DispatcherProvider, I18nContext, NO_RECORD_SCOPE_FRAMES, QUICK_ANCHOR_ATTRIBUTE, QuickEntryContext, RecordScopeChain, RouteSourceContext, ScreenStateProvider, formatBytes, optionFieldName, recordRouteAvailable, resolveErrorText, resolveOptionLabel, retryRecordRead, useApp, useAppActions, useApplicationSnapshot, useAvailabilityGate, useAvailableEnumValues, useBoundEnum, useCapabilityResolver, useChangeLocale, useChromeT, useCommandPalette, useCurrentUserId, useDebouncedValue, useDispatcherEffects, useDocPanel, useDocScopes, useDocTopics, useDocTrailScopes, useDocsConfig, useDocumentedScopes, useEntryGate, useEnumValues, useFieldAccess, useFieldMetaSources, useFileField, useFileUrls, useFormController, useFrameImplementations, useFrameT, useI18nCaps, useIdentity, useLanguageStorageKey, useLinkKeys, useList, useListAccess, useLocale, useLogout, useNavigationGuardText, useNavigationOrigin, useOne, useOptionCaps, useOptionalApp, useOptionalAuthController, useOptionalDataRuntime, useOptionalFileStorage, useOptionalLocale, useOptionalRouterAdapter, useOptionalT, useOriginIntent, usePlatformStorage, usePresentBlock, useProjectedRecord, useProjectedTitle, usePublishOriginTitle, useQuick, useQuickEntry, useQuickEntryValue, useQuickOpener, useRecordTitle, useRefresh, useRegisterNavigationGuardDialog, useRelatedRecord, useRouteNavigate, useRouteRecordId, useRouterAdapter, useScope, useT, useTestIds, useTimeZone, useUIInstance, useUIPresentationRuntime, useVisibilityCtx } from "@burojs/react";
21
+ import { IconAlertCircle, IconArrowDown, IconArrowLeft, IconArrowUp, IconArrowUpRight, IconBook2, IconCheck, IconChevronDown, IconChevronRight, IconDeviceDesktop, IconDots, IconExternalLink, IconHelp, IconHelpHexagon, IconLayoutSidebar, IconLoader2, IconLogin, IconLogout, IconMaximize, IconMinimize, IconMoon, IconPlus, IconRefresh, IconRotate, IconSearch, IconSelector, IconSun, IconTrash, IconUpload, IconUser, IconX } from "@tabler/icons-react";
21
22
  import * as React from "react";
22
23
  import { Children, Fragment, Suspense, cloneElement, createContext, createElement, isValidElement, lazy, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
23
24
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -29,7 +30,7 @@ import * as SeparatorPrimitive from "@radix-ui/react-separator";
29
30
  import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
30
31
  import * as AvatarPrimitive from "@radix-ui/react-avatar";
31
32
  import * as CollapsiblePrimitive from "@radix-ui/react-collapsible";
32
- import { enumBindingKey } from "@burojs/core/internal";
33
+ import { enumBindingKey, enumParamsOf, narrowEntriesOf } from "@burojs/core/internal";
33
34
  import { Controller, FormProvider, useForm, useFormContext } from "react-hook-form";
34
35
  import { zodResolver } from "@hookform/resolvers/zod";
35
36
  import { z } from "zod";
@@ -1974,6 +1975,10 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
1974
1975
  const t = useT();
1975
1976
  const RouterLink = useLinkComponent();
1976
1977
  const navIcon = useNavIcon();
1978
+ const intent = useOriginIntent();
1979
+ const jump = (entry) => () => {
1980
+ if (entry.href !== void 0) intent(entry.href, "jump");
1981
+ };
1977
1982
  const ownOr = (own, name) => own !== void 0 ? own : navIcon(name);
1978
1983
  const groupAsSection = (key) => app.registry.sections.get(key) ?? app.registry.groups.get(key);
1979
1984
  const sectionIcon = (key, name) => {
@@ -2000,6 +2005,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
2000
2005
  href: entry.href ?? "",
2001
2006
  "aria-current": entry.active ? "page" : void 0,
2002
2007
  "data-testid": entryTestId(entry),
2008
+ onClick: jump(entry),
2003
2009
  children: [icon != null && jsx("span", {
2004
2010
  className: "inline-flex h-4 w-4 items-center justify-center",
2005
2011
  "aria-hidden": "true",
@@ -2015,6 +2021,7 @@ function NavMain({ topLabel, iconForResource, iconForCustomPage, iconForSection,
2015
2021
  href: entry.href ?? "",
2016
2022
  "aria-current": entry.active ? "page" : void 0,
2017
2023
  "data-testid": entryTestId(entry),
2024
+ onClick: jump(entry),
2018
2025
  children: jsx("span", { children: entry.label })
2019
2026
  })
2020
2027
  }) }, entry.key);
@@ -2128,11 +2135,17 @@ function Breadcrumbs(input) {
2128
2135
  const t = useOptionalT();
2129
2136
  const RouterLink = useLinkComponent();
2130
2137
  const caps = useI18nCaps(def?.name);
2138
+ const intent = useOriginIntent();
2139
+ const onJump = (seg) => {
2140
+ const href = seg.href;
2141
+ return seg.jump === true && href !== void 0 ? () => intent(href, "jump") : void 0;
2142
+ };
2131
2143
  const trailScopes = useDocTrailScopes(def?.name);
2132
2144
  const leading = (name) => leadingSegments?.map((seg, i) => jsxs("span", {
2133
2145
  className: "flex min-w-0 items-center gap-1",
2134
2146
  children: [seg.href ? jsx(RouterLink, {
2135
2147
  href: seg.href,
2148
+ onClick: onJump(seg),
2136
2149
  "data-testid": `${tid.navBreadcrumb(name)}:lead:${i}`,
2137
2150
  className: cn(LINK_CLASS, "truncate"),
2138
2151
  title: seg.label,
@@ -2167,9 +2180,34 @@ function Breadcrumbs(input) {
2167
2180
  ]
2168
2181
  });
2169
2182
  if (!def) return null;
2170
- const { recordId, pageLabel, middleSegments } = props;
2183
+ const { recordId, pageLabel, middleSegments, rootSegments } = props;
2171
2184
  const resourceKey = canonicalResourceKey$1(def);
2172
- const listHref = hrefFor(app.registry, resourceKey);
2185
+ if (rootSegments !== void 0 && rootSegments.length > 0) return jsxs("nav", {
2186
+ className: navClass,
2187
+ "aria-label": ariaLabel,
2188
+ "data-testid": testId,
2189
+ children: [
2190
+ rootSegments.map((seg, i) => jsxs("span", {
2191
+ className: "flex min-w-0 items-center gap-1",
2192
+ children: [i > 0 && jsx(Chevron, {}), seg.href ? jsx(RouterLink, {
2193
+ href: seg.href,
2194
+ onClick: onJump(seg),
2195
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2196
+ className: cn(LINK_CLASS, "truncate"),
2197
+ title: seg.label,
2198
+ children: seg.label
2199
+ }) : jsx("span", {
2200
+ "data-testid": `${tid.navBreadcrumb(resourceKey)}:root:${i}`,
2201
+ className: "truncate",
2202
+ title: seg.label,
2203
+ children: seg.label
2204
+ })]
2205
+ }, `root:${i}:${seg.label}`)),
2206
+ pageLabel && jsxs(Fragment$1, { children: [jsx(Chevron, {}), current(tid.navBreadcrumb(resourceKey, recordId), pageLabel)] }),
2207
+ help
2208
+ ]
2209
+ });
2210
+ const listHref = props.resourceHref ?? hrefFor(app.registry, resourceKey);
2173
2211
  const resourceLabel = resolveResourceLabel(caps, resourceKey, "plural", def);
2174
2212
  const resourceIsCurrent = !pageLabel && !(middleSegments && middleSegments.length > 0);
2175
2213
  return jsxs("nav", {
@@ -2194,6 +2232,7 @@ function Breadcrumbs(input) {
2194
2232
  className: "flex min-w-0 items-center gap-1",
2195
2233
  children: [jsx(Chevron, {}), seg.href ? jsx(RouterLink, {
2196
2234
  href: seg.href,
2235
+ onClick: onJump(seg),
2197
2236
  "data-testid": `${tid.navBreadcrumb(resourceKey)}:mid:${i}`,
2198
2237
  className: cn(LINK_CLASS, "truncate"),
2199
2238
  title: seg.label,
@@ -2211,6 +2250,12 @@ function Breadcrumbs(input) {
2211
2250
  }
2212
2251
  //#endregion
2213
2252
  //#region src/layout/record-breadcrumbs.tsx
2253
+ function viewOrigin(ctx, trail, resource) {
2254
+ if (trail === void 0 || trail.resource === void 0 || trail.segments.length > 0) return void 0;
2255
+ const target = ctx.registry.get(trail.resource)?.routesTo?.show;
2256
+ if (target === void 0 || ctx.registry.get(target) !== ctx.registry.get(resource)) return void 0;
2257
+ return trail.resource;
2258
+ }
2214
2259
  function RecordBreadcrumbs() {
2215
2260
  const ctx = useTrailContext();
2216
2261
  const match = useMatch();
@@ -2218,9 +2263,17 @@ function RecordBreadcrumbs() {
2218
2263
  const route = recordTrailRoute(ctx.registry, match);
2219
2264
  const published = usePublishedRecordTrail(route === null ? "" : recordTrailKey(route.resource, route.id, route.flow === void 0 ? route.action : `flow:${route.flow}`));
2220
2265
  const idTitle = useRecordTitle(route?.resource, route?.id);
2266
+ usePublishOriginTitle(published?.title || void 0);
2267
+ const origin = useNavigationOrigin();
2268
+ const rooted = origin === null ? void 0 : originTrail(ctx, origin);
2269
+ const view = route === null ? void 0 : viewOrigin(ctx, rooted, route.resource);
2270
+ const viewScopes = useDocTrailScopes(view);
2271
+ const ownScopes = useDocTrailScopes(view === void 0 ? void 0 : route?.resource);
2272
+ const docScopes = view === void 0 ? {} : { docScopes: [...new Set([...viewScopes, ...ownScopes])] };
2221
2273
  if (route === null || match === null) return null;
2222
2274
  const { resource, id, groupChain } = route;
2223
2275
  const title = published?.title ?? idTitle;
2276
+ const withOrigin = rooted === void 0 ? {} : { origin: rooted };
2224
2277
  if (route.flow !== void 0) {
2225
2278
  if (effectiveFlow(snapshot, match.ref, route.flow) === void 0) return null;
2226
2279
  const flowLabel = published?.flowLabel;
@@ -2230,8 +2283,10 @@ function RecordBreadcrumbs() {
2230
2283
  action: "show",
2231
2284
  id,
2232
2285
  title: idTitle,
2233
- groupChain
2286
+ groupChain,
2287
+ ...withOrigin
2234
2288
  }),
2289
+ ...docScopes,
2235
2290
  "data-testid": "record-breadcrumbs"
2236
2291
  });
2237
2292
  return jsx(Breadcrumbs, {
@@ -2240,8 +2295,10 @@ function RecordBreadcrumbs() {
2240
2295
  action: "edit",
2241
2296
  id,
2242
2297
  title,
2243
- groupChain
2298
+ groupChain,
2299
+ ...withOrigin
2244
2300
  }),
2301
+ ...docScopes,
2245
2302
  pageLabel: flowLabel,
2246
2303
  "data-testid": "record-breadcrumbs"
2247
2304
  });
@@ -2252,8 +2309,10 @@ function RecordBreadcrumbs() {
2252
2309
  action: route.action,
2253
2310
  id,
2254
2311
  title,
2255
- groupChain
2312
+ groupChain,
2313
+ ...withOrigin
2256
2314
  }),
2315
+ ...docScopes,
2257
2316
  "data-testid": "record-breadcrumbs"
2258
2317
  });
2259
2318
  }
@@ -2598,7 +2657,7 @@ function CommandPaletteNavigationGroups({ onSelect, getTestId }) {
2598
2657
  }, [app, visibilityCtx]);
2599
2658
  const goTo = (href) => {
2600
2659
  onSelect?.();
2601
- navigate(href);
2660
+ navigate(href, { origin: "jump" });
2602
2661
  };
2603
2662
  const resourceLabel = (def) => resolveResourceLabel(caps, canonicalResourceKey$1(def), "plural", def);
2604
2663
  const pageLabel = (def) => resolveNavLabel(caps, `pages.${canonicalNavKey(def)}`, declaredText("chrome", def, "label"));
@@ -2802,7 +2861,7 @@ function CommandPaletteRecentGroup({ onSelect, getTestId, heading, refreshKey, w
2802
2861
  const goTo = (href, entry) => {
2803
2862
  onSelect?.();
2804
2863
  if (href === null) quick.show(entry.canonicalRef, entry.id);
2805
- else navigate(href);
2864
+ else navigate(href, { origin: "jump" });
2806
2865
  };
2807
2866
  return jsxs(Fragment, { children: [jsx(CommandGroup, {
2808
2867
  heading: resolvedHeading,
@@ -2877,7 +2936,7 @@ function CommandPaletteRecordsGroup({ enabled = true, pageSize = 5, minQueryLeng
2877
2936
  const goTo = (href, resource, id) => {
2878
2937
  onSelect?.();
2879
2938
  if (href === null) quick.show(resource, id);
2880
- else navigate(href);
2939
+ else navigate(href, { origin: "jump" });
2881
2940
  };
2882
2941
  return jsx(CommandGroup, {
2883
2942
  heading: resolvedHeading,
@@ -2915,6 +2974,7 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2915
2974
  enabled: shouldFetch
2916
2975
  });
2917
2976
  const report = useCommandPaletteResults(`records:${resource}`);
2977
+ const rowSubtitle = useRowSubtitle(resource);
2918
2978
  const rows = !shouldFetch || q.isLoading || q.isError ? [] : q.data?.data ?? [];
2919
2979
  useEffect(() => {
2920
2980
  report(rows.length);
@@ -2929,16 +2989,25 @@ function PerResourceSearchHits({ def, displayField, query, pageSize, goTo, recor
2929
2989
  if (!id) return null;
2930
2990
  const display = titleVisible ? row[displayField] : void 0;
2931
2991
  const labelText = typeof display === "string" && display.length > 0 ? display : id;
2992
+ const subtitle = rowSubtitle(row) ?? null;
2932
2993
  const href = recordHref ? recordHref(resource, id) : isShowAvailable(registry, resource) ? resourceShowHref(registry, def, resource, id) : null;
2933
2994
  return jsxs(CommandItem, {
2934
2995
  value: `record:${resource}:${id}:${labelText}`,
2935
2996
  forceMount: true,
2936
2997
  onSelect: () => goTo(href, resource, id),
2937
2998
  "data-testid": getTestId?.("records-record", `${resource}:${id}`),
2938
- children: [jsxs("span", {
2939
- className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
2940
- children: [resourceLabel, ":"]
2941
- }), labelText]
2999
+ children: [
3000
+ jsxs("span", {
3001
+ className: "text-muted-foreground group-data-[selected=true]:text-accent-foreground mr-2",
3002
+ children: [resourceLabel, ":"]
3003
+ }),
3004
+ labelText,
3005
+ subtitle === null ? null : jsx("span", {
3006
+ "data-buro-region": "record-subtitle",
3007
+ className: "ml-auto truncate pl-2 text-xs text-muted-foreground group-data-[selected=true]:text-accent-foreground",
3008
+ children: subtitle
3009
+ })
3010
+ ]
2942
3011
  }, `record:${resource}:${id}`);
2943
3012
  }) });
2944
3013
  }
@@ -3086,7 +3155,7 @@ function CommandPaletteCreateGroup({ resourceFilter, onSelect, getTestId, headin
3086
3155
  ]);
3087
3156
  if (visibleResources.length === 0) return null;
3088
3157
  const goTo = (href) => {
3089
- navigate(href);
3158
+ navigate(href, { origin: "jump" });
3090
3159
  onSelect?.();
3091
3160
  };
3092
3161
  const createIn = (def, href) => {
@@ -3434,7 +3503,7 @@ const NONE = "__none__";
3434
3503
  function isEmpty$1(value) {
3435
3504
  return value === null || value === void 0 || value === "";
3436
3505
  }
3437
- function EnumChoiceGroup({ control, options, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3506
+ function EnumChoiceGroup({ control, options, current, settling, value, onChange, testid, name, id, required, disabled, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className }) {
3438
3507
  const t = useOptionalT();
3439
3508
  const generatedName = React.useId();
3440
3509
  const groupName = name ?? generatedName;
@@ -3449,16 +3518,25 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3449
3518
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3450
3519
  };
3451
3520
  if (control === "segmented") {
3452
- const segment = (key, label, active, select) => jsx("button", {
3521
+ const segmentLabel = (option) => jsxs(Fragment$1, { children: [option.icon ? jsx("span", {
3522
+ "data-testid": `${testid}:option:${option.value}:icon`,
3523
+ className: "contents",
3524
+ children: jsx(Icon, {
3525
+ name: option.icon,
3526
+ className: "size-3.5 shrink-0"
3527
+ })
3528
+ }) : null, option.label] });
3529
+ const segment = (key, label, active, select, currentItem = false) => jsx("button", {
3453
3530
  type: "button",
3454
3531
  "aria-pressed": active,
3455
3532
  "data-state": active ? "active" : "inactive",
3456
- "data-testid": `${testid}:option:${key}`,
3457
- disabled,
3533
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3534
+ ...currentItem ? { "data-current": "" } : {},
3535
+ disabled: disabled || currentItem,
3458
3536
  onClick: select,
3459
3537
  className: 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"),
3460
3538
  children: label
3461
- }, key);
3539
+ }, currentItem ? `current:${key}` : key);
3462
3540
  return jsxs("div", {
3463
3541
  role: "group",
3464
3542
  id,
@@ -3466,22 +3544,24 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3466
3544
  "data-testid": testid,
3467
3545
  className: cn("inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground", className),
3468
3546
  ...ariaProps,
3469
- children: [required ? null : segment(NONE, noneLabel, empty, () => pick(void 0)), options.map((option) => segment(option.value, jsxs(Fragment$1, { children: [option.icon ? jsx("span", {
3470
- "data-testid": `${testid}:option:${option.value}:icon`,
3471
- className: "contents",
3472
- children: jsx(Icon, {
3473
- name: option.icon,
3474
- className: "size-3.5 shrink-0"
3475
- })
3476
- }) : null, option.label] }), value === option.value, () => pick(option.value)))]
3547
+ children: [
3548
+ current === void 0 ? null : segment(current.value, segmentLabel(current), true, () => void 0, true),
3549
+ required || settling !== void 0 ? null : segment(NONE, noneLabel, empty, () => pick(void 0)),
3550
+ settling === void 0 ? null : jsx(EnumSettlingRow, {
3551
+ status: settling,
3552
+ testid
3553
+ }),
3554
+ options.map((option) => segment(option.value, segmentLabel(option), value === option.value, () => pick(option.value)))
3555
+ ]
3477
3556
  });
3478
3557
  }
3479
3558
  const cards = control === "cards";
3480
- const choice = (key, option, label, checked, select) => {
3481
- const inputId = `${id ?? groupName}:${key}`;
3559
+ const choice = (key, option, label, checked, select, currentItem = false) => {
3560
+ const inputId = `${id ?? groupName}:${currentItem ? "current:" : ""}${key}`;
3561
+ const inert = disabled || currentItem;
3482
3562
  return jsxs("label", {
3483
3563
  htmlFor: inputId,
3484
- className: 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"),
3564
+ className: 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"),
3485
3565
  children: [jsx("input", {
3486
3566
  type: "radio",
3487
3567
  id: inputId,
@@ -3489,9 +3569,10 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3489
3569
  value: key,
3490
3570
  checked,
3491
3571
  onChange: select,
3492
- disabled,
3572
+ disabled: inert,
3493
3573
  ...ariaProps,
3494
- "data-testid": `${testid}:option:${key}`,
3574
+ "data-testid": currentItem ? `${testid}:current` : `${testid}:option:${key}`,
3575
+ ...currentItem ? { "data-current": "" } : {},
3495
3576
  className: cn("h-4 w-4 shrink-0 accent-primary", cards ? "mt-0.5" : "mt-1")
3496
3577
  }), jsxs("span", {
3497
3578
  className: "flex min-w-0 flex-col gap-0.5",
@@ -3511,7 +3592,7 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3511
3592
  children: option.summary
3512
3593
  })]
3513
3594
  })]
3514
- }, key);
3595
+ }, currentItem ? `current:${key}` : key);
3515
3596
  };
3516
3597
  return jsxs("div", {
3517
3598
  role: "radiogroup",
@@ -3520,7 +3601,15 @@ function EnumChoiceGroup({ control, options, value, onChange, testid, name, id,
3520
3601
  "data-testid": testid,
3521
3602
  "aria-required": required,
3522
3603
  className: cn("flex flex-col", cards ? "gap-2" : "gap-1.5", className),
3523
- 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)))]
3604
+ children: [
3605
+ current === void 0 ? null : choice(current.value, current, current.label, true, () => void 0, true),
3606
+ required || settling !== void 0 ? null : choice(NONE, void 0, noneLabel, empty, () => pick(void 0)),
3607
+ settling === void 0 ? null : jsx(EnumSettlingRow, {
3608
+ status: settling,
3609
+ testid
3610
+ }),
3611
+ options.map((option) => choice(option.value, option, option.label, value === option.value, () => pick(option.value)))
3612
+ ]
3524
3613
  });
3525
3614
  }
3526
3615
  //#endregion
@@ -3529,7 +3618,7 @@ const ENUM_PICKER_CLEAR_SENTINEL = "__buro_clear__";
3529
3618
  function withSummary(summary) {
3530
3619
  return summary === void 0 ? {} : { summary };
3531
3620
  }
3532
- function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All" }) {
3621
+ function EnumPicker({ enumName: enumInput, value, onChange, control = "select", name, id, testid, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, className, clearable = false, clearLabel = "All", use }) {
3533
3622
  const enumName = enumBindingKey(enumInput) ?? "";
3534
3623
  const app = useApp();
3535
3624
  const t = useOptionalT();
@@ -3537,6 +3626,11 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3537
3626
  const caps = useI18nCaps();
3538
3627
  const ns = def?.i18nNamespace ?? enumName;
3539
3628
  const { values, isLoading, error } = useEnumValues(enumName);
3629
+ const available = useAvailableEnumValues({
3630
+ values: isLoading || values === void 0 ? "pending" : values,
3631
+ ...def === void 0 ? {} : { enum: def },
3632
+ ...use === void 0 ? {} : { use }
3633
+ });
3540
3634
  const tid = testid ?? `enum-picker:${enumName}`;
3541
3635
  if (!def) return jsxs("span", {
3542
3636
  "data-testid": `${tid}:unregistered`,
@@ -3578,9 +3672,22 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3578
3672
  });
3579
3673
  const labelOf = (entry) => resolveEnumLabel(caps, ns, entry.value, enumValueText(def, entry.value) ?? entry.label);
3580
3674
  const summaryOf = (entry) => resolveDoc(caps, `enum/${ns}/${entry.value}`)?.summary || void 0;
3675
+ const settling = available.status === "ready" ? void 0 : available.status;
3676
+ const offered = settling === void 0 ? available.values : [];
3677
+ const known = value == null ? void 0 : values.find((entry) => entry.value === value);
3678
+ const current = value == null || value === "" || offered.some((entry) => entry.value === value) ? void 0 : known === void 0 ? {
3679
+ value,
3680
+ label: unknownEnumValueLabel(caps, def, ns, value).label
3681
+ } : {
3682
+ value,
3683
+ label: labelOf(known),
3684
+ ...known.icon === void 0 ? {} : { icon: known.icon }
3685
+ };
3581
3686
  if (control !== "select") return jsx(EnumChoiceGroup, {
3582
3687
  control,
3583
- options: values.map((entry) => ({
3688
+ ...current === void 0 ? {} : { current },
3689
+ ...settling === void 0 ? {} : { settling },
3690
+ options: offered.map((entry) => ({
3584
3691
  value: entry.value,
3585
3692
  label: labelOf(entry),
3586
3693
  ...entry.icon === void 0 ? {} : { icon: entry.icon },
@@ -3617,28 +3724,43 @@ function EnumPicker({ enumName: enumInput, value, onChange, control = "select",
3617
3724
  name,
3618
3725
  id,
3619
3726
  "aria-required": required,
3727
+ "aria-busy": settling === "pending" || void 0,
3620
3728
  "aria-invalid": ariaInvalid || void 0,
3621
3729
  "aria-describedby": ariaDescribedBy,
3622
3730
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3623
3731
  className,
3624
3732
  children: jsx(SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3625
- }), jsxs(SelectContent, { children: [clearable && jsx(SelectItem, {
3626
- value: "__buro_clear__",
3627
- "data-testid": `${tid}:option:__clear__`,
3628
- children: clearLabel
3629
- }), values.map((entry) => {
3630
- const optionLabel = labelOf(entry);
3631
- const optionDoc = summaryOf(entry);
3632
- return jsx(SelectItem, {
3633
- value: entry.value,
3634
- "data-testid": `${tid}:option:${entry.value}`,
3635
- description: optionDoc === void 0 ? void 0 : jsx("span", {
3636
- "data-testid": `${tid}:option:${entry.value}:doc`,
3637
- children: optionDoc
3638
- }),
3639
- children: optionLabel
3640
- }, entry.value);
3641
- })] })]
3733
+ }), jsxs(SelectContent, { children: [
3734
+ clearable && jsx(SelectItem, {
3735
+ value: "__buro_clear__",
3736
+ "data-testid": `${tid}:option:__clear__`,
3737
+ children: clearLabel
3738
+ }),
3739
+ current === void 0 ? null : jsx(SelectItem, {
3740
+ value: current.value,
3741
+ disabled: true,
3742
+ "data-current": "",
3743
+ "data-testid": `${tid}:current`,
3744
+ children: current.label
3745
+ }),
3746
+ settling === void 0 ? null : jsx(EnumSettlingRow, {
3747
+ status: settling,
3748
+ testid: tid
3749
+ }),
3750
+ offered.map((entry) => {
3751
+ const optionLabel = labelOf(entry);
3752
+ const optionDoc = summaryOf(entry);
3753
+ return jsx(SelectItem, {
3754
+ value: entry.value,
3755
+ "data-testid": `${tid}:option:${entry.value}`,
3756
+ description: optionDoc === void 0 ? void 0 : jsx("span", {
3757
+ "data-testid": `${tid}:option:${entry.value}:doc`,
3758
+ children: optionDoc
3759
+ }),
3760
+ children: optionLabel
3761
+ }, entry.value);
3762
+ })
3763
+ ] })]
3642
3764
  });
3643
3765
  }
3644
3766
  //#endregion
@@ -3688,41 +3810,63 @@ function BooleanInput({ name, id, value, onChange, testid, disabled, required, a
3688
3810
  }
3689
3811
  //#endregion
3690
3812
  //#region src/fields/date.tsx
3691
- function DateDisplay({ value, text }) {
3813
+ function DateDisplay(props) {
3692
3814
  return jsx(TemporalDisplay, {
3693
- value,
3694
- text,
3695
- format: formatDate
3815
+ kind: "date",
3816
+ ...props
3696
3817
  });
3697
3818
  }
3698
- function DateTimeDisplay({ value, text }) {
3819
+ function DateTimeDisplay(props) {
3699
3820
  return jsx(TemporalDisplay, {
3700
- value,
3701
- text,
3702
- format: formatDateTime
3821
+ kind: "dateTime",
3822
+ ...props
3823
+ });
3824
+ }
3825
+ function TimeDisplay(props) {
3826
+ return jsx(TemporalDisplay, {
3827
+ kind: "time",
3828
+ ...props
3703
3829
  });
3704
3830
  }
3705
- function TemporalDisplay({ value, text, format }) {
3831
+ function storedText(value) {
3832
+ return value instanceof Date && !Number.isNaN(value.getTime()) ? value.toISOString() : String(value);
3833
+ }
3834
+ function TemporalDisplay({ kind, value, text, field, record }) {
3706
3835
  const locale = useOptionalLocale();
3836
+ const zone = useFieldTimeZone(field?.zone, record);
3837
+ const viewer = useTimeZone();
3707
3838
  if (value == null || value === "") return jsx("span", {
3708
3839
  className: "text-muted-foreground",
3709
3840
  children: "—"
3710
3841
  });
3711
- if (text !== void 0) return jsx("span", { children: text });
3712
- const d = new Date(String(value));
3713
- if (Number.isNaN(d.getTime())) return jsx("span", { children: String(value) });
3842
+ if (zone.status === "pending" || viewer.status === "pending") return jsx(Skeleton, {
3843
+ className: "h-4 w-24",
3844
+ "aria-busy": "true"
3845
+ });
3846
+ const raw = storedText(value);
3847
+ const formatted = formatTimeValue(kind, raw, {
3848
+ zone: zone.zone,
3849
+ viewerZone: viewer.zone,
3850
+ locale: localeTag(locale),
3851
+ params: {
3852
+ ...kind === "time" && field?.ui?.seconds === true ? { timeStyle: "medium" } : {},
3853
+ ...dateDisplayParams(field?.ui)
3854
+ }
3855
+ });
3856
+ if (text !== void 0) return jsx("span", {
3857
+ title: formatted,
3858
+ children: text
3859
+ });
3860
+ if (formatted === void 0) return jsx("span", { children: raw });
3714
3861
  return jsx("span", {
3715
3862
  className: "whitespace-nowrap",
3716
- children: format(d, locale)
3863
+ children: formatted
3717
3864
  });
3718
3865
  }
3719
3866
  function toIsoDate(v) {
3720
3867
  if (v == null || v === "") return "";
3721
3868
  const s = String(v);
3722
- if (/^\d{4}-\d{2}-\d{2}/.test(s)) return s.slice(0, 10);
3723
- const d = new Date(s);
3724
- if (Number.isNaN(d.getTime())) return "";
3725
- return d.toISOString().slice(0, 10);
3869
+ return isCalendarDate(s) ? s : "";
3726
3870
  }
3727
3871
  function DateInput(props) {
3728
3872
  return jsx(TemporalInput, {
@@ -3733,18 +3877,44 @@ function DateInput(props) {
3733
3877
  });
3734
3878
  }
3735
3879
  function DateTimeInput(props) {
3880
+ const locale = useOptionalLocale();
3881
+ const zone = useFieldTimeZone(props.field?.zone, props.values === void 0 ? props.record : {
3882
+ ...props.record,
3883
+ ...props.values
3884
+ });
3885
+ const viewer = useTimeZone();
3886
+ const pending = zone.status === "pending";
3887
+ const fieldZone = zone.status === "ready" ? zone.zone : void 0;
3888
+ const named = fieldZone !== void 0 && viewer.status === "ready" && fieldZone !== viewer.zone ? zoneShortName(canonicalInstant(String(props.value ?? "")) ?? epochMsToInstant(Date.now()), fieldZone, localeTag(locale)) : void 0;
3736
3889
  return jsx(TemporalInput, {
3737
3890
  ...props,
3738
3891
  type: "datetime-local",
3739
- toText: toLocalDateTimeText,
3740
- fromText: (text) => fromLocalDateTimeText(text) ?? null
3892
+ disabled: props.disabled || pending,
3893
+ toText: (value) => fieldZone === void 0 ? "" : toLocalDateTimeText(value, fieldZone),
3894
+ fromText: (text) => fieldZone === void 0 ? null : fromLocalDateTimeText(text, fieldZone) ?? null,
3895
+ ...named === void 0 ? {} : { zoneName: named }
3741
3896
  });
3742
3897
  }
3743
- function TemporalInput({ type, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
3744
- return jsx(Input, {
3898
+ function TimeInput(props) {
3899
+ const seconds = props.field?.ui?.seconds === true;
3900
+ return jsx(TemporalInput, {
3901
+ ...props,
3902
+ type: "time",
3903
+ step: seconds ? 1 : 60,
3904
+ toText: (value) => value == null ? "" : String(value),
3905
+ fromText: (text) => {
3906
+ if (text === "") return null;
3907
+ if (seconds) return text.length === 5 ? `${text}:00` : text;
3908
+ return text.slice(0, 5);
3909
+ }
3910
+ });
3911
+ }
3912
+ function TemporalInput({ type, step, toText, fromText, name, id, value, onChange, testid, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, zoneName }) {
3913
+ const input = jsx(Input, {
3745
3914
  name,
3746
3915
  id,
3747
3916
  type,
3917
+ ...step === void 0 ? {} : { step },
3748
3918
  value: toText(value),
3749
3919
  onChange: (e) => onChange(fromText(e.target.value)),
3750
3920
  "data-testid": testid,
@@ -3755,6 +3925,15 @@ function TemporalInput({ type, toText, fromText, name, id, value, onChange, test
3755
3925
  "aria-describedby": ariaDescribedBy,
3756
3926
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {}
3757
3927
  });
3928
+ if (zoneName === void 0) return input;
3929
+ return jsxs("div", {
3930
+ className: "flex items-center gap-2",
3931
+ children: [input, jsx("span", {
3932
+ className: "whitespace-nowrap text-xs text-muted-foreground",
3933
+ "data-testid": testid === void 0 ? void 0 : `${testid}:zone`,
3934
+ children: zoneName
3935
+ })]
3936
+ });
3758
3937
  }
3759
3938
  //#endregion
3760
3939
  //#region src/fields/enum.tsx
@@ -3775,13 +3954,30 @@ function EnumDisplay({ value, options, field, resource }) {
3775
3954
  }) : null, label]
3776
3955
  });
3777
3956
  }
3778
- function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource }) {
3957
+ function EnumInput({ name, id, value, onChange, testid, options, field, placeholder, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, resource, record, values, metaSources, baseline }) {
3779
3958
  const t = useOptionalT();
3780
3959
  const caps = useOptionCaps(resource);
3781
3960
  const enumDef = useBoundEnum(field);
3782
3961
  const ns = enumNamespaceOf(field);
3783
3962
  const control = resolveEnumControl(field?.ui?.control, enumDef, `field ${field?.name ?? name}`);
3784
- const resolved = (options ?? []).map((o) => {
3963
+ const sources = useFieldMetaSources({
3964
+ record,
3965
+ values,
3966
+ extra: metaSources
3967
+ });
3968
+ const available = useAvailableEnumValues({
3969
+ values: options ?? [],
3970
+ use: {
3971
+ narrow: narrowEntriesOf(field?.meta?.narrow),
3972
+ sources,
3973
+ mode: record === void 0 ? "create" : "edit",
3974
+ baseline: baseline ?? record
3975
+ }
3976
+ });
3977
+ const settling = available.status === "ready" ? void 0 : available.status;
3978
+ const offered = settling === void 0 ? available.values : [];
3979
+ const tid = testid ?? name;
3980
+ const resolved = offered.map((o) => {
3785
3981
  const summary = ns === void 0 ? void 0 : resolveDoc(caps, `enum/${ns}/${o.value}`)?.summary;
3786
3982
  return {
3787
3983
  value: o.value,
@@ -3790,12 +3986,21 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3790
3986
  ...summary === void 0 ? {} : { summary }
3791
3987
  };
3792
3988
  });
3989
+ const raw = value == null || value === "" ? void 0 : String(value);
3990
+ const known = raw === void 0 ? void 0 : options?.find((o) => o.value === raw);
3991
+ const current = raw === void 0 || resolved.some((o) => o.value === raw) ? void 0 : {
3992
+ value: raw,
3993
+ label: resolveOptionLabel(caps, field, raw, known, enumDef),
3994
+ ...known?.icon === void 0 ? {} : { icon: known.icon }
3995
+ };
3793
3996
  if (control !== "select") return jsx(EnumChoiceGroup, {
3794
3997
  control,
3795
3998
  options: resolved,
3999
+ ...current === void 0 ? {} : { current },
4000
+ ...settling === void 0 ? {} : { settling },
3796
4001
  value,
3797
4002
  onChange,
3798
- testid: testid ?? name,
4003
+ testid: tid,
3799
4004
  name,
3800
4005
  id,
3801
4006
  required,
@@ -3815,25 +4020,39 @@ function EnumInput({ name, id, value, onChange, testid, options, field, placehol
3815
4020
  name,
3816
4021
  id,
3817
4022
  "aria-required": required,
4023
+ "aria-busy": settling === "pending" || void 0,
3818
4024
  "aria-invalid": ariaInvalid || void 0,
3819
4025
  "aria-describedby": ariaDescribedBy,
3820
4026
  ...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
3821
4027
  children: jsx(SelectValue, { placeholder: placeholder ?? t("field.select", { defaultValue: "Select…" }) })
3822
- }), jsx(SelectContent, { children: resolved.map((o) => jsx(SelectItem, {
3823
- value: o.value,
3824
- "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
3825
- description: o.summary === void 0 ? void 0 : jsx("span", {
3826
- "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
3827
- children: o.summary
4028
+ }), jsxs(SelectContent, { children: [
4029
+ current === void 0 ? null : jsx(SelectItem, {
4030
+ value: current.value,
4031
+ disabled: true,
4032
+ "data-current": "",
4033
+ "data-testid": `${tid}:current`,
4034
+ children: current.label
3828
4035
  }),
3829
- children: jsxs("span", {
3830
- className: "inline-flex items-center gap-1.5",
3831
- children: [o.icon ? jsx(Icon, {
3832
- name: o.icon,
3833
- className: "size-3.5 shrink-0 text-muted-foreground"
3834
- }) : null, o.label]
3835
- })
3836
- }, o.value)) })]
4036
+ settling === void 0 ? null : jsx(EnumSettlingRow, {
4037
+ status: settling,
4038
+ testid: tid
4039
+ }),
4040
+ resolved.map((o) => jsx(SelectItem, {
4041
+ value: o.value,
4042
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}`,
4043
+ description: o.summary === void 0 ? void 0 : jsx("span", {
4044
+ "data-testid": testid === void 0 ? void 0 : `${testid}:option:${o.value}:doc`,
4045
+ children: o.summary
4046
+ }),
4047
+ children: jsxs("span", {
4048
+ className: "inline-flex items-center gap-1.5",
4049
+ children: [o.icon ? jsx(Icon, {
4050
+ name: o.icon,
4051
+ className: "size-3.5 shrink-0 text-muted-foreground"
4052
+ }) : null, o.label]
4053
+ })
4054
+ }, o.value))
4055
+ ] })]
3837
4056
  });
3838
4057
  }
3839
4058
  //#endregion
@@ -4254,7 +4473,7 @@ function JsonInput({ name, id, value, onChange, testid, disabled, required, aria
4254
4473
  }
4255
4474
  //#endregion
4256
4475
  //#region src/fields/lazy-relation-many.tsx
4257
- const RelationManyPickerInput = lazy(() => import("./relation-many-picker-BJhaEqxz.js").then((module) => ({ default: module.RelationManyPickerInput })));
4476
+ const RelationManyPickerInput = lazy(() => import("./relation-many-picker-BlrGRwMV.js").then((module) => ({ default: module.RelationManyPickerInput })));
4258
4477
  function LazyRelationManyInput(props) {
4259
4478
  return jsx(Suspense, {
4260
4479
  fallback: jsx(Skeleton, {
@@ -4366,6 +4585,144 @@ function NumberInput({ name, id, value, onChange, testid, placeholder, disabled,
4366
4585
  });
4367
4586
  }
4368
4587
  //#endregion
4588
+ //#region src/fields/object-group.tsx
4589
+ const GROUP = "rounded-md border border-input p-3";
4590
+ function ObjectGroupInput(props) {
4591
+ const { testIds, accessibility, children } = props;
4592
+ return jsx("div", {
4593
+ role: "group",
4594
+ "data-buro-object-group": "input",
4595
+ className: cn(GROUP, "space-y-3"),
4596
+ "data-testid": testIds.input,
4597
+ id: accessibility.input,
4598
+ "aria-labelledby": accessibility.label,
4599
+ "aria-describedby": accessibility.description,
4600
+ "aria-invalid": props.issues.some((issue) => issue.severity === "error" && issue.path.length === 0) || void 0,
4601
+ "aria-errormessage": accessibility.error,
4602
+ children
4603
+ });
4604
+ }
4605
+ function ObjectGroupDisplay(props) {
4606
+ const { testIds, children } = props;
4607
+ return jsx("div", {
4608
+ role: "group",
4609
+ "data-buro-object-group": "display",
4610
+ className: cn(GROUP, "space-y-2"),
4611
+ "data-testid": testIds.display,
4612
+ children
4613
+ });
4614
+ }
4615
+ //#endregion
4616
+ //#region src/fields/repeater.tsx
4617
+ function useRepeaterTexts() {
4618
+ const t = useChromeT();
4619
+ return {
4620
+ add: t("field.repeater.add", { defaultValue: "Add" }),
4621
+ empty: t("field.repeater.empty", { defaultValue: "No items yet" }),
4622
+ remove: (position) => t("field.repeater.remove", {
4623
+ params: { position },
4624
+ defaultValue: "Remove item {{position}}"
4625
+ }),
4626
+ moveUp: (position) => t("field.repeater.moveUp", {
4627
+ params: { position },
4628
+ defaultValue: "Move item {{position}} up"
4629
+ }),
4630
+ moveDown: (position) => t("field.repeater.moveDown", {
4631
+ params: { position },
4632
+ defaultValue: "Move item {{position}} down"
4633
+ })
4634
+ };
4635
+ }
4636
+ function RepeaterInput(props) {
4637
+ const texts = useRepeaterTexts();
4638
+ const { value, renderElement, elementKeys, onAdd, onRemove, onMove, testIds, accessibility } = props;
4639
+ const root = testIds.input;
4640
+ const at = (suffix) => root === void 0 ? void 0 : `${root}:${suffix}`;
4641
+ const editable = props.disabled !== true && props.readOnly !== true;
4642
+ const canAdd = editable && onAdd !== void 0 && props.canAdd !== false;
4643
+ const canRemove = editable && onRemove !== void 0 && props.canRemove !== false;
4644
+ const last = value.length - 1;
4645
+ return jsxs("div", {
4646
+ role: "group",
4647
+ className: "space-y-2",
4648
+ "data-testid": root,
4649
+ id: accessibility.input,
4650
+ "aria-labelledby": accessibility.label,
4651
+ "aria-describedby": accessibility.description,
4652
+ "aria-errormessage": accessibility.error,
4653
+ children: [value.length === 0 ? jsx("p", {
4654
+ className: "text-sm text-muted-foreground",
4655
+ "data-testid": at("empty"),
4656
+ children: texts.empty
4657
+ }) : jsx("ol", {
4658
+ className: "space-y-2",
4659
+ children: value.map((_, index) => jsxs("li", {
4660
+ className: "flex items-start gap-2 rounded-md border border-input p-3",
4661
+ "data-testid": at(`item:${index}`),
4662
+ children: [jsx("div", {
4663
+ className: "min-w-0 flex-1",
4664
+ children: renderElement?.(index)
4665
+ }), onMove === void 0 && onRemove === void 0 ? null : jsxs("div", {
4666
+ className: "flex shrink-0 gap-1",
4667
+ children: [onMove === void 0 ? null : jsxs(Fragment$1, { children: [jsx(Button, {
4668
+ type: "button",
4669
+ variant: "ghost",
4670
+ size: "icon",
4671
+ "aria-label": texts.moveUp(index + 1),
4672
+ disabled: !editable || index === 0,
4673
+ "data-testid": at(`up:${index}`),
4674
+ onClick: () => onMove(index, index - 1),
4675
+ children: jsx(IconArrowUp, { "aria-hidden": "true" })
4676
+ }), jsx(Button, {
4677
+ type: "button",
4678
+ variant: "ghost",
4679
+ size: "icon",
4680
+ "aria-label": texts.moveDown(index + 1),
4681
+ disabled: !editable || index === last,
4682
+ "data-testid": at(`down:${index}`),
4683
+ onClick: () => onMove(index, index + 1),
4684
+ children: jsx(IconArrowDown, { "aria-hidden": "true" })
4685
+ })] }), onRemove === void 0 ? null : jsx(Button, {
4686
+ type: "button",
4687
+ variant: "ghost",
4688
+ size: "icon",
4689
+ "aria-label": texts.remove(index + 1),
4690
+ disabled: !canRemove,
4691
+ "data-testid": at(`remove:${index}`),
4692
+ onClick: () => onRemove(index),
4693
+ children: jsx(IconTrash, { "aria-hidden": "true" })
4694
+ })]
4695
+ })]
4696
+ }, elementKeys?.[index] ?? index))
4697
+ }), onAdd === void 0 ? null : jsxs(Button, {
4698
+ type: "button",
4699
+ variant: "outline",
4700
+ size: "sm",
4701
+ disabled: !canAdd,
4702
+ "data-testid": at("add"),
4703
+ onClick: onAdd,
4704
+ children: [jsx(IconPlus, { "aria-hidden": "true" }), texts.add]
4705
+ })]
4706
+ });
4707
+ }
4708
+ function RepeaterDisplay(props) {
4709
+ const texts = useRepeaterTexts();
4710
+ const { value, renderElement, testIds } = props;
4711
+ if (value.length === 0) return jsx("span", {
4712
+ className: "text-muted-foreground",
4713
+ "data-testid": testIds.display,
4714
+ children: texts.empty
4715
+ });
4716
+ return jsx("ol", {
4717
+ className: "space-y-2",
4718
+ "data-testid": testIds.display,
4719
+ children: value.map((_, index) => jsx("li", {
4720
+ className: "rounded-md border border-input p-3",
4721
+ children: renderElement?.(index)
4722
+ }, index))
4723
+ });
4724
+ }
4725
+ //#endregion
4369
4726
  //#region src/fields/link-keys-display.tsx
4370
4727
  const isRecord$1 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
4371
4728
  function qualify(name) {
@@ -4695,12 +5052,13 @@ function TextareaInput({ name, id, value, onChange, testid, placeholder, disable
4695
5052
  //#region src/fields/default-renderers.ts
4696
5053
  function legacyField(props) {
4697
5054
  const name = optionFieldName(props.path);
4698
- const texts = props.field.texts;
5055
+ const { texts, zone } = props.field;
4699
5056
  return Object.freeze({
4700
5057
  name,
4701
5058
  meta: props.meta,
4702
5059
  ui: props.ui,
4703
- ...texts === void 0 ? {} : { texts }
5060
+ ...texts === void 0 ? {} : { texts },
5061
+ ...zone === void 0 ? {} : { zone }
4704
5062
  });
4705
5063
  }
4706
5064
  function legacyOptions(options, field) {
@@ -4763,9 +5121,12 @@ function input(renderer) {
4763
5121
  field: legacyField(props),
4764
5122
  resource: props.resource.id,
4765
5123
  record: props.record,
5124
+ values: props.form,
4766
5125
  relationSeeds: props.relationSeeds,
4767
5126
  fixedFilters: props.fixedFilters,
5127
+ optionSubtitle: props.optionSubtitle,
4768
5128
  metaSources: props.metaSources,
5129
+ ...props.baseline === void 0 ? {} : { baseline: props.baseline },
4769
5130
  link: props.link
4770
5131
  });
4771
5132
  };
@@ -4818,6 +5179,12 @@ function enumName(ui) {
4818
5179
  }
4819
5180
  function RegistryEnumInput(props) {
4820
5181
  const app = useOptionalApp();
5182
+ const meta = props.field.meta;
5183
+ const sources = useFieldMetaSources({
5184
+ record: props.record,
5185
+ values: props.form,
5186
+ extra: props.metaSources
5187
+ });
4821
5188
  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}`);
4822
5189
  return createElement(EnumPicker, {
4823
5190
  enumName: props.enumName,
@@ -4833,7 +5200,14 @@ function RegistryEnumInput(props) {
4833
5200
  ariaInvalid: props.issues.some(isErrorIssue),
4834
5201
  ariaDescribedBy: props.accessibility.description,
4835
5202
  ariaErrorMessage: props.accessibility.error,
4836
- ariaLabelledBy: props.accessibility.label
5203
+ ariaLabelledBy: props.accessibility.label,
5204
+ use: {
5205
+ params: enumParamsOf(meta?.enumParams),
5206
+ narrow: narrowEntriesOf(meta?.narrow),
5207
+ sources,
5208
+ mode: props.record === void 0 ? "create" : "edit",
5209
+ baseline: props.baseline ?? props.record
5210
+ }
4837
5211
  });
4838
5212
  }
4839
5213
  function enumAware(renderer, layout) {
@@ -4885,6 +5259,10 @@ const dateTime = {
4885
5259
  Display: DateTimeDisplay,
4886
5260
  Input: DateTimeInput
4887
5261
  };
5262
+ const time = {
5263
+ Display: TimeDisplay,
5264
+ Input: TimeInput
5265
+ };
4888
5266
  const en = {
4889
5267
  Display: EnumDisplay,
4890
5268
  Input: EnumInput
@@ -4923,6 +5301,8 @@ const shadcnFieldImplementations = Object.freeze({
4923
5301
  dateTime: scalar(dateTime),
4924
5302
  "date-time": scalar(dateTime),
4925
5303
  "default:date-time": scalar(dateTime),
5304
+ time: scalar(time),
5305
+ "default:time": scalar(time),
4926
5306
  enum: enumAware(en),
4927
5307
  json: scalar({
4928
5308
  Display: JsonDisplay,
@@ -4936,7 +5316,17 @@ const shadcnFieldImplementations = Object.freeze({
4936
5316
  richText: scalar(rich, { size: "full" }),
4937
5317
  "rich-text": scalar(rich, { size: "full" }),
4938
5318
  "default:rich-text": scalar(rich, { size: "full" }),
4939
- file: scalarOrCollection(file, { size: "full" })
5319
+ file: scalarOrCollection(file, { size: "full" }),
5320
+ object: Object.freeze({
5321
+ Input: ObjectGroupInput,
5322
+ Display: ObjectGroupDisplay,
5323
+ chrome: true
5324
+ }),
5325
+ array: Object.freeze({
5326
+ CollectionInput: RepeaterInput,
5327
+ CollectionDisplay: RepeaterDisplay,
5328
+ chrome: true
5329
+ })
4940
5330
  });
4941
5331
  //#endregion
4942
5332
  //#region src/forms/declarative-display.tsx
@@ -5166,7 +5556,8 @@ const OPERATOR_LABELS = {
5166
5556
  has: "has",
5167
5557
  hasAny: "has any of",
5168
5558
  hasAll: "has all of",
5169
- hasNone: "has none of"
5559
+ hasNone: "has none of",
5560
+ some: "has an item where"
5170
5561
  };
5171
5562
  function formatOperatorLabel(op, chromeT) {
5172
5563
  return chromeT ? chromeT(`filters.operators.${op}`, { defaultValue: OPERATOR_LABELS[op] }) : OPERATOR_LABELS[op];
@@ -5700,6 +6091,7 @@ function PeekRecord({ target, testid, row }) {
5700
6091
  function DeclaredPeekBody({ target, testid, record, frameRecord, def, capabilityFor, fieldVisible, view: View, builtin, open, openable, t }) {
5701
6092
  const host = useContext(PeekHostContext);
5702
6093
  const title = recordDisplayName(record, def?.displayField);
6094
+ const subtitle = useRecordSubtitle(target)(record) ?? void 0;
5703
6095
  const setLabel = host?.setLabel;
5704
6096
  useEffect(() => setLabel?.(title), [setLabel, title]);
5705
6097
  const controller = useFormController({
@@ -5735,6 +6127,7 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5735
6127
  children: [builtin ? jsx(PeekTitle, {
5736
6128
  testid,
5737
6129
  title,
6130
+ subtitle,
5738
6131
  open: openable ? open : void 0
5739
6132
  }) : null, jsx(Suspense, {
5740
6133
  fallback: null,
@@ -5747,11 +6140,26 @@ function DeclaredPeekBody({ target, testid, record, frameRecord, def, capability
5747
6140
  })]
5748
6141
  });
5749
6142
  }
5750
- function PeekTitle({ testid, title, open }) {
5751
- if (open === void 0) return jsx("p", {
6143
+ function PeekTitle({ testid, title, subtitle, open }) {
6144
+ const heading = open === void 0 ? jsx("p", {
5752
6145
  className: "text-sm font-semibold",
5753
6146
  children: title
6147
+ }) : jsx(PeekTitleButton, {
6148
+ testid,
6149
+ title,
6150
+ open
6151
+ });
6152
+ if (subtitle === void 0) return heading;
6153
+ return jsxs("div", {
6154
+ className: "flex flex-col gap-0.5",
6155
+ children: [heading, jsx("p", {
6156
+ "data-testid": `${testid}:subtitle`,
6157
+ className: "text-xs text-muted-foreground",
6158
+ children: subtitle
6159
+ })]
5754
6160
  });
6161
+ }
6162
+ function PeekTitleButton({ testid, title, open }) {
5755
6163
  return jsx("button", {
5756
6164
  type: "button",
5757
6165
  "data-testid": `${testid}:title`,
@@ -5779,6 +6187,8 @@ function DefaultPeekBody({ target, testid, row, open }) {
5779
6187
  const projected = useProjectedRecord(target, dtoRow);
5780
6188
  const record = projected.value ?? {};
5781
6189
  const title = recordDisplayName(record, def?.displayField);
6190
+ const subtitleOf = useRecordSubtitle(target);
6191
+ const subtitle = projected.status === "ready" ? subtitleOf(record) ?? void 0 : void 0;
5782
6192
  const setLabel = host?.setLabel;
5783
6193
  useEffect(() => setLabel?.(title), [setLabel, title]);
5784
6194
  const columns = useMemo(() => {
@@ -5810,6 +6220,7 @@ function DefaultPeekBody({ target, testid, row, open }) {
5810
6220
  children: [jsx(PeekTitle, {
5811
6221
  testid,
5812
6222
  title,
6223
+ subtitle,
5813
6224
  open
5814
6225
  }), columns.length === 0 ? null : jsx("dl", {
5815
6226
  className: "grid gap-1.5",