2
0
mirror of https://github.com/tenrok/vue-select.git synced 2026-06-22 10:30:34 +03:00

Merge branch 'master' into umd

# Conflicts:
#	src/components/Select.vue
This commit is contained in:
Jeff Sagal
2016-06-15 21:33:16 -07:00
39 changed files with 1515 additions and 914 deletions
+5 -2
View File
@@ -1,6 +1,9 @@
# vue-select [![Build Status](https://travis-ci.org/sagalbot/vue-select.svg?branch=master)](https://travis-ci.org/sagalbot/vue-select) [![Code Climate Rating](https://img.shields.io/codeclimate/github/sagalbot/vue-select.svg?style=flat-square)](https://codeclimate.com/github/sagalbot/vue-select) [![Code Coverage](https://img.shields.io/codeclimate/coverage/github/sagalbot/vue-select.svg?style=flat-square)](https://codeclimate.com/github/sagalbot/vue-select) [![No Dependencies](https://img.shields.io/gemnasium/sagalbot/vue-select.svg?style=flat-square)](https://gemnasium.com/github.com/sagalbot/vue-select) ![MIT License](https://img.shields.io/github/license/sagalbot/vue-select.svg?style=flat-square) ![Current Release](https://img.shields.io/github/release/sagalbot/vue-select.svg?style=flat-square) # vue-select [![Build Status](https://travis-ci.org/sagalbot/vue-select.svg?branch=master)](https://travis-ci.org/sagalbot/vue-select) [![Code Coverage](https://img.shields.io/codeclimate/coverage/github/sagalbot/vue-select.svg?style=flat-square)](https://codeclimate.com/github/sagalbot/vue-select) [![No Dependencies](https://img.shields.io/gemnasium/sagalbot/vue-select.svg?style=flat-square)](https://gemnasium.com/github.com/sagalbot/vue-select) ![MIT License](https://img.shields.io/github/license/sagalbot/vue-select.svg?style=flat-square) ![Current Release](https://img.shields.io/github/release/sagalbot/vue-select.svg?style=flat-square)
> A native Vue.js component that provides similar functionality to Select2 without the overhead of jQuery.
Rather than bringing in jQuery just to use Select2 or Chosen, this Vue.js component provides similar functionality without the extra overhead of jQuery, while providing the same awesome data-binding features you expect from Vue. Vue-select has no JavaScript dependencies other than Vue, and is designed to mimic [Select2](https://github.com/select2/select2).
> Rather than bringing in jQuery just to use Select2 or Chosen, this Vue.js component provides similar functionality without the extra overhead of jQuery, while providing the same awesome data-binding features you expect from Vue. Vue-select has no JavaScript dependencies other than Vue, and is designed to mimic [Select2](https://github.com/select2/select2).
#### Features #### Features
+23 -12
View File
@@ -6,13 +6,14 @@ var path = require('path')
var config = require('../config') var config = require('../config')
var ora = require('ora') var ora = require('ora')
var webpack = require('webpack') var webpack = require('webpack')
var ghpages = require('gh-pages')
var webpackConfig = require('./webpack.prod.conf') var webpackConfig = require('./webpack.prod.conf')
var umdConfig = require('./webpack.umd.conf') var umdConfig = require('./webpack.umd.conf')
console.log( console.log(
' Tip:\n' + ' Tip:\n' +
' Built files are meant to be served over an HTTP server.\n' + ' Built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n' ' Opening index.html over file:// won\'t work.\n'
) )
var spinner = ora('building for production...') var spinner = ora('building for production...')
@@ -27,15 +28,25 @@ cp('-R', 'static/', assetsPath)
* Build the /dist/ folder (demo site) * Build the /dist/ folder (demo site)
*/ */
webpack(webpackConfig, function (err, stats) { webpack(webpackConfig, function (err, stats) {
spinner.stop() spinner.stop()
if (err) throw err if (err) throw err
process.stdout.write(stats.toString({ process.stdout.write(stats.toString({
colors: true, colors: true,
modules: false, modules: false,
children: false, children: false,
chunks: false, chunks: false,
chunkModules: false chunkModules: false
}) + '\n') }) + '\n')
// $ npm run build publish
// This will publish /dist/ to the gh-pages
if (( process.argv.indexOf('publish') > 1 )) {
spinner = ora('Publishing to GitHub Pages...').start()
ghpages.publish(path.join(__dirname, '../dist'), function (err) {
spinner.stop()
if (err) throw err
});
}
}) })
/** /**
+6 -5
View File
@@ -5,7 +5,7 @@ var projectRoot = path.resolve(__dirname, '../')
module.exports = { module.exports = {
entry: { entry: {
app: './src/main.js' app: './docs/main.js'
}, },
output: { output: {
path: config.build.assetsRoot, path: config.build.assetsRoot,
@@ -17,8 +17,9 @@ module.exports = {
fallback: [path.join(__dirname, '../node_modules')], fallback: [path.join(__dirname, '../node_modules')],
alias: { alias: {
'src': path.resolve(__dirname, '../src'), 'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'), 'assets': path.resolve(__dirname, '../docs/assets'),
'components': path.resolve(__dirname, '../src/components') 'mixins': path.resolve(__dirname, '../src/mixins'),
'components': path.resolve(__dirname, '../docs/components')
} }
}, },
resolveLoader: { resolveLoader: {
@@ -45,7 +46,7 @@ module.exports = {
loader: 'vue-html' loader: 'vue-html'
}, },
{ {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, test: /\.(png|jpe?g|gif)(\?.*)?$/,
loader: 'url', loader: 'url',
query: { query: {
limit: 10000, limit: 10000,
@@ -53,7 +54,7 @@ module.exports = {
} }
}, },
{ {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, test: /\.(woff2?|eot|ttf|otf|svg)(\?.*)?$/,
loader: 'url', loader: 'url',
query: { query: {
limit: 10000, limit: 10000,
+2 -2
View File
@@ -6,8 +6,8 @@ module.exports = {
env: require('./prod.env'), env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'), index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'), assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static', assetsSubDirectory: '',
assetsPublicPath: '/', assetsPublicPath: ( process.argv.indexOf('publish') > 1 ) ? 'http://sagalbot.github.io/vue-select/' : '/',
productionSourceMap: true productionSourceMap: true
}, },
dev: { dev: {
+32
View File
@@ -0,0 +1,32 @@
<style lang="scss">
@import 'assets/scss/_demo.scss';
@import 'assets/scss/_cyan_theme.scss';
@import 'assets/scss/_prism.scss';
@import 'assets/scss/_octicons.scss';
</style>
<template>
<div class="container">
<div class="col-md-10 col-md-offset-1">
<examples></examples>
<params></params>
</div>
</div>
</template>
<script type="text/babel">
/**
* Note that this file (and anything other than src/components/Select.vue)
* has nothing to do with how you use vue-select. These files are used
* for the demo site at http://sagalbot.github.io/vue-select/.
*/
import Examples from './components/Examples.vue'
import Params from './components/Params.vue'
import Ajax from './components/snippets/Ajax.vue'
export default {
components: { Params, Examples, Ajax }
}
</script>

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

@@ -49,13 +49,15 @@ p.lead {
.btn-outline { .btn-outline {
background: none; background: none;
padding: 10px 16px;
font-size: 18px;
line-height: 1.3333333; line-height: 1.3333333;
border-radius: 6px; border-radius: 6px;
border: 3px solid #91ddec; border: 2px solid #91ddec;
color: #147688; color: #147688;
&.btn-lg {
border-width: 3px;
}
&:hover { &:hover {
border-color: rgb(65, 184, 131); border-color: rgb(65, 184, 131);
background-color: rgba(65, 184, 131, 0.67); background-color: rgba(65, 184, 131, 0.67);
@@ -83,4 +85,13 @@ p.lead {
.selected-tag .close { .selected-tag .close {
font-family: "Helvetica Neue", "Helvetica"; font-family: "Helvetica Neue", "Helvetica";
font-weight: 400; font-weight: 400;
}
.accolades a {
margin-left: 0;
margin-right: 5px;
}
.doc-row {
padding: 2em 0;
} }
@@ -1,9 +1,9 @@
@font-face { @font-face {
font-family: 'octicons'; font-family: 'octicons';
src: url('./assets/fonts/octicons.eot?#iefix') format('embedded-opentype'), src: url('~assets/fonts/octicons.eot?#iefix') format('embedded-opentype'),
url('./assets/fonts/octicons.woff') format('woff'), url('~assets/fonts/octicons.woff') format('woff'),
url('./assets/fonts/octicons.ttf') format('truetype'), url('~assets/fonts/octicons.ttf') format('truetype'),
url('./assets/fonts/octicons.svg#octicons') format('svg'); url('~assets/fonts/octicons.svg#octicons') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
@@ -14,48 +14,52 @@
<h2 class="page-header" id="examples">Examples</h2> <h2 class="page-header" id="examples">Examples</h2>
<h3 class="page-header">Single/Multiple Selection</h3> <article class="doc-row" id="ex-multiple">
<div class="row"> <h3 class="page-header">Single/Multiple Selection</h3>
<div class="col-md-6"> <div class="row">
<h4>Single Option Select</h4> <div class="col-md-6">
<pre><v-code lang="markup">&#x3C;v-select :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code></pre> <h4>Single Option Select</h4>
<v-select :options="countries"></v-select> <pre><v-code lang="markup">&#x3C;v-select :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code></pre>
</div> <v-select :options="countries"></v-select>
<div class="col-md-6">
<h4>Multiple Option Select</h4>
<pre><v-code lang="markup">&#x3C;v-select multiple :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code></pre>
<v-select multiple :options="countries"></v-select>
</div>
</div>
<h3 class="page-header">Reactive Options</h3>
<div class="row">
<div class="col-md-6">
<p>When the list of options provided by the parent changes, vue-select will react as you'd expect.</p>
<div style="margin-top:0;" class="radio">
<label>
<input type="radio" name="reactive-options" v-model="reactive" :value="countries">
<v-code lang="markup">&#x3C;v-select :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code>
</label>
</div> </div>
<div class="radio"> <div class="col-md-6">
<label> <h4>Multiple Option Select</h4>
<input type="radio" name="reactive-options" v-model="reactive" :value="['foo','bar','baz']"> <pre><v-code lang="markup">&#x3C;v-select multiple :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code></pre>
<v-code lang="markup">&#x3C;v-select options=&#x22;['foo','bar','baz']&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code> <v-select multiple :options="countries"></v-select>
</label>
</div> </div>
</div> </div>
</article>
<div class="col-md-6"> <article class="doc-row" id="ex-reactive">
<v-select :options="reactive"></v-select> <h3 class="page-header">Reactive Options</h3>
<div class="row">
<div class="col-md-6">
<p>When the list of options provided by the parent changes, vue-select will react as you'd expect.</p>
<div style="margin-top:0;" class="radio">
<label>
<input type="radio" name="reactive-options" v-model="reactive" :value="countries">
<v-code lang="markup">&#x3C;v-select :options=&#x22;countries&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code>
</label>
</div>
<div class="radio">
<label>
<input type="radio" name="reactive-options" v-model="reactive" :value="['foo','bar','baz']">
<v-code lang="markup">&#x3C;v-select options=&#x22;['foo','bar','baz']&#x22;&#x3E;&#x3C;/v-select&#x3E;</v-code>
</label>
</div>
</div>
<div class="col-md-6">
<v-select :options="reactive"></v-select>
</div>
</div> </div>
</div> </article>
<h3 class="page-header">Two-Way Value Syncing</h3> <article class="doc-row" id="ex-syncing">
<div class="row"> <h3 class="page-header">Two-Way Value Syncing</h3>
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<p>The most common use case for vue-select is being able to sync the components value with a parent component. The <code>value</code> property supports two-way data binding to accomplish this.</p> <p>The most common use case for vue-select is being able to sync the components value with a parent component. The <code>value</code> property supports two-way data binding to accomplish this.</p>
<p>The <code>.sync</code> data-binding modifier is completely optional. You may use <code>value</code> without a two-way binding to preselect options.</p> <p>The <code>.sync</code> data-binding modifier is completely optional. You may use <code>value</code> without a two-way binding to preselect options.</p>
@@ -78,9 +82,11 @@
</div> </div>
</div> </div>
</div> </div>
</article>
<h3 class="page-header">Custom Labels</h3> <article class="doc-row" id="ex-labels">
<div class="row"> <h3 class="page-header">Custom Labels</h3>
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<p>By default when the <code>options</code> array contains objects, <code>vue-select</code> looks for the <code>label</code> key for display. If your data source doesn't contain that key, you can set your own using the <code>label</code> prop.</p> <p>By default when the <code>options</code> array contains objects, <code>vue-select</code> looks for the <code>label</code> key for display. If your data source doesn't contain that key, you can set your own using the <code>label</code> prop.</p>
<p>On this page, the list of countries used in the examples contains <code>value</code> and <code>label</code> properties: <v-code lang="json">{value: "CA", label: "Canada"}</v-code>. In this example, we'll display the country code instead of the label.</p> <p>On this page, the list of countries used in the examples contains <code>value</code> and <code>label</code> properties: <v-code lang="json">{value: "CA", label: "Canada"}</v-code>. In this example, we'll display the country code instead of the label.</p>
@@ -91,9 +97,11 @@
<v-select :options="countries" label="value"></v-select> <v-select :options="countries" label="value"></v-select>
</div> </div>
</div> </div>
</article>
<h3 class="page-header">On-Change Callback <small>Vuex Compatibility</small></h3> <article class="doc-row" id="ex-vuex">
<div class="row"> <h3 class="page-header">On-Change Callback <small>Vuex Compatibility</small></h3>
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<p>vue-select provides an <code>onChange</code> property that accepts a callback function. This function is passed the currently selected value(s) as it's only parameter.</p> <p>vue-select provides an <code>onChange</code> property that accepts a callback function. This function is passed the currently selected value(s) as it's only parameter.</p>
<p>This is very useful when integrating with Vuex, as it will allow your to trigger an action to update your vuex state object. Choose a callback and see it in action.</p> <p>This is very useful when integrating with Vuex, as it will allow your to trigger an action to update your vuex state object. Choose a callback and see it in action.</p>
@@ -127,13 +135,12 @@
<v-select :options="countries" :on-change="getCallback"></v-select> <v-select :options="countries" :on-change="getCallback"></v-select>
</div> </div>
</div> </div>
</article>
<ajax></ajax>
</section> </section>
</template> </template>
<style type="scss">
</style>
<script> <script>
/** /**
* Note that this file (and anything other than src/components/Select.vue) * Note that this file (and anything other than src/components/Select.vue)
@@ -141,13 +148,15 @@
* for the demo site at http://sagalbot.github.io/vue-select/. They'll * for the demo site at http://sagalbot.github.io/vue-select/. They'll
* be moved out of this repo in the very near future to avoid confusion. * be moved out of this repo in the very near future to avoid confusion.
*/ */
import countries from '../countries/advanced' import countries from '../data/advanced'
import simple from '../countries/simple' import simple from '../data/simple'
import vSelect from './Select.vue' import vSelect from 'src/components/Select.vue'
import vCode from './Code.vue' import vCode from './Code.vue'
import Ajax from './snippets/Ajax.vue'
import InstallSnippet from './snippets/InstallSnippet.vue' import InstallSnippet from './snippets/InstallSnippet.vue'
export default { export default {
components: {vSelect,vCode,InstallSnippet}, components: {vSelect,vCode,InstallSnippet,Ajax},
data () { data () {
return { return {
countries, countries,
+122
View File
@@ -0,0 +1,122 @@
<style lang="scss">
.github-search {
&.panel-default {
border: none;
}
.panel-heading,
.panel-footer {
background: none;
}
.panel-heading {
padding: 0;
border: none;
}
.panel-body {
display: flex;
align-items: center;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
}
.panel-footer {
border: 1px solid #ddd;
}
p {
margin-bottom: 0;
}
.v-select .dropdown-toggle {
border-color: #ddd;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
padding: 5px;
}
.v-select .dropdown-toggle .open-indicator {
top: 15px;
right: 15px;
}
.v-select .selected-tag {
background: none;
border: none;
}
.gravatar {
max-width: 25px;
float: left;
margin-right: 1em;
}
img {
margin-bottom: 0;
}
.badge {
background: #7BC8A4;
}
.list-inline {
margin: 0;
}
}
</style>
<template>
<div>
<div class="github-search panel panel-default">
<div class="panel-heading">
<v-select :debounce="250" :value.sync="repo" :options="options" :on-search="getOptions" placeholder="Search GitHub Repositories..." label="full_name"></v-select>
</div>
<div class="panel-body" v-if="repo">
<img :src="repo.owner.avatar_url" alt="{{ repo.owner.login }}" class="gravatar">
<p>{{ repo.description }}</p>
</div>
<div class="panel-footer" v-if="repo">
<ul class="list-inline" role="tablist">
<li><a href="{{ repo.url }}">Stars <span class="badge">{{ repo.stargazers_count }}</span></a>
</li>
<li><a href="{{ repo.url }}">Forks <span class="badge">{{ repo.forks }}</span></a></li>
<li><a href="{{ repo.url }}">Open Issues
<span class="badge">{{ repo.open_issues_count }}</span></a></li>
</ul>
</div>
</div>
<div v-if="error" class="alert alert-warning" role="alert">
<button type="button" class="close" @click="error = null">
<span aria-hidden="true">&times;</span></button>
{{ error.message }}
</div>
</div>
</template>
<script type="text/babel">
export default {
data() {
return {
repo: null,
error: null,
options: null
}
},
methods: {
getOptions(search, loading) {
loading(true)
this.$http.get('https://api.github.com/search/repositories', {q: search})
.then(resp => {
this.options = resp.data.items
loading(false)
})
.catch(err => {
this.error = err.data
loading(false)
})
}
}
}
</script>
+38
View File
@@ -0,0 +1,38 @@
<template>
<div>
<p><v-select :debounce="250" :options="options" :on-search="getOptions" placeholder="Search GitHub Repositories..." label="full_name"></v-select></p>
<div v-if="error" class="alert alert-warning" role="alert">
<button type="button" class="close" @click="error = null">
<span aria-hidden="true">&times;</span></button>
{{ error.message }}
</div>
</div>
</template>
<script type="text/babel">
export default {
data() {
return {
repo: null,
error: null,
options: null
}
},
methods: {
getOptions(search, loading) {
loading(true)
this.$http.get('https://api.github.com/search/repositories', {q: search})
.then(resp => {
this.options = resp.data.items
loading(false)
})
.catch(err => {
this.error = err.data
loading(false)
})
}
}
}
</script>
+130
View File
@@ -0,0 +1,130 @@
<template>
<article class="example" id="ex-ajax">
<h3 id="ajax" class="page-header">AJAX Remote Option Loading</h3>
<div class="row">
<div class="col-md-6">
<p>
The <code>onSearch</code> prop allows you to load options via ajax in a parent component
when the search text is updated. It is invoked with two parameters, <code>search</code> &amp; <code>loading</code>.
</p>
<h4>onSearch Callback Parameters <small>search, loading</small></h4>
<p>
<code>search</code> is a string containing the current search text.
<code>loading</code> is a function that accepts a boolean value,
and is used to toggle the 'loading' class on the top-level vue-select wrapper.
</p>
<h4>Loading Spinner</h4>
<p>
Vue Select includes a default loading spinner that appears when the loading class is present.
The <code>spinner</code> slot allows you to implement your own spinner.
</p>
<div id="spinner-example" :class="{loading:spinner}">
<button class="btn btn-sm btn-default" @click="spinner = !spinner">Toggle Spinner</button>
<div class="spinner" v-show="spinner">Loading...</div>
</div>
<h4>Debounce Input</h4>
<p>
Vue Select also accepts a <code>debounce</code> prop that can be used to prevent
<code>onSearch</code> from being called until input has completed.
</p>
<h4>Library Agnostic</h4>
<p>
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.
</p>
</div>
<div class="col-md-6">
<h4>Example <small>GitHub API</small></h4>
<p>In this example,
<a href="https://github.com/vuejs/vue-resource">Vue Resource</a> is used to access the
<a href="https://developer.github.com/v3/">GitHub API</a>.
</p>
<git-hub-search-basic></git-hub-search-basic>
<ajax-example></ajax-example>
</div>
</div>
<div class="row">
<div class="col-md-6">
</div>
</div>
</div>
</article>
</template>
<style>
#spinner-example {
max-width: 10em;
display: block;
}
#spinner-example .spinner {
display: none;
display: inline-block;
float: right;
opacity: 0;
font-size: 5px;
text-indent: -9999em;
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;
}
#spinner-example.loading .spinner {
opacity: 1;
display: block;
}
#spinner-example .spinner,
#spinner-example .spinner:after {
border-radius: 50%;
width: 5em;
height: 5em;
}
@-webkit-keyframes vSelectSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes vSelectSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style>
<script type="text/babel">
import GitHubSearchBasic from 'components/GitHubSearchBasic.vue'
import GitHubSearch from 'components/GitHubSearch.vue'
import AjaxProps from './AjaxProps.vue'
import AjaxExample from './AjaxExample.vue'
export default {
components: {GitHubSearchBasic, GitHubSearch, AjaxProps, AjaxExample},
data() {
return {
basicSource: false,
spinner: false
}
}
}
</script>
+31
View File
@@ -0,0 +1,31 @@
<template>
<pre><v-code lang="markup">&lt;v-select
:debounce=&quot;250&quot;
:on-search=&quot;getOptions&quot;
:options=&quot;options&quot;
placeholder=&quot;Search GitHub Repositories...&quot;
label=&quot;full_name&quot;
&gt;
&lt;/v-select&gt;</v-code></pre>
<pre><v-code lang="javascript">data() {
return {
options: null
}
},
methods: {
getOptions(search, loading) {
loading(true)
this.$http.get('https://api.github.com/search/repositories', {
q: search
}).then(resp => {
this.options = resp.data.items
loading(false)
})
}
}
</v-code></pre>
</template>
<script type="text/babel">
export default {}
</script>
+28
View File
@@ -0,0 +1,28 @@
<template>
<pre><v-code lang="javascript">/**
* Accept 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(bool) Toggle loading class
*/
onSearch: {
type: Function,
default: false
},
/**
* Milliseconds to wait before invoking this.onSearch().
* Used to prevent sending an AJAX request until input
* has completed.
*/
debounce: {
type: Number,
default: 0
}</v-code></pre>
</template>
<script type="text/babel">
export default {}
</script>
+49
View File
@@ -0,0 +1,49 @@
import 'prismjs'
import Vue from 'vue'
import App from './Docs.vue'
import store from './vuex/store'
import Resource from 'vue-resource'
import vSelect from '../src/components/Select.vue'
import vCode from './components/Code.vue'
Vue.use(Resource)
Vue.component('v-select', vSelect)
Vue.component('v-code', vCode)
Vue.filter('score', function (value) {
return Math.round(value)
})
Vue.config.debug = true
Vue.config.devtools = true
import { setSelected, toggleMultiple, setPlaceholder, toggleOptionType } from './vuex/actions'
/* eslint-disable no-new */
new Vue({
el: 'body',
store,
components: { App },
vuex: {
getters: {
placeholder (store) {
return store.placeholder
},
selected (store) {
return store.selected
},
type (store) {
return store.optionType
},
options (store) {
return store.options[store.optionType]
},
multiple (store) {
return store.multiple
}
},
actions: { setSelected, toggleMultiple, setPlaceholder, toggleOptionType }
}
})
+2 -2
View File
@@ -10,8 +10,8 @@ const state = {
multiple: true, multiple: true,
maxHeight: '400px', maxHeight: '400px',
options: { options: {
advanced: require('../countries/advanced.js'), advanced: require('../data/advanced.js'),
simple: require('../countries/simple.js'), simple: require('../data/simple.js'),
}, },
optionType: 'advanced' optionType: 'advanced'
} }
+64 -9
View File
@@ -2,7 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Vue Select | VueJS Select2/Chosen Component</title> <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=Source+Sans+Pro:400,600|Roboto Mono" rel="stylesheet" type="text/css">
<link href="//fonts.googleapis.com/css?family=Dosis:300&amp;text=Vue Select" rel="stylesheet" type="text/css"> <link href="//fonts.googleapis.com/css?family=Dosis:300&amp;text=Vue Select" rel="stylesheet" type="text/css">
@@ -11,19 +11,74 @@
<meta name="title" content="Vue Select | VueJS Select2/Chosen Component"> <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."> <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/static/vue-logo.png" type="image/png"> <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 well-tested, native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery."> <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:title" content="Vue Select | VueJS Select2/Chosen Component">
<meta property="og:site_name" 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"> <meta property="og:url" content="http://sagalbot.github.io/vue-select/">
<meta property="og:description" content="A well-tested, native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.">
<meta property="og:image" content="http://sagalbot.github.io/vue-select/static/vue-logo.png">
<meta property="twitter:image" content="http://sagalbot.github.io/vue-select/static/vue-logo.png">
<meta property="twitter:title" content="Vue Select | VueJS Select2/Chosen Component">
<meta property="twitter:description" content="A well-tested, native Vue.js component that provides similar functionality to Select2/Chosen without the overhead of jQuery.">
</head> </head>
<body> <body>
<div class="jumbotron jumbotron-top">
<div class="container">
<div class="col-md-8 col-md-offset-2">
<h1>Vue Select</h1>
<p class="accolades lead">
<a href="https://travis-ci.org/sagalbot/vue-select"><img src="https://img.shields.io/travis/sagalbot/vue-select.svg?style=flat-square" alt="Build Status"></a>
<a href="https://codeclimate.com/github/sagalbot/vue-select"><img src="https://img.shields.io/codeclimate/coverage/github/sagalbot/vue-select.svg?style=flat-square" alt="Code Coverage"></a>
<a href="https://gemnasium.com/github.com/sagalbot/vue-select"><img src="https://img.shields.io/gemnasium/sagalbot/vue-select.svg?style=flat-square" alt="No Dependencies"></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 native Vue.js select component that provides similar functionality to Select2/Chosen without the overhead of jQuery.</p>
<v-select
id="v-select"
taggable
:placeholder="placeholder"
:value="selected"
:options="options"
:multiple="multiple"
:on-change="setSelected"
>
</v-select>
<div class="row">
<div class="col-md-3 col-md-offset-3">
<ul class="list-vue">
<li>Fully Reactive</li>
<li>Tagging Support <small>v1.1.0</small></li>
<li>Works with Vuex</li>
<li>Zero dependencies</li>
</ul>
</div>
<div class="col-md-3">
<ul class="list-vue">
<li>+95% Test Coverage</li>
<li>Select Single/Multiple</li>
<li>Typeahead Suggestions</li>
<li>Bootstrap Friendly Markup</li>
</ul>
</div>
</div>
<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>
</div>
</div>
<a href="#install" class="down-arrow">
Install, Examples &amp; Documentation
<i role="presentation" class="glyphicon glyphicon-chevron-down"></i>
</a>
</div>
<app></app> <app></app>
<script> <script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+2
View File
@@ -37,6 +37,7 @@
"extract-text-webpack-plugin": "^1.0.1", "extract-text-webpack-plugin": "^1.0.1",
"file-loader": "^0.8.4", "file-loader": "^0.8.4",
"function-bind": "^1.0.2", "function-bind": "^1.0.2",
"gh-pages": "^0.11.0",
"html-webpack-plugin": "^2.8.1", "html-webpack-plugin": "^2.8.1",
"http-proxy-middleware": "^0.15.2", "http-proxy-middleware": "^0.15.2",
"inject-loader": "^2.0.1", "inject-loader": "^2.0.1",
@@ -62,6 +63,7 @@
"vue-hot-reload-api": "^1.2.0", "vue-hot-reload-api": "^1.2.0",
"vue-html-loader": "^1.0.0", "vue-html-loader": "^1.0.0",
"vue-loader": "^8.3.0", "vue-loader": "^8.3.0",
"vue-resource": "^0.8.0",
"vue-style-loader": "^1.0.0", "vue-style-loader": "^1.0.0",
"vuex": "^0.6.3", "vuex": "^0.6.3",
"webpack": "^1.12.2", "webpack": "^1.12.2",
-116
View File
@@ -1,116 +0,0 @@
<style lang="scss">
@import 'assets/scss/_demo.scss';
@import 'assets/scss/_cyan_theme.scss';
@import 'assets/scss/_prism.scss';
@import 'assets/scss/_octicons.scss';
</style>
<template>
<div class="jumbotron jumbotron-top">
<div class="container">
<div class="col-md-8 col-md-offset-2">
<h1>Vue Select</h1>
<p class="accolades lead">
<a href="https://travis-ci.org/sagalbot/vue-select"><img src="https://img.shields.io/travis/sagalbot/vue-select.svg?style=flat-square" alt="Build Status"></a>
<a href="https://codeclimate.com/github/sagalbot/vue-select"><img src="https://img.shields.io/codeclimate/github/sagalbot/vue-select.svg?style=flat-square" alt="Code Climate Rating"></a>
<a href="https://codeclimate.com/github/sagalbot/vue-select"><img src="https://img.shields.io/codeclimate/coverage/github/sagalbot/vue-select.svg?style=flat-square" alt="Code Coverage"></a>
<a href="https://gemnasium.com/github.com/sagalbot/vue-select"><img src="https://img.shields.io/gemnasium/sagalbot/vue-select.svg?style=flat-square" alt="No Dependencies"></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 well-tested, native Vue.js select component that provides similar functionality to Select2/Chosen without the overhead of jQuery.</p>
<v-select
id="v-select"
taggable
:placeholder="placeholder"
:value="selected"
:options="options"
:multiple="multiple"
:on-change="setSelected"
>
</v-select>
<div class="row">
<div class="col-md-3 col-md-offset-3">
<ul class="list-vue">
<li>Fully Reactive</li>
<li>Tagging Support <small>v1.1.0</small></li>
<li>Works with Vuex</li>
<li>Zero dependencies</li>
</ul>
</div>
<div class="col-md-3">
<ul class="list-vue">
<li>+90% Test Coverage</li>
<li>Select Single/Multiple</li>
<li>Typeahead Suggestions</li>
<li>Bootstrap Friendly Markup</li>
</ul>
</div>
</div>
<a class="btn btn-primary btn-outline" href="https://github.com/sagalbot/vue-select"><span class="octicon octicon-mark-github"></span> View on GitHub</a>
</div>
</div>
<a href="#install" class="down-arrow">
Install, Examples &amp; Documentation
<i role="presentation" class="glyphicon glyphicon-chevron-down"></i>
</a>
</div>
<div class="container">
<div class="col-md-10 col-md-offset-1">
<install></install>
<params></params>
</div>
</div>
</template>
<script type="text/babel">
/**
* Note that this file (and anything other than src/components/Select.vue)
* has nothing to do with how you use vue-select. These files are used
* for the demo site at http://sagalbot.github.io/vue-select/. They'll
* be moved out of this repo in the very near future to avoid confusion.
*/
import Install from './components/Install.vue'
import Params from './components/Params.vue'
import vSelect from './components/Select.vue'
import { setSelected, toggleMultiple, setPlaceholder, toggleOptionType } from './vuex/actions'
export default {
components: { Params, Install, vSelect },
vuex: {
getters: {
placeholder (store) {
return store.placeholder
},
selected (store) {
return store.selected
},
type (store) {
return store.optionType
},
options (store) {
return store.options[store.optionType]
},
multiple (store) {
return store.multiple
}
},
actions: { setSelected, toggleMultiple, setPlaceholder, toggleOptionType }
},
methods: {
onPlaceholderChange ( e ) {
this.setPlaceholder( e.target.value )
}
}
}
</script>
Binary file not shown.
+58 -4
View File
@@ -1,5 +1,5 @@
<style> <style>
.v-select.dropdown { .v-select {
position: relative; position: relative;
} }
@@ -12,6 +12,12 @@
pointer-events: all; pointer-events: all;
transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855); transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855); transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
opacity: 1;
transition: opacity .1s;
}
.v-select.loading .open-indicator {
opacity: 0;
} }
.v-select .open-indicator:before { .v-select .open-indicator:before {
@@ -116,6 +122,47 @@
background: #f0f0f0; background: #f0f0f0;
color: #333; color: #333;
} }
.v-select .spinner {
opacity: 0;
position: absolute;
top: 5px;
right: 10px;
font-size: 5px;
text-indent: -9999em;
border-top: .9em solid rgba(100,100,100,.1);
border-right: .9em solid rgba(100,100,100,.1);
border-bottom: .9em solid rgba(100,100,100,.1);
border-left: .9em solid rgba(60,60,60,.45);
transform: translateZ(0);
animation: vSelectSpinner 1.1s infinite linear;
transition: opacity .1s;
}
.v-select.loading .spinner {
opacity: 1;
}
.v-select .spinner,
.v-select .spinner:after {
border-radius: 50%;
width: 5em;
height: 5em;
}
@-webkit-keyframes vSelectSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes vSelectSpinner {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style> </style>
<template> <template>
@@ -134,8 +181,9 @@
<input <input
v-el:search v-el:search
v-show="searchable" :debounce="debounce"
v-model="search" v-model="search"
v-show="searchable"
@keydown.delete="maybeDeleteValue" @keydown.delete="maybeDeleteValue"
@keyup.esc="onEscape" @keyup.esc="onEscape"
@keydown.up.prevent="typeAheadUp" @keydown.up.prevent="typeAheadUp"
@@ -150,6 +198,10 @@
> >
<i v-el:open-indicator role="presentation" class="open-indicator"></i> <i v-el:open-indicator role="presentation" class="open-indicator"></i>
<slot name="spinner">
<div class="spinner" v-show="onSearch && loading">Loading...</div>
</slot>
</div> </div>
<ul v-el:dropdown-menu v-show="open" :transition="transition" class="dropdown-menu" :style="{ 'max-height': maxHeight }"> <ul v-el:dropdown-menu v-show="open" :transition="transition" class="dropdown-menu" :style="{ 'max-height': maxHeight }">
@@ -170,9 +222,10 @@
<script type="text/babel"> <script type="text/babel">
import pointerScroll from '../mixins/pointerScroll' import pointerScroll from '../mixins/pointerScroll'
import typeAheadPointer from '../mixins/typeAheadPointer' import typeAheadPointer from '../mixins/typeAheadPointer'
import ajax from '../mixins/ajax'
export default { export default {
mixins: [pointerScroll, typeAheadPointer], mixins: [pointerScroll, typeAheadPointer, ajax],
props: { props: {
/** /**
@@ -492,7 +545,8 @@
dropdownClasses() { dropdownClasses() {
return { return {
open: this.open, open: this.open,
searchable: this.searchable searchable: this.searchable,
loading: this.loading
} }
}, },
-14
View File
@@ -1,14 +0,0 @@
import Vue from 'vue'
import App from './App.vue'
import store from './vuex/store'
import 'prismjs'
// Vue.config.debug = true
Vue.config.devtools = true
/* eslint-disable no-new */
new Vue({
el: 'body',
store,
components: { App }
})
+67
View File
@@ -0,0 +1,67 @@
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: false
},
/**
* The number of milliseconds to wait before
* invoking this.onSearch(). Used to prevent
* sending an AJAX request until input is complete.
*/
debounce: {
type: Number,
default: 0
}
},
watch: {
/**
* If a callback & search text has been provided,
* invoke the onSearch callback.
*/
search() {
if (this.search.length > 0 && this.onSearch) {
this.onSearch(this.search, this.toggleLoading)
}
},
},
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.loading = !this.loading
}
return this.loading = toggle
}
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long