jattac.libs.web.zest-textbox 0.2.4 → 0.2.6
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 +121 -26
- package/dist/contexts/ZestTextboxConfigContext.d.ts +6 -7
- package/dist/hooks/useZestTextboxConfig.d.ts +1 -1
- package/dist/index.d.ts +17 -14
- package/dist/index.esm.js +8 -8
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +8 -8
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +41 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ A delightful, feature-rich, and highly customizable React textbox component. Bui
|
|
|
15
15
|
- [Password Input with Visibility Toggle](#password-input-with-visibility-toggle)
|
|
16
16
|
- [Character Counter & Progress Bar](#character-counter--progress-bar)
|
|
17
17
|
- [Enhanced Numeric Input](#enhanced-numeric-input)
|
|
18
|
+
- [Custom Parser & Validator](#custom-parser--validator)
|
|
18
19
|
- [Sizing](#sizing)
|
|
19
20
|
- [Theming (Light/Dark/System)](#theming-lightdarksystem)
|
|
20
21
|
- [Multiline Textarea](#multiline-textarea)
|
|
@@ -35,6 +36,7 @@ A delightful, feature-rich, and highly customizable React textbox component. Bui
|
|
|
35
36
|
* **Password Visibility Toggle:** A crucial accessibility and usability feature for password fields.
|
|
36
37
|
* **Character Counter & Progress Bar:** Visual feedback on input length, with engaging animations as limits are approached.
|
|
37
38
|
* **Enhanced Numeric Input:** Intelligent filtering for numbers, decimals, and negative values.
|
|
39
|
+
* **Customizable Parsing & Validation:** Define how raw string input is converted to a desired type and validated, with context of the input `type`.
|
|
38
40
|
* **Engaging Animations:** Subtle, delightful micro-interactions on focus and input.
|
|
39
41
|
* **Accessible:** Built with `rem` units and best practices for inclusivity.
|
|
40
42
|
* **Centralized Configuration:** Easily manage default behaviors and styles across your application using React Context.
|
|
@@ -53,7 +55,7 @@ Get started with `ZestTextbox` in seconds. It behaves just like a standard HTML
|
|
|
53
55
|
|
|
54
56
|
```jsx
|
|
55
57
|
import React from 'react';
|
|
56
|
-
import
|
|
58
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
57
59
|
|
|
58
60
|
const App = () => {
|
|
59
61
|
return (
|
|
@@ -76,37 +78,41 @@ export default App;
|
|
|
76
78
|
| `zest` | `ZestProps` | `undefined` | An object containing all custom configurations and behaviors specific to the ZestTextbox component. See `ZestProps` interface for details below. |
|
|
77
79
|
| `className` | `string` | `""` | A custom CSS class to apply to the main textbox element. |
|
|
78
80
|
| `maxLength` | `number` | `undefined` | The maximum number of characters allowed. Enables the character counter and progress bar. |
|
|
79
|
-
| `type` | `
|
|
81
|
+
| `type` | `HtmlInputType` | `'text'` | The type of the input element. All standard HTML input types are supported. Special handling is applied for `password` and `number`. |
|
|
80
82
|
|
|
81
83
|
### `ZestProps` Interface Details
|
|
82
84
|
|
|
83
85
|
The `zest` prop is an object that encapsulates all the unique features of `ZestTextbox`. Its properties can accept primitive values, functions, or asynchronous functions (`ZestConfigValue<T>`) for dynamic configuration, especially useful with [Centralized Configuration](#centralized-configuration).
|
|
84
86
|
|
|
85
87
|
```typescript
|
|
86
|
-
import { ZestTextboxSize, ZestConfigValue, HelperTextConfig } from 'jattac.libs.web.zest-textbox';
|
|
88
|
+
import { ZestTextboxSize, ZestConfigValue, HelperTextConfig, InputParser, InputValidator, HtmlInputType } from 'jattac.libs.web.zest-textbox';
|
|
87
89
|
|
|
88
90
|
interface ZestProps {
|
|
89
91
|
helperTextConfig?: ZestConfigValue<HelperTextConfig>;
|
|
90
|
-
onTextChanged?: (value:
|
|
92
|
+
onTextChanged?: <T>(value: T | undefined) => void; // Callback for parsed & validated text changes
|
|
91
93
|
zSize?: ZestConfigValue<ZestTextboxSize>; // "sm" | "md" | "lg"
|
|
92
94
|
stretch?: ZestConfigValue<boolean>; // Full width
|
|
93
95
|
showProgressBar?: ZestConfigValue<boolean>; // Display character progress bar
|
|
94
96
|
animatedCounter?: ZestConfigValue<boolean>; // Counter color changes
|
|
95
97
|
theme?: ZestConfigValue<"light" | "dark" | "system">; // Color scheme
|
|
96
98
|
isMultiline?: ZestConfigValue<boolean>; // Render as <textarea>
|
|
99
|
+
parser?: ZestConfigValue<InputParser<any>>; // Custom parser function
|
|
100
|
+
validator?: ZestConfigValue<InputValidator<any>>; // Custom validator function
|
|
97
101
|
}
|
|
98
102
|
```
|
|
99
103
|
|
|
100
104
|
| Property | Type (`ZestConfigValue<T>`) | Default | Description |
|
|
101
105
|
| ----------------- | --------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
|
|
102
106
|
| `helperTextConfig`| `ZestConfigValue<HelperTextConfig>` | `undefined` | Configuration for dynamic helper text displayed below the input. Can be an object, a function returning an object, or a promise of an object. |
|
|
103
|
-
| `onTextChanged` |
|
|
107
|
+
| `onTextChanged` | `<T>(value: T | undefined) => void` | `undefined` | A callback function that is invoked whenever the textbox's value changes. Provides the *parsed and validated* value. `T` is the type returned by the `parser`. |
|
|
104
108
|
| `zSize` | `ZestConfigValue<"sm" | "md" | "lg">` | `'md'` | Sets the size of the textbox, affecting padding and font size. |
|
|
105
109
|
| `stretch` | `ZestConfigValue<boolean>` | `false` | If `true`, the component will stretch to the full width of its container. |
|
|
106
110
|
| `showProgressBar` | `ZestConfigValue<boolean>` | `false` | If `true`, a progress bar indicating character count vs. `maxLength` will be displayed. Requires `maxLength` to be set. |
|
|
107
111
|
| `animatedCounter` | `ZestConfigValue<boolean>` | `false` | If `true`, the character counter will change color as it approaches the `maxLength`. Requires `maxLength` to be set. |
|
|
108
112
|
| `theme` | `ZestConfigValue<"light" | "dark" | "system">` | `'system'` | Controls the component's color scheme. `'system'` automatically detects the OS/browser preference. |
|
|
109
113
|
| `isMultiline` | `ZestConfigValue<boolean>` | `false` | If `true`, the component will render as a `<textarea>`. If `false` or undefined, it renders as an `<input>`. |
|
|
114
|
+
| `parser` | `ZestConfigValue<InputParser<any>>` | `undefined` | A function to parse the raw string input into a desired type. Receives `(value: string, inputType?: HtmlInputType)`. Returns `undefined` if parsing fails. Default parsers are provided for `type="number"`. |
|
|
115
|
+
| `validator` | `ZestConfigValue<InputValidator<any>>` | `undefined` | A function to validate the parsed value. Receives `(value: T | undefined, inputType?: HtmlInputType)`. Returns `true` for valid, or a string error message for invalid. Default validators are provided for `type="number"`. |
|
|
110
116
|
|
|
111
117
|
## Feature Examples
|
|
112
118
|
|
|
@@ -118,7 +124,7 @@ Simply set the `type` prop to `"password"` to enable the built-in visibility tog
|
|
|
118
124
|
|
|
119
125
|
```jsx
|
|
120
126
|
import React from 'react';
|
|
121
|
-
import
|
|
127
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
122
128
|
|
|
123
129
|
const PasswordExample = () => {
|
|
124
130
|
return (
|
|
@@ -138,7 +144,7 @@ Enable the character counter with `maxLength` and add a visual progress bar and
|
|
|
138
144
|
|
|
139
145
|
```jsx
|
|
140
146
|
import React from 'react';
|
|
141
|
-
import
|
|
147
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
142
148
|
|
|
143
149
|
const CounterExample = () => {
|
|
144
150
|
const [text, setText] = React.useState('');
|
|
@@ -164,21 +170,33 @@ export default CounterExample;
|
|
|
164
170
|
|
|
165
171
|
### Enhanced Numeric Input
|
|
166
172
|
|
|
167
|
-
Set `type="number"` for intelligent filtering that allows only digits, a single decimal point, and a single leading negative sign.
|
|
173
|
+
Set `type="number"` for intelligent filtering that allows only digits, a single decimal point, and a single leading negative sign. The `onTextChanged` callback will now receive a `number | undefined`.
|
|
168
174
|
|
|
169
175
|
```jsx
|
|
170
176
|
import React from 'react';
|
|
171
|
-
import
|
|
177
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
172
178
|
|
|
173
179
|
const NumericExample = () => {
|
|
180
|
+
const [age, setAge] = React.useState<number | undefined>(undefined);
|
|
181
|
+
const [price, setPrice] = React.useState<number | undefined>(undefined);
|
|
182
|
+
|
|
174
183
|
return (
|
|
175
184
|
<div style={{ padding: '2rem', maxWidth: '400px', margin: '0 auto' }}>
|
|
176
|
-
<h2>Numeric Input</h2>
|
|
177
|
-
<
|
|
178
|
-
<
|
|
179
|
-
|
|
185
|
+
<h2>Enhanced Numeric Input</h2>
|
|
186
|
+
<p>Age: {age === undefined ? 'N/A' : age}</p>
|
|
187
|
+
<ZestTextbox
|
|
188
|
+
type="number"
|
|
189
|
+
placeholder="Enter your age"
|
|
190
|
+
onTextChanged={setAge}
|
|
191
|
+
/>
|
|
180
192
|
<br /><br />
|
|
181
|
-
<
|
|
193
|
+
<p>Price: {price === undefined ? 'N/A' : `$${price.toFixed(2)}`}</p>
|
|
194
|
+
<ZestTextbox
|
|
195
|
+
type="number"
|
|
196
|
+
placeholder="Enter a price"
|
|
197
|
+
onTextChanged={setPrice}
|
|
198
|
+
defaultValue="19.99"
|
|
199
|
+
/>
|
|
182
200
|
</div>
|
|
183
201
|
);
|
|
184
202
|
};
|
|
@@ -186,13 +204,66 @@ const NumericExample = () => {
|
|
|
186
204
|
export default NumericExample;
|
|
187
205
|
```
|
|
188
206
|
|
|
207
|
+
### Custom Parser & Validator
|
|
208
|
+
|
|
209
|
+
Define your own `parser` and `validator` functions to handle specific input requirements. The `inputType` is passed to these functions for context. Here, we'll create a custom parser and validator for a "positive integer" number input.
|
|
210
|
+
|
|
211
|
+
```jsx
|
|
212
|
+
import React from 'react';
|
|
213
|
+
import ZestTextbox, { InputParser, InputValidator, HtmlInputType } from 'jattac.libs.web.zest-textbox';
|
|
214
|
+
|
|
215
|
+
// Custom parser for positive integers
|
|
216
|
+
const positiveIntegerParser: InputParser<number> = (value: string, inputType?: HtmlInputType) => {
|
|
217
|
+
if (inputType === 'number') {
|
|
218
|
+
const parsed = parseInt(value, 10);
|
|
219
|
+
return isNaN(parsed) ? undefined : parsed;
|
|
220
|
+
}
|
|
221
|
+
return undefined;
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
// Custom validator for positive integers
|
|
225
|
+
const positiveIntegerValidator: InputValidator<number> = (parsedValue: number | undefined, inputType?: HtmlInputType) => {
|
|
226
|
+
if (inputType === 'number') {
|
|
227
|
+
if (parsedValue === undefined) {
|
|
228
|
+
return "Please enter a valid integer.";
|
|
229
|
+
}
|
|
230
|
+
if (parsedValue <= 0) {
|
|
231
|
+
return "Value must be a positive integer.";
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return true;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const CustomNumericParserValidatorExample = () => {
|
|
238
|
+
const [quantity, setQuantity] = React.useState<number | undefined>(undefined);
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<div style={{ padding: '2rem', maxWidth: '400px', margin: '0 auto' }}>
|
|
242
|
+
<h2>Custom Numeric Parser & Validator</h2>
|
|
243
|
+
<p>Quantity: {quantity === undefined ? 'N/A' : quantity}</p>
|
|
244
|
+
<ZestTextbox
|
|
245
|
+
type="number"
|
|
246
|
+
placeholder="Enter positive quantity"
|
|
247
|
+
onTextChanged={setQuantity}
|
|
248
|
+
zest={{
|
|
249
|
+
parser: positiveIntegerParser,
|
|
250
|
+
validator: positiveIntegerValidator,
|
|
251
|
+
}}
|
|
252
|
+
/>
|
|
253
|
+
</div>
|
|
254
|
+
);
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
export default CustomNumericParserValidatorExample;
|
|
258
|
+
```
|
|
259
|
+
|
|
189
260
|
### Sizing
|
|
190
261
|
|
|
191
262
|
Control the size of the textbox with the `zSize` property within the `zest` prop. Options are `"sm"`, `"md"` (default), and `"lg"`.
|
|
192
263
|
|
|
193
264
|
```jsx
|
|
194
265
|
import React from 'react';
|
|
195
|
-
import
|
|
266
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
196
267
|
|
|
197
268
|
const SizingExample = () => {
|
|
198
269
|
return (
|
|
@@ -216,7 +287,7 @@ Force the component into a specific theme or let it adapt to the user's system p
|
|
|
216
287
|
|
|
217
288
|
```jsx
|
|
218
289
|
import React from 'react';
|
|
219
|
-
import
|
|
290
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
220
291
|
|
|
221
292
|
const ThemingExample = () => {
|
|
222
293
|
return (
|
|
@@ -240,7 +311,7 @@ Render `ZestTextbox` as a `<textarea>` by setting `isMultiline` to `true` in the
|
|
|
240
311
|
|
|
241
312
|
```jsx
|
|
242
313
|
import React from 'react';
|
|
243
|
-
import
|
|
314
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
244
315
|
|
|
245
316
|
const MultilineExample = () => {
|
|
246
317
|
return (
|
|
@@ -264,7 +335,7 @@ Provide dynamic helper text below the input using `helperTextConfig`. You can fo
|
|
|
264
335
|
|
|
265
336
|
```jsx
|
|
266
337
|
import React from 'react';
|
|
267
|
-
import
|
|
338
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
268
339
|
|
|
269
340
|
const HelperTextExample = () => {
|
|
270
341
|
const [value, setValue] = React.useState('');
|
|
@@ -321,7 +392,7 @@ Make the textbox take up the full width of its parent container by setting `stre
|
|
|
321
392
|
|
|
322
393
|
```jsx
|
|
323
394
|
import React from 'react';
|
|
324
|
-
import
|
|
395
|
+
import ZestTextbox from 'jattac.libs.web.zest-textbox';
|
|
325
396
|
|
|
326
397
|
const StretchExample = () => {
|
|
327
398
|
return (
|
|
@@ -346,11 +417,30 @@ To maintain consistency and reduce boilerplate, `ZestTextbox` supports centraliz
|
|
|
346
417
|
|
|
347
418
|
### Usage Example
|
|
348
419
|
|
|
349
|
-
Here's how you can set up a global theme and size, and then override it for a specific component
|
|
420
|
+
Here's how you can set up a global theme and size, and then override it for a specific component. You can also define global default parsers and validators here.
|
|
350
421
|
|
|
351
422
|
```jsx
|
|
352
423
|
import React from 'react';
|
|
353
|
-
import
|
|
424
|
+
import ZestTextbox, { ZestTextboxConfigProvider, InputParser, InputValidator, HtmlInputType } from 'jattac.libs.web.zest-textbox';
|
|
425
|
+
|
|
426
|
+
// Global default parser for positive numbers
|
|
427
|
+
const globalPositiveNumberParser: InputParser<number> = (value: string, inputType?: HtmlInputType) => {
|
|
428
|
+
if (inputType === 'number') {
|
|
429
|
+
const parsed = parseFloat(value);
|
|
430
|
+
return isNaN(parsed) || parsed <= 0 ? undefined : parsed;
|
|
431
|
+
}
|
|
432
|
+
return undefined;
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
// Global default validator for positive numbers
|
|
436
|
+
const globalPositiveNumberValidator: InputValidator<number> = (parsedValue: number | undefined, inputType?: HtmlInputType) => {
|
|
437
|
+
if (inputType === 'number') {
|
|
438
|
+
if (parsedValue === undefined) {
|
|
439
|
+
return "Please enter a valid positive number.";
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return true;
|
|
443
|
+
};
|
|
354
444
|
|
|
355
445
|
const AppWithCentralConfig = () => {
|
|
356
446
|
// Define your global default ZestProps
|
|
@@ -358,15 +448,20 @@ const AppWithCentralConfig = () => {
|
|
|
358
448
|
theme: "dark", // All textboxes will be dark by default
|
|
359
449
|
zSize: () => "lg", // All textboxes will be large by default (function example)
|
|
360
450
|
animatedCounter: Promise.resolve(true), // Async example
|
|
451
|
+
parser: globalPositiveNumberParser, // Apply global positive number parser
|
|
452
|
+
validator: globalPositiveNumberValidator, // Apply global positive number validator
|
|
361
453
|
};
|
|
362
454
|
|
|
455
|
+
const [amount, setAmount] = React.useState<number | undefined>(undefined);
|
|
456
|
+
|
|
363
457
|
return (
|
|
364
458
|
<ZestTextboxConfigProvider value={globalDefaultZestProps}>
|
|
365
459
|
<div style={{ padding: '2rem', maxWidth: '600px', margin: '0 auto' }}>
|
|
366
460
|
<h1>Centralized Configuration Example</h1>
|
|
367
461
|
|
|
368
462
|
<h3>Default ZestTextbox (inherits global defaults)</h3>
|
|
369
|
-
<ZestTextbox placeholder="I'm large, dark, and
|
|
463
|
+
<ZestTextbox placeholder="I'm large, dark, animated, and expect positive numbers!" type="number" onTextChanged={setAmount} />
|
|
464
|
+
<p>Amount: {amount === undefined ? 'N/A' : amount}</p>
|
|
370
465
|
<br /><br />
|
|
371
466
|
|
|
372
467
|
<h3>Overridden ZestTextbox (component props take precedence)</h3>
|
|
@@ -377,7 +472,7 @@ const AppWithCentralConfig = () => {
|
|
|
377
472
|
<br /><br />
|
|
378
473
|
|
|
379
474
|
<h3>Another Default ZestTextbox</h3>
|
|
380
|
-
<ZestTextbox placeholder="I'm also large, dark, and
|
|
475
|
+
<ZestTextbox placeholder="I'm also large, dark, animated, and expect positive numbers!" type="number" />
|
|
381
476
|
</div>
|
|
382
477
|
</ZestTextboxConfigProvider>
|
|
383
478
|
);
|
|
@@ -399,10 +494,10 @@ The resolution order for `ZestProps` is as follows:
|
|
|
399
494
|
The `ZestTextbox` component has been refactored internally for improved maintainability, readability, and reusability. Its core logic is now distributed across several custom React hooks and smaller, focused sub-components. This internal restructuring does **not** introduce any breaking changes to the public API.
|
|
400
495
|
|
|
401
496
|
The internal structure now includes:
|
|
402
|
-
* `UI/hooks/`: Contains custom React hooks (e.g., `useThemeDetector`, `usePasswordVisibility`, `useCharacterCounter`, `useHelperText`, `useZestTextboxConfig`).
|
|
497
|
+
* `UI/hooks/`: Contains custom React hooks (e.g., `useThemeDetector`, `usePasswordVisibility`, `useCharacterCounter`, `useHelperText`, `useZestTextboxConfig`, `useParsedAndValidatedInput`).
|
|
403
498
|
* `UI/components/`: Contains smaller, focused UI components (e.g., `PasswordToggleButton`, `CharacterCounter`, `ProgressBar`, `HelperTextDisplay`).
|
|
404
|
-
* `UI/utils/`: Contains utility functions (e.g., `numericInputFilter`).
|
|
405
|
-
* `UI/types.ts`: Defines shared TypeScript interfaces and types.
|
|
499
|
+
* `UI/utils/`: Contains utility functions (e.g., `numericInputFilter`, `defaultParsersAndValidators`).
|
|
500
|
+
* `UI/types.ts`: Defines shared TypeScript interfaces and types (e.g., `HtmlInputType`, `InputParser`, `InputValidator`, `ZestConfigValue`, `ResolvedZestProps`).
|
|
406
501
|
* `UI/contexts/`: Contains React Contexts and Providers (e.g., `ZestTextboxConfigContext`, `ZestTextboxConfigProvider`).
|
|
407
502
|
|
|
408
503
|
## Breaking Changes
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import React, { ReactNode } from "react";
|
|
2
2
|
import { ZestProps } from "../types";
|
|
3
|
-
interface
|
|
4
|
-
defaultZestProps: ZestProps;
|
|
5
|
-
}
|
|
6
|
-
interface ZestTextboxConfigProviderProps {
|
|
3
|
+
interface ZestTextboxConfigProviderProps<T = string> {
|
|
7
4
|
children: ReactNode;
|
|
8
|
-
value?: ZestProps
|
|
5
|
+
value?: ZestProps<T>;
|
|
9
6
|
}
|
|
10
|
-
export declare const ZestTextboxConfigProvider: React.FC<ZestTextboxConfigProviderProps
|
|
11
|
-
export declare const useZestTextboxConfig: () =>
|
|
7
|
+
export declare const ZestTextboxConfigProvider: React.FC<ZestTextboxConfigProviderProps<any>>;
|
|
8
|
+
export declare const useZestTextboxConfig: <T = string>() => {
|
|
9
|
+
defaultZestProps: ZestProps<T>;
|
|
10
|
+
};
|
|
12
11
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { ZestProps, ResolvedZestProps, HtmlInputType } from "../types";
|
|
2
|
-
export declare const useZestTextboxConfig: (componentZestProps: ZestProps | undefined, inputType?: HtmlInputType) => ResolvedZestProps
|
|
2
|
+
export declare const useZestTextboxConfig: <T = string>(componentZestProps: ZestProps<T> | undefined, inputType?: HtmlInputType) => ResolvedZestProps<T>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
1
2
|
import React, { ReactNode } from 'react';
|
|
2
3
|
|
|
3
4
|
type ZestTextboxSize = "sm" | "md" | "lg";
|
|
@@ -27,7 +28,7 @@ interface HelperTextConfig {
|
|
|
27
28
|
*/
|
|
28
29
|
className?: string;
|
|
29
30
|
}
|
|
30
|
-
interface ZestProps {
|
|
31
|
+
interface ZestProps<T = string> {
|
|
31
32
|
/**
|
|
32
33
|
* An object to configure the dynamic helper text displayed below the input.
|
|
33
34
|
* @see HelperTextConfig
|
|
@@ -38,7 +39,7 @@ interface ZestProps {
|
|
|
38
39
|
* This is a convenience prop to avoid using `event.target.value` and manual parsing/validation.
|
|
39
40
|
* @param value The current parsed and validated value of the input, or `undefined` if parsing failed.
|
|
40
41
|
*/
|
|
41
|
-
onTextChanged?:
|
|
42
|
+
onTextChanged?: (value: T | undefined) => void;
|
|
42
43
|
/**
|
|
43
44
|
* Sets the size of the textbox, affecting padding and font size.
|
|
44
45
|
* @default 'md'
|
|
@@ -77,21 +78,20 @@ interface ZestProps {
|
|
|
77
78
|
* A function to parse the raw string input into a desired type.
|
|
78
79
|
* Returns `undefined` if parsing fails.
|
|
79
80
|
*/
|
|
80
|
-
parser?: ZestConfigValue<InputParser<
|
|
81
|
+
parser?: ZestConfigValue<InputParser<T>>;
|
|
81
82
|
/**
|
|
82
83
|
* A function to validate the parsed value.
|
|
83
84
|
* Returns `true` for valid, or a string error message for invalid.
|
|
84
85
|
*/
|
|
85
|
-
validator?: ZestConfigValue<InputValidator<
|
|
86
|
+
validator?: ZestConfigValue<InputValidator<T>>;
|
|
86
87
|
}
|
|
87
|
-
|
|
88
|
-
type SharedProps = {
|
|
88
|
+
type SharedProps<T> = {
|
|
89
89
|
/**
|
|
90
90
|
* An object containing all custom configurations and behaviors specific to the ZestTextbox component.
|
|
91
91
|
* This encapsulates all non-native HTML input/textarea props for better discoverability and DX.
|
|
92
92
|
* @see ZestProps
|
|
93
93
|
*/
|
|
94
|
-
zest?: ZestProps
|
|
94
|
+
zest?: ZestProps<T>;
|
|
95
95
|
/**
|
|
96
96
|
* A custom CSS class to apply to the main textbox element.
|
|
97
97
|
*/
|
|
@@ -108,14 +108,17 @@ type SharedProps = {
|
|
|
108
108
|
*/
|
|
109
109
|
type?: HtmlInputType;
|
|
110
110
|
};
|
|
111
|
-
type InputOnlyProps = SharedProps &
|
|
111
|
+
type InputOnlyProps<T> = SharedProps<T> & // Made InputOnlyProps generic
|
|
112
|
+
Omit<React.InputHTMLAttributes<HTMLInputElement>, "size" | "onChange"> & {
|
|
112
113
|
onChange?: React.ChangeEventHandler<HTMLInputElement>;
|
|
113
114
|
};
|
|
114
|
-
type TextareaOnlyProps = SharedProps &
|
|
115
|
+
type TextareaOnlyProps<T> = SharedProps<T> & // Made TextareaOnlyProps generic
|
|
116
|
+
Omit<React.TextareaHTMLAttributes<HTMLTextAreaElement>, "onChange"> & {
|
|
115
117
|
onChange?: React.ChangeEventHandler<HTMLTextAreaElement>;
|
|
116
118
|
};
|
|
117
|
-
type ZestTextboxProps = InputOnlyProps | TextareaOnlyProps
|
|
118
|
-
|
|
119
|
+
type ZestTextboxProps<T = string> = InputOnlyProps<T> | TextareaOnlyProps<T>;
|
|
120
|
+
|
|
121
|
+
declare const ZestTextbox: <T = string>(props: ZestTextboxProps<T>) => react_jsx_runtime.JSX.Element;
|
|
119
122
|
|
|
120
123
|
interface PasswordToggleButtonProps {
|
|
121
124
|
isPassword: boolean;
|
|
@@ -146,11 +149,11 @@ interface HelperTextDisplayProps {
|
|
|
146
149
|
}
|
|
147
150
|
declare const HelperTextDisplay: React.FC<HelperTextDisplayProps>;
|
|
148
151
|
|
|
149
|
-
interface ZestTextboxConfigProviderProps {
|
|
152
|
+
interface ZestTextboxConfigProviderProps<T = string> {
|
|
150
153
|
children: ReactNode;
|
|
151
|
-
value?: ZestProps
|
|
154
|
+
value?: ZestProps<T>;
|
|
152
155
|
}
|
|
153
|
-
declare const ZestTextboxConfigProvider: React.FC<ZestTextboxConfigProviderProps
|
|
156
|
+
declare const ZestTextboxConfigProvider: React.FC<ZestTextboxConfigProviderProps<any>>;
|
|
154
157
|
|
|
155
158
|
export { CharacterCounter, HelperTextDisplay, PasswordToggleButton, ProgressBar, ZestTextbox, ZestTextboxConfigProvider };
|
|
156
159
|
export type { HelperTextConfig, ZestProps, ZestTextboxSize };
|
package/dist/index.esm.js
CHANGED
|
@@ -247,9 +247,9 @@ var useZestTextboxConfig$1 = function () {
|
|
|
247
247
|
if (context === undefined) {
|
|
248
248
|
// This error will be caught by the useZestTextboxConfig hook in ZestTextbox.tsx
|
|
249
249
|
// if the component is used outside of a provider.
|
|
250
|
-
return { defaultZestProps: {} };
|
|
250
|
+
return { defaultZestProps: {} }; // Cast to generic T
|
|
251
251
|
}
|
|
252
|
-
return context;
|
|
252
|
+
return context; // Cast to generic T
|
|
253
253
|
};
|
|
254
254
|
|
|
255
255
|
var defaultNumberParser = function (value, inputType) {
|
|
@@ -311,21 +311,21 @@ var defaultResolvedZestProps = {
|
|
|
311
311
|
validator: undefined,
|
|
312
312
|
};
|
|
313
313
|
var useZestTextboxConfig = function (componentZestProps, inputType) {
|
|
314
|
-
var contextDefaultZestProps = useZestTextboxConfig$1().defaultZestProps;
|
|
315
|
-
var _a = useState(defaultResolvedZestProps), resolvedZestProps = _a[0], setResolvedZestProps = _a[1];
|
|
314
|
+
var contextDefaultZestProps = useZestTextboxConfig$1().defaultZestProps; // Pass generic T
|
|
315
|
+
var _a = useState(defaultResolvedZestProps), resolvedZestProps = _a[0], setResolvedZestProps = _a[1]; // Cast to generic type
|
|
316
316
|
// Memoize the merged props to avoid unnecessary re-renders
|
|
317
317
|
var mergedZestProps = useMemo(function () {
|
|
318
318
|
// Start with hardcoded defaults
|
|
319
|
-
var currentMergedProps = __assign({}, defaultResolvedZestProps);
|
|
319
|
+
var currentMergedProps = __assign({}, defaultResolvedZestProps); // Cast
|
|
320
320
|
// Apply context defaults
|
|
321
|
-
currentMergedProps = __assign(__assign({}, currentMergedProps), contextDefaultZestProps);
|
|
321
|
+
currentMergedProps = __assign(__assign({}, currentMergedProps), contextDefaultZestProps); // No longer need cast here
|
|
322
322
|
// Apply type-specific defaults if not already overridden by context
|
|
323
323
|
if (inputType === "number") {
|
|
324
324
|
if (currentMergedProps.parser === undefined) {
|
|
325
|
-
currentMergedProps.parser = defaultNumberParser;
|
|
325
|
+
currentMergedProps.parser = defaultNumberParser; // Cast
|
|
326
326
|
}
|
|
327
327
|
if (currentMergedProps.validator === undefined) {
|
|
328
|
-
currentMergedProps.validator = defaultNumberValidator;
|
|
328
|
+
currentMergedProps.validator = defaultNumberValidator; // Cast
|
|
329
329
|
}
|
|
330
330
|
}
|
|
331
331
|
// Apply component-level props (highest precedence)
|