@fiscozen/input 0.1.16 → 1.0.0-next.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 +718 -1
- package/coverage/FzCurrencyInput.vue.html +640 -0
- package/coverage/FzInput.vue.html +709 -0
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/clover.xml +494 -0
- package/coverage/coverage-final.json +4 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +146 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/coverage/useInputStyle.ts.html +343 -0
- package/dist/index.d.ts +1 -0
- package/dist/input.js +7950 -0
- package/dist/input.umd.cjs +561 -0
- package/dist/src/FzCurrencyInput.vue.d.ts +202 -0
- package/dist/src/FzInput.vue.d.ts +254 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/types.d.ts +247 -0
- package/dist/src/useInputStyle.d.ts +27 -0
- package/dist/src/utils.d.ts +21 -0
- package/dist/style.css +1 -0
- package/package.json +6 -6
- package/src/FzCurrencyInput.vue +746 -106
- package/src/FzInput.vue +467 -97
- package/src/__tests__/FzCurrencyInput.test.ts +1528 -0
- package/src/__tests__/FzInput.test.ts +1005 -0
- package/src/index.ts +3 -0
- package/src/types.ts +171 -46
- package/src/useInputStyle.ts +96 -38
- package/src/utils.ts +64 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/FzCurrencyInput.spec.ts +0 -204
- package/src/__tests__/FzInput.spec.ts +0 -181
package/README.md
CHANGED
|
@@ -1,3 +1,720 @@
|
|
|
1
1
|
# @fiscozen/input
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Flexible input component library for Vue 3 applications, featuring icon support, validation states, multiple variants, and specialized currency input with number formatting.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Multiple Input Types**: text, password, email, number, tel, url
|
|
8
|
+
- **Icon Support**: Left and right icons (static or clickable buttons)
|
|
9
|
+
- **Validation States**: Error and valid states with visual feedback
|
|
10
|
+
- **Two Variants**: Normal and floating-label presentation
|
|
11
|
+
- **Two Environments**: frontoffice and backoffice (different heights and styling)
|
|
12
|
+
- **Currency Input**: Specialized component with locale-aware number formatting
|
|
13
|
+
- **Full Accessibility**: ARIA attributes, keyboard navigation, screen reader support
|
|
14
|
+
- **Customizable**: Slots for label, icons, help text, and error messages
|
|
15
|
+
- **TypeScript**: Full type safety with TypeScript definitions
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @fiscozen/input
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Components
|
|
24
|
+
|
|
25
|
+
This package exports two components:
|
|
26
|
+
|
|
27
|
+
- `FzInput` - Standard input with label, icons, and validation states
|
|
28
|
+
- `FzCurrencyInput` - Specialized currency input with number formatting and validation
|
|
29
|
+
|
|
30
|
+
## Basic Usage
|
|
31
|
+
|
|
32
|
+
### FzInput
|
|
33
|
+
|
|
34
|
+
```vue
|
|
35
|
+
<script setup lang="ts">
|
|
36
|
+
import { FzInput } from '@fiscozen/input'
|
|
37
|
+
import { ref } from 'vue'
|
|
38
|
+
|
|
39
|
+
const email = ref('')
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<template>
|
|
43
|
+
<FzInput label="Email" type="email" v-model="email" />
|
|
44
|
+
</template>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### FzCurrencyInput
|
|
48
|
+
|
|
49
|
+
```vue
|
|
50
|
+
<script setup lang="ts">
|
|
51
|
+
import { FzCurrencyInput } from '@fiscozen/input'
|
|
52
|
+
import { ref } from 'vue'
|
|
53
|
+
|
|
54
|
+
const amount = ref<number | undefined>(undefined)
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<template>
|
|
58
|
+
<FzCurrencyInput label="Amount" v-model="amount" />
|
|
59
|
+
</template>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Props
|
|
63
|
+
|
|
64
|
+
### FzInput Props
|
|
65
|
+
|
|
66
|
+
| Prop | Type | Default | Description |
|
|
67
|
+
|------|------|---------|-------------|
|
|
68
|
+
| `label` | `string` | - | Text label displayed above the input field. Overridden by label slot if provided. |
|
|
69
|
+
| `environment` | `'backoffice' \| 'frontoffice'` | `'frontoffice'` | Environment determining input size and styling |
|
|
70
|
+
| `size` | `'sm' \| 'md' \| 'lg'` | - | **Deprecated**: Use `environment` prop instead. Size values map to environments: sm/md → backoffice, lg → frontoffice |
|
|
71
|
+
| `placeholder` | `string` | - | Placeholder text shown when input is empty. Behavior differs based on variant. |
|
|
72
|
+
| `required` | `boolean` | `false` | Marks input as required. Adds asterisk to label and sets native required attribute. |
|
|
73
|
+
| `disabled` | `boolean` | `false` | Disables input interaction and applies disabled styling |
|
|
74
|
+
| `error` | `boolean` | `false` | Shows error state with red border and enables errorMessage slot display |
|
|
75
|
+
| `valid` | `boolean` | `false` | Shows success checkmark icon on the right when true. Takes precedence over rightIcon |
|
|
76
|
+
| `variant` | `'normal' \| 'floating-label'` | `'normal'` | Visual presentation style. 'floating-label' moves placeholder above input when focused/filled |
|
|
77
|
+
| `type` | `'text' \| 'password' \| 'email' \| 'number' \| 'tel' \| 'url'` | `'text'` | Native HTML input type. Determines keyboard layout and validation behavior |
|
|
78
|
+
| `leftIcon` | `string` | - | Font Awesome icon name displayed on the left side of input |
|
|
79
|
+
| `leftIconVariant` | `IconVariant` | - | Visual style variant for left icon (solid, regular, light, etc.) |
|
|
80
|
+
| `leftIconButtonVariant` | `IconButtonVariant` | - | Button variant for left icon when rendered as clickable button |
|
|
81
|
+
| `leftIconAriaLabel` | `string` | - | Accessible label for left icon when clickable. Required for screen reader accessibility |
|
|
82
|
+
| `rightIcon` | `string` | - | Font Awesome icon name displayed on the right side of input |
|
|
83
|
+
| `rightIconSize` | `IconSize` | - | **Deprecated**: Size override for right icon. Icons now have a fixed size of "md". This prop is ignored. |
|
|
84
|
+
| `rightIconVariant` | `IconVariant` | - | Visual style variant for right icon (solid, regular, light, etc.) |
|
|
85
|
+
| `rightIconButton` | `boolean` | `false` | Renders right icon as clickable button instead of static icon |
|
|
86
|
+
| `rightIconButtonVariant` | `IconButtonVariant` | `'invisible'` | Button variant for right icon when rightIconButton is true |
|
|
87
|
+
| `rightIconAriaLabel` | `string` | - | Accessible label for right icon when clickable. Required for screen reader accessibility |
|
|
88
|
+
| `secondRightIcon` | `string` | - | Font Awesome icon name displayed as second icon on the right side of input. Order: secondRightIcon > rightIcon > valid (all can be present simultaneously) |
|
|
89
|
+
| `secondRightIconClass` | `string` | - | Additional CSS classes applied to second right icon container |
|
|
90
|
+
| `secondRightIconVariant` | `IconVariant` | - | Visual style variant for second right icon (solid, regular, light, etc.) |
|
|
91
|
+
| `secondRightIconButton` | `boolean` | `false` | Renders second right icon as clickable button instead of static icon |
|
|
92
|
+
| `secondRightIconButtonVariant` | `IconButtonVariant` | `'invisible'` | Button variant for second right icon when secondRightIconButton is true |
|
|
93
|
+
| `secondRightIconAriaLabel` | `string` | - | Accessible label for second right icon when clickable. Required for screen reader accessibility |
|
|
94
|
+
| `pattern` | `string` | - | HTML5 pattern attribute for native browser validation |
|
|
95
|
+
| `name` | `string` | - | Native name attribute for form submission and identification |
|
|
96
|
+
| `readonly` | `boolean` | `false` | Native readonly attribute. Prevents user input while keeping field focusable |
|
|
97
|
+
| `maxlength` | `number` | - | Native maxlength attribute. Limits maximum number of characters |
|
|
98
|
+
| `rightIconClass` | `string` | - | Additional CSS classes applied to right icon container |
|
|
99
|
+
| `leftIconClass` | `string` | - | Additional CSS classes applied to left icon container |
|
|
100
|
+
|
|
101
|
+
### FzCurrencyInput Props
|
|
102
|
+
|
|
103
|
+
FzCurrencyInput extends FzInput props (except `type`, `modelValue`, `rightIcon`, `rightIconSize`, `rightIconVariant`, `rightIconButton`, `rightIconButtonVariant`, `rightIconAriaLabel`, `rightIconClass`, `secondRightIcon`, `secondRightIconClass`, `secondRightIconVariant`, `secondRightIconButton`, `secondRightIconButtonVariant`, `secondRightIconAriaLabel`) and adds:
|
|
104
|
+
|
|
105
|
+
| Prop | Type | Default | Description |
|
|
106
|
+
|------|------|---------|-------------|
|
|
107
|
+
| `modelValue` | `number \| string \| undefined` | - | **Type assertion**: Accepts `number \| string \| undefined` as input, but **always emits** `number \| undefined` (never `string`). Strings are deprecated and trigger a console warning. See [v-model Type Behavior](#v-model-type-behavior) for details. |
|
|
108
|
+
| `nullOnEmpty` | `boolean` | `false` | Converts empty input to null instead of 0 |
|
|
109
|
+
| `minimumFractionDigits` | `number` | `2` | Minimum decimal places in formatted output |
|
|
110
|
+
| `maximumFractionDigits` | `number` | `2` | Maximum decimal places in formatted output |
|
|
111
|
+
| `min` | `number` | - | Minimum allowed value. Values below this are clamped to min |
|
|
112
|
+
| `max` | `number` | - | Maximum allowed value. Values above this are clamped to max |
|
|
113
|
+
| `step` | `number` | `1` | Step increment for arrow buttons. When forceStep is true, values are rounded to nearest step multiple |
|
|
114
|
+
| `forceStep` | `boolean` | `false` | Enforces quantization: values are automatically rounded to nearest step multiple |
|
|
115
|
+
| `stepUpAriaLabel` | `string` | - | Custom accessible label for step up button. If not provided, uses default label |
|
|
116
|
+
| `stepDownAriaLabel` | `string` | - | Custom accessible label for step down button. If not provided, uses default label |
|
|
117
|
+
|
|
118
|
+
**Note**: `rightIcon` and `secondRightIcon` props are not available in FzCurrencyInput. Only `valid` checkmark icon can be displayed alongside step controls.
|
|
119
|
+
|
|
120
|
+
## Slots
|
|
121
|
+
|
|
122
|
+
| Slot | Description |
|
|
123
|
+
|------|-------------|
|
|
124
|
+
| `label` | Custom label content (overrides `label` prop) |
|
|
125
|
+
| `left-icon` | Custom left icon content (overrides `leftIcon` prop) |
|
|
126
|
+
| `right-icon` | Custom right icon content (overrides `rightIcon` prop and `valid` checkmark) |
|
|
127
|
+
| `helpText` | Help text displayed below input when no error is present |
|
|
128
|
+
| `errorMessage` | Error message displayed below input when `error` is true |
|
|
129
|
+
|
|
130
|
+
## Variants
|
|
131
|
+
|
|
132
|
+
### Normal (Default)
|
|
133
|
+
|
|
134
|
+
Standard input with label above and placeholder inside the input field.
|
|
135
|
+
|
|
136
|
+
```vue
|
|
137
|
+
<FzInput label="Email" type="email" placeholder="Enter your email" v-model="email" />
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Floating Label
|
|
141
|
+
|
|
142
|
+
Floating label variant moves placeholder above input when focused or when input has a value.
|
|
143
|
+
|
|
144
|
+
```vue
|
|
145
|
+
<FzInput
|
|
146
|
+
label="Email"
|
|
147
|
+
variant="floating-label"
|
|
148
|
+
placeholder="Enter your email"
|
|
149
|
+
v-model="email"
|
|
150
|
+
/>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Environments
|
|
154
|
+
|
|
155
|
+
Inputs support two environments that determine their height and styling:
|
|
156
|
+
|
|
157
|
+
- **frontoffice** (default): larger spacing
|
|
158
|
+
- **backoffice**: compact spacing
|
|
159
|
+
|
|
160
|
+
```vue
|
|
161
|
+
<template>
|
|
162
|
+
<FzInput label="Frontoffice (Default)" environment="frontoffice" v-model="value1" />
|
|
163
|
+
<FzInput label="Backoffice" environment="backoffice" v-model="value2" />
|
|
164
|
+
</template>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
**Note**: The `size` prop is deprecated. Use `environment` instead.
|
|
168
|
+
|
|
169
|
+
## Input Types
|
|
170
|
+
|
|
171
|
+
### Text
|
|
172
|
+
|
|
173
|
+
```vue
|
|
174
|
+
<FzInput label="Name" type="text" v-model="name" />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Password
|
|
178
|
+
|
|
179
|
+
```vue
|
|
180
|
+
<FzInput label="Password" type="password" v-model="password" />
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Email
|
|
184
|
+
|
|
185
|
+
```vue
|
|
186
|
+
<FzInput label="Email" type="email" required v-model="email" />
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Number
|
|
190
|
+
|
|
191
|
+
```vue
|
|
192
|
+
<FzInput label="Age" type="number" v-model="age" />
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### Telephone
|
|
196
|
+
|
|
197
|
+
```vue
|
|
198
|
+
<FzInput
|
|
199
|
+
label="Phone"
|
|
200
|
+
type="tel"
|
|
201
|
+
pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
|
|
202
|
+
v-model="phone"
|
|
203
|
+
/>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### URL
|
|
207
|
+
|
|
208
|
+
```vue
|
|
209
|
+
<FzInput label="Website" type="url" v-model="website" />
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## States
|
|
213
|
+
|
|
214
|
+
### Required
|
|
215
|
+
|
|
216
|
+
Required inputs show an asterisk (*) next to the label and set the native required attribute.
|
|
217
|
+
|
|
218
|
+
```vue
|
|
219
|
+
<FzInput label="Email" type="email" required v-model="email" />
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Disabled
|
|
223
|
+
|
|
224
|
+
Disabled inputs prevent user interaction and apply muted styling.
|
|
225
|
+
|
|
226
|
+
```vue
|
|
227
|
+
<FzInput label="Disabled Input" disabled v-model="value" />
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Error
|
|
231
|
+
|
|
232
|
+
Error state shows red border and displays error message via errorMessage slot.
|
|
233
|
+
|
|
234
|
+
```vue
|
|
235
|
+
<FzInput label="Email" type="email" :error="hasError" v-model="email">
|
|
236
|
+
<template #errorMessage>Please enter a valid email address</template>
|
|
237
|
+
</FzInput>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Valid
|
|
241
|
+
|
|
242
|
+
Valid state shows a green checkmark icon on the right side.
|
|
243
|
+
|
|
244
|
+
```vue
|
|
245
|
+
<FzInput label="Email" type="email" :valid="isValid" v-model="email" />
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Readonly
|
|
249
|
+
|
|
250
|
+
Readonly inputs prevent editing but remain focusable and visible.
|
|
251
|
+
|
|
252
|
+
```vue
|
|
253
|
+
<FzInput label="Read-only Value" readonly v-model="readonlyValue" />
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## With Icons
|
|
257
|
+
|
|
258
|
+
### Left Icon
|
|
259
|
+
|
|
260
|
+
```vue
|
|
261
|
+
<FzInput
|
|
262
|
+
label="Date"
|
|
263
|
+
leftIcon="calendar-lines"
|
|
264
|
+
v-model="date"
|
|
265
|
+
/>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Right Icon
|
|
269
|
+
|
|
270
|
+
```vue
|
|
271
|
+
<FzInput
|
|
272
|
+
label="Search"
|
|
273
|
+
rightIcon="magnifying-glass"
|
|
274
|
+
v-model="search"
|
|
275
|
+
/>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Right Icon as Button
|
|
279
|
+
|
|
280
|
+
Right icon can be rendered as a clickable button (useful for password visibility toggle, clear button, etc.).
|
|
281
|
+
|
|
282
|
+
```vue
|
|
283
|
+
<template>
|
|
284
|
+
<FzInput
|
|
285
|
+
label="Password"
|
|
286
|
+
:type="passwordType"
|
|
287
|
+
rightIcon="eye"
|
|
288
|
+
:rightIconButton="true"
|
|
289
|
+
rightIconButtonVariant="secondary"
|
|
290
|
+
rightIconAriaLabel="Toggle password visibility"
|
|
291
|
+
@fzinput:right-icon-click="togglePasswordVisibility"
|
|
292
|
+
v-model="password"
|
|
293
|
+
/>
|
|
294
|
+
</template>
|
|
295
|
+
|
|
296
|
+
<script setup>
|
|
297
|
+
import { ref } from 'vue'
|
|
298
|
+
|
|
299
|
+
const passwordType = ref('password')
|
|
300
|
+
const password = ref('')
|
|
301
|
+
|
|
302
|
+
const togglePasswordVisibility = () => {
|
|
303
|
+
passwordType.value = passwordType.value === 'password' ? 'text' : 'password'
|
|
304
|
+
}
|
|
305
|
+
</script>
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Clickable Icons with Accessibility
|
|
309
|
+
|
|
310
|
+
When icons are clickable, provide `leftIconAriaLabel` or `rightIconAriaLabel` for keyboard accessibility:
|
|
311
|
+
|
|
312
|
+
```vue
|
|
313
|
+
<FzInput
|
|
314
|
+
label="Search"
|
|
315
|
+
leftIcon="magnifying-glass"
|
|
316
|
+
leftIconAriaLabel="Open search options"
|
|
317
|
+
@fzinput:left-icon-click="openSearchOptions"
|
|
318
|
+
v-model="search"
|
|
319
|
+
/>
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Both Icons
|
|
323
|
+
|
|
324
|
+
```vue
|
|
325
|
+
<FzInput
|
|
326
|
+
label="Amount"
|
|
327
|
+
leftIcon="dollar-sign"
|
|
328
|
+
rightIcon="credit-card"
|
|
329
|
+
v-model="amount"
|
|
330
|
+
/>
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Help Text and Error Messages
|
|
334
|
+
|
|
335
|
+
### Help Text
|
|
336
|
+
|
|
337
|
+
Help text is displayed below the input when no error is present.
|
|
338
|
+
|
|
339
|
+
```vue
|
|
340
|
+
<FzInput label="Username" v-model="username">
|
|
341
|
+
<template #helpText>
|
|
342
|
+
Username must be between 3 and 20 characters
|
|
343
|
+
</template>
|
|
344
|
+
</FzInput>
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Error Message
|
|
348
|
+
|
|
349
|
+
Error message is displayed below the input when error prop is true.
|
|
350
|
+
|
|
351
|
+
```vue
|
|
352
|
+
<FzInput label="Email" type="email" :error="hasError" v-model="email">
|
|
353
|
+
<template #errorMessage>
|
|
354
|
+
Please enter a valid email address
|
|
355
|
+
</template>
|
|
356
|
+
</FzInput>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Custom Label
|
|
360
|
+
|
|
361
|
+
You can provide custom label content using the label slot.
|
|
362
|
+
|
|
363
|
+
```vue
|
|
364
|
+
<FzInput v-model="value">
|
|
365
|
+
<template #label>
|
|
366
|
+
<strong>Custom Label</strong> with <em>formatting</em>
|
|
367
|
+
</template>
|
|
368
|
+
</FzInput>
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Examples
|
|
372
|
+
|
|
373
|
+
### Form with Validation
|
|
374
|
+
|
|
375
|
+
```vue
|
|
376
|
+
<template>
|
|
377
|
+
<form @submit.prevent="handleSubmit">
|
|
378
|
+
<FzInput
|
|
379
|
+
label="Email"
|
|
380
|
+
type="email"
|
|
381
|
+
required
|
|
382
|
+
:error="errors.email"
|
|
383
|
+
v-model="form.email"
|
|
384
|
+
>
|
|
385
|
+
<template #errorMessage v-if="errors.email">
|
|
386
|
+
{{ errors.email }}
|
|
387
|
+
</template>
|
|
388
|
+
</FzInput>
|
|
389
|
+
|
|
390
|
+
<FzInput
|
|
391
|
+
label="Password"
|
|
392
|
+
type="password"
|
|
393
|
+
required
|
|
394
|
+
:error="errors.password"
|
|
395
|
+
v-model="form.password"
|
|
396
|
+
>
|
|
397
|
+
<template #errorMessage v-if="errors.password">
|
|
398
|
+
{{ errors.password }}
|
|
399
|
+
</template>
|
|
400
|
+
</FzInput>
|
|
401
|
+
|
|
402
|
+
<button type="submit">Submit</button>
|
|
403
|
+
</form>
|
|
404
|
+
</template>
|
|
405
|
+
|
|
406
|
+
<script setup>
|
|
407
|
+
import { ref } from 'vue'
|
|
408
|
+
|
|
409
|
+
const form = ref({
|
|
410
|
+
email: '',
|
|
411
|
+
password: ''
|
|
412
|
+
})
|
|
413
|
+
|
|
414
|
+
const errors = ref({
|
|
415
|
+
email: null,
|
|
416
|
+
password: null
|
|
417
|
+
})
|
|
418
|
+
|
|
419
|
+
const handleSubmit = () => {
|
|
420
|
+
// Validation logic
|
|
421
|
+
}
|
|
422
|
+
</script>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Password with Visibility Toggle
|
|
426
|
+
|
|
427
|
+
```vue
|
|
428
|
+
<template>
|
|
429
|
+
<FzInput
|
|
430
|
+
label="Password"
|
|
431
|
+
:type="showPassword ? 'text' : 'password'"
|
|
432
|
+
rightIcon="eye"
|
|
433
|
+
:rightIconButton="true"
|
|
434
|
+
@fzinput:right-icon-click="togglePassword"
|
|
435
|
+
v-model="password"
|
|
436
|
+
/>
|
|
437
|
+
</template>
|
|
438
|
+
|
|
439
|
+
<script setup>
|
|
440
|
+
import { ref } from 'vue'
|
|
441
|
+
|
|
442
|
+
const password = ref('')
|
|
443
|
+
const showPassword = ref(false)
|
|
444
|
+
|
|
445
|
+
const togglePassword = () => {
|
|
446
|
+
showPassword.value = !showPassword.value
|
|
447
|
+
}
|
|
448
|
+
</script>
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
### Search Input
|
|
452
|
+
|
|
453
|
+
```vue
|
|
454
|
+
<FzInput
|
|
455
|
+
label="Search"
|
|
456
|
+
leftIcon="magnifying-glass"
|
|
457
|
+
rightIcon="xmark"
|
|
458
|
+
:rightIconButton="true"
|
|
459
|
+
@fzinput:right-icon-click="clearSearch"
|
|
460
|
+
v-model="searchQuery"
|
|
461
|
+
/>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Input with Max Length
|
|
465
|
+
|
|
466
|
+
```vue
|
|
467
|
+
<FzInput
|
|
468
|
+
label="PIN"
|
|
469
|
+
type="text"
|
|
470
|
+
maxlength="4"
|
|
471
|
+
pattern="[0-9]{4}"
|
|
472
|
+
v-model="pin"
|
|
473
|
+
/>
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
## FzCurrencyInput
|
|
477
|
+
|
|
478
|
+
Specialized currency input component built on FzInput with number formatting, validation, and step controls. Formats values using Intl.NumberFormat with locale-aware separators.
|
|
479
|
+
|
|
480
|
+
### Features
|
|
481
|
+
|
|
482
|
+
- Locale-aware number formatting (decimal and thousand separators)
|
|
483
|
+
- Min/max value constraints
|
|
484
|
+
- Step quantization with arrow buttons
|
|
485
|
+
- Intelligent paste parsing (detects decimal/thousand separators automatically)
|
|
486
|
+
- Configurable decimal places
|
|
487
|
+
|
|
488
|
+
### Basic Usage
|
|
489
|
+
|
|
490
|
+
```vue
|
|
491
|
+
<script setup lang="ts">
|
|
492
|
+
import { FzCurrencyInput } from '@fiscozen/input'
|
|
493
|
+
import { ref } from 'vue'
|
|
494
|
+
|
|
495
|
+
const amount = ref<number | undefined>(undefined)
|
|
496
|
+
</script>
|
|
497
|
+
|
|
498
|
+
<template>
|
|
499
|
+
<FzCurrencyInput
|
|
500
|
+
label="Amount"
|
|
501
|
+
v-model="amount"
|
|
502
|
+
:min="0"
|
|
503
|
+
:max="1000"
|
|
504
|
+
/>
|
|
505
|
+
</template>
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### With Step Controls
|
|
509
|
+
|
|
510
|
+
Step controls (arrow buttons) are always visible in FzCurrencyInput. Default step is 1, but can be customized.
|
|
511
|
+
|
|
512
|
+
```vue
|
|
513
|
+
<FzCurrencyInput
|
|
514
|
+
label="Quantity"
|
|
515
|
+
v-model="quantity"
|
|
516
|
+
:step="5"
|
|
517
|
+
/>
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
### With Step Quantization
|
|
521
|
+
|
|
522
|
+
When `forceStep` is true, values are automatically rounded to the nearest step multiple.
|
|
523
|
+
|
|
524
|
+
```vue
|
|
525
|
+
<FzCurrencyInput
|
|
526
|
+
label="Quantity"
|
|
527
|
+
v-model="quantity"
|
|
528
|
+
:step="4"
|
|
529
|
+
:forceStep="true"
|
|
530
|
+
/>
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
### With Min/Max Constraints
|
|
534
|
+
|
|
535
|
+
```vue
|
|
536
|
+
<FzCurrencyInput
|
|
537
|
+
label="Price"
|
|
538
|
+
v-model="price"
|
|
539
|
+
:min="0"
|
|
540
|
+
:max="9999.99"
|
|
541
|
+
:minimumFractionDigits="2"
|
|
542
|
+
:maximumFractionDigits="2"
|
|
543
|
+
/>
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
### With Valid State
|
|
547
|
+
|
|
548
|
+
Valid checkmark icon is displayed alongside step controls.
|
|
549
|
+
|
|
550
|
+
```vue
|
|
551
|
+
<FzCurrencyInput
|
|
552
|
+
label="Amount"
|
|
553
|
+
v-model="amount"
|
|
554
|
+
:valid="isValid"
|
|
555
|
+
/>
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
### Currency Input Behavior
|
|
559
|
+
|
|
560
|
+
- **Formatting**: Values are formatted using Intl.NumberFormat with locale settings (default: 'it-IT')
|
|
561
|
+
- **Paste Handling**: Automatically detects and parses various number formats (e.g., "1.234,56", "1,234.56")
|
|
562
|
+
- **Step Controls**: Arrow buttons are always visible (default step = 1). Support keyboard accessibility (Enter/Space to activate)
|
|
563
|
+
- **Step Quantization**: When `forceStep` is true, values are automatically rounded to nearest step multiple
|
|
564
|
+
- **Empty Values**: When `nullOnEmpty` is true, empty input converts to null instead of 0
|
|
565
|
+
- **Valid State**: Valid checkmark icon can be displayed alongside step controls
|
|
566
|
+
- **Right Icons**: `rightIcon` and `secondRightIcon` props are not available. Only `valid` icon is supported.
|
|
567
|
+
|
|
568
|
+
### v-model Type Behavior
|
|
569
|
+
|
|
570
|
+
FzCurrencyInput uses a **type assertion** pattern for its v-model:
|
|
571
|
+
|
|
572
|
+
- **Accepts**: `number | string | undefined` as input
|
|
573
|
+
- **Emits**: Always `number | undefined` (never `string`)
|
|
574
|
+
|
|
575
|
+
#### Type Assertion
|
|
576
|
+
|
|
577
|
+
The component accepts `number | string | undefined` as input, but **always emits** `number | undefined`. Strings are automatically parsed (Italian format: "1.234,56" → 1234.56) and converted to numbers internally.
|
|
578
|
+
|
|
579
|
+
#### Deprecation Warning
|
|
580
|
+
|
|
581
|
+
**String values are deprecated** and will be removed in a future version. A console warning is shown when strings are used. Please use `number | undefined` instead for type safety and future compatibility.
|
|
582
|
+
|
|
583
|
+
#### Recommended Usage
|
|
584
|
+
|
|
585
|
+
```vue
|
|
586
|
+
<script setup lang="ts">
|
|
587
|
+
import { ref } from 'vue'
|
|
588
|
+
|
|
589
|
+
// ✅ Recommended: number | undefined (future-proof)
|
|
590
|
+
const amount = ref<number | undefined>(undefined)
|
|
591
|
+
</script>
|
|
592
|
+
|
|
593
|
+
<template>
|
|
594
|
+
<FzCurrencyInput label="Amount" v-model="amount" />
|
|
595
|
+
</template>
|
|
596
|
+
```
|
|
597
|
+
|
|
598
|
+
#### Deprecated Usage (Still Works)
|
|
599
|
+
|
|
600
|
+
```vue
|
|
601
|
+
<script setup lang="ts">
|
|
602
|
+
import { ref } from 'vue'
|
|
603
|
+
|
|
604
|
+
// ⚠️ Deprecated: string (still works but shows warning)
|
|
605
|
+
// Strings are parsed and converted to numbers internally
|
|
606
|
+
const amount = ref<string>("1234,56")
|
|
607
|
+
</script>
|
|
608
|
+
|
|
609
|
+
<template>
|
|
610
|
+
<FzCurrencyInput label="Amount" v-model="amount" />
|
|
611
|
+
</template>
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
**Note**: When using strings, the component will:
|
|
615
|
+
1. Show a console warning about deprecation
|
|
616
|
+
2. Parse the string using Italian format (points = thousands, comma = decimal)
|
|
617
|
+
3. Convert it to a number internally
|
|
618
|
+
4. Always emit a `number | undefined` value
|
|
619
|
+
|
|
620
|
+
#### Migration Guide
|
|
621
|
+
|
|
622
|
+
If you're currently using strings, migrate to numbers:
|
|
623
|
+
|
|
624
|
+
```vue
|
|
625
|
+
<!-- Before (deprecated) -->
|
|
626
|
+
<script setup lang="ts">
|
|
627
|
+
const amount = ref<string>("1234,56")
|
|
628
|
+
</script>
|
|
629
|
+
|
|
630
|
+
<!-- After (recommended) -->
|
|
631
|
+
<script setup lang="ts">
|
|
632
|
+
const amount = ref<number | undefined>(1234.56)
|
|
633
|
+
// or
|
|
634
|
+
const amount = ref<number | undefined>(undefined)
|
|
635
|
+
</script>
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
## Accessibility
|
|
639
|
+
|
|
640
|
+
FzInput and FzCurrencyInput are fully accessible and meet WCAG 2.1 AA standards:
|
|
641
|
+
|
|
642
|
+
- **ARIA Attributes**: Proper aria-required, aria-invalid, aria-disabled, aria-labelledby, aria-describedby
|
|
643
|
+
- **Keyboard Navigation**: Full keyboard support (Tab, Enter, Space, Arrow keys)
|
|
644
|
+
- **Screen Readers**: Error messages and help text are properly associated with inputs
|
|
645
|
+
- **Focus Management**: Visible focus indicators with proper contrast
|
|
646
|
+
- **Semantic HTML**: Native input elements with proper label associations
|
|
647
|
+
- **Error Announcements**: Error messages use role="alert" for immediate screen reader announcements
|
|
648
|
+
|
|
649
|
+
### ARIA Attributes
|
|
650
|
+
|
|
651
|
+
- **aria-required**: Set to "true" or "false" (string values for Vue 3 compatibility)
|
|
652
|
+
- **aria-invalid**: Set to "true" when error prop is true
|
|
653
|
+
- **aria-disabled**: Set to "true" when disabled prop is true
|
|
654
|
+
- **aria-labelledby**: Links to label element when label prop is provided
|
|
655
|
+
- **aria-describedby**: Links to help text or error message when present
|
|
656
|
+
|
|
657
|
+
### Error Message Accessibility
|
|
658
|
+
|
|
659
|
+
Error messages are rendered with `role="alert"` to ensure screen readers announce them immediately when displayed.
|
|
660
|
+
|
|
661
|
+
## Behavior & Concepts
|
|
662
|
+
|
|
663
|
+
### Label vs Slot Priority
|
|
664
|
+
|
|
665
|
+
When both `label` prop and label slot are provided, the slot takes precedence:
|
|
666
|
+
|
|
667
|
+
```vue
|
|
668
|
+
<FzInput label="This won't show">
|
|
669
|
+
<template #label>This will show instead</template>
|
|
670
|
+
</FzInput>
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### Right Icons Display Order
|
|
674
|
+
|
|
675
|
+
The component supports three types of right-side icons that can all be displayed simultaneously:
|
|
676
|
+
1. **`valid` checkmark** (when `valid` prop is `true`) - displayed first
|
|
677
|
+
2. **`secondRightIcon`** (when provided) - displayed second
|
|
678
|
+
3. **`rightIcon`** (when provided) - displayed third
|
|
679
|
+
|
|
680
|
+
All three icons can be visible at the same time, appearing in this order from left to right.
|
|
681
|
+
|
|
682
|
+
### Floating Label Placeholder Behavior
|
|
683
|
+
|
|
684
|
+
In floating-label variant:
|
|
685
|
+
- When input is empty and not focused: placeholder shows above input as floating text
|
|
686
|
+
- When input has value or is focused: placeholder moves above input permanently
|
|
687
|
+
- Normal placeholder attribute is hidden in this mode
|
|
688
|
+
|
|
689
|
+
### Icon Button Size Mapping
|
|
690
|
+
|
|
691
|
+
Right icon buttons use a smaller size scale than inputs to maintain visual balance:
|
|
692
|
+
- Input size `sm` → Icon button size `xs`
|
|
693
|
+
- Input size `md` → Icon button size `sm`
|
|
694
|
+
- Input size `lg` → Icon button size `md`
|
|
695
|
+
|
|
696
|
+
## Notes
|
|
697
|
+
|
|
698
|
+
### Input Type Behavior
|
|
699
|
+
|
|
700
|
+
Different input types provide different keyboard layouts and validation:
|
|
701
|
+
- **email**: Triggers email keyboard on mobile devices
|
|
702
|
+
- **tel**: Triggers numeric keyboard on mobile devices
|
|
703
|
+
- **number**: Allows numeric input with spinner controls
|
|
704
|
+
- **password**: Masks input characters
|
|
705
|
+
- **url**: Validates URL format
|
|
706
|
+
|
|
707
|
+
### Currency Input Formatting
|
|
708
|
+
|
|
709
|
+
FzCurrencyInput uses Intl.NumberFormat for locale-aware formatting. The formatting respects:
|
|
710
|
+
- Browser locale settings
|
|
711
|
+
- Minimum and maximum fraction digits
|
|
712
|
+
- Decimal and thousand separator conventions
|
|
713
|
+
|
|
714
|
+
### Paste Handling in Currency Input
|
|
715
|
+
|
|
716
|
+
The currency input uses intelligent heuristics to parse pasted values:
|
|
717
|
+
- Multiple different separators: rightmost is decimal separator
|
|
718
|
+
- Multiple same separators: thousand separator
|
|
719
|
+
- Single separator with <3 digits after: decimal separator
|
|
720
|
+
- Single separator with 3+ digits after: ambiguous, uses default formatting
|