@pequity/squirrel 6.0.8 → 6.0.10
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-dropdown-select.js +4 -1
- package/dist/cjs/chunks/p-icon.js +24 -4
- package/dist/cjs/chunks/p-ring-loader.js +12 -65
- package/dist/cjs/p-btn.js +13 -21
- package/dist/cjs/p-loading.js +38 -4
- package/dist/es/chunks/p-action-bar.js +1 -1
- package/dist/es/chunks/p-card.js +1 -1
- package/dist/es/chunks/p-date-picker.js +1 -1
- package/dist/es/chunks/p-dropdown-select.js +5 -2
- package/dist/es/chunks/p-icon.js +25 -5
- package/dist/es/chunks/p-inline-date-picker.js +1 -1
- package/dist/es/chunks/p-input-percent.js +1 -1
- package/dist/es/chunks/p-link.js +1 -1
- package/dist/es/chunks/p-pagination-info.js +1 -1
- package/dist/es/chunks/p-pagination.js +1 -1
- package/dist/es/chunks/p-ring-loader.js +13 -66
- package/dist/es/chunks/p-select-btn.js +1 -1
- package/dist/es/chunks/p-select.js +1 -1
- package/dist/es/chunks/p-table-loader.js +1 -1
- package/dist/es/chunks/p-tabs.js +1 -1
- package/dist/es/index.js +1 -1
- package/dist/es/inputClassesMixin.js +1 -1
- package/dist/es/listKeyboardNavigation.js +1 -1
- package/dist/es/p-alert.js +1 -1
- package/dist/es/p-avatar.js +1 -1
- package/dist/es/p-btn.js +14 -22
- package/dist/es/p-checkbox.js +1 -1
- package/dist/es/p-chips.js +1 -1
- package/dist/es/p-close-btn.js +1 -1
- package/dist/es/p-drawer.js +1 -1
- package/dist/es/p-dropdown.js +1 -1
- package/dist/es/p-info-icon.js +1 -1
- package/dist/es/p-input-number.js +1 -1
- package/dist/es/p-input-search.js +1 -1
- package/dist/es/p-input.js +1 -1
- package/dist/es/p-loading.js +39 -5
- package/dist/es/p-modal.js +1 -1
- package/dist/es/p-progress-bar.js +1 -1
- package/dist/es/p-select-pill.js +1 -1
- package/dist/es/p-skeleton-loader.js +1 -1
- package/dist/es/p-table-filter-icon.js +1 -1
- package/dist/es/p-table-header-cell.js +1 -1
- package/dist/es/p-table-td.js +1 -1
- package/dist/es/p-textarea.js +1 -1
- package/dist/es/p-toggle.js +1 -1
- package/dist/es/useSelectList.js +1 -1
- package/dist/squirrel/components/p-alert/p-alert.vue.d.ts +1 -1
- package/dist/squirrel/components/p-btn/p-btn.vue.d.ts +10 -37
- package/dist/squirrel/components/p-date-picker/p-date-picker.vue.d.ts +1 -1
- package/dist/squirrel/components/p-drawer/p-drawer.vue.d.ts +7 -7
- package/dist/squirrel/components/p-inline-date-picker/p-inline-date-picker.vue.d.ts +1 -1
- package/dist/squirrel/components/p-modal/p-modal.vue.d.ts +1 -1
- package/dist/squirrel/components/p-ring-loader/p-ring-loader.vue.d.ts +6 -31
- package/dist/squirrel/components/p-table/p-table.vue.d.ts +2 -2
- package/dist/squirrel/components/p-table-header-cell/p-table-header-cell.vue.d.ts +1 -1
- package/dist/squirrel.css +6 -6
- package/package.json +28 -28
- package/squirrel/assets/p-loading-spinner.svg +9 -0
- package/squirrel/components/p-btn/p-btn.vue +12 -21
- package/squirrel/components/p-dropdown-select/p-dropdown-select.spec.js +36 -0
- package/squirrel/components/p-dropdown-select/p-dropdown-select.vue +8 -2
- package/squirrel/components/p-loading/p-loading.vue +4 -3
- package/squirrel/components/p-ring-loader/p-ring-loader.spec.js +14 -34
- package/squirrel/components/p-ring-loader/p-ring-loader.stories.js +0 -6
- package/squirrel/components/p-ring-loader/p-ring-loader.vue +13 -56
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pequity/squirrel",
|
|
3
3
|
"description": "Squirrel component library",
|
|
4
|
-
"version": "6.0.
|
|
5
|
-
"packageManager": "pnpm@9.15.
|
|
4
|
+
"version": "6.0.10",
|
|
5
|
+
"packageManager": "pnpm@9.15.5",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"preinstall": "npx only-allow pnpm",
|
|
@@ -47,58 +47,58 @@
|
|
|
47
47
|
"vue-toastification": "^2.0.0-rc.5"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@commitlint/cli": "^19.
|
|
51
|
-
"@commitlint/config-conventional": "^19.
|
|
52
|
-
"@pequity/eslint-config": "^1.0
|
|
53
|
-
"@playwright/test": "^1.
|
|
50
|
+
"@commitlint/cli": "^19.7.1",
|
|
51
|
+
"@commitlint/config-conventional": "^19.7.1",
|
|
52
|
+
"@pequity/eslint-config": "^1.1.0",
|
|
53
|
+
"@playwright/test": "^1.50.1",
|
|
54
54
|
"@semantic-release/changelog": "^6.0.3",
|
|
55
55
|
"@semantic-release/git": "^10.0.1",
|
|
56
|
-
"@storybook/addon-a11y": "^8.5.
|
|
57
|
-
"@storybook/addon-actions": "^8.5.
|
|
58
|
-
"@storybook/addon-essentials": "^8.5.
|
|
59
|
-
"@storybook/addon-interactions": "^8.5.
|
|
60
|
-
"@storybook/addon-links": "^8.5.
|
|
61
|
-
"@storybook/blocks": "^8.5.
|
|
62
|
-
"@storybook/manager-api": "^8.5.
|
|
63
|
-
"@storybook/test": "^8.5.
|
|
56
|
+
"@storybook/addon-a11y": "^8.5.3",
|
|
57
|
+
"@storybook/addon-actions": "^8.5.3",
|
|
58
|
+
"@storybook/addon-essentials": "^8.5.3",
|
|
59
|
+
"@storybook/addon-interactions": "^8.5.3",
|
|
60
|
+
"@storybook/addon-links": "^8.5.3",
|
|
61
|
+
"@storybook/blocks": "^8.5.3",
|
|
62
|
+
"@storybook/manager-api": "^8.5.3",
|
|
63
|
+
"@storybook/test": "^8.5.3",
|
|
64
64
|
"@storybook/test-runner": "^0.21.0",
|
|
65
|
-
"@storybook/theming": "^8.5.
|
|
66
|
-
"@storybook/vue3": "^8.5.
|
|
67
|
-
"@storybook/vue3-vite": "^8.5.
|
|
68
|
-
"@tanstack/vue-virtual": "3.
|
|
65
|
+
"@storybook/theming": "^8.5.3",
|
|
66
|
+
"@storybook/vue3": "^8.5.3",
|
|
67
|
+
"@storybook/vue3-vite": "^8.5.3",
|
|
68
|
+
"@tanstack/vue-virtual": "3.13.0",
|
|
69
69
|
"@types/jsdom": "^21.1.7",
|
|
70
70
|
"@types/lodash-es": "^4.17.12",
|
|
71
|
-
"@types/node": "^22.
|
|
71
|
+
"@types/node": "^22.13.1",
|
|
72
72
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
73
|
-
"@vitest/coverage-v8": "^3.0.
|
|
73
|
+
"@vitest/coverage-v8": "^3.0.5",
|
|
74
74
|
"@vue/compiler-sfc": "3.5.13",
|
|
75
75
|
"@vue/test-utils": "^2.4.6",
|
|
76
76
|
"@vuepic/vue-datepicker": "11.0.1",
|
|
77
77
|
"autoprefixer": "^10.4.20",
|
|
78
78
|
"dayjs": "1.11.13",
|
|
79
|
-
"eslint": "^9.
|
|
79
|
+
"eslint": "^9.20.0",
|
|
80
80
|
"eslint-plugin-storybook": "^0.11.2",
|
|
81
81
|
"floating-vue": "5.2.2",
|
|
82
82
|
"glob": "^11.0.1",
|
|
83
83
|
"husky": "^9.1.7",
|
|
84
84
|
"iconify-icon": "^2.3.0",
|
|
85
85
|
"jsdom": "^26.0.0",
|
|
86
|
-
"lint-staged": "^15.4.
|
|
86
|
+
"lint-staged": "^15.4.3",
|
|
87
87
|
"lodash-es": "4.17.21",
|
|
88
88
|
"make-coverage-badge": "^1.2.0",
|
|
89
89
|
"postcss": "^8.5.1",
|
|
90
90
|
"prettier": "^3.4.2",
|
|
91
|
-
"prettier-plugin-tailwindcss": "^0.6.
|
|
91
|
+
"prettier-plugin-tailwindcss": "^0.6.11",
|
|
92
92
|
"resolve-tspaths": "^0.8.23",
|
|
93
93
|
"rimraf": "^6.0.1",
|
|
94
|
-
"sass": "^1.
|
|
95
|
-
"semantic-release": "^24.2.
|
|
96
|
-
"storybook": "^8.5.
|
|
94
|
+
"sass": "^1.84.0",
|
|
95
|
+
"semantic-release": "^24.2.2",
|
|
96
|
+
"storybook": "^8.5.3",
|
|
97
97
|
"svgo": "^3.3.2",
|
|
98
98
|
"tailwindcss": "^3.4.17",
|
|
99
99
|
"typescript": "5.7.3",
|
|
100
|
-
"vite": "^6.0
|
|
101
|
-
"vitest": "^3.0.
|
|
100
|
+
"vite": "^6.1.0",
|
|
101
|
+
"vitest": "^3.0.5",
|
|
102
102
|
"vue": "3.5.13",
|
|
103
103
|
"vue-currency-input": "3.2.1",
|
|
104
104
|
"vue-router": "4.5.0",
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="19" height="19" viewBox="0 0 24 24">
|
|
2
|
+
<path fill="currentColor" d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
|
|
3
|
+
opacity="0.25" />
|
|
4
|
+
<path fill="currentColor"
|
|
5
|
+
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z">
|
|
6
|
+
<animateTransform attributeName="transform" dur="0.75s" repeatCount="indefinite" type="rotate"
|
|
7
|
+
values="0 12 12;360 12 12" />
|
|
8
|
+
</path>
|
|
9
|
+
</svg>
|
|
@@ -24,10 +24,9 @@
|
|
|
24
24
|
<div :class="{ invisible: loading }"><slot></slot></div>
|
|
25
25
|
<PRingLoader
|
|
26
26
|
v-if="loading"
|
|
27
|
-
:style="loaderStyle"
|
|
28
27
|
:color="loaderColor"
|
|
29
28
|
:size="loaderSize"
|
|
30
|
-
class="left-0 right-0 top-0
|
|
29
|
+
class="absolute bottom-0 left-0 right-0 top-0 flex items-center justify-center"
|
|
31
30
|
/>
|
|
32
31
|
</Component>
|
|
33
32
|
</template>
|
|
@@ -37,7 +36,6 @@ import { type Size } from '@squirrel/components/p-btn/p-btn.types';
|
|
|
37
36
|
import PRingLoader from '@squirrel/components/p-ring-loader/p-ring-loader.vue';
|
|
38
37
|
import { isExternalLink } from '@squirrel/utils/link';
|
|
39
38
|
import { sanitizeUrl } from '@squirrel/utils/sanitization';
|
|
40
|
-
import { type Color, getColorDeep } from '@squirrel/utils/tailwind';
|
|
41
39
|
import { defineComponent, type PropType } from 'vue';
|
|
42
40
|
import { type RouteLocationRaw, RouterLink } from 'vue-router';
|
|
43
41
|
|
|
@@ -94,16 +92,16 @@ const LOADER_SIZES = {
|
|
|
94
92
|
} as const satisfies { [key in Size]: number };
|
|
95
93
|
|
|
96
94
|
const LOADER_COLORS = {
|
|
97
|
-
[BUTTON_TYPES.PRIMARY]: 'p-blue-15',
|
|
98
|
-
[BUTTON_TYPES.SECONDARY]: 'p-purple-60',
|
|
99
|
-
[BUTTON_TYPES.PRIMARY_OUTLINE]: 'p-blue-60',
|
|
100
|
-
[BUTTON_TYPES.SECONDARY_OUTLINE]: 'p-purple-60',
|
|
101
|
-
[BUTTON_TYPES.SECONDARY_OUTLINE_BLUE]: 'p-purple-60',
|
|
102
|
-
[BUTTON_TYPES.ERROR]: 'p-blue-15',
|
|
103
|
-
[BUTTON_TYPES.SUCCESS]: 'p-blue-15',
|
|
104
|
-
[BUTTON_TYPES.PRIMARY_LINK]: 'p-blue-60',
|
|
105
|
-
[BUTTON_TYPES.SECONDARY_GHOST]: 'p-purple-60',
|
|
106
|
-
[BUTTON_TYPES.SECONDARY_GHOST_DARK]: 'p-blue-15',
|
|
95
|
+
[BUTTON_TYPES.PRIMARY]: 'var(--color-p-blue-15)',
|
|
96
|
+
[BUTTON_TYPES.SECONDARY]: 'var(--color-p-purple-60)',
|
|
97
|
+
[BUTTON_TYPES.PRIMARY_OUTLINE]: 'var(--color-p-blue-60)',
|
|
98
|
+
[BUTTON_TYPES.SECONDARY_OUTLINE]: 'var(--color-p-purple-60)',
|
|
99
|
+
[BUTTON_TYPES.SECONDARY_OUTLINE_BLUE]: 'var(--color-p-purple-60)',
|
|
100
|
+
[BUTTON_TYPES.ERROR]: 'var(--color-p-blue-15)',
|
|
101
|
+
[BUTTON_TYPES.SUCCESS]: 'var(--color-p-blue-15)',
|
|
102
|
+
[BUTTON_TYPES.PRIMARY_LINK]: 'var(--color-p-blue-60)',
|
|
103
|
+
[BUTTON_TYPES.SECONDARY_GHOST]: 'var(--color-p-purple-60)',
|
|
104
|
+
[BUTTON_TYPES.SECONDARY_GHOST_DARK]: 'var(--color-p-blue-15)',
|
|
107
105
|
} as const;
|
|
108
106
|
|
|
109
107
|
export default defineComponent({
|
|
@@ -167,11 +165,6 @@ export default defineComponent({
|
|
|
167
165
|
default: '',
|
|
168
166
|
},
|
|
169
167
|
},
|
|
170
|
-
data() {
|
|
171
|
-
return {
|
|
172
|
-
loaderStyle: { position: 'absolute' },
|
|
173
|
-
};
|
|
174
|
-
},
|
|
175
168
|
computed: {
|
|
176
169
|
classes() {
|
|
177
170
|
return `${DEFAULT_CLASSES} ${BUTTON_SIZES[this.size]} ${BUTTON_CLASSES[this.type]}`;
|
|
@@ -180,9 +173,7 @@ export default defineComponent({
|
|
|
180
173
|
return Number(`${LOADER_SIZES[this.size]}`);
|
|
181
174
|
},
|
|
182
175
|
loaderColor() {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
return getColorDeep(type);
|
|
176
|
+
return LOADER_COLORS[this.type];
|
|
186
177
|
},
|
|
187
178
|
},
|
|
188
179
|
methods: {
|
|
@@ -193,6 +193,42 @@ describe('PDropdownSelect.vue', () => {
|
|
|
193
193
|
|
|
194
194
|
expect(selectedItems.length).toBe(selectedItemsOptions.length);
|
|
195
195
|
expect(wrapper.vm.$data.selected.length).toBe(items.length);
|
|
196
|
+
expect(wrapper.find('button').text()).toBe('All options selected');
|
|
197
|
+
|
|
198
|
+
cleanup(wrapper);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('shows "All options selected" when all selectable options and disabled-selected options are selected', async () => {
|
|
202
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(10));
|
|
203
|
+
|
|
204
|
+
const items = cloneDeep(filterListItems).slice(0, 10);
|
|
205
|
+
items[0].disabled = true;
|
|
206
|
+
items[1].disabled = true;
|
|
207
|
+
// Pre-select one disabled item
|
|
208
|
+
const wrapper = createWrapper({ selected: [1], items }, { multiple: true });
|
|
209
|
+
|
|
210
|
+
await wrapper.find('button').trigger('click');
|
|
211
|
+
await wrapper.findByText('Select all').trigger('click');
|
|
212
|
+
|
|
213
|
+
const selectedItemsOptions = wrapper.findAll('[p-select-list-option-item]');
|
|
214
|
+
const selectedItems = wrapper.findAll('[p-select-list-option-item].selected');
|
|
215
|
+
|
|
216
|
+
// Should have all non-disabled items (8) plus the pre-selected disabled item (1)
|
|
217
|
+
expect(selectedItems.length).toBe(selectedItemsOptions.length - 1);
|
|
218
|
+
expect(wrapper.vm.$data.selected.length).toBe(items.length - 1);
|
|
219
|
+
expect(wrapper.find('button').text()).toBe('All options selected');
|
|
220
|
+
|
|
221
|
+
cleanup(wrapper);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it('shows number of selected options when not all non-disabled options are selected', async () => {
|
|
225
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(10));
|
|
226
|
+
|
|
227
|
+
const items = cloneDeep(filterListItems).slice(0, 10);
|
|
228
|
+
items[0].disabled = true;
|
|
229
|
+
const wrapper = createWrapper({ selected: [2, 3], items }, { multiple: true });
|
|
230
|
+
|
|
231
|
+
expect(wrapper.find('button').text()).toBe('2 options selected');
|
|
196
232
|
|
|
197
233
|
cleanup(wrapper);
|
|
198
234
|
});
|
|
@@ -32,8 +32,10 @@
|
|
|
32
32
|
<slot v-else name="selected-item" :item="multiple ? selectedItems : selectedItems[0]">
|
|
33
33
|
<div class="truncate text-left">
|
|
34
34
|
{{
|
|
35
|
-
multiple
|
|
36
|
-
?
|
|
35
|
+
multiple
|
|
36
|
+
? selectedItems.length === selectableItemsCount
|
|
37
|
+
? 'All options selected'
|
|
38
|
+
: `${selectedItems.length} option${selectedItems.length > 1 ? 's' : ''} selected`
|
|
37
39
|
: selectedItems[0][itemText]
|
|
38
40
|
}}
|
|
39
41
|
</div>
|
|
@@ -419,6 +421,10 @@ const attrs = computed(() => {
|
|
|
419
421
|
|
|
420
422
|
const style = computed(() => $attrs.style as StyleValue);
|
|
421
423
|
|
|
424
|
+
const selectableItemsCount = computed(
|
|
425
|
+
() => internalItems.value.filter((item) => !isDisabled(item) || isSelected(item[props.itemValue])).length
|
|
426
|
+
);
|
|
427
|
+
|
|
422
428
|
// Watch
|
|
423
429
|
// Sorts internalItems putting the selected ones first
|
|
424
430
|
watch(
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
>
|
|
14
14
|
<Transition enter-from-class="opacity-0" enter-active-class="transition duration-500">
|
|
15
15
|
<Component :is="content" v-if="isComponent(content)" v-bind="componentProps" />
|
|
16
|
-
<div v-else :class="textDivClass"
|
|
16
|
+
<div v-else :class="textDivClass"><PLoadingSpinner class="pt-0.5" /> {{ content }}</div>
|
|
17
17
|
</Transition>
|
|
18
18
|
</div>
|
|
19
19
|
</div>
|
|
@@ -21,18 +21,19 @@
|
|
|
21
21
|
<div v-if="content" class="invisible fixed">
|
|
22
22
|
<div ref="dimsReference">
|
|
23
23
|
<Component :is="content" v-if="isComponent(content)" v-bind="componentProps" />
|
|
24
|
-
<div v-else :class="textDivClass"
|
|
24
|
+
<div v-else :class="textDivClass"><PLoadingSpinner class="pt-0.5" /> {{ content }}</div>
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
27
27
|
</Teleport>
|
|
28
28
|
</template>
|
|
29
29
|
|
|
30
30
|
<script setup lang="ts">
|
|
31
|
+
import PLoadingSpinner from '@squirrel/assets//p-loading-spinner.svg?inline';
|
|
31
32
|
import { usePLoading } from '@squirrel/components/p-loading/usePLoading';
|
|
32
33
|
import { isComponent } from '@squirrel/utils/component';
|
|
33
34
|
import { onBeforeUnmount, ref, toValue, watch } from 'vue';
|
|
34
35
|
|
|
35
|
-
const textDivClass = `overflow-hidden whitespace-nowrap px-
|
|
36
|
+
const textDivClass = `flex h-8 justify-center gap-x-1.5 overflow-hidden whitespace-nowrap px-6 pt-1 text-sm font-semibold text-p-purple-60`;
|
|
36
37
|
|
|
37
38
|
defineOptions({
|
|
38
39
|
name: 'PLoading',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import PRingLoader from '@squirrel/components/p-ring-loader/p-ring-loader.vue';
|
|
2
|
+
import { expect } from '@storybook/test';
|
|
2
3
|
import { createWrapperFor } from '@tests/vitest.helpers';
|
|
3
4
|
|
|
4
5
|
describe('PRingLoader.vue', () => {
|
|
@@ -9,35 +10,19 @@ describe('PRingLoader.vue', () => {
|
|
|
9
10
|
color: '#ccc',
|
|
10
11
|
duration: '1s',
|
|
11
12
|
},
|
|
13
|
+
global: { stubs: { PIcon: true } },
|
|
12
14
|
});
|
|
13
15
|
|
|
14
|
-
const loader =
|
|
15
|
-
|
|
16
|
-
const innerDivs = await loader.findAll('div');
|
|
17
|
-
|
|
18
|
-
innerDivs.forEach((innerDiv, i) => {
|
|
19
|
-
expect(innerDiv.attributes().style).toContain(
|
|
20
|
-
'border-width: 7px; border-color: #ccc transparent transparent transparent; animation-duration: 1s; animation-timing-function: cubic-bezier(0.5, 0, 0.5, 1);'
|
|
21
|
-
);
|
|
22
|
-
if (i === 0) {
|
|
23
|
-
expect(innerDiv.attributes().style).toContain('animation-delay: -0.375s;');
|
|
24
|
-
}
|
|
25
|
-
if (i === 1) {
|
|
26
|
-
expect(innerDiv.attributes().style).toContain('animation-delay: -0.25s;');
|
|
27
|
-
}
|
|
28
|
-
if (i === 2) {
|
|
29
|
-
expect(innerDiv.attributes().style).toContain('animation-delay: -0.125s;');
|
|
30
|
-
}
|
|
31
|
-
if (i === 3) {
|
|
32
|
-
expect(innerDiv.attributes().style).not.toContain('animation-delay');
|
|
33
|
-
}
|
|
34
|
-
expect(innerDiv.attributes().class).toBe(
|
|
35
|
-
'block animate-spin absolute box-border rounded-full w-4/5 h-4/5 m-[10%]'
|
|
36
|
-
);
|
|
37
|
-
});
|
|
16
|
+
const loader = wrapper.findComponent({ name: 'PIcon' });
|
|
38
17
|
|
|
39
18
|
expect(loader.exists()).toBe(true);
|
|
40
|
-
expect(
|
|
19
|
+
expect(loader.props()).toEqual({ icon: 'svg-spinners:90-ring-with-bg' });
|
|
20
|
+
expect(loader.attributes()).toEqual({
|
|
21
|
+
duration: '1s',
|
|
22
|
+
icon: 'svg-spinners:90-ring-with-bg',
|
|
23
|
+
style: 'color: rgb(204, 204, 204);',
|
|
24
|
+
width: '62.44',
|
|
25
|
+
});
|
|
41
26
|
});
|
|
42
27
|
|
|
43
28
|
it('changes the color dynamically', async () => {
|
|
@@ -45,20 +30,15 @@ describe('PRingLoader.vue', () => {
|
|
|
45
30
|
props: {
|
|
46
31
|
color: '#ccc',
|
|
47
32
|
},
|
|
33
|
+
global: { stubs: { PIcon: true } },
|
|
48
34
|
});
|
|
49
35
|
|
|
50
|
-
const loader =
|
|
36
|
+
const loader = wrapper.findComponent({ name: 'PIcon' });
|
|
51
37
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
innerDivs.forEach((innerDiv, i) => {
|
|
55
|
-
expect(innerDiv.element.style['border-color']).toBe('#ccc transparent transparent transparent');
|
|
56
|
-
});
|
|
38
|
+
expect(loader.attributes().style).toBe('color: rgb(204, 204, 204);');
|
|
57
39
|
|
|
58
40
|
await wrapper.setProps({ color: '#ddd' });
|
|
59
41
|
|
|
60
|
-
|
|
61
|
-
expect(innerDiv.element.style['border-color']).toBe('#ddd transparent transparent transparent');
|
|
62
|
-
});
|
|
42
|
+
expect(loader.attributes().style).toBe('color: rgb(221, 221, 221);');
|
|
63
43
|
});
|
|
64
44
|
});
|
|
@@ -13,12 +13,7 @@ export default {
|
|
|
13
13
|
control: { type: 'color' },
|
|
14
14
|
description: 'color of the loader',
|
|
15
15
|
},
|
|
16
|
-
duration: {
|
|
17
|
-
control: { type: 'text' },
|
|
18
|
-
description: 'duration of the animation in seconds e.g. 1.2s, 2s',
|
|
19
|
-
},
|
|
20
16
|
},
|
|
21
|
-
|
|
22
17
|
parameters: {
|
|
23
18
|
docs: {
|
|
24
19
|
description: {
|
|
@@ -39,6 +34,5 @@ export const Default = {
|
|
|
39
34
|
args: {
|
|
40
35
|
size: 100,
|
|
41
36
|
color: '#333393',
|
|
42
|
-
duration: '1.8s',
|
|
43
37
|
},
|
|
44
38
|
};
|
|
@@ -1,71 +1,28 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<div :class="INNER_DIV_CLASS" :style="[spinnerStyle, animDiv1]"></div>
|
|
4
|
-
<div :class="INNER_DIV_CLASS" :style="[spinnerStyle, animDiv2]"></div>
|
|
5
|
-
<div :class="INNER_DIV_CLASS" :style="[spinnerStyle, animDiv3]"></div>
|
|
6
|
-
<div :class="INNER_DIV_CLASS" :style="[spinnerStyle]"></div>
|
|
7
|
-
</div>
|
|
2
|
+
<PIcon icon="svg-spinners:90-ring-with-bg" :width="spinnerSize" :style="style" />
|
|
8
3
|
</template>
|
|
9
4
|
|
|
10
5
|
<script setup lang="ts">
|
|
11
|
-
import
|
|
6
|
+
import PIcon from '@squirrel/components/p-icon/p-icon.vue';
|
|
12
7
|
import { computed } from 'vue';
|
|
13
8
|
|
|
14
|
-
const calcPropertyValue = (propName: string, originalValue: string, modificator: number) => {
|
|
15
|
-
const computedStyle: Record<string, string> = {};
|
|
16
|
-
const timeQuantityOuter = originalValue.match(/^\d*\.?\d+/)?.[0];
|
|
17
|
-
const timeUnit = originalValue.match(/s|(ms)$/)?.[0] || 's';
|
|
18
|
-
const timeQuantityInner = Math.round(Number(timeQuantityOuter) * 1000 * modificator) / 1000;
|
|
19
|
-
|
|
20
|
-
computedStyle[propName] = timeQuantityInner + timeUnit;
|
|
21
|
-
|
|
22
|
-
return computedStyle;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
const INNER_DIV_CLASS = 'block animate-spin absolute box-border rounded-full w-4/5 h-4/5 m-[10%]';
|
|
26
|
-
|
|
27
9
|
defineOptions({
|
|
28
10
|
name: 'PRingLoader',
|
|
29
11
|
});
|
|
30
12
|
|
|
31
|
-
|
|
32
|
-
size
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
},
|
|
36
|
-
color: {
|
|
37
|
-
type: String,
|
|
38
|
-
default: getColor('primary' as Color),
|
|
39
|
-
},
|
|
40
|
-
duration: {
|
|
41
|
-
type: String,
|
|
42
|
-
default: '1.2s',
|
|
43
|
-
validator(value: string) {
|
|
44
|
-
const res = /^\d*\.?\d+(s|ms)$/;
|
|
45
|
-
|
|
46
|
-
return res.test(value);
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
const spinnerStyle = computed(() => {
|
|
52
|
-
return {
|
|
53
|
-
borderWidth: `${props.size * 0.1}px`,
|
|
54
|
-
borderColor: `${props.color} transparent transparent transparent`,
|
|
55
|
-
animationDuration: props.duration,
|
|
56
|
-
animationTimingFunction: 'cubic-bezier(0.5, 0, 0.5, 1)',
|
|
57
|
-
};
|
|
58
|
-
});
|
|
13
|
+
type Props = {
|
|
14
|
+
size?: number;
|
|
15
|
+
color?: string;
|
|
16
|
+
};
|
|
59
17
|
|
|
60
|
-
const
|
|
61
|
-
|
|
18
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
19
|
+
size: 80,
|
|
20
|
+
color: 'var(--color-p-blue-60)',
|
|
62
21
|
});
|
|
63
22
|
|
|
64
|
-
const
|
|
65
|
-
return calcPropertyValue('animationDelay', props.duration, -0.25);
|
|
66
|
-
});
|
|
23
|
+
const spinnerSize = computed(() => props.size * 0.892);
|
|
67
24
|
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
});
|
|
25
|
+
const style = computed(() => ({
|
|
26
|
+
color: props.color,
|
|
27
|
+
}));
|
|
71
28
|
</script>
|