@mozaic-ds/vue 1.0.0-beta.3 → 1.0.0-beta.4

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 (179) hide show
  1. package/LICENSE +51 -0
  2. package/README.md +218 -84
  3. package/dist/mozaic-vue.css +1 -1
  4. package/dist/mozaic-vue.d.ts +920 -0
  5. package/dist/mozaic-vue.js +877 -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 +80 -50
  11. package/src/components/Contributing.mdx +118 -0
  12. package/src/components/GettingStarted.mdx +39 -0
  13. package/src/components/Introduction.mdx +54 -0
  14. package/src/components/Support.mdx +18 -0
  15. package/src/components/badge/MBadge.spec.ts +16 -0
  16. package/src/components/badge/MBadge.stories.ts +50 -0
  17. package/src/components/badge/MBadge.vue +36 -34
  18. package/src/components/button/MButton.spec.ts +191 -0
  19. package/src/components/button/MButton.stories.ts +66 -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/field/MField.spec.ts +166 -0
  28. package/src/components/field/MField.stories.ts +376 -0
  29. package/src/components/field/MField.vue +78 -61
  30. package/src/components/fieldgroup/MFieldGroup.spec.ts +165 -0
  31. package/src/components/fieldgroup/MFieldGroup.stories.ts +274 -0
  32. package/src/components/fieldgroup/MFieldGroup.vue +79 -0
  33. package/src/components/iconbutton/MIconButton.spec.ts +108 -0
  34. package/src/components/iconbutton/MIconButton.stories.ts +66 -0
  35. package/src/components/iconbutton/MIconButton.vue +73 -0
  36. package/src/components/link/MLink.spec.ts +154 -0
  37. package/src/components/link/MLink.stories.ts +98 -0
  38. package/src/components/link/MLink.vue +86 -109
  39. package/src/components/loader/MLoader.spec.ts +104 -0
  40. package/src/components/loader/MLoader.stories.ts +45 -0
  41. package/src/components/loader/MLoader.vue +65 -55
  42. package/src/components/overlay/MOverlay.spec.ts +51 -0
  43. package/src/components/overlay/MOverlay.stories.ts +40 -0
  44. package/src/components/overlay/MOverlay.vue +27 -19
  45. package/src/components/quantityselector/MQuantitySelector.spec.ts +262 -0
  46. package/src/components/quantityselector/MQuantitySelector.stories.ts +89 -0
  47. package/src/components/quantityselector/MQuantitySelector.vue +160 -136
  48. package/src/components/radio/MRadio.spec.ts +104 -0
  49. package/src/components/radio/MRadio.stories.ts +68 -0
  50. package/src/components/radio/MRadio.vue +56 -39
  51. package/src/components/radiogroup/MRadioGroup.spec.ts +54 -0
  52. package/src/components/radiogroup/MRadioGroup.stories.ts +61 -0
  53. package/src/components/radiogroup/MRadioGroup.vue +79 -0
  54. package/src/components/select/MSelect.spec.ts +114 -0
  55. package/src/components/select/MSelect.stories.ts +101 -0
  56. package/src/components/select/MSelect.vue +77 -119
  57. package/src/components/statusbadge/MStatusBadge.stories.ts +45 -0
  58. package/src/components/statusbadge/MStatusBadge.vue +40 -0
  59. package/src/components/statusbadge/MStatusDot.vue +32 -0
  60. package/src/components/statusbadge/MstatusBadge.spec.ts +16 -0
  61. package/src/components/textarea/MTextArea.spec.ts +112 -0
  62. package/src/components/textarea/MTextArea.stories.ts +67 -0
  63. package/src/components/textarea/MTextArea.vue +81 -42
  64. package/src/components/textinput/MTextInput.spec.ts +121 -0
  65. package/src/components/textinput/MTextInput.stories.ts +114 -0
  66. package/src/components/textinput/MTextInput.vue +127 -47
  67. package/src/components/toggle/MToggle.spec.ts +99 -0
  68. package/src/components/toggle/MToggle.stories.ts +68 -0
  69. package/src/components/toggle/MToggle.vue +63 -103
  70. package/src/components/usingIcons.mdx +43 -0
  71. package/src/components/usingPresets.mdx +125 -0
  72. package/src/main.ts +39 -0
  73. package/dist/demo.html +0 -1
  74. package/dist/mozaic-vue.adeo.css +0 -45
  75. package/dist/mozaic-vue.adeo.umd.js +0 -41775
  76. package/dist/mozaic-vue.common.js +0 -41765
  77. package/dist/mozaic-vue.common.js.map +0 -1
  78. package/dist/mozaic-vue.umd.js +0 -41776
  79. package/dist/mozaic-vue.umd.js.map +0 -1
  80. package/dist/mozaic-vue.umd.min.js +0 -4
  81. package/dist/mozaic-vue.umd.min.js.map +0 -1
  82. package/postinstall.js +0 -3
  83. package/src/components/accordion/MAccordion.vue +0 -128
  84. package/src/components/accordion/index.js +0 -7
  85. package/src/components/autocomplete/MAutocomplete.vue +0 -198
  86. package/src/components/autocomplete/index.js +0 -7
  87. package/src/components/badge/index.js +0 -7
  88. package/src/components/breadcrumb/MBreadcrumb.vue +0 -73
  89. package/src/components/breadcrumb/index.js +0 -7
  90. package/src/components/button/index.js +0 -7
  91. package/src/components/card/MCard.vue +0 -78
  92. package/src/components/card/index.js +0 -7
  93. package/src/components/checkbox/MCheckboxGroup.vue +0 -155
  94. package/src/components/checkbox/index.js +0 -12
  95. package/src/components/container/MContainer.vue +0 -33
  96. package/src/components/container/index.js +0 -7
  97. package/src/components/datatable/MDataTable.vue +0 -651
  98. package/src/components/datatable/MDataTableHeader.vue +0 -55
  99. package/src/components/datatable/MDataTableTop.vue +0 -35
  100. package/src/components/datatable/helpers.js +0 -132
  101. package/src/components/datatable/index.js +0 -12
  102. package/src/components/field/index.js +0 -7
  103. package/src/components/fileuploader/MFileResult.vue +0 -149
  104. package/src/components/fileuploader/MFileUploader.vue +0 -142
  105. package/src/components/fileuploader/index.js +0 -7
  106. package/src/components/flag/MFlag.vue +0 -46
  107. package/src/components/flag/index.js +0 -7
  108. package/src/components/heading/MHeading.vue +0 -75
  109. package/src/components/heading/index.js +0 -7
  110. package/src/components/hero/MHero.vue +0 -93
  111. package/src/components/hero/index.js +0 -7
  112. package/src/components/icon/MIcon.vue +0 -120
  113. package/src/components/icon/index.js +0 -7
  114. package/src/components/index.js +0 -43
  115. package/src/components/layer/MLayer.vue +0 -208
  116. package/src/components/layer/index.js +0 -7
  117. package/src/components/link/index.js +0 -7
  118. package/src/components/listbox/MListBox.vue +0 -106
  119. package/src/components/listbox/index.js +0 -7
  120. package/src/components/loader/index.js +0 -7
  121. package/src/components/modal/MModal.vue +0 -179
  122. package/src/components/modal/index.js +0 -7
  123. package/src/components/notification/MNotification.vue +0 -110
  124. package/src/components/notification/index.js +0 -7
  125. package/src/components/optionbutton/MOptionButton.vue +0 -67
  126. package/src/components/optionbutton/index.js +0 -7
  127. package/src/components/optioncard/MOptionCard.vue +0 -132
  128. package/src/components/optioncard/index.js +0 -7
  129. package/src/components/optiongroup/MOptionGroup.vue +0 -18
  130. package/src/components/optiongroup/index.js +0 -7
  131. package/src/components/overlay/MOverlayLoader.vue +0 -43
  132. package/src/components/overlay/index.js +0 -12
  133. package/src/components/pagination/MPagination.vue +0 -162
  134. package/src/components/pagination/index.js +0 -7
  135. package/src/components/passwordinput/MPasswordInput.vue +0 -96
  136. package/src/components/passwordinput/index.js +0 -7
  137. package/src/components/phonenumber/MPhoneNumber.vue +0 -390
  138. package/src/components/phonenumber/index.js +0 -7
  139. package/src/components/progressbar/MProgress.vue +0 -102
  140. package/src/components/progressbar/index.js +0 -7
  141. package/src/components/quantityselector/index.js +0 -7
  142. package/src/components/radio/MRadioGroup.vue +0 -111
  143. package/src/components/radio/index.js +0 -12
  144. package/src/components/ratingstars/MStarsInput.vue +0 -118
  145. package/src/components/ratingstars/MStarsResult.vue +0 -89
  146. package/src/components/ratingstars/index.js +0 -12
  147. package/src/components/select/index.js +0 -7
  148. package/src/components/stepper/MStepper.vue +0 -70
  149. package/src/components/stepper/index.js +0 -7
  150. package/src/components/tabs/MTab.vue +0 -184
  151. package/src/components/tabs/index.js +0 -7
  152. package/src/components/tags/MTag.vue +0 -173
  153. package/src/components/tags/index.js +0 -7
  154. package/src/components/textarea/index.js +0 -7
  155. package/src/components/textinput/MTextInputField.vue +0 -105
  156. package/src/components/textinput/MTextInputIcon.vue +0 -42
  157. package/src/components/textinput/index.js +0 -7
  158. package/src/components/toggle/index.js +0 -7
  159. package/src/components/tooltip/MTooltip.vue +0 -42
  160. package/src/components/tooltip/index.js +0 -7
  161. package/src/index.js +0 -62
  162. package/src/shims-tsx.d.ts +0 -13
  163. package/src/shims.vue.d.ts +0 -4
  164. package/src/tokens/adeo/android/colors.xml +0 -391
  165. package/src/tokens/adeo/android/font_dimens.xml +0 -18
  166. package/src/tokens/adeo/css/_variables.scss +0 -385
  167. package/src/tokens/adeo/css/root.scss +0 -387
  168. package/src/tokens/adeo/ios/StyleDictionaryColor.h +0 -399
  169. package/src/tokens/adeo/ios/StyleDictionaryColor.m +0 -411
  170. package/src/tokens/adeo/ios/StyleDictionaryColor.swift +0 -394
  171. package/src/tokens/adeo/ios/StyleDictionarySize.h +0 -69
  172. package/src/tokens/adeo/ios/StyleDictionarySize.m +0 -70
  173. package/src/tokens/adeo/ios/StyleDictionarySize.swift +0 -71
  174. package/src/tokens/adeo/js/tokens.js +0 -483
  175. package/src/tokens/adeo/js/tokensObject.js +0 -10354
  176. package/src/tokens/adeo/scss/_tokens.scss +0 -1300
  177. package/src/utils/mozaicClasses.js +0 -16
  178. package/src/utils/theme.validator.js +0 -19
  179. package/types/index.d.ts +0 -100
@@ -0,0 +1,16 @@
1
+ import { describe, it, expect } from 'vitest';
2
+
3
+ import { mount } from '@vue/test-utils';
4
+ import MStatusBadge from './MStatusBadge.vue';
5
+
6
+ describe('MStatusBadge component', () => {
7
+ it('renders properly', () => {
8
+ const wrapper = mount(MStatusBadge, {
9
+ props: {
10
+ label: 'Badge Label',
11
+ },
12
+ });
13
+
14
+ expect(wrapper.text()).toContain('Badge Label');
15
+ });
16
+ });
@@ -0,0 +1,112 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect } from 'vitest';
3
+ import MTextArea from './MTextArea.vue';
4
+
5
+ describe('MTextArea component', () => {
6
+ it('should render correctly with the given props', () => {
7
+ const wrapper = mount(MTextArea, {
8
+ props: {
9
+ id: 'textarea-id',
10
+ modelValue: 'Test value',
11
+ placeholder: 'Enter text here...',
12
+ rows: 5,
13
+ maxLength: 200,
14
+ },
15
+ });
16
+
17
+ const textarea = wrapper.find('textarea');
18
+
19
+ expect(textarea.attributes('id')).toBe('textarea-id');
20
+ expect(textarea.attributes('placeholder')).toBe('Enter text here...');
21
+ expect(textarea.attributes('rows')).toBe('5');
22
+ expect(textarea.attributes('maxlength')).toBe('200');
23
+ });
24
+
25
+ it('should apply is-invalid class when isInvalid prop is true', () => {
26
+ const wrapper = mount(MTextArea, {
27
+ props: {
28
+ id: 'textarea-id',
29
+ modelValue: 'Test value',
30
+ isInvalid: true,
31
+ },
32
+ });
33
+
34
+ const textarea = wrapper.find('textarea');
35
+ expect(textarea.classes()).toContain('is-invalid');
36
+ });
37
+
38
+ it('should update modelValue when the textarea value changes', async () => {
39
+ const wrapper = mount(MTextArea, {
40
+ props: {
41
+ id: 'textarea-id',
42
+ modelValue: 'Initial value',
43
+ },
44
+ });
45
+
46
+ const textarea = wrapper.find('textarea');
47
+ await textarea.setValue('Updated value');
48
+
49
+ expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
50
+ expect(wrapper.emitted()['update:modelValue'][0]).toEqual([
51
+ 'Updated value',
52
+ ]);
53
+ });
54
+
55
+ it('should not allow changes if the textarea is disabled', async () => {
56
+ const wrapper = mount(MTextArea, {
57
+ props: {
58
+ id: 'textarea-id',
59
+ modelValue: 'Initial value',
60
+ disabled: true,
61
+ },
62
+ });
63
+
64
+ const textarea = wrapper.find('textarea');
65
+ expect(textarea.attributes('disabled')).toBeDefined();
66
+
67
+ await textarea.setValue('Updated value');
68
+
69
+ expect(wrapper.emitted()['update:modelValue']).toBeFalsy();
70
+ });
71
+
72
+ it('should be read-only if the readonly prop is true', async () => {
73
+ const wrapper = mount(MTextArea, {
74
+ props: {
75
+ id: 'textarea-id',
76
+ modelValue: 'Initial value',
77
+ readonly: true,
78
+ },
79
+ });
80
+
81
+ const textarea = wrapper.find('textarea');
82
+ expect(textarea.attributes('readonly')).toBeDefined();
83
+
84
+ await textarea.setValue('Updated value');
85
+
86
+ expect(textarea.attributes('value')).toBe('Initial value');
87
+ });
88
+
89
+ it('should apply a default classObject computed class', () => {
90
+ const wrapper = mount(MTextArea, {
91
+ props: {
92
+ id: 'textarea-id',
93
+ modelValue: 'Test value',
94
+ },
95
+ });
96
+
97
+ expect(wrapper.classes()).toContain('mc-textarea');
98
+ });
99
+
100
+ it('should correctly bind rows attribute', () => {
101
+ const wrapper = mount(MTextArea, {
102
+ props: {
103
+ id: 'textarea-id',
104
+ modelValue: 'Test value',
105
+ rows: 4,
106
+ },
107
+ });
108
+
109
+ const textarea = wrapper.find('textarea');
110
+ expect(textarea.attributes('rows')).toBe('4');
111
+ });
112
+ });
@@ -0,0 +1,67 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3';
2
+ import { action } from '@storybook/addon-actions';
3
+
4
+ import MTextArea from './MTextArea.vue';
5
+
6
+ const meta: Meta<typeof MTextArea> = {
7
+ title: 'Form Elements/Textarea',
8
+ component: MTextArea,
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component:
13
+ 'A textarea is a form element for multi-line text input, ideal for longer content like comments or descriptions.<br><br> To put a label, requierement text, help text or to apply a valid or invalid message, the examples are available in the [Field section](/docs/form-elements-field--docs#textarea).',
14
+ },
15
+ },
16
+ },
17
+ args: {
18
+ id: 'textareaId',
19
+ placeholder: 'Placeholder',
20
+ },
21
+ render: (args) => ({
22
+ components: { MTextArea },
23
+ setup() {
24
+ const handleUpdate = action('update:modelValue');
25
+
26
+ return { args, handleUpdate };
27
+ },
28
+ template: `
29
+ <MTextArea
30
+ v-bind="args"
31
+ @update:modelValue="handleUpdate"
32
+ />
33
+ `,
34
+ }),
35
+ };
36
+ export default meta;
37
+ type Story = StoryObj<typeof MTextArea>;
38
+
39
+ export const WithValue: Story = {
40
+ args: {
41
+ id: 'withValueId',
42
+ modelValue: 'Value of the textarea component',
43
+ },
44
+ };
45
+
46
+ export const Default: Story = {};
47
+
48
+ export const Disabled: Story = {
49
+ args: {
50
+ id: 'disabledId',
51
+ disabled: true,
52
+ },
53
+ };
54
+
55
+ export const ReadOnly: Story = {
56
+ args: {
57
+ id: 'readonlyId',
58
+ readonly: true,
59
+ },
60
+ };
61
+
62
+ export const Invalid: Story = {
63
+ args: {
64
+ id: 'invalidId',
65
+ isInvalid: true,
66
+ },
67
+ };
@@ -1,53 +1,92 @@
1
1
  <template>
2
2
  <textarea
3
+ :id="id"
3
4
  class="mc-textarea"
4
- :class="[
5
- { 'is-valid': isValid, 'is-invalid': isInvalid },
6
- cssFieldElementClass,
7
- ]"
5
+ :class="classObject"
8
6
  :aria-invalid="isInvalid"
9
- :value="value"
10
- v-on="inputListeners"
7
+ :value="modelValue"
8
+ :name="name"
9
+ :placeholder="placeholder"
10
+ :disabled="disabled"
11
+ :minlength="minLength"
12
+ :maxlength="maxLength"
13
+ :rows="rows"
14
+ :readonly="readonly"
15
+ v-bind="$attrs"
16
+ @input="
17
+ emit('update:modelValue', ($event.target as HTMLInputElement).value)
18
+ "
11
19
  />
12
20
  </template>
13
21
 
14
- <script>
15
- export default {
16
- name: 'MTextArea',
17
- inject: {
18
- cssFieldElementClass: {
19
- default: '',
20
- },
21
- },
22
- props: {
23
- value: {
24
- type: String,
25
- default: null,
26
- },
27
- isValid: {
28
- type: Boolean,
29
- default: false,
30
- },
31
- isInvalid: {
32
- type: Boolean,
33
- default: false,
34
- },
35
- },
36
- computed: {
37
- inputListeners: function () {
38
- // see => https://vuejs.org/v2/guide/components-custom-events.html#Binding-Native-Events-to-Components
39
- var vm = this;
40
- return Object.assign({}, this.$listeners, {
41
- input: function (event) {
42
- vm.$emit('input', event.target.value);
43
- },
44
- });
45
- },
22
+ <script setup lang="ts">
23
+ import { computed } from 'vue';
24
+
25
+ /**
26
+ * A textarea is a form element for multi-line text input, ideal for longer content like comments or descriptions.
27
+ */
28
+ const props = withDefaults(
29
+ defineProps<{
30
+ /**
31
+ * A unique identifier for the textarea, used to associate the label with the form element.
32
+ */
33
+ id: string;
34
+ /**
35
+ * The name attribute for the textarea element, used for form submission.
36
+ */
37
+ name?: string;
38
+ /**
39
+ * The current value of the textarea field.
40
+ */
41
+ modelValue?: string | number;
42
+ /**
43
+ * Text displayed when the textarea is empty.
44
+ */
45
+ placeholder?: string;
46
+ /**
47
+ * If `true`, the textarea is marked as invalid.
48
+ */
49
+ isInvalid?: boolean;
50
+ /**
51
+ * If `true`, the textarea is disabled and non-interactive.
52
+ */
53
+ disabled?: boolean;
54
+ /**
55
+ * The number of visible text lines in the textarea.
56
+ */
57
+ rows?: number;
58
+ /**
59
+ * Minimum number of characters required for the textarea.
60
+ */
61
+ minLength?: number;
62
+ /**
63
+ * Maximum number of characters allowed in the textarea.
64
+ */
65
+ maxLength?: number;
66
+ /**
67
+ * If `true`, the textarea is read-only (cannot be edited).
68
+ */
69
+ readonly?: boolean;
70
+ }>(),
71
+ {
72
+ rows: 2,
46
73
  },
47
- };
74
+ );
75
+
76
+ const classObject = computed(() => {
77
+ return {
78
+ 'is-invalid': props.isInvalid,
79
+ };
80
+ });
81
+
82
+ const emit = defineEmits<{
83
+ /**
84
+ * Emits when the textarea value changes, updating the modelValue prop.
85
+ */
86
+ (on: 'update:modelValue', value: string | number): void;
87
+ }>();
48
88
  </script>
49
89
 
50
- <style lang="scss">
51
- @import 'settings-tools/_all-settings';
52
- @import 'components/_c.textarea';
90
+ <style lang="scss" scoped>
91
+ @use '@mozaic-ds/styles/components/textarea';
53
92
  </style>
@@ -0,0 +1,121 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect } from 'vitest';
3
+ import MTextInput from './MTextInput.vue';
4
+ import Search24 from '@mozaic-ds/icons-vue/src/components/Search24/Search24.vue';
5
+
6
+ describe('MTextInput component', () => {
7
+ it('should render correctly with the given props', () => {
8
+ const wrapper = mount(MTextInput, {
9
+ props: {
10
+ id: 'input-id',
11
+ modelValue: 'test',
12
+ placeholder: 'Enter text',
13
+ inputType: 'text',
14
+ size: 's',
15
+ },
16
+ });
17
+
18
+ const input = wrapper.find('input');
19
+
20
+ expect(input.attributes('id')).toBe('input-id');
21
+ expect(input.attributes('placeholder')).toBe('Enter text');
22
+ expect(input.attributes('type')).toBe('text');
23
+ expect(wrapper.classes()).toContain('mc-text-input--s');
24
+ });
25
+
26
+ it('should update modelValue when input value changes', async () => {
27
+ const wrapper = mount(MTextInput, {
28
+ props: {
29
+ id: 'input-id',
30
+ modelValue: 'initial value',
31
+ },
32
+ });
33
+
34
+ const input = wrapper.find('input');
35
+ await input.setValue('new value');
36
+
37
+ expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
38
+ expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['new value']);
39
+ });
40
+
41
+ it('should render Search24 icon when passed to icon slot', () => {
42
+ const wrapper = mount(MTextInput, {
43
+ props: {
44
+ id: 'input-id',
45
+ modelValue: 'test',
46
+ },
47
+ slots: {
48
+ icon: Search24,
49
+ },
50
+ });
51
+
52
+ const iconWrapper = wrapper.find('.mc-text-input__icon');
53
+ expect(iconWrapper.exists()).toBe(true);
54
+ expect(iconWrapper.findComponent(Search24).exists()).toBe(true);
55
+ });
56
+
57
+ it('should render the clear button when isClearable is true and modelValue is not empty', () => {
58
+ const wrapper = mount(MTextInput, {
59
+ props: {
60
+ id: 'input-id',
61
+ modelValue: 'text content',
62
+ isClearable: true,
63
+ },
64
+ });
65
+
66
+ const clearButton = wrapper.find('.mc-controls-options__button');
67
+ expect(clearButton.exists()).toBe(true);
68
+ });
69
+
70
+ it('should clear the input value when the clear button is clicked', async () => {
71
+ const wrapper = mount(MTextInput, {
72
+ props: {
73
+ id: 'input-id',
74
+ modelValue: 'text content',
75
+ isClearable: true,
76
+ },
77
+ });
78
+
79
+ const clearButton = wrapper.find('.mc-controls-options__button');
80
+ await clearButton.trigger('click');
81
+
82
+ expect(wrapper.vm.modelValue).toBe('');
83
+ expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['']);
84
+ });
85
+
86
+ it('should not render the clear button if isClearable is false', () => {
87
+ const wrapper = mount(MTextInput, {
88
+ props: {
89
+ id: 'input-id',
90
+ modelValue: 'text content',
91
+ isClearable: false,
92
+ },
93
+ });
94
+
95
+ const clearButton = wrapper.find('.mc-controls-options__button');
96
+ expect(clearButton.exists()).toBe(false);
97
+ });
98
+
99
+ it('should apply the correct classes based on validation props', () => {
100
+ const wrapper = mount(MTextInput, {
101
+ props: {
102
+ id: 'input-id',
103
+ modelValue: 'text content',
104
+ isInvalid: true,
105
+ },
106
+ });
107
+
108
+ expect(wrapper.classes()).toContain('is-invalid');
109
+ });
110
+
111
+ it('should not apply is-invalid if not specified', () => {
112
+ const wrapper = mount(MTextInput, {
113
+ props: {
114
+ id: 'input-id',
115
+ modelValue: 'text content',
116
+ },
117
+ });
118
+
119
+ expect(wrapper.classes()).not.toContain('is-invalid');
120
+ });
121
+ });
@@ -0,0 +1,114 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3';
2
+ import { action } from '@storybook/addon-actions';
3
+
4
+ import MTextInput from './MTextInput.vue';
5
+ import Search24 from '@mozaic-ds/icons-vue/src/components/Search24/Search24.vue';
6
+
7
+ const meta: Meta<typeof MTextInput> = {
8
+ title: 'Form Elements/TextInput',
9
+ component: MTextInput,
10
+ parameters: {
11
+ docs: {
12
+ description: {
13
+ component:
14
+ 'Inputs are used to create input fields with text on a single line. Their states depends on the user interaction or the context.<br><br> To put a label, requierement text, help text or to apply a valid or invalid message, the examples are available in the [Field section](/docs/form-elements-field--docs#input).',
15
+ },
16
+ },
17
+ },
18
+ args: {
19
+ id: 'textInputId',
20
+ placeholder: 'Placeholder',
21
+ },
22
+ argTypes: {
23
+ $slots: {
24
+ table: {
25
+ disable: true,
26
+ },
27
+ },
28
+ },
29
+ render: (args) => ({
30
+ components: { MTextInput, Search24 },
31
+ setup() {
32
+ const handleUpdate = action('update:modelValue');
33
+
34
+ return { args, handleUpdate };
35
+ },
36
+ template: `
37
+ <MTextInput
38
+ v-bind="args"
39
+ @update:modelValue="handleUpdate"
40
+ />
41
+ `,
42
+ }),
43
+ };
44
+ export default meta;
45
+ type Story = StoryObj<typeof MTextInput>;
46
+
47
+ export const WithValue: Story = {
48
+ args: {
49
+ id: 'withValueId',
50
+ modelValue: 'Value of the input component',
51
+ isClearable: true,
52
+ },
53
+ };
54
+
55
+ export const Default: Story = {};
56
+
57
+ export const Small: Story = {
58
+ args: {
59
+ id: 'smallId',
60
+ size: 's',
61
+ },
62
+ };
63
+
64
+ export const WithIcon: Story = {
65
+ args: {
66
+ id: 'withIconId',
67
+ icon: `
68
+ <template v-slot:icon>
69
+ <Search24/>
70
+ </template>
71
+ `,
72
+ },
73
+ render: (args) => ({
74
+ components: { MTextInput, Search24 },
75
+ setup() {
76
+ return { args };
77
+ },
78
+ template: `
79
+ <MTextInput v-bind="args">
80
+ ${args.icon}
81
+ </MTextInput>
82
+ `,
83
+ }),
84
+ };
85
+
86
+ export const minValue: Story = {
87
+ args: {
88
+ id: 'minValueId',
89
+ inputType: 'number',
90
+ modelValue: '4',
91
+ min: '3',
92
+ },
93
+ };
94
+
95
+ export const Disabled: Story = {
96
+ args: {
97
+ id: 'disableId',
98
+ disabled: true,
99
+ },
100
+ };
101
+
102
+ export const ReadOnly: Story = {
103
+ args: {
104
+ id: 'readonlyId',
105
+ readonly: true,
106
+ },
107
+ };
108
+
109
+ export const Invalid: Story = {
110
+ args: {
111
+ id: 'invalidId',
112
+ isInvalid: true,
113
+ },
114
+ };