mirror of
https://github.com/directus/directus.git
synced 2026-04-25 03:00:53 -04:00
Enable search in v-select for string items (#19736)
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
This commit is contained in:
5
.changeset/chatty-cheetahs-begin.md
Normal file
5
.changeset/chatty-cheetahs-begin.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@directus/app": patch
|
||||
---
|
||||
|
||||
Enabled search in `v-select` component for string items
|
||||
@@ -1,3 +1,169 @@
|
||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||
|
||||
exports[`Mount component 1`] = `"<v-menu-stub data-v-cdcb6889=\\"\\" class=\\"v-select\\" disabled=\\"false\\" attached=\\"true\\" is-same-width=\\"true\\" show-arrow=\\"false\\" close-on-content-click=\\"true\\" placement=\\"bottom\\"></v-menu-stub>"`;
|
||||
exports[`should hide items not matching search value > object items 1`] = `
|
||||
"<div data-v-cdcb6889=\\"\\" id=\\"v-menu-stub\\" class=\\"v-select\\" disabled=\\"false\\" attached=\\"true\\" is-same-width=\\"true\\" show-arrow=\\"false\\" close-on-content-click=\\"true\\" placement=\\"bottom\\">
|
||||
<div data-v-cdcb6889=\\"\\" id=\\"v-input-stub\\" full-width=\\"true\\" readonly=\\"\\" clickable=\\"\\" disabled=\\"false\\"></div>
|
||||
<ul data-v-ff20e609=\\"\\" data-v-cdcb6889=\\"\\" class=\\"v-list list\\">
|
||||
<!--v-if-->
|
||||
<div data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\">
|
||||
<div data-v-cdcb6889=\\"\\" id=\\"v-list-item-content-stub\\">
|
||||
<div data-v-cdcb6889=\\"\\" id=\\"v-input-stub\\" autofocus=\\"\\" small=\\"\\" placeholder=\\"search\\" modelvalue=\\"Item 1\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item1\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 1</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item2\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 2</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item3\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 3</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item4\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 4</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item5\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 5</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item6\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 6</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item7\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 7</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item8\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 8</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item9\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 9</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item10\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 10</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item11\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 11</span></div>
|
||||
</div>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</ul>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`should hide items not matching search value > string items 1`] = `
|
||||
"<div data-v-cdcb6889=\\"\\" id=\\"v-menu-stub\\" class=\\"v-select\\" disabled=\\"false\\" attached=\\"true\\" is-same-width=\\"true\\" show-arrow=\\"false\\" close-on-content-click=\\"true\\" placement=\\"bottom\\">
|
||||
<div data-v-cdcb6889=\\"\\" id=\\"v-input-stub\\" full-width=\\"true\\" readonly=\\"\\" clickable=\\"\\" disabled=\\"false\\"></div>
|
||||
<ul data-v-ff20e609=\\"\\" data-v-cdcb6889=\\"\\" class=\\"v-list list\\">
|
||||
<!--v-if-->
|
||||
<div data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\">
|
||||
<div data-v-cdcb6889=\\"\\" id=\\"v-list-item-content-stub\\">
|
||||
<div data-v-cdcb6889=\\"\\" id=\\"v-input-stub\\" autofocus=\\"\\" small=\\"\\" placeholder=\\"search\\" modelvalue=\\"Item 1\\"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 1\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 1</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 2\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 2</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 3\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 3</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 4\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 4</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 5\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 5</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 6\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 6</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 7\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 7</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 8\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 8</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 9\\" style=\\"display: none;\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 9</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 10\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 10</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 11\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 11</span></div>
|
||||
</div>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</ul>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`should render with object items 1`] = `
|
||||
"<div data-v-cdcb6889=\\"\\" id=\\"v-menu-stub\\" class=\\"v-select\\" disabled=\\"false\\" attached=\\"true\\" is-same-width=\\"true\\" show-arrow=\\"false\\" close-on-content-click=\\"true\\" placement=\\"bottom\\">
|
||||
<v-input-stub data-v-cdcb6889=\\"\\" full-width=\\"true\\" readonly=\\"\\" clickable=\\"\\" disabled=\\"false\\"></v-input-stub>
|
||||
<ul data-v-ff20e609=\\"\\" data-v-cdcb6889=\\"\\" class=\\"v-list list\\">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item1\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 1</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item2\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 2</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"item3\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 3</span></div>
|
||||
</div>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</ul>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
exports[`should render with string items 1`] = `
|
||||
"<div data-v-cdcb6889=\\"\\" id=\\"v-menu-stub\\" class=\\"v-select\\" disabled=\\"false\\" attached=\\"true\\" is-same-width=\\"true\\" show-arrow=\\"false\\" close-on-content-click=\\"true\\" placement=\\"bottom\\">
|
||||
<v-input-stub data-v-cdcb6889=\\"\\" full-width=\\"true\\" readonly=\\"\\" clickable=\\"\\" disabled=\\"false\\"></v-input-stub>
|
||||
<ul data-v-ff20e609=\\"\\" data-v-cdcb6889=\\"\\" class=\\"v-list list\\">
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 1\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 1</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 2\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 2</span></div>
|
||||
</div>
|
||||
<div data-v-e8b3360c=\\"\\" data-v-cdcb6889=\\"\\" data-v-ff20e609-s=\\"\\" id=\\"v-list-item-stub\\" active=\\"false\\" clickable=\\"\\" value=\\"Item 3\\">
|
||||
<!--v-if-->
|
||||
<div data-v-e8b3360c=\\"\\" id=\\"v-list-item-content-stub\\"><span data-v-e8b3360c=\\"\\" class=\\"item-text\\">Item 3</span></div>
|
||||
</div>
|
||||
<!--v-if-->
|
||||
<!--v-if-->
|
||||
</ul>
|
||||
</div>"
|
||||
`;
|
||||
|
||||
@@ -1,47 +1,79 @@
|
||||
import { test, expect } from 'vitest';
|
||||
import { mount } from '@vue/test-utils';
|
||||
|
||||
import VSelect from './v-select.vue';
|
||||
import { GlobalMountOptions } from '@vue/test-utils/dist/types';
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import { Focus } from '@/__utils__/focus';
|
||||
import { mount } from '@vue/test-utils';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import VList from '../v-list.vue';
|
||||
import VSelect from './v-select.vue';
|
||||
|
||||
const i18n = createI18n({ legacy: false });
|
||||
const i18n = createI18n({
|
||||
legacy: false,
|
||||
messages: {
|
||||
'en-US': {
|
||||
search: 'search',
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const global: GlobalMountOptions = {
|
||||
stubs: [
|
||||
'v-list',
|
||||
'v-list-item',
|
||||
'v-list-item-icon',
|
||||
'v-list-item-content',
|
||||
'v-divider',
|
||||
'v-checkbox',
|
||||
'v-menu',
|
||||
'v-icon',
|
||||
'v-input',
|
||||
],
|
||||
const VMenu = {
|
||||
template: `
|
||||
<div id="v-menu-stub">
|
||||
<slot name="activator" />
|
||||
<slot
|
||||
v-bind="{
|
||||
active: true,
|
||||
}"
|
||||
/>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
const VInput = {
|
||||
template: `<div id="v-input-stub" />`,
|
||||
setup(_props: any, { emit }: any) {
|
||||
emit('update:modelValue', 'Item 1');
|
||||
},
|
||||
};
|
||||
|
||||
const VListItem = {
|
||||
template: `
|
||||
<div id="v-list-item-stub">
|
||||
<slot />
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
const VListItemContent = {
|
||||
template: `
|
||||
<div id="v-list-item-content-stub">
|
||||
<slot />
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
|
||||
const global = {
|
||||
stubs: {
|
||||
'v-menu': VMenu,
|
||||
'v-input': true,
|
||||
'v-list': VList,
|
||||
'v-list-item': VListItem,
|
||||
'v-list-item-content': VListItemContent,
|
||||
'v-list-item-icon': true,
|
||||
'v-divider': true,
|
||||
'v-checkbox': true,
|
||||
'v-icon': true,
|
||||
},
|
||||
plugins: [i18n],
|
||||
directives: {
|
||||
Focus,
|
||||
},
|
||||
};
|
||||
|
||||
const items = [
|
||||
{
|
||||
text: 'Item 1',
|
||||
value: 'item1',
|
||||
},
|
||||
{
|
||||
text: 'Item 2',
|
||||
value: 'item2',
|
||||
},
|
||||
{
|
||||
text: 'Item 3',
|
||||
value: 'item3',
|
||||
},
|
||||
];
|
||||
test('should render with object items', () => {
|
||||
const items = Array.from({ length: 3 }, (_, index) => {
|
||||
const number = index + 1;
|
||||
return { text: `Item ${number}`, value: `item${number}` };
|
||||
});
|
||||
|
||||
test('Mount component', () => {
|
||||
expect(VSelect).toBeTruthy();
|
||||
|
||||
const wrapper = mount(VSelect, {
|
||||
@@ -53,3 +85,48 @@ test('Mount component', () => {
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('should render with string items', () => {
|
||||
const items = Array.from({ length: 3 }, (_, index) => `Item ${index + 1}`);
|
||||
|
||||
expect(VSelect).toBeTruthy();
|
||||
|
||||
const wrapper = mount(VSelect, {
|
||||
props: {
|
||||
items,
|
||||
},
|
||||
global,
|
||||
});
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
describe('should hide items not matching search value', () => {
|
||||
// There have to be >10 items to enable search
|
||||
|
||||
const objectItems = Array.from({ length: 11 }, (_, index) => {
|
||||
const number = index + 1;
|
||||
return { text: `Item ${number}`, value: `item${number}` };
|
||||
});
|
||||
|
||||
const stringItems = Array.from({ length: 11 }, (_, index) => `Item ${index + 1}`);
|
||||
|
||||
test.each([
|
||||
['object items', objectItems],
|
||||
['string items', stringItems],
|
||||
])('%s', async (_, items) => {
|
||||
expect(VSelect).toBeTruthy();
|
||||
|
||||
const wrapper = mount(VSelect, {
|
||||
props: {
|
||||
items,
|
||||
},
|
||||
global: { ...global, stubs: { ...global.stubs, 'v-input': VInput } },
|
||||
});
|
||||
|
||||
// Wait for search debounce
|
||||
await new Promise((r) => setTimeout(r, 300));
|
||||
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -204,17 +204,10 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
itemSelectable: 'selectable',
|
||||
itemChildren: 'children',
|
||||
modelValue: null,
|
||||
multiple: false,
|
||||
groupSelectable: false,
|
||||
mandatory: true,
|
||||
placeholder: null,
|
||||
fullWidth: true,
|
||||
disabled: false,
|
||||
showDeselect: false,
|
||||
allowOther: false,
|
||||
closeOnContentClick: true,
|
||||
inline: false,
|
||||
label: false,
|
||||
multiplePreviewThreshold: 3,
|
||||
placement: 'bottom',
|
||||
isMenuSameWidth: true,
|
||||
@@ -251,42 +244,57 @@ function useItems() {
|
||||
const internalSearch = ref<string | null>(null);
|
||||
|
||||
const internalItems = computed(() => {
|
||||
const parseItem = (item: Record<string, any>): Option => {
|
||||
const parseItem = (item: Record<string, any> | string): Option => {
|
||||
if (typeof item === 'string') {
|
||||
return {
|
||||
text: item,
|
||||
value: item,
|
||||
hidden: internalSearch.value ? !filterItem(item) : false,
|
||||
};
|
||||
}
|
||||
|
||||
if (item.divider === true) return { value: null, divider: true };
|
||||
|
||||
const text = get(item, props.itemText);
|
||||
const value = get(item, props.itemValue);
|
||||
const children = get(item, props.itemChildren) ? get(item, props.itemChildren).map(parseItem) : null;
|
||||
|
||||
return {
|
||||
text: get(item, props.itemText),
|
||||
value: get(item, props.itemValue),
|
||||
text,
|
||||
value,
|
||||
icon: props.itemIcon ? get(item, props.itemIcon) : undefined,
|
||||
disabled: get(item, props.itemDisabled),
|
||||
selectable: get(item, props.itemSelectable),
|
||||
children: children ? children.filter(filterItem) : children,
|
||||
hidden: internalSearch.value ? !filterItem(item) : false,
|
||||
children: children
|
||||
? children.filter((childItem: Record<string, any>) =>
|
||||
filterItem(get(childItem, props.itemText), get(childItem, props.itemValue), childItem.children)
|
||||
)
|
||||
: children,
|
||||
hidden: internalSearch.value ? !filterItem(text, value, item.children) : false,
|
||||
};
|
||||
};
|
||||
|
||||
const filterItem = (item: Record<string, any>): boolean => {
|
||||
const filterItem = (
|
||||
text: string | undefined,
|
||||
value?: string | number | null,
|
||||
children?: Record<string, any>[] | null
|
||||
): boolean => {
|
||||
if (!internalSearch.value) return true;
|
||||
|
||||
const searchValue = internalSearch.value.toLowerCase();
|
||||
|
||||
return item?.children
|
||||
? isMatchingCurrentItem(item, searchValue) ||
|
||||
item.children.some((item: Record<string, any>) => filterItem(item))
|
||||
: isMatchingCurrentItem(item, searchValue);
|
||||
return children
|
||||
? isMatchingCurrentItem(text, value, searchValue) ||
|
||||
children.some((childItem: Record<string, any>) =>
|
||||
filterItem(get(childItem, props.itemText), get(childItem, props.itemValue), childItem.children)
|
||||
)
|
||||
: isMatchingCurrentItem(text, value, searchValue);
|
||||
|
||||
function isMatchingCurrentItem(item: Record<string, any>, searchValue: string): boolean {
|
||||
const text = get(item, props.itemText);
|
||||
const value = get(item, props.itemValue);
|
||||
function isMatchingCurrentItem(
|
||||
text: string | undefined,
|
||||
value: string | number | null | undefined,
|
||||
searchValue: string
|
||||
): boolean {
|
||||
return (
|
||||
(text ? String(text).toLowerCase().includes(searchValue) : false) ||
|
||||
(value ? String(value).toLowerCase().includes(searchValue) : false)
|
||||
|
||||
Reference in New Issue
Block a user