@skiddph/prui 0.9.0 → 0.10.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.
@@ -12,6 +12,10 @@ export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElem
12
12
  size?: InputSize;
13
13
  /** Visual variant: outlined (default) or filled. */
14
14
  variant?: "default" | "filled";
15
+ /** Icon rendered inside the field's leading edge. */
16
+ icon?: React.ReactNode;
17
+ /** Icon rendered inside the field's trailing edge. */
18
+ trailingIcon?: React.ReactNode;
15
19
  }
16
20
  export declare const Input: React.ForwardRefExoticComponent<InputProps & React.RefAttributes<HTMLInputElement>>;
17
21
  export declare const inputPropsMeta: PropsMeta;
@@ -1,46 +1,59 @@
1
- import { jsx as o } from "react/jsx-runtime";
2
- import * as l from "react";
3
- import { resolveSurface as v, withSurface as h } from "./surface.js";
4
- import { cn as s } from "./cn.js";
5
- const u = "prui-f-control prui-input w-full bg-[var(--prui-s-bg,var(--prui-background))] text-[var(--prui-s-fg,var(--prui-fg))] placeholder:text-[var(--prui-dim)] border border-[var(--prui-line)] rounded-[var(--prui-s-radius,var(--prui-radius))] text-sm outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30 disabled:opacity-50 disabled:cursor-not-allowed", w = {
1
+ import { jsx as a, jsxs as N } from "react/jsx-runtime";
2
+ import * as d from "react";
3
+ import { resolveSurface as R, withSurface as j } from "./surface.js";
4
+ import { cn as u } from "./cn.js";
5
+ const p = "prui-f-control prui-input w-full bg-[var(--prui-s-bg,var(--prui-background))] text-[var(--prui-s-fg,var(--prui-fg))] placeholder:text-[var(--prui-dim)] border border-[var(--prui-line)] rounded-[var(--prui-s-radius,var(--prui-radius))] text-sm outline-none transition-colors focus:border-[var(--prui-brand)] focus:ring-2 focus:ring-[var(--prui-brand)]/30 disabled:opacity-50 disabled:cursor-not-allowed", z = {
6
6
  sm: "h-8 px-2.5",
7
7
  md: "h-9 px-3",
8
8
  lg: "h-11 px-4 text-base"
9
- }, N = l.forwardRef(
10
- ({ className: e, style: t, type: r = "text", size: a = "md", variant: i = "default", bg: p, fg: d, radius: c, texture: m, textureColor: f, elevation: x, ...b }, g) => {
11
- const y = v({ bg: p, fg: d, radius: c, texture: m, textureColor: f, elevation: x }), n = h(
12
- s(u, w[a], i === "filled" && "bg-[var(--prui-s-bg,var(--prui-raise))] border-transparent", e),
13
- t,
14
- y
15
- );
16
- return /* @__PURE__ */ o("input", { ref: g, type: r, className: n.className, style: n.style, ...b });
9
+ }, C = d.forwardRef(
10
+ ({ className: r, style: n, type: l = "text", size: o = "md", variant: c = "default", icon: e, trailingIcon: t, bg: m, fg: f, radius: g, texture: x, textureColor: v, elevation: y, ...b }, h) => {
11
+ const w = R({ bg: m, fg: f, radius: g, texture: x, textureColor: v, elevation: y }), s = j(
12
+ u(
13
+ p,
14
+ z[o],
15
+ c === "filled" && "bg-[var(--prui-s-bg,var(--prui-raise))] border-transparent",
16
+ e && "pl-9",
17
+ t && "pr-9",
18
+ r
19
+ ),
20
+ n,
21
+ w
22
+ ), i = /* @__PURE__ */ a("input", { ref: h, type: l, className: s.className, style: s.style, ...b });
23
+ return !e && !t ? i : /* @__PURE__ */ N("span", { className: "relative inline-flex w-full", children: [
24
+ e ? /* @__PURE__ */ a("span", { "aria-hidden": !0, className: "pointer-events-none absolute left-3 top-1/2 flex -translate-y-1/2 items-center text-[var(--prui-dim)] [&>svg]:h-4 [&>svg]:w-4", children: e }) : null,
25
+ i,
26
+ t ? /* @__PURE__ */ a("span", { "aria-hidden": !0, className: "pointer-events-none absolute right-3 top-1/2 flex -translate-y-1/2 items-center text-[var(--prui-dim)] [&>svg]:h-4 [&>svg]:w-4", children: t }) : null
27
+ ] });
17
28
  }
18
29
  );
19
- N.displayName = "Input";
20
- const S = {
30
+ C.displayName = "Input";
31
+ const P = {
21
32
  name: "Input",
22
33
  props: [
23
34
  { name: "type", type: "string", default: "'text'", control: "select", options: ["text", "password", "email", "number", "search"] },
24
35
  { name: "size", type: "'sm' | 'md' | 'lg'", default: "'md'", control: "select", options: ["sm", "md", "lg"] },
25
36
  { name: "variant", type: "'default' | 'filled'", default: "'default'", control: "select", options: ["default", "filled"] },
37
+ { name: "icon", type: "ReactNode", default: "undefined", control: "none", description: "Icon inside the leading edge (padding adjusts)." },
38
+ { name: "trailingIcon", type: "ReactNode", default: "undefined", control: "none", description: "Icon inside the trailing edge." },
26
39
  { name: "value", type: "string", default: null, control: "text" },
27
40
  { name: "placeholder", type: "string", default: "undefined", control: "text" },
28
41
  { name: "disabled", type: "boolean", default: "false", control: "boolean" },
29
42
  { name: "onChange", type: "(e) => void", default: null, control: "none" }
30
43
  ]
31
- }, z = l.forwardRef(
32
- ({ className: e, style: t, ...r }, a) => /* @__PURE__ */ o(
44
+ }, I = d.forwardRef(
45
+ ({ className: r, style: n, ...l }, o) => /* @__PURE__ */ a(
33
46
  "textarea",
34
47
  {
35
- ref: a,
36
- style: t,
37
- className: s(u, "h-auto min-h-20 py-2 resize-y", e),
38
- ...r
48
+ ref: o,
49
+ style: n,
50
+ className: u(p, "h-auto min-h-20 resize-y px-3 py-2", r),
51
+ ...l
39
52
  }
40
53
  )
41
54
  );
42
- z.displayName = "Textarea";
43
- const T = {
55
+ I.displayName = "Textarea";
56
+ const k = {
44
57
  name: "Textarea",
45
58
  props: [
46
59
  { name: "value", type: "string", default: null, control: "textarea" },
@@ -50,8 +63,8 @@ const T = {
50
63
  ]
51
64
  };
52
65
  export {
53
- N as Input,
54
- z as Textarea,
55
- S as inputPropsMeta,
56
- T as textareaPropsMeta
66
+ C as Input,
67
+ I as Textarea,
68
+ P as inputPropsMeta,
69
+ k as textareaPropsMeta
57
70
  };
@@ -1,79 +1,86 @@
1
- import { jsx as e, jsxs as a } from "react/jsx-runtime";
2
- import * as o from "react";
3
- import { createRoot as X } from "react-dom/client";
4
- import { X as q } from "lucide-react";
5
- import { cn as G } from "./cn.js";
6
- import { useReducedMotion as B, useOverlay as F, Portal as H } from "./overlay.js";
7
- import { getPruiDictionary as J } from "../i18n.js";
8
- const O = {
1
+ import { jsx as e, jsxs as n } from "react/jsx-runtime";
2
+ import * as r from "react";
3
+ import { createRoot as q } from "react-dom/client";
4
+ import { X as G } from "lucide-react";
5
+ import { cn as H } from "./cn.js";
6
+ import { useReducedMotion as F, useOverlay as O, Portal as J } from "./overlay.js";
7
+ import { getPruiDictionary as K } from "../i18n.js";
8
+ const Y = {
9
9
  xs: { width: "320px", minWidth: "280px" },
10
10
  sm: { width: "448px", minWidth: "320px" },
11
11
  md: { width: "640px", minWidth: "384px" },
12
12
  lg: { width: "896px", minWidth: "512px" },
13
13
  xl: { width: "1152px", minWidth: "640px" }
14
- }, K = {
14
+ }, Q = {
15
15
  xs: "24px 32px",
16
16
  sm: "24px 32px",
17
17
  md: "32px 40px",
18
18
  lg: "32px 40px",
19
19
  xl: "40px 48px"
20
- }, Q = o.forwardRef(function({
21
- open: r,
22
- onClose: n,
20
+ }, U = r.forwardRef(function({
21
+ open: t,
22
+ onClose: a,
23
23
  children: W,
24
- disableDefaultClose: p = !1,
24
+ disableDefaultClose: m = !1,
25
25
  closeOnOverlayClick: M = !0,
26
- size: y,
27
- xs: S,
28
- sm: T,
26
+ size: w,
27
+ xs: R,
28
+ sm: S,
29
29
  md: N,
30
- lg: m,
30
+ lg: f,
31
31
  xl: b,
32
- maxWidth: R,
33
- padding: z,
34
- noPadding: w = !1,
35
- showCloseButton: k = !0,
36
- ariaLabel: f,
37
- className: h,
32
+ maxWidth: z,
33
+ padding: P,
34
+ noPadding: k = !1,
35
+ showCloseButton: C = !0,
36
+ ariaLabel: h,
37
+ className: v,
38
38
  style: s,
39
- initialFocus: P = "first"
39
+ initialFocus: j = "first"
40
40
  }, l) {
41
- const v = y ?? (S ? "xs" : T ? "sm" : m ? "lg" : b ? "xl" : "md"), [x, i] = o.useState(r), [d, u] = o.useState(!1), [g, L] = o.useState(!1), A = o.useRef(null), C = B(), E = () => {
42
- C || (L(!0), setTimeout(() => L(!1), 500));
41
+ const x = w ?? (R ? "xs" : S ? "sm" : f ? "lg" : b ? "xl" : "md"), [g, i] = r.useState(t), [u, c] = r.useState(!1), [y, E] = r.useState(!1), V = r.useRef(null), T = F(), d = r.useRef(null), I = () => {
42
+ T || (E(!0), d.current != null && window.clearTimeout(d.current), d.current = window.setTimeout(() => {
43
+ d.current = null, E(!1);
44
+ }, 500));
43
45
  };
44
- o.useEffect(() => {
45
- if (r) {
46
- if (i(!0), C) {
47
- u(!0);
46
+ r.useEffect(
47
+ () => () => {
48
+ d.current != null && window.clearTimeout(d.current);
49
+ },
50
+ []
51
+ ), r.useEffect(() => {
52
+ if (t) {
53
+ if (i(!0), T) {
54
+ c(!0);
48
55
  return;
49
56
  }
50
- const t = setTimeout(() => {
51
- u(!0);
57
+ const o = setTimeout(() => {
58
+ c(!0);
52
59
  }, 10);
53
- return () => clearTimeout(t);
60
+ return () => clearTimeout(o);
54
61
  }
55
- u(!1), C && i(!1);
56
- }, [r, C]);
57
- const { ref: V } = F({
58
- open: r,
62
+ c(!1), T && i(!1);
63
+ }, [t, T]);
64
+ const { ref: D } = O({
65
+ open: t,
59
66
  onEscape: () => {
60
- if (p)
61
- return E(), !1;
62
- n();
67
+ if (m)
68
+ return I(), !1;
69
+ a();
63
70
  },
64
- initialFocus: P
71
+ initialFocus: j
65
72
  });
66
- if (!x && !d) return null;
67
- const I = (t) => {
68
- if (t.target === t.currentTarget) {
69
- if (p || !M) {
70
- E();
73
+ if (!g && !u) return null;
74
+ const B = (o) => {
75
+ if (o.target === o.currentTarget) {
76
+ if (m || !M) {
77
+ I();
71
78
  return;
72
79
  }
73
- n();
80
+ a();
74
81
  }
75
- }, j = O[v], D = w ? "0" : z ?? K[v];
76
- return /* @__PURE__ */ e(H, { children: /* @__PURE__ */ e("div", { ref: V, children: /* @__PURE__ */ e(
82
+ }, L = Y[x], X = k ? "0" : P ?? Q[x];
83
+ return /* @__PURE__ */ e(J, { children: /* @__PURE__ */ e("div", { ref: D, children: /* @__PURE__ */ e(
77
84
  "div",
78
85
  {
79
86
  className: "prui-modal-overlay fixed inset-0 z-[var(--prui-z-modal)] flex justify-center overflow-y-auto p-4",
@@ -82,55 +89,55 @@ const O = {
82
89
  paddingTop: "10vh",
83
90
  backgroundColor: "var(--prui-scrim)",
84
91
  backdropFilter: "blur(4px)",
85
- opacity: d ? 1 : 0,
92
+ opacity: u ? 1 : 0,
86
93
  transition: "opacity var(--prui-duration-slow) var(--prui-ease-out)"
87
94
  },
88
- onClick: I,
89
- onMouseDown: (t) => {
90
- t.target === t.currentTarget && I(t);
95
+ onClick: B,
96
+ onMouseDown: (o) => {
97
+ o.target === o.currentTarget && B(o);
91
98
  },
92
- children: /* @__PURE__ */ a(
99
+ children: /* @__PURE__ */ n(
93
100
  "div",
94
101
  {
95
- ref: (t) => {
96
- A.current = t, typeof l == "function" ? l(t) : l && (l.current = t);
102
+ ref: (o) => {
103
+ V.current = o, typeof l == "function" ? l(o) : l && (l.current = o);
97
104
  },
98
105
  role: "dialog",
99
106
  "aria-modal": "true",
100
- "aria-label": f,
101
- className: G(
107
+ "aria-label": h,
108
+ className: H(
102
109
  "prui-modal-content relative h-fit m-auto w-full",
103
- g && "prui-modal-shake",
104
- h
110
+ y && "prui-modal-shake",
111
+ v
105
112
  ),
106
113
  style: {
107
- width: j.width,
108
- minWidth: j.minWidth,
109
- maxWidth: R ?? j.width,
110
- padding: D,
114
+ width: L.width,
115
+ minWidth: L.minWidth,
116
+ maxWidth: z ?? L.width,
117
+ padding: X,
111
118
  backgroundColor: "var(--prui-surface)",
112
119
  border: "1px solid var(--prui-line)",
113
120
  borderRadius: "var(--prui-radius-3)",
114
121
  boxShadow: "var(--prui-shadow-modal)",
115
122
  color: "var(--prui-fg)",
116
- transform: d ? "scale(1) translateY(0)" : "scale(0.95) translateY(8px)",
117
- opacity: d ? 1 : 0,
123
+ transform: u ? "scale(1) translateY(0)" : "scale(0.95) translateY(8px)",
124
+ opacity: u ? 1 : 0,
118
125
  transition: "transform var(--prui-duration-slow) var(--prui-ease-out), opacity var(--prui-duration-slow) var(--prui-ease-out)",
119
126
  ...s
120
127
  },
121
128
  onTransitionEnd: () => {
122
- r || i(!1);
129
+ t || i(!1);
123
130
  },
124
131
  children: [
125
132
  W,
126
- k && !p ? /* @__PURE__ */ e(
133
+ C && !m ? /* @__PURE__ */ e(
127
134
  "button",
128
135
  {
129
136
  type: "button",
130
- onClick: n,
137
+ onClick: a,
131
138
  "aria-label": "Close modal",
132
139
  className: "absolute right-4 top-4 flex h-10 w-10 cursor-pointer items-center justify-center rounded-[var(--prui-radius)] text-[var(--prui-dim)] transition-all hover:bg-[var(--prui-raise)] hover:text-[var(--prui-fg)]",
133
- children: /* @__PURE__ */ e(q, { className: "h-4 w-4", "aria-hidden": !0 })
140
+ children: /* @__PURE__ */ e(G, { className: "h-4 w-4", "aria-hidden": !0 })
134
141
  }
135
142
  ) : null
136
143
  ]
@@ -139,32 +146,32 @@ const O = {
139
146
  }
140
147
  ) }) });
141
148
  });
142
- Q.displayName = "Modal";
143
- const Y = {
149
+ U.displayName = "Modal";
150
+ const A = {
144
151
  success: "var(--prui-ok)",
145
152
  warning: "var(--prui-warn)",
146
153
  danger: "var(--prui-danger)",
147
154
  error: "var(--prui-danger)",
148
155
  info: "var(--prui-brand)",
149
156
  default: "var(--prui-brand)"
150
- }, U = ({ type: c }) => {
151
- const r = Y[c ?? "default"];
152
- switch (c) {
157
+ }, Z = ({ type: p }) => {
158
+ const t = A[p ?? "default"];
159
+ switch (p) {
153
160
  case "success":
154
- return /* @__PURE__ */ a("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: r }, "aria-hidden": !0, children: [
161
+ return /* @__PURE__ */ n("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: t }, "aria-hidden": !0, children: [
155
162
  /* @__PURE__ */ e("path", { d: "M9 12l2 2 4-4", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
156
163
  /* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" })
157
164
  ] });
158
165
  case "warning":
159
- return /* @__PURE__ */ e("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: r }, "aria-hidden": !0, children: /* @__PURE__ */ e("path", { d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.694-.833-2.464 0L4.34 16.5c-.77.833.192 2.5 1.732 2.5z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) });
166
+ return /* @__PURE__ */ e("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: t }, "aria-hidden": !0, children: /* @__PURE__ */ e("path", { d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.694-.833-2.464 0L4.34 16.5c-.77.833.192 2.5 1.732 2.5z", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) });
160
167
  case "danger":
161
168
  case "error":
162
- return /* @__PURE__ */ a("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: r }, "aria-hidden": !0, children: [
169
+ return /* @__PURE__ */ n("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: t }, "aria-hidden": !0, children: [
163
170
  /* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" }),
164
171
  /* @__PURE__ */ e("path", { d: "M15 9l-6 6m0-6l6 6", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
165
172
  ] });
166
173
  case "info":
167
- return /* @__PURE__ */ a("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: r }, "aria-hidden": !0, children: [
174
+ return /* @__PURE__ */ n("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", style: { color: t }, "aria-hidden": !0, children: [
168
175
  /* @__PURE__ */ e("circle", { cx: "12", cy: "12", r: "9", stroke: "currentColor", strokeWidth: "2" }),
169
176
  /* @__PURE__ */ e("path", { d: "M12 8v4m0 4h.01", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round" })
170
177
  ] });
@@ -172,39 +179,39 @@ const Y = {
172
179
  return null;
173
180
  }
174
181
  };
175
- function oe(c) {
176
- const r = J(), { title: n, message: W, confirmText: p = r.confirm, cancelText: M = r.cancel, type: y, size: S = "sm" } = c, T = Y[y ?? "default"];
182
+ function ne(p) {
183
+ const t = K(), { title: a, message: W, confirmText: m = t.confirm, cancelText: M = t.cancel, type: w, size: R = "sm" } = p, S = A[w ?? "default"];
177
184
  return new Promise((N) => {
178
- const m = document.createElement("div");
179
- document.body.appendChild(m);
180
- const b = X(m), R = () => {
185
+ const f = document.createElement("div");
186
+ document.body.appendChild(f);
187
+ const b = q(f), z = () => {
181
188
  setTimeout(() => {
182
- b.unmount(), m.remove();
189
+ b.unmount(), f.remove();
183
190
  }, 320);
184
- }, z = () => {
185
- const [w, k] = o.useState(!1), [f, h] = o.useState(!1), [s, P] = o.useState(!1), l = o.useRef(null), v = o.useRef(null), x = B();
186
- o.useEffect(() => {
187
- if (x) {
188
- k(!0), h(!0);
191
+ }, P = () => {
192
+ const [k, C] = r.useState(!1), [h, v] = r.useState(!1), [s, j] = r.useState(!1), l = r.useRef(null), x = r.useRef(null), g = F();
193
+ r.useEffect(() => {
194
+ if (g) {
195
+ C(!0), v(!0);
189
196
  return;
190
197
  }
191
- const g = setTimeout(() => {
192
- k(!0), h(!0);
198
+ const y = setTimeout(() => {
199
+ C(!0), v(!0);
193
200
  }, 10);
194
- return () => clearTimeout(g);
195
- }, [x]);
196
- const i = (g) => {
197
- P(!0), h(!1), setTimeout(() => {
198
- R(), N(g);
199
- }, x ? 0 : 300);
200
- }, { ref: d } = F({
201
- open: w && !s,
201
+ return () => clearTimeout(y);
202
+ }, [g]);
203
+ const i = (y) => {
204
+ j(!0), v(!1), setTimeout(() => {
205
+ z(), N(y);
206
+ }, g ? 0 : 300);
207
+ }, { ref: u } = O({
208
+ open: k && !s,
202
209
  onEscape: () => (s || i(!1), !1),
203
- initialFocus: v
210
+ initialFocus: x
204
211
  });
205
- if (!w) return null;
206
- const u = O[S];
207
- return /* @__PURE__ */ e("div", { ref: d, children: /* @__PURE__ */ e(
212
+ if (!k) return null;
213
+ const c = Y[R];
214
+ return /* @__PURE__ */ e("div", { ref: u, children: /* @__PURE__ */ e(
208
215
  "div",
209
216
  {
210
217
  className: "prui-modal-overlay fixed inset-0 z-[var(--prui-z-confirm)] flex justify-center overflow-y-auto p-4",
@@ -213,37 +220,37 @@ function oe(c) {
213
220
  paddingTop: "12vh",
214
221
  backgroundColor: "var(--prui-scrim)",
215
222
  backdropFilter: "blur(4px)",
216
- opacity: f ? 1 : 0,
223
+ opacity: h ? 1 : 0,
217
224
  transition: "opacity var(--prui-duration-slow) var(--prui-ease-out)"
218
225
  },
219
- children: /* @__PURE__ */ a(
226
+ children: /* @__PURE__ */ n(
220
227
  "div",
221
228
  {
222
229
  role: "alertdialog",
223
230
  "aria-modal": "true",
224
- "aria-label": n,
231
+ "aria-label": a,
225
232
  className: "prui-modal-content relative m-auto w-full",
226
233
  style: {
227
- width: u.width,
228
- minWidth: u.minWidth,
234
+ width: c.width,
235
+ minWidth: c.minWidth,
229
236
  backgroundColor: "var(--prui-surface)",
230
237
  border: "1px solid var(--prui-line)",
231
238
  borderRadius: "var(--prui-radius-3)",
232
239
  boxShadow: "var(--prui-shadow-modal)",
233
240
  color: "var(--prui-fg)",
234
- transform: f ? "scale(1) translateY(0)" : "scale(0.95) translateY(8px)",
235
- opacity: f ? 1 : 0,
241
+ transform: h ? "scale(1) translateY(0)" : "scale(0.95) translateY(8px)",
242
+ opacity: h ? 1 : 0,
236
243
  transition: "transform var(--prui-duration-slow) var(--prui-ease-out), opacity var(--prui-duration-slow) var(--prui-ease-out)"
237
244
  },
238
245
  children: [
239
- /* @__PURE__ */ a("div", { className: "flex items-start gap-3 p-4 pb-2", children: [
240
- /* @__PURE__ */ e(U, { type: y }),
241
- /* @__PURE__ */ a("div", { className: "min-w-0", children: [
242
- /* @__PURE__ */ e("h2", { className: "m-0 text-lg font-semibold leading-normal", style: { color: "var(--prui-fg)" }, children: n }),
246
+ /* @__PURE__ */ n("div", { className: "flex items-start gap-3 p-4 pb-2", children: [
247
+ /* @__PURE__ */ e(Z, { type: w }),
248
+ /* @__PURE__ */ n("div", { className: "min-w-0", children: [
249
+ /* @__PURE__ */ e("h2", { className: "m-0 text-lg font-semibold leading-normal", style: { color: "var(--prui-fg)" }, children: a }),
243
250
  /* @__PURE__ */ e("p", { className: "mt-2 text-sm leading-normal", style: { color: "var(--prui-dim)" }, children: W })
244
251
  ] })
245
252
  ] }),
246
- /* @__PURE__ */ a("div", { className: "flex items-center justify-end gap-3 px-4 pb-4", children: [
253
+ /* @__PURE__ */ n("div", { className: "flex items-center justify-end gap-3 px-4 pb-4", children: [
247
254
  /* @__PURE__ */ e(
248
255
  "button",
249
256
  {
@@ -260,12 +267,12 @@ function oe(c) {
260
267
  "button",
261
268
  {
262
269
  type: "button",
263
- ref: v,
270
+ ref: x,
264
271
  disabled: s,
265
272
  onClick: () => i(!0),
266
273
  className: "cursor-pointer rounded-[var(--prui-radius)] border border-transparent px-4 py-2 text-sm font-medium text-white transition-all disabled:opacity-60",
267
- style: { backgroundColor: T },
268
- children: p
274
+ style: { backgroundColor: S },
275
+ children: m
269
276
  }
270
277
  )
271
278
  ] })
@@ -275,10 +282,10 @@ function oe(c) {
275
282
  }
276
283
  ) });
277
284
  };
278
- b.render(/* @__PURE__ */ e(z, {}));
285
+ b.render(/* @__PURE__ */ e(P, {}));
279
286
  });
280
287
  }
281
- const ae = {
288
+ const ie = {
282
289
  name: "Modal",
283
290
  props: [
284
291
  { name: "open", type: "boolean", default: null, control: "boolean" },
@@ -292,7 +299,7 @@ const ae = {
292
299
  { name: "maxWidth", type: "string (CSS)", default: "per-size", control: "text" },
293
300
  { name: "initialFocus", type: 'ref | "first" | "container" | false', default: '"first"', control: "none" }
294
301
  ]
295
- }, ie = {
302
+ }, ae = {
296
303
  name: "confirmModal",
297
304
  props: [
298
305
  { name: "title", type: "string", default: null, control: "text" },
@@ -303,8 +310,8 @@ const ae = {
303
310
  ]
304
311
  };
305
312
  export {
306
- Q as Modal,
307
- oe as confirmModal,
308
- ie as confirmModalPropsMeta,
309
- ae as modalPropsMeta
313
+ U as Modal,
314
+ ne as confirmModal,
315
+ ae as confirmModalPropsMeta,
316
+ ie as modalPropsMeta
310
317
  };
@@ -1,28 +1,44 @@
1
1
  import { PropsMeta } from './props-meta';
2
2
  import * as React from "react";
3
3
  /**
4
- * Select: a native-feeling single-select listbox. Full keyboard support:
5
- * Enter/Space/ArrowDown open, ArrowUp/Down/Home/End move, Enter/Space pick,
6
- * Escape (topmost overlay only) closes and restores focus, Tab closes,
7
- * printable-character typeahead jumps. Non-modal: no scroll lock.
4
+ * Select: a native-feeling single/multiple select listbox.
5
+ *
6
+ * - searchable: a filter input pins to the top of the listbox; typing
7
+ * narrows the options in place (works with the options prop and with
8
+ * compound <SelectItem> children alike).
9
+ * - multiple: multi-select — clicking toggles without closing; value and
10
+ * onChange become string[] and the trigger shows the first selected
11
+ * label plus a +N count.
12
+ *
13
+ * Keyboard: Enter/Space/ArrowDown open, ArrowUp/Down/Home/End move,
14
+ * Enter/Space pick, Escape (topmost overlay only) closes and restores
15
+ * focus, Tab closes, printable-character typeahead jumps. Non-modal: no
16
+ * scroll lock. The listbox portals to the body and anchors under the
17
+ * trigger, so no ancestor can clip or displace it.
8
18
  */
9
19
  export interface SelectOption {
10
20
  label: string;
11
21
  value: string;
12
22
  disabled?: boolean;
13
23
  }
14
- export interface SelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value"> {
24
+ export interface SelectProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onChange" | "value" | "defaultValue" | "multiple"> {
15
25
  options?: SelectOption[];
16
- value?: string;
17
- defaultValue?: string;
26
+ /** string in single mode, string[] with multiple. */
27
+ value?: string | string[];
28
+ defaultValue?: string | string[];
18
29
  placeholder?: string;
19
30
  disabled?: boolean;
20
31
  name?: string;
21
- onChange?: (value: string) => void;
32
+ /** Emits string in single mode, string[] with multiple. */
33
+ onChange?: (value: string | string[]) => void;
22
34
  onOpenChange?: (open: boolean) => void;
35
+ /** Type-to-filter the options inside the listbox. */
36
+ searchable?: boolean;
37
+ /** Multi-select: value/onChange become string[], items toggle. */
38
+ multiple?: boolean;
23
39
  }
24
40
  export declare const Select: {
25
- ({ options, value: valueProp, defaultValue, placeholder, disabled, name, id, onChange, onOpenChange, children, ...rest }: SelectProps): React.JSX.Element;
41
+ ({ options, value: valueProp, defaultValue, placeholder, disabled, name, onChange, onOpenChange, searchable, multiple, id, children, ...rest }: SelectProps): React.JSX.Element;
26
42
  displayName: string;
27
43
  };
28
44
  export type SelectTriggerProps = React.ButtonHTMLAttributes<HTMLButtonElement>;