@burojs/ui-shadcn 0.4.0 → 0.5.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 (137) hide show
  1. package/README.md +22 -5
  2. package/dist/bulk-summary-CwSd6Yjb.cjs +108 -0
  3. package/dist/bulk-summary-CwSd6Yjb.cjs.map +1 -0
  4. package/dist/bulk-summary-GxMDP4bw.js +108 -0
  5. package/dist/bulk-summary-GxMDP4bw.js.map +1 -0
  6. package/dist/button-BxnnE28H.cjs +55 -0
  7. package/dist/button-BxnnE28H.cjs.map +1 -0
  8. package/dist/button-MWVeZaqj.js +44 -0
  9. package/dist/button-MWVeZaqj.js.map +1 -0
  10. package/dist/candidates-gate-CX2PBu6l.js +63 -0
  11. package/dist/candidates-gate-CX2PBu6l.js.map +1 -0
  12. package/dist/candidates-gate-DiFI52r7.cjs +70 -0
  13. package/dist/candidates-gate-DiFI52r7.cjs.map +1 -0
  14. package/dist/candidates-relation-picker-CBsVcnPR.js +82 -0
  15. package/dist/candidates-relation-picker-CBsVcnPR.js.map +1 -0
  16. package/dist/candidates-relation-picker-Dd_GVLlu.cjs +84 -0
  17. package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +1 -0
  18. package/dist/check-confirm-dialog-BRByTFpg.cjs +1534 -0
  19. package/dist/check-confirm-dialog-BRByTFpg.cjs.map +1 -0
  20. package/dist/check-confirm-dialog-CkaVTPT9.js +1232 -0
  21. package/dist/check-confirm-dialog-CkaVTPT9.js.map +1 -0
  22. package/dist/dialog-B_rt9S1c.js +63 -0
  23. package/dist/dialog-B_rt9S1c.js.map +1 -0
  24. package/dist/dialog-DRNUq9EA.cjs +112 -0
  25. package/dist/dialog-DRNUq9EA.cjs.map +1 -0
  26. package/dist/filter-builder-B3mZFL-K.cjs +1761 -0
  27. package/dist/filter-builder-B3mZFL-K.cjs.map +1 -0
  28. package/dist/filter-builder-DOnaXNfP.js +1605 -0
  29. package/dist/filter-builder-DOnaXNfP.js.map +1 -0
  30. package/dist/flow-runtime-B6zOHYqI.cjs +255 -0
  31. package/dist/flow-runtime-B6zOHYqI.cjs.map +1 -0
  32. package/dist/flow-runtime-D8h99FSg.js +252 -0
  33. package/dist/flow-runtime-D8h99FSg.js.map +1 -0
  34. package/dist/flow-screen-CX05b3G9.cjs +705 -0
  35. package/dist/flow-screen-CX05b3G9.cjs.map +1 -0
  36. package/dist/flow-screen-CmbARSqg.js +701 -0
  37. package/dist/flow-screen-CmbARSqg.js.map +1 -0
  38. package/dist/index.cjs +2825 -11912
  39. package/dist/index.cjs.map +1 -1
  40. package/dist/index.d.cts +1612 -1862
  41. package/dist/index.d.ts +1700 -1950
  42. package/dist/index.js +2498 -11605
  43. package/dist/index.js.map +1 -1
  44. package/dist/inline-flow-host-B7U1OJUe.cjs +112 -0
  45. package/dist/inline-flow-host-B7U1OJUe.cjs.map +1 -0
  46. package/dist/inline-flow-host-C3H2UpSA.js +112 -0
  47. package/dist/inline-flow-host-C3H2UpSA.js.map +1 -0
  48. package/dist/input-BI0czGyI.cjs +23 -0
  49. package/dist/input-BI0czGyI.cjs.map +1 -0
  50. package/dist/input-CUPStzZO.js +17 -0
  51. package/dist/input-CUPStzZO.js.map +1 -0
  52. package/dist/label-66W1qbke.js +29 -0
  53. package/dist/label-66W1qbke.js.map +1 -0
  54. package/dist/label-w6JYf2cF.cjs +36 -0
  55. package/dist/label-w6JYf2cF.cjs.map +1 -0
  56. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +14 -0
  57. package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +1 -0
  58. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +19 -0
  59. package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +1 -0
  60. package/dist/markdown/index.cjs +1 -1
  61. package/dist/markdown/index.js +1 -1
  62. package/dist/page-flow-route-CQ7HsbBm.cjs +277 -0
  63. package/dist/page-flow-route-CQ7HsbBm.cjs.map +1 -0
  64. package/dist/page-flow-route-CyXSvXSE.js +277 -0
  65. package/dist/page-flow-route-CyXSvXSE.js.map +1 -0
  66. package/dist/peek-filter-CnqHwTMU.cjs +51 -0
  67. package/dist/peek-filter-CnqHwTMU.cjs.map +1 -0
  68. package/dist/peek-filter-ErLfO153.js +28 -0
  69. package/dist/peek-filter-ErLfO153.js.map +1 -0
  70. package/dist/place-node--GdsP688.js +7315 -0
  71. package/dist/place-node--GdsP688.js.map +1 -0
  72. package/dist/place-node-SIp4XYQH.cjs +7833 -0
  73. package/dist/place-node-SIp4XYQH.cjs.map +1 -0
  74. package/dist/related-list-cards-B6x9HQQp.js +42 -0
  75. package/dist/related-list-cards-B6x9HQQp.js.map +1 -0
  76. package/dist/related-list-cards-nxuODlIA.cjs +42 -0
  77. package/dist/related-list-cards-nxuODlIA.cjs.map +1 -0
  78. package/dist/related-list-timeline-BYJKEbmA.cjs +142 -0
  79. package/dist/related-list-timeline-BYJKEbmA.cjs.map +1 -0
  80. package/dist/related-list-timeline-DEdfd-rr.js +142 -0
  81. package/dist/related-list-timeline-DEdfd-rr.js.map +1 -0
  82. package/dist/related-rows-B4levHcR.js +186 -0
  83. package/dist/related-rows-B4levHcR.js.map +1 -0
  84. package/dist/related-rows-zh5f_4QR.cjs +209 -0
  85. package/dist/related-rows-zh5f_4QR.cjs.map +1 -0
  86. package/dist/relation-create-BOaUe12G.cjs +362 -0
  87. package/dist/relation-create-BOaUe12G.cjs.map +1 -0
  88. package/dist/relation-create-Bg-eEJLs.js +337 -0
  89. package/dist/relation-create-Bg-eEJLs.js.map +1 -0
  90. package/dist/relation-many-picker-B-NCEUgX.cjs +465 -0
  91. package/dist/relation-many-picker-B-NCEUgX.cjs.map +1 -0
  92. package/dist/relation-many-picker-gdAOD-qK.js +464 -0
  93. package/dist/relation-many-picker-gdAOD-qK.js.map +1 -0
  94. package/dist/relation-picker-BAY77ivO.js +462 -0
  95. package/dist/relation-picker-BAY77ivO.js.map +1 -0
  96. package/dist/relation-picker-Da_uhFvA.cjs +479 -0
  97. package/dist/relation-picker-Da_uhFvA.cjs.map +1 -0
  98. package/dist/relation-picker-dialog-M0pQaWlp.cjs +300 -0
  99. package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +1 -0
  100. package/dist/relation-picker-dialog-hA9rYrZB.js +299 -0
  101. package/dist/relation-picker-dialog-hA9rYrZB.js.map +1 -0
  102. package/dist/resource-page-router-OSQyRA5b.cjs +1779 -0
  103. package/dist/resource-page-router-OSQyRA5b.cjs.map +1 -0
  104. package/dist/resource-page-router-T4vS5gbJ.js +1582 -0
  105. package/dist/resource-page-router-T4vS5gbJ.js.map +1 -0
  106. package/dist/{rich-text-IDFvyvRE.js → rich-text-DFerywgz.js} +7 -4
  107. package/dist/{rich-text-IDFvyvRE.js.map → rich-text-DFerywgz.js.map} +1 -1
  108. package/dist/{rich-text-lndbYqzR.cjs → rich-text-vTyVjDoa.cjs} +25 -22
  109. package/dist/{rich-text-lndbYqzR.cjs.map → rich-text-vTyVjDoa.cjs.map} +1 -1
  110. package/dist/search-access-B7G5oR8n.cjs +812 -0
  111. package/dist/search-access-B7G5oR8n.cjs.map +1 -0
  112. package/dist/search-access-CURsWn-U.js +669 -0
  113. package/dist/search-access-CURsWn-U.js.map +1 -0
  114. package/dist/shell-BPlk8hEa.js +205 -0
  115. package/dist/shell-BPlk8hEa.js.map +1 -0
  116. package/dist/shell-DxhlsPwm.cjs +271 -0
  117. package/dist/shell-DxhlsPwm.cjs.map +1 -0
  118. package/dist/skeleton-U2noefj5.js +13 -0
  119. package/dist/skeleton-U2noefj5.js.map +1 -0
  120. package/dist/skeleton-_1gP7wan.cjs +18 -0
  121. package/dist/skeleton-_1gP7wan.cjs.map +1 -0
  122. package/dist/styles.css +241 -9
  123. package/dist/toaster-C7CiYA4Z.cjs +248 -0
  124. package/dist/toaster-C7CiYA4Z.cjs.map +1 -0
  125. package/dist/toaster-CfCRLgR-.js +164 -0
  126. package/dist/toaster-CfCRLgR-.js.map +1 -0
  127. package/dist/use-dialog-filter-state-BBCC0OEK.cjs +92 -0
  128. package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +1 -0
  129. package/dist/use-dialog-filter-state-BDcgS5Oz.js +87 -0
  130. package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +1 -0
  131. package/dist/{use-theme-BwPWinB2.cjs → use-theme-DFlpXils.cjs} +12 -1
  132. package/dist/use-theme-DFlpXils.cjs.map +1 -0
  133. package/dist/{use-theme-IHmtrhEt.js → use-theme-dnE3Od3I.js} +7 -2
  134. package/dist/use-theme-dnE3Od3I.js.map +1 -0
  135. package/package.json +16 -14
  136. package/dist/use-theme-BwPWinB2.cjs.map +0 -1
  137. package/dist/use-theme-IHmtrhEt.js.map +0 -1
@@ -0,0 +1,669 @@
1
+ import { l as cn } from "./use-theme-dnE3Od3I.js";
2
+ import { d as useLinkComponent } from "./toaster-CfCRLgR-.js";
3
+ import { i as DialogDescription, r as DialogContent, s as DialogTitle, t as Dialog } from "./dialog-B_rt9S1c.js";
4
+ import { hasRecordPage, relationAmbiguousError, relationOpenOf, resourceKey, resourceShowHref } from "@burojs/core";
5
+ import { PEEK_COMPONENT, QUICK_ANCHOR_ATTRIBUTE, filterFields, quickAnchorRef, useApp, useCurrentUIActivation, useEntryGate, useList, useListAccess, useOptionalT, useQuickOpener, useRelatedRecord, useUIPresentationRuntime } from "@burojs/react";
6
+ import { IconSearch } from "@tabler/icons-react";
7
+ import * as React from "react";
8
+ import { createContext, useCallback, useContext, useEffect, useRef, useState, useSyncExternalStore } from "react";
9
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
10
+ import { Command } from "cmdk";
11
+ //#region src/primitives/command.tsx
12
+ const Command$1 = React.forwardRef(({ className, ...props }, ref) => jsx(Command, {
13
+ ref,
14
+ className: cn("flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground", className),
15
+ ...props
16
+ }));
17
+ Command$1.displayName = Command.displayName;
18
+ const CommandInput = React.forwardRef(({ className, ...props }, ref) => jsxs("div", {
19
+ className: "flex items-center border-b px-3",
20
+ "cmdk-input-wrapper": "",
21
+ children: [jsx(IconSearch, {
22
+ className: "mr-2 h-4 w-4 shrink-0 opacity-50",
23
+ "aria-hidden": "true"
24
+ }), jsx(Command.Input, {
25
+ ref,
26
+ className: cn("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", className),
27
+ ...props
28
+ })]
29
+ }));
30
+ CommandInput.displayName = Command.Input.displayName;
31
+ const CommandList = React.forwardRef(({ className, ...props }, ref) => jsx(Command.List, {
32
+ ref,
33
+ className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
34
+ ...props
35
+ }));
36
+ CommandList.displayName = Command.List.displayName;
37
+ const CommandEmpty = React.forwardRef((props, ref) => jsx(Command.Empty, {
38
+ ref,
39
+ className: "py-6 text-center text-sm text-muted-foreground",
40
+ ...props
41
+ }));
42
+ CommandEmpty.displayName = Command.Empty.displayName;
43
+ const CommandGroup = React.forwardRef(({ className, ...props }, ref) => jsx(Command.Group, {
44
+ ref,
45
+ className: cn("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", className),
46
+ ...props
47
+ }));
48
+ CommandGroup.displayName = Command.Group.displayName;
49
+ const CommandSeparator = React.forwardRef(({ className, ...props }, ref) => jsx(Command.Separator, {
50
+ ref,
51
+ className: cn("-mx-1 h-px bg-border", className),
52
+ ...props
53
+ }));
54
+ CommandSeparator.displayName = Command.Separator.displayName;
55
+ const CommandItem = React.forwardRef(({ className, ...props }, ref) => jsx(Command.Item, {
56
+ ref,
57
+ className: cn("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", className),
58
+ ...props
59
+ }));
60
+ CommandItem.displayName = Command.Item.displayName;
61
+ const CommandLoading = React.forwardRef(({ ...props }, ref) => jsx(Command.Loading, {
62
+ ref,
63
+ ...props
64
+ }));
65
+ CommandLoading.displayName = Command.Loading.displayName;
66
+ function CommandDialog({ open, onOpenChange, defaultOpen, modal, title = "Command Palette", description = "Search and run actions.", className, commandClassName, children, contentProps }) {
67
+ return jsx(Dialog, {
68
+ open,
69
+ onOpenChange,
70
+ defaultOpen,
71
+ modal,
72
+ children: jsxs(DialogContent, {
73
+ ...contentProps,
74
+ className: cn("overflow-hidden p-0 shadow-lg max-w-[480px] sm:max-w-[480px]", className),
75
+ overlayClassName: "backdrop-blur-sm",
76
+ children: [
77
+ jsx(DialogTitle, {
78
+ className: "sr-only",
79
+ children: title
80
+ }),
81
+ jsx(DialogDescription, {
82
+ className: "sr-only",
83
+ children: description
84
+ }),
85
+ jsx(Command$1, {
86
+ className: cn("[&_[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", commandClassName),
87
+ children
88
+ })
89
+ ]
90
+ })
91
+ });
92
+ }
93
+ CommandDialog.displayName = "CommandDialog";
94
+ //#endregion
95
+ //#region src/fields/claimed-quick-link.tsx
96
+ function isPlainLeftClick(event) {
97
+ return event.button === 0 && !event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey;
98
+ }
99
+ function claimAnchor(wrapper) {
100
+ const anchor = wrapper?.querySelector("a") ?? null;
101
+ quickAnchorRef(anchor);
102
+ }
103
+ function ClaimedQuickLink({ href, testid, className, onOpen, children }) {
104
+ const RouterLink = useLinkComponent();
105
+ return jsx("span", {
106
+ ref: claimAnchor,
107
+ className: "contents",
108
+ children: jsx(RouterLink, {
109
+ href,
110
+ ...testid === void 0 ? {} : { "data-testid": testid },
111
+ [QUICK_ANCHOR_ATTRIBUTE]: "",
112
+ ...className === void 0 ? {} : { className },
113
+ onClick: (event) => {
114
+ event.stopPropagation();
115
+ if (!isPlainLeftClick(event) || event.currentTarget.target === "_blank") return;
116
+ event.preventDefault();
117
+ onOpen();
118
+ },
119
+ children
120
+ })
121
+ });
122
+ }
123
+ //#endregion
124
+ //#region src/resource/record-display-name.ts
125
+ function recordDisplayName(record, displayField) {
126
+ if (displayField && record[displayField] != null && record[displayField] !== "") return String(record[displayField]);
127
+ return String(record.id ?? "");
128
+ }
129
+ //#endregion
130
+ //#region src/resource/use-row-title.ts
131
+ function useRowTitle(target, displayField) {
132
+ const access = useListAccess(target);
133
+ const visible = displayField !== void 0 && access.status === "ready" && access.fieldVisible(displayField);
134
+ return useCallback((row) => recordDisplayName(row, visible ? displayField : void 0), [visible, displayField]);
135
+ }
136
+ //#endregion
137
+ //#region src/quick/peek-context.ts
138
+ const PeekHostContext = createContext(null);
139
+ const PeekContext = createContext(false);
140
+ const KEYBOARD_FOCUS_WINDOW_MS = 100;
141
+ const NAVIGATION_KEYS = new Set([
142
+ "Tab",
143
+ "ArrowUp",
144
+ "ArrowDown",
145
+ "ArrowLeft",
146
+ "ArrowRight"
147
+ ]);
148
+ let lastNavigationKeyAt = Number.NEGATIVE_INFINITY;
149
+ const listening = new WeakSet();
150
+ function listenForModality(doc) {
151
+ if (listening.has(doc)) return;
152
+ listening.add(doc);
153
+ doc.addEventListener("keydown", (event) => {
154
+ if (NAVIGATION_KEYS.has(event.key)) lastNavigationKeyAt = Date.now();
155
+ }, true);
156
+ const forget = () => {
157
+ lastNavigationKeyAt = Number.NEGATIVE_INFINITY;
158
+ };
159
+ doc.addEventListener("pointerdown", forget, true);
160
+ doc.addEventListener("mousedown", forget, true);
161
+ }
162
+ function keyboardModality() {
163
+ return Date.now() - lastNavigationKeyAt <= KEYBOARD_FOCUS_WINDOW_MS;
164
+ }
165
+ const focusedByCode = new WeakSet();
166
+ function focusWithoutPeek(element) {
167
+ focusedByCode.add(element);
168
+ element.focus();
169
+ focusedByCode.delete(element);
170
+ }
171
+ const anchorOpeners = new WeakMap();
172
+ function peekAnchorOpener(anchor) {
173
+ return anchor === null ? void 0 : anchorOpeners.get(anchor);
174
+ }
175
+ function anchorIn(wrapper) {
176
+ if (wrapper === null) return null;
177
+ const marked = wrapper.querySelector("[data-buro-quick]");
178
+ if (marked !== null) return marked;
179
+ const first = wrapper.firstElementChild;
180
+ return first instanceof HTMLElement ? first : null;
181
+ }
182
+ const noSubscription = () => () => void 0;
183
+ function PeekIntent({ target, children }) {
184
+ if (useContext(PeekContext)) return jsx(Fragment$1, { children });
185
+ return jsx(ActivePeekIntent, {
186
+ target,
187
+ children
188
+ });
189
+ }
190
+ function ActivePeekIntent({ target, children }) {
191
+ const gate = useEntryGate();
192
+ const runtime = useUIPresentationRuntime();
193
+ const activation = useCurrentUIActivation();
194
+ const [anchor, setAnchor] = useState(null);
195
+ const wrapper = useRef(null);
196
+ const timer = useRef(null);
197
+ const latest = useRef({
198
+ gate,
199
+ target,
200
+ activation
201
+ });
202
+ latest.current = {
203
+ gate,
204
+ target,
205
+ activation
206
+ };
207
+ const attach = useCallback((element) => {
208
+ wrapper.current = element;
209
+ if (element !== null && element.ownerDocument !== void 0) listenForModality(element.ownerDocument);
210
+ setAnchor(anchorIn(element));
211
+ }, []);
212
+ const expanded = useSyncExternalStore(anchor === null ? noSubscription : runtime.subscribe, () => anchor !== null && runtime.getSnapshot().some((d) => d.component === PEEK_COMPONENT && d.anchor?.element === anchor), () => false);
213
+ const peekable = gate(target.to, "peek").state === "open";
214
+ useEffect(() => {
215
+ if (anchor === null) return;
216
+ if (!peekable) {
217
+ anchor.removeAttribute("aria-haspopup");
218
+ anchor.removeAttribute("aria-expanded");
219
+ return;
220
+ }
221
+ anchor.setAttribute("aria-haspopup", "dialog");
222
+ anchor.setAttribute("aria-expanded", expanded ? "true" : "false");
223
+ }, [
224
+ anchor,
225
+ peekable,
226
+ expanded
227
+ ]);
228
+ const quickOpen = useQuickOpener();
229
+ const onOpen = useCallback((to, id) => void quickOpen(to, id), [quickOpen]);
230
+ useEffect(() => {
231
+ if (anchor === null) return;
232
+ anchorOpeners.set(anchor, onOpen);
233
+ return () => {
234
+ if (anchorOpeners.get(anchor) === onOpen) anchorOpeners.delete(anchor);
235
+ };
236
+ }, [anchor, onOpen]);
237
+ const cancel = useCallback(() => {
238
+ if (timer.current === null) return;
239
+ clearTimeout(timer.current);
240
+ timer.current = null;
241
+ }, []);
242
+ useEffect(() => cancel, [cancel]);
243
+ const fire = useCallback(() => {
244
+ timer.current = null;
245
+ const { gate: ask, target: what, activation: from } = latest.current;
246
+ const element = anchorIn(wrapper.current);
247
+ if (element === null || !element.isConnected) return;
248
+ const answer = ask(what.to, "peek");
249
+ if (answer.state !== "open") return;
250
+ const snapshot = runtime.getSnapshot();
251
+ if (snapshot.some((d) => d.component === PEEK_COMPONENT && d.anchor?.element === element)) return;
252
+ for (const descriptor of snapshot) if (descriptor.component === PEEK_COMPONENT) runtime.dismiss(descriptor.id);
253
+ const props = {
254
+ target: answer.target,
255
+ ...what.id === void 0 ? {} : { id: what.id },
256
+ ...what.by === void 0 ? {} : { by: what.by }
257
+ };
258
+ runtime.present({
259
+ component: PEEK_COMPONENT,
260
+ host: "popover",
261
+ anchor: { element },
262
+ props,
263
+ activation: from
264
+ });
265
+ }, [runtime]);
266
+ const schedule = useCallback(() => {
267
+ if (timer.current !== null) return;
268
+ timer.current = setTimeout(fire, 500);
269
+ }, [fire]);
270
+ return jsx("span", {
271
+ ref: attach,
272
+ className: "contents",
273
+ onPointerEnter: (event) => {
274
+ if (event.pointerType === "mouse" || event.pointerType === "pen") schedule();
275
+ },
276
+ onPointerLeave: cancel,
277
+ onFocus: (event) => {
278
+ if (focusedByCode.has(event.target)) return;
279
+ if (keyboardModality()) schedule();
280
+ },
281
+ onBlur: cancel,
282
+ onPointerDown: cancel,
283
+ onClickCapture: cancel,
284
+ children
285
+ });
286
+ }
287
+ //#endregion
288
+ //#region src/fields/relation-display.tsx
289
+ const relationLinkClassName = "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";
290
+ function RelationDisplay({ value, field }) {
291
+ const app = useApp();
292
+ const meta = field?.meta;
293
+ const by = typeof meta?.by === "string" ? meta.by : void 0;
294
+ const lazy = meta?.resolve === "lazy";
295
+ let to;
296
+ try {
297
+ to = meta?.to === void 0 ? void 0 : resourceKey(meta.to);
298
+ } catch {
299
+ to = void 0;
300
+ }
301
+ const id = value;
302
+ const idStr = String(value ?? "");
303
+ const baseId = `relation-display:${to ?? "unknown"}:${idStr}`;
304
+ const open = relationOpenOf({ ui: field?.ui });
305
+ if (value == null || value === "") return jsx("span", {
306
+ "data-testid": `${baseId}:empty`,
307
+ className: "text-muted-foreground",
308
+ children: "—"
309
+ });
310
+ if (!to) {
311
+ if (process.env.NODE_ENV !== "production") console.warn(`[RelationDisplay] no meta.to declared on field — rendering raw value '${idStr}'`);
312
+ return jsx("span", {
313
+ "data-testid": `relation-display:unknown:${idStr}:no-target`,
314
+ children: idStr
315
+ });
316
+ }
317
+ if (lazy) return jsx(LazyRelationDisplay, {
318
+ to,
319
+ by,
320
+ idStr,
321
+ app,
322
+ open
323
+ });
324
+ return jsx(GatedRelationDisplay, {
325
+ to,
326
+ by,
327
+ id,
328
+ idStr,
329
+ app,
330
+ open
331
+ });
332
+ }
333
+ function RelationField({ to, value }) {
334
+ return jsx(RelationDisplay, {
335
+ value,
336
+ field: {
337
+ name: "",
338
+ meta: { to }
339
+ }
340
+ });
341
+ }
342
+ function peekTarget(to, by, key) {
343
+ return by === void 0 ? {
344
+ to,
345
+ id: key
346
+ } : {
347
+ to,
348
+ by: {
349
+ field: by,
350
+ key
351
+ }
352
+ };
353
+ }
354
+ function showPageDef(app, def) {
355
+ const delegate = def.routesTo?.show;
356
+ if (delegate === void 0) return def;
357
+ try {
358
+ return app.registry.get(resourceKey(delegate));
359
+ } catch {
360
+ return;
361
+ }
362
+ }
363
+ function linksToPage(app, def) {
364
+ const target = showPageDef(app, def);
365
+ return target !== void 0 && hasRecordPage(target, "show");
366
+ }
367
+ function QuickOpener({ href, testid, onOpen, children }) {
368
+ if (href === null) return jsx("button", {
369
+ type: "button",
370
+ "data-testid": testid,
371
+ [QUICK_ANCHOR_ATTRIBUTE]: "",
372
+ className: `${relationLinkClassName} text-left`,
373
+ onClick: (event) => {
374
+ event.preventDefault();
375
+ event.stopPropagation();
376
+ onOpen();
377
+ },
378
+ children
379
+ });
380
+ return jsx(ClaimedQuickLink, {
381
+ href,
382
+ testid,
383
+ className: relationLinkClassName,
384
+ onOpen,
385
+ children
386
+ });
387
+ }
388
+ function LazyRelationDisplay({ to, by, idStr, app, open: openMode }) {
389
+ const RouterLink = useLinkComponent();
390
+ const gate = useEntryGate();
391
+ const open = useQuickOpener();
392
+ const targetDef = app.registry.get(to);
393
+ const baseId = `relation-display:${to}:${idStr}`;
394
+ if (!targetDef || openMode === "none") return jsx("span", {
395
+ "data-testid": `${baseId}:lazy`,
396
+ children: idStr
397
+ });
398
+ const answer = gate(to, "show");
399
+ if (answer.state === "undecided") return jsx(PeekIntent, {
400
+ target: peekTarget(to, by, idStr),
401
+ children: jsx("span", {
402
+ "data-testid": `${baseId}:lazy`,
403
+ children: idStr
404
+ })
405
+ });
406
+ if (answer.state === "hidden" || answer.state === "disabled") return jsx("span", {
407
+ "data-testid": `${baseId}:lazy`,
408
+ children: idStr
409
+ });
410
+ const page = linksToPage(app, targetDef);
411
+ if (openMode === "page") {
412
+ if (by !== void 0 || !page) return jsx("span", {
413
+ "data-testid": `${baseId}:lazy`,
414
+ children: idStr
415
+ });
416
+ return jsx(RouterLink, {
417
+ href: resourceShowHref(app.registry, targetDef, to, idStr),
418
+ "data-testid": `${baseId}:lazy`,
419
+ className: relationLinkClassName,
420
+ onClick: (e) => e.stopPropagation(),
421
+ children: idStr
422
+ });
423
+ }
424
+ if (answer.state !== "open") {
425
+ if (by !== void 0 || !page) return jsx("span", {
426
+ "data-testid": `${baseId}:lazy`,
427
+ children: idStr
428
+ });
429
+ return jsx(RouterLink, {
430
+ href: resourceShowHref(app.registry, targetDef, to, idStr),
431
+ "data-testid": `${baseId}:lazy`,
432
+ className: relationLinkClassName,
433
+ onClick: (e) => e.stopPropagation(),
434
+ children: idStr
435
+ });
436
+ }
437
+ if (by !== void 0) return jsx(PeekIntent, {
438
+ target: peekTarget(to, by, idStr),
439
+ children: jsx(LazyByOpener, {
440
+ to,
441
+ by,
442
+ idStr,
443
+ target: answer.target
444
+ })
445
+ });
446
+ const openKey = () => void open(to, idStr);
447
+ return jsx(PeekIntent, {
448
+ target: peekTarget(to, void 0, idStr),
449
+ children: jsx(QuickOpener, {
450
+ href: page ? resourceShowHref(app.registry, targetDef, to, idStr) : null,
451
+ testid: `${baseId}:lazy`,
452
+ onOpen: openKey,
453
+ children: idStr
454
+ })
455
+ });
456
+ }
457
+ function LazyByOpener({ to, by, idStr, target }) {
458
+ const app = useApp();
459
+ const t = useOptionalT();
460
+ const open = useQuickOpener();
461
+ const [asked, setAsked] = useState(false);
462
+ const rows = useList(to, {
463
+ ...asked ? {
464
+ filter: {
465
+ field: by,
466
+ op: "eq",
467
+ value: idStr
468
+ },
469
+ pagination: {
470
+ kind: "offset",
471
+ page: 1,
472
+ pageSize: 2
473
+ }
474
+ } : {},
475
+ enabled: asked,
476
+ retry: false
477
+ }).data?.data;
478
+ const baseId = `relation-display:${to}:${idStr}`;
479
+ const idField = (app.registry.get(target)?.data)?.idField;
480
+ const rowId = rows?.length === 1 ? rows[0]?.[typeof idField === "string" && idField.length > 0 ? idField : "id"] : void 0;
481
+ const requested = useRef(false);
482
+ useEffect(() => {
483
+ if (!asked || rows === void 0 || !requested.current) return;
484
+ if (rows.length > 1) {
485
+ requested.current = false;
486
+ if (process.env.NODE_ENV !== "production") console.error(`[burojs] ${relationAmbiguousError(to, by, idStr).message}`);
487
+ return;
488
+ }
489
+ requested.current = false;
490
+ if (rows.length === 1 && rowId !== void 0 && rowId !== null) open(to, String(rowId));
491
+ }, [
492
+ asked,
493
+ rows,
494
+ rowId,
495
+ open,
496
+ to,
497
+ by,
498
+ idStr
499
+ ]);
500
+ if (asked && rows !== void 0 && rows.length === 0) return jsx("span", {
501
+ "data-testid": `${baseId}:unavailable`,
502
+ className: "text-muted-foreground",
503
+ children: t("relation.unavailable", { defaultValue: "Not available" })
504
+ });
505
+ if (asked && rows !== void 0 && rows.length > 1) return jsx("span", {
506
+ "data-testid": `${baseId}:ambiguous`,
507
+ className: "text-muted-foreground",
508
+ children: idStr
509
+ });
510
+ return jsx("button", {
511
+ type: "button",
512
+ "data-testid": `${baseId}:lazy`,
513
+ [QUICK_ANCHOR_ATTRIBUTE]: "",
514
+ className: `${relationLinkClassName} text-left`,
515
+ onClick: (event) => {
516
+ event.preventDefault();
517
+ event.stopPropagation();
518
+ if (asked && rowId !== void 0 && rowId !== null) open(to, String(rowId));
519
+ else {
520
+ requested.current = true;
521
+ setAsked(true);
522
+ }
523
+ },
524
+ children: idStr
525
+ });
526
+ }
527
+ function GatedRelationDisplay(props) {
528
+ const gate = useEntryGate();
529
+ const target = props.to;
530
+ const { idStr } = props;
531
+ const answer = gate(target, "show");
532
+ if (answer.state === "undecided") return jsx(PeekIntent, {
533
+ target: peekTarget(target, props.by, idStr),
534
+ children: jsx("span", {
535
+ "data-testid": `relation-display:${target}:${idStr}:text`,
536
+ children: idStr
537
+ })
538
+ });
539
+ if (answer.state === "hidden" || answer.state === "disabled") return jsx("span", {
540
+ "data-testid": `relation-display:${target}:${idStr}:text`,
541
+ children: idStr
542
+ });
543
+ return jsx(RelationDisplayBody, {
544
+ ...props,
545
+ quickTarget: answer.state === "open" && props.open === "quick" ? answer.target : null
546
+ });
547
+ }
548
+ function RelationDisplayBody({ to, by, id, idStr, app, open: openMode, quickTarget }) {
549
+ const targetDef = app.registry.get(to);
550
+ const rowTitle = useRowTitle(to, targetDef?.displayField);
551
+ const baseId = `relation-display:${to}:${idStr}`;
552
+ const RouterLink = useLinkComponent();
553
+ const open = useQuickOpener();
554
+ const { record, isLoading, error, ambiguous } = useRelatedRecord(to, id, by === void 0 ? void 0 : { by });
555
+ if (!targetDef) {
556
+ if (process.env.NODE_ENV !== "production") console.warn(`[RelationDisplay] target resource '${to}' not registered — rendering raw value '${idStr}'`);
557
+ return jsx("span", {
558
+ "data-testid": `${baseId}:unregistered`,
559
+ className: "text-muted-foreground",
560
+ children: idStr
561
+ });
562
+ }
563
+ if (isLoading) return jsx("span", {
564
+ "data-testid": `relation-display-loading:${to}`,
565
+ className: "inline-block h-5 w-20 animate-pulse rounded bg-muted",
566
+ "aria-busy": "true"
567
+ });
568
+ if (ambiguous) return jsx("span", {
569
+ "data-testid": `${baseId}:ambiguous`,
570
+ className: "text-muted-foreground",
571
+ title: `${to}: more than one row has ${by ?? "id"} ${idStr}`,
572
+ children: idStr
573
+ });
574
+ if (error) return jsx("span", {
575
+ "data-testid": `${baseId}:error`,
576
+ className: "text-muted-foreground",
577
+ title: error.message,
578
+ children: idStr
579
+ });
580
+ if (!record) return jsx("span", {
581
+ "data-testid": `${baseId}:not-found`,
582
+ className: "text-muted-foreground",
583
+ title: `${to} #${idStr} not found`,
584
+ children: idStr
585
+ });
586
+ const displayName = rowTitle(record);
587
+ const idField = targetDef.data?.idField;
588
+ const rowId = record[typeof idField === "string" && idField.length > 0 ? idField : "id"];
589
+ if (rowId === null || rowId === void 0 || rowId === "") return jsx("span", {
590
+ "data-testid": `${baseId}:no-id`,
591
+ className: "text-muted-foreground",
592
+ children: displayName
593
+ });
594
+ const href = linksToPage(app, targetDef) ? resourceShowHref(app.registry, targetDef, to, String(rowId)) : null;
595
+ if (openMode === "none") return jsx("span", {
596
+ "data-testid": baseId,
597
+ children: displayName
598
+ });
599
+ if (quickTarget !== null) return jsx(RowOpener, {
600
+ to,
601
+ rowId: String(rowId),
602
+ href,
603
+ testid: baseId,
604
+ open,
605
+ children: displayName
606
+ });
607
+ if (href === null) return jsx("span", {
608
+ "data-testid": baseId,
609
+ children: displayName
610
+ });
611
+ return jsx(RouterLink, {
612
+ href,
613
+ "data-testid": baseId,
614
+ className: relationLinkClassName,
615
+ onClick: (e) => e.stopPropagation(),
616
+ children: displayName
617
+ });
618
+ }
619
+ function RowOpener({ to, rowId, href, testid, open, children }) {
620
+ const onOpen = useCallback(() => void open(to, rowId), [
621
+ open,
622
+ to,
623
+ rowId
624
+ ]);
625
+ return jsx(PeekIntent, {
626
+ target: peekTarget(to, void 0, rowId),
627
+ children: jsx(QuickOpener, {
628
+ href,
629
+ testid,
630
+ onOpen,
631
+ children
632
+ })
633
+ });
634
+ }
635
+ function RelationManyDisplay({ value, field }) {
636
+ const keys = Array.isArray(value) ? value : [];
637
+ if (keys.length === 0) return jsx("span", {
638
+ "data-testid": "relation-many-display:empty",
639
+ className: "text-muted-foreground",
640
+ children: "—"
641
+ });
642
+ return jsx("span", {
643
+ className: "inline-flex flex-wrap gap-x-2",
644
+ "data-testid": "relation-many-display",
645
+ children: keys.map((key, index) => jsx(RelationDisplay, {
646
+ value: key,
647
+ field
648
+ }, `${String(key)}:${index}`))
649
+ });
650
+ }
651
+ //#endregion
652
+ //#region src/fields/search-access.ts
653
+ function narrowSearchDecl(declared, visible) {
654
+ if (declared === void 0 || typeof declared === "function") return declared;
655
+ if (!Array.isArray(declared.fields)) return declared;
656
+ const fields = declared.fields.filter((ref) => visible(typeof ref === "string" ? ref : ref.field));
657
+ if (fields.length === declared.fields.length) return declared;
658
+ return fields.length === 0 ? void 0 : {
659
+ ...declared,
660
+ fields
661
+ };
662
+ }
663
+ function namesHiddenField(filter, visible) {
664
+ return filter !== void 0 && filterFields(filter).some((field) => !visible(field));
665
+ }
666
+ //#endregion
667
+ export { CommandLoading as C, CommandList as S, CommandDialog as _, RelationManyDisplay as a, CommandInput as b, focusWithoutPeek as c, PeekHostContext as d, useRowTitle as f, Command$1 as g, isPlainLeftClick as h, RelationField as i, peekAnchorOpener as l, ClaimedQuickLink as m, narrowSearchDecl as n, linksToPage as o, recordDisplayName as p, RelationDisplay as r, relationLinkClassName as s, namesHiddenField as t, PeekContext as u, CommandEmpty as v, CommandSeparator as w, CommandItem as x, CommandGroup as y };
668
+
669
+ //# sourceMappingURL=search-access-CURsWn-U.js.map