@burojs/ui-shadcn 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/{bulk-summary-2HLgz7Il.cjs → bulk-summary-Chc61Pyw.cjs} +9 -7
  2. package/dist/bulk-summary-Chc61Pyw.cjs.map +1 -0
  3. package/dist/{bulk-summary-D6A0ua21.js → bulk-summary-DpSQD2Fq.js} +9 -7
  4. package/dist/bulk-summary-DpSQD2Fq.js.map +1 -0
  5. package/dist/{candidates-relation-picker-CGXItMN0.js → candidates-relation-picker-DRsHKe6N.js} +3 -3
  6. package/dist/{candidates-relation-picker-CGXItMN0.js.map → candidates-relation-picker-DRsHKe6N.js.map} +1 -1
  7. package/dist/{candidates-relation-picker-C47mF260.cjs → candidates-relation-picker-GIxsp7D_.cjs} +3 -3
  8. package/dist/{candidates-relation-picker-C47mF260.cjs.map → candidates-relation-picker-GIxsp7D_.cjs.map} +1 -1
  9. package/dist/{check-confirm-dialog-BT04Mieo.cjs → check-confirm-dialog-BMSb7wFv.cjs} +76 -9
  10. package/dist/check-confirm-dialog-BMSb7wFv.cjs.map +1 -0
  11. package/dist/{check-confirm-dialog-CtiRzOAt.js → check-confirm-dialog-B_u3YVHS.js} +72 -11
  12. package/dist/{check-confirm-dialog-CtiRzOAt.js.map → check-confirm-dialog-B_u3YVHS.js.map} +1 -1
  13. package/dist/{filter-builder-z3Axzf9Y.js → filter-builder-DX-xC3Yd.js} +14 -6
  14. package/dist/filter-builder-DX-xC3Yd.js.map +1 -0
  15. package/dist/{filter-builder-ByGhxLf_.cjs → filter-builder-Dt5E8PSX.cjs} +14 -6
  16. package/dist/filter-builder-Dt5E8PSX.cjs.map +1 -0
  17. package/dist/{flow-runtime-BVFjMU5-.cjs → flow-runtime-CQ4wf8co.cjs} +3 -3
  18. package/dist/{flow-runtime-BVFjMU5-.cjs.map → flow-runtime-CQ4wf8co.cjs.map} +1 -1
  19. package/dist/{flow-runtime-DrUWyTS0.js → flow-runtime-Q2vD7R3c.js} +3 -3
  20. package/dist/{flow-runtime-DrUWyTS0.js.map → flow-runtime-Q2vD7R3c.js.map} +1 -1
  21. package/dist/{flow-screen-3fk6J33y.js → flow-screen-B1y2yizP.js} +68 -29
  22. package/dist/flow-screen-B1y2yizP.js.map +1 -0
  23. package/dist/{flow-screen-6y5E_HT6.cjs → flow-screen-sw2cP70t.cjs} +67 -28
  24. package/dist/flow-screen-sw2cP70t.cjs.map +1 -0
  25. package/dist/index.cjs +2304 -247
  26. package/dist/index.cjs.map +1 -1
  27. package/dist/index.d.cts +119 -12
  28. package/dist/index.d.ts +119 -12
  29. package/dist/index.js +2225 -172
  30. package/dist/index.js.map +1 -1
  31. package/dist/{inline-flow-host-C4KmZIYE.cjs → inline-flow-host-CkhoA69R.cjs} +3 -3
  32. package/dist/{inline-flow-host-C4KmZIYE.cjs.map → inline-flow-host-CkhoA69R.cjs.map} +1 -1
  33. package/dist/{inline-flow-host-YnnvWjdU.js → inline-flow-host-DqbXqcPS.js} +3 -3
  34. package/dist/{inline-flow-host-YnnvWjdU.js.map → inline-flow-host-DqbXqcPS.js.map} +1 -1
  35. package/dist/{lazy-relation-picker-dialog-DN4bvQfg.js → lazy-relation-picker-dialog-BaIEWLbF.js} +3 -52
  36. package/dist/lazy-relation-picker-dialog-BaIEWLbF.js.map +1 -0
  37. package/dist/{lazy-relation-picker-dialog-BAKBRn3V.cjs → lazy-relation-picker-dialog-CeRzOAi0.cjs} +3 -52
  38. package/dist/lazy-relation-picker-dialog-CeRzOAi0.cjs.map +1 -0
  39. package/dist/{page-flow-route-CtEfqAvU.js → page-flow-route-CP7cS7FY.js} +7 -7
  40. package/dist/page-flow-route-CP7cS7FY.js.map +1 -0
  41. package/dist/{page-flow-route-DEjAxHe3.cjs → page-flow-route-UDx8qvdM.cjs} +10 -10
  42. package/dist/page-flow-route-UDx8qvdM.cjs.map +1 -0
  43. package/dist/{place-node-Bhl8B3fF.cjs → place-node-C5ZmuHaN.cjs} +208 -55
  44. package/dist/place-node-C5ZmuHaN.cjs.map +1 -0
  45. package/dist/{place-node-BdxT-30h.js → place-node-DwWAigv0.js} +205 -58
  46. package/dist/place-node-DwWAigv0.js.map +1 -0
  47. package/dist/record-trail-store-Cjo9vtod.cjs +126 -0
  48. package/dist/record-trail-store-Cjo9vtod.cjs.map +1 -0
  49. package/dist/record-trail-store-Dn6bVry4.js +91 -0
  50. package/dist/record-trail-store-Dn6bVry4.js.map +1 -0
  51. package/dist/{related-list-cards-Bc_vfCE_.cjs → related-list-cards-BypKfm9t.cjs} +3 -3
  52. package/dist/{related-list-cards-Bc_vfCE_.cjs.map → related-list-cards-BypKfm9t.cjs.map} +1 -1
  53. package/dist/{related-list-cards-BvkD5OcC.js → related-list-cards-Dcmruy09.js} +3 -3
  54. package/dist/{related-list-cards-BvkD5OcC.js.map → related-list-cards-Dcmruy09.js.map} +1 -1
  55. package/dist/{related-list-timeline-k0DtnxTs.cjs → related-list-timeline-D-KClgKb.cjs} +4 -4
  56. package/dist/related-list-timeline-D-KClgKb.cjs.map +1 -0
  57. package/dist/{related-list-timeline-DCrwN9oO.js → related-list-timeline-DZON_qSc.js} +4 -4
  58. package/dist/related-list-timeline-DZON_qSc.js.map +1 -0
  59. package/dist/{related-rows-BW9Jr07T.cjs → related-rows-DgF05ssi.cjs} +4 -4
  60. package/dist/{related-rows-BW9Jr07T.cjs.map → related-rows-DgF05ssi.cjs.map} +1 -1
  61. package/dist/{related-rows-CPE-9FFr.js → related-rows-ETZl5CB9.js} +4 -4
  62. package/dist/{related-rows-CPE-9FFr.js.map → related-rows-ETZl5CB9.js.map} +1 -1
  63. package/dist/{relation-create-DDEYcKfw.cjs → relation-create-B8zngAcA.cjs} +82 -13
  64. package/dist/relation-create-B8zngAcA.cjs.map +1 -0
  65. package/dist/{relation-create-C43cdPQt.js → relation-create-CeCWyxIb.js} +79 -16
  66. package/dist/relation-create-CeCWyxIb.js.map +1 -0
  67. package/dist/{relation-many-picker-BlrGRwMV.js → relation-many-picker-CT7nKfE2.js} +12 -10
  68. package/dist/relation-many-picker-CT7nKfE2.js.map +1 -0
  69. package/dist/{relation-many-picker-Br-zBHxT.cjs → relation-many-picker-Cq0EHY5I.cjs} +12 -10
  70. package/dist/relation-many-picker-Cq0EHY5I.cjs.map +1 -0
  71. package/dist/{relation-picker-x7P5HKie.js → relation-picker-CCyuMeGq.js} +13 -10
  72. package/dist/relation-picker-CCyuMeGq.js.map +1 -0
  73. package/dist/{relation-picker-ADjxI_TI.cjs → relation-picker-DmwTzgsd.cjs} +13 -10
  74. package/dist/relation-picker-DmwTzgsd.cjs.map +1 -0
  75. package/dist/{relation-picker-dialog-CyKliBkN.js → relation-picker-dialog-CoWKjNv8.js} +5 -5
  76. package/dist/relation-picker-dialog-CoWKjNv8.js.map +1 -0
  77. package/dist/{relation-picker-dialog-DimVQF9Y.cjs → relation-picker-dialog-mbwyNK43.cjs} +5 -5
  78. package/dist/relation-picker-dialog-mbwyNK43.cjs.map +1 -0
  79. package/dist/{relation-select-Cr3CfNLy.cjs → relation-select-CguIo2M5.cjs} +2 -2
  80. package/dist/{relation-select-Cr3CfNLy.cjs.map → relation-select-CguIo2M5.cjs.map} +1 -1
  81. package/dist/{relation-select-B8Fq4o-t.js → relation-select-nAYxhopN.js} +2 -2
  82. package/dist/{relation-select-B8Fq4o-t.js.map → relation-select-nAYxhopN.js.map} +1 -1
  83. package/dist/{success-notices-Dl3M1fZP.cjs → success-notices-Cl4b6MLQ.cjs} +3 -2
  84. package/dist/success-notices-Cl4b6MLQ.cjs.map +1 -0
  85. package/dist/{success-notices-LDEgEkc4.js → success-notices-CrcWOGSo.js} +3 -2
  86. package/dist/success-notices-CrcWOGSo.js.map +1 -0
  87. package/dist/{use-dialog-filter-state-tNvqAAjh.cjs → use-dialog-filter-state-CpWblz3C.cjs} +2 -2
  88. package/dist/{use-dialog-filter-state-tNvqAAjh.cjs.map → use-dialog-filter-state-CpWblz3C.cjs.map} +1 -1
  89. package/dist/{use-dialog-filter-state-B_MqzHaT.js → use-dialog-filter-state-ZYxOp5WO.js} +2 -2
  90. package/dist/{use-dialog-filter-state-B_MqzHaT.js.map → use-dialog-filter-state-ZYxOp5WO.js.map} +1 -1
  91. package/dist/{use-record-subtitle-bfwIoUme.cjs → use-record-subtitle-B4lTR7pf.cjs} +5 -8
  92. package/dist/use-record-subtitle-B4lTR7pf.cjs.map +1 -0
  93. package/dist/{use-record-subtitle-gIaCGgbI.js → use-record-subtitle-pWMBqQx9.js} +5 -8
  94. package/dist/use-record-subtitle-pWMBqQx9.js.map +1 -0
  95. package/package.json +9 -9
  96. package/dist/bulk-summary-2HLgz7Il.cjs.map +0 -1
  97. package/dist/bulk-summary-D6A0ua21.js.map +0 -1
  98. package/dist/check-confirm-dialog-BT04Mieo.cjs.map +0 -1
  99. package/dist/filter-builder-ByGhxLf_.cjs.map +0 -1
  100. package/dist/filter-builder-z3Axzf9Y.js.map +0 -1
  101. package/dist/flow-screen-3fk6J33y.js.map +0 -1
  102. package/dist/flow-screen-6y5E_HT6.cjs.map +0 -1
  103. package/dist/lazy-relation-picker-dialog-BAKBRn3V.cjs.map +0 -1
  104. package/dist/lazy-relation-picker-dialog-DN4bvQfg.js.map +0 -1
  105. package/dist/page-flow-route-CtEfqAvU.js.map +0 -1
  106. package/dist/page-flow-route-DEjAxHe3.cjs.map +0 -1
  107. package/dist/place-node-BdxT-30h.js.map +0 -1
  108. package/dist/place-node-Bhl8B3fF.cjs.map +0 -1
  109. package/dist/related-list-timeline-DCrwN9oO.js.map +0 -1
  110. package/dist/related-list-timeline-k0DtnxTs.cjs.map +0 -1
  111. package/dist/relation-create-C43cdPQt.js.map +0 -1
  112. package/dist/relation-create-DDEYcKfw.cjs.map +0 -1
  113. package/dist/relation-many-picker-BlrGRwMV.js.map +0 -1
  114. package/dist/relation-many-picker-Br-zBHxT.cjs.map +0 -1
  115. package/dist/relation-picker-ADjxI_TI.cjs.map +0 -1
  116. package/dist/relation-picker-dialog-CyKliBkN.js.map +0 -1
  117. package/dist/relation-picker-dialog-DimVQF9Y.cjs.map +0 -1
  118. package/dist/relation-picker-x7P5HKie.js.map +0 -1
  119. package/dist/resource-page-router-BRpUnhay.js +0 -1958
  120. package/dist/resource-page-router-BRpUnhay.js.map +0 -1
  121. package/dist/resource-page-router-qEd2xb55.cjs +0 -2167
  122. package/dist/resource-page-router-qEd2xb55.cjs.map +0 -1
  123. package/dist/success-notices-Dl3M1fZP.cjs.map +0 -1
  124. package/dist/success-notices-LDEgEkc4.js.map +0 -1
  125. package/dist/use-record-subtitle-bfwIoUme.cjs.map +0 -1
  126. package/dist/use-record-subtitle-gIaCGgbI.js.map +0 -1
@@ -2,8 +2,8 @@ import { l as cn } from "./use-theme-dnE3Od3I.js";
2
2
  import { a as technicalText, l as useLinkComponent, n as toast, o as technicalTexts, r as friendlyStringsFrom, s as toFriendlyError } from "./toaster-Ct_YHGs6.js";
3
3
  import { n as buttonVariants, t as Button } from "./button-MWVeZaqj.js";
4
4
  import { i as DialogDescription, r as DialogContent, s as DialogTitle, t as Dialog } from "./dialog-C123sVQ8.js";
5
- import { composeListFilter, hasRecordPage, normalizeDataError, normalizeFixedFilters, relationAmbiguousError, relationOpenOf, resourceKey, resourceShowHref, routeResourceKey } from "@burojs/core";
6
- import { PEEK_COMPONENT, QUICK_ANCHOR_ATTRIBUTE, filterFields, quickAnchorRef, specificErrorText, useApp, useChromeT, useCurrentUIActivation, useEntryGate, useI18nCaps, useList, useListAccess, useLoadErrorView, useOptionalT, useQuick, useQuickOpener, useRelatedRecord, useRouteNavigate, useT, useTestIds, useUIPresentationRuntime } from "@burojs/react";
5
+ import { composeListFilter, hasRecordPage, normalizeDataError, normalizeFixedFilters, relationAmbiguousError, relationOpenOf, resolveEnumLabel, resourceKey, resourceShowHref, routeResourceKey } from "@burojs/core";
6
+ import { PEEK_COMPONENT, QUICK_ANCHOR_ATTRIBUTE, collectionRowHref, filterFields, quickAnchorRef, specificErrorText, useApp, useAvailabilityGate, useChromeT, useCollectionRows, useCurrentUIActivation, useEntryGate, useI18nCaps, useList, useListAccess, useLoadErrorView, useOptionalT, useQuick, useQuickOpener, useRelatedRecord, useRouteNavigate, useT, useTestIds, useUIPresentationRuntime } from "@burojs/react";
7
7
  import { IconAlertCircle, IconEye, IconRefresh, IconSearch } from "@tabler/icons-react";
8
8
  import * as React from "react";
9
9
  import { Component, createContext, useCallback, useContext, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";
@@ -365,11 +365,39 @@ function recordDisplayName(record, displayField) {
365
365
  return String(record.id ?? "");
366
366
  }
367
367
  //#endregion
368
+ //#region src/resource/visible-row.ts
369
+ function visibleRow(def, access, row) {
370
+ if (access.status !== "ready") return void 0;
371
+ const idField = def?.data?.idField || "id";
372
+ const visible = {};
373
+ for (const name of Object.keys(def?.fields ?? {})) if (Object.hasOwn(row, name) && access.fieldVisible(name)) visible[name] = row[name];
374
+ if (Object.hasOwn(row, idField)) visible[idField] = row[idField];
375
+ return visible;
376
+ }
377
+ //#endregion
368
378
  //#region src/resource/use-row-title.ts
369
- function useRowTitle(target, displayField) {
379
+ function useRowTitle(target, displayField, options) {
380
+ const app = useApp();
370
381
  const access = useListAccess(target);
382
+ const caps = useI18nCaps(target);
383
+ const def = app.registry.get(target);
384
+ const hook = options?.recordTitle === true && displayField === def?.displayField ? def?.recordTitle : void 0;
371
385
  const visible = displayField !== void 0 && access.status === "ready" && access.fieldVisible(displayField);
372
- return useCallback((row) => recordDisplayName(row, visible ? displayField : void 0), [visible, displayField]);
386
+ return useCallback((row) => {
387
+ const narrowed = hook === void 0 ? void 0 : visibleRow(def, access, row);
388
+ if (hook !== void 0 && narrowed !== void 0) {
389
+ const title = hook(narrowed, { resolveEnum: (namespace, value, inlineDefault) => resolveEnumLabel(caps, namespace, value, inlineDefault) });
390
+ if (typeof title === "string" && title.trim() !== "") return title;
391
+ }
392
+ return recordDisplayName(row, visible ? displayField : void 0);
393
+ }, [
394
+ hook,
395
+ access,
396
+ def,
397
+ caps,
398
+ visible,
399
+ displayField
400
+ ]);
373
401
  }
374
402
  //#endregion
375
403
  //#region src/quick/peek-context.ts
@@ -791,6 +819,8 @@ function RelationDisplayBody({ to, by, id, idStr, app, open: openMode, quickTarg
791
819
  const baseId = `relation-display:${to}:${idStr}`;
792
820
  const RouterLink = useLinkComponent();
793
821
  const open = useQuickOpener();
822
+ const gate = useEntryGate();
823
+ const collectionRow = useCollectionRows(to);
794
824
  const { record, isLoading, error, ambiguous } = useRelatedRecord(to, id, by === void 0 ? void 0 : { by });
795
825
  if (!targetDef) {
796
826
  if (process.env.NODE_ENV !== "production") console.warn(`[RelationDisplay] target resource '${to}' not registered — rendering raw value '${idStr}'`);
@@ -837,7 +867,9 @@ function RelationDisplayBody({ to, by, id, idStr, app, open: openMode, quickTarg
837
867
  className: "text-muted-foreground",
838
868
  children: displayName
839
869
  });
840
- const href = linksToPage(app, targetDef) ? resourceShowHref(app.registry, targetDef, to, String(rowId)) : null;
870
+ const kind = collectionRow?.(record);
871
+ const member = kind !== void 0 && "member" in kind ? kind.member : void 0;
872
+ const href = linksToPage(app, (member === void 0 ? void 0 : app.registry.get(member)) ?? targetDef) ? resourceShowHref(app.registry, targetDef, to, String(rowId), record) : null;
841
873
  if (openMode === "none") return jsx("span", {
842
874
  "data-testid": baseId,
843
875
  children: displayName
@@ -850,6 +882,21 @@ function RelationDisplayBody({ to, by, id, idStr, app, open: openMode, quickTarg
850
882
  open,
851
883
  children: displayName
852
884
  });
885
+ if (collectionRow !== void 0) {
886
+ const answer = gate(to, "show", record);
887
+ if (answer.state === "hidden" || answer.state === "disabled" || answer.state === "undecided") return jsx("span", {
888
+ "data-testid": `${baseId}:text`,
889
+ children: idStr
890
+ });
891
+ if (member !== void 0 && answer.state === "open" && openMode === "quick") return jsx(RowOpener, {
892
+ to: answer.target,
893
+ rowId: String(rowId),
894
+ href,
895
+ testid: baseId,
896
+ open,
897
+ children: displayName
898
+ });
899
+ }
853
900
  if (href === null) return jsx("span", {
854
901
  "data-testid": baseId,
855
902
  children: displayName
@@ -968,16 +1015,20 @@ const TITLE_CLASS = "min-w-0 max-w-[16rem] truncate";
968
1015
  const TITLE_VIEW_CLASS = cn(TITLE_CLASS, "cursor-pointer rounded-sm text-left hover:underline focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring");
969
1016
  function RelationViewButton(props) {
970
1017
  const gate = useEntryGate();
1018
+ const availability = useAvailabilityGate("show");
971
1019
  const { to, value, by } = props;
1020
+ const collection = useCollectionRows(to) !== void 0;
972
1021
  const access = useListAccess(to);
973
1022
  const key = selectKey(value);
974
1023
  const plain = plainTitle(props.title);
975
1024
  if (key === null || props.open === "none") return plain;
976
1025
  if (by !== void 0 && !(access.status === "ready" && access.fieldVisible(by))) return plain;
977
- if (gate(to, "show").state !== "open") return plain;
1026
+ const answer = gate(to, "show");
1027
+ if (!(collection ? answer.state === "absent" && availability(to, "show").state === "available" : answer.state === "open")) return plain;
978
1028
  return jsx(ViewButton, {
979
1029
  ...props,
980
- keyString: key
1030
+ keyString: key,
1031
+ collection
981
1032
  }, key);
982
1033
  }
983
1034
  function plainTitle(title) {
@@ -986,18 +1037,21 @@ function plainTitle(title) {
986
1037
  children: title
987
1038
  });
988
1039
  }
989
- function ViewButton({ to, by, fieldName, keyString, beforeOpen, open: openMode = "quick", title }) {
1040
+ function ViewButton({ to, by: byField, fieldName, keyString, beforeOpen, open: openMode = "quick", title, collection }) {
990
1041
  const app = useApp();
991
1042
  const t = useOptionalT();
992
1043
  const tid = useTestIds();
993
1044
  const quick = useQuick();
1045
+ const openQuick = useQuickOpener();
994
1046
  const navigate = useRouteNavigate();
1047
+ const availability = useAvailabilityGate("show");
995
1048
  const RouterLink = useLinkComponent();
996
1049
  const [asked, setAsked] = React.useState(false);
997
1050
  const requested = React.useRef(false);
998
1051
  const targetDef = app.registry.get(to);
999
1052
  const rawIdField = (targetDef?.data)?.idField;
1000
1053
  const idField = typeof rawIdField === "string" && rawIdField.length > 0 ? rawIdField : "id";
1054
+ const by = byField ?? (collection && openMode !== "page" ? idField : void 0);
1001
1055
  const read = useList(to, {
1002
1056
  ...asked && by !== void 0 ? {
1003
1057
  filter: {
@@ -1016,21 +1070,30 @@ function ViewButton({ to, by, fieldName, keyString, beforeOpen, open: openMode =
1016
1070
  retry: false
1017
1071
  });
1018
1072
  const rows = read.isCurrentData && !read.isPlaceholderData && !read.isFetching ? read.data?.data : void 0;
1019
- const open = React.useCallback((id) => {
1073
+ const open = React.useCallback((id, row) => {
1020
1074
  beforeOpen();
1021
1075
  if (openMode === "page") {
1022
- if (targetDef !== void 0 && linksToPage(app, targetDef)) navigate(resourceShowHref(app.registry, targetDef, to, id));
1076
+ if (targetDef !== void 0 && linksToPage(app, targetDef)) navigate(resourceShowHref(app.registry, targetDef, to, id, row));
1077
+ return;
1078
+ }
1079
+ if (!collection) {
1080
+ quick.show(to, id);
1023
1081
  return;
1024
1082
  }
1025
- quick.show(to, id);
1083
+ if (openQuick(to, id, { row }) !== "absent" || targetDef === void 0) return;
1084
+ const href = collectionRowHref(app.registry, targetDef, to, id, row, availability);
1085
+ if (href !== void 0 && href !== "") navigate(href);
1026
1086
  }, [
1027
1087
  beforeOpen,
1028
1088
  quick,
1089
+ openQuick,
1090
+ collection,
1029
1091
  to,
1030
1092
  openMode,
1031
1093
  navigate,
1032
1094
  app,
1033
- targetDef
1095
+ targetDef,
1096
+ availability
1034
1097
  ]);
1035
1098
  React.useEffect(() => {
1036
1099
  if (by === void 0 || !asked || rows === void 0 || !requested.current) return;
@@ -1041,7 +1104,7 @@ function ViewButton({ to, by, fieldName, keyString, beforeOpen, open: openMode =
1041
1104
  }
1042
1105
  const id = rows[0]?.[idField];
1043
1106
  const next = selectKey(id);
1044
- if (next !== null) open(next);
1107
+ if (next !== null) open(next, rows[0]);
1045
1108
  }, [
1046
1109
  by,
1047
1110
  asked,
@@ -1098,7 +1161,7 @@ function ViewButton({ to, by, fieldName, keyString, beforeOpen, open: openMode =
1098
1161
  if (rows !== void 0 && rows.length === 1) {
1099
1162
  const next = selectKey(rows[0]?.[idField]);
1100
1163
  requested.current = false;
1101
- if (next !== null) open(next);
1164
+ if (next !== null) open(next, rows[0]);
1102
1165
  }
1103
1166
  },
1104
1167
  children: content
@@ -1231,6 +1294,6 @@ function CreateButton({ to, fieldName, create, seeds, search, beforeOpen, classN
1231
1294
  });
1232
1295
  }
1233
1296
  //#endregion
1234
- export { CommandEmpty as C, CommandList as D, CommandItem as E, CommandLoading as O, CommandDialog as S, CommandInput as T, isPlainLeftClick as _, namesHiddenField as a, RecordState as b, RelationField as c, peekAnchorOpener as d, PeekContext as f, ClaimedQuickLink as g, recordDisplayName as h, selectKey as i, CommandSeparator as k, relationLinkClassName as l, useRowTitle as m, useSelectCreate as n, narrowSearchDecl as o, PeekHostContext as p, RelationViewButton as r, RelationDisplay as s, RelationCreateButton as t, focusWithoutPeek as u, InvalidRouteId as v, CommandGroup as w, Command$1 as x, LoadError as y };
1297
+ export { CommandSeparator as A, CommandDialog as C, CommandItem as D, CommandInput as E, CommandList as O, Command$1 as S, CommandGroup as T, ClaimedQuickLink as _, namesHiddenField as a, LoadError as b, RelationField as c, peekAnchorOpener as d, PeekContext as f, recordDisplayName as g, visibleRow as h, selectKey as i, CommandLoading as k, relationLinkClassName as l, useRowTitle as m, useSelectCreate as n, narrowSearchDecl as o, PeekHostContext as p, RelationViewButton as r, RelationDisplay as s, RelationCreateButton as t, focusWithoutPeek as u, isPlainLeftClick as v, CommandEmpty as w, RecordState as x, InvalidRouteId as y };
1235
1298
 
1236
- //# sourceMappingURL=relation-create-C43cdPQt.js.map
1299
+ //# sourceMappingURL=relation-create-CeCWyxIb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relation-create-CeCWyxIb.js","names":["Command","CommandPrimitive"],"sources":["../src/primitives/command.tsx","../src/record/record-state.tsx","../src/load-error/list-error-panel.tsx","../src/load-error/state.ts","../src/load-error/load-error-view.tsx","../src/fields/claimed-quick-link.tsx","../src/resource/record-display-name.ts","../src/resource/visible-row.ts","../src/resource/use-row-title.ts","../src/quick/peek-context.ts","../src/quick/use-peek-intent.tsx","../src/fields/relation-display.tsx","../src/fields/search-access.ts","../src/fields/relation-hand-back.tsx","../src/fields/relation-view-button.tsx","../src/fields/relation-create.tsx"],"sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { Command as CommandPrimitive } from 'cmdk';\nimport { IconSearch } from '@tabler/icons-react';\nimport { cn } from '../lib/cn.js';\nimport {\n Dialog,\n DialogContent,\n DialogTitle,\n DialogDescription,\n type DialogContentProps,\n} from './dialog.js';\n\n/**\n * Shadcn-canonical Command primitive built on `cmdk`. Provides\n * keyboard-navigable, ARIA-correct combobox/listbox semantics: arrow\n * keys to navigate items, Enter to select, type-ahead search via the\n * embedded `<CommandInput>`. Use this for any searchable list inside a\n * Popover (typeaheads, command palettes, relation pickers).\n *\n * Filter behavior: by default cmdk filters items client-side based on\n * the input text. For server-side filtering (typical for relation\n * pickers that hit `useList` with a `contains` operator), pass\n * `shouldFilter={false}` to the root `<Command>` and drive the option\n * list yourself from the server-side results.\n */\nconst Command = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive\n ref={ref}\n className={cn(\n 'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',\n className,\n )}\n {...props}\n />\n));\nCommand.displayName = CommandPrimitive.displayName;\n\nconst CommandInput = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Input>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ className, ...props }, ref) => (\n <div className=\"flex items-center border-b px-3\" cmdk-input-wrapper=\"\">\n <IconSearch className=\"mr-2 h-4 w-4 shrink-0 opacity-50\" aria-hidden=\"true\" />\n <CommandPrimitive.Input\n ref={ref}\n className={cn(\n 'flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 disabled:bg-input-disabled',\n className,\n )}\n {...props}\n />\n </div>\n));\nCommandInput.displayName = CommandPrimitive.Input.displayName;\n\nconst CommandList = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.List>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.List\n ref={ref}\n className={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}\n {...props}\n />\n));\nCommandList.displayName = CommandPrimitive.List.displayName;\n\nconst CommandEmpty = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Empty>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>\n>((props, ref) => (\n <CommandPrimitive.Empty\n ref={ref}\n className=\"py-6 text-center text-sm text-muted-foreground\"\n {...props}\n />\n));\nCommandEmpty.displayName = CommandPrimitive.Empty.displayName;\n\nconst CommandGroup = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Group>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Group\n ref={ref}\n className={cn(\n 'overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground',\n className,\n )}\n {...props}\n />\n));\nCommandGroup.displayName = CommandPrimitive.Group.displayName;\n\nconst CommandSeparator = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 h-px bg-border', className)}\n {...props}\n />\n));\nCommandSeparator.displayName = CommandPrimitive.Separator.displayName;\n\nconst CommandItem = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <CommandPrimitive.Item\n ref={ref}\n className={cn(\n \"group relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50\",\n className,\n )}\n {...props}\n />\n));\nCommandItem.displayName = CommandPrimitive.Item.displayName;\n\nexport type CommandLoadingProps = React.ComponentPropsWithoutRef<typeof CommandPrimitive.Loading>;\n\nconst CommandLoading = React.forwardRef<\n React.ElementRef<typeof CommandPrimitive.Loading>,\n CommandLoadingProps\n>(({ ...props }, ref) => <CommandPrimitive.Loading ref={ref} {...props} />);\nCommandLoading.displayName = CommandPrimitive.Loading.displayName;\n\n/**\n * Props for `<CommandDialog>`. Mirrors Radix Dialog's `Root` props\n * (`open`, `onOpenChange`, `defaultOpen`, `modal`) plus optional\n * accessibility labels and dialog-content className overrides.\n *\n * The shadcn-canonical pattern wraps a Radix `<Dialog>` around the\n * `<Command>` root so cmdk's keyboard navigation (arrow keys, Enter,\n * type-ahead) operates on the items rendered as children. We render\n * a visually-hidden `<DialogTitle>` + `<DialogDescription>` for the\n * a11y tree (Radix requires a labelled dialog or it warns at runtime).\n */\nexport interface CommandDialogProps {\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n defaultOpen?: boolean;\n modal?: boolean;\n /** Accessible title (visually hidden). Defaults to \"Command Palette\". */\n title?: string;\n /** Accessible description (visually hidden). Defaults to \"Search and run actions.\" */\n description?: string;\n /** Forwarded to the `<DialogContent>` className. */\n className?: string;\n /** Forwarded to the inner `<Command>` className. */\n commandClassName?: string;\n /** The Command groups + items + input. */\n children?: React.ReactNode;\n /** Optional dialog-content overrides (e.g. style for animations). */\n contentProps?: Omit<DialogContentProps, 'children' | 'className'>;\n}\n\n/**\n * Modal command palette. Combines Radix Dialog with cmdk's `<Command>`\n * root so adopters can compose `<CommandInput>`, `<CommandList>`,\n * `<CommandGroup>`, `<CommandItem>` as children and get focus-trapped\n * keyboard navigation out of the box.\n *\n * Usage:\n * ```tsx\n * <CommandDialog open={open} onOpenChange={setOpen}>\n * <CommandInput placeholder=\"Search…\" />\n * <CommandList>\n * <CommandEmpty>No matches.</CommandEmpty>\n * <CommandGroup heading=\"Resources\">\n * <CommandItem onSelect={...}>Documents</CommandItem>\n * </CommandGroup>\n * </CommandList>\n * </CommandDialog>\n * ```\n */\nfunction CommandDialog({\n open,\n onOpenChange,\n defaultOpen,\n modal,\n title = 'Command Palette',\n description = 'Search and run actions.',\n className,\n commandClassName,\n children,\n contentProps,\n}: CommandDialogProps) {\n return (\n <Dialog open={open} onOpenChange={onOpenChange} defaultOpen={defaultOpen} modal={modal}>\n <DialogContent\n {...contentProps}\n // Width: cap to 480px regardless of breakpoint (the shadcn default\n // `DialogContent` uses `max-w-lg` ~512px). `sm:max-w-[480px]`\n // re-asserts at the `sm` breakpoint so any built-in `sm:max-w-lg`\n // override loses to ours.\n className={cn('overflow-hidden p-0 shadow-lg max-w-[480px] sm:max-w-[480px]', className)}\n // Backdrop blur for the command palette specifically: softens\n // the underlying chrome so the palette feels like a focused\n // overlay rather than a stacked panel. Other dialogs keep the\n // shadcn-default solid backdrop.\n overlayClassName=\"backdrop-blur-sm\"\n >\n {/* Visually-hidden labels: Radix Dialog needs them for a11y, but\n the palette UI itself supplies its own search affordance. */}\n <DialogTitle className=\"sr-only\">{title}</DialogTitle>\n <DialogDescription className=\"sr-only\">{description}</DialogDescription>\n <Command\n className={cn(\n '[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5',\n commandClassName,\n )}\n >\n {children}\n </Command>\n </DialogContent>\n </Dialog>\n );\n}\nCommandDialog.displayName = 'CommandDialog';\n\nexport {\n Command,\n CommandInput,\n CommandList,\n CommandEmpty,\n CommandGroup,\n CommandItem,\n CommandSeparator,\n CommandLoading,\n CommandDialog,\n};\n","'use client';\nimport { useChromeT, useT } from '@burojs/react';\nimport type { ReactElement } from 'react';\nimport type { LoadErrorState } from '../load-error/state.js';\nimport { Button } from '../primitives/button.js';\n\nexport type RecordErrorState = LoadErrorState;\n\n/**\n * A record that is loading or cannot be shown: `record-page:loading`, or\n * `record-page:<state>` with Retry when the caller passes `onRetry`. Shared by\n * the record route and `<RecordScreen>`.\n */\nexport function RecordState({\n state,\n onRetry,\n message: given,\n}: {\n readonly state: RecordErrorState | 'loading';\n readonly onRetry?: () => void;\n /** The sentence to show instead of the state's `router.record*` text (a load error's own). */\n readonly message?: string;\n}): ReactElement {\n const t = useT();\n const chromeT = useChromeT();\n if (state === 'loading') {\n return (\n <div\n role=\"status\"\n aria-busy=\"true\"\n data-testid=\"record-page:loading\"\n className=\"p-6 text-sm text-muted-foreground\"\n >\n {t('router.recordLoading')}\n </div>\n );\n }\n const message =\n given ??\n (state === 'not-found'\n ? t('record.notFoundOrNoAccess')\n : state === 'session-expired'\n ? t('router.recordSessionExpired')\n : t('router.recordError'));\n return (\n <div\n // A failed read is announced; loading stays a polite `status`.\n role=\"alert\"\n data-testid={`record-page:${state}`}\n className=\"flex flex-col items-center justify-center gap-3 px-6 py-24 text-center\"\n >\n <p className=\"max-w-sm text-sm text-muted-foreground\">{message}</p>\n {onRetry ? (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n data-testid=\"record-page:retry\"\n onClick={onRetry}\n >\n {chromeT('actions.retry')}\n </Button>\n ) : null}\n </div>\n );\n}\n","'use client';\nimport { useChromeT, useOptionalT, useT } from '@burojs/react';\nimport { IconAlertCircle, IconRefresh } from '@tabler/icons-react';\nimport { cn } from '../lib/cn.js';\nimport { Button } from '../primitives/button.js';\nimport type { ListErrorStateProps } from '../resource/list-error-state.js';\n\n/**\n * The kit's default `list` load-error view: the panel `<ListErrorState>` draws. Its sentence is\n * the load error's one text (`useLoadErrorText`, the rule every surface shares); the technical\n * text is shown under Details in development only.\n */\nexport function ListErrorPanel({\n text,\n technical,\n onRetry,\n resource,\n title,\n className,\n}: Omit<ListErrorStateProps, 'error'> & {\n /** The sentence the user reads. */\n readonly text: string;\n /** The failure's first technical text, for whoever diagnoses it. */\n readonly technical?: string | undefined;\n}): React.ReactElement {\n // `useT()` keeps this panel provider-only (it throws without a BuroProvider) and subscribes\n // to the locale; `useOptionalT()` is the translator that honours a `defaultValue`.\n useT();\n const t = useOptionalT();\n const chromeT = useChromeT();\n const raw = process.env.NODE_ENV === 'production' ? undefined : technical;\n\n return (\n <div\n role=\"alert\"\n className={cn(\n 'flex flex-col items-center justify-center gap-3 px-6 py-16 rounded-lg border border-destructive/40 bg-destructive/5 text-center',\n className,\n )}\n data-testid=\"error\"\n >\n <div className=\"rounded-full bg-destructive/10 p-3 text-destructive\">\n <IconAlertCircle className=\"size-6\" aria-hidden=\"true\" />\n </div>\n <div className=\"space-y-1\">\n <h3 className=\"text-base font-semibold tracking-tight text-destructive\">\n {title ?? t('list.errorTitle')}\n </h3>\n <p className=\"max-w-md text-sm text-muted-foreground\">{text}</p>\n </div>\n {/*\n The raw string still matters — to whoever has to diagnose it, not to\n the operator staring at a broken page. Collapsed, and only when it\n actually differs from what is already shown.\n */}\n {raw && raw !== text ? (\n <details className=\"max-w-md text-left\">\n <summary className=\"cursor-pointer text-xs text-muted-foreground hover:text-foreground\">\n {t('list.errorDetails')}\n </summary>\n <p\n className=\"mt-1.5 break-all font-mono text-xs text-muted-foreground\"\n data-testid=\"list-error-detail\"\n >\n {raw}\n </p>\n </details>\n ) : null}\n {onRetry && (\n <div className=\"flex justify-center pt-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"sm\"\n data-testid={resource ? `list-error-retry:${resource}` : 'list-error-retry'}\n onClick={onRetry}\n className=\"gap-1.5\"\n >\n <IconRefresh className=\"size-3.5\" aria-hidden=\"true\" />\n {chromeT('actions.retry')}\n </Button>\n </div>\n )}\n </div>\n );\n}\n","import { normalizeDataError } from '@burojs/core';\nimport type { LoadErrorViewProps } from '@burojs/react';\n\n/** The state a failed read renders: {@link LoadErrorViewProps.state}. */\nexport type LoadErrorState = LoadErrorViewProps['state'];\n\n/**\n * The state a failed read renders. `not-found` and `forbidden` render\n * identically (no existence oracle). `auth` is a session-expired state with no\n * Retry: the session failed rather than the request, and the runtime's auth\n * controller has already tried to recover. Every other kind — including an\n * error of no recognisable shape, which normalizes to `transport` — is the\n * error state with Retry. The mapping is the providers' job, never a status\n * fallback here.\n */\nexport function recordErrorState(error: unknown): LoadErrorState {\n const { kind } = normalizeDataError(error);\n if (kind === 'not-found' || kind === 'forbidden') return 'not-found';\n if (kind === 'auth') return 'session-expired';\n return 'error';\n}\n","'use client';\nimport { type DataError, normalizeDataError } from '@burojs/core';\nimport {\n type LoadErrorViewProps,\n specificErrorText,\n useChromeT,\n useI18nCaps,\n useLoadErrorView,\n useOptionalT,\n} from '@burojs/react';\nimport { Component, type ErrorInfo, type ReactElement, type ReactNode, useMemo } from 'react';\nimport { cn } from '../lib/cn.js';\nimport { friendlyStringsFrom, technicalTexts, toFriendlyError } from '../lib/friendly-error.js';\nimport { Button } from '../primitives/button.js';\nimport { RecordState } from '../record/record-state.js';\nimport { ListErrorPanel } from './list-error-panel.js';\nimport { type LoadErrorState, recordErrorState } from './state.js';\n\n/** The text a surface falls back to, when no specific text of the error answers (spec 4.15, kind tier). */\nexport interface LoadErrorFallback {\n readonly key: string;\n readonly default: string;\n}\n\nexport interface LoadErrorProps {\n /** Whatever the read threw; the app's view receives it normalized. */\n readonly error: unknown;\n readonly surface: LoadErrorViewProps['surface'];\n readonly resource?: string;\n /** The state to render; derived from the error's kind when omitted. */\n readonly state?: LoadErrorState;\n /** The Retry the surface offers; the kit passes it on for the `'error'` state only. */\n readonly retry?: () => void;\n /** The sentence a surface falls back to (record: `router.record*`, by state). */\n readonly fallback?: LoadErrorFallback;\n /** The default view's test id (a compact surface keeps the id it always had). */\n readonly testId?: string;\n readonly className?: string;\n /** A compact surface's visible content; the sentence is its `title`. */\n readonly children?: ReactNode;\n /** The `list` surface's heading override. */\n readonly title?: string;\n /** Extra DOM attributes for the default alert (a screen node's `data-buro-*`). */\n readonly attributes?: Readonly<Record<string, string | undefined>>;\n}\n\n/** What the kit's default view reads besides the view props. */\ntype DefaultViewProps = LoadErrorViewProps & {\n readonly original: unknown;\n readonly fallback: LoadErrorFallback | undefined;\n readonly testId: string | undefined;\n readonly className: string | undefined;\n readonly title: string | undefined;\n readonly attributes: LoadErrorProps['attributes'];\n readonly children?: ReactNode;\n};\n\nconst RECORD_KEYS: Record<LoadErrorState, string> = {\n 'not-found': 'record.notFoundOrNoAccess',\n 'session-expired': 'router.recordSessionExpired',\n error: 'router.recordError',\n};\n\n/** The list surface's sentence for a failure with no text of its own. */\nconst LIST_FALLBACK: LoadErrorFallback = {\n key: 'list.errorBody',\n default: 'Failed to load data. Please try again.',\n};\n\n/**\n * Every developer-facing text of a failed read: the normalized error's (`details`, `cause`), then\n * the value as thrown (a legacy object's string `message`). For the friendly sentence and the\n * development details only; never the sentence itself.\n */\nexport function loadErrorTechnicalTexts(error: DataError, original: unknown): readonly string[] {\n const out = [...technicalTexts(error), ...technicalTexts(original)];\n if (original !== null && typeof original === 'object' && !(original instanceof Error)) {\n const message = (original as { readonly message?: unknown }).message;\n if (typeof message === 'string') out.push(message);\n }\n return out.filter((text, index) => text.length > 0 && out.indexOf(text) === index);\n}\n\n/**\n * The one sentence of a load error on every surface (spec 4.15 and 4.16). Not-found and forbidden\n * read the not-found sentence and never the error's own text, so no surface tells a missing record\n * from a forbidden one; an expired session reads the session sentence. Every other failure reads\n * the error's own text (the code's, the provider's reference), then the plain-language sentence of\n * a dead network or an unavailable service recognised in its technical text, then the surface's\n * sentence. Technical text itself is never the sentence.\n */\nfunction useLoadErrorText(\n error: DataError,\n original: unknown,\n state: LoadErrorState,\n surface: LoadErrorViewProps['surface'],\n fallback: LoadErrorFallback | undefined,\n): string {\n const t = useOptionalT();\n const caps = useI18nCaps();\n if (state !== 'error') return t(RECORD_KEYS[state]);\n const own = specificErrorText(error, caps);\n if (own !== undefined) return own;\n const strings = friendlyStringsFrom(t);\n for (const text of loadErrorTechnicalTexts(error, original)) {\n const friendly = toFriendlyError(text, '', strings);\n // \"Please try again.\" alone says less than the surface's own sentence.\n if (friendly.replaced && friendly.detail !== strings.generic) return friendly.detail;\n }\n const generic = surface === 'list' ? (fallback ?? LIST_FALLBACK) : fallback;\n if (surface === 'record' || generic === undefined) return t(RECORD_KEYS.error);\n return t(generic.key, { defaultValue: generic.default });\n}\n\n/** The kit's view of a load error, for every surface. */\nfunction DefaultLoadErrorView(props: DefaultViewProps): ReactElement {\n const {\n error,\n surface,\n state,\n retry,\n original,\n fallback,\n testId,\n className,\n children,\n attributes,\n } = props;\n const text = useLoadErrorText(error, original, state, surface, fallback);\n const chromeT = useChromeT();\n if (surface === 'record') {\n return (\n <RecordState\n state={state}\n message={text}\n {...(retry === undefined ? {} : { onRetry: retry })}\n />\n );\n }\n if (surface === 'list') {\n return (\n <ListErrorPanel\n text={text}\n technical={loadErrorTechnicalTexts(error, original)[0]}\n {...(retry === undefined ? {} : { onRetry: retry })}\n {...(props.resource === undefined ? {} : { resource: props.resource })}\n {...(props.title === undefined ? {} : { title: props.title })}\n {...(className === undefined ? {} : { className })}\n />\n );\n }\n if (surface === 'relation' || surface === 'picker') {\n // The raw failure text is for whoever diagnoses it: a tooltip detail in development only.\n const technical =\n process.env.NODE_ENV === 'production'\n ? undefined\n : loadErrorTechnicalTexts(error, original)[0];\n return (\n <span\n {...attributes}\n {...(testId === undefined ? {} : { 'data-testid': testId })}\n className={className}\n title={technical === undefined ? text : `${text} (${technical})`}\n >\n {children ?? text}\n </span>\n );\n }\n return (\n <div\n {...attributes}\n role=\"alert\"\n {...(testId === undefined ? {} : { 'data-testid': testId })}\n className={cn(\n 'flex flex-wrap items-center gap-2 rounded-md border border-dashed px-3 py-2 text-sm text-muted-foreground',\n className,\n )}\n >\n <span>{text}</span>\n {retry === undefined ? null : (\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={retry}>\n {chromeT('actions.retry', { defaultValue: 'Retry' })}\n </Button>\n )}\n </div>\n );\n}\n\ninterface BoundaryProps {\n readonly error: unknown;\n readonly fallback: ReactElement;\n readonly children: ReactNode;\n}\n\n/**\n * Renders the app's view; if it throws, the kit's view takes over and one development error names\n * the failure. A new error to show gives the app's view another chance.\n */\nconst UNSET = Symbol('unset');\n\nclass AppViewBoundary extends Component<BoundaryProps, { failedFor: unknown; failed: boolean }> {\n override state: { failedFor: unknown; failed: boolean } = { failedFor: UNSET, failed: false };\n\n static getDerivedStateFromError(): { failed: true } {\n return { failed: true };\n }\n\n static getDerivedStateFromProps(\n props: BoundaryProps,\n state: { failedFor: unknown; failed: boolean },\n ): { failedFor: unknown; failed: boolean } | null {\n if (state.failed && state.failedFor !== UNSET && state.failedFor !== props.error) {\n return { failedFor: UNSET, failed: false };\n }\n return null;\n }\n\n override componentDidCatch(error: unknown, _info: ErrorInfo): void {\n this.setState({ failedFor: this.props.error });\n if (process.env.NODE_ENV !== 'production') {\n console.error(\n \"[burojs] load-error.view-threw: the app's views.loadError threw while rendering; the kit's view is shown instead.\",\n error,\n );\n }\n }\n\n override render(): ReactNode {\n return this.state.failed ? this.props.fallback : this.props.children;\n }\n}\n\n/**\n * A failed read, drawn by the app's `views.loadError` when it has one and by the kit's view\n * otherwise. The error is normalized once, here; the app's view receives the raw {@link DataError}.\n */\nexport function LoadError(props: LoadErrorProps): ReactElement {\n const App = useLoadErrorView();\n const { error: original, surface, resource } = props;\n const error = useMemo(() => normalizeDataError(original), [original]);\n const state = props.state ?? recordErrorState(error);\n const retry = state === 'error' ? props.retry : undefined;\n const viewProps: LoadErrorViewProps = {\n error,\n surface,\n state,\n ...(resource === undefined ? {} : { resource }),\n ...(retry === undefined ? {} : { retry }),\n };\n const standard = (\n <DefaultLoadErrorView\n {...viewProps}\n original={original}\n fallback={props.fallback}\n testId={props.testId}\n className={props.className}\n title={props.title}\n attributes={props.attributes}\n >\n {props.children}\n </DefaultLoadErrorView>\n );\n if (App === undefined) return standard;\n return (\n <AppViewBoundary error={original} fallback={standard}>\n <App {...viewProps} />\n </AppViewBoundary>\n );\n}\n\n/**\n * What a route's id that names no record reads as (`/orders/abc` for a numeric id field): a\n * not-found answered without a request, under the framework's `invalid-record-id` code.\n */\nconst INVALID_ROUTE_ID: DataError = Object.freeze({\n kind: 'not-found',\n code: 'invalid-record-id',\n});\n\n/**\n * The not-found of a record route whose id is no valid id of its resource (spec 4.19), through\n * {@link LoadError}, so an app's `views.loadError` draws it like any other not-found.\n */\nexport function InvalidRouteId({ resource }: { readonly resource: string }): ReactElement {\n return (\n <LoadError surface=\"record\" resource={resource} state=\"not-found\" error={INVALID_ROUTE_ID} />\n );\n}\n","'use client';\nimport { QUICK_ANCHOR_ATTRIBUTE, quickAnchorRef } from '@burojs/react';\nimport type * as React from 'react';\nimport { useLinkComponent } from '../layout/link-component.js';\n\n/** A plain left click: the main button, no modifier. Anything else follows the `href`. */\nexport function isPlainLeftClick(event: React.MouseEvent): boolean {\n return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;\n}\n\n/** Claims the anchor an app's link component rendered (it may not forward a ref). */\nfunction claimAnchor(wrapper: HTMLSpanElement | null): void {\n const anchor = wrapper?.querySelector('a') ?? null;\n quickAnchorRef(anchor);\n}\n\n/**\n * A quick opener's anchor (spec 4.5): the app's link component to the record's page, marked with\n * `data-buro-quick` and claimed for its opener, so the navigation guard leaves its click to it. A\n * plain left click calls `preventDefault()` and `onOpen()`; a modified click follows the `href`\n * (a new tab, guarded as any link).\n */\nexport function ClaimedQuickLink({\n href,\n testid,\n className,\n onOpen,\n children,\n}: {\n readonly href: string;\n readonly testid?: string;\n readonly className?: string;\n readonly onOpen: () => void;\n readonly children: React.ReactNode;\n}): React.ReactElement {\n const RouterLink = useLinkComponent();\n return (\n <span ref={claimAnchor} className=\"contents\">\n <RouterLink\n href={href}\n {...(testid === undefined ? {} : { 'data-testid': testid })}\n {...{ [QUICK_ANCHOR_ATTRIBUTE]: '' }}\n {...(className === undefined ? {} : { className })}\n onClick={(event: React.MouseEvent<HTMLAnchorElement>) => {\n event.stopPropagation();\n if (!isPlainLeftClick(event) || event.currentTarget.target === '_blank') return;\n event.preventDefault();\n onOpen();\n }}\n >\n {children}\n </RouterLink>\n </span>\n );\n}\n","/**\n * A record's display name: its `displayField` value when present and non-empty, else its `id`.\n * Exported for consumers building delete dialogs, breadcrumbs and relation labels.\n */\nexport function recordDisplayName(record: Record<string, unknown>, displayField?: string): string {\n if (displayField && record[displayField] != null && record[displayField] !== '') {\n return String(record[displayField]);\n }\n return String(record.id ?? '');\n}\n","import type { useApp, useListAccess } from '@burojs/react';\n\ntype ResourceDefOf = ReturnType<ReturnType<typeof useApp>['registry']['get']>;\n\n/**\n * A list row as a declared hook (`recordTitle`, `recordSubtitle`) may read it (P5 spec 3.6): the\n * row's declared fields its user may view in any-record reach, and its id. `undefined` while the\n * access decision is pending, when a hook reads nothing.\n */\nexport function visibleRow(\n def: ResourceDefOf,\n access: ReturnType<typeof useListAccess>,\n row: Readonly<Record<string, unknown>>,\n): Record<string, unknown> | undefined {\n if (access.status !== 'ready') return undefined;\n const idField = def?.data?.idField || 'id';\n const visible: Record<string, unknown> = {};\n for (const name of Object.keys(def?.fields ?? {}))\n if (Object.hasOwn(row, name) && access.fieldVisible(name)) visible[name] = row[name];\n if (Object.hasOwn(row, idField)) visible[idField] = row[idField];\n return visible;\n}\n","import { type RecordTitleContext, resolveEnumLabel } from '@burojs/core';\nimport { useApp, useI18nCaps, useListAccess } from '@burojs/react';\nimport { useCallback } from 'react';\nimport { recordDisplayName } from './record-display-name.js';\nimport { visibleRow } from './visible-row.js';\n\n/**\n * The display name of a row of `target` as a list surface may show it (P5 spec 3.6, decision\n * P5-27): the row's `displayField` value, else the id; the display field is read only while it is\n * visible, and while the decision is pending the id is shown, never a value. Picker options,\n * relation displays, related labels and palette results read their titles through this.\n *\n * With `recordTitle: true` (the picker options and chips of a relation field, and the relation\n * filter's options and value labels: L3 9.12) the target's `recordTitle` hook comes first. It\n * sees only the row's declared fields its user may view in any-record reach, and its id, as\n * `recordSubtitle` does, and applies only when `displayField` is the target's own (a surface that\n * titles rows by another field, such as a dimension's `labelField`, asked for that field). A\n * relation's display in a cell or on a show page keeps the display field.\n */\nexport function useRowTitle(\n target: string,\n displayField: string | undefined,\n options?: { readonly recordTitle?: boolean },\n): (row: Record<string, unknown>) => string {\n const app = useApp();\n const access = useListAccess(target);\n const caps = useI18nCaps(target);\n const def = app.registry.get(target);\n const hook =\n options?.recordTitle === true && displayField === def?.displayField\n ? def?.recordTitle\n : undefined;\n const visible =\n displayField !== undefined && access.status === 'ready' && access.fieldVisible(displayField);\n return useCallback(\n (row) => {\n const narrowed = hook === undefined ? undefined : visibleRow(def, access, row);\n if (hook !== undefined && narrowed !== undefined) {\n const ctx: RecordTitleContext = {\n resolveEnum: (namespace, value, inlineDefault) =>\n resolveEnumLabel(caps, namespace, value, inlineDefault),\n };\n const title = hook(narrowed, ctx);\n if (typeof title === 'string' && title.trim() !== '') return title;\n }\n return recordDisplayName(row, visible ? displayField : undefined);\n },\n [hook, access, def, caps, visible, displayField],\n );\n}\n","'use client';\nimport { createContext } from 'react';\n\n/**\n * @internal What the popover host gives the screen inside it: the anchor element it is positioned\n * against (the relation display the peek was opened from), and a setter for the popover's\n * accessible name once the screen knows the record's title.\n */\nexport interface PeekHostValue {\n readonly anchor: HTMLElement | null;\n setLabel(label: string): void;\n}\n\n/** @internal Provided by `PopoverPresentationHost`; `null` outside a popover. */\nexport const PeekHostContext = createContext<PeekHostValue | null>(null);\n\n/**\n * @internal True inside a peek (provided by `PeekScreen`): a relation display there attaches no\n * hover intent, so a peek never opens a second peek (spec 4.6).\n */\nexport const PeekContext = createContext(false);\n","'use client';\nimport {\n PEEK_COMPONENT,\n type PeekScreenProps,\n useCurrentUIActivation,\n useEntryGate,\n useQuickOpener,\n useUIPresentationRuntime,\n} from '@burojs/react';\nimport {\n type FocusEvent,\n type PointerEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useContext,\n useEffect,\n useRef,\n useState,\n useSyncExternalStore,\n} from 'react';\nimport { PeekContext } from './peek-context.js';\n\n/** The hover (and keyboard-focus) delay before a peek opens (spec 4.6). */\nexport const PEEK_DELAY_MS = 500;\n/** Focus this soon after a Tab or arrow keydown is keyboard modality. */\nconst KEYBOARD_FOCUS_WINDOW_MS = 100;\n\nconst NAVIGATION_KEYS = new Set(['Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight']);\n\n/** When the last Tab or arrow keydown happened; a pointer down forgets it. */\nlet lastNavigationKeyAt = Number.NEGATIVE_INFINITY;\nconst listening = new WeakSet<Document>();\n\nfunction listenForModality(doc: Document): void {\n if (listening.has(doc)) return;\n listening.add(doc);\n doc.addEventListener(\n 'keydown',\n (event) => {\n if (NAVIGATION_KEYS.has(event.key)) lastNavigationKeyAt = Date.now();\n },\n true,\n );\n const forget = () => {\n lastNavigationKeyAt = Number.NEGATIVE_INFINITY;\n };\n doc.addEventListener('pointerdown', forget, true);\n doc.addEventListener('mousedown', forget, true);\n}\n\n/** Whether a focus now came from the keyboard (a Tab or arrow keydown just before it). */\nfunction keyboardModality(): boolean {\n return Date.now() - lastNavigationKeyAt <= KEYBOARD_FOCUS_WINDOW_MS;\n}\n\n/** Elements about to be focused by code: their next focus opens no peek. */\nconst focusedByCode = new WeakSet<Element>();\n\n/**\n * @internal Focus `element` by code (the peek's anchor, when its title opens `quick.show`): the\n * focus opens no peek, whatever key was pressed last.\n */\nexport function focusWithoutPeek(element: HTMLElement): void {\n focusedByCode.add(element);\n element.focus();\n focusedByCode.delete(element);\n}\n\n/** What opens a record from where an anchor sits: its display's own quick opener. */\nexport type PeekAnchorOpener = (target: string, id: string) => void;\n\n/**\n * Each anchor's opener, taken where the display renders: inside a quick sheet it pushes into that\n * sheet, inside a dialog it closes the dialog first. The peek renders beside the overlays, outside\n * the sheet's context, so its title opens through this instead of its own opener.\n */\nconst anchorOpeners = new WeakMap<Element, PeekAnchorOpener>();\n\n/** @internal The opener registered for `anchor` by its peek intent, if any. */\nexport function peekAnchorOpener(anchor: Element | null): PeekAnchorOpener | undefined {\n return anchor === null ? undefined : anchorOpeners.get(anchor);\n}\n\n/** What a peek previews: the display's target and the key it holds (an id, or a `by` key). */\nexport interface PeekTarget {\n readonly to: string;\n readonly id?: string;\n readonly by?: { readonly field: string; readonly key: string };\n}\n\n/** The anchor inside the wrapper: the opener (`data-buro-quick`), else the first element. */\nfunction anchorIn(wrapper: HTMLElement | null): HTMLElement | null {\n if (wrapper === null) return null;\n const marked = wrapper.querySelector<HTMLElement>('[data-buro-quick]');\n if (marked !== null) return marked;\n const first = wrapper.firstElementChild;\n return first instanceof HTMLElement ? first : null;\n}\n\nconst noSubscription = () => () => undefined;\n\n/**\n * A relation display's hover intent (spec 4.6): a `mouse` or `pen` pointer resting on the anchor,\n * or keyboard-modality focus on it (a Tab or arrow keydown just before, never focus set by code),\n * for {@link PEEK_DELAY_MS} asks the entry gate for the target's peek; only `open` presents it,\n * after dismissing any other open peek. Leaving or blurring before then cancels. Nothing is read\n * before the peek opens. Inside a peek it renders its children only.\n */\nexport function PeekIntent({\n target,\n children,\n}: {\n readonly target: PeekTarget;\n readonly children: ReactNode;\n}): ReactElement {\n const inside = useContext(PeekContext);\n if (inside) return <>{children}</>;\n return <ActivePeekIntent target={target}>{children}</ActivePeekIntent>;\n}\n\nfunction ActivePeekIntent({\n target,\n children,\n}: {\n readonly target: PeekTarget;\n readonly children: ReactNode;\n}): ReactElement {\n const gate = useEntryGate();\n const runtime = useUIPresentationRuntime();\n const activation = useCurrentUIActivation();\n const [anchor, setAnchor] = useState<HTMLElement | null>(null);\n const wrapper = useRef<HTMLSpanElement | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n // The latest of each, read when the timer fires (the access answer may have changed since).\n const latest = useRef({ gate, target, activation });\n latest.current = { gate, target, activation };\n\n const attach = useCallback((element: HTMLSpanElement | null) => {\n wrapper.current = element;\n if (element !== null && element.ownerDocument !== undefined)\n listenForModality(element.ownerDocument);\n setAnchor(anchorIn(element));\n }, []);\n\n const expanded = useSyncExternalStore(\n anchor === null ? noSubscription : runtime.subscribe,\n () =>\n anchor !== null &&\n runtime\n .getSnapshot()\n .some((d) => d.component === PEEK_COMPONENT && d.anchor?.element === anchor),\n () => false,\n );\n const peekable = gate(target.to, 'peek').state === 'open';\n\n // The anchor is the app's link (it may not forward props): its popup state is set on it.\n useEffect(() => {\n if (anchor === null) return;\n if (!peekable) {\n anchor.removeAttribute('aria-haspopup');\n anchor.removeAttribute('aria-expanded');\n return;\n }\n anchor.setAttribute('aria-haspopup', 'dialog');\n anchor.setAttribute('aria-expanded', expanded ? 'true' : 'false');\n }, [anchor, peekable, expanded]);\n\n // The opener of where this display sits (a sheet pushes, a dialog closes first), for every\n // display with a peek: an eager one, a lazy `by` one and one under undecided access alike.\n const quickOpen = useQuickOpener();\n const onOpen = useCallback<PeekAnchorOpener>((to, id) => void quickOpen(to, id), [quickOpen]);\n useEffect(() => {\n if (anchor === null) return;\n anchorOpeners.set(anchor, onOpen);\n return () => {\n if (anchorOpeners.get(anchor) === onOpen) anchorOpeners.delete(anchor);\n };\n }, [anchor, onOpen]);\n\n const cancel = useCallback(() => {\n if (timer.current === null) return;\n clearTimeout(timer.current);\n timer.current = null;\n }, []);\n useEffect(() => cancel, [cancel]);\n\n const fire = useCallback(() => {\n timer.current = null;\n const { gate: ask, target: what, activation: from } = latest.current;\n const element = anchorIn(wrapper.current);\n if (element === null || !element.isConnected) return;\n // Only `open` presents: undecided access reads nothing (spec 4.14), a refusal opens nothing.\n const answer = ask(what.to, 'peek');\n if (answer.state !== 'open') return;\n const snapshot = runtime.getSnapshot();\n if (snapshot.some((d) => d.component === PEEK_COMPONENT && d.anchor?.element === element))\n return;\n // One peek at a time.\n for (const descriptor of snapshot)\n if (descriptor.component === PEEK_COMPONENT) runtime.dismiss(descriptor.id);\n const props: PeekScreenProps = {\n target: answer.target,\n ...(what.id === undefined ? {} : { id: what.id }),\n ...(what.by === undefined ? {} : { by: what.by }),\n };\n runtime.present({\n component: PEEK_COMPONENT,\n host: 'popover',\n anchor: { element },\n props: props as unknown as Readonly<Record<string, unknown>>,\n activation: from,\n });\n }, [runtime]);\n\n const schedule = useCallback(() => {\n if (timer.current !== null) return;\n timer.current = setTimeout(fire, PEEK_DELAY_MS);\n }, [fire]);\n\n return (\n // biome-ignore lint/a11y/noStaticElementInteractions: a `display: contents` wrapper that only observes the anchor inside it; the anchor is the interactive element\n <span\n ref={attach}\n className=\"contents\"\n onPointerEnter={(event: PointerEvent) => {\n if (event.pointerType === 'mouse' || event.pointerType === 'pen') schedule();\n }}\n onPointerLeave={cancel}\n onFocus={(event: FocusEvent) => {\n if (focusedByCode.has(event.target)) return;\n if (keyboardModality()) schedule();\n }}\n onBlur={cancel}\n // A click is always quick.show (spec 4.6): it cancels a pending peek.\n onPointerDown={cancel}\n onClickCapture={cancel}\n >\n {children}\n </span>\n );\n}\n","'use client';\nimport type * as React from 'react';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n hasRecordPage,\n relationAmbiguousError,\n resourceKey,\n relationOpenOf,\n type RelationOpen,\n resourceShowHref,\n type ResourceDef,\n type ResourceRefInput,\n routeResourceKey,\n type ResourceNameOrRef,\n} from '@burojs/core';\nimport {\n QUICK_ANCHOR_ATTRIBUTE,\n useApp,\n useCollectionRows,\n useEntryGate,\n useList,\n useOptionalT,\n useQuickOpener,\n useRelatedRecord,\n} from '@burojs/react';\nimport { LoadError } from '../load-error/load-error-view.js';\nimport { technicalText } from '../lib/friendly-error.js';\nimport { useRowTitle } from '../resource/use-row-title.js';\nimport { useLinkComponent } from '../layout/link-component.js';\nimport { PeekIntent, type PeekTarget } from '../quick/use-peek-intent.js';\nimport { ClaimedQuickLink } from './claimed-quick-link.js';\nimport type { FieldRendererProps } from './registry.js';\n\ntype App = ReturnType<typeof useApp>;\n\n/**\n * Shared link styling for in-table relation/row links. Persistent muted\n * dotted underline at idle that snaps to a solid foreground underline on\n * hover. Color stays at `text-foreground` so the link blends with body\n * text — affordance is carried by the underline alone, avoiding the\n * \"every link in brand color\" noise common in admin tables.\n *\n * Used by `<RelationDisplay>` and the first-cell row-anchor link in\n * `<ResourceList>`.\n *\n * `underline-offset-4` is intentional (vs the more common `-2`) to\n * clear the descenders of non-Latin glyphs seen in our\n * playground's Locations column.\n */\nexport const relationLinkClassName =\n 'rounded text-foreground underline decoration-muted-foreground/40 decoration-dotted underline-offset-4 transition-all hover:decoration-foreground hover:decoration-solid focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring';\n\n/**\n * Render a foreign-key value as a clickable link to the related\n * entity's show page.\n *\n * Resolution order:\n * 1. Read `field.meta.to` to get the target resource name (set by\n * `f.relation({ to: '<name>' })`).\n * 2. Look up the target resource's `displayField` from the app\n * registry — used to resolve the link text.\n * 3. Fetch the target record via `useRelatedRecord(to, id)`.\n * 4. Render `<a href=\"/<to>/<id>\">{displayName}</a>`.\n *\n * Fallbacks (matches the fail-soft policy used by `<EnumBadge>`):\n * - Value null/undefined/empty → em-dash placeholder, no fetch.\n * - Target resource not in registry → raw value as muted plain text.\n * Do NOT fire the fetch — the data provider would 404.\n * - Loading → small skeleton placeholder.\n * - Fetch errored → raw value muted, with the error message as title.\n * - Target row not found (no error, no record) → raw value muted with\n * `title=\"<resource>#<id> not found\"`.\n */\nexport function RelationDisplay({ value, field }: FieldRendererProps): React.ReactElement {\n const app = useApp();\n const meta = field?.meta as\n | { to?: ResourceRefInput; by?: unknown; resolve?: unknown }\n | undefined;\n const by = typeof meta?.by === 'string' ? meta.by : undefined;\n const lazy = meta?.resolve === 'lazy';\n // A target this surface cannot name — a builder field's thunk `to` that no app registration\n // lowered (a declarative form or display), or a malformed ref — renders like no target, as the\n // picker does, instead of throwing during render.\n let to: string | undefined;\n try {\n to = meta?.to === undefined ? undefined : resourceKey(meta.to);\n } catch {\n to = undefined;\n }\n const id = value as string | number | null | undefined;\n const idStr = String(value ?? '');\n const baseId = `relation-display:${to ?? 'unknown'}:${idStr}`;\n // What a click on the title opens: the overlay (default), the page, or nothing (`ui.open`).\n const open = relationOpenOf({ ui: (field as { readonly ui?: unknown } | undefined)?.ui });\n\n // Empty / null FK — render em-dash, do not fetch.\n // NB: do NOT short-circuit on `value === 0`; the relation schema is\n // `string | number`, and a target row with PK 0 (rare but valid) would\n // otherwise be silently treated as missing.\n if (value == null || value === '') {\n return (\n <span data-testid={`${baseId}:empty`} className=\"text-muted-foreground\">\n —\n </span>\n );\n }\n\n // Target resource not declared on the field. Without a target we\n // cannot build a link — degrade to plain text.\n if (!to) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(\n `[RelationDisplay] no meta.to declared on field — rendering raw value '${idStr}'`,\n );\n }\n return <span data-testid={`relation-display:unknown:${idStr}:no-target`}>{idStr}</span>;\n }\n\n // `lazy` (spec 4.3): nothing registers, nothing is read — the key itself is shown.\n if (lazy) return <LazyRelationDisplay to={to} by={by} idStr={idStr} app={app} open={open} />;\n\n return (\n <GatedRelationDisplay\n to={to}\n by={by}\n id={id as string | number}\n idStr={idStr}\n app={app}\n open={open}\n />\n );\n}\n\n/**\n * Public, adopter-facing entry point for rendering a foreign-key value.\n * Thin convenience wrapper over `<RelationDisplay>`: adopters write\n * `<RelationField to=\"reference_locations\" value={id} />` instead of\n * constructing the field-registry `{ name, meta }` shape by hand.\n * `RelationDisplay` itself stays the field-kind renderer registered for\n * `f.relation(...)` — its `{ value, field }` signature is dictated by the\n * `FieldRendererProps` contract and is unchanged.\n *\n * `RelationDisplay` reads the target resource from `field.meta.to` (see\n * `RelationDisplay` above), so this wrapper just shapes that `meta` object;\n * `field.name` is set to `''` since standalone usage has no owning field.\n */\nexport function RelationField<const N extends string = string>({\n to: toInput,\n value,\n}: {\n /** Target resource name (matches `f.relation({ to: '...' })`). */\n to: ResourceNameOrRef<N>;\n /** FK value to resolve, or null/undefined/'' when empty. */\n value: unknown;\n}): React.ReactElement {\n const to = routeResourceKey(toInput);\n return <RelationDisplay value={value} field={{ name: '', meta: { to } }} />;\n}\n\n/** What a key's peek previews: the row by id, or by the `by` field the key holds. */\nfunction peekTarget(to: string, by: string | undefined, key: string): PeekTarget {\n return by === undefined ? { to, id: key } : { to, by: { field: by, key } };\n}\n\n/** The definition whose record pages a link to `def`'s record lands on (`routesTo.show`). */\nfunction showPageDef(app: App, def: ResourceDef): ResourceDef | undefined {\n const delegate = def.routesTo?.show;\n if (delegate === undefined) return def;\n try {\n return app.registry.get(resourceKey(delegate as ResourceRefInput));\n } catch {\n return undefined;\n }\n}\n\n/** Whether `def`'s record has a show page to link to, following `routesTo.show`. */\nexport function linksToPage(app: App, def: ResourceDef): boolean {\n const target = showPageDef(app, def);\n return target !== undefined && hasRecordPage(target, 'show');\n}\n\n/**\n * A relation display's opener (spec 4.5): the title as an anchor to the page (when there is one)\n * or a button (when there is none), carrying `data-buro-quick` and claimed for the opener, whose\n * plain left click opens `quick.show` instead of navigating. A modified click follows the `href`.\n */\nfunction QuickOpener({\n href,\n testid,\n onOpen,\n children,\n}: {\n readonly href: string | null;\n readonly testid: string;\n readonly onOpen: () => void;\n readonly children: React.ReactNode;\n}): React.ReactElement {\n if (href === null)\n return (\n <button\n type=\"button\"\n data-testid={testid}\n {...{ [QUICK_ANCHOR_ATTRIBUTE]: '' }}\n className={`${relationLinkClassName} text-left`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n onOpen();\n }}\n >\n {children}\n </button>\n );\n return (\n <ClaimedQuickLink href={href} testid={testid} className={relationLinkClassName} onOpen={onOpen}>\n {children}\n </ClaimedQuickLink>\n );\n}\n\n/**\n * A lazy relation's key (spec 4.3, 4.5): nothing is read until it is clicked. An id key is the\n * opener of the target's `quick.show`; a `by` key is a button whose click reads the one row the\n * key names (`where <by> eq <key>`, two rows) and opens it — no row renders the not-available\n * text, two rows the muted key with the development error, and neither opens anything.\n */\nfunction LazyRelationDisplay({\n to,\n by,\n idStr,\n app,\n open: openMode,\n}: Omit<BodyProps, 'id'>): React.ReactElement {\n const RouterLink = useLinkComponent();\n const gate = useEntryGate();\n const open = useQuickOpener();\n const targetDef = app.registry.get(to);\n const baseId = `relation-display:${to}:${idStr}`;\n if (!targetDef || openMode === 'none') return <span data-testid={`${baseId}:lazy`}>{idStr}</span>;\n const answer = gate(to, 'show');\n // Undecided: the key as text, nothing read; its peek asks the gate again when it would open.\n if (answer.state === 'undecided')\n return (\n <PeekIntent target={peekTarget(to, by, idStr)}>\n <span data-testid={`${baseId}:lazy`}>{idStr}</span>\n </PeekIntent>\n );\n // Denied: the key as text, nothing to open (no read, no anchor).\n if (answer.state === 'hidden' || answer.state === 'disabled')\n return <span data-testid={`${baseId}:lazy`}>{idStr}</span>;\n const page = linksToPage(app, targetDef);\n // `open: 'page'`: the key is a plain page link whatever the gate says about the overlay.\n if (openMode === 'page') {\n if (by !== undefined || !page) return <span data-testid={`${baseId}:lazy`}>{idStr}</span>;\n return (\n <RouterLink\n href={resourceShowHref(app.registry, targetDef, to, idStr)}\n data-testid={`${baseId}:lazy`}\n className={relationLinkClassName}\n onClick={(e) => e.stopPropagation()}\n >\n {idStr}\n </RouterLink>\n );\n }\n if (answer.state !== 'open') {\n if (by !== undefined || !page) return <span data-testid={`${baseId}:lazy`}>{idStr}</span>;\n return (\n <RouterLink\n href={resourceShowHref(app.registry, targetDef, to, idStr)}\n data-testid={`${baseId}:lazy`}\n className={relationLinkClassName}\n onClick={(e) => e.stopPropagation()}\n >\n {idStr}\n </RouterLink>\n );\n }\n if (by !== undefined)\n return (\n <PeekIntent target={peekTarget(to, by, idStr)}>\n <LazyByOpener to={to} by={by} idStr={idStr} target={answer.target} />\n </PeekIntent>\n );\n const openKey = () => void open(to, idStr);\n return (\n <PeekIntent target={peekTarget(to, undefined, idStr)}>\n <QuickOpener\n href={page ? resourceShowHref(app.registry, targetDef, to, idStr) : null}\n testid={`${baseId}:lazy`}\n onOpen={openKey}\n >\n {idStr}\n </QuickOpener>\n </PeekIntent>\n );\n}\n\n/** A lazy `by` key's button: one `where <by> eq <key>` read on click, then the row it names. */\nfunction LazyByOpener({\n to,\n by,\n idStr,\n target,\n}: {\n readonly to: string;\n readonly by: string;\n readonly idStr: string;\n readonly target: string;\n}): React.ReactElement {\n const app = useApp();\n const t = useOptionalT();\n const open = useQuickOpener();\n const [asked, setAsked] = useState(false);\n const read = useList(to, {\n ...(asked\n ? {\n filter: { field: by, op: 'eq', value: idStr } as never,\n pagination: { kind: 'offset', page: 1, pageSize: 2 } as never,\n }\n : {}),\n // A key names one record: never narrowed by a scope. The quick peek reads this same\n // descriptor (`peek-screen.tsx`), so both say `'none'`.\n scope: 'none',\n enabled: asked,\n retry: false,\n });\n const rows = (read.data as { readonly data?: readonly Record<string, unknown>[] } | undefined)\n ?.data;\n const baseId = `relation-display:${to}:${idStr}`;\n const idField = (app.registry.get(target)?.data as { readonly idField?: unknown } | undefined)\n ?.idField;\n const rowId =\n rows?.length === 1\n ? rows[0]?.[typeof idField === 'string' && idField.length > 0 ? idField : 'id']\n : undefined;\n // Only a click opens: a click before the row is read leaves a request here, the effect below\n // answers it once; a refetch that changes the rows later opens nothing.\n const requested = useRef(false);\n useEffect(() => {\n if (!asked || rows === undefined || !requested.current) return;\n if (rows.length > 1) {\n requested.current = false;\n if (process.env.NODE_ENV !== 'production')\n console.error(`[burojs] ${technicalText(relationAmbiguousError(to, by, idStr))}`);\n return;\n }\n requested.current = false;\n if (rows.length === 1 && rowId !== undefined && rowId !== null) open(to, String(rowId));\n }, [asked, rows, rowId, open, to, by, idStr]);\n if (asked && rows !== undefined && rows.length === 0)\n return (\n <span data-testid={`${baseId}:unavailable`} className=\"text-muted-foreground\">\n {t('relation.unavailable', { defaultValue: 'Not available' })}\n </span>\n );\n if (asked && rows !== undefined && rows.length > 1)\n return (\n <span data-testid={`${baseId}:ambiguous`} className=\"text-muted-foreground\">\n {idStr}\n </span>\n );\n return (\n <button\n type=\"button\"\n data-testid={`${baseId}:lazy`}\n {...{ [QUICK_ANCHOR_ATTRIBUTE]: '' }}\n className={`${relationLinkClassName} text-left`}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n // A key already read opens its row at once; otherwise the read answers this click.\n if (asked && rowId !== undefined && rowId !== null) open(to, String(rowId));\n else {\n requested.current = true;\n setAsked(true);\n }\n }}\n >\n {idStr}\n </button>\n );\n}\n\ninterface BodyProps {\n to: string;\n /** The target field the key holds (`meta.by`); the target's id field when absent. */\n by?: string;\n id: string | number;\n idStr: string;\n app: App;\n /** What a click on the title opens (`ui.open`). */\n open: RelationOpen;\n}\n\n/**\n * The entry gate decides before anything is read (spec 4.4, 4.14): while it is undecided (the\n * permission map loads) or when `show` is denied, the key renders as plain text and the display\n * registers no read; otherwise the body reads the title and renders the opener — or, when the\n * target has no quick show (`absent`), the page link of before, or text when there is no page.\n */\nfunction GatedRelationDisplay(props: BodyProps): React.ReactElement {\n const gate = useEntryGate();\n const target = props.to;\n const { idStr } = props;\n const answer = gate(target, 'show');\n // Undecided: plain text and no read; its peek (hover) asks the gate again when it would open,\n // and opens nothing until access is decided (spec 4.14).\n if (answer.state === 'undecided')\n return (\n <PeekIntent target={peekTarget(target, props.by, idStr)}>\n <span data-testid={`relation-display:${target}:${idStr}:text`}>{idStr}</span>\n </PeekIntent>\n );\n if (answer.state === 'hidden' || answer.state === 'disabled')\n return <span data-testid={`relation-display:${target}:${idStr}:text`}>{idStr}</span>;\n return (\n <RelationDisplayBody\n {...props}\n quickTarget={answer.state === 'open' && props.open === 'quick' ? answer.target : null}\n />\n );\n}\n\n/**\n * Split body so the hook is only called when we know `to` is set and\n * the value is non-falsy. React's rules of hooks require unconditional\n * hook calls per render — separating the body keeps the early-return\n * branches above hook-free.\n */\nfunction RelationDisplayBody({\n to,\n by,\n id,\n idStr,\n app,\n open: openMode,\n quickTarget,\n}: BodyProps & { readonly quickTarget: string | null }): React.ReactElement {\n const targetDef = app.registry.get(to);\n const rowTitle = useRowTitle(to, targetDef?.displayField);\n const baseId = `relation-display:${to}:${idStr}`;\n const RouterLink = useLinkComponent();\n const open = useQuickOpener();\n const gate = useEntryGate();\n const collectionRow = useCollectionRows(to);\n const { record, isLoading, error, ambiguous } = useRelatedRecord(\n to,\n id,\n by === undefined ? undefined : { by },\n );\n\n // Target resource not in registry — degrade to plain text. No link\n // can be built without a basePath. Same fail-soft as `<EnumBadge>`.\n if (!targetDef) {\n if (process.env.NODE_ENV !== 'production') {\n // eslint-disable-next-line no-console\n console.warn(\n `[RelationDisplay] target resource '${to}' not registered — rendering raw value '${idStr}'`,\n );\n }\n return (\n <span data-testid={`${baseId}:unregistered`} className=\"text-muted-foreground\">\n {idStr}\n </span>\n );\n }\n\n if (isLoading) {\n return (\n <span\n data-testid={`relation-display-loading:${to}`}\n className=\"inline-block h-5 w-20 animate-pulse rounded bg-muted\"\n aria-busy=\"true\"\n />\n );\n }\n\n // A key two rows hold: the raw key, muted — never either row (spec 4.2, fail closed).\n if (ambiguous) {\n return (\n <span\n data-testid={`${baseId}:ambiguous`}\n className=\"text-muted-foreground\"\n title={`${to}: more than one row has ${by ?? 'id'} ${idStr}`}\n >\n {idStr}\n </span>\n );\n }\n\n if (error) {\n return (\n <LoadError\n surface=\"relation\"\n error={error}\n resource={to}\n testId={`${baseId}:error`}\n className=\"text-muted-foreground\"\n fallback={{ key: 'relation.failed', default: 'Failed to load options.' }}\n >\n {idStr}\n </LoadError>\n );\n }\n\n if (!record) {\n return (\n <span\n data-testid={`${baseId}:not-found`}\n className=\"text-muted-foreground\"\n title={`${to} #${idStr} not found`}\n >\n {idStr}\n </span>\n );\n }\n\n const displayName = rowTitle(record);\n // The link names the resolved row by its id field (spec 4.2), never by the key: a `by` key is\n // not an id, and the target's id field need not be `id`.\n const idField = (targetDef.data as { readonly idField?: unknown } | undefined)?.idField;\n const rowId = record[typeof idField === 'string' && idField.length > 0 ? idField : 'id'];\n if (rowId === null || rowId === undefined || rowId === '')\n return (\n <span data-testid={`${baseId}:no-id`} className=\"text-muted-foreground\">\n {displayName}\n </span>\n );\n // A collection's loaded row is its member's (REF-131 B12): the link goes to the member's\n // page, and the title opens and peeks the member, as the member's entry gate answers for this\n // row. A row of a type no member claims links to the collection's record URL, which redirects.\n const kind = collectionRow?.(record);\n const member = kind !== undefined && 'member' in kind ? kind.member : undefined;\n const memberDef = member === undefined ? undefined : app.registry.get(member);\n const page = linksToPage(app, memberDef ?? targetDef);\n const href = page ? resourceShowHref(app.registry, targetDef, to, String(rowId), record) : null;\n // `open: 'none'`: the title is text, no anchor and no button.\n if (openMode === 'none') return <span data-testid={baseId}>{displayName}</span>;\n if (quickTarget !== null)\n return (\n <RowOpener to={to} rowId={String(rowId)} href={href} testid={baseId} open={open}>\n {displayName}\n </RowOpener>\n );\n if (collectionRow !== undefined) {\n // The gate answers for the row: its member's rules for a member's row, the collection's own\n // `show` for a row no member claims. Denied or not yet decided, the key is text, as a denied\n // target's is (spec 4.14): never the title the read returned.\n const answer = gate(to, 'show', record);\n if (answer.state === 'hidden' || answer.state === 'disabled' || answer.state === 'undecided')\n return <span data-testid={`${baseId}:text`}>{idStr}</span>;\n if (member !== undefined && answer.state === 'open' && openMode === 'quick')\n return (\n <RowOpener to={answer.target} rowId={String(rowId)} href={href} testid={baseId} open={open}>\n {displayName}\n </RowOpener>\n );\n }\n // No quick show (switched off, or no host wired): the page link, or text without a page.\n if (href === null) return <span data-testid={baseId}>{displayName}</span>;\n return (\n <RouterLink\n href={href}\n data-testid={baseId}\n className={relationLinkClassName}\n onClick={(e) => e.stopPropagation()}\n >\n {displayName}\n </RouterLink>\n );\n}\n\n/**\n * A resolved row's opener: a click opens its `quick.show`, a hover its peek — by the row's id,\n * the record descriptor `quick.show` reads, so the two share one read.\n */\nfunction RowOpener({\n to,\n rowId,\n href,\n testid,\n open,\n children,\n}: {\n readonly to: string;\n readonly rowId: string;\n readonly href: string | null;\n readonly testid: string;\n readonly open: ReturnType<typeof useQuickOpener>;\n readonly children: React.ReactNode;\n}): React.ReactElement {\n const onOpen = useCallback(() => void open(to, rowId), [open, to, rowId]);\n return (\n <PeekIntent target={peekTarget(to, undefined, rowId)}>\n <QuickOpener href={href} testid={testid} onOpen={onOpen}>\n {children}\n </QuickOpener>\n </PeekIntent>\n );\n}\n","import type { ErasedResourceHandle, FilterExpression, SearchDecl } from '@burojs/core';\nimport { filterFields } from '@burojs/react';\n\n/**\n * A declared search set without the fields its user may not view (P5 spec 3.7, decision P5-17).\n * No field left means no search. A function search is kept: its output is checked by\n * {@link namesHiddenField}.\n */\nexport function narrowSearchDecl(\n declared: SearchDecl | undefined,\n visible: (field: string) => boolean,\n): SearchDecl | undefined {\n if (declared === undefined || typeof declared === 'function') return declared;\n if (!Array.isArray(declared.fields)) return declared;\n const fields = declared.fields.filter((ref) =>\n visible(typeof ref === 'string' ? ref : ref.field),\n );\n if (fields.length === declared.fields.length) return declared;\n return fields.length === 0 ? undefined : { ...declared, fields };\n}\n\n/**\n * Whether a composed filter names a field its user may not view: an author predicate (a fixed\n * filter) or a function search's output. Such a read is forbidden, never narrowed — dropping a\n * narrowing predicate would fail open.\n */\nexport function namesHiddenField(\n filter: FilterExpression<ErasedResourceHandle> | undefined,\n visible: (field: string) => boolean,\n): boolean {\n return filter !== undefined && filterFields(filter).some((field) => !visible(field));\n}\n","'use client';\n\nimport * as React from 'react';\nimport {\n composeListFilter,\n type ErasedResourceHandle,\n type FilterExpression,\n type FixedFilterInput,\n normalizeFixedFilters,\n type ScopeSource,\n type SearchDecl,\n} from '@burojs/core';\nimport { useList } from '@burojs/react';\n\ntype ErasedExpression = FilterExpression<ErasedResourceHandle>;\n\n/**\n * The filter the select re-reads a created record through (P6-33): the picker's own option query\n * for an empty search (`composeListFilter`, the same `fixed` filters, the same search\n * declaration), conjoined with `<idField> eq <id>`. The row must come back through the query the\n * select offers from, or it is not selected.\n */\nexport function createdOptionFilter(input: {\n readonly fixed: readonly FixedFilterInput[] | undefined;\n readonly idField: string;\n readonly id: string | number;\n readonly searchDecl?: SearchDecl | undefined;\n readonly searchContext?: { readonly resource: string; readonly def: unknown };\n}): ErasedExpression {\n const own = createdOptionScope(input);\n const byId = { field: input.idField, op: 'eq', value: input.id } as ErasedExpression;\n return own === undefined ? byId : ({ and: [own, byId] } as ErasedExpression);\n}\n\n/**\n * The select's option query for an empty search, without the id predicate: what the picker itself\n * sends, so the same hidden-field rule (`namesHiddenField`) judges both.\n */\nexport function createdOptionScope(input: {\n readonly fixed: readonly FixedFilterInput[] | undefined;\n readonly searchDecl?: SearchDecl | undefined;\n readonly searchContext?: { readonly resource: string; readonly def: unknown };\n}): ErasedExpression | undefined {\n return composeListFilter({\n fixed: normalizeFixedFilters(input.fixed),\n search: '',\n ...(input.searchDecl === undefined ? {} : { searchDecl: input.searchDecl }),\n ...(input.searchContext === undefined ? {} : { searchContext: input.searchContext as never }),\n });\n}\n\n/** What the re-read settled on: the value to select, \"does not fit\", or a failed read. */\nexport type CreatedOptionResult =\n | { readonly kind: 'fits'; readonly value: string | number }\n | { readonly kind: 'does-not-fit' }\n | { readonly kind: 'failed' };\n\nexport interface CreatedOptionReadProps {\n readonly to: string;\n readonly filter: ErasedExpression;\n /**\n * The select's read scope, as its option list takes it: the picker and the hand-back never\n * disagree on which rows fit.\n */\n readonly scope: ScopeSource;\n /** The record field the select writes (`useList`'s `scopeField`), as its option list passes it. */\n readonly scopeField?: string;\n readonly by: string | undefined;\n readonly idField: string;\n /** Called once, with the settled answer. */\n readonly onSettled: (result: CreatedOptionResult) => void;\n}\n\n/**\n * Mounted only while a created record is being handed back. One list read, limit 1, through the\n * select's own option query (Known finding 13): an empty answer is \"does not fit\", a failed read\n * is a failure, never \"fits\". Mounting it is the request; unmounting it drops the answer.\n */\nexport function CreatedOptionRead({\n to,\n filter,\n scope,\n scopeField,\n by,\n idField,\n onSettled,\n}: CreatedOptionReadProps): null {\n const query = useList(to, {\n filter: filter as never,\n pagination: { kind: 'offset', page: 1, pageSize: 1 },\n scope,\n ...(scopeField === undefined ? {} : { scopeField }),\n retry: false,\n });\n const settled = React.useRef(false);\n const latest = React.useRef(onSettled);\n latest.current = onSettled;\n const rows = (query.data as { readonly data?: readonly Record<string, unknown>[] } | undefined)\n ?.data;\n const answered = rows !== undefined && query.isCurrentData && !query.isFetching;\n const failed = query.isError && !query.isFetching;\n React.useEffect(() => {\n if (settled.current) return;\n if (failed) {\n settled.current = true;\n latest.current({ kind: 'failed' });\n return;\n }\n if (!answered) return;\n settled.current = true;\n const value = rows[0]?.[by ?? idField];\n latest.current(\n typeof value === 'string' || typeof value === 'number'\n ? { kind: 'fits', value }\n : { kind: 'does-not-fit' },\n );\n }, [answered, failed, rows, by, idField]);\n return null;\n}\n","'use client';\n\nimport * as React from 'react';\nimport { IconEye } from '@tabler/icons-react';\nimport { type RelationOpen, resourceShowHref } from '@burojs/core';\nimport {\n QUICK_ANCHOR_ATTRIBUTE,\n collectionRowHref,\n useApp,\n useAvailabilityGate,\n useCollectionRows,\n useEntryGate,\n useList,\n useListAccess,\n useOptionalT,\n useQuick,\n useQuickOpener,\n useRouteNavigate,\n useTestIds,\n} from '@burojs/react';\nimport { buttonVariants } from '../primitives/button.js';\nimport { cn } from '../lib/cn.js';\nimport { useLinkComponent } from '../layout/link-component.js';\nimport { ClaimedQuickLink, isPlainLeftClick } from './claimed-quick-link.js';\nimport { linksToPage } from './relation-display.js';\n\n/** A key a read may send: a non-empty string or a finite number (Known finding 1). */\nexport function selectKey(value: unknown): string | null {\n if (typeof value === 'string') return value.length === 0 ? null : value;\n if (typeof value === 'number') return Number.isFinite(value) ? String(value) : null;\n return null;\n}\n\nconst VIEW_CLASS = cn(buttonVariants({ variant: 'outline', size: 'icon' }), 'shrink-0');\nconst TITLE_CLASS = 'min-w-0 max-w-[16rem] truncate';\nconst TITLE_VIEW_CLASS = cn(\n TITLE_CLASS,\n 'cursor-pointer rounded-sm text-left hover:underline focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring',\n);\n\nexport interface RelationViewButtonProps {\n readonly to: string;\n readonly value: unknown;\n readonly by: string | undefined;\n /** The form field holding the key: the test id's second part. */\n readonly fieldName: string;\n /** Runs before the overlay opens: the picker moves focus to its trigger, where it returns. */\n readonly beforeOpen: () => void;\n /**\n * The field's `ui.open` (P7 3.6): `quick` (default) opens the record above the form, `page`\n * goes to its show page through the navigation guard (a dirty form asks first), `none` draws\n * no button.\n */\n readonly open?: RelationOpen;\n /**\n * Draw the record's title as the trigger instead of the eye icon (a relation chip): the title\n * itself opens the record. Where \"view\" is not offered, the title is drawn as plain text.\n */\n readonly title?: string;\n}\n\n/**\n * \"View\" beside a relation select's trigger (P6-28): the target's `quick.show` as a new overlay\n * above the form, never a push and never closing the host. Drawn only when the select holds a\n * key and the entry gate is open without a row (the row-level re-check runs inside the overlay,\n * P3-44); while the gate is undecided nothing is drawn and nothing is read (P3-15). A `by` key is\n * resolved by the limit-2 read on click; zero or two rows open nothing.\n */\nexport function RelationViewButton(props: RelationViewButtonProps): React.ReactElement | null {\n const gate = useEntryGate();\n const availability = useAvailabilityGate('show');\n const { to, value, by } = props;\n const collection = useCollectionRows(to) !== undefined;\n const access = useListAccess(to);\n const key = selectKey(value);\n const plain = plainTitle(props.title);\n if (key === null || props.open === 'none') return plain;\n // A `by` field the user may not view is never sent as a predicate: no \"view\", no read.\n if (by !== undefined && !(access.status === 'ready' && access.fieldVisible(by))) return plain;\n const answer = gate(to, 'show');\n // A collection has no entry of its own: asked without a row its gate is `absent` once\n // decided, and \"view\" then reads the row (the overlay opens as its member) or links to the\n // collection's record URL, which redirects. Its own `show` must still be available.\n const viewable = collection\n ? answer.state === 'absent' && availability(to, 'show').state === 'available'\n : answer.state === 'open';\n if (!viewable) return plain;\n // Keyed by the value: a click asked for one key's read and must not outlive it.\n return <ViewButton key={key} {...props} keyString={key} collection={collection} />;\n}\n\nfunction plainTitle(title: string | undefined): React.ReactElement | null {\n return title === undefined ? null : <span className={TITLE_CLASS}>{title}</span>;\n}\n\nfunction ViewButton({\n to,\n by: byField,\n fieldName,\n keyString,\n beforeOpen,\n open: openMode = 'quick',\n title,\n collection,\n}: RelationViewButtonProps & {\n readonly keyString: string;\n readonly collection: boolean;\n}): React.ReactElement | null {\n const app = useApp();\n const t = useOptionalT();\n const tid = useTestIds();\n const quick = useQuick();\n const openQuick = useQuickOpener();\n const navigate = useRouteNavigate();\n const availability = useAvailabilityGate('show');\n const RouterLink = useLinkComponent();\n const [asked, setAsked] = React.useState(false);\n const requested = React.useRef(false);\n const targetDef = app.registry.get(to);\n const rawIdField = (targetDef?.data as { readonly idField?: unknown } | undefined)?.idField;\n const idField = typeof rawIdField === 'string' && rawIdField.length > 0 ? rawIdField : 'id';\n // The field the click reads the row by. A collection's overlay opens as the row's member, so\n // even an id key is read first (`where <id> eq <key>`), and the row goes to the opener.\n const by = byField ?? (collection && openMode !== 'page' ? idField : undefined);\n const read = useList(to, {\n ...(asked && by !== undefined\n ? {\n filter: { field: by, op: 'eq', value: keyString } as never,\n pagination: { kind: 'offset', page: 1, pageSize: 2 } as never,\n }\n : {}),\n // A key names one record: the read is never narrowed by a scope.\n scope: 'none',\n enabled: asked && by !== undefined,\n retry: false,\n });\n // Rows of this key only: a placeholder carried over from another key's read is not an answer.\n const current = read.isCurrentData && !read.isPlaceholderData && !read.isFetching;\n const rows = current\n ? (read.data as { readonly data?: readonly Record<string, unknown>[] } | undefined)?.data\n : undefined;\n const open = React.useCallback(\n (id: string, row?: unknown) => {\n beforeOpen();\n if (openMode === 'page') {\n // The page of the record, through the navigation guard: unsaved input asks first. A row\n // read for a `by` key names its member when the target is a collection (B12).\n if (targetDef !== undefined && linksToPage(app, targetDef))\n navigate(resourceShowHref(app.registry, targetDef, to, id, row));\n return;\n }\n if (!collection) {\n quick.show(to, id);\n return;\n }\n // The row's member may open nothing above the form (a row of a type no member claims, a\n // member denying `show` or without `quick.show`, no host): the click then goes where the\n // collection's list row would link, the member's show or edit page or the collection's\n // record URL, and does nothing only when that row links nowhere either. An undecided gate\n // waits, as the row link does.\n if (openQuick(to, id, { row }) !== 'absent' || targetDef === undefined) return;\n const href = collectionRowHref(app.registry, targetDef, to, id, row, availability);\n if (href !== undefined && href !== '') navigate(href);\n },\n [\n beforeOpen,\n quick,\n openQuick,\n collection,\n to,\n openMode,\n navigate,\n app,\n targetDef,\n availability,\n ],\n );\n // Only a click opens: the read answers the click that asked for it, once.\n React.useEffect(() => {\n if (by === undefined || !asked || rows === undefined || !requested.current) return;\n requested.current = false;\n if (rows.length !== 1) {\n if (rows.length > 1 && process.env.NODE_ENV !== 'production')\n console.error(\n `[burojs] ${to}: more than one row has ${by} ${keyString}; \"view\" opened nothing.`,\n );\n return;\n }\n const id = rows[0]?.[idField];\n const next = selectKey(id);\n if (next !== null) open(next, rows[0]);\n }, [by, asked, rows, idField, keyString, to, open]);\n\n const label = t('relationPicker.view', { defaultValue: 'View' });\n const content = title === undefined ? <IconEye className=\"h-4 w-4\" aria-hidden /> : title;\n const className = title === undefined ? VIEW_CLASS : TITLE_VIEW_CLASS;\n const testid = tid.relationView(to, fieldName);\n // `page` needs a page to go to (the publish check says so): without one, nothing is drawn.\n if (openMode === 'page' && (targetDef === undefined || !linksToPage(app, targetDef)))\n return plainTitle(title);\n if (openMode === 'page' && by === undefined && targetDef !== undefined)\n return (\n <RouterLink\n href={resourceShowHref(app.registry, targetDef, to, keyString)}\n data-testid={testid}\n className={className}\n onClick={() => beforeOpen()}\n >\n <span className=\"sr-only\">{label} </span>\n {content}\n </RouterLink>\n );\n if (by === undefined && targetDef !== undefined && linksToPage(app, targetDef))\n return (\n <ClaimedQuickLink\n href={resourceShowHref(app.registry, targetDef, to, keyString)}\n testid={testid}\n className={className}\n onOpen={() => open(keyString)}\n >\n <span className=\"sr-only\">{label} </span>\n {content}\n </ClaimedQuickLink>\n );\n return (\n <button\n type=\"button\"\n className={className}\n data-testid={testid}\n aria-label={title === undefined ? label : `${label} ${title}`}\n {...{ [QUICK_ANCHOR_ATTRIBUTE]: '' }}\n onClick={(event) => {\n event.preventDefault();\n event.stopPropagation();\n // No page to follow (or, for a `by` key, no id to build it from): a modified click is\n // nothing, never an overlay the user asked to avoid.\n if (!isPlainLeftClick(event)) return;\n if (by === undefined) {\n open(keyString);\n return;\n }\n requested.current = true;\n setAsked(true);\n // A key already read opens at once; the effect answers a click made before the read.\n if (rows !== undefined && rows.length === 1) {\n const next = selectKey(rows[0]?.[idField]);\n requested.current = false;\n if (next !== null) open(next, rows[0]);\n }\n }}\n >\n {content}\n </button>\n );\n}\n","'use client';\n\nimport * as React from 'react';\nimport type { FixedFilterInput, ScopeSource, SearchDecl } from '@burojs/core';\nimport {\n type QuickSettledRow,\n useApp,\n useListAccess,\n useEntryGate,\n useOptionalT,\n useQuick,\n useTestIds,\n} from '@burojs/react';\nimport { toast } from '../notification/toaster.js';\nimport {\n CreatedOptionRead,\n type CreatedOptionResult,\n createdOptionFilter,\n createdOptionScope,\n} from './relation-hand-back.js';\nimport { namesHiddenField } from './search-access.js';\nimport { selectKey } from './relation-view-button.js';\n\n/** What the picker and its dialog share: one pending create per select (P6-34). */\nexport interface SelectCreate {\n readonly pending: boolean;\n /**\n * The hand-back read is forbidden: its filter names a field P5 hides from the user (the same\n * rule that stops the picker's own option read), or the access map is not ready. A blocked\n * select offers no \"+ Create\" and starts none, so no predicate on a hidden field is ever sent.\n */\n readonly blocked: boolean;\n /** Runs `open` unless a create of this select is already pending or the select is gone. */\n start(open: () => Promise<QuickSettledRow>): void;\n}\n\ninterface SelectCreateInput {\n readonly to: string;\n readonly by: string | undefined;\n /** The row field the select holds (`by`, else the target's id field). */\n readonly valueField: string;\n readonly idField: string;\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n /** The select's read scope: the hand-back reads as the option list does. */\n readonly scope: ScopeSource;\n /** The record field the select writes, as the option list passes it. */\n readonly scopeField?: string;\n /**\n * The select's candidates gate is not ready (pending, empty, forbidden): the filters above\n * lack the candidate filters, so the hand-back must not read.\n */\n readonly held?: boolean;\n readonly searchDecl: SearchDecl | undefined;\n readonly searchContext: { readonly resource: string; readonly def: unknown };\n /** Called with the value to select, as a user's pick would. */\n readonly onValue: (value: string | number) => void;\n}\n\n/**\n * The select's one pending create: the latch (a ref, so a double click or a second render cannot\n * start two), the mounted guard (a result arriving after the select unmounted is ignored — the\n * record exists, nothing is selected), and the hand-back re-read through the select's own option\n * query. `reader` is mounted by the select while a created record is being handed back.\n */\nexport function useSelectCreate(input: SelectCreateInput): {\n readonly create: SelectCreate;\n readonly reader: React.ReactNode;\n} {\n const t = useOptionalT();\n const { to: target } = input;\n const [pending, setPending] = React.useState(false);\n const [created, setCreated] = React.useState<{ readonly id: string } | null>(null);\n const latch = React.useRef(false);\n const mounted = React.useRef(true);\n React.useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n const latest = React.useRef(input);\n latest.current = input;\n const access = useListAccess(target);\n // The hand-back's own filter, judged as the picker judges its option query.\n const blocked =\n input.held === true ||\n access.status !== 'ready' ||\n namesHiddenField(\n createdOptionScope({\n fixed: input.fixedFilters,\n searchDecl: input.searchDecl,\n searchContext: input.searchContext,\n }),\n (name) => access.fieldVisible(name),\n );\n const blockedRef = React.useRef(blocked);\n blockedRef.current = blocked;\n\n const release = React.useCallback(() => {\n latch.current = false;\n if (mounted.current) {\n setPending(false);\n setCreated(null);\n }\n }, []);\n\n const start = React.useCallback(\n (open: () => Promise<QuickSettledRow>) => {\n if (latch.current || !mounted.current || blockedRef.current) return;\n latch.current = true;\n setPending(true);\n let opened: Promise<QuickSettledRow>;\n try {\n opened = open();\n } catch (error) {\n // A synchronous throw (a `beforeOpen`, the host) must not leave the select locked.\n release();\n throw error;\n }\n void opened.then(\n (row) => {\n if (!mounted.current) {\n latch.current = false;\n return;\n }\n const id =\n row === null ? null : (selectKey(row[latest.current.idField]) ?? selectKey(row.id));\n if (id === null) release();\n else setCreated({ id });\n },\n () => release(),\n );\n },\n [release],\n );\n\n const settle = React.useCallback(\n (result: CreatedOptionResult) => {\n if (mounted.current) {\n if (result.kind === 'fits') latest.current.onValue(result.value);\n else if (result.kind === 'does-not-fit')\n toast(\n t('relationPicker.createdNotFitting', {\n defaultValue: 'The record was created but does not fit this field',\n }),\n );\n else\n toast.error(\n t('relationPicker.createdNotSelected', {\n defaultValue: 'The record was created but could not be selected',\n }),\n );\n }\n release();\n },\n [release, t],\n );\n\n const create = React.useMemo<SelectCreate>(\n () => ({ pending, blocked, start }),\n [pending, blocked, start],\n );\n const reader =\n created === null || blocked ? null : (\n <CreatedOptionRead\n key={created.id}\n to={target}\n filter={createdOptionFilter({\n fixed: input.fixedFilters,\n idField: input.idField,\n id: created.id,\n searchDecl: input.searchDecl,\n searchContext: input.searchContext,\n })}\n scope={input.scope}\n {...(input.scopeField === undefined ? {} : { scopeField: input.scopeField })}\n by={input.by}\n idField={input.idField}\n onSettled={settle}\n />\n );\n return { create, reader };\n}\n\n/** A string field a typed search text may fill: declared plain, not system, not an enum. */\nfunction plainStringField(def: unknown): boolean {\n if (def === null || typeof def !== 'object') return false;\n const field = def as {\n readonly kind?: unknown;\n readonly system?: unknown;\n readonly opts?: {\n readonly system?: unknown;\n readonly enum?: unknown;\n readonly localized?: unknown;\n };\n };\n return (\n field.kind === 'string' &&\n field.system !== true &&\n field.opts?.system !== true &&\n field.opts?.enum === undefined &&\n field.opts?.localized !== true\n );\n}\n\nexport interface RelationCreateButtonProps {\n readonly to: string;\n readonly fieldName: string;\n readonly create: SelectCreate;\n /** The trusted `defaults` tier: the registry field's static `eq` literals (P6-31). */\n readonly seeds: Readonly<Record<string, unknown>> | undefined;\n /** The text typed into the select's search, if any: prefills the display field as user input. */\n readonly search?: string;\n /** Runs before the overlay opens: closes the popover, returns focus to the trigger. */\n readonly beforeOpen: () => void;\n readonly className?: string;\n readonly testId?: string;\n}\n\n/**\n * \"+ create\" (P6-29): the target's `quick.create` as a new overlay above the form. Drawn only when\n * the entry gate is open (P3 4.4: `operations.create`, `views.quick.create`, the host wired, the\n * `create` availability); undecided or denied draws nothing and reads nothing. Disabled while one\n * create of the select is pending.\n */\nexport function RelationCreateButton(props: RelationCreateButtonProps): React.ReactElement | null {\n const gate = useEntryGate();\n const { to } = props;\n if (props.create.blocked || gate(to, 'create').state !== 'open') return null;\n return <CreateButton {...props} />;\n}\n\nfunction CreateButton({\n to,\n fieldName,\n create,\n seeds,\n search,\n beforeOpen,\n className,\n testId,\n}: RelationCreateButtonProps): React.ReactElement {\n const app = useApp();\n const t = useOptionalT();\n const tid = useTestIds();\n const quick = useQuick();\n const label = t('relationPicker.create', { defaultValue: '+ Create' });\n return (\n <button\n type=\"button\"\n data-testid={testId ?? tid.relationCreate(to, fieldName)}\n disabled={create.pending}\n className={className}\n onClick={() => {\n const text = search?.trim() ?? '';\n const displayField = (\n app.registry.get(to) as { readonly displayField?: unknown } | undefined\n )?.displayField;\n const fields = (\n app.registry.get(to) as { readonly fields?: Record<string, unknown> } | undefined\n )?.fields;\n const prefill =\n text.length > 0 &&\n typeof displayField === 'string' &&\n fields !== undefined &&\n Object.hasOwn(fields, displayField) &&\n plainStringField(fields[displayField])\n ? { [displayField]: text }\n : undefined;\n create.start(() => {\n beforeOpen();\n return quick.create(to, {\n ...(seeds === undefined || Object.keys(seeds).length === 0 ? {} : { defaults: seeds }),\n ...(prefill === undefined ? {} : { input: prefill }),\n });\n });\n }}\n >\n {label}\n </button>\n );\n}\n"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  import { l as cn } from "./use-theme-dnE3Od3I.js";
2
2
  import { m as PopoverTrigger, p as PopoverContent, u as Popover } from "./toaster-Ct_YHGs6.js";
3
3
  import { t as Button } from "./button-MWVeZaqj.js";
4
- import { C as CommandEmpty, D as CommandList, E as CommandItem, T as CommandInput, a as namesHiddenField, i as selectKey, m as useRowTitle, n as useSelectCreate, o as narrowSearchDecl, r as RelationViewButton, t as RelationCreateButton, x as Command, y as LoadError } from "./relation-create-C43cdPQt.js";
5
- import { r as useCandidatesGate, t as LazyRelationPickerDialog } from "./lazy-relation-picker-dialog-DN4bvQfg.js";
6
- import { r as useRowSubtitle, t as optionSubtitle } from "./use-record-subtitle-gIaCGgbI.js";
4
+ import { D as CommandItem, E as CommandInput, O as CommandList, S as Command, a as namesHiddenField, b as LoadError, i as selectKey, m as useRowTitle, n as useSelectCreate, o as narrowSearchDecl, r as RelationViewButton, t as RelationCreateButton, w as CommandEmpty } from "./relation-create-CeCWyxIb.js";
5
+ import { r as useCandidatesGate, t as LazyRelationPickerDialog } from "./lazy-relation-picker-dialog-BaIEWLbF.js";
6
+ import { r as useRowSubtitle, t as optionSubtitle } from "./use-record-subtitle-pWMBqQx9.js";
7
7
  import { composeListFilter, normalizeFixedFilters, relationOpenOf, resolveResourceLabel, resourceKey } from "@burojs/core";
8
8
  import { resolveErrorText, useApp, useI18nCaps, useList, useListAccess, useOptionalT, useRelatedRecord, useTestIds } from "@burojs/react";
9
9
  import { IconCheck, IconChevronDown, IconLoader2, IconX } from "@tabler/icons-react";
@@ -37,7 +37,7 @@ function keysOf(value) {
37
37
  return out;
38
38
  }
39
39
  function RelationManyPickerInput(props) {
40
- const { name, id, value, onChange, testid, field, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, relationSeeds, fixedFilters, metaSources, resource, link } = props;
40
+ const { name, id, value, onChange, testid, field, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy, relationSeeds, fixedFilters, metaSources, resource, link } = props;
41
41
  const meta = field?.meta;
42
42
  let to;
43
43
  try {
@@ -115,16 +115,17 @@ function RelationManyPickerInput(props) {
115
115
  required,
116
116
  ariaInvalid,
117
117
  ariaDescribedBy,
118
- ariaErrorMessage
118
+ ariaErrorMessage,
119
+ ariaLabelledBy
119
120
  });
120
121
  }
121
- function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, createSeeds, name, id, testid, resource, fieldName, open: openMode, optionSubtitle: optionSubtitle$1, canAdd = true, canRemove = true, hidden = NO_KEYS, notAtomic = false, readOnly = false, keyNotice, scope = "context", disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
122
+ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, createSeeds, name, id, testid, resource, fieldName, open: openMode, optionSubtitle: optionSubtitle$1, canAdd = true, canRemove = true, hidden = NO_KEYS, notAtomic = false, readOnly = false, keyNotice, scope = "context", disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, ariaLabelledBy }) {
122
123
  const app = useApp();
123
124
  const caps = useI18nCaps();
124
125
  const t = useOptionalT();
125
126
  const tid = useTestIds();
126
127
  const targetDef = app.registry.get(to);
127
- const rowTitle = useRowTitle(to, targetDef?.displayField);
128
+ const rowTitle = useRowTitle(to, targetDef?.displayField, { recordTitle: true });
128
129
  const rowSubtitle = useRowSubtitle(to, optionSubtitle$1);
129
130
  const targetLabel = resolveResourceLabel(caps, to, "single", targetDef).toLowerCase();
130
131
  const childPrefix = `relation-picker:${to}`;
@@ -431,7 +432,8 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
431
432
  jsxs(CommandList, {
432
433
  "data-testid": `${childPrefix}:list`,
433
434
  "aria-multiselectable": "true",
434
- "aria-label": targetLabel,
435
+ label: targetLabel,
436
+ ...ariaLabelledBy ? { "aria-labelledby": ariaLabelledBy } : {},
435
437
  children: [
436
438
  isLoading && jsxs("div", {
437
439
  className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
@@ -538,7 +540,7 @@ function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, c
538
540
  function Chip({ to, keyValue, by, resource, fieldName, testId, open: openMode, disabled, focusTrigger, onRemove }) {
539
541
  const t = useOptionalT();
540
542
  const targetDef = useApp().registry.get(to);
541
- const rowTitle = useRowTitle(to, targetDef?.displayField);
543
+ const rowTitle = useRowTitle(to, targetDef?.displayField, { recordTitle: true });
542
544
  const { record, isLoading } = useRelatedRecord(to, keyValue, by === void 0 ? void 0 : { by });
543
545
  const title = record ? rowTitle(record) : String(keyValue);
544
546
  return jsxs("span", {
@@ -569,4 +571,4 @@ function Chip({ to, keyValue, by, resource, fieldName, testId, open: openMode, d
569
571
  //#endregion
570
572
  export { RelationManyPickerInput };
571
573
 
572
- //# sourceMappingURL=relation-many-picker-BlrGRwMV.js.map
574
+ //# sourceMappingURL=relation-many-picker-CT7nKfE2.js.map