@thewrong/ui 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +2 -2
  2. package/dist/components/button/Button.cjs +1 -1
  3. package/dist/components/button/Button.d.ts +3 -0
  4. package/dist/components/button/Button.esm.js +17 -5
  5. package/dist/components/button/types.d.ts +3 -1
  6. package/dist/components/button/utils.cjs +1 -1
  7. package/dist/components/button/utils.d.ts +2 -2
  8. package/dist/components/button/utils.esm.js +6 -2
  9. package/dist/components/progress/Progress.cjs +1 -1
  10. package/dist/components/progress/Progress.d.ts +3 -4
  11. package/dist/components/progress/Progress.esm.js +5 -5
  12. package/dist/components/progress/types.d.ts +2 -2
  13. package/dist/components/select/MultiSelect.cjs +1 -1
  14. package/dist/components/select/MultiSelect.esm.js +140 -138
  15. package/dist/components/select/Select.cjs +1 -1
  16. package/dist/components/select/Select.esm.js +190 -182
  17. package/dist/components/select/types.d.ts +7 -0
  18. package/dist/components/slider/Slider.cjs +1 -0
  19. package/dist/components/slider/Slider.d.ts +6 -0
  20. package/dist/components/slider/Slider.esm.js +36 -0
  21. package/dist/components/slider/index.d.ts +2 -0
  22. package/dist/components/slider/types.d.ts +15 -0
  23. package/dist/components/slider/utils.cjs +1 -0
  24. package/dist/components/slider/utils.d.ts +3 -0
  25. package/dist/components/slider/utils.esm.js +15 -0
  26. package/dist/components/table/accordion-table.cjs +1 -1
  27. package/dist/components/table/accordion-table.esm.js +194 -180
  28. package/dist/components/table/components/SortHeader.cjs +1 -0
  29. package/dist/components/table/components/SortHeader.d.ts +10 -0
  30. package/dist/components/table/components/SortHeader.esm.js +27 -0
  31. package/dist/components/table/components/SortableHeaderCell.cjs +1 -1
  32. package/dist/components/table/components/SortableHeaderCell.d.ts +10 -2
  33. package/dist/components/table/components/SortableHeaderCell.esm.js +54 -26
  34. package/dist/components/table/hooks/sort-state.cjs +1 -0
  35. package/dist/components/table/hooks/sort-state.d.ts +5 -0
  36. package/dist/components/table/hooks/sort-state.esm.js +21 -0
  37. package/dist/components/table/hooks/useTableSort.cjs +1 -1
  38. package/dist/components/table/hooks/useTableSort.d.ts +6 -3
  39. package/dist/components/table/hooks/useTableSort.esm.js +18 -19
  40. package/dist/components/table/paginated-table.d.ts +2 -0
  41. package/dist/components/table/table.cjs +1 -1
  42. package/dist/components/table/table.d.ts +2 -0
  43. package/dist/components/table/table.esm.js +119 -104
  44. package/dist/components/table/types.d.ts +11 -4
  45. package/dist/components/tabs/Tabs.cjs +1 -0
  46. package/dist/components/tabs/Tabs.d.ts +8 -0
  47. package/dist/components/tabs/Tabs.esm.js +53 -0
  48. package/dist/components/tabs/index.d.ts +2 -0
  49. package/dist/components/tabs/navigation.cjs +1 -0
  50. package/dist/components/tabs/navigation.d.ts +2 -0
  51. package/dist/components/tabs/navigation.esm.js +18 -0
  52. package/dist/components/tabs/types.d.ts +20 -0
  53. package/dist/index.cjs +1 -1
  54. package/dist/index.d.ts +2 -0
  55. package/dist/index.esm.js +3 -1
  56. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-down.cjs +1 -0
  57. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-down.esm.js +10 -0
  58. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-up-down.cjs +1 -0
  59. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-up-down.esm.js +21 -0
  60. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-up.cjs +1 -0
  61. package/dist/node_modules/lucide-react/dist/esm/icons/arrow-up.esm.js +10 -0
  62. package/dist/tokens.css +78 -5
  63. package/dist/ui.css +1 -1
  64. package/llms.txt +9 -6
  65. package/package.json +1 -1
@@ -6,43 +6,43 @@ import { getInputContainerClasses as ie, getInputHelpClasses as ae, getInputLabe
6
6
  import { c as le } from "../../node_modules/use-debounce/dist/index.module.esm.js";
7
7
  import { LoadingDots as ue } from "./loading-dots.esm.js";
8
8
  import { computeSelectPanelMaxWidth as de } from "./panel-width.esm.js";
9
- import { forwardRef as a, useEffect as fe, useId as pe, useMemo as me, useRef as o, useState as s } from "react";
10
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
11
- import { FloatingFocusManager as he, FloatingPortal as ge, autoUpdate as _e, flip as ve, offset as ye, shift as be, size as xe, useClick as Se, useDismiss as Ce, useFloating as we, useInteractions as Te, useListNavigation as Ee, useRole as De, useTypeahead as Oe } from "@floating-ui/react";
9
+ import { forwardRef as a, useEffect as o, useId as s, useMemo as fe, useRef as c, useState as l } from "react";
10
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
11
+ import { FloatingFocusManager as pe, FloatingPortal as me, autoUpdate as he, flip as ge, offset as _e, shift as ve, size as ye, useClick as be, useDismiss as xe, useFloating as Se, useInteractions as Ce, useListNavigation as we, useRole as Te, useTypeahead as Ee } from "@floating-ui/react";
12
12
  //#region src/components/select/Select.tsx
13
- var u = a(function({ options: a, value: u, onChange: d, variant: f, selectSize: p = "medium", label: ke, labelOption: Ae = "appear", help: je, placeholder: Me = "선택해주세요", hasError: m = !1, disabled: h = !1, suffix: g, trailingIcon: _, clearable: v = !1, badge: y, searchable: b = !1, searchPlaceholder: Ne = "검색...", onSearchChange: x, isSearchLoading: S = !1, containerProps: Pe, containerRef: Fe, className: C = "", panelClassName: Ie = "", id: Le, name: Re, onLoadMore: w, hasMore: T = !1, searchDebounceMs: E = 300, openOnFocus: ze = !1, validateSearchQuery: D, open: Be, onOpenChange: Ve, "data-testid": He }, O) {
14
- let [Ue, We] = s(!1), k = Be ?? Ue, A = (e) => {
15
- Be === void 0 && We(e), Ve?.(e);
16
- }, [j, M] = s(null), [N, P] = s(""), Ge = o([]), F = o(null), [I, Ke] = s(null), [L, qe] = s(null), R = pe(), Je = pe(), z = Le ?? Je, Ye = (e) => `${R}-opt-${e}`, Xe = j === null ? void 0 : Ye(j), B = typeof x == "function", V = o(x);
17
- V.current = x;
18
- let Ze = E === !1 || E <= 0 ? 0 : E, Qe = le((e) => {
19
- V.current?.(e);
20
- }, Ze), H = (e, t) => {
21
- B && (t || Ze === 0 ? (Qe.cancel(), V.current?.(e)) : Qe(e));
22
- }, U = a.find((e) => String(e.value) === u), $e = o(U?.label ?? "");
23
- $e.current = U?.label ?? "";
24
- let et = o(H);
25
- et.current = H;
26
- let tt = b && (U !== void 0 && N === U.label || U === void 0 && u !== "" && N !== ""), W = me(() => {
27
- if (!b || B || N.length === 0 || tt) return a;
28
- let e = N.toLowerCase();
13
+ var f = a(function({ options: a, value: f, onChange: p, variant: m, selectSize: h = "medium", label: De, "aria-label": Oe, "aria-labelledby": ke, labelOption: Ae = "appear", help: je, placeholder: Me = "선택해주세요", hasError: g = !1, disabled: _ = !1, suffix: v, trailingIcon: y, clearable: b = !1, badge: x, searchable: S = !1, searchPlaceholder: Ne = "검색...", onSearchChange: C, isSearchLoading: w = !1, containerProps: Pe, containerRef: Fe, className: Ie = "", panelClassName: Le = "", id: Re, name: ze, onLoadMore: T, hasMore: E = !1, searchDebounceMs: D = 300, openOnFocus: Be = !1, validateSearchQuery: Ve, open: He, onOpenChange: Ue, "data-testid": O }, k) {
14
+ let [We, Ge] = l(!1), A = He ?? We, j = (e) => {
15
+ He === void 0 && Ge(e), Ue?.(e);
16
+ }, [M, N] = l(null), [P, F] = l(""), Ke = c([]), I = c(null), [L, qe] = l(null), [R, Je] = l(null), z = s(), Ye = s(), B = Re ?? Ye, Xe = (e) => `${z}-opt-${e}`, Ze = M === null ? void 0 : Xe(M), V = typeof C == "function", H = c(C);
17
+ H.current = C;
18
+ let Qe = D === !1 || D <= 0 ? 0 : D, $e = le((e) => {
19
+ H.current?.(e);
20
+ }, Qe), U = (e, t) => {
21
+ V && (t || Qe === 0 ? ($e.cancel(), H.current?.(e)) : $e(e));
22
+ }, W = a.find((e) => String(e.value) === f), et = c(W?.label ?? "");
23
+ et.current = W?.label ?? "";
24
+ let tt = c(U);
25
+ tt.current = U;
26
+ let nt = S && (W !== void 0 && P === W.label || W === void 0 && f !== "" && P !== ""), G = fe(() => {
27
+ if (!S || V || P.length === 0 || nt) return a;
28
+ let e = P.toLowerCase();
29
29
  return a.filter((t) => t.label.toLowerCase().includes(e));
30
30
  }, [
31
31
  a,
32
- b,
33
- B,
34
- N,
35
- tt
36
- ]), { refs: G, floatingStyles: nt, context: K } = we({
37
- open: k,
38
- onOpenChange: A,
32
+ S,
33
+ V,
34
+ P,
35
+ nt
36
+ ]), { refs: K, floatingStyles: rt, context: q } = Se({
37
+ open: A,
38
+ onOpenChange: j,
39
39
  placement: "bottom-start",
40
- whileElementsMounted: _e,
40
+ whileElementsMounted: he,
41
41
  middleware: [
42
- ye(4),
42
+ _e(4),
43
+ ge({ padding: 8 }),
43
44
  ve({ padding: 8 }),
44
- be({ padding: 8 }),
45
- xe({
45
+ ye({
46
46
  apply({ rects: e, elements: t, availableHeight: n, availableWidth: r }) {
47
47
  Object.assign(t.floating.style, {
48
48
  minWidth: `${e.reference.width}px`,
@@ -53,268 +53,276 @@ var u = a(function({ options: a, value: u, onChange: d, variant: f, selectSize:
53
53
  padding: 8
54
54
  })
55
55
  ]
56
- }), { getReferenceProps: rt, getFloatingProps: it, getItemProps: at } = Te([
57
- Se(K, { enabled: !h && !b }),
58
- Ce(K),
59
- De(K, { role: "listbox" }),
60
- Ee(K, {
61
- listRef: Ge,
62
- activeIndex: j,
63
- onNavigate: M,
64
- virtual: b,
56
+ }), { getReferenceProps: it, getFloatingProps: at, getItemProps: ot } = Ce([
57
+ be(q, { enabled: !_ && !S }),
58
+ xe(q),
59
+ Te(q, { role: "listbox" }),
60
+ we(q, {
61
+ listRef: Ke,
62
+ activeIndex: M,
63
+ onNavigate: N,
64
+ virtual: S,
65
65
  loop: !0
66
66
  }),
67
- Oe(K, {
68
- listRef: { current: W.map((e) => e.label) },
69
- activeIndex: j,
70
- onMatch: M,
71
- enabled: !b
67
+ Ee(q, {
68
+ listRef: { current: G.map((e) => e.label) },
69
+ activeIndex: M,
70
+ onMatch: N,
71
+ enabled: !S
72
72
  })
73
- ]), ot = o(!1);
74
- fe(() => {
75
- if (k) {
76
- if (ot.current = !0, b) {
77
- let e = $e.current;
78
- P(e), e !== "" && requestAnimationFrame(() => {
79
- F.current?.select();
73
+ ]), st = c(!1);
74
+ o(() => {
75
+ if (A) {
76
+ if (st.current = !0, S) {
77
+ let e = et.current;
78
+ F(e), e !== "" && requestAnimationFrame(() => {
79
+ I.current?.select();
80
80
  });
81
81
  }
82
- } else P(""), M(null), ot.current && et.current("", !0);
82
+ } else F(""), N(null), st.current && tt.current("", !0);
83
83
  }, [
84
- k,
85
- b,
86
- B
87
- ]), fe(() => {
88
- if (!k || !w || !T || !I || !L) return;
84
+ A,
85
+ S,
86
+ V
87
+ ]), o(() => {
88
+ if (!A || !T || !E || !L || !R) return;
89
89
  let e = new IntersectionObserver((e) => {
90
- for (let t of e) t.isIntersecting && !S && w();
90
+ for (let t of e) t.isIntersecting && !w && T();
91
91
  }, {
92
- root: L,
92
+ root: R,
93
93
  rootMargin: "0px 0px 80px 0px"
94
94
  });
95
- return e.observe(I), () => e.disconnect();
95
+ return e.observe(L), () => e.disconnect();
96
96
  }, [
97
- k,
98
- w,
97
+ A,
99
98
  T,
100
- S,
101
- I,
102
- L
99
+ E,
100
+ w,
101
+ L,
102
+ R
103
103
  ]);
104
- let q = (e) => {
105
- d(e), A(!1);
106
- }, st = (e) => {
107
- e.stopPropagation(), d(""), P("");
104
+ let J = (e) => {
105
+ p(e), j(!1);
108
106
  }, ct = (e) => {
109
- b || !v || h || !J || k || (e.key === "Backspace" || e.key === "Delete") && (e.preventDefault(), d(""));
107
+ e.stopPropagation(), p(""), F("");
110
108
  }, lt = (e) => {
111
- let t = e.target.value;
112
- D && !D(t) || (t !== N && (L && (L.scrollTop = 0), M(null)), P(t), H(t, !1), k || A(!0));
109
+ S || !b || _ || !Y || A || (e.key === "Backspace" || e.key === "Delete") && (e.preventDefault(), p(""));
113
110
  }, ut = (e) => {
111
+ let t = e.target.value;
112
+ Ve && !Ve(t) || (t !== P && (R && (R.scrollTop = 0), N(null)), F(t), U(t, !1), A || j(!0));
113
+ }, dt = (e) => {
114
114
  if (!e.nativeEvent.isComposing) {
115
- if (e.key === "Enter" && j !== null) {
115
+ if (e.key === "Enter" && M !== null) {
116
116
  e.preventDefault();
117
- let t = W[j];
118
- t && !t.disabled && q(String(t.value));
117
+ let t = G[M];
118
+ t && !t.disabled && J(String(t.value));
119
119
  return;
120
120
  }
121
- (e.key === "Backspace" || e.key === "Delete") && U && (!k || N === "") && (e.preventDefault(), d(""));
121
+ (e.key === "Backspace" || e.key === "Delete") && W && (!A || P === "") && (e.preventDefault(), p(""));
122
122
  }
123
- }, dt = Ae === "sustain" || Ae === "appear" && !!U, J = !!U, ft = U ? U.label : Me, pt = k ? N : U?.label ?? "", mt = ne[p], Y = te[p], ht = ee[p], X = re[p], gt = r[p], _t = ce(f, m, h, p), Z = se(m, h, J || k), Q = i[p], $ = h ? "text-fg-disabled" : m ? "text-fg-danger" : J ? "text-fg-default" : "text-fg-subtle";
124
- return /* @__PURE__ */ l("div", {
123
+ }, ft = Ae === "sustain" || Ae === "appear" && !!W, Y = !!W, pt = W ? W.label : Me, mt = A ? P : W?.label ?? "", ht = ne[h], X = te[h], gt = ee[h], Z = re[h], _t = r[h], vt = ce(m, g, _, h), Q = se(g, _, Y || A), $ = i[h], yt = _ ? "text-fg-disabled" : g ? "text-fg-danger" : Y ? "text-fg-default" : "text-fg-subtle";
124
+ return /* @__PURE__ */ d("div", {
125
125
  ref: Fe,
126
126
  className: e(ie(), "min-w-0"),
127
127
  ...Pe,
128
128
  children: [
129
- dt && ke && /* @__PURE__ */ c("label", {
130
- className: oe(f, m),
131
- htmlFor: z,
132
- children: ke
129
+ ft && De && /* @__PURE__ */ u("label", {
130
+ className: oe(m, g),
131
+ htmlFor: B,
132
+ children: De
133
133
  }),
134
- b ? /* @__PURE__ */ l("div", {
134
+ S ? /* @__PURE__ */ d("div", {
135
135
  ref: (e) => {
136
- G.setReference(e);
136
+ K.setReference(e);
137
137
  },
138
- ...rt({ onClick: () => {
139
- h || (F.current?.focus(), k || A(!0));
138
+ ...it({ onClick: () => {
139
+ _ || (I.current?.focus(), A || j(!0));
140
140
  } }),
141
- className: e(_t, "flex w-full min-w-0 items-center", mt, f !== "box" && "focus-within:border-primary", f !== "box" && f !== "line" && "focus-within:ring-control focus-within:ring-primary", h ? "cursor-not-allowed" : "cursor-text", C),
141
+ role: "presentation",
142
+ "aria-expanded": void 0,
143
+ "aria-controls": void 0,
144
+ "aria-haspopup": void 0,
145
+ className: e(vt, "flex w-full min-w-0 items-center", ht, m !== "box" && "focus-within:border-primary", m !== "box" && m !== "line" && "focus-within:ring-control focus-within:ring-primary", _ ? "cursor-not-allowed" : "cursor-text", Ie),
142
146
  children: [
143
- /* @__PURE__ */ c("input", {
147
+ /* @__PURE__ */ u("input", {
144
148
  ref: (e) => {
145
- F.current = e, typeof O == "function" ? O(e) : O && (O.current = e);
149
+ I.current = e, typeof k == "function" ? k(e) : k && (k.current = e);
146
150
  },
147
- id: z,
151
+ id: B,
148
152
  type: "text",
149
153
  role: "combobox",
150
- readOnly: !k,
151
- disabled: h,
154
+ "aria-label": Oe,
155
+ "aria-labelledby": ke,
156
+ readOnly: !A,
157
+ disabled: _,
152
158
  "aria-haspopup": "listbox",
153
- "aria-expanded": k,
154
- "aria-controls": k ? R : void 0,
155
- "aria-activedescendant": Xe,
159
+ "aria-expanded": A,
160
+ "aria-controls": A ? z : void 0,
161
+ "aria-activedescendant": Ze,
156
162
  "aria-autocomplete": "list",
157
- "data-testid": He,
158
- value: pt,
159
- placeholder: U ? Ne : Me,
160
- onChange: lt,
161
- onKeyDown: ut,
163
+ "data-testid": O,
164
+ value: mt,
165
+ placeholder: W ? Ne : Me,
166
+ onChange: ut,
167
+ onKeyDown: dt,
162
168
  onFocus: () => {
163
- ze && !h && !k && A(!0);
169
+ Be && !_ && !A && j(!0);
164
170
  },
165
- className: e("min-w-0 flex-1 truncate bg-transparent text-left outline-hidden placeholder:text-fg-subtle", Q, $, h && "cursor-not-allowed")
171
+ className: e("min-w-0 flex-1 truncate bg-transparent text-left outline-hidden placeholder:text-fg-subtle", $, yt, _ && "cursor-not-allowed")
166
172
  }),
167
- g && /* @__PURE__ */ c("span", {
168
- className: e("shrink-0 whitespace-nowrap", Q, Z),
169
- children: g
173
+ v && /* @__PURE__ */ u("span", {
174
+ className: e("shrink-0 whitespace-nowrap", $, Q),
175
+ children: v
170
176
  }),
171
- _ && /* @__PURE__ */ c("span", {
172
- className: e("flex shrink-0 items-center", Z, Y),
173
- children: _
177
+ y && /* @__PURE__ */ u("span", {
178
+ className: e("flex shrink-0 items-center", Q, X),
179
+ children: y
174
180
  }),
175
- S && /* @__PURE__ */ c(ue, { className: e("shrink-0 text-fg-subtle", X) }),
176
- v && !h && J && /* @__PURE__ */ c("button", {
181
+ w && /* @__PURE__ */ u(ue, { className: e("shrink-0 text-fg-subtle", Z) }),
182
+ b && !_ && Y && /* @__PURE__ */ u("button", {
177
183
  type: "button",
178
184
  tabIndex: -1,
179
- onClick: st,
185
+ onClick: ct,
180
186
  "aria-label": "선택 지우기",
181
- className: e("flex shrink-0 cursor-pointer items-center rounded", Z, "hover:text-fg-default focus:outline-hidden focus-visible:ring-input-clear focus-visible:ring-input-clear-ring"),
182
- children: /* @__PURE__ */ c(n, {
183
- className: X,
187
+ className: e("flex shrink-0 cursor-pointer items-center rounded", Q, "hover:text-fg-default focus:outline-hidden focus-visible:ring-input-clear focus-visible:ring-input-clear-ring"),
188
+ children: /* @__PURE__ */ u(n, {
189
+ className: Z,
184
190
  strokeWidth: 1.5,
185
191
  "aria-hidden": !0
186
192
  })
187
193
  }),
188
- y && /* @__PURE__ */ c("span", {
189
- className: e("flex shrink-0 items-center", Y, ht),
190
- children: y
194
+ x && /* @__PURE__ */ u("span", {
195
+ className: e("flex shrink-0 items-center", X, gt),
196
+ children: x
191
197
  }),
192
- /* @__PURE__ */ c(t, {
193
- className: e("shrink-0 transition-transform", gt, Z, k && "rotate-180"),
198
+ /* @__PURE__ */ u(t, {
199
+ className: e("shrink-0 transition-transform", _t, Q, A && "rotate-180"),
194
200
  strokeWidth: 1.5,
195
201
  "aria-hidden": !0
196
202
  })
197
203
  ]
198
- }) : /* @__PURE__ */ l("button", {
204
+ }) : /* @__PURE__ */ d("button", {
199
205
  ref: (e) => {
200
- G.setReference(e), typeof O == "function" ? O(e) : O && (O.current = e);
206
+ K.setReference(e), typeof k == "function" ? k(e) : k && (k.current = e);
201
207
  },
202
- id: z,
208
+ id: B,
203
209
  type: "button",
204
- disabled: h,
210
+ disabled: _,
205
211
  "aria-haspopup": "listbox",
206
- "aria-expanded": k,
207
- "aria-controls": k ? R : void 0,
208
- "aria-activedescendant": Xe,
209
- "data-testid": He,
210
- ...rt({ onKeyDown: ct }),
211
- className: e(_t, "flex w-full min-w-0 items-center", mt, h ? "cursor-not-allowed" : "cursor-pointer", C),
212
+ "aria-expanded": A,
213
+ "aria-controls": A ? z : void 0,
214
+ "aria-activedescendant": Ze,
215
+ "data-testid": O,
216
+ ...it({ onKeyDown: lt }),
217
+ "aria-label": Oe,
218
+ "aria-labelledby": ke,
219
+ className: e(vt, "flex w-full min-w-0 items-center", ht, _ ? "cursor-not-allowed" : "cursor-pointer", Ie),
212
220
  children: [
213
- /* @__PURE__ */ c("span", {
214
- className: e("min-w-0 flex-1 truncate text-left", Q, $),
215
- children: ft
221
+ /* @__PURE__ */ u("span", {
222
+ className: e("min-w-0 flex-1 truncate text-left", $, yt),
223
+ children: pt
216
224
  }),
217
- g && /* @__PURE__ */ c("span", {
218
- className: e("shrink-0 whitespace-nowrap", Q, Z),
219
- children: g
225
+ v && /* @__PURE__ */ u("span", {
226
+ className: e("shrink-0 whitespace-nowrap", $, Q),
227
+ children: v
220
228
  }),
221
- _ && /* @__PURE__ */ c("span", {
222
- className: e("flex shrink-0 items-center", Z, Y),
223
- children: _
229
+ y && /* @__PURE__ */ u("span", {
230
+ className: e("flex shrink-0 items-center", Q, X),
231
+ children: y
224
232
  }),
225
- v && !h && J && /* @__PURE__ */ c("span", {
233
+ b && !_ && Y && /* @__PURE__ */ u("span", {
226
234
  role: "button",
227
235
  tabIndex: -1,
228
- onClick: st,
236
+ onClick: ct,
229
237
  "aria-label": "선택 지우기",
230
- className: e("flex shrink-0 cursor-pointer items-center", Z, "hover:text-fg-default"),
231
- children: /* @__PURE__ */ c(n, {
232
- className: X,
238
+ className: e("flex shrink-0 cursor-pointer items-center", Q, "hover:text-fg-default"),
239
+ children: /* @__PURE__ */ u(n, {
240
+ className: Z,
233
241
  strokeWidth: 1.5,
234
242
  "aria-hidden": !0
235
243
  })
236
244
  }),
237
- y && /* @__PURE__ */ c("span", {
238
- className: e("flex shrink-0 items-center", Y, ht),
239
- children: y
245
+ x && /* @__PURE__ */ u("span", {
246
+ className: e("flex shrink-0 items-center", X, gt),
247
+ children: x
240
248
  }),
241
- /* @__PURE__ */ c(t, {
242
- className: e("shrink-0 transition-transform", gt, Z, k && "rotate-180"),
249
+ /* @__PURE__ */ u(t, {
250
+ className: e("shrink-0 transition-transform", _t, Q, A && "rotate-180"),
243
251
  strokeWidth: 1.5,
244
252
  "aria-hidden": !0
245
253
  })
246
254
  ]
247
255
  }),
248
- Re && /* @__PURE__ */ c("input", {
256
+ ze && /* @__PURE__ */ u("input", {
249
257
  type: "hidden",
250
- name: Re,
251
- value: u
258
+ name: ze,
259
+ value: f
252
260
  }),
253
- k && /* @__PURE__ */ c(ge, { children: /* @__PURE__ */ c(he, {
254
- context: K,
261
+ A && /* @__PURE__ */ u(me, { children: /* @__PURE__ */ u(pe, {
262
+ context: q,
255
263
  modal: !1,
256
- initialFocus: b ? -1 : 0,
257
- children: /* @__PURE__ */ c("div", {
258
- ref: G.setFloating,
259
- id: R,
260
- style: nt,
261
- ...it(),
262
- className: e("z-floating overflow-hidden rounded-surface border border-border-subtle bg-bg-surface shadow-overlay", Ie),
263
- children: /* @__PURE__ */ l("div", {
264
- ref: qe,
264
+ initialFocus: S ? -1 : 0,
265
+ children: /* @__PURE__ */ u("div", {
266
+ ref: K.setFloating,
267
+ id: z,
268
+ style: rt,
269
+ ...at(),
270
+ className: e("z-floating overflow-hidden rounded-surface border border-border-subtle bg-bg-surface shadow-overlay", Le),
271
+ children: /* @__PURE__ */ d("div", {
272
+ ref: Je,
265
273
  className: "max-h-72 overflow-y-auto py-1",
266
- children: [W.length === 0 ? /* @__PURE__ */ c("div", {
274
+ children: [G.length === 0 ? /* @__PURE__ */ u("div", {
267
275
  className: "px-3 py-4 text-center text-sm text-fg-subtle",
268
- children: S ? "검색 중..." : "옵션이 없어요"
269
- }) : W.map((t, n) => {
270
- let r = String(t.value) === u, i = j === n;
271
- return /* @__PURE__ */ l("div", {
272
- id: Ye(n),
276
+ children: w ? "검색 중..." : "옵션이 없어요"
277
+ }) : G.map((t, n) => {
278
+ let r = String(t.value) === f, i = M === n;
279
+ return /* @__PURE__ */ d("div", {
280
+ id: Xe(n),
273
281
  ref: (e) => {
274
- Ge.current[n] = e;
282
+ Ke.current[n] = e;
275
283
  },
276
284
  role: "option",
277
285
  "aria-selected": r,
278
286
  "aria-disabled": t.disabled || void 0,
279
287
  tabIndex: i ? 0 : -1,
280
- ...at({
288
+ ...ot({
281
289
  onClick: () => {
282
- t.disabled || q(String(t.value));
290
+ t.disabled || J(String(t.value));
283
291
  },
284
292
  onKeyDown: (e) => {
285
- t.disabled || (e.key === "Enter" || e.key === " ") && (e.preventDefault(), q(String(t.value)));
293
+ t.disabled || (e.key === "Enter" || e.key === " ") && (e.preventDefault(), J(String(t.value)));
286
294
  }
287
295
  }),
288
296
  className: e("flex cursor-pointer items-start gap-3 px-3 py-2 text-sm transition-colors", t.disabled ? "cursor-not-allowed text-fg-disabled" : r ? e("font-medium text-primary-fg", i ? "bg-primary-subtle" : "bg-primary-subtle/60 hover:bg-primary-subtle/80") : i ? "bg-bg-subtle text-fg-default" : "text-fg-default hover:bg-bg-subtle"),
289
- children: [/* @__PURE__ */ l("div", {
297
+ children: [/* @__PURE__ */ d("div", {
290
298
  className: "min-w-0 flex-1",
291
- children: [/* @__PURE__ */ c("div", {
299
+ children: [/* @__PURE__ */ u("div", {
292
300
  className: "truncate",
293
301
  children: t.label
294
- }), t.description && /* @__PURE__ */ c("div", {
302
+ }), t.description && /* @__PURE__ */ u("div", {
295
303
  className: "mt-0.5 truncate text-xs text-fg-subtle",
296
304
  children: t.description
297
305
  })]
298
- }), t.trailing && /* @__PURE__ */ c("span", {
306
+ }), t.trailing && /* @__PURE__ */ u("span", {
299
307
  className: "shrink-0 text-xs text-fg-subtle",
300
308
  children: t.trailing
301
309
  })]
302
310
  }, String(t.value));
303
- }), w && T && /* @__PURE__ */ c("div", {
304
- ref: Ke,
311
+ }), T && E && /* @__PURE__ */ u("div", {
312
+ ref: qe,
305
313
  "aria-hidden": !0,
306
314
  className: "flex items-center justify-center px-3 py-3 text-fg-subtle",
307
- children: S && /* @__PURE__ */ c(ue, {})
315
+ children: w && /* @__PURE__ */ u(ue, {})
308
316
  })]
309
317
  })
310
318
  })
311
319
  }) }),
312
- je && /* @__PURE__ */ c("div", {
313
- className: ae(m),
320
+ je && /* @__PURE__ */ u("div", {
321
+ className: ae(g),
314
322
  children: je
315
323
  })
316
324
  ]
317
325
  });
318
326
  });
319
327
  //#endregion
320
- export { u as Select };
328
+ export { f as Select };
@@ -32,6 +32,13 @@ export interface SelectCommonProps {
32
32
  * Select 필드의 상단의 라벨
33
33
  */
34
34
  label?: string;
35
+ /**
36
+ * 트리거의 접근성 이름. 명시된 aria 속성은 시각 label보다 우선한다.
37
+ * 보이는 라벨이 있으면 그 텍스트를 포함한다(WCAG 2.5.3).
38
+ */
39
+ "aria-label"?: string;
40
+ /** 참조한 요소로 접근성 이름을 지정한다. aria-label보다 우선하며 보이는 라벨 텍스트를 포함해야 한다. */
41
+ "aria-labelledby"?: string;
35
42
  /**
36
43
  * label 표시 방식
37
44
  * 'appear': value가 있을 때만 label이 보여요
@@ -0,0 +1 @@
1
+ const e=require("../../lib/utils.cjs"),t=require("./utils.cjs");let n=require("react"),r=require("react/jsx-runtime");var i=(0,n.forwardRef)(function({min:i=0,max:a=100,step:o=1,value:s,defaultValue:c,onValueChange:l,formatValue:u,className:d,style:f,"aria-valuetext":p,...m},h){let g=(0,n.useRef)(null),_=c??i+(a-i)/2,[v,y]=(0,n.useState)(_),b=t.normalizeSliderValue(s??v,i,a,o);return(0,n.useEffect)(()=>{let e=g.current?.form;if(!e||s!==void 0)return;let t=()=>y(_);return e.addEventListener(`reset`,t),()=>e.removeEventListener(`reset`,t)},[s,_]),(0,r.jsx)(`input`,{...m,ref:e=>{g.current=e,typeof h==`function`?h(e):h&&(h.current=e)},type:`range`,min:i,max:a,step:o,value:b,"aria-valuetext":u?u(b):p,onChange:e=>{let n=t.normalizeSliderValue(e.currentTarget.valueAsNumber,i,a,o);s===void 0&&y(n),l?.(n)},className:e.cn(`ui-slider`,d),style:{...f,"--slider-fill":`${t.sliderPercent(b,i,a)}%`}})});exports.Slider=i;
@@ -0,0 +1,6 @@
1
+ import { SliderProps } from './types.js';
2
+ /**
3
+ * 단일 thumb 네이티브 범위 입력. aria-label 또는 연결된 label을 제공한다.
4
+ * 범위 밖 controlled 값은 화면에서만 범위 내로 보정하며 그 자체로 onValueChange를 호출하지 않는다.
5
+ */
6
+ export declare const Slider: import('react').ForwardRefExoticComponent<SliderProps & import('react').RefAttributes<HTMLInputElement>>;
@@ -0,0 +1,36 @@
1
+ import { cn as e } from "../../lib/utils.esm.js";
2
+ import { normalizeSliderValue as t, sliderPercent as n } from "./utils.esm.js";
3
+ import { forwardRef as r, useEffect as i, useRef as a, useState as o } from "react";
4
+ import { jsx as s } from "react/jsx-runtime";
5
+ //#region src/components/slider/Slider.tsx
6
+ var c = r(function({ min: r = 0, max: c = 100, step: l = 1, value: u, defaultValue: d, onValueChange: f, formatValue: p, className: m, style: h, "aria-valuetext": g, ..._ }, v) {
7
+ let y = a(null), b = d ?? r + (c - r) / 2, [x, S] = o(b), C = t(u ?? x, r, c, l);
8
+ return i(() => {
9
+ let e = y.current?.form;
10
+ if (!e || u !== void 0) return;
11
+ let t = () => S(b);
12
+ return e.addEventListener("reset", t), () => e.removeEventListener("reset", t);
13
+ }, [u, b]), /* @__PURE__ */ s("input", {
14
+ ..._,
15
+ ref: (e) => {
16
+ y.current = e, typeof v == "function" ? v(e) : v && (v.current = e);
17
+ },
18
+ type: "range",
19
+ min: r,
20
+ max: c,
21
+ step: l,
22
+ value: C,
23
+ "aria-valuetext": p ? p(C) : g,
24
+ onChange: (e) => {
25
+ let n = t(e.currentTarget.valueAsNumber, r, c, l);
26
+ u === void 0 && S(n), f?.(n);
27
+ },
28
+ className: e("ui-slider", m),
29
+ style: {
30
+ ...h,
31
+ "--slider-fill": `${n(C, r, c)}%`
32
+ }
33
+ });
34
+ });
35
+ //#endregion
36
+ export { c as Slider };
@@ -0,0 +1,2 @@
1
+ export { Slider } from './Slider.js';
2
+ export type { SliderProps } from './types.js';
@@ -0,0 +1,15 @@
1
+ import { ComponentPropsWithoutRef } from 'react';
2
+ export interface SliderProps extends Omit<ComponentPropsWithoutRef<"input">, "type" | "value" | "defaultValue" | "onChange" | "min" | "max" | "step"> {
3
+ /** 범위의 시작. 기본 0. */
4
+ min?: number;
5
+ /** 범위의 끝. min 이상이어야 한다. 기본 100. */
6
+ max?: number;
7
+ /** 양수 간격. 기본 1. */
8
+ step?: number;
9
+ /** 범위 밖 값은 화면에서만 보정하며 그 자체로 콜백을 호출하지 않는다. */
10
+ value?: number;
11
+ defaultValue?: number;
12
+ onValueChange?: (value: number) => void;
13
+ /** 현재 값을 스크린리더에 읽힐 단위 포함 텍스트로 변환한다. */
14
+ formatValue?: (value: number) => string;
15
+ }
@@ -0,0 +1 @@
1
+ function e(e){let[t,n=`0`]=String(e).toLowerCase().split(`e`);return Math.max(0,(t.split(`.`)[1]?.length??0)-Number(n))}function t(t,n,r,i){if(r<=n)return n;let a=Number.isFinite(i)&&i>0?i:1,o=(t-n)/a,s=Math.floor((r-n)/a+1e-10),c=Math.min(s,Math.max(0,Math.round(o+1e-10))),l=Math.min(12,Math.max(e(n),e(a)));return Number((n+c*a).toFixed(l))}function n(e,t,n){return n<=t?0:Math.min(100,Math.max(0,(e-t)/(n-t)*100))}exports.normalizeSliderValue=t,exports.sliderPercent=n;
@@ -0,0 +1,3 @@
1
+ /** 범위의 시작을 기준으로 step에 맞추고, 부동소수 오차를 제거한다. */
2
+ export declare function normalizeSliderValue(value: number, min: number, max: number, step: number): number;
3
+ export declare function sliderPercent(value: number, min: number, max: number): number;
@@ -0,0 +1,15 @@
1
+ //#region src/components/slider/utils.ts
2
+ function e(e) {
3
+ let [t, n = "0"] = String(e).toLowerCase().split("e");
4
+ return Math.max(0, (t.split(".")[1]?.length ?? 0) - Number(n));
5
+ }
6
+ function t(t, n, r, i) {
7
+ if (r <= n) return n;
8
+ let a = Number.isFinite(i) && i > 0 ? i : 1, o = (t - n) / a, s = Math.floor((r - n) / a + 1e-10), c = Math.min(s, Math.max(0, Math.round(o + 1e-10))), l = Math.min(12, Math.max(e(n), e(a)));
9
+ return Number((n + c * a).toFixed(l));
10
+ }
11
+ function n(e, t, n) {
12
+ return n <= t ? 0 : Math.min(100, Math.max(0, (e - t) / (n - t) * 100));
13
+ }
14
+ //#endregion
15
+ export { t as normalizeSliderValue, n as sliderPercent };