bo-ui-kit 0.1.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/dist/index.js ADDED
@@ -0,0 +1,665 @@
1
+ import { jsxs as h, jsx as t } from "react/jsx-runtime";
2
+ import * as i from "react";
3
+ import { cva as j } from "class-variance-authority";
4
+ import { clsx as G } from "clsx";
5
+ import { twMerge as B } from "tailwind-merge";
6
+ function f(...e) {
7
+ return B(G(e));
8
+ }
9
+ const P = j(
10
+ // 공통: gap-0 + 라벨 자체 padding 으로 Figma 의 LabelFrame 구조를 재현
11
+ "inline-flex shrink-0 items-center justify-center gap-0 whitespace-nowrap border font-medium transition-colors outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",
12
+ {
13
+ variants: {
14
+ variant: {
15
+ default: "border-primary bg-primary text-primary-foreground shadow-btn hover:bg-primary/90",
16
+ outline: "border-border bg-card text-foreground shadow-xs hover:bg-secondary/50",
17
+ secondary: "border-transparent bg-secondary text-foreground hover:bg-secondary/80",
18
+ destructive: "border-border bg-destructive text-primary-foreground shadow-btn hover:bg-destructive/90",
19
+ "destructive-outline": "border-border bg-background text-destructive-foreground shadow-xs hover:bg-destructive/10",
20
+ ghost: "border-transparent bg-transparent text-foreground hover:bg-secondary",
21
+ link: "border-transparent bg-transparent text-foreground underline-offset-4 hover:underline"
22
+ },
23
+ size: {
24
+ xs: "h-6 min-w-6 rounded-radius-lg px-1 text-xs [&_svg]:size-4",
25
+ sm: "h-7 min-w-7 rounded-radius px-1.5 text-sm [&_svg]:size-4",
26
+ md: "h-8 min-w-8 rounded-radius px-1.5 text-sm [&_svg]:size-[18px]",
27
+ lg: "h-9 min-w-9 rounded-radius px-2 text-sm [&_svg]:size-5 [&_[data-label]]:px-1.5",
28
+ xl: "h-10 min-w-10 rounded-radius px-2.5 text-base [&_svg]:size-5 [&_[data-label]]:px-1.5"
29
+ }
30
+ },
31
+ defaultVariants: {
32
+ variant: "default",
33
+ size: "md"
34
+ }
35
+ }
36
+ ), q = i.forwardRef(
37
+ ({ className: e, variant: n, size: l, type: o = "button", icon: a, rightIcon: d, children: s, ...u }, c) => /* @__PURE__ */ h(
38
+ "button",
39
+ {
40
+ ref: c,
41
+ type: o,
42
+ className: f(P({ variant: n, size: l }), e),
43
+ "data-node-id": "1692:74",
44
+ ...u,
45
+ children: [
46
+ a ? /* @__PURE__ */ t("span", { className: "inline-flex shrink-0 opacity-80", children: a }) : null,
47
+ s != null ? /* @__PURE__ */ t("span", { "data-label": !0, className: "px-1", children: s }) : null,
48
+ d ? /* @__PURE__ */ t("span", { className: "inline-flex shrink-0 opacity-80", children: d }) : null
49
+ ]
50
+ }
51
+ )
52
+ );
53
+ q.displayName = "Button";
54
+ const C = i.forwardRef(
55
+ ({
56
+ checked: e,
57
+ defaultChecked: n,
58
+ indeterminate: l = !1,
59
+ disabled: o = !1,
60
+ mobile: a = !1,
61
+ onCheckedChange: d,
62
+ className: s,
63
+ ...u
64
+ }, c) => {
65
+ const x = e !== void 0, [b, g] = i.useState(n ?? !1), k = x ? e : b, m = i.useRef(null);
66
+ i.useImperativeHandle(c, () => m.current);
67
+ const v = k && !l, y = k && l;
68
+ i.useEffect(() => {
69
+ m.current && (m.current.indeterminate = y);
70
+ }, [y]);
71
+ const N = (w) => {
72
+ const z = w.target.checked;
73
+ x || g(z), d == null || d(z);
74
+ };
75
+ return /* @__PURE__ */ h(
76
+ "label",
77
+ {
78
+ className: f(
79
+ "inline-flex shrink-0 items-center justify-center",
80
+ o ? "cursor-not-allowed opacity-[0.64]" : "cursor-pointer",
81
+ s
82
+ ),
83
+ children: [
84
+ /* @__PURE__ */ t(
85
+ "input",
86
+ {
87
+ ref: m,
88
+ type: "checkbox",
89
+ className: "peer sr-only",
90
+ checked: x ? e : void 0,
91
+ defaultChecked: x ? void 0 : n,
92
+ disabled: o,
93
+ onChange: N,
94
+ ...u
95
+ }
96
+ ),
97
+ /* @__PURE__ */ h(
98
+ "span",
99
+ {
100
+ "aria-hidden": !0,
101
+ className: f(
102
+ "relative flex items-center justify-center rounded-radius-sm border transition-colors",
103
+ "peer-focus-visible:ring-2 peer-focus-visible:ring-ring peer-focus-visible:ring-offset-1 peer-focus-visible:ring-offset-background",
104
+ a ? "size-[18px]" : "size-4",
105
+ v ? "border-transparent bg-primary text-primary-foreground" : "border-input bg-card shadow-xs"
106
+ ),
107
+ children: [
108
+ v && /* @__PURE__ */ t(
109
+ "svg",
110
+ {
111
+ viewBox: "0 0 8 8",
112
+ fill: "none",
113
+ stroke: "currentColor",
114
+ strokeWidth: "1.5",
115
+ className: a ? "size-2.5" : "size-2",
116
+ "aria-hidden": !0,
117
+ children: /* @__PURE__ */ t(
118
+ "path",
119
+ {
120
+ d: "M1 4.2 3 6l4-4.5",
121
+ strokeLinecap: "round",
122
+ strokeLinejoin: "round"
123
+ }
124
+ )
125
+ }
126
+ ),
127
+ y && /* @__PURE__ */ t("span", { className: f("h-0.5 rounded-full bg-primary", a ? "w-2" : "w-1.5") })
128
+ ]
129
+ }
130
+ )
131
+ ]
132
+ }
133
+ );
134
+ }
135
+ );
136
+ C.displayName = "Checkbox";
137
+ const F = j(
138
+ "flex w-full items-center gap-1 rounded-radius border bg-card text-sm text-foreground shadow-xs transition-colors focus-within:ring-[3px] focus-within:ring-offset-0 has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-[0.64]",
139
+ {
140
+ variants: {
141
+ inputSize: {
142
+ sm: "h-7 px-1.5",
143
+ md: "h-8 px-2",
144
+ lg: "h-9 px-2"
145
+ },
146
+ invalid: {
147
+ true: "border-destructive focus-within:ring-destructive/[0.15]",
148
+ false: "border-input focus-within:border-disabled/30 focus-within:ring-disabled/[0.07]"
149
+ }
150
+ },
151
+ defaultVariants: { inputSize: "md", invalid: !1 }
152
+ }
153
+ ), W = i.forwardRef(
154
+ ({
155
+ className: e,
156
+ containerClassName: n,
157
+ inputSize: l,
158
+ invalid: o = !1,
159
+ leftIcon: a,
160
+ rightIcon: d,
161
+ prefix: s,
162
+ suffix: u,
163
+ type: c = "text",
164
+ ...x
165
+ }, b) => /* @__PURE__ */ h(
166
+ "div",
167
+ {
168
+ className: f(F({ inputSize: l, invalid: o }), n),
169
+ "data-node-id": "7745:699",
170
+ children: [
171
+ a ? /* @__PURE__ */ t("span", { className: "inline-flex shrink-0 opacity-80 [&_svg]:size-4", children: a }) : null,
172
+ s != null ? /* @__PURE__ */ t("span", { className: "shrink-0 text-muted-foreground", children: s }) : null,
173
+ /* @__PURE__ */ t(
174
+ "input",
175
+ {
176
+ ref: b,
177
+ type: c,
178
+ className: f(
179
+ "min-w-0 flex-1 bg-transparent px-1 text-foreground outline-none placeholder:text-muted-foreground",
180
+ e
181
+ ),
182
+ ...x
183
+ }
184
+ ),
185
+ u != null ? /* @__PURE__ */ t("span", { className: "shrink-0 text-muted-foreground", children: u }) : null,
186
+ d ? /* @__PURE__ */ t("span", { className: "inline-flex shrink-0 opacity-80 [&_svg]:size-4", children: d }) : null
187
+ ]
188
+ }
189
+ )
190
+ );
191
+ W.displayName = "Input";
192
+ const K = i.forwardRef(
193
+ ({ className: e, ...n }, l) => /* @__PURE__ */ t(
194
+ "label",
195
+ {
196
+ ref: l,
197
+ className: f(
198
+ "inline-flex items-center text-xs font-medium text-foreground",
199
+ "peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
200
+ e
201
+ ),
202
+ "data-node-id": "7658:2157",
203
+ ...n
204
+ }
205
+ )
206
+ );
207
+ K.displayName = "Label";
208
+ const $ = i.forwardRef(
209
+ ({ className: e, label: n, required: l = !1, htmlFor: o, description: a, error: d, validity: s, children: u, ...c }, x) => /* @__PURE__ */ h(
210
+ "div",
211
+ {
212
+ ref: x,
213
+ className: f("flex w-full flex-col gap-2", e),
214
+ "data-node-id": "7745:713",
215
+ ...c,
216
+ children: [
217
+ /* @__PURE__ */ h("div", { className: "flex flex-col gap-1.5", children: [
218
+ n != null && /* @__PURE__ */ h(
219
+ "label",
220
+ {
221
+ htmlFor: o,
222
+ className: "flex items-center gap-1.5 text-sm font-medium leading-5 text-foreground",
223
+ children: [
224
+ n,
225
+ l && /* @__PURE__ */ t("span", { className: "text-destructive-foreground", "aria-hidden": !0, children: "*" })
226
+ ]
227
+ }
228
+ ),
229
+ u
230
+ ] }),
231
+ d != null ? /* @__PURE__ */ t("p", { className: "text-xs leading-[14px] tracking-[0.12px] text-destructive-foreground", children: d }) : a != null ? /* @__PURE__ */ t("p", { className: "text-xs leading-[14px] tracking-[0.12px] text-muted-foreground", children: a }) : null,
232
+ s != null && /* @__PURE__ */ t("div", { className: "rounded-radius-lg bg-secondary p-2", children: /* @__PURE__ */ t("p", { className: "text-xs leading-[14px] tracking-[0.12px] text-foreground", children: s }) })
233
+ ]
234
+ }
235
+ )
236
+ );
237
+ $.displayName = "Field";
238
+ const _ = i.createContext(!1), H = i.forwardRef(
239
+ ({
240
+ className: e,
241
+ isLarge: n = !1,
242
+ title: l = "Verification code",
243
+ showTitle: o = !0,
244
+ belowText: a = "Enter the 6-digit code sent to your email.",
245
+ showBelowText: d = !0,
246
+ children: s,
247
+ ...u
248
+ }, c) => /* @__PURE__ */ t(_.Provider, { value: n, children: /* @__PURE__ */ h(
249
+ "div",
250
+ {
251
+ ref: c,
252
+ className: f("flex flex-col items-center gap-2", e),
253
+ "data-node-id": "8060:1580",
254
+ ...u,
255
+ children: [
256
+ o ? /* @__PURE__ */ t("p", { className: "w-full text-center text-sm font-medium text-foreground", children: l }) : null,
257
+ /* @__PURE__ */ t("div", { className: "flex items-center justify-center gap-2", children: s }),
258
+ d ? /* @__PURE__ */ t("p", { className: "w-full text-center text-xs text-muted-foreground", children: a }) : null
259
+ ]
260
+ }
261
+ ) })
262
+ );
263
+ H.displayName = "InputOTP";
264
+ const U = j(
265
+ "relative flex shrink-0 items-center justify-center rounded-radius border bg-card text-sm text-foreground shadow-xs transition-[color,box-shadow]",
266
+ {
267
+ variants: {
268
+ isLarge: { true: "size-9", false: "size-8" },
269
+ // active = 다음 입력 위치(캐럿). Figma 는 disabled(#45556c) 색의 테두리 + 부드러운 링.
270
+ active: {
271
+ true: "z-10 border-disabled/30 ring-[3px] ring-disabled/20",
272
+ false: "border-input"
273
+ }
274
+ },
275
+ defaultVariants: { isLarge: !1, active: !1 }
276
+ }
277
+ ), J = i.forwardRef(
278
+ ({ className: e, char: n, active: l = !1, isLarge: o, ...a }, d) => {
279
+ const s = i.useContext(_);
280
+ return /* @__PURE__ */ t(
281
+ "div",
282
+ {
283
+ ref: d,
284
+ className: f(U({ isLarge: o ?? s, active: l }), e),
285
+ ...a,
286
+ children: n != null ? /* @__PURE__ */ t("span", { className: "text-center", children: n }) : null
287
+ }
288
+ );
289
+ }
290
+ );
291
+ J.displayName = "InputOTPSlot";
292
+ const Q = i.forwardRef(({ className: e, ...n }, l) => /* @__PURE__ */ t(
293
+ "div",
294
+ {
295
+ ref: l,
296
+ role: "separator",
297
+ className: f("flex w-3 shrink-0 items-center justify-center", e),
298
+ ...n,
299
+ children: /* @__PURE__ */ t("div", { className: "h-0.5 w-full rounded-full bg-border" })
300
+ }
301
+ ));
302
+ Q.displayName = "InputOTPSeparator";
303
+ const X = i.forwardRef(
304
+ ({
305
+ className: e,
306
+ value: n = 50,
307
+ min: l = 0,
308
+ max: o = 100,
309
+ label: a = "Label",
310
+ valueLabel: d,
311
+ showLabels: s = !0,
312
+ showSecondaryLabel: u = !0,
313
+ ...c
314
+ }, x) => {
315
+ const b = o - l || 1, g = Math.min(100, Math.max(0, (n - l) / b * 100));
316
+ return /* @__PURE__ */ h(
317
+ "div",
318
+ {
319
+ ref: x,
320
+ role: "meter",
321
+ "aria-valuenow": n,
322
+ "aria-valuemin": l,
323
+ "aria-valuemax": o,
324
+ "aria-label": a,
325
+ className: f("flex w-full flex-col gap-2", e),
326
+ "data-node-id": "7664:31",
327
+ ...c,
328
+ children: [
329
+ s ? /* @__PURE__ */ h("div", { className: "flex items-center justify-between", children: [
330
+ a != null ? /* @__PURE__ */ t("span", { className: "text-xs font-medium text-foreground", children: a }) : null,
331
+ u ? /* @__PURE__ */ t("span", { className: "text-xs font-medium text-foreground", children: d ?? `${Math.round(g)}%` }) : null
332
+ ] }) : null,
333
+ /* @__PURE__ */ t("div", { className: "relative h-2 w-full overflow-hidden bg-input", "data-node-id": "7664:42", children: /* @__PURE__ */ t(
334
+ "div",
335
+ {
336
+ className: "absolute inset-y-0 left-0 bg-primary transition-[width]",
337
+ style: { width: `${g}%` },
338
+ "data-node-id": "7664:44"
339
+ }
340
+ ) })
341
+ ]
342
+ }
343
+ );
344
+ }
345
+ );
346
+ X.displayName = "Meter";
347
+ const A = j(
348
+ "inline-flex shrink-0 items-center justify-center gap-1 rounded-radius-lg text-sm text-foreground transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-offset-0 focus-visible:ring-disabled/[0.07] disabled:pointer-events-none disabled:opacity-50 data-[state=off]:hover:bg-card/50 data-[state=on]:bg-secondary/[0.64] [&_svg]:size-4 [&_svg]:shrink-0",
349
+ {
350
+ variants: {
351
+ variant: {
352
+ // 두 변형 모두 1px 테두리를 둬서 정렬/크기가 흔들리지 않게 한다(Default 는 투명 테두리).
353
+ default: "border border-transparent",
354
+ outline: "border border-border bg-card shadow-xs"
355
+ },
356
+ size: {
357
+ sm: "h-7 px-1.5",
358
+ md: "h-8 px-2",
359
+ lg: "h-9 px-2.5"
360
+ },
361
+ iconOnly: {
362
+ true: "px-0",
363
+ false: ""
364
+ }
365
+ },
366
+ compoundVariants: [
367
+ { iconOnly: !0, size: "sm", class: "w-7" },
368
+ { iconOnly: !0, size: "md", class: "w-8" },
369
+ { iconOnly: !0, size: "lg", class: "w-9" }
370
+ ],
371
+ defaultVariants: { variant: "default", size: "md", iconOnly: !1 }
372
+ }
373
+ ), Y = i.forwardRef(
374
+ ({
375
+ className: e,
376
+ variant: n,
377
+ size: l,
378
+ iconOnly: o,
379
+ pressed: a,
380
+ defaultPressed: d = !1,
381
+ onPressedChange: s,
382
+ onClick: u,
383
+ ...c
384
+ }, x) => {
385
+ const b = a !== void 0, [g, k] = i.useState(d), m = b ? a : g;
386
+ return /* @__PURE__ */ t(
387
+ "button",
388
+ {
389
+ ref: x,
390
+ type: "button",
391
+ "aria-pressed": m,
392
+ "data-state": m ? "on" : "off",
393
+ className: f(A({ variant: n, size: l, iconOnly: o }), e),
394
+ onClick: (v) => {
395
+ b || k((y) => !y), s == null || s(!m), u == null || u(v);
396
+ },
397
+ "data-node-id": "5685:204",
398
+ ...c
399
+ }
400
+ );
401
+ }
402
+ );
403
+ Y.displayName = "Toggle";
404
+ const M = i.createContext(
405
+ null
406
+ ), Z = i.forwardRef(
407
+ (e, n) => {
408
+ const {
409
+ type: l,
410
+ variant: o = "outline",
411
+ size: a = "md",
412
+ orientation: d = "horizontal",
413
+ className: s,
414
+ children: u
415
+ } = e, c = e.value !== void 0, [x, b] = i.useState(() => e.defaultValue == null ? [] : Array.isArray(e.defaultValue) ? e.defaultValue : [e.defaultValue]), g = c ? Array.isArray(e.value) ? e.value : e.value ? [e.value] : [] : x, k = (m) => {
416
+ var y, N;
417
+ let v;
418
+ l === "single" ? (v = g[0] === m ? [] : [m], c || b(v), (y = e.onValueChange) == null || y.call(
419
+ e,
420
+ v[0] ?? ""
421
+ )) : (v = g.includes(m) ? g.filter((w) => w !== m) : [...g, m], c || b(v), (N = e.onValueChange) == null || N.call(e, v));
422
+ };
423
+ return /* @__PURE__ */ t(
424
+ M.Provider,
425
+ {
426
+ value: { value: g, toggle: k, variant: o, size: a, orientation: d },
427
+ children: /* @__PURE__ */ t(
428
+ "div",
429
+ {
430
+ ref: n,
431
+ role: "group",
432
+ "data-node-id": "5686:270",
433
+ className: f(
434
+ "inline-flex w-fit overflow-hidden rounded-radius-lg",
435
+ d === "vertical" ? "flex-col [&>*:not(:first-child)]:-mt-px" : "flex-row [&>*:not(:first-child)]:-ml-px",
436
+ s
437
+ ),
438
+ children: u
439
+ }
440
+ )
441
+ }
442
+ );
443
+ }
444
+ );
445
+ Z.displayName = "ToggleGroup";
446
+ const ee = i.forwardRef(({ value: e, iconOnly: n, className: l, onClick: o, ...a }, d) => {
447
+ const s = i.useContext(M);
448
+ if (!s) throw new Error("ToggleGroupItem must be used within ToggleGroup");
449
+ const u = s.value.includes(e);
450
+ return /* @__PURE__ */ t(
451
+ "button",
452
+ {
453
+ ref: d,
454
+ type: "button",
455
+ "aria-pressed": u,
456
+ "data-state": u ? "on" : "off",
457
+ className: f(
458
+ A({ variant: s.variant, size: s.size, iconOnly: n }),
459
+ // twMerge 가 커스텀 radius 키(rounded-radius-lg)를 충돌로 인식 못 하므로 !important 로 강제.
460
+ // 그룹이 rounded+overflow-hidden 이라 바깥 모서리는 그룹이 둥글게 클립한다.
461
+ "!rounded-none focus-visible:z-10",
462
+ l
463
+ ),
464
+ onClick: (c) => {
465
+ s.toggle(e), o == null || o(c);
466
+ },
467
+ ...a
468
+ }
469
+ );
470
+ });
471
+ ee.displayName = "ToggleGroupItem";
472
+ const te = j(
473
+ "flex w-full select-none items-center justify-between gap-1 rounded-radius border bg-card text-sm text-foreground shadow-xs transition-colors outline-none focus-visible:ring-[3px] focus-visible:ring-offset-0 disabled:cursor-not-allowed disabled:opacity-[0.64]",
474
+ {
475
+ variants: {
476
+ inputSize: { sm: "h-7 px-1.5", md: "h-8 px-2", lg: "h-9 px-2" },
477
+ invalid: {
478
+ true: "border-destructive focus-visible:ring-destructive/[0.15]",
479
+ false: "border-input focus-visible:border-disabled/30 focus-visible:ring-disabled/[0.07]"
480
+ }
481
+ },
482
+ defaultVariants: { inputSize: "md", invalid: !1 }
483
+ }
484
+ );
485
+ function re({ className: e }) {
486
+ return /* @__PURE__ */ t(
487
+ "svg",
488
+ {
489
+ viewBox: "0 0 24 24",
490
+ fill: "none",
491
+ stroke: "currentColor",
492
+ strokeWidth: "2",
493
+ className: e,
494
+ "aria-hidden": !0,
495
+ children: /* @__PURE__ */ t("path", { d: "m6 9 6 6 6-6", strokeLinecap: "round", strokeLinejoin: "round" })
496
+ }
497
+ );
498
+ }
499
+ function ne() {
500
+ return /* @__PURE__ */ t(
501
+ "svg",
502
+ {
503
+ viewBox: "0 0 24 24",
504
+ fill: "none",
505
+ stroke: "currentColor",
506
+ strokeWidth: "2.2",
507
+ className: "size-4",
508
+ "aria-hidden": !0,
509
+ children: /* @__PURE__ */ t("path", { d: "M20 6 9 17l-5-5", strokeLinecap: "round", strokeLinejoin: "round" })
510
+ }
511
+ );
512
+ }
513
+ const se = i.forwardRef(
514
+ ({
515
+ options: e,
516
+ value: n,
517
+ defaultValue: l,
518
+ onValueChange: o,
519
+ placeholder: a = "Select…",
520
+ disabled: d = !1,
521
+ inputSize: s,
522
+ invalid: u,
523
+ className: c,
524
+ contentClassName: x,
525
+ id: b,
526
+ name: g
527
+ }, k) => {
528
+ const m = n !== void 0, [v, y] = i.useState(
529
+ l
530
+ ), N = m ? n : v, [w, z] = i.useState(!1), L = i.useRef(null), T = i.useRef(null), I = e.find((r) => r.value === N);
531
+ i.useEffect(() => {
532
+ if (!w) return;
533
+ const r = (p) => {
534
+ L.current && !L.current.contains(p.target) && z(!1);
535
+ };
536
+ return document.addEventListener("mousedown", r), () => document.removeEventListener("mousedown", r);
537
+ }, [w]), i.useEffect(() => {
538
+ var R;
539
+ if (!w) return;
540
+ const r = (R = T.current) == null ? void 0 : R.querySelectorAll(
541
+ "[data-select-item]:not([disabled])"
542
+ );
543
+ if (!(r != null && r.length)) return;
544
+ (Array.from(r).find(
545
+ (S) => S.dataset.value === N
546
+ ) ?? r[0]).focus();
547
+ }, [w, N]);
548
+ const V = (r) => {
549
+ m || y(r), o == null || o(r), z(!1);
550
+ }, O = (r) => {
551
+ var E;
552
+ const p = Array.from(
553
+ ((E = T.current) == null ? void 0 : E.querySelectorAll(
554
+ "[data-select-item]:not([disabled])"
555
+ )) ?? []
556
+ ), R = p.findIndex((D) => D === document.activeElement), S = p[(R + r + p.length) % p.length];
557
+ S == null || S.focus();
558
+ };
559
+ return /* @__PURE__ */ h("div", { ref: L, className: "relative", children: [
560
+ /* @__PURE__ */ h(
561
+ "button",
562
+ {
563
+ ref: k,
564
+ type: "button",
565
+ id: b,
566
+ name: g,
567
+ disabled: d,
568
+ "aria-haspopup": "listbox",
569
+ "aria-expanded": w,
570
+ "data-node-id": "7751:1561",
571
+ className: f(te({ inputSize: s, invalid: u }), c),
572
+ onClick: () => z((r) => !r),
573
+ onKeyDown: (r) => {
574
+ (r.key === "ArrowDown" || r.key === "Enter" || r.key === " ") && (r.preventDefault(), z(!0));
575
+ },
576
+ children: [
577
+ /* @__PURE__ */ t(
578
+ "span",
579
+ {
580
+ className: f(
581
+ "truncate",
582
+ !I && "text-muted-foreground"
583
+ ),
584
+ children: I ? I.label : a
585
+ }
586
+ ),
587
+ /* @__PURE__ */ t(
588
+ re,
589
+ {
590
+ className: f(
591
+ "size-4 shrink-0 opacity-50 transition-transform",
592
+ w && "rotate-180"
593
+ )
594
+ }
595
+ )
596
+ ]
597
+ }
598
+ ),
599
+ w && /* @__PURE__ */ t(
600
+ "div",
601
+ {
602
+ ref: T,
603
+ role: "listbox",
604
+ tabIndex: -1,
605
+ className: f(
606
+ "absolute left-0 top-full z-50 mt-1 flex max-h-64 w-full flex-col gap-px overflow-auto rounded-radius-xl border border-border bg-popover p-1 shadow-popover",
607
+ x
608
+ ),
609
+ onKeyDown: (r) => {
610
+ var p, R;
611
+ r.key === "Escape" ? (z(!1), (R = (p = L.current) == null ? void 0 : p.querySelector("button")) == null || R.focus()) : r.key === "ArrowDown" ? (r.preventDefault(), O(1)) : r.key === "ArrowUp" && (r.preventDefault(), O(-1));
612
+ },
613
+ children: e.map((r) => {
614
+ const p = r.value === N;
615
+ return /* @__PURE__ */ h(
616
+ "button",
617
+ {
618
+ type: "button",
619
+ role: "option",
620
+ "aria-selected": p,
621
+ disabled: r.disabled,
622
+ "data-select-item": "",
623
+ "data-value": r.value,
624
+ className: f(
625
+ "flex h-7 w-full items-center gap-0.5 rounded-radius-lg px-0.5 text-left text-xs font-medium text-accent-foreground outline-none transition-colors",
626
+ "hover:bg-accent focus-visible:bg-accent",
627
+ "disabled:pointer-events-none disabled:opacity-[0.64]",
628
+ p && "bg-primary/[0.04]"
629
+ ),
630
+ onClick: () => V(r.value),
631
+ children: [
632
+ /* @__PURE__ */ t("span", { className: "flex size-7 shrink-0 items-center justify-center", children: p ? /* @__PURE__ */ t(ne, {}) : null }),
633
+ r.icon ? /* @__PURE__ */ t("span", { className: "inline-flex size-4 shrink-0 items-center justify-center [&_svg]:size-4", children: r.icon }) : null,
634
+ /* @__PURE__ */ t("span", { className: "min-w-0 flex-1 truncate", children: r.label })
635
+ ]
636
+ },
637
+ r.value
638
+ );
639
+ })
640
+ }
641
+ )
642
+ ] });
643
+ }
644
+ );
645
+ se.displayName = "Select";
646
+ export {
647
+ q as Button,
648
+ C as Checkbox,
649
+ $ as Field,
650
+ W as Input,
651
+ H as InputOTP,
652
+ Q as InputOTPSeparator,
653
+ J as InputOTPSlot,
654
+ K as Label,
655
+ X as Meter,
656
+ se as Select,
657
+ Y as Toggle,
658
+ Z as ToggleGroup,
659
+ ee as ToggleGroupItem,
660
+ P as buttonVariants,
661
+ F as inputVariants,
662
+ te as selectTriggerVariants,
663
+ U as slotVariants,
664
+ A as toggleVariants
665
+ };
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from "clsx";
2
+ /** Tailwind 클래스 병합 유틸 (clsx + tailwind-merge) */
3
+ export declare function cn(...inputs: ClassValue[]): string;