@burdenoff/microfe-vibecontrols 2026.1013.3 → 2026.1013.4
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.
|
@@ -1,189 +1,151 @@
|
|
|
1
1
|
import { useTr as e } from "../../shared/hooks/useTr.js";
|
|
2
2
|
import { useCallback as t, useEffect as n, useId as r, useLayoutEffect as i, useMemo as a, useRef as o, useState as s } from "react";
|
|
3
3
|
import { Check as c, ChevronDown as l, Search as u, X as d } from "lucide-react";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { createPortal as g } from "react-dom";
|
|
4
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
5
|
+
import { Popover as m, PopoverContent as h, PopoverTrigger as g } from "@burdenoff/fe-libs/ui";
|
|
7
6
|
//#region src/components/shared/SearchableSelect.tsx
|
|
8
7
|
function _({ label: _, placeholder: v, options: y, value: b, onChange: x, searchPlaceholder: S, disabled: C = !1, className: w = "", clearable: T = !1, emptyValue: E = "", dropdownAlign: D = "left" }) {
|
|
9
|
-
let O = e(), k = v ?? O("vibecontrols.shared.searchableSelect.placeholder", "Select..."), A = S ?? O("vibecontrols.shared.searchableSelect.searchPlaceholder", "Search..."), j = `searchable-select-${r()}`, [M, N] = s(!1), [P, F] = s(""), [I, L] = s(-1),
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
}
|
|
8
|
+
let O = e(), k = v ?? O("vibecontrols.shared.searchableSelect.placeholder", "Select..."), A = S ?? O("vibecontrols.shared.searchableSelect.searchPlaceholder", "Search..."), j = `searchable-select-${r()}`, [M, N] = s(!1), [P, F] = s(""), [I, L] = s(-1), R = o(null), z = o(null), B = o(0), [V, H] = s(!1);
|
|
9
|
+
i(() => {
|
|
10
|
+
H(!!z.current?.closest("[role=\"dialog\"], [role=\"alertdialog\"]"));
|
|
11
|
+
}, []);
|
|
12
|
+
let U = y.find((e) => e.value === b), W = a(() => {
|
|
13
13
|
if (!P) return y;
|
|
14
14
|
let e = P.toLowerCase();
|
|
15
15
|
return y.filter((t) => t.label.toLowerCase().includes(e) || t.description?.toLowerCase().includes(e) || t.value.toLowerCase().includes(e));
|
|
16
16
|
}, [y, P]);
|
|
17
17
|
n(() => {
|
|
18
|
-
L(
|
|
19
|
-
}, [
|
|
20
|
-
|
|
21
|
-
let
|
|
22
|
-
!n && !r && (N(!1), F(""));
|
|
23
|
-
}
|
|
24
|
-
return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e);
|
|
25
|
-
}, []), n(() => {
|
|
26
|
-
M && requestAnimationFrame(() => {
|
|
27
|
-
H.current?.focus();
|
|
28
|
-
});
|
|
29
|
-
}, [M]), n(() => {
|
|
30
|
-
if (I >= 0 && U.current) {
|
|
31
|
-
let e = U.current.querySelectorAll("[data-option]")[I];
|
|
18
|
+
L(W.length > 0 ? 0 : -1);
|
|
19
|
+
}, [W.length, P]), n(() => {
|
|
20
|
+
if (I >= 0 && R.current) {
|
|
21
|
+
let e = R.current.querySelectorAll("[data-option]")[I];
|
|
32
22
|
e && e.scrollIntoView({ block: "nearest" });
|
|
33
23
|
}
|
|
34
|
-
}, [I])
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
minWidth: 220
|
|
39
|
-
};
|
|
40
|
-
if (r ? i.bottom = n - e.top + 4 : i.top = e.bottom + 4, D === "right") {
|
|
41
|
-
let n = t - e.right;
|
|
42
|
-
i.right = Math.max(4, n), i.maxWidth = Math.max(80, t - Math.max(4, n) - 4);
|
|
43
|
-
} else {
|
|
44
|
-
let n = Math.max(4, e.left + e.width + 220 > t ? t - 220 - 4 : e.left);
|
|
45
|
-
i.left = n, i.width = Math.min(e.width, t - n - 4);
|
|
46
|
-
}
|
|
47
|
-
z({
|
|
48
|
-
...i,
|
|
49
|
-
visibility: "visible"
|
|
50
|
-
});
|
|
51
|
-
}, [M, D]), n(() => {
|
|
52
|
-
M || z({
|
|
53
|
-
visibility: "hidden",
|
|
54
|
-
position: "fixed"
|
|
55
|
-
});
|
|
56
|
-
}, [M]);
|
|
57
|
-
let K = t((e) => {
|
|
24
|
+
}, [I]);
|
|
25
|
+
let G = t((e) => {
|
|
26
|
+
N(e), e || F("");
|
|
27
|
+
}, []), K = t((e) => {
|
|
58
28
|
x(e), N(!1), F("");
|
|
59
29
|
}, [x]), q = t((e) => {
|
|
60
|
-
if (!M) {
|
|
61
|
-
(e.key === "Enter" || e.key === " " || e.key === "ArrowDown") && (e.preventDefault(), N(!0));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
30
|
switch (e.key) {
|
|
65
31
|
case "ArrowDown":
|
|
66
|
-
e.preventDefault(), L((e) => e <
|
|
32
|
+
e.preventDefault(), L((e) => e < W.length - 1 ? e + 1 : 0);
|
|
67
33
|
break;
|
|
68
34
|
case "ArrowUp":
|
|
69
|
-
e.preventDefault(), L((e) => e > 0 ? e - 1 :
|
|
35
|
+
e.preventDefault(), L((e) => e > 0 ? e - 1 : W.length - 1);
|
|
70
36
|
break;
|
|
71
|
-
case "Enter":
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
break;
|
|
77
|
-
case "Escape":
|
|
78
|
-
e.preventDefault(), N(!1), F("");
|
|
37
|
+
case "Enter": {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
let t = W[I];
|
|
40
|
+
t && !t.disabled && K(t.value);
|
|
79
41
|
break;
|
|
42
|
+
}
|
|
80
43
|
case "Tab":
|
|
81
|
-
N(!1), F("");
|
|
44
|
+
e.preventDefault(), B.current = e.shiftKey ? -1 : 1, N(!1), F("");
|
|
82
45
|
break;
|
|
83
46
|
}
|
|
84
47
|
}, [
|
|
85
|
-
|
|
86
|
-
G,
|
|
48
|
+
W,
|
|
87
49
|
I,
|
|
88
50
|
K
|
|
89
51
|
]), J = t((e) => {
|
|
52
|
+
!M && e.key === "ArrowDown" && (e.preventDefault(), N(!0));
|
|
53
|
+
}, [M]), Y = t((e) => {
|
|
54
|
+
let t = z.current;
|
|
55
|
+
if (!t) return !1;
|
|
56
|
+
let n = t.closest("[role=\"dialog\"], [role=\"alertdialog\"]") ?? document.body, r = Array.from(n.querySelectorAll("a[href], button:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [contenteditable]:not([contenteditable=\"false\"]), [tabindex]:not([tabindex=\"-1\"])")).filter((e) => e.tabIndex >= 0 && e.getClientRects().length > 0), i = r.indexOf(t);
|
|
57
|
+
if (i === -1) return !1;
|
|
58
|
+
let a = r[i + e];
|
|
59
|
+
return a ||= e === 1 ? r[0] : r[r.length - 1], a ? (a.focus(), !0) : !1;
|
|
60
|
+
}, []), X = t((e) => {
|
|
61
|
+
let t = B.current;
|
|
62
|
+
B.current = 0, t !== 0 && Y(t) && e.preventDefault();
|
|
63
|
+
}, [Y]), Z = t((e) => {
|
|
90
64
|
e.stopPropagation(), x(E);
|
|
91
65
|
}, [x, E]);
|
|
92
|
-
return /* @__PURE__ */
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
children: [/* @__PURE__ */
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
className: "text-text-
|
|
109
|
-
children: [
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
66
|
+
return /* @__PURE__ */ p(m, {
|
|
67
|
+
open: M,
|
|
68
|
+
onOpenChange: G,
|
|
69
|
+
modal: V,
|
|
70
|
+
children: [/* @__PURE__ */ f("div", {
|
|
71
|
+
className: `relative ${w}`,
|
|
72
|
+
children: /* @__PURE__ */ f(g, {
|
|
73
|
+
asChild: !0,
|
|
74
|
+
children: /* @__PURE__ */ p("button", {
|
|
75
|
+
ref: z,
|
|
76
|
+
type: "button",
|
|
77
|
+
"aria-haspopup": "listbox",
|
|
78
|
+
"aria-expanded": M,
|
|
79
|
+
"aria-controls": M ? j : void 0,
|
|
80
|
+
onKeyDown: J,
|
|
81
|
+
disabled: C,
|
|
82
|
+
className: `inline-flex items-center gap-2 w-full px-3 py-2 text-sm border rounded-md transition-colors text-left ${C ? "bg-bg-sunken border-border-default text-text-muted cursor-not-allowed" : M ? "bg-bg-surface border-border-strong ring-1 ring-border-strong text-text-primary" : "bg-bg-sunken border-border-default text-text-primary hover:bg-bg-elevated"}`,
|
|
83
|
+
children: [
|
|
84
|
+
_ && /* @__PURE__ */ p("span", {
|
|
85
|
+
className: "text-text-secondary flex-shrink-0",
|
|
86
|
+
children: [_, ":"]
|
|
87
|
+
}),
|
|
88
|
+
/* @__PURE__ */ f("span", {
|
|
89
|
+
className: `flex-1 truncate ${U ? "font-medium" : "text-text-placeholder"}`,
|
|
90
|
+
children: U?.label || k
|
|
91
|
+
}),
|
|
92
|
+
/* @__PURE__ */ p("span", {
|
|
93
|
+
className: "flex items-center gap-1 flex-shrink-0",
|
|
94
|
+
children: [T && b !== E && /* @__PURE__ */ f("span", {
|
|
95
|
+
onKeyDown: (e) => {
|
|
96
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), Z(e));
|
|
97
|
+
},
|
|
98
|
+
role: "button",
|
|
99
|
+
tabIndex: -1,
|
|
100
|
+
"aria-label": O("vibecontrols.shared.searchableSelect.clear", "Clear selection"),
|
|
101
|
+
onClick: Z,
|
|
102
|
+
className: "p-0.5 rounded hover:bg-bg-sunken transition-colors",
|
|
103
|
+
children: /* @__PURE__ */ f(d, { className: "size-3 text-text-muted" })
|
|
104
|
+
}), /* @__PURE__ */ f(l, { className: `size-4 text-text-secondary transition-transform ${M ? "rotate-180" : ""}` })]
|
|
105
|
+
})
|
|
106
|
+
]
|
|
127
107
|
})
|
|
128
|
-
|
|
129
|
-
}),
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
scale: .97
|
|
138
|
-
},
|
|
139
|
-
animate: {
|
|
140
|
-
opacity: 1,
|
|
141
|
-
y: 0,
|
|
142
|
-
scale: 1
|
|
143
|
-
},
|
|
144
|
-
exit: {
|
|
145
|
-
opacity: 0,
|
|
146
|
-
y: -4,
|
|
147
|
-
scale: .97
|
|
148
|
-
},
|
|
149
|
-
transition: {
|
|
150
|
-
duration: .15,
|
|
151
|
-
ease: [
|
|
152
|
-
.4,
|
|
153
|
-
0,
|
|
154
|
-
.2,
|
|
155
|
-
1
|
|
156
|
-
]
|
|
157
|
-
},
|
|
158
|
-
className: "z-[200] bg-bg-surface border border-border-default rounded-md shadow-lg",
|
|
159
|
-
style: R,
|
|
160
|
-
children: [/* @__PURE__ */ m("div", {
|
|
108
|
+
})
|
|
109
|
+
}), /* @__PURE__ */ p(h, {
|
|
110
|
+
align: D === "right" ? "end" : "start",
|
|
111
|
+
sideOffset: 4,
|
|
112
|
+
collisionPadding: 8,
|
|
113
|
+
onKeyDown: q,
|
|
114
|
+
onCloseAutoFocus: X,
|
|
115
|
+
className: "z-[200] w-(--radix-popover-trigger-width) min-w-[220px] max-w-[calc(100vw-1rem)] p-0 rounded-md bg-bg-surface border-border-default shadow-lg",
|
|
116
|
+
children: [/* @__PURE__ */ f("div", {
|
|
161
117
|
className: "p-2 border-b border-border-default",
|
|
162
|
-
children: /* @__PURE__ */
|
|
118
|
+
children: /* @__PURE__ */ p("div", {
|
|
163
119
|
className: "flex items-center gap-2 px-2 py-1.5 bg-bg-sunken border border-border-default rounded-md",
|
|
164
120
|
children: [
|
|
165
|
-
/* @__PURE__ */
|
|
166
|
-
|
|
167
|
-
"aria-
|
|
168
|
-
|
|
121
|
+
/* @__PURE__ */ f(u, {
|
|
122
|
+
className: "size-3.5 text-text-muted flex-shrink-0",
|
|
123
|
+
"aria-hidden": "true"
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ f("input", {
|
|
126
|
+
"aria-label": A,
|
|
169
127
|
type: "text",
|
|
170
128
|
value: P,
|
|
171
129
|
onChange: (e) => F(e.target.value),
|
|
172
130
|
placeholder: A,
|
|
173
131
|
className: "flex-1 text-sm bg-transparent text-text-primary placeholder:text-text-placeholder outline-none"
|
|
174
132
|
}),
|
|
175
|
-
P && /* @__PURE__ */
|
|
133
|
+
P && /* @__PURE__ */ f("button", {
|
|
176
134
|
type: "button",
|
|
177
135
|
onClick: () => F(""),
|
|
136
|
+
"aria-label": O("vibecontrols.shared.searchableSelect.clearSearch", "Clear search"),
|
|
178
137
|
className: "p-0.5 rounded hover:bg-bg-surface transition-colors",
|
|
179
|
-
children: /* @__PURE__ */
|
|
138
|
+
children: /* @__PURE__ */ f(d, { className: "size-3 text-text-muted" })
|
|
180
139
|
})
|
|
181
140
|
]
|
|
182
141
|
})
|
|
183
|
-
}), /* @__PURE__ */
|
|
184
|
-
ref:
|
|
142
|
+
}), /* @__PURE__ */ f("div", {
|
|
143
|
+
ref: R,
|
|
144
|
+
id: j,
|
|
145
|
+
role: "listbox",
|
|
146
|
+
"aria-label": _ || k,
|
|
185
147
|
className: "max-h-56 overflow-y-auto py-1",
|
|
186
|
-
children:
|
|
148
|
+
children: W.length > 0 ? W.map((e, t) => /* @__PURE__ */ p("button", {
|
|
187
149
|
"data-option": !0,
|
|
188
150
|
type: "button",
|
|
189
151
|
role: "option",
|
|
@@ -193,24 +155,24 @@ function _({ label: _, placeholder: v, options: y, value: b, onChange: x, search
|
|
|
193
155
|
e.disabled || K(e.value);
|
|
194
156
|
},
|
|
195
157
|
disabled: e.disabled,
|
|
196
|
-
className: `flex items-center justify-between w-full px-3 py-2 text-sm transition-colors ${e.disabled ? "text-text-muted cursor-not-allowed" : t === I ? "bg-bg-sunken text-text-primary" : "text-text-primary hover:bg-bg-sunken"}`,
|
|
158
|
+
className: `flex items-center justify-between w-full px-3 py-2 text-sm text-left transition-colors ${e.disabled ? "text-text-muted cursor-not-allowed" : t === I ? "bg-bg-sunken text-text-primary" : "text-text-primary hover:bg-bg-sunken"}`,
|
|
197
159
|
onMouseEnter: () => L(t),
|
|
198
|
-
children: [/* @__PURE__ */
|
|
160
|
+
children: [/* @__PURE__ */ p("span", {
|
|
199
161
|
className: "flex flex-col items-start min-w-0",
|
|
200
|
-
children: [/* @__PURE__ */
|
|
162
|
+
children: [/* @__PURE__ */ f("span", {
|
|
201
163
|
className: "truncate w-full",
|
|
202
164
|
children: e.label
|
|
203
|
-
}), e.description && /* @__PURE__ */
|
|
165
|
+
}), e.description && /* @__PURE__ */ f("span", {
|
|
204
166
|
className: "text-xs text-text-muted truncate w-full",
|
|
205
167
|
children: e.description
|
|
206
168
|
})]
|
|
207
|
-
}), b === e.value && /* @__PURE__ */
|
|
208
|
-
}, e.value)) : /* @__PURE__ */
|
|
169
|
+
}), b === e.value && /* @__PURE__ */ f(c, { className: "size-4 text-action-primary-bg flex-shrink-0 ml-2" })]
|
|
170
|
+
}, e.value)) : /* @__PURE__ */ f("div", {
|
|
209
171
|
className: "px-3 py-4 text-sm text-text-muted text-center",
|
|
210
172
|
children: O("vibecontrols.shared.searchableSelect.noOptionsFound", "No options found")
|
|
211
173
|
})
|
|
212
174
|
})]
|
|
213
|
-
})
|
|
175
|
+
})]
|
|
214
176
|
});
|
|
215
177
|
}
|
|
216
178
|
//#endregion
|