@pequity/squirrel 8.3.0 → 8.3.2
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/cjs/index.js +69 -18
- package/dist/cjs/p-modal.js +9 -5
- package/dist/cjs/p-steps.js +0 -2
- package/dist/es/chunks/p-dropdown-select.js +2 -2
- package/dist/es/index.js +102 -51
- package/dist/es/p-dropdown-select.js +1 -1
- package/dist/es/p-modal.js +9 -5
- package/dist/es/p-steps.js +1 -4
- package/dist/squirrel/components/index.d.ts +2 -1
- package/dist/squirrel/components/p-modal/p-modal.vue.d.ts +9 -0
- package/dist/squirrel/components/p-steps/p-steps.types.d.ts +5 -0
- package/dist/squirrel/components/p-steps/p-steps.vue.d.ts +14 -15
- package/dist/squirrel.css +88 -88
- package/package.json +5 -5
- package/squirrel/components/index.ts +2 -0
- package/squirrel/components/p-drawer/p-drawer.stories.js +4 -6
- package/squirrel/components/p-dropdown/p-dropdown.stories.js +5 -7
- package/squirrel/components/p-dropdown-select/p-dropdown-select.stories.js +8 -14
- package/squirrel/components/p-input-percent/p-input-percent.stories.js +7 -12
- package/squirrel/components/p-modal/p-modal-basic.spec.js +32 -0
- package/squirrel/components/p-modal/p-modal.stories.js +22 -0
- package/squirrel/components/p-modal/p-modal.vue +7 -4
- package/squirrel/components/p-pagination/p-pagination.stories.js +4 -6
- package/squirrel/components/p-select/p-select.stories.js +2 -2
- package/squirrel/components/p-select-btn/p-select-btn.stories.js +15 -26
- package/squirrel/components/p-select-pill/p-select-pill.stories.js +12 -20
- package/squirrel/components/p-steps/__snapshots__/{p-steps.spec.js.snap → p-steps.spec.ts.snap} +5 -5
- package/squirrel/components/p-steps/p-steps.spec.ts +203 -0
- package/squirrel/components/p-steps/p-steps.stories.js +32 -4
- package/squirrel/components/p-steps/p-steps.types.ts +5 -0
- package/squirrel/components/p-steps/p-steps.vue +30 -21
- package/squirrel/components/p-table-sort/p-table-sort.stories.js +4 -6
- package/dist/cjs/chunks/p-steps.js +0 -55
- package/dist/es/chunks/p-steps.js +0 -56
- package/squirrel/components/p-steps/p-steps.spec.js +0 -126
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { fieldArgTypes } from '@root/stories/common/field';
|
|
2
2
|
import PSelect from '@squirrel/components/p-select/p-select.vue';
|
|
3
3
|
|
|
4
|
-
const selectItems =
|
|
4
|
+
const selectItems = [
|
|
5
5
|
{ value: 1, text: 'Aleksandr Chappel' },
|
|
6
6
|
{ value: 2, text: 'Van Deyes' },
|
|
7
7
|
{ value: 3, text: 'Meris Hardman and a very long text here' },
|
|
8
8
|
{ value: 4, text: 'Chick Catto' },
|
|
9
9
|
{ value: 5, text: "Alys O'Flynn" },
|
|
10
|
-
]
|
|
10
|
+
];
|
|
11
11
|
|
|
12
12
|
export default {
|
|
13
13
|
title: 'Components/PSelect',
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { fieldArgTypes } from '@root/stories/common/field';
|
|
2
2
|
import PSelectBtn from '@squirrel/components/p-select-btn/p-select-btn.vue';
|
|
3
3
|
import { expect, userEvent, within } from '@storybook/test';
|
|
4
|
+
import { ref } from 'vue';
|
|
4
5
|
|
|
5
|
-
const selectItems =
|
|
6
|
+
const selectItems = [
|
|
6
7
|
{ value: 1, text: 'Aleksandr Chappel', tooltip: 'lorem ipsum text 1' },
|
|
7
8
|
{ value: 2, text: 'Van Deyes', tooltip: 'lorem ipsum text 2' },
|
|
8
9
|
{ value: 3, text: 'Meris Hardman', tooltip: 'lorem ipsum text 3' },
|
|
9
10
|
{ value: 4, text: 'Chick Catto', tooltip: 'lorem ipsum text 4' },
|
|
10
11
|
{ value: 5, text: "Alys O'Flynn", tooltip: 'lorem ipsum text 5' },
|
|
11
|
-
]
|
|
12
|
+
];
|
|
12
13
|
|
|
13
14
|
export default {
|
|
14
15
|
title: 'Components/PSelectBtn',
|
|
@@ -17,7 +18,9 @@ export default {
|
|
|
17
18
|
render: (args) => ({
|
|
18
19
|
components: { PSelectBtn },
|
|
19
20
|
setup() {
|
|
20
|
-
|
|
21
|
+
const selected = ref(1);
|
|
22
|
+
|
|
23
|
+
return { args, selected };
|
|
21
24
|
},
|
|
22
25
|
template: `
|
|
23
26
|
<div>
|
|
@@ -27,11 +30,6 @@ export default {
|
|
|
27
30
|
Selected: {{ selected }}
|
|
28
31
|
</div>
|
|
29
32
|
`,
|
|
30
|
-
data() {
|
|
31
|
-
return {
|
|
32
|
-
selected: 1,
|
|
33
|
-
};
|
|
34
|
-
},
|
|
35
33
|
}),
|
|
36
34
|
argTypes: {
|
|
37
35
|
size: fieldArgTypes.size,
|
|
@@ -86,7 +84,9 @@ export const Sizes = {
|
|
|
86
84
|
render: (args) => ({
|
|
87
85
|
components: { PSelectBtn },
|
|
88
86
|
setup() {
|
|
89
|
-
|
|
87
|
+
const selected = ref(1);
|
|
88
|
+
|
|
89
|
+
return { args, selected };
|
|
90
90
|
},
|
|
91
91
|
template: `
|
|
92
92
|
<div>
|
|
@@ -101,11 +101,6 @@ export const Sizes = {
|
|
|
101
101
|
</div>
|
|
102
102
|
</div>
|
|
103
103
|
`,
|
|
104
|
-
data() {
|
|
105
|
-
return {
|
|
106
|
-
selected: 1,
|
|
107
|
-
};
|
|
108
|
-
},
|
|
109
104
|
}),
|
|
110
105
|
argTypes: {
|
|
111
106
|
modelValue: {
|
|
@@ -135,7 +130,9 @@ export const WithTooltip = {
|
|
|
135
130
|
render: (args) => ({
|
|
136
131
|
components: { PSelectBtn },
|
|
137
132
|
setup() {
|
|
138
|
-
|
|
133
|
+
const selected = ref(1);
|
|
134
|
+
|
|
135
|
+
return { args, selected };
|
|
139
136
|
},
|
|
140
137
|
template: `
|
|
141
138
|
<div>
|
|
@@ -144,11 +141,6 @@ export const WithTooltip = {
|
|
|
144
141
|
</div>
|
|
145
142
|
</div>
|
|
146
143
|
`,
|
|
147
|
-
data() {
|
|
148
|
-
return {
|
|
149
|
-
selected: 1,
|
|
150
|
-
};
|
|
151
|
-
},
|
|
152
144
|
}),
|
|
153
145
|
argTypes: {
|
|
154
146
|
modelValue: {
|
|
@@ -218,7 +210,9 @@ export const MultipleSelected = {
|
|
|
218
210
|
render: (args) => ({
|
|
219
211
|
components: { PSelectBtn },
|
|
220
212
|
setup() {
|
|
221
|
-
|
|
213
|
+
const selected = ref([{ value: 2, text: 'Van Deyes', tooltip: 'lorem ipsum text 2' }]);
|
|
214
|
+
|
|
215
|
+
return { args, selected };
|
|
222
216
|
},
|
|
223
217
|
template: `
|
|
224
218
|
<div>
|
|
@@ -228,11 +222,6 @@ export const MultipleSelected = {
|
|
|
228
222
|
Selected: {{ selected }}
|
|
229
223
|
</div>
|
|
230
224
|
`,
|
|
231
|
-
data() {
|
|
232
|
-
return {
|
|
233
|
-
selected: [{ value: 2, text: 'Van Deyes', tooltip: 'lorem ipsum text 2' }],
|
|
234
|
-
};
|
|
235
|
-
},
|
|
236
225
|
}),
|
|
237
226
|
args: {
|
|
238
227
|
items: selectItems,
|
|
@@ -2,16 +2,17 @@ import { fieldArgTypes } from '@root/stories/common/field';
|
|
|
2
2
|
import { getCSSTransitionDuration, sleep } from '@root/stories/common/helpers';
|
|
3
3
|
import PSelectPill from '@squirrel/components/p-select-pill/p-select-pill.vue';
|
|
4
4
|
import { expect, userEvent, within } from '@storybook/test';
|
|
5
|
+
import { ref } from 'vue';
|
|
5
6
|
|
|
6
7
|
const ACTIVE_CLASS = 'text-p-purple-60';
|
|
7
8
|
|
|
8
|
-
const selectItems =
|
|
9
|
+
const selectItems = [
|
|
9
10
|
{ value: 1, text: 'Aleksandr Chappel' },
|
|
10
11
|
{ value: 2, text: 'Van Deyes' },
|
|
11
12
|
{ value: 3, text: 'Meris Hardman' },
|
|
12
13
|
{ value: 4, text: 'Chick Catto' },
|
|
13
14
|
{ value: 5, text: "Alys O'Flynn" },
|
|
14
|
-
]
|
|
15
|
+
];
|
|
15
16
|
|
|
16
17
|
const selectItemsSubtext = selectItems.map((item, i) => ({ ...item, subtext: `text${i + 1}` }));
|
|
17
18
|
|
|
@@ -22,7 +23,9 @@ export default {
|
|
|
22
23
|
render: (args) => ({
|
|
23
24
|
components: { PSelectPill },
|
|
24
25
|
setup() {
|
|
25
|
-
|
|
26
|
+
const selected = ref(1);
|
|
27
|
+
|
|
28
|
+
return { args, selected };
|
|
26
29
|
},
|
|
27
30
|
template: `
|
|
28
31
|
<div>
|
|
@@ -32,11 +35,6 @@ export default {
|
|
|
32
35
|
Selected: {{ selected }}
|
|
33
36
|
</div>
|
|
34
37
|
`,
|
|
35
|
-
data() {
|
|
36
|
-
return {
|
|
37
|
-
selected: 1,
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
38
|
}),
|
|
41
39
|
argTypes: {
|
|
42
40
|
size: fieldArgTypes.size,
|
|
@@ -98,7 +96,9 @@ export const Sizes = {
|
|
|
98
96
|
render: (args) => ({
|
|
99
97
|
components: { PSelectPill },
|
|
100
98
|
setup() {
|
|
101
|
-
|
|
99
|
+
const selected = ref(1);
|
|
100
|
+
|
|
101
|
+
return { args, selected };
|
|
102
102
|
},
|
|
103
103
|
template: `
|
|
104
104
|
<div>
|
|
@@ -113,11 +113,6 @@ export const Sizes = {
|
|
|
113
113
|
</div>
|
|
114
114
|
</div>
|
|
115
115
|
`,
|
|
116
|
-
data() {
|
|
117
|
-
return {
|
|
118
|
-
selected: 1,
|
|
119
|
-
};
|
|
120
|
-
},
|
|
121
116
|
}),
|
|
122
117
|
argTypes: {
|
|
123
118
|
modelValue: {
|
|
@@ -147,7 +142,9 @@ export const Subtext = {
|
|
|
147
142
|
render: (args) => ({
|
|
148
143
|
components: { PSelectPill },
|
|
149
144
|
setup() {
|
|
150
|
-
|
|
145
|
+
const selected = ref(1);
|
|
146
|
+
|
|
147
|
+
return { args, selected };
|
|
151
148
|
},
|
|
152
149
|
template: `
|
|
153
150
|
<div>
|
|
@@ -156,11 +153,6 @@ export const Subtext = {
|
|
|
156
153
|
</div>
|
|
157
154
|
</div>
|
|
158
155
|
`,
|
|
159
|
-
data() {
|
|
160
|
-
return {
|
|
161
|
-
selected: 1,
|
|
162
|
-
};
|
|
163
|
-
},
|
|
164
156
|
}),
|
|
165
157
|
argTypes: {
|
|
166
158
|
modelValue: {
|
package/squirrel/components/p-steps/__snapshots__/{p-steps.spec.js.snap → p-steps.spec.ts.snap}
RENAMED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
2
|
|
|
3
|
-
exports[`PSteps.vue > renders correctly 1`] = `
|
|
3
|
+
exports[`PSteps.vue > render tests > renders correctly 1`] = `
|
|
4
4
|
"<div class="flex items-center gap-2">
|
|
5
|
-
<div class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold border
|
|
5
|
+
<div class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold border-p-gray-30 text-p-gray-30">First</div>
|
|
6
6
|
<div class="flex items-center">
|
|
7
|
-
<iconify-icon icon="material-symbols:arrow-right-alt-rounded" class="text-p-
|
|
7
|
+
<iconify-icon icon="material-symbols:arrow-right-alt-rounded" class="text-p-gray-30"></iconify-icon>
|
|
8
8
|
</div>
|
|
9
|
-
<div class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold border
|
|
9
|
+
<div class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold border-p-gray-30 text-p-gray-30">Second</div>
|
|
10
10
|
<div class="flex items-center">
|
|
11
11
|
<iconify-icon icon="material-symbols:arrow-right-alt-rounded" class="text-p-gray-30"></iconify-icon>
|
|
12
12
|
</div>
|
|
13
|
-
<div class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold border
|
|
13
|
+
<div class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold border-p-gray-30 text-p-gray-30">Third</div>
|
|
14
14
|
<!--v-if-->
|
|
15
15
|
</div>"
|
|
16
16
|
`;
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import PSteps from '@squirrel/components/p-steps/p-steps.vue';
|
|
2
|
+
import { createWrapperFor } from '@tests/vitest.helpers';
|
|
3
|
+
import { type VueWrapper } from '@vue/test-utils';
|
|
4
|
+
|
|
5
|
+
const createSteps = () => [
|
|
6
|
+
{ value: 'first', text: 'First' },
|
|
7
|
+
{ value: 'second', text: 'Second' },
|
|
8
|
+
{ value: 'third', text: 'Third' },
|
|
9
|
+
];
|
|
10
|
+
|
|
11
|
+
const createWrapper = (props = {}) => {
|
|
12
|
+
return createWrapperFor(PSteps, {
|
|
13
|
+
props: {
|
|
14
|
+
steps: createSteps(),
|
|
15
|
+
activeStep: null,
|
|
16
|
+
clickable: false,
|
|
17
|
+
...props,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe('PSteps.vue', () => {
|
|
23
|
+
describe('render tests', () => {
|
|
24
|
+
it('renders correctly', () => {
|
|
25
|
+
const wrapper = createWrapper();
|
|
26
|
+
|
|
27
|
+
expect(wrapper.html()).toMatchSnapshot();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('renders the correct number of steps', () => {
|
|
31
|
+
const wrapper = createWrapper({
|
|
32
|
+
steps: createSteps(),
|
|
33
|
+
activeStep: 'second',
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
37
|
+
expect(stepElements.length).toBe(createSteps().length);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('applies correct classes for current step', () => {
|
|
41
|
+
const wrapper = createWrapper({
|
|
42
|
+
activeStep: 'second',
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
46
|
+
|
|
47
|
+
// First step should be completed (blue text)
|
|
48
|
+
expect(stepElements[0].classes()).toContain('text-nowrap');
|
|
49
|
+
expect(stepElements[0].classes()).toContain('text-p-blue-50');
|
|
50
|
+
expect(stepElements[0].classes()).toContain('border-p-blue-50');
|
|
51
|
+
|
|
52
|
+
// Second step should be current (blue background)
|
|
53
|
+
expect(stepElements[1].classes()).toContain('text-nowrap');
|
|
54
|
+
expect(stepElements[1].classes()).toContain('bg-p-blue-50');
|
|
55
|
+
expect(stepElements[1].classes()).toContain('text-surface');
|
|
56
|
+
expect(stepElements[1].classes()).toContain('border-p-blue-50');
|
|
57
|
+
|
|
58
|
+
// Third step should be upcoming (gray)
|
|
59
|
+
expect(stepElements[2].classes()).toContain('text-nowrap');
|
|
60
|
+
expect(stepElements[2].classes()).toContain('text-p-gray-30');
|
|
61
|
+
expect(stepElements[2].classes()).toContain('border-p-gray-30');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it('displays step titles', () => {
|
|
65
|
+
const wrapper = createWrapper({
|
|
66
|
+
steps: [
|
|
67
|
+
{ value: 'step1', text: 'Custom Step 1' },
|
|
68
|
+
{ value: 'step2', text: 'Custom Step 2' },
|
|
69
|
+
{ value: 'step3', text: 'Custom Step 3' },
|
|
70
|
+
],
|
|
71
|
+
activeStep: 'step2',
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
75
|
+
expect(stepElements[0].text()).toBe('Custom Step 1');
|
|
76
|
+
expect(stepElements[1].text()).toBe('Custom Step 2');
|
|
77
|
+
expect(stepElements[2].text()).toBe('Custom Step 3');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('displays step titles in startCase when the text is missing', () => {
|
|
81
|
+
const wrapper = createWrapper({
|
|
82
|
+
steps: [{ value: 'customStep1' }, { value: 'customStep2' }, { value: 'customStep3' }],
|
|
83
|
+
activeStep: 'customStep2',
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
87
|
+
|
|
88
|
+
expect(stepElements[0].text()).toBe('Custom Step 1');
|
|
89
|
+
expect(stepElements[1].text()).toBe('Custom Step 2');
|
|
90
|
+
expect(stepElements[2].text()).toBe('Custom Step 3');
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('renders the correct number of arrows between steps', () => {
|
|
94
|
+
const wrapper = createWrapper({
|
|
95
|
+
steps: [
|
|
96
|
+
{ value: 1, text: '1' },
|
|
97
|
+
{ value: 2, text: '2' },
|
|
98
|
+
{ value: 3, text: '3' },
|
|
99
|
+
{ value: 4, text: '4' },
|
|
100
|
+
],
|
|
101
|
+
activeStep: 'second',
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// There should be 3 arrows for 4 steps
|
|
105
|
+
const arrowElements = wrapper.findAll('[icon="material-symbols:arrow-right-alt-rounded"]');
|
|
106
|
+
expect(arrowElements.length).toBe(3);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('applies the correct classes to arrows based on current step', () => {
|
|
110
|
+
const wrapper = createWrapper({
|
|
111
|
+
steps: [
|
|
112
|
+
{ value: 1, text: '1' },
|
|
113
|
+
{ value: 2, text: '2' },
|
|
114
|
+
{ value: 3, text: '3' },
|
|
115
|
+
{ value: 4, text: '4' },
|
|
116
|
+
],
|
|
117
|
+
activeStep: 2,
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
const arrowElements = wrapper.findAll('[icon="material-symbols:arrow-right-alt-rounded"]');
|
|
121
|
+
|
|
122
|
+
expect(arrowElements.length).toBe(3);
|
|
123
|
+
|
|
124
|
+
// Arrow between first and second step should be colored
|
|
125
|
+
expect(arrowElements[0].classes()).toContain('text-p-blue-50');
|
|
126
|
+
|
|
127
|
+
// Arrow after current step should be gray
|
|
128
|
+
expect(arrowElements[1].classes()).toContain('text-p-gray-30');
|
|
129
|
+
expect(arrowElements[2].classes()).toContain('text-p-gray-30');
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('sets cursor-pointer when clickable is true', async () => {
|
|
133
|
+
const wrapper = createWrapper({ activeStep: 'first', clickable: true });
|
|
134
|
+
|
|
135
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
136
|
+
|
|
137
|
+
stepElements.forEach((stepElement: VueWrapper) => {
|
|
138
|
+
expect(stepElement.classes()).toContain('cursor-pointer');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('sets cursor-pointer clickable steps only', async () => {
|
|
143
|
+
const wrapper = createWrapper({
|
|
144
|
+
steps: [
|
|
145
|
+
{ value: 1, text: '1', disabled: false },
|
|
146
|
+
{ value: 2, text: '2', disabled: true },
|
|
147
|
+
{ value: 3, text: '3', disabled: false },
|
|
148
|
+
],
|
|
149
|
+
activeStep: 1,
|
|
150
|
+
clickable: true,
|
|
151
|
+
});
|
|
152
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
153
|
+
|
|
154
|
+
// First step should be clickable
|
|
155
|
+
expect(stepElements[0].classes()).toContain('cursor-pointer');
|
|
156
|
+
|
|
157
|
+
// Second step should not be clickable
|
|
158
|
+
expect(stepElements[1].classes()).not.toContain('cursor-pointer');
|
|
159
|
+
|
|
160
|
+
// Third step should be clickable
|
|
161
|
+
expect(stepElements[2].classes()).toContain('cursor-pointer');
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('does not set cursor-pointer when item disabled is true', async () => {
|
|
165
|
+
const wrapper = createWrapper({
|
|
166
|
+
steps: [
|
|
167
|
+
{ value: 1, text: '1', disabled: true },
|
|
168
|
+
{ value: 2, text: '2', disabled: true },
|
|
169
|
+
],
|
|
170
|
+
activeStep: 1,
|
|
171
|
+
clickable: true,
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
175
|
+
|
|
176
|
+
stepElements.forEach((stepElement: VueWrapper) => {
|
|
177
|
+
expect(stepElement.classes()).not.toContain('cursor-pointer');
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('emits click:step when a step is clicked', async () => {
|
|
182
|
+
const wrapper = createWrapper({ activeStep: 'first', clickable: true });
|
|
183
|
+
|
|
184
|
+
const stepElements = wrapper.findAll('.rounded-full.border');
|
|
185
|
+
|
|
186
|
+
await stepElements[1].trigger('click');
|
|
187
|
+
|
|
188
|
+
expect(wrapper.emitted()['click:step'][0]).toEqual([{ text: 'Second', value: 'second' }, 1]);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('updates the active step when activeStep changes', async () => {
|
|
192
|
+
const wrapper = createWrapper({ activeStep: 'first' });
|
|
193
|
+
|
|
194
|
+
const getStepElements = () => wrapper.findAll('.rounded-full.border');
|
|
195
|
+
|
|
196
|
+
expect(getStepElements()[0].classes()).toContain('bg-p-blue-50');
|
|
197
|
+
|
|
198
|
+
await wrapper.setProps({ activeStep: 'second' });
|
|
199
|
+
|
|
200
|
+
expect(getStepElements()[1].classes()).toContain('bg-p-blue-50');
|
|
201
|
+
});
|
|
202
|
+
});
|
|
203
|
+
});
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import PSteps from '@squirrel/components/p-steps/p-steps.vue';
|
|
2
|
+
import { ref } from 'vue';
|
|
2
3
|
|
|
3
4
|
export default {
|
|
4
5
|
title: 'Components/PSteps',
|
|
@@ -22,10 +23,37 @@ export const Default = {
|
|
|
22
23
|
template: `<PSteps v-bind="args" />`,
|
|
23
24
|
}),
|
|
24
25
|
args: {
|
|
25
|
-
steps: [
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
steps: [
|
|
27
|
+
{ value: 'stepOne', text: 'Step One' },
|
|
28
|
+
{ value: 'stepTwo', text: 'Step Two' },
|
|
29
|
+
{ value: 'stepThree', text: 'Step Three' },
|
|
30
|
+
{ value: 'stepFour', text: 'Step Four' },
|
|
31
|
+
],
|
|
32
|
+
activeStep: 'stepTwo',
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const Clickable = {
|
|
37
|
+
render: (args) => ({
|
|
38
|
+
components: { PSteps },
|
|
39
|
+
setup() {
|
|
40
|
+
const activeStep = ref('stepTwo');
|
|
41
|
+
|
|
42
|
+
const setActiveStep = (step) => {
|
|
43
|
+
activeStep.value = String(step.value);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
return { args, activeStep, setActiveStep };
|
|
29
47
|
},
|
|
48
|
+
template: `<PSteps v-bind="args" :active-step="activeStep" @click:step="setActiveStep" />`,
|
|
49
|
+
}),
|
|
50
|
+
args: {
|
|
51
|
+
steps: [
|
|
52
|
+
{ value: 'stepOne', text: 'Step One' },
|
|
53
|
+
{ value: 'stepTwo', text: 'Step Two' },
|
|
54
|
+
{ value: 'stepThree', text: 'Step Three' },
|
|
55
|
+
{ value: 'stepFour', text: 'Step Four' },
|
|
56
|
+
],
|
|
57
|
+
clickable: true,
|
|
30
58
|
},
|
|
31
59
|
};
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="flex items-center gap-2">
|
|
3
|
-
<template v-for="(step,
|
|
4
|
-
<div
|
|
5
|
-
|
|
3
|
+
<template v-for="(step, i) in steps" :key="step.value">
|
|
4
|
+
<div
|
|
5
|
+
class="text-nowrap rounded-full border px-4 py-1 text-sm font-semibold"
|
|
6
|
+
:class="[stepClasses(step, i), { 'cursor-pointer': clickable && !step.disabled }]"
|
|
7
|
+
@click="emit('click:step', step, i)"
|
|
8
|
+
>
|
|
9
|
+
{{ step.text || startCase(String(step.value)) }}
|
|
6
10
|
</div>
|
|
7
|
-
<div v-if="
|
|
11
|
+
<div v-if="i < steps.length - 1" class="flex items-center">
|
|
8
12
|
<PIcon
|
|
9
13
|
icon="material-symbols:arrow-right-alt-rounded"
|
|
10
|
-
:class="[
|
|
14
|
+
:class="[activeStepIndex <= i ? 'text-p-gray-30' : 'text-p-blue-50']"
|
|
11
15
|
/>
|
|
12
16
|
</div>
|
|
13
17
|
</template>
|
|
14
18
|
</div>
|
|
15
19
|
</template>
|
|
16
20
|
|
|
17
|
-
<script setup lang="ts"
|
|
21
|
+
<script setup lang="ts">
|
|
18
22
|
import PIcon from '@squirrel/components/p-icon/p-icon.vue';
|
|
23
|
+
import type { StepItem } from '@squirrel/components/p-steps/p-steps.types';
|
|
19
24
|
import { startCase } from 'lodash-es';
|
|
20
25
|
import { computed } from 'vue';
|
|
21
26
|
|
|
@@ -24,28 +29,32 @@ defineOptions({
|
|
|
24
29
|
});
|
|
25
30
|
|
|
26
31
|
type Props = {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
32
|
+
activeStep?: StepItem['value'];
|
|
33
|
+
steps?: readonly StepItem[];
|
|
34
|
+
clickable?: boolean;
|
|
30
35
|
};
|
|
31
36
|
|
|
32
|
-
const props = defineProps<Props>()
|
|
37
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
38
|
+
activeStep: null,
|
|
39
|
+
steps: () => [],
|
|
40
|
+
clickable: false,
|
|
41
|
+
});
|
|
33
42
|
|
|
34
|
-
const
|
|
43
|
+
const emit = defineEmits<{
|
|
44
|
+
'click:step': [step: StepItem, index: number];
|
|
45
|
+
}>();
|
|
35
46
|
|
|
36
|
-
const
|
|
37
|
-
if (step === props.currentStep) {
|
|
38
|
-
return 'border border-p-blue-50 bg-p-blue-50 text-surface';
|
|
39
|
-
}
|
|
47
|
+
const activeStepIndex = computed(() => props.steps.findIndex((s) => s.value === props.activeStep));
|
|
40
48
|
|
|
41
|
-
|
|
42
|
-
|
|
49
|
+
const stepClasses = (step: StepItem, stepIndex: number) => {
|
|
50
|
+
if (step.value === props.activeStep) {
|
|
51
|
+
return 'border-p-blue-50 bg-p-blue-50 text-surface';
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
if (activeStepIndex.value < stepIndex) {
|
|
55
|
+
return 'border-p-gray-30 text-p-gray-30';
|
|
56
|
+
}
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
return props.stepTitleMap?.[step] || startCase(step);
|
|
58
|
+
return 'border-p-blue-50 text-p-blue-50';
|
|
50
59
|
};
|
|
51
60
|
</script>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SORTING_TYPES } from '@squirrel/components/p-table-sort/p-table-sort.config';
|
|
2
2
|
import PTableSort from '@squirrel/components/p-table-sort/p-table-sort.vue';
|
|
3
|
+
import { ref } from 'vue';
|
|
3
4
|
|
|
4
5
|
export default {
|
|
5
6
|
title: 'Components/PTableSort',
|
|
@@ -37,17 +38,14 @@ export const WithVModel = {
|
|
|
37
38
|
render: (args) => ({
|
|
38
39
|
components: { PTableSort },
|
|
39
40
|
setup() {
|
|
40
|
-
|
|
41
|
+
const selected = ref(SORTING_TYPES.NO_SORTING);
|
|
42
|
+
|
|
43
|
+
return { args, selected };
|
|
41
44
|
},
|
|
42
45
|
template: `
|
|
43
46
|
<div>
|
|
44
47
|
<PTableSort v-model="selected" v-bind="args" />
|
|
45
48
|
<div class="mt-2">Selected: {{ selected }}</div>
|
|
46
49
|
</div>`,
|
|
47
|
-
data() {
|
|
48
|
-
return {
|
|
49
|
-
selected: SORTING_TYPES.NO_SORTING,
|
|
50
|
-
};
|
|
51
|
-
},
|
|
52
50
|
}),
|
|
53
51
|
};
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
const vue = require("vue");
|
|
3
|
-
const pIcon_vue_vue_type_script_setup_true_lang = require("./p-icon.js");
|
|
4
|
-
const lodashEs = require("lodash-es");
|
|
5
|
-
const _hoisted_1 = { class: "flex items-center gap-2" };
|
|
6
|
-
const _hoisted_2 = {
|
|
7
|
-
key: 0,
|
|
8
|
-
class: "flex items-center"
|
|
9
|
-
};
|
|
10
|
-
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
11
|
-
...{
|
|
12
|
-
name: "PSteps"
|
|
13
|
-
},
|
|
14
|
-
__name: "p-steps",
|
|
15
|
-
props: {
|
|
16
|
-
steps: {},
|
|
17
|
-
currentStep: {},
|
|
18
|
-
stepTitleMap: {}
|
|
19
|
-
},
|
|
20
|
-
setup(__props) {
|
|
21
|
-
const props = __props;
|
|
22
|
-
const currentStepIndex = vue.computed(() => props.steps.findIndex((s) => s === props.currentStep));
|
|
23
|
-
const stepClasses = (step, stepIndex) => {
|
|
24
|
-
if (step === props.currentStep) {
|
|
25
|
-
return "border border-p-blue-50 bg-p-blue-50 text-surface";
|
|
26
|
-
}
|
|
27
|
-
if (currentStepIndex.value < stepIndex) {
|
|
28
|
-
return "border border-p-gray-30 text-p-gray-30";
|
|
29
|
-
}
|
|
30
|
-
return "border border-p-blue-50 text-p-blue-50";
|
|
31
|
-
};
|
|
32
|
-
const stepTitle = (step) => {
|
|
33
|
-
var _a;
|
|
34
|
-
return ((_a = props.stepTitleMap) == null ? void 0 : _a[step]) || lodashEs.startCase(step);
|
|
35
|
-
};
|
|
36
|
-
return (_ctx, _cache) => {
|
|
37
|
-
return vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
|
|
38
|
-
(vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(_ctx.steps, (step, idx) => {
|
|
39
|
-
return vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: step }, [
|
|
40
|
-
vue.createElementVNode("div", {
|
|
41
|
-
class: vue.normalizeClass(["text-nowrap rounded-full border px-4 py-1 text-sm font-semibold", stepClasses(step, idx)])
|
|
42
|
-
}, vue.toDisplayString(stepTitle(step)), 3),
|
|
43
|
-
idx < _ctx.steps.length - 1 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2, [
|
|
44
|
-
vue.createVNode(pIcon_vue_vue_type_script_setup_true_lang._sfc_main, {
|
|
45
|
-
icon: "material-symbols:arrow-right-alt-rounded",
|
|
46
|
-
class: vue.normalizeClass([currentStepIndex.value <= idx ? "text-p-gray-30" : "text-p-blue-50"])
|
|
47
|
-
}, null, 8, ["class"])
|
|
48
|
-
])) : vue.createCommentVNode("", true)
|
|
49
|
-
], 64);
|
|
50
|
-
}), 128))
|
|
51
|
-
]);
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
exports._sfc_main = _sfc_main;
|