@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.
Files changed (224) hide show
  1. package/LICENSE +51 -0
  2. package/README.md +76 -77
  3. package/dist/mozaic-vue.css +1 -1
  4. package/dist/mozaic-vue.d.ts +1718 -0
  5. package/dist/mozaic-vue.js +1971 -0
  6. package/dist/mozaic-vue.js.map +1 -0
  7. package/dist/mozaic-vue.umd.cjs +2 -0
  8. package/dist/mozaic-vue.umd.cjs.map +1 -0
  9. package/env.d.ts +1 -0
  10. package/package.json +78 -51
  11. package/src/components/Contributing.mdx +118 -0
  12. package/src/components/GettingStarted.mdx +45 -0
  13. package/src/components/Introduction.mdx +100 -0
  14. package/src/components/Support.mdx +18 -0
  15. package/src/components/breadcrumb/MBreadcrumb.spec.ts +105 -0
  16. package/src/components/breadcrumb/MBreadcrumb.stories.ts +82 -0
  17. package/src/components/breadcrumb/MBreadcrumb.vue +52 -55
  18. package/src/components/button/MButton.spec.ts +191 -0
  19. package/src/components/button/MButton.stories.ts +59 -0
  20. package/src/components/button/MButton.vue +98 -154
  21. package/src/components/checkbox/MCheckbox.spec.ts +104 -0
  22. package/src/components/checkbox/MCheckbox.stories.ts +83 -0
  23. package/src/components/checkbox/MCheckbox.vue +60 -101
  24. package/src/components/checkboxgroup/MCheckboxGroup.spec.ts +78 -0
  25. package/src/components/checkboxgroup/MCheckboxGroup.stories.ts +61 -0
  26. package/src/components/checkboxgroup/MCheckboxGroup.vue +97 -0
  27. package/src/components/datepicker/MDatepicker.spec.ts +95 -0
  28. package/src/components/datepicker/MDatepicker.stories.ts +75 -0
  29. package/src/components/datepicker/MDatepicker.vue +114 -0
  30. package/src/components/divider/MDivider.spec.ts +57 -0
  31. package/src/components/divider/MDivider.stories.ts +64 -0
  32. package/src/components/divider/MDivider.vue +56 -0
  33. package/src/components/drawer/MDrawer.spec.ts +100 -0
  34. package/src/components/drawer/MDrawer.stories.ts +128 -0
  35. package/src/components/drawer/MDrawer.vue +140 -0
  36. package/src/components/field/MField.spec.ts +166 -0
  37. package/src/components/field/MField.stories.ts +369 -0
  38. package/src/components/field/MField.vue +78 -61
  39. package/src/components/fieldgroup/MFieldGroup.spec.ts +165 -0
  40. package/src/components/fieldgroup/MFieldGroup.stories.ts +416 -0
  41. package/src/components/fieldgroup/MFieldGroup.vue +79 -0
  42. package/src/components/flag/MFlag.spec.ts +46 -0
  43. package/src/components/flag/MFlag.stories.ts +46 -0
  44. package/src/components/flag/MFlag.vue +28 -39
  45. package/src/components/iconbutton/MIconButton.spec.ts +108 -0
  46. package/src/components/iconbutton/MIconButton.stories.ts +74 -0
  47. package/src/components/iconbutton/MIconButton.vue +73 -0
  48. package/src/components/link/MLink.spec.ts +154 -0
  49. package/src/components/link/MLink.stories.ts +89 -0
  50. package/src/components/link/MLink.vue +86 -120
  51. package/src/components/loader/MLoader.spec.ts +104 -0
  52. package/src/components/loader/MLoader.stories.ts +43 -0
  53. package/src/components/loader/MLoader.vue +66 -55
  54. package/src/components/loadingoverlay/MLoadingOverlay.spec.ts +37 -0
  55. package/src/components/loadingoverlay/MLoadingOverlay.stories.ts +40 -0
  56. package/src/components/loadingoverlay/MLoadingOverlay.vue +28 -0
  57. package/src/components/modal/MModal.spec.ts +103 -0
  58. package/src/components/modal/MModal.stories.ts +127 -0
  59. package/src/components/modal/MModal.vue +111 -159
  60. package/src/components/numberbadge/MNumberBadge.spec.ts +56 -0
  61. package/src/components/numberbadge/MNumberBadge.stories.ts +48 -0
  62. package/src/components/numberbadge/MNumberBadge.vue +45 -0
  63. package/src/components/overlay/MOverlay.spec.ts +51 -0
  64. package/src/components/overlay/MOverlay.stories.ts +35 -0
  65. package/src/components/overlay/MOverlay.vue +27 -19
  66. package/src/components/pagination/MPagination.spec.ts +123 -0
  67. package/src/components/pagination/MPagination.stories.ts +83 -0
  68. package/src/components/pagination/MPagination.vue +120 -140
  69. package/src/components/passwordinput/MPasswordInput.spec.ts +104 -0
  70. package/src/components/passwordinput/MPasswordInput.stories.ts +75 -0
  71. package/src/components/passwordinput/MPasswordInput.vue +126 -77
  72. package/src/components/pincode/MPincode.spec.ts +126 -0
  73. package/src/components/pincode/MPincode.stories.ts +68 -0
  74. package/src/components/pincode/MPincode.vue +148 -0
  75. package/src/components/quantityselector/MQuantitySelector.spec.ts +262 -0
  76. package/src/components/quantityselector/MQuantitySelector.stories.ts +89 -0
  77. package/src/components/quantityselector/MQuantitySelector.vue +159 -148
  78. package/src/components/radio/MRadio.spec.ts +104 -0
  79. package/src/components/radio/MRadio.stories.ts +68 -0
  80. package/src/components/radio/MRadio.vue +56 -39
  81. package/src/components/radiogroup/MRadioGroup.spec.ts +54 -0
  82. package/src/components/radiogroup/MRadioGroup.stories.ts +61 -0
  83. package/src/components/radiogroup/MRadioGroup.vue +79 -0
  84. package/src/components/select/MSelect.spec.ts +114 -0
  85. package/src/components/select/MSelect.stories.ts +101 -0
  86. package/src/components/select/MSelect.vue +77 -119
  87. package/src/components/statusbadge/MStatusBadge.stories.ts +45 -0
  88. package/src/components/statusbadge/MStatusBadge.vue +40 -0
  89. package/src/components/statusbadge/MstatusBadge.spec.ts +16 -0
  90. package/src/components/statusdot/MStatusDot.spec.ts +51 -0
  91. package/src/components/statusdot/MStatusDot.stories.ts +48 -0
  92. package/src/components/statusdot/MStatusDot.vue +36 -0
  93. package/src/components/statusnotification/MStatusNotification.spec.ts +103 -0
  94. package/src/components/statusnotification/MStatusNotification.stories.ts +89 -0
  95. package/src/components/statusnotification/MStatusNotification.vue +106 -0
  96. package/src/components/tabs/MTabs.stories.ts +104 -0
  97. package/src/components/tabs/MTabs.vue +113 -0
  98. package/src/components/tabs/Mtabs.spec.ts +149 -0
  99. package/src/components/tag/MTag.spec.ts +107 -0
  100. package/src/components/tag/MTag.stories.ts +75 -0
  101. package/src/components/tag/MTag.vue +151 -0
  102. package/src/components/textarea/MTextArea.spec.ts +112 -0
  103. package/src/components/textarea/MTextArea.stories.ts +67 -0
  104. package/src/components/textarea/MTextArea.vue +81 -43
  105. package/src/components/textinput/MTextInput.spec.ts +121 -0
  106. package/src/components/textinput/MTextInput.stories.ts +107 -0
  107. package/src/components/textinput/MTextInput.vue +127 -47
  108. package/src/components/toggle/MToggle.spec.ts +99 -0
  109. package/src/components/toggle/MToggle.stories.ts +68 -0
  110. package/src/components/toggle/MToggle.vue +63 -103
  111. package/src/components/togglegroup/MToggleGroup.spec.ts +78 -0
  112. package/src/components/togglegroup/MToggleGroup.stories.ts +61 -0
  113. package/src/components/togglegroup/MToggleGroup.vue +97 -0
  114. package/src/components/tooltip/MTooltip.spec.ts +47 -0
  115. package/src/components/tooltip/MTooltip.stories.ts +59 -0
  116. package/src/components/tooltip/MTooltip.vue +49 -32
  117. package/src/components/usingIcons.mdx +35 -0
  118. package/src/components/usingPresets.mdx +128 -0
  119. package/src/main.ts +33 -0
  120. package/dist/demo.html +0 -1
  121. package/dist/mozaic-vue.adeo.css +0 -47
  122. package/dist/mozaic-vue.adeo.umd.js +0 -31341
  123. package/dist/mozaic-vue.common.js +0 -31331
  124. package/dist/mozaic-vue.common.js.map +0 -1
  125. package/dist/mozaic-vue.umd.js +0 -31342
  126. package/dist/mozaic-vue.umd.js.map +0 -1
  127. package/dist/mozaic-vue.umd.min.js +0 -4
  128. package/dist/mozaic-vue.umd.min.js.map +0 -1
  129. package/postinstall.js +0 -3
  130. package/src/components/accordion/MAccordion.vue +0 -128
  131. package/src/components/accordion/index.js +0 -7
  132. package/src/components/autocomplete/MAutocomplete.vue +0 -380
  133. package/src/components/autocomplete/index.js +0 -7
  134. package/src/components/badge/MBadge.vue +0 -43
  135. package/src/components/badge/index.js +0 -7
  136. package/src/components/breadcrumb/index.js +0 -7
  137. package/src/components/button/index.js +0 -7
  138. package/src/components/card/MCard.vue +0 -78
  139. package/src/components/card/index.js +0 -7
  140. package/src/components/checkbox/MCheckboxGroup.vue +0 -163
  141. package/src/components/checkbox/index.js +0 -12
  142. package/src/components/container/MContainer.vue +0 -33
  143. package/src/components/container/index.js +0 -7
  144. package/src/components/datatable/MDataTable.vue +0 -651
  145. package/src/components/datatable/MDataTableHeader.vue +0 -55
  146. package/src/components/datatable/MDataTableTop.vue +0 -35
  147. package/src/components/datatable/helpers.js +0 -132
  148. package/src/components/datatable/index.js +0 -12
  149. package/src/components/dropdown/MDropdown.vue +0 -317
  150. package/src/components/dropdown/index.js +0 -7
  151. package/src/components/field/index.js +0 -7
  152. package/src/components/fileuploader/MFileResult.vue +0 -149
  153. package/src/components/fileuploader/MFileUploader.vue +0 -142
  154. package/src/components/fileuploader/index.js +0 -7
  155. package/src/components/flag/index.js +0 -7
  156. package/src/components/heading/MHeading.vue +0 -75
  157. package/src/components/heading/index.js +0 -7
  158. package/src/components/hero/MHero.vue +0 -93
  159. package/src/components/hero/index.js +0 -7
  160. package/src/components/icon/MIcon.vue +0 -136
  161. package/src/components/icon/index.js +0 -7
  162. package/src/components/index.js +0 -44
  163. package/src/components/layer/MLayer.vue +0 -208
  164. package/src/components/layer/index.js +0 -7
  165. package/src/components/link/index.js +0 -7
  166. package/src/components/listbox/MListBox.vue +0 -146
  167. package/src/components/listbox/MListBoxActions.vue +0 -251
  168. package/src/components/listbox/index.js +0 -12
  169. package/src/components/loader/index.js +0 -7
  170. package/src/components/modal/index.js +0 -7
  171. package/src/components/notification/MNotification.vue +0 -110
  172. package/src/components/notification/index.js +0 -7
  173. package/src/components/optionbutton/MOptionButton.vue +0 -67
  174. package/src/components/optionbutton/index.js +0 -7
  175. package/src/components/optioncard/MOptionCard.vue +0 -132
  176. package/src/components/optioncard/index.js +0 -7
  177. package/src/components/optiongroup/MOptionGroup.vue +0 -18
  178. package/src/components/optiongroup/index.js +0 -7
  179. package/src/components/overlay/MOverlayLoader.vue +0 -43
  180. package/src/components/overlay/index.js +0 -12
  181. package/src/components/pagination/index.js +0 -7
  182. package/src/components/passwordinput/index.js +0 -7
  183. package/src/components/phonenumber/MPhoneNumber.vue +0 -398
  184. package/src/components/phonenumber/index.js +0 -7
  185. package/src/components/progressbar/MProgress.vue +0 -102
  186. package/src/components/progressbar/index.js +0 -7
  187. package/src/components/quantityselector/index.js +0 -7
  188. package/src/components/radio/MRadioGroup.vue +0 -111
  189. package/src/components/radio/index.js +0 -12
  190. package/src/components/ratingstars/MStarsInput.vue +0 -119
  191. package/src/components/ratingstars/MStarsResult.vue +0 -89
  192. package/src/components/ratingstars/index.js +0 -12
  193. package/src/components/select/index.js +0 -7
  194. package/src/components/stepper/MStepper.vue +0 -111
  195. package/src/components/stepper/index.js +0 -7
  196. package/src/components/tabs/MTab.vue +0 -204
  197. package/src/components/tabs/index.js +0 -7
  198. package/src/components/tags/MTag.vue +0 -175
  199. package/src/components/tags/index.js +0 -7
  200. package/src/components/textarea/index.js +0 -7
  201. package/src/components/textinput/MTextInputField.vue +0 -105
  202. package/src/components/textinput/MTextInputIcon.vue +0 -42
  203. package/src/components/textinput/index.js +0 -7
  204. package/src/components/toggle/index.js +0 -7
  205. package/src/components/tooltip/index.js +0 -7
  206. package/src/index.js +0 -63
  207. package/src/shims-tsx.d.ts +0 -13
  208. package/src/shims.vue.d.ts +0 -4
  209. package/src/tokens/adeo/android/colors.xml +0 -452
  210. package/src/tokens/adeo/android/font_dimens.xml +0 -18
  211. package/src/tokens/adeo/css/_variables.scss +0 -446
  212. package/src/tokens/adeo/css/root.scss +0 -448
  213. package/src/tokens/adeo/ios/StyleDictionaryColor.h +0 -460
  214. package/src/tokens/adeo/ios/StyleDictionaryColor.m +0 -472
  215. package/src/tokens/adeo/ios/StyleDictionaryColor.swift +0 -455
  216. package/src/tokens/adeo/ios/StyleDictionarySize.h +0 -69
  217. package/src/tokens/adeo/ios/StyleDictionarySize.m +0 -70
  218. package/src/tokens/adeo/ios/StyleDictionarySize.swift +0 -71
  219. package/src/tokens/adeo/js/tokens.js +0 -544
  220. package/src/tokens/adeo/js/tokensObject.js +0 -11733
  221. package/src/tokens/adeo/scss/_tokens.scss +0 -1522
  222. package/src/utils/mozaicClasses.js +0 -16
  223. package/src/utils/theme.validator.js +0 -19
  224. package/types/index.d.ts +0 -104
@@ -0,0 +1,166 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect } from 'vitest';
3
+ import MField from './MField.vue';
4
+
5
+ describe('MField component', () => {
6
+ it('should render label correctly', () => {
7
+ const wrapper = mount(MField, {
8
+ props: {
9
+ id: 'input-id',
10
+ label: 'Field Label',
11
+ },
12
+ });
13
+
14
+ const label = wrapper.find('label');
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(MField, {
21
+ props: {
22
+ id: 'input-id',
23
+ label: '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(MField, {
35
+ props: {
36
+ id: 'input-id',
37
+ label: '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(MField, {
47
+ props: {
48
+ id: 'input-id',
49
+ label: 'Field Label',
50
+ helpText: 'This is some help text.',
51
+ helpId: 'help-id',
52
+ },
53
+ });
54
+
55
+ const helpText = wrapper.find('.mc-field__help');
56
+ expect(helpText.exists()).toBe(true);
57
+ expect(helpText.text()).toBe('This is some help text.');
58
+ });
59
+
60
+ it('should not render help text if not provided', () => {
61
+ const wrapper = mount(MField, {
62
+ props: {
63
+ id: 'input-id',
64
+ label: 'Field Label',
65
+ },
66
+ });
67
+
68
+ const helpText = wrapper.find('.mc-field__help');
69
+ expect(helpText.exists()).toBe(false);
70
+ });
71
+
72
+ it('should apply is-valid class when isValid prop is true', () => {
73
+ const wrapper = mount(MField, {
74
+ props: {
75
+ id: 'input-id',
76
+ label: 'Field Label',
77
+ isValid: true,
78
+ message: 'Valid input',
79
+ },
80
+ });
81
+
82
+ expect(wrapper.find('.mc-field__validation-message').classes()).toContain(
83
+ 'is-valid',
84
+ );
85
+ expect(wrapper.find('.mc-field__validation-message').text()).toBe(
86
+ 'Valid input',
87
+ );
88
+ });
89
+
90
+ it('should apply is-invalid class when isInvalid prop is true', () => {
91
+ const wrapper = mount(MField, {
92
+ props: {
93
+ id: 'input-id',
94
+ label: 'Field Label',
95
+ isInvalid: true,
96
+ message: 'Invalid input',
97
+ },
98
+ });
99
+
100
+ expect(wrapper.find('.mc-field__validation-message').classes()).toContain(
101
+ 'is-invalid',
102
+ );
103
+ expect(wrapper.find('.mc-field__validation-message').text()).toBe(
104
+ 'Invalid input',
105
+ );
106
+ });
107
+
108
+ it('should render a validation message only when isValid or isInvalid is true and message is provided', () => {
109
+ const wrapper = mount(MField, {
110
+ props: {
111
+ id: 'input-id',
112
+ label: 'Field Label',
113
+ isValid: true,
114
+ message: 'This is a valid input',
115
+ },
116
+ });
117
+
118
+ const validationMessage = wrapper.find('.mc-field__validation-message');
119
+ expect(validationMessage.exists()).toBe(true);
120
+ expect(validationMessage.text()).toBe('This is a valid input');
121
+ });
122
+
123
+ it('should render the form element passed in the slot', () => {
124
+ const wrapper = mount(MField, {
125
+ props: {
126
+ id: 'input-id',
127
+ label: 'Field Label',
128
+ },
129
+ slots: {
130
+ default: '<input type="text" />',
131
+ },
132
+ });
133
+
134
+ const input = wrapper.find('input');
135
+ expect(input.exists()).toBe(true);
136
+ expect(input.attributes('type')).toBe('text');
137
+ });
138
+
139
+ it('should render validation message when isInvalid is true and message is provided', () => {
140
+ const wrapper = mount(MField, {
141
+ props: {
142
+ id: 'input-id',
143
+ label: 'Field Label',
144
+ isInvalid: true,
145
+ message: 'There is an error',
146
+ },
147
+ });
148
+
149
+ const validationMessage = wrapper.find('.mc-field__validation-message');
150
+ expect(validationMessage.exists()).toBe(true);
151
+ expect(validationMessage.text()).toBe('There is an error');
152
+ });
153
+
154
+ it('should not render validation message when message is not provided', () => {
155
+ const wrapper = mount(MField, {
156
+ props: {
157
+ id: 'input-id',
158
+ label: 'Field Label',
159
+ isValid: true,
160
+ },
161
+ });
162
+
163
+ const validationMessage = wrapper.find('.mc-field__validation-message');
164
+ expect(validationMessage.exists()).toBe(false);
165
+ });
166
+ });
@@ -0,0 +1,369 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+ import { action } from 'storybook/actions';
3
+
4
+ import MField from './MField.vue';
5
+ import MTextInput from '../textinput/MTextInput.vue';
6
+ import MTextArea from '../textarea/MTextArea.vue';
7
+ import MSelect from '../select/MSelect.vue';
8
+
9
+ const meta: Meta<typeof MField> = {
10
+ title: 'Form Elements/Field',
11
+ component: MField,
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
+ label: 'Label',
22
+ id: 'ReplaceByInputId',
23
+ default: `
24
+ <!-- All the code below must be replaced by a form element. -->
25
+ <div class="content-slot">
26
+ Insert a form element here to replace this slot.
27
+ </div>
28
+ `,
29
+ },
30
+ render: (args) => ({
31
+ components: { MField, MTextInput },
32
+ setup() {
33
+ const handleUpdate = action('update:modelValue');
34
+
35
+ return { args, handleUpdate };
36
+ },
37
+ template: `
38
+ <MField v-bind="args">
39
+ ${args.default}
40
+ </MField>
41
+ `,
42
+ }),
43
+ };
44
+ export default meta;
45
+ type Story = StoryObj<typeof MField>;
46
+
47
+ export const Default: Story = {
48
+ render: (args) => ({
49
+ components: { MField },
50
+ setup() {
51
+ return { args };
52
+ },
53
+ template: `
54
+ <MField v-bind="args">
55
+ ${args.default}
56
+ </MField>
57
+ `,
58
+ }),
59
+ };
60
+
61
+ export const Input: Story = {
62
+ args: {
63
+ label: 'Label',
64
+ id: 'inputId',
65
+ default: `
66
+ <MTextInput
67
+ id="inputId"
68
+ placeholder="Placeholder"
69
+ @update:modelValue="handleUpdate"
70
+ />
71
+ `,
72
+ },
73
+ };
74
+
75
+ export const InputFull: Story = {
76
+ args: {
77
+ label: 'Label',
78
+ requirementText: 'optional',
79
+ helpText: 'Help text',
80
+ id: 'inputFullId',
81
+ default: `
82
+ <MTextInput
83
+ id="inputFullId"
84
+ placeholder="Placeholder"
85
+ @update:modelValue="handleUpdate"
86
+ />
87
+ `,
88
+ },
89
+ };
90
+
91
+ export const InputValid: Story = {
92
+ args: {
93
+ label: 'Label',
94
+ requirementText: 'required',
95
+ helpText: 'Help text',
96
+ id: 'inputvalidId',
97
+ isValid: true,
98
+ message: 'Validation message (Be concise and use comprehensive words).',
99
+ default: `
100
+ <MTextInput
101
+ id="inputvalidId"
102
+ placeholder="Placeholder"
103
+ @update:modelValue="handleUpdate"
104
+ />
105
+ `,
106
+ },
107
+ };
108
+
109
+ export const InputInvalid: Story = {
110
+ args: {
111
+ label: 'Label',
112
+ requirementText: 'required',
113
+ helpText: 'Help text',
114
+ id: 'inputInvalidId',
115
+ isInvalid: true,
116
+ message: 'Error message (Be concise and use comprehensive words)',
117
+ default: `
118
+ <MTextInput
119
+ id="inputInvalidId"
120
+ placeholder="Placeholder"
121
+ isInvalid
122
+ @update:modelValue="handleUpdate"
123
+ />
124
+ `,
125
+ },
126
+ };
127
+
128
+ export const Textarea: Story = {
129
+ args: {
130
+ label: 'Label',
131
+ id: 'textareaId',
132
+ default: `
133
+ <MTextArea
134
+ id="textareaId"
135
+ placeholder="Placeholder"
136
+ @update:modelValue="handleUpdate"
137
+ />
138
+ `,
139
+ },
140
+ render: (args) => ({
141
+ components: { MField, MTextArea },
142
+ setup() {
143
+ const handleUpdate = action('update:modelValue');
144
+
145
+ return { args, handleUpdate };
146
+ },
147
+ template: `
148
+ <MField v-bind="args">
149
+ ${args.default}
150
+ </MField>
151
+ `,
152
+ }),
153
+ };
154
+
155
+ export const TextareaValid: Story = {
156
+ args: {
157
+ label: 'Label',
158
+ id: 'textareaValidId',
159
+ requirementText: 'required',
160
+ helpText: 'Help text',
161
+ isValid: true,
162
+ message: 'Validation message (Be concise and use comprehensive words).',
163
+ default: `
164
+ <MTextArea
165
+ id="textareaValidId"
166
+ placeholder="Placeholder"
167
+ @update:modelValue="handleUpdate"
168
+ />
169
+ `,
170
+ },
171
+ render: (args) => ({
172
+ components: { MField, MTextArea },
173
+ setup() {
174
+ const handleUpdate = action('update:modelValue');
175
+
176
+ return { args, handleUpdate };
177
+ },
178
+ template: `
179
+ <MField v-bind="args">
180
+ ${args.default}
181
+ </MField>
182
+ `,
183
+ }),
184
+ };
185
+
186
+ export const TextareaInvalid: Story = {
187
+ args: {
188
+ label: 'Label',
189
+ id: 'textareaValidId',
190
+ requirementText: 'required',
191
+ helpText: 'Help text',
192
+ isInvalid: true,
193
+ message: 'Error message (Be concise and use comprehensive words)',
194
+ default: `
195
+ <MTextArea
196
+ id="textareaValidId"
197
+ isInvalid
198
+ placeholder="Placeholder"
199
+ @update:modelValue="handleUpdate"
200
+ />
201
+ `,
202
+ },
203
+ render: (args) => ({
204
+ components: { MField, MTextArea },
205
+ setup() {
206
+ const handleUpdate = action('update:modelValue');
207
+
208
+ return { args, handleUpdate };
209
+ },
210
+ template: `
211
+ <MField v-bind="args">
212
+ ${args.default}
213
+ </MField>
214
+ `,
215
+ }),
216
+ };
217
+
218
+ export const Select: Story = {
219
+ args: {
220
+ label: 'Label',
221
+ id: 'selectId',
222
+ default: `
223
+ <MSelect
224
+ id="selectId"
225
+ name="selectName"
226
+ placeholder="Choose an option"
227
+ :options="
228
+ [
229
+ {
230
+ text: 'Option 1',
231
+ value: 'option1',
232
+ },
233
+ {
234
+ text: 'Option 2',
235
+ value: 'option2',
236
+ },
237
+ {
238
+ text: 'Option 3',
239
+ value: 'option3',
240
+ },
241
+ {
242
+ text: 'Option 4',
243
+ value: 'option4',
244
+ },
245
+ ]
246
+ "
247
+ @update:modelValue="handleUpdate"
248
+ />
249
+ `,
250
+ },
251
+ render: (args) => ({
252
+ components: { MField, MSelect },
253
+ setup() {
254
+ const handleUpdate = action('update:modelValue');
255
+
256
+ return { args, handleUpdate };
257
+ },
258
+ template: `
259
+ <MField v-bind="args">
260
+ ${args.default}
261
+ </MField>
262
+ `,
263
+ }),
264
+ };
265
+
266
+ export const SelectValid: Story = {
267
+ args: {
268
+ label: 'Label',
269
+ id: 'selectValidId',
270
+ requirementText: 'required',
271
+ helpText: 'Help text',
272
+ isValid: true,
273
+ message: 'Validation message (Be concise and use comprehensive words).',
274
+ default: `
275
+ <MSelect
276
+ id="selectValidId"
277
+ name="selectValidName"
278
+ placeholder="Choose an option"
279
+ :options="
280
+ [
281
+ {
282
+ text: 'Option 1',
283
+ value: 'option1',
284
+ },
285
+ {
286
+ text: 'Option 2',
287
+ value: 'option2',
288
+ },
289
+ {
290
+ text: 'Option 3',
291
+ value: 'option3',
292
+ },
293
+ {
294
+ text: 'Option 4',
295
+ value: 'option4',
296
+ },
297
+ ]
298
+ "
299
+ @update:modelValue="handleUpdate"
300
+ />
301
+ `,
302
+ },
303
+ render: (args) => ({
304
+ components: { MField, MSelect },
305
+ setup() {
306
+ const handleUpdate = action('update:modelValue');
307
+
308
+ return { args, handleUpdate };
309
+ },
310
+ template: `
311
+ <MField v-bind="args">
312
+ ${args.default}
313
+ </MField>
314
+ `,
315
+ }),
316
+ };
317
+
318
+ export const SelectInvalid: Story = {
319
+ args: {
320
+ label: 'Label',
321
+ id: 'selectInvalidId',
322
+ requirementText: 'required',
323
+ helpText: 'Help text',
324
+ isInvalid: true,
325
+ message: 'Error message (Be concise and use comprehensive words)',
326
+ default: `
327
+ <MSelect
328
+ id="selectInvalidId"
329
+ name="selectInvalidName"
330
+ isInvalid
331
+ placeholder="Choose an option"
332
+ :options="
333
+ [
334
+ {
335
+ text: 'Option 1',
336
+ value: 'option1',
337
+ },
338
+ {
339
+ text: 'Option 2',
340
+ value: 'option2',
341
+ },
342
+ {
343
+ text: 'Option 3',
344
+ value: 'option3',
345
+ },
346
+ {
347
+ text: 'Option 4',
348
+ value: 'option4',
349
+ },
350
+ ]
351
+ "
352
+ @update:modelValue="handleUpdate"
353
+ />
354
+ `,
355
+ },
356
+ render: (args) => ({
357
+ components: { MField, MSelect },
358
+ setup() {
359
+ const handleUpdate = action('update:modelValue');
360
+
361
+ return { args, handleUpdate };
362
+ },
363
+ template: `
364
+ <MField v-bind="args">
365
+ ${args.default}
366
+ </MField>
367
+ `,
368
+ }),
369
+ };
@@ -1,73 +1,90 @@
1
1
  <template>
2
2
  <div class="mc-field">
3
- <label :for="id" class="mc-field__label">
3
+ <label class="mc-field__label" :for="id">
4
4
  {{ label }}
5
- <span
6
- v-if="requirementText"
7
- class="mc-field__requirement"
8
- aria-hidden="true"
5
+ <span v-if="requirementText" class="mc-field__requirement"
6
+ >({{ requirementText }})</span
9
7
  >
10
- {{ requirementText }}
11
- </span>
12
8
  </label>
13
- <span v-if="helpId && helpText" :id="helpId" class="mc-field__help">
14
- {{ helpText }}
15
- </span>
16
- <slot />
17
- <span v-if="isInvalid" :id="errorId" class="mc-field__error-message">
18
- {{ errorMessage }}
9
+
10
+ <span v-if="helpId && helpText" :id="helpId" class="mc-field__help">{{
11
+ helpText
12
+ }}</span>
13
+
14
+ <div class="mc-field__content">
15
+ <slot />
16
+ </div>
17
+
18
+ <span
19
+ v-if="(isValid || isInvalid) && message"
20
+ class="mc-field__validation-message"
21
+ :id="messageId"
22
+ :class="classObjectValidation"
23
+ >
24
+ {{ message }}
19
25
  </span>
20
26
  </div>
21
27
  </template>
22
28
 
23
- <script>
24
- export default {
25
- name: 'MField',
26
- provide: {
27
- cssFieldElementClass: 'mc-field__element',
28
- },
29
- props: {
30
- id: {
31
- type: String,
32
- required: true,
33
- },
34
- label: {
35
- type: String,
36
- required: true,
37
- },
38
- required: {
39
- type: Boolean,
40
- default: false,
41
- },
42
- requirementText: {
43
- type: String,
44
- default: null,
45
- },
46
- helpId: {
47
- type: String,
48
- default: null,
49
- },
50
- helpText: {
51
- type: String,
52
- default: null,
53
- },
54
- errorId: {
55
- type: String,
56
- default: null,
57
- },
58
- errorMessage: {
59
- type: String,
60
- default: null,
61
- },
62
- isInvalid: {
63
- type: Boolean,
64
- default: false,
65
- },
66
- },
67
- };
29
+ <script setup lang="ts">
30
+ import { computed, type VNode } from 'vue';
31
+ /**
32
+ * This component creates a structured form field with a label, optional help text, error and validation message handling.
33
+ */
34
+ const props = defineProps<{
35
+ /**
36
+ * A unique identifier for the form field, used to associate the label with the form element.
37
+ */
38
+ id: string;
39
+ /**
40
+ * The text displayed as the label for the form field.
41
+ */
42
+ label: string;
43
+ /**
44
+ * Additional text displayed alongside the label, typically used to indicate if the form field is required or optional
45
+ */
46
+ requirementText?: string;
47
+ /**
48
+ * Text shown below the form field to provide additional context or instructions for the user.
49
+ */
50
+ helpText?: string;
51
+ /**
52
+ * The value of the `id` attribute set on the **helpText** element. _This value is mandatory when using a helpText in order to guarantee the accessibility of the component._
53
+ */
54
+ helpId?: string;
55
+ /**
56
+ * If `true`, applies a valid state to the form field.
57
+ */
58
+ isValid?: boolean;
59
+ /**
60
+ * If `true`, applies an invalid state to the form field.
61
+ */
62
+ isInvalid?: boolean;
63
+ /**
64
+ * The value of the `id` attribute set on the **validationMessage** element. _This value is mandatory when using a validationMessage in order to guarantee the accessibility of the component._
65
+ */
66
+ messageId?: string;
67
+ /**
68
+ * message displayed when the form field has a valid or invalid state, usually indicating validation or errors.
69
+ */
70
+ message?: string;
71
+ }>();
72
+
73
+ defineSlots<{
74
+ /**
75
+ * Use this slot to insert the form element of your choice
76
+ */
77
+ default: VNode;
78
+ }>();
79
+
80
+ const classObjectValidation = computed(() => {
81
+ return {
82
+ 'is-valid': props.isValid,
83
+ 'is-invalid': props.isInvalid,
84
+ };
85
+ });
68
86
  </script>
69
87
 
70
- <style lang="scss">
71
- @import 'settings-tools/_all-settings';
72
- @import 'components/_c.fields';
88
+ <style lang="scss" scoped>
89
+ @use '@mozaic-ds/styles/components/field';
73
90
  </style>