feat(base-picker): for select & cascader

This commit is contained in:
07akioni 2019-08-24 01:30:52 +08:00
parent c381db1f36
commit 240a65fa30
6 changed files with 411 additions and 3 deletions

View File

@ -50,7 +50,7 @@ import Anchor from './packages/common/Anchor'
import Dropdown from './packages/common/Dropdown'
import Popselect from './packages/common/Popselect'
import App from './packages/common/App'
import CancelMark from './packages/common/CancelMark'
import CancelMark from './packages/base/CancelMark'
function install (Vue) {
Card.install(Vue)

View File

@ -0,0 +1,8 @@
/* istanbul ignore file */
import BasePicker from './src/main.vue'
BasePicker.install = function (Vue) {
Vue.component(BasePicker.name, BasePicker)
}
export default BasePicker

View File

@ -0,0 +1,199 @@
<template>
<div
class="n-base-picker"
:class="{
'n-base-picker--active': active,
'n-base-picker--selected': selected || (active && pattern),
'n-base-picker--disabled': disabled,
[`n-base-picker--${size}-size`]: true,
'n-base-picker--multiple': multiple
}"
@click="handleActivatorClick"
>
<template v-if="multiple">
<div
class="n-base-picker-tags"
:class="{
'n-base-picker-tags--selected': selected
}"
>
<div
v-for="option in selectedOptions"
:key="option.value"
class="n-base-picker-tag"
>
<div class="n-base-picker-tag__content">
{{ option.label }}
</div>
<n-icon
class="n-base-picker-tag__icon"
type="md-close"
@click.stop="toggleOption(option)"
/>
</div>
<div
v-if="filterable && active"
class="n-base-picker-input-tag"
>
<input
ref="inputTagInput"
:value="pattern"
class="n-base-picker-input-tag__input"
@keyup.delete="handlePatternInputDelete"
@input="handlePatternInput"
>
<span
ref="inputTagMirror"
class="n-base-picker-input-tag__mirror"
>{{ pattern ? pattern : '&nbsp;' }}</span>
</div>
</div>
<div
class="n-base-picker__placeholder"
>
{{ placeholder }}
</div>
<n-base-cancel-mark
class="n-base-picker__mark"
arrow
:show="!remote"
:disabled="disabled"
:active="active"
:clearable="clearable && selected"
@clear="handleClear"
/>
</template>
<template v-else>
<div class="n-base-picker-label">
<input
ref="singleInput"
:value="singleInputActive ? pattern : (selectedOption && selectedOption.label)"
class="n-base-picker-label__input"
:placeholder="selectedOption ? selectedOption.label : placeholder"
:readonly="!disabled && filterable ? false : 'readonly'"
@input="handlePatternInput"
@focus="handleSingleInputFocus"
>
</div>
<n-base-cancel-mark
class="n-base-picker__mark"
arrow
:show="!remote"
:disabled="disabled"
:active="active"
:clearable="clearable && selected"
@clear="handleClear"
/>
</template>
</div>
</template>
<script>
import NBaseCancelMark from '../../CancelMark'
import NIcon from '../../../common/Icon'
export default {
name: 'NBasePicker',
components: {
NBaseCancelMark,
NIcon
},
props: {
active: {
type: Boolean,
default: false
},
pattern: {
type: String,
default: null
},
placeholder: {
type: String,
default: null
},
selectedOption: {
validator () {
return true
},
default: null
},
selectedOptions: {
validator () {
return true
},
default: null
},
toggleOption: {
type: Function,
default: () => {}
},
multiple: {
type: Boolean,
default: false
},
filterable: {
type: Boolean,
default: false
},
singleInputActive: {
type: Boolean,
default: false
},
remote: {
type: Boolean,
default: false
},
clearable: {
type: Boolean,
default: false
},
disabled: {
type: Boolean,
default: false
},
size: {
type: String,
default: 'medium'
}
},
computed: {
selected () {
if (this.multiple) return !!(Array.isArray(this.selectedOptions) && this.selectedOptions.length)
else {
return this.selectedOption !== null
}
}
},
methods: {
handleClear () {
this.$emit('clear')
},
handleActivatorClick () {
this.$emit('activator-click')
},
handlePatternInputDelete () {
this.$emit('pattern-input-delete')
},
handlePatternInput (e) {
if (this.multiple) {
this.$nextTick().then(() => {
const textWidth = this.$refs.inputTagMirror.getBoundingClientRect().width
this.$refs.inputTagInput.style.width = textWidth + 'px'
this.$emit('pattern-input', e)
})
} else {
this.$emit('pattern-input', e)
}
},
handleSingleInputFocus () {
this.$emit('single-input-focus')
},
blurSingleInput () {
this.$refs.singleInput.blur()
},
focusInputTag () {
this.$refs.inputTagInput.focus()
}
}
}
</script>

View File

@ -64,7 +64,7 @@
<script>
import NIcon from '../../Icon'
import Emitter from '../../../mixins/emitter'
import NCancelMark from '../../CancelMark'
import NCancelMark from '../../../base/CancelMark'
export default {
name: 'NInput',

200
styles/BasePicker.scss Normal file
View File

@ -0,0 +1,200 @@
@import './mixins/mixins.scss';
@import './theme/default.scss';
@include b(base-picker) {
position: relative;
box-shadow: none;
cursor: pointer;
border-radius: $select-border-radius;
.n-base-picker__mark {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 14px;
}
.n-base-picker__placeholder {
pointer-events: none;
position: absolute;
left: 14px;
top: 0;
color: $select-placeholder-color;
opacity: 1;
}
.n-base-picker-label, .n-base-picker-tags {
position: relative;
transition: box-shadow .3s $default-cubic-bezier, background-color .3s $default-cubic-bezier;
box-sizing: border-box;
border-radius: $select-border-radius;
background-color: $select-background-color;
}
.n-base-picker-label {
display: flex;
.n-base-picker-label__input {
vertical-align: baseline;
display: inline-block;
border:none;
width: 100%;
cursor: inherit;
background: transparent;
outline: none;
color: $select-text-color;
padding: 0 32px 0 14px;
&::placeholder {
color: $select-placeholder-color;
}
}
}
.n-base-picker-tags {
padding: 4px 32px 0 14px;
display: flex;
flex-wrap: wrap;
align-items: center;
.n-base-picker-tag {
vertical-align: bottom;
box-sizing: border-box;
position: relative;
display: inline-block;
border: 1px solid #63E2B7FF;
color: #63E2B7FF;
border-radius: 4px;
margin-right: 7px;
margin-bottom: 4px;
font-size: 14px;
max-width: 100%;
.n-base-picker-tag__content {
transform: translateY(-1px);
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.n-base-picker-tag__icon {
position: absolute;
right: 4px;
top: 50%;
transform: translateY(-50%);
i::before {
color: #63E2B7FF;
}
}
}
}
&.n-base-picker--selected {
.n-base-picker__placeholder {
opacity: 0;
}
}
&.n-base-picker--active {
.n-base-picker-label, .n-base-picker-tags {
box-shadow: inset 0 0 0 1px $select-border-color--active, 0px 0px 10px 1px #366555;
background-color: $select-background-color--active;
}
}
&.n-base-picker--small-size {
font-size: 14px;
.n-base-picker__placeholder {
height: $small-height;
line-height: $small-height;
}
.n-base-picker-tags {
min-height: $small-height;
.n-base-picker-tag {
font-size: 13px;
padding: 0px 20px 0 7px;
height: 20px;
line-height: 20px;
}
.n-base-picker-input-tag {
height: 20px;
line-height: 20px;
}
}
.n-base-picker-label {
height: $small-height;
line-height: $small-height;
.n-base-picker-label__input {
height: $small-height;
line-height: $small-height;
}
}
}
&.n-base-picker--default-size, &.n-base-picker--medium-size {
font-size: 14px;
.n-base-picker__placeholder {
height: $medium-height;
line-height: $medium-height;
}
.n-base-picker-tags {
min-height: $medium-height;
.n-base-picker-tag {
padding: 0px 20px 0 7px;
height: 26px;
line-height: 26px;
}
.n-base-picker-input-tag {
height: 26px;
line-height: 26px;
}
}
.n-base-picker-label {
height: $medium-height;
line-height: $medium-height;
.n-base-picker-label__input {
height: $medium-height;
line-height: $medium-height;
}
}
}
&.n-base-picker--large-size {
font-size: 14px;
.n-base-picker__placeholder {
height: $large-height;
line-height: $large-height;
}
.n-base-picker-tags {
min-height: $large-height;
.n-base-picker-tag {
padding: 0px 20px 0 7px;
height: 32px;
line-height: 32px;
}
.n-base-picker-input-tag {
height: 32px;
line-height: 32px;
}
}
.n-base-picker-label {
height: $large-height;
line-height: $large-height;
.n-base-picker-label__input {
height: $large-height;
line-height: $large-height;
}
}
}
&.n-base-picker--disabled {
cursor: not-allowed;
.n-base-picker-label, .n-base-picker-tags {
background-color: rgba(255, 255, 255, 0.08);
}
.n-base-picker-tag {
border-color: rgba(255, 255, 255, 0.20);
color: rgba(255, 255, 255, 0.20);
}
.n-base-picker__placeholder {
color: rgba(255, 255, 255, 0.20);
}
.n-base-picker-label {
.n-base-picker-label__input {
color: rgba(255, 255, 255, 0.20);
&::placeholder {
color: rgba(255, 255, 255, 0.20);
}
}
}
}
&:hover:not(.n-base-picker--disabled) {
.n-base-picker-label, .n-base-picker-tags {
box-shadow: inset 0 0 0 1px $select-border-color--active;
}
}
}

View File

@ -39,7 +39,8 @@
@import './Anchor.scss';
@import './Dropdown.scss';
@import './Popselect.scss';
@import './CancelMark.scss';
@import './BaseCancelMark.scss';
@import './BasePicker.scss';
@import "./NimbusServiceLayout.scss";
@import "./Popover.scss";