@pequity/squirrel 6.0.14 → 6.1.1
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/chunks/p-action-bar.js +4 -4
- package/dist/cjs/chunks/p-btn.js +204 -0
- package/dist/cjs/chunks/p-select-btn.js +8 -8
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/p-btn.js +2 -169
- package/dist/es/chunks/p-action-bar.js +8 -8
- package/dist/es/chunks/p-btn.js +205 -0
- package/dist/es/chunks/p-select-btn.js +9 -9
- package/dist/es/index.js +62 -62
- package/dist/es/p-btn.js +2 -169
- package/dist/squirrel/components/p-btn/p-btn.vue.d.ts +106 -46
- package/dist/squirrel/components/p-card/p-card.vue.d.ts +27 -14
- package/dist/squirrel/components/p-checkbox/p-checkbox.vue.d.ts +43 -12
- package/dist/squirrel/components/p-close-btn/p-close-btn.vue.d.ts +1 -1
- package/dist/squirrel/components/p-drawer/p-drawer.vue.d.ts +1 -1
- package/dist/squirrel/components/p-dropdown-select/p-dropdown-select.vue.d.ts +15 -422
- package/dist/squirrel/components/p-file-upload/p-file-upload.vue.d.ts +1 -3
- package/dist/squirrel/components/p-info-icon/p-info-icon.vue.d.ts +13 -11
- package/dist/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue.d.ts +39 -14
- package/dist/squirrel/components/p-input/p-input.vue.d.ts +2 -2
- package/dist/squirrel/components/p-input-number/p-input-number.vue.d.ts +2 -2
- package/dist/squirrel/components/p-input-search/p-input-search.vue.d.ts +2 -2
- package/dist/squirrel/components/p-link/p-link.vue.d.ts +17 -13
- package/dist/squirrel/components/p-loading/p-loading.vue.d.ts +1 -3
- package/dist/squirrel/components/p-modal/p-modal.vue.d.ts +240 -22
- package/dist/squirrel/components/p-pagination-info/p-pagination-info.vue.d.ts +77 -10
- package/dist/squirrel/components/p-select/p-select.vue.d.ts +116 -14
- package/dist/squirrel/components/p-select-btn/p-select-btn.vue.d.ts +37 -13
- package/dist/squirrel/components/p-select-list/p-select-list.vue.d.ts +14 -418
- package/dist/squirrel/components/p-table/p-table.vue.d.ts +61 -19
- package/dist/squirrel/components/p-table-header-cell/p-table-header-cell.vue.d.ts +2 -2
- package/dist/squirrel/components/p-table-loader/p-table-loader.vue.d.ts +1 -1
- package/dist/squirrel/components/p-table-td/p-table-td.vue.d.ts +23 -11
- package/dist/squirrel/components/p-tabs/p-tabs.vue.d.ts +1 -1
- package/dist/squirrel/components/p-textarea/p-textarea.vue.d.ts +1 -1
- package/dist/squirrel/components/p-toggle/p-toggle.vue.d.ts +1 -1
- package/dist/squirrel/utils/inputClassesMixin.d.ts +1 -1
- package/package.json +25 -24
- package/squirrel/components/p-btn/p-btn.spec.js +229 -161
- package/squirrel/components/p-btn/p-btn.stories.js +32 -8
- package/squirrel/components/p-btn/p-btn.vue +106 -73
- package/squirrel/components/p-dropdown/p-dropdown.vue +0 -1
- package/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue +1 -1
- package/squirrel/components/p-select-btn/p-select-btn.spec.js +24 -5
- package/squirrel/components/p-select-btn/p-select-btn.stories.js +45 -4
- package/squirrel/components/p-select-btn/p-select-btn.vue +3 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pequity/squirrel",
|
|
3
3
|
"description": "Squirrel component library",
|
|
4
|
-
"version": "6.
|
|
4
|
+
"version": "6.1.1",
|
|
5
5
|
"packageManager": "pnpm@9.15.5",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"storybook": "storybook dev -p 6006",
|
|
19
19
|
"build-storybook": "storybook build",
|
|
20
20
|
"test-storybook": "test-storybook",
|
|
21
|
+
"quality": "pnpm run lint && pnpm run typecheck && pnpm run test:unit && pnpm run build",
|
|
21
22
|
"prepare": "husky"
|
|
22
23
|
},
|
|
23
24
|
"files": [
|
|
@@ -53,30 +54,30 @@
|
|
|
53
54
|
"@playwright/test": "^1.50.1",
|
|
54
55
|
"@semantic-release/changelog": "^6.0.3",
|
|
55
56
|
"@semantic-release/git": "^10.0.1",
|
|
56
|
-
"@storybook/addon-a11y": "^8.
|
|
57
|
-
"@storybook/addon-actions": "^8.
|
|
58
|
-
"@storybook/addon-essentials": "^8.
|
|
59
|
-
"@storybook/addon-interactions": "^8.
|
|
60
|
-
"@storybook/addon-links": "^8.
|
|
61
|
-
"@storybook/blocks": "^8.
|
|
62
|
-
"@storybook/manager-api": "^8.
|
|
63
|
-
"@storybook/test": "^8.
|
|
64
|
-
"@storybook/test-runner": "^0.21.
|
|
65
|
-
"@storybook/theming": "^8.
|
|
66
|
-
"@storybook/vue3": "^8.
|
|
67
|
-
"@storybook/vue3-vite": "^8.
|
|
68
|
-
"@tanstack/vue-virtual": "3.13.
|
|
57
|
+
"@storybook/addon-a11y": "^8.6.0",
|
|
58
|
+
"@storybook/addon-actions": "^8.6.0",
|
|
59
|
+
"@storybook/addon-essentials": "^8.6.0",
|
|
60
|
+
"@storybook/addon-interactions": "^8.6.0",
|
|
61
|
+
"@storybook/addon-links": "^8.6.0",
|
|
62
|
+
"@storybook/blocks": "^8.6.0",
|
|
63
|
+
"@storybook/manager-api": "^8.6.0",
|
|
64
|
+
"@storybook/test": "^8.6.0",
|
|
65
|
+
"@storybook/test-runner": "^0.21.3",
|
|
66
|
+
"@storybook/theming": "^8.6.0",
|
|
67
|
+
"@storybook/vue3": "^8.6.0",
|
|
68
|
+
"@storybook/vue3-vite": "^8.6.0",
|
|
69
|
+
"@tanstack/vue-virtual": "3.13.2",
|
|
69
70
|
"@types/jsdom": "^21.1.7",
|
|
70
71
|
"@types/lodash-es": "^4.17.12",
|
|
71
|
-
"@types/node": "^22.13.
|
|
72
|
+
"@types/node": "^22.13.5",
|
|
72
73
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
73
|
-
"@vitest/coverage-v8": "^3.0.
|
|
74
|
+
"@vitest/coverage-v8": "^3.0.7",
|
|
74
75
|
"@vue/compiler-sfc": "3.5.13",
|
|
75
76
|
"@vue/test-utils": "^2.4.6",
|
|
76
77
|
"@vuepic/vue-datepicker": "11.0.1",
|
|
77
78
|
"autoprefixer": "^10.4.20",
|
|
78
79
|
"dayjs": "1.11.13",
|
|
79
|
-
"eslint": "^9.
|
|
80
|
+
"eslint": "^9.21.0",
|
|
80
81
|
"eslint-plugin-storybook": "^0.11.3",
|
|
81
82
|
"floating-vue": "5.2.2",
|
|
82
83
|
"glob": "^11.0.1",
|
|
@@ -86,24 +87,24 @@
|
|
|
86
87
|
"lint-staged": "^15.4.3",
|
|
87
88
|
"lodash-es": "4.17.21",
|
|
88
89
|
"make-coverage-badge": "^1.2.0",
|
|
89
|
-
"postcss": "^8.5.
|
|
90
|
-
"prettier": "^3.5.
|
|
90
|
+
"postcss": "^8.5.3",
|
|
91
|
+
"prettier": "^3.5.2",
|
|
91
92
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
92
93
|
"resolve-tspaths": "^0.8.23",
|
|
93
94
|
"rimraf": "^6.0.1",
|
|
94
|
-
"sass": "^1.85.
|
|
95
|
+
"sass": "^1.85.1",
|
|
95
96
|
"semantic-release": "^24.2.3",
|
|
96
|
-
"storybook": "^8.
|
|
97
|
+
"storybook": "^8.6.0",
|
|
97
98
|
"svgo": "^3.3.2",
|
|
98
99
|
"tailwindcss": "^3.4.17",
|
|
99
100
|
"typescript": "5.7.3",
|
|
100
|
-
"vite": "^6.
|
|
101
|
-
"vitest": "^3.0.
|
|
101
|
+
"vite": "^6.2.0",
|
|
102
|
+
"vitest": "^3.0.7",
|
|
102
103
|
"vue": "3.5.13",
|
|
103
104
|
"vue-currency-input": "3.2.1",
|
|
104
105
|
"vue-router": "4.5.0",
|
|
105
106
|
"vue-toastification": "2.0.0-rc.5",
|
|
106
|
-
"vue-tsc": "2.2.
|
|
107
|
+
"vue-tsc": "2.2.4"
|
|
107
108
|
},
|
|
108
109
|
"dependencies": {
|
|
109
110
|
"tailwind-variants": "^0.3.1"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import PBtn from '@squirrel/components/p-btn/p-btn.vue';
|
|
2
2
|
import { sanitizeUrl } from '@squirrel/utils/sanitization';
|
|
3
3
|
import { createWrapperFor } from '@tests/vitest.helpers';
|
|
4
|
+
import { describe } from 'vitest';
|
|
4
5
|
|
|
5
6
|
vi.mock('@squirrel/utils/sanitization', () => {
|
|
6
7
|
return {
|
|
@@ -27,215 +28,282 @@ const DEFAULT_CLASSES_ARRAY = [
|
|
|
27
28
|
];
|
|
28
29
|
|
|
29
30
|
describe('PBtn.vue', () => {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
describe('default button', () => {
|
|
32
|
+
Object.keys(ELEMENTS_MAP).forEach((el) => {
|
|
33
|
+
const to = ELEMENTS_MAP[el];
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
[
|
|
41
|
-
'secondary-outline',
|
|
35
|
+
it.each([
|
|
36
|
+
['primary', ['text-surface', 'bg-primary', 'hover:bg-accent', 'active:bg-p-blue-80']],
|
|
37
|
+
['secondary', ['bg-p-gray-20', 'hover:bg-p-gray-30', 'active:bg-p-gray-40']],
|
|
38
|
+
[
|
|
39
|
+
'primary-outline',
|
|
40
|
+
['text-p-purple-60', 'bg-p-blue-10', 'ring-1', 'ring-inset', 'ring-p-purple-60', 'hover:bg-p-gray-20'],
|
|
41
|
+
],
|
|
42
42
|
[
|
|
43
|
-
'
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
'secondary-outline',
|
|
44
|
+
[
|
|
45
|
+
'text-p-purple-60',
|
|
46
|
+
'bg-surface',
|
|
47
|
+
'ring-1',
|
|
48
|
+
'ring-inset',
|
|
49
|
+
'ring-p-gray-30',
|
|
50
|
+
'hover:bg-p-blue-10',
|
|
51
|
+
'aria-selected:bg-p-blue-10',
|
|
52
|
+
],
|
|
50
53
|
],
|
|
51
|
-
],
|
|
52
|
-
[
|
|
53
|
-
'secondary-outline-blue',
|
|
54
54
|
[
|
|
55
|
-
'
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
55
|
+
'secondary-outline-blue',
|
|
56
|
+
[
|
|
57
|
+
'text-p-purple-60',
|
|
58
|
+
'bg-surface',
|
|
59
|
+
'ring-1',
|
|
60
|
+
'ring-inset',
|
|
61
|
+
'ring-p-gray-30',
|
|
62
|
+
'hover:bg-p-blue-10',
|
|
63
|
+
'aria-selected:bg-p-blue-15',
|
|
64
|
+
'aria-selected:text-p-blue-60',
|
|
65
|
+
],
|
|
63
66
|
],
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
['error', ['text-white', 'bg-p-red-40', 'hover:bg-p-red-50']],
|
|
68
|
+
['success', ['text-white', 'bg-p-green-40', 'hover:bg-p-green-50']],
|
|
69
|
+
['primary-link', ['text-primary', 'bg-transparent', 'hover:text-accent', 'underline']],
|
|
70
|
+
['secondary-ghost', ['text-on-surface', 'hover:bg-p-gray-20']],
|
|
71
|
+
])(`renders a ${el} of type %s`, async (type, classes) => {
|
|
72
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
73
|
+
props: { type },
|
|
74
|
+
attrs: { to },
|
|
75
|
+
global: {
|
|
76
|
+
stubs: { RouterLink: { template: '<section class="router-link-stub"><slot /></section>' } },
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const element = wrapper.find(el);
|
|
81
|
+
|
|
82
|
+
if (el !== 'a') {
|
|
83
|
+
const slotWrapper = wrapper.find('.slot-wrapper');
|
|
84
|
+
expect(slotWrapper.classes()).toEqual(['slot-wrapper', 'empty:hidden']);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
expect(classes.every((c) => element.classes().includes(c))).toBe(true);
|
|
88
|
+
expect(DEFAULT_CLASSES_ARRAY.every((c) => element.classes().includes(c))).toBe(true);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it.each([
|
|
93
|
+
['sm', ['flex', 'items-center', 'justify-center', 'has-[.slot-wrapper:empty]:gap-0', 'gap-1']],
|
|
94
|
+
['md', ['flex', 'items-center', 'justify-center', 'has-[.slot-wrapper:empty]:gap-0', 'gap-2']],
|
|
95
|
+
['lg', ['flex', 'items-center', 'justify-center', 'has-[.slot-wrapper:empty]:gap-0', 'gap-2.5']],
|
|
96
|
+
])('renders slots for content', async (size, classes) => {
|
|
70
97
|
const wrapper = createWrapperFor(PBtn, {
|
|
71
|
-
props: {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
stubs: { RouterLink: { template: '<section class="router-link-stub"><slot /></section>' } },
|
|
98
|
+
props: { size },
|
|
99
|
+
slots: {
|
|
100
|
+
default: `This is a button`,
|
|
75
101
|
},
|
|
76
102
|
});
|
|
77
103
|
|
|
78
|
-
const
|
|
104
|
+
const contentWrapper = await wrapper.find('div');
|
|
105
|
+
const button = await wrapper.find('button');
|
|
79
106
|
|
|
80
|
-
expect(
|
|
81
|
-
expect(
|
|
107
|
+
expect(contentWrapper.classes()).toEqual(classes);
|
|
108
|
+
expect(button.text()).toContain(`This is a button`);
|
|
82
109
|
});
|
|
83
|
-
});
|
|
84
110
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
111
|
+
it.each([
|
|
112
|
+
['button', undefined],
|
|
113
|
+
['a', 'https://pequity.com/'],
|
|
114
|
+
['a', { name: 'home', params: { id: 1 } }],
|
|
115
|
+
])('gets disabled when the element is a %s and points to %s', async (el, to) => {
|
|
116
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
117
|
+
props: {
|
|
118
|
+
to,
|
|
119
|
+
},
|
|
120
|
+
attrs: {
|
|
121
|
+
disabled: true,
|
|
122
|
+
},
|
|
123
|
+
global: {
|
|
124
|
+
stubs: { RouterLink: { template: '<a class="router-link-stub"><slot /></a>' } },
|
|
125
|
+
},
|
|
126
|
+
});
|
|
91
127
|
|
|
92
|
-
|
|
128
|
+
const button = await wrapper.find(el);
|
|
93
129
|
|
|
94
|
-
|
|
95
|
-
});
|
|
130
|
+
await button.trigger('click');
|
|
96
131
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const wrapper = createWrapperFor(PBtn, {
|
|
103
|
-
props: {
|
|
104
|
-
to,
|
|
105
|
-
},
|
|
106
|
-
attrs: {
|
|
107
|
-
disabled: true,
|
|
108
|
-
},
|
|
109
|
-
global: {
|
|
110
|
-
stubs: { RouterLink: { template: '<a class="router-link-stub"><slot /></a>' } },
|
|
111
|
-
},
|
|
112
|
-
});
|
|
132
|
+
if (el === 'button') {
|
|
133
|
+
expect(wrapper.emitted().click).toBeFalsy();
|
|
134
|
+
}
|
|
135
|
+
expect(button.attributes()).toHaveProperty('disabled');
|
|
136
|
+
expect(button.attributes()['aria-disabled']).toBe('true');
|
|
113
137
|
|
|
114
|
-
|
|
138
|
+
await wrapper.setProps({ disabled: false });
|
|
115
139
|
|
|
116
|
-
|
|
140
|
+
await button.trigger('click');
|
|
117
141
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
142
|
+
if (el === 'button') {
|
|
143
|
+
expect(wrapper.emitted().click[0][0] instanceof MouseEvent).toBe(true);
|
|
144
|
+
}
|
|
145
|
+
expect(button.attributes()).not.toHaveProperty('disabled');
|
|
146
|
+
expect(button.attributes()['aria-disabled']).toBe('false');
|
|
147
|
+
});
|
|
123
148
|
|
|
124
|
-
|
|
149
|
+
it('has a loading state', async () => {
|
|
150
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
151
|
+
props: {
|
|
152
|
+
loading: true,
|
|
153
|
+
},
|
|
154
|
+
global: {
|
|
155
|
+
stubs: { PRingLoader: { template: '<div class="loader-stub">loader</div>' } },
|
|
156
|
+
},
|
|
157
|
+
});
|
|
125
158
|
|
|
126
|
-
|
|
159
|
+
const button = await wrapper.find('button');
|
|
160
|
+
const loader = await wrapper.find('.loader-stub');
|
|
127
161
|
|
|
128
|
-
|
|
129
|
-
expect(wrapper.emitted().click[0][0] instanceof MouseEvent).toBe(true);
|
|
130
|
-
}
|
|
131
|
-
expect(button.attributes()).not.toHaveProperty('disabled');
|
|
132
|
-
expect(button.attributes()['aria-disabled']).toBe('false');
|
|
133
|
-
});
|
|
162
|
+
await button.trigger('click');
|
|
134
163
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
loading: true,
|
|
139
|
-
},
|
|
140
|
-
global: {
|
|
141
|
-
stubs: { PRingLoader: { template: '<div class="loader-stub">loader</div>' } },
|
|
142
|
-
},
|
|
164
|
+
expect(wrapper.emitted().click).toBeFalsy();
|
|
165
|
+
expect(button.attributes()).toHaveProperty('disabled');
|
|
166
|
+
expect(loader.exists()).toBe(true);
|
|
143
167
|
});
|
|
144
168
|
|
|
145
|
-
|
|
146
|
-
|
|
169
|
+
it.each(['button', 'submit', 'reset'])('renders a button of native type %s', async (nativeType) => {
|
|
170
|
+
const wrapper = createWrapperFor(PBtn, { props: { nativeType } });
|
|
147
171
|
|
|
148
|
-
|
|
172
|
+
const button = await wrapper.find('button');
|
|
149
173
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
expect(loader.exists()).toBe(true);
|
|
153
|
-
});
|
|
174
|
+
expect(button.attributes().type).toBe(nativeType);
|
|
175
|
+
});
|
|
154
176
|
|
|
155
|
-
|
|
156
|
-
|
|
177
|
+
it.each([
|
|
178
|
+
['sm', ['py-1.5', 'px-3', 'rounded', 'font-medium', 'text-sm', 'leading-5']],
|
|
179
|
+
['md', ['py-2', 'px-6', 'rounded', 'font-medium', 'text-base']],
|
|
180
|
+
['lg', ['py-3', 'px-6', 'rounded', 'font-medium', 'text-lg']],
|
|
181
|
+
])('renders a button of size %s', async (size, classes) => {
|
|
182
|
+
const wrapper = createWrapperFor(PBtn, { props: { size }, slots: { default: `button` } });
|
|
157
183
|
|
|
158
|
-
|
|
184
|
+
const button = await wrapper.find('button');
|
|
159
185
|
|
|
160
|
-
|
|
161
|
-
|
|
186
|
+
expect(classes.every((c) => button.classes().includes(c))).toBe(true);
|
|
187
|
+
});
|
|
162
188
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
189
|
+
it('renders an href in case it is an external link', async () => {
|
|
190
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
191
|
+
props: {
|
|
192
|
+
to: 'https://pequity.com/',
|
|
193
|
+
},
|
|
194
|
+
slots: {
|
|
195
|
+
default: `This is a button`,
|
|
196
|
+
},
|
|
197
|
+
});
|
|
169
198
|
|
|
170
|
-
|
|
199
|
+
const a = await wrapper.find('a');
|
|
171
200
|
|
|
172
|
-
|
|
173
|
-
|
|
201
|
+
expect(a.attributes().href).toBe(`sanitized-https://pequity.com/`);
|
|
202
|
+
expect(a.attributes().target).toBe('_blank');
|
|
203
|
+
expect(a.text()).toBe('This is a button');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
it('renders a router link', async () => {
|
|
207
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
208
|
+
props: {
|
|
209
|
+
to: { name: 'home', params: { id: 1 } },
|
|
210
|
+
},
|
|
211
|
+
slots: {
|
|
212
|
+
default: `This is a button`,
|
|
213
|
+
},
|
|
214
|
+
global: {
|
|
215
|
+
stubs: { RouterLink: { template: '<section class="router-link-stub"><slot /></section>' } },
|
|
216
|
+
},
|
|
217
|
+
});
|
|
174
218
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
},
|
|
180
|
-
slots: {
|
|
181
|
-
default: `This is a button`,
|
|
182
|
-
},
|
|
219
|
+
const routerLink = await wrapper.find('section');
|
|
220
|
+
|
|
221
|
+
expect(routerLink.classes()).toContain('router-link-stub');
|
|
222
|
+
expect(routerLink.text()).toBe('This is a button');
|
|
183
223
|
});
|
|
184
224
|
|
|
185
|
-
|
|
225
|
+
it('sets the aria-selected attribute when the selected prop is set', async () => {
|
|
226
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
227
|
+
props: {
|
|
228
|
+
selected: true,
|
|
229
|
+
},
|
|
230
|
+
slots: {
|
|
231
|
+
default: `This is a button`,
|
|
232
|
+
},
|
|
233
|
+
});
|
|
186
234
|
|
|
187
|
-
|
|
188
|
-
expect(a.attributes().target).toBe('_blank');
|
|
189
|
-
expect(a.text()).toBe('This is a button');
|
|
190
|
-
});
|
|
235
|
+
const button = await wrapper.find('button');
|
|
191
236
|
|
|
192
|
-
|
|
193
|
-
const wrapper = createWrapperFor(PBtn, {
|
|
194
|
-
props: {
|
|
195
|
-
to: { name: 'home', params: { id: 1 } },
|
|
196
|
-
},
|
|
197
|
-
slots: {
|
|
198
|
-
default: `This is a button`,
|
|
199
|
-
},
|
|
200
|
-
global: {
|
|
201
|
-
stubs: { RouterLink: { template: '<section class="router-link-stub"><slot /></section>' } },
|
|
202
|
-
},
|
|
237
|
+
expect(button.attributes()['aria-selected']).toBe('true');
|
|
203
238
|
});
|
|
204
239
|
|
|
205
|
-
|
|
240
|
+
it('sanitizes an invalid link', async () => {
|
|
241
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
242
|
+
props: {
|
|
243
|
+
to: 'javascript:evil()',
|
|
244
|
+
},
|
|
245
|
+
slots: {
|
|
246
|
+
default: `This is a button`,
|
|
247
|
+
},
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
const a = await wrapper.find('a');
|
|
206
251
|
|
|
207
|
-
|
|
208
|
-
|
|
252
|
+
expect(a.text()).toBe('This is a button');
|
|
253
|
+
expect(sanitizeUrl).toHaveBeenCalledTimes(1);
|
|
254
|
+
});
|
|
209
255
|
});
|
|
210
256
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
257
|
+
describe('icon button', () => {
|
|
258
|
+
it.each([
|
|
259
|
+
['sm', ['shrink-0', 'text-[20px]']],
|
|
260
|
+
['md', ['shrink-0', 'text-xl']],
|
|
261
|
+
['lg', ['shrink-0', 'text-2xl']],
|
|
262
|
+
])('renders a button with icon of size %s', async (size, classes) => {
|
|
263
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
264
|
+
props: { size, icon: 'edit' },
|
|
265
|
+
slots: { default: 'text' },
|
|
266
|
+
global: { stubs: { PIcon: true } },
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
const icon = await wrapper.findComponent({ name: 'PIcon' });
|
|
270
|
+
|
|
271
|
+
console.log(icon.classes());
|
|
272
|
+
|
|
273
|
+
expect(classes.every((c) => icon.classes().includes(c))).toBe(true);
|
|
219
274
|
});
|
|
220
275
|
|
|
221
|
-
|
|
276
|
+
it.each([
|
|
277
|
+
['sm', ['shrink-0', 'text-[20px]']],
|
|
278
|
+
['md', ['shrink-0', 'text-xl']],
|
|
279
|
+
['lg', ['shrink-0', 'text-2xl']],
|
|
280
|
+
])('renders a button with a right icon of size %s', async (size, classes) => {
|
|
281
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
282
|
+
props: { size, iconRight: 'edit' },
|
|
283
|
+
slots: { default: 'text' },
|
|
284
|
+
global: { stubs: { PIcon: true } },
|
|
285
|
+
});
|
|
222
286
|
|
|
223
|
-
|
|
224
|
-
});
|
|
287
|
+
const icon = await wrapper.findComponent({ name: 'PIcon' });
|
|
225
288
|
|
|
226
|
-
|
|
227
|
-
const wrapper = createWrapperFor(PBtn, {
|
|
228
|
-
props: {
|
|
229
|
-
to: 'javascript:evil()',
|
|
230
|
-
},
|
|
231
|
-
slots: {
|
|
232
|
-
default: `This is a button`,
|
|
233
|
-
},
|
|
289
|
+
expect(classes.every((c) => icon.classes().includes(c))).toBe(true);
|
|
234
290
|
});
|
|
235
291
|
|
|
236
|
-
|
|
292
|
+
it.each([
|
|
293
|
+
['sm', ['shrink-0', 'text-[20px]'], ['has-[.slot-wrapper:empty]:px-1.5']],
|
|
294
|
+
['md', ['shrink-0', 'text-xl'], ['has-[.slot-wrapper:empty]:px-2.5']],
|
|
295
|
+
['lg', ['shrink-0', 'text-2xl'], ['has-[.slot-wrapper:empty]:px-3']],
|
|
296
|
+
])('renders a button with an icon without text of size %s', async (size, classes, buttonClasses) => {
|
|
297
|
+
const wrapper = createWrapperFor(PBtn, {
|
|
298
|
+
props: { size, icon: 'edit' },
|
|
299
|
+
global: { stubs: { PIcon: true } },
|
|
300
|
+
});
|
|
237
301
|
|
|
238
|
-
|
|
239
|
-
|
|
302
|
+
const button = wrapper.find('button');
|
|
303
|
+
const icon = wrapper.findComponent({ name: 'PIcon' });
|
|
304
|
+
|
|
305
|
+
expect(classes.every((c) => icon.classes().includes(c))).toBe(true);
|
|
306
|
+
expect(buttonClasses.every((c) => button.classes().includes(c))).toBe(true);
|
|
307
|
+
});
|
|
240
308
|
});
|
|
241
309
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import Icon from '@squirrel/assets/info-circle-icon.svg?inline';
|
|
2
1
|
import PBtn from '@squirrel/components/p-btn/p-btn.vue';
|
|
3
2
|
import { action } from '@storybook/addon-actions';
|
|
4
3
|
import { expect, within } from '@storybook/test';
|
|
@@ -101,19 +100,44 @@ export const PrimaryLink = {
|
|
|
101
100
|
},
|
|
102
101
|
};
|
|
103
102
|
|
|
104
|
-
export const
|
|
103
|
+
export const Icon = {
|
|
105
104
|
render: (args) => ({
|
|
106
|
-
components: { PBtn
|
|
105
|
+
components: { PBtn },
|
|
107
106
|
setup() {
|
|
108
107
|
return { args };
|
|
109
108
|
},
|
|
110
|
-
template: `
|
|
111
|
-
<PBtn v-bind="args">
|
|
112
|
-
<Icon class="my-1" />
|
|
113
|
-
</PBtn>`,
|
|
109
|
+
template: ` <PBtn v-bind="args" icon="archive">Icon Button</PBtn> `,
|
|
114
110
|
}),
|
|
115
111
|
args: {
|
|
116
|
-
size: '
|
|
112
|
+
size: 'md',
|
|
113
|
+
type: 'secondary-outline',
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
export const IconRight = {
|
|
118
|
+
render: (args) => ({
|
|
119
|
+
components: { PBtn },
|
|
120
|
+
setup() {
|
|
121
|
+
return { args };
|
|
122
|
+
},
|
|
123
|
+
template: ` <PBtn v-bind="args" icon-right="archive">Icon Button</PBtn> `,
|
|
124
|
+
}),
|
|
125
|
+
args: {
|
|
126
|
+
size: 'md',
|
|
127
|
+
type: 'secondary-outline',
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const IconWithoutContent = {
|
|
132
|
+
render: (args) => ({
|
|
133
|
+
components: { PBtn },
|
|
134
|
+
setup() {
|
|
135
|
+
return { args };
|
|
136
|
+
},
|
|
137
|
+
template: ` <PBtn v-bind="args" icon-right="archive"></PBtn> `,
|
|
138
|
+
}),
|
|
139
|
+
args: {
|
|
140
|
+
size: 'md',
|
|
117
141
|
type: 'secondary-outline',
|
|
118
142
|
},
|
|
119
143
|
};
|