@burojs/ui-shadcn 0.3.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 +26 -7
- 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 +6453 -17494
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3754 -3621
- package/dist/index.d.ts +3754 -3621
- package/dist/index.js +6217 -17219
- 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/layout/theme-storage-key.cjs +5 -10
- package/dist/layout/theme-storage-key.cjs.map +1 -1
- package/dist/layout/theme-storage-key.d.cts +2 -23
- package/dist/layout/theme-storage-key.d.ts +2 -23
- package/dist/layout/theme-storage-key.js +5 -2
- package/dist/layout/theme-storage-key.js.map +1 -1
- 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 +424 -511
- package/dist/markdown/index.cjs.map +1 -1
- package/dist/markdown/index.d.cts +1072 -34
- package/dist/markdown/index.d.ts +1072 -34
- package/dist/markdown/index.js +411 -459
- package/dist/markdown/index.js.map +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-DFerywgz.js +457 -0
- package/dist/rich-text-DFerywgz.js.map +1 -0
- package/dist/rich-text-vTyVjDoa.cjs +460 -0
- package/dist/rich-text-vTyVjDoa.cjs.map +1 -0
- 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 +255 -17
- package/dist/theme/theme-css.cjs +95 -96
- package/dist/theme/theme-css.cjs.map +1 -1
- package/dist/theme/theme-css.d.cts +10 -8
- package/dist/theme/theme-css.d.ts +10 -8
- package/dist/theme/theme-css.js +94 -94
- package/dist/theme/theme-css.js.map +1 -1
- package/dist/theme/theme-storage.cjs +34 -39
- package/dist/theme/theme-storage.cjs.map +1 -1
- package/dist/theme/theme-storage.d.cts +3 -1
- package/dist/theme/theme-storage.d.ts +3 -1
- package/dist/theme/theme-storage.js +33 -37
- package/dist/theme/theme-storage.js.map +1 -1
- package/dist/theme-storage-key-pYlp4aDS.d.cts +31 -0
- package/dist/theme-storage-key-pYlp4aDS.d.ts +31 -0
- 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-DFlpXils.cjs +257 -0
- package/dist/use-theme-DFlpXils.cjs.map +1 -0
- package/dist/use-theme-dnE3Od3I.js +175 -0
- package/dist/use-theme-dnE3Od3I.js.map +1 -0
- package/package.json +18 -17
- package/dist/chunk-ABUQPOOE.js +0 -11
- package/dist/chunk-ABUQPOOE.js.map +0 -1
- package/dist/chunk-DBGGWBFG.cjs +0 -199
- package/dist/chunk-DBGGWBFG.cjs.map +0 -1
- package/dist/chunk-FMX4GLCQ.js +0 -6
- package/dist/chunk-FMX4GLCQ.js.map +0 -1
- package/dist/chunk-UC57Z243.js +0 -143
- package/dist/chunk-UC57Z243.js.map +0 -1
- package/dist/chunk-UPGPO75B.js +0 -164
- package/dist/chunk-UPGPO75B.js.map +0 -1
- package/dist/chunk-VXJAXJ3U.cjs +0 -8
- package/dist/chunk-VXJAXJ3U.cjs.map +0 -1
- package/dist/chunk-W7AEYE7A.cjs +0 -13
- package/dist/chunk-W7AEYE7A.cjs.map +0 -1
- package/dist/chunk-YF5IW525.cjs +0 -155
- package/dist/chunk-YF5IW525.cjs.map +0 -1
- package/dist/rich-text-6V7WZ3WV.cjs +0 -518
- package/dist/rich-text-6V7WZ3WV.cjs.map +0 -1
- package/dist/rich-text-N2FZEJJV.js +0 -491
- package/dist/rich-text-N2FZEJJV.js.map +0 -1
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
const require_use_theme = require("./use-theme-DFlpXils.cjs");
|
|
2
|
+
const require_toaster = require("./toaster-C7CiYA4Z.cjs");
|
|
3
|
+
const require_button = require("./button-BxnnE28H.cjs");
|
|
4
|
+
const require_search_access = require("./search-access-B7G5oR8n.cjs");
|
|
5
|
+
const require_lazy_relation_picker_dialog = require("./lazy-relation-picker-dialog-BfAGKzUG.cjs");
|
|
6
|
+
const require_relation_create = require("./relation-create-BOaUe12G.cjs");
|
|
7
|
+
const require_candidates_gate = require("./candidates-gate-DiFI52r7.cjs");
|
|
8
|
+
let _burojs_core = require("@burojs/core");
|
|
9
|
+
let _burojs_react = require("@burojs/react");
|
|
10
|
+
let _tabler_icons_react = require("@tabler/icons-react");
|
|
11
|
+
let react = require("react");
|
|
12
|
+
react = require_use_theme.__toESM(react, 1);
|
|
13
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
14
|
+
//#region src/fields/relation-many-picker.tsx
|
|
15
|
+
const DEBOUNCE_MS = 250;
|
|
16
|
+
function keysOf(value) {
|
|
17
|
+
if (!Array.isArray(value)) return [];
|
|
18
|
+
const seen = new Set();
|
|
19
|
+
const out = [];
|
|
20
|
+
for (const entry of value) {
|
|
21
|
+
const key = require_relation_create.selectKey(entry);
|
|
22
|
+
if (key === null || seen.has(key)) continue;
|
|
23
|
+
seen.add(key);
|
|
24
|
+
out.push(entry);
|
|
25
|
+
}
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
function RelationManyPickerInput(props) {
|
|
29
|
+
const { name, id, value, onChange, testid, field, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage, relationSeeds, fixedFilters, metaSources, resource } = props;
|
|
30
|
+
const meta = field?.meta;
|
|
31
|
+
let to;
|
|
32
|
+
try {
|
|
33
|
+
to = meta?.to === void 0 ? void 0 : (0, _burojs_core.resourceKey)(meta.to);
|
|
34
|
+
} catch {
|
|
35
|
+
to = void 0;
|
|
36
|
+
}
|
|
37
|
+
const gate = require_candidates_gate.useCandidatesGate({
|
|
38
|
+
to,
|
|
39
|
+
candidates: Array.isArray(meta?.candidates) ? meta.candidates : void 0,
|
|
40
|
+
sources: metaSources,
|
|
41
|
+
resource: resource ?? "",
|
|
42
|
+
fieldName: field?.name ?? name
|
|
43
|
+
});
|
|
44
|
+
if (!to) return (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
45
|
+
type: "button",
|
|
46
|
+
variant: "outline",
|
|
47
|
+
disabled: true,
|
|
48
|
+
"data-testid": `${testid ?? `relation-many:${name}`}:no-target`,
|
|
49
|
+
className: "w-full justify-between font-normal",
|
|
50
|
+
name,
|
|
51
|
+
id,
|
|
52
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
53
|
+
className: "truncate text-muted-foreground",
|
|
54
|
+
children: "—"
|
|
55
|
+
})
|
|
56
|
+
});
|
|
57
|
+
const filters = gate.filters.length === 0 ? fixedFilters : [...gate.filters, ...fixedFilters ?? []];
|
|
58
|
+
return (0, react_jsx_runtime.jsx)(ManyPicker, {
|
|
59
|
+
to,
|
|
60
|
+
keys: keysOf(value),
|
|
61
|
+
onChange: (next) => onChange(next),
|
|
62
|
+
...typeof meta?.by === "string" ? { by: meta.by } : {},
|
|
63
|
+
searchField: meta?.searchField,
|
|
64
|
+
fixedFilters: filters,
|
|
65
|
+
...gate.gate === void 0 ? {} : { gate: gate.gate },
|
|
66
|
+
createSeeds: relationSeeds,
|
|
67
|
+
name,
|
|
68
|
+
id,
|
|
69
|
+
testid: testid ?? `relation-many:${to}`,
|
|
70
|
+
resource: resource ?? "",
|
|
71
|
+
fieldName: field?.name ?? name,
|
|
72
|
+
open: (0, _burojs_core.relationOpenOf)(field ?? {}),
|
|
73
|
+
disabled,
|
|
74
|
+
required,
|
|
75
|
+
ariaInvalid,
|
|
76
|
+
ariaDescribedBy,
|
|
77
|
+
ariaErrorMessage
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
function ManyPicker({ to, keys, onChange, by, searchField, fixedFilters, gate, createSeeds, name, id, testid, resource, fieldName, open: openMode, disabled, required, ariaInvalid, ariaDescribedBy, ariaErrorMessage }) {
|
|
81
|
+
const app = (0, _burojs_react.useApp)();
|
|
82
|
+
const caps = (0, _burojs_react.useI18nCaps)();
|
|
83
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
84
|
+
const tid = (0, _burojs_react.useTestIds)();
|
|
85
|
+
const targetDef = app.registry.get(to);
|
|
86
|
+
const rowTitle = require_search_access.useRowTitle(to, targetDef?.displayField);
|
|
87
|
+
const targetLabel = (0, _burojs_core.resolveResourceLabel)(caps, to, "single", targetDef).toLowerCase();
|
|
88
|
+
const childPrefix = `relation-picker:${to}`;
|
|
89
|
+
const effectiveSearchField = searchField ?? targetDef?.displayField ?? "name";
|
|
90
|
+
const [open, setOpen] = react.useState(false);
|
|
91
|
+
const [dialogOpen, setDialogOpen] = react.useState(false);
|
|
92
|
+
const gated = gate !== void 0;
|
|
93
|
+
const [dialogMounted, setDialogMounted] = react.useState(false);
|
|
94
|
+
react.useEffect(() => {
|
|
95
|
+
if (gated) setDialogOpen(false);
|
|
96
|
+
}, [gated]);
|
|
97
|
+
react.useEffect(() => {
|
|
98
|
+
if (dialogOpen) setDialogMounted(true);
|
|
99
|
+
}, [dialogOpen]);
|
|
100
|
+
const [search, setSearch] = react.useState("");
|
|
101
|
+
const [debouncedSearch, setDebouncedSearch] = react.useState("");
|
|
102
|
+
const triggerRef = react.useRef(null);
|
|
103
|
+
const focusTrigger = react.useCallback(() => triggerRef.current?.focus(), []);
|
|
104
|
+
react.useEffect(() => {
|
|
105
|
+
const handle = setTimeout(() => setDebouncedSearch(search), DEBOUNCE_MS);
|
|
106
|
+
return () => clearTimeout(handle);
|
|
107
|
+
}, [search]);
|
|
108
|
+
react.useEffect(() => {
|
|
109
|
+
if (!open) {
|
|
110
|
+
setSearch("");
|
|
111
|
+
setDebouncedSearch("");
|
|
112
|
+
}
|
|
113
|
+
}, [open]);
|
|
114
|
+
const targetIdField = (targetDef?.data)?.idField;
|
|
115
|
+
const idField = typeof targetIdField === "string" && targetIdField.length > 0 ? targetIdField : "id";
|
|
116
|
+
const valueField = by ?? idField;
|
|
117
|
+
const access = (0, _burojs_react.useListAccess)(to);
|
|
118
|
+
const accessReady = access.status === "ready";
|
|
119
|
+
const searchDecl = react.useMemo(() => require_search_access.narrowSearchDecl(targetDef?.views?.list?.search ?? { fields: [effectiveSearchField] }, (field) => access.fieldVisible(field)), [
|
|
120
|
+
targetDef,
|
|
121
|
+
effectiveSearchField,
|
|
122
|
+
access
|
|
123
|
+
]);
|
|
124
|
+
const filter = react.useMemo(() => (0, _burojs_core.composeListFilter)({
|
|
125
|
+
fixed: (0, _burojs_core.normalizeFixedFilters)(fixedFilters),
|
|
126
|
+
search: debouncedSearch,
|
|
127
|
+
searchDecl,
|
|
128
|
+
searchContext: {
|
|
129
|
+
resource: to,
|
|
130
|
+
def: targetDef
|
|
131
|
+
}
|
|
132
|
+
}), [
|
|
133
|
+
fixedFilters,
|
|
134
|
+
debouncedSearch,
|
|
135
|
+
searchDecl,
|
|
136
|
+
to,
|
|
137
|
+
targetDef
|
|
138
|
+
]);
|
|
139
|
+
const blocked = !accessReady || gate !== void 0 || require_search_access.namesHiddenField(filter, (field) => access.fieldVisible(field));
|
|
140
|
+
const append = react.useCallback((next) => {
|
|
141
|
+
if (keys.some((key) => String(key) === String(next))) return;
|
|
142
|
+
onChange([...keys, next]);
|
|
143
|
+
}, [keys, onChange]);
|
|
144
|
+
const toggle = react.useCallback((next) => {
|
|
145
|
+
onChange(keys.some((key) => String(key) === String(next)) ? keys.filter((key) => String(key) !== String(next)) : [...keys, next]);
|
|
146
|
+
}, [keys, onChange]);
|
|
147
|
+
const { create, reader: createReader } = require_relation_create.useSelectCreate({
|
|
148
|
+
to,
|
|
149
|
+
by,
|
|
150
|
+
valueField,
|
|
151
|
+
idField,
|
|
152
|
+
fixedFilters,
|
|
153
|
+
held: gated,
|
|
154
|
+
searchDecl,
|
|
155
|
+
searchContext: {
|
|
156
|
+
resource: to,
|
|
157
|
+
def: targetDef
|
|
158
|
+
},
|
|
159
|
+
onValue: (picked) => {
|
|
160
|
+
append(picked);
|
|
161
|
+
setDialogOpen(false);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
const listQuery = (0, _burojs_react.useList)(to, {
|
|
165
|
+
...filter ? { filter } : {},
|
|
166
|
+
pagination: {
|
|
167
|
+
kind: "offset",
|
|
168
|
+
page: 1,
|
|
169
|
+
pageSize: 10
|
|
170
|
+
},
|
|
171
|
+
...fixedFilters && fixedFilters.length > 0 ? { providerOptionsOverride: { ignoreScope: true } } : {},
|
|
172
|
+
enabled: open && targetDef != null && !blocked
|
|
173
|
+
});
|
|
174
|
+
const rows = listQuery.data?.data ?? [];
|
|
175
|
+
const isLoading = listQuery.isLoading || listQuery.isFetching;
|
|
176
|
+
const error = listQuery.isError ? listQuery.error : null;
|
|
177
|
+
if (!targetDef) return (0, react_jsx_runtime.jsx)(require_button.Button, {
|
|
178
|
+
type: "button",
|
|
179
|
+
variant: "outline",
|
|
180
|
+
disabled: true,
|
|
181
|
+
"data-testid": `${childPrefix}:unregistered`,
|
|
182
|
+
className: "w-full justify-between font-normal",
|
|
183
|
+
name,
|
|
184
|
+
id,
|
|
185
|
+
children: (0, react_jsx_runtime.jsx)("span", {
|
|
186
|
+
className: "truncate text-muted-foreground",
|
|
187
|
+
children: keys.map(String).join(", ") || "—"
|
|
188
|
+
})
|
|
189
|
+
});
|
|
190
|
+
const placeholder = t("relation.select", {
|
|
191
|
+
params: { name: targetLabel },
|
|
192
|
+
defaultValue: `Select ${targetLabel}…`
|
|
193
|
+
});
|
|
194
|
+
const chips = (0, react_jsx_runtime.jsx)("div", {
|
|
195
|
+
className: "flex flex-wrap items-center gap-1",
|
|
196
|
+
"data-testid": `${testid}:chips`,
|
|
197
|
+
children: keys.map((key) => (0, react_jsx_runtime.jsx)(Chip, {
|
|
198
|
+
to,
|
|
199
|
+
keyValue: key,
|
|
200
|
+
by,
|
|
201
|
+
resource,
|
|
202
|
+
fieldName,
|
|
203
|
+
open: openMode,
|
|
204
|
+
testId: tid.relationManyChip(resource, fieldName, String(key)),
|
|
205
|
+
disabled: disabled === true,
|
|
206
|
+
ignoreScope: fixedFilters !== void 0 && fixedFilters.length > 0,
|
|
207
|
+
focusTrigger,
|
|
208
|
+
onRemove: () => onChange(keys.filter((entry) => String(entry) !== String(key)))
|
|
209
|
+
}, String(key)))
|
|
210
|
+
});
|
|
211
|
+
if (gate?.kind === "pending") return (0, react_jsx_runtime.jsxs)("div", {
|
|
212
|
+
className: "flex flex-col gap-1.5",
|
|
213
|
+
children: [chips, (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
214
|
+
type: "button",
|
|
215
|
+
variant: "outline",
|
|
216
|
+
disabled: true,
|
|
217
|
+
"aria-busy": "true",
|
|
218
|
+
"data-testid": testid,
|
|
219
|
+
"data-buro-candidates": "pending",
|
|
220
|
+
className: "w-full justify-between font-normal",
|
|
221
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
222
|
+
className: "truncate text-muted-foreground",
|
|
223
|
+
children: placeholder
|
|
224
|
+
}), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
|
|
225
|
+
className: "h-4 w-4 shrink-0 animate-spin opacity-50",
|
|
226
|
+
"aria-hidden": true
|
|
227
|
+
})]
|
|
228
|
+
})]
|
|
229
|
+
});
|
|
230
|
+
if (gate?.kind === "forbidden") return (0, react_jsx_runtime.jsxs)("div", {
|
|
231
|
+
className: "flex flex-col gap-1.5",
|
|
232
|
+
children: [
|
|
233
|
+
chips,
|
|
234
|
+
(0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
235
|
+
type: "button",
|
|
236
|
+
variant: "outline",
|
|
237
|
+
disabled: true,
|
|
238
|
+
"data-testid": testid,
|
|
239
|
+
"data-buro-candidates": "forbidden",
|
|
240
|
+
"aria-describedby": gate.testId,
|
|
241
|
+
className: "w-full justify-between font-normal",
|
|
242
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
243
|
+
className: "truncate text-muted-foreground",
|
|
244
|
+
children: placeholder
|
|
245
|
+
}), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, {
|
|
246
|
+
className: "h-4 w-4 shrink-0 opacity-50",
|
|
247
|
+
"aria-hidden": true
|
|
248
|
+
})]
|
|
249
|
+
}),
|
|
250
|
+
(0, react_jsx_runtime.jsx)("p", {
|
|
251
|
+
id: gate.testId,
|
|
252
|
+
"data-testid": gate.testId,
|
|
253
|
+
className: "text-xs text-muted-foreground",
|
|
254
|
+
children: gate.message
|
|
255
|
+
})
|
|
256
|
+
]
|
|
257
|
+
});
|
|
258
|
+
return (0, react_jsx_runtime.jsxs)(require_toaster.Popover, {
|
|
259
|
+
open,
|
|
260
|
+
onOpenChange: setOpen,
|
|
261
|
+
children: [
|
|
262
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
263
|
+
className: "flex flex-col gap-1.5",
|
|
264
|
+
children: [chips, (0, react_jsx_runtime.jsx)(require_toaster.PopoverTrigger, {
|
|
265
|
+
asChild: true,
|
|
266
|
+
children: (0, react_jsx_runtime.jsxs)(require_button.Button, {
|
|
267
|
+
ref: triggerRef,
|
|
268
|
+
type: "button",
|
|
269
|
+
variant: "outline",
|
|
270
|
+
role: "combobox",
|
|
271
|
+
"aria-expanded": open,
|
|
272
|
+
"aria-haspopup": "listbox",
|
|
273
|
+
"aria-required": required,
|
|
274
|
+
"aria-invalid": ariaInvalid || void 0,
|
|
275
|
+
"aria-describedby": ariaDescribedBy,
|
|
276
|
+
...ariaErrorMessage ? { "aria-errormessage": ariaErrorMessage } : {},
|
|
277
|
+
disabled,
|
|
278
|
+
"data-testid": testid,
|
|
279
|
+
name,
|
|
280
|
+
id,
|
|
281
|
+
className: "w-full justify-between font-normal",
|
|
282
|
+
children: [(0, react_jsx_runtime.jsx)("span", {
|
|
283
|
+
className: "truncate text-left text-muted-foreground",
|
|
284
|
+
children: placeholder
|
|
285
|
+
}), (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconChevronDown, {
|
|
286
|
+
className: "h-4 w-4 shrink-0 opacity-50",
|
|
287
|
+
"aria-hidden": true
|
|
288
|
+
})]
|
|
289
|
+
})
|
|
290
|
+
})]
|
|
291
|
+
}),
|
|
292
|
+
(0, react_jsx_runtime.jsx)(require_toaster.PopoverContent, {
|
|
293
|
+
className: "w-[var(--radix-popover-trigger-width)] p-0",
|
|
294
|
+
align: "start",
|
|
295
|
+
children: gate?.kind === "empty" ? (0, react_jsx_runtime.jsx)("p", {
|
|
296
|
+
className: "px-3 py-6 text-center text-sm text-muted-foreground",
|
|
297
|
+
"data-testid": gate.testId,
|
|
298
|
+
children: gate.message
|
|
299
|
+
}) : (0, react_jsx_runtime.jsxs)(require_search_access.Command, {
|
|
300
|
+
shouldFilter: false,
|
|
301
|
+
children: [
|
|
302
|
+
searchDecl !== void 0 && (0, react_jsx_runtime.jsx)(require_search_access.CommandInput, {
|
|
303
|
+
value: search,
|
|
304
|
+
onValueChange: setSearch,
|
|
305
|
+
placeholder: t("toolbar.search", {
|
|
306
|
+
params: { name: targetLabel },
|
|
307
|
+
defaultValue: `Search ${targetLabel}…`
|
|
308
|
+
}),
|
|
309
|
+
"data-testid": `${childPrefix}:search`,
|
|
310
|
+
"aria-label": t("toolbar.search", {
|
|
311
|
+
params: { name: targetLabel },
|
|
312
|
+
defaultValue: `Search ${targetLabel}`
|
|
313
|
+
}),
|
|
314
|
+
onKeyDown: (event) => {
|
|
315
|
+
if (event.key === "Backspace" && search === "" && keys.length > 0) {
|
|
316
|
+
event.preventDefault();
|
|
317
|
+
onChange(keys.slice(0, -1));
|
|
318
|
+
}
|
|
319
|
+
if (event.key === " " && search === "") {
|
|
320
|
+
event.preventDefault();
|
|
321
|
+
document.querySelector(`[data-testid="${childPrefix}:list"] [aria-selected="true"]`)?.click();
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}),
|
|
325
|
+
(0, react_jsx_runtime.jsxs)(require_search_access.CommandList, {
|
|
326
|
+
"data-testid": `${childPrefix}:list`,
|
|
327
|
+
"aria-multiselectable": "true",
|
|
328
|
+
"aria-label": targetLabel,
|
|
329
|
+
children: [
|
|
330
|
+
isLoading && (0, react_jsx_runtime.jsxs)("div", {
|
|
331
|
+
className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
|
|
332
|
+
"data-testid": `${childPrefix}:loading`,
|
|
333
|
+
children: [(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconLoader2, {
|
|
334
|
+
className: "h-4 w-4 animate-spin",
|
|
335
|
+
"aria-hidden": true
|
|
336
|
+
}), (0, react_jsx_runtime.jsx)("span", { children: t("table.loading", { defaultValue: "Loading…" }) })]
|
|
337
|
+
}),
|
|
338
|
+
!isLoading && error && (0, react_jsx_runtime.jsx)("div", {
|
|
339
|
+
className: "px-3 py-6 text-center text-sm text-muted-foreground",
|
|
340
|
+
"data-testid": `${childPrefix}:error`,
|
|
341
|
+
title: error.message,
|
|
342
|
+
children: t("relation.failed", { defaultValue: "Failed to load options." })
|
|
343
|
+
}),
|
|
344
|
+
!isLoading && !error && rows.length === 0 && (0, react_jsx_runtime.jsx)(require_search_access.CommandEmpty, {
|
|
345
|
+
"data-testid": `${childPrefix}:empty`,
|
|
346
|
+
children: t("relation.noResults", { defaultValue: "No results." })
|
|
347
|
+
}),
|
|
348
|
+
!isLoading && !error && rows.map((row) => {
|
|
349
|
+
const rowValue = row[valueField];
|
|
350
|
+
if (rowValue === null || rowValue === void 0 || rowValue === "") return null;
|
|
351
|
+
const idStr = String(rowValue);
|
|
352
|
+
const label = rowTitle(row);
|
|
353
|
+
const chosen = keys.some((key) => String(key) === idStr);
|
|
354
|
+
return (0, react_jsx_runtime.jsxs)(require_search_access.CommandItem, {
|
|
355
|
+
value: `${label} ${idStr}`,
|
|
356
|
+
"data-testid": `${childPrefix}:option:${idStr}`,
|
|
357
|
+
"aria-checked": chosen,
|
|
358
|
+
onSelect: () => toggle(rowValue),
|
|
359
|
+
children: [
|
|
360
|
+
(0, react_jsx_runtime.jsx)(_tabler_icons_react.IconCheck, {
|
|
361
|
+
className: require_use_theme.cn("mr-2 h-4 w-4 shrink-0", chosen ? "opacity-100" : "opacity-0"),
|
|
362
|
+
"aria-hidden": true
|
|
363
|
+
}),
|
|
364
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
365
|
+
className: "truncate",
|
|
366
|
+
children: label
|
|
367
|
+
}),
|
|
368
|
+
label === idStr ? null : (0, react_jsx_runtime.jsxs)("span", {
|
|
369
|
+
className: "ml-auto shrink-0 pl-2 text-xs text-muted-foreground",
|
|
370
|
+
children: ["#", idStr]
|
|
371
|
+
})
|
|
372
|
+
]
|
|
373
|
+
}, idStr);
|
|
374
|
+
})
|
|
375
|
+
]
|
|
376
|
+
}),
|
|
377
|
+
(0, react_jsx_runtime.jsxs)("div", {
|
|
378
|
+
className: "flex items-center justify-between gap-2 border-t px-3 py-2 text-sm",
|
|
379
|
+
children: [(0, react_jsx_runtime.jsx)("button", {
|
|
380
|
+
type: "button",
|
|
381
|
+
onClick: () => {
|
|
382
|
+
setOpen(false);
|
|
383
|
+
setDialogOpen(true);
|
|
384
|
+
},
|
|
385
|
+
"data-testid": `${childPrefix}:advanced`,
|
|
386
|
+
className: "text-foreground hover:underline focus:outline-hidden focus-visible:underline",
|
|
387
|
+
children: t("relationPicker.advancedSearch", { defaultValue: "Advanced search" })
|
|
388
|
+
}), !disabled && (0, react_jsx_runtime.jsx)(require_relation_create.RelationCreateButton, {
|
|
389
|
+
to,
|
|
390
|
+
fieldName,
|
|
391
|
+
create,
|
|
392
|
+
seeds: createSeeds,
|
|
393
|
+
search,
|
|
394
|
+
beforeOpen: () => {
|
|
395
|
+
setOpen(false);
|
|
396
|
+
focusTrigger();
|
|
397
|
+
},
|
|
398
|
+
className: "text-foreground hover:underline focus:outline-hidden focus-visible:underline disabled:opacity-50"
|
|
399
|
+
})]
|
|
400
|
+
})
|
|
401
|
+
]
|
|
402
|
+
})
|
|
403
|
+
}),
|
|
404
|
+
dialogMounted && !gated && (0, react_jsx_runtime.jsx)(require_lazy_relation_picker_dialog.LazyRelationPickerDialog, {
|
|
405
|
+
to,
|
|
406
|
+
open: dialogOpen,
|
|
407
|
+
onOpenChange: setDialogOpen,
|
|
408
|
+
onSelect: () => void 0,
|
|
409
|
+
multiple: true,
|
|
410
|
+
selected: keys,
|
|
411
|
+
onToggle: toggle,
|
|
412
|
+
valueField,
|
|
413
|
+
searchField,
|
|
414
|
+
fixedFilters,
|
|
415
|
+
...disabled ? {} : { create },
|
|
416
|
+
createSeeds,
|
|
417
|
+
fieldName,
|
|
418
|
+
onBeforeCreate: focusTrigger
|
|
419
|
+
}),
|
|
420
|
+
createReader
|
|
421
|
+
]
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
function Chip({ to, keyValue, by, resource, fieldName, testId, open: openMode, disabled, ignoreScope, focusTrigger, onRemove }) {
|
|
425
|
+
const t = (0, _burojs_react.useOptionalT)();
|
|
426
|
+
const targetDef = (0, _burojs_react.useApp)().registry.get(to);
|
|
427
|
+
const rowTitle = require_search_access.useRowTitle(to, targetDef?.displayField);
|
|
428
|
+
const { record, isLoading } = (0, _burojs_react.useRelatedRecord)(to, keyValue, by === void 0 ? void 0 : { by });
|
|
429
|
+
const title = record ? rowTitle(record) : String(keyValue);
|
|
430
|
+
return (0, react_jsx_runtime.jsxs)("span", {
|
|
431
|
+
"data-testid": testId,
|
|
432
|
+
"data-resource": resource,
|
|
433
|
+
className: "inline-flex items-center gap-0.5 rounded-md border bg-secondary pl-2 text-sm text-secondary-foreground",
|
|
434
|
+
children: [
|
|
435
|
+
(0, react_jsx_runtime.jsx)("span", {
|
|
436
|
+
className: "max-w-[16rem] truncate",
|
|
437
|
+
children: isLoading ? t("table.loading", { defaultValue: "Loading…" }) : title
|
|
438
|
+
}),
|
|
439
|
+
(0, react_jsx_runtime.jsx)(require_relation_create.RelationViewButton, {
|
|
440
|
+
to,
|
|
441
|
+
value: keyValue,
|
|
442
|
+
by,
|
|
443
|
+
ignoreScope,
|
|
444
|
+
fieldName: `${fieldName}:${String(keyValue)}`,
|
|
445
|
+
beforeOpen: focusTrigger,
|
|
446
|
+
open: openMode
|
|
447
|
+
}),
|
|
448
|
+
!disabled && (0, react_jsx_runtime.jsx)("button", {
|
|
449
|
+
type: "button",
|
|
450
|
+
onClick: onRemove,
|
|
451
|
+
"data-testid": `${testId}:remove`,
|
|
452
|
+
"aria-label": `${t("relationPicker.clear", { defaultValue: "Clear" })} ${title}`,
|
|
453
|
+
className: "inline-flex size-6 items-center justify-center rounded-sm text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring",
|
|
454
|
+
children: (0, react_jsx_runtime.jsx)(_tabler_icons_react.IconX, {
|
|
455
|
+
className: "size-3.5",
|
|
456
|
+
"aria-hidden": true
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
]
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
//#endregion
|
|
463
|
+
exports.RelationManyPickerInput = RelationManyPickerInput;
|
|
464
|
+
|
|
465
|
+
//# sourceMappingURL=relation-many-picker-B-NCEUgX.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relation-many-picker-B-NCEUgX.cjs","names":["selectKey","resourceKey","useCandidatesGate","Button","relationOpenOf","useApp","useI18nCaps","useOptionalT","useTestIds","useRowTitle","resolveResourceLabel","React","useListAccess","narrowSearchDecl","composeListFilter","normalizeFixedFilters","namesHiddenField","useSelectCreate","useList","IconLoader2","IconChevronDown","Popover","PopoverTrigger","PopoverContent","Command","CommandInput","CommandList","CommandEmpty","CommandItem","IconCheck","cn","RelationCreateButton","LazyRelationPickerDialog","useRelatedRecord","RelationViewButton","IconX"],"sources":["../src/fields/relation-many-picker.tsx"],"sourcesContent":["'use client';\n\nimport {\n type ErasedResourceHandle,\n type FilterExpression,\n type FixedFilterInput,\n type RelationCandidate,\n type RelationOpen,\n relationOpenOf,\n type ResourceRefInput,\n type SearchDecl,\n composeListFilter,\n normalizeFixedFilters,\n resolveResourceLabel,\n resourceKey,\n} from '@burojs/core';\nimport {\n useApp,\n useI18nCaps,\n useList,\n useListAccess,\n useOptionalT,\n useRelatedRecord,\n useTestIds,\n} from '@burojs/react';\nimport { IconCheck, IconChevronDown, IconLoader2, IconX } from '@tabler/icons-react';\nimport * as React from 'react';\nimport { cn } from '../lib/cn.js';\nimport { Button } from '../primitives/button.js';\nimport {\n Command,\n CommandEmpty,\n CommandInput,\n CommandItem,\n CommandList,\n} from '../primitives/command.js';\nimport { Popover, PopoverContent, PopoverTrigger } from '../primitives/popover.js';\nimport { useRowTitle } from '../resource/use-row-title.js';\nimport { useCandidatesGate } from './candidates-gate.js';\nimport { RelationCreateButton, useSelectCreate } from './relation-create.js';\nimport { LazyRelationPickerDialog } from './lazy-relation-picker-dialog.js';\nimport { RelationViewButton, selectKey } from './relation-view-button.js';\nimport type { FieldInputProps } from './registry.js';\nimport { namesHiddenField, narrowSearchDecl } from './search-access.js';\n\ntype ErasedExpression = FilterExpression<ErasedResourceHandle>;\ntype Key = string | number;\n\nconst DEBOUNCE_MS = 250;\n\n/** The keys a to-many field holds: strings and finite numbers, the user's order, no repeats. */\nfunction keysOf(value: unknown): readonly Key[] {\n if (!Array.isArray(value)) return [];\n const seen = new Set<string>();\n const out: Key[] = [];\n for (const entry of value) {\n const key = selectKey(entry);\n if (key === null || seen.has(key)) continue;\n seen.add(key);\n out.push(entry as Key);\n }\n return out;\n}\n\n/**\n * Form input of `f.relationMany` (P7 3.5): the chosen rows as chips (titles through the relation\n * aggregator, one batched read), a popover that searches the same option query a single select\n * does (candidates, field access and the create hand-back included), \"Advanced search\" in a\n * multiple-choice dialog, a \"view\" on every chip and \"+ create\" that appends what it created.\n * The value is `row[by ?? id]` for each chosen row. Loaded lazily: it is not on any screen's\n * first paint.\n */\nexport function RelationManyPickerInput(props: FieldInputProps): React.ReactElement {\n const {\n name,\n id,\n value,\n onChange,\n testid,\n field,\n disabled,\n required,\n ariaInvalid,\n ariaDescribedBy,\n ariaErrorMessage,\n relationSeeds,\n fixedFilters,\n metaSources,\n resource,\n } = props;\n const meta = field?.meta as\n | { to?: ResourceRefInput; by?: unknown; searchField?: string; candidates?: unknown }\n | undefined;\n let to: string | undefined;\n try {\n to = meta?.to === undefined ? undefined : resourceKey(meta.to);\n } catch {\n to = undefined;\n }\n const gate = useCandidatesGate({\n to,\n candidates: Array.isArray(meta?.candidates)\n ? (meta.candidates as readonly RelationCandidate[])\n : undefined,\n sources: metaSources,\n resource: resource ?? '',\n fieldName: field?.name ?? name,\n });\n if (!to) {\n return (\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n data-testid={`${testid ?? `relation-many:${name}`}:no-target`}\n className=\"w-full justify-between font-normal\"\n name={name}\n id={id}\n >\n <span className=\"truncate text-muted-foreground\">—</span>\n </Button>\n );\n }\n const filters =\n gate.filters.length === 0 ? fixedFilters : [...gate.filters, ...(fixedFilters ?? [])];\n return (\n <ManyPicker\n to={to}\n keys={keysOf(value)}\n onChange={(next) => onChange(next)}\n {...(typeof meta?.by === 'string' ? { by: meta.by } : {})}\n searchField={meta?.searchField}\n fixedFilters={filters}\n {...(gate.gate === undefined ? {} : { gate: gate.gate })}\n createSeeds={relationSeeds}\n name={name}\n id={id}\n testid={testid ?? `relation-many:${to}`}\n resource={resource ?? ''}\n fieldName={field?.name ?? name}\n open={relationOpenOf(field ?? {})}\n disabled={disabled}\n required={required}\n ariaInvalid={ariaInvalid}\n ariaDescribedBy={ariaDescribedBy}\n ariaErrorMessage={ariaErrorMessage}\n />\n );\n}\n\ninterface ManyPickerProps {\n readonly to: string;\n readonly keys: readonly Key[];\n readonly onChange: (next: readonly Key[]) => void;\n readonly by?: string;\n readonly searchField?: string | undefined;\n readonly fixedFilters: readonly FixedFilterInput[] | undefined;\n readonly gate?: import('./candidates-gate.js').CandidatesGate;\n readonly createSeeds: Readonly<Record<string, unknown>> | undefined;\n readonly name: string;\n readonly id: string | undefined;\n readonly testid: string;\n readonly resource: string;\n readonly fieldName: string;\n readonly open: RelationOpen;\n readonly disabled: boolean | undefined;\n readonly required: boolean | undefined;\n readonly ariaInvalid: boolean | undefined;\n readonly ariaDescribedBy: string | undefined;\n readonly ariaErrorMessage: string | undefined;\n}\n\nfunction ManyPicker({\n to,\n keys,\n onChange,\n by,\n searchField,\n fixedFilters,\n gate,\n createSeeds,\n name,\n id,\n testid,\n resource,\n fieldName,\n open: openMode,\n disabled,\n required,\n ariaInvalid,\n ariaDescribedBy,\n ariaErrorMessage,\n}: ManyPickerProps): React.ReactElement {\n const app = useApp();\n const caps = useI18nCaps();\n const t = useOptionalT();\n const tid = useTestIds();\n const targetDef = app.registry.get(to);\n const rowTitle = useRowTitle(to, targetDef?.displayField);\n const targetLabel = resolveResourceLabel(caps, to, 'single', targetDef).toLowerCase();\n const childPrefix = `relation-picker:${to}`;\n const effectiveSearchField = searchField ?? targetDef?.displayField ?? 'name';\n const [open, setOpen] = React.useState(false);\n const [dialogOpen, setDialogOpen] = React.useState(false);\n // Mounted on the first open, and only while no candidates gate holds the read: without the\n // candidate filters the dialog would list rows the field must not offer.\n const gated = gate !== undefined;\n const [dialogMounted, setDialogMounted] = React.useState(false);\n React.useEffect(() => {\n if (gated) setDialogOpen(false);\n }, [gated]);\n React.useEffect(() => {\n if (dialogOpen) setDialogMounted(true);\n }, [dialogOpen]);\n const [search, setSearch] = React.useState('');\n const [debouncedSearch, setDebouncedSearch] = React.useState('');\n const triggerRef = React.useRef<HTMLButtonElement | null>(null);\n const focusTrigger = React.useCallback(() => triggerRef.current?.focus(), []);\n\n React.useEffect(() => {\n const handle = setTimeout(() => setDebouncedSearch(search), DEBOUNCE_MS);\n return () => clearTimeout(handle);\n }, [search]);\n React.useEffect(() => {\n if (!open) {\n setSearch('');\n setDebouncedSearch('');\n }\n }, [open]);\n\n const targetIdField = (targetDef?.data as { readonly idField?: unknown } | undefined)?.idField;\n const idField =\n typeof targetIdField === 'string' && targetIdField.length > 0 ? targetIdField : 'id';\n const valueField = by ?? idField;\n const access = useListAccess(to);\n const accessReady = access.status === 'ready';\n const searchDecl = React.useMemo<SearchDecl | undefined>(\n () =>\n narrowSearchDecl(\n targetDef?.views?.list?.search ?? { fields: [effectiveSearchField] },\n (field) => access.fieldVisible(field),\n ),\n [targetDef, effectiveSearchField, access],\n );\n const filter = React.useMemo<ErasedExpression | undefined>(\n () =>\n composeListFilter({\n fixed: normalizeFixedFilters(fixedFilters),\n search: debouncedSearch,\n searchDecl,\n searchContext: { resource: to, def: targetDef },\n }),\n [fixedFilters, debouncedSearch, searchDecl, to, targetDef],\n );\n const blocked =\n !accessReady ||\n gate !== undefined ||\n namesHiddenField(filter, (field) => access.fieldVisible(field));\n\n const append = React.useCallback(\n (next: Key) => {\n if (keys.some((key) => String(key) === String(next))) return;\n onChange([...keys, next]);\n },\n [keys, onChange],\n );\n const toggle = React.useCallback(\n (next: Key) => {\n onChange(\n keys.some((key) => String(key) === String(next))\n ? keys.filter((key) => String(key) !== String(next))\n : [...keys, next],\n );\n },\n [keys, onChange],\n );\n const { create, reader: createReader } = useSelectCreate({\n to,\n by,\n valueField,\n idField,\n fixedFilters,\n held: gated,\n searchDecl,\n searchContext: { resource: to, def: targetDef },\n // What was created and fits is appended, as a pick would be; the dialog it came from is done.\n onValue: (picked) => {\n append(picked);\n setDialogOpen(false);\n },\n });\n\n const listQuery = useList(to, {\n ...(filter ? { filter } : {}),\n pagination: { kind: 'offset', page: 1, pageSize: 10 },\n ...(fixedFilters && fixedFilters.length > 0\n ? { providerOptionsOverride: { ignoreScope: true } }\n : {}),\n enabled: open && targetDef != null && !blocked,\n });\n const rows = (listQuery.data?.data ?? []) as Array<Record<string, unknown>>;\n const isLoading = listQuery.isLoading || listQuery.isFetching;\n const error = listQuery.isError ? (listQuery.error as unknown as Error) : null;\n\n if (!targetDef) {\n return (\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n data-testid={`${childPrefix}:unregistered`}\n className=\"w-full justify-between font-normal\"\n name={name}\n id={id}\n >\n <span className=\"truncate text-muted-foreground\">{keys.map(String).join(', ') || '—'}</span>\n </Button>\n );\n }\n\n const placeholder = t('relation.select', {\n params: { name: targetLabel },\n defaultValue: `Select ${targetLabel}…`,\n });\n const chips = (\n <div className=\"flex flex-wrap items-center gap-1\" data-testid={`${testid}:chips`}>\n {keys.map((key) => (\n <Chip\n key={String(key)}\n to={to}\n keyValue={key}\n by={by}\n resource={resource}\n fieldName={fieldName}\n open={openMode}\n testId={tid.relationManyChip(resource, fieldName, String(key))}\n disabled={disabled === true}\n ignoreScope={fixedFilters !== undefined && fixedFilters.length > 0}\n focusTrigger={focusTrigger}\n onRemove={() => onChange(keys.filter((entry) => String(entry) !== String(key)))}\n />\n ))}\n </div>\n );\n\n if (gate?.kind === 'pending')\n return (\n <div className=\"flex flex-col gap-1.5\">\n {chips}\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n aria-busy=\"true\"\n data-testid={testid}\n data-buro-candidates=\"pending\"\n className=\"w-full justify-between font-normal\"\n >\n <span className=\"truncate text-muted-foreground\">{placeholder}</span>\n <IconLoader2 className=\"h-4 w-4 shrink-0 animate-spin opacity-50\" aria-hidden />\n </Button>\n </div>\n );\n if (gate?.kind === 'forbidden')\n return (\n <div className=\"flex flex-col gap-1.5\">\n {chips}\n <Button\n type=\"button\"\n variant=\"outline\"\n disabled\n data-testid={testid}\n data-buro-candidates=\"forbidden\"\n aria-describedby={gate.testId}\n className=\"w-full justify-between font-normal\"\n >\n <span className=\"truncate text-muted-foreground\">{placeholder}</span>\n <IconChevronDown className=\"h-4 w-4 shrink-0 opacity-50\" aria-hidden />\n </Button>\n <p id={gate.testId} data-testid={gate.testId} className=\"text-xs text-muted-foreground\">\n {gate.message}\n </p>\n </div>\n );\n\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <div className=\"flex flex-col gap-1.5\">\n {chips}\n <PopoverTrigger asChild>\n <Button\n ref={triggerRef}\n type=\"button\"\n variant=\"outline\"\n role=\"combobox\"\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-required={required}\n aria-invalid={ariaInvalid || undefined}\n aria-describedby={ariaDescribedBy}\n {...(ariaErrorMessage ? { 'aria-errormessage': ariaErrorMessage } : {})}\n disabled={disabled}\n data-testid={testid}\n name={name}\n id={id}\n className=\"w-full justify-between font-normal\"\n >\n <span className=\"truncate text-left text-muted-foreground\">{placeholder}</span>\n <IconChevronDown className=\"h-4 w-4 shrink-0 opacity-50\" aria-hidden />\n </Button>\n </PopoverTrigger>\n </div>\n <PopoverContent className=\"w-[var(--radix-popover-trigger-width)] p-0\" align=\"start\">\n {gate?.kind === 'empty' ? (\n <p\n className=\"px-3 py-6 text-center text-sm text-muted-foreground\"\n data-testid={gate.testId}\n >\n {gate.message}\n </p>\n ) : (\n <Command shouldFilter={false}>\n {searchDecl !== undefined && (\n <CommandInput\n value={search}\n onValueChange={setSearch}\n placeholder={t('toolbar.search', {\n params: { name: targetLabel },\n defaultValue: `Search ${targetLabel}…`,\n })}\n data-testid={`${childPrefix}:search`}\n aria-label={t('toolbar.search', {\n params: { name: targetLabel },\n defaultValue: `Search ${targetLabel}`,\n })}\n onKeyDown={(event) => {\n // Backspace in an empty search takes the last chip off.\n if (event.key === 'Backspace' && search === '' && keys.length > 0) {\n event.preventDefault();\n onChange(keys.slice(0, -1));\n }\n // Space toggles the highlighted option while nothing is typed.\n if (event.key === ' ' && search === '') {\n event.preventDefault();\n document\n .querySelector<HTMLElement>(\n `[data-testid=\"${childPrefix}:list\"] [aria-selected=\"true\"]`,\n )\n ?.click();\n }\n }}\n />\n )}\n <CommandList\n data-testid={`${childPrefix}:list`}\n aria-multiselectable=\"true\"\n aria-label={targetLabel}\n >\n {isLoading && (\n <div\n className=\"flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground\"\n data-testid={`${childPrefix}:loading`}\n >\n <IconLoader2 className=\"h-4 w-4 animate-spin\" aria-hidden />\n <span>{t('table.loading', { defaultValue: 'Loading…' })}</span>\n </div>\n )}\n {!isLoading && error && (\n <div\n className=\"px-3 py-6 text-center text-sm text-muted-foreground\"\n data-testid={`${childPrefix}:error`}\n title={error.message}\n >\n {t('relation.failed', { defaultValue: 'Failed to load options.' })}\n </div>\n )}\n {!isLoading && !error && rows.length === 0 && (\n <CommandEmpty data-testid={`${childPrefix}:empty`}>\n {t('relation.noResults', { defaultValue: 'No results.' })}\n </CommandEmpty>\n )}\n {!isLoading &&\n !error &&\n rows.map((row) => {\n const rowValue = row[valueField];\n if (rowValue === null || rowValue === undefined || rowValue === '') return null;\n const idStr = String(rowValue);\n const label = rowTitle(row);\n const chosen = keys.some((key) => String(key) === idStr);\n return (\n <CommandItem\n key={idStr}\n value={`${label} ${idStr}`}\n data-testid={`${childPrefix}:option:${idStr}`}\n aria-checked={chosen}\n onSelect={() => toggle(rowValue as Key)}\n >\n <IconCheck\n className={cn(\n 'mr-2 h-4 w-4 shrink-0',\n chosen ? 'opacity-100' : 'opacity-0',\n )}\n aria-hidden\n />\n <span className=\"truncate\">{label}</span>\n {/* A label that already is the id would print it twice (REF-40). */}\n {label === idStr ? null : (\n <span className=\"ml-auto shrink-0 pl-2 text-xs text-muted-foreground\">\n #{idStr}\n </span>\n )}\n </CommandItem>\n );\n })}\n </CommandList>\n <div className=\"flex items-center justify-between gap-2 border-t px-3 py-2 text-sm\">\n <button\n type=\"button\"\n onClick={() => {\n setOpen(false);\n setDialogOpen(true);\n }}\n data-testid={`${childPrefix}:advanced`}\n className=\"text-foreground hover:underline focus:outline-hidden focus-visible:underline\"\n >\n {t('relationPicker.advancedSearch', { defaultValue: 'Advanced search' })}\n </button>\n {!disabled && (\n <RelationCreateButton\n to={to}\n fieldName={fieldName}\n create={create}\n seeds={createSeeds}\n search={search}\n beforeOpen={() => {\n setOpen(false);\n focusTrigger();\n }}\n className=\"text-foreground hover:underline focus:outline-hidden focus-visible:underline disabled:opacity-50\"\n />\n )}\n </div>\n </Command>\n )}\n </PopoverContent>\n {dialogMounted && !gated && (\n <LazyRelationPickerDialog\n to={to}\n open={dialogOpen}\n onOpenChange={setDialogOpen}\n onSelect={() => undefined}\n multiple\n selected={keys}\n onToggle={toggle}\n valueField={valueField}\n searchField={searchField}\n fixedFilters={fixedFilters}\n {...(disabled ? {} : { create })}\n createSeeds={createSeeds}\n fieldName={fieldName}\n onBeforeCreate={focusTrigger}\n />\n )}\n {createReader}\n </Popover>\n );\n}\n\n/** One chosen row: its title (the aggregator batches every chip's read), \"view\" and remove. */\nfunction Chip({\n to,\n keyValue,\n by,\n resource,\n fieldName,\n testId,\n open: openMode,\n disabled,\n ignoreScope,\n focusTrigger,\n onRemove,\n}: {\n readonly to: string;\n readonly keyValue: Key;\n readonly by: string | undefined;\n readonly resource: string;\n readonly fieldName: string;\n readonly testId: string;\n readonly open: RelationOpen;\n readonly disabled: boolean;\n readonly ignoreScope: boolean;\n readonly focusTrigger: () => void;\n readonly onRemove: () => void;\n}): React.ReactElement {\n const t = useOptionalT();\n const app = useApp();\n const targetDef = app.registry.get(to);\n const rowTitle = useRowTitle(to, targetDef?.displayField);\n const { record, isLoading } = useRelatedRecord(\n to,\n keyValue,\n by === undefined ? undefined : { by },\n );\n const title = record ? rowTitle(record as Record<string, unknown>) : String(keyValue);\n return (\n <span\n data-testid={testId}\n data-resource={resource}\n className=\"inline-flex items-center gap-0.5 rounded-md border bg-secondary pl-2 text-sm text-secondary-foreground\"\n >\n <span className=\"max-w-[16rem] truncate\">\n {isLoading ? t('table.loading', { defaultValue: 'Loading…' }) : title}\n </span>\n <RelationViewButton\n to={to}\n value={keyValue}\n by={by}\n ignoreScope={ignoreScope}\n fieldName={`${fieldName}:${String(keyValue)}`}\n beforeOpen={focusTrigger}\n open={openMode}\n />\n {!disabled && (\n <button\n type=\"button\"\n onClick={onRemove}\n data-testid={`${testId}:remove`}\n aria-label={`${t('relationPicker.clear', { defaultValue: 'Clear' })} ${title}`}\n className=\"inline-flex size-6 items-center justify-center rounded-sm text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <IconX className=\"size-3.5\" aria-hidden />\n </button>\n )}\n </span>\n );\n}\n"],"mappings":"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"}
|