srcdev-nuxt-forms 2.4.23 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/nuxt.config.ts +3 -0
  2. package/package.json +2 -2
  3. package/assets/styles/ally/_utils.css +0 -20
  4. package/assets/styles/ally/_variables.css +0 -8
  5. package/assets/styles/ally/index.css +0 -2
  6. package/assets/styles/forms/index.css +0 -2
  7. package/assets/styles/forms/themes/_error.css +0 -85
  8. package/assets/styles/forms/themes/_ghost.css +0 -85
  9. package/assets/styles/forms/themes/_input-action-underlined.css +0 -20
  10. package/assets/styles/forms/themes/_input-action.css +0 -20
  11. package/assets/styles/forms/themes/_primary.css +0 -90
  12. package/assets/styles/forms/themes/_secondary.css +0 -85
  13. package/assets/styles/forms/themes/_success.css +0 -85
  14. package/assets/styles/forms/themes/_tertiary.css +0 -85
  15. package/assets/styles/forms/themes/_warning.css +0 -85
  16. package/assets/styles/forms/themes/index.css +0 -9
  17. package/assets/styles/forms/variables/_sizes.css +0 -71
  18. package/assets/styles/forms/variables/_theme.css +0 -11
  19. package/assets/styles/forms/variables/index.css +0 -2
  20. package/assets/styles/main.css +0 -5
  21. package/assets/styles/typography/index.css +0 -2
  22. package/assets/styles/typography/utils/_font-classes.css +0 -190
  23. package/assets/styles/typography/utils/_weights.css +0 -69
  24. package/assets/styles/typography/utils/index.css +0 -2
  25. package/assets/styles/typography/variables/_colors.css +0 -14
  26. package/assets/styles/typography/variables/_reponsive-font-size.css +0 -10
  27. package/assets/styles/typography/variables/index.css +0 -2
  28. package/assets/styles/utils/_margin-helpers.css +0 -334
  29. package/assets/styles/utils/_padding-helpers.css +0 -308
  30. package/assets/styles/utils/_page.css +0 -36
  31. package/assets/styles/utils/index.css +0 -3
  32. package/assets/styles/variables/colors/_blue.css +0 -15
  33. package/assets/styles/variables/colors/_gray.css +0 -16
  34. package/assets/styles/variables/colors/_green.css +0 -15
  35. package/assets/styles/variables/colors/_orange.css +0 -15
  36. package/assets/styles/variables/colors/_red.css +0 -15
  37. package/assets/styles/variables/colors/_yellow.css +0 -15
  38. package/assets/styles/variables/colors/colors.css +0 -6
  39. package/assets/styles/variables/index.css +0 -1
  40. package/components/forms/c12/prop-validators/index.ts +0 -38
  41. package/components/forms/c12/utils.ts +0 -14
  42. package/components/forms/form-errors/InputError.vue +0 -172
  43. package/components/forms/form-errors/tests/InputError.spec.ts +0 -67
  44. package/components/forms/input-button/InputButtonCore.vue +0 -191
  45. package/components/forms/input-button/variants/InputButtonConfirm.vue +0 -66
  46. package/components/forms/input-button/variants/InputButtonSubmit.vue +0 -62
  47. package/components/forms/input-checkbox/MultipleCheckboxes.vue +0 -203
  48. package/components/forms/input-checkbox/SingleCheckbox.vue +0 -169
  49. package/components/forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +0 -98
  50. package/components/forms/input-checkbox/tests/data/tags.json +0 -67
  51. package/components/forms/input-checkbox-radio/InputCheckboxRadioButton.vue +0 -214
  52. package/components/forms/input-checkbox-radio/InputCheckboxRadioCore.vue +0 -191
  53. package/components/forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +0 -111
  54. package/components/forms/input-number/InputNumberCore.vue +0 -203
  55. package/components/forms/input-number/variants/InputNumberDefault.vue +0 -154
  56. package/components/forms/input-radio/MultipleRadiobuttons.vue +0 -201
  57. package/components/forms/input-radio/tests/MultipleRadioButtons.spec.ts +0 -89
  58. package/components/forms/input-radio/tests/data/tags.json +0 -67
  59. package/components/forms/input-range/InputRangeCore.vue +0 -274
  60. package/components/forms/input-range/variants/InputRangeDefault.vue +0 -156
  61. package/components/forms/input-range-fancy/InputRangeFancyCore.vue +0 -450
  62. package/components/forms/input-range-fancy/InputRangeFancyWithLabel.vue +0 -124
  63. package/components/forms/input-text/InputTextCore.vue +0 -331
  64. package/components/forms/input-text/variants/InputPasswordWithLabel.vue +0 -130
  65. package/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +0 -187
  66. package/components/forms/input-text/variants/InputTextWithLabel.vue +0 -298
  67. package/components/forms/input-textarea/InputTextareaCore.vue +0 -234
  68. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +0 -267
  69. package/components/forms/toggle-switch/ToggleSwitchCore.vue +0 -216
  70. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +0 -105
  71. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +0 -102
  72. package/components/forms/ui/FormField.vue +0 -78
  73. package/components/forms/ui/FormWrapper.vue +0 -35
  74. package/components/utils/colour-scheme-select/ColourSchemeSelect.vue +0 -270
  75. package/components/utils/colour-scheme-select/ColourSchemeSelectOld.vue +0 -225
  76. package/components/utils/dark-mode-switcher/DarkModeSwitcher.vue +0 -47
  77. package/composables/useApiRequest.ts +0 -25
  78. package/composables/useColourScheme.ts +0 -25
  79. package/composables/useErrorMessages.ts +0 -59
  80. package/composables/useFormControl.ts +0 -248
  81. package/composables/useSleep.ts +0 -5
  82. package/composables/useStyleClassPassthrough.ts +0 -30
  83. package/composables/useZodValidation.ts +0 -148
  84. package/types/types.forms.ts +0 -216
  85. package/types/types.zodFormControl.ts +0 -21
@@ -1,331 +0,0 @@
1
- <template>
2
- <div
3
- class="input-text-wrapper"
4
- :data-form-theme="formTheme"
5
- :data-size="size"
6
- :class="[inputVariant, { dirty: isDirty }, { active: isActive }, { error: fieldHasError }, { 'has-left-slot': hasLeftSlot }, { 'has-right-slot': hasRightSlot }]"
7
- >
8
- <span v-if="hasLeftSlot" class="slot left-slot">
9
- <slot name="left"></slot>
10
- </span>
11
-
12
- <input
13
- :type
14
- :placeholder
15
- :id
16
- :name
17
- :required
18
- :maxlength
19
- :class="['input-text-core', elementClasses, { dirty: isDirty }, { active: isActive }]"
20
- v-model="modelValue"
21
- ref="inputField"
22
- :aria-invalid="fieldHasError"
23
- :aria-describedby
24
- :pattern="inputPattern"
25
- :inputmode
26
- @focusin="updateFocus(true)"
27
- @focusout="updateFocus(false)"
28
- />
29
-
30
- <span v-if="hasRightSlot" class="slot right-slot">
31
- <slot name="right"></slot>
32
- </span>
33
- </div>
34
- </template>
35
-
36
- <script setup lang="ts">
37
- import propValidators from '../c12/prop-validators';
38
-
39
- const props = defineProps({
40
- type: {
41
- type: String as PropType<'text' | 'email' | 'password' | 'number' | 'tel' | 'url'>,
42
- // type: String,
43
- default: 'text',
44
- validator(value: string) {
45
- return propValidators.inputTypesText.includes(value);
46
- },
47
- },
48
- inputmode: {
49
- type: String as PropType<'text' | 'email' | 'tel' | 'url' | 'search' | 'numeric' | 'none' | 'decimal'>,
50
- default: 'text',
51
- validator(value: string) {
52
- return propValidators.inputMode.includes(value);
53
- },
54
- },
55
- maxlength: {
56
- type: Number,
57
- default: 255,
58
- },
59
- id: {
60
- type: String,
61
- required: true,
62
- },
63
- name: {
64
- type: String,
65
- required: true,
66
- },
67
- required: {
68
- type: Boolean,
69
- default: false,
70
- },
71
- placeholder: {
72
- type: String,
73
- default: '',
74
- },
75
- fieldHasError: {
76
- type: Boolean,
77
- default: false,
78
- },
79
- styleClassPassthrough: {
80
- type: Array as PropType<string[]>,
81
- default: () => [],
82
- },
83
- theme: {
84
- type: String as PropType<string>,
85
- default: 'primary',
86
- validator(value: string) {
87
- return propValidators.theme.includes(value);
88
- },
89
- },
90
- ariaDescribedby: {
91
- type: String,
92
- default: null,
93
- },
94
- size: {
95
- type: String as PropType<string>,
96
- default: 'normal',
97
- validator(value: string) {
98
- return propValidators.size.includes(value);
99
- },
100
- },
101
- inputVariant: {
102
- type: String as PropType<string>,
103
- default: 'normal',
104
- validator(value: string) {
105
- return propValidators.inputVariant.includes(value);
106
- },
107
- },
108
- });
109
-
110
- const slots = useSlots();
111
- const hasLeftSlot = computed(() => slots.left !== undefined);
112
- const hasRightSlot = computed(() => slots.right !== undefined);
113
-
114
- const formTheme = computed(() => {
115
- return props.fieldHasError ? 'error' : props.theme;
116
- });
117
-
118
- const modelValue = defineModel();
119
- const isDirty = defineModel('isDirty');
120
- const isActive = defineModel('isActive');
121
-
122
- const inputPattern = computed(() => {
123
- return props.inputmode === 'numeric' ? '[0-9]+' : undefined;
124
- });
125
-
126
- const updateFocus = (isFocused: boolean) => {
127
- isActive.value = isFocused;
128
- };
129
-
130
- const inputField = ref<HTMLInputElement | null>(null);
131
-
132
- const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
133
-
134
- // TODO: Move this to a utility function to allow removeEventListener on unmounted
135
- // Leaving like this could lead to memory leaks
136
- const validateInput = () => {
137
- if (inputField.value !== null) {
138
- inputField.value.addEventListener('beforeinput', (event: any) => {
139
- let beforeValue = modelValue.value;
140
- event.target.addEventListener(
141
- 'input',
142
- () => {
143
- if (inputField.value !== null && inputField.value.validity.patternMismatch) {
144
- inputField.value.value = beforeValue as string;
145
- }
146
- },
147
- { once: true }
148
- );
149
- });
150
- }
151
- };
152
-
153
- onMounted(() => {
154
- if (props.inputmode === 'numeric') validateInput();
155
- });
156
- </script>
157
-
158
- <style lang="css">
159
- .input-text-wrapper {
160
- --_focus-box-shadow: var(--box-shadow-off);
161
- --_input-text-core-color: var(--theme-form-input-text-color-normal);
162
-
163
- --_input-text-wrapper-background-color: var(--theme-form-input-bg-normal);
164
-
165
- --_input-text-wrapper-border: var(--form-element-border-width) solid var(--theme-form-input-border);
166
- --_input-text-wrapper-border-radius: var(--form-input-border-radius);
167
-
168
- --_input-text-wrapper-outline: var(--form-element-outline-width) solid var(--theme-form-input-outline);
169
- --_input-text-wrapper-opacity: 1;
170
- --_input-text-wrapper-box-shadow: var(--_focus-box-shadow);
171
- --_input-text-wrapper-margin-inline: 0;
172
- --_input-text-wrapper-padding-block: 0;
173
-
174
- &.underlined {
175
- --_input-text-core-color: var(--theme-form-input-text-color-underlined);
176
- --_input-text-wrapper-background-color: transparent;
177
- --_input-text-wrapper-padding-block: 0.5rem;
178
- }
179
-
180
- &.outlined {
181
- --_input-text-wrapper-margin-inline: 1px;
182
- --_input-text-wrapper-background-color: var(--theme-form-input-bg-outlined);
183
- }
184
-
185
- &.normal {
186
- &:focus-within {
187
- --_input-text-wrapper-box-shadow: var(--box-shadow-on);
188
- --_input-text-wrapper-outline: var(--form-element-outline-width) solid hsl(from var(--theme-form-input-outline-focus) h s 90%);
189
- }
190
- }
191
-
192
- &:not(.normal) {
193
- --_input-text-wrapper-border: none;
194
- --_input-text-wrapper-box-shadow: none;
195
- --_input-text-wrapper-outline: none;
196
- --_input-text-wrapper-opacity: 0;
197
-
198
- &:focus {
199
- --_input-text-wrapper-border: none;
200
- --_input-text-wrapper-box-shadow: none;
201
- --_input-text-wrapper-outline: none;
202
- --_input-text-wrapper-background-color: transparent;
203
- }
204
-
205
- &:focus-within {
206
- --_input-text-wrapper-border: none;
207
- --_input-text-wrapper-box-shadow: none;
208
- --_input-text-wrapper-outline: none;
209
- --_input-text-wrapper-background-color: transparent;
210
- }
211
-
212
- &.active,
213
- &.dirty {
214
- --_input-text-wrapper-border: none;
215
- --_input-text-wrapper-box-shadow: none;
216
- --_input-text-wrapper-outline: none;
217
- --_input-text-wrapper-background-color: transparent;
218
-
219
- --_input-text-wrapper-opacity: 1;
220
- }
221
- }
222
-
223
- display: flex;
224
- align-items: center;
225
-
226
- background-color: var(--_input-text-wrapper-background-color);
227
- border-radius: var(--_input-text-wrapper-border-radius);
228
- border: var(--_input-text-wrapper-border);
229
- outline: var(--_input-text-wrapper-outline);
230
- box-shadow: var(--_input-text-wrapper-box-shadow);
231
- opacity: var(--_input-text-wrapper-opacity);
232
-
233
- margin-inline: var(--_input-text-wrapper-margin-inline);
234
- padding-block: var(--_input-text-wrapper-padding-block);
235
-
236
- &:not(.normal) {
237
- transition: opacity 0.2s ease-in-out;
238
- }
239
-
240
- &:not(:has(.input-button-core)) {
241
- .slot {
242
- display: inline-block;
243
-
244
- .icon {
245
- color: var(--_input-text-core-color);
246
- aspect-ratio: 1;
247
- height: var(--form-icon-size);
248
- width: var(--form-icon-size);
249
- margin: 0 !important;
250
- padding: 0 !important;
251
- }
252
- }
253
- }
254
-
255
- &.has-left-slot {
256
- .left-slot {
257
- display: flex;
258
- align-items: center;
259
- margin-inline-start: 1rem;
260
- }
261
- }
262
-
263
- &.has-right-slot {
264
- .right-slot {
265
- display: flex;
266
- align-items: center;
267
- margin-inline-end: 1rem;
268
- }
269
- }
270
-
271
- .input-text-core {
272
- background-color: transparent;
273
- border: none;
274
- outline: none;
275
- box-shadow: none;
276
- flex-grow: 1;
277
-
278
- color: var(--_input-text-core-color);
279
- font-family: var(--font-family);
280
- font-size: var(--form-element-font-size);
281
- line-height: var(--form-element-line-height);
282
-
283
- padding-inline: var(--form-text-padding-inline);
284
- padding-block-start: var(--form-element-padding-block-start);
285
- padding-block-end: var(--form-element-padding-block-end);
286
-
287
- &::placeholder,
288
- &::-webkit-input-placeholder {
289
- font-family: var(--font-family);
290
- font-size: var(--form-element-font-size);
291
- font-style: italic;
292
- font-weight: 400;
293
- }
294
- }
295
-
296
- &:has(.has-left-button),
297
- &:has(.has-right-button) {
298
- .slot {
299
- .input-button-core {
300
- border: initial;
301
- border-radius: 0;
302
- outline: initial;
303
- box-shadow: unset;
304
- }
305
- }
306
-
307
- .left-slot {
308
- margin-inline-end: 0;
309
- border-right: 2px solid var(--theme-btn-bg-hover);
310
- }
311
-
312
- .right-slot {
313
- margin-inline-end: 0;
314
- border-left: 2px solid var(--theme-btn-bg-hover);
315
- }
316
- }
317
- }
318
-
319
- input:autofill,
320
- input:-internal-autofill-selected,
321
- input:-webkit-autofill-strong-password,
322
- input:-webkit-autofill-strong-password-viewable,
323
- input:-webkit-autofill-and-obscured {
324
- background-color: var(--theme-form-input-bg-normal) !important;
325
- background-image: none !important;
326
- color: var(--_input-text-core-color) !important;
327
- -webkit-box-shadow: 0 0 0rem 1000px var(--theme-form-input-bg-normal) inset;
328
- -webkit-text-fill-color: var(--_input-text-core-color);
329
- transition: background-color 5000s ease-in-out 0s;
330
- }
331
- </style>
@@ -1,130 +0,0 @@
1
- <template>
2
- <InputTextWithLabel
3
- v-model="modelValue"
4
- :data-form-theme="formTheme"
5
- :type="inputType"
6
- :maxlength
7
- :name
8
- :placeholder
9
- :label
10
- :errorMessage
11
- :fieldHasError
12
- :required
13
- :styleClassPassthrough
14
- :theme
15
- :size
16
- :inputVariant
17
- >
18
- <template #right>
19
- <InputButtonCore
20
- type="button"
21
- @click.stop.prevent="toggleDisplayPassword"
22
- :is-pending="false"
23
- :buttonText
24
- :theme="buttonTheme"
25
- :size
26
- @focusin="updateFocus(name, true)"
27
- @focusout="updateFocus(name, false)"
28
- >
29
- <template #iconOnly>
30
- <Icon v-if="displayPassword" name="radix-icons:eye-none" class="icon" />
31
- <Icon v-else name="radix-icons:eye-open" class="icon" />
32
- </template>
33
- </InputButtonCore>
34
- </template>
35
- </InputTextWithLabel>
36
- </template>
37
-
38
- <script setup lang="ts">
39
- import propValidators from '../../c12/prop-validators';
40
-
41
- const props = defineProps({
42
- type: {
43
- type: String as PropType<'text' | 'password'>,
44
- default: 'password',
45
- },
46
- maxlength: {
47
- type: Number,
48
- default: 255,
49
- },
50
- name: {
51
- type: String,
52
- required: true,
53
- },
54
- placeholder: {
55
- type: String,
56
- default: '',
57
- },
58
- label: {
59
- type: String,
60
- required: true,
61
- },
62
- errorMessage: {
63
- type: [Object, String],
64
- required: true,
65
- },
66
- fieldHasError: {
67
- type: Boolean,
68
- default: false,
69
- },
70
- required: {
71
- type: Boolean,
72
- default: false,
73
- },
74
- styleClassPassthrough: {
75
- type: Array as PropType<string[]>,
76
- default: () => [],
77
- },
78
- theme: {
79
- type: String as PropType<string>,
80
- default: 'primary',
81
- validator(value: string) {
82
- return propValidators.theme.includes(value);
83
- },
84
- },
85
- size: {
86
- type: String as PropType<string>,
87
- default: 'medium',
88
- validator(value: string) {
89
- return propValidators.size.includes(value);
90
- },
91
- },
92
- inputVariant: {
93
- type: String as PropType<string>,
94
- default: 'normal',
95
- validator(value: string) {
96
- return propValidators.inputVariant.includes(value);
97
- },
98
- },
99
- });
100
-
101
- const formTheme = computed(() => {
102
- return props.fieldHasError ? 'error' : props.theme;
103
- });
104
-
105
- const buttonTheme = computed(() => {
106
- return props.inputVariant === 'underlined' ? 'input-action-underlined' : 'input-action';
107
- });
108
-
109
- const modelValue = defineModel();
110
-
111
- const { elementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
112
-
113
- const updateFocus = (name: string, isFocused: boolean) => {
114
- // console.log('updateFocus', name, isFocused);
115
- // modelValue.value.focusedField = isFocused ? name : '';
116
- };
117
-
118
- const inputType = ref<'text' | 'password'>(props.type);
119
-
120
- const displayPassword = ref(false);
121
- const buttonText = computed(() => {
122
- inputType.value = displayPassword.value ? 'text' : 'password';
123
- return displayPassword.value ? 'Hide password' : 'Show password';
124
- });
125
- const toggleDisplayPassword = () => {
126
- displayPassword.value = !displayPassword.value;
127
- };
128
-
129
- updateElementClasses(['has-right-button']);
130
- </script>
@@ -1,187 +0,0 @@
1
- <template>
2
- <div class="input-text-with-label" :data-form-theme="formTheme" :class="[inputVariant, elementClasses, { dirty: isDirty }, { active: isActive }]">
3
- <label :for="id" class="input-text-label body-normal-bold">{{ label }}</label>
4
-
5
- <div v-if="hasDescriptionSlot" :id="`${id}-description`">
6
- <slot name="description"></slot>
7
- </div>
8
-
9
- <InputTextCore
10
- v-model="modelValue"
11
- v-model:isDirty="isDirty"
12
- v-model:isActive="isActive"
13
- type="text"
14
- :maxlength
15
- :id
16
- :name
17
- :placeholder
18
- :label
19
- :errorMessage
20
- :fieldHasError
21
- :required
22
- :styleClassPassthrough
23
- :theme
24
- inputmode="numeric"
25
- :ariaDescribedby
26
- :size
27
- :inputVariant
28
- >
29
- <template v-if="hasLeftSlot" #left>
30
- <InputButtonCore
31
- type="button"
32
- @click.stop.prevent="updateValue(-step, Number(modelValue) > min)"
33
- :readonly="Number(modelValue) <= min"
34
- :is-pending="false"
35
- buttonText="Step down"
36
- theme="input-action"
37
- :size
38
- >
39
- <template #iconOnly>
40
- <slot name="left"></slot>
41
- </template>
42
- </InputButtonCore>
43
- </template>
44
- <template v-if="hasRightSlot" #right>
45
- <InputButtonCore
46
- type="button"
47
- @click.stop.prevent="updateValue(step, Number(modelValue) < max)"
48
- :readonly="Number(modelValue) >= max"
49
- :is-pending="false"
50
- buttonText="Step up"
51
- theme="input-action"
52
- :size
53
- >
54
- <template #iconOnly>
55
- <slot name="right"></slot>
56
- </template>
57
- </InputButtonCore>
58
- </template>
59
- </InputTextCore>
60
- <InputError :errorMessage :showError="fieldHasError" :id="errorId" :isDetached="true" />
61
- </div>
62
- </template>
63
-
64
- <script setup lang="ts">
65
- import propValidators from '../../c12/prop-validators';
66
- const props = defineProps({
67
- maxlength: {
68
- type: Number,
69
- default: 255,
70
- },
71
- name: {
72
- type: String,
73
- required: true,
74
- },
75
- placeholder: {
76
- type: String,
77
- default: '',
78
- },
79
- label: {
80
- type: String,
81
- required: true,
82
- },
83
- errorMessage: {
84
- type: [Object, String],
85
- required: true,
86
- },
87
- fieldHasError: {
88
- type: Boolean,
89
- default: false,
90
- },
91
- required: {
92
- type: Boolean,
93
- default: false,
94
- },
95
- styleClassPassthrough: {
96
- type: Array as PropType<string[]>,
97
- default: () => [],
98
- },
99
- theme: {
100
- type: String as PropType<string>,
101
- default: 'primary',
102
- validator(value: string) {
103
- return propValidators.theme.includes(value);
104
- },
105
- },
106
- min: {
107
- type: Number,
108
- required: true,
109
- },
110
- max: {
111
- type: Number,
112
- required: true,
113
- },
114
- step: {
115
- type: Number,
116
- default: 1,
117
- },
118
- size: {
119
- type: String as PropType<string>,
120
- default: 'normal',
121
- validator(value: string) {
122
- return propValidators.size.includes(value);
123
- },
124
- },
125
- inputVariant: {
126
- type: String as PropType<string>,
127
- default: 'normal',
128
- validator(value: string) {
129
- return propValidators.inputVariant.includes(value);
130
- },
131
- },
132
- });
133
-
134
- const slots = useSlots();
135
- const hasDescriptionSlot = computed(() => slots.description !== undefined);
136
- const hasLeftSlot = computed(() => slots.left !== undefined);
137
- const hasRightSlot = computed(() => slots.right !== undefined);
138
-
139
- const formTheme = computed(() => {
140
- return props.fieldHasError ? 'error' : props.theme;
141
- });
142
-
143
- const id = useId();
144
- const errorId = `${id}-error-message`;
145
- const ariaDescribedby = computed(() => {
146
- const ariaDescribedbyId = hasDescriptionSlot.value ? `${id}-description` : undefined;
147
- return props.fieldHasError ? errorId : ariaDescribedbyId;
148
- });
149
-
150
- const modelValue = defineModel();
151
- const isActive = ref<boolean>(false);
152
- const isDirty = ref<boolean>(false);
153
-
154
- const { elementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
155
- const minLength = computed(() => `${props.max.toString().length + 1}em`);
156
-
157
- const updateValue = (step: number, withinRangeLimit: boolean) => {
158
- if (withinRangeLimit) {
159
- modelValue.value = (Number(modelValue.value) + step) as number;
160
- }
161
- };
162
-
163
- updateElementClasses(['input-text-as-number', 'has-left-button', 'has-right-button']);
164
- </script>
165
-
166
- <style lang="css">
167
- .input-text-as-number {
168
- .input-text-wrapper {
169
- width: fit-content;
170
-
171
- &:has(.input-text-as-number) {
172
- .left-slot {
173
- margin-inline: 0;
174
- }
175
- .right-slot {
176
- margin-inline: 0;
177
- }
178
- }
179
-
180
- .input-text-core.input-text-as-number {
181
- flex-grow: initial;
182
- text-align: center;
183
- width: v-bind(minLength);
184
- }
185
- }
186
- }
187
- </style>