@bethinkpl/design-system 43.0.0 → 44.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/design-system.css +1 -1
- package/dist/design-system.js +11664 -11121
- package/dist/design-system.js.map +1 -1
- package/dist/lib/js/components/Form/PinInputField/PinInputField.consts.d.ts +14 -0
- package/dist/lib/js/components/Form/PinInputField/PinInputField.types.d.ts +12 -0
- package/dist/lib/js/components/Form/PinInputField/PinInputField.utils.d.ts +2 -0
- package/dist/lib/js/components/Form/PinInputField/PinInputField.vue.d.ts +91 -0
- package/dist/lib/js/components/Form/PinInputField/index.d.ts +5 -0
- package/dist/lib/js/components/Form/PinInputField/usePinInputFieldWithinForm.d.ts +8 -0
- package/dist/lib/js/components/Form/TextAreaField/TextAreaField.types.d.ts +9 -0
- package/dist/lib/js/components/Form/TextAreaField/TextAreaField.vue.d.ts +76 -0
- package/dist/lib/js/components/Form/TextAreaField/TextAreaFieldAutosized.vue.d.ts +6 -0
- package/dist/lib/js/components/Form/TextAreaField/index.d.ts +4 -0
- package/dist/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue.d.ts +12 -1
- package/dist/lib/js/components/Toast/Toast.consts.d.ts +11 -9
- package/dist/lib/js/components/Toast/Toast.vue.d.ts +51 -433
- package/dist/lib/js/{components/Form/InputField/useInputFieldWithinForm.d.ts → composables/useTextFieldWithinForm.d.ts} +1 -1
- package/dist/lib/js/index.d.ts +4 -0
- package/lib/js/components/Form/CheckboxGroupField/CheckboxGroupField.spec.ts +15 -0
- package/lib/js/components/Form/CheckboxGroupField/CheckboxGroupField.vue +5 -2
- package/lib/js/components/Form/Form.stories.ts +23 -2
- package/lib/js/components/Form/InputField/InputField.spec.ts +11 -1
- package/lib/js/components/Form/InputField/InputField.vue +7 -4
- package/lib/js/components/Form/PinInputField/PinInputField.consts.ts +18 -0
- package/lib/js/components/Form/PinInputField/PinInputField.spec.ts +394 -0
- package/lib/js/components/Form/PinInputField/PinInputField.stories.ts +124 -0
- package/lib/js/components/Form/PinInputField/PinInputField.types.ts +42 -0
- package/lib/js/components/Form/PinInputField/PinInputField.utils.ts +5 -0
- package/lib/js/components/Form/PinInputField/PinInputField.vue +211 -0
- package/lib/js/components/Form/PinInputField/index.ts +6 -0
- package/lib/js/components/Form/PinInputField/usePinInputFieldWithinForm.ts +29 -0
- package/lib/js/components/Form/SelectField/SelectField.stories.ts +0 -5
- package/lib/js/components/Form/SelectField/useSelectFieldWithinForm.ts +1 -1
- package/lib/js/components/Form/TextAreaField/TextAreaField.spec.ts +341 -0
- package/lib/js/components/Form/TextAreaField/TextAreaField.stories.ts +99 -0
- package/lib/js/components/Form/TextAreaField/TextAreaField.types.ts +23 -0
- package/lib/js/components/Form/TextAreaField/TextAreaField.vue +190 -0
- package/lib/js/components/Form/TextAreaField/TextAreaFieldAutosized.vue +19 -0
- package/lib/js/components/Form/TextAreaField/index.ts +5 -0
- package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.spec.ts +26 -0
- package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.stories.ts +16 -3
- package/lib/js/components/LabelValue/LabelValueItem/LabelValueItem.vue +5 -0
- package/lib/js/components/LoadingBar/LoadingBar.spec.ts +84 -0
- package/lib/js/components/LoadingBar/LoadingBar.vue +30 -19
- package/lib/js/components/Toast/Toast.consts.ts +4 -2
- package/lib/js/components/Toast/Toast.spec.ts +177 -0
- package/lib/js/components/Toast/Toast.stories.ts +65 -31
- package/lib/js/components/Toast/Toast.vue +176 -195
- package/lib/js/{components/Form/InputField/useInputFieldWithinForm.ts → composables/useTextFieldWithinForm.ts} +7 -2
- package/lib/js/index.ts +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import { mount } from '@vue/test-utils';
|
|
3
|
+
import { h } from 'vue';
|
|
4
|
+
import Toast from './Toast.vue';
|
|
5
|
+
import { TOAST_COLORS, TOAST_POSITIONS, TOAST_SIZES } from './Toast.consts';
|
|
6
|
+
import DsButton, { BUTTON_SIZES } from '../Buttons/Button';
|
|
7
|
+
import DsIconButton, { ICON_BUTTON_COLORS, ICON_BUTTON_SIZES } from '../Buttons/IconButton';
|
|
8
|
+
import { ICONS } from '../Icons/Icon';
|
|
9
|
+
import { ComponentProps } from 'vue-component-type-helpers';
|
|
10
|
+
|
|
11
|
+
const setup = (props: ComponentProps<typeof Toast> = {}) =>
|
|
12
|
+
mount(Toast, {
|
|
13
|
+
props,
|
|
14
|
+
slots: {
|
|
15
|
+
content: () => h('span', 'Wpłynąłem na suchego przestwór oceanu'),
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe('Toast', () => {
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
vi.useRealTimers();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should render the content slot', () => {
|
|
25
|
+
const wrapper = setup();
|
|
26
|
+
|
|
27
|
+
expect(wrapper.find('.ds-toast__content').text()).toBe(
|
|
28
|
+
'Wpłynąłem na suchego przestwór oceanu',
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it.each(Object.values(TOAST_POSITIONS))('should render in position: %s', (position) => {
|
|
33
|
+
const wrapper = setup({ position });
|
|
34
|
+
|
|
35
|
+
expect(wrapper.find('.ds-toast').classes()).toContain(`-ds-position-${position}`);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should update the position modifier when the prop changes', async () => {
|
|
39
|
+
const wrapper = setup({ position: TOAST_POSITIONS.CENTER });
|
|
40
|
+
|
|
41
|
+
await wrapper.setProps({ position: TOAST_POSITIONS.NONE });
|
|
42
|
+
|
|
43
|
+
expect(wrapper.find('.ds-toast').classes()).toContain('-ds-position-none');
|
|
44
|
+
expect(wrapper.find('.ds-toast').classes()).not.toContain('-ds-position-center');
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it.each(Object.values(TOAST_SIZES))('should render in size: %s', (size) => {
|
|
48
|
+
const wrapper = setup({ size });
|
|
49
|
+
|
|
50
|
+
expect(wrapper.find('.ds-toast').classes()).toContain(`-ds-size-${size}`);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it.each(Object.values(TOAST_COLORS))('should render in color: %s', (color) => {
|
|
54
|
+
const wrapper = setup({ color });
|
|
55
|
+
|
|
56
|
+
expect(wrapper.find('.ds-toast').classes()).toContain(`-ds-color-${color}`);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should render the title when provided', () => {
|
|
60
|
+
const wrapper = setup({ title: 'Tytuł' });
|
|
61
|
+
|
|
62
|
+
expect(wrapper.find('.ds-toast__title').text()).toBe('Tytuł');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should not render the title when not provided', () => {
|
|
66
|
+
const wrapper = setup();
|
|
67
|
+
|
|
68
|
+
expect(wrapper.find('.ds-toast__title').exists()).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it.each([
|
|
72
|
+
{ size: TOAST_SIZES.SMALL, expectedButtonSize: BUTTON_SIZES.SMALL },
|
|
73
|
+
{ size: TOAST_SIZES.MEDIUM, expectedButtonSize: BUTTON_SIZES.MEDIUM },
|
|
74
|
+
{ size: TOAST_SIZES.LARGE, expectedButtonSize: BUTTON_SIZES.MEDIUM },
|
|
75
|
+
])(
|
|
76
|
+
'should render $expectedButtonSize footer buttons in size $size',
|
|
77
|
+
({ size, expectedButtonSize }) => {
|
|
78
|
+
const wrapper = setup({
|
|
79
|
+
size,
|
|
80
|
+
footerPrimaryButtonText: 'primary',
|
|
81
|
+
footerSecondaryButtonText: 'secondary',
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const buttonSizes = wrapper
|
|
85
|
+
.findAllComponents(DsButton)
|
|
86
|
+
.map((button) => button.props('size'));
|
|
87
|
+
|
|
88
|
+
expect(buttonSizes).toEqual([expectedButtonSize, expectedButtonSize]);
|
|
89
|
+
},
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
it('should not render the footer without button texts', () => {
|
|
93
|
+
const wrapper = setup();
|
|
94
|
+
|
|
95
|
+
expect(wrapper.find('.ds-toast__footerButtons').exists()).toBe(false);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it('should emit primary-button-click on the primary button click', async () => {
|
|
99
|
+
const wrapper = setup({ footerPrimaryButtonText: 'primary' });
|
|
100
|
+
|
|
101
|
+
await wrapper.findComponent(DsButton).trigger('click');
|
|
102
|
+
|
|
103
|
+
expect(wrapper.emitted('primary-button-click')).toHaveLength(1);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should emit secondary-button-click on the secondary button click', async () => {
|
|
107
|
+
const wrapper = setup({ footerSecondaryButtonText: 'secondary' });
|
|
108
|
+
|
|
109
|
+
await wrapper.findComponent(DsButton).trigger('click');
|
|
110
|
+
|
|
111
|
+
expect(wrapper.emitted('secondary-button-click')).toHaveLength(1);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('should emit close after the disappearing timeout', () => {
|
|
115
|
+
vi.useFakeTimers();
|
|
116
|
+
const wrapper = setup({ isDisappearing: true, disappearingTimeout: '3' });
|
|
117
|
+
|
|
118
|
+
vi.advanceTimersByTime(3 * 1000 + 100);
|
|
119
|
+
|
|
120
|
+
expect(wrapper.emitted('close')).toHaveLength(1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should not emit close when it is not disappearing', () => {
|
|
124
|
+
vi.useFakeTimers();
|
|
125
|
+
const wrapper = setup({ isDisappearing: false, disappearingTimeout: '3' });
|
|
126
|
+
|
|
127
|
+
vi.advanceTimersByTime(3 * 1000 + 100);
|
|
128
|
+
|
|
129
|
+
expect(wrapper.emitted('close')).toBeUndefined();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should not render the close button by default', () => {
|
|
133
|
+
const wrapper = setup();
|
|
134
|
+
|
|
135
|
+
expect(wrapper.find('.ds-toast__close').exists()).toBe(false);
|
|
136
|
+
expect(wrapper.find('.ds-toast').classes()).not.toContain('-ds-closable');
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('should render the close button when it is closable', () => {
|
|
140
|
+
const wrapper = setup({ isClosable: true });
|
|
141
|
+
|
|
142
|
+
expect(wrapper.find('.ds-toast__close').exists()).toBe(true);
|
|
143
|
+
expect(wrapper.find('.ds-toast').classes()).toContain('-ds-closable');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should render the close button as a small neutral-weak xmark', () => {
|
|
147
|
+
const wrapper = setup({ isClosable: true });
|
|
148
|
+
|
|
149
|
+
const closeButton = wrapper.findComponent(DsIconButton);
|
|
150
|
+
|
|
151
|
+
expect(closeButton.props('icon')).toBe(ICONS.FA_XMARK);
|
|
152
|
+
expect(closeButton.props('size')).toBe(ICON_BUTTON_SIZES.SMALL);
|
|
153
|
+
expect(closeButton.props('color')).toBe(ICON_BUTTON_COLORS.NEUTRAL_WEAK);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should emit close on the close button click', async () => {
|
|
157
|
+
const wrapper = setup({ isClosable: true });
|
|
158
|
+
|
|
159
|
+
await wrapper.find('.ds-toast__close > *').trigger('click');
|
|
160
|
+
|
|
161
|
+
expect(wrapper.emitted('close')).toHaveLength(1);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('should emit close only once when the close button pre-empts the disappearing timeout', async () => {
|
|
165
|
+
vi.useFakeTimers();
|
|
166
|
+
const wrapper = setup({
|
|
167
|
+
isClosable: true,
|
|
168
|
+
isDisappearing: true,
|
|
169
|
+
disappearingTimeout: '3',
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
await wrapper.find('.ds-toast__close > *').trigger('click');
|
|
173
|
+
vi.advanceTimersByTime(3 * 1000 + 100);
|
|
174
|
+
|
|
175
|
+
expect(wrapper.emitted('close')).toHaveLength(1);
|
|
176
|
+
});
|
|
177
|
+
});
|
|
@@ -10,6 +10,26 @@ export default {
|
|
|
10
10
|
decorators: [withActions],
|
|
11
11
|
} as Meta<typeof DsToast>;
|
|
12
12
|
|
|
13
|
+
const toastTemplate = `<ds-toast
|
|
14
|
+
v-if="isVisible"
|
|
15
|
+
:title="title"
|
|
16
|
+
:size="size"
|
|
17
|
+
:position="position"
|
|
18
|
+
:color="color"
|
|
19
|
+
:footer-primary-button-text="footerPrimaryButtonText"
|
|
20
|
+
:footer-primary-button-icon="ICONS[footerPrimaryButtonIcon]"
|
|
21
|
+
:footer-secondary-button-text="footerSecondaryButtonText"
|
|
22
|
+
:footer-secondary-button-icon="ICONS[footerSecondaryButtonIcon]"
|
|
23
|
+
:is-disappearing="isDisappearing"
|
|
24
|
+
:disappearing-timeout="disappearingTimeout"
|
|
25
|
+
:is-closable="isClosable"
|
|
26
|
+
@close="isVisible = false"
|
|
27
|
+
>
|
|
28
|
+
<template #content>
|
|
29
|
+
<span v-html="content" />
|
|
30
|
+
</template>
|
|
31
|
+
</ds-toast>`;
|
|
32
|
+
|
|
13
33
|
const StoryTemplate: StoryFn<typeof DsToast> = (args) => ({
|
|
14
34
|
components: { DsToast },
|
|
15
35
|
setup() {
|
|
@@ -19,40 +39,41 @@ const StoryTemplate: StoryFn<typeof DsToast> = (args) => ({
|
|
|
19
39
|
return {
|
|
20
40
|
ICONS: Object.freeze(ICONS),
|
|
21
41
|
isVisible: true,
|
|
22
|
-
boundariesSelectorId:
|
|
23
|
-
this.boundariesSelector != null ? `#${this.boundariesSelector}` : null,
|
|
24
42
|
};
|
|
25
43
|
},
|
|
26
|
-
template: `<div style="
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<div
|
|
46
|
-
|
|
44
|
+
template: `<div style="height: 1200px; width: 100%;">
|
|
45
|
+
${toastTemplate}
|
|
46
|
+
</div>`,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// `position: none` leaves the placement to the consumer — here the wrapper anchors the toast to the
|
|
50
|
+
// bottom right of its own container instead of the viewport.
|
|
51
|
+
const ClientPositionedStoryTemplate: StoryFn<typeof DsToast> = (args) => ({
|
|
52
|
+
components: { DsToast },
|
|
53
|
+
setup() {
|
|
54
|
+
return args;
|
|
55
|
+
},
|
|
56
|
+
data() {
|
|
57
|
+
return {
|
|
58
|
+
ICONS: Object.freeze(ICONS),
|
|
59
|
+
isVisible: true,
|
|
60
|
+
};
|
|
61
|
+
},
|
|
62
|
+
template: `<div style="height: 400px; padding: 24px; width: 100%;">
|
|
63
|
+
<div style="position: relative; height: 100%; border: 1px black solid;">
|
|
64
|
+
<div style="position: absolute; bottom: 16px; right: 16px;">
|
|
65
|
+
${toastTemplate}
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
47
68
|
</div>`,
|
|
48
69
|
});
|
|
49
70
|
|
|
50
71
|
export const Interactive = StoryTemplate.bind({});
|
|
51
72
|
|
|
52
73
|
const args = {
|
|
74
|
+
title: 'Opcjonalny Title wpisz tutaj',
|
|
53
75
|
size: TOAST_SIZES.MEDIUM,
|
|
54
76
|
position: TOAST_POSITIONS.CENTER,
|
|
55
|
-
boundariesSelector: null,
|
|
56
77
|
color: TOAST_COLORS.INFO,
|
|
57
78
|
footerPrimaryButtonText: 'primary',
|
|
58
79
|
footerPrimaryButtonIcon: null,
|
|
@@ -60,10 +81,14 @@ const args = {
|
|
|
60
81
|
footerSecondaryButtonIcon: null,
|
|
61
82
|
isDisappearing: false,
|
|
62
83
|
disappearingTimeout: '0',
|
|
84
|
+
isClosable: true,
|
|
63
85
|
content: 'Wpłynąłem na suchego przestwór oceanu',
|
|
64
86
|
} as Args;
|
|
65
87
|
|
|
66
88
|
const argTypes = {
|
|
89
|
+
title: {
|
|
90
|
+
control: 'text',
|
|
91
|
+
},
|
|
67
92
|
size: {
|
|
68
93
|
control: 'select',
|
|
69
94
|
options: Object.values(TOAST_SIZES),
|
|
@@ -72,10 +97,6 @@ const argTypes = {
|
|
|
72
97
|
control: 'select',
|
|
73
98
|
options: Object.values(TOAST_POSITIONS),
|
|
74
99
|
},
|
|
75
|
-
boundariesSelector: {
|
|
76
|
-
control: 'select',
|
|
77
|
-
options: [null, 'left', 'right'],
|
|
78
|
-
},
|
|
79
100
|
color: {
|
|
80
101
|
control: 'select',
|
|
81
102
|
options: Object.values(TOAST_COLORS),
|
|
@@ -88,20 +109,33 @@ const argTypes = {
|
|
|
88
109
|
control: 'select',
|
|
89
110
|
options: [null, ...Object.keys(ICONS)],
|
|
90
111
|
},
|
|
112
|
+
isClosable: {
|
|
113
|
+
control: 'boolean',
|
|
114
|
+
},
|
|
91
115
|
content: {
|
|
92
116
|
control: 'text',
|
|
93
117
|
},
|
|
94
118
|
} as ArgTypes;
|
|
95
119
|
|
|
120
|
+
const actionsParameters = {
|
|
121
|
+
actions: {
|
|
122
|
+
handles: ['close', 'primary-button-click', 'secondary-button-click'],
|
|
123
|
+
},
|
|
124
|
+
};
|
|
125
|
+
|
|
96
126
|
Interactive.argTypes = argTypes;
|
|
97
127
|
Interactive.args = args;
|
|
98
128
|
|
|
99
129
|
Interactive.parameters = {
|
|
100
|
-
|
|
101
|
-
handles: ['close', 'primary-button-click', 'secondary-button-click'],
|
|
102
|
-
},
|
|
130
|
+
...actionsParameters,
|
|
103
131
|
design: {
|
|
104
132
|
type: 'figma',
|
|
105
133
|
url: 'https://www.figma.com/design/izQdYyiBR1GQgFkaOIfIJI/LMS---DS-Components?node-id=8091-108960',
|
|
106
134
|
},
|
|
107
135
|
};
|
|
136
|
+
|
|
137
|
+
export const ClientPositioned = ClientPositionedStoryTemplate.bind({});
|
|
138
|
+
|
|
139
|
+
ClientPositioned.argTypes = argTypes;
|
|
140
|
+
ClientPositioned.args = { ...args, position: TOAST_POSITIONS.NONE };
|
|
141
|
+
ClientPositioned.parameters = actionsParameters;
|