mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-22 10:30:34 +03:00
Sass & Class Renames (#759)
* - add autoprefixer - add cssnano - add postcss-loader - remove unused packages * create RTL scss module * add vs__ prefix to open-indicator, extract to module * module for dropdown-toggle * vs__clear module * vs__dropdown-menu module * rename `selected-tag` to `vs__selected` * remove rtl class * remove dropdown class * search-input scss module * move animations to global module * refactor dropdown list items * - spinner slot is now scoped with `loading` variable - move spinner to scss module * apply vs__search class directly to search input: if you're using the slot, you might not want default styles * finish global modules * make RTL a component state * - update component states to use vs-- prefix - rename dropdownClasses to stateClasses * remove unused property * Closes #760 * fix states * more state fixes * rename .close to vs__deselect * - simplify dev.html - start on 'sandbox' development * update build * - update webpack config - move Sandbox to VuePress folder * update external framework version links * assign grid areas, ensure 100% height outside of docs * limit specificity * first pass at assigning variables * assign 'darkest' * remove max-height prop * rename 'component' variables to 'state' * update badges * add deprecation notice to docs * bump travis config * add coveralls coverage reporter * bump netlify config * additional pass pulling up to variables * start converting to SVG icons * middle align action icons * update netlify config * netlify bump * fix travis * fix travis * try lcov * netlify attempt * prune old packages * bump travis config
This commit is contained in:
+5
-4
@@ -1,8 +1,9 @@
|
|||||||
language: node_js
|
language: node_js
|
||||||
|
cache: npm
|
||||||
|
|
||||||
node_js:
|
node_js:
|
||||||
- node
|
- node
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- node_modules
|
|
||||||
script:
|
script:
|
||||||
- yarn test --coverage --coverageReporters=text-lcov | coveralls
|
- yarn test --coverage --coverageReporters=text-lcov
|
||||||
|
- codecov
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const webpack = require('webpack');
|
const webpack = require('webpack');
|
||||||
const chokidar = require('chokidar');
|
|
||||||
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');
|
||||||
|
|
||||||
@@ -8,7 +7,9 @@ const env = process.env.NODE_ENV === 'production'
|
|||||||
? 'production'
|
? 'production'
|
||||||
: 'development';
|
: 'development';
|
||||||
|
|
||||||
const extractOrInjectStyles = process.env.NODE_ENV !== 'production'
|
const devtool = env === 'production' ? 'source-map' : 'eval-source-map';
|
||||||
|
|
||||||
|
const extractOrInjectStyles = env !== 'production'
|
||||||
? 'vue-style-loader'
|
? 'vue-style-loader'
|
||||||
: MiniCssExtractPlugin.loader;
|
: MiniCssExtractPlugin.loader;
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ module.exports = {
|
|||||||
publicPath: '/',
|
publicPath: '/',
|
||||||
filename: '[name].js',
|
filename: '[name].js',
|
||||||
},
|
},
|
||||||
// devtool: env === 'production' ? 'source-map' : 'eval-source-map',
|
devtool,
|
||||||
resolve: {
|
resolve: {
|
||||||
extensions: ['.js', '.vue'],
|
extensions: ['.js', '.vue'],
|
||||||
alias: {
|
alias: {
|
||||||
@@ -47,13 +48,10 @@ module.exports = {
|
|||||||
use: [
|
use: [
|
||||||
extractOrInjectStyles,
|
extractOrInjectStyles,
|
||||||
'css-loader',
|
'css-loader',
|
||||||
|
'postcss-loader',
|
||||||
'sass-loader',
|
'sass-loader',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.html$/,
|
|
||||||
loader: 'vue-html-loader',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
@@ -65,17 +63,8 @@ module.exports = {
|
|||||||
}),
|
}),
|
||||||
new VueLoaderPlugin(),
|
new VueLoaderPlugin(),
|
||||||
],
|
],
|
||||||
devServer: {
|
stats: {
|
||||||
hot: true,
|
children: false,
|
||||||
hotOnly: true,
|
modules: false,
|
||||||
inline: true,
|
|
||||||
port: 8080,
|
|
||||||
before (app, server) {
|
|
||||||
chokidar.watch([
|
|
||||||
'./**/*.html',
|
|
||||||
]).on('all', function () {
|
|
||||||
server.sockWrite(server.sockets, 'content-changed');
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
const merge = require('webpack-merge');
|
const merge = require('webpack-merge');
|
||||||
|
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');
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
module.exports = merge(baseWebpackConfig, {
|
module.exports = merge(baseWebpackConfig, {
|
||||||
entry: './dev/dev.js',
|
entry: './dev/dev.js',
|
||||||
plugins: [
|
plugins: [
|
||||||
new HtmlWebpackPlugin({
|
new HtmlWebpackPlugin({
|
||||||
filename: 'index.html',
|
|
||||||
template: './dev/dev.html',
|
template: './dev/dev.html',
|
||||||
inject: true,
|
inject: true,
|
||||||
}),
|
}),
|
||||||
@@ -14,4 +17,23 @@ module.exports = merge(baseWebpackConfig, {
|
|||||||
optimization: {
|
optimization: {
|
||||||
noEmitOnErrors: true,
|
noEmitOnErrors: true,
|
||||||
},
|
},
|
||||||
|
devServer: {
|
||||||
|
hot: true,
|
||||||
|
hotOnly: true,
|
||||||
|
open: true,
|
||||||
|
inline: true,
|
||||||
|
stats: {
|
||||||
|
children: false,
|
||||||
|
modules: false,
|
||||||
|
chunks: false,
|
||||||
|
},
|
||||||
|
port: 8080,
|
||||||
|
before (app, server) {
|
||||||
|
chokidar.watch([
|
||||||
|
'./**/*.html',
|
||||||
|
]).on('all', function () {
|
||||||
|
server.sockWrite(server.sockets, 'content-changed');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
+20
-115
@@ -1,130 +1,35 @@
|
|||||||
<template>
|
<template>
|
||||||
<div id="app">
|
<div id="app">
|
||||||
<v-select placeholder="default" :options="options"></v-select>
|
<sandbox hide-help>
|
||||||
<v-select placeholder="default, RTL" :options="options" dir="rtl"></v-select>
|
<template slot-scope="config">
|
||||||
<v-select placeholder="default, options=[1,5,10]" :options="[1,5,10]"></v-select>
|
|
||||||
<v-select placeholder="multiple" multiple :options="options"></v-select>
|
<v-select v-bind="config" />
|
||||||
<v-select placeholder="multiple, taggable" multiple taggable :options="options" no-drop></v-select>
|
|
||||||
<v-select placeholder="multiple, taggable, push-tags" multiple push-tags taggable :options="[{label: 'Foo', value: 'foo'}]"></v-select>
|
|
||||||
<v-select placeholder="multiple, closeOnSelect=true" multiple :options="['cat', 'dog', 'bear']"></v-select>
|
|
||||||
<v-select placeholder="multiple, closeOnSelect=false" multiple :close-on-select="false" :options="['cat', 'dog', 'bear']"></v-select>
|
|
||||||
<v-select placeholder="searchable=false" :options="options" :searchable="false"></v-select>
|
|
||||||
<v-select placeholder="search github.." label="full_name" @search="search" :options="ajaxRes"></v-select>
|
|
||||||
<v-select placeholder="custom option template" :options="options" multiple>
|
|
||||||
<template slot="selected-option" slot-scope="option">
|
|
||||||
{{option.label}}
|
|
||||||
</template>
|
</template>
|
||||||
<template slot="option" slot-scope="option">
|
</sandbox>
|
||||||
{{option.label}} ({{option.value}})
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<v-select placeholder="custom option template for string array" taggable :options="['cat', 'dog', 'bear']" multiple>
|
|
||||||
<template slot="selected-option" slot-scope="option">
|
|
||||||
{{option.label}}
|
|
||||||
</template>
|
|
||||||
<template slot="option" slot-scope="option">
|
|
||||||
{{option.label}}
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<v-select multiple placeholder="custom label template" :options="options">
|
|
||||||
<span
|
|
||||||
slot="selected-option-container"
|
|
||||||
slot-scope="props"
|
|
||||||
class="selected-tag"
|
|
||||||
>
|
|
||||||
{{ props.option.label }} ({{ props.option.value }})
|
|
||||||
<button v-if="props.multiple" @click="props.deselect(props.option)" type="button" class="close" aria-label="Remove option">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</v-select>
|
|
||||||
<v-select placeholder="select on tab" :select-on-tab="true" :options="options"></v-select>
|
|
||||||
<v-select placeholder="disabled" disabled value="disabled"></v-select>
|
|
||||||
<v-select placeholder="disabled multiple" disabled multiple :value="['disabled', 'multiple']"></v-select>
|
|
||||||
<v-select placeholder="filterable=false, @search=searchPeople" label="first_name" :filterable="false" @search="searchPeople" :options="people"></v-select>
|
|
||||||
<v-select placeholder="filtering with fuse.js" label="title" :options="fuseSearchOptions" :filter="fuseSearch">
|
|
||||||
<template slot="option" slot-scope="option">
|
|
||||||
<strong>{{ option.title }}</strong><br>
|
|
||||||
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Fuse from "fuse.js";
|
import vSelect from '../src/components/Select';
|
||||||
import debounce from "lodash/debounce";
|
import Sandbox from '../docs/.vuepress/components/Sandbox';
|
||||||
import vSelect from "../src/components/Select.vue";
|
// import countries from '../docs/.vuepress/data/countryCodes';
|
||||||
import countries from "./data/countryCodes";
|
// import books from '../docs/.vuepress/data/books';
|
||||||
import fuseSearchOptions from "./data/books";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { vSelect },
|
components: {Sandbox, vSelect},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
placeholder: "placeholder",
|
|
||||||
value: null,
|
|
||||||
options: countries,
|
|
||||||
ajaxRes: [],
|
|
||||||
people: [],
|
|
||||||
fuseSearchOptions
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
search(search, loading) {
|
|
||||||
loading(true);
|
|
||||||
this.getRepositories(search, loading, this);
|
|
||||||
},
|
|
||||||
searchPeople(search, loading) {
|
|
||||||
loading(true);
|
|
||||||
this.getPeople(loading, this);
|
|
||||||
},
|
|
||||||
getPeople: debounce((loading, vm) => {
|
|
||||||
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then(res => {
|
|
||||||
vm.people = res.data.data;
|
|
||||||
loading(false);
|
|
||||||
});
|
|
||||||
}, 250),
|
|
||||||
getRepositories: debounce((search, loading, vm) => {
|
|
||||||
vm.$http
|
|
||||||
.get(`https://api.github.com/search/repositories?q=${search}`)
|
|
||||||
.then(res => {
|
|
||||||
vm.ajaxRes = res.data.items;
|
|
||||||
loading(false);
|
|
||||||
});
|
|
||||||
}, 250),
|
|
||||||
fuseSearch(options, search) {
|
|
||||||
return new Fuse(options, {
|
|
||||||
keys: ["title", "author.firstName", "author.lastName"]
|
|
||||||
}).search(search);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
/*@import "https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css";*/
|
html,
|
||||||
/*@import "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.2/css/bulma.min.css";*/
|
body {
|
||||||
/*@import "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css";*/
|
margin: 0;
|
||||||
/*@import "https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css";*/
|
height: 100%;
|
||||||
|
font-family: -apple-system, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
body,
|
#app {
|
||||||
html {
|
height: 100%;
|
||||||
font-family: -apple-system, sans-serif;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#app {
|
|
||||||
height: 95vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-select {
|
|
||||||
width: 25em;
|
|
||||||
margin: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
+7
-80
@@ -1,87 +1,14 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Vue Select Dev</title>
|
<title>Vue Select Dev</title>
|
||||||
<!--<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet">-->
|
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.5.3/css/foundation.min.css">-->
|
||||||
<!--<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.2/css/bulma.min.css" rel="stylesheet">-->
|
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">-->
|
||||||
<!--<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">-->
|
<!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css">-->
|
||||||
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css">-->
|
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0/css/bootstrap.min.css">-->
|
||||||
<style>
|
|
||||||
|
|
||||||
#app {
|
|
||||||
height: 95vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-content: center;
|
|
||||||
font-family: -apple-system, sans-serif;
|
|
||||||
}
|
|
||||||
|
|
||||||
.v-select {
|
|
||||||
width: 25em;
|
|
||||||
margin: 1em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div id="app">
|
<div id="app"></div>
|
||||||
<v-select placeholder="default" :options="options"></v-select>
|
|
||||||
<v-select placeholder="default, RTL" :options="options" dir="rtl"></v-select>
|
|
||||||
<v-select placeholder="default, options=[1,5,10]" :options="[1,5,10]"></v-select>
|
|
||||||
<v-select placeholder="multiple" multiple :options="options"></v-select>
|
|
||||||
<v-select placeholder="multiple, taggable" multiple taggable :options="options" no-drop></v-select>
|
|
||||||
<v-select placeholder="multiple, taggable, push-tags" multiple push-tags taggable :options="[{label: 'Foo', value: 'foo'}]"></v-select>
|
|
||||||
<v-select placeholder="multiple, closeOnSelect=true" multiple :options="['cat', 'dog', 'bear']"></v-select>
|
|
||||||
<v-select placeholder="multiple, closeOnSelect=false" multiple :close-on-select="false" :options="['cat', 'dog', 'bear']"></v-select>
|
|
||||||
<v-select placeholder="searchable=false" :options="options" :searchable="false"></v-select>
|
|
||||||
<v-select placeholder="search github.." label="full_name" @search="search" :options="ajaxRes"></v-select>
|
|
||||||
<v-select placeholder="custom option template" :options="options" multiple>
|
|
||||||
<template slot="selected-option" slot-scope="option">
|
|
||||||
{{option.label}}
|
|
||||||
</template>
|
|
||||||
<template slot="option" slot-scope="option">
|
|
||||||
{{option.label}} ({{option.value}})
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<v-select placeholder="custom option template for string array" taggable :options="['cat', 'dog', 'bear']" multiple>
|
|
||||||
<template slot="selected-option" slot-scope="option">
|
|
||||||
{{option.label}}
|
|
||||||
</template>
|
|
||||||
<template slot="option" slot-scope="option">
|
|
||||||
{{option.label}}
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<v-select multiple placeholder="custom label template" :options="options">
|
|
||||||
<span
|
|
||||||
slot="selected-option-container"
|
|
||||||
slot-scope="props"
|
|
||||||
class="selected-tag"
|
|
||||||
>
|
|
||||||
{{ props.option.label }} ({{ props.option.value }})
|
|
||||||
<button v-if="props.multiple" @click="props.deselect(props.option)" type="button" class="close" aria-label="Remove option">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</v-select>
|
|
||||||
<v-select placeholder="select on tab" :select-on-tab="true" :options="options"></v-select>
|
|
||||||
<v-select placeholder="disabled" disabled value="disabled"></v-select>
|
|
||||||
<v-select placeholder="disabled multiple" disabled multiple :value="['disabled', 'multiple']"></v-select>
|
|
||||||
<v-select placeholder="filterable=false, @search=searchPeople" label="first_name" :filterable="false" @search="searchPeople" :options="people"></v-select>
|
|
||||||
<v-select placeholder="filtering with fuse.js" label="title" :options="fuseSearchOptions" :filter="fuseSearch">
|
|
||||||
<template slot="option" scope="option">
|
|
||||||
<strong>{{ option.title }}</strong><br>
|
|
||||||
<em>{{ option.author.firstName + ' ' + option.author.lastName }}</em>
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
<v-select placeholder="Vue select with no options and a custom no-option span" >
|
|
||||||
<span slot="no-options">Custom no options message</span>
|
|
||||||
</v-select>
|
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div id="home">
|
|
||||||
<div class="container">
|
|
||||||
<h1>Vue Select</h1>
|
|
||||||
|
|
||||||
<p class="accolades lead">
|
|
||||||
<a href="https://github.com/sagalbot/vue-select">
|
|
||||||
<img src="https://img.shields.io/github/stars/sagalbot/vue-select.svg?label=Stars&style=flat-square"
|
|
||||||
alt="GitHub Stars">
|
|
||||||
</a>
|
|
||||||
<a href="https://www.npmjs.com/package/vue-select">
|
|
||||||
<img src="https://img.shields.io/npm/dm/vue-select.svg?style=flat-square" alt="Downloads per Month">
|
|
||||||
</a>
|
|
||||||
<a href="https://codeclimate.com/github/sagalbot/vue-select/maintainability">
|
|
||||||
<img src="https://img.shields.io/codeclimate/maintainability/sagalbot/vue-select.svg?style=flat-square"
|
|
||||||
alt="Maintainability"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<img src="https://img.shields.io/github/license/sagalbot/vue-select.svg?style=flat-square" alt="MIT License">
|
|
||||||
<img src="https://img.shields.io/github/release/sagalbot/vue-select.svg?style=flat-square"
|
|
||||||
alt="Current Release">
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p class="lead">
|
|
||||||
A Vue.js select component that provides similar functionality
|
|
||||||
to Select2/Chosen without the overhead of jQuery.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<ClientOnly>
|
|
||||||
<v-select id="v-select" :options="options" @input="redirect" label="title">
|
|
||||||
<template slot="option" slot-scope="option">
|
|
||||||
<span class="octicon" :class="option.icon"></span>
|
|
||||||
{{ option.title }}
|
|
||||||
</template>
|
|
||||||
</v-select>
|
|
||||||
</ClientOnly>
|
|
||||||
|
|
||||||
<section class="content">
|
|
||||||
<div class="feature-list">
|
|
||||||
<ul class="list-vue">
|
|
||||||
<li>Supports Vuex</li>
|
|
||||||
<li>Tagging Support</li>
|
|
||||||
<li>Custom Templating</li>
|
|
||||||
<li>Zero JS/CSS dependencies</li>
|
|
||||||
<li>Custom Filtering Algorithms</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul class="list-vue">
|
|
||||||
<li>+95% Test Coverage</li>
|
|
||||||
<li>Select Single/Multiple</li>
|
|
||||||
<li>Typeahead Suggestions</li>
|
|
||||||
<li>Supports RTL & Translations</li>
|
|
||||||
<li>Plays nice with CSS Frameworks</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>
|
|
||||||
And so much more! Get started with: <br>
|
|
||||||
<code>yarn add vue-select</code>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div class="cta">
|
|
||||||
<a class="btn btn-primary btn-outline btn-lg" href="https://github.com/sagalbot/vue-select">
|
|
||||||
<span class="octicon octicon-mark-github"></span> View on GitHub
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<router-link class="btn btn-primary btn-outline btn-lg" to="/docs/">
|
|
||||||
<span class="octicon octicon-book"></span> Read the Docs
|
|
||||||
</router-link>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import "../scss/home";
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
data () {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
selected: null,
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
title: 'Read the Docs',
|
|
||||||
icon: 'octicon-book',
|
|
||||||
url: 'docs/',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'View on GitHub',
|
|
||||||
icon: 'octicon-mark-github',
|
|
||||||
url: 'https://github.com/sagalbot/vue-select',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'View on NPM',
|
|
||||||
icon: 'octicon-database',
|
|
||||||
url: 'https://www.npmjs.com/package/vue-select',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'View Code Climate Analysis',
|
|
||||||
icon: 'octicon-graph',
|
|
||||||
url: 'https://codeclimate.com/github/sagalbot/vue-select',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'View Codepen Examples',
|
|
||||||
icon: 'octicon-pencil',
|
|
||||||
url: 'https://codepen.io/collection/nrkgxV/',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
redirect (option) {
|
|
||||||
// if (window) {
|
|
||||||
// window.location = option.url;
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
<template>
|
||||||
|
<div id="sandbox-wrap">
|
||||||
|
<div id="config">
|
||||||
|
|
||||||
|
<div class="list-item" v-if="!hideHelp">
|
||||||
|
<p>Use the controls below to adjust the props used
|
||||||
|
by the vue-select components.</p>
|
||||||
|
<p>The API provides
|
||||||
|
more props than are shown here, these are some
|
||||||
|
commonly adjusted settings.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="list-item">Basic Features</h5>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="multiple">
|
||||||
|
<input id="multiple" type="checkbox" v-model="configuration.multiple">
|
||||||
|
<code>:multiple="{{ configuration.multiple ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="disabled">
|
||||||
|
<input id="disabled" type="checkbox" v-model="configuration.disabled">
|
||||||
|
<code>:disabled="{{ configuration.disabled ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="clearable">
|
||||||
|
<input id="clearable" type="checkbox" v-model="configuration.clearable">
|
||||||
|
<code>:clearable="{{ configuration.clearable ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="searchable">
|
||||||
|
<input id="searchable" type="checkbox" v-model="configuration.searchable">
|
||||||
|
<code>:searchable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="filterable">
|
||||||
|
<input id="filterable" type="checkbox" v-model="configuration.filterable">
|
||||||
|
<code>:filterable="{{ configuration.searchable ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="list-item">Tagging</h5>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="taggable">
|
||||||
|
<input id="taggable" type="checkbox" v-model="configuration.taggable">
|
||||||
|
<code>:taggable="{{ configuration.taggable ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="noDrop">
|
||||||
|
<input id="noDrop" type="checkbox" v-model="configuration.noDrop">
|
||||||
|
<code>:no-drop="{{ configuration.noDrop ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="pushTags">
|
||||||
|
<input id="pushTags" type="checkbox" v-model="configuration.pushTags">
|
||||||
|
<code>:push-tags="{{ configuration.pushTags ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="list-item">UX</h5>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="selectOnTab">
|
||||||
|
<input id="selectOnTab" type="checkbox" v-model="configuration.selectOnTab">
|
||||||
|
<code>:select-on-tab="{{ configuration.selectOnTab ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="closeOnSelect">
|
||||||
|
<input id="closeOnSelect" type="checkbox" v-model="configuration.closeOnSelect">
|
||||||
|
<code>:close-on-select="{{ configuration.closeOnSelect ? 'true' : 'false' }}"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h5 class="list-item">Localization / i18n</h5>
|
||||||
|
|
||||||
|
<div class="list-item">
|
||||||
|
<label for="rtl">
|
||||||
|
<input id="rtl" type="radio" v-model="configuration.dir" value="rtl">
|
||||||
|
<code>dir="rtl"</code>
|
||||||
|
</label>
|
||||||
|
<label for="ltr">
|
||||||
|
<input id="ltr" type="radio" v-model="configuration.dir" value="ltr">
|
||||||
|
<code>dir="ltr"</code>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="sandbox">
|
||||||
|
<slot v-bind="configuration">
|
||||||
|
<div class="example">
|
||||||
|
<v-select v-bind="configuration" placeholder="country objects"></v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<v-select v-bind="configuration" placeholder="country objects, using option scoped slots">
|
||||||
|
<template slot="selected-option" slot-scope="{ label, value }">
|
||||||
|
{{ label }} -- {{ value }}
|
||||||
|
</template>
|
||||||
|
<template slot="option" slot-scope="{ label, value }">
|
||||||
|
{{ label }} ({{ value }})
|
||||||
|
</template>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<v-select v-bind="configuration" :options="['cat', 'dog', 'bear']" placeholder="string options, option slots">
|
||||||
|
<template slot="selected-option" slot-scope="{ label }">
|
||||||
|
{{ label }}
|
||||||
|
</template>
|
||||||
|
<template slot="option" slot-scope="{ label }">
|
||||||
|
{{ label }}
|
||||||
|
</template>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<v-select v-bind="configuration" :options="[1,5,10]" placeholder="options=[1,5,10]"></v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<v-select v-bind="configuration" label="title" :options="optionDataSets.books" :filter="fuseSearch"
|
||||||
|
placeholder="advanced filtering w/ fuse.js + scoped slots">
|
||||||
|
<template slot="option" slot-scope="option">
|
||||||
|
<strong>{{ option.title }}</strong><br>
|
||||||
|
<em>{{ `${option.author.firstName} ${option.author.lastName}` }}</em>
|
||||||
|
</template>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<v-select
|
||||||
|
v-bind="configuration"
|
||||||
|
placeholder="search github repositories.."
|
||||||
|
label="full_name"
|
||||||
|
@search="search"
|
||||||
|
:options="ajaxRes"
|
||||||
|
>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="example">
|
||||||
|
<v-select v-bind="configuration" :options="[]" placeholder="options=[]"></v-select>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Fuse from 'fuse.js';
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
import vSelect from '../../../src/components/Select.vue';
|
||||||
|
import countries from '../data/countryCodes';
|
||||||
|
import books from '../data/books';
|
||||||
|
|
||||||
|
const defaultConfig = () => ({
|
||||||
|
options: countries,
|
||||||
|
multiple: false,
|
||||||
|
dir: 'ltr',
|
||||||
|
clearable: true,
|
||||||
|
searchable: true,
|
||||||
|
filterable: true,
|
||||||
|
noDrop: false,
|
||||||
|
closeOnSelect: true,
|
||||||
|
disabled: false,
|
||||||
|
selectOntab: false,
|
||||||
|
placeholder: 'placeholder',
|
||||||
|
});
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
hideHelp: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {vSelect},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
configuration: defaultConfig(),
|
||||||
|
value: null,
|
||||||
|
ajaxRes: [],
|
||||||
|
people: [],
|
||||||
|
optionDataSet: 'countries',
|
||||||
|
optionDataSets: {
|
||||||
|
countries,
|
||||||
|
books,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
search (search, loading) {
|
||||||
|
loading(true);
|
||||||
|
this.getRepositories(search, loading, this);
|
||||||
|
},
|
||||||
|
searchPeople (search, loading) {
|
||||||
|
loading(true);
|
||||||
|
this.getPeople(loading, this);
|
||||||
|
},
|
||||||
|
getPeople: debounce((loading, vm) => {
|
||||||
|
vm.$http.get(`https://reqres.in/api/users?per_page=10`).then(res => {
|
||||||
|
vm.people = res.data.data;
|
||||||
|
loading(false);
|
||||||
|
});
|
||||||
|
}, 250),
|
||||||
|
getRepositories: debounce((search, loading, vm) => {
|
||||||
|
vm.$http
|
||||||
|
.get(`https://api.github.com/search/repositories?q=${search}`)
|
||||||
|
.then(res => {
|
||||||
|
vm.ajaxRes = res.data.items;
|
||||||
|
loading(false);
|
||||||
|
});
|
||||||
|
}, 250),
|
||||||
|
fuseSearch (options, search) {
|
||||||
|
return new Fuse(options, {
|
||||||
|
keys: ['title', 'author.firstName', 'author.lastName'],
|
||||||
|
}).search(search);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#sandbox-wrap {
|
||||||
|
min-height: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 75%;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-template-areas:
|
||||||
|
"sidebar component"
|
||||||
|
}
|
||||||
|
|
||||||
|
#config {
|
||||||
|
grid-area: sidebar;
|
||||||
|
border-right: 1px solid #eaecef;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sandbox {
|
||||||
|
grid-area: component;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
padding: 1rem 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item:not(:first-child) {
|
||||||
|
border-top: 1px solid #eaecef;
|
||||||
|
}
|
||||||
|
|
||||||
|
.example {
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select {
|
||||||
|
width: 25em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+52
-35
@@ -1,34 +1,44 @@
|
|||||||
|
const isDeployPreview = process.env.hasOwnProperty('DEPLOY_PREVIEW');
|
||||||
|
|
||||||
const meta = {
|
const meta = {
|
||||||
title: 'Vue Select | VueJS Select2/Chosen Component',
|
title: 'Vue Select | VueJS Select2/Chosen Component',
|
||||||
description: 'A well-tested, native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.',
|
description: 'Everything you wish the native <select> element could do, wrapped up into a zero dependency, highly extensible Vue component.',
|
||||||
icon: 'static/vue-logo.png',
|
url: 'http://sagalbot.github.io/vue-select/',
|
||||||
|
icon: '/vue-logo.png',
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
let head = [
|
||||||
title: 'Vue Select',
|
[
|
||||||
description: meta.description,
|
'link',
|
||||||
head: [
|
{
|
||||||
[
|
href: '//fonts.googleapis.com/css?family=Source+Sans+Pro:400,600|Roboto Mono',
|
||||||
'link',
|
rel: 'stylesheet',
|
||||||
{
|
type: 'text/css',
|
||||||
href: '//fonts.googleapis.com/css?family=Source+Sans+Pro:400,600|Roboto Mono',
|
}],
|
||||||
rel: 'stylesheet',
|
[
|
||||||
type: 'text/css',
|
'link',
|
||||||
}],
|
{
|
||||||
[
|
href: '//fonts.googleapis.com/css?family=Dosis:300&text=Vue Select',
|
||||||
'link',
|
rel: 'stylesheet',
|
||||||
{
|
type: 'text/css',
|
||||||
href: '//fonts.googleapis.com/css?family=Dosis:300&text=Vue Select',
|
}],
|
||||||
rel: 'stylesheet',
|
['link', { rel: 'icon', href: `/vue-logo.png` }],
|
||||||
type: 'text/css',
|
['meta', { name: 'theme-color', content: '#3eaf7c' }],
|
||||||
}],
|
['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` }],
|
||||||
{
|
['link', { rel: 'mask-icon', href: '/icons/safari-pinned-tab.svg', color: '#3eaf7c' }],
|
||||||
href: 'https://cdnjs.cloudflare.com/ajax/libs/octicons/4.4.0/font/octicons.min.css',
|
['meta', { name: 'msapplication-TileImage', content: '/icons/msapplication-icon-144x144.png' }],
|
||||||
rel: 'stylesheet',
|
['meta', { name: 'msapplication-TileColor', content: '#000000' }]
|
||||||
type: 'text/css',
|
];
|
||||||
}],
|
|
||||||
|
if (isDeployPreview) {
|
||||||
|
head.push(
|
||||||
|
['meta', {name: 'robots', content: 'noindex'}],
|
||||||
|
['meta', {name: 'googlebot', content: 'noindex'}],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
head.push(
|
||||||
['meta', {name: 'title', content: meta.title}],
|
['meta', {name: 'title', content: meta.title}],
|
||||||
['meta', {name: 'description', content: meta.description}],
|
['meta', {name: 'description', content: meta.description}],
|
||||||
['link', {rel: 'icon', href: meta.icon, type: 'image/png'}],
|
['link', {rel: 'icon', href: meta.icon, type: 'image/png'}],
|
||||||
@@ -40,16 +50,24 @@ module.exports = {
|
|||||||
['meta', {property: 'twitter:title', content: meta.title}],
|
['meta', {property: 'twitter:title', content: meta.title}],
|
||||||
['meta', {property: 'og:title', content: meta.title}],
|
['meta', {property: 'og:title', content: meta.title}],
|
||||||
['meta', {property: 'og:site_name', content: meta.title}],
|
['meta', {property: 'og:site_name', content: meta.title}],
|
||||||
[
|
['meta', {property: 'og:url', content: meta.url}],
|
||||||
'meta',
|
);
|
||||||
{property: 'og:url', content: 'http://sagalbot.github.io/vue-select/'}],
|
}
|
||||||
],
|
|
||||||
serviceWorker: true,
|
module.exports = {
|
||||||
ga: 'UA-12818324-8',
|
title: 'Vue Select',
|
||||||
|
description: meta.description,
|
||||||
|
head,
|
||||||
|
serviceWorker: !isDeployPreview,
|
||||||
|
ga: isDeployPreview ? '' : 'UA-12818324-8',
|
||||||
themeConfig: {
|
themeConfig: {
|
||||||
repo: 'sagalbot/vue-select',
|
repo: 'sagalbot/vue-select',
|
||||||
editLinks: true,
|
editLinks: true,
|
||||||
docsDir: 'docs',
|
docsDir: 'docs',
|
||||||
|
nav: [
|
||||||
|
{text: 'Home', link: '/'},
|
||||||
|
{text: 'Sandbox', link: '/sandbox'},
|
||||||
|
],
|
||||||
sidebar: {
|
sidebar: {
|
||||||
'/': [
|
'/': [
|
||||||
{
|
{
|
||||||
@@ -78,11 +96,10 @@ module.exports = {
|
|||||||
children: [
|
children: [
|
||||||
['api/props', 'Props'],
|
['api/props', 'Props'],
|
||||||
['api/slots', 'Slots'],
|
['api/slots', 'Slots'],
|
||||||
['api/events', 'Events']
|
['api/events', 'Events'],
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
@import 'variables';
|
|
||||||
|
|
||||||
#v-select {
|
|
||||||
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
|
||||||
max-width: 500px;
|
|
||||||
margin: 0 auto;
|
|
||||||
text-align: left;
|
|
||||||
|
|
||||||
.dropdown-toggle {
|
|
||||||
background: #fff;
|
|
||||||
border-color: rgba(82, 166, 183, 0.39);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.dropdown.open .dropdown-toggle,
|
|
||||||
&.dropdown.open .dropdown-menu,
|
|
||||||
&.dropdown.open .open-indicator:before {
|
|
||||||
border-color: #4CC3D9;
|
|
||||||
}
|
|
||||||
.active a {
|
|
||||||
background: rgba(50, 50, 50, .1);
|
|
||||||
color: #333;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.dropdown li {
|
|
||||||
border-bottom: 1px solid rgba($code-grey, .1);
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.dropdown li a {
|
|
||||||
padding: 10px 20px;
|
|
||||||
display: inline-flex;
|
|
||||||
width: 100%;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 1.5em;
|
|
||||||
.octicon {
|
|
||||||
font-size: 1.5em;
|
|
||||||
width: 1.5em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.dropdown .highlight a,
|
|
||||||
&.dropdown li:hover a {
|
|
||||||
background: #4CC3D9;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,17 +0,0 @@
|
|||||||
$orange: #e96900;
|
|
||||||
$yellow: #FFC65D;
|
|
||||||
$green: #42b983;
|
|
||||||
$blue: #4CC3D9;
|
|
||||||
$purple: #93648D;
|
|
||||||
$black: #34495e;
|
|
||||||
$red: #ff6666;
|
|
||||||
|
|
||||||
$gradient: linear-gradient(45deg, rgba(76,195,217,0) 0%,rgba(152,227,234,1) 100%);
|
|
||||||
|
|
||||||
// Code
|
|
||||||
$code-blue: #66d9ef;
|
|
||||||
$code-purple: #ae81ff;
|
|
||||||
$code-black: #272822;
|
|
||||||
$code-white: #f8f8f8;
|
|
||||||
$code-grey: #708090;
|
|
||||||
$code-green: #a6e22e;
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
@import '~normalize.css';
|
|
||||||
@import 'demo';
|
|
||||||
@import 'cyan_theme';
|
|
||||||
+12
-7
@@ -1,10 +1,11 @@
|
|||||||
# Vue Select
|
# Vue Select
|
||||||
|
|
||||||

|

|
||||||
|

|
||||||

|

|
||||||
|

|
||||||

|

|
||||||

|

|
||||||

|
|
||||||
|
|
||||||
> Everything you wish the native `<select>` element could do, wrapped
|
> Everything you wish the native `<select>` element could do, wrapped
|
||||||
up into a zero dependency, highly extensible Vue component.
|
up into a zero dependency, highly extensible Vue component.
|
||||||
@@ -14,17 +15,21 @@ template that fits the 80% use case for a select dropdown. Here it is by default
|
|||||||
|
|
||||||
<div style="max-width:50%; margin: 0 auto; padding: 1rem 0;">
|
<div style="max-width:50%; margin: 0 auto; padding: 1rem 0;">
|
||||||
<v-select :options="['Option One','Option Two','Option Three']" />
|
<v-select :options="['Option One','Option Two','Option Three']" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
If you want to get a quick sense of what vue-select can do, check out
|
||||||
|
[the sandbox](sandbox.md).
|
||||||
|
|
||||||
#### Features
|
#### Features
|
||||||
- AJAX Support
|
|
||||||
- Tagging
|
- Tagging
|
||||||
- List Filtering/Searching
|
- Filtering/Searching
|
||||||
- Supports Vuex
|
- Vuex Support
|
||||||
|
- AJAX Support
|
||||||
|
- SSR Support
|
||||||
- Select Single/Multiple Options
|
- Select Single/Multiple Options
|
||||||
- Tested with Bootstrap 3/4, Bulma, Foundation
|
- Tested with Bootstrap 3/4, Bulma, Foundation
|
||||||
- +95% Test Coverage
|
- +95% Test Coverage
|
||||||
- ~33kb minified with CSS
|
- ~20kb Total / ~5kb CSS / ~15kb JS
|
||||||
- Zero dependencies
|
- Zero dependencies
|
||||||
|
|
||||||
#### Resources
|
#### Resources
|
||||||
|
|||||||
@@ -50,6 +50,11 @@ clearable: {
|
|||||||
|
|
||||||
## maxHeight
|
## maxHeight
|
||||||
|
|
||||||
|
::: warning Deprecated in `v2.x` & Removed in `v3.0`
|
||||||
|
This prop was removed in `v3.0`. You can use the `$vs-dropdown-max-height`
|
||||||
|
SCSS variable to adjust this setting in `v3.x`.
|
||||||
|
:::
|
||||||
|
|
||||||
Sets the max-height property on the dropdown list.
|
Sets the max-height property on the dropdown list.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ The most common use case for `vue-select` is to have the chosen value synced wit
|
|||||||
<v-select v-model="selected"></v-select>
|
<v-select v-model="selected"></v-select>
|
||||||
```
|
```
|
||||||
|
|
||||||
<CodePen url="Kqxbjw" height="25"/>
|
<CodePen url="Kqxbjw" height="250"/>
|
||||||
|
|
||||||
If you don't require the `value` to be synced, you can also pass the prop directly:
|
If you don't require the `value` to be synced, you can also pass the prop directly:
|
||||||
|
|
||||||
@@ -31,14 +31,10 @@ By default, `vue-select` supports choosing a single value. If you need multiple
|
|||||||
To allow input that's not present within the options, set the `taggable` prop to true.
|
To allow input that's not present within the options, set the `taggable` prop to true.
|
||||||
If you want new tags to be pushed to the options list, set `push-tags` to true.
|
If you want new tags to be pushed to the options list, set `push-tags` to true.
|
||||||
|
|
||||||
```html
|
<CodePen url="XVoWxm" height="350"/>
|
||||||
<v-select taggable></v-select>
|
|
||||||
```
|
|
||||||
|
|
||||||
## Return a Single Key from an Object
|
## Return a Single Key from an Object
|
||||||
|
|
||||||
<CodePen url="XVoWxm" height="350"/>
|
|
||||||
|
|
||||||
When the `options` array contains objects, `vue-select` returns the whole object as dropdown value upon selection. You can specify your own `index` prop to return only the value contained in the specific property.
|
When the `options` array contains objects, `vue-select` returns the whole object as dropdown value upon selection. You can specify your own `index` prop to return only the value contained in the specific property.
|
||||||
|
|
||||||
For example, consider an object with `value` and `label` properties:
|
For example, consider an object with `value` and `label` properties:
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
sidebar: false
|
||||||
|
editLink: false
|
||||||
|
layout: Sandbox
|
||||||
|
---
|
||||||
|
|
||||||
+8
-1
@@ -2,7 +2,14 @@
|
|||||||
#
|
#
|
||||||
# “publish” is the directory to publish (relative to root of your repo),
|
# “publish” is the directory to publish (relative to root of your repo),
|
||||||
# “command” is your build command,
|
# “command” is your build command,
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
publish = "docs/.vuepress/dist"
|
publish = "docs/.vuepress/dist"
|
||||||
command = "yarn build:docs"
|
command = "yarn build:docs"
|
||||||
|
|
||||||
|
# Deploy Preview context
|
||||||
|
#
|
||||||
|
# All deploys resulting from a pull/merge request will
|
||||||
|
# inherit these settings.
|
||||||
|
[context.deploy-preview]
|
||||||
|
publish = "docs/.vuepress/dist"
|
||||||
|
command = "yarn add --dev webpack@~4.28 && yarn && yarn build:preview"
|
||||||
|
|||||||
+9
-10
@@ -8,10 +8,11 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm run dev",
|
"start": "npm run dev",
|
||||||
"dev": "webpack-dev-server --config build/webpack.dev.conf.js --hot --progress -d",
|
"serve": "webpack-dev-server --config build/webpack.dev.conf.js --hot --progress -d",
|
||||||
"dev:docs": "vuepress dev docs",
|
"serve:docs": "vuepress dev docs",
|
||||||
"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js --progress",
|
"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js --progress",
|
||||||
"build:docs": "vuepress build docs",
|
"build:docs": "vuepress build docs",
|
||||||
|
"build:preview": "cross-env DEPLOY_PREVIEW=true vuepress build --debug docs",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -29,29 +30,27 @@
|
|||||||
"@babel/plugin-transform-runtime": "^7.2.0",
|
"@babel/plugin-transform-runtime": "^7.2.0",
|
||||||
"@babel/preset-env": "^7.3.1",
|
"@babel/preset-env": "^7.3.1",
|
||||||
"@babel/runtime": "^7.3.1",
|
"@babel/runtime": "^7.3.1",
|
||||||
"@vue/cli-service": "^3.4.0",
|
|
||||||
"@vue/test-utils": "^1.0.0-beta.29",
|
"@vue/test-utils": "^1.0.0-beta.29",
|
||||||
|
"autoprefixer": "^9.4.7",
|
||||||
"babel-core": "^7.0.0-bridge.0",
|
"babel-core": "^7.0.0-bridge.0",
|
||||||
"babel-loader": "^8.0.0",
|
"babel-loader": "^8.0.0",
|
||||||
"chokidar": "^2.0.4",
|
"chokidar": "^2.0.4",
|
||||||
"coveralls": "^3.0.2",
|
"coveralls": "^3.0.2",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^2.1.0",
|
||||||
"eventsource-polyfill": "^0.9.6",
|
"cssnano": "^4.1.10",
|
||||||
"extract-text-webpack-plugin": "^3.0.0",
|
|
||||||
"file-loader": "^3.0.0",
|
|
||||||
"function-bind": "^1.0.2",
|
|
||||||
"fuse.js": "^3.2.0",
|
"fuse.js": "^3.2.0",
|
||||||
"gh-pages": "^0.11.0",
|
"gh-pages": "^0.11.0",
|
||||||
"html-loader": "^0.5.0",
|
"html-loader": "^0.5.5",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^3.2.0",
|
||||||
"jest": "^24.1.0",
|
"jest": "^24.1.0",
|
||||||
"jest-serializer-vue": "^2.0.2",
|
"jest-serializer-vue": "^2.0.2",
|
||||||
"jest-transform-stub": "^2.0.0",
|
"jest-transform-stub": "^2.0.0",
|
||||||
"mini-css-extract-plugin": "^0.5.0",
|
"mini-css-extract-plugin": "^0.5.0",
|
||||||
"node-sass": "^4.10.0",
|
"node-sass": "^4.10.0",
|
||||||
|
"postcss-loader": "^3.0.0",
|
||||||
|
"postcss-scss": "^2.0.0",
|
||||||
"sass-loader": "^7.1.0",
|
"sass-loader": "^7.1.0",
|
||||||
"shelljs": "^0.7.0",
|
|
||||||
"url-loader": "^1.1.2",
|
"url-loader": "^1.1.2",
|
||||||
"vue": "^2.6.4",
|
"vue": "^2.6.4",
|
||||||
"vue-html-loader": "^1.2.4",
|
"vue-html-loader": "^1.2.4",
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: [
|
||||||
|
require('autoprefixer'),
|
||||||
|
require('cssnano')({
|
||||||
|
preset: 'default',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
};
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<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"/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<template>
|
||||||
|
<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"/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
+52
-351
@@ -1,363 +1,69 @@
|
|||||||
<style>
|
<style lang="scss">
|
||||||
.v-select {
|
@import '../scss/vue-select.scss';
|
||||||
position: relative;
|
|
||||||
font-family: inherit;
|
|
||||||
}
|
|
||||||
.v-select,
|
|
||||||
.v-select * {
|
|
||||||
-webkit-box-sizing: border-box;
|
|
||||||
-moz-box-sizing: border-box;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Rtl support - Because we're using a flexbox-based layout, the `dir="rtl"` HTML
|
|
||||||
attribute does most of the work for us by rearranging the child elements visually.
|
|
||||||
*/
|
|
||||||
.v-select[dir="rtl"] .vs__actions {
|
|
||||||
padding: 0 3px 0 6px;
|
|
||||||
}
|
|
||||||
.v-select[dir="rtl"] .dropdown-toggle .clear {
|
|
||||||
margin-left: 6px;
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
.v-select[dir="rtl"] .selected-tag .close {
|
|
||||||
margin-left: 0;
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
.v-select[dir="rtl"] .dropdown-menu {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open Indicator */
|
|
||||||
.v-select .open-indicator {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: all;
|
|
||||||
transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
|
||||||
transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
|
||||||
opacity: 1;
|
|
||||||
width: 12px; /* To account for extra width from rotating. */
|
|
||||||
}
|
|
||||||
.v-select .open-indicator:before {
|
|
||||||
border-color: rgba(60, 60, 60, .5);
|
|
||||||
border-style: solid;
|
|
||||||
border-width: 3px 3px 0 0;
|
|
||||||
content: '';
|
|
||||||
display: inline-block;
|
|
||||||
height: 10px;
|
|
||||||
width: 10px;
|
|
||||||
vertical-align: text-top;
|
|
||||||
transform: rotate(133deg);
|
|
||||||
transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
|
||||||
transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
|
||||||
box-sizing: inherit;
|
|
||||||
}
|
|
||||||
/* Open Indicator States */
|
|
||||||
.v-select.open .open-indicator:before {
|
|
||||||
transform: rotate(315deg);
|
|
||||||
}
|
|
||||||
.v-select.loading .open-indicator {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown Toggle */
|
|
||||||
.v-select .dropdown-toggle {
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
appearance: none;
|
|
||||||
display: flex;
|
|
||||||
padding: 0 0 4px 0;
|
|
||||||
background: none;
|
|
||||||
border: 1px solid rgba(60, 60, 60, .26);
|
|
||||||
border-radius: 4px;
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
.v-select .vs__selected-options {
|
|
||||||
display: flex;
|
|
||||||
flex-basis: 100%;
|
|
||||||
flex-grow: 1;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
padding: 0 2px;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.v-select .vs__actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: stretch;
|
|
||||||
padding: 0 6px 0 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Clear Button */
|
|
||||||
.v-select .dropdown-toggle .clear {
|
|
||||||
font-size: 23px;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 1;
|
|
||||||
color: rgba(60, 60, 60, 0.5);
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
background-color: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
margin-right: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Dropdown Toggle States */
|
|
||||||
.v-select.searchable .dropdown-toggle {
|
|
||||||
cursor: text;
|
|
||||||
}
|
|
||||||
.v-select.unsearchable .dropdown-toggle {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.v-select.open .dropdown-toggle {
|
|
||||||
border-bottom-color: transparent;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
/* Dropdown Menu */
|
|
||||||
.v-select .dropdown-menu {
|
|
||||||
display:block;
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1000;
|
|
||||||
min-width: 160px;
|
|
||||||
padding: 5px 0;
|
|
||||||
margin: 0;
|
|
||||||
width: 100%;
|
|
||||||
overflow-y: auto;
|
|
||||||
border: 1px solid rgba(0, 0, 0, .26);
|
|
||||||
box-shadow: 0px 3px 6px 0px rgba(0,0,0,.15);
|
|
||||||
border-top: none;
|
|
||||||
border-radius: 0 0 4px 4px;
|
|
||||||
text-align: left;
|
|
||||||
list-style: none;
|
|
||||||
background: #fff;
|
|
||||||
}
|
|
||||||
.v-select .no-options {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
/* Selected Tags */
|
|
||||||
.v-select .selected-tag {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1.42857143; /* Normalize line height */
|
|
||||||
margin: 4px 2px 0px 2px;
|
|
||||||
padding: 0 0.25em;
|
|
||||||
transition: opacity .25s;
|
|
||||||
}
|
|
||||||
.v-select.single .selected-tag {
|
|
||||||
background-color: transparent;
|
|
||||||
border-color: transparent;
|
|
||||||
}
|
|
||||||
.v-select.single.open .selected-tag {
|
|
||||||
position: absolute;
|
|
||||||
opacity: .4;
|
|
||||||
}
|
|
||||||
.v-select.single.searching .selected-tag {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.v-select .selected-tag .close {
|
|
||||||
margin-left: 2px;
|
|
||||||
font-size: 1.25em;
|
|
||||||
appearance: none;
|
|
||||||
padding: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
background: 0 0;
|
|
||||||
border: 0;
|
|
||||||
font-weight: 700;
|
|
||||||
line-height: 1;
|
|
||||||
color: #000;
|
|
||||||
text-shadow: 0 1px 0 #fff;
|
|
||||||
filter: alpha(opacity=20);
|
|
||||||
opacity: .2;
|
|
||||||
}
|
|
||||||
.v-select.single.searching:not(.open):not(.loading) input[type="search"] {
|
|
||||||
opacity: .2;
|
|
||||||
}
|
|
||||||
/* Search Input */
|
|
||||||
.v-select input[type="search"]::-webkit-search-decoration,
|
|
||||||
.v-select input[type="search"]::-webkit-search-cancel-button,
|
|
||||||
.v-select input[type="search"]::-webkit-search-results-button,
|
|
||||||
.v-select input[type="search"]::-webkit-search-results-decoration {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.v-select input[type="search"]::-ms-clear {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.v-select input[type="search"],
|
|
||||||
.v-select input[type="search"]:focus {
|
|
||||||
appearance: none;
|
|
||||||
-webkit-appearance: none;
|
|
||||||
-moz-appearance: none;
|
|
||||||
line-height: 1.42857143;
|
|
||||||
font-size: 1em;
|
|
||||||
display: inline-block;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
border-left: none;
|
|
||||||
outline: none;
|
|
||||||
margin: 4px 0 0 0;
|
|
||||||
padding: 0 7px;
|
|
||||||
max-width: 100%;
|
|
||||||
background: none;
|
|
||||||
box-shadow: none;
|
|
||||||
flex-grow: 1;
|
|
||||||
width: 0;
|
|
||||||
}
|
|
||||||
.v-select.unsearchable input[type="search"] {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
.v-select.unsearchable input[type="search"]:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* List Items */
|
|
||||||
.v-select li {
|
|
||||||
line-height: 1.42857143; /* Normalize line height */
|
|
||||||
}
|
|
||||||
.v-select li > a {
|
|
||||||
display: block;
|
|
||||||
padding: 3px 20px;
|
|
||||||
clear: both;
|
|
||||||
color: #333; /* Overrides most CSS frameworks */
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
.v-select li:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.v-select .dropdown-menu .active > a {
|
|
||||||
color: #333;
|
|
||||||
background: rgba(50, 50, 50, .1);
|
|
||||||
}
|
|
||||||
.v-select .dropdown-menu > .highlight > a {
|
|
||||||
/*
|
|
||||||
* required to override bootstrap 3's
|
|
||||||
* .dropdown-menu > li > a:hover {} styles
|
|
||||||
*/
|
|
||||||
background: #5897fb;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
.v-select .highlight:not(:last-child) {
|
|
||||||
margin-bottom: 0; /* Fixes Bulma Margin */
|
|
||||||
}
|
|
||||||
/* Loading Spinner */
|
|
||||||
.v-select .spinner {
|
|
||||||
align-self: center;
|
|
||||||
opacity: 0;
|
|
||||||
font-size: 5px;
|
|
||||||
text-indent: -9999em;
|
|
||||||
overflow: hidden;
|
|
||||||
border-top: .9em solid rgba(100, 100, 100, .1);
|
|
||||||
border-right: .9em solid rgba(100, 100, 100, .1);
|
|
||||||
border-bottom: .9em solid rgba(100, 100, 100, .1);
|
|
||||||
border-left: .9em solid rgba(60, 60, 60, .45);
|
|
||||||
transform: translateZ(0);
|
|
||||||
animation: vSelectSpinner 1.1s infinite linear;
|
|
||||||
transition: opacity .1s;
|
|
||||||
}
|
|
||||||
.v-select .spinner,
|
|
||||||
.v-select .spinner:after {
|
|
||||||
border-radius: 50%;
|
|
||||||
width: 5em;
|
|
||||||
height: 5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disabled state */
|
|
||||||
.v-select.disabled .dropdown-toggle,
|
|
||||||
.v-select.disabled .dropdown-toggle .clear,
|
|
||||||
.v-select.disabled .dropdown-toggle input,
|
|
||||||
.v-select.disabled .selected-tag .close,
|
|
||||||
.v-select.disabled .open-indicator {
|
|
||||||
cursor: not-allowed;
|
|
||||||
background-color: rgb(248, 248, 248);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loading Spinner States */
|
|
||||||
.v-select.loading .spinner {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
/* KeyFrames */
|
|
||||||
@-webkit-keyframes vSelectSpinner {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@keyframes vSelectSpinner {
|
|
||||||
0% {
|
|
||||||
transform: rotate(0deg);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Dropdown Default Transition */
|
|
||||||
.fade-enter-active,
|
|
||||||
.fade-leave-active {
|
|
||||||
transition: opacity .15s cubic-bezier(1.0, 0.5, 0.8, 1.0);
|
|
||||||
}
|
|
||||||
.fade-enter,
|
|
||||||
.fade-leave-to {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :dir="dir" class="dropdown v-select" :class="dropdownClasses">
|
<div :dir="dir" class="v-select" :class="stateClasses">
|
||||||
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="dropdown-toggle">
|
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="vs__dropdown-toggle">
|
||||||
|
|
||||||
<div class="vs__selected-options" ref="selectedOptions">
|
<div class="vs__selected-options" ref="selectedOptions">
|
||||||
<slot v-for="option in valueAsArray" name="selected-option-container"
|
<slot v-for="option in valueAsArray"
|
||||||
:option="(typeof option === 'object')?option:{[label]: option}" :deselect="deselect" :multiple="multiple" :disabled="disabled">
|
name="selected-option-container"
|
||||||
<span class="selected-tag" v-bind:key="option.index">
|
:option="(typeof option === 'object')?option:{[label]: option}"
|
||||||
|
:deselect="deselect"
|
||||||
|
:multiple="multiple"
|
||||||
|
:disabled="disabled">
|
||||||
|
<span class="vs__selected" v-bind:key="option.index">
|
||||||
<slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
<slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||||
{{ getOptionLabel(option) }}
|
{{ getOptionLabel(option) }}
|
||||||
</slot>
|
</slot>
|
||||||
<button v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="close" aria-label="Remove option">
|
<button v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="vs__deselect" aria-label="Deselect option">
|
||||||
<span aria-hidden="true">×</span>
|
<deselect />
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
<slot name="search" v-bind="scope.search">
|
<slot name="search" v-bind="scope.search">
|
||||||
<input v-bind="scope.search.attributes" v-on="scope.search.events">
|
<input class="vs__search" v-bind="scope.search.attributes" v-on="scope.search.events">
|
||||||
</slot>
|
</slot>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="vs__actions">
|
<div class="vs__actions">
|
||||||
<button
|
<button
|
||||||
v-show="showClearButton"
|
v-show="showClearButton"
|
||||||
:disabled="disabled"
|
:disabled="disabled"
|
||||||
@click="clearSelection"
|
@click="clearSelection"
|
||||||
type="button"
|
type="button"
|
||||||
class="clear"
|
class="vs__clear"
|
||||||
title="Clear selection"
|
title="Clear selection"
|
||||||
>
|
>
|
||||||
<span aria-hidden="true">×</span>
|
<deselect />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<i v-if="!noDrop" ref="openIndicator" role="presentation" class="open-indicator"></i>
|
<open-indicator v-if="!noDrop" ref="openIndicator" role="presentation" class="vs__open-indicator" />
|
||||||
|
|
||||||
<slot name="spinner">
|
<slot name="spinner" v-bind="scope.spinner">
|
||||||
<div class="spinner" v-show="mutableLoading">Loading...</div>
|
<div class="vs__spinner" v-show="mutableLoading">Loading...</div>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<transition :name="transition">
|
<transition :name="transition">
|
||||||
<ul ref="dropdownMenu" v-if="dropdownOpen" class="dropdown-menu" :style="{ 'max-height': maxHeight }" role="listbox" @mousedown="onMousedown">
|
<ul ref="dropdownMenu" v-if="dropdownOpen" class="vs__dropdown-menu" role="listbox" @mousedown="onMousedown">
|
||||||
<li role="option" v-for="(option, index) in filteredOptions" v-bind:key="index" :class="{ active: isOptionSelected(option), highlight: index === typeAheadPointer }" @mouseover="typeAheadPointer = index">
|
<li
|
||||||
<a @mousedown.prevent.stop="select(option)">
|
role="option"
|
||||||
|
v-for="(option, index) in filteredOptions"
|
||||||
|
:key="index"
|
||||||
|
class="vs__dropdown-option"
|
||||||
|
:class="{ active: isOptionSelected(option), 'vs__dropdown-option--highlight': index === typeAheadPointer }"
|
||||||
|
@mouseover="typeAheadPointer = index"
|
||||||
|
@mousedown.prevent.stop="select(option)"
|
||||||
|
>
|
||||||
<slot name="option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
<slot name="option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||||
{{ getOptionLabel(option) }}
|
{{ getOptionLabel(option) }}
|
||||||
</slot>
|
</slot>
|
||||||
</a>
|
|
||||||
</li>
|
</li>
|
||||||
<li v-if="!filteredOptions.length" class="no-options" @mousedown.stop="">
|
<li v-if="!filteredOptions.length" class="vs__no-options" @mousedown.stop="">
|
||||||
<slot name="no-options">Sorry, no matching options.</slot>
|
<slot name="no-options">Sorry, no matching options.</slot>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
@@ -369,8 +75,12 @@
|
|||||||
import pointerScroll from '../mixins/pointerScroll'
|
import pointerScroll from '../mixins/pointerScroll'
|
||||||
import typeAheadPointer from '../mixins/typeAheadPointer'
|
import typeAheadPointer from '../mixins/typeAheadPointer'
|
||||||
import ajax from '../mixins/ajax'
|
import ajax from '../mixins/ajax'
|
||||||
|
import Deselect from './Deselect'
|
||||||
|
import OpenIndicator from './OpenIndicator'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {Deselect, OpenIndicator},
|
||||||
|
|
||||||
mixins: [pointerScroll, typeAheadPointer, ajax],
|
mixins: [pointerScroll, typeAheadPointer, ajax],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
@@ -416,16 +126,6 @@
|
|||||||
default: true
|
default: true
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the max-height property on the dropdown list.
|
|
||||||
* @deprecated
|
|
||||||
* @type {String}
|
|
||||||
*/
|
|
||||||
maxHeight: {
|
|
||||||
type: String,
|
|
||||||
default: '400px'
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable/disable filtering the options.
|
* Enable/disable filtering the options.
|
||||||
* @type {Boolean}
|
* @type {Boolean}
|
||||||
@@ -454,13 +154,12 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets a Vue transition property on the `.dropdown-menu`. vue-select
|
* Sets a Vue transition property on the `.vs__dropdown-menu`.
|
||||||
* does not include CSS for transitions, you'll need to add them yourself.
|
|
||||||
* @type {String}
|
* @type {String}
|
||||||
*/
|
*/
|
||||||
transition: {
|
transition: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'fade'
|
default: 'vs__fade'
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -902,7 +601,7 @@
|
|||||||
*/
|
*/
|
||||||
toggleDropdown(e) {
|
toggleDropdown(e) {
|
||||||
if (e.target === this.$refs.openIndicator || e.target === this.searchEl || e.target === this.$refs.toggle ||
|
if (e.target === this.$refs.openIndicator || e.target === this.searchEl || e.target === this.$refs.toggle ||
|
||||||
e.target.classList.contains('selected-tag') || e.target === this.$el) {
|
e.target.classList.contains('vs__selected') || e.target === this.$el) {
|
||||||
if (this.open) {
|
if (this.open) {
|
||||||
this.searchEl.blur() // dropdown will close on blur
|
this.searchEl.blur() // dropdown will close on blur
|
||||||
} else {
|
} else {
|
||||||
@@ -1147,7 +846,7 @@
|
|||||||
'role': 'combobox',
|
'role': 'combobox',
|
||||||
'type': 'search',
|
'type': 'search',
|
||||||
'autocomplete': 'off',
|
'autocomplete': 'off',
|
||||||
'class': 'form-control',
|
'value': this.search,
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
'keydown': this.onSearchKeyDown,
|
'keydown': this.onSearchKeyDown,
|
||||||
@@ -1157,23 +856,25 @@
|
|||||||
'input': (e) => this.search = e.target.value,
|
'input': (e) => this.search = e.target.value,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
spinner: {
|
||||||
|
loading: this.mutableLoading
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classes to be output on .dropdown
|
* Holds the current state of the component.
|
||||||
* @return {Object}
|
* @return {Object}
|
||||||
*/
|
*/
|
||||||
dropdownClasses() {
|
stateClasses() {
|
||||||
return {
|
return {
|
||||||
open: this.dropdownOpen,
|
'vs--open': this.dropdownOpen,
|
||||||
single: !this.multiple,
|
'vs--single': !this.multiple,
|
||||||
searching: this.searching,
|
'vs--searching': this.searching,
|
||||||
searchable: this.searchable,
|
'vs--searchable': this.searchable,
|
||||||
unsearchable: !this.searchable,
|
'vs--unsearchable': !this.searchable,
|
||||||
loading: this.mutableLoading,
|
'vs--loading': this.mutableLoading,
|
||||||
rtl: this.dir === 'rtl', // This can be removed - styling is handled by `dir="rtl"` attribute
|
'vs--disabled': this.disabled
|
||||||
disabled: this.disabled
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1191,7 +892,7 @@
|
|||||||
* @return {Boolean} True if non empty value
|
* @return {Boolean} True if non empty value
|
||||||
*/
|
*/
|
||||||
searching() {
|
searching() {
|
||||||
return !!this.search
|
return !! this.search
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
$transition-timing-function: cubic-bezier(1.0, 0.5, 0.8, 1.0);
|
||||||
|
$transition-duration: .15s;
|
||||||
|
|
||||||
|
/* KeyFrames */
|
||||||
|
@-webkit-keyframes vSelectSpinner {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes vSelectSpinner {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dropdown Default Transition */
|
||||||
|
.vs__fade-enter-active,
|
||||||
|
.vs__fade-leave-active {
|
||||||
|
transition: opacity $transition-duration $transition-timing-function;
|
||||||
|
}
|
||||||
|
.vs__fade-enter,
|
||||||
|
.vs__fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
.v-select {
|
||||||
|
position: relative;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select,
|
||||||
|
.v-select * {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/** Component States */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disabled
|
||||||
|
*
|
||||||
|
* When the component is disabled, all interaction
|
||||||
|
* should be prevented. Here we modify the bg color,
|
||||||
|
* and change the cursor displayed on the interactive
|
||||||
|
* components.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$disabled-bg: $vs-state-disabled-bg;
|
||||||
|
$disabled-color: $vs-state-disabled-color;
|
||||||
|
$disabled-cursor: $vs-state-disabled-cursor;
|
||||||
|
|
||||||
|
.vs--disabled {
|
||||||
|
.vs__dropdown-toggle,
|
||||||
|
.vs__clear,
|
||||||
|
.vs__search,
|
||||||
|
.vs__selected,
|
||||||
|
.vs__open-indicator {
|
||||||
|
cursor: $disabled-cursor;
|
||||||
|
background-color: $disabled-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RTL - Right to Left Support
|
||||||
|
*
|
||||||
|
* Because we're using a flexbox layout, the `dir="rtl"`
|
||||||
|
* HTML attribute does most of the work for us by
|
||||||
|
* rearranging the child elements visually.
|
||||||
|
*/
|
||||||
|
|
||||||
|
.v-select[dir="rtl"] {
|
||||||
|
.vs__actions {
|
||||||
|
padding: 0 3px 0 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__clear {
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__deselect {
|
||||||
|
margin-left: 0;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__dropdown-menu {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
$vs-colors: (
|
||||||
|
lightest: rgba(60, 60, 60, 0.26),
|
||||||
|
light: rgba(60, 60, 60, 0.5),
|
||||||
|
dark: #333,
|
||||||
|
darkest: rgba(0, 0, 0, .15),
|
||||||
|
) !default;
|
||||||
|
|
||||||
|
// Global Component Variables
|
||||||
|
$vs-component-line-height: 1.4 !default;
|
||||||
|
$vs-component-placeholder-color: inherit !default;
|
||||||
|
|
||||||
|
// Active State
|
||||||
|
$vs-state-active-bg: #5897fb !default;
|
||||||
|
$vs-state-active-color: #fff !default;
|
||||||
|
|
||||||
|
// Disabled State
|
||||||
|
$vs-state-disabled-bg: rgb(248, 248, 248) !default;
|
||||||
|
$vs-state-disabled-color: map_get($vs-colors, 'light') !default;
|
||||||
|
$vs-state-disabled-controls-color: map_get($vs-colors, 'light') !default;
|
||||||
|
$vs-state-disabled-cursor: not-allowed !default;
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
$vs-border-width: 1px !default;
|
||||||
|
$vs-border-style: solid !default;
|
||||||
|
$vs-border-radius: 4px !default;
|
||||||
|
$vs-border-color: map_get($vs-colors, 'lightest') !default;
|
||||||
|
|
||||||
|
// Component Controls: Clear, Open Indicator
|
||||||
|
$vs-controls-color: map_get($vs-colors, 'light') !default;
|
||||||
|
$vs-controls-size: 1 !default;
|
||||||
|
$vs-controls-deselect-text-shadow: 0 1px 0 #fff;
|
||||||
|
|
||||||
|
// Selected
|
||||||
|
$vs-selected-bg: #f0f0f0 !default;
|
||||||
|
$vs-selected-border-color: $vs-border-color !default;
|
||||||
|
$vs-selected-border-style: $vs-border-style !default;
|
||||||
|
$vs-selected-border-width: $vs-border-width !default;
|
||||||
|
|
||||||
|
// Dropdown
|
||||||
|
$vs-dropdown-z-index: 1000 !default;
|
||||||
|
$vs-dropdown-min-width: 160px !default;
|
||||||
|
$vs-dropdown-max-height: 350px !default;
|
||||||
|
$vs-dropdown-box-shadow: 0px 3px 6px 0px map_get($vs-colors, 'darkest') !default;
|
||||||
|
$vs-dropdown-bg: #fff !default;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/* Clear Button */
|
||||||
|
|
||||||
|
.vs__clear {
|
||||||
|
fill: $vs-controls-color;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
cursor: pointer;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
/* Dropdown Menu */
|
||||||
|
|
||||||
|
$border-width: $vs-border-width;
|
||||||
|
$border-style: solid;
|
||||||
|
$border-color: $vs-border-color;
|
||||||
|
$border-radius: $vs-border-radius;
|
||||||
|
$box-shadow: $vs-dropdown-box-shadow;
|
||||||
|
|
||||||
|
$bg-color: $vs-dropdown-bg;
|
||||||
|
$z-index: $vs-dropdown-z-index;
|
||||||
|
$min-width: $vs-dropdown-min-width;
|
||||||
|
$max-height: $vs-dropdown-max-height;
|
||||||
|
|
||||||
|
.vs__dropdown-menu {
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% - #{$border-width}); // -{#$border-width} here ensures the left and right borders of the dropdown appear flush with the toggle.
|
||||||
|
left: 0;
|
||||||
|
z-index: $z-index;
|
||||||
|
padding: 5px 0;
|
||||||
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-height: $max-height;
|
||||||
|
min-width: $min-width;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-shadow: $box-shadow;
|
||||||
|
border: $border-width $border-style $border-color;
|
||||||
|
border-top-style: none;
|
||||||
|
border-radius: 0 0 $border-radius $border-radius;
|
||||||
|
text-align: left;
|
||||||
|
list-style: none;
|
||||||
|
background: $bg-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__no-options {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
/* List Items */
|
||||||
|
.vs__dropdown-option {
|
||||||
|
line-height: 1.42857143; /* Normalize line height */
|
||||||
|
display: block;
|
||||||
|
padding: 3px 20px;
|
||||||
|
clear: both;
|
||||||
|
color: #333; /* Overrides most CSS frameworks */
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__dropdown-option--highlight {
|
||||||
|
background: $vs-state-active-bg;
|
||||||
|
color: $vs-state-active-color;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
Dropdown Toggle
|
||||||
|
|
||||||
|
The dropdown toggle is the primary wrapper of the component. It
|
||||||
|
has two direct descendants: .vs__selected-options, and .vs__actions.
|
||||||
|
|
||||||
|
.vs__selected-options holds the .vs__selected's as well as the
|
||||||
|
main search input.
|
||||||
|
|
||||||
|
.vs__actions holds the clear button and dropdown toggle.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$border-width: $vs-border-width;
|
||||||
|
$border-style: $vs-border-style;
|
||||||
|
$border-color: $vs-border-color;
|
||||||
|
$border-radius: $vs-border-radius;
|
||||||
|
|
||||||
|
.vs__dropdown-toggle {
|
||||||
|
appearance: none;
|
||||||
|
display: flex;
|
||||||
|
padding: 0 0 4px 0;
|
||||||
|
background: none;
|
||||||
|
border: $border-width $border-style $border-color;
|
||||||
|
border-radius: $border-radius;
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__selected-options {
|
||||||
|
display: flex;
|
||||||
|
flex-basis: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
padding: 0 2px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 4px 6px 0 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Dropdown Toggle States */
|
||||||
|
.vs--searchable .vs__dropdown-toggle {
|
||||||
|
cursor: text;
|
||||||
|
}
|
||||||
|
.vs--unsearchable .vs__dropdown-toggle {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.vs--open .vs__dropdown-toggle {
|
||||||
|
border-bottom-color: transparent;
|
||||||
|
border-bottom-left-radius: 0;
|
||||||
|
border-bottom-right-radius: 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Open Indicator
|
||||||
|
|
||||||
|
// The open indicator appears as a down facing
|
||||||
|
// caret on the right side of the select.
|
||||||
|
|
||||||
|
$transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
||||||
|
$transition-duration: 150ms;
|
||||||
|
|
||||||
|
$open-indicator-color: $vs-controls-color;
|
||||||
|
$open-indicator-size: $vs-controls-size;
|
||||||
|
|
||||||
|
.vs__open-indicator {
|
||||||
|
fill: $open-indicator-color;
|
||||||
|
transform: scale($open-indicator-size);
|
||||||
|
transition: transform $transition-duration $transition-timing-function;
|
||||||
|
transition-timing-function: $transition-timing-function;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open State
|
||||||
|
|
||||||
|
.vs--open .vs__open-indicator {
|
||||||
|
transform: rotate(180deg) scale($open-indicator-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loading State
|
||||||
|
|
||||||
|
.vs--loading .vs__open-indicator {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/* Search Input */
|
||||||
|
|
||||||
|
$line-height: $vs-component-line-height;
|
||||||
|
$font-size: 1em;
|
||||||
|
|
||||||
|
.vs__search::-webkit-search-decoration,
|
||||||
|
.vs__search::-webkit-search-cancel-button,
|
||||||
|
.vs__search::-webkit-search-results-button,
|
||||||
|
.vs__search::-webkit-search-results-decoration,
|
||||||
|
.vs__search::-ms-clear {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__search,
|
||||||
|
.vs__search:focus {
|
||||||
|
appearance: none;
|
||||||
|
line-height: $line-height;
|
||||||
|
font-size: $font-size;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-left: none;
|
||||||
|
outline: none;
|
||||||
|
margin: 4px 0 0 0;
|
||||||
|
padding: 0 7px;
|
||||||
|
background: none;
|
||||||
|
box-shadow: none;
|
||||||
|
width: 0;
|
||||||
|
max-width: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__search::placeholder {
|
||||||
|
color: $vs-component-placeholder-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
States
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Unsearchable
|
||||||
|
.vs--unsearchable {
|
||||||
|
.vs__search {
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Single, when searching but not loading or open
|
||||||
|
.vs--single.vs--searching:not(.vs--open):not(.vs--loading) {
|
||||||
|
.vs__search {
|
||||||
|
opacity: .2;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/* Selected Tags */
|
||||||
|
.vs__selected {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: $vs-selected-bg;
|
||||||
|
border: $vs-selected-border-width $vs-selected-border-style $vs-selected-border-color;
|
||||||
|
border-radius: $vs-border-radius;
|
||||||
|
color: map_get($vs-colors, 'dark');
|
||||||
|
line-height: $vs-component-line-height;
|
||||||
|
margin: 4px 2px 0px 2px;
|
||||||
|
padding: 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__deselect {
|
||||||
|
display: inline-flex;
|
||||||
|
appearance: none;
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background: none;
|
||||||
|
fill: $vs-controls-color;
|
||||||
|
text-shadow: $vs-controls-deselect-text-shadow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* States */
|
||||||
|
|
||||||
|
.vs--single {
|
||||||
|
.vs__selected {
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: transparent;
|
||||||
|
}
|
||||||
|
&.vs--open .vs__selected {
|
||||||
|
position: absolute;
|
||||||
|
opacity: .4;
|
||||||
|
}
|
||||||
|
&.vs--searching .vs__selected {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/* Loading Spinner */
|
||||||
|
.vs__spinner {
|
||||||
|
align-self: center;
|
||||||
|
opacity: 0;
|
||||||
|
font-size: 5px;
|
||||||
|
text-indent: -9999em;
|
||||||
|
overflow: hidden;
|
||||||
|
border-top: .9em solid rgba(100, 100, 100, .1);
|
||||||
|
border-right: .9em solid rgba(100, 100, 100, .1);
|
||||||
|
border-bottom: .9em solid rgba(100, 100, 100, .1);
|
||||||
|
border-left: .9em solid rgba(60, 60, 60, .45);
|
||||||
|
transform: translateZ(0);
|
||||||
|
animation: vSelectSpinner 1.1s infinite linear;
|
||||||
|
transition: opacity .1s;
|
||||||
|
}
|
||||||
|
.vs__spinner,
|
||||||
|
.vs__spinner:after {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 5em;
|
||||||
|
height: 5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loading Spinner States */
|
||||||
|
.vs--loading .vs__spinner {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
@import "global/variables";
|
||||||
|
@import "global/component";
|
||||||
|
@import "global/animations";
|
||||||
|
@import "global/states";
|
||||||
|
|
||||||
|
@import "modules/dropdown-toggle";
|
||||||
|
@import "modules/open-indicator";
|
||||||
|
@import "modules/clear";
|
||||||
|
@import "modules/dropdown-menu";
|
||||||
|
@import "modules/dropdown-option";
|
||||||
|
@import "modules/selected";
|
||||||
|
@import "modules/search-input";
|
||||||
|
@import "modules/spinner";
|
||||||
@@ -4,7 +4,7 @@ describe("Removing values", () => {
|
|||||||
it("can remove the given tag when its close icon is clicked", () => {
|
it("can remove the given tag when its close icon is clicked", () => {
|
||||||
const Select = selectWithProps({ multiple: true, value: ["foo"] });
|
const Select = selectWithProps({ multiple: true, value: ["foo"] });
|
||||||
|
|
||||||
Select.find(".close").trigger("click");
|
Select.find(".vs__deselect").trigger("click");
|
||||||
expect(Select.vm.mutableValue).toEqual([]);
|
expect(Select.vm.mutableValue).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ describe("Removing values", () => {
|
|||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
|
|
||||||
Select.find(".close").trigger("click");
|
Select.find(".vs__deselect").trigger("click");
|
||||||
expect(Select.vm.mutableValue).toEqual(["one"]);
|
expect(Select.vm.mutableValue).toEqual(["one"]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ describe("Removing values", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
expect(Select.vm.mutableValue).toEqual("foo");
|
expect(Select.vm.mutableValue).toEqual("foo");
|
||||||
Select.find("button.clear").trigger("click");
|
Select.find("button.vs__clear").trigger("click");
|
||||||
expect(Select.vm.mutableValue).toEqual(null);
|
expect(Select.vm.mutableValue).toEqual(null);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ describe("Removing values", () => {
|
|||||||
disabled: true
|
disabled: true
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(Select.find("button.clear").attributes().disabled).toEqual(
|
expect(Select.find("button.vs__clear").attributes().disabled).toEqual(
|
||||||
"disabled"
|
"disabled"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ describe("Toggling Dropdown", () => {
|
|||||||
options: [{ label: "one" }]
|
options: [{ label: "one" }]
|
||||||
});
|
});
|
||||||
|
|
||||||
const selectedTag = Select.find(".selected-tag").element;
|
const selectedTag = Select.find(".vs__selected").element;
|
||||||
|
|
||||||
Select.vm.toggleDropdown({ target: selectedTag });
|
Select.vm.toggleDropdown({ target: selectedTag });
|
||||||
expect(Select.vm.open).toEqual(true);
|
expect(Select.vm.open).toEqual(true);
|
||||||
@@ -127,9 +127,9 @@ describe("Toggling Dropdown", () => {
|
|||||||
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.dropdownClasses.open).toEqual(false);
|
expect(Select.vm.stateClasses['vs--open']).toEqual(false);
|
||||||
|
|
||||||
Select.vm.open = true;
|
Select.vm.open = true;
|
||||||
expect(Select.vm.dropdownClasses.open).toEqual(true);
|
expect(Select.vm.stateClasses['vs--open']).toEqual(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ describe("Labels", () => {
|
|||||||
label: "name",
|
label: "name",
|
||||||
value: { name: "Foo" }
|
value: { name: "Foo" }
|
||||||
});
|
});
|
||||||
expect(Select.find(".selected-tag").text()).toBe("Foo");
|
expect(Select.find(".vs__selected").text()).toBe("Foo");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("will console.warn when options contain objects without a valid label key", () => {
|
it("will console.warn when options contain objects without a valid label key", () => {
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ describe("When index prop is defined", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(Select.find(".selected-tag").text()).toContain("Baz");
|
expect(Select.find(".vs__selected").text()).toContain("Baz");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("will console.warn when attempting to select an option with an undefined index", () => {
|
it("will console.warn when attempting to select an option with an undefined index", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user