@gridui/input 2.0.0 → 3.0.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @gridui/input
2
2
 
3
- Core family. Public API: `Input`, `InputProps`, `Label`, `LabelProps`, `Textarea`, `TextareaProps`, `controlVariants`.
3
+ Core family. Public API: `Input`, `InputProps`, `Label`, `LabelProps`, `Textarea`, `TextareaProps`, `controlVariants`, `InputGroup`, `InputGroupAddon`, `InputGroupButton`, `PasswordInput`, and `SearchInput`.
4
4
 
5
5
  Import components from `@gridui/input` and load `@gridui/input/styles.css` after Theme.
6
6
  Load styles for any composed dependency used by this family. Applications own routes, labels, state persistence, and branding.
@@ -15,3 +15,44 @@ See [Textarea](docs/textarea.md) for multiline input contracts and
15
15
 
16
16
  `Label` owns inline label alignment and an optional decorative `icon` slot.
17
17
  Icons use the standard 16px token size without an ancestor layout styling labels.
18
+
19
+ [Component reference](docs/reference/README.md) contains focused API pages for each public component.
20
+
21
+ ## Text entry compositions
22
+
23
+ `InputGroup` owns one outline around Input or Textarea and optional addons. Place
24
+ `InputGroupAddon` after the control in the DOM; `align` selects `inline-start`,
25
+ `inline-end`, `block-start`, or `block-end`. Logical alignment follows `dir`.
26
+ `controlSize` on the group supplies the default density to its Input/Textarea and
27
+ InputGroupButton children. An explicit child density wins. Each interactive child
28
+ owns its disabled state; a native disabled fieldset also disables all controls.
29
+ Decorative icons should be hidden from assistive technology. Interactive addons
30
+ keep their own keyboard focus indicators. Load Button styles before Input styles
31
+ when rendering InputGroupButton, PasswordInput, or SearchInput.
32
+
33
+ ```tsx
34
+ <InputGroup>
35
+ <Input aria-label="Website" name="website" />
36
+ <InputGroupAddon>https://</InputGroupAddon>
37
+ <InputGroupAddon align="inline-end">
38
+ <InputGroupButton>Open</InputGroupButton>
39
+ </InputGroupAddon>
40
+ </InputGroup>
41
+ ```
42
+
43
+ PasswordInput requires localized `showLabel` and `hideLabel`. It starts concealed,
44
+ preserves the native input element, and toggles its type with a non-submit button.
45
+ Native autocomplete and password managers remain available; applications choose
46
+ `current-password` or `new-password`. Read-only passwords can still be revealed.
47
+
48
+ SearchInput requires a localized `clearLabel`. Its clear action emits
49
+ `onValueChange("")`, focuses the input, and changes native uncontrolled values.
50
+ Controlled callers may reject the request. As with NumberField step buttons, this
51
+ explicit action does not synthesize a native onChange event. Use onValueChange
52
+ when controlled clearing is needed. Native reset restores defaultValue.
53
+ `loading` and `loadingLabel` provide status feedback without disabling typing.
54
+ Fetching, debouncing, caching and form submission remain application-owned.
55
+
56
+ For both compositions, ref, className, style, name and native attributes target
57
+ the input; `rootClassName` styles the group. Standard and small densities remain
58
+ available. `Field` and `useField` from Form can associate labels and help text.
package/dist/index.d.ts CHANGED
@@ -6,8 +6,18 @@
6
6
  */
7
7
  export type { InputProps } from "./input/input";
8
8
  export { Input } from "./input/input";
9
+ export type { InputGroupProps } from "./input-group/input-group";
10
+ export { InputGroup } from "./input-group/input-group";
11
+ export type { InputGroupAddonProps } from "./input-group-addon/input-group-addon";
12
+ export { InputGroupAddon } from "./input-group-addon/input-group-addon";
13
+ export type { InputGroupButtonProps } from "./input-group-button/input-group-button";
14
+ export { InputGroupButton } from "./input-group-button/input-group-button";
9
15
  export type { LabelProps } from "./label/label";
10
16
  export { Label } from "./label/label";
17
+ export type { PasswordInputProps } from "./password-input/password-input";
18
+ export { PasswordInput } from "./password-input/password-input";
19
+ export type { SearchInputProps } from "./search-input/search-input";
20
+ export { SearchInput } from "./search-input/search-input";
11
21
  export { controlVariants } from "./shared/style";
12
22
  export type { TextareaProps } from "./textarea/textarea";
13
23
  export { Textarea } from "./textarea/textarea";
package/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ // src/shared/input-group-context.ts
2
+ import { createContext, useContext } from "react";
3
+ var inputGroupContext = createContext(null);
4
+ var useInputGroupSize = () => {
5
+ return useContext(inputGroupContext);
6
+ };
7
+
1
8
  // src/shared/style.ts
2
9
  import { cn } from "@gridui/style-utils";
3
10
  import { cva } from "class-variance-authority";
@@ -29,9 +36,10 @@ var controlVariants = cva(controlStyles(), {
29
36
  import { cn as cn2 } from "@gridui/style-utils";
30
37
  import { jsx } from "react/jsx-runtime";
31
38
  var Input = (props) => {
39
+ const groupSize = useInputGroupSize();
32
40
  const {
33
41
  size,
34
- controlSize = "standard",
42
+ controlSize = groupSize ?? "standard",
35
43
  className,
36
44
  onChange,
37
45
  onValueChange,
@@ -46,32 +54,88 @@ var Input = (props) => {
46
54
  onChange?.(event);
47
55
  onValueChange?.(event.currentTarget.value);
48
56
  },
49
- className: cn2(controlVariants({ size: controlSize }), className)
57
+ className: cn2(controlVariants({ size: controlSize }), groupSize && "gridui-u-input--flex-1 gridui-u-input--w-0 gridui-u-input--border-0 gridui-u-input--bg-transparent", className)
50
58
  }
51
59
  );
52
60
  };
53
61
 
54
- // src/label/style.ts
62
+ // src/input-group/input-group.tsx
55
63
  import { cn as cn3 } from "@gridui/style-utils";
64
+ import { jsx as jsx2 } from "react/jsx-runtime";
65
+ var InputGroup = (props) => {
66
+ const { controlSize = "standard", className, children, ...restProps } = props;
67
+ return /* @__PURE__ */ jsx2(
68
+ inputGroupContext.Provider,
69
+ {
70
+ value: controlSize,
71
+ children: /* @__PURE__ */ jsx2(
72
+ "div",
73
+ {
74
+ ...restProps,
75
+ "data-control-size": controlSize,
76
+ "data-gridui-outline-target": "",
77
+ className: cn3("gridui-input-group", className),
78
+ children
79
+ }
80
+ )
81
+ }
82
+ );
83
+ };
84
+
85
+ // src/input-group-addon/input-group-addon.tsx
86
+ import { cn as cn4 } from "@gridui/style-utils";
87
+ import { jsx as jsx3 } from "react/jsx-runtime";
88
+ var InputGroupAddon = (props) => {
89
+ const { align = "inline-start", className, ...restProps } = props;
90
+ return /* @__PURE__ */ jsx3(
91
+ "div",
92
+ {
93
+ ...restProps,
94
+ "data-align": align,
95
+ className: cn4("gridui-input-group-addon", className)
96
+ }
97
+ );
98
+ };
99
+
100
+ // src/input-group-button/input-group-button.tsx
101
+ import { Button } from "@gridui/button";
102
+ import { cn as cn5 } from "@gridui/style-utils";
103
+ import { jsx as jsx4 } from "react/jsx-runtime";
104
+ var InputGroupButton = (props) => {
105
+ const size = useInputGroupSize() ?? "standard";
106
+ const { className, ...restProps } = props;
107
+ return /* @__PURE__ */ jsx4(
108
+ Button,
109
+ {
110
+ variant: "quiet",
111
+ size,
112
+ ...restProps,
113
+ className: cn5("gridui-input-group-button", className)
114
+ }
115
+ );
116
+ };
117
+
118
+ // src/label/style.ts
119
+ import { cn as cn6 } from "@gridui/style-utils";
56
120
  import { cva as cva2 } from "class-variance-authority";
57
- var labelStyles = cva2(cn3(
121
+ var labelStyles = cva2(cn6(
58
122
  "gridui-label",
59
123
  "gridui-u-input--inline-flex gridui-u-input--items-center gridui-u-input--gap-gridui-4 gridui-u-input--type-ui"
60
124
  ));
61
125
  var labelIconStyles = cva2("gridui-u-input--inline-flex gridui-u-input--shrink-0 gridui-u-input--text-foreground gridui-u-input--[&>svg]:size-gridui-16");
62
126
 
63
127
  // src/label/label.tsx
64
- import { cn as cn4 } from "@gridui/style-utils";
65
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
128
+ import { cn as cn7 } from "@gridui/style-utils";
129
+ import { jsx as jsx5, jsxs } from "react/jsx-runtime";
66
130
  var Label = (props) => {
67
131
  const { icon, children, className, ...restProps } = props;
68
132
  return /* @__PURE__ */ jsxs(
69
133
  "label",
70
134
  {
71
135
  ...restProps,
72
- className: cn4(labelStyles(), className),
136
+ className: cn7(labelStyles(), className),
73
137
  children: [
74
- icon && /* @__PURE__ */ jsx2(
138
+ icon && /* @__PURE__ */ jsx5(
75
139
  "span",
76
140
  {
77
141
  "aria-hidden": "true",
@@ -85,132 +149,223 @@ var Label = (props) => {
85
149
  );
86
150
  };
87
151
 
88
- // src/textarea/use-textarea-autosize.ts
89
- import { useCallback, useEffect, useLayoutEffect } from "react";
90
- var useTextareaAutosize = (ref, enabled, maxHeight) => {
91
- if (maxHeight !== void 0 && (!Number.isFinite(maxHeight) || maxHeight <= 0)) {
92
- throw new Error("Textarea maxHeight must be finite and positive.");
93
- }
94
- const resize = useCallback(() => {
95
- const element = ref.current;
96
- if (!enabled || !element || element.clientWidth === 0) {
97
- return;
98
- }
99
- const style = getComputedStyle(element);
100
- const borders = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
101
- const padding = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);
102
- element.style.height = "auto";
103
- const contentHeight = element.scrollHeight;
104
- const height = style.boxSizing === "border-box" ? contentHeight + borders : contentHeight - padding;
105
- const boundedHeight = Math.min(height, maxHeight ?? Number.POSITIVE_INFINITY);
106
- element.style.height = `${boundedHeight}px`;
107
- element.style.overflowY = height > boundedHeight ? "auto" : "hidden";
108
- }, [
109
- ref,
110
- enabled,
111
- maxHeight
112
- ]);
113
- useLayoutEffect(() => {
114
- const element = ref.current;
115
- if (!enabled || !element) {
116
- return;
152
+ // src/password-input/password-input.tsx
153
+ import { Eye, EyeOff } from "lucide-react";
154
+ import { useState } from "react";
155
+ import { jsx as jsx6, jsxs as jsxs2 } from "react/jsx-runtime";
156
+ var PasswordInput = (props) => {
157
+ const { showLabel, hideLabel, rootClassName, controlSize = "standard", ...restProps } = props;
158
+ const [
159
+ visible,
160
+ setVisible
161
+ ] = useState(false);
162
+ return /* @__PURE__ */ jsxs2(
163
+ InputGroup,
164
+ {
165
+ controlSize,
166
+ dir: restProps.dir,
167
+ className: rootClassName,
168
+ children: [
169
+ /* @__PURE__ */ jsx6(
170
+ Input,
171
+ {
172
+ ...restProps,
173
+ type: visible ? "text" : "password"
174
+ }
175
+ ),
176
+ /* @__PURE__ */ jsx6(
177
+ InputGroupAddon,
178
+ {
179
+ align: "inline-end",
180
+ children: /* @__PURE__ */ jsx6(
181
+ InputGroupButton,
182
+ {
183
+ layout: "icon",
184
+ "aria-label": visible ? hideLabel : showLabel,
185
+ disabled: restProps.disabled,
186
+ onClick: () => {
187
+ setVisible((current) => {
188
+ return !current;
189
+ });
190
+ },
191
+ children: visible ? /* @__PURE__ */ jsx6(
192
+ EyeOff,
193
+ {
194
+ "aria-hidden": "true"
195
+ }
196
+ ) : /* @__PURE__ */ jsx6(
197
+ Eye,
198
+ {
199
+ "aria-hidden": "true"
200
+ }
201
+ )
202
+ }
203
+ )
204
+ }
205
+ )
206
+ ]
117
207
  }
118
- const originalHeight = element.style.height;
119
- const originalOverflow = element.style.overflowY;
120
- return () => {
121
- element.style.height = originalHeight;
122
- element.style.overflowY = originalOverflow;
123
- };
124
- }, [
208
+ );
209
+ };
210
+
211
+ // src/search-input/search-input.tsx
212
+ import { Search, X } from "lucide-react";
213
+ import { useImperativeHandle, useRef } from "react";
214
+ import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
215
+ var SearchInput = (props) => {
216
+ const {
217
+ clearLabel,
218
+ loading = false,
219
+ loadingLabel,
220
+ rootClassName,
221
+ controlSize = "standard",
125
222
  ref,
126
- enabled
127
- ]);
128
- useLayoutEffect(() => {
129
- resize();
223
+ onValueChange,
224
+ ...restProps
225
+ } = props;
226
+ const input = useRef(null);
227
+ useImperativeHandle(ref, () => {
228
+ return input.current;
130
229
  });
131
- useEffect(() => {
132
- const element = ref.current;
133
- if (!enabled || !element) {
134
- return;
230
+ return /* @__PURE__ */ jsxs3(
231
+ InputGroup,
232
+ {
233
+ controlSize,
234
+ dir: restProps.dir,
235
+ className: rootClassName,
236
+ children: [
237
+ /* @__PURE__ */ jsx7(
238
+ Input,
239
+ {
240
+ ...restProps,
241
+ ref: input,
242
+ type: "search",
243
+ "aria-busy": loading || restProps["aria-busy"],
244
+ onValueChange: (next) => {
245
+ onValueChange?.(next);
246
+ }
247
+ }
248
+ ),
249
+ /* @__PURE__ */ jsx7(
250
+ InputGroupAddon,
251
+ {
252
+ "aria-hidden": "true",
253
+ children: /* @__PURE__ */ jsx7(
254
+ Search,
255
+ {
256
+ size: 16
257
+ }
258
+ )
259
+ }
260
+ ),
261
+ /* @__PURE__ */ jsxs3(
262
+ InputGroupAddon,
263
+ {
264
+ align: "inline-end",
265
+ children: [
266
+ loading && /* @__PURE__ */ jsx7(
267
+ "span",
268
+ {
269
+ role: "status",
270
+ children: loadingLabel
271
+ }
272
+ ),
273
+ /* @__PURE__ */ jsx7(
274
+ InputGroupButton,
275
+ {
276
+ layout: "icon",
277
+ "aria-label": clearLabel,
278
+ disabled: restProps.disabled || restProps.readOnly,
279
+ onClick: () => {
280
+ const element = input.current;
281
+ if (!element || element.matches(":disabled") || element.readOnly) {
282
+ return;
283
+ }
284
+ if (element.value !== "") {
285
+ if (restProps.value === void 0) {
286
+ element.value = "";
287
+ }
288
+ onValueChange?.("");
289
+ }
290
+ element.focus();
291
+ },
292
+ children: /* @__PURE__ */ jsx7(
293
+ X,
294
+ {
295
+ "aria-hidden": "true"
296
+ }
297
+ )
298
+ }
299
+ )
300
+ ]
301
+ }
302
+ )
303
+ ]
135
304
  }
136
- let frame = 0;
137
- let width = element.clientWidth;
138
- const schedule = () => {
139
- cancelAnimationFrame(frame);
140
- frame = requestAnimationFrame(resize);
141
- };
142
- const observer = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(() => {
143
- if (element.clientWidth !== width) {
144
- width = element.clientWidth;
145
- schedule();
146
- }
147
- });
148
- observer?.observe(element);
149
- const reset = (event) => {
150
- if (event.target === element.form) {
151
- schedule();
152
- }
153
- };
154
- const document = element.ownerDocument;
155
- document.addEventListener("reset", reset, true);
156
- return () => {
157
- cancelAnimationFrame(frame);
158
- observer?.disconnect();
159
- document.removeEventListener("reset", reset, true);
160
- };
161
- }, [
162
- ref,
163
- enabled,
164
- resize
165
- ]);
166
- return resize;
305
+ );
167
306
  };
168
307
 
169
308
  // src/textarea/textarea.tsx
170
309
  import { useScrollbars } from "@gridui/overlay";
171
- import { cn as cn5 } from "@gridui/style-utils";
172
- import { useImperativeHandle, useRef } from "react";
173
- import { jsx as jsx3 } from "react/jsx-runtime";
310
+ import { cn as cn8 } from "@gridui/style-utils";
311
+ import "react";
312
+ import { jsx as jsx8 } from "react/jsx-runtime";
174
313
  var Textarea = (props) => {
314
+ const groupSize = useInputGroupSize();
175
315
  const {
176
- controlSize = "standard",
316
+ controlSize = groupSize ?? "standard",
177
317
  className,
178
318
  onChange,
179
- onInput,
180
319
  onValueChange,
181
320
  ref,
182
321
  autoSize = false,
183
322
  maxHeight,
323
+ maxRows,
324
+ rows = 2,
184
325
  style,
185
326
  ...restProps
186
327
  } = props;
187
- const element = useRef(null);
188
- useImperativeHandle(ref, () => {
189
- return element.current;
190
- });
191
- const scrollRef = useScrollbars({ ref: element });
192
- const resize = useTextareaAutosize(element, autoSize, maxHeight);
193
- return /* @__PURE__ */ jsx3(
328
+ if (maxHeight !== void 0 && (!Number.isFinite(maxHeight) || maxHeight <= 0)) {
329
+ throw new RangeError("Textarea maxHeight must be finite and positive.");
330
+ }
331
+ if (maxRows !== void 0 && (!Number.isSafeInteger(maxRows) || maxRows < rows)) {
332
+ throw new RangeError("Textarea maxRows must be an integer at least as large as rows.");
333
+ }
334
+ if (maxHeight !== void 0 && maxRows !== void 0) {
335
+ throw new RangeError("Textarea accepts either maxRows or maxHeight, not both.");
336
+ }
337
+ const scrollRef = useScrollbars({ ref });
338
+ const sizing = {
339
+ "--_gridui-textarea-rows": rows,
340
+ "--_gridui-textarea-max-rows": maxRows,
341
+ ...style,
342
+ ...autoSize && maxHeight !== void 0 ? { maxHeight } : {}
343
+ };
344
+ return /* @__PURE__ */ jsx8(
194
345
  "textarea",
195
346
  {
196
347
  ...restProps,
197
348
  ref: scrollRef,
198
- style,
199
- onInput: (event) => {
200
- resize();
201
- onInput?.(event);
202
- },
349
+ rows,
350
+ style: sizing,
351
+ "data-autosize": autoSize || void 0,
352
+ "data-max-rows": maxRows !== void 0 || void 0,
203
353
  onChange: (event) => {
204
354
  onChange?.(event);
205
355
  onValueChange?.(event.currentTarget.value);
206
356
  },
207
- className: cn5(controlVariants({ size: controlSize }), "gridui-u-input--overflow-auto", autoSize ? "gridui-u-input--resize-none" : "gridui-u-input--resize-y", className)
357
+ className: cn8(controlVariants({ size: controlSize }), "gridui-textarea gridui-u-input--overflow-auto", groupSize && "gridui-u-input--border-0 gridui-u-input--bg-transparent", autoSize ? "gridui-u-input--resize-none gridui-u-input--min-h-(--_gridui-textarea-min-height)" : "gridui-u-input--resize-y", className)
208
358
  }
209
359
  );
210
360
  };
211
361
  export {
212
362
  Input,
363
+ InputGroup,
364
+ InputGroupAddon,
365
+ InputGroupButton,
213
366
  Label,
367
+ PasswordInput,
368
+ SearchInput,
214
369
  Textarea,
215
370
  controlVariants
216
371
  };
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/shared/style.ts", "../src/input/input.tsx", "../src/label/style.ts", "../src/label/label.tsx", "../src/textarea/use-textarea-autosize.ts", "../src/textarea/textarea.tsx"],
4
- "sourcesContent": ["/**\n * @author WMXPY\n * @package Input\n * @namespace Shared\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const controlStyles = cva(cn(\n \"gridui-control\",\n \"gridui-u-input--min-w-0 gridui-u-input--w-full gridui-u-input--box-border gridui-u-input--border gridui-u-input--border-solid gridui-u-input--border-border gridui-u-input--rounded-control gridui-u-input--text-foreground gridui-u-input--bg-background gridui-u-input--type-input\",\n \"gridui-u-input--disabled:opacity-50 gridui-u-input--disabled:cursor-not-allowed\",\n \"gridui-u-input--aria-invalid:border-danger-foreground\",\n));\n\nexport const controlStandardStyles = cva(cn(\n \"gridui-control-standard\",\n \"gridui-u-input--p-gridui-8 gridui-u-input--min-h-gridui-control\",\n));\n\nexport const controlSmallStyles = cva(cn(\n \"gridui-control-small\",\n \"gridui-u-input--py-gridui-4 gridui-u-input--px-gridui-8 gridui-u-input--min-h-gridui-control-small\",\n));\n\nexport const controlVariants = cva(controlStyles(), {\n variants: {\n size: {\n standard: controlStandardStyles(),\n small: controlSmallStyles(),\n },\n },\n defaultVariants: { size: \"standard\" },\n});\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Input\n * @description Input\n */\n\nimport { controlVariants } from \"../shared/style\";\nimport type { TextControlOptions } from \"../shared/text-control-options\";\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type InputProps = ComponentPropsWithRef<\"input\"> & TextControlOptions;\n\nexport const Input: FC<InputProps> = (props: InputProps) => {\n const {\n size,\n controlSize = \"standard\",\n className,\n onChange,\n onValueChange,\n ...restProps\n } = props;\n return (<input\n {...restProps}\n size={size}\n onChange={(event) => {\n onChange?.(event);\n onValueChange?.(event.currentTarget.value);\n }}\n className={cn(controlVariants({ size: controlSize }), className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Label\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const labelStyles = cva(cn(\n \"gridui-label\",\n \"gridui-u-input--inline-flex gridui-u-input--items-center gridui-u-input--gap-gridui-4 gridui-u-input--type-ui\",\n));\n\nexport const labelIconStyles = cva(\"gridui-u-input--inline-flex gridui-u-input--shrink-0 gridui-u-input--text-foreground gridui-u-input--[&>svg]:size-gridui-16\");\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Label\n * @description Label\n */\n\nimport { labelIconStyles, labelStyles } from \"./style\";\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC, ReactNode } from \"react\";\n\nexport type LabelProps = ComponentPropsWithRef<\"label\"> & {\n readonly icon?: ReactNode;\n};\n\nexport const Label: FC<LabelProps> = (props: LabelProps) => {\n const { icon, children, className, ...restProps } = props;\n return (<label\n {...restProps}\n className={cn(labelStyles(), className)}\n >\n {icon && (<span\n aria-hidden=\"true\"\n className={labelIconStyles()}\n >\n {icon}\n </span>)}\n {children}\n </label>);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Textarea\n * @description Use Textarea Autosize\n */\n\nimport { type RefObject, useCallback, useEffect, useLayoutEffect } from \"react\";\n\nexport const useTextareaAutosize = (ref: RefObject<HTMLTextAreaElement | null>, enabled: boolean, maxHeight?: number) => {\n if (maxHeight !== undefined && (!Number.isFinite(maxHeight) || maxHeight <= 0)) {\n throw new Error(\"Textarea maxHeight must be finite and positive.\");\n }\n const resize = useCallback(() => {\n const element = ref.current;\n if (!enabled || !element || element.clientWidth === 0) {\n return;\n }\n const style = getComputedStyle(element);\n const borders = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);\n const padding = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom);\n element.style.height = \"auto\";\n const contentHeight = element.scrollHeight;\n const height = style.boxSizing === \"border-box\" ? contentHeight + borders : contentHeight - padding;\n const boundedHeight = Math.min(height, maxHeight ?? Number.POSITIVE_INFINITY);\n element.style.height = `${boundedHeight}px`;\n element.style.overflowY = height > boundedHeight ? \"auto\" : \"hidden\";\n }, [\n ref,\n enabled,\n maxHeight,\n ]);\n useLayoutEffect(() => {\n const element = ref.current;\n if (!enabled || !element) {\n return;\n }\n const originalHeight = element.style.height;\n const originalOverflow = element.style.overflowY;\n return () => {\n element.style.height = originalHeight;\n element.style.overflowY = originalOverflow;\n };\n }, [\n ref,\n enabled,\n ]);\n useLayoutEffect(() => {\n resize();\n });\n useEffect(() => {\n const element = ref.current;\n if (!enabled || !element) {\n return;\n }\n let frame = 0;\n let width = element.clientWidth;\n const schedule = () => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(resize);\n };\n const observer = typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(() => {\n if (element.clientWidth !== width) {\n width = element.clientWidth;\n schedule();\n }\n });\n observer?.observe(element);\n // A capture listener follows the live form owner, including DOM reassociation.\n const reset = (event: Event): void => {\n if (event.target === element.form) {\n schedule();\n }\n };\n const document = element.ownerDocument;\n document.addEventListener(\"reset\", reset, true);\n return () => {\n cancelAnimationFrame(frame);\n observer?.disconnect();\n document.removeEventListener(\"reset\", reset, true);\n };\n }, [\n ref,\n enabled,\n resize,\n ]);\n return resize;\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Textarea\n * @description Textarea\n */\n\nimport { controlVariants } from \"../shared/style\";\nimport type { TextControlOptions } from \"../shared/text-control-options\";\nimport { useTextareaAutosize } from \"./use-textarea-autosize\";\nimport { useScrollbars } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport { type ComponentPropsWithRef, type FC, useImperativeHandle, useRef } from \"react\";\n\nexport type TextareaProps = ComponentPropsWithRef<\"textarea\"> & TextControlOptions & {\n readonly autoSize?: boolean;\n readonly maxHeight?: number;\n};\n\nexport const Textarea: FC<TextareaProps> = (props: TextareaProps) => {\n const {\n controlSize = \"standard\",\n className,\n onChange,\n onInput,\n onValueChange,\n ref,\n autoSize = false,\n maxHeight,\n style,\n ...restProps\n } = props;\n const element = useRef<HTMLTextAreaElement>(null);\n // React attaches the native element before assigning imperative handles.\n useImperativeHandle(ref, () => {\n return element.current!;\n });\n const scrollRef = useScrollbars({ ref: element });\n const resize = useTextareaAutosize(element, autoSize, maxHeight);\n return (<textarea\n {...restProps}\n ref={scrollRef}\n style={style}\n onInput={(event) => {\n resize();\n onInput?.(event);\n }}\n onChange={(event) => {\n onChange?.(event);\n onValueChange?.(event.currentTarget.value);\n }}\n className={cn(controlVariants({ size: controlSize }), \"gridui-u-input--overflow-auto\", autoSize ? \"gridui-u-input--resize-none\" : \"gridui-u-input--resize-y\", className)}\n />);\n};\n"],
5
- "mappings": ";AAOA,SAAS,UAAU;AACnB,SAAS,WAAW;AAEb,IAAM,gBAAgB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,wBAAwB,IAAI;AAAA,EACrC;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,qBAAqB,IAAI;AAAA,EAClC;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,kBAAkB,IAAI,cAAc,GAAG;AAAA,EAChD,UAAU;AAAA,IACN,MAAM;AAAA,MACF,UAAU,sBAAsB;AAAA,MAChC,OAAO,mBAAmB;AAAA,IAC9B;AAAA,EACJ;AAAA,EACA,iBAAiB,EAAE,MAAM,WAAW;AACxC,CAAC;;;AC1BD,SAAS,MAAAA,WAAU;AAcP;AATL,IAAM,QAAwB,CAAC,UAAsB;AACxD,QAAM;AAAA,IACF;AAAA,IACA,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACP,IAAI;AACJ,SAAQ;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ;AAAA,MACA,UAAU,CAAC,UAAU;AACjB,mBAAW,KAAK;AAChB,wBAAgB,MAAM,cAAc,KAAK;AAAA,MAC7C;AAAA,MACA,WAAWA,IAAG,gBAAgB,EAAE,MAAM,YAAY,CAAC,GAAG,SAAS;AAAA;AAAA,EACnE;AACJ;;;ACzBA,SAAS,MAAAC,WAAU;AACnB,SAAS,OAAAC,YAAW;AAEb,IAAM,cAAcA,KAAID;AAAA,EAC3B;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,kBAAkBC,KAAI,6HAA6H;;;ACPhK,SAAS,MAAAC,WAAU;AASP,SAIM,OAAAC,MAJN;AAFL,IAAM,QAAwB,CAAC,UAAsB;AACxD,QAAM,EAAE,MAAM,UAAU,WAAW,GAAG,UAAU,IAAI;AACpD,SAAQ;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ,WAAWD,IAAG,YAAY,GAAG,SAAS;AAAA,MAErC;AAAA,gBAAS,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACP,eAAY;AAAA,YACZ,WAAW,gBAAgB;AAAA,YAE1B;AAAA;AAAA,QACL;AAAA,QACC;AAAA;AAAA;AAAA,EACL;AACJ;;;ACtBA,SAAyB,aAAa,WAAW,uBAAuB;AAEjE,IAAM,sBAAsB,CAAC,KAA4C,SAAkB,cAAuB;AACrH,MAAI,cAAc,WAAc,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,IAAI;AAC5E,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACrE;AACA,QAAM,SAAS,YAAY,MAAM;AAC7B,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,WAAW,CAAC,WAAW,QAAQ,gBAAgB,GAAG;AACnD;AAAA,IACJ;AACA,UAAM,QAAQ,iBAAiB,OAAO;AACtC,UAAM,UAAU,WAAW,MAAM,cAAc,IAAI,WAAW,MAAM,iBAAiB;AACrF,UAAM,UAAU,WAAW,MAAM,UAAU,IAAI,WAAW,MAAM,aAAa;AAC7E,YAAQ,MAAM,SAAS;AACvB,UAAM,gBAAgB,QAAQ;AAC9B,UAAM,SAAS,MAAM,cAAc,eAAe,gBAAgB,UAAU,gBAAgB;AAC5F,UAAM,gBAAgB,KAAK,IAAI,QAAQ,aAAa,OAAO,iBAAiB;AAC5E,YAAQ,MAAM,SAAS,GAAG,aAAa;AACvC,YAAQ,MAAM,YAAY,SAAS,gBAAgB,SAAS;AAAA,EAChE,GAAG;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACJ,CAAC;AACD,kBAAgB,MAAM;AAClB,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,WAAW,CAAC,SAAS;AACtB;AAAA,IACJ;AACA,UAAM,iBAAiB,QAAQ,MAAM;AACrC,UAAM,mBAAmB,QAAQ,MAAM;AACvC,WAAO,MAAM;AACT,cAAQ,MAAM,SAAS;AACvB,cAAQ,MAAM,YAAY;AAAA,IAC9B;AAAA,EACJ,GAAG;AAAA,IACC;AAAA,IACA;AAAA,EACJ,CAAC;AACD,kBAAgB,MAAM;AAClB,WAAO;AAAA,EACX,CAAC;AACD,YAAU,MAAM;AACZ,UAAM,UAAU,IAAI;AACpB,QAAI,CAAC,WAAW,CAAC,SAAS;AACtB;AAAA,IACJ;AACA,QAAI,QAAQ;AACZ,QAAI,QAAQ,QAAQ;AACpB,UAAM,WAAW,MAAM;AACnB,2BAAqB,KAAK;AAC1B,cAAQ,sBAAsB,MAAM;AAAA,IACxC;AACA,UAAM,WAAW,OAAO,mBAAmB,cAAc,SAAY,IAAI,eAAe,MAAM;AAC1F,UAAI,QAAQ,gBAAgB,OAAO;AAC/B,gBAAQ,QAAQ;AAChB,iBAAS;AAAA,MACb;AAAA,IACJ,CAAC;AACD,cAAU,QAAQ,OAAO;AAEzB,UAAM,QAAQ,CAAC,UAAuB;AAClC,UAAI,MAAM,WAAW,QAAQ,MAAM;AAC/B,iBAAS;AAAA,MACb;AAAA,IACJ;AACA,UAAM,WAAW,QAAQ;AACzB,aAAS,iBAAiB,SAAS,OAAO,IAAI;AAC9C,WAAO,MAAM;AACT,2BAAqB,KAAK;AAC1B,gBAAU,WAAW;AACrB,eAAS,oBAAoB,SAAS,OAAO,IAAI;AAAA,IACrD;AAAA,EACJ,GAAG;AAAA,IACC;AAAA,IACA;AAAA,IACA;AAAA,EACJ,CAAC;AACD,SAAO;AACX;;;AC7EA,SAAS,qBAAqB;AAC9B,SAAS,MAAAC,WAAU;AACnB,SAA8C,qBAAqB,cAAc;AA2BrE,gBAAAC,YAAA;AApBL,IAAM,WAA8B,CAAC,UAAyB;AACjE,QAAM;AAAA,IACF,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACP,IAAI;AACJ,QAAM,UAAU,OAA4B,IAAI;AAEhD,sBAAoB,KAAK,MAAM;AAC3B,WAAO,QAAQ;AAAA,EACnB,CAAC;AACD,QAAM,YAAY,cAAc,EAAE,KAAK,QAAQ,CAAC;AAChD,QAAM,SAAS,oBAAoB,SAAS,UAAU,SAAS;AAC/D,SAAQ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ,KAAK;AAAA,MACL;AAAA,MACA,SAAS,CAAC,UAAU;AAChB,eAAO;AACP,kBAAU,KAAK;AAAA,MACnB;AAAA,MACA,UAAU,CAAC,UAAU;AACjB,mBAAW,KAAK;AAChB,wBAAgB,MAAM,cAAc,KAAK;AAAA,MAC7C;AAAA,MACA,WAAWD,IAAG,gBAAgB,EAAE,MAAM,YAAY,CAAC,GAAG,iCAAiC,WAAW,gCAAgC,4BAA4B,SAAS;AAAA;AAAA,EAC3K;AACJ;",
6
- "names": ["cn", "cn", "cva", "cn", "jsx", "cn", "jsx"]
3
+ "sources": ["../src/shared/input-group-context.ts", "../src/shared/style.ts", "../src/input/input.tsx", "../src/input-group/input-group.tsx", "../src/input-group-addon/input-group-addon.tsx", "../src/input-group-button/input-group-button.tsx", "../src/label/style.ts", "../src/label/label.tsx", "../src/password-input/password-input.tsx", "../src/search-input/search-input.tsx", "../src/textarea/textarea.tsx"],
4
+ "sourcesContent": ["/**\n * @author WMXPY\n * @package Input\n * @namespace Shared\n * @description Input Group Context\n */\n\nimport { createContext, useContext } from \"react\";\n\nexport const inputGroupContext = createContext<\"standard\" | \"small\" | null>(null);\nexport const useInputGroupSize = () => {\n return useContext(inputGroupContext);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Shared\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const controlStyles = cva(cn(\n \"gridui-control\",\n \"gridui-u-input--min-w-0 gridui-u-input--w-full gridui-u-input--box-border gridui-u-input--border gridui-u-input--border-solid gridui-u-input--border-border gridui-u-input--rounded-control gridui-u-input--text-foreground gridui-u-input--bg-background gridui-u-input--type-input\",\n \"gridui-u-input--disabled:opacity-50 gridui-u-input--disabled:cursor-not-allowed\",\n \"gridui-u-input--aria-invalid:border-danger-foreground\",\n));\n\nexport const controlStandardStyles = cva(cn(\n \"gridui-control-standard\",\n \"gridui-u-input--p-gridui-8 gridui-u-input--min-h-gridui-control\",\n));\n\nexport const controlSmallStyles = cva(cn(\n \"gridui-control-small\",\n \"gridui-u-input--py-gridui-4 gridui-u-input--px-gridui-8 gridui-u-input--min-h-gridui-control-small\",\n));\n\nexport const controlVariants = cva(controlStyles(), {\n variants: {\n size: {\n standard: controlStandardStyles(),\n small: controlSmallStyles(),\n },\n },\n defaultVariants: { size: \"standard\" },\n});\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Input\n * @description Input\n */\n\nimport { useInputGroupSize } from \"../shared/input-group-context\";\nimport { controlVariants } from \"../shared/style\";\nimport type { TextControlOptions } from \"../shared/text-control-options\";\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type InputProps = ComponentPropsWithRef<\"input\"> & TextControlOptions;\n\nexport const Input: FC<InputProps> = (props: InputProps) => {\n const groupSize = useInputGroupSize();\n const {\n size,\n controlSize = groupSize ?? \"standard\",\n className,\n onChange,\n onValueChange,\n ...restProps\n } = props;\n return (<input\n {...restProps}\n size={size}\n onChange={(event) => {\n onChange?.(event);\n onValueChange?.(event.currentTarget.value);\n }}\n className={cn(controlVariants({ size: controlSize }), groupSize && \"gridui-u-input--flex-1 gridui-u-input--w-0 gridui-u-input--border-0 gridui-u-input--bg-transparent\", className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace InputGroup\n * @description Input Group\n */\n\nimport { inputGroupContext } from \"../shared/input-group-context\";\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type InputGroupProps = ComponentPropsWithRef<\"div\"> & {\n readonly controlSize?: \"standard\" | \"small\";\n};\nexport const InputGroup: FC<InputGroupProps> = (props: InputGroupProps) => {\n const { controlSize = \"standard\", className, children, ...restProps } = props;\n return (<inputGroupContext.Provider\n value={controlSize}\n >\n <div\n {...restProps}\n data-control-size={controlSize}\n data-gridui-outline-target=\"\"\n className={cn(\"gridui-input-group\", className)}\n >\n {children}\n </div>\n </inputGroupContext.Provider>);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace InputGroupAddon\n * @description Input Group Addon\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC } from \"react\";\n\nexport type InputGroupAddonProps = ComponentPropsWithRef<\"div\"> & {\n readonly align?: \"inline-start\" | \"inline-end\" | \"block-start\" | \"block-end\";\n};\nexport const InputGroupAddon: FC<InputGroupAddonProps> = (props: InputGroupAddonProps) => {\n const { align = \"inline-start\", className, ...restProps } = props;\n return (<div\n {...restProps}\n data-align={align}\n className={cn(\"gridui-input-group-addon\", className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace InputGroupButton\n * @description Input Group Button\n */\n\nimport { useInputGroupSize } from \"../shared/input-group-context\";\nimport { Button, type ButtonProps } from \"@gridui/button\";\nimport { cn } from \"@gridui/style-utils\";\nimport type { FC } from \"react\";\n\nexport type InputGroupButtonProps = ButtonProps;\nexport const InputGroupButton: FC<InputGroupButtonProps> = (props: InputGroupButtonProps) => {\n const size = useInputGroupSize() ?? \"standard\";\n const { className, ...restProps } = props;\n return (<Button\n variant=\"quiet\"\n size={size}\n {...restProps}\n className={cn(\"gridui-input-group-button\", className)}\n />);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Label\n * @description Style\n */\n\nimport { cn } from \"@gridui/style-utils\";\nimport { cva } from \"class-variance-authority\";\n\nexport const labelStyles = cva(cn(\n \"gridui-label\",\n \"gridui-u-input--inline-flex gridui-u-input--items-center gridui-u-input--gap-gridui-4 gridui-u-input--type-ui\",\n));\n\nexport const labelIconStyles = cva(\"gridui-u-input--inline-flex gridui-u-input--shrink-0 gridui-u-input--text-foreground gridui-u-input--[&>svg]:size-gridui-16\");\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Label\n * @description Label\n */\n\nimport { labelIconStyles, labelStyles } from \"./style\";\nimport { cn } from \"@gridui/style-utils\";\nimport type { ComponentPropsWithRef, FC, ReactNode } from \"react\";\n\nexport type LabelProps = ComponentPropsWithRef<\"label\"> & {\n readonly icon?: ReactNode;\n};\n\nexport const Label: FC<LabelProps> = (props: LabelProps) => {\n const { icon, children, className, ...restProps } = props;\n return (<label\n {...restProps}\n className={cn(labelStyles(), className)}\n >\n {icon && (<span\n aria-hidden=\"true\"\n className={labelIconStyles()}\n >\n {icon}\n </span>)}\n {children}\n </label>);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace PasswordInput\n * @description Password Input\n */\n\nimport { Input, type InputProps } from \"../input/input\";\nimport { InputGroup } from \"../input-group/input-group\";\nimport { InputGroupAddon } from \"../input-group-addon/input-group-addon\";\nimport { InputGroupButton } from \"../input-group-button/input-group-button\";\nimport { Eye, EyeOff } from \"lucide-react\";\nimport { type FC, useState } from \"react\";\n\nexport type PasswordInputProps = Omit<InputProps, \"type\"> & {\n readonly showLabel: string;\n readonly hideLabel: string;\n readonly rootClassName?: string;\n};\nexport const PasswordInput: FC<PasswordInputProps> = (props: PasswordInputProps) => {\n const { showLabel, hideLabel, rootClassName, controlSize = \"standard\", ...restProps } = props;\n const [\n visible,\n setVisible,\n ] = useState(false);\n return (<InputGroup\n controlSize={controlSize}\n dir={restProps.dir}\n className={rootClassName}\n >\n <Input\n {...restProps}\n type={visible ? \"text\" : \"password\"}\n />\n <InputGroupAddon\n align=\"inline-end\"\n >\n <InputGroupButton\n layout=\"icon\"\n aria-label={visible ? hideLabel : showLabel}\n disabled={restProps.disabled}\n onClick={() => {\n setVisible(current => {\n return !current;\n });\n }}\n >\n {visible ? (<EyeOff\n aria-hidden=\"true\"\n />) : (<Eye\n aria-hidden=\"true\"\n />)}\n </InputGroupButton>\n </InputGroupAddon>\n </InputGroup>);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace SearchInput\n * @description Search Input\n */\n\nimport { Input, type InputProps } from \"../input/input\";\nimport { InputGroup } from \"../input-group/input-group\";\nimport { InputGroupAddon } from \"../input-group-addon/input-group-addon\";\nimport { InputGroupButton } from \"../input-group-button/input-group-button\";\nimport { Search, X } from \"lucide-react\";\nimport { type FC, useImperativeHandle, useRef } from \"react\";\n\nexport type SearchInputProps = Omit<InputProps, \"type\"> & {\n readonly clearLabel: string;\n readonly loading?: boolean;\n readonly loadingLabel?: string;\n readonly rootClassName?: string;\n};\nexport const SearchInput: FC<SearchInputProps> = (props: SearchInputProps) => {\n const { clearLabel, loading = false, loadingLabel, rootClassName, controlSize = \"standard\", ref,\n onValueChange, ...restProps } = props;\n const input = useRef<HTMLInputElement>(null);\n useImperativeHandle(ref, () => {\n return input.current!;\n });\n return (<InputGroup\n controlSize={controlSize}\n dir={restProps.dir}\n className={rootClassName}\n >\n <Input\n {...restProps}\n ref={input}\n type=\"search\"\n aria-busy={loading || restProps[\"aria-busy\"]}\n onValueChange={(next) => {\n onValueChange?.(next);\n }}\n />\n <InputGroupAddon\n aria-hidden=\"true\"\n >\n <Search\n size={16}\n />\n </InputGroupAddon>\n <InputGroupAddon\n align=\"inline-end\"\n >\n {loading && (<span\n role=\"status\"\n >\n {loadingLabel}\n </span>)}\n <InputGroupButton\n layout=\"icon\"\n aria-label={clearLabel}\n disabled={restProps.disabled || restProps.readOnly}\n onClick={() => {\n const element = input.current;\n if (!element || element.matches(\":disabled\") || element.readOnly) {\n return;\n }\n if (element.value !== \"\") {\n if (restProps.value === undefined) {\n element.value = \"\";\n }\n onValueChange?.(\"\");\n }\n element.focus();\n }}\n >\n <X\n aria-hidden=\"true\"\n />\n </InputGroupButton>\n </InputGroupAddon>\n </InputGroup>);\n};\n", "/**\n * @author WMXPY\n * @package Input\n * @namespace Textarea\n * @description Textarea\n */\n\nimport { useInputGroupSize } from \"../shared/input-group-context\";\nimport { controlVariants } from \"../shared/style\";\nimport type { TextControlOptions } from \"../shared/text-control-options\";\nimport { useScrollbars } from \"@gridui/overlay\";\nimport { cn } from \"@gridui/style-utils\";\nimport { type ComponentPropsWithRef, type CSSProperties, type FC } from \"react\";\n\nexport type TextareaProps = ComponentPropsWithRef<\"textarea\"> & TextControlOptions & {\n readonly autoSize?: boolean;\n readonly maxHeight?: number;\n readonly maxRows?: number;\n};\nexport const Textarea: FC<TextareaProps> = (props: TextareaProps) => {\n const groupSize = useInputGroupSize();\n const { controlSize = groupSize ?? \"standard\", className, onChange, onValueChange, ref, autoSize = false,\n maxHeight, maxRows, rows = 2, style, ...restProps } = props;\n if (maxHeight !== undefined && (!Number.isFinite(maxHeight) || maxHeight <= 0)) {\n throw new RangeError(\"Textarea maxHeight must be finite and positive.\");\n }\n if (maxRows !== undefined && (!Number.isSafeInteger(maxRows) || maxRows < rows)) {\n throw new RangeError(\"Textarea maxRows must be an integer at least as large as rows.\");\n }\n if (maxHeight !== undefined && maxRows !== undefined) {\n throw new RangeError(\"Textarea accepts either maxRows or maxHeight, not both.\");\n }\n const scrollRef = useScrollbars<HTMLTextAreaElement>({ ref });\n const sizing: CSSProperties & Record<`--${string}`, string | number | undefined> = {\n \"--_gridui-textarea-rows\": rows,\n \"--_gridui-textarea-max-rows\": maxRows,\n ...style,\n ...(autoSize && maxHeight !== undefined ? { maxHeight } : {}),\n };\n return (<textarea\n {...restProps}\n ref={scrollRef}\n rows={rows}\n style={sizing}\n data-autosize={autoSize || undefined}\n data-max-rows={maxRows !== undefined || undefined}\n onChange={(event) => {\n onChange?.(event);\n onValueChange?.(event.currentTarget.value);\n }}\n className={cn(controlVariants({ size: controlSize }), \"gridui-textarea gridui-u-input--overflow-auto\", groupSize && \"gridui-u-input--border-0 gridui-u-input--bg-transparent\", autoSize ? \"gridui-u-input--resize-none gridui-u-input--min-h-(--_gridui-textarea-min-height)\" : \"gridui-u-input--resize-y\", className)}\n />);\n};\n"],
5
+ "mappings": ";AAOA,SAAS,eAAe,kBAAkB;AAEnC,IAAM,oBAAoB,cAA2C,IAAI;AACzE,IAAM,oBAAoB,MAAM;AACnC,SAAO,WAAW,iBAAiB;AACvC;;;ACLA,SAAS,UAAU;AACnB,SAAS,WAAW;AAEb,IAAM,gBAAgB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,wBAAwB,IAAI;AAAA,EACrC;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,qBAAqB,IAAI;AAAA,EAClC;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,kBAAkB,IAAI,cAAc,GAAG;AAAA,EAChD,UAAU;AAAA,IACN,MAAM;AAAA,MACF,UAAU,sBAAsB;AAAA,MAChC,OAAO,mBAAmB;AAAA,IAC9B;AAAA,EACJ;AAAA,EACA,iBAAiB,EAAE,MAAM,WAAW;AACxC,CAAC;;;ACzBD,SAAS,MAAAA,WAAU;AAeP;AAVL,IAAM,QAAwB,CAAC,UAAsB;AACxD,QAAM,YAAY,kBAAkB;AACpC,QAAM;AAAA,IACF;AAAA,IACA,cAAc,aAAa;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EACP,IAAI;AACJ,SAAQ;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ;AAAA,MACA,UAAU,CAAC,UAAU;AACjB,mBAAW,KAAK;AAChB,wBAAgB,MAAM,cAAc,KAAK;AAAA,MAC7C;AAAA,MACA,WAAWA,IAAG,gBAAgB,EAAE,MAAM,YAAY,CAAC,GAAG,aAAa,sGAAsG,SAAS;AAAA;AAAA,EACtL;AACJ;;;AC1BA,SAAS,MAAAC,WAAU;AAWX,gBAAAC,YAAA;AALD,IAAM,aAAkC,CAAC,UAA2B;AACvE,QAAM,EAAE,cAAc,YAAY,WAAW,UAAU,GAAG,UAAU,IAAI;AACxE,SAAQ,gBAAAA;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACL,OAAO;AAAA,MAEP,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACI,GAAG;AAAA,UACJ,qBAAmB;AAAA,UACnB,8BAA2B;AAAA,UAC3B,WAAWD,IAAG,sBAAsB,SAAS;AAAA,UAE5C;AAAA;AAAA,MACL;AAAA;AAAA,EACJ;AACJ;;;ACrBA,SAAS,MAAAE,WAAU;AAQP,gBAAAC,YAAA;AAFL,IAAM,kBAA4C,CAAC,UAAgC;AACtF,QAAM,EAAE,QAAQ,gBAAgB,WAAW,GAAG,UAAU,IAAI;AAC5D,SAAQ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ,cAAY;AAAA,MACZ,WAAWD,IAAG,4BAA4B,SAAS;AAAA;AAAA,EACvD;AACJ;;;ACZA,SAAS,cAAgC;AACzC,SAAS,MAAAE,WAAU;AAOP,gBAAAC,YAAA;AAHL,IAAM,mBAA8C,CAAC,UAAiC;AACzF,QAAM,OAAO,kBAAkB,KAAK;AACpC,QAAM,EAAE,WAAW,GAAG,UAAU,IAAI;AACpC,SAAQ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACL,SAAQ;AAAA,MACR;AAAA,MACC,GAAG;AAAA,MACJ,WAAWD,IAAG,6BAA6B,SAAS;AAAA;AAAA,EACxD;AACJ;;;ACfA,SAAS,MAAAE,WAAU;AACnB,SAAS,OAAAC,YAAW;AAEb,IAAM,cAAcA,KAAID;AAAA,EAC3B;AAAA,EACA;AACJ,CAAC;AAEM,IAAM,kBAAkBC,KAAI,6HAA6H;;;ACPhK,SAAS,MAAAC,WAAU;AASP,SAIM,OAAAC,MAJN;AAFL,IAAM,QAAwB,CAAC,UAAsB;AACxD,QAAM,EAAE,MAAM,UAAU,WAAW,GAAG,UAAU,IAAI;AACpD,SAAQ;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ,WAAWD,IAAG,YAAY,GAAG,SAAS;AAAA,MAErC;AAAA,gBAAS,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACP,eAAY;AAAA,YACZ,WAAW,gBAAgB;AAAA,YAE1B;AAAA;AAAA,QACL;AAAA,QACC;AAAA;AAAA;AAAA,EACL;AACJ;;;AClBA,SAAS,KAAK,cAAc;AAC5B,SAAkB,gBAAgB;AAatB,SAKJ,OAAAC,MALI,QAAAC,aAAA;AANL,IAAM,gBAAwC,CAAC,UAA8B;AAChF,QAAM,EAAE,WAAW,WAAW,eAAe,cAAc,YAAY,GAAG,UAAU,IAAI;AACxF,QAAM;AAAA,IACF;AAAA,IACA;AAAA,EACJ,IAAI,SAAS,KAAK;AAClB,SAAQ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACL;AAAA,MACA,KAAK,UAAU;AAAA,MACf,WAAW;AAAA,MAEX;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACI,GAAG;AAAA,YACJ,MAAM,UAAU,SAAS;AAAA;AAAA,QAC7B;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACG,OAAM;AAAA,YAEN,0BAAAA;AAAA,cAAC;AAAA;AAAA,gBACG,QAAO;AAAA,gBACP,cAAY,UAAU,YAAY;AAAA,gBAClC,UAAU,UAAU;AAAA,gBACpB,SAAS,MAAM;AACX,6BAAW,aAAW;AAClB,2BAAO,CAAC;AAAA,kBACZ,CAAC;AAAA,gBACL;AAAA,gBAEC,oBAAW,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACT,eAAY;AAAA;AAAA,gBAChB,IAAO,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACJ,eAAY;AAAA;AAAA,gBAChB;AAAA;AAAA,YACJ;AAAA;AAAA,QACJ;AAAA;AAAA;AAAA,EACJ;AACJ;;;AC5CA,SAAS,QAAQ,SAAS;AAC1B,SAAkB,qBAAqB,cAAc;AAoB7C,gBAAAE,MAgBA,QAAAC,aAhBA;AAZD,IAAM,cAAoC,CAAC,UAA4B;AAC1E,QAAM;AAAA,IAAE;AAAA,IAAY,UAAU;AAAA,IAAO;AAAA,IAAc;AAAA,IAAe,cAAc;AAAA,IAAY;AAAA,IACxF;AAAA,IAAe,GAAG;AAAA,EAAU,IAAI;AACpC,QAAM,QAAQ,OAAyB,IAAI;AAC3C,sBAAoB,KAAK,MAAM;AAC3B,WAAO,MAAM;AAAA,EACjB,CAAC;AACD,SAAQ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACL;AAAA,MACA,KAAK,UAAU;AAAA,MACf,WAAW;AAAA,MAEX;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACI,GAAG;AAAA,YACJ,KAAK;AAAA,YACL,MAAK;AAAA,YACL,aAAW,WAAW,UAAU,WAAW;AAAA,YAC3C,eAAe,CAAC,SAAS;AACrB,8BAAgB,IAAI;AAAA,YACxB;AAAA;AAAA,QACJ;AAAA,QACA,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACG,eAAY;AAAA,YAEZ,0BAAAA;AAAA,cAAC;AAAA;AAAA,gBACG,MAAM;AAAA;AAAA,YACV;AAAA;AAAA,QACJ;AAAA,QACA,gBAAAC;AAAA,UAAC;AAAA;AAAA,YACG,OAAM;AAAA,YAEL;AAAA,yBAAY,gBAAAD;AAAA,gBAAC;AAAA;AAAA,kBACV,MAAK;AAAA,kBAEJ;AAAA;AAAA,cACL;AAAA,cACA,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACG,QAAO;AAAA,kBACP,cAAY;AAAA,kBACZ,UAAU,UAAU,YAAY,UAAU;AAAA,kBAC1C,SAAS,MAAM;AACX,0BAAM,UAAU,MAAM;AACtB,wBAAI,CAAC,WAAW,QAAQ,QAAQ,WAAW,KAAK,QAAQ,UAAU;AAC9D;AAAA,oBACJ;AACA,wBAAI,QAAQ,UAAU,IAAI;AACtB,0BAAI,UAAU,UAAU,QAAW;AAC/B,gCAAQ,QAAQ;AAAA,sBACpB;AACA,sCAAgB,EAAE;AAAA,oBACtB;AACA,4BAAQ,MAAM;AAAA,kBAClB;AAAA,kBAEA,0BAAAA;AAAA,oBAAC;AAAA;AAAA,sBACG,eAAY;AAAA;AAAA,kBAChB;AAAA;AAAA,cACJ;AAAA;AAAA;AAAA,QACJ;AAAA;AAAA;AAAA,EACJ;AACJ;;;ACtEA,SAAS,qBAAqB;AAC9B,SAAS,MAAAE,WAAU;AACnB,OAAwE;AA2B5D,gBAAAC,YAAA;AApBL,IAAM,WAA8B,CAAC,UAAyB;AACjE,QAAM,YAAY,kBAAkB;AACpC,QAAM;AAAA,IAAE,cAAc,aAAa;AAAA,IAAY;AAAA,IAAW;AAAA,IAAU;AAAA,IAAe;AAAA,IAAK,WAAW;AAAA,IAC/F;AAAA,IAAW;AAAA,IAAS,OAAO;AAAA,IAAG;AAAA,IAAO,GAAG;AAAA,EAAU,IAAI;AAC1D,MAAI,cAAc,WAAc,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,IAAI;AAC5E,UAAM,IAAI,WAAW,iDAAiD;AAAA,EAC1E;AACA,MAAI,YAAY,WAAc,CAAC,OAAO,cAAc,OAAO,KAAK,UAAU,OAAO;AAC7E,UAAM,IAAI,WAAW,gEAAgE;AAAA,EACzF;AACA,MAAI,cAAc,UAAa,YAAY,QAAW;AAClD,UAAM,IAAI,WAAW,yDAAyD;AAAA,EAClF;AACA,QAAM,YAAY,cAAmC,EAAE,IAAI,CAAC;AAC5D,QAAM,SAA6E;AAAA,IAC/E,2BAA2B;AAAA,IAC3B,+BAA+B;AAAA,IAC/B,GAAG;AAAA,IACH,GAAI,YAAY,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,EAC/D;AACA,SAAQ,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACJ,GAAG;AAAA,MACJ,KAAK;AAAA,MACL;AAAA,MACA,OAAO;AAAA,MACP,iBAAe,YAAY;AAAA,MAC3B,iBAAe,YAAY,UAAa;AAAA,MACxC,UAAU,CAAC,UAAU;AACjB,mBAAW,KAAK;AAChB,wBAAgB,MAAM,cAAc,KAAK;AAAA,MAC7C;AAAA,MACA,WAAWD,IAAG,gBAAgB,EAAE,MAAM,YAAY,CAAC,GAAG,iDAAiD,aAAa,2DAA2D,WAAW,sFAAsF,4BAA4B,SAAS;AAAA;AAAA,EACzT;AACJ;",
6
+ "names": ["cn", "cn", "jsx", "cn", "jsx", "cn", "jsx", "cn", "cva", "cn", "jsx", "jsx", "jsxs", "jsx", "jsxs", "cn", "jsx"]
7
7
  }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Input
4
+ * @namespace InputGroup
5
+ * @description Input Group
6
+ */
7
+ import type { ComponentPropsWithRef, FC } from "react";
8
+ export type InputGroupProps = ComponentPropsWithRef<"div"> & {
9
+ readonly controlSize?: "standard" | "small";
10
+ };
11
+ export declare const InputGroup: FC<InputGroupProps>;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Input
4
+ * @namespace InputGroupAddon
5
+ * @description Input Group Addon
6
+ */
7
+ import type { ComponentPropsWithRef, FC } from "react";
8
+ export type InputGroupAddonProps = ComponentPropsWithRef<"div"> & {
9
+ readonly align?: "inline-start" | "inline-end" | "block-start" | "block-end";
10
+ };
11
+ export declare const InputGroupAddon: FC<InputGroupAddonProps>;
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @author WMXPY
3
+ * @package Input
4
+ * @namespace InputGroupButton
5
+ * @description Input Group Button
6
+ */
7
+ import { type ButtonProps } from "@gridui/button";
8
+ import type { FC } from "react";
9
+ export type InputGroupButtonProps = ButtonProps;
10
+ export declare const InputGroupButton: FC<InputGroupButtonProps>;