refactor(input): code clean & composition & icon motion & api typo fix & new doc

This commit is contained in:
07akioni 2020-02-10 22:07:02 +08:00
parent 08c21a332f
commit 519393729c
14 changed files with 308 additions and 146 deletions

View File

@ -17,7 +17,7 @@ Input can be disabled.
:disabled="!active"
round
/>
<n-input split splitor="to" v-model="value" clearable :disabled="!active">
<n-input split seperator="to" v-model="value" clearable :disabled="!active">
<template v-slot:affix>
<n-icon><ios-calendar /></n-icon>
</template>

View File

@ -1,18 +1,16 @@
# Icon
Use icon in input.
# Prefix & Suffix
Fill content in prefix or suffix of the input.
```html
<n-input v-model="value" placeholder="Search">
<template v-slot:affix>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" round placeholder="Search">
<template v-slot:affix>
<n-icon>
<md-search/>
</n-icon>
<n-input v-model="value" round placeholder="1,400,000">
<template v-slot:suffix>
$
</template>
</n-input>
<n-input v-model="value" round placeholder="Search">

View File

@ -7,10 +7,10 @@ size
round
icon
password
event
disabled
clearable
autosize
pair
input-group
```
## V-model
@ -23,7 +23,8 @@ input-group
|Name|Type|Default|Description|
|-|-|-|-|
|type|`'text' \| 'password' \| 'textarea'`|`'text'`||
|value|`string \| [string \| null, string \| null]`|`null`||
|pair|`boolean`|`false`|Whether to input pairwise value.|
|value|`string \| [string, string]`|`null`|Value of input. When `pair` is `true`, `value` is an array.|
|disabled|`boolean`|`false`||
|size|`'small' \| 'medium' \| 'large'`|`'medium'`||
|rows|`number`|`3`||
@ -33,13 +34,14 @@ input-group
|clearable|`boolean`|`false`||
|autosize|`boolean \| { minRows?: number, maxRows?: number }`|`false`||
|readonly|`boolean`|`false`||
|placeholder|`string`|`null`||
|seperator|`string`|`null`|The seperator bewteen pairwise inputs.|
|placeholder|`string \| [string, string]`|`null`|Placeholder of input. When `pair` is `true`, placeholder is an array.|
## Slots
### Input Slots
|Name|Parameters|Description|
|-|-|-|
|affix|`()`||
|prefix|`()`||
|suffix|`()`||
### Input Group Slots
@ -56,7 +58,8 @@ input-group
### Input Events
|Name|Parameters|Description|
|-|-|-|
|input|`(value: string)`||
|change|`(value: string)`||
|input|`(value: string \| [string, string])`||
|change|`(value: string \| [string, string])`||
|blur|`()`||
|focus|`()`||
|clear|`()`||

View File

@ -0,0 +1,43 @@
# Pairwise Value
```html
<n-input
pair
seperator="-"
v-model="value"
:placeholder="placeholder"
clearable
@blur="handleInputBlur"
@focus="handleInputFocus"
@change="handleInputChange"
@input="handleInputInput"
/>
```
```js
export default {
data () {
return {
placeholder: ['From', 'To'],
value: [0, 100]
}
},
methods: {
handleInputBlur () {
this.$NMessage.info('Pairwise ValueBlur')
},
handleInputFocus () {
this.$NMessage.info('Pairwise ValueFocus')
},
handleInputInput () {
this.$NMessage.info('Pairwise ValueInput')
},
handleInputChange () {
this.$NMessage.info('Pairwise ValueChange')
}
}
}
```
```css
.n-input {
margin-bottom: 8px;
}
```

View File

@ -1,42 +0,0 @@
# Pair
```html
<n-input pair seperator="to" v-model="value">
<template v-slot:affix>
<n-icon><ios-calendar /></n-icon>
</template>
</n-input>
<n-input pair seperator="to" v-model="value">
<template v-slot:suffix>
<n-icon><ios-calendar /></n-icon>
</template>
</n-input>
<n-input pair seperator="to" v-model="value" clearable>
<template v-slot:suffix>
<n-icon><ios-calendar /></n-icon>
</template>
</n-input>
<n-input pair seperator="to" v-model="value" clearable>
<template v-slot:affix>
<n-icon><ios-calendar /></n-icon>
</template>
</n-input>
```
```js
import iosCalendar from 'naive-ui/lib/icons/ios-calendar'
export default {
components: {
iosCalendar
},
data () {
return {
value: []
}
}
}
```
```css
.n-input {
margin-bottom: 8px;
}
```

View File

@ -17,7 +17,7 @@
:disabled="!active"
round
/>
<n-input split splitor="to" v-model="value" clearable :disabled="!active">
<n-input split seperator="to" v-model="value" clearable :disabled="!active">
<template v-slot:affix>
<n-icon><ios-calendar /></n-icon>
</template>

View File

@ -0,0 +1,114 @@
# 图标
添加图标
```html
<n-input v-model="value" placeholder="搜索" clearable>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" placeholder="搜索" clearable>
<template v-slot:suffix>
DOLLAR
</template>
</n-input>
<n-input v-model="value" round placeholder="搜索" size="small" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" placeholder="搜索" size="large" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" placeholder="搜索" size="small" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" placeholder="搜索" pair size="large" seperator="-" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" placeholder="搜索" pair size="small" seperator="-" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" round placeholder="搜索" size="large" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" round placeholder="搜索" clearable>
<template v-slot:suffix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
```
```js
import mdSearch from 'naive-ui/lib/icons/md-search'
export default {
components: {
mdSearch
},
data() {
return {
value: null
}
}
}
```
```css
.n-input {
margin-bottom: 8px;
}
```

View File

@ -1,18 +1,16 @@
# 图标
添加图标
# 前缀 & 后缀
在前缀后缀添加内容。
```html
<n-input v-model="value" placeholder="搜索">
<template v-slot:affix>
<template v-slot:prefix>
<n-icon>
<md-search/>
</n-icon>
</template>
</n-input>
<n-input v-model="value" round placeholder="搜索">
<template v-slot:affix>
<n-icon>
<md-search/>
</n-icon>
<n-input v-model="value" round placeholder="100,000,000">
<template v-slot:suffix>
</template>
</n-input>
<n-input v-model="value" round placeholder="搜索">

View File

@ -7,10 +7,10 @@ size
round
icon
password
event
disabled
clearable
autosize
pair
input-group
```
## V-model
@ -23,7 +23,8 @@ input-group
|名称|类型|默认值|说明|
|-|-|-|-|
|type|`'text' \| 'password' \| 'textarea'`|`'text'`||
|value|`string \| [string \| null, string \| null]`|`null`||
|pair|`boolean`|`false`|是否输入成对的值|
|value|`string \| [string, string]`|`null`|文本输入的值。如果是 `pair``true``value` 是一个数组|
|disabled|`boolean`|`false`||
|size|`'small' \| 'medium' \| 'large'`|`'medium'`||
|rows|`number`|`3`||
@ -33,13 +34,14 @@ input-group
|clearable|`boolean`|`false`||
|autosize|`boolean \| { minRows?: number, maxRows?: number }`|`false`||
|readonly|`boolean`|`false`||
|placeholder|`string`|`null`||
|seperator|`string`|`null`|成对的值中间的分隔符|
|placeholder|`string \| [string, string]`|`null`|文本输入的占位符。如果是 `pair``true``placeholder`是一个数组|
## Slots
### Input Slots
|属性|类型|说明|
|-|-|-|
|affix|`()`||
|prefix|`()`||
|suffix|`()`||
### Input Group Slots
@ -57,7 +59,8 @@ input-group
### Input Events
|属性|类型|说明|
|-|-|-|
|input|`(value: string)`||
|change|`(value: string)`||
|input|`(value: string \| [string, string])`||
|change|`(value: string \| [string, string])`||
|blur|`()`||
|focus|`()`||
|clear|`()`||

View File

@ -0,0 +1,43 @@
# 输入成对值
```html
<n-input
pair
seperator="-"
v-model="value"
:placeholder="placeholder"
clearable
@blur="handleInputBlur"
@focus="handleInputFocus"
@change="handleInputChange"
@input="handleInputInput"
/>
```
```js
export default {
data () {
return {
placeholder: ['从', '到'],
value: [0, 100]
}
},
methods: {
handleInputBlur () {
this.$NMessage.info('输入成对值Blur')
},
handleInputFocus () {
this.$NMessage.info('输入成对值Focus')
},
handleInputInput () {
this.$NMessage.info('输入成对值Input')
},
handleInputChange () {
this.$NMessage.info('输入成对值Change')
}
}
}
```
```css
.n-input {
margin-bottom: 8px;
}
```

View File

@ -5,13 +5,13 @@
:class="{
'n-input--disabled': disabled,
[`n-input--${size}-size`]: true,
'n-input--textarea': type==='textarea',
'n-input--round': round && type!=='textarea',
'n-input--textarea': isTextarea,
'n-input--round': round && !isTextarea,
'n-input--clearable': clearable,
'n-input--split': pair,
'n-input--focus': forceFocus || focus,
'n-input--suffix': $slots.suffix,
'n-input--affix': $slots.affix,
'n-input--prefix': $slots.prefix || $slots.affix,
[`n-${synthesizedTheme}-theme`]: synthesizedTheme
}"
:tabindex="!disabled && (pressEnterToActivateInput && !inputFocused) ? 0 : false"
@ -22,6 +22,8 @@
@click="handleClick"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
>
<pre
v-if="isTextarea && autosize"
@ -29,7 +31,7 @@
class="n-input__textarea-mirror"
>{{ value }}<br></pre>
<textarea
v-if="type==='textarea'"
v-if="type === 'textarea'"
ref="textarea"
class="n-input__textarea"
:class="{
@ -48,8 +50,6 @@
@input="handleInput"
@change="handleChange"
@keyup="handleKeyUp"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
/>
<input
v-else
@ -68,8 +68,6 @@
@input="handleInput($event, 0)"
@change="handleChange"
@keyup="handleKeyUp"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
>
<span
v-if="pair"
@ -94,32 +92,30 @@
@input="handleInput($event, 1)"
@change="handleChange"
@keyup="handleKeyUp"
@compositionstart="handleCompositionStart"
@compositionend="handleCompositionEnd"
>
<div
v-if="$slots.affix"
class="n-input__affix"
v-if="$slots.affix || $slots.prefix"
class="n-input__prefix"
>
<slot name="affix" />
</div>
<div
v-if="$slots.suffix"
class="n-input__suffix"
:class="{
'n-input__suffix--hide': !showIcon
}"
>
<slot name="suffix" />
</div>
<div class="n-input__cancel-mark">
<n-cancel-mark
:theme="synthesizedTheme"
:show="showCancelMark"
:clearable="clearable"
@clear="handleClear"
/>
<slot name="affix">
<slot name="prefix" />
</slot>
</div>
<transition name="n-button-suffix--transition">
<div
class="n-input__suffix"
>
<div class="n-input__cancel-mark">
<n-cancel-mark
:theme="synthesizedTheme"
:show="showCancelMark"
:clearable="clearable"
@clear="handleClear"
/>
</div>
<slot name="suffix" />
</div>
</transition>
<div class="n-input__border-mask" />
</div>
</template>
@ -217,9 +213,9 @@ export default {
},
data () {
return {
isComposing: false,
focus: false,
hover: false,
isComposing: false,
inputFocused: false,
shouldReturnFocusToWrapper: false,
waitingBlurCallback: false
@ -240,16 +236,12 @@ export default {
return this.placeholder
}
},
showIcon () {
if (this.$slots.suffix && this.showCancelMark) return false
return true
},
showCancelMark () {
if (this.disabled || !this.clearable || (!this.focus && !this.hover)) return false
if (this.disabled || !this.clearable) return false
if (this.pair) {
return !!(Array.isArray(this.value) && (this.value[0] || this.value[1])) && (this.hover || this.focus)
return !!(Array.isArray(this.value) && (this.value[0] || this.value[1]))
} else {
return !!this.value && (this.hover || this.focus)
return !!this.value
}
},
isTextarea () {
@ -294,9 +286,9 @@ export default {
handleCompositionStart () {
this.isComposing = true
},
handleCompositionEnd (event) {
handleCompositionEnd (e) {
this.isComposing = false
this.handleInput(event)
this.handleInput(e)
},
handleInput (e, index) {
if (this.isComposing) return
@ -347,7 +339,6 @@ export default {
}
},
handleKeyUp (e) {
if (this.isComposing) return
this.$emit('keyup', e)
},
handleChange (e) {
@ -357,6 +348,7 @@ export default {
this.$emit('click', e)
},
handleClear () {
this.$emit('clear')
if (this.pair) {
this.$emit('change', [])
this.$emit('input', [])

View File

@ -4,7 +4,7 @@
@include themes-mixin {
@include b(cancel-mark) {
@include once {
@include fade-in-transition(cancel-mark);
@include fade-in-scale-up-transition(cancel-mark);
user-select: none;
display: inline-block;
position: relative;

View File

@ -8,4 +8,8 @@
display: inline-block;
position: relative;
transition: $--icon-transition;
svg {
height: 1em;
width: 1em;
}
}

View File

@ -43,7 +43,7 @@
}
}
}
@include m(affix) {
@include m(prefix) {
@include not-m(split) {
@include e(input) {
padding-left: 38px!important;
@ -111,32 +111,32 @@
border-radius: $--input-border-radius;
transition: border-color .3s $--n-ease-in-out-cubic-bezier, box-shadow .3s $--n-ease-in-out-cubic-bezier;
}
@include e(suffix, affix) {
transition: opacity .3s $--n-ease-in-out-cubic-bezier;
@include e(suffix, prefix) {
position: absolute;
line-height: $--input-icon-size;
height: $--input-icon-size;
line-height: 1.5;
height: 0;
width: $--input-icon-size;
white-space: nowrap;
display: flex;
align-items: center;
justify-content: center;
top: 50%;
@include b(icon) {
justify-self: center;
font-size: $--input-icon-size;
}
top: calc(50% - 9px);
}
@include e(suffix) {
@include fade-in-scale-up-transition(button-suffix);
justify-content: flex-end;
right: 12px;
}
@include e(affix) {
@include e(prefix) {
justify-content: flex-start;
left: 12px;
}
@include e(cancel-mark) {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
line-height: 12px;
display: flex;
margin-right: 4px;
}
@include e(textarea, textarea-mirror) {
display: inline-block;
@ -188,19 +188,17 @@
}
background-color: map-get($--input-background-color, 'focus');
}
@include m(textarea) {
padding-left: 0;
padding-right: 0;
@include e(textarea, textarea-mirror) {
padding-left: 14px;
padding-right: 14px;
@include once {
@include m(textarea) {
padding-left: 0;
padding-right: 0;
@include e(textarea, textarea-mirror) {
padding-left: 14px;
padding-right: 14px;
}
}
}
@include e(suffix, affix) {
opacity: 1;
@include m(hide) {
opacity: 0;
}
@include e(suffix, prefix) {
@include b(icon) {
fill: $--input-icon-color;
stroke: $--input-icon-color;
@ -216,37 +214,45 @@
font-family: $--n-font-family;
width: 100%;
transition: color .3s $--n-ease-in-out-cubic-bezier, text-decoration-color .3s $--n-ease-in-out-cubic-bezier;
background-color: transparent;
}
color: map-get($--input-color, 'default');
caret-color: map-get($--input-caret-color, 'default');
background-color: transparent;
&::placeholder {
transition: color .3s $--n-ease-in-out-cubic-bezier;
@include once {
transition: color .3s $--n-ease-in-out-cubic-bezier;
opacity: 1;
}
color: map-get($--input-placeholder-color, 'default');
opacity: 1;
}
}
@include e(splitor) {
transition: color .3s $--n-ease-in-out-cubic-bezier;
color: map-get($--input-color, 'default');
padding-left: 0px;
padding-right: 0px;
@include once {
padding-left: 0px;
padding-right: 0px;
}
}
@include m(disabled) {
cursor: not-allowed;
@include once {
cursor: not-allowed;
}
box-shadow: map-get($--input-box-shadow, 'disabled') !important;
@include e(border-mask) {
border-color: map-get($--input-border-mask-border-color, 'disabled') !important;
}
background-color: map-get($--input-background-color, 'disabled');
@include e(input, textarea) {
cursor: not-allowed;
@include once {
cursor: not-allowed;
}
color: map-get($--input-color, 'disabled');
&::placeholder {
color: map-get($--input-placeholder-color, 'disabled');
}
}
@include e(suffix, affix) {
@include e(suffix, prefix) {
@include b(icon) {
fill: map-get($--input-placeholder-color, 'disabled');
stroke: map-get($--input-placeholder-color, 'disabled');