srcdev-nuxt-forms 6.1.0 → 6.1.2
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/app/assets/styles/extends-layer/srcdev-forms/components/_input-description.css +13 -0
- package/app/assets/styles/extends-layer/srcdev-forms/components/index.css +10 -9
- package/app/assets/styles/setup/theming/themes/_default.css +3 -0
- package/app/assets/styles/setup/theming/themes/_error.css +4 -1
- package/app/assets/styles/setup/theming/themes/_secondary.css +4 -1
- package/app/assets/styles/setup/theming/themes/_success.css +4 -1
- package/app/assets/styles/setup/theming/themes/_warning.css +4 -1
- package/app/assets/styles/setup/utility-classes/_margin.css +334 -0
- package/app/assets/styles/setup/utility-classes/_padding.css +308 -0
- package/app/assets/styles/setup/utility-classes/index.css +4 -2
- package/app/components/forms/form-fieldset/FormFieldset.vue +19 -10
- package/app/components/forms/input-button/InputButtonCore.vue +25 -28
- package/app/components/forms/input-checkbox/MultipleCheckboxes.vue +48 -38
- package/app/components/forms/input-checkbox/SingleCheckbox.vue +52 -33
- package/app/components/forms/input-checkbox-radio/InputCheckboxRadioButton.vue +40 -22
- package/app/components/forms/input-checkbox-radio/InputCheckboxRadioWithLabel.vue +33 -17
- package/app/components/forms/input-description/InputDescription.vue +71 -0
- package/app/components/forms/input-label/InputLabel.vue +14 -12
- package/app/components/forms/input-number/InputNumberCore.vue +26 -22
- package/app/components/forms/input-number/variants/InputNumberDefault.vue +50 -27
- package/app/components/forms/input-radio/MultipleRadiobuttons.vue +31 -25
- package/app/components/forms/input-range/InputRangeCore.vue +30 -28
- package/app/components/forms/input-range/variants/InputRangeDefault.vue +45 -28
- package/app/components/forms/input-range-fancy/InputRangeFancyWithLabel.vue +31 -18
- package/app/components/forms/input-select/variants/InputSelectWithLabel.vue +80 -45
- package/app/components/forms/input-text/InputTextCore.vue +4 -6
- package/app/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +42 -33
- package/app/components/forms/input-text/variants/InputTextWithLabel.vue +83 -50
- package/app/components/forms/input-textarea/InputTextareaCore.vue +34 -25
- package/app/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +100 -50
- package/app/components/forms/toggle-switch/ToggleSwitchCore.vue +43 -25
- package/app/components/forms/toggle-switch/ToggleSwitchCoreOld.vue +36 -22
- package/app/components/forms/toggle-switch/variants/ToggleSwitchWithLabel.vue +42 -25
- package/app/components/forms/toggle-switch/variants/ToggleSwitchWithLabelInline.vue +30 -26
- package/package.json +1 -1
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
4
|
-
|
|
3
|
+
<div
|
|
4
|
+
class="input-select-with-label"
|
|
5
|
+
:class="[inputVariant, { dirty: isDirty }, { active: isActive }, { error: fieldHasError }]"
|
|
6
|
+
:data-testid
|
|
7
|
+
:data-theme="formTheme"
|
|
8
|
+
:data-size="size"
|
|
9
|
+
>
|
|
10
|
+
<InputLabel
|
|
11
|
+
:for="id"
|
|
12
|
+
:id
|
|
13
|
+
:theme
|
|
14
|
+
:name
|
|
15
|
+
:input-variant
|
|
16
|
+
:field-has-error
|
|
17
|
+
:style-class-passthrough="['input-select-label']"
|
|
18
|
+
>
|
|
5
19
|
<template #textLabel>{{ label }}</template>
|
|
6
20
|
</InputLabel>
|
|
7
21
|
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
<InputDescription
|
|
23
|
+
v-if="inputVariant !== 'outlined'"
|
|
24
|
+
:id
|
|
25
|
+
:name
|
|
26
|
+
:input-variant
|
|
27
|
+
:field-has-error="fieldHasError"
|
|
28
|
+
:style-class-passthrough="['input-text-description']"
|
|
29
|
+
>
|
|
30
|
+
<template v-if="slots.descriptionHtml" #descriptionHtml>
|
|
31
|
+
<slot name="descriptionHtml"></slot>
|
|
32
|
+
</template>
|
|
33
|
+
<template v-if="slots.descriptionText" #descriptionText>
|
|
34
|
+
<slot name="descriptionText"></slot>
|
|
35
|
+
</template>
|
|
36
|
+
</InputDescription>
|
|
11
37
|
|
|
12
38
|
<InputSelectCore
|
|
13
39
|
v-model="modelValue"
|
|
@@ -17,31 +43,49 @@
|
|
|
17
43
|
:id
|
|
18
44
|
:name
|
|
19
45
|
:placeholder
|
|
20
|
-
:
|
|
46
|
+
:field-has-error
|
|
21
47
|
:required
|
|
22
|
-
:
|
|
48
|
+
:style-class-passthrough
|
|
23
49
|
:theme="formTheme"
|
|
24
|
-
:
|
|
50
|
+
:aria-describedby
|
|
25
51
|
:size
|
|
26
|
-
:
|
|
52
|
+
:input-variant
|
|
27
53
|
/>
|
|
28
54
|
|
|
29
|
-
<InputError
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
55
|
+
<InputError
|
|
56
|
+
:errorMessage="errorMessage"
|
|
57
|
+
:showError="fieldHasError"
|
|
58
|
+
:id="errorId"
|
|
59
|
+
:isDetached="false"
|
|
60
|
+
:inputVariant
|
|
61
|
+
/>
|
|
33
62
|
</div>
|
|
63
|
+
<InputDescription
|
|
64
|
+
v-if="inputVariant === 'outlined'"
|
|
65
|
+
:id
|
|
66
|
+
:name
|
|
67
|
+
:input-variant
|
|
68
|
+
:field-has-error="fieldHasError"
|
|
69
|
+
:style-class-passthrough="['input-text-description']"
|
|
70
|
+
>
|
|
71
|
+
<template v-if="slots.descriptionHtml" #descriptionHtml>
|
|
72
|
+
<slot name="descriptionHtml"></slot>
|
|
73
|
+
</template>
|
|
74
|
+
<template v-if="slots.descriptionText" #descriptionText>
|
|
75
|
+
<slot name="descriptionText"></slot>
|
|
76
|
+
</template>
|
|
77
|
+
</InputDescription>
|
|
34
78
|
</div>
|
|
35
79
|
</template>
|
|
36
80
|
|
|
37
81
|
<script setup lang="ts">
|
|
38
|
-
import propValidators from
|
|
39
|
-
import type { IFormMultipleOptions } from
|
|
82
|
+
import propValidators from "../../c12/prop-validators"
|
|
83
|
+
import type { IFormMultipleOptions } from "../../../../../shared/types/types.forms"
|
|
40
84
|
|
|
41
85
|
const props = defineProps({
|
|
42
86
|
dataTestid: {
|
|
43
87
|
type: String,
|
|
44
|
-
default:
|
|
88
|
+
default: "input-select-with-label",
|
|
45
89
|
},
|
|
46
90
|
name: {
|
|
47
91
|
type: String,
|
|
@@ -53,7 +97,7 @@ const props = defineProps({
|
|
|
53
97
|
},
|
|
54
98
|
placeholder: {
|
|
55
99
|
type: String,
|
|
56
|
-
default:
|
|
100
|
+
default: "",
|
|
57
101
|
},
|
|
58
102
|
errorMessage: {
|
|
59
103
|
type: [Object, String],
|
|
@@ -69,9 +113,9 @@ const props = defineProps({
|
|
|
69
113
|
},
|
|
70
114
|
size: {
|
|
71
115
|
type: String as PropType<string>,
|
|
72
|
-
default:
|
|
116
|
+
default: "medium",
|
|
73
117
|
validator(value: string) {
|
|
74
|
-
return propValidators.size.includes(value)
|
|
118
|
+
return propValidators.size.includes(value)
|
|
75
119
|
},
|
|
76
120
|
},
|
|
77
121
|
styleClassPassthrough: {
|
|
@@ -80,44 +124,35 @@ const props = defineProps({
|
|
|
80
124
|
},
|
|
81
125
|
theme: {
|
|
82
126
|
type: String as PropType<string>,
|
|
83
|
-
default:
|
|
127
|
+
default: "primary",
|
|
84
128
|
validator(value: string) {
|
|
85
|
-
return propValidators.theme.includes(value)
|
|
129
|
+
return propValidators.theme.includes(value)
|
|
86
130
|
},
|
|
87
131
|
},
|
|
88
132
|
inputVariant: {
|
|
89
133
|
type: String as PropType<string>,
|
|
90
|
-
default:
|
|
134
|
+
default: "normal",
|
|
91
135
|
validator(value: string) {
|
|
92
|
-
return propValidators.inputVariant.includes(value)
|
|
136
|
+
return propValidators.inputVariant.includes(value)
|
|
93
137
|
},
|
|
94
138
|
},
|
|
95
|
-
})
|
|
139
|
+
})
|
|
96
140
|
|
|
97
|
-
const slots = useSlots()
|
|
98
|
-
const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
99
|
-
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
141
|
+
const slots = useSlots()
|
|
100
142
|
|
|
101
143
|
const formTheme = computed(() => {
|
|
102
|
-
return props.fieldHasError ?
|
|
103
|
-
})
|
|
144
|
+
return props.fieldHasError ? "error" : props.theme
|
|
145
|
+
})
|
|
104
146
|
|
|
105
|
-
const id = `${props.name}-${useId()}
|
|
106
|
-
const errorId = `${
|
|
147
|
+
const id = `${props.name}-${useId()}`
|
|
148
|
+
const errorId = `${id}-error-message`
|
|
107
149
|
const ariaDescribedby = computed(() => {
|
|
108
|
-
const ariaDescribedbyId =
|
|
109
|
-
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
110
|
-
})
|
|
150
|
+
const ariaDescribedbyId = slots.descriptionText || slots.descriptionHtml ? `${id}-description` : undefined
|
|
151
|
+
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
152
|
+
})
|
|
111
153
|
|
|
112
|
-
const modelValue = defineModel({ required: true })
|
|
113
|
-
const isDirty = defineModel(
|
|
114
|
-
const isActive = defineModel(
|
|
115
|
-
const fieldData = defineModel(
|
|
154
|
+
const modelValue = defineModel({ required: true })
|
|
155
|
+
const isDirty = defineModel("isDirty")
|
|
156
|
+
const isActive = defineModel("isActive")
|
|
157
|
+
const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>
|
|
116
158
|
</script>
|
|
117
|
-
|
|
118
|
-
<style lang="css">
|
|
119
|
-
.input-select-with-label {
|
|
120
|
-
.input-select-label {
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
</style>
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
{ dirty: isDirty },
|
|
10
10
|
{ active: isActive },
|
|
11
11
|
{ error: fieldHasError },
|
|
12
|
-
{ 'has-left-slot':
|
|
13
|
-
{ 'has-right-slot':
|
|
12
|
+
{ 'has-left-slot': slots.left },
|
|
13
|
+
{ 'has-right-slot': slots.right },
|
|
14
14
|
]"
|
|
15
15
|
>
|
|
16
|
-
<span v-if="
|
|
16
|
+
<span v-if="slots.left" class="slot left-slot">
|
|
17
17
|
<slot name="left"></slot>
|
|
18
18
|
</span>
|
|
19
19
|
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
@focusout="updateFocus(false)"
|
|
36
36
|
/>
|
|
37
37
|
|
|
38
|
-
<span v-if="
|
|
38
|
+
<span v-if="slots.right" class="slot right-slot">
|
|
39
39
|
<slot name="right"></slot>
|
|
40
40
|
</span>
|
|
41
41
|
</div>
|
|
@@ -115,8 +115,6 @@ const props = defineProps({
|
|
|
115
115
|
})
|
|
116
116
|
|
|
117
117
|
const slots = useSlots()
|
|
118
|
-
const hasLeftSlot = computed(() => slots.left !== undefined)
|
|
119
|
-
const hasRightSlot = computed(() => slots.right !== undefined)
|
|
120
118
|
|
|
121
119
|
const formTheme = computed(() => {
|
|
122
120
|
return props.fieldHasError ? "error" : props.theme
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
|
|
2
|
+
<div
|
|
3
|
+
class="input-text-with-label"
|
|
4
|
+
:data-theme="formTheme"
|
|
5
|
+
:class="[inputVariant, elementClasses, { dirty: isDirty }, { active: isActive }]"
|
|
6
|
+
>
|
|
7
|
+
<InputLabel
|
|
8
|
+
:for="id"
|
|
9
|
+
:id
|
|
10
|
+
:theme
|
|
11
|
+
:name
|
|
12
|
+
:input-variant
|
|
13
|
+
:field-has-error
|
|
14
|
+
:style-class-passthrough="['input-text-label', 'body-normal-bold']"
|
|
15
|
+
>
|
|
4
16
|
<template #textLabel>{{ label }}</template>
|
|
5
17
|
</InputLabel>
|
|
6
18
|
|
|
7
|
-
<div v-if="
|
|
19
|
+
<div v-if="slots.description" :id="`${id}-description`">
|
|
8
20
|
<slot name="description"></slot>
|
|
9
21
|
</div>
|
|
10
22
|
|
|
@@ -28,7 +40,7 @@
|
|
|
28
40
|
:size
|
|
29
41
|
:inputVariant
|
|
30
42
|
>
|
|
31
|
-
<template v-if="
|
|
43
|
+
<template v-if="slots.left" #left>
|
|
32
44
|
<InputButtonCore
|
|
33
45
|
type="button"
|
|
34
46
|
@click.stop.prevent="updateValue(-step, Number(modelValue) > min)"
|
|
@@ -43,7 +55,7 @@
|
|
|
43
55
|
</template>
|
|
44
56
|
</InputButtonCore>
|
|
45
57
|
</template>
|
|
46
|
-
<template v-if="
|
|
58
|
+
<template v-if="slots.right" #right>
|
|
47
59
|
<InputButtonCore
|
|
48
60
|
type="button"
|
|
49
61
|
@click.stop.prevent="updateValue(step, Number(modelValue) < max)"
|
|
@@ -64,7 +76,7 @@
|
|
|
64
76
|
</template>
|
|
65
77
|
|
|
66
78
|
<script setup lang="ts">
|
|
67
|
-
import propValidators from
|
|
79
|
+
import propValidators from "../../c12/prop-validators"
|
|
68
80
|
const props = defineProps({
|
|
69
81
|
maxlength: {
|
|
70
82
|
type: Number,
|
|
@@ -76,7 +88,7 @@ const props = defineProps({
|
|
|
76
88
|
},
|
|
77
89
|
placeholder: {
|
|
78
90
|
type: String,
|
|
79
|
-
default:
|
|
91
|
+
default: "",
|
|
80
92
|
},
|
|
81
93
|
label: {
|
|
82
94
|
type: String,
|
|
@@ -100,9 +112,9 @@ const props = defineProps({
|
|
|
100
112
|
},
|
|
101
113
|
theme: {
|
|
102
114
|
type: String as PropType<string>,
|
|
103
|
-
default:
|
|
115
|
+
default: "primary",
|
|
104
116
|
validator(value: string) {
|
|
105
|
-
return propValidators.theme.includes(value)
|
|
117
|
+
return propValidators.theme.includes(value)
|
|
106
118
|
},
|
|
107
119
|
},
|
|
108
120
|
min: {
|
|
@@ -119,50 +131,47 @@ const props = defineProps({
|
|
|
119
131
|
},
|
|
120
132
|
size: {
|
|
121
133
|
type: String as PropType<string>,
|
|
122
|
-
default:
|
|
134
|
+
default: "default",
|
|
123
135
|
validator(value: string) {
|
|
124
|
-
return propValidators.size.includes(value)
|
|
136
|
+
return propValidators.size.includes(value)
|
|
125
137
|
},
|
|
126
138
|
},
|
|
127
139
|
inputVariant: {
|
|
128
140
|
type: String as PropType<string>,
|
|
129
|
-
default:
|
|
141
|
+
default: "normal",
|
|
130
142
|
validator(value: string) {
|
|
131
|
-
return propValidators.inputVariant.includes(value)
|
|
143
|
+
return propValidators.inputVariant.includes(value)
|
|
132
144
|
},
|
|
133
145
|
},
|
|
134
|
-
})
|
|
146
|
+
})
|
|
135
147
|
|
|
136
|
-
const slots = useSlots()
|
|
137
|
-
const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
138
|
-
const hasLeftSlot = computed(() => slots.left !== undefined);
|
|
139
|
-
const hasRightSlot = computed(() => slots.right !== undefined);
|
|
148
|
+
const slots = useSlots()
|
|
140
149
|
|
|
141
150
|
const formTheme = computed(() => {
|
|
142
|
-
return props.fieldHasError ?
|
|
143
|
-
})
|
|
151
|
+
return props.fieldHasError ? "error" : props.theme
|
|
152
|
+
})
|
|
144
153
|
|
|
145
|
-
const id = useId()
|
|
146
|
-
const errorId = `${id}-error-message
|
|
154
|
+
const id = useId()
|
|
155
|
+
const errorId = `${id}-error-message`
|
|
147
156
|
const ariaDescribedby = computed(() => {
|
|
148
|
-
const ariaDescribedbyId =
|
|
149
|
-
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
150
|
-
})
|
|
157
|
+
const ariaDescribedbyId = slots.description ? `${id}-description` : undefined
|
|
158
|
+
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
159
|
+
})
|
|
151
160
|
|
|
152
|
-
const modelValue = defineModel()
|
|
153
|
-
const isActive = ref<boolean>(false)
|
|
154
|
-
const isDirty = ref<boolean>(false)
|
|
161
|
+
const modelValue = defineModel()
|
|
162
|
+
const isActive = ref<boolean>(false)
|
|
163
|
+
const isDirty = ref<boolean>(false)
|
|
155
164
|
|
|
156
|
-
const { elementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
157
|
-
const minLength = computed(() => `${props.max.toString().length + 1}em`)
|
|
165
|
+
const { elementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
166
|
+
const minLength = computed(() => `${props.max.toString().length + 1}em`)
|
|
158
167
|
|
|
159
168
|
const updateValue = (step: number, withinRangeLimit: boolean) => {
|
|
160
169
|
if (withinRangeLimit) {
|
|
161
|
-
modelValue.value = (Number(modelValue.value) + step) as number
|
|
170
|
+
modelValue.value = (Number(modelValue.value) + step) as number
|
|
162
171
|
}
|
|
163
|
-
}
|
|
172
|
+
}
|
|
164
173
|
|
|
165
|
-
updateElementClasses([
|
|
174
|
+
updateElementClasses(["input-text-as-number", "has-left-button", "has-right-button"])
|
|
166
175
|
</script>
|
|
167
176
|
|
|
168
177
|
<style lang="css">
|
|
@@ -1,13 +1,37 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div>
|
|
3
|
-
<div
|
|
4
|
-
|
|
3
|
+
<div
|
|
4
|
+
class="input-text-with-label"
|
|
5
|
+
:data-theme="formTheme"
|
|
6
|
+
:class="[elementClasses, inputVariant, { dirty: isDirty }, { active: isActive }]"
|
|
7
|
+
>
|
|
8
|
+
<InputLabel
|
|
9
|
+
:for="id"
|
|
10
|
+
:id
|
|
11
|
+
:theme
|
|
12
|
+
:name
|
|
13
|
+
:input-variant
|
|
14
|
+
:field-has-error
|
|
15
|
+
:style-class-passthrough="['input-text-label']"
|
|
16
|
+
>
|
|
5
17
|
<template #textLabel>{{ label }}</template>
|
|
6
18
|
</InputLabel>
|
|
7
19
|
|
|
8
|
-
<
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
<InputDescription
|
|
21
|
+
v-if="inputVariant !== 'outlined'"
|
|
22
|
+
:id
|
|
23
|
+
:name
|
|
24
|
+
:input-variant
|
|
25
|
+
:field-has-error="fieldHasError"
|
|
26
|
+
:style-class-passthrough="['input-text-description']"
|
|
27
|
+
>
|
|
28
|
+
<template v-if="slots.descriptionHtml" #descriptionHtml>
|
|
29
|
+
<slot name="descriptionHtml"></slot>
|
|
30
|
+
</template>
|
|
31
|
+
<template v-if="slots.descriptionText" #descriptionText>
|
|
32
|
+
<slot name="descriptionText"></slot>
|
|
33
|
+
</template>
|
|
34
|
+
</InputDescription>
|
|
11
35
|
|
|
12
36
|
<InputTextCore
|
|
13
37
|
v-model="modelValue"
|
|
@@ -21,18 +45,18 @@
|
|
|
21
45
|
:placeholder
|
|
22
46
|
:label
|
|
23
47
|
:errorMessage
|
|
24
|
-
:
|
|
48
|
+
:field-has-error
|
|
25
49
|
:required
|
|
26
|
-
:
|
|
50
|
+
:style-class-passthrough
|
|
27
51
|
:theme
|
|
28
|
-
:
|
|
52
|
+
:aria-describedby
|
|
29
53
|
:size
|
|
30
|
-
:
|
|
54
|
+
:input-variant
|
|
31
55
|
>
|
|
32
|
-
<template v-if="
|
|
56
|
+
<template v-if="slots.left" #left>
|
|
33
57
|
<slot name="left"></slot>
|
|
34
58
|
</template>
|
|
35
|
-
<template v-if="
|
|
59
|
+
<template v-if="slots.right" #right>
|
|
36
60
|
<slot name="right"></slot>
|
|
37
61
|
</template>
|
|
38
62
|
</InputTextCore>
|
|
@@ -40,28 +64,40 @@
|
|
|
40
64
|
<InputError :errorMessage :showError="fieldHasError" :id="errorId" :isDetached="false" :inputVariant />
|
|
41
65
|
</div>
|
|
42
66
|
|
|
43
|
-
<
|
|
44
|
-
|
|
45
|
-
|
|
67
|
+
<InputDescription
|
|
68
|
+
v-if="inputVariant === 'outlined'"
|
|
69
|
+
:id
|
|
70
|
+
:name
|
|
71
|
+
:input-variant
|
|
72
|
+
:field-has-error="fieldHasError"
|
|
73
|
+
:style-class-passthrough="['input-text-description']"
|
|
74
|
+
>
|
|
75
|
+
<template v-if="slots.descriptionHtml" #descriptionHtml>
|
|
76
|
+
<slot name="descriptionHtml"></slot>
|
|
77
|
+
</template>
|
|
78
|
+
<template v-if="slots.descriptionText" #descriptionText>
|
|
79
|
+
<slot name="descriptionText"></slot>
|
|
80
|
+
</template>
|
|
81
|
+
</InputDescription>
|
|
46
82
|
</div>
|
|
47
83
|
</template>
|
|
48
84
|
|
|
49
85
|
<script setup lang="ts">
|
|
50
|
-
import propValidators from
|
|
86
|
+
import propValidators from "../../c12/prop-validators"
|
|
51
87
|
const props = defineProps({
|
|
52
88
|
maxlength: {
|
|
53
89
|
type: Number,
|
|
54
90
|
default: 255,
|
|
55
91
|
},
|
|
56
92
|
type: {
|
|
57
|
-
type: String as PropType<
|
|
93
|
+
type: String as PropType<"text" | "email" | "password" | "number" | "tel" | "url">,
|
|
58
94
|
required: true,
|
|
59
95
|
},
|
|
60
96
|
inputmode: {
|
|
61
|
-
type: String as PropType<
|
|
62
|
-
default:
|
|
97
|
+
type: String as PropType<"text" | "email" | "tel" | "url" | "search" | "numeric" | "none" | "decimal">,
|
|
98
|
+
default: "text",
|
|
63
99
|
validator(value: string) {
|
|
64
|
-
return propValidators.inputMode.includes(value)
|
|
100
|
+
return propValidators.inputMode.includes(value)
|
|
65
101
|
},
|
|
66
102
|
},
|
|
67
103
|
name: {
|
|
@@ -70,7 +106,7 @@ const props = defineProps({
|
|
|
70
106
|
},
|
|
71
107
|
placeholder: {
|
|
72
108
|
type: String,
|
|
73
|
-
default:
|
|
109
|
+
default: "",
|
|
74
110
|
},
|
|
75
111
|
label: {
|
|
76
112
|
type: String,
|
|
@@ -94,65 +130,62 @@ const props = defineProps({
|
|
|
94
130
|
},
|
|
95
131
|
theme: {
|
|
96
132
|
type: String as PropType<string>,
|
|
97
|
-
default:
|
|
133
|
+
default: "primary",
|
|
98
134
|
validator(value: string) {
|
|
99
|
-
return propValidators.theme.includes(value)
|
|
135
|
+
return propValidators.theme.includes(value)
|
|
100
136
|
},
|
|
101
137
|
},
|
|
102
138
|
size: {
|
|
103
139
|
type: String as PropType<string>,
|
|
104
|
-
default:
|
|
140
|
+
default: "default",
|
|
105
141
|
validator(value: string) {
|
|
106
|
-
return propValidators.size.includes(value)
|
|
142
|
+
return propValidators.size.includes(value)
|
|
107
143
|
},
|
|
108
144
|
},
|
|
109
145
|
inputVariant: {
|
|
110
146
|
type: String as PropType<string>,
|
|
111
|
-
default:
|
|
147
|
+
default: "normal",
|
|
112
148
|
validator(value: string) {
|
|
113
|
-
return propValidators.inputVariant.includes(value)
|
|
149
|
+
return propValidators.inputVariant.includes(value)
|
|
114
150
|
},
|
|
115
151
|
},
|
|
116
|
-
})
|
|
152
|
+
})
|
|
117
153
|
|
|
118
|
-
const slots = useSlots()
|
|
119
|
-
const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
120
|
-
const hasLeftSlot = computed(() => slots.left !== undefined);
|
|
121
|
-
const hasRightSlot = computed(() => slots.right !== undefined);
|
|
154
|
+
const slots = useSlots()
|
|
122
155
|
|
|
123
156
|
const formTheme = computed(() => {
|
|
124
|
-
return props.fieldHasError ?
|
|
125
|
-
})
|
|
157
|
+
return props.fieldHasError ? "error" : props.theme
|
|
158
|
+
})
|
|
126
159
|
|
|
127
|
-
const id = `${props.name}-${useId()}
|
|
128
|
-
const errorId = `${id}-error-message
|
|
160
|
+
const id = `${props.name}-${useId()}`
|
|
161
|
+
const errorId = `${id}-error-message`
|
|
129
162
|
const ariaDescribedby = computed(() => {
|
|
130
|
-
const ariaDescribedbyId =
|
|
131
|
-
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
132
|
-
})
|
|
163
|
+
const ariaDescribedbyId = slots.descriptionText || slots.descriptionHtml ? `${id}-description` : undefined
|
|
164
|
+
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
165
|
+
})
|
|
133
166
|
|
|
134
|
-
const modelValue = defineModel()
|
|
135
|
-
const isActive = ref<boolean>(false)
|
|
136
|
-
const isDirty = ref<boolean>(false)
|
|
167
|
+
const modelValue = defineModel()
|
|
168
|
+
const isActive = ref<boolean>(false)
|
|
169
|
+
const isDirty = ref<boolean>(false)
|
|
137
170
|
|
|
138
|
-
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
171
|
+
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
139
172
|
|
|
140
173
|
const testDirty = () => {
|
|
141
|
-
const watchValue = modelValue.value ??
|
|
174
|
+
const watchValue = modelValue.value ?? ""
|
|
142
175
|
|
|
143
|
-
if (!isDirty.value && typeof watchValue ===
|
|
144
|
-
isDirty.value = true
|
|
176
|
+
if (!isDirty.value && typeof watchValue === "string" && watchValue.length > 0) {
|
|
177
|
+
isDirty.value = true
|
|
145
178
|
}
|
|
146
|
-
}
|
|
179
|
+
}
|
|
147
180
|
|
|
148
181
|
onMounted(() => {
|
|
149
|
-
testDirty()
|
|
150
|
-
})
|
|
182
|
+
testDirty()
|
|
183
|
+
})
|
|
151
184
|
|
|
152
185
|
watch(
|
|
153
186
|
() => modelValue.value,
|
|
154
187
|
() => {
|
|
155
|
-
testDirty()
|
|
188
|
+
testDirty()
|
|
156
189
|
}
|
|
157
|
-
)
|
|
190
|
+
)
|
|
158
191
|
</script>
|