@mozaic-ds/vue 1.0.0-beta.4 → 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.
- package/README.md +14 -6
- package/dist/mozaic-vue.css +1 -1
- package/dist/mozaic-vue.d.ts +349 -67
- package/dist/mozaic-vue.js +670 -327
- package/dist/mozaic-vue.js.map +1 -1
- package/dist/mozaic-vue.umd.cjs +1 -1
- package/dist/mozaic-vue.umd.cjs.map +1 -1
- package/package.json +3 -2
- package/src/components/GettingStarted.mdx +15 -4
- package/src/components/badge/MBadge.stories.ts +1 -1
- package/src/components/breadcrumb/MBreadcrumb.spec.ts +105 -0
- package/src/components/breadcrumb/MBreadcrumb.stories.ts +57 -0
- package/src/components/breadcrumb/MBreadcrumb.vue +70 -0
- package/src/components/button/MButton.stories.ts +1 -1
- package/src/components/checkbox/MCheckbox.stories.ts +1 -1
- package/src/components/checkboxgroup/MCheckboxGroup.stories.ts +1 -1
- package/src/components/checkboxgroup/MCheckboxGroup.vue +2 -2
- package/src/components/field/MField.stories.ts +1 -1
- package/src/components/fieldgroup/MFieldGroup.stories.ts +175 -26
- package/src/components/iconbutton/MIconButton.stories.ts +1 -1
- package/src/components/loader/MLoader.stories.ts +1 -1
- package/src/components/passwordinput/MPasswordInput.spec.ts +104 -0
- package/src/components/passwordinput/MPasswordInput.stories.ts +75 -0
- package/src/components/passwordinput/MPasswordInput.vue +149 -0
- package/src/components/quantityselector/MQuantitySelector.stories.ts +1 -1
- package/src/components/radio/MRadio.stories.ts +1 -1
- package/src/components/radiogroup/MRadioGroup.stories.ts +1 -1
- package/src/components/select/MSelect.stories.ts +1 -1
- package/src/components/statusbadge/MStatusBadge.stories.ts +5 -5
- package/src/components/statusbadge/MStatusBadge.vue +6 -6
- package/src/components/statusdot/MStatusDot.spec.ts +51 -0
- package/src/components/statusdot/MStatusDot.stories.ts +48 -0
- package/src/components/{statusbadge → statusdot}/MStatusDot.vue +8 -4
- package/src/components/statusnotification/MStatusNotification.spec.ts +99 -0
- package/src/components/statusnotification/MStatusNotification.stories.ts +96 -0
- package/src/components/statusnotification/MStatusNotification.vue +106 -0
- package/src/components/textarea/MTextArea.stories.ts +1 -1
- package/src/components/textinput/MTextInput.stories.ts +1 -1
- package/src/components/toggle/MToggle.stories.ts +2 -2
- 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/main.ts +8 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<nav class="mc-breadcrumb" :class="classObject" aria-label="Breadcrumb">
|
|
3
|
+
<ul class="mc-breadcrumb__container">
|
|
4
|
+
<li
|
|
5
|
+
class="mc-breadcrumb__item"
|
|
6
|
+
v-for="(link, index) in links"
|
|
7
|
+
:key="`breadcrumb-${index}`"
|
|
8
|
+
>
|
|
9
|
+
<MLink
|
|
10
|
+
:href="link.href"
|
|
11
|
+
:router="link.router"
|
|
12
|
+
:appearance="appearance"
|
|
13
|
+
inline
|
|
14
|
+
:class="{
|
|
15
|
+
'mc-breadcrumb__current': isLastLink(index),
|
|
16
|
+
}"
|
|
17
|
+
:aria-current="isLastLink(index) ? 'page' : undefined"
|
|
18
|
+
>
|
|
19
|
+
{{ link.label }}
|
|
20
|
+
</MLink>
|
|
21
|
+
</li>
|
|
22
|
+
</ul>
|
|
23
|
+
</nav>
|
|
24
|
+
</template>
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
import { computed } from 'vue';
|
|
28
|
+
import MLink from '../link/MLink.vue';
|
|
29
|
+
/**
|
|
30
|
+
* A breadcrumb is a navigation help that displays the hierarchical path of the current page within a website or application. It helps users understand their location and allows them to navigate back to previous levels easily. Breadcrumbs improve usability and accessibility, especially in multi-level websites, dashboards, and e-commerce platforms.
|
|
31
|
+
*/
|
|
32
|
+
const props = defineProps<{
|
|
33
|
+
/**
|
|
34
|
+
* Allows to define the breadcrumb style
|
|
35
|
+
*/
|
|
36
|
+
appearance?: 'standard' | 'inverse';
|
|
37
|
+
/**
|
|
38
|
+
* Links of the breadcrumb
|
|
39
|
+
*/
|
|
40
|
+
links?: Array<{
|
|
41
|
+
/**
|
|
42
|
+
* The label displayed for the link.
|
|
43
|
+
*/
|
|
44
|
+
label: string;
|
|
45
|
+
/**
|
|
46
|
+
* URL for the link (for external links or the `to` prop for `router-link`).
|
|
47
|
+
*/
|
|
48
|
+
href: string;
|
|
49
|
+
/**
|
|
50
|
+
* If `true`, the link will be rendered as a `router-link` for internal navigation (Vue Router).
|
|
51
|
+
*/
|
|
52
|
+
router?: boolean;
|
|
53
|
+
}>;
|
|
54
|
+
}>();
|
|
55
|
+
|
|
56
|
+
const classObject = computed(() => {
|
|
57
|
+
return {
|
|
58
|
+
[`mc-breadcrumb--${props.appearance}`]:
|
|
59
|
+
props.appearance && props.appearance != 'standard',
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const isLastLink = (index: number) => {
|
|
64
|
+
return index === (props.links?.length ?? 0) - 1;
|
|
65
|
+
};
|
|
66
|
+
</script>
|
|
67
|
+
|
|
68
|
+
<style lang="scss" scoped>
|
|
69
|
+
@use '@mozaic-ds/styles/components/breadcrumb';
|
|
70
|
+
</style>
|
|
@@ -11,7 +11,7 @@ const meta: Meta<typeof MButton> = {
|
|
|
11
11
|
docs: {
|
|
12
12
|
description: {
|
|
13
13
|
component:
|
|
14
|
-
'Buttons are used to
|
|
14
|
+
'Buttons are key interactive elements used to perform actions and can be used as standalone element, or as part of another component. Their appearance depends on the type of action required from the user and the context in which they are used.',
|
|
15
15
|
},
|
|
16
16
|
},
|
|
17
17
|
},
|
|
@@ -10,7 +10,7 @@ const meta: Meta<typeof MCheckbox> = {
|
|
|
10
10
|
docs: {
|
|
11
11
|
description: {
|
|
12
12
|
component:
|
|
13
|
-
'
|
|
13
|
+
'A checkbox is an interactive component used to select or deselect an option, typically within a list of choices. It allows users to make multiple selections independently and is often accompanied by a label for clarity. Checkboxes are commonly used in forms, filters, settings, and preference selections to provide a simple and intuitive way to enable or disable specific options.',
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
@@ -10,7 +10,7 @@ const meta: Meta<typeof MCheckboxGroup> = {
|
|
|
10
10
|
docs: {
|
|
11
11
|
description: {
|
|
12
12
|
component:
|
|
13
|
-
'
|
|
13
|
+
'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.<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 Group section](/docs/form-elements-field-group--docs#checkbox-group).',
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
@@ -25,7 +25,7 @@ import MCheckbox from '../checkbox/MCheckbox.vue';
|
|
|
25
25
|
*/
|
|
26
26
|
const props = defineProps<{
|
|
27
27
|
/**
|
|
28
|
-
* The name attribute for the
|
|
28
|
+
* The name attribute for the checkbox element, typically used for form submission.
|
|
29
29
|
*/
|
|
30
30
|
name: string;
|
|
31
31
|
/**
|
|
@@ -34,7 +34,7 @@ const props = defineProps<{
|
|
|
34
34
|
*/
|
|
35
35
|
modelValue?: Array<string>;
|
|
36
36
|
/**
|
|
37
|
-
* list of properties of each
|
|
37
|
+
* list of properties of each checkbox button of the checkbox group
|
|
38
38
|
*/
|
|
39
39
|
options: Array<{
|
|
40
40
|
id: string;
|
|
@@ -13,7 +13,7 @@ const meta: Meta<typeof MField> = {
|
|
|
13
13
|
docs: {
|
|
14
14
|
description: {
|
|
15
15
|
component:
|
|
16
|
-
'
|
|
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
17
|
},
|
|
18
18
|
},
|
|
19
19
|
},
|
|
@@ -4,6 +4,7 @@ import { action } from '@storybook/addon-actions';
|
|
|
4
4
|
import MFieldGroup from './MFieldGroup.vue';
|
|
5
5
|
import MCheckboxGroup from '../checkboxgroup/MCheckboxGroup.vue';
|
|
6
6
|
import MRadioGroup from '../radiogroup/MRadioGroup.vue';
|
|
7
|
+
import MToggleGroup from '../togglegroup/MToggleGroup.vue';
|
|
7
8
|
|
|
8
9
|
const meta: Meta<typeof MFieldGroup> = {
|
|
9
10
|
title: 'Form Elements/Field Group',
|
|
@@ -12,7 +13,7 @@ const meta: Meta<typeof MFieldGroup> = {
|
|
|
12
13
|
docs: {
|
|
13
14
|
description: {
|
|
14
15
|
component:
|
|
15
|
-
'
|
|
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.',
|
|
16
17
|
},
|
|
17
18
|
},
|
|
18
19
|
},
|
|
@@ -60,7 +61,7 @@ const meta: Meta<typeof MFieldGroup> = {
|
|
|
60
61
|
},
|
|
61
62
|
},
|
|
62
63
|
render: (args) => ({
|
|
63
|
-
components: { MFieldGroup, MCheckboxGroup, MRadioGroup },
|
|
64
|
+
components: { MFieldGroup, MCheckboxGroup, MRadioGroup, MToggleGroup },
|
|
64
65
|
setup() {
|
|
65
66
|
const handleUpdate = action('update:modelValue');
|
|
66
67
|
|
|
@@ -111,6 +112,36 @@ export const CheckboxGroupValid: Story = {
|
|
|
111
112
|
requirementText: 'required',
|
|
112
113
|
isValid: true,
|
|
113
114
|
message: 'Validation message (Be concise and use comprehensive words).',
|
|
115
|
+
default: `
|
|
116
|
+
<MCheckboxGroup
|
|
117
|
+
name="checkboxGroupName"
|
|
118
|
+
:options="
|
|
119
|
+
[
|
|
120
|
+
{
|
|
121
|
+
id: 'checkbox-05',
|
|
122
|
+
label: 'checkbox Label',
|
|
123
|
+
value: 'checkbox5',
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'checkbox-06',
|
|
127
|
+
label: 'checkbox Label',
|
|
128
|
+
value: 'checkbox6',
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
id: 'checkbox-07',
|
|
132
|
+
label: 'checkbox Label',
|
|
133
|
+
value: 'checkbox7',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'checkbox-08',
|
|
137
|
+
label: 'checkbox Label',
|
|
138
|
+
value: 'checkbox8',
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
"
|
|
142
|
+
@update:modelValue="handleUpdate"
|
|
143
|
+
/>
|
|
144
|
+
`,
|
|
114
145
|
},
|
|
115
146
|
};
|
|
116
147
|
|
|
@@ -128,24 +159,24 @@ export const CheckboxGroupInvalid: Story = {
|
|
|
128
159
|
:options="
|
|
129
160
|
[
|
|
130
161
|
{
|
|
131
|
-
id: 'checkbox-
|
|
162
|
+
id: 'checkbox-09',
|
|
132
163
|
label: 'checkbox Label',
|
|
133
|
-
value: '
|
|
164
|
+
value: 'checkbox9',
|
|
134
165
|
},
|
|
135
166
|
{
|
|
136
|
-
id: 'checkbox-
|
|
167
|
+
id: 'checkbox-10',
|
|
137
168
|
label: 'checkbox Label',
|
|
138
|
-
value: '
|
|
169
|
+
value: 'checkbox10',
|
|
139
170
|
},
|
|
140
171
|
{
|
|
141
|
-
id: 'checkbox-
|
|
172
|
+
id: 'checkbox-11',
|
|
142
173
|
label: 'checkbox Label',
|
|
143
|
-
value: '
|
|
174
|
+
value: 'checkbox11',
|
|
144
175
|
},
|
|
145
176
|
{
|
|
146
|
-
id: 'checkbox-
|
|
177
|
+
id: 'checkbox-12',
|
|
147
178
|
label: 'checkbox Label',
|
|
148
|
-
value: '
|
|
179
|
+
value: 'checkbox12',
|
|
149
180
|
},
|
|
150
181
|
]
|
|
151
182
|
"
|
|
@@ -205,24 +236,24 @@ export const RadioGroupValid: Story = {
|
|
|
205
236
|
:options="
|
|
206
237
|
[
|
|
207
238
|
{
|
|
208
|
-
id: '
|
|
239
|
+
id: 'radio05',
|
|
209
240
|
label: 'Radio button Label',
|
|
210
|
-
value: '
|
|
241
|
+
value: 'radio5'
|
|
211
242
|
},
|
|
212
243
|
{
|
|
213
|
-
id: '
|
|
244
|
+
id: 'radio06',
|
|
214
245
|
label: 'Radio button Label',
|
|
215
|
-
value: '
|
|
246
|
+
value: 'radio6'
|
|
216
247
|
},
|
|
217
248
|
{
|
|
218
|
-
id: '
|
|
249
|
+
id: 'radio07',
|
|
219
250
|
label: 'Radio button Label',
|
|
220
|
-
value: '
|
|
251
|
+
value: 'radio7'
|
|
221
252
|
},
|
|
222
253
|
{
|
|
223
|
-
id: '
|
|
254
|
+
id: 'radio08',
|
|
224
255
|
label: 'Radio button Label',
|
|
225
|
-
value: '
|
|
256
|
+
value: 'radio8'
|
|
226
257
|
}
|
|
227
258
|
]
|
|
228
259
|
"
|
|
@@ -246,24 +277,24 @@ export const RadioGroupInvalid: Story = {
|
|
|
246
277
|
:options="
|
|
247
278
|
[
|
|
248
279
|
{
|
|
249
|
-
id: 'radio-
|
|
280
|
+
id: 'radio-9',
|
|
250
281
|
label: 'Radio button Label',
|
|
251
|
-
value: '
|
|
282
|
+
value: 'radio9'
|
|
252
283
|
},
|
|
253
284
|
{
|
|
254
|
-
id: 'radio-
|
|
285
|
+
id: 'radio-10',
|
|
255
286
|
label: 'Radio button Label',
|
|
256
|
-
value: '
|
|
287
|
+
value: 'radio10'
|
|
257
288
|
},
|
|
258
289
|
{
|
|
259
|
-
id: 'radio-
|
|
290
|
+
id: 'radio-11',
|
|
260
291
|
label: 'Radio button Label',
|
|
261
|
-
value: '
|
|
292
|
+
value: 'radio11'
|
|
262
293
|
},
|
|
263
294
|
{
|
|
264
|
-
id: 'radio-
|
|
295
|
+
id: 'radio-12',
|
|
265
296
|
label: 'Radio button Label',
|
|
266
|
-
value: '
|
|
297
|
+
value: 'radio12'
|
|
267
298
|
}
|
|
268
299
|
]
|
|
269
300
|
"
|
|
@@ -272,3 +303,121 @@ export const RadioGroupInvalid: Story = {
|
|
|
272
303
|
`,
|
|
273
304
|
},
|
|
274
305
|
};
|
|
306
|
+
|
|
307
|
+
export const ToggleGroup: Story = {
|
|
308
|
+
args: {
|
|
309
|
+
legend: 'Label',
|
|
310
|
+
id: 'ToggleGroupId',
|
|
311
|
+
requirementText: 'required',
|
|
312
|
+
default: `
|
|
313
|
+
<MToggleGroup
|
|
314
|
+
name="ToggleGroupName"
|
|
315
|
+
:options="
|
|
316
|
+
[
|
|
317
|
+
{
|
|
318
|
+
id: 'toggle-01',
|
|
319
|
+
label: 'Toggle Label',
|
|
320
|
+
value: 'toggle1',
|
|
321
|
+
},
|
|
322
|
+
{
|
|
323
|
+
id: 'toggle-02',
|
|
324
|
+
label: 'Toggle Label',
|
|
325
|
+
value: 'toggle2',
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
id: 'toggle-03',
|
|
329
|
+
label: 'Toggle Label',
|
|
330
|
+
value: 'toggle3',
|
|
331
|
+
},
|
|
332
|
+
{
|
|
333
|
+
id: 'toggle-04',
|
|
334
|
+
label: 'Toggle Label',
|
|
335
|
+
value: 'toggle4',
|
|
336
|
+
},
|
|
337
|
+
]
|
|
338
|
+
"
|
|
339
|
+
@update:modelValue="handleUpdate"
|
|
340
|
+
/>
|
|
341
|
+
`,
|
|
342
|
+
},
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
export const ToggleGroupValid: Story = {
|
|
346
|
+
args: {
|
|
347
|
+
legend: 'Label',
|
|
348
|
+
id: 'ToggleGroupId',
|
|
349
|
+
requirementText: 'required',
|
|
350
|
+
isValid: true,
|
|
351
|
+
message: 'Validation message (Be concise and use comprehensive words).',
|
|
352
|
+
default: `
|
|
353
|
+
<MToggleGroup
|
|
354
|
+
name="ToggleGroupName"
|
|
355
|
+
:options="
|
|
356
|
+
[
|
|
357
|
+
{
|
|
358
|
+
id: 'toggle-05',
|
|
359
|
+
label: 'Toggle Label',
|
|
360
|
+
value: 'toggle5',
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: 'toggle-06',
|
|
364
|
+
label: 'Toggle Label',
|
|
365
|
+
value: 'toggle6',
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
id: 'toggle-07',
|
|
369
|
+
label: 'Toggle Label',
|
|
370
|
+
value: 'toggle7',
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
id: 'toggle-08',
|
|
374
|
+
label: 'Toggle Label',
|
|
375
|
+
value: 'toggle8',
|
|
376
|
+
},
|
|
377
|
+
]
|
|
378
|
+
"
|
|
379
|
+
@update:modelValue="handleUpdate"
|
|
380
|
+
/>
|
|
381
|
+
`,
|
|
382
|
+
},
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
export const ToggleGroupInvalid: Story = {
|
|
386
|
+
args: {
|
|
387
|
+
legend: 'Label',
|
|
388
|
+
id: 'ToggleGroupId',
|
|
389
|
+
requirementText: 'required',
|
|
390
|
+
isInvalid: true,
|
|
391
|
+
message: 'Error message (Be concise and use comprehensive words)',
|
|
392
|
+
default: `
|
|
393
|
+
<MToggleGroup
|
|
394
|
+
name="ToggleGroupName"
|
|
395
|
+
:options="
|
|
396
|
+
[
|
|
397
|
+
{
|
|
398
|
+
id: 'toggle-09',
|
|
399
|
+
label: 'Toggle Label',
|
|
400
|
+
value: 'toggle9',
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
id: 'toggle-10',
|
|
404
|
+
label: 'Toggle Label',
|
|
405
|
+
value: 'toggle10',
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
id: 'toggle-11',
|
|
409
|
+
label: 'Toggle Label',
|
|
410
|
+
value: 'toggle11',
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
id: 'toggle-12',
|
|
414
|
+
label: 'Toggle Label',
|
|
415
|
+
value: 'toggle12',
|
|
416
|
+
},
|
|
417
|
+
]
|
|
418
|
+
"
|
|
419
|
+
@update:modelValue="handleUpdate"
|
|
420
|
+
/>
|
|
421
|
+
`,
|
|
422
|
+
},
|
|
423
|
+
};
|
|
@@ -10,7 +10,7 @@ const meta: Meta<typeof MIconButton> = {
|
|
|
10
10
|
docs: {
|
|
11
11
|
description: {
|
|
12
12
|
component:
|
|
13
|
-
'
|
|
13
|
+
'Buttons are key interactive elements used to perform actions and can be used as standalone element, or as part of another component. Their appearance depends on the type of action required from the user and the context in which they are used.',
|
|
14
14
|
},
|
|
15
15
|
},
|
|
16
16
|
},
|
|
@@ -8,7 +8,7 @@ const meta: Meta<typeof MLoader> = {
|
|
|
8
8
|
docs: {
|
|
9
9
|
description: {
|
|
10
10
|
component:
|
|
11
|
-
'A loader
|
|
11
|
+
'A loader is a visual indicator used to inform users that a process is in progress, typically during data fetching, page loading, or background operations. It provides feedback that the system is working, helping to manage user expectations and reduce perceived wait time.',
|
|
12
12
|
},
|
|
13
13
|
},
|
|
14
14
|
},
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import MPasswordInput from './MPasswordInput.vue';
|
|
4
|
+
|
|
5
|
+
describe('MPasswordInput.vue', () => {
|
|
6
|
+
it('renders correctly with default props', () => {
|
|
7
|
+
const wrapper = mount(MPasswordInput, {
|
|
8
|
+
props: {
|
|
9
|
+
id: 'password-input',
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const input = wrapper.find('input');
|
|
14
|
+
const toggleButton = wrapper.find('button[role="switch"]');
|
|
15
|
+
|
|
16
|
+
expect(input.exists()).toBe(true);
|
|
17
|
+
expect(input.attributes('type')).toBe('password');
|
|
18
|
+
|
|
19
|
+
expect(toggleButton.exists()).toBe(true);
|
|
20
|
+
expect(toggleButton.text()).toBe('Show');
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('toggles password visibility on button click', async () => {
|
|
24
|
+
const wrapper = mount(MPasswordInput, {
|
|
25
|
+
props: {
|
|
26
|
+
id: 'password-input',
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const toggleButton = wrapper.find('button[role="switch"]');
|
|
31
|
+
const input = wrapper.find('input');
|
|
32
|
+
|
|
33
|
+
expect(input.attributes('type')).toBe('password');
|
|
34
|
+
|
|
35
|
+
await toggleButton.trigger('click');
|
|
36
|
+
|
|
37
|
+
expect(input.attributes('type')).toBe('text');
|
|
38
|
+
expect(toggleButton.text()).toBe('Hide');
|
|
39
|
+
|
|
40
|
+
await toggleButton.trigger('click');
|
|
41
|
+
|
|
42
|
+
expect(input.attributes('type')).toBe('password');
|
|
43
|
+
expect(toggleButton.text()).toBe('Show');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should update modelValue when input value changes', async () => {
|
|
47
|
+
const wrapper = mount(MPasswordInput, {
|
|
48
|
+
props: {
|
|
49
|
+
id: 'password-input',
|
|
50
|
+
modelValue: '',
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const input = wrapper.find('input');
|
|
55
|
+
await input.setValue('newPassword123');
|
|
56
|
+
|
|
57
|
+
expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
|
|
58
|
+
expect(wrapper.emitted()['update:modelValue'][0]).toEqual([
|
|
59
|
+
'newPassword123',
|
|
60
|
+
]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('clears the input when the clear button is clicked', async () => {
|
|
64
|
+
const wrapper = mount(MPasswordInput, {
|
|
65
|
+
props: {
|
|
66
|
+
id: 'password-input',
|
|
67
|
+
modelValue: 'somePassword',
|
|
68
|
+
isClearable: true,
|
|
69
|
+
clearLabel: 'Clear content',
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const clearButton = wrapper.find('.mc-controls-options__button');
|
|
74
|
+
|
|
75
|
+
await clearButton.trigger('click');
|
|
76
|
+
|
|
77
|
+
expect(wrapper.emitted()['update:modelValue']).toBeTruthy();
|
|
78
|
+
expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['']);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it('disables the input when disabled prop is passed', () => {
|
|
82
|
+
const wrapper = mount(MPasswordInput, {
|
|
83
|
+
props: {
|
|
84
|
+
id: 'password-input',
|
|
85
|
+
disabled: true,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const input = wrapper.find('input');
|
|
90
|
+
|
|
91
|
+
expect(input.attributes('disabled')).toBeDefined();
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('applies invalid state when isInvalid prop is true', () => {
|
|
95
|
+
const wrapper = mount(MPasswordInput, {
|
|
96
|
+
props: {
|
|
97
|
+
id: 'password-input',
|
|
98
|
+
isInvalid: true,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
expect(wrapper.classes()).toContain('is-invalid');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3';
|
|
2
|
+
import { action } from '@storybook/addon-actions';
|
|
3
|
+
|
|
4
|
+
import MPasswordInput from './MPasswordInput.vue';
|
|
5
|
+
|
|
6
|
+
const meta: Meta<typeof MPasswordInput> = {
|
|
7
|
+
title: 'Form Elements/PasswordInput',
|
|
8
|
+
component: MPasswordInput,
|
|
9
|
+
parameters: {
|
|
10
|
+
docs: {
|
|
11
|
+
description: {
|
|
12
|
+
component:
|
|
13
|
+
'A password input is a specialized input field used to securely enter and manage passwords. It typically masks the characters entered to protect sensitive information from being seen. It includes a toggle button to show or hide the password, improving usability while maintaining security. Password inputs are commonly used in login forms, account creation, and authentication flows.<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).',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
args: {
|
|
18
|
+
id: 'passwordInputId',
|
|
19
|
+
placeholder: 'Enter your password',
|
|
20
|
+
},
|
|
21
|
+
render: (args) => ({
|
|
22
|
+
components: { MPasswordInput },
|
|
23
|
+
setup() {
|
|
24
|
+
const handleUpdate = action('update:modelValue');
|
|
25
|
+
|
|
26
|
+
return { args, handleUpdate };
|
|
27
|
+
},
|
|
28
|
+
template: `
|
|
29
|
+
<MPasswordInput
|
|
30
|
+
v-bind="args"
|
|
31
|
+
@update:modelValue="handleUpdate"
|
|
32
|
+
/>
|
|
33
|
+
`,
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
36
|
+
export default meta;
|
|
37
|
+
type Story = StoryObj<typeof MPasswordInput>;
|
|
38
|
+
|
|
39
|
+
export const WithValue: Story = {
|
|
40
|
+
args: {
|
|
41
|
+
id: 'withValueId',
|
|
42
|
+
modelValue: 'Magic-word-123',
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export const Default: Story = {};
|
|
47
|
+
|
|
48
|
+
export const Clearable: Story = {
|
|
49
|
+
args: {
|
|
50
|
+
id: 'clearableId',
|
|
51
|
+
modelValue: 'Magic-word-123',
|
|
52
|
+
isClearable: true,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Disabled: Story = {
|
|
57
|
+
args: {
|
|
58
|
+
id: 'disableId',
|
|
59
|
+
disabled: true,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const ReadOnly: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
id: 'readonlyId',
|
|
66
|
+
readonly: true,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export const Invalid: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
id: 'invalidId',
|
|
73
|
+
isInvalid: true,
|
|
74
|
+
},
|
|
75
|
+
};
|