@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.
- package/README.md +22 -5
- package/dist/bulk-summary-CwSd6Yjb.cjs +108 -0
- package/dist/bulk-summary-CwSd6Yjb.cjs.map +1 -0
- package/dist/bulk-summary-GxMDP4bw.js +108 -0
- package/dist/bulk-summary-GxMDP4bw.js.map +1 -0
- package/dist/button-BxnnE28H.cjs +55 -0
- package/dist/button-BxnnE28H.cjs.map +1 -0
- package/dist/button-MWVeZaqj.js +44 -0
- package/dist/button-MWVeZaqj.js.map +1 -0
- package/dist/candidates-gate-CX2PBu6l.js +63 -0
- package/dist/candidates-gate-CX2PBu6l.js.map +1 -0
- package/dist/candidates-gate-DiFI52r7.cjs +70 -0
- package/dist/candidates-gate-DiFI52r7.cjs.map +1 -0
- package/dist/candidates-relation-picker-CBsVcnPR.js +82 -0
- package/dist/candidates-relation-picker-CBsVcnPR.js.map +1 -0
- package/dist/candidates-relation-picker-Dd_GVLlu.cjs +84 -0
- package/dist/candidates-relation-picker-Dd_GVLlu.cjs.map +1 -0
- package/dist/check-confirm-dialog-BRByTFpg.cjs +1534 -0
- package/dist/check-confirm-dialog-BRByTFpg.cjs.map +1 -0
- package/dist/check-confirm-dialog-CkaVTPT9.js +1232 -0
- package/dist/check-confirm-dialog-CkaVTPT9.js.map +1 -0
- package/dist/dialog-B_rt9S1c.js +63 -0
- package/dist/dialog-B_rt9S1c.js.map +1 -0
- package/dist/dialog-DRNUq9EA.cjs +112 -0
- package/dist/dialog-DRNUq9EA.cjs.map +1 -0
- package/dist/filter-builder-B3mZFL-K.cjs +1761 -0
- package/dist/filter-builder-B3mZFL-K.cjs.map +1 -0
- package/dist/filter-builder-DOnaXNfP.js +1605 -0
- package/dist/filter-builder-DOnaXNfP.js.map +1 -0
- package/dist/flow-runtime-B6zOHYqI.cjs +255 -0
- package/dist/flow-runtime-B6zOHYqI.cjs.map +1 -0
- package/dist/flow-runtime-D8h99FSg.js +252 -0
- package/dist/flow-runtime-D8h99FSg.js.map +1 -0
- package/dist/flow-screen-CX05b3G9.cjs +705 -0
- package/dist/flow-screen-CX05b3G9.cjs.map +1 -0
- package/dist/flow-screen-CmbARSqg.js +701 -0
- package/dist/flow-screen-CmbARSqg.js.map +1 -0
- package/dist/index.cjs +2825 -11912
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1612 -1862
- package/dist/index.d.ts +1700 -1950
- package/dist/index.js +2498 -11605
- package/dist/index.js.map +1 -1
- package/dist/inline-flow-host-B7U1OJUe.cjs +112 -0
- package/dist/inline-flow-host-B7U1OJUe.cjs.map +1 -0
- package/dist/inline-flow-host-C3H2UpSA.js +112 -0
- package/dist/inline-flow-host-C3H2UpSA.js.map +1 -0
- package/dist/input-BI0czGyI.cjs +23 -0
- package/dist/input-BI0czGyI.cjs.map +1 -0
- package/dist/input-CUPStzZO.js +17 -0
- package/dist/input-CUPStzZO.js.map +1 -0
- package/dist/label-66W1qbke.js +29 -0
- package/dist/label-66W1qbke.js.map +1 -0
- package/dist/label-w6JYf2cF.cjs +36 -0
- package/dist/label-w6JYf2cF.cjs.map +1 -0
- package/dist/lazy-relation-picker-dialog-2oxnA6IR.js +14 -0
- package/dist/lazy-relation-picker-dialog-2oxnA6IR.js.map +1 -0
- package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs +19 -0
- package/dist/lazy-relation-picker-dialog-BfAGKzUG.cjs.map +1 -0
- package/dist/markdown/index.cjs +1 -1
- package/dist/markdown/index.js +1 -1
- package/dist/page-flow-route-CQ7HsbBm.cjs +277 -0
- package/dist/page-flow-route-CQ7HsbBm.cjs.map +1 -0
- package/dist/page-flow-route-CyXSvXSE.js +277 -0
- package/dist/page-flow-route-CyXSvXSE.js.map +1 -0
- package/dist/peek-filter-CnqHwTMU.cjs +51 -0
- package/dist/peek-filter-CnqHwTMU.cjs.map +1 -0
- package/dist/peek-filter-ErLfO153.js +28 -0
- package/dist/peek-filter-ErLfO153.js.map +1 -0
- package/dist/place-node--GdsP688.js +7315 -0
- package/dist/place-node--GdsP688.js.map +1 -0
- package/dist/place-node-SIp4XYQH.cjs +7833 -0
- package/dist/place-node-SIp4XYQH.cjs.map +1 -0
- package/dist/related-list-cards-B6x9HQQp.js +42 -0
- package/dist/related-list-cards-B6x9HQQp.js.map +1 -0
- package/dist/related-list-cards-nxuODlIA.cjs +42 -0
- package/dist/related-list-cards-nxuODlIA.cjs.map +1 -0
- package/dist/related-list-timeline-BYJKEbmA.cjs +142 -0
- package/dist/related-list-timeline-BYJKEbmA.cjs.map +1 -0
- package/dist/related-list-timeline-DEdfd-rr.js +142 -0
- package/dist/related-list-timeline-DEdfd-rr.js.map +1 -0
- package/dist/related-rows-B4levHcR.js +186 -0
- package/dist/related-rows-B4levHcR.js.map +1 -0
- package/dist/related-rows-zh5f_4QR.cjs +209 -0
- package/dist/related-rows-zh5f_4QR.cjs.map +1 -0
- package/dist/relation-create-BOaUe12G.cjs +362 -0
- package/dist/relation-create-BOaUe12G.cjs.map +1 -0
- package/dist/relation-create-Bg-eEJLs.js +337 -0
- package/dist/relation-create-Bg-eEJLs.js.map +1 -0
- package/dist/relation-many-picker-B-NCEUgX.cjs +465 -0
- package/dist/relation-many-picker-B-NCEUgX.cjs.map +1 -0
- package/dist/relation-many-picker-gdAOD-qK.js +464 -0
- package/dist/relation-many-picker-gdAOD-qK.js.map +1 -0
- package/dist/relation-picker-BAY77ivO.js +462 -0
- package/dist/relation-picker-BAY77ivO.js.map +1 -0
- package/dist/relation-picker-Da_uhFvA.cjs +479 -0
- package/dist/relation-picker-Da_uhFvA.cjs.map +1 -0
- package/dist/relation-picker-dialog-M0pQaWlp.cjs +300 -0
- package/dist/relation-picker-dialog-M0pQaWlp.cjs.map +1 -0
- package/dist/relation-picker-dialog-hA9rYrZB.js +299 -0
- package/dist/relation-picker-dialog-hA9rYrZB.js.map +1 -0
- package/dist/resource-page-router-OSQyRA5b.cjs +1779 -0
- package/dist/resource-page-router-OSQyRA5b.cjs.map +1 -0
- package/dist/resource-page-router-T4vS5gbJ.js +1582 -0
- package/dist/resource-page-router-T4vS5gbJ.js.map +1 -0
- package/dist/{rich-text-IDFvyvRE.js → rich-text-DFerywgz.js} +7 -4
- package/dist/{rich-text-IDFvyvRE.js.map → rich-text-DFerywgz.js.map} +1 -1
- package/dist/{rich-text-lndbYqzR.cjs → rich-text-vTyVjDoa.cjs} +25 -22
- package/dist/{rich-text-lndbYqzR.cjs.map → rich-text-vTyVjDoa.cjs.map} +1 -1
- package/dist/search-access-B7G5oR8n.cjs +812 -0
- package/dist/search-access-B7G5oR8n.cjs.map +1 -0
- package/dist/search-access-CURsWn-U.js +669 -0
- package/dist/search-access-CURsWn-U.js.map +1 -0
- package/dist/shell-BPlk8hEa.js +205 -0
- package/dist/shell-BPlk8hEa.js.map +1 -0
- package/dist/shell-DxhlsPwm.cjs +271 -0
- package/dist/shell-DxhlsPwm.cjs.map +1 -0
- package/dist/skeleton-U2noefj5.js +13 -0
- package/dist/skeleton-U2noefj5.js.map +1 -0
- package/dist/skeleton-_1gP7wan.cjs +18 -0
- package/dist/skeleton-_1gP7wan.cjs.map +1 -0
- package/dist/styles.css +241 -9
- package/dist/toaster-C7CiYA4Z.cjs +248 -0
- package/dist/toaster-C7CiYA4Z.cjs.map +1 -0
- package/dist/toaster-CfCRLgR-.js +164 -0
- package/dist/toaster-CfCRLgR-.js.map +1 -0
- package/dist/use-dialog-filter-state-BBCC0OEK.cjs +92 -0
- package/dist/use-dialog-filter-state-BBCC0OEK.cjs.map +1 -0
- package/dist/use-dialog-filter-state-BDcgS5Oz.js +87 -0
- package/dist/use-dialog-filter-state-BDcgS5Oz.js.map +1 -0
- package/dist/{use-theme-BwPWinB2.cjs → use-theme-DFlpXils.cjs} +12 -1
- package/dist/use-theme-DFlpXils.cjs.map +1 -0
- package/dist/{use-theme-IHmtrhEt.js → use-theme-dnE3Od3I.js} +7 -2
- package/dist/use-theme-dnE3Od3I.js.map +1 -0
- package/package.json +16 -14
- package/dist/use-theme-BwPWinB2.cjs.map +0 -1
- 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
|