srcdev-nuxt-forms 6.0.1 → 6.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -5
- package/app/assets/styles/extends-layer/srcdev-forms/components/_form-fieldset.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-button.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-core.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-checkbox-radio-options-button.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-error.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-label.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-select.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-text.css +1 -1
- package/app/assets/styles/extends-layer/srcdev-forms/components/_input-textarea.css +1 -1
- package/app/assets/styles/setup/_head.css +1 -1
- package/app/assets/styles/setup/typography/vars/_reponsive-font-sizes.css +10 -10
- package/app/assets/styles/setup/typography/vars/index.css +0 -1
- 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 -27
- 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-label/InputLabel.vue +10 -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 +48 -37
- package/app/components/forms/input-text/InputTextCore.vue +56 -52
- package/app/components/forms/input-text/variants/InputTextAsNumberWithLabel.vue +42 -33
- package/app/components/forms/input-text/variants/InputTextWithLabel.vue +51 -42
- package/app/components/forms/input-textarea/InputTextareaCore.vue +29 -24
- package/app/components/forms/input-textarea/variants/InputTextareaWithLabel.vue +41 -31
- 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/nuxt.config.ts +11 -11
- package/package.json +2 -2
- package/app/assets/styles/setup/typography/vars/_colors.css +0 -14
- package/app/assets/styles/setup/variables/index.css +0 -1
package/README.md
CHANGED
|
@@ -83,18 +83,58 @@ Styles exist for multiple themes/variants, primary, secondary, tertiary, error e
|
|
|
83
83
|
|
|
84
84
|
Colour scheme can be updated by modifying the css colour variables
|
|
85
85
|
|
|
86
|
-
##
|
|
86
|
+
## Styles Architecture
|
|
87
87
|
|
|
88
|
-
|
|
88
|
+
The `/app/assets/styles` folder contains the CSS architecture for this Nuxt layer, organized into two main directories:
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
### `/app/assets/styles/setup/`
|
|
91
|
+
|
|
92
|
+
This directory contains the foundational styles that will be mirrored in any app that extends this layer. It includes:
|
|
93
|
+
|
|
94
|
+
- **`index.css`** - Main setup file that imports all setup modules
|
|
95
|
+
- **`_head.css`** - Head-level styles and document setup
|
|
96
|
+
- **`a11y/`** - Accessibility utilities and variables
|
|
97
|
+
- **`theming/`** - Theme definitions, color schemes, and theme variants
|
|
98
|
+
- **`typography/`** - Typography setup, font definitions, and text utility classes
|
|
99
|
+
- **`utility-classes/`** - General utility classes including fluid spacing and animations
|
|
100
|
+
|
|
101
|
+
These styles form the base layer and will be automatically available in any app that extends this layer.
|
|
102
|
+
|
|
103
|
+
### `/app/assets/styles/extends-layer/srcdev-forms/`
|
|
104
|
+
|
|
105
|
+
This directory contains override styles specifically for apps that extend this layer. It includes:
|
|
106
|
+
|
|
107
|
+
- **`index.css`** - Main override file
|
|
108
|
+
- **`components/`** - Component-specific overrides
|
|
109
|
+
- **`setup/`** - Setup overrides for extended apps
|
|
110
|
+
|
|
111
|
+
This folder structure will also be present in the extending app's assets directory, allowing for easy customization and theming.
|
|
112
|
+
|
|
113
|
+
### Layer Override Namespace
|
|
114
|
+
|
|
115
|
+
To enable proper CSS override functionality, the extending app must include the `srcdev-forms-extended` class namespace:
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
// nuxt.config.ts in the extending app
|
|
119
|
+
export default defineNuxtConfig({
|
|
120
|
+
extends: 'srcdev-nuxt-forms',
|
|
91
121
|
app: {
|
|
92
122
|
head: {
|
|
93
123
|
htmlAttrs: {
|
|
94
|
-
class: '
|
|
124
|
+
class: 'srcdev-forms-extended',
|
|
95
125
|
},
|
|
96
126
|
},
|
|
97
127
|
},
|
|
128
|
+
});
|
|
98
129
|
```
|
|
99
130
|
|
|
100
|
-
|
|
131
|
+
**Important:** All override CSS files in the extending app's `~/assets/styles/extends-layer/srcdev-forms/` directory must use the `.srcdev-forms-extended` class as a namespace prefix to ensure proper specificity and override behavior.
|
|
132
|
+
|
|
133
|
+
Example override structure in the extending app:
|
|
134
|
+
|
|
135
|
+
```css
|
|
136
|
+
/* ~/assets/styles/extends-layer/srcdev-forms/components/button.css */
|
|
137
|
+
.srcdev-forms-extended .btn-primary {
|
|
138
|
+
/* Your custom button styles */
|
|
139
|
+
}
|
|
140
|
+
```
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
:root {
|
|
2
|
-
--step-10: clamp(4.0311rem, 3.36rem + 3.3555vw, 5.9605rem);
|
|
3
|
-
--step-9: clamp(3.3592rem, 2.8691rem + 2.4507vw, 4.7684rem);
|
|
4
|
-
--step-8: clamp(2.7994rem, 2.4462rem + 1.7658vw, 3.8147rem);
|
|
5
|
-
--step-7: clamp(2.3328rem, 2.0827rem + 1.2504vw, 3.0518rem);
|
|
6
|
-
--step-6: clamp(1.944rem, 1.771rem + 0.8651vw, 2.4414rem);
|
|
7
|
-
--step-5: clamp(1.62rem, 1.5041rem + 0.5793vw, 1.9531rem);
|
|
8
|
-
--step-4: clamp(1.35rem, 1.2761rem + 0.3696vw, 1.5625rem);
|
|
9
|
-
--step-3: clamp(1.125rem, 1.0815rem + 0.2174vw, 1.25rem);
|
|
10
|
-
--step-2: clamp(0.9375rem, 0.9158rem + 0.1087vw, 1rem);
|
|
11
|
-
--step-1: clamp(0.7813rem, 0.7747rem + 0.0326vw, 0.8rem);
|
|
2
|
+
--step-10: clamp(4.0311rem, 3.36rem + 3.3555vw, 5.9605rem);
|
|
3
|
+
--step-9: clamp(3.3592rem, 2.8691rem + 2.4507vw, 4.7684rem);
|
|
4
|
+
--step-8: clamp(2.7994rem, 2.4462rem + 1.7658vw, 3.8147rem);
|
|
5
|
+
--step-7: clamp(2.3328rem, 2.0827rem + 1.2504vw, 3.0518rem);
|
|
6
|
+
--step-6: clamp(1.944rem, 1.771rem + 0.8651vw, 2.4414rem);
|
|
7
|
+
--step-5: clamp(1.62rem, 1.5041rem + 0.5793vw, 1.9531rem);
|
|
8
|
+
--step-4: clamp(1.35rem, 1.2761rem + 0.3696vw, 1.5625rem);
|
|
9
|
+
--step-3: clamp(1.125rem, 1.0815rem + 0.2174vw, 1.25rem);
|
|
10
|
+
--step-2: clamp(0.9375rem, 0.9158rem + 0.1087vw, 1rem);
|
|
11
|
+
--step-1: clamp(0.7813rem, 0.7747rem + 0.0326vw, 0.8rem);
|
|
12
12
|
}
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<fieldset
|
|
3
|
-
|
|
2
|
+
<fieldset
|
|
3
|
+
:aria-required="required"
|
|
4
|
+
:aria-invalid="fieldHasError"
|
|
5
|
+
role="radiogroup"
|
|
6
|
+
:id
|
|
7
|
+
:name
|
|
8
|
+
class="form-fieldset"
|
|
9
|
+
:class="[elementClasses, { error: fieldHasError }]"
|
|
10
|
+
:data-testid="dataTestid"
|
|
11
|
+
>
|
|
12
|
+
<legend v-if="legend" class="form-fieldset-legend" :class="[{ 'has-description': slots.description }]">
|
|
4
13
|
<slot name="legend">{{ legend }}</slot>
|
|
5
14
|
</legend>
|
|
6
15
|
|
|
7
|
-
<div v-if="
|
|
16
|
+
<div v-if="slots.description" class="form-fieldset-description" :id="`${id}-description`">
|
|
8
17
|
<slot name="description"></slot>
|
|
9
18
|
</div>
|
|
10
19
|
|
|
@@ -28,7 +37,7 @@ const props = defineProps({
|
|
|
28
37
|
},
|
|
29
38
|
legend: {
|
|
30
39
|
type: String,
|
|
31
|
-
default:
|
|
40
|
+
default: "",
|
|
32
41
|
},
|
|
33
42
|
required: {
|
|
34
43
|
type: Boolean,
|
|
@@ -40,18 +49,18 @@ const props = defineProps({
|
|
|
40
49
|
},
|
|
41
50
|
dataTestid: {
|
|
42
51
|
type: String,
|
|
43
|
-
default:
|
|
52
|
+
default: "",
|
|
44
53
|
},
|
|
45
54
|
styleClassPassthrough: {
|
|
46
55
|
type: Array as PropType<string[]>,
|
|
47
56
|
default: () => [],
|
|
48
57
|
},
|
|
49
|
-
})
|
|
58
|
+
})
|
|
50
59
|
|
|
51
|
-
const slots = useSlots()
|
|
52
|
-
const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
53
|
-
const hasDescription = computed(() => slots.description !== undefined)
|
|
54
|
-
const { elementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
60
|
+
const slots = useSlots()
|
|
61
|
+
// const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
62
|
+
const hasDescription = computed(() => slots.description !== undefined)
|
|
63
|
+
const { elementClasses, updateElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
55
64
|
</script>
|
|
56
65
|
|
|
57
66
|
<style lang="css">
|
|
@@ -7,21 +7,21 @@
|
|
|
7
7
|
:data-theme="theme"
|
|
8
8
|
:data-size="size"
|
|
9
9
|
class="input-button-core"
|
|
10
|
-
:class="[`btn-${type}`, effectClass, elementClasses, { 'icon-only':
|
|
10
|
+
:class="[`btn-${type}`, effectClass, elementClasses, { 'icon-only': slots.iconOnly }]"
|
|
11
11
|
>
|
|
12
12
|
<span v-if="useEffect && effect == 'fancy'" class="fancy"></span>
|
|
13
|
-
<template v-if="
|
|
13
|
+
<template v-if="slots.left && !slots.iconOnly">
|
|
14
14
|
<span class="btn-icon left">
|
|
15
15
|
<slot name="left"></slot>
|
|
16
16
|
</span>
|
|
17
17
|
</template>
|
|
18
|
-
<span class="btn-text" :class="[weight, { 'sr-only':
|
|
19
|
-
<template v-if="
|
|
18
|
+
<span class="btn-text" :class="[weight, { 'sr-only': slots.iconOnly }]">{{ buttonText }}</span>
|
|
19
|
+
<template v-if="slots.right && !slots.iconOnly">
|
|
20
20
|
<span class="btn-icon right">
|
|
21
21
|
<slot name="right"></slot>
|
|
22
22
|
</span>
|
|
23
23
|
</template>
|
|
24
|
-
<template v-if="
|
|
24
|
+
<template v-if="slots.iconOnly">
|
|
25
25
|
<span class="btn-icon icon-only">
|
|
26
26
|
<slot name="iconOnly"></slot>
|
|
27
27
|
</span>
|
|
@@ -30,35 +30,35 @@
|
|
|
30
30
|
</template>
|
|
31
31
|
|
|
32
32
|
<script setup lang="ts">
|
|
33
|
-
import propValidators from
|
|
33
|
+
import propValidators from "../c12/prop-validators"
|
|
34
34
|
|
|
35
35
|
const props = defineProps({
|
|
36
36
|
size: {
|
|
37
37
|
type: String as PropType<string>,
|
|
38
|
-
default:
|
|
38
|
+
default: "default",
|
|
39
39
|
validator(value: string) {
|
|
40
|
-
return propValidators.size.includes(value)
|
|
40
|
+
return propValidators.size.includes(value)
|
|
41
41
|
},
|
|
42
42
|
},
|
|
43
43
|
weight: {
|
|
44
44
|
type: String as PropType<string>,
|
|
45
|
-
default:
|
|
45
|
+
default: "wght-400",
|
|
46
46
|
validator(value: string) {
|
|
47
|
-
return propValidators.weight.includes(value)
|
|
47
|
+
return propValidators.weight.includes(value)
|
|
48
48
|
},
|
|
49
49
|
},
|
|
50
50
|
theme: {
|
|
51
51
|
type: String as PropType<string>,
|
|
52
|
-
default:
|
|
52
|
+
default: "primary",
|
|
53
53
|
validator(value: string) {
|
|
54
|
-
return propValidators.theme.includes(value)
|
|
54
|
+
return propValidators.theme.includes(value)
|
|
55
55
|
},
|
|
56
56
|
},
|
|
57
57
|
type: {
|
|
58
|
-
type: String as PropType<
|
|
59
|
-
default:
|
|
58
|
+
type: String as PropType<"submit" | "button" | "reset">,
|
|
59
|
+
default: "button",
|
|
60
60
|
validator(value: string) {
|
|
61
|
-
return propValidators.inputTypesButton.includes(value)
|
|
61
|
+
return propValidators.inputTypesButton.includes(value)
|
|
62
62
|
},
|
|
63
63
|
},
|
|
64
64
|
buttonText: {
|
|
@@ -67,7 +67,7 @@ const props = defineProps({
|
|
|
67
67
|
},
|
|
68
68
|
dataTestid: {
|
|
69
69
|
type: String,
|
|
70
|
-
default:
|
|
70
|
+
default: "",
|
|
71
71
|
},
|
|
72
72
|
styleClassPassthrough: {
|
|
73
73
|
type: Array as PropType<string[]>,
|
|
@@ -79,9 +79,9 @@ const props = defineProps({
|
|
|
79
79
|
},
|
|
80
80
|
effect: {
|
|
81
81
|
type: String as PropType<string>,
|
|
82
|
-
default:
|
|
82
|
+
default: "fancy",
|
|
83
83
|
validator(value: string) {
|
|
84
|
-
return [
|
|
84
|
+
return ["fancy", "pulse"].includes(value)
|
|
85
85
|
},
|
|
86
86
|
},
|
|
87
87
|
isPending: {
|
|
@@ -92,23 +92,20 @@ const props = defineProps({
|
|
|
92
92
|
type: Boolean,
|
|
93
93
|
default: false,
|
|
94
94
|
},
|
|
95
|
-
})
|
|
95
|
+
})
|
|
96
96
|
|
|
97
|
-
const type = toRef(() => props.type)
|
|
97
|
+
const type = toRef(() => props.type)
|
|
98
98
|
const effectClass = computed(() => {
|
|
99
99
|
if (props.useEffect) {
|
|
100
|
-
return props.effect ===
|
|
100
|
+
return props.effect === "fancy" ? "" : props.effect
|
|
101
101
|
} else {
|
|
102
|
-
return
|
|
102
|
+
return ""
|
|
103
103
|
}
|
|
104
|
-
})
|
|
104
|
+
})
|
|
105
105
|
|
|
106
|
-
const slots = useSlots()
|
|
107
|
-
const hasLeftContent = computed(() => slots.left !== undefined);
|
|
108
|
-
const hasRightContent = computed(() => slots.right !== undefined);
|
|
109
|
-
const isIconOnly = computed(() => slots.iconOnly !== undefined);
|
|
106
|
+
const slots = useSlots()
|
|
110
107
|
|
|
111
|
-
const { elementClasses
|
|
108
|
+
const { elementClasses } = useStyleClassPassthrough(props.styleClassPassthrough)
|
|
112
109
|
</script>
|
|
113
110
|
|
|
114
111
|
<style lang="css">
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<FormFieldset
|
|
2
|
+
<FormFieldset
|
|
3
|
+
:id
|
|
4
|
+
:name
|
|
5
|
+
:legend
|
|
6
|
+
:fieldHasError
|
|
7
|
+
:required
|
|
8
|
+
:data-testid
|
|
9
|
+
:styleClassPassthrough="['multiple-checkboxes-fieldset']"
|
|
10
|
+
>
|
|
3
11
|
<template #description>
|
|
4
12
|
<slot name="description"></slot>
|
|
5
13
|
</template>
|
|
@@ -61,13 +69,29 @@
|
|
|
61
69
|
</template>
|
|
62
70
|
|
|
63
71
|
<script setup lang="ts">
|
|
64
|
-
import propValidators from
|
|
65
|
-
import type { IOptionsConfig, IFormMultipleOptions } from
|
|
72
|
+
import propValidators from "../c12/prop-validators"
|
|
73
|
+
import type { IOptionsConfig, IFormMultipleOptions } from "../../../../shared/types/types.forms"
|
|
66
74
|
|
|
67
|
-
const {
|
|
75
|
+
const {
|
|
76
|
+
dataTestid,
|
|
77
|
+
name,
|
|
78
|
+
legend,
|
|
79
|
+
label,
|
|
80
|
+
required,
|
|
81
|
+
fieldHasError,
|
|
82
|
+
placeholder,
|
|
83
|
+
isButton,
|
|
84
|
+
errorMessage,
|
|
85
|
+
size,
|
|
86
|
+
optionsLayout,
|
|
87
|
+
equalCols,
|
|
88
|
+
styleClassPassthrough,
|
|
89
|
+
theme,
|
|
90
|
+
direction,
|
|
91
|
+
} = defineProps({
|
|
68
92
|
dataTestid: {
|
|
69
93
|
type: String,
|
|
70
|
-
default:
|
|
94
|
+
default: "multiple-checkboxes",
|
|
71
95
|
},
|
|
72
96
|
name: {
|
|
73
97
|
type: String,
|
|
@@ -83,7 +107,7 @@ const { dataTestid, name, legend, label, required, fieldHasError, placeholder, i
|
|
|
83
107
|
},
|
|
84
108
|
placeholder: {
|
|
85
109
|
type: String,
|
|
86
|
-
default:
|
|
110
|
+
default: "",
|
|
87
111
|
},
|
|
88
112
|
isButton: {
|
|
89
113
|
type: Boolean,
|
|
@@ -107,16 +131,16 @@ const { dataTestid, name, legend, label, required, fieldHasError, placeholder, i
|
|
|
107
131
|
},
|
|
108
132
|
size: {
|
|
109
133
|
type: String as PropType<string>,
|
|
110
|
-
default:
|
|
134
|
+
default: "medium",
|
|
111
135
|
validator(value: string) {
|
|
112
|
-
return propValidators.size.includes(value)
|
|
136
|
+
return propValidators.size.includes(value)
|
|
113
137
|
},
|
|
114
138
|
},
|
|
115
139
|
optionsLayout: {
|
|
116
140
|
type: String as PropType<string>,
|
|
117
|
-
default:
|
|
141
|
+
default: "equal-widths",
|
|
118
142
|
validator(value: string) {
|
|
119
|
-
return propValidators.optionsLayout.includes(value)
|
|
143
|
+
return propValidators.optionsLayout.includes(value)
|
|
120
144
|
},
|
|
121
145
|
},
|
|
122
146
|
equalCols: {
|
|
@@ -129,38 +153,35 @@ const { dataTestid, name, legend, label, required, fieldHasError, placeholder, i
|
|
|
129
153
|
},
|
|
130
154
|
theme: {
|
|
131
155
|
type: String as PropType<string>,
|
|
132
|
-
default:
|
|
156
|
+
default: "primary",
|
|
133
157
|
validator(value: string) {
|
|
134
|
-
return propValidators.theme.includes(value)
|
|
158
|
+
return propValidators.theme.includes(value)
|
|
135
159
|
},
|
|
136
160
|
},
|
|
137
161
|
direction: {
|
|
138
|
-
type: String as PropType<
|
|
139
|
-
default:
|
|
162
|
+
type: String as PropType<"row" | "row-reverse">,
|
|
163
|
+
default: "row",
|
|
140
164
|
validator(value: string) {
|
|
141
|
-
return [
|
|
165
|
+
return ["row", "row-reverse"].includes(value)
|
|
142
166
|
},
|
|
143
167
|
},
|
|
144
168
|
displayAsDisc: {
|
|
145
169
|
type: Boolean,
|
|
146
170
|
default: false,
|
|
147
171
|
},
|
|
148
|
-
})
|
|
172
|
+
})
|
|
149
173
|
|
|
150
|
-
const slots = useSlots()
|
|
151
|
-
const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
152
|
-
const hasDescription = computed(() => slots.description !== undefined);
|
|
153
|
-
const { elementClasses, updateElementClasses } = useStyleClassPassthrough(styleClassPassthrough);
|
|
174
|
+
const slots = useSlots()
|
|
154
175
|
|
|
155
|
-
const modelValue = defineModel()
|
|
156
|
-
const fieldData = defineModel(
|
|
176
|
+
const modelValue = defineModel()
|
|
177
|
+
const fieldData = defineModel("fieldData") as Ref<IFormMultipleOptions>
|
|
157
178
|
|
|
158
|
-
const id = `${name}-input-${useId()}
|
|
159
|
-
const errorId = `${name}-error-message
|
|
179
|
+
const id = `${name}-input-${useId()}`
|
|
180
|
+
const errorId = `${name}-error-message`
|
|
160
181
|
const ariaDescribedby = computed(() => {
|
|
161
|
-
const ariaDescribedbyId =
|
|
162
|
-
return fieldHasError ? errorId : ariaDescribedbyId
|
|
163
|
-
})
|
|
182
|
+
const ariaDescribedbyId = slots.description ? `${name}-description` : undefined
|
|
183
|
+
return fieldHasError ? errorId : ariaDescribedbyId
|
|
184
|
+
})
|
|
164
185
|
</script>
|
|
165
186
|
|
|
166
187
|
<style lang="css">
|
|
@@ -1,33 +1,58 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<FormFieldset
|
|
2
|
+
<FormFieldset
|
|
3
|
+
:id
|
|
4
|
+
:name
|
|
5
|
+
:legend
|
|
6
|
+
:fieldHasError
|
|
7
|
+
:required
|
|
8
|
+
:data-testid
|
|
9
|
+
:styleClassPassthrough="['single-checkbox-fieldset']"
|
|
10
|
+
>
|
|
3
11
|
<template #description>
|
|
4
12
|
<slot name="description"></slot>
|
|
5
13
|
</template>
|
|
6
14
|
|
|
7
15
|
<template #content>
|
|
8
16
|
<div class="single-checkbox-items" :class="[optionsLayout]">
|
|
9
|
-
<InputCheckboxRadioWithLabel
|
|
17
|
+
<InputCheckboxRadioWithLabel
|
|
18
|
+
type="checkbox"
|
|
19
|
+
:name
|
|
20
|
+
:required
|
|
21
|
+
:label
|
|
22
|
+
:fieldHasError
|
|
23
|
+
v-model="modelValue"
|
|
24
|
+
:trueValue
|
|
25
|
+
:falseValue
|
|
26
|
+
:size
|
|
27
|
+
:theme
|
|
28
|
+
:ariaDescribedby
|
|
29
|
+
>
|
|
10
30
|
<template #checkedIcon>
|
|
11
31
|
<slot name="checkedIcon"></slot>
|
|
12
32
|
</template>
|
|
13
|
-
<template v-if="
|
|
33
|
+
<template v-if="slots.labelContent" #labelContent>
|
|
14
34
|
<slot name="labelContent"></slot>
|
|
15
35
|
</template>
|
|
16
36
|
</InputCheckboxRadioWithLabel>
|
|
17
37
|
</div>
|
|
18
|
-
<InputError
|
|
38
|
+
<InputError
|
|
39
|
+
:errorMessage
|
|
40
|
+
:showError="fieldHasError"
|
|
41
|
+
:id="errorId"
|
|
42
|
+
:isDetached="true"
|
|
43
|
+
:styleClassPassthrough="inputErrorStyles"
|
|
44
|
+
/>
|
|
19
45
|
</template>
|
|
20
46
|
</FormFieldset>
|
|
21
47
|
</template>
|
|
22
48
|
|
|
23
49
|
<script setup lang="ts">
|
|
24
|
-
import propValidators from
|
|
25
|
-
import type { IFormMultipleOptions } from '../../../../shared/types/types.forms';
|
|
50
|
+
import propValidators from "../c12/prop-validators"
|
|
26
51
|
|
|
27
52
|
const props = defineProps({
|
|
28
53
|
dataTestid: {
|
|
29
54
|
type: String,
|
|
30
|
-
default:
|
|
55
|
+
default: "multiple-radio-buttons",
|
|
31
56
|
},
|
|
32
57
|
name: {
|
|
33
58
|
type: String,
|
|
@@ -40,7 +65,7 @@ const props = defineProps({
|
|
|
40
65
|
label: {
|
|
41
66
|
type: String,
|
|
42
67
|
required: false,
|
|
43
|
-
default:
|
|
68
|
+
default: "",
|
|
44
69
|
},
|
|
45
70
|
errorMessage: {
|
|
46
71
|
type: [Object, String],
|
|
@@ -60,9 +85,9 @@ const props = defineProps({
|
|
|
60
85
|
},
|
|
61
86
|
size: {
|
|
62
87
|
type: String as PropType<string>,
|
|
63
|
-
default:
|
|
88
|
+
default: "medium",
|
|
64
89
|
validator(value: string) {
|
|
65
|
-
return propValidators.size.includes(value)
|
|
90
|
+
return propValidators.size.includes(value)
|
|
66
91
|
},
|
|
67
92
|
},
|
|
68
93
|
trueValue: {
|
|
@@ -75,9 +100,9 @@ const props = defineProps({
|
|
|
75
100
|
},
|
|
76
101
|
optionsLayout: {
|
|
77
102
|
type: String as PropType<string>,
|
|
78
|
-
default:
|
|
103
|
+
default: "equal-widths",
|
|
79
104
|
validator(value: string) {
|
|
80
|
-
return propValidators.optionsLayout.includes(value)
|
|
105
|
+
return propValidators.optionsLayout.includes(value)
|
|
81
106
|
},
|
|
82
107
|
},
|
|
83
108
|
equalCols: {
|
|
@@ -90,39 +115,33 @@ const props = defineProps({
|
|
|
90
115
|
},
|
|
91
116
|
theme: {
|
|
92
117
|
type: String as PropType<string>,
|
|
93
|
-
default:
|
|
118
|
+
default: "primary",
|
|
94
119
|
validator(value: string) {
|
|
95
|
-
return propValidators.theme.includes(value)
|
|
120
|
+
return propValidators.theme.includes(value)
|
|
96
121
|
},
|
|
97
122
|
},
|
|
98
|
-
})
|
|
123
|
+
})
|
|
99
124
|
|
|
100
|
-
const slots = useSlots()
|
|
101
|
-
const hasDescriptionSlot = computed(() => slots.description !== undefined);
|
|
102
|
-
const hasDescription = computed(() => slots.description !== undefined);
|
|
103
|
-
const hasLabelContent = computed(() => slots.labelContent !== undefined);
|
|
125
|
+
const slots = useSlots()
|
|
104
126
|
|
|
105
|
-
const
|
|
127
|
+
const modelValue = defineModel()
|
|
106
128
|
|
|
107
|
-
const
|
|
108
|
-
const fieldData = defineModel('fieldData') as Ref<IFormMultipleOptions>;
|
|
129
|
+
const inputErrorStyles = ref<string[]>(props.styleClassPassthrough)
|
|
109
130
|
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
const id = `${props.name}-input-${useId()}`;
|
|
113
|
-
const errorId = `${name}-error-message`;
|
|
131
|
+
const id = `${props.name}-input-${useId()}`
|
|
132
|
+
const errorId = `${name}-error-message`
|
|
114
133
|
const ariaDescribedby = computed(() => {
|
|
115
|
-
const ariaDescribedbyId =
|
|
116
|
-
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
117
|
-
})
|
|
134
|
+
const ariaDescribedbyId = slots.description ? `${name}-description` : undefined
|
|
135
|
+
return props.fieldHasError ? errorId : ariaDescribedbyId
|
|
136
|
+
})
|
|
118
137
|
|
|
119
138
|
watchEffect(() => {
|
|
120
|
-
if (!
|
|
121
|
-
inputErrorStyles.value.push(
|
|
139
|
+
if (!slots.description && props.fieldHasError) {
|
|
140
|
+
inputErrorStyles.value.push("mbs-12")
|
|
122
141
|
} else {
|
|
123
|
-
inputErrorStyles.value = inputErrorStyles.value.filter((style) => style !==
|
|
142
|
+
inputErrorStyles.value = inputErrorStyles.value.filter((style) => style !== "mbs-12")
|
|
124
143
|
}
|
|
125
|
-
})
|
|
144
|
+
})
|
|
126
145
|
</script>
|
|
127
146
|
|
|
128
147
|
<style lang="css">
|