@fiscozen/input 0.1.17 → 1.0.0-next.1

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