@fvc/input 3.0.1 → 3.0.2-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997
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 +432 -0
- package/package.json +14 -4
package/README.md
ADDED
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
# @fvc/input
|
|
2
|
+
|
|
3
|
+
`@fvc/input` provides FE-VIS styled input primitives on top of Ant Design. It keeps the Ant Design input API familiar while adding the design-system behavior used across FE-VIS applications: labels, required markers, error messaging, custom clear icons, prefix/suffix handling, value transforms, and masked input support.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bun add @fvc/input
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Peer Dependencies
|
|
12
|
+
|
|
13
|
+
The package expects these dependencies to be available in the consuming application:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
bun add react antd antd-mask-input @fvc/icons @fvc/utils
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Import
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { Input } from '@fvc/input';
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Quick Start
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { useState } from 'react';
|
|
29
|
+
import { Input } from '@fvc/input';
|
|
30
|
+
|
|
31
|
+
export function AccountForm() {
|
|
32
|
+
const [username, setUsername] = useState('');
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<Input
|
|
36
|
+
name="username"
|
|
37
|
+
label="Username"
|
|
38
|
+
placeholder="Enter username"
|
|
39
|
+
value={username}
|
|
40
|
+
onChange={(event) => setUsername(event.target.value)}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Components
|
|
47
|
+
|
|
48
|
+
| Component | Use case |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `Input` | Standard text, number, email, telephone, or URL input. |
|
|
51
|
+
| `Input.Textarea` | Multi-line text entry. |
|
|
52
|
+
| `Input.Search` | Search input with optional Ant Design search button behavior. |
|
|
53
|
+
| `Input.Password` | Password input with Ant Design visibility toggle behavior. |
|
|
54
|
+
| `Input.Masked` | Masked input powered by `antd-mask-input`. |
|
|
55
|
+
|
|
56
|
+
All variants share the FE-VIS input styling and support the common props where applicable.
|
|
57
|
+
|
|
58
|
+
## Common Usage
|
|
59
|
+
|
|
60
|
+
### Label and Required Marker
|
|
61
|
+
|
|
62
|
+
Use `label` to render the FE-VIS label above the field. Add `withAsterisk` when the field is required.
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
<Input
|
|
66
|
+
name="email"
|
|
67
|
+
label="Email"
|
|
68
|
+
withAsterisk
|
|
69
|
+
placeholder="name@example.com"
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Error State
|
|
74
|
+
|
|
75
|
+
`error` can be a string or a boolean.
|
|
76
|
+
|
|
77
|
+
| Value | Behavior |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| `string` | Applies error styling and renders the message below the field. |
|
|
80
|
+
| `true` | Applies error styling without rendering a message. |
|
|
81
|
+
| `false` or `undefined` | Uses the default state. |
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
<Input
|
|
85
|
+
name="email"
|
|
86
|
+
label="Email"
|
|
87
|
+
error="Invalid email address"
|
|
88
|
+
placeholder="name@example.com"
|
|
89
|
+
/>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Controlled and Uncontrolled Inputs
|
|
93
|
+
|
|
94
|
+
Use `value` and `onChange` for controlled fields:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<Input
|
|
98
|
+
name="tin"
|
|
99
|
+
label="TIN"
|
|
100
|
+
value={tin}
|
|
101
|
+
onChange={(event) => setTin(event.target.value)}
|
|
102
|
+
/>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Use `defaultValue` when the field does not need to be controlled by React state:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
<Input
|
|
109
|
+
name="country"
|
|
110
|
+
label="Country"
|
|
111
|
+
defaultValue="Azerbaijan"
|
|
112
|
+
/>
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Prefix and Suffix
|
|
116
|
+
|
|
117
|
+
Use `prefix` and `suffix` for compact adornments such as currency, units, or static hints.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
<Input
|
|
121
|
+
name="price"
|
|
122
|
+
label="Price"
|
|
123
|
+
prefix="$"
|
|
124
|
+
suffix="USD"
|
|
125
|
+
placeholder="Enter amount"
|
|
126
|
+
/>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`suffixType` controls suffix positioning.
|
|
130
|
+
|
|
131
|
+
| `suffixType` | Behavior |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| `fixed` | Renders the suffix as a standard input suffix. |
|
|
134
|
+
| `sticky` | Keeps the suffix visually aligned with the typed value. |
|
|
135
|
+
|
|
136
|
+
```tsx
|
|
137
|
+
<Input
|
|
138
|
+
name="weight"
|
|
139
|
+
label="Weight"
|
|
140
|
+
suffix="kg"
|
|
141
|
+
suffixType="sticky"
|
|
142
|
+
value="100"
|
|
143
|
+
/>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Text Transforms
|
|
147
|
+
|
|
148
|
+
`textTransform` transforms the entered value before the component stores it internally and before `onChange` receives the event.
|
|
149
|
+
|
|
150
|
+
| Transform | Result |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `uppercase` | Converts text to uppercase. |
|
|
153
|
+
| `lowercase` | Converts text to lowercase. |
|
|
154
|
+
| `capitalize` | Capitalizes each word. |
|
|
155
|
+
| `integer` | Keeps digits only. |
|
|
156
|
+
|
|
157
|
+
```tsx
|
|
158
|
+
<Input
|
|
159
|
+
name="code"
|
|
160
|
+
label="Code"
|
|
161
|
+
textTransform="uppercase"
|
|
162
|
+
placeholder="Enter code"
|
|
163
|
+
/>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Number Input Without Native Controls
|
|
167
|
+
|
|
168
|
+
Set `controls={false}` to hide native number spinner controls.
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<Input
|
|
172
|
+
name="amount"
|
|
173
|
+
label="Amount"
|
|
174
|
+
type="number"
|
|
175
|
+
controls={false}
|
|
176
|
+
placeholder="Enter amount"
|
|
177
|
+
/>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Clear Button
|
|
181
|
+
|
|
182
|
+
`allowClear` enables the FE-VIS clear icon.
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
<Input
|
|
186
|
+
name="search"
|
|
187
|
+
label="Search"
|
|
188
|
+
allowClear
|
|
189
|
+
placeholder="Search..."
|
|
190
|
+
/>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Subcomponents
|
|
194
|
+
|
|
195
|
+
### Textarea
|
|
196
|
+
|
|
197
|
+
```tsx
|
|
198
|
+
<Input.Textarea
|
|
199
|
+
name="description"
|
|
200
|
+
label="Description"
|
|
201
|
+
placeholder="Enter description"
|
|
202
|
+
/>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
`Input.Textarea` does not accept `suffix`, `suffixType`, or `controls`.
|
|
206
|
+
|
|
207
|
+
### Search
|
|
208
|
+
|
|
209
|
+
```tsx
|
|
210
|
+
<Input.Search
|
|
211
|
+
placeholder="Search records"
|
|
212
|
+
enterButton="Search"
|
|
213
|
+
/>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Password
|
|
217
|
+
|
|
218
|
+
```tsx
|
|
219
|
+
<Input.Password placeholder="Enter password" />
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Masked
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
<Input.Masked
|
|
226
|
+
name="phone"
|
|
227
|
+
label="Phone number"
|
|
228
|
+
mask="(999) 999-9999"
|
|
229
|
+
placeholder="Enter phone number"
|
|
230
|
+
/>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Props
|
|
234
|
+
|
|
235
|
+
The base `Input` accepts Ant Design input props plus the FE-VIS additions below.
|
|
236
|
+
|
|
237
|
+
| Prop | Type | Description |
|
|
238
|
+
| --- | --- | --- |
|
|
239
|
+
| `label` | `ReactNode` | Renders a label above the field. |
|
|
240
|
+
| `withAsterisk` | `boolean` | Shows a required marker next to the label. |
|
|
241
|
+
| `error` | `string \| boolean` | Applies error styling and optionally renders an error message. |
|
|
242
|
+
| `suffixType` | `'fixed' \| 'sticky'` | Controls suffix positioning. Defaults to `fixed`. |
|
|
243
|
+
| `textTransform` | `'uppercase' \| 'lowercase' \| 'capitalize' \| 'integer'` | Transforms the value before change handling. |
|
|
244
|
+
| `controls` | `boolean` | Controls native number spinners. Defaults to `true`. |
|
|
245
|
+
| `testId` | `string` | Maps to `data-testid`. |
|
|
246
|
+
| `variant` | `'outlined'` | Visual variant. Currently only `outlined` is supported. |
|
|
247
|
+
|
|
248
|
+
## Consumer Example
|
|
249
|
+
|
|
250
|
+
```tsx
|
|
251
|
+
import { Input } from '@fvc/input';
|
|
252
|
+
|
|
253
|
+
export function SettingsForm() {
|
|
254
|
+
return (
|
|
255
|
+
<form>
|
|
256
|
+
<Input
|
|
257
|
+
name="title"
|
|
258
|
+
label="Title"
|
|
259
|
+
withAsterisk
|
|
260
|
+
placeholder="Enter title"
|
|
261
|
+
/>
|
|
262
|
+
|
|
263
|
+
<Input.Textarea
|
|
264
|
+
name="description"
|
|
265
|
+
label="Description"
|
|
266
|
+
placeholder="Write a short description"
|
|
267
|
+
/>
|
|
268
|
+
|
|
269
|
+
<Input.Search placeholder="Search records" />
|
|
270
|
+
</form>
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
## Testing
|
|
276
|
+
|
|
277
|
+
Use `testId` when a stable test selector is needed.
|
|
278
|
+
|
|
279
|
+
```tsx
|
|
280
|
+
<Input
|
|
281
|
+
name="customerName"
|
|
282
|
+
label="Customer name"
|
|
283
|
+
testId="customer-name-input"
|
|
284
|
+
/>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
```tsx
|
|
288
|
+
screen.getByTestId('customer-name-input');
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## CSS Classes
|
|
292
|
+
|
|
293
|
+
The component applies BEM-style classes to its DOM elements. These can be used for targeted styling overrides in consuming applications.
|
|
294
|
+
|
|
295
|
+
### Root and layout
|
|
296
|
+
|
|
297
|
+
| Class | Applied when |
|
|
298
|
+
| --- | --- |
|
|
299
|
+
| `.fvc-input-root` | Always — the outermost wrapper `<div>`. |
|
|
300
|
+
| `.fvc-input-label` | Always — the `<label>` element above the field. |
|
|
301
|
+
| `.fvc-input-label-asterisk` | When `withAsterisk={true}` — the `*` span inside the label. |
|
|
302
|
+
| `.fvc-input-error-text` | When `error` is a string — the error message container below the field. |
|
|
303
|
+
|
|
304
|
+
### Input element modifiers
|
|
305
|
+
|
|
306
|
+
| Class | Applied when |
|
|
307
|
+
| --- | --- |
|
|
308
|
+
| `.fvc-input-outlined` | Always — the only supported `variant` value. |
|
|
309
|
+
| `.fvc-input-error` | When `error` is truthy (`string` or `true`). |
|
|
310
|
+
| `.fvc-input-empty` | When the current value is empty or undefined. |
|
|
311
|
+
| `.fvc-input-with-prefix` | When `prefix` is provided. |
|
|
312
|
+
| `.fvc-input-no-controls` | When `controls={false}`. |
|
|
313
|
+
| `.fvc-input-suffix-sticky` | When `suffixType="sticky"` and `suffix` is provided. |
|
|
314
|
+
|
|
315
|
+
### Variant root classes
|
|
316
|
+
|
|
317
|
+
Each compound component variant adds its own `rootClassName` to the antd wrapper element:
|
|
318
|
+
|
|
319
|
+
| Class | Variant |
|
|
320
|
+
| --- | --- |
|
|
321
|
+
| `.fvc-input-textarea` | `Input.Textarea` |
|
|
322
|
+
| `.fvc-input-search` | `Input.Search` |
|
|
323
|
+
| `.fvc-input-password` | `Input.Password` |
|
|
324
|
+
| `.fvc-input-masked` | `Input.Masked` |
|
|
325
|
+
|
|
326
|
+
### Example override
|
|
327
|
+
|
|
328
|
+
```scss
|
|
329
|
+
// Target the error message text color for a specific form
|
|
330
|
+
.checkout-form .fvc-input-error-text {
|
|
331
|
+
color: var(--danger-700);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Hide the spinner controls only inside a specific container
|
|
335
|
+
.summary-panel .fvc-input-no-controls input[type='number'] {
|
|
336
|
+
appearance: textfield;
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
## CSS Custom Properties
|
|
343
|
+
|
|
344
|
+
Override these variables in your global stylesheet. All variables are declared on `:root` in `src/styles/variables.scss`.
|
|
345
|
+
|
|
346
|
+
### Base
|
|
347
|
+
|
|
348
|
+
| Variable | Default |
|
|
349
|
+
| --- | --- |
|
|
350
|
+
| `--input-font-family` | `'Roboto', sans-serif` |
|
|
351
|
+
| `--input-border-width` | `1px` |
|
|
352
|
+
| `--input-addon-text-color` | `var(--blue-gray-600)` |
|
|
353
|
+
| `--input-addon-min-width` | `56px` |
|
|
354
|
+
| `--input-description-spacing` | `4px` |
|
|
355
|
+
| `--input-description-error-color` | `var(--red-800)` |
|
|
356
|
+
| `--input-asterisk-color` | `var(--red-800)` |
|
|
357
|
+
|
|
358
|
+
### Size (md)
|
|
359
|
+
|
|
360
|
+
| Variable | Default |
|
|
361
|
+
| --- | --- |
|
|
362
|
+
| `--input-md-size-height` | `32px` |
|
|
363
|
+
| `--input-md-size-border-radius` | `4px` |
|
|
364
|
+
| `--input-md-size-spacing` | `7px 12px` |
|
|
365
|
+
| `--input-md-size-fz` | `14px` |
|
|
366
|
+
| `--input-md-size-fw` | `400` |
|
|
367
|
+
| `--input-md-size-lh` | `16px` |
|
|
368
|
+
| `--input-md-size-label-fw` | `700` |
|
|
369
|
+
| `--input-md-size-label-spacing` | `6px` |
|
|
370
|
+
|
|
371
|
+
### Outlined variant — default state
|
|
372
|
+
|
|
373
|
+
| Variable | Default |
|
|
374
|
+
| --- | --- |
|
|
375
|
+
| `--input-outlined-text-color` | `var(--black-1000)` |
|
|
376
|
+
| `--input-outlined-placeholder-color` | `var(--blue-300)` |
|
|
377
|
+
| `--input-outlined-bg-color` | `var(--neutral-0)` |
|
|
378
|
+
| `--input-outlined-border-color` | `var(--gray-400)` |
|
|
379
|
+
| `--input-outlined-hover-bg-color` | `var(--neutral-0)` |
|
|
380
|
+
| `--input-outlined-hover-border-color` | `var(--gray-600)` |
|
|
381
|
+
| `--input-outlined-focus-border-color` | `var(--blue-400)` |
|
|
382
|
+
| `--input-outlined-valid-bg-color` | `var(--neutral-0)` |
|
|
383
|
+
| `--input-outlined-valid-border-color` | `var(--gray-400)` |
|
|
384
|
+
| `--input-outlined-disabled-bg-color` | `var(--gray-50)` |
|
|
385
|
+
| `--input-outlined-disabled-border-color` | `var(--gray-400)` |
|
|
386
|
+
| `--input-outlined-disabled-text-color` | `var(--blue-gray-600)` |
|
|
387
|
+
| `--input-outlined-label-color` | `var(--black-1000)` |
|
|
388
|
+
| `--input-outlined-addon-bg-color` | `var(--blue-20)` |
|
|
389
|
+
|
|
390
|
+
### Error state
|
|
391
|
+
|
|
392
|
+
| Variable | Default |
|
|
393
|
+
| --- | --- |
|
|
394
|
+
| `--input-error-text-color` | `var(--black-1000)` |
|
|
395
|
+
| `--input-error-placeholder-color` | `var(--blue-300)` |
|
|
396
|
+
| `--input-error-bg-color` | `var(--red-100)` |
|
|
397
|
+
| `--input-error-border-color` | `var(--red-800)` |
|
|
398
|
+
| `--input-error-hover-bg-color` | `var(--red-100)` |
|
|
399
|
+
| `--input-error-hover-border-color` | `var(--red-600)` |
|
|
400
|
+
| `--input-error-focus-border-color` | `var(--red-800)` |
|
|
401
|
+
| `--input-error-valid-bg-color` | `var(--red-100)` |
|
|
402
|
+
| `--input-error-valid-border-color` | `var(--red-800)` |
|
|
403
|
+
| `--input-error-disabled-bg-color` | `var(--red-100)` |
|
|
404
|
+
| `--input-error-disabled-border-color` | `var(--red-800)` |
|
|
405
|
+
| `--input-error-disabled-text-color` | `var(--blue-gray-600)` |
|
|
406
|
+
| `--input-error-label-color` | `var(--black-1000)` |
|
|
407
|
+
| `--input-error-addon-bg-color` | `#f9cbd166` |
|
|
408
|
+
|
|
409
|
+
### Global override example
|
|
410
|
+
|
|
411
|
+
```scss
|
|
412
|
+
// globals.scss
|
|
413
|
+
:root {
|
|
414
|
+
--input-font-family: 'Inter', sans-serif;
|
|
415
|
+
--input-md-size-height: 36px;
|
|
416
|
+
--input-outlined-border-color: var(--gray-300);
|
|
417
|
+
--input-outlined-focus-border-color: var(--brand-500);
|
|
418
|
+
--input-error-border-color: var(--danger-600);
|
|
419
|
+
--input-error-bg-color: var(--danger-50);
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
---
|
|
424
|
+
|
|
425
|
+
## Development
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
bun run lint
|
|
429
|
+
bun run type-check
|
|
430
|
+
bun run test
|
|
431
|
+
bun run build
|
|
432
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fvc/input",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997",
|
|
4
4
|
"main": "./dist/lib/index.js",
|
|
5
5
|
"types": "./dist/lib/input/src/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -27,10 +27,20 @@
|
|
|
27
27
|
"test": "bun test --preload ../../tests/happydom.ts --preload ../../tests/testing-library.tsx"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@fvc/icons": "
|
|
31
|
-
"@fvc/utils": "
|
|
30
|
+
"@fvc/icons": "1.1.4-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997",
|
|
31
|
+
"@fvc/utils": "3.0.2-next-ec65dfb844e6183b3d7f417eee613cfe5ecfd997",
|
|
32
32
|
"react": "^18.0.0",
|
|
33
33
|
"antd": "^5.0.0",
|
|
34
34
|
"antd-mask-input": "^2.0.7"
|
|
35
|
-
}
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"react",
|
|
38
|
+
"react-component",
|
|
39
|
+
"fvc",
|
|
40
|
+
"fe-vis-core",
|
|
41
|
+
"ui",
|
|
42
|
+
"input",
|
|
43
|
+
"design-system",
|
|
44
|
+
"antd"
|
|
45
|
+
]
|
|
36
46
|
}
|