parent
8773a560bd
commit
72ae76bd5f
@ -0,0 +1,884 @@ |
|||||||
|
<template> |
||||||
|
<div |
||||||
|
v-clickoutside="handleClose" |
||||||
|
class="el-select" |
||||||
|
:class="[selectSize ? 'el-select--' + selectSize : '']" |
||||||
|
@click.stop="toggleMenu" |
||||||
|
> |
||||||
|
<div |
||||||
|
v-if="multiple" |
||||||
|
ref="tags" |
||||||
|
class="el-select__tags" |
||||||
|
:style="{ 'max-width': inputWidth - 32 + 'px', width: '100%' }" |
||||||
|
> |
||||||
|
|
||||||
|
<span v-if="collapseTags && selected.length"> |
||||||
|
<el-tag |
||||||
|
:closable="!selectDisabled" |
||||||
|
:size="collapseTagSize" |
||||||
|
:hit="selected[0].hitState" |
||||||
|
type="info" |
||||||
|
@close="deleteTag($event, selected[0])" |
||||||
|
disable-transitions |
||||||
|
> |
||||||
|
<span class="el-select__tags-text">{{ selected[0].currentLabel }}</span> |
||||||
|
</el-tag> |
||||||
|
<el-tag |
||||||
|
v-if="selected.length > 1" |
||||||
|
:closable="false" |
||||||
|
:size="collapseTagSize" |
||||||
|
type="info" |
||||||
|
disable-transitions |
||||||
|
> |
||||||
|
<span class="el-select__tags-text">+ {{ selected.length - 1 }}</span> |
||||||
|
</el-tag> |
||||||
|
</span> |
||||||
|
<transition-group @after-leave="resetInputHeight" v-if="!collapseTags"> |
||||||
|
<el-tag |
||||||
|
v-for="item in selected" |
||||||
|
:key="getValueKey(item)" |
||||||
|
:closable="!selectDisabled" |
||||||
|
:size="collapseTagSize" |
||||||
|
:hit="item.hitState" |
||||||
|
type="info" |
||||||
|
@close="deleteTag($event, item)" |
||||||
|
disable-transitions |
||||||
|
> |
||||||
|
<span class="el-select__tags-text">{{ item.currentLabel }}</span> |
||||||
|
</el-tag> |
||||||
|
</transition-group> |
||||||
|
<input |
||||||
|
type="text" |
||||||
|
class="el-select__input" |
||||||
|
:class="[selectSize ? `is-${ selectSize }` : '']" |
||||||
|
:disabled="selectDisabled" |
||||||
|
:autocomplete="autocomplete" |
||||||
|
@focus="handleFocus" |
||||||
|
@blur="softFocus = false" |
||||||
|
@keyup="managePlaceholder" |
||||||
|
@keydown="resetInputState" |
||||||
|
@keydown.down.prevent="navigateOptions('next')" |
||||||
|
@keydown.up.prevent="navigateOptions('prev')" |
||||||
|
@keydown.enter.prevent="selectOption" |
||||||
|
@keydown.esc.stop.prevent="visible = false" |
||||||
|
@keydown.delete="deletePrevTag" |
||||||
|
@keydown.tab="visible = false" |
||||||
|
@compositionstart="handleComposition" |
||||||
|
@compositionupdate="handleComposition" |
||||||
|
@compositionend="handleComposition" |
||||||
|
v-model="query" |
||||||
|
@input="debouncedQueryChange" |
||||||
|
v-if="filterable" |
||||||
|
:style="{ 'flex-grow': '1', width: inputLength / (inputWidth - 32) + '%', 'max-width': inputWidth - 42 + 'px' }" |
||||||
|
ref="input"> |
||||||
|
</div> |
||||||
|
<el-input |
||||||
|
ref="reference" |
||||||
|
v-model="selectedLabel" |
||||||
|
type="text" |
||||||
|
:placeholder="currentPlaceholder" |
||||||
|
:name="name" |
||||||
|
:id="id" |
||||||
|
:autocomplete="autocomplete" |
||||||
|
:size="selectSize" |
||||||
|
:disabled="selectDisabled" |
||||||
|
:readonly="readonly" |
||||||
|
:validate-event="false" |
||||||
|
:class="{ 'is-focus': visible }" |
||||||
|
:tabindex="(multiple && filterable) ? '-1' : null" |
||||||
|
@focus="handleFocus" |
||||||
|
@blur="handleBlur" |
||||||
|
@keyup.native="debouncedOnInputChange" |
||||||
|
@keydown.native.down.stop.prevent="navigateOptions('next')" |
||||||
|
@keydown.native.up.stop.prevent="navigateOptions('prev')" |
||||||
|
@keydown.native.enter.prevent="selectOption" |
||||||
|
@keydown.native.esc.stop.prevent="visible = false" |
||||||
|
@keydown.native.tab="visible = false" |
||||||
|
@paste.native="debouncedOnInputChange" |
||||||
|
@mouseenter.native="inputHovering = true" |
||||||
|
@mouseleave.native="inputHovering = false"> |
||||||
|
<template slot="prefix" v-if="$slots.prefix"> |
||||||
|
<slot name="prefix"/> |
||||||
|
</template> |
||||||
|
<template slot="suffix"> |
||||||
|
<i v-show="!showClose" :class="['el-select__caret', 'el-input__icon', 'el-icon-' + iconClass]"/> |
||||||
|
<i v-if="showClose" class="el-select__caret el-input__icon el-icon-circle-close" |
||||||
|
@click="handleClearClick"/> |
||||||
|
</template> |
||||||
|
</el-input> |
||||||
|
<transition name="el-zoom-in-top" @before-enter="handleMenuEnter" @after-leave="doDestroy"> |
||||||
|
<el-select-menu |
||||||
|
v-show="visible && emptyText !== false" |
||||||
|
placement="bottom" |
||||||
|
:append-to-body="popperAppendToBody" |
||||||
|
> |
||||||
|
<el-scrollbar |
||||||
|
ref="scrollbar" |
||||||
|
v-show="options.length > 0 && !loading" |
||||||
|
:class="{ 'is-empty': !allowCreate && query && filteredOptionsCount === 0 }" |
||||||
|
tag="ul" |
||||||
|
wrap-class="el-select-dropdown__wrap" |
||||||
|
view-class="el-select-dropdown__list" |
||||||
|
> |
||||||
|
<el-option v-if="showNewOption" :value="query" created/> |
||||||
|
<slot/> |
||||||
|
</el-scrollbar> |
||||||
|
<template v-if="emptyText && (!allowCreate || loading || (allowCreate && options.length === 0 ))"> |
||||||
|
<slot name="empty" v-if="$slots.empty"/> |
||||||
|
<p class="el-select-dropdown__empty" v-else>{{ emptyText }}</p> |
||||||
|
</template> |
||||||
|
</el-select-menu> |
||||||
|
</transition> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script> |
||||||
|
import Emitter from 'element-ui/lib/mixins/emitter' |
||||||
|
import Focus from 'element-ui/lib/mixins/focus' |
||||||
|
import Locale from 'element-ui/lib/mixins/locale' |
||||||
|
import ElSelectMenu from './SelectDropdown.vue' |
||||||
|
import {debounce} from '@/utils' |
||||||
|
import Clickoutside from 'element-ui/lib/utils/clickoutside' |
||||||
|
import {addResizeListener, removeResizeListener} from 'element-ui/lib/utils/resize-event' |
||||||
|
import {t} from 'element-ui/lib/locale' |
||||||
|
import scrollIntoView from 'element-ui/lib/utils/scroll-into-view' |
||||||
|
import {getValueByPath, isEdge, isIE, valueEquals} from 'element-ui/lib/utils/util' |
||||||
|
import NavigationMixin from 'element-ui/packages/select/src/navigation-mixin' |
||||||
|
import {isKorean} from 'element-ui/lib/utils/shared' |
||||||
|
|
||||||
|
export default { |
||||||
|
mixins: [Emitter, Locale, Focus('reference'), NavigationMixin], |
||||||
|
|
||||||
|
name: 'ElSelect', |
||||||
|
|
||||||
|
componentName: 'ElSelect', |
||||||
|
|
||||||
|
inject: { |
||||||
|
elForm: { |
||||||
|
default: '' |
||||||
|
}, |
||||||
|
|
||||||
|
elFormItem: { |
||||||
|
default: '' |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
provide() { |
||||||
|
return { |
||||||
|
'select': this |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
components: {ElSelectMenu}, |
||||||
|
|
||||||
|
directives: {Clickoutside}, |
||||||
|
|
||||||
|
props: { |
||||||
|
name: String, |
||||||
|
id: String, |
||||||
|
value: { |
||||||
|
required: true |
||||||
|
}, |
||||||
|
autocomplete: { |
||||||
|
type: String, |
||||||
|
default: 'off' |
||||||
|
}, |
||||||
|
automaticDropdown: Boolean, |
||||||
|
size: String, |
||||||
|
disabled: Boolean, |
||||||
|
clearable: Boolean, |
||||||
|
filterable: Boolean, |
||||||
|
allowCreate: Boolean, |
||||||
|
loading: Boolean, |
||||||
|
popperClass: String, |
||||||
|
remote: Boolean, |
||||||
|
loadingText: String, |
||||||
|
noMatchText: String, |
||||||
|
noDataText: String, |
||||||
|
remoteMethod: Function, |
||||||
|
filterMethod: Function, |
||||||
|
multiple: Boolean, |
||||||
|
multipleLimit: { |
||||||
|
type: Number, |
||||||
|
default: 0 |
||||||
|
}, |
||||||
|
placeholder: { |
||||||
|
type: String, |
||||||
|
default() { |
||||||
|
return t('el.select.placeholder') |
||||||
|
} |
||||||
|
}, |
||||||
|
defaultFirstOption: Boolean, |
||||||
|
reserveKeyword: Boolean, |
||||||
|
valueKey: { |
||||||
|
type: String, |
||||||
|
default: 'value' |
||||||
|
}, |
||||||
|
collapseTags: Boolean, |
||||||
|
popperAppendToBody: Boolean |
||||||
|
}, |
||||||
|
|
||||||
|
data() { |
||||||
|
return { |
||||||
|
options: [], |
||||||
|
cachedOptions: [], |
||||||
|
createdLabel: null, |
||||||
|
createdSelected: false, |
||||||
|
selected: this.multiple ? [] : {}, |
||||||
|
inputLength: 20, |
||||||
|
inputWidth: 0, |
||||||
|
initialInputHeight: 0, |
||||||
|
cachedPlaceHolder: '', |
||||||
|
optionsCount: 0, |
||||||
|
filteredOptionsCount: 0, |
||||||
|
visible: false, |
||||||
|
softFocus: false, |
||||||
|
selectedLabel: '', |
||||||
|
hoverIndex: -1, |
||||||
|
query: '', |
||||||
|
previousQuery: null, |
||||||
|
inputHovering: false, |
||||||
|
currentPlaceholder: '', |
||||||
|
menuVisibleOnFocus: false, |
||||||
|
isOnComposition: false, |
||||||
|
isSilentBlur: false |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
computed: { |
||||||
|
_elFormItemSize() { |
||||||
|
return (this.elFormItem || {}).elFormItemSize |
||||||
|
}, |
||||||
|
|
||||||
|
readonly() { |
||||||
|
return !this.filterable || this.multiple || (!isIE() && !isEdge() && !this.visible) |
||||||
|
}, |
||||||
|
|
||||||
|
showClose() { |
||||||
|
let hasValue = this.multiple |
||||||
|
? Array.isArray(this.value) && this.value.length > 0 |
||||||
|
: this.value !== undefined && this.value !== null && this.value !== '' |
||||||
|
return this.clearable && |
||||||
|
!this.selectDisabled && |
||||||
|
this.inputHovering && |
||||||
|
hasValue |
||||||
|
}, |
||||||
|
|
||||||
|
iconClass() { |
||||||
|
return this.remote && this.filterable ? '' : (this.visible ? 'arrow-up is-reverse' : 'arrow-up') |
||||||
|
}, |
||||||
|
|
||||||
|
debounce() { |
||||||
|
return this.remote ? 300 : 0 |
||||||
|
}, |
||||||
|
|
||||||
|
emptyText() { |
||||||
|
if (this.loading) { |
||||||
|
return this.loadingText || this.t('el.select.loading') |
||||||
|
} |
||||||
|
else { |
||||||
|
if (this.remote && this.query === '' && this.options.length === 0) return false |
||||||
|
if (this.filterable && this.query && this.options.length > 0 && this.filteredOptionsCount === 0) { |
||||||
|
return this.noMatchText || this.t('el.select.noMatch') |
||||||
|
} |
||||||
|
if (this.options.length === 0) { |
||||||
|
return this.noDataText || this.t('el.select.noData') |
||||||
|
} |
||||||
|
} |
||||||
|
return null |
||||||
|
}, |
||||||
|
|
||||||
|
showNewOption() { |
||||||
|
let hasExistingOption = this.options.filter(option => !option.created) |
||||||
|
.some(option => option.currentLabel === this.query) |
||||||
|
return this.filterable && this.allowCreate && this.query !== '' && !hasExistingOption |
||||||
|
}, |
||||||
|
|
||||||
|
selectSize() { |
||||||
|
return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size |
||||||
|
}, |
||||||
|
|
||||||
|
selectDisabled() { |
||||||
|
return this.disabled || (this.elForm || {}).disabled |
||||||
|
}, |
||||||
|
|
||||||
|
collapseTagSize() { |
||||||
|
return ['small', 'mini'].indexOf(this.selectSize) > -1 |
||||||
|
? 'mini' |
||||||
|
: 'small' |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
watch: { |
||||||
|
selectDisabled() { |
||||||
|
this.$nextTick(() => { |
||||||
|
this.resetInputHeight() |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
placeholder(val) { |
||||||
|
this.cachedPlaceHolder = this.currentPlaceholder = val |
||||||
|
}, |
||||||
|
|
||||||
|
value(val, oldVal) { |
||||||
|
if (this.multiple) { |
||||||
|
this.resetInputHeight() |
||||||
|
if ((val && val.length > 0) || (this.$refs.input && this.query !== '')) { |
||||||
|
this.currentPlaceholder = '' |
||||||
|
} |
||||||
|
else { |
||||||
|
this.currentPlaceholder = this.cachedPlaceHolder |
||||||
|
} |
||||||
|
if (this.filterable && !this.reserveKeyword) { |
||||||
|
this.query = '' |
||||||
|
this.handleQueryChange(this.query) |
||||||
|
} |
||||||
|
} |
||||||
|
this.setSelected() |
||||||
|
if (this.filterable && !this.multiple) { |
||||||
|
this.inputLength = 20 |
||||||
|
} |
||||||
|
if (!valueEquals(val, oldVal)) { |
||||||
|
this.dispatch('ElFormItem', 'el.form.change', val) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
visible(val) { |
||||||
|
if (!val) { |
||||||
|
this.broadcast('ElSelectDropdown', 'destroyPopper') |
||||||
|
if (this.$refs.input) { |
||||||
|
this.$refs.input.blur() |
||||||
|
} |
||||||
|
this.query = '' |
||||||
|
this.previousQuery = null |
||||||
|
this.selectedLabel = '' |
||||||
|
this.inputLength = 20 |
||||||
|
this.menuVisibleOnFocus = false |
||||||
|
this.resetHoverIndex() |
||||||
|
this.$nextTick(() => { |
||||||
|
if (this.$refs.input && |
||||||
|
this.$refs.input.value === '' && |
||||||
|
this.selected.length === 0) { |
||||||
|
this.currentPlaceholder = this.cachedPlaceHolder |
||||||
|
} |
||||||
|
}) |
||||||
|
if (!this.multiple) { |
||||||
|
if (this.selected) { |
||||||
|
if (this.filterable && this.allowCreate && |
||||||
|
this.createdSelected && this.createdLabel) { |
||||||
|
this.selectedLabel = this.createdLabel |
||||||
|
} |
||||||
|
else { |
||||||
|
this.selectedLabel = this.selected.currentLabel |
||||||
|
} |
||||||
|
if (this.filterable) this.query = this.selectedLabel |
||||||
|
} |
||||||
|
|
||||||
|
if (this.filterable) { |
||||||
|
this.currentPlaceholder = this.cachedPlaceHolder |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
this.broadcast('ElSelectDropdown', 'updatePopper') |
||||||
|
if (this.filterable) { |
||||||
|
this.query = this.remote ? '' : this.selectedLabel |
||||||
|
this.handleQueryChange(this.query) |
||||||
|
if (this.multiple) { |
||||||
|
this.$refs.input.focus() |
||||||
|
} |
||||||
|
else { |
||||||
|
if (!this.remote) { |
||||||
|
this.broadcast('ElOption', 'queryChange', '') |
||||||
|
this.broadcast('ElOptionGroup', 'queryChange') |
||||||
|
} |
||||||
|
|
||||||
|
if (this.selectedLabel) { |
||||||
|
this.currentPlaceholder = this.selectedLabel |
||||||
|
this.selectedLabel = '' |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
this.$emit('visible-change', val) |
||||||
|
}, |
||||||
|
|
||||||
|
options() { |
||||||
|
if (this.$isServer) return |
||||||
|
this.$nextTick(() => { |
||||||
|
this.broadcast('ElSelectDropdown', 'updatePopper') |
||||||
|
}) |
||||||
|
if (this.multiple) { |
||||||
|
this.resetInputHeight() |
||||||
|
} |
||||||
|
let inputs = this.$el.querySelectorAll('input') |
||||||
|
if ([].indexOf.call(inputs, document.activeElement) === -1) { |
||||||
|
this.setSelected() |
||||||
|
} |
||||||
|
if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) { |
||||||
|
this.checkDefaultFirstOption() |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
methods: { |
||||||
|
handleComposition(event) { |
||||||
|
const text = event.target.value |
||||||
|
if (event.type === 'compositionend') { |
||||||
|
this.isOnComposition = false |
||||||
|
this.$nextTick(_ => this.handleQueryChange(text)) |
||||||
|
} |
||||||
|
else { |
||||||
|
const lastCharacter = text[text.length - 1] || '' |
||||||
|
this.isOnComposition = !isKorean(lastCharacter) |
||||||
|
} |
||||||
|
}, |
||||||
|
handleQueryChange(val) { |
||||||
|
if (this.previousQuery === val || this.isOnComposition) return |
||||||
|
if ( |
||||||
|
this.previousQuery === null && |
||||||
|
(typeof this.filterMethod === 'function' || typeof this.remoteMethod === 'function') |
||||||
|
) { |
||||||
|
this.previousQuery = val |
||||||
|
return |
||||||
|
} |
||||||
|
this.previousQuery = val |
||||||
|
this.$nextTick(() => { |
||||||
|
if (this.visible) this.broadcast('ElSelectDropdown', 'updatePopper') |
||||||
|
}) |
||||||
|
this.hoverIndex = -1 |
||||||
|
if (this.multiple && this.filterable) { |
||||||
|
this.$nextTick(() => { |
||||||
|
const length = this.$refs.input.value.length * 15 + 20 |
||||||
|
this.inputLength = this.collapseTags ? Math.min(50, length) : length |
||||||
|
this.managePlaceholder() |
||||||
|
this.resetInputHeight() |
||||||
|
}) |
||||||
|
} |
||||||
|
if (this.remote && typeof this.remoteMethod === 'function') { |
||||||
|
this.hoverIndex = -1 |
||||||
|
this.remoteMethod(val) |
||||||
|
} |
||||||
|
else if (typeof this.filterMethod === 'function') { |
||||||
|
this.filterMethod(val) |
||||||
|
this.broadcast('ElOptionGroup', 'queryChange') |
||||||
|
} |
||||||
|
else { |
||||||
|
this.filteredOptionsCount = this.optionsCount |
||||||
|
this.broadcast('ElOption', 'queryChange', val) |
||||||
|
this.broadcast('ElOptionGroup', 'queryChange') |
||||||
|
} |
||||||
|
if (this.defaultFirstOption && (this.filterable || this.remote) && this.filteredOptionsCount) { |
||||||
|
this.checkDefaultFirstOption() |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
scrollToOption(option) { |
||||||
|
const target = Array.isArray(option) && option[0] ? option[0].$el : option.$el |
||||||
|
if (this.$refs.popper && target) { |
||||||
|
const menu = this.$refs.popper.$el.querySelector('.el-select-dropdown__wrap') |
||||||
|
scrollIntoView(menu, target) |
||||||
|
} |
||||||
|
this.$refs.scrollbar && this.$refs.scrollbar.handleScroll() |
||||||
|
}, |
||||||
|
|
||||||
|
handleMenuEnter() { |
||||||
|
this.$nextTick(() => this.scrollToOption(this.selected)) |
||||||
|
}, |
||||||
|
|
||||||
|
emitChange(val) { |
||||||
|
if (!valueEquals(this.value, val)) { |
||||||
|
this.$emit('change', val) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
getOption(value) { |
||||||
|
let option |
||||||
|
const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]' |
||||||
|
const isNull = Object.prototype.toString.call(value).toLowerCase() === '[object null]' |
||||||
|
const isUndefined = Object.prototype.toString.call(value).toLowerCase() === '[object undefined]' |
||||||
|
|
||||||
|
for (let i = this.cachedOptions.length - 1; i >= 0; i--) { |
||||||
|
const cachedOption = this.cachedOptions[i] |
||||||
|
const isEqual = isObject |
||||||
|
? getValueByPath(cachedOption.value, this.valueKey) === getValueByPath(value, this.valueKey) |
||||||
|
: cachedOption.value === value |
||||||
|
if (isEqual) { |
||||||
|
option = cachedOption |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
if (option) return option |
||||||
|
const label = (!isObject && !isNull && !isUndefined) |
||||||
|
? value : '' |
||||||
|
let newOption = { |
||||||
|
value: value, |
||||||
|
currentLabel: label |
||||||
|
} |
||||||
|
if (this.multiple) { |
||||||
|
newOption.hitState = false |
||||||
|
} |
||||||
|
return newOption |
||||||
|
}, |
||||||
|
|
||||||
|
setSelected() { |
||||||
|
if (!this.multiple) { |
||||||
|
let option = this.getOption(this.value) |
||||||
|
if (option.created) { |
||||||
|
this.createdLabel = option.currentLabel |
||||||
|
this.createdSelected = true |
||||||
|
} |
||||||
|
else { |
||||||
|
this.createdSelected = false |
||||||
|
} |
||||||
|
this.selectedLabel = option.currentLabel |
||||||
|
this.selected = option |
||||||
|
if (this.filterable) this.query = this.selectedLabel |
||||||
|
return |
||||||
|
} |
||||||
|
let result = [] |
||||||
|
if (Array.isArray(this.value)) { |
||||||
|
this.value.forEach(value => { |
||||||
|
result.push(this.getOption(value)) |
||||||
|
}) |
||||||
|
} |
||||||
|
this.selected = result |
||||||
|
this.$nextTick(() => { |
||||||
|
this.resetInputHeight() |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
handleFocus(event) { |
||||||
|
if (!this.softFocus) { |
||||||
|
if (this.automaticDropdown || this.filterable) { |
||||||
|
this.visible = true |
||||||
|
if (this.filterable) { |
||||||
|
this.menuVisibleOnFocus = true |
||||||
|
} |
||||||
|
} |
||||||
|
this.$emit('focus', event) |
||||||
|
} |
||||||
|
else { |
||||||
|
this.softFocus = false |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
blur() { |
||||||
|
this.visible = false |
||||||
|
this.$refs.reference.blur() |
||||||
|
}, |
||||||
|
|
||||||
|
handleBlur(event) { |
||||||
|
setTimeout(() => { |
||||||
|
if (this.isSilentBlur) { |
||||||
|
this.isSilentBlur = false |
||||||
|
} |
||||||
|
else { |
||||||
|
this.$emit('blur', event) |
||||||
|
} |
||||||
|
}, 50) |
||||||
|
this.softFocus = false |
||||||
|
}, |
||||||
|
|
||||||
|
handleClearClick(event) { |
||||||
|
this.deleteSelected(event) |
||||||
|
}, |
||||||
|
|
||||||
|
doDestroy() { |
||||||
|
this.$refs.popper && this.$refs.popper.doDestroy() |
||||||
|
}, |
||||||
|
|
||||||
|
handleClose() { |
||||||
|
this.visible = false |
||||||
|
}, |
||||||
|
|
||||||
|
toggleLastOptionHitState(hit) { |
||||||
|
if (!Array.isArray(this.selected)) return |
||||||
|
const option = this.selected[this.selected.length - 1] |
||||||
|
if (!option) return |
||||||
|
|
||||||
|
if (hit === true || hit === false) { |
||||||
|
option.hitState = hit |
||||||
|
return hit |
||||||
|
} |
||||||
|
|
||||||
|
option.hitState = !option.hitState |
||||||
|
return option.hitState |
||||||
|
}, |
||||||
|
|
||||||
|
deletePrevTag(e) { |
||||||
|
if (e.target.value.length <= 0 && !this.toggleLastOptionHitState()) { |
||||||
|
const value = this.value.slice() |
||||||
|
value.pop() |
||||||
|
this.$emit('input', value) |
||||||
|
this.emitChange(value) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
managePlaceholder() { |
||||||
|
if (this.currentPlaceholder !== '') { |
||||||
|
this.currentPlaceholder = this.$refs.input.value ? '' : this.cachedPlaceHolder |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
resetInputState(e) { |
||||||
|
if (e.keyCode !== 8) this.toggleLastOptionHitState(false) |
||||||
|
this.inputLength = this.$refs.input.value.length * 15 + 20 |
||||||
|
this.resetInputHeight() |
||||||
|
}, |
||||||
|
|
||||||
|
resetInputHeight() { |
||||||
|
if (this.collapseTags && !this.filterable) return |
||||||
|
this.$nextTick(() => { |
||||||
|
if (!this.$refs.reference) return |
||||||
|
let inputChildNodes = this.$refs.reference.$el.childNodes |
||||||
|
let input = [].filter.call(inputChildNodes, item => item.tagName === 'INPUT')[0] |
||||||
|
const tags = this.$refs.tags |
||||||
|
const sizeInMap = this.initialInputHeight || 40 |
||||||
|
input.style.height = this.selected.length === 0 |
||||||
|
? sizeInMap + 'px' |
||||||
|
: Math.max( |
||||||
|
tags ? (tags.clientHeight + (tags.clientHeight > sizeInMap ? 6 : 0)) : 0, |
||||||
|
sizeInMap |
||||||
|
) + 'px' |
||||||
|
if (this.visible && this.emptyText !== false) { |
||||||
|
this.broadcast('ElSelectDropdown', 'updatePopper') |
||||||
|
} |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
resetHoverIndex() { |
||||||
|
setTimeout(() => { |
||||||
|
if (!this.multiple) { |
||||||
|
this.hoverIndex = this.options.indexOf(this.selected) |
||||||
|
} |
||||||
|
else { |
||||||
|
if (this.selected.length > 0) { |
||||||
|
this.hoverIndex = Math.min.apply(null, this.selected.map(item => this.options.indexOf(item))) |
||||||
|
} |
||||||
|
else { |
||||||
|
this.hoverIndex = -1 |
||||||
|
} |
||||||
|
} |
||||||
|
}, 300) |
||||||
|
}, |
||||||
|
|
||||||
|
handleOptionSelect(option, byClick) { |
||||||
|
if (this.multiple) { |
||||||
|
const value = (this.value || []).slice() |
||||||
|
const optionIndex = this.getValueIndex(value, option.value) |
||||||
|
if (optionIndex > -1) { |
||||||
|
value.splice(optionIndex, 1) |
||||||
|
} |
||||||
|
else if (this.multipleLimit <= 0 || value.length < this.multipleLimit) { |
||||||
|
value.push(option.value) |
||||||
|
} |
||||||
|
this.$emit('input', value) |
||||||
|
this.emitChange(value) |
||||||
|
if (option.created) { |
||||||
|
this.query = '' |
||||||
|
this.handleQueryChange('') |
||||||
|
this.inputLength = 20 |
||||||
|
} |
||||||
|
if (this.filterable) this.$refs.input.focus() |
||||||
|
} |
||||||
|
else { |
||||||
|
this.$emit('input', option.value) |
||||||
|
this.emitChange(option.value) |
||||||
|
this.visible = false |
||||||
|
} |
||||||
|
this.isSilentBlur = byClick |
||||||
|
this.setSoftFocus() |
||||||
|
if (this.visible) return |
||||||
|
this.$nextTick(() => { |
||||||
|
this.scrollToOption(option) |
||||||
|
}) |
||||||
|
}, |
||||||
|
|
||||||
|
setSoftFocus() { |
||||||
|
this.softFocus = true |
||||||
|
const input = this.$refs.input || this.$refs.reference |
||||||
|
if (input) { |
||||||
|
input.focus() |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
getValueIndex(arr = [], value) { |
||||||
|
const isObject = Object.prototype.toString.call(value).toLowerCase() === '[object object]' |
||||||
|
if (!isObject) { |
||||||
|
return arr.indexOf(value) |
||||||
|
} |
||||||
|
else { |
||||||
|
const valueKey = this.valueKey |
||||||
|
let index = -1 |
||||||
|
arr.some((item, i) => { |
||||||
|
if (getValueByPath(item, valueKey) === getValueByPath(value, valueKey)) { |
||||||
|
index = i |
||||||
|
return true |
||||||
|
} |
||||||
|
return false |
||||||
|
}) |
||||||
|
return index |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
toggleMenu() { |
||||||
|
if (!this.selectDisabled) { |
||||||
|
if (this.menuVisibleOnFocus) { |
||||||
|
this.menuVisibleOnFocus = false |
||||||
|
} |
||||||
|
else { |
||||||
|
this.visible = !this.visible |
||||||
|
} |
||||||
|
if (this.visible) { |
||||||
|
(this.$refs.input || this.$refs.reference).focus() |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
selectOption() { |
||||||
|
if (!this.visible) { |
||||||
|
this.toggleMenu() |
||||||
|
} |
||||||
|
else { |
||||||
|
if (this.options[this.hoverIndex]) { |
||||||
|
this.handleOptionSelect(this.options[this.hoverIndex]) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
deleteSelected(event) { |
||||||
|
event.stopPropagation() |
||||||
|
const value = this.multiple ? [] : '' |
||||||
|
this.$emit('input', value) |
||||||
|
this.emitChange(value) |
||||||
|
this.visible = false |
||||||
|
this.$emit('clear') |
||||||
|
}, |
||||||
|
|
||||||
|
deleteTag(event, tag) { |
||||||
|
let index = this.selected.indexOf(tag) |
||||||
|
if (index > -1 && !this.selectDisabled) { |
||||||
|
const value = this.value.slice() |
||||||
|
value.splice(index, 1) |
||||||
|
this.$emit('input', value) |
||||||
|
this.emitChange(value) |
||||||
|
this.$emit('remove-tag', tag.value) |
||||||
|
} |
||||||
|
event.stopPropagation() |
||||||
|
}, |
||||||
|
|
||||||
|
onInputChange() { |
||||||
|
if (this.filterable && this.query !== this.selectedLabel) { |
||||||
|
this.query = this.selectedLabel |
||||||
|
this.handleQueryChange(this.query) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
onOptionDestroy(index) { |
||||||
|
if (index > -1) { |
||||||
|
this.optionsCount-- |
||||||
|
this.filteredOptionsCount-- |
||||||
|
this.options.splice(index, 1) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
resetInputWidth() { |
||||||
|
this.inputWidth = this.$refs.reference.$el.getBoundingClientRect().width |
||||||
|
}, |
||||||
|
|
||||||
|
handleResize() { |
||||||
|
this.resetInputWidth() |
||||||
|
if (this.multiple) this.resetInputHeight() |
||||||
|
}, |
||||||
|
|
||||||
|
checkDefaultFirstOption() { |
||||||
|
this.hoverIndex = -1 |
||||||
|
// highlight the created option |
||||||
|
let hasCreated = false |
||||||
|
for (let i = this.options.length - 1; i >= 0; i--) { |
||||||
|
if (this.options[i].created) { |
||||||
|
hasCreated = true |
||||||
|
this.hoverIndex = i |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
if (hasCreated) return |
||||||
|
for (let i = 0; i !== this.options.length; ++i) { |
||||||
|
const option = this.options[i] |
||||||
|
if (this.query) { |
||||||
|
// highlight first options that passes the filter |
||||||
|
if (!option.disabled && !option.groupDisabled && option.visible) { |
||||||
|
this.hoverIndex = i |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
// highlight currently selected option |
||||||
|
if (option.itemSelected) { |
||||||
|
this.hoverIndex = i |
||||||
|
break |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
getValueKey(item) { |
||||||
|
if (Object.prototype.toString.call(item.value).toLowerCase() !== '[object object]') { |
||||||
|
return item.value |
||||||
|
} |
||||||
|
else { |
||||||
|
return getValueByPath(item.value, this.valueKey) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
created() { |
||||||
|
this.cachedPlaceHolder = this.currentPlaceholder = this.placeholder |
||||||
|
if (this.multiple && !Array.isArray(this.value)) { |
||||||
|
this.$emit('input', []) |
||||||
|
} |
||||||
|
if (!this.multiple && Array.isArray(this.value)) { |
||||||
|
this.$emit('input', '') |
||||||
|
} |
||||||
|
|
||||||
|
this.debouncedOnInputChange = debounce(this.onInputChange, this.debounce) |
||||||
|
|
||||||
|
this.debouncedQueryChange = debounce(e => this.handleQueryChange(e.target.value), this.debounce) |
||||||
|
|
||||||
|
this.$on('handleOptionClick', this.handleOptionSelect) |
||||||
|
this.$on('setSelected', this.setSelected) |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
if (this.multiple && Array.isArray(this.value) && this.value.length > 0) { |
||||||
|
this.currentPlaceholder = '' |
||||||
|
} |
||||||
|
addResizeListener(this.$el, this.handleResize) |
||||||
|
|
||||||
|
const reference = this.$refs.reference |
||||||
|
if (reference && reference.$el) { |
||||||
|
const sizeMap = { |
||||||
|
medium: 36, |
||||||
|
small: 32, |
||||||
|
mini: 28 |
||||||
|
} |
||||||
|
const input = reference.$el.querySelector('input') |
||||||
|
this.initialInputHeight = input.getBoundingClientRect().height || sizeMap[this.selectSize] |
||||||
|
} |
||||||
|
if (this.remote && this.multiple) { |
||||||
|
this.resetInputHeight() |
||||||
|
} |
||||||
|
this.$nextTick(() => { |
||||||
|
if (reference && reference.$el) { |
||||||
|
this.inputWidth = reference.$el.getBoundingClientRect().width |
||||||
|
} |
||||||
|
}) |
||||||
|
this.setSelected() |
||||||
|
}, |
||||||
|
|
||||||
|
beforeDestroy() { |
||||||
|
if (this.$el && this.handleResize) removeResizeListener(this.$el, this.handleResize) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
@ -0,0 +1,47 @@ |
|||||||
|
<template> |
||||||
|
<div |
||||||
|
ref="popper" |
||||||
|
class="el-select-dropdown el-popper" |
||||||
|
:class="[{ 'is-multiple': $parent.multiple }, popperClass]" |
||||||
|
:style="{ minWidth }"> |
||||||
|
<slot/> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script type="text/babel"> |
||||||
|
import Popper from '@ele/mixins/vue-popper' |
||||||
|
|
||||||
|
export default { |
||||||
|
name: 'ElSelectDropdown', |
||||||
|
|
||||||
|
componentName: 'ElSelectDropdown', |
||||||
|
|
||||||
|
mixins: [Popper], |
||||||
|
|
||||||
|
data() { |
||||||
|
return { |
||||||
|
minWidth: '' |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
computed: { |
||||||
|
popperClass() { |
||||||
|
return this.$parent.popperClass |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
watch: { |
||||||
|
'$parent.inputWidth'() { |
||||||
|
this.minWidth = this.$parent.$el.getBoundingClientRect().width + 'px' |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
mounted() { |
||||||
|
this.referenceElm = this.$parent.$refs.reference.$el |
||||||
|
this.$parent.popperElm = this.popperElm = this.$el |
||||||
|
this.$on('updatePopper', () => { |
||||||
|
this.$parent.visible && this.updatePopper() |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
</script> |
||||||
@ -0,0 +1,163 @@ |
|||||||
|
import {PopupManager} from 'element-ui/lib/utils/popup' |
||||||
|
|
||||||
|
const PopperJS = require('@popperjs/core') |
||||||
|
|
||||||
|
const stop = e => e.stopPropagation() |
||||||
|
|
||||||
|
/** |
||||||
|
* @param {HTMLElement} [reference=$refs.reference] - The reference element used to position the popper. |
||||||
|
* @param {HTMLElement} [popper=$refs.popper] - The HTML element used as popper, or a configuration used to generate the popper. |
||||||
|
* @param {String} [placement=button] - Placement of the popper accepted values: top(-start, -end), right(-start, -end), bottom(-start, -end), left(-start, -end) |
||||||
|
* @param {Number} [offset=0] - Amount of pixels the popper will be shifted (can be negative). |
||||||
|
* @param {Boolean} [visible=false] Visibility of the popup element. |
||||||
|
* @param {Boolean} [visible-arrow=false] Visibility of the arrow, no style. |
||||||
|
*/ |
||||||
|
export default { |
||||||
|
props: { |
||||||
|
transformOrigin: { |
||||||
|
type: [Boolean, String], |
||||||
|
default: true |
||||||
|
}, |
||||||
|
placement: { |
||||||
|
type: String, |
||||||
|
default: 'bottom' |
||||||
|
}, |
||||||
|
boundariesPadding: { |
||||||
|
type: Number, |
||||||
|
default: 5 |
||||||
|
}, |
||||||
|
reference: {}, |
||||||
|
popper: {}, |
||||||
|
offset: { |
||||||
|
type: Number, |
||||||
|
default: 12 |
||||||
|
}, |
||||||
|
value: Boolean, |
||||||
|
visibleArrow: { |
||||||
|
type: Boolean, |
||||||
|
default: true |
||||||
|
}, |
||||||
|
arrowOffset: { |
||||||
|
type: Number, |
||||||
|
default: 35 |
||||||
|
}, |
||||||
|
appendToBody: Boolean, |
||||||
|
popperOptions: { |
||||||
|
type: Object, |
||||||
|
default: () => ({modifiers: []}) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
data() { |
||||||
|
return { |
||||||
|
showPopper: this.value |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
watch: { |
||||||
|
value: { |
||||||
|
immediate: true, |
||||||
|
handler(val) { |
||||||
|
if (this.disabled) return |
||||||
|
val && this.updatePopper() |
||||||
|
this.showPopper = val |
||||||
|
this.$emit('input', val) |
||||||
|
} |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
methods: { |
||||||
|
createPopper() { |
||||||
|
if (!/^(top|bottom|left|right)(-start|-end)?$/g.test(this.placement)) { |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
const options = this.popperOptions |
||||||
|
const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper |
||||||
|
let reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference |
||||||
|
|
||||||
|
if (!reference && this.$slots.reference && this.$slots.reference[0]) { |
||||||
|
reference = this.referenceElm = this.$slots.reference[0].elm |
||||||
|
} |
||||||
|
|
||||||
|
if (!popper || !reference) return |
||||||
|
|
||||||
|
if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) { |
||||||
|
this.popperJS.destroy() |
||||||
|
} |
||||||
|
|
||||||
|
if (this.appendToBody) document.body.appendChild(this.popperElm) |
||||||
|
if (this.visibleArrow) this.setArrow() |
||||||
|
this.setOffset() |
||||||
|
|
||||||
|
options.placement = this.placement |
||||||
|
options.onFirstUpdate = () => { |
||||||
|
this.$emit('created', this) |
||||||
|
this.$nextTick(this.updatePopper) |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
this.popperJS = PopperJS.createPopper(reference, popper, options) |
||||||
|
|
||||||
|
popper.style.zIndex = PopupManager.nextZIndex() |
||||||
|
this.popperElm.addEventListener('click', stop) |
||||||
|
}, |
||||||
|
|
||||||
|
updatePopper() { |
||||||
|
const popper = this.popperJS |
||||||
|
|
||||||
|
if (!popper) return this.createPopper() |
||||||
|
|
||||||
|
popper.update() |
||||||
|
this.popperElm.style.zIndex = PopupManager.nextZIndex() |
||||||
|
}, |
||||||
|
|
||||||
|
doDestroy(forceDestroy) { |
||||||
|
if (!this.popperJS || (this.showPopper && !forceDestroy)) return |
||||||
|
this.popperJS.destroy() |
||||||
|
this.popperJS = null |
||||||
|
}, |
||||||
|
|
||||||
|
setArrow() { |
||||||
|
if (this.appended) return |
||||||
|
this.appended = true |
||||||
|
|
||||||
|
const arrow = document.createElement('div') |
||||||
|
arrow.className = 'popper__arrow' |
||||||
|
arrow.setAttribute('data-popper-arrow', '') |
||||||
|
|
||||||
|
this.popperElm.appendChild(arrow) |
||||||
|
|
||||||
|
const modifier = this.popperOptions.modifiers.find(modifier => modifier.name === 'arrow'), |
||||||
|
options = {element: '[data-popper-arrow]', padding: this.arrowOffset} |
||||||
|
|
||||||
|
if (!modifier) { |
||||||
|
this.popperOptions.modifiers.push({name: 'arrow', options}) |
||||||
|
} |
||||||
|
else modifier.options = options |
||||||
|
}, |
||||||
|
|
||||||
|
setOffset() { |
||||||
|
const modifier = this.popperOptions.modifiers.find(modifier => modifier.name === 'offset'), |
||||||
|
options = {offset: [0, this.offset]} |
||||||
|
|
||||||
|
if (!modifier) { |
||||||
|
this.popperOptions.modifiers.push({name: 'offset', options}) |
||||||
|
} |
||||||
|
else modifier.options = options |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
beforeDestroy() { |
||||||
|
this.doDestroy(true) |
||||||
|
if (this.popperElm && this.popperElm.parentNode === document.body) { |
||||||
|
this.popperElm.removeEventListener('click', stop) |
||||||
|
document.body.removeChild(this.popperElm) |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
// call destroy in keep-alive mode
|
||||||
|
deactivated() { |
||||||
|
this.$options.beforeDestroy[0].call(this) |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,2 @@ |
|||||||
|
@import "./message.scss"; |
||||||
|
@import "./popper.scss"; |
||||||
@ -0,0 +1,58 @@ |
|||||||
|
.el-message { |
||||||
|
overflow: visible; |
||||||
|
|
||||||
|
&__badge { |
||||||
|
animation: el-message-badge .42s; |
||||||
|
padding: 4px 8px; |
||||||
|
position: absolute; |
||||||
|
box-shadow: 0 1px 3px rgba(#000, .2), 0 1px 1px rgba(#000, .14), 0 2px 1px -1px rgba(#000, .12); |
||||||
|
background-color: $--color-danger; |
||||||
|
color: #fff; |
||||||
|
border-radius: 4px; |
||||||
|
top: -10px; |
||||||
|
left: -10px; |
||||||
|
font-size: 12px; |
||||||
|
line-height: 12px; |
||||||
|
} |
||||||
|
|
||||||
|
&__progress { |
||||||
|
z-index: -1; |
||||||
|
position: absolute; |
||||||
|
height: 3px; |
||||||
|
bottom: 0; |
||||||
|
left: 10px; |
||||||
|
right: 10px; |
||||||
|
animation: el-message-progress linear; |
||||||
|
background: currentColor; |
||||||
|
opacity: .3; |
||||||
|
transform-origin: 0 50%; |
||||||
|
transform: scaleX(0); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes el-message-badge { |
||||||
|
15% { |
||||||
|
transform: translate3d(-25%, 0, 0) rotate3d(0, 0, 1, -5deg) |
||||||
|
} |
||||||
|
30% { |
||||||
|
transform: translate3d(20%, 0, 0) rotate3d(0, 0, 1, 3deg) |
||||||
|
} |
||||||
|
45% { |
||||||
|
transform: translate3d(-15%, 0, 0) rotate3d(0, 0, 1, -3deg) |
||||||
|
} |
||||||
|
60% { |
||||||
|
transform: translate3d(10%, 0, 0) rotate3d(0, 0, 1, 2deg) |
||||||
|
} |
||||||
|
75% { |
||||||
|
transform: translate3d(-5%, 0, 0) rotate3d(0, 0, 1, -1deg) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@keyframes el-message-progress { |
||||||
|
0% { |
||||||
|
transform: scaleX(1) |
||||||
|
} |
||||||
|
100% { |
||||||
|
transform: scaleX(0) |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,98 @@ |
|||||||
|
@include b(popper) { |
||||||
|
.popper__arrow, |
||||||
|
.popper__arrow::after { |
||||||
|
position: absolute; |
||||||
|
display: block; |
||||||
|
width: 0; |
||||||
|
height: 0; |
||||||
|
border-color: transparent; |
||||||
|
border-style: solid; |
||||||
|
} |
||||||
|
|
||||||
|
.popper__arrow { |
||||||
|
border-width: $--popover-arrow-size; |
||||||
|
filter: drop-shadow(0 2px 12px rgba(0, 0, 0, 0.03)) |
||||||
|
} |
||||||
|
|
||||||
|
.popper__arrow::after { |
||||||
|
content: " "; |
||||||
|
border-width: $--popover-arrow-size; |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="top"] { |
||||||
|
margin-bottom: #{$--popover-arrow-size + 6}; |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="top"] .popper__arrow { |
||||||
|
bottom: -$--popover-arrow-size; |
||||||
|
left: 50%; |
||||||
|
margin-right: #{$--tooltip-arrow-size / 2}; |
||||||
|
border-top-color: $--popover-border-color; |
||||||
|
border-bottom-width: 0; |
||||||
|
|
||||||
|
&::after { |
||||||
|
bottom: 1px; |
||||||
|
margin-left: -$--popover-arrow-size; |
||||||
|
border-top-color: $--popover-background-color; |
||||||
|
border-bottom-width: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="bottom"] { |
||||||
|
margin-top: #{$--popover-arrow-size + 6}; |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="bottom"] .popper__arrow { |
||||||
|
top: -$--popover-arrow-size; |
||||||
|
left: 50%; |
||||||
|
margin-right: #{$--tooltip-arrow-size / 2}; |
||||||
|
border-top-width: 0; |
||||||
|
border-bottom-color: $--popover-border-color; |
||||||
|
|
||||||
|
&::after { |
||||||
|
top: 1px; |
||||||
|
margin-left: -$--popover-arrow-size; |
||||||
|
border-top-width: 0; |
||||||
|
border-bottom-color: $--popover-background-color; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="right"] { |
||||||
|
margin-left: #{$--popover-arrow-size + 6}; |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="right"] .popper__arrow { |
||||||
|
top: 50%; |
||||||
|
left: -$--popover-arrow-size; |
||||||
|
margin-bottom: #{$--tooltip-arrow-size / 2}; |
||||||
|
border-right-color: $--popover-border-color; |
||||||
|
border-left-width: 0; |
||||||
|
|
||||||
|
&::after { |
||||||
|
bottom: -$--popover-arrow-size; |
||||||
|
left: 1px; |
||||||
|
border-right-color: $--popover-background-color; |
||||||
|
border-left-width: 0; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="left"] { |
||||||
|
margin-right: #{$--popover-arrow-size + 6}; |
||||||
|
} |
||||||
|
|
||||||
|
&[data-popper-placement^="left"] .popper__arrow { |
||||||
|
top: 50%; |
||||||
|
right: -$--popover-arrow-size; |
||||||
|
margin-bottom: #{$--tooltip-arrow-size / 2}; |
||||||
|
border-right-width: 0; |
||||||
|
border-left-color: $--popover-border-color; |
||||||
|
|
||||||
|
&::after { |
||||||
|
right: 1px; |
||||||
|
bottom: -$--popover-arrow-size; |
||||||
|
margin-left: -$--popover-arrow-size; |
||||||
|
border-right-width: 0; |
||||||
|
border-left-color: $--popover-background-color; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue