@mozaic-ds/vue 1.0.0-rc.3 → 2.2.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.
- package/LICENSE +51 -0
- package/README.md +76 -77
- package/dist/mozaic-vue.css +1 -1
- package/dist/mozaic-vue.d.ts +1718 -0
- package/dist/mozaic-vue.js +1971 -0
- package/dist/mozaic-vue.js.map +1 -0
- package/dist/mozaic-vue.umd.cjs +2 -0
- package/dist/mozaic-vue.umd.cjs.map +1 -0
- package/env.d.ts +1 -0
- package/package.json +78 -51
- package/src/components/Contributing.mdx +118 -0
- package/src/components/GettingStarted.mdx +45 -0
- package/src/components/Introduction.mdx +100 -0
- package/src/components/Support.mdx +18 -0
- package/src/components/breadcrumb/MBreadcrumb.spec.ts +105 -0
- package/src/components/breadcrumb/MBreadcrumb.stories.ts +82 -0
- package/src/components/breadcrumb/MBreadcrumb.vue +52 -55
- package/src/components/button/MButton.spec.ts +191 -0
- package/src/components/button/MButton.stories.ts +59 -0
- package/src/components/button/MButton.vue +98 -154
- package/src/components/checkbox/MCheckbox.spec.ts +104 -0
- package/src/components/checkbox/MCheckbox.stories.ts +83 -0
- package/src/components/checkbox/MCheckbox.vue +60 -101
- package/src/components/checkboxgroup/MCheckboxGroup.spec.ts +78 -0
- package/src/components/checkboxgroup/MCheckboxGroup.stories.ts +61 -0
- package/src/components/checkboxgroup/MCheckboxGroup.vue +97 -0
- package/src/components/datepicker/MDatepicker.spec.ts +95 -0
- package/src/components/datepicker/MDatepicker.stories.ts +75 -0
- package/src/components/datepicker/MDatepicker.vue +114 -0
- package/src/components/divider/MDivider.spec.ts +57 -0
- package/src/components/divider/MDivider.stories.ts +64 -0
- package/src/components/divider/MDivider.vue +56 -0
- package/src/components/drawer/MDrawer.spec.ts +100 -0
- package/src/components/drawer/MDrawer.stories.ts +128 -0
- package/src/components/drawer/MDrawer.vue +140 -0
- package/src/components/field/MField.spec.ts +166 -0
- package/src/components/field/MField.stories.ts +369 -0
- package/src/components/field/MField.vue +78 -61
- package/src/components/fieldgroup/MFieldGroup.spec.ts +165 -0
- package/src/components/fieldgroup/MFieldGroup.stories.ts +416 -0
- package/src/components/fieldgroup/MFieldGroup.vue +79 -0
- package/src/components/flag/MFlag.spec.ts +46 -0
- package/src/components/flag/MFlag.stories.ts +46 -0
- package/src/components/flag/MFlag.vue +28 -39
- package/src/components/iconbutton/MIconButton.spec.ts +108 -0
- package/src/components/iconbutton/MIconButton.stories.ts +74 -0
- package/src/components/iconbutton/MIconButton.vue +73 -0
- package/src/components/link/MLink.spec.ts +154 -0
- package/src/components/link/MLink.stories.ts +89 -0
- package/src/components/link/MLink.vue +86 -120
- package/src/components/loader/MLoader.spec.ts +104 -0
- package/src/components/loader/MLoader.stories.ts +43 -0
- package/src/components/loader/MLoader.vue +66 -55
- package/src/components/loadingoverlay/MLoadingOverlay.spec.ts +37 -0
- package/src/components/loadingoverlay/MLoadingOverlay.stories.ts +40 -0
- package/src/components/loadingoverlay/MLoadingOverlay.vue +28 -0
- package/src/components/modal/MModal.spec.ts +103 -0
- package/src/components/modal/MModal.stories.ts +127 -0
- package/src/components/modal/MModal.vue +111 -159
- package/src/components/numberbadge/MNumberBadge.spec.ts +56 -0
- package/src/components/numberbadge/MNumberBadge.stories.ts +48 -0
- package/src/components/numberbadge/MNumberBadge.vue +45 -0
- package/src/components/overlay/MOverlay.spec.ts +51 -0
- package/src/components/overlay/MOverlay.stories.ts +35 -0
- package/src/components/overlay/MOverlay.vue +27 -19
- package/src/components/pagination/MPagination.spec.ts +123 -0
- package/src/components/pagination/MPagination.stories.ts +83 -0
- package/src/components/pagination/MPagination.vue +120 -140
- package/src/components/passwordinput/MPasswordInput.spec.ts +104 -0
- package/src/components/passwordinput/MPasswordInput.stories.ts +75 -0
- package/src/components/passwordinput/MPasswordInput.vue +126 -77
- package/src/components/pincode/MPincode.spec.ts +126 -0
- package/src/components/pincode/MPincode.stories.ts +68 -0
- package/src/components/pincode/MPincode.vue +148 -0
- package/src/components/quantityselector/MQuantitySelector.spec.ts +262 -0
- package/src/components/quantityselector/MQuantitySelector.stories.ts +89 -0
- package/src/components/quantityselector/MQuantitySelector.vue +159 -148
- package/src/components/radio/MRadio.spec.ts +104 -0
- package/src/components/radio/MRadio.stories.ts +68 -0
- package/src/components/radio/MRadio.vue +56 -39
- package/src/components/radiogroup/MRadioGroup.spec.ts +54 -0
- package/src/components/radiogroup/MRadioGroup.stories.ts +61 -0
- package/src/components/radiogroup/MRadioGroup.vue +79 -0
- package/src/components/select/MSelect.spec.ts +114 -0
- package/src/components/select/MSelect.stories.ts +101 -0
- package/src/components/select/MSelect.vue +77 -119
- package/src/components/statusbadge/MStatusBadge.stories.ts +45 -0
- package/src/components/statusbadge/MStatusBadge.vue +40 -0
- package/src/components/statusbadge/MstatusBadge.spec.ts +16 -0
- package/src/components/statusdot/MStatusDot.spec.ts +51 -0
- package/src/components/statusdot/MStatusDot.stories.ts +48 -0
- package/src/components/statusdot/MStatusDot.vue +36 -0
- package/src/components/statusnotification/MStatusNotification.spec.ts +103 -0
- package/src/components/statusnotification/MStatusNotification.stories.ts +89 -0
- package/src/components/statusnotification/MStatusNotification.vue +106 -0
- package/src/components/tabs/MTabs.stories.ts +104 -0
- package/src/components/tabs/MTabs.vue +113 -0
- package/src/components/tabs/Mtabs.spec.ts +149 -0
- package/src/components/tag/MTag.spec.ts +107 -0
- package/src/components/tag/MTag.stories.ts +75 -0
- package/src/components/tag/MTag.vue +151 -0
- package/src/components/textarea/MTextArea.spec.ts +112 -0
- package/src/components/textarea/MTextArea.stories.ts +67 -0
- package/src/components/textarea/MTextArea.vue +81 -43
- package/src/components/textinput/MTextInput.spec.ts +121 -0
- package/src/components/textinput/MTextInput.stories.ts +107 -0
- package/src/components/textinput/MTextInput.vue +127 -47
- package/src/components/toggle/MToggle.spec.ts +99 -0
- package/src/components/toggle/MToggle.stories.ts +68 -0
- package/src/components/toggle/MToggle.vue +63 -103
- package/src/components/togglegroup/MToggleGroup.spec.ts +78 -0
- package/src/components/togglegroup/MToggleGroup.stories.ts +61 -0
- package/src/components/togglegroup/MToggleGroup.vue +97 -0
- package/src/components/tooltip/MTooltip.spec.ts +47 -0
- package/src/components/tooltip/MTooltip.stories.ts +59 -0
- package/src/components/tooltip/MTooltip.vue +49 -32
- package/src/components/usingIcons.mdx +35 -0
- package/src/components/usingPresets.mdx +128 -0
- package/src/main.ts +33 -0
- package/dist/demo.html +0 -1
- package/dist/mozaic-vue.adeo.css +0 -47
- package/dist/mozaic-vue.adeo.umd.js +0 -31341
- package/dist/mozaic-vue.common.js +0 -31331
- package/dist/mozaic-vue.common.js.map +0 -1
- package/dist/mozaic-vue.umd.js +0 -31342
- package/dist/mozaic-vue.umd.js.map +0 -1
- package/dist/mozaic-vue.umd.min.js +0 -4
- package/dist/mozaic-vue.umd.min.js.map +0 -1
- package/postinstall.js +0 -3
- package/src/components/accordion/MAccordion.vue +0 -128
- package/src/components/accordion/index.js +0 -7
- package/src/components/autocomplete/MAutocomplete.vue +0 -380
- package/src/components/autocomplete/index.js +0 -7
- package/src/components/badge/MBadge.vue +0 -43
- package/src/components/badge/index.js +0 -7
- package/src/components/breadcrumb/index.js +0 -7
- package/src/components/button/index.js +0 -7
- package/src/components/card/MCard.vue +0 -78
- package/src/components/card/index.js +0 -7
- package/src/components/checkbox/MCheckboxGroup.vue +0 -163
- package/src/components/checkbox/index.js +0 -12
- package/src/components/container/MContainer.vue +0 -33
- package/src/components/container/index.js +0 -7
- package/src/components/datatable/MDataTable.vue +0 -651
- package/src/components/datatable/MDataTableHeader.vue +0 -55
- package/src/components/datatable/MDataTableTop.vue +0 -35
- package/src/components/datatable/helpers.js +0 -132
- package/src/components/datatable/index.js +0 -12
- package/src/components/dropdown/MDropdown.vue +0 -317
- package/src/components/dropdown/index.js +0 -7
- package/src/components/field/index.js +0 -7
- package/src/components/fileuploader/MFileResult.vue +0 -149
- package/src/components/fileuploader/MFileUploader.vue +0 -142
- package/src/components/fileuploader/index.js +0 -7
- package/src/components/flag/index.js +0 -7
- package/src/components/heading/MHeading.vue +0 -75
- package/src/components/heading/index.js +0 -7
- package/src/components/hero/MHero.vue +0 -93
- package/src/components/hero/index.js +0 -7
- package/src/components/icon/MIcon.vue +0 -136
- package/src/components/icon/index.js +0 -7
- package/src/components/index.js +0 -44
- package/src/components/layer/MLayer.vue +0 -208
- package/src/components/layer/index.js +0 -7
- package/src/components/link/index.js +0 -7
- package/src/components/listbox/MListBox.vue +0 -146
- package/src/components/listbox/MListBoxActions.vue +0 -251
- package/src/components/listbox/index.js +0 -12
- package/src/components/loader/index.js +0 -7
- package/src/components/modal/index.js +0 -7
- package/src/components/notification/MNotification.vue +0 -110
- package/src/components/notification/index.js +0 -7
- package/src/components/optionbutton/MOptionButton.vue +0 -67
- package/src/components/optionbutton/index.js +0 -7
- package/src/components/optioncard/MOptionCard.vue +0 -132
- package/src/components/optioncard/index.js +0 -7
- package/src/components/optiongroup/MOptionGroup.vue +0 -18
- package/src/components/optiongroup/index.js +0 -7
- package/src/components/overlay/MOverlayLoader.vue +0 -43
- package/src/components/overlay/index.js +0 -12
- package/src/components/pagination/index.js +0 -7
- package/src/components/passwordinput/index.js +0 -7
- package/src/components/phonenumber/MPhoneNumber.vue +0 -398
- package/src/components/phonenumber/index.js +0 -7
- package/src/components/progressbar/MProgress.vue +0 -102
- package/src/components/progressbar/index.js +0 -7
- package/src/components/quantityselector/index.js +0 -7
- package/src/components/radio/MRadioGroup.vue +0 -111
- package/src/components/radio/index.js +0 -12
- package/src/components/ratingstars/MStarsInput.vue +0 -119
- package/src/components/ratingstars/MStarsResult.vue +0 -89
- package/src/components/ratingstars/index.js +0 -12
- package/src/components/select/index.js +0 -7
- package/src/components/stepper/MStepper.vue +0 -111
- package/src/components/stepper/index.js +0 -7
- package/src/components/tabs/MTab.vue +0 -204
- package/src/components/tabs/index.js +0 -7
- package/src/components/tags/MTag.vue +0 -175
- package/src/components/tags/index.js +0 -7
- package/src/components/textarea/index.js +0 -7
- package/src/components/textinput/MTextInputField.vue +0 -105
- package/src/components/textinput/MTextInputIcon.vue +0 -42
- package/src/components/textinput/index.js +0 -7
- package/src/components/toggle/index.js +0 -7
- package/src/components/tooltip/index.js +0 -7
- package/src/index.js +0 -63
- package/src/shims-tsx.d.ts +0 -13
- package/src/shims.vue.d.ts +0 -4
- package/src/tokens/adeo/android/colors.xml +0 -452
- package/src/tokens/adeo/android/font_dimens.xml +0 -18
- package/src/tokens/adeo/css/_variables.scss +0 -446
- package/src/tokens/adeo/css/root.scss +0 -448
- package/src/tokens/adeo/ios/StyleDictionaryColor.h +0 -460
- package/src/tokens/adeo/ios/StyleDictionaryColor.m +0 -472
- package/src/tokens/adeo/ios/StyleDictionaryColor.swift +0 -455
- package/src/tokens/adeo/ios/StyleDictionarySize.h +0 -69
- package/src/tokens/adeo/ios/StyleDictionarySize.m +0 -70
- package/src/tokens/adeo/ios/StyleDictionarySize.swift +0 -71
- package/src/tokens/adeo/js/tokens.js +0 -544
- package/src/tokens/adeo/js/tokensObject.js +0 -11733
- package/src/tokens/adeo/scss/_tokens.scss +0 -1522
- package/src/utils/mozaicClasses.js +0 -16
- package/src/utils/theme.validator.js +0 -19
- package/types/index.d.ts +0 -104
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import MFieldGroup from './MFieldGroup.vue';
|
|
4
|
+
|
|
5
|
+
describe('MFieldGroup component', () => {
|
|
6
|
+
it('should render label correctly', () => {
|
|
7
|
+
const wrapper = mount(MFieldGroup, {
|
|
8
|
+
props: {
|
|
9
|
+
id: 'input-id',
|
|
10
|
+
legend: 'Field Label',
|
|
11
|
+
},
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const label = wrapper.find('legend');
|
|
15
|
+
expect(label.exists()).toBe(true);
|
|
16
|
+
expect(label.text()).toBe('Field Label');
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('should render requirement text if provided', () => {
|
|
20
|
+
const wrapper = mount(MFieldGroup, {
|
|
21
|
+
props: {
|
|
22
|
+
id: 'input-id',
|
|
23
|
+
legend: 'Field Label',
|
|
24
|
+
requirementText: 'required',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const requirementText = wrapper.find('.mc-field__requirement');
|
|
29
|
+
expect(requirementText.exists()).toBe(true);
|
|
30
|
+
expect(requirementText.text()).toBe('(required)');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should not render requirement text if not provided', () => {
|
|
34
|
+
const wrapper = mount(MFieldGroup, {
|
|
35
|
+
props: {
|
|
36
|
+
id: 'input-id',
|
|
37
|
+
legend: 'Field Label',
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const requirementText = wrapper.find('.mc-field__requirement');
|
|
42
|
+
expect(requirementText.exists()).toBe(false);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should render help text if provided', () => {
|
|
46
|
+
const wrapper = mount(MFieldGroup, {
|
|
47
|
+
props: {
|
|
48
|
+
id: 'input-id',
|
|
49
|
+
legend: 'Field Label',
|
|
50
|
+
helpText: 'This is some help text.',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const helpText = wrapper.find('.mc-field__help');
|
|
55
|
+
expect(helpText.exists()).toBe(true);
|
|
56
|
+
expect(helpText.text()).toBe('This is some help text.');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should not render help text if not provided', () => {
|
|
60
|
+
const wrapper = mount(MFieldGroup, {
|
|
61
|
+
props: {
|
|
62
|
+
id: 'input-id',
|
|
63
|
+
legend: 'Field Label',
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const helpText = wrapper.find('.mc-field__help');
|
|
68
|
+
expect(helpText.exists()).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('should apply is-valid class when isValid prop is true', () => {
|
|
72
|
+
const wrapper = mount(MFieldGroup, {
|
|
73
|
+
props: {
|
|
74
|
+
id: 'input-id',
|
|
75
|
+
legend: 'Field Label',
|
|
76
|
+
isValid: true,
|
|
77
|
+
message: 'Valid input',
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
expect(wrapper.find('.mc-field__validation-message').classes()).toContain(
|
|
82
|
+
'is-valid',
|
|
83
|
+
);
|
|
84
|
+
expect(wrapper.find('.mc-field__validation-message').text()).toBe(
|
|
85
|
+
'Valid input',
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should apply is-invalid class when isInvalid prop is true', () => {
|
|
90
|
+
const wrapper = mount(MFieldGroup, {
|
|
91
|
+
props: {
|
|
92
|
+
id: 'input-id',
|
|
93
|
+
legend: 'Field Label',
|
|
94
|
+
isInvalid: true,
|
|
95
|
+
message: 'Invalid input',
|
|
96
|
+
},
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
expect(wrapper.find('.mc-field__validation-message').classes()).toContain(
|
|
100
|
+
'is-invalid',
|
|
101
|
+
);
|
|
102
|
+
expect(wrapper.find('.mc-field__validation-message').text()).toBe(
|
|
103
|
+
'Invalid input',
|
|
104
|
+
);
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
it('should render a validation message only when isValid or isInvalid is true and message is provided', () => {
|
|
108
|
+
const wrapper = mount(MFieldGroup, {
|
|
109
|
+
props: {
|
|
110
|
+
id: 'input-id',
|
|
111
|
+
legend: 'Field Label',
|
|
112
|
+
isValid: true,
|
|
113
|
+
message: 'This is a valid input',
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const validationMessage = wrapper.find('.mc-field__validation-message');
|
|
118
|
+
expect(validationMessage.exists()).toBe(true);
|
|
119
|
+
expect(validationMessage.text()).toBe('This is a valid input');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should render the form element passed in the slot', () => {
|
|
123
|
+
const wrapper = mount(MFieldGroup, {
|
|
124
|
+
props: {
|
|
125
|
+
id: 'input-id',
|
|
126
|
+
legend: 'Field Label',
|
|
127
|
+
},
|
|
128
|
+
slots: {
|
|
129
|
+
default: '<input type="text" />',
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const input = wrapper.find('input');
|
|
134
|
+
expect(input.exists()).toBe(true);
|
|
135
|
+
expect(input.attributes('type')).toBe('text');
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
it('should render validation message when isInvalid is true and message is provided', () => {
|
|
139
|
+
const wrapper = mount(MFieldGroup, {
|
|
140
|
+
props: {
|
|
141
|
+
id: 'input-id',
|
|
142
|
+
legend: 'Field Label',
|
|
143
|
+
isInvalid: true,
|
|
144
|
+
message: 'There is an error',
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const validationMessage = wrapper.find('.mc-field__validation-message');
|
|
149
|
+
expect(validationMessage.exists()).toBe(true);
|
|
150
|
+
expect(validationMessage.text()).toBe('There is an error');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should not render validation message when message is not provided', () => {
|
|
154
|
+
const wrapper = mount(MFieldGroup, {
|
|
155
|
+
props: {
|
|
156
|
+
id: 'input-id',
|
|
157
|
+
legend: 'Field Label',
|
|
158
|
+
isValid: true,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const validationMessage = wrapper.find('.mc-field__validation-message');
|
|
163
|
+
expect(validationMessage.exists()).toBe(false);
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite';
|
|
2
|
+
import { action } from 'storybook/actions';
|
|
3
|
+
|
|
4
|
+
import MFieldGroup from './MFieldGroup.vue';
|
|
5
|
+
import MCheckboxGroup from '../checkboxgroup/MCheckboxGroup.vue';
|
|
6
|
+
import MRadioGroup from '../radiogroup/MRadioGroup.vue';
|
|
7
|
+
import MToggleGroup from '../togglegroup/MToggleGroup.vue';
|
|
8
|
+
|
|
9
|
+
const meta: Meta<typeof MFieldGroup> = {
|
|
10
|
+
title: 'Form Elements/Field Group',
|
|
11
|
+
component: MFieldGroup,
|
|
12
|
+
parameters: {
|
|
13
|
+
docs: {
|
|
14
|
+
description: {
|
|
15
|
+
component:
|
|
16
|
+
'A field label is a text element that identifies the purpose of an input field, providing users with clear guidance on what information to enter. It is typically placed above the input field and may include indicators for required or optional fields. Field Labels improve form usability, accessibility, and data entry accuracy by ensuring users understand the expected input.',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
args: {
|
|
21
|
+
legend: 'Label',
|
|
22
|
+
id: 'ReplaceByInputId',
|
|
23
|
+
requirementText: 'required',
|
|
24
|
+
helpText: 'Help text',
|
|
25
|
+
default: `
|
|
26
|
+
<MCheckboxGroup
|
|
27
|
+
name="checkboxGroupName"
|
|
28
|
+
:options="
|
|
29
|
+
[
|
|
30
|
+
{
|
|
31
|
+
id: 'checkbox-01',
|
|
32
|
+
label: 'checkbox Label',
|
|
33
|
+
value: 'checkbox1',
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: 'checkbox-02',
|
|
37
|
+
label: 'checkbox Label',
|
|
38
|
+
value: 'checkbox2',
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'checkbox-03',
|
|
42
|
+
label: 'checkbox Label',
|
|
43
|
+
value: 'checkbox3',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'checkbox-04',
|
|
47
|
+
label: 'checkbox Label',
|
|
48
|
+
value: 'checkbox4',
|
|
49
|
+
},
|
|
50
|
+
]
|
|
51
|
+
"
|
|
52
|
+
@update:modelValue="handleUpdate"
|
|
53
|
+
/>
|
|
54
|
+
`,
|
|
55
|
+
},
|
|
56
|
+
render: (args) => ({
|
|
57
|
+
components: { MFieldGroup, MCheckboxGroup, MRadioGroup, MToggleGroup },
|
|
58
|
+
setup() {
|
|
59
|
+
const handleUpdate = action('update:modelValue');
|
|
60
|
+
|
|
61
|
+
return { args, handleUpdate };
|
|
62
|
+
},
|
|
63
|
+
template: `
|
|
64
|
+
<MFieldGroup v-bind="args">
|
|
65
|
+
${args.default}
|
|
66
|
+
</MFieldGroup>
|
|
67
|
+
`,
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
export default meta;
|
|
71
|
+
type Story = StoryObj<typeof MFieldGroup>;
|
|
72
|
+
|
|
73
|
+
export const Default: Story = {
|
|
74
|
+
args: {
|
|
75
|
+
legend: 'Label',
|
|
76
|
+
id: 'ReplaceByInputId',
|
|
77
|
+
helpText: 'Help text',
|
|
78
|
+
requirementText: 'optional',
|
|
79
|
+
default: `
|
|
80
|
+
<!-- All the code below must be replaced by a form element. -->
|
|
81
|
+
<div class="content-slot">
|
|
82
|
+
Insert a form element here to replace this slot.
|
|
83
|
+
</div>
|
|
84
|
+
`,
|
|
85
|
+
},
|
|
86
|
+
render: (args) => ({
|
|
87
|
+
components: { MFieldGroup },
|
|
88
|
+
setup() {
|
|
89
|
+
return { args };
|
|
90
|
+
},
|
|
91
|
+
template: `
|
|
92
|
+
<MFieldGroup v-bind="args">
|
|
93
|
+
${args.default}
|
|
94
|
+
</MFieldGroup>
|
|
95
|
+
`,
|
|
96
|
+
}),
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const CheckboxGroup: Story = {};
|
|
100
|
+
|
|
101
|
+
export const CheckboxGroupValid: Story = {
|
|
102
|
+
args: {
|
|
103
|
+
legend: 'Label',
|
|
104
|
+
id: 'ReplaceByInputId',
|
|
105
|
+
requirementText: 'required',
|
|
106
|
+
isValid: true,
|
|
107
|
+
message: 'Validation message (Be concise and use comprehensive words).',
|
|
108
|
+
default: `
|
|
109
|
+
<MCheckboxGroup
|
|
110
|
+
name="checkboxGroupName"
|
|
111
|
+
:options="
|
|
112
|
+
[
|
|
113
|
+
{
|
|
114
|
+
id: 'checkbox-05',
|
|
115
|
+
label: 'checkbox Label',
|
|
116
|
+
value: 'checkbox5',
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
id: 'checkbox-06',
|
|
120
|
+
label: 'checkbox Label',
|
|
121
|
+
value: 'checkbox6',
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: 'checkbox-07',
|
|
125
|
+
label: 'checkbox Label',
|
|
126
|
+
value: 'checkbox7',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: 'checkbox-08',
|
|
130
|
+
label: 'checkbox Label',
|
|
131
|
+
value: 'checkbox8',
|
|
132
|
+
},
|
|
133
|
+
]
|
|
134
|
+
"
|
|
135
|
+
@update:modelValue="handleUpdate"
|
|
136
|
+
/>
|
|
137
|
+
`,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
export const CheckboxGroupInvalid: Story = {
|
|
142
|
+
args: {
|
|
143
|
+
legend: 'Label',
|
|
144
|
+
id: 'ReplaceByInputId',
|
|
145
|
+
requirementText: 'required',
|
|
146
|
+
isInvalid: true,
|
|
147
|
+
message: 'Error message (Be concise and use comprehensive words)',
|
|
148
|
+
default: `
|
|
149
|
+
<MCheckboxGroup
|
|
150
|
+
name="checkboxGroupName"
|
|
151
|
+
isInvalid
|
|
152
|
+
:options="
|
|
153
|
+
[
|
|
154
|
+
{
|
|
155
|
+
id: 'checkbox-09',
|
|
156
|
+
label: 'checkbox Label',
|
|
157
|
+
value: 'checkbox9',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'checkbox-10',
|
|
161
|
+
label: 'checkbox Label',
|
|
162
|
+
value: 'checkbox10',
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
id: 'checkbox-11',
|
|
166
|
+
label: 'checkbox Label',
|
|
167
|
+
value: 'checkbox11',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: 'checkbox-12',
|
|
171
|
+
label: 'checkbox Label',
|
|
172
|
+
value: 'checkbox12',
|
|
173
|
+
},
|
|
174
|
+
]
|
|
175
|
+
"
|
|
176
|
+
@update:modelValue="handleUpdate"
|
|
177
|
+
/>
|
|
178
|
+
`,
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
export const RadioGroup: Story = {
|
|
183
|
+
args: {
|
|
184
|
+
legend: 'Label',
|
|
185
|
+
id: 'ReplaceByInputId',
|
|
186
|
+
default: `
|
|
187
|
+
<MRadioGroup
|
|
188
|
+
name="radioGroupName"
|
|
189
|
+
:options="
|
|
190
|
+
[
|
|
191
|
+
{
|
|
192
|
+
id: 'radio-01',
|
|
193
|
+
label: 'Radio button Label',
|
|
194
|
+
value: 'radio1'
|
|
195
|
+
},
|
|
196
|
+
{
|
|
197
|
+
id: 'radio-02',
|
|
198
|
+
label: 'Radio button Label',
|
|
199
|
+
value: 'radio2'
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
id: 'radio-03',
|
|
203
|
+
label: 'Radio button Label',
|
|
204
|
+
value: 'radio3'
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: 'radio-04',
|
|
208
|
+
label: 'Radio button Label',
|
|
209
|
+
value: 'radio4'
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
"
|
|
213
|
+
@update:modelValue="handleUpdate"
|
|
214
|
+
/>
|
|
215
|
+
`,
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
export const RadioGroupValid: Story = {
|
|
220
|
+
args: {
|
|
221
|
+
legend: 'Label',
|
|
222
|
+
id: 'ReplaceByInputId',
|
|
223
|
+
requirementText: 'required',
|
|
224
|
+
isValid: true,
|
|
225
|
+
message: 'Validation message (Be concise and use comprehensive words).',
|
|
226
|
+
default: `
|
|
227
|
+
<MRadioGroup
|
|
228
|
+
name="radioGroupValidName"
|
|
229
|
+
:options="
|
|
230
|
+
[
|
|
231
|
+
{
|
|
232
|
+
id: 'radio05',
|
|
233
|
+
label: 'Radio button Label',
|
|
234
|
+
value: 'radio5'
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
id: 'radio06',
|
|
238
|
+
label: 'Radio button Label',
|
|
239
|
+
value: 'radio6'
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: 'radio07',
|
|
243
|
+
label: 'Radio button Label',
|
|
244
|
+
value: 'radio7'
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
id: 'radio08',
|
|
248
|
+
label: 'Radio button Label',
|
|
249
|
+
value: 'radio8'
|
|
250
|
+
}
|
|
251
|
+
]
|
|
252
|
+
"
|
|
253
|
+
@update:modelValue="handleUpdate"
|
|
254
|
+
/>
|
|
255
|
+
`,
|
|
256
|
+
},
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
export const RadioGroupInvalid: Story = {
|
|
260
|
+
args: {
|
|
261
|
+
legend: 'Label',
|
|
262
|
+
id: 'ReplaceByInputId',
|
|
263
|
+
requirementText: 'required',
|
|
264
|
+
isInvalid: true,
|
|
265
|
+
message: 'Error message (Be concise and use comprehensive words)',
|
|
266
|
+
default: `
|
|
267
|
+
<MRadioGroup
|
|
268
|
+
name="radioGroupInvalidName"
|
|
269
|
+
isInvalid
|
|
270
|
+
:options="
|
|
271
|
+
[
|
|
272
|
+
{
|
|
273
|
+
id: 'radio-9',
|
|
274
|
+
label: 'Radio button Label',
|
|
275
|
+
value: 'radio9'
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
id: 'radio-10',
|
|
279
|
+
label: 'Radio button Label',
|
|
280
|
+
value: 'radio10'
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: 'radio-11',
|
|
284
|
+
label: 'Radio button Label',
|
|
285
|
+
value: 'radio11'
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: 'radio-12',
|
|
289
|
+
label: 'Radio button Label',
|
|
290
|
+
value: 'radio12'
|
|
291
|
+
}
|
|
292
|
+
]
|
|
293
|
+
"
|
|
294
|
+
@update:modelValue="handleUpdate"
|
|
295
|
+
/>
|
|
296
|
+
`,
|
|
297
|
+
},
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
export const ToggleGroup: Story = {
|
|
301
|
+
args: {
|
|
302
|
+
legend: 'Label',
|
|
303
|
+
id: 'ToggleGroupId',
|
|
304
|
+
requirementText: 'required',
|
|
305
|
+
default: `
|
|
306
|
+
<MToggleGroup
|
|
307
|
+
name="ToggleGroupName"
|
|
308
|
+
:options="
|
|
309
|
+
[
|
|
310
|
+
{
|
|
311
|
+
id: 'toggle-01',
|
|
312
|
+
label: 'Toggle Label',
|
|
313
|
+
value: 'toggle1',
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
id: 'toggle-02',
|
|
317
|
+
label: 'Toggle Label',
|
|
318
|
+
value: 'toggle2',
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: 'toggle-03',
|
|
322
|
+
label: 'Toggle Label',
|
|
323
|
+
value: 'toggle3',
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: 'toggle-04',
|
|
327
|
+
label: 'Toggle Label',
|
|
328
|
+
value: 'toggle4',
|
|
329
|
+
},
|
|
330
|
+
]
|
|
331
|
+
"
|
|
332
|
+
@update:modelValue="handleUpdate"
|
|
333
|
+
/>
|
|
334
|
+
`,
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
export const ToggleGroupValid: Story = {
|
|
339
|
+
args: {
|
|
340
|
+
legend: 'Label',
|
|
341
|
+
id: 'ToggleGroupId',
|
|
342
|
+
requirementText: 'required',
|
|
343
|
+
isValid: true,
|
|
344
|
+
message: 'Validation message (Be concise and use comprehensive words).',
|
|
345
|
+
default: `
|
|
346
|
+
<MToggleGroup
|
|
347
|
+
name="ToggleGroupName"
|
|
348
|
+
:options="
|
|
349
|
+
[
|
|
350
|
+
{
|
|
351
|
+
id: 'toggle-05',
|
|
352
|
+
label: 'Toggle Label',
|
|
353
|
+
value: 'toggle5',
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
id: 'toggle-06',
|
|
357
|
+
label: 'Toggle Label',
|
|
358
|
+
value: 'toggle6',
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
id: 'toggle-07',
|
|
362
|
+
label: 'Toggle Label',
|
|
363
|
+
value: 'toggle7',
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
id: 'toggle-08',
|
|
367
|
+
label: 'Toggle Label',
|
|
368
|
+
value: 'toggle8',
|
|
369
|
+
},
|
|
370
|
+
]
|
|
371
|
+
"
|
|
372
|
+
@update:modelValue="handleUpdate"
|
|
373
|
+
/>
|
|
374
|
+
`,
|
|
375
|
+
},
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
export const ToggleGroupInvalid: Story = {
|
|
379
|
+
args: {
|
|
380
|
+
legend: 'Label',
|
|
381
|
+
id: 'ToggleGroupId',
|
|
382
|
+
requirementText: 'required',
|
|
383
|
+
isInvalid: true,
|
|
384
|
+
message: 'Error message (Be concise and use comprehensive words)',
|
|
385
|
+
default: `
|
|
386
|
+
<MToggleGroup
|
|
387
|
+
name="ToggleGroupName"
|
|
388
|
+
:options="
|
|
389
|
+
[
|
|
390
|
+
{
|
|
391
|
+
id: 'toggle-09',
|
|
392
|
+
label: 'Toggle Label',
|
|
393
|
+
value: 'toggle9',
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: 'toggle-10',
|
|
397
|
+
label: 'Toggle Label',
|
|
398
|
+
value: 'toggle10',
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
id: 'toggle-11',
|
|
402
|
+
label: 'Toggle Label',
|
|
403
|
+
value: 'toggle11',
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
id: 'toggle-12',
|
|
407
|
+
label: 'Toggle Label',
|
|
408
|
+
value: 'toggle12',
|
|
409
|
+
},
|
|
410
|
+
]
|
|
411
|
+
"
|
|
412
|
+
@update:modelValue="handleUpdate"
|
|
413
|
+
/>
|
|
414
|
+
`,
|
|
415
|
+
},
|
|
416
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<fieldset class="mc-field--group">
|
|
3
|
+
<legend class="mc-field__legend" :for="id">
|
|
4
|
+
{{ legend }}
|
|
5
|
+
<span v-if="requirementText" class="mc-field__requirement"
|
|
6
|
+
>({{ requirementText }})</span
|
|
7
|
+
>
|
|
8
|
+
</legend>
|
|
9
|
+
|
|
10
|
+
<span v-if="helpText" class="mc-field__help">{{ helpText }}</span>
|
|
11
|
+
|
|
12
|
+
<div class="mc-field__content">
|
|
13
|
+
<slot />
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
<span
|
|
17
|
+
v-if="(isValid || isInvalid) && message"
|
|
18
|
+
class="mc-field__validation-message"
|
|
19
|
+
:class="classObjectValidation"
|
|
20
|
+
>
|
|
21
|
+
{{ message }}
|
|
22
|
+
</span>
|
|
23
|
+
</fieldset>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { computed, type VNode } from 'vue';
|
|
28
|
+
/**
|
|
29
|
+
* This component creates a structured form field for group field such as Radio Group, Checkbox Group or Toggle Group with a label, optional help text, error and validation message handling.
|
|
30
|
+
*/
|
|
31
|
+
const props = defineProps<{
|
|
32
|
+
/**
|
|
33
|
+
* A unique identifier for the form field, used to associate the label with the form element.
|
|
34
|
+
*/
|
|
35
|
+
id: string;
|
|
36
|
+
/**
|
|
37
|
+
* The text displayed as the legend for the form fieldset.
|
|
38
|
+
*/
|
|
39
|
+
legend: string;
|
|
40
|
+
/**
|
|
41
|
+
* Additional text displayed alongside the label, typically used to indicate if the form field is required or optional
|
|
42
|
+
*/
|
|
43
|
+
requirementText?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Text shown below the form field to provide additional context or instructions for the user.
|
|
46
|
+
*/
|
|
47
|
+
helpText?: string;
|
|
48
|
+
/**
|
|
49
|
+
* If `true`, applies a valid state to the form field.
|
|
50
|
+
*/
|
|
51
|
+
isValid?: boolean;
|
|
52
|
+
/**
|
|
53
|
+
* If `true`, applies an invalid state to the form field.
|
|
54
|
+
*/
|
|
55
|
+
isInvalid?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* message displayed when the form field has a valid or invalid state, usually indicating validation or errors.
|
|
58
|
+
*/
|
|
59
|
+
message?: string;
|
|
60
|
+
}>();
|
|
61
|
+
|
|
62
|
+
defineSlots<{
|
|
63
|
+
/**
|
|
64
|
+
* Use this slot to insert the form element of your choice
|
|
65
|
+
*/
|
|
66
|
+
default: VNode;
|
|
67
|
+
}>();
|
|
68
|
+
|
|
69
|
+
const classObjectValidation = computed(() => {
|
|
70
|
+
return {
|
|
71
|
+
'is-valid': props.isValid,
|
|
72
|
+
'is-invalid': props.isInvalid,
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
</script>
|
|
76
|
+
|
|
77
|
+
<style lang="scss" scoped>
|
|
78
|
+
@use '@mozaic-ds/styles/components/field';
|
|
79
|
+
</style>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import Flag from './MFlag.vue';
|
|
4
|
+
|
|
5
|
+
describe('Flag component', () => {
|
|
6
|
+
it('renders the label correctly', () => {
|
|
7
|
+
const wrapper = mount(Flag, {
|
|
8
|
+
props: {
|
|
9
|
+
label: 'New',
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
expect(wrapper.text()).toContain('New');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('applies no modifier class when appearance is standard or undefined', () => {
|
|
16
|
+
const wrapperDefault = mount(Flag, {
|
|
17
|
+
props: {
|
|
18
|
+
label: 'Default',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
expect(wrapperDefault.classes()).not.toContain('mc-flag--standard');
|
|
22
|
+
|
|
23
|
+
const wrapperStandard = mount(Flag, {
|
|
24
|
+
props: {
|
|
25
|
+
label: 'Standard',
|
|
26
|
+
appearance: 'standard',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
expect(wrapperStandard.classes()).not.toContain('mc-flag--standard');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('applies correct modifier class for non-standard appearance', () => {
|
|
33
|
+
const appearances = ['danger', 'accent', 'inverse'] as const;
|
|
34
|
+
|
|
35
|
+
appearances.forEach((appearance) => {
|
|
36
|
+
const wrapper = mount(Flag, {
|
|
37
|
+
props: {
|
|
38
|
+
label: `Label ${appearance}`,
|
|
39
|
+
appearance,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
expect(wrapper.classes()).toContain(`mc-flag--${appearance}`);
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
});
|