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

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 (191) hide show
  1. package/LICENSE +51 -0
  2. package/README.md +224 -82
  3. package/dist/mozaic-vue.css +1 -1
  4. package/dist/mozaic-vue.d.ts +1202 -0
  5. package/dist/mozaic-vue.js +1220 -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 +81 -50
  11. package/src/components/Contributing.mdx +118 -0
  12. package/src/components/GettingStarted.mdx +50 -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/breadcrumb/MBreadcrumb.spec.ts +105 -0
  19. package/src/components/breadcrumb/MBreadcrumb.stories.ts +57 -0
  20. package/src/components/breadcrumb/MBreadcrumb.vue +52 -55
  21. package/src/components/button/MButton.spec.ts +191 -0
  22. package/src/components/button/MButton.stories.ts +66 -0
  23. package/src/components/button/MButton.vue +98 -154
  24. package/src/components/checkbox/MCheckbox.spec.ts +104 -0
  25. package/src/components/checkbox/MCheckbox.stories.ts +83 -0
  26. package/src/components/checkbox/MCheckbox.vue +60 -101
  27. package/src/components/checkboxgroup/MCheckboxGroup.spec.ts +78 -0
  28. package/src/components/checkboxgroup/MCheckboxGroup.stories.ts +61 -0
  29. package/src/components/checkboxgroup/MCheckboxGroup.vue +97 -0
  30. package/src/components/field/MField.spec.ts +166 -0
  31. package/src/components/field/MField.stories.ts +376 -0
  32. package/src/components/field/MField.vue +78 -61
  33. package/src/components/fieldgroup/MFieldGroup.spec.ts +165 -0
  34. package/src/components/fieldgroup/MFieldGroup.stories.ts +423 -0
  35. package/src/components/fieldgroup/MFieldGroup.vue +79 -0
  36. package/src/components/iconbutton/MIconButton.spec.ts +108 -0
  37. package/src/components/iconbutton/MIconButton.stories.ts +66 -0
  38. package/src/components/iconbutton/MIconButton.vue +73 -0
  39. package/src/components/link/MLink.spec.ts +154 -0
  40. package/src/components/link/MLink.stories.ts +98 -0
  41. package/src/components/link/MLink.vue +86 -109
  42. package/src/components/loader/MLoader.spec.ts +104 -0
  43. package/src/components/loader/MLoader.stories.ts +45 -0
  44. package/src/components/loader/MLoader.vue +65 -55
  45. package/src/components/overlay/MOverlay.spec.ts +51 -0
  46. package/src/components/overlay/MOverlay.stories.ts +40 -0
  47. package/src/components/overlay/MOverlay.vue +27 -19
  48. package/src/components/passwordinput/MPasswordInput.spec.ts +104 -0
  49. package/src/components/passwordinput/MPasswordInput.stories.ts +75 -0
  50. package/src/components/passwordinput/MPasswordInput.vue +129 -76
  51. package/src/components/quantityselector/MQuantitySelector.spec.ts +262 -0
  52. package/src/components/quantityselector/MQuantitySelector.stories.ts +89 -0
  53. package/src/components/quantityselector/MQuantitySelector.vue +160 -136
  54. package/src/components/radio/MRadio.spec.ts +104 -0
  55. package/src/components/radio/MRadio.stories.ts +68 -0
  56. package/src/components/radio/MRadio.vue +56 -39
  57. package/src/components/radiogroup/MRadioGroup.spec.ts +54 -0
  58. package/src/components/radiogroup/MRadioGroup.stories.ts +61 -0
  59. package/src/components/radiogroup/MRadioGroup.vue +79 -0
  60. package/src/components/select/MSelect.spec.ts +114 -0
  61. package/src/components/select/MSelect.stories.ts +101 -0
  62. package/src/components/select/MSelect.vue +77 -119
  63. package/src/components/statusbadge/MStatusBadge.stories.ts +45 -0
  64. package/src/components/statusbadge/MStatusBadge.vue +40 -0
  65. package/src/components/statusbadge/MstatusBadge.spec.ts +16 -0
  66. package/src/components/statusdot/MStatusDot.spec.ts +51 -0
  67. package/src/components/statusdot/MStatusDot.stories.ts +48 -0
  68. package/src/components/statusdot/MStatusDot.vue +36 -0
  69. package/src/components/statusnotification/MStatusNotification.spec.ts +99 -0
  70. package/src/components/statusnotification/MStatusNotification.stories.ts +96 -0
  71. package/src/components/statusnotification/MStatusNotification.vue +106 -0
  72. package/src/components/textarea/MTextArea.spec.ts +112 -0
  73. package/src/components/textarea/MTextArea.stories.ts +67 -0
  74. package/src/components/textarea/MTextArea.vue +81 -42
  75. package/src/components/textinput/MTextInput.spec.ts +121 -0
  76. package/src/components/textinput/MTextInput.stories.ts +114 -0
  77. package/src/components/textinput/MTextInput.vue +127 -47
  78. package/src/components/toggle/MToggle.spec.ts +99 -0
  79. package/src/components/toggle/MToggle.stories.ts +68 -0
  80. package/src/components/toggle/MToggle.vue +63 -103
  81. package/src/components/togglegroup/MToggleGroup.spec.ts +78 -0
  82. package/src/components/togglegroup/MToggleGroup.stories.ts +61 -0
  83. package/src/components/togglegroup/MToggleGroup.vue +97 -0
  84. package/src/components/usingIcons.mdx +43 -0
  85. package/src/components/usingPresets.mdx +125 -0
  86. package/src/main.ts +47 -0
  87. package/dist/demo.html +0 -1
  88. package/dist/mozaic-vue.adeo.css +0 -45
  89. package/dist/mozaic-vue.adeo.umd.js +0 -41775
  90. package/dist/mozaic-vue.common.js +0 -41765
  91. package/dist/mozaic-vue.common.js.map +0 -1
  92. package/dist/mozaic-vue.umd.js +0 -41776
  93. package/dist/mozaic-vue.umd.js.map +0 -1
  94. package/dist/mozaic-vue.umd.min.js +0 -4
  95. package/dist/mozaic-vue.umd.min.js.map +0 -1
  96. package/postinstall.js +0 -3
  97. package/src/components/accordion/MAccordion.vue +0 -128
  98. package/src/components/accordion/index.js +0 -7
  99. package/src/components/autocomplete/MAutocomplete.vue +0 -198
  100. package/src/components/autocomplete/index.js +0 -7
  101. package/src/components/badge/index.js +0 -7
  102. package/src/components/breadcrumb/index.js +0 -7
  103. package/src/components/button/index.js +0 -7
  104. package/src/components/card/MCard.vue +0 -78
  105. package/src/components/card/index.js +0 -7
  106. package/src/components/checkbox/MCheckboxGroup.vue +0 -155
  107. package/src/components/checkbox/index.js +0 -12
  108. package/src/components/container/MContainer.vue +0 -33
  109. package/src/components/container/index.js +0 -7
  110. package/src/components/datatable/MDataTable.vue +0 -651
  111. package/src/components/datatable/MDataTableHeader.vue +0 -55
  112. package/src/components/datatable/MDataTableTop.vue +0 -35
  113. package/src/components/datatable/helpers.js +0 -132
  114. package/src/components/datatable/index.js +0 -12
  115. package/src/components/field/index.js +0 -7
  116. package/src/components/fileuploader/MFileResult.vue +0 -149
  117. package/src/components/fileuploader/MFileUploader.vue +0 -142
  118. package/src/components/fileuploader/index.js +0 -7
  119. package/src/components/flag/MFlag.vue +0 -46
  120. package/src/components/flag/index.js +0 -7
  121. package/src/components/heading/MHeading.vue +0 -75
  122. package/src/components/heading/index.js +0 -7
  123. package/src/components/hero/MHero.vue +0 -93
  124. package/src/components/hero/index.js +0 -7
  125. package/src/components/icon/MIcon.vue +0 -120
  126. package/src/components/icon/index.js +0 -7
  127. package/src/components/index.js +0 -43
  128. package/src/components/layer/MLayer.vue +0 -208
  129. package/src/components/layer/index.js +0 -7
  130. package/src/components/link/index.js +0 -7
  131. package/src/components/listbox/MListBox.vue +0 -106
  132. package/src/components/listbox/index.js +0 -7
  133. package/src/components/loader/index.js +0 -7
  134. package/src/components/modal/MModal.vue +0 -179
  135. package/src/components/modal/index.js +0 -7
  136. package/src/components/notification/MNotification.vue +0 -110
  137. package/src/components/notification/index.js +0 -7
  138. package/src/components/optionbutton/MOptionButton.vue +0 -67
  139. package/src/components/optionbutton/index.js +0 -7
  140. package/src/components/optioncard/MOptionCard.vue +0 -132
  141. package/src/components/optioncard/index.js +0 -7
  142. package/src/components/optiongroup/MOptionGroup.vue +0 -18
  143. package/src/components/optiongroup/index.js +0 -7
  144. package/src/components/overlay/MOverlayLoader.vue +0 -43
  145. package/src/components/overlay/index.js +0 -12
  146. package/src/components/pagination/MPagination.vue +0 -162
  147. package/src/components/pagination/index.js +0 -7
  148. package/src/components/passwordinput/index.js +0 -7
  149. package/src/components/phonenumber/MPhoneNumber.vue +0 -390
  150. package/src/components/phonenumber/index.js +0 -7
  151. package/src/components/progressbar/MProgress.vue +0 -102
  152. package/src/components/progressbar/index.js +0 -7
  153. package/src/components/quantityselector/index.js +0 -7
  154. package/src/components/radio/MRadioGroup.vue +0 -111
  155. package/src/components/radio/index.js +0 -12
  156. package/src/components/ratingstars/MStarsInput.vue +0 -118
  157. package/src/components/ratingstars/MStarsResult.vue +0 -89
  158. package/src/components/ratingstars/index.js +0 -12
  159. package/src/components/select/index.js +0 -7
  160. package/src/components/stepper/MStepper.vue +0 -70
  161. package/src/components/stepper/index.js +0 -7
  162. package/src/components/tabs/MTab.vue +0 -184
  163. package/src/components/tabs/index.js +0 -7
  164. package/src/components/tags/MTag.vue +0 -173
  165. package/src/components/tags/index.js +0 -7
  166. package/src/components/textarea/index.js +0 -7
  167. package/src/components/textinput/MTextInputField.vue +0 -105
  168. package/src/components/textinput/MTextInputIcon.vue +0 -42
  169. package/src/components/textinput/index.js +0 -7
  170. package/src/components/toggle/index.js +0 -7
  171. package/src/components/tooltip/MTooltip.vue +0 -42
  172. package/src/components/tooltip/index.js +0 -7
  173. package/src/index.js +0 -62
  174. package/src/shims-tsx.d.ts +0 -13
  175. package/src/shims.vue.d.ts +0 -4
  176. package/src/tokens/adeo/android/colors.xml +0 -391
  177. package/src/tokens/adeo/android/font_dimens.xml +0 -18
  178. package/src/tokens/adeo/css/_variables.scss +0 -385
  179. package/src/tokens/adeo/css/root.scss +0 -387
  180. package/src/tokens/adeo/ios/StyleDictionaryColor.h +0 -399
  181. package/src/tokens/adeo/ios/StyleDictionaryColor.m +0 -411
  182. package/src/tokens/adeo/ios/StyleDictionaryColor.swift +0 -394
  183. package/src/tokens/adeo/ios/StyleDictionarySize.h +0 -69
  184. package/src/tokens/adeo/ios/StyleDictionarySize.m +0 -70
  185. package/src/tokens/adeo/ios/StyleDictionarySize.swift +0 -71
  186. package/src/tokens/adeo/js/tokens.js +0 -483
  187. package/src/tokens/adeo/js/tokensObject.js +0 -10354
  188. package/src/tokens/adeo/scss/_tokens.scss +0 -1300
  189. package/src/utils/mozaicClasses.js +0 -16
  190. package/src/utils/theme.validator.js +0 -19
  191. package/types/index.d.ts +0 -100
@@ -0,0 +1,51 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect } from 'vitest';
3
+ import MStatusDot from './MStatusDot.vue';
4
+
5
+ describe('MStatusDot.vue', () => {
6
+ it('renders with default status and size', () => {
7
+ const wrapper = mount(MStatusDot);
8
+
9
+ expect(wrapper.classes()).toContain('mc-status-dot');
10
+ });
11
+
12
+ it('renders with custom status', () => {
13
+ const wrapper = mount(MStatusDot, {
14
+ props: {
15
+ status: 'success',
16
+ },
17
+ });
18
+
19
+ expect(wrapper.classes()).toContain('mc-status-dot--success');
20
+ });
21
+
22
+ it('renders with custom size', () => {
23
+ const wrapper = mount(MStatusDot, {
24
+ props: {
25
+ size: 's',
26
+ },
27
+ });
28
+
29
+ expect(wrapper.classes()).toContain('mc-status-dot--s');
30
+ });
31
+
32
+ it('does not render the "info" status when a custom one is passed', () => {
33
+ const wrapper = mount(MStatusDot, {
34
+ props: {
35
+ status: 'warning',
36
+ },
37
+ });
38
+
39
+ expect(wrapper.classes()).not.toContain('mc-status-dot--info');
40
+ });
41
+
42
+ it('does not render the "m" size when a custom one is passed', () => {
43
+ const wrapper = mount(MStatusDot, {
44
+ props: {
45
+ size: 'l',
46
+ },
47
+ });
48
+
49
+ expect(wrapper.classes()).not.toContain('mc-status-dot--m');
50
+ });
51
+ });
@@ -0,0 +1,48 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3';
2
+ import MStatusDot from './MStatusDot.vue';
3
+
4
+ const meta: Meta<typeof MStatusDot> = {
5
+ title: 'Status/Status Dot',
6
+ component: MStatusDot,
7
+ parameters: {
8
+ docs: {
9
+ description: {
10
+ component:
11
+ 'A Status dot is a small visual indicator used to represent the state or condition of an element. It is often color-coded to convey different statuses at a glance, such as availability, activity, or urgency. Status Dots are commonly found in user presence indicators, system statuses, or process tracking to provide quick, unobtrusive feedback.',
12
+ },
13
+ },
14
+ },
15
+ render: (args) => ({
16
+ components: { MStatusDot },
17
+ setup() {
18
+ return { args };
19
+ },
20
+ template: `
21
+ <MStatusDot v-bind="args"></MStatusDot>
22
+ `,
23
+ }),
24
+ };
25
+ export default meta;
26
+ type Story = StoryObj<typeof MStatusDot>;
27
+
28
+ export const Info: Story = {};
29
+
30
+ export const Success: Story = {
31
+ args: { status: 'success' },
32
+ };
33
+
34
+ export const Warning: Story = {
35
+ args: { status: 'warning' },
36
+ };
37
+
38
+ export const Error: Story = {
39
+ args: { status: 'error' },
40
+ };
41
+
42
+ export const Neutral: Story = {
43
+ args: { status: 'neutral' },
44
+ };
45
+
46
+ export const Size: Story = {
47
+ args: { size: 'l' },
48
+ };
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <span class="mc-status-dot" :class="classObject"></span>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import { computed } from 'vue';
7
+ /**
8
+ * A badge indicates the status of an entity and can evolve at any time.
9
+ */
10
+ const props = withDefaults(
11
+ defineProps<{
12
+ /**
13
+ * Allows to define the Status Dot style
14
+ */
15
+ status?: 'info' | 'success' | 'warning' | 'error' | 'neutral';
16
+ /**
17
+ * Determines the size of the Status Dot.
18
+ */
19
+ size?: 's' | 'm' | 'l';
20
+ }>(),
21
+ {
22
+ status: 'info',
23
+ },
24
+ );
25
+
26
+ const classObject = computed(() => {
27
+ return {
28
+ [`mc-status-dot--${props.status}`]: props.status && props.status != 'info',
29
+ [`mc-status-dot--${props.size}`]: props.size && props.size != 'm',
30
+ };
31
+ });
32
+ </script>
33
+
34
+ <style lang="scss" scoped>
35
+ @use '@mozaic-ds/styles/components/status-dot';
36
+ </style>
@@ -0,0 +1,99 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect } from 'vitest';
3
+ import MStatusNotification from './MStatusNotification.vue';
4
+ import InfoCircle32 from '@mozaic-ds/icons-vue/src/components/InfoCircle32/InfoCircle32.vue';
5
+ import CheckCircle32 from '@mozaic-ds/icons-vue/src/components/CheckCircle32/CheckCircle32.vue';
6
+ import WarningCircle32 from '@mozaic-ds/icons-vue/src/components/WarningCircle32/WarningCircle32.vue';
7
+ import CrossCircle32 from '@mozaic-ds/icons-vue/src/components/CrossCircle32/CrossCircle32.vue';
8
+
9
+ describe('MStatusNotification.vue', () => {
10
+ it('should render correctly with the default props', () => {
11
+ const wrapper = mount(MStatusNotification, {
12
+ props: {
13
+ title: 'Test Title',
14
+ description: 'Test Description',
15
+ },
16
+ });
17
+
18
+ expect(wrapper.text()).toContain('Test Title');
19
+ expect(wrapper.text()).toContain('Test Description');
20
+ expect(wrapper.findComponent(InfoCircle32).exists()).toBe(true); // Default icon is InfoCircle32
21
+ expect(wrapper.classes()).toContain('mc-status-notification');
22
+ });
23
+
24
+ it('should display the correct icon based on the status prop', () => {
25
+ const wrapperSuccess = mount(MStatusNotification, {
26
+ props: {
27
+ title: 'Success',
28
+ description: 'Success Description',
29
+ status: 'success',
30
+ },
31
+ });
32
+ expect(wrapperSuccess.findComponent(CheckCircle32).exists()).toBe(true);
33
+
34
+ const wrapperWarning = mount(MStatusNotification, {
35
+ props: {
36
+ title: 'Warning',
37
+ description: 'Warning Description',
38
+ status: 'warning',
39
+ },
40
+ });
41
+ expect(wrapperWarning.findComponent(WarningCircle32).exists()).toBe(true);
42
+
43
+ const wrapperError = mount(MStatusNotification, {
44
+ props: {
45
+ title: 'Error',
46
+ description: 'Error Description',
47
+ status: 'error',
48
+ },
49
+ });
50
+ expect(wrapperError.findComponent(CrossCircle32).exists()).toBe(true);
51
+ });
52
+
53
+ it('should show the close button if closable prop is true', () => {
54
+ const wrapper = mount(MStatusNotification, {
55
+ props: {
56
+ title: 'Closable Test',
57
+ description: 'Test Description',
58
+ closable: true,
59
+ },
60
+ });
61
+
62
+ expect(
63
+ wrapper.find('button.mc-status-notification-closable__close').exists(),
64
+ ).toBe(true);
65
+ });
66
+
67
+ it('should emit a close event when the close button is clicked', async () => {
68
+ const wrapper = mount(MStatusNotification, {
69
+ props: {
70
+ title: 'Closable Test',
71
+ description: 'Test Description',
72
+ closable: true,
73
+ },
74
+ });
75
+
76
+ const closeButton = wrapper.find(
77
+ 'button.mc-status-notification-closable__close',
78
+ );
79
+ await closeButton.trigger('click');
80
+
81
+ // Check if the "close" event was emitted
82
+ expect(wrapper.emitted()).toHaveProperty('close');
83
+ });
84
+
85
+ it('should render footer slot if provided', () => {
86
+ const footerSlotContent = '<button>Footer Button</button>';
87
+ const wrapper = mount(MStatusNotification, {
88
+ props: {
89
+ title: 'With Footer',
90
+ description: 'Description with footer',
91
+ },
92
+ slots: {
93
+ footer: footerSlotContent,
94
+ },
95
+ });
96
+
97
+ expect(wrapper.html()).toContain(footerSlotContent);
98
+ });
99
+ });
@@ -0,0 +1,96 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3';
2
+ import MStatusNotification from './MStatusNotification.vue';
3
+ import { action } from '@storybook/addon-actions';
4
+ import MButton from '../button/MButton.vue';
5
+ import MLink from '../link/MLink.vue';
6
+ import ArrowNext20 from '@mozaic-ds/icons-vue/src/components/ArrowNext20/ArrowNext20.vue';
7
+
8
+ const meta: Meta<typeof MStatusNotification> = {
9
+ title: 'Status/Status Notification',
10
+ component: MStatusNotification,
11
+ parameters: {
12
+ docs: {
13
+ description: {
14
+ component:
15
+ 'A Status Notification is used to draw the user’s attention to important information that needs to be acknowledged. It often provides feedback on a process, highlights a status update, or alerts users about an issue. Notifications are typically triggered by user actions or system events and are designed to be easily noticeable while maintaining a non-intrusive experience.',
16
+ },
17
+ },
18
+ },
19
+ args: {
20
+ title:
21
+ 'This is a title, be concise and use the description message to give details.',
22
+ description: 'Description message.',
23
+ },
24
+ argTypes: {
25
+ $slots: {
26
+ table: {
27
+ disable: true,
28
+ },
29
+ },
30
+ },
31
+ render: (args) => ({
32
+ components: { MStatusNotification, MButton, MLink, ArrowNext20 },
33
+ setup() {
34
+ const handleClick = action('close');
35
+
36
+ return { args, handleClick };
37
+ },
38
+ template: `
39
+ <MStatusNotification
40
+ v-bind="args"
41
+ @click="handleClick"
42
+ >
43
+ <template v-if="${'footer' in args}" v-slot:footer>${args.footer}</template>
44
+ </MStatusNotification>
45
+ `,
46
+ }),
47
+ };
48
+ export default meta;
49
+ type Story = StoryObj<typeof MStatusNotification>;
50
+
51
+ export const Info: Story = {};
52
+
53
+ export const Success: Story = {
54
+ args: { status: 'success' },
55
+ };
56
+
57
+ export const Warning: Story = {
58
+ args: { status: 'warning' },
59
+ };
60
+
61
+ export const Error: Story = {
62
+ args: { status: 'error' },
63
+ };
64
+
65
+ export const Closable: Story = {
66
+ args: { closable: true },
67
+ };
68
+
69
+ export const WithButton = {
70
+ args: {
71
+ footer: `
72
+ <MButton outlined>Button Label</MButton>
73
+ `,
74
+ },
75
+ };
76
+
77
+ export const WithLink = {
78
+ args: {
79
+ footer: `
80
+ <MLink href="#" iconPosition="right">
81
+ Stand-alone link
82
+
83
+ <template #icon><ArrowNext20 /></template>
84
+ </MLink>
85
+ `,
86
+ },
87
+ };
88
+
89
+ export const WithButtons = {
90
+ args: {
91
+ footer: `
92
+ <MButton>Button Label</MButton>
93
+ <MButton outlined>Button Label</MButton>
94
+ `,
95
+ },
96
+ };
@@ -0,0 +1,106 @@
1
+ <template>
2
+ <section class="mc-status-notification" role="status" :class="classObject">
3
+ <component
4
+ :is="iconComponent"
5
+ class="mc-status-notification__icon"
6
+ aria-hidden="true"
7
+ />
8
+ <div class="mc-status-notification__content">
9
+ <h2 class="mc-status-notification__title">{{ title }}</h2>
10
+
11
+ <p class="mc-status-notification__message">
12
+ {{ description }}
13
+ </p>
14
+
15
+ <div v-if="$slots.footer" class="mc-status-notification__footer">
16
+ <slot name="footer" />
17
+ </div>
18
+ </div>
19
+
20
+ <button
21
+ v-if="closable"
22
+ class="mc-status-notification-closable__close"
23
+ @click="emit('close')"
24
+ >
25
+ <Cross20
26
+ class="mc-status-notification-closable__icon"
27
+ aria-hidden="true"
28
+ />
29
+ <span class="mc-status-notification-closable__text">Close</span>
30
+ </button>
31
+ </section>
32
+ </template>
33
+
34
+ <script setup lang="ts">
35
+ import { computed, type VNode } from 'vue';
36
+ import Cross20 from '@mozaic-ds/icons-vue/src/components/Cross20/Cross20.vue';
37
+ import InfoCircle32 from '@mozaic-ds/icons-vue/src/components/InfoCircle32/InfoCircle32.vue';
38
+ import WarningCircle32 from '@mozaic-ds/icons-vue/src/components/WarningCircle32/WarningCircle32.vue';
39
+ import CrossCircle32 from '@mozaic-ds/icons-vue/src/components/CrossCircle32/CrossCircle32.vue';
40
+ import CheckCircle32 from '@mozaic-ds/icons-vue/src/components/CheckCircle32/CheckCircle32.vue';
41
+ /**
42
+ * A Status Notification is used to draw the user’s attention to important information that needs to be acknowledged. It often provides feedback on a process, highlights a status update, or alerts users about an issue. Notifications are typically triggered by user actions or system events and are designed to be easily noticeable while maintaining a non-intrusive experience.
43
+ */
44
+ const props = withDefaults(
45
+ defineProps<{
46
+ /**
47
+ * Title of the Status Notification
48
+ */
49
+ title: string;
50
+ /**
51
+ * Description of the Status Notification
52
+ */
53
+ description: string;
54
+ /**
55
+ * Allows to define the Status Notification style
56
+ */
57
+ status?: 'info' | 'success' | 'warning' | 'error';
58
+ /**
59
+ * if `true`, display the close button.
60
+ */
61
+ closable?: boolean;
62
+ }>(),
63
+ {
64
+ status: 'info',
65
+ },
66
+ );
67
+
68
+ defineSlots<{
69
+ /**
70
+ * Use this slot to insert a button or a link in the footer
71
+ */
72
+ footer?: VNode;
73
+ }>();
74
+
75
+ const classObject = computed(() => {
76
+ return {
77
+ [`mc-status-notification--${props.status}`]:
78
+ props.status && props.status != 'info',
79
+ };
80
+ });
81
+
82
+ const iconComponent = computed(() => {
83
+ switch (props.status) {
84
+ case 'success':
85
+ return CheckCircle32;
86
+ case 'warning':
87
+ return WarningCircle32;
88
+ case 'error':
89
+ return CrossCircle32;
90
+ case 'info':
91
+ default:
92
+ return InfoCircle32;
93
+ }
94
+ });
95
+
96
+ const emit = defineEmits<{
97
+ /**
98
+ * Emits when closing the notification.
99
+ */
100
+ (on: 'close'): void;
101
+ }>();
102
+ </script>
103
+
104
+ <style lang="scss" scoped>
105
+ @use '@mozaic-ds/styles/components/status-notification';
106
+ </style>
@@ -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 text area is an input designed for multi-line text entry, allowing users to input longer content compared to a standard text input. It is commonly used for comments, feedback, descriptions, and messaging. Text areas can be resizable or fixed in height, depending on the context, and often include placeholder text, character limits, and validation messages to guide users.<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
+ };