mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-10 07:52:23 +03:00
Merge remote-tracking branch 'origin/release/v3.0'
* origin/release/v3.0: (67 commits) ensure #222 stays closed (#828) add guide for reduce and taggable (#827) Remove foo bar (#826) WIP: v3 – remove onSearch callback prop (#811) doc content updates overhaul selecting docs, updated navigation and URL structure bump vue-server-renderer (#807) WIP: V3 - Remove index prop, add reduce prop (#800) V3/update list items slot (#799) update vuepress (#797) Update sandbox Add patch from #787 update package deps, remove extra dev options V3 - Remove `mutable` class properties plus other misc changes (#781) refactor deselect method (#768) Sass & Class Renames (#759) fix coveralls coverage reporter (#766) remove: - express - gitbook - json-loader - markdown-loader - normalize.css - prismjs - vue-resource use test-utils beta-20 fix failing test ... # Conflicts: # docs/gitbook/README.md # docs/homepage/home.html # src/components/Select.vue
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"presets": ["es2015", "stage-2"],
|
||||
"plugins": ["transform-runtime"],
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": ["@babel/plugin-transform-runtime"],
|
||||
"comments": false
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
engines:
|
||||
csslint:
|
||||
enabled: true
|
||||
duplication:
|
||||
enabled: true
|
||||
config:
|
||||
languages:
|
||||
- ruby
|
||||
- javascript
|
||||
- python
|
||||
- php
|
||||
eslint:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
ratings:
|
||||
paths:
|
||||
- "src/components/Select.vue"
|
||||
exclude_paths:
|
||||
- dist/
|
||||
- test/
|
||||
- docs/
|
||||
- config/
|
||||
- build/
|
||||
@@ -1,2 +0,0 @@
|
||||
--exclude-exts=.min.css
|
||||
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes
|
||||
@@ -1 +0,0 @@
|
||||
**/*{.,-}min.js
|
||||
@@ -1,185 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"html"
|
||||
],
|
||||
|
||||
"env": {
|
||||
"browser": true,
|
||||
"node": true
|
||||
},
|
||||
|
||||
"ecmaFeatures": {
|
||||
"arrowFunctions": true,
|
||||
"destructuring": true,
|
||||
"classes": true,
|
||||
"defaultParams": true,
|
||||
"blockBindings": true,
|
||||
"modules": true,
|
||||
"objectLiteralComputedProperties": true,
|
||||
"objectLiteralShorthandMethods": true,
|
||||
"objectLiteralShorthandProperties": true,
|
||||
"restParams": true,
|
||||
"spread": true,
|
||||
"forOf": true,
|
||||
"generators": true,
|
||||
"templateStrings": true,
|
||||
"superInFunctions": true,
|
||||
"experimentalObjectRestSpread": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"accessor-pairs": 2,
|
||||
"array-bracket-spacing": 0,
|
||||
"block-scoped-var": 0,
|
||||
"brace-style": [2, "1tbs", { "allowSingleLine": true }],
|
||||
"camelcase": 0,
|
||||
"comma-dangle": [2, "never"],
|
||||
"comma-spacing": [2, { "before": false, "after": true }],
|
||||
"comma-style": [2, "last"],
|
||||
"complexity": 0,
|
||||
"computed-property-spacing": 0,
|
||||
"consistent-return": 0,
|
||||
"consistent-this": 0,
|
||||
"constructor-super": 2,
|
||||
"curly": [2, "multi-line"],
|
||||
"default-case": 0,
|
||||
"dot-location": [2, "property"],
|
||||
"dot-notation": 0,
|
||||
"eol-last": 2,
|
||||
"eqeqeq": [2, "allow-null"],
|
||||
"func-names": 0,
|
||||
"func-style": 0,
|
||||
"generator-star-spacing": [2, { "before": true, "after": true }],
|
||||
"guard-for-in": 0,
|
||||
"handle-callback-err": [2, "^(err|error)$" ],
|
||||
"indent": [2, 2, { "SwitchCase": 1 }],
|
||||
"key-spacing": [2, { "beforeColon": false, "afterColon": true }],
|
||||
"linebreak-style": 0,
|
||||
"lines-around-comment": 0,
|
||||
"max-nested-callbacks": 0,
|
||||
"new-cap": [2, { "newIsCap": true, "capIsNew": false }],
|
||||
"new-parens": 2,
|
||||
"newline-after-var": 0,
|
||||
"no-alert": 0,
|
||||
"no-array-constructor": 2,
|
||||
"no-caller": 2,
|
||||
"no-catch-shadow": 0,
|
||||
"no-cond-assign": 2,
|
||||
"no-console": 0,
|
||||
"no-constant-condition": 0,
|
||||
"no-continue": 0,
|
||||
"no-control-regex": 2,
|
||||
"no-debugger": 2,
|
||||
"no-delete-var": 2,
|
||||
"no-div-regex": 0,
|
||||
"no-dupe-args": 2,
|
||||
"no-dupe-keys": 2,
|
||||
"no-duplicate-case": 2,
|
||||
"no-else-return": 0,
|
||||
"no-empty": 0,
|
||||
"no-empty-character-class": 2,
|
||||
"no-empty-label": 2,
|
||||
"no-eq-null": 0,
|
||||
"no-eval": 2,
|
||||
"no-ex-assign": 2,
|
||||
"no-extend-native": 2,
|
||||
"no-extra-bind": 2,
|
||||
"no-extra-boolean-cast": 2,
|
||||
"no-extra-parens": 0,
|
||||
"no-extra-semi": 0,
|
||||
"no-fallthrough": 2,
|
||||
"no-floating-decimal": 2,
|
||||
"no-func-assign": 2,
|
||||
"no-implied-eval": 2,
|
||||
"no-inline-comments": 0,
|
||||
"no-inner-declarations": [2, "functions"],
|
||||
"no-invalid-regexp": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"no-iterator": 2,
|
||||
"no-label-var": 2,
|
||||
"no-labels": 2,
|
||||
"no-lone-blocks": 2,
|
||||
"no-lonely-if": 0,
|
||||
"no-loop-func": 0,
|
||||
"no-mixed-requires": 0,
|
||||
"no-mixed-spaces-and-tabs": 2,
|
||||
"no-multi-spaces": 2,
|
||||
"no-multi-str": 2,
|
||||
"no-multiple-empty-lines": [2, { "max": 1 }],
|
||||
"no-native-reassign": 2,
|
||||
"no-negated-in-lhs": 2,
|
||||
"no-nested-ternary": 0,
|
||||
"no-new": 2,
|
||||
"no-new-func": 0,
|
||||
"no-new-object": 2,
|
||||
"no-new-require": 2,
|
||||
"no-new-wrappers": 2,
|
||||
"no-obj-calls": 2,
|
||||
"no-octal": 2,
|
||||
"no-octal-escape": 2,
|
||||
"no-param-reassign": 0,
|
||||
"no-path-concat": 0,
|
||||
"no-process-env": 0,
|
||||
"no-process-exit": 0,
|
||||
"no-proto": 0,
|
||||
"no-redeclare": 2,
|
||||
"no-regex-spaces": 2,
|
||||
"no-restricted-modules": 0,
|
||||
"no-return-assign": 2,
|
||||
"no-script-url": 0,
|
||||
"no-self-compare": 2,
|
||||
"no-sequences": 2,
|
||||
"no-shadow": 0,
|
||||
"no-shadow-restricted-names": 2,
|
||||
"no-spaced-func": 2,
|
||||
"no-sparse-arrays": 2,
|
||||
"no-sync": 0,
|
||||
"no-ternary": 0,
|
||||
"no-this-before-super": 2,
|
||||
"no-throw-literal": 2,
|
||||
"no-trailing-spaces": 2,
|
||||
"no-undef": 2,
|
||||
"no-undef-init": 2,
|
||||
"no-undefined": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"no-unexpected-multiline": 2,
|
||||
"no-unneeded-ternary": 2,
|
||||
"no-unreachable": 2,
|
||||
"no-unused-expressions": 0,
|
||||
"no-unused-vars": [2, { "vars": "all", "args": "none" }],
|
||||
"no-use-before-define": 0,
|
||||
"no-var": 0,
|
||||
"no-void": 0,
|
||||
"no-warning-comments": 0,
|
||||
"no-with": 2,
|
||||
"object-curly-spacing": 0,
|
||||
"object-shorthand": 0,
|
||||
"one-var": [2, { "initialized": "never" }],
|
||||
"operator-assignment": 0,
|
||||
"operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }],
|
||||
"padded-blocks": 0,
|
||||
"prefer-const": 0,
|
||||
"quote-props": 0,
|
||||
"quotes": [2, "single", "avoid-escape"],
|
||||
"radix": 2,
|
||||
"semi": [2, "never"],
|
||||
"semi-spacing": 0,
|
||||
"sort-vars": 0,
|
||||
"space-after-keywords": [2, "always"],
|
||||
"space-before-blocks": [2, "always"],
|
||||
"space-before-function-paren": [2, "always"],
|
||||
"space-in-parens": [2, "never"],
|
||||
"space-infix-ops": 2,
|
||||
"space-return-throw-case": 2,
|
||||
"space-unary-ops": [2, { "words": true, "nonwords": false }],
|
||||
"spaced-comment": [2, "always", { "markers": ["global", "globals", "eslint", "eslint-disable", "*package", "!"] }],
|
||||
"strict": 0,
|
||||
"use-isnan": 2,
|
||||
"valid-jsdoc": 0,
|
||||
"valid-typeof": 2,
|
||||
"vars-on-top": 0,
|
||||
"wrap-iife": [2, "any"],
|
||||
"wrap-regex": 0,
|
||||
"yoda": [2, "never"]
|
||||
}
|
||||
}
|
||||
+24
-8
@@ -1,12 +1,28 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
npm-debug.log
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
test/unit/coverage
|
||||
.coveralls.yml
|
||||
.flowconfig
|
||||
package-lock.json
|
||||
docs/gitbook/_book
|
||||
docs/node_modules
|
||||
site
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw*
|
||||
|
||||
# Project specific
|
||||
coverage
|
||||
dist
|
||||
test/unit/coverage
|
||||
package-lock.json
|
||||
dev/dist
|
||||
docs/.vuepress/dist
|
||||
|
||||
+5
-2
@@ -1,5 +1,8 @@
|
||||
language: node_js
|
||||
cache: npm
|
||||
|
||||
node_js:
|
||||
- node
|
||||
after_success:
|
||||
- codeclimate-test-reporter < ./test/unit/coverage/lcov.info
|
||||
|
||||
script:
|
||||
- yarn test --coverage --coverageReporters=text-lcov | coveralls
|
||||
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
## Pull Requests
|
||||
|
||||
Looks like you want to help out on vue-select.. awesome! Here's a couple things to keep in mind when contributing.
|
||||
Looks like you want to help out on vue-select.. awesome! Here's a few things to keep in mind when contributing.
|
||||
|
||||
1. If your PR contains multiple commits, try to keep those commits succinct, with descriptive messages. This makes it easier to understand your thought process.
|
||||
2. Don't run the build before submitting. The build is only run and committed immediately before a new release, and submitting a PR with a build included is just more to parse.
|
||||
2. **Don't run the build** before submitting. The build is only run and committed immediately before a new release.
|
||||
3. If your PR fixes or references an open issue, be sure to reference it in your message.
|
||||
4. If you're adding new functionality, make sure your code has good test coverage.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# vue-select [](https://travis-ci.org/sagalbot/vue-select)  
|
||||
# vue-select [](https://travis-ci.org/sagalbot/vue-select) [](https://coveralls.io/github/sagalbot/vue-select)  
|
||||
|
||||
> A native Vue.js select component that provides similar functionality to Select2 without the overhead of jQuery.
|
||||
> Everything you wish the native `<select>` element could do, wrapped up into a zero dependency, highly extensible Vue component.
|
||||
|
||||
Want to help out as a primary contributor? [Get in touch](https://github.com/sagalbot/vue-select/issues/581)!
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"title": "vue-select",
|
||||
"gitbook": ">3.0.0",
|
||||
"root": "./docs/gitbook",
|
||||
"plugins": ["edit-link", "-fontsettings", "codepen", "include-csv"],
|
||||
"pluginsConfig": {
|
||||
"edit-link": {
|
||||
"base": "https://github.com/sagalbot/vue-select/edit/gitbook/docs/gitbook",
|
||||
"label": "Edit This Page"
|
||||
},
|
||||
"github": {
|
||||
"url": "https://github.com/sagalbot/vue-select/"
|
||||
},
|
||||
"codepen": {
|
||||
"theme": 32252
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
"sharing": {
|
||||
"facebook": false,
|
||||
"twitter": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
// https://github.com/shelljs/shelljs
|
||||
const shell = require('shelljs');
|
||||
|
||||
shell.exec('gitbook build', (code, stdout, stderr) => {
|
||||
if( code === 0 ) {
|
||||
shell.rm('-rf', 'site/docs');
|
||||
shell.exec('mv _book site/docs')
|
||||
}
|
||||
});
|
||||
@@ -1,35 +0,0 @@
|
||||
// https://github.com/shelljs/shelljs
|
||||
require('shelljs/global');
|
||||
env.NODE_ENV = 'production';
|
||||
|
||||
var path = require('path');
|
||||
var config = require('../config');
|
||||
var ora = require('ora');
|
||||
var webpack = require('webpack');
|
||||
var utils = require('./utils');
|
||||
var webpackConfig = utils.shouldBuildHomepage() ? require('./webpack.site.conf') : require('./webpack.prod.conf');
|
||||
|
||||
var text = utils.shouldBuildHomepage() ? 'homepage' : 'vue-select UMD module';
|
||||
var spinner = ora(`building ${text}...`);
|
||||
spinner.start();
|
||||
|
||||
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory);
|
||||
if (!utils.shouldBuildHomepage()) {
|
||||
rm('-rf', assetsPath);
|
||||
mkdir('-p', assetsPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the /dist/ folder
|
||||
*/
|
||||
webpack(webpackConfig, function (err, stats) {
|
||||
spinner.stop();
|
||||
if (err) throw err;
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n')
|
||||
});
|
||||
@@ -1,9 +0,0 @@
|
||||
/* eslint-disable */
|
||||
require('eventsource-polyfill')
|
||||
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
|
||||
|
||||
hotClient.subscribe(function (event) {
|
||||
if (event.action === 'reload') {
|
||||
window.location.reload()
|
||||
}
|
||||
})
|
||||
@@ -1,65 +0,0 @@
|
||||
var path = require('path')
|
||||
var express = require('express')
|
||||
var webpack = require('webpack')
|
||||
var config = require('../config')
|
||||
var proxyMiddleware = require('http-proxy-middleware')
|
||||
var webpackConfig = process.env.NODE_ENV === 'testing'
|
||||
? require('./webpack.prod.conf')
|
||||
: require('./webpack.dev.conf')
|
||||
|
||||
// default port where dev server listens for incoming traffic
|
||||
var port = process.env.PORT || config.dev.port
|
||||
// Define HTTP proxies to your custom API backend
|
||||
// https://github.com/chimurai/http-proxy-middleware
|
||||
var proxyTable = config.dev.proxyTable
|
||||
|
||||
var app = express()
|
||||
var compiler = webpack(webpackConfig)
|
||||
|
||||
var devMiddleware = require('webpack-dev-middleware')(compiler, {
|
||||
publicPath: webpackConfig.output.publicPath,
|
||||
stats: {
|
||||
colors: true,
|
||||
chunks: false
|
||||
}
|
||||
})
|
||||
|
||||
var hotMiddleware = require('webpack-hot-middleware')(compiler)
|
||||
// force page reload when html-webpack-plugin template changes
|
||||
compiler.plugin('compilation', function (compilation) {
|
||||
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
|
||||
hotMiddleware.publish({ action: 'reload' })
|
||||
cb()
|
||||
})
|
||||
})
|
||||
|
||||
// proxy api requests
|
||||
Object.keys(proxyTable).forEach(function (context) {
|
||||
var options = proxyTable[context]
|
||||
if (typeof options === 'string') {
|
||||
options = { target: options }
|
||||
}
|
||||
app.use(proxyMiddleware(context, options))
|
||||
})
|
||||
|
||||
// handle fallback for HTML5 history API
|
||||
app.use(require('connect-history-api-fallback')())
|
||||
|
||||
// serve webpack bundle output
|
||||
app.use(devMiddleware)
|
||||
|
||||
// enable hot-reload and state-preserving
|
||||
// compilation error display
|
||||
app.use(hotMiddleware)
|
||||
|
||||
// serve pure static assets
|
||||
var staticPath = path.posix.join(config.build.assetsPublicPath, config.build.assetsSubDirectory)
|
||||
app.use(staticPath, express.static('./static'))
|
||||
|
||||
module.exports = app.listen(port, function (err) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
return
|
||||
}
|
||||
console.log('Listening at http://localhost:' + port + '\n')
|
||||
})
|
||||
@@ -1,83 +0,0 @@
|
||||
var path = require('path')
|
||||
var config = require('../config')
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
|
||||
/**
|
||||
* Get the path to the assetsSubDirectory
|
||||
* @param _path
|
||||
* @returns {*|string}
|
||||
*/
|
||||
exports.assetsPath = function (_path) {
|
||||
return path.posix.join(config.build.assetsSubDirectory, _path)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate loader string to be used with extract text plugin
|
||||
* @param options
|
||||
* @returns {{css: *, postcss: *, less: *, sass: *, scss: *, stylus: *, styl: *}}
|
||||
*/
|
||||
exports.cssLoaders = function (options) {
|
||||
options = options || {}
|
||||
|
||||
function generateLoaders (loaders) {
|
||||
var sourceLoader = loaders.map(function (loader) {
|
||||
var extraParamChar
|
||||
if (/\?/.test(loader)) {
|
||||
loader = loader.replace(/\?/, '-loader?')
|
||||
extraParamChar = '&'
|
||||
} else {
|
||||
loader = loader + '-loader'
|
||||
extraParamChar = '?'
|
||||
}
|
||||
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
|
||||
}).join('!')
|
||||
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
|
||||
} else {
|
||||
return ['vue-style-loader', sourceLoader].join('!')
|
||||
}
|
||||
}
|
||||
|
||||
// http://vuejs.github.io/vue-loader/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(['css']),
|
||||
postcss: generateLoaders(['css']),
|
||||
less: generateLoaders(['css', 'less']),
|
||||
sass: generateLoaders(['css', 'sass?indentedSyntax']),
|
||||
scss: generateLoaders(['css', 'sass']),
|
||||
stylus: generateLoaders(['css', 'stylus']),
|
||||
styl: generateLoaders(['css', 'stylus'])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate loaders for standalone style files (outside of .vue)
|
||||
* @param options
|
||||
* @returns {Array}
|
||||
*/
|
||||
exports.styleLoaders = function (options) {
|
||||
var output = []
|
||||
var loaders = exports.cssLoaders(options)
|
||||
for (var extension in loaders) {
|
||||
var loader = loaders[extension]
|
||||
output.push({
|
||||
test: new RegExp('\\.' + extension + '$'),
|
||||
loader: loader
|
||||
})
|
||||
}
|
||||
return output
|
||||
}
|
||||
|
||||
/**
|
||||
* Are we serving the docs or
|
||||
* the dev environment?
|
||||
* @returns {boolean}
|
||||
*/
|
||||
exports.shouldServeHomepage = function () {
|
||||
return process.argv.indexOf('--docs') > 0
|
||||
}
|
||||
|
||||
exports.shouldBuildHomepage = function () {
|
||||
return process.argv.indexOf('--homepage') > 0
|
||||
}
|
||||
+48
-49
@@ -1,71 +1,70 @@
|
||||
var path = require('path')
|
||||
var config = require('../config')
|
||||
var utils = require('./utils')
|
||||
var projectRoot = path.resolve(__dirname, '../')
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const VueLoaderPlugin = require('vue-loader').VueLoaderPlugin;
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
|
||||
const env = process.env.NODE_ENV === 'production'
|
||||
? 'production'
|
||||
: 'development';
|
||||
|
||||
const devtool = env === 'production' ? 'source-map' : 'eval-source-map';
|
||||
|
||||
const extractOrInjectStyles = env !== 'production'
|
||||
? 'vue-style-loader'
|
||||
: MiniCssExtractPlugin.loader;
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: utils.shouldServeHomepage() ? './docs/homepage/home.js' : './dev/dev.js',
|
||||
},
|
||||
mode: env,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
publicPath: config.build.assetsPublicPath,
|
||||
filename: '[name].js'
|
||||
path: path.resolve(__dirname, '../dist'),
|
||||
publicPath: '/',
|
||||
filename: '[name].js',
|
||||
},
|
||||
devtool,
|
||||
resolve: {
|
||||
extensions: ['', '.js', '.vue'],
|
||||
fallback: [path.join(__dirname, '../node_modules')],
|
||||
extensions: ['.js', '.vue'],
|
||||
alias: {
|
||||
'src': path.resolve(__dirname, '../src'),
|
||||
'assets': path.resolve(__dirname, '../docs/assets'),
|
||||
'mixins': path.resolve(__dirname, '../src/mixins'),
|
||||
'components': path.resolve(__dirname, '../src/components'),
|
||||
'docs': path.resolve(__dirname, '../docs'),
|
||||
'vue$': 'vue/dist/vue.common.js',
|
||||
}
|
||||
},
|
||||
resolveLoader: {
|
||||
fallback: [path.join(__dirname, '../node_modules')]
|
||||
'vue$': 'vue/dist/vue.esm.js',
|
||||
},
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
rules: [
|
||||
{
|
||||
test: /\.vue$/,
|
||||
loader: 'vue-loader'
|
||||
loader: 'vue-loader',
|
||||
},
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader',
|
||||
include: projectRoot,
|
||||
exclude: /node_modules/
|
||||
include: path.resolve(__dirname, '../'),
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader'
|
||||
test: /\.s?css$/,
|
||||
use: [
|
||||
extractOrInjectStyles,
|
||||
'css-loader',
|
||||
'postcss-loader',
|
||||
'sass-loader',
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.html$/,
|
||||
loader: 'vue-html-loader'
|
||||
},
|
||||
{
|
||||
test: /\.(png|jpe?g|gif)(\?.*)?$/,
|
||||
loader: 'url',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('img/[name].[hash:7].[ext]')
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
|
||||
loader: 'url',
|
||||
query: {
|
||||
limit: 10000,
|
||||
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
},
|
||||
vue: {
|
||||
loaders: utils.cssLoaders()
|
||||
}
|
||||
}
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env,
|
||||
}),
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'vue-select.css',
|
||||
}),
|
||||
new VueLoaderPlugin(),
|
||||
],
|
||||
stats: {
|
||||
children: false,
|
||||
modules: false,
|
||||
},
|
||||
};
|
||||
|
||||
+34
-34
@@ -1,39 +1,39 @@
|
||||
var config = require('../config')
|
||||
var webpack = require('webpack')
|
||||
var merge = require('webpack-merge')
|
||||
var utils = require('./utils')
|
||||
var baseWebpackConfig = require('./webpack.base.conf')
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
|
||||
// add hot-reload related code to entry chunks
|
||||
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
|
||||
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
|
||||
})
|
||||
const merge = require('webpack-merge');
|
||||
const chokidar = require('chokidar');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const baseWebpackConfig = require('./webpack.base.conf');
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
module.exports = merge(baseWebpackConfig, {
|
||||
module: {
|
||||
loaders: utils.styleLoaders().concat({ test: /\.md$/, loader: "html!markdown" })
|
||||
},
|
||||
// eval-source-map is faster for development
|
||||
devtool: '#eval-source-map',
|
||||
entry: './dev/dev.js',
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': config.dev.env
|
||||
}),
|
||||
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NoErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: utils.shouldServeHomepage() ? './docs/homepage/home.html' : './dev/dev.html',
|
||||
inject: true
|
||||
})
|
||||
template: './dev/dev.html',
|
||||
inject: true,
|
||||
}),
|
||||
],
|
||||
markdownLoader: {
|
||||
highlight: function (code) {
|
||||
return require('highlight.js').highlightAuto(code).value;
|
||||
}
|
||||
}
|
||||
})
|
||||
optimization: {
|
||||
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');
|
||||
});
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
+24
-31
@@ -1,32 +1,25 @@
|
||||
const webpack = require('webpack')
|
||||
const base = require('./webpack.base.conf')
|
||||
const config = require('../config')
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const merge = require('webpack-merge');
|
||||
const baseWebpackConfig = require('./webpack.base.conf');
|
||||
|
||||
base.entry = {
|
||||
lib: './src/index.js'
|
||||
}
|
||||
|
||||
base.output = {
|
||||
path: config.build.assetsRoot,
|
||||
publicPath: config.build.assetsPublicPath,
|
||||
filename: 'vue-select.js',
|
||||
library: 'VueSelect',
|
||||
libraryTarget: 'umd'
|
||||
}
|
||||
|
||||
var webpackConfig = Object.assign({}, base)
|
||||
|
||||
webpackConfig.devtool = '#source-map'
|
||||
webpackConfig.plugins = (webpackConfig.plugins || []).concat([
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: { warnings: false }
|
||||
}),
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
])
|
||||
|
||||
module.exports = webpackConfig
|
||||
module.exports = merge(baseWebpackConfig, {
|
||||
entry: './src/index.js',
|
||||
output: {
|
||||
filename: 'vue-select.js',
|
||||
library: 'VueSelect',
|
||||
libraryTarget: 'umd',
|
||||
globalObject: 'typeof self !== \'undefined\' ? self : this',
|
||||
},
|
||||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
sourceMap: true,
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
var path = require('path')
|
||||
var config = require('../config')
|
||||
var utils = require('./utils')
|
||||
var webpack = require('webpack')
|
||||
var merge = require('webpack-merge')
|
||||
var baseWebpackConfig = require('./webpack.base.conf')
|
||||
var ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
var HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
var env = process.env.NODE_ENV === 'testing'
|
||||
? require('../config/test.env')
|
||||
: config.homepage.env
|
||||
|
||||
module.exports = merge(baseWebpackConfig, {
|
||||
entry: {
|
||||
app: config.homepage.entry
|
||||
},
|
||||
module: {
|
||||
loaders: utils.styleLoaders({ sourceMap: config.homepage.productionSourceMap, extract: true })
|
||||
},
|
||||
devtool: config.homepage.productionSourceMap ? '#source-map' : false,
|
||||
output: {
|
||||
publicPath: config.homepage.assetsPublicPath,
|
||||
path: config.homepage.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
||||
},
|
||||
vue: {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: config.homepage.productionSourceMap,
|
||||
extract: true
|
||||
})
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
}),
|
||||
new webpack.optimize.OccurenceOrderPlugin(),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
// see https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
template: './docs/homepage/home.html',
|
||||
inject: true,
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency'
|
||||
}),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks: function (module, count) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
)
|
||||
}
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
chunks: ['vendor']
|
||||
})
|
||||
]
|
||||
})
|
||||
@@ -1,6 +0,0 @@
|
||||
var merge = require('webpack-merge')
|
||||
var prodEnv = require('./prod.env')
|
||||
|
||||
module.exports = merge(prodEnv, {
|
||||
NODE_ENV: '"development"'
|
||||
})
|
||||
@@ -1,30 +0,0 @@
|
||||
// see http://vuejs-templates.github.io/webpack for documentation.
|
||||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
build: {
|
||||
env: require('./prod.env'),
|
||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
||||
assetsSubDirectory: '',
|
||||
assetsPublicPath: '/',
|
||||
productionSourceMap: true
|
||||
},
|
||||
dev: {
|
||||
env: require('./dev.env'),
|
||||
port: 8080,
|
||||
proxyTable: {}
|
||||
},
|
||||
umd: {
|
||||
assetsRoot: path.resolve(__dirname, '../umd'),
|
||||
assetsPublicPath: '/'
|
||||
},
|
||||
homepage: {
|
||||
env: require('./prod.env'),
|
||||
entry: './docs/homepage/home.js',
|
||||
assetsRoot: path.resolve(__dirname, '../site'),
|
||||
assetsSubDirectory: '',
|
||||
assetsPublicPath: '',
|
||||
productionSourceMap: true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"'
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
var merge = require('webpack-merge')
|
||||
var devEnv = require('./dev.env')
|
||||
|
||||
module.exports = merge(devEnv, {
|
||||
NODE_ENV: '"testing"'
|
||||
})
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<sandbox hide-help v-slot="config">
|
||||
<v-select v-bind="config" />
|
||||
</sandbox>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import vSelect from '../src/components/Select';
|
||||
import Sandbox from '../docs/.vuepress/components/Sandbox';
|
||||
// import countries from '../docs/.vuepress/data/countryCodes';
|
||||
// import books from '../docs/.vuepress/data/books';
|
||||
|
||||
export default {
|
||||
components: {Sandbox, vSelect},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html,
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
font-family: -apple-system, sans-serif;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: none;
|
||||
border-bottom: 1px solid #cacaca;
|
||||
margin-bottom: 1em;
|
||||
padding-top: 1em;
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
@@ -1 +0,0 @@
|
||||
export default ["Afghanistan", "Åland Islands", "Albania", "Algeria", "American Samoa", "Andorra", "Angola", "Anguilla", "Antarctica", "Antigua and Barbuda", "Argentina", "Armenia", "Aruba", "Australia", "Austria", "Azerbaijan", "Bahamas", "Bahrain", "Bangladesh", "Barbados", "Belarus", "Belgium", "Belize", "Benin", "Bermuda", "Bhutan", "Bolivia", "Bosnia and Herzegovina", "Botswana", "Bouvet Island", "Brazil", "British Indian Ocean Territory", "Brunei Darussalam", "Bulgaria", "Burkina Faso", "Burundi", "Cambodia", "Cameroon", "Canada", "Cape Verde", "Cayman Islands", "Central African Republic", "Chad", "Chile", "China", "Christmas Island", "Cocos (Keeling) Islands", "Colombia", "Comoros", "Congo", "Congo, The Democratic Republic of The", "Cook Islands", "Costa Rica", "Cote D'ivoire", "Croatia", "Cuba", "Cyprus", "Czech Republic", "Denmark", "Djibouti", "Dominica", "Dominican Republic", "Ecuador", "Egypt", "El Salvador", "Equatorial Guinea", "Eritrea", "Estonia", "Ethiopia", "Falkland Islands (Malvinas)", "Faroe Islands", "Fiji", "Finland", "France", "French Guiana", "French Polynesia", "French Southern Territories", "Gabon", "Gambia", "Georgia", "Germany", "Ghana", "Gibraltar", "Greece", "Greenland", "Grenada", "Guadeloupe", "Guam", "Guatemala", "Guernsey", "Guinea", "Guinea-bissau", "Guyana", "Haiti", "Heard Island and Mcdonald Islands", "Holy See (Vatican City State)", "Honduras", "Hong Kong", "Hungary", "Iceland", "India", "Indonesia", "Iran, Islamic Republic of", "Iraq", "Ireland", "Isle of Man", "Israel", "Italy", "Jamaica", "Japan", "Jersey", "Jordan", "Kazakhstan", "Kenya", "Kiribati", "Korea, Democratic People's Republic of", "Korea, Republic of", "Kuwait", "Kyrgyzstan", "Lao People's Democratic Republic", "Latvia", "Lebanon", "Lesotho", "Liberia", "Libyan Arab Jamahiriya", "Liechtenstein", "Lithuania", "Luxembourg", "Macao", "Macedonia, The Former Yugoslav Republic of", "Madagascar", "Malawi", "Malaysia", "Maldives", "Mali", "Malta", "Marshall Islands", "Martinique", "Mauritania", "Mauritius", "Mayotte", "Mexico", "Micronesia, Federated States of", "Moldova, Republic of", "Monaco", "Mongolia", "Montenegro", "Montserrat", "Morocco", "Mozambique", "Myanmar", "Namibia", "Nauru", "Nepal", "Netherlands", "Netherlands Antilles", "New Caledonia", "New Zealand", "Nicaragua", "Niger", "Nigeria", "Niue", "Norfolk Island", "Northern Mariana Islands", "Norway", "Oman", "Pakistan", "Palau", "Palestinian Territory, Occupied", "Panama", "Papua New Guinea", "Paraguay", "Peru", "Philippines", "Pitcairn", "Poland", "Portugal", "Puerto Rico", "Qatar", "Reunion", "Romania", "Russian Federation", "Rwanda", "Saint Helena", "Saint Kitts and Nevis", "Saint Lucia", "Saint Pierre and Miquelon", "Saint Vincent and The Grenadines", "Samoa", "San Marino", "Sao Tome and Principe", "Saudi Arabia", "Senegal", "Serbia", "Seychelles", "Sierra Leone", "Singapore", "Slovakia", "Slovenia", "Solomon Islands", "Somalia", "South Africa", "South Georgia and The South Sandwich Islands", "Spain", "Sri Lanka", "Sudan", "Suriname", "Svalbard and Jan Mayen", "Swaziland", "Sweden", "Switzerland", "Syrian Arab Republic", "Taiwan, Province of China", "Tajikistan", "Tanzania, United Republic of", "Thailand", "Timor-leste", "Togo", "Tokelau", "Tonga", "Trinidad and Tobago", "Tunisia", "Turkey", "Turkmenistan", "Turks and Caicos Islands", "Tuvalu", "Uganda", "Ukraine", "United Arab Emirates", "United Kingdom", "United States", "United States Minor Outlying Islands", "Uruguay", "Uzbekistan", "Vanuatu", "Venezuela", "Viet Nam", "Virgin Islands, British", "Virgin Islands, U.S.", "Wallis and Futuna", "Western Sahara", "Yemen", "Zambia", "Zimbabwe"];
|
||||
+7
-80
@@ -1,87 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue Select Dev</title>
|
||||
<!--<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.1/css/foundation.min.css" rel="stylesheet">-->
|
||||
<!--<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.3.2/css/bulma.min.css" rel="stylesheet">-->
|
||||
<!--<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">-->
|
||||
<!--<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>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue Select Dev</title>
|
||||
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.5.3/css/foundation.min.css">-->
|
||||
<!--<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.4/css/bulma.min.css">-->
|
||||
<!--<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">-->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<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>
|
||||
<div id="app"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
||||
+5
-47
@@ -1,50 +1,8 @@
|
||||
import Vue from 'vue'
|
||||
import Fuse from 'fuse.js'
|
||||
import debounce from 'lodash/debounce'
|
||||
import resource from 'vue-resource'
|
||||
import vSelect from '../src/components/Select.vue'
|
||||
import countries from './data/countryCodes'
|
||||
import fuseSearchOptions from './data/books'
|
||||
import Vue from "vue";
|
||||
import Dev from "./Dev.vue";
|
||||
|
||||
Vue.use(resource)
|
||||
Vue.component('v-select', vSelect)
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
render: h => h(Dev)
|
||||
}).$mount("#app");
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<template>
|
||||
<p :data-height="height"
|
||||
data-theme-id="32252"
|
||||
:data-slug-hash="url"
|
||||
data-default-tab="result"
|
||||
data-user="sagalbot"
|
||||
class="codepen">
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mountCodePen from '../utils/codePen';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
url: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
height: {
|
||||
default: 250
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
mountCodePen();
|
||||
},
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,18 @@
|
||||
<template>
|
||||
<v-select :options="options"></v-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import countryCodes from '../data/countryCodes';
|
||||
|
||||
export default {
|
||||
name: 'CountrySelect',
|
||||
data: () => ({
|
||||
options: countryCodes,
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,60 @@
|
||||
<template>
|
||||
<div class="flex">
|
||||
<div>
|
||||
<v-select
|
||||
label="country"
|
||||
v-model="selected"
|
||||
:reduce="opt => opt.meta.id"
|
||||
:options="options"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<pre><code>v-model value: {{ selected || 'null' }}</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ReducerNestedValue',
|
||||
data: () => ({
|
||||
selected: null,
|
||||
options: [
|
||||
{
|
||||
country: 'canada',
|
||||
meta: {
|
||||
id: '1',
|
||||
code: 'ca',
|
||||
},
|
||||
}],
|
||||
}),
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.flex {
|
||||
margin-bottom: 2rem;
|
||||
border: 1px solid #eaecef;
|
||||
/*padding: 1rem;*/
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.flex > div {
|
||||
flex-grow: 1;
|
||||
width: 50%;
|
||||
padding: 0 1rem;
|
||||
}
|
||||
|
||||
pre {
|
||||
margin: 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
code {
|
||||
color: #635762 !important;
|
||||
color: #5b2d2d !important;
|
||||
/*color: #7ec699 !important;*/
|
||||
}
|
||||
</style>
|
||||
@@ -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: 'Select a Country...',
|
||||
});
|
||||
|
||||
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>
|
||||
@@ -0,0 +1,104 @@
|
||||
const isDeployPreview = process.env.hasOwnProperty('DEPLOY_PREVIEW');
|
||||
|
||||
const meta = {
|
||||
title: 'Vue Select | VueJS Select2/Chosen Component',
|
||||
description: 'Everything you wish the native <select> element could do, wrapped up into a zero dependency, highly extensible Vue component.',
|
||||
url: 'http://sagalbot.github.io/vue-select/',
|
||||
icon: '/vue-logo.png',
|
||||
};
|
||||
|
||||
let head = [
|
||||
[
|
||||
'link',
|
||||
{
|
||||
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',
|
||||
rel: 'stylesheet',
|
||||
type: 'text/css',
|
||||
}],
|
||||
['link', { rel: 'icon', href: `/vue-logo.png` }],
|
||||
['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', { rel: 'apple-touch-icon', href: `/icons/apple-touch-icon-152x152.png` }],
|
||||
['link', { rel: 'mask-icon', href: '/icons/safari-pinned-tab.svg', color: '#3eaf7c' }],
|
||||
['meta', { name: 'msapplication-TileImage', content: '/icons/msapplication-icon-144x144.png' }],
|
||||
['meta', { name: 'msapplication-TileColor', content: '#000000' }]
|
||||
];
|
||||
|
||||
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: 'description', content: meta.description}],
|
||||
['link', {rel: 'icon', href: meta.icon, type: 'image/png'}],
|
||||
['meta', {property: 'og:image', content: meta.icon}],
|
||||
['meta', {property: 'twitter:image', content: meta.icon}],
|
||||
['meta', {name: 'description', content: meta.description}],
|
||||
['meta', {property: 'og:description', content: ''}],
|
||||
['meta', {property: 'twitter:description', content: meta.description}],
|
||||
['meta', {property: 'twitter:title', content: meta.title}],
|
||||
['meta', {property: 'og:title', content: meta.title}],
|
||||
['meta', {property: 'og:site_name', content: meta.title}],
|
||||
['meta', {property: 'og:url', content: meta.url}],
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
title: 'Vue Select',
|
||||
description: meta.description,
|
||||
head,
|
||||
serviceWorker: !isDeployPreview,
|
||||
ga: isDeployPreview ? '' : 'UA-12818324-8',
|
||||
themeConfig: {
|
||||
repo: 'sagalbot/vue-select',
|
||||
editLinks: true,
|
||||
docsDir: 'docs',
|
||||
nav: [
|
||||
{text: 'Home', link: '/'},
|
||||
{text: 'Sandbox', link: '/sandbox'},
|
||||
],
|
||||
sidebar: {
|
||||
'/': [
|
||||
{
|
||||
title: 'Getting Started',
|
||||
collapsable: false,
|
||||
children: [
|
||||
['guide/install', 'Installation'],
|
||||
['guide/options', 'Dropdown Options'],
|
||||
['guide/values', 'Selecting Values'],
|
||||
['guide/localization', 'Localization'],
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Digging Deeper',
|
||||
collapsable: false,
|
||||
children: [
|
||||
['guide/templating', 'Templating'],
|
||||
['guide/vuex', 'Vuex'],
|
||||
['guide/ajax', 'AJAX'],
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'API',
|
||||
collapsable: false,
|
||||
children: [
|
||||
['api/props', 'Props'],
|
||||
['api/slots', 'Slots'],
|
||||
['api/events', 'Events'],
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
export default [
|
||||
{
|
||||
title: "Old Man's War",
|
||||
@@ -160,4 +161,4 @@ export default [
|
||||
lastName: "Maine"
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,246 @@
|
||||
/* eslint-disable */
|
||||
export default [
|
||||
'Afghanistan',
|
||||
'Åland Islands',
|
||||
'Albania',
|
||||
'Algeria',
|
||||
'American Samoa',
|
||||
'Andorra',
|
||||
'Angola',
|
||||
'Anguilla',
|
||||
'Antarctica',
|
||||
'Antigua and Barbuda',
|
||||
'Argentina',
|
||||
'Armenia',
|
||||
'Aruba',
|
||||
'Australia',
|
||||
'Austria',
|
||||
'Azerbaijan',
|
||||
'Bahamas',
|
||||
'Bahrain',
|
||||
'Bangladesh',
|
||||
'Barbados',
|
||||
'Belarus',
|
||||
'Belgium',
|
||||
'Belize',
|
||||
'Benin',
|
||||
'Bermuda',
|
||||
'Bhutan',
|
||||
'Bolivia',
|
||||
'Bosnia and Herzegovina',
|
||||
'Botswana',
|
||||
'Bouvet Island',
|
||||
'Brazil',
|
||||
'British Indian Ocean Territory',
|
||||
'Brunei Darussalam',
|
||||
'Bulgaria',
|
||||
'Burkina Faso',
|
||||
'Burundi',
|
||||
'Cambodia',
|
||||
'Cameroon',
|
||||
'Canada',
|
||||
'Cape Verde',
|
||||
'Cayman Islands',
|
||||
'Central African Republic',
|
||||
'Chad',
|
||||
'Chile',
|
||||
'China',
|
||||
'Christmas Island',
|
||||
'Cocos (Keeling) Islands',
|
||||
'Colombia',
|
||||
'Comoros',
|
||||
'Congo',
|
||||
'Congo, The Democratic Republic of The',
|
||||
'Cook Islands',
|
||||
'Costa Rica',
|
||||
'Cote D\'ivoire',
|
||||
'Croatia',
|
||||
'Cuba',
|
||||
'Cyprus',
|
||||
'Czech Republic',
|
||||
'Denmark',
|
||||
'Djibouti',
|
||||
'Dominica',
|
||||
'Dominican Republic',
|
||||
'Ecuador',
|
||||
'Egypt',
|
||||
'El Salvador',
|
||||
'Equatorial Guinea',
|
||||
'Eritrea',
|
||||
'Estonia',
|
||||
'Ethiopia',
|
||||
'Falkland Islands (Malvinas)',
|
||||
'Faroe Islands',
|
||||
'Fiji',
|
||||
'Finland',
|
||||
'France',
|
||||
'French Guiana',
|
||||
'French Polynesia',
|
||||
'French Southern Territories',
|
||||
'Gabon',
|
||||
'Gambia',
|
||||
'Georgia',
|
||||
'Germany',
|
||||
'Ghana',
|
||||
'Gibraltar',
|
||||
'Greece',
|
||||
'Greenland',
|
||||
'Grenada',
|
||||
'Guadeloupe',
|
||||
'Guam',
|
||||
'Guatemala',
|
||||
'Guernsey',
|
||||
'Guinea',
|
||||
'Guinea-bissau',
|
||||
'Guyana',
|
||||
'Haiti',
|
||||
'Heard Island and Mcdonald Islands',
|
||||
'Holy See (Vatican City State)',
|
||||
'Honduras',
|
||||
'Hong Kong',
|
||||
'Hungary',
|
||||
'Iceland',
|
||||
'India',
|
||||
'Indonesia',
|
||||
'Iran, Islamic Republic of',
|
||||
'Iraq',
|
||||
'Ireland',
|
||||
'Isle of Man',
|
||||
'Israel',
|
||||
'Italy',
|
||||
'Jamaica',
|
||||
'Japan',
|
||||
'Jersey',
|
||||
'Jordan',
|
||||
'Kazakhstan',
|
||||
'Kenya',
|
||||
'Kiribati',
|
||||
'Korea, Democratic People\'s Republic of',
|
||||
'Korea, Republic of',
|
||||
'Kuwait',
|
||||
'Kyrgyzstan',
|
||||
'Lao People\'s Democratic Republic',
|
||||
'Latvia',
|
||||
'Lebanon',
|
||||
'Lesotho',
|
||||
'Liberia',
|
||||
'Libyan Arab Jamahiriya',
|
||||
'Liechtenstein',
|
||||
'Lithuania',
|
||||
'Luxembourg',
|
||||
'Macao',
|
||||
'Macedonia, The Former Yugoslav Republic of',
|
||||
'Madagascar',
|
||||
'Malawi',
|
||||
'Malaysia',
|
||||
'Maldives',
|
||||
'Mali',
|
||||
'Malta',
|
||||
'Marshall Islands',
|
||||
'Martinique',
|
||||
'Mauritania',
|
||||
'Mauritius',
|
||||
'Mayotte',
|
||||
'Mexico',
|
||||
'Micronesia, Federated States of',
|
||||
'Moldova, Republic of',
|
||||
'Monaco',
|
||||
'Mongolia',
|
||||
'Montenegro',
|
||||
'Montserrat',
|
||||
'Morocco',
|
||||
'Mozambique',
|
||||
'Myanmar',
|
||||
'Namibia',
|
||||
'Nauru',
|
||||
'Nepal',
|
||||
'Netherlands',
|
||||
'Netherlands Antilles',
|
||||
'New Caledonia',
|
||||
'New Zealand',
|
||||
'Nicaragua',
|
||||
'Niger',
|
||||
'Nigeria',
|
||||
'Niue',
|
||||
'Norfolk Island',
|
||||
'Northern Mariana Islands',
|
||||
'Norway',
|
||||
'Oman',
|
||||
'Pakistan',
|
||||
'Palau',
|
||||
'Palestinian Territory, Occupied',
|
||||
'Panama',
|
||||
'Papua New Guinea',
|
||||
'Paraguay',
|
||||
'Peru',
|
||||
'Philippines',
|
||||
'Pitcairn',
|
||||
'Poland',
|
||||
'Portugal',
|
||||
'Puerto Rico',
|
||||
'Qatar',
|
||||
'Reunion',
|
||||
'Romania',
|
||||
'Russian Federation',
|
||||
'Rwanda',
|
||||
'Saint Helena',
|
||||
'Saint Kitts and Nevis',
|
||||
'Saint Lucia',
|
||||
'Saint Pierre and Miquelon',
|
||||
'Saint Vincent and The Grenadines',
|
||||
'Samoa',
|
||||
'San Marino',
|
||||
'Sao Tome and Principe',
|
||||
'Saudi Arabia',
|
||||
'Senegal',
|
||||
'Serbia',
|
||||
'Seychelles',
|
||||
'Sierra Leone',
|
||||
'Singapore',
|
||||
'Slovakia',
|
||||
'Slovenia',
|
||||
'Solomon Islands',
|
||||
'Somalia',
|
||||
'South Africa',
|
||||
'South Georgia and The South Sandwich Islands',
|
||||
'Spain',
|
||||
'Sri Lanka',
|
||||
'Sudan',
|
||||
'Suriname',
|
||||
'Svalbard and Jan Mayen',
|
||||
'Swaziland',
|
||||
'Sweden',
|
||||
'Switzerland',
|
||||
'Syrian Arab Republic',
|
||||
'Taiwan, Province of China',
|
||||
'Tajikistan',
|
||||
'Tanzania, United Republic of',
|
||||
'Thailand',
|
||||
'Timor-leste',
|
||||
'Togo',
|
||||
'Tokelau',
|
||||
'Tonga',
|
||||
'Trinidad and Tobago',
|
||||
'Tunisia',
|
||||
'Turkey',
|
||||
'Turkmenistan',
|
||||
'Turks and Caicos Islands',
|
||||
'Tuvalu',
|
||||
'Uganda',
|
||||
'Ukraine',
|
||||
'United Arab Emirates',
|
||||
'United Kingdom',
|
||||
'United States',
|
||||
'United States Minor Outlying Islands',
|
||||
'Uruguay',
|
||||
'Uzbekistan',
|
||||
'Vanuatu',
|
||||
'Venezuela',
|
||||
'Viet Nam',
|
||||
'Virgin Islands, British',
|
||||
'Virgin Islands, U.S.',
|
||||
'Wallis and Futuna',
|
||||
'Western Sahara',
|
||||
'Yemen',
|
||||
'Zambia',
|
||||
'Zimbabwe'];
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
export default [
|
||||
{value: "AF", label: "Afghanistan"},
|
||||
{value: "AX", label: "Åland Islands"},
|
||||
@@ -0,0 +1,5 @@
|
||||
import vSelect from '../../src/components/Select';
|
||||
|
||||
export default ({Vue, options, router, siteData}) => {
|
||||
Vue.component('v-select', vSelect);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
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();) o.push(r); else for (n = a.getElementsByTagName('*'), t = new RegExp(
|
||||
'(^|\\s)' + e + '(\\s|$)'), r = 0; r < n.length; r++) t.test(n[r].className) && o.push(n[r]);
|
||||
return o;
|
||||
}), function () {
|
||||
function e () {
|
||||
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();
|
||||
}
|
||||
|
||||
function n (e, n) {
|
||||
if ('string' == typeof e.user) return e.user;
|
||||
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);
|
||||
if (i) return i[2];
|
||||
}
|
||||
return 'anon';
|
||||
}
|
||||
|
||||
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 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 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;});
|
||||
}();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
# Vue Select
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> Everything you wish the HTML `<select>` element could do, wrapped
|
||||
up into a zero dependency, highly extensible Vue component.
|
||||
|
||||
Vue Select is a feature rich select/dropdown/typeahead component. It provides a default
|
||||
template that fits the 80% use case for a select dropdown. Here it is by default:
|
||||
|
||||
<div style="max-width:25rem; margin: 0 auto; padding: 1rem 0;">
|
||||
<country-select />
|
||||
</div>
|
||||
|
||||
If you want to get a quick sense of what vue-select can do, check out
|
||||
[the sandbox](sandbox.md).
|
||||
|
||||
#### Features
|
||||
- Tagging
|
||||
- Filtering/Searching
|
||||
- Vuex Support
|
||||
- AJAX Support
|
||||
- SSR Support
|
||||
- Select Single/Multiple Options
|
||||
- Tested with Bootstrap 3/4, Bulma, Foundation
|
||||
- +95% Test Coverage
|
||||
- ~20kb Total / ~5kb CSS / ~15kb JS
|
||||
- Zero dependencies
|
||||
|
||||
#### Resources
|
||||
- **[CodePen Template](http://codepen.io/sagalbot/pen/NpwrQO)**
|
||||
- **[Trello Roadmap](https://trello.com/b/vWvITNzS/vue-select)**
|
||||
- **[GitHub](https://github.com/sagalbot/vue-select)**
|
||||
@@ -0,0 +1,39 @@
|
||||
## `input`
|
||||
|
||||
Triggered when the selected value changes. Used internally for `v-model`.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param val {Object|String}` - selected option.
|
||||
*/
|
||||
this.$emit("input", val);
|
||||
```
|
||||
|
||||
## `option:created`
|
||||
|
||||
Triggered when `taggable` is `true` and a new option has been created.
|
||||
|
||||
```js
|
||||
/**
|
||||
* @param newOption {Object} - created option
|
||||
*/
|
||||
this.$emit("option:created", newOption);
|
||||
```
|
||||
|
||||
## `search:blur`
|
||||
|
||||
Triggered when the text input loses focus. The dropdown will close immediately before this
|
||||
event is triggered.
|
||||
|
||||
```js
|
||||
this.$emit("search:blur");
|
||||
```
|
||||
|
||||
## `search:focus`
|
||||
|
||||
Triggered when the text input gains focus. The dropdown will open immediately before this
|
||||
event is triggered.
|
||||
|
||||
```js
|
||||
this.$emit("search:focus");
|
||||
```
|
||||
@@ -0,0 +1,359 @@
|
||||
## value
|
||||
|
||||
Contains the currently selected value. Very similar to a
|
||||
`value` attribute on an `<input>`. You can listen for changes
|
||||
using 'change' event using v-on.
|
||||
|
||||
```js
|
||||
value: {
|
||||
default: null
|
||||
},
|
||||
```
|
||||
|
||||
## options
|
||||
|
||||
An array of strings or objects to be used as dropdown choices.
|
||||
If you are using an array of objects, vue-select will look for
|
||||
a `label` key (ex. `[{label: 'Canada', value: 'CA'}]`). A
|
||||
custom label key can be set with the `label` prop.
|
||||
|
||||
```js
|
||||
options: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## disabled
|
||||
|
||||
Disable the entire component.
|
||||
|
||||
```js
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## clearable
|
||||
|
||||
Can the user clear the selected property?
|
||||
|
||||
```js
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
```js
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: "400px"
|
||||
},
|
||||
```
|
||||
|
||||
## searchable
|
||||
|
||||
Enable/disable filtering the options.
|
||||
|
||||
```js
|
||||
searchable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## multiple
|
||||
|
||||
Equivalent to the `multiple` attribute on a `<select>` input.
|
||||
|
||||
```js
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## placeholder
|
||||
|
||||
Equivalent to the `placeholder` attribute on an `<input>`.
|
||||
|
||||
```js
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
```
|
||||
|
||||
## transition
|
||||
|
||||
Sets a Vue transition property on the `.dropdown-menu`. vue-select
|
||||
does not include CSS for transitions, you'll need to add them yourself.
|
||||
|
||||
```js
|
||||
transition: {
|
||||
type: String,
|
||||
default: "fade"
|
||||
},
|
||||
```
|
||||
|
||||
## clearSearchOnSelect
|
||||
|
||||
Enables/disables clearing the search text when an option is selected.
|
||||
|
||||
```js
|
||||
clearSearchOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## closeOnSelect
|
||||
|
||||
Close a dropdown when an option is chosen. Set to false to keep the dropdown
|
||||
open (useful when combined with multi-select, for example)
|
||||
|
||||
```js
|
||||
closeOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## label
|
||||
|
||||
Tells vue-select what key to use when generating option
|
||||
labels when each `option` is an object.
|
||||
|
||||
```js
|
||||
label: {
|
||||
type: String,
|
||||
default: "label"
|
||||
},
|
||||
```
|
||||
|
||||
## index
|
||||
|
||||
Tells vue-select what key to use when generating option
|
||||
values when each `option` is an object.
|
||||
|
||||
```js
|
||||
index: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
```
|
||||
|
||||
## getOptionLabel
|
||||
|
||||
Callback to generate the label text. If `{option}`
|
||||
is an object, returns `option[this.label]` by default.
|
||||
|
||||
Label text is used for filtering comparison and
|
||||
displaying. If you only need to adjust the
|
||||
display, you should use the `option` and
|
||||
`selected-option` slots.
|
||||
|
||||
```js
|
||||
getOptionLabel: {
|
||||
type: Function,
|
||||
default(option) {
|
||||
if (this.index) {
|
||||
option = this.findOptionByIndexValue(option);
|
||||
}
|
||||
|
||||
if (typeof option === "object") {
|
||||
if (!option.hasOwnProperty(this.label)) {
|
||||
return console.warn(
|
||||
`[vue-select warn]: Label key "option.${this.label}" does not` +
|
||||
` exist in options object ${JSON.stringify(option)}.\n` +
|
||||
"http://sagalbot.github.io/vue-select/#ex-labels"
|
||||
);
|
||||
}
|
||||
return option[this.label];
|
||||
}
|
||||
return option;
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## onTab
|
||||
|
||||
Select the current value if `selectOnTab` is enabled
|
||||
|
||||
```js
|
||||
onTab: {
|
||||
type: Function,
|
||||
default: function() {
|
||||
if (this.selectOnTab) {
|
||||
this.typeAheadSelect();
|
||||
}
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## taggable
|
||||
|
||||
Enable/disable creating options from searchInput.
|
||||
|
||||
```js
|
||||
taggable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## tabindex
|
||||
|
||||
Set the tabindex for the input field.
|
||||
|
||||
```js
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
```
|
||||
|
||||
## pushTags
|
||||
|
||||
When true, newly created tags will be added to
|
||||
the options list.
|
||||
|
||||
```js
|
||||
pushTags: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## filterable
|
||||
|
||||
When true, existing options will be filtered
|
||||
by the search text. Should not be used in conjunction
|
||||
with taggable.
|
||||
|
||||
```js
|
||||
filterable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## filterBy
|
||||
|
||||
Callback to determine if the provided option should
|
||||
match the current search text. Used to determine
|
||||
if the option should be displayed.
|
||||
|
||||
```js
|
||||
filterBy: {
|
||||
type: Function,
|
||||
default(option, label, search) {
|
||||
return (label | "").toLowerCase().indexOf(search.toLowerCase()) > -1;
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## filter
|
||||
|
||||
Callback to filter results when search text
|
||||
is provided. Default implementation loops
|
||||
each option, and returns the result of
|
||||
this.filterBy.
|
||||
|
||||
```js
|
||||
filter: {
|
||||
type: Function,
|
||||
default(options, search) {
|
||||
return options.filter(option => {
|
||||
let label = this.getOptionLabel(option);
|
||||
if (typeof label === "number") {
|
||||
label = label.toString();
|
||||
}
|
||||
return this.filterBy(option, label, search);
|
||||
});
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## createOption
|
||||
|
||||
User defined function for adding Options
|
||||
|
||||
```js
|
||||
createOption: {
|
||||
type: Function,
|
||||
default(newOption) {
|
||||
if (typeof this.optionList[0] === "object") {
|
||||
newOption = { [this.label]: newOption };
|
||||
}
|
||||
this.$emit("option:created", newOption);
|
||||
return newOption;
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
## resetOnOptionsChange
|
||||
|
||||
When false, updating the options will not reset the select value
|
||||
|
||||
```js
|
||||
resetOnOptionsChange: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## noDrop
|
||||
|
||||
Disable the dropdown entirely.
|
||||
|
||||
```js
|
||||
noDrop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
## inputId
|
||||
|
||||
Sets the id of the input element.
|
||||
|
||||
```js
|
||||
inputId: {
|
||||
type: String
|
||||
},
|
||||
```
|
||||
|
||||
## dir
|
||||
|
||||
Sets RTL support. Accepts `ltr`, `rtl`, `auto`.
|
||||
|
||||
```js
|
||||
dir: {
|
||||
type: String,
|
||||
default: "auto"
|
||||
},
|
||||
```
|
||||
|
||||
## selectOnTab
|
||||
|
||||
When true, hitting the 'tab' key will select the current select value
|
||||
|
||||
```js
|
||||
selectOnTab: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
::: tip
|
||||
VueSelect leverages scoped slots to allow for total customization of the presentation layer.
|
||||
Slots can be used to change the look and feel of the UI, or to simply swap out text.
|
||||
:::
|
||||
|
||||
## Selected Option(s)
|
||||
|
||||
### `selected-option`
|
||||
|
||||
#### Scope:
|
||||
|
||||
- `option {Object}` - A selected option
|
||||
|
||||
```html
|
||||
<slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||
{{ getOptionLabel(option) }}
|
||||
</slot>
|
||||
```
|
||||
|
||||
### `selected-option-container`
|
||||
|
||||
#### Scope:
|
||||
|
||||
- `option {Object}` - A selected option
|
||||
- `deselect {Function}` - Method used to deselect a given option when `multiple` is true
|
||||
- `disabled {Boolean}` - Determine if the component is disabled
|
||||
- `multiple {Boolean}` - If the component supports the selection of multiple values
|
||||
|
||||
```html
|
||||
<slot v-for="option in valueAsArray" name="selected-option-container"
|
||||
:option="(typeof option === 'object')?option:{[label]: option}" :deselect="deselect" :multiple="multiple" :disabled="disabled">
|
||||
<span class="selected-tag" v-bind:key="option.index">
|
||||
<slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||
{{ getOptionLabel(option) }}
|
||||
</slot>
|
||||
<button v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="close" aria-label="Remove option">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</span>
|
||||
</slot>
|
||||
```
|
||||
|
||||
## Component Actions
|
||||
|
||||
### `spinner`
|
||||
|
||||
```html
|
||||
<slot name="spinner">
|
||||
<div class="spinner" v-show="mutableLoading">Loading...</div>
|
||||
</slot>
|
||||
```
|
||||
|
||||
## Dropdown
|
||||
|
||||
### `option`
|
||||
|
||||
#### Scope:
|
||||
|
||||
- `option {Object}` - The currently iterated option from `filteredOptions`
|
||||
|
||||
```html
|
||||
<slot name="option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||
{{ getOptionLabel(option) }}
|
||||
</slot>
|
||||
```
|
||||
@@ -1,60 +0,0 @@
|
||||
## AJAX Remote Option Loading
|
||||
|
||||
[](codepen://sagalbot/POMeOX?height=400)
|
||||
|
||||
The `onSearch` prop allows you to load options via ajax in a parent component
|
||||
when the search text is updated. It is invoked with two parameters, `search` & `loading`.
|
||||
|
||||
```js
|
||||
/**
|
||||
* Accepts a callback function that will be run
|
||||
* when the search text changes. The callback
|
||||
* will be invoked with these parameters:
|
||||
*
|
||||
* @param {search} String Current search text
|
||||
* @param {loading} Function Toggle loading class
|
||||
*/
|
||||
onSearch: {
|
||||
type: Function,
|
||||
default: false
|
||||
},
|
||||
```
|
||||
|
||||
The `loading` function accepts a boolean parameter that will be assigned
|
||||
to the vue-select internal `loading` property. Call `loading(true)` to set the
|
||||
`loading` property to `true` - toggling the loading spinner. After your
|
||||
asynchronous operation completes, call `loading(false)` to toggle it off.
|
||||
|
||||
#### Disabling Filtering
|
||||
|
||||
When loading server side options, it can be useful to disable the
|
||||
client side filtering. Use the `filterable` prop to disable filtering.
|
||||
|
||||
```js
|
||||
/**
|
||||
* When true, existing options will be filtered
|
||||
* by the search text. Should not be used in
|
||||
* conjunction with taggable.
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
filterable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
#### Loading Spinner
|
||||
|
||||
Vue Select includes a default loading spinner that appears when the loading class is present. The `spinner` slot allows you to implement your own spinner.
|
||||
|
||||
```html
|
||||
<div class="spinner" v-show="spinner">Loading...</div>
|
||||
```
|
||||
|
||||
#### Library Agnostic
|
||||
|
||||
Since Vue.js does not ship with ajax functionality as part of the core library, it's up to you to process the ajax requests in your parent component.
|
||||
|
||||
I recommend using [axios](https://github.com/axios/axios) for creating your applications HTTP layer,
|
||||
or [`fetch()`](https://github.com/github/fetch) for simple requests.
|
||||
@@ -1 +0,0 @@
|
||||
[](codepen://sagalbot/zZQJKW?height=600)
|
||||
@@ -1,311 +0,0 @@
|
||||
## Select
|
||||
|
||||
```js
|
||||
/**
|
||||
* Contains the currently selected value. Very similar to a
|
||||
* `value` attribute on an <input>. You can listen for changes
|
||||
* using 'change' event using v-on
|
||||
* @type {Object||String||null}
|
||||
*/
|
||||
value: {
|
||||
default: null
|
||||
},
|
||||
|
||||
/**
|
||||
* An array of strings or objects to be used as dropdown choices.
|
||||
* If you are using an array of objects, vue-select will look for
|
||||
* a `label` key (ex. [{label: 'This is Foo', value: 'foo'}]). A
|
||||
* custom label key can be set with the `label` prop.
|
||||
* @type {Array}
|
||||
*/
|
||||
options: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable the entire component.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Value of the 'autocomplete' field of the input
|
||||
* element.
|
||||
* @type {String}
|
||||
*/
|
||||
autocomplete: {
|
||||
type: String,
|
||||
default: 'off'
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the max-height property on the dropdown list.
|
||||
* @deprecated
|
||||
* @type {String}
|
||||
*/
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: '400px'
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable/disable filtering the options.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
searchable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Equivalent to the `multiple` attribute on a `<select>` input.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Equivalent to the `placeholder` attribute on an `<input>`.
|
||||
* @type {String}
|
||||
*/
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a Vue transition property on the `.dropdown-menu`. vue-select
|
||||
* does not include CSS for transitions, you'll need to add them yourself.
|
||||
* @type {String}
|
||||
*/
|
||||
transition: {
|
||||
type: String,
|
||||
default: 'fade'
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/disables clearing the search text when an option is selected.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
clearSearchOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables/disables allowing the user to clear the selected property.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
clearable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Close a dropdown when an option is chosen. Set to false to keep the dropdown
|
||||
* open (useful when combined with multi-select, for example)
|
||||
* @type {Boolean}
|
||||
*/
|
||||
closeOnSelect: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Tells vue-select what key to use when generating option
|
||||
* labels when each `option` is an object.
|
||||
* @type {String}
|
||||
*/
|
||||
label: {
|
||||
type: String,
|
||||
default: 'label'
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback to generate the label text. If {option}
|
||||
* is an object, returns option[this.label] by default.
|
||||
* @type {Function}
|
||||
* @param {Object || String} option
|
||||
* @return {String}
|
||||
*/
|
||||
getOptionLabel: {
|
||||
type: Function,
|
||||
default(option) {
|
||||
if (typeof option === 'object') {
|
||||
if (!option.hasOwnProperty(this.label)) {
|
||||
return console.warn(
|
||||
`[vue-select warn]: Label key "option.${this.label}" does not` +
|
||||
` exist in options object ${JSON.stringify(option)}.\n` +
|
||||
'http://sagalbot.github.io/vue-select/#ex-labels'
|
||||
)
|
||||
}
|
||||
if (this.label && option[this.label]) {
|
||||
return option[this.label]
|
||||
}
|
||||
}
|
||||
return option;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback to determine if the provided option should
|
||||
* match the current search text. Used to determine
|
||||
* if the option should be displayed.
|
||||
* @type {Function}
|
||||
* @param {Object || String} option
|
||||
* @param {String} label
|
||||
* @param {String} search
|
||||
* @return {Boolean}
|
||||
*/
|
||||
filterBy: {
|
||||
type: Function,
|
||||
default(option, label, search) {
|
||||
return (label || '').toLowerCase().indexOf(search.toLowerCase()) > -1
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* An optional callback function that is called each time the selected
|
||||
* value(s) change. When integrating with Vuex, use this callback to trigger
|
||||
* an action, rather than using :value.sync to retreive the selected value.
|
||||
* @type {Function}
|
||||
* @param {Object || String} val
|
||||
*/
|
||||
onChange: {
|
||||
type: Function,
|
||||
default: function (val) {
|
||||
this.$emit('input', val)
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable/disable creating options from searchInput.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
taggable: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Set the tabindex for the input field.
|
||||
* @type {Number}
|
||||
*/
|
||||
tabindex: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
|
||||
/**
|
||||
* When true, newly created tags will be added to
|
||||
* the options list.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
pushTags: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* When true, existing options will be filtered
|
||||
* by the search text. Should not be used in conjunction
|
||||
* with taggable.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
filterable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* User defined function for adding Options
|
||||
* @type {Function}
|
||||
*/
|
||||
createOption: {
|
||||
type: Function,
|
||||
default(newOption) {
|
||||
if (typeof this.mutableOptions[0] === 'object') {
|
||||
newOption = {[this.label]: newOption}
|
||||
}
|
||||
this.$emit('option:created', newOption)
|
||||
return newOption
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* When false, updating the options will not reset the select value
|
||||
* @type {Boolean}
|
||||
*/
|
||||
resetOnOptionsChange: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Disable the dropdown entirely.
|
||||
* @type {Boolean}
|
||||
*/
|
||||
noDrop: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the id of the input element.
|
||||
* @type {String}
|
||||
* @default {null}
|
||||
*/
|
||||
inputId: {
|
||||
type: String
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets RTL support. Accepts 'ltr', 'rtl', 'auto'.
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir
|
||||
* @type {String}
|
||||
* @default 'auto'
|
||||
*/
|
||||
dir: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
},
|
||||
```
|
||||
|
||||
## AJAX
|
||||
|
||||
```js
|
||||
/**
|
||||
* Toggles the adding of a 'loading' class to the main
|
||||
* .v-select wrapper. Useful to control UI state when
|
||||
* results are being processed through AJAX.
|
||||
*/
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Accept a callback function that will be
|
||||
* run when the search text changes.
|
||||
*
|
||||
* loading() accepts a boolean value, and can
|
||||
* be used to toggle a loading class from
|
||||
* the onSearch callback.
|
||||
*
|
||||
* @param {search} String Current search text
|
||||
* @param {loading} Function(bool) Toggle loading class
|
||||
*/
|
||||
onSearch: {
|
||||
type: Function,
|
||||
default: function(search, loading){}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
name,type
|
||||
value,Object||String||null
|
||||
options,Array
|
||||
disabled,Boolean
|
||||
maxHeight,String
|
||||
searchable,Boolean
|
||||
multiple,Boolean
|
||||
placeholder,String
|
||||
transition,String
|
||||
clearSearchOnSelect,Boolean
|
||||
closeOnSelect,Boolean
|
||||
label,String
|
||||
getOptionLabel,Function
|
||||
filterFunction,Function
|
||||
filter,Function
|
||||
onChange,Function
|
||||
taggable,Boolean
|
||||
tabindex,Number
|
||||
pushTags,Boolean
|
||||
filterable,Boolean
|
||||
createOption,Function
|
||||
resetOnOptionsChange,Boolean
|
||||
noDrop,Boolean
|
||||
inputId,String
|
||||
dir,String
|
||||
|
@@ -1 +0,0 @@
|
||||
## Getting Started
|
||||
@@ -1,59 +0,0 @@
|
||||
## Dropdown Options {#options}
|
||||
|
||||
`vue-select` accepts arrays of strings or objects to use as options through the `options` prop:
|
||||
|
||||
```html
|
||||
<v-select :options="['foo','bar']"></v-select>
|
||||
```
|
||||
|
||||
When provided an array of objects, `vue-select` will display a single value of the object. By default, `vue-select` will look for a key named `label` on the object to use as display text.
|
||||
|
||||
```html
|
||||
<v-select :options="[{label: 'foo', value: 'Foo'}]"></v-select>
|
||||
```
|
||||
|
||||
### Option Labels {#labels}
|
||||
|
||||
When the `options` array contains objects, `vue-select` looks for the `label` key to display by default. You can set your own label to match your source data using the `label` prop.
|
||||
|
||||
For example, consider an object with `countryCode` and `countryName` properties:
|
||||
|
||||
```json
|
||||
{
|
||||
countryCode: "CA",
|
||||
countryName: "Canada"
|
||||
}
|
||||
```
|
||||
|
||||
If you wanted to display `Canada` in the dropdown, you'd use the `countryName` key:
|
||||
|
||||
```html
|
||||
<v-select label="countryName" :options="countries"></v-select>
|
||||
```
|
||||
|
||||
[](codepen://sagalbot/aEjLPB?height=500)
|
||||
|
||||
|
||||
### Option index {#values}
|
||||
|
||||
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:
|
||||
|
||||
```json
|
||||
{
|
||||
value: "CA",
|
||||
label: "Canada"
|
||||
}
|
||||
```
|
||||
|
||||
If you wanted to return `CA` in the dropdown when `Canada` is selected, you'd use the `index` key:
|
||||
|
||||
```html
|
||||
<v-select index="value" :options="countries"></v-select>
|
||||
```
|
||||
|
||||
|
||||
### Null / Empty Options {#null}
|
||||
|
||||
`vue-select` requires the `option` property to be an `array`. If you are using Vue in development mode, you will get warnings attempting to pass anything other than an `array` to the `options` prop. If you need a `null`/`empty` value, use an empty array `[]`.
|
||||
@@ -1,38 +0,0 @@
|
||||
## Selecting Values {#single}
|
||||
|
||||
The most common use case for `vue-select` is to have the chosen value synced with a parent component. `vue-select` takes advantage of the `v-model` syntax to sync values with a parent.
|
||||
|
||||
```html
|
||||
<v-select v-model="selected"></v-select>
|
||||
```
|
||||
|
||||
[](codepen://sagalbot/Kqxbjw?height=250)
|
||||
|
||||
If you don't require the `value` to be synced, you can also pass the prop directly:
|
||||
|
||||
```html
|
||||
<v-select :value="selected"></v-select>
|
||||
```
|
||||
|
||||
This method allows you to pre-select a value(s), without syncing any changes to the parent component. This is also very useful when using a state management tool, like Vuex.
|
||||
|
||||
### Single/Multiple Selection {#multiple}
|
||||
|
||||
By default, `vue-select` supports choosing a single value. If you need multiple values, use the `multiple` prop:
|
||||
|
||||
```html
|
||||
<v-select multiple v-model="selected"></v-select>
|
||||
```
|
||||
|
||||
[](codepen://sagalbot/opMGro?height=250)
|
||||
|
||||
### Tagging {#tagging}
|
||||
|
||||
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.
|
||||
|
||||
```html
|
||||
<v-select taggable></v-select>
|
||||
```
|
||||
|
||||
[](codepen://sagalbot/XVoWxm?height=350)
|
||||
@@ -1,43 +0,0 @@
|
||||
## Vue Compatibility
|
||||
- `vue ~2.0` use `vue-select ~2.0`
|
||||
- `vue ~1.0` use `vue-select ~1.0`
|
||||
|
||||
## Yarn / NPM
|
||||
Install with yarn:
|
||||
```bash
|
||||
yarn add vue-select
|
||||
```
|
||||
or, using NPM:
|
||||
```
|
||||
npm install vue-select
|
||||
```
|
||||
|
||||
Then, import and register the component:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
Vue.component('v-select', vSelect)
|
||||
```
|
||||
|
||||
## CDN
|
||||
|
||||
Include `vue` & `vue-select.js` - I recommend using [unpkg.com](https://unpkg.com/#/).
|
||||
|
||||
```html
|
||||
<!-- include VueJS first -->
|
||||
<script src="https://unpkg.com/vue@latest"></script>
|
||||
|
||||
<!-- use the latest release -->
|
||||
<script src="https://unpkg.com/vue-select@latest"></script>
|
||||
<!-- or point to a specific release -->
|
||||
<script src="https://unpkg.com/vue-select@1.30"></script>
|
||||
```
|
||||
Then register the component in your javascript:
|
||||
|
||||
```js
|
||||
Vue.component('v-select', VueSelect.VueSelect);
|
||||
```
|
||||
|
||||
[](codepen://sagalbot/dJjzeP)
|
||||
@@ -1,25 +0,0 @@
|
||||
# vue-select
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> A Vue.js select component that provides similar functionality to Select2 without the overhead of jQuery.
|
||||
|
||||
#### Features
|
||||
- AJAX Support
|
||||
- Tagging
|
||||
- List Filtering/Searching
|
||||
- Supports Vuex
|
||||
- Select Single/Multiple Options
|
||||
- Tested with Bootstrap 3/4, Bulma, Foundation
|
||||
- +95% Test Coverage
|
||||
- ~33kb minified with CSS
|
||||
- Zero dependencies
|
||||
|
||||
#### Resources
|
||||
- **[CodePen Template](http://codepen.io/sagalbot/pen/NpwrQO)**
|
||||
- **[Trello Roadmap](https://trello.com/b/vWvITNzS/vue-select)**
|
||||
- **[GitHub](https://github.com/sagalbot/vue-select)**
|
||||
@@ -1,21 +0,0 @@
|
||||
# Summary
|
||||
|
||||
- Getting Started
|
||||
- [Installation](Install.md)
|
||||
- [Dropdown Options](Basics/Options.md)
|
||||
- [Option Labels](Basics/Options.md#labels)
|
||||
- [Null Options](Basics/Options.md#null)
|
||||
- [Selecting Values](Basics/Values.md#values)
|
||||
- [Single](Basics/Values.md#single)
|
||||
- [Multiple](Basics/Values.md#multiple)
|
||||
- [Tagging](Basics/Values.md#tagging)
|
||||
- [Localization](Basics/Localization.md)
|
||||
|
||||
- Digging Deeper
|
||||
- [Templating](Advanced/Templating.md)
|
||||
- [Vuex](Advanced/Vuex.md)
|
||||
- [AJAX](Advanced/Ajax.md)
|
||||
- [Examples](Examples.md)
|
||||
|
||||
- API
|
||||
- [Props](Api/Props.md)
|
||||
@@ -1,228 +0,0 @@
|
||||
@import url('https://fonts.googleapis.com/css?family=Roboto+Mono|Source+Sans+Pro:300,400,600');
|
||||
|
||||
body {
|
||||
letter-spacing: 0;
|
||||
color: #34495e;
|
||||
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
||||
font-size: 15px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #34495e;
|
||||
background-color: #fff;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* LANGS.md index page */
|
||||
.book-langs-index {
|
||||
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
.book-langs-index .inner .languages {
|
||||
padding: 20px 0px;
|
||||
}
|
||||
.book-langs-index .inner .languages li {
|
||||
float: none;
|
||||
}
|
||||
li a {
|
||||
color: #42b983;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* set correct fonts on sidebar and main page */
|
||||
.book .book-body .page-wrapper .page-inner section.normal, .book-summary { font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif; }
|
||||
|
||||
/* sidebar */
|
||||
.book-summary ul.summary li a,
|
||||
.book-summary ul.summary li span {
|
||||
color: #7f8c8d;
|
||||
font-family: 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
.book .book-summary ul.summary li span {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.book-summary ul.summary li.active>a {
|
||||
color: #42b983;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
#book-search-input { background-color: #fafafa; }
|
||||
.book-summary { background-color: #fff; }
|
||||
|
||||
/* markdown content found on pages */
|
||||
.markdown-section h1,
|
||||
.markdown-section h2,
|
||||
.markdown-section h3,
|
||||
.markdown-section h4,
|
||||
.markdown-section strong {
|
||||
font-weight: 600;
|
||||
color: #2c3e50;
|
||||
}
|
||||
.markdown-section a {
|
||||
color: #42b983;
|
||||
font-weight: 600;
|
||||
}
|
||||
.markdown-section p,
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
word-spacing: 0.05em;
|
||||
}
|
||||
.markdown-section em {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
|
||||
.markdown-section pre {
|
||||
padding: 1.2em 1.4em;
|
||||
line-height: 1.5em;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown-section code, .markdown-section pre {
|
||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
||||
-webkit-font-smoothing: initial;
|
||||
-moz-osx-font-smoothing: initial;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
code span.css,
|
||||
code span.javascript,
|
||||
code span.html,
|
||||
span[class^="hljs-"] {
|
||||
-webkit-font-smoothing: initial;
|
||||
-moz-osx-font-smoothing: initial;
|
||||
}
|
||||
.markdown-section pre>code {
|
||||
font-size: 0.8em;
|
||||
display: block;
|
||||
}
|
||||
.markdown-section code:after, .markdown-section code:before {
|
||||
content: none;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
code, pre {
|
||||
font-family: 'Roboto Mono', Monaco, courier, monospace;
|
||||
font-size: 0.8em;
|
||||
background-color: #f8f8f8;
|
||||
-webkit-font-smoothing: initial;
|
||||
-moz-osx-font-smoothing: initial;
|
||||
}
|
||||
code {
|
||||
color: #e96900;
|
||||
padding: 3px 5px;
|
||||
margin: 0 2px;
|
||||
border-radius: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
code .token {
|
||||
min-height: 1.5em;
|
||||
-webkit-font-smoothing: initial;
|
||||
-moz-osx-font-smoothing: initial;
|
||||
}
|
||||
pre code { position: relative; }
|
||||
pre code.lang-html:after,
|
||||
pre code.lang-js:after,
|
||||
pre code.lang-bash:after,
|
||||
pre code.lang-css:after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
color: #ccc;
|
||||
text-align: right;
|
||||
font-size: 0.75em;
|
||||
padding: 5px 10px 0;
|
||||
line-height: 15px;
|
||||
height: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
pre code.lang-html:after {
|
||||
content: 'HTML';
|
||||
}
|
||||
pre code.lang-js:after {
|
||||
content: 'JS';
|
||||
}
|
||||
pre code.lang-bash:after {
|
||||
content: 'Shell';
|
||||
}
|
||||
pre code.lang-css:after {
|
||||
content: 'CSS';
|
||||
}
|
||||
.content img {
|
||||
max-width: 100%;
|
||||
}
|
||||
.content span.light {
|
||||
color: #7f8c8d;
|
||||
}
|
||||
.content span.info {
|
||||
font-size: 0.85em;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 280px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.markdown-section h1 {
|
||||
margin: 0 0 1em;
|
||||
}
|
||||
.markdown-section h2 {
|
||||
margin: 45px 0 0.8em;
|
||||
padding-bottom: 0.7em;
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
.markdown-section h3 {
|
||||
margin: 52px 0 1.2em;
|
||||
}
|
||||
.markdown-section figure,
|
||||
.markdown-section p,
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
margin: 1.2em 0;
|
||||
}
|
||||
.markdown-section p,
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
line-height: 1.6em;
|
||||
}
|
||||
.markdown-section ul,
|
||||
.markdown-section ol {
|
||||
padding-left: 1.5em;
|
||||
}
|
||||
.markdown-section a {
|
||||
color: #42b983;
|
||||
font-weight: 600;
|
||||
}
|
||||
.markdown-section blockquote {
|
||||
margin: 2em 0;
|
||||
padding-left: 20px;
|
||||
border-left: 4px solid #42b983;
|
||||
}
|
||||
.markdown-section blockquote p {
|
||||
font-weight: 600;
|
||||
margin-left: 0;
|
||||
}
|
||||
.markdown-section iframe {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
/* these aren't in gitbook at the moment, but leaving them in for future reference */
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
.highlight {
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
background-color: #f8f8f8;
|
||||
padding: 0.8em 0.8em 0.4em;
|
||||
line-height: 1.1em;
|
||||
border-radius: 2px;
|
||||
}
|
||||
.highlight table,
|
||||
.highlight tr,
|
||||
.highlight td {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.highlight .gutter {
|
||||
width: 1.5em;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
## Loading Options with AJAX
|
||||
|
||||
The `search` event provides a hook to load options from a parent component
|
||||
when the search text is updated. It is emitted with two parameters:
|
||||
|
||||
**Search Event Parameters**
|
||||
- `search {String}` The current search string
|
||||
- `loading {Function}` Accepts a boolean parameter to toggle the loading state
|
||||
|
||||
```html
|
||||
<v-select @search="fetchOptions" />
|
||||
```
|
||||
|
||||
```js
|
||||
/**
|
||||
* Triggered when the search text changes.
|
||||
*
|
||||
* @param search {String} Current search text
|
||||
* @param loading {Function} Toggle loading class
|
||||
*/
|
||||
fetchOptions (search, loading) {
|
||||
// ... do some asynchronous stuff!
|
||||
},
|
||||
```
|
||||
|
||||
The `loading` function accepts a boolean parameter that will be assigned
|
||||
to the vue-select internal `loading` property. Call `loading(true)` to set the
|
||||
`loading` property to `true` - toggling the loading spinner. After your
|
||||
asynchronous operation completes, call `loading(false)` to toggle it off.
|
||||
|
||||
## Disabling Filtering
|
||||
|
||||
When loading server side options, it can be useful to disable the
|
||||
client side filtering. Use the `filterable` prop to disable filtering.
|
||||
|
||||
```js
|
||||
/**
|
||||
* When true, existing options will be filtered
|
||||
* by the search text. Should not be used in
|
||||
* conjunction with taggable.
|
||||
*
|
||||
* @type {Boolean}
|
||||
*/
|
||||
filterable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
```
|
||||
|
||||
## Loading Spinner
|
||||
|
||||
Vue Select includes a default loading spinner that appears when the loading class is present. The
|
||||
`spinner` slot allows you to implement your own spinner.
|
||||
|
||||
```html
|
||||
<div class="spinner" v-show="spinner">Loading...</div>
|
||||
```
|
||||
|
||||
## Library Agnostic
|
||||
|
||||
Since Vue.js does not ship with ajax functionality as part of the core library, it's up to you to
|
||||
process the ajax requests in your parent component.
|
||||
|
||||
I recommend using [axios](https://github.com/axios/axios) for creating your applications HTTP layer,
|
||||
or [`fetch()`](https://github.com/github/fetch) for simple requests.
|
||||
|
||||
## Example
|
||||
|
||||
The [codepen example](https://codepen.io/sagalbot/pen/POMeOX) wraps up all the above concepts and
|
||||
searches GitHub repositories. It also uses scoped slots to add some custom templating.
|
||||
|
||||
<CodePen url="POMeOX" height="400"/>
|
||||
@@ -0,0 +1,60 @@
|
||||
## Yarn / NPM
|
||||
Install with yarn:
|
||||
```bash
|
||||
yarn add vue-select
|
||||
|
||||
# or, using NPM
|
||||
npm install vue-select
|
||||
```
|
||||
|
||||
Then, import and register the component:
|
||||
|
||||
```js
|
||||
import Vue from 'vue'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
Vue.component('v-select', vSelect)
|
||||
```
|
||||
|
||||
The component itself does not include any CSS. You'll need to include it separately:
|
||||
|
||||
```js
|
||||
import 'vue-select/dist/vue-select.css';
|
||||
```
|
||||
|
||||
Alternatively, you can import the scss for complete control of the component styles:
|
||||
|
||||
```scss
|
||||
@import "vue-select/src/scss/vue-select.scss";
|
||||
```
|
||||
|
||||
## In the Browser
|
||||
|
||||
vue-select ships as an UMD module that is accessible in the browser. When loaded
|
||||
in the browser, you can access the component through the `VueSelect.VueSelect`
|
||||
global variable. You'll need to load Vue.js, vue-select JS & vue-select CSS.
|
||||
|
||||
```html
|
||||
<!-- include VueJS first -->
|
||||
<script src="https://unpkg.com/vue@latest"></script>
|
||||
|
||||
<!-- use the latest vue-select release -->
|
||||
<script src="https://unpkg.com/vue-select@latest"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/vue-select@latest/dist/vue-select.css">
|
||||
|
||||
<!-- or point to a specific vue-select release -->
|
||||
<script src="https://unpkg.com/vue-select@2.6.0"></script>
|
||||
<link rel="stylesheet" href="https://unpkg.com/vue-select@2.6.0/dist/vue-select.css">
|
||||
```
|
||||
Then register the component in your javascript:
|
||||
|
||||
```js
|
||||
Vue.component('v-select', VueSelect.VueSelect);
|
||||
```
|
||||
|
||||
<CodePen url="dJjzeP" />
|
||||
|
||||
## Vue Compatibility
|
||||
|
||||
If you're on Vue `1.x`, use vue-select `1.x`. The `1.x` branch has not received updates
|
||||
since the 2.0 release.
|
||||
@@ -1,4 +1,4 @@
|
||||
### RTL
|
||||
## RTL
|
||||
|
||||
vue-select supports RTL using the standard HTML API using the `dir` attribute.
|
||||
|
||||
@@ -8,11 +8,11 @@ vue-select supports RTL using the standard HTML API using the `dir` attribute.
|
||||
|
||||
The `dir` attribute accepts the same values as the [HTML spec](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/dir): `rtl`,`ltr`, and `auto`.
|
||||
|
||||
### Component Text
|
||||
## Component Text
|
||||
|
||||
All of the text within the component has been wrapped within [slots](https://vuejs.org/v2/guide/components.html#Content-Distribution-with-Slots) and can be replaced in your app.
|
||||
|
||||
##### Loading Spinner
|
||||
### Loading Spinner
|
||||
*Slot Definition:*
|
||||
```html
|
||||
<slot name="spinner">
|
||||
@@ -26,7 +26,7 @@ All of the text within the component has been wrapped within [slots](https://vue
|
||||
</v-select>
|
||||
```
|
||||
|
||||
##### No Options Text
|
||||
### No Options Text
|
||||
*Slot Definition:*
|
||||
```html
|
||||
<slot name="no-options">Sorry, no matching options.</slot>
|
||||
@@ -38,6 +38,4 @@ All of the text within the component has been wrapped within [slots](https://vue
|
||||
</v-select>
|
||||
```
|
||||
|
||||
For a full list of component slots, view the [slots API docs](Api/Slots.md).
|
||||
|
||||
[](codepen://sagalbot/oZmLVN?height=250)
|
||||
For a full list of component slots, view the [slots API docs](../api/slots.md).
|
||||
@@ -0,0 +1,54 @@
|
||||
## Options Prop
|
||||
|
||||
`vue-select` accepts arrays of primitive values or objects to use as options through the `options` prop:
|
||||
|
||||
```html
|
||||
<!-- array of strings or numbers -->
|
||||
<v-select :options="['Canada', 'United States']"></v-select>
|
||||
```
|
||||
|
||||
<v-select :options="['Canada', 'United States']"></v-select>
|
||||
|
||||
```html
|
||||
<!-- or, an array of objects -->
|
||||
<v-select :options="[{label: 'Canada', code: 'ca'}]"></v-select>
|
||||
```
|
||||
|
||||
<v-select :options="[{label: 'Canada', code: 'ca'}]"></v-select>
|
||||
|
||||
## Option Labels
|
||||
|
||||
#### Options as Primitives (strings, numbers, boolean)
|
||||
|
||||
When `options` contains strings or numbers, they'll be used as the label for the option within the
|
||||
component. No further configuration is necessary.
|
||||
|
||||
#### Options as Objects
|
||||
|
||||
When `options` is an array of objects, the component must generate a label to be shown as the
|
||||
options text. By default, `vue-select` will attempt to render `option.label` as the option label.
|
||||
You might not have a `label` key in your objects, so you can set your own label to match your
|
||||
source data using the `label {String}` prop.
|
||||
|
||||
For example, consider an object with `countryCode` and `countryName` properties:
|
||||
|
||||
```json
|
||||
{
|
||||
countryCode: "CA",
|
||||
countryName: "Canada"
|
||||
}
|
||||
```
|
||||
|
||||
If you wanted to display `Canada` in the dropdown, you'd use the `countryName` key:
|
||||
|
||||
```html
|
||||
<v-select label="countryName" :options="countries"></v-select>
|
||||
```
|
||||
|
||||
<country-select />
|
||||
|
||||
## Null / Empty Options
|
||||
|
||||
`vue-select` requires the `options` prop to be an `array`. If you are using Vue in development
|
||||
mode, you will get warnings attempting to pass anything other than an `array` to the `options` prop.
|
||||
If you need a `null`/`empty` value, use an empty array `[]`.
|
||||
@@ -14,4 +14,4 @@ vue-select provides the scoped `option` slot in order to create custom dropdown
|
||||
Using the `option` slot with `slot-scope="option"` gives the
|
||||
provides the current option variable to the template.
|
||||
|
||||
[](codepen://sagalbot/NXBwYG?height=500)
|
||||
<CodePen url="NXBwYG" height="500"/>
|
||||
@@ -0,0 +1,176 @@
|
||||
## Getting and Setting
|
||||
|
||||
### `v-model`
|
||||
|
||||
The most common use case for vue-select is to have the chosen value synced with a parent component. vue-select
|
||||
takes advantage of the `v-model` syntax to sync values with a parent. The `v-model` syntax works with
|
||||
primitives and objects.
|
||||
|
||||
```html
|
||||
<v-select v-model="selected" />
|
||||
```
|
||||
|
||||
Note that when using the `multiple` prop, the `v-model` value will always be an array.
|
||||
|
||||
### Props and Events
|
||||
|
||||
Sometimes `v-model` might not fit your use case. For example, when working with [Vuex](https://vuex.vuejs.org),
|
||||
you'll need to trigger a mutation rather than mutating a value directly. In that case, maybe you need
|
||||
to bind a pre-selected value, and trigger a mutation when it changes.
|
||||
|
||||
vue-select exposes the `value` prop and an `input` event to enable this. This combo of props and
|
||||
events is also how Vue wires up the `v-model` syntax internally.
|
||||
|
||||
#### Prop: `value`
|
||||
|
||||
The `value` prop lets vue-select know what value is currently selected. It will accept strings,
|
||||
numbers or objects. If you're using a `multiple` v-select, you'll want to pass an array.
|
||||
|
||||
```html
|
||||
<v-select :value="selected" />
|
||||
```
|
||||
|
||||
::: tip 🤓
|
||||
Anytime you bind the `value` prop directly, you're responsible for updating the bound variable
|
||||
in your code using the `@input` event.
|
||||
:::
|
||||
|
||||
#### Event: `input`
|
||||
|
||||
The `input` event is triggered anytime the value state changes, and is emitted with the `value`
|
||||
state as it's only parameter.
|
||||
|
||||
#### Vuex Support
|
||||
|
||||
The `value` prop and `emit` event are very useful when using a state management tool, like Vuex.
|
||||
You can bind the selected value with `:value="$store.myValue"`, and use the `input` event to
|
||||
trigger a mutation, or dispatch an action – or anything else you might need to do when the selection
|
||||
changes.
|
||||
|
||||
```html
|
||||
<v-select :value="$store.myValue" @input="setSelected" />
|
||||
```
|
||||
|
||||
```js
|
||||
methods: {
|
||||
setSelected(value) {
|
||||
// trigger a mutation, or dispatch an action
|
||||
}
|
||||
}
|
||||
```
|
||||
## Transforming Selections
|
||||
|
||||
When the `options` array contains objects, vue-select returns the whole object as dropdown value
|
||||
upon selection. This approach makes no assumptions about the data you need, and provides a lot of
|
||||
flexibility. However, there will be situations where maybe you just need to return a single key
|
||||
from an object.
|
||||
|
||||
### Returning a single key with `reduce`
|
||||
|
||||
If you need to return a single key, or transform the selection before it is synced, vue-select
|
||||
provides a `reduce` callback that allows you to transform a selected option before it is passed to
|
||||
the `@input` event. Consider this data structure:
|
||||
|
||||
```js
|
||||
let options = [{code: 'CA', country: 'Canada'}];
|
||||
```
|
||||
|
||||
If we want to display the `country`, but return the `code` to `v-model`, we can use the `reduce`
|
||||
prop to receive only the data that's required.
|
||||
|
||||
```html
|
||||
<v-select :options="options" :reduce="country => country.code" label="country" />
|
||||
```
|
||||
|
||||
### Deep Nested Values
|
||||
|
||||
The `reduce` property also works well when you have a deeply nested value:
|
||||
|
||||
```
|
||||
{
|
||||
country: 'canada',
|
||||
meta: {
|
||||
code: 'ca'
|
||||
provinces: [...],
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```html
|
||||
<v-select :options="options" :reduce="country => country.meta.code" label="country" />
|
||||
```
|
||||
|
||||
<reducer-nested-value />
|
||||
|
||||
## Single/Multiple Selection
|
||||
|
||||
By default, vue-select supports choosing a single value. If you need multiple values, use the
|
||||
`multiple` boolean prop, much the same way you would on an HTML `<select>` element. When `multiple`
|
||||
is true, `v-model` and `value` must be an array.
|
||||
|
||||
|
||||
```html
|
||||
<v-select multiple v-model="selected" :options="['Canada','United States']" />
|
||||
```
|
||||
<v-select multiple :options="['Canada','United States']" />
|
||||
|
||||
## Tagging
|
||||
|
||||
To allow input that's not present within the options, set the `taggable` prop to true.
|
||||
|
||||
```html
|
||||
<v-select taggable multiple />
|
||||
```
|
||||
|
||||
<v-select taggable multiple />
|
||||
|
||||
If you want added tags to be pushed to the options array, set `push-tags` to true.
|
||||
|
||||
```html
|
||||
<v-select taggable multiple />
|
||||
```
|
||||
|
||||
<v-select taggable multiple push-tags />
|
||||
|
||||
### Using `taggable` & `reduce` together
|
||||
|
||||
When combining `taggable` with `reduce`, you must define the `createOption` prop. The
|
||||
`createOption` function is responsible for defining the structure of the objects that Vue Select
|
||||
will create for you when adding a tag. It should return a value that has the same properties as the
|
||||
rest of your `options`.
|
||||
|
||||
If you don't define `createOption`, Vue Select will construct a simple object following this structure:
|
||||
`{[this.label]: searchText}`. If you're using `reduce`, this is probably not what your options look
|
||||
like, which is why you'll need to set the function yourself.
|
||||
|
||||
**Example**
|
||||
|
||||
We have a taggable select for adding books to a collection. We're just concerned about getting the
|
||||
book title added, and our server side code will add the author details in a background process. The
|
||||
user has already selected a book.
|
||||
|
||||
```js
|
||||
const options = [
|
||||
{
|
||||
title: "HTML5",
|
||||
author: {
|
||||
firstName: "Remy",
|
||||
lastName: "Sharp"
|
||||
}
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
```html
|
||||
<v-select
|
||||
taggable
|
||||
multiple
|
||||
label="title"
|
||||
:options="options"
|
||||
:create-option="book => ({ title: book, author: { firstName: '', lastName: '' } })"
|
||||
:reduce="book => `${book.author.firstName} ${book.author.lastName}`"
|
||||
/>
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -13,4 +13,4 @@ action, or trigger a mutation.
|
||||
></v-select>
|
||||
```
|
||||
|
||||
[](codepen://sagalbot/aJQJyp?height=500)
|
||||
<CodePen url="aJQJyp" height="350"/>
|
||||
@@ -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';
|
||||
@@ -1,117 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Vue Select | VueJS Select2 Component</title>
|
||||
|
||||
<link 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" rel="stylesheet" type="text/css">
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/octicons/4.4.0/font/octicons.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<meta name="title" content="Vue Select | VueJS Select2/Chosen Component">
|
||||
<meta name="description"
|
||||
content="A well-tested, native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.">
|
||||
|
||||
<link rel="icon" href="static/vue-logo.png" type="image/png">
|
||||
<meta property="og:image" content="static/vue-logo.png">
|
||||
<meta property="twitter:image" content="static/vue-logo.png">
|
||||
|
||||
<meta name="description"
|
||||
content="A native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.">
|
||||
<meta property="og:description"
|
||||
content="A native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.">
|
||||
<meta property="twitter:description"
|
||||
content="A native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.">
|
||||
|
||||
<meta property="twitter:title" content="Vue Select | VueJS Select2/Chosen Component">
|
||||
<meta property="og:title" content="Vue Select | VueJS Select2/Chosen Component">
|
||||
<meta property="og:site_name" content="Vue Select | VueJS Select2/Chosen Component">
|
||||
<meta property="og:url" content="http://sagalbot.github.io/vue-select/">
|
||||
</head>
|
||||
<body>
|
||||
<div id="app">
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<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>
|
||||
|
||||
<a class="btn btn-primary btn-outline btn-lg" href="docs/">
|
||||
<span class="octicon octicon-book"></span> Read the Docs
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<script>
|
||||
(function (i, s, o, g, r, a, m) {
|
||||
i['GoogleAnalyticsObject'] = r;
|
||||
i[r] = i[r] || function () {
|
||||
(i[r].q = i[r].q || []).push(arguments)
|
||||
}, i[r].l = 1 * new Date();
|
||||
a = s.createElement(o),
|
||||
m = s.getElementsByTagName(o)[0];
|
||||
a.async = 1;
|
||||
a.src = g;
|
||||
m.parentNode.insertBefore(a, m)
|
||||
})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga');
|
||||
|
||||
ga('create', 'UA-12818324-8', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,49 +0,0 @@
|
||||
import Vue from 'vue'
|
||||
import vSelect from 'vue-select'
|
||||
|
||||
import './assets/scss/home.scss'
|
||||
|
||||
Vue.component('v-select', vSelect);
|
||||
|
||||
/* eslint-disable no-new */
|
||||
new Vue({
|
||||
el: '#app',
|
||||
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) {
|
||||
window.location = option.url;
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
sidebar: false
|
||||
editLink: false
|
||||
layout: Sandbox
|
||||
---
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<CodePen url="zZQJKW" height="60"/>
|
||||
@@ -0,0 +1,15 @@
|
||||
# Global settings applied to the whole site.
|
||||
#
|
||||
# “publish” is the directory to publish (relative to root of your repo),
|
||||
# “command” is your build command,
|
||||
[build]
|
||||
publish = "docs/.vuepress/dist"
|
||||
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"
|
||||
+81
-66
@@ -7,17 +7,12 @@
|
||||
"main": "dist/vue-select.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "node build/dev-server.js",
|
||||
"dev:homepage": "node build/dev-server.js --docs",
|
||||
"dev:docs": "gitbook serve",
|
||||
"build": "node build/build.js",
|
||||
"build:homepage": "node build/build.js --homepage",
|
||||
"build:docs": "yarn run build:homepage && node build/build-docs.js",
|
||||
"deploy": "yarn run build:homepage && node build/build-docs.js && gh-pages -d site",
|
||||
"lint": "eslint --ext .js,.vue src test/unit/specs",
|
||||
"test": "karma start test/unit/karma.conf.js --single-run",
|
||||
"test-watch": "karma start test/unit/karma.conf.js --single-run=false --auto-watch=true"
|
||||
"serve": "webpack-dev-server --config build/webpack.dev.conf.js --hot --progress -d",
|
||||
"serve:docs": "vuepress dev docs",
|
||||
"build": "cross-env NODE_ENV=production webpack --config build/webpack.prod.conf.js --progress",
|
||||
"build:docs": "vuepress build docs",
|
||||
"build:preview": "cross-env DEPLOY_PREVIEW=true vuepress build --debug docs",
|
||||
"test": "jest"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -26,63 +21,83 @@
|
||||
"peerDependencies": {
|
||||
"vue": "2.x"
|
||||
},
|
||||
"resolutions": {
|
||||
"ajv": "6.8.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.0.0",
|
||||
"babel-loader": "^6.0.0",
|
||||
"babel-plugin-transform-runtime": "^6.0.0",
|
||||
"babel-preset-es2015": "^6.0.0",
|
||||
"babel-preset-stage-2": "^6.0.0",
|
||||
"codeclimate-test-reporter": "^0.3.1",
|
||||
"connect-history-api-fallback": "^1.1.0",
|
||||
"css-loader": "^0.23.0",
|
||||
"eventsource-polyfill": "^0.9.6",
|
||||
"express": "^4.13.3",
|
||||
"extract-text-webpack-plugin": "^1.0.1",
|
||||
"file-loader": "^0.8.4",
|
||||
"function-bind": "^1.0.2",
|
||||
"@babel/core": "^7.4.0",
|
||||
"@babel/plugin-transform-runtime": "^7.4.0",
|
||||
"@babel/preset-env": "^7.4.2",
|
||||
"@babel/runtime": "^7.4.2",
|
||||
"@vue/test-utils": "^1.0.0-beta.29",
|
||||
"autoprefixer": "^9.4.7",
|
||||
"babel-core": "^7.0.0-bridge.0",
|
||||
"babel-loader": "^8.0.5",
|
||||
"chokidar": "^2.1.5",
|
||||
"coveralls": "^3.0.2",
|
||||
"cross-env": "^5.2.0",
|
||||
"css-loader": "^2.1.0",
|
||||
"cssnano": "^4.1.10",
|
||||
"fuse.js": "^3.2.0",
|
||||
"gh-pages": "^0.11.0",
|
||||
"gitbook-plugin-codepen": "^0.1.2",
|
||||
"gitbook-plugin-edit-link": "^2.0.2",
|
||||
"gitbook-plugin-github": "^3.0.0",
|
||||
"highlight.js": "^9.9.0",
|
||||
"html-loader": "^0.4.4",
|
||||
"html-webpack-plugin": "^2.8.1",
|
||||
"http-proxy-middleware": "^0.15.2",
|
||||
"inject-loader": "^2.0.1",
|
||||
"isparta-loader": "^2.0.0",
|
||||
"jasmine": "^2.4.1",
|
||||
"json-loader": "^0.5.4",
|
||||
"karma": "^0.13.15",
|
||||
"karma-coverage": "^1.0.0",
|
||||
"karma-jasmine": "^1.0.2",
|
||||
"karma-phantomjs-launcher": "^1.0.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.26",
|
||||
"karma-webpack": "^1.7.0",
|
||||
"lolex": "^1.4.0",
|
||||
"markdown-loader": "^0.1.7",
|
||||
"node-sass": "^3.7.0",
|
||||
"normalize.css": "^7.0.0",
|
||||
"ora": "^0.2.0",
|
||||
"phantomjs-prebuilt": "^2.1.3",
|
||||
"prismjs": "^1.5.0",
|
||||
"sass-loader": "^3.2.0",
|
||||
"shelljs": "^0.7.0",
|
||||
"url-loader": "^0.5.7",
|
||||
"vue": "^2.1.8",
|
||||
"vue-hot-reload-api": "^2.0.7",
|
||||
"vue-html-loader": "^1.2.3",
|
||||
"vue-loader": "^10.0.2",
|
||||
"vue-markdown-loader": "^0.6.1",
|
||||
"vue-resource": "^1.0.3",
|
||||
"vue-select": "*",
|
||||
"vue-style-loader": "^1.0.0",
|
||||
"vue-template-compiler": "^2.1.8",
|
||||
"vuex": "^2.1.1",
|
||||
"webpack": "^1.12.2",
|
||||
"webpack-dev-middleware": "^1.4.0",
|
||||
"webpack-hot-middleware": "^2.6.0",
|
||||
"webpack-merge": "^0.13.0"
|
||||
"html-loader": "^0.5.5",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"jest": "^24.1.0",
|
||||
"jest-serializer-vue": "^2.0.2",
|
||||
"jest-transform-stub": "^2.0.0",
|
||||
"mini-css-extract-plugin": "^0.5.0",
|
||||
"node-sass": "^4.10.0",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-scss": "^2.0.0",
|
||||
"sass-loader": "^7.1.0",
|
||||
"terser-webpack-plugin": "^1.2.3",
|
||||
"url-loader": "^1.1.2",
|
||||
"vue": "^2.6.10",
|
||||
"vue-html-loader": "^1.2.4",
|
||||
"vue-jest": "^3.0.4",
|
||||
"vue-loader": "^15.7.0",
|
||||
"vue-server-renderer": "^2.6.10",
|
||||
"vue-style-loader": "^4.1.2",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"vuepress": "^0.14.10",
|
||||
"vuex": "^3.1.0",
|
||||
"webpack": "^4.29.6",
|
||||
"webpack-cli": "^3.3.0",
|
||||
"webpack-dev-server": "^3.2.1",
|
||||
"webpack-merge": "^4.2.1"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"jsx",
|
||||
"json",
|
||||
"vue"
|
||||
],
|
||||
"transform": {
|
||||
"^.+\\.vue$": "vue-jest",
|
||||
".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
|
||||
"^.+\\.jsx?$": "babel-jest"
|
||||
},
|
||||
"moduleNameMapper": {
|
||||
"^@/(.*)$": "<rootDir>/src/$1"
|
||||
},
|
||||
"snapshotSerializers": [
|
||||
"jest-serializer-vue"
|
||||
],
|
||||
"testMatch": [
|
||||
"**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"
|
||||
],
|
||||
"testURL": "http://localhost/",
|
||||
"collectCoverage": true,
|
||||
"collectCoverageFrom": [
|
||||
"src/mixins/*.js",
|
||||
"!src/mixins/index.js",
|
||||
"src/components/Select.vue",
|
||||
"!**/node_modules/**"
|
||||
],
|
||||
"coverageReporters": [
|
||||
"html",
|
||||
"text-summary"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
+364
-602
File diff suppressed because it is too large
Load Diff
+55
-68
@@ -1,72 +1,59 @@
|
||||
module.exports = {
|
||||
props: {
|
||||
/**
|
||||
* Toggles the adding of a 'loading' class to the main
|
||||
* .v-select wrapper. Useful to control UI state when
|
||||
* results are being processed through AJAX.
|
||||
*/
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
|
||||
/**
|
||||
* Accept a callback function that will be
|
||||
* run when the search text changes.
|
||||
*
|
||||
* loading() accepts a boolean value, and can
|
||||
* be used to toggle a loading class from
|
||||
* the onSearch callback.
|
||||
*
|
||||
* @param {search} String Current search text
|
||||
* @param {loading} Function(bool) Toggle loading class
|
||||
*/
|
||||
onSearch: {
|
||||
type: Function,
|
||||
default: function(search, loading){}
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
mutableLoading: false
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* If a callback & search text has been provided,
|
||||
* invoke the onSearch callback.
|
||||
*/
|
||||
search() {
|
||||
if (this.search.length > 0) {
|
||||
this.onSearch(this.search, this.toggleLoading)
|
||||
this.$emit('search', this.search, this.toggleLoading)
|
||||
}
|
||||
},
|
||||
export default {
|
||||
props: {
|
||||
/**
|
||||
* Sync the loading prop with the internal
|
||||
* mutable loading value.
|
||||
* Toggles the adding of a 'loading' class to the main
|
||||
* .v-select wrapper. Useful to control UI state when
|
||||
* results are being processed through AJAX.
|
||||
*/
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
data () {
|
||||
return {
|
||||
mutableLoading: false,
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
/**
|
||||
* Anytime the search string changes, emit the
|
||||
* 'search' event. The event is passed with two
|
||||
* parameters: the search string, and a function
|
||||
* that accepts a boolean parameter to toggle the
|
||||
* loading state.
|
||||
*
|
||||
* @emits search
|
||||
*/
|
||||
search () {
|
||||
this.$emit('search', this.search, this.toggleLoading);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sync the loading prop with the internal
|
||||
* mutable loading value.
|
||||
* @param val
|
||||
*/
|
||||
loading(val) {
|
||||
this.mutableLoading = val
|
||||
}
|
||||
},
|
||||
loading (val) {
|
||||
this.mutableLoading = val;
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
/**
|
||||
* Toggle this.loading. Optionally pass a boolean
|
||||
* value. If no value is provided, this.loading
|
||||
* will be set to the opposite of it's current value.
|
||||
* @param toggle Boolean
|
||||
* @returns {*}
|
||||
*/
|
||||
toggleLoading(toggle = null) {
|
||||
if (toggle == null) {
|
||||
return this.mutableLoading = !this.mutableLoading
|
||||
}
|
||||
return this.mutableLoading = toggle
|
||||
}
|
||||
}
|
||||
}
|
||||
methods: {
|
||||
/**
|
||||
* Toggle this.loading. Optionally pass a boolean
|
||||
* value. If no value is provided, this.loading
|
||||
* will be set to the opposite of it's current value.
|
||||
* @param toggle Boolean
|
||||
* @returns {*}
|
||||
*/
|
||||
toggleLoading (toggle = null) {
|
||||
if (toggle == null) {
|
||||
return (this.mutableLoading = !this.mutableLoading);
|
||||
}
|
||||
return (this.mutableLoading = toggle);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
+28
-22
@@ -1,9 +1,7 @@
|
||||
// flow
|
||||
|
||||
module.exports = {
|
||||
export default {
|
||||
watch: {
|
||||
typeAheadPointer() {
|
||||
this.maybeAdjustScroll()
|
||||
this.maybeAdjustScroll();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -15,13 +13,13 @@ module.exports = {
|
||||
* @returns {*}
|
||||
*/
|
||||
maybeAdjustScroll() {
|
||||
let pixelsToPointerTop = this.pixelsToPointerTop()
|
||||
let pixelsToPointerBottom = this.pixelsToPointerBottom()
|
||||
let pixelsToPointerTop = this.pixelsToPointerTop();
|
||||
let pixelsToPointerBottom = this.pixelsToPointerBottom();
|
||||
|
||||
if ( pixelsToPointerTop <= this.viewport().top) {
|
||||
return this.scrollTo( pixelsToPointerTop )
|
||||
if (pixelsToPointerTop <= this.viewport().top) {
|
||||
return this.scrollTo(pixelsToPointerTop);
|
||||
} else if (pixelsToPointerBottom >= this.viewport().bottom) {
|
||||
return this.scrollTo( this.viewport().top + this.pointerHeight() )
|
||||
return this.scrollTo(this.viewport().top + this.pointerHeight());
|
||||
}
|
||||
},
|
||||
|
||||
@@ -31,13 +29,14 @@ module.exports = {
|
||||
* @returns {number}
|
||||
*/
|
||||
pixelsToPointerTop() {
|
||||
let pixelsToPointerTop = 0
|
||||
if( this.$refs.dropdownMenu ) {
|
||||
let pixelsToPointerTop = 0;
|
||||
if (this.$refs.dropdownMenu) {
|
||||
for (let i = 0; i < this.typeAheadPointer; i++) {
|
||||
pixelsToPointerTop += this.$refs.dropdownMenu.children[i].offsetHeight
|
||||
pixelsToPointerTop += this.$refs.dropdownMenu.children[i]
|
||||
.offsetHeight;
|
||||
}
|
||||
}
|
||||
return pixelsToPointerTop
|
||||
return pixelsToPointerTop;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -46,7 +45,7 @@ module.exports = {
|
||||
* @returns {*}
|
||||
*/
|
||||
pixelsToPointerBottom() {
|
||||
return this.pixelsToPointerTop() + this.pointerHeight()
|
||||
return this.pixelsToPointerTop() + this.pointerHeight();
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -54,8 +53,10 @@ module.exports = {
|
||||
* @returns {number}
|
||||
*/
|
||||
pointerHeight() {
|
||||
let element = this.$refs.dropdownMenu ? this.$refs.dropdownMenu.children[this.typeAheadPointer] : false
|
||||
return element ? element.offsetHeight : 0
|
||||
let element = this.$refs.dropdownMenu
|
||||
? this.$refs.dropdownMenu.children[this.typeAheadPointer]
|
||||
: false;
|
||||
return element ? element.offsetHeight : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -64,9 +65,12 @@ module.exports = {
|
||||
*/
|
||||
viewport() {
|
||||
return {
|
||||
top: this.$refs.dropdownMenu ? this.$refs.dropdownMenu.scrollTop: 0,
|
||||
bottom: this.$refs.dropdownMenu ? this.$refs.dropdownMenu.offsetHeight + this.$refs.dropdownMenu.scrollTop : 0
|
||||
}
|
||||
top: this.$refs.dropdownMenu ? this.$refs.dropdownMenu.scrollTop : 0,
|
||||
bottom: this.$refs.dropdownMenu
|
||||
? this.$refs.dropdownMenu.offsetHeight +
|
||||
this.$refs.dropdownMenu.scrollTop
|
||||
: 0
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -75,7 +79,9 @@ module.exports = {
|
||||
* @returns {*}
|
||||
*/
|
||||
scrollTo(position) {
|
||||
return this.$refs.dropdownMenu ? this.$refs.dropdownMenu.scrollTop = position : null
|
||||
},
|
||||
return this.$refs.dropdownMenu
|
||||
? (this.$refs.dropdownMenu.scrollTop = position)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = {
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
typeAheadPointer: -1
|
||||
@@ -57,4 +57,4 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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: 1;
|
||||
|
||||
&: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";
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.2 KiB |
@@ -1,12 +0,0 @@
|
||||
// Polyfill fn.bind() for PhantomJS
|
||||
/* eslint-disable no-extend-native */
|
||||
Function.prototype.bind = require('function-bind')
|
||||
|
||||
// require all test files (files that ends with .spec.js)
|
||||
var testsContext = require.context('./specs', true, /\.spec$/)
|
||||
testsContext.keys().forEach(testsContext)
|
||||
|
||||
// require all src files except main.js for coverage.
|
||||
// you can also change this to match only the subset of files that
|
||||
// you want coverage for.
|
||||
var srcContext = require('../../src/components/Select.vue')
|
||||
@@ -1,78 +0,0 @@
|
||||
// This is a karma config file. For more details see
|
||||
// http://karma-runner.github.io/0.13/config/configuration-file.html
|
||||
// we are also using it with karma-webpack
|
||||
// https://github.com/webpack/karma-webpack
|
||||
|
||||
var path = require('path')
|
||||
var merge = require('webpack-merge')
|
||||
var baseConfig = require('../../build/webpack.base.conf')
|
||||
var utils = require('../../build/utils')
|
||||
var webpack = require('webpack')
|
||||
var projectRoot = path.resolve(__dirname, '../../')
|
||||
|
||||
var webpackConfig = merge(baseConfig, {
|
||||
// use inline sourcemap for karma-sourcemap-loader
|
||||
module: {
|
||||
loaders: utils.styleLoaders()
|
||||
},
|
||||
devtool: '#inline-source-map',
|
||||
vue: {
|
||||
loaders: {
|
||||
js: 'isparta'
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': require('../../config/test.env')
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
// no need for app entry during tests
|
||||
delete webpackConfig.entry
|
||||
|
||||
// make sure isparta loader is applied before eslint
|
||||
webpackConfig.module.preLoaders = webpackConfig.module.preLoaders || []
|
||||
webpackConfig.module.preLoaders.unshift({
|
||||
test: /\.js$/,
|
||||
loader: 'isparta',
|
||||
include: path.resolve(projectRoot, 'src')
|
||||
})
|
||||
|
||||
// only apply babel for test files when using isparta
|
||||
webpackConfig.module.loaders.some(function (loader, i) {
|
||||
if (loader.loader === 'babel') {
|
||||
loader.include = path.resolve(projectRoot, 'test/unit')
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
// to run in additional browsers:
|
||||
// 1. install corresponding karma launcher
|
||||
// http://karma-runner.github.io/0.13/config/browsers.html
|
||||
// 2. add it to the `browsers` array below.
|
||||
browsers: ['PhantomJS'],
|
||||
frameworks: ['jasmine'],
|
||||
reporters: ['spec', 'coverage'],
|
||||
files: ['./index.js'],
|
||||
preprocessors: {
|
||||
'./index.js': ['webpack', 'sourcemap']
|
||||
},
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
noInfo: true
|
||||
},
|
||||
specReporter: {
|
||||
suppressSkipped: true
|
||||
},
|
||||
coverageReporter: {
|
||||
dir: './coverage',
|
||||
reporters: [
|
||||
{ type: 'lcov', subdir: '.' },
|
||||
{ type: 'text-summary' }
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user