@pequity/squirrel 6.0.6 → 6.0.7
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 +2 -2
- package/dist/cjs/chunks/p-dropdown-select.js +1 -1
- package/dist/cjs/useSelectList.js +10 -5
- package/dist/es/chunks/p-dropdown-select.js +1 -1
- package/dist/es/useSelectList.js +10 -5
- package/package.json +24 -24
- package/squirrel/components/p-dropdown-select/p-dropdown-select.spec.js +47 -0
- package/squirrel/components/p-dropdown-select/p-dropdown-select.vue +2 -2
- package/squirrel/components/p-select-list/useSelectList.ts +12 -8
package/README.md
CHANGED
|
@@ -76,7 +76,7 @@ Import and use the components you need in your Vue 3 project:
|
|
|
76
76
|
</template>
|
|
77
77
|
|
|
78
78
|
<script setup lang="ts">
|
|
79
|
-
import { PBtn
|
|
79
|
+
import { PBtn } from '@pequity/squirrel';
|
|
80
80
|
</script>
|
|
81
81
|
```
|
|
82
82
|
|
|
@@ -111,7 +111,7 @@ Then, in your consumer project's `.env.local` file, add an `VUE_APP_SQUIRREL_LOC
|
|
|
111
111
|
|
|
112
112
|
Finally, in your project's `vite.config` file, add the following:
|
|
113
113
|
|
|
114
|
-
> Heads up! The `vite.config.
|
|
114
|
+
> Heads up! The `vite.config.ts` file of the `pequity/frontendv2` already includes the following configuration.
|
|
115
115
|
|
|
116
116
|
```js
|
|
117
117
|
import { defineConfig, searchForWorkspaceRoot } from 'vite';
|
|
@@ -420,7 +420,7 @@ const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
|
420
420
|
}, () => [
|
|
421
421
|
vue.createElementVNode("div", _hoisted_3, vue.toDisplayString(__props.multiple && vue.unref(selectedItems).length > 1 ? `${vue.unref(selectedItems).length} option${vue.unref(selectedItems).length > 1 ? "s" : ""} selected` : vue.unref(selectedItems)[0][__props.itemText]), 1)
|
|
422
422
|
]),
|
|
423
|
-
__props.clearable && vue.unref(
|
|
423
|
+
__props.clearable && vue.unref(selectedItems).length ? (vue.openBlock(), vue.createElementBlock("button", {
|
|
424
424
|
key: 2,
|
|
425
425
|
class: vue.normalizeClass(["absolute top-1/2 flex -translate-y-1/2 items-center justify-center text-p-gray-40 hover:text-p-gray-60", [vue.unref(pSelectList.SIZES)[__props.size], CLEAR_BUTTON_SPACING[__props.size]]]),
|
|
426
426
|
"aria-label": "Clear selection",
|
|
@@ -217,12 +217,17 @@ const useSelectList = (props, inputSearch, virtualizerRef, emit) => {
|
|
|
217
217
|
emit("update:modelValue", toArrOfObjIfNeeded(toEmit));
|
|
218
218
|
};
|
|
219
219
|
const clearAll = () => {
|
|
220
|
-
if (!props.multiple) return;
|
|
221
220
|
search.value = "";
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
221
|
+
if (props.multiple) {
|
|
222
|
+
const disabledItemsValues = internalItems.value.filter((item) => isDisabled(item)).map((item) => item[props.itemValue]);
|
|
223
|
+
const selectedItemsValues = internalValue.value;
|
|
224
|
+
const selectedDisabledItems = lodashEs.intersection(disabledItemsValues, selectedItemsValues);
|
|
225
|
+
emit("update:modelValue", toArrOfObjIfNeeded(selectedDisabledItems));
|
|
226
|
+
} else {
|
|
227
|
+
if (!isDisabled(selectedItems.value[0])) {
|
|
228
|
+
emit("update:modelValue", null);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
226
231
|
};
|
|
227
232
|
vue.watch(
|
|
228
233
|
() => props.items,
|
|
@@ -419,7 +419,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
419
419
|
}, () => [
|
|
420
420
|
createElementVNode("div", _hoisted_3, toDisplayString(__props.multiple && unref(selectedItems).length > 1 ? `${unref(selectedItems).length} option${unref(selectedItems).length > 1 ? "s" : ""} selected` : unref(selectedItems)[0][__props.itemText]), 1)
|
|
421
421
|
]),
|
|
422
|
-
__props.clearable && unref(
|
|
422
|
+
__props.clearable && unref(selectedItems).length ? (openBlock(), createElementBlock("button", {
|
|
423
423
|
key: 2,
|
|
424
424
|
class: normalizeClass(["absolute top-1/2 flex -translate-y-1/2 items-center justify-center text-p-gray-40 hover:text-p-gray-60", [unref(SIZES)[__props.size], CLEAR_BUTTON_SPACING[__props.size]]]),
|
|
425
425
|
"aria-label": "Clear selection",
|
package/dist/es/useSelectList.js
CHANGED
|
@@ -215,12 +215,17 @@ const useSelectList = (props, inputSearch, virtualizerRef, emit) => {
|
|
|
215
215
|
emit("update:modelValue", toArrOfObjIfNeeded(toEmit));
|
|
216
216
|
};
|
|
217
217
|
const clearAll = () => {
|
|
218
|
-
if (!props.multiple) return;
|
|
219
218
|
search.value = "";
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
219
|
+
if (props.multiple) {
|
|
220
|
+
const disabledItemsValues = internalItems.value.filter((item) => isDisabled(item)).map((item) => item[props.itemValue]);
|
|
221
|
+
const selectedItemsValues = internalValue.value;
|
|
222
|
+
const selectedDisabledItems = intersection(disabledItemsValues, selectedItemsValues);
|
|
223
|
+
emit("update:modelValue", toArrOfObjIfNeeded(selectedDisabledItems));
|
|
224
|
+
} else {
|
|
225
|
+
if (!isDisabled(selectedItems.value[0])) {
|
|
226
|
+
emit("update:modelValue", null);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
224
229
|
};
|
|
225
230
|
watch(
|
|
226
231
|
() => props.items,
|
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.7",
|
|
5
|
+
"packageManager": "pnpm@9.15.4",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"preinstall": "npx only-allow pnpm",
|
|
@@ -53,54 +53,54 @@
|
|
|
53
53
|
"@playwright/test": "^1.49.1",
|
|
54
54
|
"@semantic-release/changelog": "^6.0.3",
|
|
55
55
|
"@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.
|
|
56
|
+
"@storybook/addon-a11y": "^8.5.0",
|
|
57
|
+
"@storybook/addon-actions": "^8.5.0",
|
|
58
|
+
"@storybook/addon-essentials": "^8.5.0",
|
|
59
|
+
"@storybook/addon-interactions": "^8.5.0",
|
|
60
|
+
"@storybook/addon-links": "^8.5.0",
|
|
61
|
+
"@storybook/blocks": "^8.5.0",
|
|
62
|
+
"@storybook/manager-api": "^8.5.0",
|
|
63
|
+
"@storybook/test": "^8.5.0",
|
|
64
64
|
"@storybook/test-runner": "^0.21.0",
|
|
65
|
-
"@storybook/theming": "^8.
|
|
66
|
-
"@storybook/vue3": "^8.
|
|
67
|
-
"@storybook/vue3-vite": "^8.
|
|
65
|
+
"@storybook/theming": "^8.5.0",
|
|
66
|
+
"@storybook/vue3": "^8.5.0",
|
|
67
|
+
"@storybook/vue3-vite": "^8.5.0",
|
|
68
68
|
"@tanstack/vue-virtual": "3.11.2",
|
|
69
69
|
"@types/jsdom": "^21.1.7",
|
|
70
70
|
"@types/lodash-es": "^4.17.12",
|
|
71
|
-
"@types/node": "^22.10.
|
|
71
|
+
"@types/node": "^22.10.7",
|
|
72
72
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
73
|
-
"@vitest/coverage-v8": "^
|
|
73
|
+
"@vitest/coverage-v8": "^3.0.3",
|
|
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.18.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.
|
|
86
|
+
"lint-staged": "^15.4.1",
|
|
87
87
|
"lodash-es": "4.17.21",
|
|
88
88
|
"make-coverage-badge": "^1.2.0",
|
|
89
|
-
"postcss": "^8.
|
|
89
|
+
"postcss": "^8.5.1",
|
|
90
90
|
"prettier": "^3.4.2",
|
|
91
|
-
"prettier-plugin-tailwindcss": "^0.6.
|
|
91
|
+
"prettier-plugin-tailwindcss": "^0.6.10",
|
|
92
92
|
"resolve-tspaths": "^0.8.23",
|
|
93
93
|
"rimraf": "^6.0.1",
|
|
94
|
-
"sass": "^1.83.
|
|
94
|
+
"sass": "^1.83.4",
|
|
95
95
|
"semantic-release": "^24.2.1",
|
|
96
|
-
"storybook": "^8.
|
|
96
|
+
"storybook": "^8.5.0",
|
|
97
97
|
"svgo": "^3.3.2",
|
|
98
98
|
"tailwindcss": "^3.4.17",
|
|
99
99
|
"typescript": "5.7.3",
|
|
100
|
-
"vite": "^6.0.
|
|
101
|
-
"vitest": "^
|
|
100
|
+
"vite": "^6.0.11",
|
|
101
|
+
"vitest": "^3.0.3",
|
|
102
102
|
"vue": "3.5.13",
|
|
103
|
-
"vue-currency-input": "3.1
|
|
103
|
+
"vue-currency-input": "3.2.1",
|
|
104
104
|
"vue-router": "4.5.0",
|
|
105
105
|
"vue-toastification": "2.0.0-rc.5",
|
|
106
106
|
"vue-tsc": "2.2.0"
|
|
@@ -653,6 +653,17 @@ describe('PDropdownSelect.vue', () => {
|
|
|
653
653
|
cleanup(wrapper);
|
|
654
654
|
});
|
|
655
655
|
|
|
656
|
+
it('does not render clear button when there is no value selected', async () => {
|
|
657
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
658
|
+
|
|
659
|
+
const wrapper = createWrapper({ selected: null }, { clearable: true });
|
|
660
|
+
|
|
661
|
+
const clearButton = wrapper.find('button[aria-label="Clear selection"]');
|
|
662
|
+
expect(clearButton.exists()).toBe(false);
|
|
663
|
+
|
|
664
|
+
cleanup(wrapper);
|
|
665
|
+
});
|
|
666
|
+
|
|
656
667
|
it('clears multiple selections when clearable is true', async () => {
|
|
657
668
|
useVirtualizer.mockImplementation(() => createMockedVirtualizer(20));
|
|
658
669
|
|
|
@@ -666,4 +677,40 @@ describe('PDropdownSelect.vue', () => {
|
|
|
666
677
|
|
|
667
678
|
cleanup(wrapper);
|
|
668
679
|
});
|
|
680
|
+
|
|
681
|
+
it('clears a single selection select when clearable is true', async () => {
|
|
682
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(10));
|
|
683
|
+
|
|
684
|
+
const items = cloneDeep(filterListItems).slice(0, 10);
|
|
685
|
+
items[0].disabled = false;
|
|
686
|
+
const wrapper = createWrapper({ selected: 1, items }, { multiple: false, clearable: true });
|
|
687
|
+
|
|
688
|
+
expect(wrapper.vm.$data.selected).toEqual(1);
|
|
689
|
+
|
|
690
|
+
const clearButton = wrapper.find('button[aria-label="Clear selection"]');
|
|
691
|
+
expect(clearButton.exists()).toBe(true);
|
|
692
|
+
|
|
693
|
+
await clearButton.trigger('click');
|
|
694
|
+
expect(wrapper.vm.$data.selected).toEqual(null);
|
|
695
|
+
|
|
696
|
+
cleanup(wrapper);
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
it('does not clear a single selection select when the item is disabled', async () => {
|
|
700
|
+
useVirtualizer.mockImplementation(() => createMockedVirtualizer(10));
|
|
701
|
+
|
|
702
|
+
const items = cloneDeep(filterListItems).slice(0, 10);
|
|
703
|
+
items[0].disabled = true;
|
|
704
|
+
const wrapper = createWrapper({ selected: 1, items }, { multiple: false, clearable: true });
|
|
705
|
+
|
|
706
|
+
expect(wrapper.vm.$data.selected).toEqual(1);
|
|
707
|
+
|
|
708
|
+
const clearButton = wrapper.find('button[aria-label="Clear selection"]');
|
|
709
|
+
expect(clearButton.exists()).toBe(true);
|
|
710
|
+
|
|
711
|
+
await clearButton.trigger('click');
|
|
712
|
+
expect(wrapper.vm.$data.selected).toEqual(1);
|
|
713
|
+
|
|
714
|
+
cleanup(wrapper);
|
|
715
|
+
});
|
|
669
716
|
});
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
}}
|
|
39
39
|
</div>
|
|
40
40
|
</slot>
|
|
41
|
-
<!--
|
|
41
|
+
<!-- Clear selection button -->
|
|
42
42
|
<button
|
|
43
|
-
v-if="clearable &&
|
|
43
|
+
v-if="clearable && selectedItems.length"
|
|
44
44
|
class="absolute top-1/2 flex -translate-y-1/2 items-center justify-center text-p-gray-40 hover:text-p-gray-60"
|
|
45
45
|
:class="[SIZES[size], CLEAR_BUTTON_SPACING[size]]"
|
|
46
46
|
aria-label="Clear selection"
|
|
@@ -299,20 +299,24 @@ export const useSelectList = (props: Props, inputSearch: InputSearch, virtualize
|
|
|
299
299
|
};
|
|
300
300
|
|
|
301
301
|
const clearAll = () => {
|
|
302
|
-
if (!props.multiple) return;
|
|
303
|
-
|
|
304
302
|
search.value = '';
|
|
305
303
|
|
|
306
304
|
// We cannot clear disabled items that are selected
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
305
|
+
if (props.multiple) {
|
|
306
|
+
const disabledItemsValues = internalItems.value
|
|
307
|
+
.filter((item) => isDisabled(item))
|
|
308
|
+
.map((item) => item[props.itemValue]);
|
|
310
309
|
|
|
311
|
-
|
|
310
|
+
const selectedItemsValues = internalValue.value;
|
|
312
311
|
|
|
313
|
-
|
|
312
|
+
const selectedDisabledItems = intersection(disabledItemsValues, selectedItemsValues);
|
|
314
313
|
|
|
315
|
-
|
|
314
|
+
emit('update:modelValue', toArrOfObjIfNeeded(selectedDisabledItems));
|
|
315
|
+
} else {
|
|
316
|
+
if (!isDisabled(selectedItems.value[0])) {
|
|
317
|
+
emit('update:modelValue', null);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
316
320
|
};
|
|
317
321
|
|
|
318
322
|
// Watch
|