mirror of
https://github.com/tenrok/vue-select.git
synced 2026-05-17 02:29:37 +03:00
refactor: apply eslint fixes (#1469)
This commit is contained in:
+14
-17
@@ -1,17 +1,14 @@
|
|||||||
const path = require('path');
|
const path = require('path')
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack')
|
||||||
const VueLoaderPlugin = require('vue-loader').VueLoaderPlugin;
|
const VueLoaderPlugin = require('vue-loader').VueLoaderPlugin
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||||
|
|
||||||
const env = process.env.NODE_ENV === 'production'
|
const env = process.env.NODE_ENV === 'production' ? 'production' : 'development'
|
||||||
? 'production'
|
|
||||||
: 'development';
|
|
||||||
|
|
||||||
const devtool = env === 'production' ? 'source-map' : 'eval-source-map';
|
const devtool = env === 'production' ? 'source-map' : 'eval-source-map'
|
||||||
|
|
||||||
const extractOrInjectStyles = env !== 'production'
|
const extractOrInjectStyles =
|
||||||
? 'vue-style-loader'
|
env !== 'production' ? 'vue-style-loader' : MiniCssExtractPlugin.loader
|
||||||
: MiniCssExtractPlugin.loader;
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
mode: env,
|
mode: env,
|
||||||
@@ -24,11 +21,11 @@ module.exports = {
|
|||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.vue'],
|
extensions: ['.js', '.vue'],
|
||||||
alias: {
|
alias: {
|
||||||
'src': path.resolve(__dirname, '../src'),
|
src: path.resolve(__dirname, '../src'),
|
||||||
'assets': path.resolve(__dirname, '../docs/assets'),
|
assets: path.resolve(__dirname, '../docs/assets'),
|
||||||
'mixins': path.resolve(__dirname, '../src/mixins'),
|
mixins: path.resolve(__dirname, '../src/mixins'),
|
||||||
'components': path.resolve(__dirname, '../src/components'),
|
components: path.resolve(__dirname, '../src/components'),
|
||||||
'vue$': 'vue/dist/vue.esm.js',
|
vue$: 'vue/dist/vue.esm.js',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
@@ -67,4 +64,4 @@ module.exports = {
|
|||||||
children: false,
|
children: false,
|
||||||
modules: false,
|
modules: false,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge')
|
||||||
const chokidar = require('chokidar');
|
const chokidar = require('chokidar')
|
||||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||||
const baseWebpackConfig = require('./webpack.base.conf');
|
const baseWebpackConfig = require('./webpack.base.conf')
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -28,12 +28,10 @@ module.exports = merge(baseWebpackConfig, {
|
|||||||
chunks: false,
|
chunks: false,
|
||||||
},
|
},
|
||||||
port: 8080,
|
port: 8080,
|
||||||
before (app, server) {
|
before(app, server) {
|
||||||
chokidar.watch([
|
chokidar.watch(['./**/*.html']).on('all', function () {
|
||||||
'./**/*.html',
|
server.sockWrite(server.sockets, 'content-changed')
|
||||||
]).on('all', function () {
|
})
|
||||||
server.sockWrite(server.sockets, 'content-changed');
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const TerserPlugin = require('terser-webpack-plugin');
|
const TerserPlugin = require('terser-webpack-plugin')
|
||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge')
|
||||||
const baseWebpackConfig = require('./webpack.base.conf');
|
const baseWebpackConfig = require('./webpack.base.conf')
|
||||||
|
|
||||||
module.exports = merge(baseWebpackConfig, {
|
module.exports = merge(baseWebpackConfig, {
|
||||||
entry: './src/index.js',
|
entry: './src/index.js',
|
||||||
@@ -8,7 +8,7 @@ module.exports = merge(baseWebpackConfig, {
|
|||||||
filename: 'vue-select.js',
|
filename: 'vue-select.js',
|
||||||
library: 'VueSelect',
|
library: 'VueSelect',
|
||||||
libraryTarget: 'umd',
|
libraryTarget: 'umd',
|
||||||
globalObject: 'typeof self !== \'undefined\' ? self : this',
|
globalObject: "typeof self !== 'undefined' ? self : this",
|
||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
minimizer: [
|
minimizer: [
|
||||||
@@ -16,5 +16,5 @@ module.exports = merge(baseWebpackConfig, {
|
|||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|||||||
+7
-7
@@ -5,19 +5,19 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import vSelect from "../src/components/Select";
|
import vSelect from '../src/components/Select'
|
||||||
import countries from "../docs/.vuepress/data/countryCodes";
|
import countries from '../docs/.vuepress/data/countryCodes'
|
||||||
import books from "../docs/.vuepress/data/books";
|
import books from '../docs/.vuepress/data/books'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { vSelect },
|
components: { vSelect },
|
||||||
data: () => ({
|
data: () => ({
|
||||||
selected: null,
|
selected: null,
|
||||||
config: {
|
config: {
|
||||||
options: countries
|
options: countries,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
+5
-5
@@ -1,8 +1,8 @@
|
|||||||
import Vue from "vue";
|
import Vue from 'vue'
|
||||||
import Dev from "./Dev.vue";
|
import Dev from './Dev.vue'
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
render: h => h(Dev)
|
render: (h) => h(Dev),
|
||||||
}).$mount("#app");
|
}).$mount('#app')
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
<v-select>
|
<v-select>
|
||||||
<template v-slot:no-options="{ search, searching }">
|
<template v-slot:no-options="{ search, searching }">
|
||||||
<template v-if="searching">
|
<template v-if="searching">
|
||||||
No results found for <em>{{ search }}</em>.
|
No results found for <em>{{ search }}</em
|
||||||
|
>.
|
||||||
</template>
|
</template>
|
||||||
<em style="opacity: 0.5;" v-else>Start typing to search for a country.</em>
|
<em v-else style="opacity: 0.5">Start typing to search for a country.</em>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</template>
|
</template>
|
||||||
@@ -12,5 +13,5 @@
|
|||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'BetterNoOptions',
|
name: 'BetterNoOptions',
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-select
|
<v-select
|
||||||
placeholder="choose a country"
|
v-model="selected"
|
||||||
v-model="selected"
|
placeholder="choose a country"
|
||||||
:components="{Deselect}"
|
:components="{ Deselect }"
|
||||||
:options="['Canada', 'United States']"
|
:options="['Canada', 'United States']"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -14,8 +14,8 @@ export default {
|
|||||||
data: () => ({
|
data: () => ({
|
||||||
selected: 'Canada',
|
selected: 'Canada',
|
||||||
Deselect: {
|
Deselect: {
|
||||||
render: createElement => createElement('span', '❌'),
|
render: (createElement) => createElement('span', '❌'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
<template>
|
<template>
|
||||||
<p :data-height="height"
|
<p
|
||||||
data-theme-id="32252"
|
:data-height="height"
|
||||||
:data-slug-hash="url"
|
data-theme-id="32252"
|
||||||
data-default-tab="result"
|
:data-slug-hash="url"
|
||||||
data-user="sagalbot"
|
data-default-tab="result"
|
||||||
class="codepen">
|
data-user="sagalbot"
|
||||||
</p>
|
class="codepen"
|
||||||
|
></p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import mountCodePen from '../utils/codePen';
|
import mountCodePen from '../utils/codePen'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@@ -18,11 +19,12 @@ export default {
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
height: {
|
height: {
|
||||||
default: 250
|
type: [String, Number],
|
||||||
}
|
default: 250,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted() {
|
||||||
mountCodePen();
|
mountCodePen()
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="{ login, avatar_url, html_url, contributions } in contributors">
|
<li
|
||||||
|
v-for="{ login, avatar_url, html_url, contributions } in contributors"
|
||||||
|
:key="login"
|
||||||
|
>
|
||||||
<img :src="`${avatar_url}&s=75`" :alt="`${login}'s Avatar`" />
|
<img :src="`${avatar_url}&s=75`" :alt="`${login}'s Avatar`" />
|
||||||
<div>
|
<div>
|
||||||
<a :href="html_url">@{{ login }}</a>
|
<a :href="html_url">@{{ login }}</a>
|
||||||
<br /><a
|
<br /><a
|
||||||
class="contributions-link"
|
class="contributions-link"
|
||||||
:href="
|
:href="`https://github.com/sagalbot/vue-select/commits?author=${login}`"
|
||||||
`https://github.com/sagalbot/vue-select/commits?author=${login}`
|
|
||||||
"
|
|
||||||
>{{ contributions }} contributions</a
|
>{{ contributions }} contributions</a
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -17,15 +18,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { CONTRIBUTORS } from "@dynamic/constants";
|
import { CONTRIBUTORS } from '@dynamic/constants'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
contributors: CONTRIBUTORS.filter(
|
contributors: CONTRIBUTORS.filter(
|
||||||
({ login }) => login !== "semantic-release-bot"
|
({ login }) => login !== 'semantic-release-bot'
|
||||||
)
|
),
|
||||||
})
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -3,16 +3,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countryCodes from '../data/countryCodes';
|
import countryCodes from '../data/countryCodes'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CountrySelect',
|
name: 'CountrySelect',
|
||||||
data: () => ({
|
data: () => ({
|
||||||
options: countryCodes,
|
options: countryCodes,
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -9,18 +9,18 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.style-chooser .vs__search::placeholder,
|
.style-chooser .vs__search::placeholder,
|
||||||
.style-chooser .vs__dropdown-toggle,
|
.style-chooser .vs__dropdown-toggle,
|
||||||
.style-chooser .vs__dropdown-menu {
|
.style-chooser .vs__dropdown-menu {
|
||||||
background: #dfe5fb;
|
background: #dfe5fb;
|
||||||
border: none;
|
border: none;
|
||||||
color: #394066;
|
color: #394066;
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
font-variant: small-caps;
|
font-variant: small-caps;
|
||||||
}
|
}
|
||||||
|
|
||||||
.style-chooser .vs__clear,
|
.style-chooser .vs__clear,
|
||||||
.style-chooser .vs__open-indicator {
|
.style-chooser .vs__open-indicator {
|
||||||
fill: #394066;
|
fill: #394066;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select
|
<v-select
|
||||||
:options="['Vue.js', 'React', 'Angular']"
|
:options="['Vue.js', 'React', 'Angular']"
|
||||||
:components="{Deselect, OpenIndicator}"
|
:components="{ Deselect, OpenIndicator }"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -9,11 +9,11 @@
|
|||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
Deselect: {
|
Deselect: {
|
||||||
render: createElement => createElement('span', '❌'),
|
render: (createElement) => createElement('span', '❌'),
|
||||||
},
|
},
|
||||||
OpenIndicator: {
|
OpenIndicator: {
|
||||||
render: createElement => createElement('span', '🔽'),
|
render: (createElement) => createElement('span', '🔽'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select
|
<v-select
|
||||||
taggable
|
taggable
|
||||||
multiple
|
multiple
|
||||||
no-drop
|
no-drop
|
||||||
:map-keydown="handlers"
|
:map-keydown="handlers"
|
||||||
placeholder="enter an email"
|
placeholder="enter an email"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -13,13 +13,14 @@ export default {
|
|||||||
name: 'CustomHandlers',
|
name: 'CustomHandlers',
|
||||||
methods: {
|
methods: {
|
||||||
handlers: (map, vm) => ({
|
handlers: (map, vm) => ({
|
||||||
...map, 50: e => {
|
...map,
|
||||||
e.preventDefault();
|
50: (e) => {
|
||||||
if( e.key === '@' && vm.search.length > 0 ) {
|
e.preventDefault()
|
||||||
vm.search = `${vm.search}@gmail.com`;
|
if (e.key === '@' && vm.search.length > 0) {
|
||||||
|
vm.search = `${vm.search}@gmail.com`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select :filter="fuseSearch" :options="books" :getOptionLabel="option => option.title">
|
<v-select
|
||||||
|
:filter="fuseSearch"
|
||||||
|
:options="books"
|
||||||
|
:get-option-label="(option) => option.title"
|
||||||
|
>
|
||||||
<template #option="{ author, title }">
|
<template #option="{ author, title }">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<br />
|
<br />
|
||||||
@@ -9,23 +13,23 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Fuse from "fuse.js";
|
import Fuse from 'fuse.js'
|
||||||
import books from "../data/books";
|
import books from '../data/books'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
books: () => books
|
books: () => books,
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
fuseSearch(options, search) {
|
fuseSearch(options, search) {
|
||||||
const fuse = new Fuse(options, {
|
const fuse = new Fuse(options, {
|
||||||
keys: ["title", "author.firstName", "author.lastName"],
|
keys: ['title', 'author.firstName', 'author.lastName'],
|
||||||
shouldSort: true
|
shouldSort: true,
|
||||||
});
|
})
|
||||||
return search.length
|
return search.length
|
||||||
? fuse.search(search).map(({ item }) => item)
|
? fuse.search(search).map(({ item }) => item)
|
||||||
: fuse.list;
|
: fuse.list
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,10 +4,10 @@
|
|||||||
:filterable="false"
|
:filterable="false"
|
||||||
@open="onOpen"
|
@open="onOpen"
|
||||||
@close="onClose"
|
@close="onClose"
|
||||||
@search="query => search = query"
|
@search="(query) => (search = query)"
|
||||||
>
|
>
|
||||||
<template #list-footer>
|
<template #list-footer>
|
||||||
<li ref="load" class="loader" v-show="hasNextPage">
|
<li v-show="hasNextPage" ref="load" class="loader">
|
||||||
Loading more options...
|
Loading more options...
|
||||||
</li>
|
</li>
|
||||||
</template>
|
</template>
|
||||||
@@ -15,60 +15,60 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries';
|
import countries from '../data/countries'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "InfiniteScroll",
|
name: 'InfiniteScroll',
|
||||||
data: () => ({
|
data: () => ({
|
||||||
observer: null,
|
observer: null,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
search: ''
|
search: '',
|
||||||
}),
|
}),
|
||||||
mounted () {
|
computed: {
|
||||||
|
filtered() {
|
||||||
|
return countries.filter((country) => country.includes(this.search))
|
||||||
|
},
|
||||||
|
paginated() {
|
||||||
|
return this.filtered.slice(0, this.limit)
|
||||||
|
},
|
||||||
|
hasNextPage() {
|
||||||
|
return this.paginated.length < this.filtered.length
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
/**
|
/**
|
||||||
* You could do this directly in data(), but since these docs
|
* You could do this directly in data(), but since these docs
|
||||||
* are server side rendered, IntersectionObserver doesn't exist
|
* are server side rendered, IntersectionObserver doesn't exist
|
||||||
* in that environment, so we need to do it in mounted() instead.
|
* in that environment, so we need to do it in mounted() instead.
|
||||||
*/
|
*/
|
||||||
this.observer = new IntersectionObserver(this.infiniteScroll);
|
this.observer = new IntersectionObserver(this.infiniteScroll)
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
filtered () {
|
|
||||||
return countries.filter(country => country.includes(this.search));
|
|
||||||
},
|
|
||||||
paginated () {
|
|
||||||
return this.filtered.slice(0, this.limit);
|
|
||||||
},
|
|
||||||
hasNextPage () {
|
|
||||||
return this.paginated.length < this.filtered.length;
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onOpen () {
|
async onOpen() {
|
||||||
if (this.hasNextPage) {
|
if (this.hasNextPage) {
|
||||||
await this.$nextTick();
|
await this.$nextTick()
|
||||||
this.observer.observe(this.$refs.load)
|
this.observer.observe(this.$refs.load)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onClose () {
|
onClose() {
|
||||||
this.observer.disconnect();
|
this.observer.disconnect()
|
||||||
},
|
},
|
||||||
async infiniteScroll ([{isIntersecting, target}]) {
|
async infiniteScroll([{ isIntersecting, target }]) {
|
||||||
if (isIntersecting) {
|
if (isIntersecting) {
|
||||||
const ul = target.offsetParent;
|
const ul = target.offsetParent
|
||||||
const scrollTop = target.offsetParent.scrollTop;
|
const scrollTop = target.offsetParent.scrollTop
|
||||||
this.limit += 10;
|
this.limit += 10
|
||||||
await this.$nextTick();
|
await this.$nextTick()
|
||||||
ul.scrollTop = scrollTop;
|
ul.scrollTop = scrollTop
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.loader {
|
.loader {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #bbbbbb;
|
color: #bbbbbb;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select
|
<v-select
|
||||||
|
v-model="selected"
|
||||||
multiple
|
multiple
|
||||||
placeholder="Choose up to 3 books!"
|
placeholder="Choose up to 3 books!"
|
||||||
label="title"
|
label="title"
|
||||||
v-model="selected"
|
|
||||||
:options="books"
|
:options="books"
|
||||||
:selectable="() => selected.length < 3"
|
:selectable="() => selected.length < 3"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import books from '../data/books';
|
import books from '../data/books'
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return { selected: [] }
|
return { selected: [] }
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
books: () => books,
|
books: () => books,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -4,13 +4,13 @@
|
|||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Country</th>
|
<th>Country</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-for="person in people">
|
<tr v-for="person in people" :key="person.name">
|
||||||
<td>{{ person.name }}</td>
|
<td>{{ person.name }}</td>
|
||||||
<td>
|
<td>
|
||||||
<v-select
|
<v-select
|
||||||
:options="options"
|
:options="options"
|
||||||
:value="person.country"
|
:value="person.country"
|
||||||
@input="country => updateCountry(person, country)"
|
@input="(country) => updateCountry(person, country)"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -18,26 +18,29 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries';
|
import countries from '../data/countries'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
people: [{name: 'John', country: ''}, {name: 'Jane', country: ''}],
|
people: [
|
||||||
|
{ name: 'John', country: '' },
|
||||||
|
{ name: 'Jane', country: '' },
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
methods: {
|
|
||||||
updateCountry (person, country) {
|
|
||||||
person.country = country;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
options: () => countries,
|
options: () => countries,
|
||||||
},
|
},
|
||||||
};
|
methods: {
|
||||||
|
updateCountry(person, country) {
|
||||||
|
person.country = country
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
table {
|
table {
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-select
|
<v-select
|
||||||
multiple
|
v-model="selected"
|
||||||
v-model="selected"
|
multiple
|
||||||
:options="['Canada', 'United States']"
|
:options="['Canada', 'United States']"
|
||||||
:components="{Deselect}"
|
:components="{ Deselect }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -14,8 +14,8 @@ export default {
|
|||||||
data: () => ({
|
data: () => ({
|
||||||
selected: ['Canada'],
|
selected: ['Canada'],
|
||||||
Deselect: {
|
Deselect: {
|
||||||
render: createElement => createElement('span', '❌'),
|
render: (createElement) => createElement('span', '❌'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-select
|
<v-select
|
||||||
:options="['Canada', 'United States']"
|
:options="['Canada', 'United States']"
|
||||||
:components="{OpenIndicator}"
|
:components="{ OpenIndicator }"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
OpenIndicator: {
|
OpenIndicator: {
|
||||||
render: createElement => createElement('span', '🔽'),
|
render: (createElement) => createElement('span', '🔽'),
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select :options="paginated" @search="query => search = query" :filterable="false">
|
<v-select
|
||||||
|
:options="paginated"
|
||||||
|
:filterable="false"
|
||||||
|
@search="(query) => (search = query)"
|
||||||
|
>
|
||||||
<li slot="list-footer" class="pagination">
|
<li slot="list-footer" class="pagination">
|
||||||
<button @click="offset -= 10" :disabled="!hasPrevPage">Prev</button>
|
<button :disabled="!hasPrevPage" @click="offset -= 10">Prev</button>
|
||||||
<button @click="offset += 10" :disabled="!hasNextPage">Next</button>
|
<button :disabled="!hasNextPage" @click="offset += 10">Next</button>
|
||||||
</li>
|
</li>
|
||||||
</v-select>
|
</v-select>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries';
|
import countries from '../data/countries'
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
countries,
|
countries,
|
||||||
@@ -17,33 +21,37 @@ export default {
|
|||||||
limit: 10,
|
limit: 10,
|
||||||
}),
|
}),
|
||||||
computed: {
|
computed: {
|
||||||
filtered () {
|
filtered() {
|
||||||
return this.countries.filter(country => country.includes(this.search));
|
return this.countries.filter((country) => country.includes(this.search))
|
||||||
},
|
},
|
||||||
paginated () {
|
paginated() {
|
||||||
return this.filtered.slice(this.offset, this.limit + this.offset);
|
return this.filtered.slice(this.offset, this.limit + this.offset)
|
||||||
},
|
},
|
||||||
hasNextPage () {
|
hasNextPage() {
|
||||||
const nextOffset = this.offset + 10;
|
const nextOffset = this.offset + 10
|
||||||
return Boolean(this.filtered.slice(nextOffset, this.limit + nextOffset).length);
|
return Boolean(
|
||||||
|
this.filtered.slice(nextOffset, this.limit + nextOffset).length
|
||||||
|
)
|
||||||
|
},
|
||||||
|
hasPrevPage() {
|
||||||
|
const prevOffset = this.offset - 10
|
||||||
|
return Boolean(
|
||||||
|
this.filtered.slice(prevOffset, this.limit + prevOffset).length
|
||||||
|
)
|
||||||
},
|
},
|
||||||
hasPrevPage () {
|
|
||||||
const prevOffset = this.offset - 10;
|
|
||||||
return Boolean(this.filtered.slice(prevOffset, this.limit + prevOffset).length);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.pagination {
|
.pagination {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin: .25rem .25rem 0;
|
margin: 0.25rem 0.25rem 0;
|
||||||
}
|
}
|
||||||
.pagination button {
|
.pagination button {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
.pagination button:hover {
|
.pagination button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,15 +1,19 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<v-select :options="countries" append-to-body :calculate-position="withPopper" />
|
<v-select
|
||||||
|
:options="countries"
|
||||||
|
append-to-body
|
||||||
|
:calculate-position="withPopper"
|
||||||
|
/>
|
||||||
|
|
||||||
<label for="position" style="display: block; margin: 1rem 0;">
|
<label for="position" style="display: block; margin: 1rem 0">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
|
||||||
id="position"
|
id="position"
|
||||||
v-model="placement"
|
v-model="placement"
|
||||||
|
type="checkbox"
|
||||||
true-value="top"
|
true-value="top"
|
||||||
false-value="bottom"
|
false-value="bottom"
|
||||||
>
|
/>
|
||||||
Position dropdown above
|
Position dropdown above
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -17,17 +21,17 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import countries from '../data/countries'
|
import countries from '../data/countries'
|
||||||
import { createPopper } from '@popperjs/core';
|
import { createPopper } from '@popperjs/core'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: () => ({countries, placement: 'top'}),
|
data: () => ({ countries, placement: 'top' }),
|
||||||
methods: {
|
methods: {
|
||||||
withPopper (dropdownList, component, {width}) {
|
withPopper(dropdownList, component, { width }) {
|
||||||
/**
|
/**
|
||||||
* We need to explicitly define the dropdown width since
|
* We need to explicitly define the dropdown width since
|
||||||
* it is usually inherited from the parent with CSS.
|
* it is usually inherited from the parent with CSS.
|
||||||
*/
|
*/
|
||||||
dropdownList.style.width = width;
|
dropdownList.style.width = width
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Here we position the dropdownList relative to the $refs.toggle Element.
|
* Here we position the dropdownList relative to the $refs.toggle Element.
|
||||||
@@ -43,41 +47,46 @@ export default {
|
|||||||
placement: this.placement,
|
placement: this.placement,
|
||||||
modifiers: [
|
modifiers: [
|
||||||
{
|
{
|
||||||
name: 'offset', options: {
|
name: 'offset',
|
||||||
offset: [0, -1]
|
options: {
|
||||||
}
|
offset: [0, -1],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'toggleClass',
|
name: 'toggleClass',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
phase: 'write',
|
phase: 'write',
|
||||||
fn ({state}) {
|
fn({ state }) {
|
||||||
component.$el.classList.toggle('drop-up', state.placement === 'top')
|
component.$el.classList.toggle(
|
||||||
|
'drop-up',
|
||||||
|
state.placement === 'top'
|
||||||
|
)
|
||||||
},
|
},
|
||||||
}]
|
},
|
||||||
});
|
],
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To prevent memory leaks Popper needs to be destroyed.
|
* To prevent memory leaks Popper needs to be destroyed.
|
||||||
* If you return function, it will be called just before dropdown is removed from DOM.
|
* If you return function, it will be called just before dropdown is removed from DOM.
|
||||||
*/
|
*/
|
||||||
return () => popper.destroy();
|
return () => popper.destroy()
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.v-select.drop-up.vs--open .vs__dropdown-toggle {
|
.v-select.drop-up.vs--open .vs__dropdown-toggle {
|
||||||
border-radius: 0 0 4px 4px;
|
border-radius: 0 0 4px 4px;
|
||||||
border-top-color: transparent;
|
border-top-color: transparent;
|
||||||
border-bottom-color: rgba(60, 60, 60, 0.26);
|
border-bottom-color: rgba(60, 60, 60, 0.26);
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-popper-placement='top'] {
|
[data-popper-placement='top'] {
|
||||||
border-radius: 4px 4px 0 0;
|
border-radius: 4px 4px 0 0;
|
||||||
border-top-style: solid;
|
border-top-style: solid;
|
||||||
border-bottom-style: none;
|
border-bottom-style: none;
|
||||||
box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.15)
|
box-shadow: 0 -3px 6px rgba(0, 0, 0, 0.15);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
<div class="flex">
|
<div class="flex">
|
||||||
<div>
|
<div>
|
||||||
<v-select
|
<v-select
|
||||||
label="country"
|
v-model="selected"
|
||||||
v-model="selected"
|
label="country"
|
||||||
:reduce="opt => opt.meta.id"
|
:reduce="(opt) => opt.meta.id"
|
||||||
:options="options"
|
:options="options"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -26,35 +26,36 @@ export default {
|
|||||||
id: '1',
|
id: '1',
|
||||||
code: 'ca',
|
code: 'ca',
|
||||||
},
|
},
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.flex {
|
.flex {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
border: 1px solid #eaecef;
|
border: 1px solid #eaecef;
|
||||||
/*padding: 1rem;*/
|
/*padding: 1rem;*/
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flex > div {
|
.flex > div {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
width: 50%;
|
width: 50%;
|
||||||
padding: 0 1rem;
|
padding: 0 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
code {
|
code {
|
||||||
color: #635762 !important;
|
color: #635762 !important;
|
||||||
color: #5b2d2d !important;
|
color: #5b2d2d !important;
|
||||||
/*color: #7ec699 !important;*/
|
/*color: #7ec699 !important;*/
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,49 +1,85 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="sandbox-wrap">
|
<div id="sandbox-wrap">
|
||||||
<div id="config">
|
<div id="config">
|
||||||
|
<div v-if="!hideHelp" class="list-item">
|
||||||
<div class="list-item" v-if="!hideHelp">
|
<p>
|
||||||
<p>Use the controls below to adjust the props used
|
Use the controls below to adjust the props used by the vue-select
|
||||||
by the vue-select components.</p>
|
components.
|
||||||
<p>The API provides
|
</p>
|
||||||
more props than are shown here, these are some
|
<p>
|
||||||
commonly adjusted settings.</p>
|
The API provides more props than are shown here, these are some
|
||||||
|
commonly adjusted settings.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h5 class="list-item">Basic Features</h5>
|
<h5 class="list-item">Basic Features</h5>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="multiple">
|
<label for="multiple">
|
||||||
<input id="multiple" type="checkbox" v-model="configuration.multiple">
|
<input
|
||||||
<code>:multiple="{{ configuration.multiple ? 'true' : 'false' }}"</code>
|
id="multiple"
|
||||||
|
v-model="configuration.multiple"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:multiple="{{ configuration.multiple ? 'true' : 'false' }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="disabled">
|
<label for="disabled">
|
||||||
<input id="disabled" type="checkbox" v-model="configuration.disabled">
|
<input
|
||||||
<code>:disabled="{{ configuration.disabled ? 'true' : 'false' }}"</code>
|
id="disabled"
|
||||||
|
v-model="configuration.disabled"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:disabled="{{ configuration.disabled ? 'true' : 'false' }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="clearable">
|
<label for="clearable">
|
||||||
<input id="clearable" type="checkbox" v-model="configuration.clearable">
|
<input
|
||||||
<code>:clearable="{{ configuration.clearable ? 'true' : 'false' }}"</code>
|
id="clearable"
|
||||||
|
v-model="configuration.clearable"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:clearable="{{ configuration.clearable ? 'true' : 'false' }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="searchable">
|
<label for="searchable">
|
||||||
<input id="searchable" type="checkbox" v-model="configuration.searchable">
|
<input
|
||||||
<code>:searchable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
|
id="searchable"
|
||||||
|
v-model="configuration.searchable"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:searchable="{{
|
||||||
|
configuration.searchable ? 'true' : 'false'
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="filterable">
|
<label for="filterable">
|
||||||
<input id="filterable" type="checkbox" v-model="configuration.filterable">
|
<input
|
||||||
<code>:filterable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
|
id="filterable"
|
||||||
|
v-model="configuration.filterable"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:filterable="{{
|
||||||
|
configuration.searchable ? 'true' : 'false'
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -51,22 +87,34 @@
|
|||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="taggable">
|
<label for="taggable">
|
||||||
<input id="taggable" type="checkbox" v-model="configuration.taggable">
|
<input
|
||||||
<code>:taggable="{{ configuration.taggable ? 'true' : 'false' }}"</code>
|
id="taggable"
|
||||||
|
v-model="configuration.taggable"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:taggable="{{ configuration.taggable ? 'true' : 'false' }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="noDrop">
|
<label for="noDrop">
|
||||||
<input id="noDrop" type="checkbox" v-model="configuration.noDrop">
|
<input id="noDrop" v-model="configuration.noDrop" type="checkbox" />
|
||||||
<code>:no-drop="{{ configuration.noDrop ? 'true' : 'false' }}"</code>
|
<code>:no-drop="{{ configuration.noDrop ? 'true' : 'false' }}"</code>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="pushTags">
|
<label for="pushTags">
|
||||||
<input id="pushTags" type="checkbox" v-model="configuration.pushTags">
|
<input
|
||||||
<code>:push-tags="{{ configuration.pushTags ? 'true' : 'false' }}"</code>
|
id="pushTags"
|
||||||
|
v-model="configuration.pushTags"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:push-tags="{{ configuration.pushTags ? 'true' : 'false' }}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -74,15 +122,31 @@
|
|||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="selectOnTab">
|
<label for="selectOnTab">
|
||||||
<input id="selectOnTab" type="checkbox" v-model="configuration.selectOnTab">
|
<input
|
||||||
<code>:select-on-tab="{{ configuration.selectOnTab ? 'true' : 'false' }}"</code>
|
id="selectOnTab"
|
||||||
|
v-model="configuration.selectOnTab"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:select-on-tab="{{
|
||||||
|
configuration.selectOnTab ? 'true' : 'false'
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="closeOnSelect">
|
<label for="closeOnSelect">
|
||||||
<input id="closeOnSelect" type="checkbox" v-model="configuration.closeOnSelect">
|
<input
|
||||||
<code>:close-on-select="{{ configuration.closeOnSelect ? 'true' : 'false' }}"</code>
|
id="closeOnSelect"
|
||||||
|
v-model="configuration.closeOnSelect"
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<code
|
||||||
|
>:close-on-select="{{
|
||||||
|
configuration.closeOnSelect ? 'true' : 'false'
|
||||||
|
}}"</code
|
||||||
|
>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -90,11 +154,21 @@
|
|||||||
|
|
||||||
<div class="list-item">
|
<div class="list-item">
|
||||||
<label for="rtl">
|
<label for="rtl">
|
||||||
<input id="rtl" type="radio" v-model="configuration.dir" value="rtl">
|
<input
|
||||||
|
id="rtl"
|
||||||
|
v-model="configuration.dir"
|
||||||
|
type="radio"
|
||||||
|
value="rtl"
|
||||||
|
/>
|
||||||
<code>dir="rtl"</code>
|
<code>dir="rtl"</code>
|
||||||
</label>
|
</label>
|
||||||
<label for="ltr">
|
<label for="ltr">
|
||||||
<input id="ltr" type="radio" v-model="configuration.dir" value="ltr">
|
<input
|
||||||
|
id="ltr"
|
||||||
|
v-model="configuration.dir"
|
||||||
|
type="radio"
|
||||||
|
value="ltr"
|
||||||
|
/>
|
||||||
<code>dir="ltr"</code>
|
<code>dir="ltr"</code>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -103,22 +177,32 @@
|
|||||||
<div id="sandbox">
|
<div id="sandbox">
|
||||||
<slot v-bind="configuration">
|
<slot v-bind="configuration">
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" placeholder="country objects"></v-select>
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
placeholder="country objects"
|
||||||
|
></v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" placeholder="country objects, using option scoped slots">
|
<v-select
|
||||||
<template slot="selected-option" slot-scope="{ label, value }">
|
v-bind="configuration"
|
||||||
{{ label }} -- {{ value }}
|
placeholder="country objects, using option scoped slots"
|
||||||
|
>
|
||||||
|
<template slot="selected-option" slot-scope="option">
|
||||||
|
{{ option.label }} -- {{ option.value }}
|
||||||
</template>
|
</template>
|
||||||
<template slot="option" slot-scope="{ label, value }">
|
<template slot="option" slot-scope="option">
|
||||||
{{ label }} ({{ value }})
|
{{ option.label }} ({{ option.value }})
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" :options="['cat', 'dog', 'bear']" placeholder="string options, option slots">
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
:options="['cat', 'dog', 'bear']"
|
||||||
|
placeholder="string options, option slots"
|
||||||
|
>
|
||||||
<template slot="selected-option" slot-scope="{ label }">
|
<template slot="selected-option" slot-scope="{ label }">
|
||||||
{{ label }}
|
{{ label }}
|
||||||
</template>
|
</template>
|
||||||
@@ -129,32 +213,48 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" :options="[1,5,10]" placeholder="options=[1,5,10]"></v-select>
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
:options="[1, 5, 10]"
|
||||||
|
placeholder="options=[1,5,10]"
|
||||||
|
></v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" label="title" :options="optionDataSets.books" :filter="fuseSearch"
|
<v-select
|
||||||
placeholder="advanced filtering w/ fuse.js + scoped slots">
|
v-bind="configuration"
|
||||||
|
label="title"
|
||||||
|
:options="optionDataSets.books"
|
||||||
|
:filter="fuseSearch"
|
||||||
|
placeholder="advanced filtering w/ fuse.js + scoped slots"
|
||||||
|
>
|
||||||
<template slot="option" slot-scope="option">
|
<template slot="option" slot-scope="option">
|
||||||
<strong>{{ option.title }}</strong><br>
|
<strong>{{ option.title }}</strong
|
||||||
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
|
><br />
|
||||||
|
<em>{{
|
||||||
|
`${option.author.firstName} ${option.author.lastName}`
|
||||||
|
}}</em>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select
|
<v-select
|
||||||
v-bind="configuration"
|
v-bind="configuration"
|
||||||
placeholder="search github repositories.."
|
placeholder="search github repositories.."
|
||||||
label="full_name"
|
label="full_name"
|
||||||
@search="search"
|
:options="ajaxRes"
|
||||||
:options="ajaxRes"
|
@search="search"
|
||||||
>
|
>
|
||||||
</v-select>
|
</v-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="example">
|
<div class="example">
|
||||||
<v-select v-bind="configuration" :options="[]" placeholder="options=[]"></v-select>
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
:options="[]"
|
||||||
|
placeholder="options=[]"
|
||||||
|
></v-select>
|
||||||
</div>
|
</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -162,11 +262,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Fuse from 'fuse.js';
|
import Fuse from 'fuse.js'
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce'
|
||||||
import vSelect from '../../../src/components/Select.vue';
|
import vSelect from '../../../src/components/Select.vue'
|
||||||
import countries from '../data/countryCodes';
|
import countries from '../data/countryCodes'
|
||||||
import books from '../data/books';
|
import books from '../data/books'
|
||||||
|
|
||||||
const defaultConfig = () => ({
|
const defaultConfig = () => ({
|
||||||
options: countries,
|
options: countries,
|
||||||
@@ -180,17 +280,17 @@ const defaultConfig = () => ({
|
|||||||
disabled: false,
|
disabled: false,
|
||||||
selectOntab: false,
|
selectOntab: false,
|
||||||
placeholder: 'Select a Country...',
|
placeholder: 'Select a Country...',
|
||||||
});
|
})
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { vSelect },
|
||||||
props: {
|
props: {
|
||||||
hideHelp: {
|
hideHelp: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {vSelect},
|
data() {
|
||||||
data () {
|
|
||||||
return {
|
return {
|
||||||
configuration: defaultConfig(),
|
configuration: defaultConfig(),
|
||||||
value: null,
|
value: null,
|
||||||
@@ -201,76 +301,75 @@ export default {
|
|||||||
countries,
|
countries,
|
||||||
books,
|
books,
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
search (search, loading) {
|
search(search, loading) {
|
||||||
loading(true);
|
loading(true)
|
||||||
this.getRepositories(search, loading, this);
|
this.getRepositories(search, loading, this)
|
||||||
},
|
},
|
||||||
searchPeople (search, loading) {
|
searchPeople(search, loading) {
|
||||||
loading(true);
|
loading(true)
|
||||||
this.getPeople(loading, this);
|
this.getPeople(loading, this)
|
||||||
},
|
},
|
||||||
getPeople: debounce((loading, vm) => {
|
getPeople: debounce((loading, vm) => {
|
||||||
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then(res => {
|
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then((res) => {
|
||||||
vm.people = res.data.data;
|
vm.people = res.data.data
|
||||||
loading(false);
|
loading(false)
|
||||||
});
|
})
|
||||||
}, 250),
|
}, 250),
|
||||||
getRepositories: debounce((search, loading, vm) => {
|
getRepositories: debounce((search, loading, vm) => {
|
||||||
vm.$http
|
vm.$http
|
||||||
.get(`https://api.github.com/search/repositories?q=${search}`)
|
.get(`https://api.github.com/search/repositories?q=${search}`)
|
||||||
.then(res => {
|
.then((res) => {
|
||||||
vm.ajaxRes = res.data.items;
|
vm.ajaxRes = res.data.items
|
||||||
loading(false);
|
loading(false)
|
||||||
});
|
})
|
||||||
}, 250),
|
}, 250),
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
#sandbox-wrap {
|
#sandbox-wrap {
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 75%;
|
grid-template-columns: auto 75%;
|
||||||
grid-template-rows: auto;
|
grid-template-rows: auto;
|
||||||
grid-template-areas:
|
grid-template-areas: 'sidebar component';
|
||||||
"sidebar component"
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#config {
|
#config {
|
||||||
grid-area: sidebar;
|
grid-area: sidebar;
|
||||||
border-right: 1px solid #eaecef;
|
border-right: 1px solid #eaecef;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
#sandbox {
|
#sandbox {
|
||||||
grid-area: component;
|
grid-area: component;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item {
|
.list-item {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
padding: 1rem 1rem 0;
|
padding: 1rem 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.list-item:not(:first-child) {
|
.list-item:not(:first-child) {
|
||||||
border-top: 1px solid #eaecef;
|
border-top: 1px solid #eaecef;
|
||||||
}
|
}
|
||||||
|
|
||||||
.example {
|
.example {
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-select {
|
.v-select {
|
||||||
width: 25em;
|
width: 25em;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select append-to-body>
|
<v-select append-to-body>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<div style="opacity: .8">Bottom of the component, in the footer slot!</div>
|
<div style="opacity: 0.8">
|
||||||
|
Bottom of the component, in the footer slot!
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select>
|
<v-select>
|
||||||
<template #header>
|
<template #header>
|
||||||
<div style="opacity: .8">Top of the component, in the header slot!</div>
|
<div style="opacity: 0.8">Top of the component, in the header slot!</div>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select>
|
<v-select>
|
||||||
|
<!-- eslint-disable-next-line vue/no-unused-vars -->
|
||||||
<template #no-options="{ search, searching, loading }">
|
<template #no-options="{ search, searching, loading }">
|
||||||
This is the no options slot.
|
This is the no options slot.
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ export default {
|
|||||||
{
|
{
|
||||||
title: "Old Man's War",
|
title: "Old Man's War",
|
||||||
author: {
|
author: {
|
||||||
firstName: "John",
|
firstName: 'John',
|
||||||
lastName: "Scalzi"
|
lastName: 'Scalzi',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
class="vs__search"
|
class="vs__search"
|
||||||
v-bind="attributes"
|
v-bind="attributes"
|
||||||
v-on="events"
|
v-on="events"
|
||||||
>
|
/>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select v-model="selected" :options="books" label="title">
|
<v-select v-model="selected" :options="books" label="title">
|
||||||
<template #selected-option="{ title, author }">
|
<template #selected-option="{ title, author }">
|
||||||
<div style="display: flex; align-items: baseline;">
|
<div style="display: flex; align-items: baseline">
|
||||||
<strong>{{ title }}</strong>
|
<strong>{{ title }}</strong>
|
||||||
<em style="margin-left: .5rem;">by {{ author.firstName }} {{ author.lastName }}</em>
|
<em style="margin-left: 0.5rem"
|
||||||
|
>by {{ author.firstName }} {{ author.lastName }}</em
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
@@ -13,14 +15,14 @@
|
|||||||
const book = {
|
const book = {
|
||||||
title: "Old Man's War",
|
title: "Old Man's War",
|
||||||
author: {
|
author: {
|
||||||
firstName: "John",
|
firstName: 'John',
|
||||||
lastName: "Scalzi"
|
lastName: 'Scalzi',
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
books: [book],
|
books: [book],
|
||||||
selected: book
|
selected: book,
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<!-- eslint-disable vue/no-unused-vars -->
|
||||||
<v-select :options="books" label="title">
|
<v-select :options="books" label="title">
|
||||||
<template #selected-option-container="{ option, deselect, multiple, disabled }">
|
<template
|
||||||
|
#selected-option-container="{ option, deselect, multiple, disabled }"
|
||||||
|
>
|
||||||
<div class="vs__selected">{{ option.title }}</div>
|
<div class="vs__selected">{{ option.title }}</div>
|
||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
@@ -13,11 +16,11 @@ export default {
|
|||||||
{
|
{
|
||||||
title: "Old Man's War",
|
title: "Old Man's War",
|
||||||
author: {
|
author: {
|
||||||
firstName: "John",
|
firstName: 'John',
|
||||||
lastName: "Scalzi"
|
lastName: 'Scalzi',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-select :loading="true">
|
<v-select :loading="true">
|
||||||
<template #spinner="{ loading }">
|
<template #spinner="{ loading }">
|
||||||
<div v-if="loading" style="border-left-color: rgba(88,151,251,0.71)" class="vs__spinner">
|
<div
|
||||||
|
v-if="loading"
|
||||||
|
style="border-left-color: rgba(88, 151, 251, 0.71)"
|
||||||
|
class="vs__spinner"
|
||||||
|
>
|
||||||
The .vs__spinner class will hide the text for me.
|
The .vs__spinner class will hide the text for me.
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -20,6 +20,6 @@
|
|||||||
color: #8492a4;
|
color: #8492a4;
|
||||||
}
|
}
|
||||||
p a {
|
p a {
|
||||||
color: #48BB78;
|
color: #48bb78;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="cta">
|
<div class="cta">
|
||||||
<p style="font-size: 1.2rem; font-weight: 600;">
|
<p style="font-size: 1.2rem; font-weight: 600">
|
||||||
Hi! I'm Jeff Sagal, the author of Vue Select.
|
Hi! I'm Jeff Sagal, the author of Vue Select.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -35,7 +35,11 @@
|
|||||||
</svg>
|
</svg>
|
||||||
Sponsor Vue Select!
|
Sponsor Vue Select!
|
||||||
</a>
|
</a>
|
||||||
<a href="https://twitter.com/sagalbot" target="_blank" class="social-link">
|
<a
|
||||||
|
href="https://twitter.com/sagalbot"
|
||||||
|
target="_blank"
|
||||||
|
class="social-link"
|
||||||
|
>
|
||||||
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
<path
|
<path
|
||||||
d="M23.954 4.569a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.691 8.094 4.066 6.13 1.64 3.161a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.061a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.937 4.937 0 004.604 3.417 9.868 9.868 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63a9.936 9.936 0 002.46-2.548l-.047-.02z"
|
d="M23.954 4.569a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.691 8.094 4.066 6.13 1.64 3.161a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.061a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.937 4.937 0 004.604 3.417 9.868 9.868 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.054 0 13.999-7.496 13.999-13.986 0-.209 0-.42-.015-.63a9.936 9.936 0 002.46-2.548l-.047-.02z"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<ul>
|
<ul>
|
||||||
<li v-for="{ createdAt, login, avatarUrl } in sponsors">
|
<li v-for="{ createdAt, login, avatarUrl } in sponsors" :key="login">
|
||||||
<img :src="avatarUrl + '&s=150'" :alt="`@${login}'s avatar`" />
|
<img :src="avatarUrl + '&s=150'" :alt="`@${login}'s avatar`" />
|
||||||
<p>
|
<p>
|
||||||
<a :href="`https://github.com/${login}`">@{{ login }}</a> <br />
|
<a :href="`https://github.com/${login}`">@{{ login }}</a> <br />
|
||||||
@@ -11,17 +11,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { SPONSORS } from "@dynamic/constants";
|
import { SPONSORS } from '@dynamic/constants'
|
||||||
import { format } from "date-fns";
|
import { format } from 'date-fns'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
data: () => ({
|
data: () => ({
|
||||||
sponsors: SPONSORS.map(({ createdAt, sponsorEntity }) => ({
|
sponsors: SPONSORS.map(({ createdAt, sponsorEntity }) => ({
|
||||||
createdAt: format(new Date(createdAt), "LLL yyyy"),
|
createdAt: format(new Date(createdAt), 'LLL yyyy'),
|
||||||
...sponsorEntity
|
...sponsorEntity,
|
||||||
}))
|
})),
|
||||||
}),
|
}),
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
placeholder="Choose a book to read"
|
placeholder="Choose a book to read"
|
||||||
label="title"
|
label="title"
|
||||||
:options="books"
|
:options="books"
|
||||||
:selectable="option => ! option.author.lastName.includes('Woodhouse')"
|
:selectable="(option) => !option.author.lastName.includes('Woodhouse')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import books from '../data/books';
|
import books from '../data/books'
|
||||||
export default {
|
export default {
|
||||||
computed: {
|
computed: {
|
||||||
books: () => books,
|
books: () => books,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<form @submit.stop="onSubmit">
|
<form @submit.stop="onSubmit">
|
||||||
<v-select :options="books" label="title" v-model="selected">
|
<v-select v-model="selected" :options="books" label="title">
|
||||||
<template #search="{attributes, events}">
|
<template #search="{ attributes, events }">
|
||||||
<input
|
<input
|
||||||
:required="!selected"
|
:required="!selected"
|
||||||
class="vs__search"
|
class="vs__search"
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</template>
|
</template>
|
||||||
</v-select>
|
</v-select>
|
||||||
|
|
||||||
<input type="submit">
|
<input type="submit" />
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -24,28 +24,28 @@ export default {
|
|||||||
}),
|
}),
|
||||||
methods: {
|
methods: {
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
alert('Submitted!');
|
alert('Submitted!')
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
form {
|
form {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
}
|
}
|
||||||
|
|
||||||
.v-select {
|
.v-select {
|
||||||
width: 75%;
|
width: 75%;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="submit"] {
|
input[type='submit'] {
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
background: #44ae7d;
|
background: #44ae7d;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
width: 20%;
|
width: 20%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const {description} = require('./config/meta');
|
const { description } = require('./config/meta')
|
||||||
const head = require('./config/head');
|
const head = require('./config/head')
|
||||||
const plugins = require('./config/plugins');
|
const plugins = require('./config/plugins')
|
||||||
const themeConfig = require('./config/themeConfig');
|
const themeConfig = require('./config/themeConfig')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
title: 'Vue Select',
|
title: 'Vue Select',
|
||||||
@@ -9,5 +9,4 @@ module.exports = {
|
|||||||
head,
|
head,
|
||||||
plugins,
|
plugins,
|
||||||
themeConfig,
|
themeConfig,
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,57 +1,67 @@
|
|||||||
const isDeployPreview = require('./isDeployPreview');
|
const isDeployPreview = require('./isDeployPreview')
|
||||||
const meta = require('./meta');
|
const meta = require('./meta')
|
||||||
|
|
||||||
const head = [
|
const head = [
|
||||||
[
|
[
|
||||||
'link',
|
'link',
|
||||||
{
|
{
|
||||||
href: '//fonts.googleapis.com/css?family=Source+Sans+Pro:400,600|Roboto Mono',
|
href:
|
||||||
|
'//fonts.googleapis.com/css?family=Source+Sans+Pro:400,600|Roboto Mono',
|
||||||
rel: 'stylesheet',
|
rel: 'stylesheet',
|
||||||
type: 'text/css',
|
type: 'text/css',
|
||||||
}],
|
},
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'link',
|
'link',
|
||||||
{
|
{
|
||||||
href: '//fonts.googleapis.com/css?family=Dosis:300&text=Vue Select',
|
href: '//fonts.googleapis.com/css?family=Dosis:300&text=Vue Select',
|
||||||
rel: 'stylesheet',
|
rel: 'stylesheet',
|
||||||
type: 'text/css',
|
type: 'text/css',
|
||||||
}],
|
},
|
||||||
['link', {rel: 'icon', href: `/vue-logo.png`}],
|
],
|
||||||
['meta', {name: 'theme-color', content: '#3eaf7c'}],
|
['link', { rel: 'icon', href: `/vue-logo.png` }],
|
||||||
['meta', {name: 'apple-mobile-web-app-capable', content: 'yes'}],
|
['meta', { name: 'theme-color', content: '#3eaf7c' }],
|
||||||
['meta', {name: 'apple-mobile-web-app-status-bar-style', content: 'black'}],
|
['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }],
|
||||||
|
['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }],
|
||||||
[
|
[
|
||||||
'link',
|
'link',
|
||||||
{rel: 'apple-touch-icon', href: `/icons/apple-touch-icon-152x152.png`}],
|
{ rel: 'apple-touch-icon', href: `/icons/apple-touch-icon-152x152.png` },
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'link',
|
'link',
|
||||||
{rel: 'mask-icon', href: '/icons/safari-pinned-tab.svg', color: '#3eaf7c'}],
|
{
|
||||||
|
rel: 'mask-icon',
|
||||||
|
href: '/icons/safari-pinned-tab.svg',
|
||||||
|
color: '#3eaf7c',
|
||||||
|
},
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'meta',
|
'meta',
|
||||||
{
|
{
|
||||||
name: 'msapplication-TileImage',
|
name: 'msapplication-TileImage',
|
||||||
content: '/icons/msapplication-icon-144x144.png',
|
content: '/icons/msapplication-icon-144x144.png',
|
||||||
}],
|
},
|
||||||
['meta', {name: 'msapplication-TileColor', content: '#000000'}],
|
],
|
||||||
['meta', {name: 'title', content: meta.title}],
|
['meta', { name: 'msapplication-TileColor', content: '#000000' }],
|
||||||
['meta', {name: 'description', content: meta.description}],
|
['meta', { name: 'title', content: meta.title }],
|
||||||
['link', {rel: 'icon', href: meta.icon, type: 'image/png'}],
|
['meta', { name: 'description', content: meta.description }],
|
||||||
['meta', {property: 'og:image', content: meta.icon}],
|
['link', { rel: 'icon', href: meta.icon, type: 'image/png' }],
|
||||||
['meta', {property: 'twitter:image', content: meta.icon}],
|
['meta', { property: 'og:image', content: meta.icon }],
|
||||||
['meta', {name: 'description', content: meta.description}],
|
['meta', { property: 'twitter:image', content: meta.icon }],
|
||||||
['meta', {property: 'og:description', content: ''}],
|
['meta', { name: 'description', content: meta.description }],
|
||||||
['meta', {property: 'twitter:description', content: meta.description}],
|
['meta', { property: 'og:description', content: '' }],
|
||||||
['meta', {property: 'twitter:title', content: meta.title}],
|
['meta', { property: 'twitter:description', content: meta.description }],
|
||||||
['meta', {property: 'og:title', content: meta.title}],
|
['meta', { property: 'twitter:title', content: meta.title }],
|
||||||
['meta', {property: 'og:site_name', content: meta.title}],
|
['meta', { property: 'og:title', content: meta.title }],
|
||||||
['meta', {property: 'og:url', content: meta.url}],
|
['meta', { property: 'og:site_name', content: meta.title }],
|
||||||
];
|
['meta', { property: 'og:url', content: meta.url }],
|
||||||
|
]
|
||||||
|
|
||||||
if (isDeployPreview) {
|
if (isDeployPreview) {
|
||||||
head.push(
|
head.push(
|
||||||
['meta', {name: 'robots', content: 'noindex'}],
|
['meta', { name: 'robots', content: 'noindex' }],
|
||||||
['meta', {name: 'googlebot', content: 'noindex'}],
|
['meta', { name: 'googlebot', content: 'noindex' }]
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = head;
|
module.exports = head
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
module.exports = process.env.hasOwnProperty('DEPLOY_PREVIEW');
|
module.exports = process.env.hasOwnProperty('DEPLOY_PREVIEW')
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
title: 'Vue Select | VueJS Select2/Chosen Component',
|
title: 'Vue Select | VueJS Select2/Chosen Component',
|
||||||
description: 'Everything you wish the HTML select element could do, wrapped up into a lightweight, extensible Vue component.',
|
description:
|
||||||
|
'Everything you wish the HTML select element could do, wrapped up into a lightweight, extensible Vue component.',
|
||||||
url: 'https://vue-select.org',
|
url: 'https://vue-select.org',
|
||||||
icon: '/vue-logo.png'
|
icon: '/vue-logo.png',
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const isDeployPreview = require("./isDeployPreview");
|
const isDeployPreview = require('./isDeployPreview')
|
||||||
|
|
||||||
module.exports = [
|
module.exports = [
|
||||||
[
|
[
|
||||||
"@vuepress/google-analytics",
|
'@vuepress/google-analytics',
|
||||||
{
|
{
|
||||||
ga: isDeployPreview ? "" : "UA-12818324-8"
|
ga: isDeployPreview ? '' : 'UA-12818324-8',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"@vuepress/pwa",
|
'@vuepress/pwa',
|
||||||
{
|
{
|
||||||
serviceWorker: false,
|
serviceWorker: false,
|
||||||
updatePopup: true
|
updatePopup: true,
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"@vuepress/plugin-register-components",
|
'@vuepress/plugin-register-components',
|
||||||
"@vuepress/plugin-active-header-links",
|
'@vuepress/plugin-active-header-links',
|
||||||
"@vuepress/plugin-search",
|
'@vuepress/plugin-search',
|
||||||
"@vuepress/plugin-nprogress",
|
'@vuepress/plugin-nprogress',
|
||||||
require('../github/index')
|
require('../github/index'),
|
||||||
];
|
]
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ module.exports = {
|
|||||||
repo: 'sagalbot/vue-select',
|
repo: 'sagalbot/vue-select',
|
||||||
editLinks: true,
|
editLinks: true,
|
||||||
docsDir: 'docs',
|
docsDir: 'docs',
|
||||||
nav: [
|
nav: [{ text: 'Sandbox', link: '/sandbox' }],
|
||||||
{text: 'Sandbox', link: '/sandbox'},
|
|
||||||
],
|
|
||||||
sidebar: {
|
sidebar: {
|
||||||
'/': [
|
'/': [
|
||||||
{
|
{
|
||||||
@@ -75,4 +73,4 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
import vSelect from '../../src/components/Select';
|
import vSelect from '../../src/components/Select'
|
||||||
|
|
||||||
export default ({Vue, options, router, siteData}) => {
|
export default ({ Vue, options, router, siteData }) => {
|
||||||
Vue.component('v-select', vSelect);
|
Vue.component('v-select', vSelect)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove service workers.
|
* Remove service workers.
|
||||||
*/
|
*/
|
||||||
if (typeof navigator !== 'undefined' && 'serviceWorker' in navigator) {
|
if (typeof navigator !== 'undefined' && 'serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.getRegistrations().then(registrations => {
|
navigator.serviceWorker.getRegistrations().then((registrations) => {
|
||||||
registrations.forEach(registration => {
|
registrations.forEach((registration) => {
|
||||||
registration
|
registration
|
||||||
.unregister()
|
.unregister()
|
||||||
.then(() => console.log('Service worker unregistered.'))
|
.then(() => console.log('Service worker unregistered.'))
|
||||||
.catch(() => console.log('Error unregistering service worker.'));
|
.catch(() => console.log('Error unregistering service worker.'))
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
require("dotenv").config();
|
require('dotenv').config()
|
||||||
const axios = require("axios");
|
const axios = require('axios')
|
||||||
const { graphql } = require("@octokit/graphql");
|
const { graphql } = require('@octokit/graphql')
|
||||||
|
|
||||||
module.exports = async () => ({
|
module.exports = async () => ({
|
||||||
name: "constants.js",
|
name: 'constants.js',
|
||||||
content: `
|
content: `
|
||||||
export const SPONSORS = ${JSON.stringify(await getSponsors())};
|
export const SPONSORS = ${JSON.stringify(await getSponsors())};
|
||||||
export const CONTRIBUTORS = ${JSON.stringify(await getContributors())};
|
export const CONTRIBUTORS = ${JSON.stringify(await getContributors())};
|
||||||
`
|
`,
|
||||||
});
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a list of vue select contributors.
|
* Get a list of vue select contributors.
|
||||||
@@ -16,10 +16,10 @@ module.exports = async () => ({
|
|||||||
*/
|
*/
|
||||||
async function getContributors() {
|
async function getContributors() {
|
||||||
const { data } = await axios.get(
|
const { data } = await axios.get(
|
||||||
"https://api.github.com/repos/sagalbot/vue-select/contributors?per_page=100"
|
'https://api.github.com/repos/sagalbot/vue-select/contributors?per_page=100'
|
||||||
);
|
)
|
||||||
|
|
||||||
return data;
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,17 +49,17 @@ async function getSponsors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { user } = await graphql(query, {
|
const { user } = await graphql(query, {
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `token ${process.env.GITHUB_TOKEN || ""}`
|
authorization: `token ${process.env.GITHUB_TOKEN || ''}`,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
return user.sponsorshipsAsMaintainer.nodes;
|
return user.sponsorshipsAsMaintainer.nodes
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`${e.status} ${e.name} - Couldn't fetch sponsor data.`);
|
console.log(`${e.status} ${e.name} - Couldn't fetch sponsor data.`)
|
||||||
return [];
|
return []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const clientDynamicModules = require('./clientDynamicModules');
|
const clientDynamicModules = require('./clientDynamicModules')
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
clientDynamicModules: async () => await clientDynamicModules(),
|
clientDynamicModules: async () => await clientDynamicModules(),
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -3,19 +3,6 @@
|
|||||||
* @see https://ethical-ad-client.readthedocs.io/en/latest/
|
* @see https://ethical-ad-client.readthedocs.io/en/latest/
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
render(h) {
|
|
||||||
return h("div", {
|
|
||||||
attrs: {
|
|
||||||
id: "ads",
|
|
||||||
"data-ea-publisher": "vue-select",
|
|
||||||
"data-ea-type": "image"
|
|
||||||
},
|
|
||||||
class: "flat horizontal"
|
|
||||||
});
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.load();
|
|
||||||
},
|
|
||||||
watch: {
|
watch: {
|
||||||
$route(to, from) {
|
$route(to, from) {
|
||||||
if (
|
if (
|
||||||
@@ -23,24 +10,37 @@ export default {
|
|||||||
// Only reload if the ad has been loaded
|
// Only reload if the ad has been loaded
|
||||||
// otherwise it's possible that the script is appended but
|
// otherwise it's possible that the script is appended but
|
||||||
// the ads are not loaded yet. This would result in duplicated ads.
|
// the ads are not loaded yet. This would result in duplicated ads.
|
||||||
[...this.$el.classList].includes("loaded")
|
[...this.$el.classList].includes('loaded')
|
||||||
) {
|
) {
|
||||||
this.$el.innerHTML = "";
|
this.$el.innerHTML = ''
|
||||||
this.$el.classList.remove("loaded");
|
this.$el.classList.remove('loaded')
|
||||||
this.load();
|
this.load()
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.load()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
load() {
|
load() {
|
||||||
const s = document.createElement("script");
|
const s = document.createElement('script')
|
||||||
s.id = "_ads_js";
|
s.id = '_ads_js'
|
||||||
s.src = `https://media.ethicalads.io/media/client/ethicalads.min.js`;
|
s.src = `https://media.ethicalads.io/media/client/ethicalads.min.js`
|
||||||
s.async = "async";
|
s.async = 'async'
|
||||||
this.$el.appendChild(s);
|
this.$el.appendChild(s)
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
render(h) {
|
||||||
|
return h('div', {
|
||||||
|
attrs: {
|
||||||
|
id: 'ads',
|
||||||
|
'data-ea-publisher': 'vue-select',
|
||||||
|
'data-ea-type': 'image',
|
||||||
|
},
|
||||||
|
class: 'flat horizontal',
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -51,4 +51,4 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 264px;
|
min-height: 264px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
extend: '@vuepress/theme-default',
|
extend: '@vuepress/theme-default',
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import ParentLayout from "@parent-theme/layouts/Layout.vue";
|
import ParentLayout from '@parent-theme/layouts/Layout.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ParentLayout,
|
ParentLayout,
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
+162
-98
@@ -1,111 +1,175 @@
|
|||||||
export default () => {
|
export default () => {
|
||||||
|
document.getElementsByClassName ||
|
||||||
|
(document.getElementsByClassName = function (e) {
|
||||||
|
var n,
|
||||||
|
t,
|
||||||
|
r,
|
||||||
|
a = document,
|
||||||
|
o = []
|
||||||
|
if (a.querySelectorAll) return a.querySelectorAll('.' + e)
|
||||||
|
if (a.evaluate)
|
||||||
|
for (
|
||||||
|
t = ".//*[contains(concat(' ', @class, ' '), ' " + e + " ')]",
|
||||||
|
n = a.evaluate(t, a, null, 0, null);
|
||||||
|
(r = n.iterateNext());
|
||||||
|
|
||||||
document.getElementsByClassName || (document.getElementsByClassName = function (e) {
|
)
|
||||||
var n, t, r, a = document, o = [];
|
o.push(r)
|
||||||
if (a.querySelectorAll) return a.querySelectorAll('.' + e);
|
else
|
||||||
if (a.evaluate) for (t = './/*[contains(concat(\' \', @class, \' \'), \' ' + e + ' \')]', n = a.evaluate(t, a,
|
for (
|
||||||
null, 0,
|
n = a.getElementsByTagName('*'),
|
||||||
null); r = n.iterateNext();) o.push(r); else for (n = a.getElementsByTagName('*'), t = new RegExp(
|
t = new RegExp('(^|\\s)' + e + '(\\s|$)'),
|
||||||
'(^|\\s)' + e + '(\\s|$)'), r = 0; r < n.length; r++) t.test(n[r].className) && o.push(n[r]);
|
r = 0;
|
||||||
return o;
|
r < n.length;
|
||||||
}), function () {
|
r++
|
||||||
function e () {
|
)
|
||||||
function e () {
|
t.test(n[r].className) && o.push(n[r])
|
||||||
for (var e = document.getElementsByClassName('codepen'), t = e.length - 1; t > -1; t--) {
|
return o
|
||||||
var u = a(e[t]);
|
}),
|
||||||
if (0 !== Object.keys(u).length && (u = o(u), u.user = n(u, e[t]), r(u))) {
|
(function () {
|
||||||
var c = i(u), l = s(u, c);
|
function e() {
|
||||||
f(e[t], l);
|
function e() {
|
||||||
|
for (
|
||||||
|
var e = document.getElementsByClassName('codepen'),
|
||||||
|
t = e.length - 1;
|
||||||
|
t > -1;
|
||||||
|
t--
|
||||||
|
) {
|
||||||
|
var u = a(e[t])
|
||||||
|
if (
|
||||||
|
0 !== Object.keys(u).length &&
|
||||||
|
((u = o(u)), (u.user = n(u, e[t])), r(u))
|
||||||
|
) {
|
||||||
|
var c = i(u),
|
||||||
|
l = s(u, c)
|
||||||
|
f(e[t], l)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
m()
|
||||||
}
|
}
|
||||||
m();
|
|
||||||
}
|
|
||||||
|
|
||||||
function n (e, n) {
|
function n(e, n) {
|
||||||
if ('string' == typeof e.user) return e.user;
|
if ('string' == typeof e.user) return e.user
|
||||||
for (var t = 0, r = n.children.length; t < r; t++) {
|
for (var t = 0, r = n.children.length; t < r; t++) {
|
||||||
var a = n.children[t], o = a.href || '', i = o.match(/codepen\.(io|dev)\/(\w+)\/pen\//i);
|
var a = n.children[t],
|
||||||
if (i) return i[2];
|
o = a.href || '',
|
||||||
|
i = o.match(/codepen\.(io|dev)\/(\w+)\/pen\//i)
|
||||||
|
if (i) return i[2]
|
||||||
|
}
|
||||||
|
return 'anon'
|
||||||
}
|
}
|
||||||
return 'anon';
|
|
||||||
}
|
|
||||||
|
|
||||||
function r (e) {return e['slug-hash'];}
|
function r(e) {
|
||||||
|
return e['slug-hash']
|
||||||
function a (e) {
|
|
||||||
for (var n = {}, t = e.attributes, r = 0, a = t.length; r < a; r++) {
|
|
||||||
var o = t[r].name;
|
|
||||||
0 === o.indexOf('data-') && (n[o.replace('data-', '')] = t[r].value);
|
|
||||||
}
|
}
|
||||||
return n;
|
|
||||||
|
function a(e) {
|
||||||
|
for (var n = {}, t = e.attributes, r = 0, a = t.length; r < a; r++) {
|
||||||
|
var o = t[r].name
|
||||||
|
0 === o.indexOf('data-') && (n[o.replace('data-', '')] = t[r].value)
|
||||||
|
}
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
function o(e) {
|
||||||
|
return (
|
||||||
|
e.href && (e['slug-hash'] = e.href),
|
||||||
|
e.type && (e['default-tab'] = e.type),
|
||||||
|
e.safe &&
|
||||||
|
('true' === e.safe
|
||||||
|
? (e.animations = 'run')
|
||||||
|
: (e.animations = 'stop-after-5')),
|
||||||
|
e
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function i(e) {
|
||||||
|
var n = u(e),
|
||||||
|
t = e.user ? e.user : 'anon',
|
||||||
|
r = '?' + l(e),
|
||||||
|
a = e.preview && 'true' === e.preview ? 'embed/preview' : 'embed',
|
||||||
|
o = [n, t, a, e['slug-hash'] + r].join('/')
|
||||||
|
return o.replace(/\/\//g, '//')
|
||||||
|
}
|
||||||
|
|
||||||
|
function u(e) {
|
||||||
|
return e.host
|
||||||
|
? c(e.host)
|
||||||
|
: 'file:' === document.location.protocol
|
||||||
|
? 'https://codepen.io'
|
||||||
|
: '//codepen.io'
|
||||||
|
}
|
||||||
|
|
||||||
|
function c(e) {
|
||||||
|
return e.match(/^\/\//) || !e.match(/https?:/)
|
||||||
|
? document.location.protocol + '//' + e
|
||||||
|
: e
|
||||||
|
}
|
||||||
|
|
||||||
|
function l(e) {
|
||||||
|
var n = ''
|
||||||
|
for (var t in e)
|
||||||
|
'' !== n && (n += '&'), (n += t + '=' + encodeURIComponent(e[t]))
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
|
function s(e, n) {
|
||||||
|
var r
|
||||||
|
e['pen-title']
|
||||||
|
? (r = e['pen-title'])
|
||||||
|
: ((r = 'CodePen Embed ' + t), t++)
|
||||||
|
var a = {
|
||||||
|
id: 'cp_embed_' + e['slug-hash'].replace('/', '_'),
|
||||||
|
src: n,
|
||||||
|
scrolling: 'no',
|
||||||
|
frameborder: '0',
|
||||||
|
height: d(e),
|
||||||
|
allowTransparency: 'true',
|
||||||
|
allowfullscreen: 'true',
|
||||||
|
allowpaymentrequest: 'true',
|
||||||
|
name: 'CodePen Embed',
|
||||||
|
title: r,
|
||||||
|
class: 'cp_embed_iframe ' + (e['class'] ? e['class'] : ''),
|
||||||
|
style: 'width: ' + p + '; overflow: hidden;',
|
||||||
|
},
|
||||||
|
o = '<iframe '
|
||||||
|
for (var i in a) o += i + '="' + a[i] + '" '
|
||||||
|
return (o += '></iframe>')
|
||||||
|
}
|
||||||
|
|
||||||
|
function d(e) {
|
||||||
|
return e.height ? e.height : 300
|
||||||
|
}
|
||||||
|
|
||||||
|
function f(e, n) {
|
||||||
|
if (e.parentNode) {
|
||||||
|
var t = document.createElement('div')
|
||||||
|
;(t.className = 'cp_embed_wrapper'),
|
||||||
|
(t.innerHTML = n),
|
||||||
|
e.parentNode.replaceChild(t, e)
|
||||||
|
} else e.innerHTML = n
|
||||||
|
}
|
||||||
|
|
||||||
|
function m() {
|
||||||
|
'function' == typeof __CodePenIFrameAddedToPage &&
|
||||||
|
__CodePenIFrameAddedToPage()
|
||||||
|
}
|
||||||
|
|
||||||
|
var p = '100%'
|
||||||
|
e()
|
||||||
}
|
}
|
||||||
|
|
||||||
function o (e) {
|
function n(e) {
|
||||||
return e.href && (e['slug-hash'] = e.href), e.type && (e['default-tab'] = e.type), e.safe &&
|
;/in/.test(document.readyState)
|
||||||
('true' === e.safe ? e.animations = 'run' : e.animations = 'stop-after-5'), e;
|
? setTimeout('window.__cp_domReady(' + e + ')', 9)
|
||||||
|
: e()
|
||||||
}
|
}
|
||||||
|
|
||||||
function i (e) {
|
var t = 1
|
||||||
var n = u(e), t = e.user ? e.user : 'anon', r = '?' + l(e),
|
;(window.__cp_domReady = n),
|
||||||
a = e.preview && 'true' === e.preview ? 'embed/preview' : 'embed',
|
(window.__CPEmbed = e),
|
||||||
o = [n, t, a, e['slug-hash'] + r].join('/');
|
n(function () {
|
||||||
return o.replace(/\/\//g, '//');
|
new __CPEmbed()
|
||||||
}
|
})
|
||||||
|
})()
|
||||||
function u (e) {
|
|
||||||
return e.host ? c(e.host) : 'file:' === document.location.protocol
|
|
||||||
? 'https://codepen.io'
|
|
||||||
: '//codepen.io';
|
|
||||||
}
|
|
||||||
|
|
||||||
function c (e) {return e.match(/^\/\//) || !e.match(/https?:/) ? document.location.protocol + '//' + e : e;}
|
|
||||||
|
|
||||||
function l (e) {
|
|
||||||
var n = '';
|
|
||||||
for (var t in e) '' !== n && (n += '&'), n += t + '=' + encodeURIComponent(e[t]);
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
function s (e, n) {
|
|
||||||
var r;
|
|
||||||
e['pen-title'] ? r = e['pen-title'] : (r = 'CodePen Embed ' + t, t++);
|
|
||||||
var a = {
|
|
||||||
id: 'cp_embed_' + e['slug-hash'].replace('/', '_'),
|
|
||||||
src: n,
|
|
||||||
scrolling: 'no',
|
|
||||||
frameborder: '0',
|
|
||||||
height: d(e),
|
|
||||||
allowTransparency: 'true',
|
|
||||||
allowfullscreen: 'true',
|
|
||||||
allowpaymentrequest: 'true',
|
|
||||||
name: 'CodePen Embed',
|
|
||||||
title: r,
|
|
||||||
'class': 'cp_embed_iframe ' + (e['class'] ? e['class'] : ''),
|
|
||||||
style: 'width: ' + p + '; overflow: hidden;',
|
|
||||||
}, o = '<iframe ';
|
|
||||||
for (var i in a) o += i + '="' + a[i] + '" ';
|
|
||||||
return o += '></iframe>';
|
|
||||||
}
|
|
||||||
|
|
||||||
function d (e) {return e.height ? e.height : 300;}
|
|
||||||
|
|
||||||
function f (e, n) {
|
|
||||||
if (e.parentNode) {
|
|
||||||
var t = document.createElement('div');
|
|
||||||
t.className = 'cp_embed_wrapper', t.innerHTML = n, e.parentNode.replaceChild(t, e);
|
|
||||||
} else e.innerHTML = n;
|
|
||||||
}
|
|
||||||
|
|
||||||
function m () {'function' == typeof __CodePenIFrameAddedToPage && __CodePenIFrameAddedToPage();}
|
|
||||||
|
|
||||||
var p = '100%';
|
|
||||||
e();
|
|
||||||
}
|
|
||||||
|
|
||||||
function n (e) {/in/.test(document.readyState) ? setTimeout('window.__cp_domReady(' + e + ')', 9) : e();}
|
|
||||||
|
|
||||||
var t = 1;
|
|
||||||
window.__cp_domReady = n, window.__CPEmbed = e, n(function () {new __CPEmbed;});
|
|
||||||
}();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -5,4 +5,4 @@ module.exports = {
|
|||||||
preset: 'default',
|
preset: 'default',
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
};
|
}
|
||||||
|
|||||||
+14
-14
@@ -1,23 +1,23 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
release: {
|
release: {
|
||||||
branch: "master"
|
branch: 'master',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
"@semantic-release/npm",
|
'@semantic-release/npm',
|
||||||
"@semantic-release/commit-analyzer",
|
'@semantic-release/commit-analyzer',
|
||||||
"@semantic-release/release-notes-generator",
|
'@semantic-release/release-notes-generator',
|
||||||
[
|
[
|
||||||
"@semantic-release/github",
|
'@semantic-release/github',
|
||||||
{
|
{
|
||||||
assets: ["dist/**"]
|
assets: ['dist/**'],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
"@semantic-release/git",
|
'@semantic-release/git',
|
||||||
{
|
{
|
||||||
assets: ["package.json"],
|
assets: ['package.json'],
|
||||||
message: "chore(🚀): ${nextRelease.version}"
|
message: 'chore(🚀): ${nextRelease.version}',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
||||||
<path d="M6.895455 5l2.842897-2.842898c.348864-.348863.348864-.914488 0-1.263636L9.106534.261648c-.348864-.348864-.914489-.348864-1.263636 0L5 3.104545 2.157102.261648c-.348863-.348864-.914488-.348864-1.263636 0L.261648.893466c-.348864.348864-.348864.914489 0 1.263636L3.104545 5 .261648 7.842898c-.348864.348863-.348864.914488 0 1.263636l.631818.631818c.348864.348864.914773.348864 1.263636 0L5 6.895455l2.842898 2.842897c.348863.348864.914772.348864 1.263636 0l.631818-.631818c.348864-.348864.348864-.914489 0-1.263636L6.895455 5z"/>
|
<path
|
||||||
|
d="M6.895455 5l2.842897-2.842898c.348864-.348863.348864-.914488 0-1.263636L9.106534.261648c-.348864-.348864-.914489-.348864-1.263636 0L5 3.104545 2.157102.261648c-.348863-.348864-.914488-.348864-1.263636 0L.261648.893466c-.348864.348864-.348864.914489 0 1.263636L3.104545 5 .261648 7.842898c-.348864.348863-.348864.914488 0 1.263636l.631818.631818c.348864.348864.914773.348864 1.263636 0L5 6.895455l2.842898 2.842897c.348863.348864.914772.348864 1.263636 0l.631818-.631818c.348864-.348864.348864-.914489 0-1.263636L6.895455 5z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="10">
|
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="10">
|
||||||
<path d="M9.211364 7.59931l4.48338-4.867229c.407008-.441854.407008-1.158247 0-1.60046l-.73712-.80023c-.407008-.441854-1.066904-.441854-1.474243 0L7 5.198617 2.51662.33139c-.407008-.441853-1.066904-.441853-1.474243 0l-.737121.80023c-.407008.441854-.407008 1.158248 0 1.600461l4.48338 4.867228L7 10l2.211364-2.40069z"/>
|
<path
|
||||||
|
d="M9.211364 7.59931l4.48338-4.867229c.407008-.441854.407008-1.158247 0-1.60046l-.73712-.80023c-.407008-.441854-1.066904-.441854-1.474243 0L7 5.198617 2.51662.33139c-.407008-.441853-1.066904-.441853-1.474243 0l-.737121.80023c-.407008.441854-.407008 1.158248 0 1.600461l4.48338 4.867228L7 10l2.211364-2.40069z"
|
||||||
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+1199
-1100
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
|||||||
import Deselect from './Deselect';
|
import Deselect from './Deselect'
|
||||||
import OpenIndicator from './OpenIndicator';
|
import OpenIndicator from './OpenIndicator'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Deselect,
|
Deselect,
|
||||||
OpenIndicator
|
OpenIndicator,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +1,34 @@
|
|||||||
export default {
|
export default {
|
||||||
inserted (el, bindings, {context}) {
|
inserted(el, bindings, { context }) {
|
||||||
if (context.appendToBody) {
|
if (context.appendToBody) {
|
||||||
const {height, top, left, width} = context.$refs.toggle.getBoundingClientRect();
|
const {
|
||||||
let scrollX = window.scrollX || window.pageXOffset;
|
height,
|
||||||
let scrollY = window.scrollY || window.pageYOffset;
|
top,
|
||||||
el.unbindPosition = context.calculatePosition(el, context, {
|
left,
|
||||||
width: width + 'px',
|
width,
|
||||||
left: (scrollX + left) + 'px',
|
} = context.$refs.toggle.getBoundingClientRect()
|
||||||
top: (scrollY + top + height) + 'px',
|
|
||||||
});
|
|
||||||
|
|
||||||
document.body.appendChild(el);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
unbind (el, bindings, {context}) {
|
let scrollX = window.scrollX || window.pageXOffset
|
||||||
if (context.appendToBody) {
|
let scrollY = window.scrollY || window.pageYOffset
|
||||||
if (el.unbindPosition && typeof el.unbindPosition === 'function') {
|
|
||||||
el.unbindPosition();
|
el.unbindPosition = context.calculatePosition(el, context, {
|
||||||
}
|
width: width + 'px',
|
||||||
if (el.parentNode) {
|
left: scrollX + left + 'px',
|
||||||
el.parentNode.removeChild(el);
|
top: scrollY + top + height + 'px',
|
||||||
}
|
})
|
||||||
}
|
|
||||||
},
|
document.body.appendChild(el)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
unbind(el, bindings, { context }) {
|
||||||
|
if (context.appendToBody) {
|
||||||
|
if (el.unbindPosition && typeof el.unbindPosition === 'function') {
|
||||||
|
el.unbindPosition()
|
||||||
|
}
|
||||||
|
if (el.parentNode) {
|
||||||
|
el.parentNode.removeChild(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-10
@@ -11,10 +11,10 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data() {
|
||||||
return {
|
return {
|
||||||
mutableLoading: false,
|
mutableLoading: false,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
@@ -27,8 +27,8 @@ export default {
|
|||||||
*
|
*
|
||||||
* @emits search
|
* @emits search
|
||||||
*/
|
*/
|
||||||
search () {
|
search() {
|
||||||
this.$emit('search', this.search, this.toggleLoading);
|
this.$emit('search', this.search, this.toggleLoading)
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,8 +36,8 @@ export default {
|
|||||||
* mutable loading value.
|
* mutable loading value.
|
||||||
* @param val
|
* @param val
|
||||||
*/
|
*/
|
||||||
loading (val) {
|
loading(val) {
|
||||||
this.mutableLoading = val;
|
this.mutableLoading = val
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -49,11 +49,11 @@ export default {
|
|||||||
* @param toggle Boolean
|
* @param toggle Boolean
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
toggleLoading (toggle = null) {
|
toggleLoading(toggle = null) {
|
||||||
if (toggle == null) {
|
if (toggle == null) {
|
||||||
return (this.mutableLoading = !this.mutableLoading);
|
return (this.mutableLoading = !this.mutableLoading)
|
||||||
}
|
}
|
||||||
return (this.mutableLoading = toggle);
|
return (this.mutableLoading = toggle)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|||||||
+13
-13
@@ -2,14 +2,14 @@ export default {
|
|||||||
props: {
|
props: {
|
||||||
autoscroll: {
|
autoscroll: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: true
|
default: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
watch: {
|
watch: {
|
||||||
typeAheadPointer() {
|
typeAheadPointer() {
|
||||||
if (this.autoscroll) {
|
if (this.autoscroll) {
|
||||||
this.maybeAdjustScroll();
|
this.maybeAdjustScroll()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -23,17 +23,17 @@ export default {
|
|||||||
*/
|
*/
|
||||||
maybeAdjustScroll() {
|
maybeAdjustScroll() {
|
||||||
const optionEl =
|
const optionEl =
|
||||||
this.$refs.dropdownMenu?.children[this.typeAheadPointer] || false;
|
this.$refs.dropdownMenu?.children[this.typeAheadPointer] || false
|
||||||
|
|
||||||
if (optionEl) {
|
if (optionEl) {
|
||||||
const bounds = this.getDropdownViewport();
|
const bounds = this.getDropdownViewport()
|
||||||
const { top, bottom, height } = optionEl.getBoundingClientRect();
|
const { top, bottom, height } = optionEl.getBoundingClientRect()
|
||||||
|
|
||||||
if (top < bounds.top) {
|
if (top < bounds.top) {
|
||||||
return (this.$refs.dropdownMenu.scrollTop = optionEl.offsetTop);
|
return (this.$refs.dropdownMenu.scrollTop = optionEl.offsetTop)
|
||||||
} else if (bottom > bounds.bottom) {
|
} else if (bottom > bounds.bottom) {
|
||||||
return (this.$refs.dropdownMenu.scrollTop =
|
return (this.$refs.dropdownMenu.scrollTop =
|
||||||
optionEl.offsetTop - (bounds.height - height));
|
optionEl.offsetTop - (bounds.height - height))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -48,8 +48,8 @@ export default {
|
|||||||
: {
|
: {
|
||||||
height: 0,
|
height: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom: 0
|
bottom: 0,
|
||||||
};
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
typeAheadPointer: -1
|
typeAheadPointer: -1,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -9,11 +9,11 @@ export default {
|
|||||||
filteredOptions() {
|
filteredOptions() {
|
||||||
for (let i = 0; i < this.filteredOptions.length; i++) {
|
for (let i = 0; i < this.filteredOptions.length; i++) {
|
||||||
if (this.selectable(this.filteredOptions[i])) {
|
if (this.selectable(this.filteredOptions[i])) {
|
||||||
this.typeAheadPointer = i;
|
this.typeAheadPointer = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
@@ -25,8 +25,8 @@ export default {
|
|||||||
typeAheadUp() {
|
typeAheadUp() {
|
||||||
for (let i = this.typeAheadPointer - 1; i >= 0; i--) {
|
for (let i = this.typeAheadPointer - 1; i >= 0; i--) {
|
||||||
if (this.selectable(this.filteredOptions[i])) {
|
if (this.selectable(this.filteredOptions[i])) {
|
||||||
this.typeAheadPointer = i;
|
this.typeAheadPointer = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -37,10 +37,14 @@ export default {
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
typeAheadDown() {
|
typeAheadDown() {
|
||||||
for (let i = this.typeAheadPointer + 1; i < this.filteredOptions.length; i++) {
|
for (
|
||||||
|
let i = this.typeAheadPointer + 1;
|
||||||
|
i < this.filteredOptions.length;
|
||||||
|
i++
|
||||||
|
) {
|
||||||
if (this.selectable(this.filteredOptions[i])) {
|
if (this.selectable(this.filteredOptions[i])) {
|
||||||
this.typeAheadPointer = i;
|
this.typeAheadPointer = i
|
||||||
break;
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -51,11 +55,11 @@ export default {
|
|||||||
* @return {void}
|
* @return {void}
|
||||||
*/
|
*/
|
||||||
typeAheadSelect() {
|
typeAheadSelect() {
|
||||||
const typeAheadOption = this.filteredOptions[this.typeAheadPointer];
|
const typeAheadOption = this.filteredOptions[this.typeAheadPointer]
|
||||||
|
|
||||||
if (typeAheadOption) {
|
if (typeAheadOption) {
|
||||||
this.select(typeAheadOption);
|
this.select(typeAheadOption)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,15 @@
|
|||||||
* @return {string}
|
* @return {string}
|
||||||
*/
|
*/
|
||||||
function sortAndStringify(sortable) {
|
function sortAndStringify(sortable) {
|
||||||
const ordered = {};
|
const ordered = {}
|
||||||
|
|
||||||
Object.keys(sortable).sort().forEach(key => {
|
Object.keys(sortable)
|
||||||
ordered[key] = sortable[key];
|
.sort()
|
||||||
});
|
.forEach((key) => {
|
||||||
|
ordered[key] = sortable[key]
|
||||||
|
})
|
||||||
|
|
||||||
return JSON.stringify(ordered);
|
return JSON.stringify(ordered)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default sortAndStringify;
|
export default sortAndStringify
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
let idCount = 0;
|
let idCount = 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dead simple unique ID implementation.
|
* Dead simple unique ID implementation.
|
||||||
@@ -6,7 +6,7 @@ let idCount = 0;
|
|||||||
* @return {number}
|
* @return {number}
|
||||||
*/
|
*/
|
||||||
function uniqueId() {
|
function uniqueId() {
|
||||||
return ++idCount;
|
return ++idCount
|
||||||
}
|
}
|
||||||
|
|
||||||
export default uniqueId;
|
export default uniqueId
|
||||||
|
|||||||
+26
-26
@@ -1,6 +1,6 @@
|
|||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../src/components/Select.vue";
|
import VueSelect from '../src/components/Select.vue'
|
||||||
import Vue from 'vue';
|
import Vue from 'vue'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger a submit event on the search
|
* Trigger a submit event on the search
|
||||||
@@ -11,10 +11,10 @@ import Vue from 'vue';
|
|||||||
*/
|
*/
|
||||||
export const searchSubmit = (Wrapper, searchText = false) => {
|
export const searchSubmit = (Wrapper, searchText = false) => {
|
||||||
if (searchText) {
|
if (searchText) {
|
||||||
Wrapper.vm.search = searchText;
|
Wrapper.vm.search = searchText
|
||||||
}
|
}
|
||||||
Wrapper.find({ ref: "search" }).trigger("keydown.enter")
|
Wrapper.find({ ref: 'search' }).trigger('keydown.enter')
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Focus the input, enter some search text, hit return.
|
* Focus the input, enter some search text, hit return.
|
||||||
@@ -23,15 +23,15 @@ export const searchSubmit = (Wrapper, searchText = false) => {
|
|||||||
* @return {Promise<void>}
|
* @return {Promise<void>}
|
||||||
*/
|
*/
|
||||||
export const selectTag = async (Wrapper, searchText) => {
|
export const selectTag = async (Wrapper, searchText) => {
|
||||||
Wrapper.vm.$refs.search.focus();
|
Wrapper.vm.$refs.search.focus()
|
||||||
await Wrapper.vm.$nextTick();
|
await Wrapper.vm.$nextTick()
|
||||||
|
|
||||||
Wrapper.vm.search = searchText;
|
Wrapper.vm.search = searchText
|
||||||
await Wrapper.vm.$nextTick();
|
await Wrapper.vm.$nextTick()
|
||||||
|
|
||||||
Wrapper.find({ ref: "search" }).trigger("keydown.enter");
|
Wrapper.find({ ref: 'search' }).trigger('keydown.enter')
|
||||||
await Wrapper.vm.$nextTick();
|
await Wrapper.vm.$nextTick()
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new VueSelect instance with
|
* Create a new VueSelect instance with
|
||||||
@@ -40,8 +40,8 @@ export const selectTag = async (Wrapper, searchText) => {
|
|||||||
* @returns {Wrapper<Vue>}
|
* @returns {Wrapper<Vue>}
|
||||||
*/
|
*/
|
||||||
export const selectWithProps = (propsData = {}) => {
|
export const selectWithProps = (propsData = {}) => {
|
||||||
return shallowMount(VueSelect, { propsData });
|
return shallowMount(VueSelect, { propsData })
|
||||||
};
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a Wrapper with a v-select component.
|
* Returns a Wrapper with a v-select component.
|
||||||
@@ -56,9 +56,8 @@ export const mountDefault = (props = {}, options = {}) => {
|
|||||||
...props,
|
...props,
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
});
|
})
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a v-select component directly.
|
* Returns a v-select component directly.
|
||||||
@@ -68,11 +67,12 @@ export const mountDefault = (props = {}, options = {}) => {
|
|||||||
*/
|
*/
|
||||||
export const mountWithoutTestUtils = (props = {}, options = {}) => {
|
export const mountWithoutTestUtils = (props = {}, options = {}) => {
|
||||||
return new Vue({
|
return new Vue({
|
||||||
render: createEl => createEl('vue-select', {
|
components: { VueSelect },
|
||||||
ref: 'select',
|
render: (createEl) =>
|
||||||
props: {options: ['one', 'two', 'three'], ...props},
|
createEl('vue-select', {
|
||||||
...options
|
ref: 'select',
|
||||||
}),
|
props: { options: ['one', 'two', 'three'], ...props },
|
||||||
components: {VueSelect},
|
...options,
|
||||||
}).$mount().$refs.select;
|
}),
|
||||||
};
|
}).$mount().$refs.select
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
env: {
|
env: {
|
||||||
jest: true
|
jest: true,
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'import/no-extraneous-dependencies': 'off'
|
'import/no-extraneous-dependencies': 'off',
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,35 @@
|
|||||||
import { mountDefault } from "../helpers";
|
import { mountDefault } from '../helpers'
|
||||||
|
|
||||||
describe("Search Slot Scope", () => {
|
describe('Search Slot Scope', () => {
|
||||||
/**
|
/**
|
||||||
* @see https://www.w3.org/WAI/PF/aria/states_and_properties#aria-activedescendant
|
* @see https://www.w3.org/WAI/PF/aria/states_and_properties#aria-activedescendant
|
||||||
*/
|
*/
|
||||||
describe("aria-activedescendant", () => {
|
describe('aria-activedescendant', () => {
|
||||||
it("adds the active descendant attribute only when the dropdown is open and there is a typeAheadPointer value", async () => {
|
it('adds the active descendant attribute only when the dropdown is open and there is a typeAheadPointer value', async () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
Select.vm.scope.search.attributes["aria-activedescendant"]
|
Select.vm.scope.search.attributes['aria-activedescendant']
|
||||||
).toEqual(undefined);
|
).toEqual(undefined)
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
Select.vm.scope.search.attributes["aria-activedescendant"]
|
Select.vm.scope.search.attributes['aria-activedescendant']
|
||||||
).toEqual(undefined);
|
).toEqual(undefined)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("adds the active descendant attribute when there's a typeahead value and an open dropdown", async () => {
|
it("adds the active descendant attribute when there's a typeahead value and an open dropdown", async () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
Select.vm.scope.search.attributes["aria-activedescendant"]
|
Select.vm.scope.search.attributes['aria-activedescendant']
|
||||||
).toEqual(`vs${Select.vm.uid}__option-1`);
|
).toEqual(`vs${Select.vm.uid}__option-1`)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
+42
-42
@@ -1,65 +1,65 @@
|
|||||||
import { selectWithProps } from "../helpers";
|
import { selectWithProps } from '../helpers'
|
||||||
import { shallowMount } from '@vue/test-utils';
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import vSelect from '../../src/components/Select';
|
import vSelect from '../../src/components/Select'
|
||||||
|
|
||||||
describe("Asynchronous Loading", () => {
|
describe('Asynchronous Loading', () => {
|
||||||
it("can toggle the loading class", () => {
|
it('can toggle the loading class', () => {
|
||||||
const Select = selectWithProps();
|
const Select = selectWithProps()
|
||||||
|
|
||||||
Select.vm.toggleLoading();
|
Select.vm.toggleLoading()
|
||||||
expect(Select.vm.mutableLoading).toEqual(true);
|
expect(Select.vm.mutableLoading).toEqual(true)
|
||||||
|
|
||||||
Select.vm.toggleLoading(true);
|
Select.vm.toggleLoading(true)
|
||||||
expect(Select.vm.mutableLoading).toEqual(true);
|
expect(Select.vm.mutableLoading).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should trigger the search event when the search text changes", async () => {
|
it('should trigger the search event when the search text changes', async () => {
|
||||||
const Select = selectWithProps();
|
const Select = selectWithProps()
|
||||||
|
|
||||||
Select.vm.search = "foo";
|
Select.vm.search = 'foo'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
const events = Select.emitted("search");
|
const events = Select.emitted('search')
|
||||||
|
|
||||||
expect(events).toContainEqual(["foo", Select.vm.toggleLoading]);
|
expect(events).toContainEqual(['foo', Select.vm.toggleLoading])
|
||||||
expect(events.length).toEqual(1);
|
expect(events.length).toEqual(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should trigger the search event if the search text is empty", async () => {
|
it('should trigger the search event if the search text is empty', async () => {
|
||||||
const Select = selectWithProps();
|
const Select = selectWithProps()
|
||||||
|
|
||||||
Select.vm.search = "foo";
|
Select.vm.search = 'foo'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
Select.vm.search = "";
|
Select.vm.search = ''
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
const events = Select.emitted("search");
|
const events = Select.emitted('search')
|
||||||
|
|
||||||
expect(events).toContainEqual(["", Select.vm.toggleLoading]);
|
expect(events).toContainEqual(['', Select.vm.toggleLoading])
|
||||||
expect(events.length).toEqual(2);
|
expect(events.length).toEqual(2)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can set loading to false from the @search event callback", async () => {
|
it('can set loading to false from the @search event callback', async () => {
|
||||||
const Select = shallowMount(vSelect, {
|
const Select = shallowMount(vSelect, {
|
||||||
listeners: {
|
listeners: {
|
||||||
search: (search, loading) => {
|
search: (search, loading) => {
|
||||||
loading(false)
|
loading(false)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.mutableLoading = true;
|
Select.vm.mutableLoading = true
|
||||||
Select.vm.search = 'foo';
|
Select.vm.search = 'foo'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.mutableLoading).toEqual(false);
|
expect(Select.vm.mutableLoading).toEqual(false)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('will sync mutable loading with the loading prop', async () => {
|
it('will sync mutable loading with the loading prop', async () => {
|
||||||
const Select = selectWithProps({ loading: false });
|
const Select = selectWithProps({ loading: false })
|
||||||
Select.setProps({ loading: true });
|
Select.setProps({ loading: true })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.mutableLoading).toEqual(true);
|
expect(Select.vm.mutableLoading).toEqual(true)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,61 +1,61 @@
|
|||||||
import { mountDefault } from "../helpers";
|
import { mountDefault } from '../helpers'
|
||||||
|
|
||||||
describe("Automatic Scrolling", () => {
|
describe('Automatic Scrolling', () => {
|
||||||
it("should check if the scroll position needs to be adjusted on up arrow keyUp", async () => {
|
it('should check if the scroll position needs to be adjusted on up arrow keyUp', async () => {
|
||||||
// Given
|
// Given
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
const spy = jest.spyOn(Select.vm, "maybeAdjustScroll");
|
const spy = jest.spyOn(Select.vm, 'maybeAdjustScroll')
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
// When
|
// When
|
||||||
Select.find({ ref: "search" }).trigger("keydown.up");
|
Select.find({ ref: 'search' }).trigger('keydown.up')
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should check if the scroll position needs to be adjusted on down arrow keyUp", async () => {
|
it('should check if the scroll position needs to be adjusted on down arrow keyUp', async () => {
|
||||||
// Given
|
// Given
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
const spy = jest.spyOn(Select.vm, "maybeAdjustScroll");
|
const spy = jest.spyOn(Select.vm, 'maybeAdjustScroll')
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
// When
|
// When
|
||||||
Select.find({ ref: "search" }).trigger("keydown.down");
|
Select.find({ ref: 'search' }).trigger('keydown.down')
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should check if the scroll position needs to be adjusted when filtered options changes", async () => {
|
it('should check if the scroll position needs to be adjusted when filtered options changes', async () => {
|
||||||
// Given
|
// Given
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
const spy = jest.spyOn(Select.vm, "maybeAdjustScroll");
|
const spy = jest.spyOn(Select.vm, 'maybeAdjustScroll')
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
// When
|
// When
|
||||||
Select.vm.search = "two";
|
Select.vm.search = 'two'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(spy).toHaveBeenCalled();
|
expect(spy).toHaveBeenCalled()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not adjust scroll position when autoscroll is false", async () => {
|
it('should not adjust scroll position when autoscroll is false', async () => {
|
||||||
// Given
|
// Given
|
||||||
const Select = mountDefault({
|
const Select = mountDefault({
|
||||||
autoscroll: false
|
autoscroll: false,
|
||||||
});
|
})
|
||||||
const spy = jest.spyOn(Select.vm, "maybeAdjustScroll");
|
const spy = jest.spyOn(Select.vm, 'maybeAdjustScroll')
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
// When
|
// When
|
||||||
Select.vm.search = "two";
|
Select.vm.search = 'two'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(spy).toHaveBeenCalledTimes(0);
|
expect(spy).toHaveBeenCalledTimes(0)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,30 +1,28 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue'
|
||||||
import { selectWithProps } from '../helpers';
|
import { selectWithProps } from '../helpers'
|
||||||
|
|
||||||
describe('Components API', () => {
|
describe('Components API', () => {
|
||||||
|
|
||||||
it('swap the Deselect component', () => {
|
it('swap the Deselect component', () => {
|
||||||
const Deselect = Vue.component('Deselect', {
|
const Deselect = Vue.component('Deselect', {
|
||||||
render (createElement) {
|
render(createElement) {
|
||||||
return createElement('button', 'remove');
|
return createElement('button', 'remove')
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const Select = selectWithProps({components: {Deselect}});
|
const Select = selectWithProps({ components: { Deselect } })
|
||||||
|
|
||||||
expect(Select.contains(Deselect)).toBeTruthy();
|
expect(Select.contains(Deselect)).toBeTruthy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('swap the OpenIndicator component', () => {
|
it('swap the OpenIndicator component', () => {
|
||||||
const OpenIndicator = Vue.component('OpenIndicator', {
|
const OpenIndicator = Vue.component('OpenIndicator', {
|
||||||
render (createElement) {
|
render(createElement) {
|
||||||
return createElement('i', '^');
|
return createElement('i', '^')
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const Select = selectWithProps({components: {OpenIndicator}});
|
const Select = selectWithProps({ components: { OpenIndicator } })
|
||||||
|
|
||||||
expect(Select.contains(OpenIndicator)).toBeTruthy();
|
expect(Select.contains(OpenIndicator)).toBeTruthy()
|
||||||
});
|
})
|
||||||
|
})
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
import { searchSubmit, selectTag, selectWithProps } from "../helpers";
|
import { searchSubmit, selectTag, selectWithProps } from '../helpers'
|
||||||
|
|
||||||
describe("CreateOption When Tagging Is Enabled", () => {
|
describe('CreateOption When Tagging Is Enabled', () => {
|
||||||
it("can select the current search text as a string", async () => {
|
it('can select the current search text as a string', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: ["one", "two"],
|
options: ['one', 'two'],
|
||||||
createOption: option => "four"
|
createOption: (option) => 'four',
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
expect(Select.vm.selectedValue).toEqual(["four"]);
|
expect(Select.vm.selectedValue).toEqual(['four'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can select the current search text as an object", async () => {
|
it('can select the current search text as an object', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
value: null,
|
value: null,
|
||||||
options: [],
|
options: [],
|
||||||
label: "name",
|
label: 'name',
|
||||||
createOption: title => ({ name: title })
|
createOption: (title) => ({ name: title }),
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "two");
|
await selectTag(Select, 'two')
|
||||||
|
|
||||||
expect(Select.emitted("input")[0]).toEqual([{ name: "two" }]);
|
expect(Select.emitted('input')[0]).toEqual([{ name: 'two' }])
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,107 +1,107 @@
|
|||||||
import { mountDefault, selectWithProps } from '../helpers';
|
import { mountDefault, selectWithProps } from '../helpers'
|
||||||
|
|
||||||
describe("Removing values", () => {
|
describe('Removing values', () => {
|
||||||
it("can remove the given tag when its close icon is clicked", async () => {
|
it('can remove the given tag when its close icon is clicked', async () => {
|
||||||
const Select = selectWithProps({ multiple: true });
|
const Select = selectWithProps({ multiple: true })
|
||||||
Select.vm.$data._value = 'one';
|
Select.vm.$data._value = 'one'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
Select.find(".vs__deselect").trigger("click");
|
Select.find('.vs__deselect').trigger('click')
|
||||||
expect(Select.emitted().input).toEqual([[[]]]);
|
expect(Select.emitted().input).toEqual([[[]]])
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not remove tag when close icon is clicked and component is disabled", () => {
|
it('should not remove tag when close icon is clicked and component is disabled', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two", "three"],
|
options: ['one', 'two', 'three'],
|
||||||
multiple: true,
|
multiple: true,
|
||||||
disabled: true
|
disabled: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.find(".vs__deselect").trigger("click");
|
Select.find('.vs__deselect').trigger('click')
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should remove the last item in the value array on delete keypress when multiple is true", () => {
|
it('should remove the last item in the value array on delete keypress when multiple is true', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: ["one", "two", "three"]
|
options: ['one', 'two', 'three'],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = ["one", "two"];
|
Select.vm.$data._value = ['one', 'two']
|
||||||
|
|
||||||
Select.find('.vs__search').trigger('keydown.backspace')
|
Select.find('.vs__search').trigger('keydown.backspace')
|
||||||
|
|
||||||
expect(Select.emitted().input).toEqual([[['one']]]);
|
expect(Select.emitted().input).toEqual([[['one']]])
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should set value to null on delete keypress when multiple is false", () => {
|
it('should set value to null on delete keypress when multiple is false', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["one", "two", "three"]
|
options: ['one', 'two', 'three'],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = 'one';
|
Select.vm.$data._value = 'one'
|
||||||
|
|
||||||
Select.vm.maybeDeleteValue();
|
Select.vm.maybeDeleteValue()
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it('will not emit input event if value has not changed with backspace', () => {
|
it('will not emit input event if value has not changed with backspace', () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
Select.vm.$data._value = 'one';
|
Select.vm.$data._value = 'one'
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.backspace');
|
Select.find({ ref: 'search' }).trigger('keydown.backspace')
|
||||||
expect(Select.emitted().input.length).toBe(1);
|
expect(Select.emitted().input.length).toBe(1)
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.backspace');
|
Select.find({ ref: 'search' }).trigger('keydown.backspace')
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.backspace');
|
Select.find({ ref: 'search' }).trigger('keydown.backspace')
|
||||||
expect(Select.emitted().input.length).toBe(1);
|
expect(Select.emitted().input.length).toBe(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
describe("Clear button", () => {
|
describe('Clear button', () => {
|
||||||
it("should be displayed on single select when value is selected", () => {
|
it('should be displayed on single select when value is selected', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["foo", "bar"],
|
options: ['foo', 'bar'],
|
||||||
value: "foo"
|
value: 'foo',
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.showClearButton).toEqual(true);
|
expect(Select.vm.showClearButton).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not be displayed on multiple select", () => {
|
it('should not be displayed on multiple select', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["foo", "bar"],
|
options: ['foo', 'bar'],
|
||||||
value: "foo",
|
value: 'foo',
|
||||||
multiple: true
|
multiple: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.showClearButton).toEqual(false);
|
expect(Select.vm.showClearButton).toEqual(false)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should remove selected value when clicked", () => {
|
it('should remove selected value when clicked', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["foo", "bar"],
|
options: ['foo', 'bar'],
|
||||||
});
|
})
|
||||||
Select.vm.$data._value = 'foo';
|
Select.vm.$data._value = 'foo'
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual(["foo"]);
|
expect(Select.vm.selectedValue).toEqual(['foo'])
|
||||||
Select.find("button.vs__clear").trigger("click");
|
Select.find('button.vs__clear').trigger('click')
|
||||||
|
|
||||||
expect(Select.emitted().input).toEqual([[null]]);
|
expect(Select.emitted().input).toEqual([[null]])
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should be disabled when component is disabled", () => {
|
it('should be disabled when component is disabled', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["foo", "bar"],
|
options: ['foo', 'bar'],
|
||||||
value: "foo",
|
value: 'foo',
|
||||||
disabled: true
|
disabled: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.find("button.vs__clear").attributes().disabled).toEqual(
|
expect(Select.find('button.vs__clear').attributes().disabled).toEqual(
|
||||||
"disabled"
|
'disabled'
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
+147
-147
@@ -1,201 +1,201 @@
|
|||||||
import { selectWithProps } from "../helpers";
|
import { selectWithProps } from '../helpers'
|
||||||
import OpenIndicator from "../../src/components/OpenIndicator";
|
import OpenIndicator from '../../src/components/OpenIndicator'
|
||||||
|
|
||||||
const preventDefault = jest.fn()
|
const preventDefault = jest.fn()
|
||||||
|
|
||||||
function clickEvent (currentTarget) {
|
function clickEvent(currentTarget) {
|
||||||
return { currentTarget, preventDefault }
|
return { currentTarget, preventDefault }
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("Toggling Dropdown", () => {
|
describe('Toggling Dropdown', () => {
|
||||||
it("should not open the dropdown when the el is clicked but the component is disabled", () => {
|
it('should not open the dropdown when the el is clicked but the component is disabled', () => {
|
||||||
const Select = selectWithProps({ disabled: true });
|
const Select = selectWithProps({ disabled: true })
|
||||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search));
|
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search))
|
||||||
expect(Select.vm.open).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should open the dropdown when the el is clicked", () => {
|
|
||||||
const Select = selectWithProps({
|
|
||||||
value: [{ label: "one" }],
|
|
||||||
options: [{ label: "one" }]
|
|
||||||
});
|
|
||||||
|
|
||||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search));
|
|
||||||
expect(Select.vm.open).toEqual(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should not close the dropdown when the el is clicked and enableMouseInputSearch is set to true", () => {
|
|
||||||
const Select = selectWithProps({
|
|
||||||
value: [{ label: "one" }],
|
|
||||||
options: [{ label: "one" }],
|
|
||||||
enableMouseSearchInput: true
|
|
||||||
});
|
|
||||||
|
|
||||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search));
|
|
||||||
expect(Select.vm.open).toEqual(true);
|
|
||||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$el));
|
|
||||||
expect(Select.vm.open).toEqual(false)
|
expect(Select.vm.open).toEqual(false)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should open the dropdown when the selected tag is clicked", () => {
|
it('should open the dropdown when the el is clicked', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
value: [{ label: "one" }],
|
value: [{ label: 'one' }],
|
||||||
options: [{ label: "one" }]
|
options: [{ label: 'one' }],
|
||||||
});
|
})
|
||||||
|
|
||||||
const selectedTag = Select.find(".vs__selected").element;
|
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search))
|
||||||
|
expect(Select.vm.open).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
Select.vm.toggleDropdown(clickEvent(selectedTag));
|
it('should not close the dropdown when the el is clicked and enableMouseInputSearch is set to true', () => {
|
||||||
expect(Select.vm.open).toEqual(true);
|
const Select = selectWithProps({
|
||||||
});
|
value: [{ label: 'one' }],
|
||||||
|
options: [{ label: 'one' }],
|
||||||
|
enableMouseSearchInput: true,
|
||||||
|
})
|
||||||
|
|
||||||
it("can close the dropdown when the el is clicked", () => {
|
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search))
|
||||||
const Select = selectWithProps();
|
expect(Select.vm.open).toEqual(true)
|
||||||
const spy = jest.spyOn(Select.vm.$refs.search, "blur");
|
Select.vm.toggleDropdown(clickEvent(Select.vm.$el))
|
||||||
|
expect(Select.vm.open).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
Select.vm.open = true;
|
it('should open the dropdown when the selected tag is clicked', () => {
|
||||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$el));
|
const Select = selectWithProps({
|
||||||
|
value: [{ label: 'one' }],
|
||||||
|
options: [{ label: 'one' }],
|
||||||
|
})
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
const selectedTag = Select.find('.vs__selected').element
|
||||||
});
|
|
||||||
|
|
||||||
it("closes the dropdown when an option is selected, multiple is true, and closeOnSelect option is true", () => {
|
Select.vm.toggleDropdown(clickEvent(selectedTag))
|
||||||
|
expect(Select.vm.open).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('can close the dropdown when the el is clicked', () => {
|
||||||
|
const Select = selectWithProps()
|
||||||
|
const spy = jest.spyOn(Select.vm.$refs.search, 'blur')
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
Select.vm.toggleDropdown(clickEvent(Select.vm.$el))
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('closes the dropdown when an option is selected, multiple is true, and closeOnSelect option is true', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
value: [],
|
value: [],
|
||||||
options: ["one", "two", "three"],
|
options: ['one', 'two', 'three'],
|
||||||
multiple: true
|
|
||||||
});
|
|
||||||
|
|
||||||
Select.vm.open = true;
|
|
||||||
Select.vm.select("one");
|
|
||||||
|
|
||||||
expect(Select.vm.open).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not close the dropdown when the el is clicked, multiple is true, and closeOnSelect option is false", () => {
|
|
||||||
const Select = selectWithProps({
|
|
||||||
value: [],
|
|
||||||
options: ["one", "two", "three"],
|
|
||||||
multiple: true,
|
multiple: true,
|
||||||
closeOnSelect: false
|
})
|
||||||
});
|
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
Select.vm.select("one");
|
Select.vm.select('one')
|
||||||
|
|
||||||
expect(Select.vm.open).toEqual(true);
|
expect(Select.vm.open).toEqual(false)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should close the dropdown on search blur", () => {
|
it('does not close the dropdown when the el is clicked, multiple is true, and closeOnSelect option is false', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: [{ label: "one" }]
|
value: [],
|
||||||
});
|
options: ['one', 'two', 'three'],
|
||||||
|
multiple: true,
|
||||||
|
closeOnSelect: false,
|
||||||
|
})
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
Select.find({ ref: "search" }).trigger("blur");
|
Select.vm.select('one')
|
||||||
|
|
||||||
expect(Select.vm.open).toEqual(false);
|
expect(Select.vm.open).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will close the dropdown and emit the search:blur event from onSearchBlur", () => {
|
it('should close the dropdown on search blur', () => {
|
||||||
const Select = selectWithProps();
|
|
||||||
const spy = jest.spyOn(Select.vm, "$emit");
|
|
||||||
|
|
||||||
Select.vm.open = true;
|
|
||||||
Select.vm.onSearchBlur();
|
|
||||||
|
|
||||||
expect(Select.vm.open).toEqual(false);
|
|
||||||
expect(spy).toHaveBeenCalledWith("search:blur");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will open the dropdown and emit the search:focus event from onSearchFocus", () => {
|
|
||||||
const Select = selectWithProps();
|
|
||||||
const spy = jest.spyOn(Select.vm, "$emit");
|
|
||||||
|
|
||||||
Select.vm.onSearchFocus();
|
|
||||||
|
|
||||||
expect(Select.vm.open).toEqual(true);
|
|
||||||
expect(spy).toHaveBeenCalledWith("search:focus");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("will close the dropdown on escape, if search is empty", () => {
|
|
||||||
const Select = selectWithProps();
|
|
||||||
const spy = jest.spyOn(Select.vm.$refs.search, "blur");
|
|
||||||
|
|
||||||
Select.vm.open = true;
|
|
||||||
Select.vm.onEscape();
|
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should remove existing search text on escape keydown", () => {
|
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
value: [{ label: "one" }],
|
options: [{ label: 'one' }],
|
||||||
options: [{ label: "one" }]
|
})
|
||||||
});
|
|
||||||
|
|
||||||
Select.vm.search = "foo";
|
Select.vm.open = true
|
||||||
|
Select.find({ ref: 'search' }).trigger('blur')
|
||||||
|
|
||||||
|
expect(Select.vm.open).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('will close the dropdown and emit the search:blur event from onSearchBlur', () => {
|
||||||
|
const Select = selectWithProps()
|
||||||
|
const spy = jest.spyOn(Select.vm, '$emit')
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
Select.vm.onSearchBlur()
|
||||||
|
|
||||||
|
expect(Select.vm.open).toEqual(false)
|
||||||
|
expect(spy).toHaveBeenCalledWith('search:blur')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('will open the dropdown and emit the search:focus event from onSearchFocus', () => {
|
||||||
|
const Select = selectWithProps()
|
||||||
|
const spy = jest.spyOn(Select.vm, '$emit')
|
||||||
|
|
||||||
|
Select.vm.onSearchFocus()
|
||||||
|
|
||||||
|
expect(Select.vm.open).toEqual(true)
|
||||||
|
expect(spy).toHaveBeenCalledWith('search:focus')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('will close the dropdown on escape, if search is empty', () => {
|
||||||
|
const Select = selectWithProps()
|
||||||
|
const spy = jest.spyOn(Select.vm.$refs.search, 'blur')
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
Select.vm.onEscape()
|
||||||
|
|
||||||
|
expect(spy).toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should remove existing search text on escape keydown', () => {
|
||||||
|
const Select = selectWithProps({
|
||||||
|
value: [{ label: 'one' }],
|
||||||
|
options: [{ label: 'one' }],
|
||||||
|
})
|
||||||
|
|
||||||
|
Select.vm.search = 'foo'
|
||||||
Select.find('.vs__search').trigger('keydown.esc')
|
Select.find('.vs__search').trigger('keydown.esc')
|
||||||
expect(Select.vm.search).toEqual("");
|
expect(Select.vm.search).toEqual('')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should have an open class when dropdown is active", () => {
|
it('should have an open class when dropdown is active', () => {
|
||||||
const Select = selectWithProps();
|
const Select = selectWithProps()
|
||||||
|
|
||||||
expect(Select.vm.stateClasses['vs--open']).toEqual(false);
|
expect(Select.vm.stateClasses['vs--open']).toEqual(false)
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
expect(Select.vm.stateClasses['vs--open']).toEqual(true);
|
expect(Select.vm.stateClasses['vs--open']).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not display the dropdown if noDrop is true", async () => {
|
it('should not display the dropdown if noDrop is true', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
noDrop: true,
|
noDrop: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search));
|
Select.vm.toggleDropdown(clickEvent(Select.vm.$refs.search))
|
||||||
|
|
||||||
expect(Select.vm.open).toEqual(true);
|
expect(Select.vm.open).toEqual(true)
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.contains('.vs__dropdown-menu')).toBeFalsy();
|
expect(Select.contains('.vs__dropdown-menu')).toBeFalsy()
|
||||||
expect(Select.contains('.vs__dropdown-option')).toBeFalsy();
|
expect(Select.contains('.vs__dropdown-option')).toBeFalsy()
|
||||||
expect(Select.contains('.vs__no-options')).toBeFalsy();
|
expect(Select.contains('.vs__no-options')).toBeFalsy()
|
||||||
expect(Select.vm.stateClasses['vs--open']).toBeFalsy();
|
expect(Select.vm.stateClasses['vs--open']).toBeFalsy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should hide the open indicator if noDrop is true", () => {
|
it('should hide the open indicator if noDrop is true', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
noDrop: true,
|
noDrop: true,
|
||||||
});
|
})
|
||||||
expect(Select.contains(OpenIndicator)).toBeFalsy();
|
expect(Select.contains(OpenIndicator)).toBeFalsy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not add the searchable state class when noDrop is true", () => {
|
it('should not add the searchable state class when noDrop is true', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
noDrop: true,
|
noDrop: true,
|
||||||
});
|
})
|
||||||
expect(Select.classes('vs--searchable')).toBeFalsy();
|
expect(Select.classes('vs--searchable')).toBeFalsy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not add the searching state class when noDrop is true", () => {
|
it('should not add the searching state class when noDrop is true', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
noDrop: true,
|
noDrop: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.search = 'Canada';
|
Select.vm.search = 'Canada'
|
||||||
|
|
||||||
expect(Select.classes('vs--searching')).toBeFalsy();
|
expect(Select.classes('vs--searching')).toBeFalsy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can be opened with dropdownShouldOpen", () => {
|
it('can be opened with dropdownShouldOpen', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
noDrop: true,
|
noDrop: true,
|
||||||
dropdownShouldOpen: () => true,
|
dropdownShouldOpen: () => true,
|
||||||
options: ['one']
|
options: ['one'],
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.classes('vs--open')).toBeTruthy();
|
expect(Select.classes('vs--open')).toBeTruthy()
|
||||||
expect(Select.find('.vs__dropdown-menu li')).toBeTruthy();
|
expect(Select.find('.vs__dropdown-menu li')).toBeTruthy()
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,86 +1,86 @@
|
|||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../../src/components/Select";
|
import VueSelect from '../../src/components/Select'
|
||||||
|
|
||||||
describe("Filtering Options", () => {
|
describe('Filtering Options', () => {
|
||||||
it("should update the search value when the input element receives the 'input' event", () => {
|
it("should update the search value when the input element receives the 'input' event", () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { options: ["foo", "bar", "baz"] }
|
propsData: { options: ['foo', 'bar', 'baz'] },
|
||||||
});
|
})
|
||||||
|
|
||||||
const input = Select.find('.vs__search');
|
const input = Select.find('.vs__search')
|
||||||
input.element.value = 'a'
|
input.element.value = 'a'
|
||||||
input.trigger('input')
|
input.trigger('input')
|
||||||
expect(Select.vm.search).toEqual('a');
|
expect(Select.vm.search).toEqual('a')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should filter an array of strings", () => {
|
it('should filter an array of strings', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { options: ["foo", "bar", "baz"] }
|
propsData: { options: ['foo', 'bar', 'baz'] },
|
||||||
});
|
})
|
||||||
Select.vm.search = "ba";
|
Select.vm.search = 'ba'
|
||||||
expect(Select.vm.filteredOptions).toEqual(["bar", "baz"]);
|
expect(Select.vm.filteredOptions).toEqual(['bar', 'baz'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not filter the array of strings if filterable is false", () => {
|
it('should not filter the array of strings if filterable is false', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { options: ["foo", "bar", "baz"], filterable: false }
|
propsData: { options: ['foo', 'bar', 'baz'], filterable: false },
|
||||||
});
|
})
|
||||||
Select.vm.search = "ba";
|
Select.vm.search = 'ba'
|
||||||
expect(Select.vm.filteredOptions).toEqual(["foo", "bar", "baz"]);
|
expect(Select.vm.filteredOptions).toEqual(['foo', 'bar', 'baz'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should filter without case-sensitivity", () => {
|
it('should filter without case-sensitivity', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { options: ["Foo", "Bar", "Baz"] }
|
propsData: { options: ['Foo', 'Bar', 'Baz'] },
|
||||||
});
|
})
|
||||||
Select.vm.search = "ba";
|
Select.vm.search = 'ba'
|
||||||
expect(Select.vm.filteredOptions).toEqual(["Bar", "Baz"]);
|
expect(Select.vm.filteredOptions).toEqual(['Bar', 'Baz'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can filter an array of objects based on the objects label key", () => {
|
it('can filter an array of objects based on the objects label key', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: [{ label: "Foo" }, { label: "Bar" }, { label: "Baz" }]
|
options: [{ label: 'Foo' }, { label: 'Bar' }, { label: 'Baz' }],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
Select.vm.search = "ba";
|
Select.vm.search = 'ba'
|
||||||
expect(Select.vm.filteredOptions).toEqual([
|
expect(Select.vm.filteredOptions).toEqual([
|
||||||
{ label: "Bar" },
|
{ label: 'Bar' },
|
||||||
{ label: "Baz" }
|
{ label: 'Baz' },
|
||||||
]);
|
])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can determine if a given option should match the current search text", () => {
|
it('can determine if a given option should match the current search text', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: [{ label: "Aoo" }, { label: "Bar" }, { label: "Baz" }],
|
options: [{ label: 'Aoo' }, { label: 'Bar' }, { label: 'Baz' }],
|
||||||
filterBy: (option, label, search) =>
|
filterBy: (option, label, search) =>
|
||||||
label.match(new RegExp("^" + search, "i"))
|
label.match(new RegExp('^' + search, 'i')),
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.search = "a";
|
Select.vm.search = 'a'
|
||||||
expect(Select.vm.filteredOptions).toEqual([{ label: "Aoo" }]);
|
expect(Select.vm.filteredOptions).toEqual([{ label: 'Aoo' }])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can use a custom filtering method", () => {
|
it('can use a custom filtering method', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: ["foo", "bar", "baz"],
|
options: ['foo', 'bar', 'baz'],
|
||||||
filterBy: (option, label) => label.includes("o")
|
filterBy: (option, label) => label.includes('o'),
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
Select.vm.search = "a";
|
Select.vm.search = 'a'
|
||||||
expect(Select.vm.filteredOptions).toEqual(["foo"]);
|
expect(Select.vm.filteredOptions).toEqual(['foo'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can filter arrays of numbers", () => {
|
it('can filter arrays of numbers', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: [1, 5, 10]
|
options: [1, 5, 10],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
Select.vm.search = "1";
|
Select.vm.search = '1'
|
||||||
expect(Select.vm.filteredOptions).toEqual([1, 10]);
|
expect(Select.vm.filteredOptions).toEqual([1, 10])
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
+39
-43
@@ -1,74 +1,70 @@
|
|||||||
import { mountDefault } from '../helpers';
|
import { mountDefault } from '../helpers'
|
||||||
|
|
||||||
describe('Custom Keydown Handlers', () => {
|
describe('Custom Keydown Handlers', () => {
|
||||||
|
|
||||||
it('can use the map-keydown prop to trigger custom behaviour', () => {
|
it('can use the map-keydown prop to trigger custom behaviour', () => {
|
||||||
const onKeyDown = jest.fn();
|
const onKeyDown = jest.fn()
|
||||||
const Select = mountDefault({
|
const Select = mountDefault({
|
||||||
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown }),
|
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown }),
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.space');
|
Select.find({ ref: 'search' }).trigger('keydown.space')
|
||||||
|
|
||||||
expect(onKeyDown.mock.calls.length).toBe(1);
|
expect(onKeyDown.mock.calls.length).toBe(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('selectOnKeyCodes should trigger a selection for custom keycodes', () => {
|
it('selectOnKeyCodes should trigger a selection for custom keycodes', () => {
|
||||||
const Select = mountDefault({
|
const Select = mountDefault({
|
||||||
selectOnKeyCodes: [32],
|
selectOnKeyCodes: [32],
|
||||||
});
|
})
|
||||||
|
|
||||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
const spy = jest.spyOn(Select.vm, 'typeAheadSelect')
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.space');
|
Select.find({ ref: 'search' }).trigger('keydown.space')
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('even works when combining selectOnKeyCodes with map-keydown', () => {
|
it('even works when combining selectOnKeyCodes with map-keydown', () => {
|
||||||
const onKeyDown = jest.fn();
|
const onKeyDown = jest.fn()
|
||||||
const Select = mountDefault({
|
const Select = mountDefault({
|
||||||
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown }),
|
mapKeydown: (defaults, vm) => ({ ...defaults, 32: onKeyDown }),
|
||||||
selectOnKeyCodes: [9],
|
selectOnKeyCodes: [9],
|
||||||
});
|
})
|
||||||
|
|
||||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
const spy = jest.spyOn(Select.vm, 'typeAheadSelect')
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.space');
|
Select.find({ ref: 'search' }).trigger('keydown.space')
|
||||||
expect(onKeyDown.mock.calls.length).toBe(1);
|
expect(onKeyDown.mock.calls.length).toBe(1)
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.tab');
|
Select.find({ ref: 'search' }).trigger('keydown.tab')
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
describe('CompositionEvent support', () => {
|
describe('CompositionEvent support', () => {
|
||||||
|
|
||||||
it('will not select a value with enter if the user is composing', () => {
|
it('will not select a value with enter if the user is composing', () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
const spy = jest.spyOn(Select.vm, 'typeAheadSelect')
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('compositionstart');
|
Select.find({ ref: 'search' }).trigger('compositionstart')
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.enter');
|
Select.find({ ref: 'search' }).trigger('keydown.enter')
|
||||||
expect(spy).toHaveBeenCalledTimes(0);
|
expect(spy).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('compositionend');
|
Select.find({ ref: 'search' }).trigger('compositionend')
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.enter');
|
Select.find({ ref: 'search' }).trigger('keydown.enter')
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('will not select a value with tab if the user is composing', () => {
|
it('will not select a value with tab if the user is composing', () => {
|
||||||
const Select = mountDefault({ selectOnTab: true });
|
const Select = mountDefault({ selectOnTab: true })
|
||||||
const spy = jest.spyOn(Select.vm, 'typeAheadSelect');
|
const spy = jest.spyOn(Select.vm, 'typeAheadSelect')
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('compositionstart');
|
Select.find({ ref: 'search' }).trigger('compositionstart')
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.tab');
|
Select.find({ ref: 'search' }).trigger('keydown.tab')
|
||||||
expect(spy).toHaveBeenCalledTimes(0);
|
expect(spy).toHaveBeenCalledTimes(0)
|
||||||
|
|
||||||
Select.find({ ref: 'search' }).trigger('compositionend');
|
Select.find({ ref: 'search' }).trigger('compositionend')
|
||||||
Select.find({ ref: 'search' }).trigger('keydown.tab');
|
Select.find({ ref: 'search' }).trigger('keydown.tab')
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
});
|
})
|
||||||
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
});
|
|
||||||
|
|||||||
+49
-45
@@ -1,57 +1,61 @@
|
|||||||
import VueSelect from "../../src/components/Select";
|
import VueSelect from '../../src/components/Select'
|
||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import { selectWithProps } from "../helpers";
|
import { selectWithProps } from '../helpers'
|
||||||
|
|
||||||
describe("Labels", () => {
|
describe('Labels', () => {
|
||||||
it("can generate labels using a custom label key", () => {
|
it('can generate labels using a custom label key', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: [{ name: "Foo" }],
|
options: [{ name: 'Foo' }],
|
||||||
label: "name",
|
label: 'name',
|
||||||
value: { name: "Foo" }
|
value: { name: 'Foo' },
|
||||||
});
|
})
|
||||||
expect(Select.find(".vs__selected").text()).toBe("Foo");
|
expect(Select.find('.vs__selected').text()).toBe('Foo')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will console.warn when options contain objects without a valid label key", async () => {
|
it('will console.warn when options contain objects without a valid label key', async () => {
|
||||||
const spy = jest.spyOn(console, "warn").mockImplementation(() => {});
|
const spy = jest.spyOn(console, 'warn').mockImplementation(() => {})
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: [{}]
|
options: [{}],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledWith(
|
expect(spy).toHaveBeenCalledWith(
|
||||||
'[vue-select warn]: Label key "option.label" does not exist in options object {}.' +
|
'[vue-select warn]: Label key "option.label" does not exist in options object {}.' +
|
||||||
"\nhttps://vue-select.org/api/props.html#getoptionlabel"
|
'\nhttps://vue-select.org/api/props.html#getoptionlabel'
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should display a placeholder if the value is empty", () => {
|
it('should display a placeholder if the value is empty', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: ["one"]
|
options: ['one'],
|
||||||
},
|
},
|
||||||
attrs: {
|
attrs: {
|
||||||
placeholder: "foo"
|
placeholder: 'foo',
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.searchPlaceholder).toEqual("foo");
|
expect(Select.vm.searchPlaceholder).toEqual('foo')
|
||||||
Select.vm.$data._value = "one";
|
Select.vm.$data._value = 'one'
|
||||||
expect(Select.vm.searchPlaceholder).not.toBeDefined();
|
expect(Select.vm.searchPlaceholder).not.toBeDefined()
|
||||||
});
|
})
|
||||||
|
|
||||||
describe('getOptionLabel', () => {
|
describe('getOptionLabel', () => {
|
||||||
it('will return undefined if the option lacks the label key', () => {
|
it('will return undefined if the option lacks the label key', () => {
|
||||||
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({ label: 'label' });
|
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({
|
||||||
expect(getOptionLabel({name: 'vue'})).toEqual(undefined);
|
label: 'label',
|
||||||
});
|
})
|
||||||
|
expect(getOptionLabel({ name: 'vue' })).toEqual(undefined)
|
||||||
|
})
|
||||||
|
|
||||||
it('will return a string value for a valid key', () => {
|
it('will return a string value for a valid key', () => {
|
||||||
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({ label: 'label' });
|
const getOptionLabel = VueSelect.props.getOptionLabel.default.bind({
|
||||||
expect(getOptionLabel({label: 'vue'})).toEqual('vue');
|
label: 'label',
|
||||||
});
|
})
|
||||||
|
expect(getOptionLabel({ label: 'vue' })).toEqual('vue')
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this test fails because of a bug where Vue executes the default contents
|
* this test fails because of a bug where Vue executes the default contents
|
||||||
@@ -60,22 +64,22 @@ describe("Labels", () => {
|
|||||||
* @see https://github.com/vuejs/vue/pull/10229
|
* @see https://github.com/vuejs/vue/pull/10229
|
||||||
*/
|
*/
|
||||||
xit('will not call getOptionLabel if both scoped option slots are used and a filter is provided', () => {
|
xit('will not call getOptionLabel if both scoped option slots are used and a filter is provided', () => {
|
||||||
const spy = spyOn(VueSelect.props.getOptionLabel, 'default');
|
const spy = spyOn(VueSelect.props.getOptionLabel, 'default')
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: [{name: 'one'}],
|
options: [{ name: 'one' }],
|
||||||
filter: () => {},
|
filter: () => {},
|
||||||
},
|
},
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
'option': '<span class="option">{{ props.name }}</span>',
|
option: '<span class="option">{{ props.name }}</span>',
|
||||||
'selected-option': '<span class="selected">{{ props.name }}</span>',
|
'selected-option': '<span class="selected">{{ props.name }}</span>',
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.select({name: 'one'});
|
Select.vm.select({ name: 'one' })
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledTimes(0);
|
expect(spy).toHaveBeenCalledTimes(0)
|
||||||
expect(Select.find('.selected').exists()).toBeTruthy();
|
expect(Select.find('.selected').exists()).toBeTruthy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
+22
-22
@@ -1,30 +1,30 @@
|
|||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../../src/components/Select";
|
import VueSelect from '../../src/components/Select'
|
||||||
|
|
||||||
describe("Single value options", () => {
|
describe('Single value options', () => {
|
||||||
it("should reset the search input on focus lost", () => {
|
it('should reset the search input on focus lost', () => {
|
||||||
const Select = shallowMount(VueSelect);
|
const Select = shallowMount(VueSelect)
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
|
|
||||||
Select.vm.search = "t";
|
Select.vm.search = 't'
|
||||||
expect(Select.vm.search).toEqual("t");
|
expect(Select.vm.search).toEqual('t')
|
||||||
|
|
||||||
Select.vm.onSearchBlur();
|
Select.vm.onSearchBlur()
|
||||||
expect(Select.vm.search).toEqual("");
|
expect(Select.vm.search).toEqual('')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not reset the search input on focus lost when clearSearchOnSelect is false", () => {
|
it('should not reset the search input on focus lost when clearSearchOnSelect is false', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { value: "foo", clearSearchOnSelect: false }
|
propsData: { value: 'foo', clearSearchOnSelect: false },
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.clearSearchOnSelect).toEqual(false);
|
expect(Select.vm.clearSearchOnSelect).toEqual(false)
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
Select.vm.search = "t";
|
Select.vm.search = 't'
|
||||||
expect(Select.vm.search).toEqual("t");
|
expect(Select.vm.search).toEqual('t')
|
||||||
|
|
||||||
Select.vm.onSearchBlur();
|
Select.vm.onSearchBlur()
|
||||||
expect(Select.vm.search).toEqual("t");
|
expect(Select.vm.search).toEqual('t')
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,31 +1,32 @@
|
|||||||
import Select from '../../src/components/Select';
|
import Select from '../../src/components/Select'
|
||||||
|
|
||||||
describe('Comparing Options', () => {
|
describe('Comparing Options', () => {
|
||||||
|
|
||||||
const comparator = Select.methods.optionComparator.bind({
|
const comparator = Select.methods.optionComparator.bind({
|
||||||
getOptionKey: Select.props.getOptionKey.default,
|
getOptionKey: Select.props.getOptionKey.default,
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can compare numbers', () => {
|
it('can compare numbers', () => {
|
||||||
expect(comparator(1, 2)).toBeFalsy();
|
expect(comparator(1, 2)).toBeFalsy()
|
||||||
expect(comparator(1, 1)).toBeTruthy();
|
expect(comparator(1, 1)).toBeTruthy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can compare strings', () => {
|
it('can compare strings', () => {
|
||||||
expect(comparator('one', 'one')).toBeTruthy();
|
expect(comparator('one', 'one')).toBeTruthy()
|
||||||
expect(comparator('one', 'two')).toBeFalsy();
|
expect(comparator('one', 'two')).toBeFalsy()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can compare objects', () => {
|
it('can compare objects', () => {
|
||||||
// compare ID keys
|
// compare ID keys
|
||||||
expect(comparator({label: 'halo', id: 1}, {label: 'halo', id: 2}))
|
expect(
|
||||||
.toBeFalsy();
|
comparator({ label: 'halo', id: 1 }, { label: 'halo', id: 2 })
|
||||||
|
).toBeFalsy()
|
||||||
// compare objects
|
// compare objects
|
||||||
expect(comparator({label: 'halo', value: 1}, {label: 'halo', value: 1}))
|
expect(
|
||||||
.toBeTruthy();
|
comparator({ label: 'halo', value: 1 }, { label: 'halo', value: 1 })
|
||||||
|
).toBeTruthy()
|
||||||
// compare objects with different orders
|
// compare objects with different orders
|
||||||
expect(comparator({value: 1, label: 'halo'}, {label: 'halo', value: 1}))
|
expect(
|
||||||
.toBeTruthy();
|
comparator({ value: 1, label: 'halo' }, { label: 'halo', value: 1 })
|
||||||
});
|
).toBeTruthy()
|
||||||
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
import Select from '../../src/components/Select.vue';
|
import Select from '../../src/components/Select.vue'
|
||||||
|
|
||||||
describe('Serializing Option Keys', () => {
|
describe('Serializing Option Keys', () => {
|
||||||
|
const getOptionKey = Select.props.getOptionKey.default
|
||||||
const getOptionKey = Select.props.getOptionKey.default;
|
|
||||||
|
|
||||||
it('can serialize strings to a key', () => {
|
it('can serialize strings to a key', () => {
|
||||||
expect(getOptionKey('vue')).toBe('vue');
|
expect(getOptionKey('vue')).toBe('vue')
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can serialize integers to a key', () => {
|
it('can serialize integers to a key', () => {
|
||||||
expect(getOptionKey(1)).toBe(1);
|
expect(getOptionKey(1)).toBe(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can serialize objects to a key', () => {
|
it('can serialize objects to a key', () => {
|
||||||
expect(getOptionKey({label: 'vue'})).toBe('{"label":"vue"}');
|
expect(getOptionKey({ label: 'vue' })).toBe('{"label":"vue"}')
|
||||||
});
|
})
|
||||||
|
|
||||||
it('will use an ID property if the object contains one', () => {
|
it('will use an ID property if the object contains one', () => {
|
||||||
expect(getOptionKey({id: 1})).toBe(1);
|
expect(getOptionKey({ id: 1 })).toBe(1)
|
||||||
expect(getOptionKey({id: 'one'})).toBe('one');
|
expect(getOptionKey({ id: 'one' })).toBe('one')
|
||||||
expect(getOptionKey({id: {im: 'a nested object'}}))
|
expect(getOptionKey({ id: { im: 'a nested object' } })).toEqual({
|
||||||
.toEqual({im: 'a nested object'});
|
im: 'a nested object',
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,141 +1,163 @@
|
|||||||
import { mount, shallowMount } from '@vue/test-utils';
|
import { mount, shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../../src/components/Select";
|
import VueSelect from '../../src/components/Select'
|
||||||
import { mountDefault } from '../helpers';
|
import { mountDefault } from '../helpers'
|
||||||
|
|
||||||
describe("Reset on options change", () => {
|
describe('Reset on options change', () => {
|
||||||
it("should not reset the selected value by default when the options property changes", () => {
|
it('should not reset the selected value by default when the options property changes', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { options: ["one"] }
|
propsData: { options: ['one'] },
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = 'one';
|
Select.vm.$data._value = 'one'
|
||||||
|
|
||||||
Select.setProps({options: ["four", "five", "six"]});
|
Select.setProps({ options: ['four', 'five', 'six'] })
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
});
|
})
|
||||||
|
|
||||||
describe('resetOnOptionsChange as a function', () => {
|
describe('resetOnOptionsChange as a function', () => {
|
||||||
it('will yell at you if resetOnOptionsChange is not a function or boolean', () => {
|
it('will yell at you if resetOnOptionsChange is not a function or boolean', () => {
|
||||||
const spy = jest.spyOn(console, 'error').mockImplementation(() => {});
|
const spy = jest.spyOn(console, 'error').mockImplementation(() => {})
|
||||||
|
|
||||||
mountDefault({resetOnOptionsChange: 1});
|
mountDefault({ resetOnOptionsChange: 1 })
|
||||||
expect(spy.mock.calls[0][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
expect(spy.mock.calls[0][0]).toContain(
|
||||||
|
'Invalid prop: custom validator check failed for prop "resetOnOptionsChange"'
|
||||||
|
)
|
||||||
|
|
||||||
mountDefault({resetOnOptionsChange: 'one'});
|
mountDefault({ resetOnOptionsChange: 'one' })
|
||||||
expect(spy.mock.calls[1][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
expect(spy.mock.calls[1][0]).toContain(
|
||||||
|
'Invalid prop: custom validator check failed for prop "resetOnOptionsChange"'
|
||||||
|
)
|
||||||
|
|
||||||
mountDefault({resetOnOptionsChange: []});
|
mountDefault({ resetOnOptionsChange: [] })
|
||||||
expect(spy.mock.calls[2][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
expect(spy.mock.calls[2][0]).toContain(
|
||||||
|
'Invalid prop: custom validator check failed for prop "resetOnOptionsChange"'
|
||||||
|
)
|
||||||
|
|
||||||
mountDefault({resetOnOptionsChange: {}});
|
mountDefault({ resetOnOptionsChange: {} })
|
||||||
expect(spy.mock.calls[3][0]).toContain('Invalid prop: custom validator check failed for prop "resetOnOptionsChange"')
|
expect(spy.mock.calls[3][0]).toContain(
|
||||||
});
|
'Invalid prop: custom validator check failed for prop "resetOnOptionsChange"'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('should receive the new options, old options, and current value', async () => {
|
it('should receive the new options, old options, and current value', async () => {
|
||||||
let resetOnOptionsChange = jest.fn(option => option);
|
let resetOnOptionsChange = jest.fn((option) => option)
|
||||||
const Select = mountDefault(
|
const Select = mountDefault({
|
||||||
{resetOnOptionsChange, options: ['bear'], value: 'selected'},
|
resetOnOptionsChange,
|
||||||
);
|
options: ['bear'],
|
||||||
|
value: 'selected',
|
||||||
|
})
|
||||||
|
|
||||||
Select.setProps({options: ['lake', 'kite']});
|
Select.setProps({ options: ['lake', 'kite'] })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(resetOnOptionsChange).toHaveBeenCalledTimes(1);
|
expect(resetOnOptionsChange).toHaveBeenCalledTimes(1)
|
||||||
expect(resetOnOptionsChange)
|
expect(resetOnOptionsChange).toHaveBeenCalledWith(
|
||||||
.toHaveBeenCalledWith(['lake', 'kite'], ['bear'], ['selected']);
|
['lake', 'kite'],
|
||||||
});
|
['bear'],
|
||||||
|
['selected']
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('should allow resetOnOptionsChange to be a function that returns true', async () => {
|
it('should allow resetOnOptionsChange to be a function that returns true', async () => {
|
||||||
let resetOnOptionsChange = () => true;
|
let resetOnOptionsChange = () => true
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
propsData: { resetOnOptionsChange, options: ['one'], value: 'one' },
|
||||||
});
|
})
|
||||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
const spy = jest.spyOn(Select.vm, 'clearSelection')
|
||||||
|
|
||||||
Select.setProps({options: ['one', 'two']});
|
Select.setProps({ options: ['one', 'two'] })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should allow resetOnOptionsChange to be a function that returns false', () => {
|
it('should allow resetOnOptionsChange to be a function that returns false', () => {
|
||||||
let resetOnOptionsChange = () => false;
|
let resetOnOptionsChange = () => false
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
propsData: { resetOnOptionsChange, options: ['one'], value: 'one' },
|
||||||
});
|
})
|
||||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
const spy = jest.spyOn(Select.vm, 'clearSelection')
|
||||||
|
|
||||||
Select.setProps({options: ['one', 'two']});
|
Select.setProps({ options: ['one', 'two'] })
|
||||||
expect(spy).not.toHaveBeenCalled();
|
expect(spy).not.toHaveBeenCalled()
|
||||||
});
|
})
|
||||||
|
|
||||||
it('should reset the options if the selectedValue does not exist in the new options', async () => {
|
it('should reset the options if the selectedValue does not exist in the new options', async () => {
|
||||||
let resetOnOptionsChange = (options, old, val) => val.some(val => options.includes(val));
|
let resetOnOptionsChange = (options, old, val) =>
|
||||||
|
val.some((val) => options.includes(val))
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {resetOnOptionsChange, options: ['one'], value: 'one'},
|
propsData: { resetOnOptionsChange, options: ['one'], value: 'one' },
|
||||||
});
|
})
|
||||||
const spy = jest.spyOn(Select.vm, 'clearSelection');
|
const spy = jest.spyOn(Select.vm, 'clearSelection')
|
||||||
|
|
||||||
Select.setProps({options: ['one', 'two']});
|
Select.setProps({ options: ['one', 'two'] })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual(['one']);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
|
|
||||||
Select.setProps({options: ['two']});
|
Select.setProps({ options: ['two'] })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledTimes(1);
|
expect(spy).toHaveBeenCalledTimes(1)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should reset the selected value when the options property changes", async () => {
|
it('should reset the selected value when the options property changes', async () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { resetOnOptionsChange: true, options: ["one"] }
|
propsData: { resetOnOptionsChange: true, options: ['one'] },
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = 'one';
|
Select.vm.$data._value = 'one'
|
||||||
|
|
||||||
Select.setProps({options: ["four", "five", "six"]});
|
Select.setProps({ options: ['four', 'five', 'six'] })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should return correct selected value when the options property changes and a new option matches", async () => {
|
it('should return correct selected value when the options property changes and a new option matches', async () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { value: "one", options: [], reduce(option) { return option.value } }
|
propsData: {
|
||||||
});
|
value: 'one',
|
||||||
|
options: [],
|
||||||
|
reduce(option) {
|
||||||
|
return option.value
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
Select.setProps({options: [{ label: "oneLabel", value: "one" }]});
|
Select.setProps({ options: [{ label: 'oneLabel', value: 'one' }] })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "oneLabel", value: "one" }]);
|
expect(Select.vm.selectedValue).toEqual([
|
||||||
});
|
{ label: 'oneLabel', value: 'one' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it('clearSearchOnBlur returns false when multiple is true', () => {
|
it('clearSearchOnBlur returns false when multiple is true', () => {
|
||||||
const Select = mountDefault({});
|
const Select = mountDefault({})
|
||||||
let clearSearchOnBlur = jest.spyOn(Select.vm, 'clearSearchOnBlur');
|
let clearSearchOnBlur = jest.spyOn(Select.vm, 'clearSearchOnBlur')
|
||||||
Select.find({ref: 'search'}).trigger('click');
|
Select.find({ ref: 'search' }).trigger('click')
|
||||||
Select.setData({search: 'one'});
|
Select.setData({ search: 'one' })
|
||||||
Select.find({ref: 'search'}).trigger('blur');
|
Select.find({ ref: 'search' }).trigger('blur')
|
||||||
|
|
||||||
expect(clearSearchOnBlur).toHaveBeenCalledTimes(1);
|
expect(clearSearchOnBlur).toHaveBeenCalledTimes(1)
|
||||||
expect(clearSearchOnBlur).toHaveBeenCalledWith({
|
expect(clearSearchOnBlur).toHaveBeenCalledWith({
|
||||||
clearSearchOnSelect: true,
|
clearSearchOnSelect: true,
|
||||||
multiple: false,
|
multiple: false,
|
||||||
});
|
})
|
||||||
expect(Select.vm.search).toBe('');
|
expect(Select.vm.search).toBe('')
|
||||||
});
|
})
|
||||||
|
|
||||||
it('clearSearchOnBlur accepts a function', () => {
|
it('clearSearchOnBlur accepts a function', () => {
|
||||||
let clearSearchOnBlur = jest.fn(() => false);
|
let clearSearchOnBlur = jest.fn(() => false)
|
||||||
const Select = mountDefault({clearSearchOnBlur});
|
const Select = mountDefault({ clearSearchOnBlur })
|
||||||
|
|
||||||
Select.find({ref: 'search'}).trigger('click');
|
Select.find({ ref: 'search' }).trigger('click')
|
||||||
Select.setData({search: 'one'});
|
Select.setData({ search: 'one' })
|
||||||
Select.find({ref: 'search'}).trigger('blur');
|
Select.find({ ref: 'search' }).trigger('blur')
|
||||||
|
|
||||||
expect(clearSearchOnBlur).toHaveBeenCalledTimes(1);
|
expect(clearSearchOnBlur).toHaveBeenCalledTimes(1)
|
||||||
expect(Select.vm.search).toBe('one');
|
expect(Select.vm.search).toBe('one')
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
+185
-171
@@ -1,127 +1,133 @@
|
|||||||
import { mount, shallowMount } from "@vue/test-utils";
|
import { mount, shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../../src/components/Select";
|
import VueSelect from '../../src/components/Select'
|
||||||
|
|
||||||
describe("When reduce prop is defined", () => {
|
describe('When reduce prop is defined', () => {
|
||||||
it("can accept an array of objects and pre-selected value (single)", () => {
|
it('can accept an array of objects and pre-selected value (single)', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
value: "foo",
|
value: 'foo',
|
||||||
options: [{ label: "This is Foo", value: "foo" }]
|
options: [{ label: 'This is Foo', value: 'foo' }],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Foo", value: "foo" }]);
|
expect(Select.vm.selectedValue).toEqual([
|
||||||
});
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it("can determine if an object is pre-selected", () => {
|
it('can determine if an object is pre-selected', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.id,
|
reduce: (option) => option.id,
|
||||||
value: "foo",
|
value: 'foo',
|
||||||
options: [
|
options: [
|
||||||
{
|
{
|
||||||
id: "foo",
|
id: 'foo',
|
||||||
label: "This is Foo"
|
label: 'This is Foo',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
Select.vm.isOptionSelected({
|
Select.vm.isOptionSelected({
|
||||||
id: "foo",
|
id: 'foo',
|
||||||
label: "This is Foo"
|
label: 'This is Foo',
|
||||||
})
|
})
|
||||||
).toEqual(true);
|
).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can determine if an object is selected after its been chosen', () => {
|
it('can determine if an object is selected after its been chosen', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.id,
|
reduce: (option) => option.id,
|
||||||
options: [{id: 'foo', label: 'FooBar'}],
|
options: [{ id: 'foo', label: 'FooBar' }],
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.select({id: 'foo', label: 'FooBar'});
|
Select.vm.select({ id: 'foo', label: 'FooBar' })
|
||||||
|
|
||||||
expect(Select.vm.isOptionSelected({
|
expect(
|
||||||
|
Select.vm.isOptionSelected({
|
||||||
id: 'foo',
|
id: 'foo',
|
||||||
label: 'This is FooBar',
|
label: 'This is FooBar',
|
||||||
})).toEqual(true);
|
})
|
||||||
});
|
).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
it("can accept an array of objects and pre-selected values (multiple)", () => {
|
it('can accept an array of objects and pre-selected values (multiple)', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
value: ["foo"],
|
value: ['foo'],
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Foo", value: "foo" }]);
|
expect(Select.vm.selectedValue).toEqual([
|
||||||
});
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it("can deselect a pre-selected object", () => {
|
it('can deselect a pre-selected object', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = ['foo', 'bar'];
|
Select.vm.$data._value = ['foo', 'bar']
|
||||||
|
|
||||||
Select.vm.deselect("foo");
|
Select.vm.deselect('foo')
|
||||||
expect(Select.vm.selectedValue).toEqual(["bar"]);
|
expect(Select.vm.selectedValue).toEqual(['bar'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can deselect an option when multiple is false", () => {
|
it('can deselect an option when multiple is false', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.deselect("foo");
|
Select.vm.deselect('foo')
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can use v-model syntax for a two way binding to a parent component", async () => {
|
it('can use v-model syntax for a two way binding to a parent component', async () => {
|
||||||
const Parent = mount({
|
const Parent = mount({
|
||||||
data: () => ({
|
data: () => ({
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
current: "foo",
|
current: 'foo',
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" },
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
{ label: "This is Baz", value: "baz" }
|
{ label: 'This is Baz', value: 'baz' },
|
||||||
]
|
],
|
||||||
}),
|
}),
|
||||||
components: { "v-select": VueSelect },
|
components: { 'v-select': VueSelect },
|
||||||
computed: {
|
computed: {
|
||||||
value: {
|
value: {
|
||||||
get() {
|
get() {
|
||||||
return this.current;
|
return this.current
|
||||||
},
|
},
|
||||||
set(value) {
|
set(value) {
|
||||||
if (value == 'baz') return;
|
if (value == 'baz') return
|
||||||
this.current = value;
|
this.current = value
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
template: `
|
template: `
|
||||||
<v-select
|
<v-select
|
||||||
@@ -129,133 +135,141 @@ describe("When reduce prop is defined", () => {
|
|||||||
:reduce="option => option.value"
|
:reduce="option => option.value"
|
||||||
:options="options"
|
:options="options"
|
||||||
/>
|
/>
|
||||||
`
|
`,
|
||||||
});
|
})
|
||||||
const Select = Parent.vm.$children[0];
|
const Select = Parent.vm.$children[0]
|
||||||
|
|
||||||
expect(Select.value).toEqual("foo");
|
expect(Select.value).toEqual('foo')
|
||||||
expect(Select.selectedValue).toEqual([{ label: "This is Foo", value: "foo" }]);
|
expect(Select.selectedValue).toEqual([
|
||||||
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
|
])
|
||||||
|
|
||||||
Select.select({ label: "This is Bar", value: "bar" });
|
Select.select({ label: 'This is Bar', value: 'bar' })
|
||||||
await Select.$nextTick();
|
await Select.$nextTick()
|
||||||
expect(Parent.vm.value).toEqual("bar");
|
expect(Parent.vm.value).toEqual('bar')
|
||||||
expect(Select.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
expect(Select.selectedValue).toEqual([
|
||||||
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
|
])
|
||||||
|
|
||||||
// Parent denies to set baz
|
// Parent denies to set baz
|
||||||
Select.select({ label: "This is Baz", value: "baz" });
|
Select.select({ label: 'This is Baz', value: 'baz' })
|
||||||
await Select.$nextTick();
|
await Select.$nextTick()
|
||||||
expect(Select.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
expect(Select.selectedValue).toEqual([
|
||||||
expect(Parent.vm.value).toEqual('bar');
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
});
|
])
|
||||||
|
expect(Parent.vm.value).toEqual('bar')
|
||||||
|
})
|
||||||
|
|
||||||
it("can generate labels using a custom label key", () => {
|
it('can generate labels using a custom label key', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
value: ["CA"],
|
value: ['CA'],
|
||||||
label: "name",
|
label: 'name',
|
||||||
options: [{ value: "CA", name: "Canada" }, { value: "US", name: "United States" }]
|
options: [
|
||||||
}
|
{ value: 'CA', name: 'Canada' },
|
||||||
});
|
{ value: 'US', name: 'United States' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
expect(Select.find(".vs__selected").text()).toContain("Canada");
|
expect(Select.find('.vs__selected').text()).toContain('Canada')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can find the original option within this.options", () => {
|
it('can find the original option within this.options', () => {
|
||||||
const optionToFind = { id: 1, label: "Foo" };
|
const optionToFind = { id: 1, label: 'Foo' }
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.id,
|
reduce: (option) => option.id,
|
||||||
options: [optionToFind, { id: 2, label: "Bar" }]
|
options: [optionToFind, { id: 2, label: 'Bar' }],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.findOptionFromReducedValue(1)).toEqual(optionToFind);
|
expect(Select.vm.findOptionFromReducedValue(1)).toEqual(optionToFind)
|
||||||
expect(Select.vm.findOptionFromReducedValue(optionToFind)).toEqual(
|
expect(Select.vm.findOptionFromReducedValue(optionToFind)).toEqual(
|
||||||
optionToFind
|
optionToFind
|
||||||
);
|
)
|
||||||
});
|
})
|
||||||
|
|
||||||
it('can work with falsey values', () => {
|
it('can work with falsey values', () => {
|
||||||
const option = {value: 0, label: 'No'};
|
const option = { value: 0, label: 'No' }
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
options: [option, {value: 1, label: 'Yes'}],
|
options: [option, { value: 1, label: 'Yes' }],
|
||||||
value: 0,
|
value: 0,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option);
|
expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option)
|
||||||
expect(Select.vm.selectedValue).toEqual([option]);
|
expect(Select.vm.selectedValue).toEqual([option])
|
||||||
});
|
})
|
||||||
|
|
||||||
it('works with null values', () => {
|
it('works with null values', () => {
|
||||||
const option = {value: null, label: 'No'};
|
const option = { value: null, label: 'No' }
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
options: [option, {value: 1, label: 'Yes'}],
|
options: [option, { value: 1, label: 'Yes' }],
|
||||||
value: null,
|
value: null,
|
||||||
},
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option);
|
expect(Select.vm.findOptionFromReducedValue(option)).toEqual(option)
|
||||||
expect(Select.vm.selectedValue).toEqual([option]);
|
expect(Select.vm.selectedValue).toEqual([option])
|
||||||
});
|
})
|
||||||
|
|
||||||
describe("And when a reduced option is a nested object", () => {
|
describe('And when a reduced option is a nested object', () => {
|
||||||
it("can determine if an object is pre-selected", () => {
|
it('can determine if an object is pre-selected', () => {
|
||||||
const nestedOption = { value: { nested: true }, label: "foo" };
|
const nestedOption = { value: { nested: true }, label: 'foo' }
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
value: {
|
value: {
|
||||||
nested: true
|
nested: true,
|
||||||
},
|
},
|
||||||
options: [nestedOption]
|
options: [nestedOption],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([nestedOption]);
|
expect(Select.vm.selectedValue).toEqual([nestedOption])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can determine if an object is selected after it is chosen", () => {
|
it('can determine if an object is selected after it is chosen', () => {
|
||||||
const nestedOption = { value: { nested: true }, label: "foo" };
|
const nestedOption = { value: { nested: true }, label: 'foo' }
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
reduce: option => option.value,
|
reduce: (option) => option.value,
|
||||||
options: [nestedOption]
|
options: [nestedOption],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.select(nestedOption);
|
Select.vm.select(nestedOption)
|
||||||
expect(Select.vm.isOptionSelected(nestedOption)).toEqual(true);
|
expect(Select.vm.isOptionSelected(nestedOption)).toEqual(true)
|
||||||
});
|
})
|
||||||
|
})
|
||||||
|
|
||||||
});
|
it('reacts correctly when value property changes', async () => {
|
||||||
|
const optionToChangeTo = { id: 1, label: 'Foo' }
|
||||||
it("reacts correctly when value property changes", async () => {
|
|
||||||
const optionToChangeTo = { id: 1, label: "Foo" };
|
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
value: 2,
|
value: 2,
|
||||||
reduce: option => option.id,
|
reduce: (option) => option.id,
|
||||||
options: [optionToChangeTo, { id: 2, label: "Bar" }]
|
options: [optionToChangeTo, { id: 2, label: 'Bar' }],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.setProps({ value: optionToChangeTo.id });
|
Select.setProps({ value: optionToChangeTo.id })
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([optionToChangeTo]);
|
expect(Select.vm.selectedValue).toEqual([optionToChangeTo])
|
||||||
});
|
})
|
||||||
|
|
||||||
describe('Reducing Tags', () => {
|
describe('Reducing Tags', () => {
|
||||||
it('tracks values that have been created by the user', async () => {
|
it('tracks values that have been created by the user', async () => {
|
||||||
const Parent = mount({
|
const Parent = mount({
|
||||||
data: () => ({selected: null, options: []}),
|
data: () => ({ selected: null, options: [] }),
|
||||||
template: `
|
template: `
|
||||||
<v-select
|
<v-select
|
||||||
v-model="selected"
|
v-model="selected"
|
||||||
@@ -265,24 +279,24 @@ describe("When reduce prop is defined", () => {
|
|||||||
:create-option="label => ({ label, value: -1 })"
|
:create-option="label => ({ label, value: -1 })"
|
||||||
/>
|
/>
|
||||||
`,
|
`,
|
||||||
components: {'v-select': VueSelect},
|
components: { 'v-select': VueSelect },
|
||||||
});
|
})
|
||||||
const Select = Parent.vm.$children[0];
|
const Select = Parent.vm.$children[0]
|
||||||
|
|
||||||
// When
|
// When
|
||||||
Select.$refs.search.focus();
|
Select.$refs.search.focus()
|
||||||
await Select.$nextTick();
|
await Select.$nextTick()
|
||||||
|
|
||||||
Select.search = 'hello';
|
Select.search = 'hello'
|
||||||
await Select.$nextTick();
|
await Select.$nextTick()
|
||||||
|
|
||||||
Select.typeAheadSelect();
|
Select.typeAheadSelect()
|
||||||
await Select.$nextTick();
|
await Select.$nextTick()
|
||||||
|
|
||||||
// Then
|
// Then
|
||||||
expect(Select.selectedValue).toEqual([{label: 'hello', value: -1}]);
|
expect(Select.selectedValue).toEqual([{ label: 'hello', value: -1 }])
|
||||||
expect(Select.$refs.selectedOptions.textContent.trim()).toEqual('hello');
|
expect(Select.$refs.selectedOptions.textContent.trim()).toEqual('hello')
|
||||||
expect(Parent.vm.selected).toEqual(-1);
|
expect(Parent.vm.selected).toEqual(-1)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,59 +1,59 @@
|
|||||||
import { selectWithProps } from "../helpers";
|
import { selectWithProps } from '../helpers'
|
||||||
|
|
||||||
describe("Selectable prop", () => {
|
describe('Selectable prop', () => {
|
||||||
it("should select selectable option if clicked", async () => {
|
it('should select selectable option if clicked', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["one", "two", "three"],
|
options: ['one', 'two', 'three'],
|
||||||
selectable: (option) => option === "one"
|
selectable: (option) => option === 'one',
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data.open = true;
|
Select.vm.$data.open = true
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
Select.find(".vs__dropdown-menu li:first-child").trigger("mousedown");
|
Select.find('.vs__dropdown-menu li:first-child').trigger('mousedown')
|
||||||
|
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should not select not selectable option if clicked", async () => {
|
it('should not select not selectable option if clicked', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["one", "two", "three"],
|
options: ['one', 'two', 'three'],
|
||||||
selectable: (option) => option === "one"
|
selectable: (option) => option === 'one',
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data.open = true;
|
Select.vm.$data.open = true
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
Select.find(".vs__dropdown-menu li:last-child").trigger("mousedown");
|
Select.find('.vs__dropdown-menu li:last-child').trigger('mousedown')
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
|
||||||
|
|
||||||
it("should skip non-selectable option on down arrow keyDown", () => {
|
|
||||||
const Select = selectWithProps({
|
|
||||||
options: ["one", "two", "three"],
|
|
||||||
selectable: (option) => option !== "two"
|
|
||||||
});
|
|
||||||
|
|
||||||
Select.vm.typeAheadPointer = 1;
|
|
||||||
|
|
||||||
Select.find({ ref: "search" }).trigger("keydown.down");
|
|
||||||
|
|
||||||
expect(Select.vm.typeAheadPointer).toEqual(2);
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should skip non-selectable option on up arrow keyDown", () => {
|
it('should skip non-selectable option on down arrow keyDown', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
options: ["one", "two", "three"],
|
options: ['one', 'two', 'three'],
|
||||||
selectable: (option) => option !== "two"
|
selectable: (option) => option !== 'two',
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.typeAheadPointer = 2;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
Select.find({ ref: "search" }).trigger("keydown.up");
|
Select.find({ ref: 'search' }).trigger('keydown.down')
|
||||||
|
|
||||||
expect(Select.vm.typeAheadPointer).toEqual(0);
|
expect(Select.vm.typeAheadPointer).toEqual(2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should skip non-selectable option on up arrow keyDown', () => {
|
||||||
|
const Select = selectWithProps({
|
||||||
|
options: ['one', 'two', 'three'],
|
||||||
|
selectable: (option) => option !== 'two',
|
||||||
|
})
|
||||||
|
|
||||||
|
Select.vm.typeAheadPointer = 2
|
||||||
|
|
||||||
|
Select.find({ ref: 'search' }).trigger('keydown.up')
|
||||||
|
|
||||||
|
expect(Select.vm.typeAheadPointer).toEqual(0)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
+224
-205
@@ -1,303 +1,322 @@
|
|||||||
import { mount, shallowMount } from "@vue/test-utils";
|
import { mount, shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../../src/components/Select.vue";
|
import VueSelect from '../../src/components/Select.vue'
|
||||||
import { mountDefault } from '../helpers';
|
import { mountDefault } from '../helpers'
|
||||||
|
|
||||||
describe("VS - Selecting Values", () => {
|
describe('VS - Selecting Values', () => {
|
||||||
let defaultProps;
|
let defaultProps
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
defaultProps = {
|
defaultProps = {
|
||||||
value: "one",
|
value: 'one',
|
||||||
options: ["one", "two", "three"]
|
options: ['one', 'two', 'three'],
|
||||||
};
|
}
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can accept an array with pre-selected values", () => {
|
it('can accept an array with pre-selected values', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: defaultProps
|
propsData: defaultProps,
|
||||||
});
|
})
|
||||||
expect(Select.selectedValue).toEqual(Select.value);
|
expect(Select.selectedValue).toEqual(Select.value)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can accept an array of objects and pre-selected value (single)", () => {
|
it('can accept an array of objects and pre-selected value (single)', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
value: { label: "This is Foo", value: "foo" },
|
value: { label: 'This is Foo', value: 'foo' },
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
expect(Select.selectedValue).toEqual(Select.value);
|
expect(Select.selectedValue).toEqual(Select.value)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can accept an array of objects and pre-selected values (multiple)", () => {
|
it('can accept an array of objects and pre-selected values (multiple)', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
value: [
|
value: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
],
|
],
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
multiple: true
|
multiple: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.selectedValue).toEqual(Select.value);
|
expect(Select.selectedValue).toEqual(Select.value)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can select an option on tab", () => {
|
it('can select an option on tab', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
selectOnTab: true
|
selectOnTab: true,
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const spy = jest.spyOn(Select.vm, "typeAheadSelect");
|
const spy = jest.spyOn(Select.vm, 'typeAheadSelect')
|
||||||
|
|
||||||
Select.find({ ref: "search" }).trigger("keydown.tab");
|
Select.find({ ref: 'search' }).trigger('keydown.tab')
|
||||||
|
|
||||||
expect(spy).toHaveBeenCalledWith();
|
expect(spy).toHaveBeenCalledWith()
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can deselect a pre-selected object", () => {
|
it('can deselect a pre-selected object', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: [
|
options: [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = [
|
Select.vm.$data._value = [
|
||||||
{ label: "This is Foo", value: "foo" },
|
{ label: 'This is Foo', value: 'foo' },
|
||||||
{ label: "This is Bar", value: "bar" }
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
];
|
]
|
||||||
|
|
||||||
Select.vm.deselect({ label: "This is Foo", value: "foo" });
|
Select.vm.deselect({ label: 'This is Foo', value: 'foo' })
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "This is Bar", value: "bar" }]);
|
expect(Select.vm.selectedValue).toEqual([
|
||||||
});
|
{ label: 'This is Bar', value: 'bar' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
it("can deselect a pre-selected string", () => {
|
it('can deselect a pre-selected string', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: ["foo", "bar"]
|
options: ['foo', 'bar'],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.$data._value = "foo";
|
Select.vm.$data._value = 'foo'
|
||||||
|
|
||||||
Select.vm.deselect("foo");
|
Select.vm.deselect('foo')
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can deselect an option when multiple is false", () => {
|
it('can deselect an option when multiple is false', () => {
|
||||||
const Select = shallowMount(VueSelect);
|
const Select = shallowMount(VueSelect)
|
||||||
|
|
||||||
Select.vm.$data._value = "foo";
|
Select.vm.$data._value = 'foo'
|
||||||
|
|
||||||
Select.vm.deselect("foo");
|
Select.vm.deselect('foo')
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can determine if the value prop is empty", () => {
|
it('can determine if the value prop is empty', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
options: ["one", "two", "three"]
|
options: ['one', 'two', 'three'],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
const select = Select.vm;
|
const select = Select.vm
|
||||||
expect(select.isValueEmpty).toEqual(true);
|
expect(select.isValueEmpty).toEqual(true)
|
||||||
|
|
||||||
select.select(["one"]);
|
select.select(['one'])
|
||||||
expect(select.isValueEmpty).toEqual(false);
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.select("one");
|
select.select('one')
|
||||||
expect(select.isValueEmpty).toEqual(false);
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.select({ label: "foo", value: "foo" });
|
select.select({ label: 'foo', value: 'foo' })
|
||||||
expect(select.isValueEmpty).toEqual(false);
|
expect(select.isValueEmpty).toEqual(false)
|
||||||
|
|
||||||
select.select("");
|
select.select('')
|
||||||
expect(select.isValueEmpty).toEqual(true);
|
expect(select.isValueEmpty).toEqual(true)
|
||||||
|
|
||||||
select.select(null);
|
select.select(null)
|
||||||
expect(select.isValueEmpty).toEqual(true);
|
expect(select.isValueEmpty).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should reset the selected values when the multiple property changes", () => {
|
it('should reset the selected values when the multiple property changes', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: ["one", "two", "three"]
|
options: ['one', 'two', 'three'],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.setProps({ multiple: false });
|
Select.setProps({ multiple: false })
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
|
|
||||||
Select.setProps({ multiple: true });
|
Select.setProps({ multiple: true })
|
||||||
expect(Select.vm.selectedValue).toEqual([]);
|
expect(Select.vm.selectedValue).toEqual([])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can retain values present in a new array of options", () => {
|
it('can retain values present in a new array of options', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two", "three"]
|
options: ['one', 'two', 'three'],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.setProps({ options: ["one", "five", "six"] });
|
Select.setProps({ options: ['one', 'five', 'six'] })
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can determine if an object is already selected", () => {
|
it('can determine if an object is already selected', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
value: [{ label: "one" }],
|
value: [{ label: 'one' }],
|
||||||
options: [{ label: "one" }]
|
options: [{ label: 'one' }],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.isOptionSelected({ label: "one" })).toEqual(true);
|
expect(Select.vm.isOptionSelected({ label: 'one' })).toEqual(true)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can use v-model syntax for a two way binding to a parent component", () => {
|
it('can use v-model syntax for a two way binding to a parent component', () => {
|
||||||
const Parent = mount({
|
const Parent = mount({
|
||||||
data: () => ({ value: "foo", options: ["foo", "bar", "baz"] }),
|
data: () => ({ value: 'foo', options: ['foo', 'bar', 'baz'] }),
|
||||||
template: `<div><v-select :options="options" v-model="value" /></div>`,
|
template: `<div><v-select :options="options" v-model="value" /></div>`,
|
||||||
components: { "v-select": VueSelect }
|
components: { 'v-select': VueSelect },
|
||||||
});
|
})
|
||||||
const Select = Parent.vm.$children[0];
|
const Select = Parent.vm.$children[0]
|
||||||
|
|
||||||
expect(Select.value).toEqual("foo");
|
expect(Select.value).toEqual('foo')
|
||||||
expect(Select.selectedValue).toEqual(["foo"]);
|
expect(Select.selectedValue).toEqual(['foo'])
|
||||||
|
|
||||||
Select.select("bar");
|
Select.select('bar')
|
||||||
expect(Parent.vm.value).toEqual("bar");
|
expect(Parent.vm.value).toEqual('bar')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can check if a string value is selected when the value is an object and multiple is true", () => {
|
it('can check if a string value is selected when the value is an object and multiple is true', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: {
|
propsData: {
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: [{ label: "foo", value: "bar" }]
|
value: [{ label: 'foo', value: 'bar' }],
|
||||||
}
|
},
|
||||||
});
|
})
|
||||||
expect(Select.vm.isOptionSelected({ label: "foo", value: "bar" })).toEqual(true);
|
expect(Select.vm.isOptionSelected({ label: 'foo', value: 'bar' })).toEqual(
|
||||||
});
|
true
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
it('can select two options with the same label', () => {
|
it('can select two options with the same label', () => {
|
||||||
const options = [{label: 'one', id: 1}, {label: 'one', id: 2}];
|
const options = [
|
||||||
const Select = mountDefault({options, multiple: true});
|
{ label: 'one', id: 1 },
|
||||||
|
{ label: 'one', id: 2 },
|
||||||
|
]
|
||||||
|
const Select = mountDefault({ options, multiple: true })
|
||||||
|
|
||||||
Select.vm.select({label: 'one', id: 1});
|
Select.vm.select({ label: 'one', id: 1 })
|
||||||
Select.vm.select({label: 'one', id: 2});
|
Select.vm.select({ label: 'one', id: 2 })
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual(options);
|
expect(Select.vm.selectedValue).toEqual(options)
|
||||||
});
|
})
|
||||||
|
|
||||||
describe("input Event", () => {
|
describe('input Event', () => {
|
||||||
it("will trigger the input event when the selection changes", () => {
|
it('will trigger the input event when the selection changes', () => {
|
||||||
const Select = shallowMount(VueSelect);
|
const Select = shallowMount(VueSelect)
|
||||||
Select.vm.select("bar");
|
Select.vm.select('bar')
|
||||||
expect(Select.emitted("input")[0]).toEqual(["bar"]);
|
expect(Select.emitted('input')[0]).toEqual(['bar'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the input event when the selection changes and multiple is true", () => {
|
it('will trigger the input event when the selection changes and multiple is true', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { multiple: true, value: ["foo"], options: ["foo", "bar"] }
|
propsData: { multiple: true, value: ['foo'], options: ['foo', 'bar'] },
|
||||||
});
|
})
|
||||||
Select.vm.select("bar");
|
Select.vm.select('bar')
|
||||||
expect(Select.emitted("input")[0]).toEqual([["foo", "bar"]]);
|
expect(Select.emitted('input')[0]).toEqual([['foo', 'bar']])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will not trigger the input event when multiple is true and selection is repeated", () => {
|
it('will not trigger the input event when multiple is true and selection is repeated', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { multiple: true, value: ["foo ", "bar"], options: ["foo", "bar", "baz"] }
|
propsData: {
|
||||||
});
|
multiple: true,
|
||||||
|
value: ['foo ', 'bar'],
|
||||||
|
options: ['foo', 'bar', 'baz'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
Select.vm.select("bar");
|
Select.vm.select('bar')
|
||||||
expect(Select.emitted("input")).toBeFalsy();
|
expect(Select.emitted('input')).toBeFalsy()
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
describe("option:selecting Event", () => {
|
describe('option:selecting Event', () => {
|
||||||
it("will trigger the option:selecting event when an option is selected", () => {
|
it('will trigger the option:selecting event when an option is selected', () => {
|
||||||
const Select = shallowMount(VueSelect);
|
const Select = shallowMount(VueSelect)
|
||||||
Select.vm.select("bar");
|
Select.vm.select('bar')
|
||||||
expect(Select.emitted("option:selecting")[0]).toEqual(["bar"]);
|
expect(Select.emitted('option:selecting')[0]).toEqual(['bar'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the option:selecting event regardless of current value", () => {
|
it('will trigger the option:selecting event regardless of current value', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { value: ["foo"], options: ["foo", "bar"] }
|
propsData: { value: ['foo'], options: ['foo', 'bar'] },
|
||||||
});
|
})
|
||||||
Select.vm.select("foo");
|
Select.vm.select('foo')
|
||||||
Select.vm.select("bar");
|
Select.vm.select('bar')
|
||||||
expect(Select.emitted("option:selecting")).toEqual([["foo"], ["bar"]]);
|
expect(Select.emitted('option:selecting')).toEqual([['foo'], ['bar']])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the option:selecting event with current selected item when multiple is true", () => {
|
it('will trigger the option:selecting event with current selected item when multiple is true', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { multiple: true, value: ["foo"], options: ["foo", "bar"] }
|
propsData: { multiple: true, value: ['foo'], options: ['foo', 'bar'] },
|
||||||
});
|
})
|
||||||
Select.vm.select("bar");
|
Select.vm.select('bar')
|
||||||
expect(Select.emitted("option:selecting")[0]).toEqual(["bar"]);
|
expect(Select.emitted('option:selecting')[0]).toEqual(['bar'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the option:selecting event regardless of current value when multiple is true", () => {
|
it('will trigger the option:selecting event regardless of current value when multiple is true', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { multiple: true, value: ["foo", "bar"], options: ["foo", "bar"] }
|
propsData: {
|
||||||
});
|
multiple: true,
|
||||||
Select.vm.select("bar");
|
value: ['foo', 'bar'],
|
||||||
Select.vm.select("bar");
|
options: ['foo', 'bar'],
|
||||||
expect(Select.emitted("option:selecting")).toEqual([["bar"], ["bar"]]);
|
},
|
||||||
});
|
})
|
||||||
});
|
Select.vm.select('bar')
|
||||||
|
Select.vm.select('bar')
|
||||||
|
expect(Select.emitted('option:selecting')).toEqual([['bar'], ['bar']])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("option:deselected Event", () => {
|
describe('option:deselected Event', () => {
|
||||||
it("will trigger the option:deselected event when an option is deselected", () => {
|
it('will trigger the option:deselected event when an option is deselected', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { value: ["foo"], options: ["foo", "bar"] }
|
propsData: { value: ['foo'], options: ['foo', 'bar'] },
|
||||||
});
|
})
|
||||||
Select.vm.deselect("foo");
|
Select.vm.deselect('foo')
|
||||||
expect(Select.emitted("option:deselected")[0]).toEqual(["foo"]);
|
expect(Select.emitted('option:deselected')[0]).toEqual(['foo'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the option:deselected event regardless of current value", () => {
|
it('will trigger the option:deselected event regardless of current value', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { value: ["foo"], options: ["foo", "bar"] }
|
propsData: { value: ['foo'], options: ['foo', 'bar'] },
|
||||||
});
|
})
|
||||||
Select.vm.deselect("foo");
|
Select.vm.deselect('foo')
|
||||||
Select.vm.deselect("bar");
|
Select.vm.deselect('bar')
|
||||||
expect(Select.emitted("option:deselected")).toEqual([["foo"], ["bar"]]);
|
expect(Select.emitted('option:deselected')).toEqual([['foo'], ['bar']])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the option:selected event with current selected item when multiple is true", () => {
|
it('will trigger the option:selected event with current selected item when multiple is true', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { multiple: true, value: ["foo"], options: ["foo", "bar"] }
|
propsData: { multiple: true, value: ['foo'], options: ['foo', 'bar'] },
|
||||||
});
|
})
|
||||||
Select.vm.deselect("bar");
|
Select.vm.deselect('bar')
|
||||||
expect(Select.emitted("option:deselected")[0]).toEqual(["bar"]);
|
expect(Select.emitted('option:deselected')[0]).toEqual(['bar'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will trigger the option:selected event regardless of current value when multiple is true", () => {
|
it('will trigger the option:selected event regardless of current value when multiple is true', () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { multiple: true, value: ["foo", "bar"], options: ["foo", "bar"] }
|
propsData: {
|
||||||
});
|
multiple: true,
|
||||||
Select.vm.deselect("bar");
|
value: ['foo', 'bar'],
|
||||||
Select.vm.deselect("bar");
|
options: ['foo', 'bar'],
|
||||||
expect(Select.emitted("option:deselected")).toEqual([["bar"], ["bar"]]);
|
},
|
||||||
});
|
})
|
||||||
});
|
Select.vm.deselect('bar')
|
||||||
});
|
Select.vm.deselect('bar')
|
||||||
|
expect(Select.emitted('option:deselected')).toEqual([['bar'], ['bar']])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
+107
-76
@@ -1,122 +1,153 @@
|
|||||||
import { mountDefault } from '../helpers';
|
import { mountDefault } from '../helpers'
|
||||||
|
|
||||||
describe('Scoped Slots', () => {
|
describe('Scoped Slots', () => {
|
||||||
it('receives an option object to the selected-option-container slot', () => {
|
it('receives an option object to the selected-option-container slot', () => {
|
||||||
const Select = mountDefault(
|
const Select = mountDefault(
|
||||||
{value: 'one'},
|
{ value: 'one' },
|
||||||
{
|
{
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
'selected-option-container': `<span slot="selected-option-container" slot-scope="{option}">{{ option.label }}</span>`,
|
'selected-option-container': `<span slot="selected-option-container" slot-scope="{option}">{{ option.label }}</span>`,
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(Select.find({ref: 'selectedOptions'}).text()).toEqual('one');
|
expect(Select.find({ ref: 'selectedOptions' }).text()).toEqual('one')
|
||||||
});
|
})
|
||||||
|
|
||||||
describe('Slot: selected-option', () => {
|
describe('Slot: selected-option', () => {
|
||||||
it('receives an option object to the selected-option slot', () => {
|
it('receives an option object to the selected-option slot', () => {
|
||||||
const Select = mountDefault(
|
const Select = mountDefault(
|
||||||
{value: 'one'},
|
{ value: 'one' },
|
||||||
{
|
{
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
'selected-option': `<span slot="selected-option" slot-scope="option">{{ option.label }}</span>`,
|
'selected-option': `<span slot="selected-option" slot-scope="option">{{ option.label }}</span>`,
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
)
|
||||||
|
|
||||||
expect(Select.find('.vs__selected').text()).toEqual('one');
|
expect(Select.find('.vs__selected').text()).toEqual('one')
|
||||||
});
|
})
|
||||||
|
|
||||||
it('opens the dropdown when clicking an option in selected-option slot',
|
it('opens the dropdown when clicking an option in selected-option slot', () => {
|
||||||
() => {
|
|
||||||
const Select = mountDefault(
|
|
||||||
{value: 'one'},
|
|
||||||
{
|
|
||||||
scopedSlots: {
|
|
||||||
'selected-option': `<span class="my-option" slot-scope="option">{{ option.label }}</span>`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
Select.find('.my-option').trigger('mousedown');
|
|
||||||
expect(Select.vm.open).toEqual(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('receives an option object to the option slot in the dropdown menu',
|
|
||||||
async () => {
|
|
||||||
const Select = mountDefault(
|
const Select = mountDefault(
|
||||||
{value: 'one'},
|
{ value: 'one' },
|
||||||
{
|
{
|
||||||
scopedSlots: {
|
scopedSlots: {
|
||||||
'option': `<span slot="option" slot-scope="option">{{ option.label }}</span>`,
|
'selected-option': `<span class="my-option" slot-scope="option">{{ option.label }}</span>`,
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.find('.my-option').trigger('mousedown')
|
||||||
await Select.vm.$nextTick();
|
expect(Select.vm.open).toEqual(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
expect(Select.find({ref: 'dropdownMenu'}).text()).toEqual('onetwothree');
|
it('receives an option object to the option slot in the dropdown menu', async () => {
|
||||||
});
|
const Select = mountDefault(
|
||||||
|
{ value: 'one' },
|
||||||
|
{
|
||||||
|
scopedSlots: {
|
||||||
|
option: `<span slot="option" slot-scope="option">{{ option.label }}</span>`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
Select.vm.open = true
|
||||||
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(Select.find({ ref: 'dropdownMenu' }).text()).toEqual('onetwothree')
|
||||||
|
})
|
||||||
|
|
||||||
it('noOptions slot receives the current search text', async () => {
|
it('noOptions slot receives the current search text', async () => {
|
||||||
const noOptions = jest.fn();
|
const noOptions = jest.fn()
|
||||||
const Select = mountDefault({}, {
|
const Select = mountDefault(
|
||||||
scopedSlots: {'no-options': noOptions},
|
{},
|
||||||
});
|
{
|
||||||
|
scopedSlots: { 'no-options': noOptions },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
Select.vm.search = 'something not there';
|
Select.vm.search = 'something not there'
|
||||||
Select.vm.open = true;
|
Select.vm.open = true
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
expect(noOptions).toHaveBeenCalledWith({
|
expect(noOptions).toHaveBeenCalledWith({
|
||||||
loading: false,
|
loading: false,
|
||||||
search: 'something not there',
|
search: 'something not there',
|
||||||
searching: true,
|
searching: true,
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|
||||||
test('header slot props', async () => {
|
test('header slot props', async () => {
|
||||||
const header = jest.fn();
|
const header = jest.fn()
|
||||||
const Select = mountDefault({}, {
|
const Select = mountDefault(
|
||||||
scopedSlots: {header: header},
|
{},
|
||||||
});
|
{
|
||||||
await Select.vm.$nextTick();
|
scopedSlots: { header: header },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await Select.vm.$nextTick()
|
||||||
expect(Object.keys(header.mock.calls[0][0])).toEqual([
|
expect(Object.keys(header.mock.calls[0][0])).toEqual([
|
||||||
'search', 'loading', 'searching', 'filteredOptions', 'deselect',
|
'search',
|
||||||
]);
|
'loading',
|
||||||
});
|
'searching',
|
||||||
|
'filteredOptions',
|
||||||
|
'deselect',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('footer slot props', async () => {
|
test('footer slot props', async () => {
|
||||||
const footer = jest.fn();
|
const footer = jest.fn()
|
||||||
const Select = mountDefault({}, {
|
const Select = mountDefault(
|
||||||
scopedSlots: {footer: footer},
|
{},
|
||||||
});
|
{
|
||||||
await Select.vm.$nextTick();
|
scopedSlots: { footer: footer },
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await Select.vm.$nextTick()
|
||||||
expect(Object.keys(footer.mock.calls[0][0])).toEqual([
|
expect(Object.keys(footer.mock.calls[0][0])).toEqual([
|
||||||
'search', 'loading', 'searching', 'filteredOptions', 'deselect',
|
'search',
|
||||||
]);
|
'loading',
|
||||||
});
|
'searching',
|
||||||
|
'filteredOptions',
|
||||||
|
'deselect',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('list-header slot props', async () => {
|
test('list-header slot props', async () => {
|
||||||
const header = jest.fn();
|
const header = jest.fn()
|
||||||
const Select = mountDefault({}, {
|
const Select = mountDefault(
|
||||||
scopedSlots: {'list-header': header},
|
{},
|
||||||
});
|
{
|
||||||
Select.vm.open = true;
|
scopedSlots: { 'list-header': header },
|
||||||
await Select.vm.$nextTick();
|
}
|
||||||
|
)
|
||||||
|
Select.vm.open = true
|
||||||
|
await Select.vm.$nextTick()
|
||||||
expect(Object.keys(header.mock.calls[0][0])).toEqual([
|
expect(Object.keys(header.mock.calls[0][0])).toEqual([
|
||||||
'search', 'loading', 'searching', 'filteredOptions',
|
'search',
|
||||||
]);
|
'loading',
|
||||||
});
|
'searching',
|
||||||
|
'filteredOptions',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
test('list-footer slot props', async () => {
|
test('list-footer slot props', async () => {
|
||||||
const footer = jest.fn();
|
const footer = jest.fn()
|
||||||
const Select = mountDefault({}, {
|
const Select = mountDefault(
|
||||||
scopedSlots: {'list-footer': footer},
|
{},
|
||||||
});
|
{
|
||||||
Select.vm.open = true;
|
scopedSlots: { 'list-footer': footer },
|
||||||
await Select.vm.$nextTick();
|
}
|
||||||
|
)
|
||||||
|
Select.vm.open = true
|
||||||
|
await Select.vm.$nextTick()
|
||||||
expect(Object.keys(footer.mock.calls[0][0])).toEqual([
|
expect(Object.keys(footer.mock.calls[0][0])).toEqual([
|
||||||
'search', 'loading', 'searching', 'filteredOptions',
|
'search',
|
||||||
]);
|
'loading',
|
||||||
});
|
'searching',
|
||||||
});
|
'filteredOptions',
|
||||||
|
])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
+156
-159
@@ -3,261 +3,258 @@ import {
|
|||||||
searchSubmit,
|
searchSubmit,
|
||||||
selectTag,
|
selectTag,
|
||||||
selectWithProps,
|
selectWithProps,
|
||||||
} from '../helpers';
|
} from '../helpers'
|
||||||
import Select from '../../src/components/Select';
|
import Select from '../../src/components/Select'
|
||||||
|
|
||||||
describe("When Tagging Is Enabled", () => {
|
describe('When Tagging Is Enabled', () => {
|
||||||
|
it('can determine if a given option string already exists', () => {
|
||||||
|
const Select = selectWithProps({ taggable: true, options: ['one', 'two'] })
|
||||||
|
expect(Select.vm.optionExists('one')).toEqual(true)
|
||||||
|
expect(Select.vm.optionExists('three')).toEqual(false)
|
||||||
|
})
|
||||||
|
|
||||||
it("can determine if a given option string already exists", () => {
|
it('can determine if a given option object already exists', () => {
|
||||||
const Select = selectWithProps({ taggable: true, options: ["one", "two"] });
|
|
||||||
expect(Select.vm.optionExists("one")).toEqual(true);
|
|
||||||
expect(Select.vm.optionExists("three")).toEqual(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("can determine if a given option object already exists", () => {
|
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
options: [{ label: "one" }, { label: "two" }]
|
options: [{ label: 'one' }, { label: 'two' }],
|
||||||
});
|
})
|
||||||
|
|
||||||
expect(Select.vm.optionExists({label: "one"})).toEqual(true);
|
expect(Select.vm.optionExists({ label: 'one' })).toEqual(true)
|
||||||
expect(Select.vm.optionExists({label: "three"})).toEqual(false);
|
expect(Select.vm.optionExists({ label: 'three' })).toEqual(false)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can determine if a given option object already exists when using custom labels", () => {
|
it('can determine if a given option object already exists when using custom labels', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
options: [{ foo: "one" }, { foo: "two" }],
|
options: [{ foo: 'one' }, { foo: 'two' }],
|
||||||
label: "foo"
|
label: 'foo',
|
||||||
});
|
})
|
||||||
|
|
||||||
const createOption = (text) => Select.vm.createOption(text);
|
const createOption = (text) => Select.vm.createOption(text)
|
||||||
|
|
||||||
expect(Select.vm.optionExists(createOption("one"))).toEqual(true);
|
expect(Select.vm.optionExists(createOption('one'))).toEqual(true)
|
||||||
expect(Select.vm.optionExists(createOption("three"))).toEqual(false);
|
expect(Select.vm.optionExists(createOption('three'))).toEqual(false)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can add the current search text as the first item in the options list", async () => {
|
it('can add the current search text as the first item in the options list', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.search = "three";
|
Select.vm.search = 'three'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
expect(Select.vm.filteredOptions).toEqual(["three"]);
|
expect(Select.vm.filteredOptions).toEqual(['three'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can select the current search text as a string", async () => {
|
it('can select the current search text as a string', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual(["three"]);
|
expect(Select.vm.selectedValue).toEqual(['three'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("can select the current search text as an object", async () => {
|
it('can select the current search text as an object', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: [{ label: "one" }]
|
options: [{ label: 'one' }],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "two");
|
await selectTag(Select, 'two')
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([
|
expect(Select.vm.selectedValue).toEqual([{ label: 'two' }])
|
||||||
{ label: "two" }
|
})
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should add a freshly created option/tag to the options list when pushTags is true", async () => {
|
it('should add a freshly created option/tag to the options list when pushTags is true', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
pushTags: true,
|
pushTags: true,
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
expect(Select.vm.pushedTags).toEqual(["three"]);
|
expect(Select.vm.pushedTags).toEqual(['three'])
|
||||||
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
|
expect(Select.vm.optionList).toEqual(['one', 'two', 'three'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should pushTags even if the consumer has defined a createOption callback", async () => {
|
it('should pushTags even if the consumer has defined a createOption callback', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
pushTags: true,
|
pushTags: true,
|
||||||
taggable: true,
|
taggable: true,
|
||||||
createOption: option => option,
|
createOption: (option) => option,
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
|
|
||||||
expect(Select.vm.pushedTags).toEqual(["three"]);
|
expect(Select.vm.pushedTags).toEqual(['three'])
|
||||||
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
|
expect(Select.vm.optionList).toEqual(['one', 'two', 'three'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should add a freshly created option/tag to the options list when pushTags is true and filterable is false", async () => {
|
it('should add a freshly created option/tag to the options list when pushTags is true and filterable is false', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
filterable: false,
|
filterable: false,
|
||||||
pushTags: true,
|
pushTags: true,
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
expect(Select.vm.pushedTags).toEqual(["three"]);
|
expect(Select.vm.pushedTags).toEqual(['three'])
|
||||||
expect(Select.vm.optionList).toEqual(["one", "two", "three"]);
|
expect(Select.vm.optionList).toEqual(['one', 'two', 'three'])
|
||||||
expect(Select.vm.filteredOptions).toEqual(["one", "two", "three"]);
|
expect(Select.vm.filteredOptions).toEqual(['one', 'two', 'three'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("wont add a freshly created option/tag to the options list when pushTags is false", async () => {
|
it('wont add a freshly created option/tag to the options list when pushTags is false', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
pushTags: false,
|
pushTags: false,
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
expect(Select.vm.optionList).toEqual(["one", "two"]);
|
expect(Select.vm.optionList).toEqual(['one', 'two'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("wont add a freshly created option/tag to the options list when pushTags is false and filterable is false", async () => {
|
it('wont add a freshly created option/tag to the options list when pushTags is false and filterable is false', async () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
filterable: false,
|
filterable: false,
|
||||||
pushTags: false,
|
pushTags: false,
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: ["one"],
|
value: ['one'],
|
||||||
options: ["one", "two"]
|
options: ['one', 'two'],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "three");
|
await selectTag(Select, 'three')
|
||||||
expect(Select.vm.optionList).toEqual(["one", "two"]);
|
expect(Select.vm.optionList).toEqual(['one', 'two'])
|
||||||
expect(Select.vm.filteredOptions).toEqual(["one", "two"]);
|
expect(Select.vm.filteredOptions).toEqual(['one', 'two'])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should select an existing option if the search string matches a string from options", async () => {
|
it('should select an existing option if the search string matches a string from options', async () => {
|
||||||
let two = "two";
|
let two = 'two'
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: ["one", two]
|
options: ['one', two],
|
||||||
});
|
})
|
||||||
|
|
||||||
await selectTag(Select, "two");
|
await selectTag(Select, 'two')
|
||||||
|
|
||||||
expect(Select.vm.selectedValue).toEqual([two]);
|
expect(Select.vm.selectedValue).toEqual([two])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should select an existing option if the search string matches an objects label from options", async () => {
|
it('should select an existing option if the search string matches an objects label from options', async () => {
|
||||||
let two = { label: "two" };
|
let two = { label: 'two' }
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
options: [{ label: "one" }, two]
|
options: [{ label: 'one' }, two],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.search = "two";
|
Select.vm.search = 'two'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
searchSubmit(Select);
|
searchSubmit(Select)
|
||||||
expect(Select.vm.selectedValue).toEqual([two]);
|
expect(Select.vm.selectedValue).toEqual([two])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should select an existing option if the search string matches an objects label from options when filter-options is false", async () => {
|
it('should select an existing option if the search string matches an objects label from options when filter-options is false', async () => {
|
||||||
let two = { label: "two" };
|
let two = { label: 'two' }
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
filterable: false,
|
filterable: false,
|
||||||
options: [{ label: "one" }, two]
|
options: [{ label: 'one' }, two],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.search = "two";
|
Select.vm.search = 'two'
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
|
|
||||||
searchSubmit(Select);
|
searchSubmit(Select)
|
||||||
expect(Select.vm.selectedValue).toEqual([two]);
|
expect(Select.vm.selectedValue).toEqual([two])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not reset the selected value when the options property changes", () => {
|
it('should not reset the selected value when the options property changes', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
value: [{ label: "one" }],
|
value: [{ label: 'one' }],
|
||||||
options: [{ label: "one" }]
|
options: [{ label: 'one' }],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.setProps({ options: [{ label: "two" }] });
|
Select.setProps({ options: [{ label: 'two' }] })
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
expect(Select.vm.selectedValue).toEqual([{ label: 'one' }])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not reset the selected value when the options property changes when filterable is false", () => {
|
it('should not reset the selected value when the options property changes when filterable is false', () => {
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
filterable: false,
|
filterable: false,
|
||||||
value: [{ label: "one" }],
|
value: [{ label: 'one' }],
|
||||||
options: [{ label: "one" }]
|
options: [{ label: 'one' }],
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.setProps({ options: [{ label: "two" }] });
|
Select.setProps({ options: [{ label: 'two' }] })
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
expect(Select.vm.selectedValue).toEqual([{ label: 'one' }])
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not allow duplicate tags when using string options", async () => {
|
it('should not allow duplicate tags when using string options', async () => {
|
||||||
const Select = selectWithProps({
|
|
||||||
taggable: true,
|
|
||||||
multiple: true
|
|
||||||
});
|
|
||||||
|
|
||||||
await selectTag(Select, "one");
|
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
|
||||||
expect(Select.vm.search).toEqual("");
|
|
||||||
|
|
||||||
await selectTag(Select, "one");
|
|
||||||
expect(Select.vm.selectedValue).toEqual(["one"]);
|
|
||||||
expect(Select.vm.search).toEqual("");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should not allow duplicate tags when using object options", async () => {
|
|
||||||
const Select = selectWithProps({
|
const Select = selectWithProps({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
multiple: true,
|
multiple: true,
|
||||||
options: [{ label: "two" }]
|
})
|
||||||
});
|
|
||||||
const spy = jest.spyOn(Select.vm, 'select');
|
|
||||||
|
|
||||||
await selectTag(Select, "one");
|
await selectTag(Select, 'one')
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
expect(spy).lastCalledWith({label: 'one'});
|
expect(Select.vm.search).toEqual('')
|
||||||
expect(Select.vm.search).toEqual("");
|
|
||||||
|
|
||||||
await selectTag(Select, "one");
|
await selectTag(Select, 'one')
|
||||||
expect(Select.vm.selectedValue).toEqual([{ label: "one" }]);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
expect(Select.vm.search).toEqual("");
|
expect(Select.vm.search).toEqual('')
|
||||||
});
|
})
|
||||||
|
|
||||||
it("will select an existing option on tab", async () => {
|
it('should not allow duplicate tags when using object options', async () => {
|
||||||
|
const Select = selectWithProps({
|
||||||
|
taggable: true,
|
||||||
|
multiple: true,
|
||||||
|
options: [{ label: 'two' }],
|
||||||
|
})
|
||||||
|
const spy = jest.spyOn(Select.vm, 'select')
|
||||||
|
|
||||||
|
await selectTag(Select, 'one')
|
||||||
|
expect(Select.vm.selectedValue).toEqual([{ label: 'one' }])
|
||||||
|
expect(spy).lastCalledWith({ label: 'one' })
|
||||||
|
expect(Select.vm.search).toEqual('')
|
||||||
|
|
||||||
|
await selectTag(Select, 'one')
|
||||||
|
expect(Select.vm.selectedValue).toEqual([{ label: 'one' }])
|
||||||
|
expect(Select.vm.search).toEqual('')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('will select an existing option on tab', async () => {
|
||||||
const Select = mountDefault({
|
const Select = mountDefault({
|
||||||
taggable: true,
|
taggable: true,
|
||||||
selectOnTab: true
|
selectOnTab: true,
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.typeAheadPointer = 0;
|
Select.vm.typeAheadPointer = 0
|
||||||
Select.find({ ref: "search" }).trigger("keydown.tab");
|
Select.find({ ref: 'search' }).trigger('keydown.tab')
|
||||||
|
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
expect(Select.vm.selectedValue).toEqual(['one']);
|
expect(Select.vm.selectedValue).toEqual(['one'])
|
||||||
})
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,47 +1,47 @@
|
|||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import VueSelect from "../../src/components/Select";
|
import VueSelect from '../../src/components/Select'
|
||||||
import { mountDefault, mountWithoutTestUtils } from "../helpers";
|
import { mountDefault, mountWithoutTestUtils } from '../helpers'
|
||||||
import typeAheadMixin from "../../src/mixins/typeAheadPointer";
|
import typeAheadMixin from '../../src/mixins/typeAheadPointer'
|
||||||
import Vue from "vue";
|
import Vue from 'vue'
|
||||||
|
|
||||||
describe("Moving the Typeahead Pointer", () => {
|
describe('Moving the Typeahead Pointer', () => {
|
||||||
it("should set the pointer to zero when the filteredOptions watcher is called", async () => {
|
it('should set the pointer to zero when the filteredOptions watcher is called', async () => {
|
||||||
const Select = shallowMount(VueSelect, {
|
const Select = shallowMount(VueSelect, {
|
||||||
propsData: { options: ["one", "two", "three"] },
|
propsData: { options: ['one', 'two', 'three'] },
|
||||||
sync: false
|
sync: false,
|
||||||
});
|
})
|
||||||
|
|
||||||
Select.vm.search = "one";
|
Select.vm.search = 'one'
|
||||||
|
|
||||||
await Select.vm.$nextTick();
|
await Select.vm.$nextTick()
|
||||||
expect(Select.vm.typeAheadPointer).toEqual(0);
|
expect(Select.vm.typeAheadPointer).toEqual(0)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should move the pointer visually up the list on up arrow keyUp", () => {
|
it('should move the pointer visually up the list on up arrow keyUp', () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
|
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
Select.find({ ref: "search" }).trigger("keydown.up");
|
Select.find({ ref: 'search' }).trigger('keydown.up')
|
||||||
|
|
||||||
expect(Select.vm.typeAheadPointer).toEqual(0);
|
expect(Select.vm.typeAheadPointer).toEqual(0)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should move the pointer visually down the list on down arrow keyUp", () => {
|
it('should move the pointer visually down the list on down arrow keyUp', () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
|
|
||||||
Select.vm.typeAheadPointer = 1;
|
Select.vm.typeAheadPointer = 1
|
||||||
|
|
||||||
Select.find({ ref: "search" }).trigger("keydown.down");
|
Select.find({ ref: 'search' }).trigger('keydown.down')
|
||||||
|
|
||||||
expect(Select.vm.typeAheadPointer).toEqual(2);
|
expect(Select.vm.typeAheadPointer).toEqual(2)
|
||||||
});
|
})
|
||||||
|
|
||||||
it("should not move the pointer past the end of the list", () => {
|
it('should not move the pointer past the end of the list', () => {
|
||||||
const Select = mountDefault();
|
const Select = mountDefault()
|
||||||
|
|
||||||
Select.vm.typeAheadPointer = 2;
|
Select.vm.typeAheadPointer = 2
|
||||||
Select.vm.typeAheadDown();
|
Select.vm.typeAheadDown()
|
||||||
expect(Select.vm.typeAheadPointer).toEqual(2);
|
expect(Select.vm.typeAheadPointer).toEqual(2)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import sortAndStringify from '../../../src/utility/sortAndStringify';
|
import sortAndStringify from '../../../src/utility/sortAndStringify'
|
||||||
|
|
||||||
test('it will stringify an object', () => {
|
test('it will stringify an object', () => {
|
||||||
expect(sortAndStringify({hello: 'world'})).toEqual('{"hello":"world"}');
|
expect(sortAndStringify({ hello: 'world' })).toEqual('{"hello":"world"}')
|
||||||
});
|
})
|
||||||
|
|
||||||
test('it will sort attributes alphabetically', () => {
|
test('it will sort attributes alphabetically', () => {
|
||||||
expect(sortAndStringify({b: 'b', a: 'a'})).toEqual('{"a":"a","b":"b"}');
|
expect(sortAndStringify({ b: 'b', a: 'a' })).toEqual('{"a":"a","b":"b"}')
|
||||||
});
|
})
|
||||||
|
|
||||||
test('comparing two objects with unsorted keys', () => {
|
test('comparing two objects with unsorted keys', () => {
|
||||||
expect(sortAndStringify({b: 'b', a: 'a'}))
|
expect(sortAndStringify({ b: 'b', a: 'a' })).toEqual(
|
||||||
.toEqual(sortAndStringify({a: 'a', b: 'b'}))
|
sortAndStringify({ a: 'a', b: 'b' })
|
||||||
});
|
)
|
||||||
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import uniqueId from '../../../src/utility/uniqueId';
|
import uniqueId from '../../../src/utility/uniqueId'
|
||||||
|
|
||||||
test('it generates a unique number', () => {
|
test('it generates a unique number', () => {
|
||||||
expect(uniqueId()).not.toEqual(uniqueId());
|
expect(uniqueId()).not.toEqual(uniqueId())
|
||||||
});
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user