srcdev-nuxt-forms 3.0.0 → 4.1.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/assets/styles/ally/_utils.css +20 -0
  2. package/assets/styles/ally/_variables.css +8 -0
  3. package/assets/styles/ally/index.css +2 -0
  4. package/assets/styles/forms/index.css +2 -0
  5. package/assets/styles/forms/themes/_error.css +85 -0
  6. package/assets/styles/forms/themes/_ghost.css +85 -0
  7. package/assets/styles/forms/themes/_input-action-underlined.css +20 -0
  8. package/assets/styles/forms/themes/_input-action.css +20 -0
  9. package/assets/styles/forms/themes/_primary.css +92 -0
  10. package/assets/styles/forms/themes/_secondary.css +85 -0
  11. package/assets/styles/forms/themes/_success.css +85 -0
  12. package/assets/styles/forms/themes/_tertiary.css +85 -0
  13. package/assets/styles/forms/themes/_warning.css +85 -0
  14. package/assets/styles/forms/themes/index.css +9 -0
  15. package/assets/styles/forms/variables/_sizes.css +71 -0
  16. package/assets/styles/forms/variables/_theme.css +11 -0
  17. package/assets/styles/forms/variables/index.css +2 -0
  18. package/assets/styles/main.css +5 -0
  19. package/assets/styles/typography/index.css +2 -0
  20. package/assets/styles/typography/utils/_font-classes.css +190 -0
  21. package/assets/styles/typography/utils/_weights.css +69 -0
  22. package/assets/styles/typography/utils/index.css +2 -0
  23. package/assets/styles/typography/variables/_colors.css +14 -0
  24. package/assets/styles/typography/variables/_reponsive-font-size.css +10 -0
  25. package/assets/styles/typography/variables/index.css +2 -0
  26. package/assets/styles/utils/_margin-helpers.css +334 -0
  27. package/assets/styles/utils/_padding-helpers.css +308 -0
  28. package/assets/styles/utils/_page.css +49 -0
  29. package/assets/styles/utils/index.css +3 -0
  30. package/assets/styles/variables/colors/_blue.css +15 -0
  31. package/assets/styles/variables/colors/_gray.css +16 -0
  32. package/assets/styles/variables/colors/_green.css +15 -0
  33. package/assets/styles/variables/colors/_orange.css +15 -0
  34. package/assets/styles/variables/colors/_red.css +15 -0
  35. package/assets/styles/variables/colors/_yellow.css +15 -0
  36. package/assets/styles/variables/colors/colors.css +6 -0
  37. package/assets/styles/variables/index.css +1 -0
  38. package/components/forms/c12/prop-validators/index.ts +38 -0
  39. package/components/forms/c12/utils.ts +14 -0
  40. package/components/forms/form-errors/InputError.vue +172 -0
  41. package/components/forms/form-errors/tests/InputError.spec.ts +67 -0
  42. package/components/forms/input-button/InputButtonCore.vue +191 -0
  43. package/components/forms/input-button/variants/InputButtonConfirm.vue +66 -0
  44. package/components/forms/input-button/variants/InputButtonSubmit.vue +62 -0
  45. package/components/forms/input-checkbox/MultipleCheckboxes.vue +203 -0
  46. package/components/forms/input-checkbox/SingleCheckbox.vue +169 -0
  47. package/components/forms/input-checkbox/tests/MultipleCheckboxes.spec.ts +98 -0
  48. package/components/forms/input-checkbox/tests/data/tags.json +67 -0
  49. package/components/forms/input-checkbox-radio/InputCheckboxRadioButton.vue +214 -0
  50. package/components/forms/input-checkbox-radio/InputCheckboxRadioCore.vue +191 -0
  51. package/components/forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +111 -0
  52. package/components/forms/input-number/InputNumberCore.vue +203 -0
  53. package/components/forms/input-number/variants/InputNumberDefault.vue +154 -0
  54. package/components/forms/input-radio/MultipleRadiobuttons.vue +201 -0
  55. package/components/forms/input-radio/tests/MultipleRadioButtons.spec.ts +89 -0
  56. package/components/forms/input-radio/tests/data/tags.json +67 -0
  57. package/components/forms/input-range/InputRangeCore.vue +274 -0
  58. package/components/forms/input-range/variants/InputRangeDefault.vue +156 -0
  59. package/components/forms/input-range-fancy/InputRangeFancyCore.vue +450 -0
  60. package/components/forms/input-range-fancy/InputRangeFancyWithLabel.vue +124 -0
  61. package/components/forms/input-select/InputSelect.vue +289 -0
  62. package/components/forms/input-text/InputTextCore.vue +331 -0
  63. package/components/forms/input-text/variants/InputPasswordWithLabel.vue +130 -0
  64. package/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +187 -0
  65. package/components/forms/input-text/variants/InputTextWithLabel.vue +298 -0
  66. package/components/forms/input-textarea/InputTextareaCore.vue +234 -0
  67. package/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +267 -0
  68. package/components/forms/toggle-switch/ToggleSwitchCore.vue +198 -0
  69. package/components/forms/toggle-switch/ToggleSwitchCoreOld.vue +216 -0
  70. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +105 -0
  71. package/components/forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +102 -0
  72. package/components/forms/ui/FormField.vue +78 -0
  73. package/components/forms/ui/FormWrapper.vue +35 -0
  74. package/components/utils/colour-scheme-select/ColourSchemeSelect.vue +270 -0
  75. package/components/utils/colour-scheme-select/ColourSchemeSelectOld.vue +225 -0
  76. package/components/utils/dark-mode-switcher/DarkModeSwitcher.vue +47 -0
  77. package/composables/useApiRequest.ts +25 -0
  78. package/composables/useColourScheme.ts +25 -0
  79. package/composables/useErrorMessages.ts +59 -0
  80. package/composables/useFormControl.ts +248 -0
  81. package/composables/useSleep.ts +5 -0
  82. package/composables/useStyleClassPassthrough.ts +30 -0
  83. package/composables/useZodValidation.ts +148 -0
  84. package/nuxt.config.ts +0 -3
  85. package/package.json +1 -1
  86. package/types/types.forms.ts +217 -0
  87. package/types/types.zodFormControl.ts +21 -0
@@ -0,0 +1,130 @@
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>
@@ -0,0 +1,187 @@
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>
@@ -0,0 +1,298 @@
1
+ <template>
2
+ <div>
3
+ <div class="input-text-with-label" :data-form-theme="formTheme" :class="[elementClasses, inputVariant, { dirty: isDirty }, { active: isActive }]">
4
+ <label :for="id" class="input-text-label">{{ label }}</label>
5
+
6
+ <div v-if="inputVariant === 'normal' && hasDescriptionSlot" :id="`${id}-description`">
7
+ <slot name="description"></slot>
8
+ </div>
9
+
10
+ <InputTextCore
11
+ v-model="modelValue"
12
+ v-model:isDirty="isDirty"
13
+ v-model:isActive="isActive"
14
+ :type
15
+ :inputmode
16
+ :maxlength
17
+ :id
18
+ :name
19
+ :placeholder
20
+ :label
21
+ :errorMessage
22
+ :fieldHasError
23
+ :required
24
+ :styleClassPassthrough
25
+ :theme
26
+ :ariaDescribedby
27
+ :size
28
+ :inputVariant
29
+ >
30
+ <template v-if="hasLeftSlot" #left>
31
+ <slot name="left"></slot>
32
+ </template>
33
+ <template v-if="hasRightSlot" #right>
34
+ <slot name="right"></slot>
35
+ </template>
36
+ </InputTextCore>
37
+
38
+ <InputError :errorMessage :showError="fieldHasError" :id="errorId" :isDetached="false" :inputVariant />
39
+ </div>
40
+
41
+ <div v-if="inputVariant !== 'normal' && hasDescriptionSlot" :id="`${id}-description`">
42
+ <slot name="description"></slot>
43
+ </div>
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import propValidators from '../../c12/prop-validators';
49
+ const props = defineProps({
50
+ maxlength: {
51
+ type: Number,
52
+ default: 255,
53
+ },
54
+ type: {
55
+ type: String as PropType<'text' | 'email' | 'password' | 'number' | 'tel' | 'url'>,
56
+ required: true,
57
+ },
58
+ inputmode: {
59
+ type: String as PropType<'text' | 'email' | 'tel' | 'url' | 'search' | 'numeric' | 'none' | 'decimal'>,
60
+ default: 'text',
61
+ validator(value: string) {
62
+ return propValidators.inputMode.includes(value);
63
+ },
64
+ },
65
+ name: {
66
+ type: String,
67
+ required: true,
68
+ },
69
+ placeholder: {
70
+ type: String,
71
+ default: '',
72
+ },
73
+ label: {
74
+ type: String,
75
+ required: true,
76
+ },
77
+ errorMessage: {
78
+ type: [Object, String],
79
+ required: true,
80
+ },
81
+ fieldHasError: {
82
+ type: Boolean,
83
+ default: false,
84
+ },
85
+ required: {
86
+ type: Boolean,
87
+ default: false,
88
+ },
89
+ styleClassPassthrough: {
90
+ type: Array as PropType<string[]>,
91
+ default: () => [],
92
+ },
93
+ theme: {
94
+ type: String as PropType<string>,
95
+ default: 'primary',
96
+ validator(value: string) {
97
+ return propValidators.theme.includes(value);
98
+ },
99
+ },
100
+ size: {
101
+ type: String as PropType<string>,
102
+ default: 'normal',
103
+ validator(value: string) {
104
+ return propValidators.size.includes(value);
105
+ },
106
+ },
107
+ inputVariant: {
108
+ type: String as PropType<string>,
109
+ default: 'normal',
110
+ validator(value: string) {
111
+ return propValidators.inputVariant.includes(value);
112
+ },
113
+ },
114
+ });
115
+
116
+ const slots = useSlots();
117
+ const hasDescriptionSlot = computed(() => slots.description !== undefined);
118
+ const hasLeftSlot = computed(() => slots.left !== undefined);
119
+ const hasRightSlot = computed(() => slots.right !== undefined);
120
+
121
+ const formTheme = computed(() => {
122
+ return props.fieldHasError ? 'error' : props.theme;
123
+ });
124
+
125
+ const id = useId();
126
+ const errorId = `${id}-error-message`;
127
+ const ariaDescribedby = computed(() => {
128
+ const ariaDescribedbyId = hasDescriptionSlot.value ? `${id}-description` : undefined;
129
+ return props.fieldHasError ? errorId : ariaDescribedbyId;
130
+ });
131
+
132
+ const modelValue = defineModel();
133
+ const isActive = ref<boolean>(false);
134
+ const isDirty = ref<boolean>(false);
135
+
136
+ const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
137
+
138
+ const testDirty = () => {
139
+ const watchValue = modelValue.value ?? '';
140
+
141
+ if (!isDirty.value && typeof watchValue === 'string' && watchValue.length > 0) {
142
+ isDirty.value = true;
143
+ }
144
+ };
145
+
146
+ onMounted(() => {
147
+ testDirty();
148
+ });
149
+
150
+ watch(
151
+ () => modelValue.value,
152
+ () => {
153
+ testDirty();
154
+ }
155
+ );
156
+ </script>
157
+
158
+ <style lang="css">
159
+ .input-text-with-label {
160
+ --_input-text-with-label-margin-block-start: 0;
161
+ --_input-text-with-label-background-color: transparent;
162
+
163
+ --_input-text-wrapper-border: var(--form-element-border-width) solid var(--theme-form-input-border);
164
+ --_input-text-wrapper-border-radius: var(--form-input-border-radius);
165
+ --_input-text-wrapper-border-underlined: var(--form-element-border-width-underlined) solid var(--theme-form-input-border);
166
+ --_input-text-wrapper-outline: var(--form-element-outline-width) solid var(--theme-form-input-outline);
167
+ --_input-text-wrapper-box-shadow: var(--_focus-box-shadow);
168
+ --_input-text-wrapper-padding-block: 0;
169
+
170
+ --_focus-box-shadow: var(--box-shadow-off);
171
+
172
+ /* Label vars */
173
+ --_label-text-color: var(--theme-form-input-text-label-color-normal);
174
+ --_label-text-margin-block: 0.8rem;
175
+ --_label-text-size: var(--step-2);
176
+ --_label-text-weight: normal;
177
+ --_label-text-line-height: 1.5;
178
+ --_label-text-background-color: var(--_input-text-with-label-background-color);
179
+
180
+ &.underlined {
181
+ --_label-text-color: var(--theme-form-input-text-label-color-underlined);
182
+ --_label-offset: 1rem 0.2rem;
183
+ --_input-text-with-label-background-color: color-mix(in srgb, currentColor 5%, transparent);
184
+
185
+ --_input-text-wrapper-underlined-border-radius-top-left: 0;
186
+ --_input-text-wrapper-underlined-border-radius-top-right: 0;
187
+ --_input-text-wrapper-underlined-border-radius-bottom-left: 4px;
188
+ --_input-text-wrapper-underlined-border-radius-bottom-right: 4px;
189
+
190
+ --_label-text-background-color: transparent;
191
+
192
+ &:has(.input-text-wrapper.active),
193
+ &:has(.input-text-wrapper.dirty) {
194
+ --_label-offset: 0 -3.2rem;
195
+ --_label-text-weight: bolder;
196
+ --_label-text-size: var(--step-1);
197
+ /* line-height: 1.5; */
198
+ /* padding: 0.2rem 1.2rem; */
199
+ }
200
+ }
201
+
202
+ &.outlined {
203
+ --_label-text-color: var(--theme-form-input-text-label-color-outlined);
204
+
205
+ --_label-offset: 1rem -0.2rem;
206
+ --_input-text-with-label-background-color: var(--theme-form-input-bg-normal);
207
+
208
+ --_input-text-wrapper-padding-block: 0.4em 0;
209
+
210
+ &:has(.input-text-wrapper.active),
211
+ &:has(.input-text-wrapper.dirty) {
212
+ --_label-offset: 1rem -2.8rem;
213
+ --_label-text-weight: normal;
214
+ /* --_label-text-size: var(--step-1); */
215
+ /* line-height: 1.5; */
216
+ /* padding: 0.2rem 1.2rem; */
217
+ }
218
+ }
219
+
220
+ &:not(.normal) {
221
+ --_input-text-with-label-margin-block-start: 3em;
222
+
223
+ &:has(.input-text-wrapper.active),
224
+ &:has(.input-text-wrapper.dirty) {
225
+ /* --_label-offset: 1rem -2.8rem; */
226
+ /* font-size: var(--step-1); */
227
+ /* line-height: 1.5; */
228
+ /* padding: 0.2rem 1.2rem; */
229
+ }
230
+
231
+ &:focus-within {
232
+ --_input-text-wrapper-box-shadow: var(--box-shadow-on);
233
+ --_input-text-wrapper-outline: var(--form-element-outline-width) solid hsl(from var(--theme-form-input-outline-focus) h s 90%);
234
+ }
235
+ }
236
+
237
+ /*
238
+ * Apply generic styles
239
+ **/
240
+
241
+ background-color: var(--_input-text-with-label-background-color);
242
+ border-radius: var(--_input-text-wrapper-border-radius);
243
+
244
+ /* overflow: clip; */
245
+
246
+ &.underlined {
247
+ border-bottom: var(--_input-text-wrapper-border-underlined);
248
+ border-top-left-radius: var(--_input-text-wrapper-underlined-border-radius-top-left);
249
+ border-top-right-radius: var(--_input-text-wrapper-underlined-border-radius-top-right);
250
+ border-bottom-left-radius: var(--_input-text-wrapper-underlined-border-radius-bottom-left);
251
+ border-bottom-right-radius: var(--_input-text-wrapper-underlined-border-radius-bottom-right);
252
+ }
253
+
254
+ &.outlined {
255
+ border: var(--_input-text-wrapper-border);
256
+ outline: var(--_input-text-wrapper-outline);
257
+ box-shadow: var(--_input-text-wrapper-box-shadow);
258
+ padding-block: var(--_input-text-wrapper-padding-block);
259
+ }
260
+
261
+ &:not(.normal) {
262
+ display: grid;
263
+ grid-template-columns: 1fr;
264
+ grid-template-rows: 1fr;
265
+ grid-template-areas: 'underlined-text-stack';
266
+
267
+ margin-block-start: var(--_input-text-with-label-margin-block-start);
268
+
269
+ .input-text-label {
270
+ grid-area: underlined-text-stack;
271
+ z-index: 2;
272
+ }
273
+ .input-text-wrapper {
274
+ grid-area: underlined-text-stack;
275
+ z-index: 1;
276
+ }
277
+ }
278
+
279
+ .input-text-label {
280
+ display: inline-block;
281
+ color: var(--_label-text-color);
282
+ background-color: var(--_label-text-background-color);
283
+ margin-block: var(--_label-text-margin-block);
284
+ font-size: var(--_label-text-size);
285
+ font-weight: var(--_label-text-weight);
286
+ line-height: var(--_label-text-line-height);
287
+ translate: var(--_label-offset);
288
+ width: fit-content;
289
+ height: fit-content;
290
+ transition: font-size 0.2s ease-in-out, translate 0.2s ease-in-out;
291
+
292
+ &:not(.normal) {
293
+ display: flex;
294
+ align-items: center;
295
+ }
296
+ }
297
+ }
298
+ </style>