srcdev-nuxt-forms 0.1.0 → 1.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/assets/styles/brand/_brand.css +150 -0
  3. package/assets/styles/brand/_brand_dark.css +152 -0
  4. package/assets/styles/brand/_palette_dark.css +148 -0
  5. package/assets/styles/brand/_palette_light.css +148 -0
  6. package/assets/styles/brand/_typography.css +176 -0
  7. package/assets/styles/brand/index.css +1 -0
  8. package/assets/styles/forms/index.css +1 -1
  9. package/assets/styles/forms/themes/_default.css +3 -0
  10. package/assets/styles/forms/themes/_error.css +45 -11
  11. package/assets/styles/forms/themes/_ghost.css +42 -10
  12. package/assets/styles/forms/themes/_primary.css +42 -10
  13. package/assets/styles/forms/themes/_secondary.css +42 -10
  14. package/assets/styles/forms/themes/_success.css +42 -11
  15. package/assets/styles/forms/themes/_tertiary.css +42 -10
  16. package/assets/styles/forms/themes/_warning.css +42 -10
  17. package/assets/styles/forms/themes/index.css +1 -0
  18. package/assets/styles/forms/variables/_palette.css +104 -0
  19. package/assets/styles/forms/variables/_theme.css +12 -18
  20. package/assets/styles/forms/variables/index.css +2 -0
  21. package/assets/styles/main.css +2 -0
  22. package/assets/styles/scaffolding/_margin-helpers.css +308 -0
  23. package/assets/styles/scaffolding/_padding-helpers.css +308 -0
  24. package/assets/styles/scaffolding/_page.css +23 -0
  25. package/assets/styles/scaffolding/index.css +3 -0
  26. package/assets/styles/variables/colors/_blue.css +2 -2
  27. package/assets/styles/variables/colors/_gray.css +2 -1
  28. package/assets/styles/variables/colors/_green.css +2 -2
  29. package/assets/styles/variables/colors/_orange.css +2 -2
  30. package/assets/styles/variables/colors/_red.css +2 -2
  31. package/assets/styles/variables/colors/_yellow.css +1 -1
  32. package/components/forms/c12/prop-validators/index.ts +8 -20
  33. package/components/forms/c12/utils.ts +14 -0
  34. package/components/forms/c12/validation-patterns/en.json +12 -0
  35. package/components/forms/form-errors/InputError.vue +177 -0
  36. package/components/forms/input-button/InputButtonCore.vue +33 -109
  37. package/components/forms/input-button/variants/InputButtonConfirm.vue +1 -1
  38. package/components/forms/input-button/variants/InputButtonSubmit.vue +1 -1
  39. package/components/forms/input-checkbox/InputCheckboxCore.vue +263 -0
  40. package/components/forms/input-checkbox/InputCheckboxWithLabel.vue +116 -0
  41. package/components/forms/input-checkbox/variants/MultipleCheckboxes.vue +167 -0
  42. package/components/forms/input-checkbox/variants/SingleCheckbox.vue +172 -0
  43. package/components/forms/input-number/InputNumberCore.vue +184 -0
  44. package/components/forms/input-number/variants/InputNumberDefault.vue +155 -0
  45. package/components/forms/input-radio/InputRadiobuttonCore.vue +212 -0
  46. package/components/forms/input-radio/InputRadiobuttonWithLabel.vue +103 -0
  47. package/components/forms/input-radio/variants/MultipleRadiobuttons.vue +166 -0
  48. package/components/forms/input-range/InputRangeCore.vue +153 -0
  49. package/components/forms/input-range/variants/InputRangeDefault.vue +159 -0
  50. package/components/forms/input-text/InputTextCore.vue +149 -87
  51. package/components/forms/input-text/variants/material/InputPasswordWithLabel.vue +99 -0
  52. package/components/forms/input-text/variants/material/InputTextAsNumberWithLabel.vue +142 -0
  53. package/components/forms/input-text/variants/material/InputTextWithLabel.vue +125 -0
  54. package/components/forms/input-textarea/InputTextareaCore.vue +161 -0
  55. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +106 -0
  56. package/components/scaffolding/footer/NavFooter.vue +62 -0
  57. package/components/ui/content-grid/ContentGrid.vue +85 -0
  58. package/composables/useApiRequest.ts +25 -0
  59. package/composables/useErrorMessages.ts +17 -5
  60. package/composables/useFormControl.ts +149 -37
  61. package/composables/useSleep.ts +2 -2
  62. package/composables/useStyleClassPassthrough.ts +30 -0
  63. package/composables/useZodValidation.ts +120 -0
  64. package/layouts/default.vue +26 -16
  65. package/nuxt.config.ts +22 -0
  66. package/package.json +13 -8
  67. package/pages/forms/examples/buttons/index.vue +14 -13
  68. package/pages/forms/examples/material/cssbattle.vue +60 -0
  69. package/pages/forms/examples/material/text-fields.vue +551 -93
  70. package/pages/index.vue +2 -2
  71. package/pages/limit-text.vue +43 -0
  72. package/pages/typography.vue +83 -0
  73. package/server/api/places/list.get.ts +23 -0
  74. package/server/api/textFields.post.ts +37 -0
  75. package/server/api/utils/index.get.ts +20 -0
  76. package/server/data/places/cities.json +43 -0
  77. package/server/data/places/countries.json +55 -0
  78. package/server/data/utils/title.json +49 -0
  79. package/types/types.forms.ts +135 -3
  80. package/types/types.places.ts +8 -0
  81. package/types/types.zodFormControl.ts +21 -0
  82. package/components/forms/input-text/variants/material/InputEmailMaterial.vue +0 -72
  83. package/components/forms/input-text/variants/material/InputPasswordMaterial.vue +0 -88
  84. package/components/forms/input-text/variants/material/InputTextMaterial.vue +0 -75
  85. package/components/forms/input-text/variants/material/InputTextMaterialCore.vue +0 -258
  86. package/composables/useUpdateStyleClassPassthrough.ts +0 -29
  87. package/pages/forms/examples/material/text-fields-compact.vue +0 -136
@@ -0,0 +1,212 @@
1
+ <template>
2
+ <div class="input-radiobutton-wrapper" :data-form-theme="formTheme" :class="[size, checkboxAppearance, { error: fieldHasError }]">
3
+ <input
4
+ type="radio"
5
+ :true-value="trueValue"
6
+ :false-value="falseValue"
7
+ :id
8
+ :name
9
+ :required="required && !multipleOptions"
10
+ :value="trueValue"
11
+ :class="['input-radiobutton-core', size, checkboxAppearance, { error: fieldHasError }]"
12
+ v-model="modelValue"
13
+ ref="inputField"
14
+ />
15
+ <div v-if="checkboxAppearance === 'with-decorator'" :class="['input-radiobutton-decorator', size, checkboxStyle]">
16
+ <div v-if="checkboxStyle === 'check' || checkboxStyle === 'cross'" :class="[checkboxStyle, { checked: isChecked }]"></div>
17
+ </div>
18
+ </div>
19
+ </template>
20
+
21
+ <script setup lang="ts">
22
+ import propValidators from '../c12/prop-validators';
23
+ const { id, name, required, trueValue, falseValue, multipleOptions, theme, styleClassPassthrough, size, checkboxAppearance, checkboxStyle, fieldHasError } = defineProps({
24
+ id: {
25
+ type: String,
26
+ required: true,
27
+ },
28
+ name: {
29
+ type: String,
30
+ required: true,
31
+ },
32
+ required: {
33
+ type: Boolean,
34
+ value: false,
35
+ },
36
+ trueValue: {
37
+ type: [String, Number, Boolean],
38
+ default: true,
39
+ },
40
+ falseValue: {
41
+ type: [String, Number, Boolean],
42
+ default: false,
43
+ },
44
+ multipleOptions: {
45
+ type: Boolean,
46
+ default: false,
47
+ },
48
+ theme: {
49
+ type: String as PropType<string>,
50
+ default: 'primary',
51
+ validator(value: string) {
52
+ return propValidators.theme.includes(value);
53
+ },
54
+ },
55
+ size: {
56
+ type: String as PropType<string>,
57
+ default: 'medium',
58
+ validator(value: string) {
59
+ return propValidators.size.includes(value);
60
+ },
61
+ },
62
+ checkboxAppearance: {
63
+ type: String as PropType<string>,
64
+ default: null,
65
+ validator(value: string) {
66
+ return propValidators.checkboxAppearance.includes(value);
67
+ },
68
+ },
69
+ checkboxStyle: {
70
+ type: String as PropType<string>,
71
+ default: 'check',
72
+ validator(value: string) {
73
+ return propValidators.checkboxStyle.includes(value);
74
+ },
75
+ },
76
+ fieldHasError: {
77
+ type: Boolean,
78
+ default: false,
79
+ },
80
+ styleClassPassthrough: {
81
+ type: Array as PropType<string[]>,
82
+ default: () => [],
83
+ },
84
+ });
85
+
86
+ const slots = useSlots();
87
+ const hasLeftContent = computed(() => slots.left !== undefined);
88
+ const hasRightContent = computed(() => slots.right !== undefined);
89
+ const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
90
+
91
+ const formTheme = computed(() => {
92
+ return fieldHasError ? 'error' : theme;
93
+ });
94
+
95
+ const modelValue = defineModel<any>();
96
+
97
+ const inputField = ref<HTMLInputElement | null>(null);
98
+
99
+ const isArray = Array.isArray(modelValue.value);
100
+
101
+ const isChecked = computed(() => {
102
+ if (isArray) {
103
+ return modelValue.value.indexOf(trueValue) > -1;
104
+ } else {
105
+ return modelValue.value === trueValue;
106
+ }
107
+ });
108
+ </script>
109
+
110
+ <style scoped lang="css">
111
+ .input-radiobutton-wrapper {
112
+ --_checkbox-size: initial;
113
+ --_outline-width: var(--input-outline-width-thin);
114
+ --_border-width: var(--input-border-width-thin);
115
+
116
+ display: grid;
117
+ grid-template-areas: 'element-stack';
118
+
119
+ &.with-decorator {
120
+ border-radius: 50%;
121
+ border: var(--_border-width) solid var(--theme-form-input-border);
122
+ height: var(--_checkbox-size);
123
+ width: var(--_checkbox-size);
124
+ overflow: hidden;
125
+
126
+ &:has(.input-radiobutton-core:focus-visible) {
127
+ border: var(--_border-width) solid var(--theme-form-input-border-focus);
128
+ outline: var(--_outline-width) solid hsl(from var(--theme-form-input-outline-focus) h s 50%);
129
+ box-shadow: var(--theme-form-focus-box-shadow);
130
+ }
131
+ }
132
+
133
+ /* Sizes */
134
+ &.x-small {
135
+ --_checkbox-size: 20px;
136
+ }
137
+ &.small {
138
+ --_checkbox-size: 24px;
139
+ }
140
+ &.normal {
141
+ --_checkbox-size: 30px;
142
+ }
143
+ &.medium {
144
+ --_checkbox-size: 40px;
145
+ }
146
+ &.large {
147
+ --_checkbox-size: 44px;
148
+ }
149
+
150
+ .input-radiobutton-decorator {
151
+ --_padding: 5px;
152
+ display: grid;
153
+ grid-area: element-stack;
154
+ background-color: var(--theme-form-checkbox-bg);
155
+
156
+ place-content: center;
157
+ position: relative;
158
+ z-index: -1;
159
+
160
+ div {
161
+ grid-area: stack;
162
+ background-color: hsl(from var(--theme-form-radio-symbol) h s 50%);
163
+ width: calc(var(--_checkbox-size) - (var(--_padding) * 2));
164
+ height: calc(var(--_checkbox-size) - var(--_padding) * 2);
165
+ border: 1px solid var(--theme-form-input-border);
166
+ border-radius: 50%;
167
+ opacity: 0;
168
+ transition: opacity 0.2s ease-in-out;
169
+
170
+ &.checked {
171
+ opacity: 1;
172
+ }
173
+ }
174
+ }
175
+
176
+ .input-radiobutton-core {
177
+ grid-area: element-stack;
178
+ border: var(--_border-width) solid var(--theme-form-input-border);
179
+ height: var(--_checkbox-size);
180
+ width: var(--_checkbox-size);
181
+
182
+ transition: all 0.2s ease-in-out;
183
+
184
+ &.with-decorator {
185
+ appearance: none;
186
+ margin: 0;
187
+ overflow: hidden;
188
+ opacity: 0;
189
+ }
190
+
191
+ &:hover {
192
+ cursor: pointer;
193
+ }
194
+
195
+ /* &:focus-visible {
196
+ border-radius: var(--input-border-radius);
197
+ } */
198
+
199
+ &:focus {
200
+ border: var(--_border-width) solid var(--theme-form-input-border);
201
+ outline: var(--_outline-width) solid hsl(from var(--theme-form-input-outline) h s 50%);
202
+ }
203
+
204
+ &:checked::after {
205
+ display: grid;
206
+ font-family: var(--font-family);
207
+ place-content: center;
208
+ font-size: calc(var(--_checkbox-size) * 0.75);
209
+ }
210
+ }
211
+ }
212
+ </style>
@@ -0,0 +1,103 @@
1
+ <template>
2
+ <div class="input-radiobutton-with-label" :class="[elementClasses, { error: fieldHasError }]">
3
+ <InputRadiobuttonCore :id :name :required v-model="modelValue" :size :trueValue :falseValue :checkboxAppearance :checkboxStyle :fieldHasError :theme />
4
+ <label v-if="hasLabelContent" class="input-radiobutton-label body-normal" :for="id">
5
+ <slot name="labelContent"></slot>
6
+ </label>
7
+ <label v-else class="input-radiobutton-label body-normal-semibold" :for="id">{{ label }}</label>
8
+ </div>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import propValidators from '../c12/prop-validators';
13
+
14
+ const { id, name, label, required, fieldHasError, trueValue, falseValue, size, checkboxAppearance, checkboxStyle, styleClassPassthrough, theme } = defineProps({
15
+ id: {
16
+ type: String,
17
+ required: true,
18
+ },
19
+ name: {
20
+ type: String,
21
+ required: true,
22
+ },
23
+ label: {
24
+ type: String,
25
+ required: true,
26
+ },
27
+ required: {
28
+ type: Boolean,
29
+ default: false,
30
+ },
31
+ fieldHasError: {
32
+ type: Boolean,
33
+ default: false,
34
+ },
35
+ trueValue: {
36
+ type: [String, Number, Boolean],
37
+ default: true,
38
+ },
39
+ falseValue: {
40
+ type: [String, Number, Boolean],
41
+ default: false,
42
+ },
43
+ size: {
44
+ type: String as PropType<string>,
45
+ default: 'medium',
46
+ validator(value: string) {
47
+ return propValidators.size.includes(value);
48
+ },
49
+ },
50
+ checkboxAppearance: {
51
+ type: String as PropType<string>,
52
+ default: null,
53
+ validator(value: string) {
54
+ return propValidators.checkboxAppearance.includes(value);
55
+ },
56
+ },
57
+ checkboxStyle: {
58
+ type: String as PropType<string>,
59
+ default: 'check',
60
+ validator(value: string) {
61
+ return propValidators.checkboxStyle.includes(value);
62
+ },
63
+ },
64
+ styleClassPassthrough: {
65
+ type: Array as PropType<string[]>,
66
+ default: () => [],
67
+ },
68
+ theme: {
69
+ type: String as PropType<string>,
70
+ default: 'primary',
71
+ validator(value: string) {
72
+ return propValidators.theme.includes(value);
73
+ },
74
+ },
75
+ });
76
+
77
+ const slots = useSlots();
78
+ const hasLabelContent = computed(() => slots.labelContent !== undefined);
79
+ const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
80
+
81
+ const modelValue = defineModel();
82
+ </script>
83
+
84
+ <style lang="css">
85
+ .input-radiobutton-with-label {
86
+ display: grid;
87
+ align-items: center;
88
+ grid-template-columns: auto 1fr;
89
+
90
+ .input-radiobutton-label {
91
+ display: flex;
92
+ width: 100%;
93
+ height: 100%;
94
+ align-items: center;
95
+ margin-block: 8px;
96
+ padding-inline: 8px;
97
+
98
+ &:hover {
99
+ cursor: pointer;
100
+ }
101
+ }
102
+ }
103
+ </style>
@@ -0,0 +1,166 @@
1
+ <template>
2
+ <fieldset class="multiple-radiobuttons-fieldset" :class="[{ error: fieldHasError }]">
3
+ <legend :class="[{ 'has-description': hasDescription }]">{{ legend }}</legend>
4
+ <template v-if="hasDescription">
5
+ <slot name="description"></slot>
6
+ </template>
7
+ <div class="multiple-radiobuttons-items" :class="[optionsLayout]">
8
+ <template v-for="item in fieldData.data" :key="item.id">
9
+ <InputRadiobuttonWithLabel
10
+ :id="item.value"
11
+ :name="item.name"
12
+ :required
13
+ :label="item.label"
14
+ :fieldHasError
15
+ v-model="modelValue"
16
+ :true-value="item.value"
17
+ :size
18
+ :checkboxAppearance
19
+ :checkboxStyle
20
+ :theme
21
+ />
22
+ </template>
23
+ </div>
24
+ <InputError :errorMessage="errorMessage" :fieldHasError :id="name" :isDetached="true" />
25
+ </fieldset>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import propValidators from '../../c12/prop-validators';
30
+ import type { IOptionsConfig, IFormMultipleOptions } from '@/types/types.forms';
31
+
32
+ import type { C12nMultipleCheckboxes, IFormFieldC12, IFormData } from '@/types/types.forms';
33
+
34
+ const { id, name, legend, label, required, fieldHasError, placeholder, errorMessage, size, optionsLayout, equalCols, checkboxAppearance, checkboxStyle, styleClassPassthrough, theme } = defineProps({
35
+ id: {
36
+ type: String,
37
+ required: true,
38
+ },
39
+ name: {
40
+ type: String,
41
+ required: true,
42
+ },
43
+ legend: {
44
+ type: String,
45
+ required: true,
46
+ },
47
+ label: {
48
+ type: String,
49
+ required: true,
50
+ },
51
+ placeholder: {
52
+ type: String,
53
+ default: '',
54
+ },
55
+ errorMessage: {
56
+ type: [Object, String],
57
+ required: true,
58
+ },
59
+ required: {
60
+ type: Boolean,
61
+ default: false,
62
+ },
63
+ fieldHasError: {
64
+ type: Boolean,
65
+ default: false,
66
+ },
67
+ multipleOptions: {
68
+ type: Boolean,
69
+ default: false,
70
+ },
71
+ size: {
72
+ type: String as PropType<string>,
73
+ default: 'medium',
74
+ validator(value: string) {
75
+ return propValidators.size.includes(value);
76
+ },
77
+ },
78
+ optionsLayout: {
79
+ type: String as PropType<string>,
80
+ default: 'equal-widths',
81
+ validator(value: string) {
82
+ return propValidators.optionsLayout.includes(value);
83
+ },
84
+ },
85
+ equalCols: {
86
+ type: Boolean,
87
+ default: true,
88
+ },
89
+ checkboxAppearance: {
90
+ type: String as PropType<string>,
91
+ default: null,
92
+ validator(value: string) {
93
+ return propValidators.checkboxAppearance.includes(value);
94
+ },
95
+ },
96
+ checkboxStyle: {
97
+ type: String as PropType<string>,
98
+ default: 'check',
99
+ validator(value: string) {
100
+ return propValidators.checkboxStyle.includes(value);
101
+ },
102
+ },
103
+ styleClassPassthrough: {
104
+ type: Array as PropType<string[]>,
105
+ default: () => [],
106
+ },
107
+ theme: {
108
+ type: String as PropType<string>,
109
+ default: 'primary',
110
+ validator(value: string) {
111
+ return propValidators.theme.includes(value);
112
+ },
113
+ },
114
+ });
115
+
116
+ const slots = useSlots();
117
+ const hasDescription = computed(() => slots.description !== undefined);
118
+ const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
119
+
120
+ const modelValue = defineModel();
121
+ const fieldData = defineModel('fieldData') as Ref<IFormMultipleOptions>;
122
+ </script>
123
+
124
+ <style lang="css">
125
+ .multiple-radiobuttons-fieldset {
126
+ margin: 0;
127
+ padding: 0;
128
+ border: 0;
129
+
130
+ legend {
131
+ font-family: var(--font-family);
132
+ font-size: 16px;
133
+ font-weight: 500;
134
+
135
+ &.has-description {
136
+ margin-bottom: 0;
137
+ }
138
+ }
139
+
140
+ .label-description {
141
+ font-family: var(--font-family);
142
+ font-size: 16px;
143
+ margin-top: 12px;
144
+ }
145
+ }
146
+
147
+ .multiple-radiobuttons-items {
148
+ display: flex;
149
+ gap: 12px;
150
+ margin-top: 12px;
151
+
152
+ &.inline {
153
+ flex-direction: row;
154
+ flex-wrap: wrap;
155
+ }
156
+
157
+ &.block {
158
+ flex-direction: column;
159
+ }
160
+
161
+ &.equal-widths {
162
+ display: grid;
163
+ grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
164
+ }
165
+ }
166
+ </style>
@@ -0,0 +1,153 @@
1
+ <template>
2
+ <div class="input-range-wrapper" :data-form-theme="formTheme">
3
+ <div v-if="hasLeftContent" class="slot left">
4
+ <slot name="left"></slot>
5
+ </div>
6
+
7
+ <div class="input-range-container">
8
+ <input
9
+ type="range"
10
+ :id
11
+ :name
12
+ :required
13
+ :min
14
+ :max
15
+ :step
16
+ :list="hasDataList ? name + '-datalist' : ''"
17
+ :class="['input-range-core', `input-range--${size}`, `input-range--${weight}`, styleClassPassthrough]"
18
+ v-model="modelValue"
19
+ ref="inputField"
20
+ />
21
+
22
+ <template v-if="hasDataList">
23
+ <slot name="datalist"></slot>
24
+ </template>
25
+ </div>
26
+ <div v-if="hasRightContent" class="slot right">
27
+ <slot name="right"></slot>
28
+ </div>
29
+ </div>
30
+ </template>
31
+
32
+ <script setup lang="ts">
33
+ import propValidators from '../c12/prop-validators';
34
+
35
+ const { id, name, required, min, max, step, theme, size, weight, styleClassPassthrough, fieldHasError } = defineProps({
36
+ id: {
37
+ type: String,
38
+ required: true,
39
+ },
40
+ name: {
41
+ type: String,
42
+ required: true,
43
+ },
44
+ min: {
45
+ type: Number,
46
+ required: true,
47
+ },
48
+ max: {
49
+ type: Number,
50
+ required: true,
51
+ },
52
+ step: {
53
+ type: Number,
54
+ default: 1,
55
+ },
56
+ placeholder: {
57
+ type: String,
58
+ default: '',
59
+ },
60
+ required: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
64
+ theme: {
65
+ type: String as PropType<string>,
66
+ default: 'primary',
67
+ validator(value: string) {
68
+ return propValidators.theme.includes(value);
69
+ },
70
+ },
71
+ size: {
72
+ type: String as PropType<string>,
73
+ default: 'medium',
74
+ validator(value: string) {
75
+ return propValidators.size.includes(value);
76
+ },
77
+ },
78
+ weight: {
79
+ type: String as PropType<string>,
80
+ default: 'wght-400',
81
+ validator(value: string) {
82
+ return propValidators.weight.includes(value);
83
+ },
84
+ },
85
+ fieldHasError: {
86
+ type: Boolean,
87
+ default: false,
88
+ },
89
+ styleClassPassthrough: {
90
+ type: String,
91
+ default: '',
92
+ },
93
+ });
94
+
95
+ const slots = useSlots();
96
+ const hasDataList = computed(() => slots.datalist !== undefined);
97
+ const hasLeftContent = computed(() => slots.left !== undefined);
98
+ const hasRightContent = computed(() => slots.right !== undefined);
99
+
100
+ const formTheme = computed(() => {
101
+ return fieldHasError ? 'error' : theme;
102
+ });
103
+
104
+ const modelValue = defineModel<number | readonly number[]>();
105
+ </script>
106
+
107
+ <style lang="css">
108
+ .input-range-wrapper {
109
+ --_gutter: 12px;
110
+ --_border-width: var(--input-border-width-thin);
111
+ --_outline-width: var(--input-outline-width-thin);
112
+
113
+ --_input-range-height: 24px;
114
+ --_slot-translate-y: calc(var(--_input-range-height) / 4);
115
+
116
+ display: flex;
117
+ align-items: center;
118
+ justify-content: space-between;
119
+ gap: 10px;
120
+
121
+ .slot {
122
+ align-self: flex-start;
123
+ transform: translateY(-4px);
124
+ }
125
+
126
+ .input-range-container {
127
+ flex-grow: 1;
128
+ .input-range-core {
129
+ height: var(--_input-range-height);
130
+ margin: 0;
131
+ width: 100%;
132
+
133
+ &:focus-visible {
134
+ box-shadow: var(--theme-form-focus-box-shadow);
135
+ }
136
+ }
137
+
138
+ .input-range-datalist {
139
+ display: flex;
140
+ flex-direction: column;
141
+ font-family: var(--font-family);
142
+ font-size: 14px;
143
+ font-weight: 500;
144
+ justify-content: space-between;
145
+ writing-mode: vertical-lr;
146
+ width: 100%;
147
+ option {
148
+ padding: 0;
149
+ }
150
+ }
151
+ }
152
+ }
153
+ </style>