mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-02-17 13:20:52 +08:00
feat(input-number): add styles and some features for input-number
This commit is contained in:
parent
305d629c62
commit
3c36d36473
@ -14,31 +14,52 @@
|
||||
Basic Usage
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
{{ value }}
|
||||
<n-input-number v-model="value" />
|
||||
{{ value1 }}
|
||||
<n-input-number
|
||||
v-model="value1"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea><n-input-number v-model="value" /></textarea>
|
||||
<textarea v-pre><n-input-number
|
||||
v-model="value1"
|
||||
/>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
value1: null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Min and Max
|
||||
Disabled
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
{{ value }}
|
||||
<n-input-number
|
||||
v-model="value"
|
||||
:min="-5"
|
||||
:max="5"
|
||||
v-model="value2"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea><n-input-number
|
||||
v-model="value"
|
||||
:min="-5"
|
||||
:max="5"
|
||||
/></textarea>
|
||||
<textarea v-pre><n-input-number
|
||||
v-model="value2"
|
||||
disabled
|
||||
/>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
value2: 1
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
@ -46,20 +67,104 @@
|
||||
Step
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
{{ value }}
|
||||
{{ value3 }}
|
||||
<n-input-number
|
||||
v-model="value"
|
||||
:min="-10"
|
||||
:max="10"
|
||||
step="3"
|
||||
v-model="value3"
|
||||
:step="2"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea><n-input-number
|
||||
v-model="value"
|
||||
:min="-10"
|
||||
:max="10"
|
||||
step="3"
|
||||
v-model="value3"
|
||||
:step="2"
|
||||
/>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
value3: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Event
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
{{ value4 }}
|
||||
<n-input-number
|
||||
v-model="value4"
|
||||
@change="handleChange"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea v-pre><n-input-number
|
||||
v-model="value4"
|
||||
@change="handleChange"
|
||||
/>
|
||||
<script>
|
||||
handleChange (newValue, oldValue) {
|
||||
alert(`newValue: ${newValue}; oldValue: ${oldValue}`)
|
||||
}
|
||||
</script>
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Size
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
{{ value5 }}
|
||||
<n-input-number
|
||||
v-model="value5"
|
||||
size="small"
|
||||
/>
|
||||
<n-input-number
|
||||
v-model="value5"
|
||||
size="medium"
|
||||
/>
|
||||
<n-input-number
|
||||
v-model="value5"
|
||||
size="large"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea v-pre><n-input-number
|
||||
v-model="value5"
|
||||
size="small"
|
||||
/>
|
||||
<n-input-number
|
||||
v-model="value5"
|
||||
size="medium"
|
||||
/>
|
||||
<n-input-number
|
||||
v-model="value5"
|
||||
size="large"
|
||||
/></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="n-doc-section">
|
||||
<div class="n-doc-section__header">
|
||||
Min and Max
|
||||
</div>
|
||||
<div class="n-doc-section__view">
|
||||
{{ value6 }}
|
||||
<n-input-number
|
||||
v-model="value6"
|
||||
:min="-2"
|
||||
:max="5"
|
||||
/>
|
||||
</div>
|
||||
<div class="n-doc-section__source">
|
||||
<textarea v-pre><n-input-number
|
||||
v-model="value6"
|
||||
:min="-2"
|
||||
:max="5"
|
||||
/></textarea>
|
||||
</div>
|
||||
</div>
|
||||
@ -73,10 +178,18 @@ export default {
|
||||
mixins: [docCodeEditorMixin],
|
||||
data () {
|
||||
return {
|
||||
value: 'plx'
|
||||
value1: null,
|
||||
value2: 1,
|
||||
value3: 2,
|
||||
value4: 3,
|
||||
value5: 4,
|
||||
value6: 5
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange (newValue, oldValue) {
|
||||
alert(`newValue: ${newValue}; oldValue: ${oldValue}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -1,17 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<button @click="minus">
|
||||
-
|
||||
</button><input
|
||||
<div
|
||||
class="n-input-number"
|
||||
:class="{
|
||||
[`n-input-number--${size}-size`]: true,
|
||||
'n-input-number--disabled': disabled
|
||||
}"
|
||||
>
|
||||
<button
|
||||
class="n-input-number__minus-button"
|
||||
:class="{
|
||||
[`n-input-bumber__button--disabled`]: value !== null && safeMin !== null && value <= safeMin
|
||||
}"
|
||||
@click="minus"
|
||||
>
|
||||
<n-icon type="md-remove" />
|
||||
</button>
|
||||
<input
|
||||
class="n-input-number__input"
|
||||
type="text"
|
||||
:value="value"
|
||||
><button @click="add">
|
||||
+
|
||||
:disabled="disabled ? 'disabled' : false"
|
||||
@blur="handleBlurOrEnter"
|
||||
@keyup.enter="handleBlurOrEnter"
|
||||
>
|
||||
<button
|
||||
class="n-input-number__add-button"
|
||||
:class="{
|
||||
[`n-input-bumber__button--disabled`]: value !== null && safeMax !== null && value >= safeMax
|
||||
}"
|
||||
@click="add"
|
||||
>
|
||||
<n-icon type="md-add" />
|
||||
</button>
|
||||
<div class="n-input-number__border-layer" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import NIcon from '../../Icon/index'
|
||||
|
||||
const DEFAULT_STEP = 1
|
||||
|
||||
function parseNumber (number) {
|
||||
@ -29,13 +56,12 @@ function parseNumber (number) {
|
||||
|
||||
export default {
|
||||
name: 'NInputNumber',
|
||||
model: {
|
||||
prop: 'value',
|
||||
event: 'change'
|
||||
components: {
|
||||
NIcon
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: [Number, String],
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
step: {
|
||||
@ -49,6 +75,14 @@ export default {
|
||||
max: {
|
||||
type: [Number, String],
|
||||
default: null
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'medium'
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -66,42 +100,73 @@ export default {
|
||||
const parsedNumber = parseNumber(this.max)
|
||||
if (parsedNumber !== null) return parsedNumber
|
||||
else return null
|
||||
},
|
||||
aValidValue () {
|
||||
if (this.safeMin !== null) {
|
||||
return Math.max(0, this.safeMin)
|
||||
} else if (this.safeMax !== null) {
|
||||
return Math.min(0, this.safeMax)
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (newValue, oldValue) {
|
||||
if (newValue !== null) {
|
||||
if (this.safeMax !== null && newValue > this.safeMax) {
|
||||
newValue = this.safeMax
|
||||
}
|
||||
if (this.safeMin !== null && newValue < this.safeMin) {
|
||||
newValue = this.safeMin
|
||||
}
|
||||
}
|
||||
this.$emit('change', newValue, oldValue)
|
||||
/**
|
||||
* newValue === oldValue won't trigger watcher!
|
||||
* so the call stack won't fall in loop
|
||||
*/
|
||||
this.$emit('input', newValue)
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.guardCurrentValue()
|
||||
if (this.value !== null) {
|
||||
if (this.safeMax !== null && this.value > this.safeMax) {
|
||||
this.$emit('input', this.safeMax)
|
||||
} else if (this.safeMin !== null && this.value < this.safeMin) {
|
||||
this.$emit('input', this.safeMin)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
guardCurrentValue () {
|
||||
if (typeof this.value !== 'number') {
|
||||
const parsedNumber = Number(this.value)
|
||||
if (Number.isNaN(parsedNumber)) {
|
||||
this.$emit('change', 0)
|
||||
} else {
|
||||
this.$emit('change', parsedNumber)
|
||||
}
|
||||
}
|
||||
},
|
||||
add () {
|
||||
this.guardCurrentValue()
|
||||
const previousValue = this.value
|
||||
let valueAfterChange = this.value + this.safeStep
|
||||
if (this.safeMax !== null && valueAfterChange > this.safeMax) {
|
||||
valueAfterChange = this.safeMax
|
||||
}
|
||||
if (valueAfterChange !== previousValue) {
|
||||
this.$emit('change', valueAfterChange)
|
||||
if (this.value === null) {
|
||||
this.$emit('input', this.aValidValue)
|
||||
} else {
|
||||
const valueAfterChange = this.value + this.safeStep
|
||||
this.$emit('input', valueAfterChange)
|
||||
}
|
||||
},
|
||||
minus () {
|
||||
this.guardCurrentValue()
|
||||
const previousValue = this.value
|
||||
let valueAfterChange = this.value - this.safeStep
|
||||
if (this.safeMin !== null && valueAfterChange < this.safeMin) {
|
||||
valueAfterChange = this.safeMin
|
||||
if (this.value === null) {
|
||||
this.$emit('input', this.aValidValue)
|
||||
} else {
|
||||
const valueAfterChange = this.value - this.safeStep
|
||||
this.$emit('input', valueAfterChange)
|
||||
}
|
||||
if (valueAfterChange !== previousValue) {
|
||||
this.$emit('change', valueAfterChange)
|
||||
},
|
||||
handleBlurOrEnter (e) {
|
||||
const value = e.target.value
|
||||
if (value === '') {
|
||||
this.$emit('input', null)
|
||||
return
|
||||
}
|
||||
const parsedNumber = Number(value)
|
||||
if (Number.isNaN(parsedNumber)) {
|
||||
e.target.value = String(this.value)
|
||||
} else {
|
||||
const valueAfterChange = parsedNumber
|
||||
this.$emit('input', valueAfterChange)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
119
styles/InputNumber.scss
Normal file
119
styles/InputNumber.scss
Normal file
@ -0,0 +1,119 @@
|
||||
@import './mixins/mixins.scss';
|
||||
@import './theme/default.scss';
|
||||
|
||||
@include b(input-number) {
|
||||
position: relative;
|
||||
border-radius: $input-number-border-radius;
|
||||
background-color: $input-number-background-color;
|
||||
width: 152px;
|
||||
display: inline-block;
|
||||
vertical-align: bottom;
|
||||
& * {
|
||||
outline: none;
|
||||
}
|
||||
&.n-input-number--disabled {
|
||||
background:rgba(238,238,238,0.05);
|
||||
.n-input-number__minus-button, .n-input-number__add-button {
|
||||
background:rgba(238,238,238,0.05);
|
||||
color:rgba(233,233,236,0.2);
|
||||
pointer-events: none;
|
||||
}
|
||||
.n-input-number__input {
|
||||
color:rgba(233,233,236,0.2);
|
||||
pointer-events: none;
|
||||
}
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&.n-input-number--default-size, &.n-input-number--medium-size {
|
||||
height: $medium-height;
|
||||
line-height: $medium-height;
|
||||
.n-input-number__minus-button, .n-input-number__add-button, .n-input-number__input {
|
||||
height: $medium-height;
|
||||
line-height: $medium-height;
|
||||
}
|
||||
}
|
||||
&.n-input-number--small-size {
|
||||
height: $small-height;
|
||||
line-height: $small-height;
|
||||
.n-input-number__minus-button, .n-input-number__add-button, .n-input-number__input {
|
||||
height: $small-height;
|
||||
line-height: $small-height;
|
||||
}
|
||||
}
|
||||
&.n-input-number--large-size {
|
||||
height: $large-height;
|
||||
line-height: $large-height;
|
||||
.n-input-number__minus-button, .n-input-number__add-button, .n-input-number__input {
|
||||
height: $large-height;
|
||||
line-height: $large-height;
|
||||
}
|
||||
}
|
||||
.n-input-number__border-layer {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
border-radius: $input-number-border-radius;
|
||||
transition: box-shadow .3s $default-cubic-bezier;
|
||||
pointer-events: none;
|
||||
}
|
||||
.n-input-number__minus-button, .n-input-number__add-button {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
padding: 0;
|
||||
width: 28px;
|
||||
border: none;
|
||||
background-color: $input-number-button-background-color;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #eeeeee;
|
||||
font-size: 14px;
|
||||
transition: color .3s $default-cubic-bezier, background-color .3s $default-cubic-bezier;
|
||||
&:hover~.n-input-number__border-layer {
|
||||
box-shadow: inset 0 0 0px 1px $main-color;
|
||||
}
|
||||
&:hover {
|
||||
color: $main-color;
|
||||
}
|
||||
&:active {
|
||||
transition: color .3s $default-cubic-bezier, background-color .15s $default-cubic-bezier;
|
||||
background-color: rgba(99,226,183,0.12)
|
||||
}
|
||||
&.n-input-bumber__button--disabled {
|
||||
background-color: rgba(221,238,247,0.3);
|
||||
color: rgba(255, 255, 255, .2);
|
||||
cursor: not-allowed;
|
||||
}
|
||||
}
|
||||
.n-input-number__minus-button {
|
||||
left: 0;
|
||||
border-top-left-radius: $input-number-border-radius;
|
||||
border-bottom-left-radius: $input-number-border-radius;
|
||||
}
|
||||
.n-input-number__add-button {
|
||||
right: 0;
|
||||
border-top-right-radius: $input-number-border-radius;
|
||||
border-bottom-right-radius: $input-number-border-radius;
|
||||
}
|
||||
.n-input-number__input {
|
||||
&:hover~.n-input-number__border-layer {
|
||||
box-shadow: inset 0 0 0px 1px $main-color;
|
||||
}
|
||||
&:focus {
|
||||
background-color: rgba(99,226,183,0.12);
|
||||
&~.n-input-number__border-layer {
|
||||
box-shadow: inset 0 0 0px 1px $main-color, 0px 0px 10px 1px #366555;
|
||||
}
|
||||
}
|
||||
transition: color .3s $default-cubic-bezier, background-color .3s $default-cubic-bezier;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: $input-number-color;
|
||||
width: 84px;
|
||||
text-align: center;
|
||||
padding: 0 34px;
|
||||
caret-color: $input-caret-color;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user