mirror of
https://github.com/tenrok/vue-select.git
synced 2026-06-16 09:10:33 +03:00
Sass & Class Renames (#759)
* - add autoprefixer - add cssnano - add postcss-loader - remove unused packages * create RTL scss module * add vs__ prefix to open-indicator, extract to module * module for dropdown-toggle * vs__clear module * vs__dropdown-menu module * rename `selected-tag` to `vs__selected` * remove rtl class * remove dropdown class * search-input scss module * move animations to global module * refactor dropdown list items * - spinner slot is now scoped with `loading` variable - move spinner to scss module * apply vs__search class directly to search input: if you're using the slot, you might not want default styles * finish global modules * make RTL a component state * - update component states to use vs-- prefix - rename dropdownClasses to stateClasses * remove unused property * Closes #760 * fix states * more state fixes * rename .close to vs__deselect * - simplify dev.html - start on 'sandbox' development * update build * - update webpack config - move Sandbox to VuePress folder * update external framework version links * assign grid areas, ensure 100% height outside of docs * limit specificity * first pass at assigning variables * assign 'darkest' * remove max-height prop * rename 'component' variables to 'state' * update badges * add deprecation notice to docs * bump travis config * add coveralls coverage reporter * bump netlify config * additional pass pulling up to variables * start converting to SVG icons * middle align action icons * update netlify config * netlify bump * fix travis * fix travis * try lcov * netlify attempt * prune old packages * bump travis config
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10">
|
||||
<path d="M6.895455 5l2.842897-2.842898c.348864-.348863.348864-.914488 0-1.263636L9.106534.261648c-.348864-.348864-.914489-.348864-1.263636 0L5 3.104545 2.157102.261648c-.348863-.348864-.914488-.348864-1.263636 0L.261648.893466c-.348864.348864-.348864.914489 0 1.263636L3.104545 5 .261648 7.842898c-.348864.348863-.348864.914488 0 1.263636l.631818.631818c.348864.348864.914773.348864 1.263636 0L5 6.895455l2.842898 2.842897c.348863.348864.914772.348864 1.263636 0l.631818-.631818c.348864-.348864.348864-.914489 0-1.263636L6.895455 5z"/>
|
||||
</svg>
|
||||
</template>
|
||||
@@ -0,0 +1,5 @@
|
||||
<template>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="10">
|
||||
<path d="M9.211364 7.59931l4.48338-4.867229c.407008-.441854.407008-1.158247 0-1.60046l-.73712-.80023c-.407008-.441854-1.066904-.441854-1.474243 0L7 5.198617 2.51662.33139c-.407008-.441853-1.066904-.441853-1.474243 0l-.737121.80023c-.407008.441854-.407008 1.158248 0 1.600461l4.48338 4.867228L7 10l2.211364-2.40069z"/>
|
||||
</svg>
|
||||
</template>
|
||||
+52
-351
@@ -1,363 +1,69 @@
|
||||
<style>
|
||||
.v-select {
|
||||
position: relative;
|
||||
font-family: inherit;
|
||||
}
|
||||
.v-select,
|
||||
.v-select * {
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* Rtl support - Because we're using a flexbox-based layout, the `dir="rtl"` HTML
|
||||
attribute does most of the work for us by rearranging the child elements visually.
|
||||
*/
|
||||
.v-select[dir="rtl"] .vs__actions {
|
||||
padding: 0 3px 0 6px;
|
||||
}
|
||||
.v-select[dir="rtl"] .dropdown-toggle .clear {
|
||||
margin-left: 6px;
|
||||
margin-right: 0;
|
||||
}
|
||||
.v-select[dir="rtl"] .selected-tag .close {
|
||||
margin-left: 0;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.v-select[dir="rtl"] .dropdown-menu {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
/* Open Indicator */
|
||||
.v-select .open-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
||||
transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
||||
opacity: 1;
|
||||
width: 12px; /* To account for extra width from rotating. */
|
||||
}
|
||||
.v-select .open-indicator:before {
|
||||
border-color: rgba(60, 60, 60, .5);
|
||||
border-style: solid;
|
||||
border-width: 3px 3px 0 0;
|
||||
content: '';
|
||||
display: inline-block;
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
vertical-align: text-top;
|
||||
transform: rotate(133deg);
|
||||
transition: all 150ms cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
||||
transition-timing-function: cubic-bezier(1.000, -0.115, 0.975, 0.855);
|
||||
box-sizing: inherit;
|
||||
}
|
||||
/* Open Indicator States */
|
||||
.v-select.open .open-indicator:before {
|
||||
transform: rotate(315deg);
|
||||
}
|
||||
.v-select.loading .open-indicator {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Dropdown Toggle */
|
||||
.v-select .dropdown-toggle {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
display: flex;
|
||||
padding: 0 0 4px 0;
|
||||
background: none;
|
||||
border: 1px solid rgba(60, 60, 60, .26);
|
||||
border-radius: 4px;
|
||||
white-space: normal;
|
||||
}
|
||||
.v-select .vs__selected-options {
|
||||
display: flex;
|
||||
flex-basis: 100%;
|
||||
flex-grow: 1;
|
||||
flex-wrap: wrap;
|
||||
padding: 0 2px;
|
||||
position: relative;
|
||||
}
|
||||
.v-select .vs__actions {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
padding: 0 6px 0 3px;
|
||||
}
|
||||
|
||||
/* Clear Button */
|
||||
.v-select .dropdown-toggle .clear {
|
||||
font-size: 23px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
color: rgba(60, 60, 60, 0.5);
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
/* Dropdown Toggle States */
|
||||
.v-select.searchable .dropdown-toggle {
|
||||
cursor: text;
|
||||
}
|
||||
.v-select.unsearchable .dropdown-toggle {
|
||||
cursor: pointer;
|
||||
}
|
||||
.v-select.open .dropdown-toggle {
|
||||
border-bottom-color: transparent;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
/* Dropdown Menu */
|
||||
.v-select .dropdown-menu {
|
||||
display:block;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
z-index: 1000;
|
||||
min-width: 160px;
|
||||
padding: 5px 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
overflow-y: auto;
|
||||
border: 1px solid rgba(0, 0, 0, .26);
|
||||
box-shadow: 0px 3px 6px 0px rgba(0,0,0,.15);
|
||||
border-top: none;
|
||||
border-radius: 0 0 4px 4px;
|
||||
text-align: left;
|
||||
list-style: none;
|
||||
background: #fff;
|
||||
}
|
||||
.v-select .no-options {
|
||||
text-align: center;
|
||||
}
|
||||
/* Selected Tags */
|
||||
.v-select .selected-tag {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
color: #333;
|
||||
line-height: 1.42857143; /* Normalize line height */
|
||||
margin: 4px 2px 0px 2px;
|
||||
padding: 0 0.25em;
|
||||
transition: opacity .25s;
|
||||
}
|
||||
.v-select.single .selected-tag {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
}
|
||||
.v-select.single.open .selected-tag {
|
||||
position: absolute;
|
||||
opacity: .4;
|
||||
}
|
||||
.v-select.single.searching .selected-tag {
|
||||
display: none;
|
||||
}
|
||||
.v-select .selected-tag .close {
|
||||
margin-left: 2px;
|
||||
font-size: 1.25em;
|
||||
appearance: none;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
background: 0 0;
|
||||
border: 0;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
color: #000;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
filter: alpha(opacity=20);
|
||||
opacity: .2;
|
||||
}
|
||||
.v-select.single.searching:not(.open):not(.loading) input[type="search"] {
|
||||
opacity: .2;
|
||||
}
|
||||
/* Search Input */
|
||||
.v-select input[type="search"]::-webkit-search-decoration,
|
||||
.v-select input[type="search"]::-webkit-search-cancel-button,
|
||||
.v-select input[type="search"]::-webkit-search-results-button,
|
||||
.v-select input[type="search"]::-webkit-search-results-decoration {
|
||||
display: none;
|
||||
}
|
||||
.v-select input[type="search"]::-ms-clear {
|
||||
display: none;
|
||||
}
|
||||
.v-select input[type="search"],
|
||||
.v-select input[type="search"]:focus {
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
line-height: 1.42857143;
|
||||
font-size: 1em;
|
||||
display: inline-block;
|
||||
border: 1px solid transparent;
|
||||
border-left: none;
|
||||
outline: none;
|
||||
margin: 4px 0 0 0;
|
||||
padding: 0 7px;
|
||||
max-width: 100%;
|
||||
background: none;
|
||||
box-shadow: none;
|
||||
flex-grow: 1;
|
||||
width: 0;
|
||||
}
|
||||
.v-select.unsearchable input[type="search"] {
|
||||
opacity: 0;
|
||||
}
|
||||
.v-select.unsearchable input[type="search"]:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* List Items */
|
||||
.v-select li {
|
||||
line-height: 1.42857143; /* Normalize line height */
|
||||
}
|
||||
.v-select li > a {
|
||||
display: block;
|
||||
padding: 3px 20px;
|
||||
clear: both;
|
||||
color: #333; /* Overrides most CSS frameworks */
|
||||
white-space: nowrap;
|
||||
}
|
||||
.v-select li:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.v-select .dropdown-menu .active > a {
|
||||
color: #333;
|
||||
background: rgba(50, 50, 50, .1);
|
||||
}
|
||||
.v-select .dropdown-menu > .highlight > a {
|
||||
/*
|
||||
* required to override bootstrap 3's
|
||||
* .dropdown-menu > li > a:hover {} styles
|
||||
*/
|
||||
background: #5897fb;
|
||||
color: #fff;
|
||||
}
|
||||
.v-select .highlight:not(:last-child) {
|
||||
margin-bottom: 0; /* Fixes Bulma Margin */
|
||||
}
|
||||
/* Loading Spinner */
|
||||
.v-select .spinner {
|
||||
align-self: center;
|
||||
opacity: 0;
|
||||
font-size: 5px;
|
||||
text-indent: -9999em;
|
||||
overflow: hidden;
|
||||
border-top: .9em solid rgba(100, 100, 100, .1);
|
||||
border-right: .9em solid rgba(100, 100, 100, .1);
|
||||
border-bottom: .9em solid rgba(100, 100, 100, .1);
|
||||
border-left: .9em solid rgba(60, 60, 60, .45);
|
||||
transform: translateZ(0);
|
||||
animation: vSelectSpinner 1.1s infinite linear;
|
||||
transition: opacity .1s;
|
||||
}
|
||||
.v-select .spinner,
|
||||
.v-select .spinner:after {
|
||||
border-radius: 50%;
|
||||
width: 5em;
|
||||
height: 5em;
|
||||
}
|
||||
|
||||
/* Disabled state */
|
||||
.v-select.disabled .dropdown-toggle,
|
||||
.v-select.disabled .dropdown-toggle .clear,
|
||||
.v-select.disabled .dropdown-toggle input,
|
||||
.v-select.disabled .selected-tag .close,
|
||||
.v-select.disabled .open-indicator {
|
||||
cursor: not-allowed;
|
||||
background-color: rgb(248, 248, 248);
|
||||
}
|
||||
|
||||
/* Loading Spinner States */
|
||||
.v-select.loading .spinner {
|
||||
opacity: 1;
|
||||
}
|
||||
/* KeyFrames */
|
||||
@-webkit-keyframes vSelectSpinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
@keyframes vSelectSpinner {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* Dropdown Default Transition */
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity .15s cubic-bezier(1.0, 0.5, 0.8, 1.0);
|
||||
}
|
||||
.fade-enter,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
<style lang="scss">
|
||||
@import '../scss/vue-select.scss';
|
||||
</style>
|
||||
|
||||
<template>
|
||||
<div :dir="dir" class="dropdown v-select" :class="dropdownClasses">
|
||||
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="dropdown-toggle">
|
||||
<div :dir="dir" class="v-select" :class="stateClasses">
|
||||
<div ref="toggle" @mousedown.prevent="toggleDropdown" class="vs__dropdown-toggle">
|
||||
|
||||
<div class="vs__selected-options" ref="selectedOptions">
|
||||
<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 v-for="option in valueAsArray"
|
||||
name="selected-option-container"
|
||||
:option="(typeof option === 'object')?option:{[label]: option}"
|
||||
:deselect="deselect"
|
||||
:multiple="multiple"
|
||||
:disabled="disabled">
|
||||
<span class="vs__selected" v-bind:key="option.index">
|
||||
<slot name="selected-option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||
{{ 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 v-if="multiple" :disabled="disabled" @click="deselect(option)" type="button" class="vs__deselect" aria-label="Deselect option">
|
||||
<deselect />
|
||||
</button>
|
||||
</span>
|
||||
</slot>
|
||||
|
||||
<slot name="search" v-bind="scope.search">
|
||||
<input v-bind="scope.search.attributes" v-on="scope.search.events">
|
||||
<input class="vs__search" v-bind="scope.search.attributes" v-on="scope.search.events">
|
||||
</slot>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="vs__actions">
|
||||
<button
|
||||
v-show="showClearButton"
|
||||
:disabled="disabled"
|
||||
@click="clearSelection"
|
||||
type="button"
|
||||
class="clear"
|
||||
class="vs__clear"
|
||||
title="Clear selection"
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
<deselect />
|
||||
</button>
|
||||
|
||||
<i v-if="!noDrop" ref="openIndicator" role="presentation" class="open-indicator"></i>
|
||||
<open-indicator v-if="!noDrop" ref="openIndicator" role="presentation" class="vs__open-indicator" />
|
||||
|
||||
<slot name="spinner">
|
||||
<div class="spinner" v-show="mutableLoading">Loading...</div>
|
||||
<slot name="spinner" v-bind="scope.spinner">
|
||||
<div class="vs__spinner" v-show="mutableLoading">Loading...</div>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<transition :name="transition">
|
||||
<ul ref="dropdownMenu" v-if="dropdownOpen" class="dropdown-menu" :style="{ 'max-height': maxHeight }" role="listbox" @mousedown="onMousedown">
|
||||
<li role="option" v-for="(option, index) in filteredOptions" v-bind:key="index" :class="{ active: isOptionSelected(option), highlight: index === typeAheadPointer }" @mouseover="typeAheadPointer = index">
|
||||
<a @mousedown.prevent.stop="select(option)">
|
||||
<ul ref="dropdownMenu" v-if="dropdownOpen" class="vs__dropdown-menu" role="listbox" @mousedown="onMousedown">
|
||||
<li
|
||||
role="option"
|
||||
v-for="(option, index) in filteredOptions"
|
||||
:key="index"
|
||||
class="vs__dropdown-option"
|
||||
:class="{ active: isOptionSelected(option), 'vs__dropdown-option--highlight': index === typeAheadPointer }"
|
||||
@mouseover="typeAheadPointer = index"
|
||||
@mousedown.prevent.stop="select(option)"
|
||||
>
|
||||
<slot name="option" v-bind="(typeof option === 'object')?option:{[label]: option}">
|
||||
{{ getOptionLabel(option) }}
|
||||
</slot>
|
||||
</a>
|
||||
</li>
|
||||
<li v-if="!filteredOptions.length" class="no-options" @mousedown.stop="">
|
||||
<li v-if="!filteredOptions.length" class="vs__no-options" @mousedown.stop="">
|
||||
<slot name="no-options">Sorry, no matching options.</slot>
|
||||
</li>
|
||||
</ul>
|
||||
@@ -369,8 +75,12 @@
|
||||
import pointerScroll from '../mixins/pointerScroll'
|
||||
import typeAheadPointer from '../mixins/typeAheadPointer'
|
||||
import ajax from '../mixins/ajax'
|
||||
import Deselect from './Deselect'
|
||||
import OpenIndicator from './OpenIndicator'
|
||||
|
||||
export default {
|
||||
components: {Deselect, OpenIndicator},
|
||||
|
||||
mixins: [pointerScroll, typeAheadPointer, ajax],
|
||||
|
||||
props: {
|
||||
@@ -416,16 +126,6 @@
|
||||
default: true
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the max-height property on the dropdown list.
|
||||
* @deprecated
|
||||
* @type {String}
|
||||
*/
|
||||
maxHeight: {
|
||||
type: String,
|
||||
default: '400px'
|
||||
},
|
||||
|
||||
/**
|
||||
* Enable/disable filtering the options.
|
||||
* @type {Boolean}
|
||||
@@ -454,13 +154,12 @@
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets a Vue transition property on the `.dropdown-menu`. vue-select
|
||||
* does not include CSS for transitions, you'll need to add them yourself.
|
||||
* Sets a Vue transition property on the `.vs__dropdown-menu`.
|
||||
* @type {String}
|
||||
*/
|
||||
transition: {
|
||||
type: String,
|
||||
default: 'fade'
|
||||
default: 'vs__fade'
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -902,7 +601,7 @@
|
||||
*/
|
||||
toggleDropdown(e) {
|
||||
if (e.target === this.$refs.openIndicator || e.target === this.searchEl || e.target === this.$refs.toggle ||
|
||||
e.target.classList.contains('selected-tag') || e.target === this.$el) {
|
||||
e.target.classList.contains('vs__selected') || e.target === this.$el) {
|
||||
if (this.open) {
|
||||
this.searchEl.blur() // dropdown will close on blur
|
||||
} else {
|
||||
@@ -1147,7 +846,7 @@
|
||||
'role': 'combobox',
|
||||
'type': 'search',
|
||||
'autocomplete': 'off',
|
||||
'class': 'form-control',
|
||||
'value': this.search,
|
||||
},
|
||||
events: {
|
||||
'keydown': this.onSearchKeyDown,
|
||||
@@ -1157,23 +856,25 @@
|
||||
'input': (e) => this.search = e.target.value,
|
||||
},
|
||||
},
|
||||
spinner: {
|
||||
loading: this.mutableLoading
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Classes to be output on .dropdown
|
||||
* Holds the current state of the component.
|
||||
* @return {Object}
|
||||
*/
|
||||
dropdownClasses() {
|
||||
stateClasses() {
|
||||
return {
|
||||
open: this.dropdownOpen,
|
||||
single: !this.multiple,
|
||||
searching: this.searching,
|
||||
searchable: this.searchable,
|
||||
unsearchable: !this.searchable,
|
||||
loading: this.mutableLoading,
|
||||
rtl: this.dir === 'rtl', // This can be removed - styling is handled by `dir="rtl"` attribute
|
||||
disabled: this.disabled
|
||||
'vs--open': this.dropdownOpen,
|
||||
'vs--single': !this.multiple,
|
||||
'vs--searching': this.searching,
|
||||
'vs--searchable': this.searchable,
|
||||
'vs--unsearchable': !this.searchable,
|
||||
'vs--loading': this.mutableLoading,
|
||||
'vs--disabled': this.disabled
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1191,7 +892,7 @@
|
||||
* @return {Boolean} True if non empty value
|
||||
*/
|
||||
searching() {
|
||||
return !!this.search
|
||||
return !! this.search
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user