From c221922e04575463a8e4ece566ebb70d4e52ed24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=98=89=E6=B6=B5?= Date: Fri, 8 Sep 2017 16:33:20 +0800 Subject: [PATCH 1/3] Loading: fix white spinner color --- docs/examples-docs/loading.md | 2 +- packages/vant-css/src/loading.css | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples-docs/loading.md b/docs/examples-docs/loading.md index b6a4521f7..4b577895c 100644 --- a/docs/examples-docs/loading.md +++ b/docs/examples-docs/loading.md @@ -22,8 +22,8 @@ Vue.component(Loading.name, Loading); :::demo 单色 spinner ```html - + ``` ::: diff --git a/packages/vant-css/src/loading.css b/packages/vant-css/src/loading.css index 94288eeb3..055031e79 100644 --- a/packages/vant-css/src/loading.css +++ b/packages/vant-css/src/loading.css @@ -41,8 +41,8 @@ } &.van-loading__spinner--white { - border-color: rgba(0, 0, 0, .5); - border-top-color: transparent; + border-color: rgba(0, 0, 0, .1); + border-top-color: rgba(255, 255, 255, .7); } } From f0cbcc99dcb5c78d72396c2c19565b1cc371d55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=98=89=E6=B6=B5?= Date: Fri, 8 Sep 2017 21:06:16 +0800 Subject: [PATCH 2/3] add NumberKeyboard component --- docs/examples-docs/number-keyboard.md | 101 ++++++++++++++ docs/src/doc.config.js | 4 + packages/index.js | 3 + packages/number-keyboard/index.vue | 137 +++++++++++++++++++ packages/vant-css/src/base.css | 1 + packages/vant-css/src/common/animation.css | 21 +++ packages/vant-css/src/index.css | 1 + packages/vant-css/src/number-keyboard.css | 52 ++++++++ test/unit/specs/number-keyboard.spec.js | 146 +++++++++++++++++++++ 9 files changed, 466 insertions(+) create mode 100644 docs/examples-docs/number-keyboard.md create mode 100644 packages/number-keyboard/index.vue create mode 100644 packages/vant-css/src/common/animation.css create mode 100644 packages/vant-css/src/number-keyboard.css create mode 100644 test/unit/specs/number-keyboard.spec.js diff --git a/docs/examples-docs/number-keyboard.md b/docs/examples-docs/number-keyboard.md new file mode 100644 index 000000000..362d1d1f8 --- /dev/null +++ b/docs/examples-docs/number-keyboard.md @@ -0,0 +1,101 @@ + + + + +## NumberKeyboard 数字键盘 + +### 使用指南 +``` javascript +import { NumberKeyboard } from 'vant'; + +Vue.component(NumberKeyboard.name, NumberKeyboard); +``` + +### 代码演示 + +#### 基础用法 + +:::demo 基础用法 +```html + + 弹出键盘 + + + + 收起键盘 + + + +``` + +```javascript +export default { + data() { + return { + showKeyboard: true + } + }, + + methods: { + onInput(value) { + Toast(value); + }, + onDelete() { + Toast('delete'); + } + } +} +``` +::: + + +### API + +| 参数 | 说明 | 类型 | 默认值 | 可选值 | +|-----------|-----------|-----------|-------------|-------------| +| show | 是否显示键盘 | `Boolean` | - | - | +| title | 键盘标题 | `String` | `安全输入键盘` | - | +| extraKey | 左下角按键内容 | `String` | `''` | - | +| zIndex | 键盘 z-index | `Number` | `100` | - | +| transition | 是否开启过场动画 | `Boolean` | `true` | - | +| showDeleteKey | 是否展示删除按钮 | `Boolean` | `true` | - | + +### Event + +| 事件名 | 说明 | 参数 | +|-----------|-----------|-----------| +| input | 点击按键时触发 | key: 按键内容 | +| delete | 点击删除键时触发 | - | +| blur | 点击非键盘区域时触发 | - | +| show | 键盘完全弹出时触发 | - | +| hide | 键盘完全收起时触发 | - | diff --git a/docs/src/doc.config.js b/docs/src/doc.config.js index 492844c19..a840d170d 100644 --- a/docs/src/doc.config.js +++ b/docs/src/doc.config.js @@ -143,6 +143,10 @@ module.exports = { "path": "/field", "title": "Field 输入框" }, + { + "path": "/number-keyboard", + "title": "NumberKeyboard 数字键盘" + }, { "path": "/radio", "title": "Radio 单选框" diff --git a/packages/index.js b/packages/index.js index 2129658e0..08d141822 100644 --- a/packages/index.js +++ b/packages/index.js @@ -24,6 +24,7 @@ import Lazyload from './lazyload'; import Loading from './loading'; import NavBar from './nav-bar'; import NoticeBar from './notice-bar'; +import NumberKeyboard from './number-keyboard'; import Panel from './panel'; import Picker from './picker'; import Popup from './popup'; @@ -74,6 +75,7 @@ const components = [ Loading, NavBar, NoticeBar, + NumberKeyboard, Panel, Picker, Popup, @@ -140,6 +142,7 @@ export { Loading, NavBar, NoticeBar, + NumberKeyboard, Panel, Picker, Popup, diff --git a/packages/number-keyboard/index.vue b/packages/number-keyboard/index.vue new file mode 100644 index 000000000..41ac7d1f1 --- /dev/null +++ b/packages/number-keyboard/index.vue @@ -0,0 +1,137 @@ + + + diff --git a/packages/vant-css/src/base.css b/packages/vant-css/src/base.css index 5cbf9bc24..9a148e573 100644 --- a/packages/vant-css/src/base.css +++ b/packages/vant-css/src/base.css @@ -5,4 +5,5 @@ @import "./common/var.css"; @import "./common/normalize.css"; @import "./common/hairline.css"; +@import "./common/animation.css"; diff --git a/packages/vant-css/src/common/animation.css b/packages/vant-css/src/common/animation.css new file mode 100644 index 000000000..070c8e1fc --- /dev/null +++ b/packages/vant-css/src/common/animation.css @@ -0,0 +1,21 @@ +@keyframes van-slide-bottom-enter { + from { + transform: translate3d(0, 100%, 0); + } +} + +@keyframes van-slide-bottom-leave { + to { + transform: translate3d(0, 100%, 0); + } +} + +.van-slide-bottom { + &-enter-active { + animation: van-slide-bottom-enter .3s both ease; + } + + &-leave-active { + animation: van-slide-bottom-leave .3s both ease; + } +} diff --git a/packages/vant-css/src/index.css b/packages/vant-css/src/index.css index 140c245e2..545716d92 100644 --- a/packages/vant-css/src/index.css +++ b/packages/vant-css/src/index.css @@ -34,6 +34,7 @@ @import './radio.css'; @import './switch.css'; @import './uploader.css'; +@import './number-keyboard.css'; /* action components */ @import './actionsheet.css'; diff --git a/packages/vant-css/src/number-keyboard.css b/packages/vant-css/src/number-keyboard.css new file mode 100644 index 000000000..fc2c4b39a --- /dev/null +++ b/packages/vant-css/src/number-keyboard.css @@ -0,0 +1,52 @@ +@import "./common/var.css"; + +.van-number-keyboard { + left: 0; + bottom: 0; + width: 100%; + position: fixed; + user-select: none; + background-color: $white; + animation-timing-function: ease-out; + + &__title { + font-weight: 400; + text-align: center; + color: $gray-dark; + font-size: 12px; + line-height: 25px; + } + + i { + width: calc(100%/3); + height: 54px; + font-size: 24px; + line-height: 54px; + font-style: normal; + text-align: center; + display: inline-block; + vertical-align: middle; + + &::after { + border-top-width: 1px; + } + + &:not(:nth-of-type(3n))::after { + border-right-width: 1px; + } + + &:nth-of-type(10), + &:nth-of-type(12) { + background-color: #F3F3F6; + } + } + + &__delete { + background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAeCAMAAABg6AyVAAAAbFBMVEUAAAAfHiIdHB4eHR8dHR4eHB4dHB4dHR8gICIdHB4dHB4dHB4dHB8eHh8hISEeHR8fHB8fHR8fHR8fHx8eHiArKyszMzMeHB8eHB8fHR8eHiAeHh4dHB4vLjDY2Nn////b29zKysq9vb28vLzkfBRpAAAAHHRSTlMAK/PW+I/llBv77N1kSCPwWlFAOTMGBb28hHlu08g5sgAAAMlJREFUOMuV1MsWgiAQgGHQyOx+s+sgYO//jnnMGIdDDfwbN99CYEDQFiVEKkolPUG7gl9VTWC31NKuDbVz+Fc1tRJtPDmxS2BS3p5ZC+XXnnbAVoz2WEBCH7uZAalzGoa06whGiznT6sG2xgX4QO2Aej1+KN7XBKL2FvGaMtTWBhbQhtoaYzVQrHKwuGf8hhAPSF5g3xPSt45sCHcouNWx436FGA+RHyQcD35EcUj54U8ff4WYvVi1zLjelUh/OG6XjOeLWv5hfAOI+HLwwOAqhAAAAABJRU5ErkJggg==") no-repeat center center; + background-size: auto 15px; + } + + i&--active { + background-color: $active-color!important; + } +} diff --git a/test/unit/specs/number-keyboard.spec.js b/test/unit/specs/number-keyboard.spec.js new file mode 100644 index 000000000..526a65885 --- /dev/null +++ b/test/unit/specs/number-keyboard.spec.js @@ -0,0 +1,146 @@ +import NumberKeyboard from 'packages/number-keyboard'; +import { mount } from 'avoriaz'; +import { triggerTouch } from '../utils'; + +function mockKeyDown(wrapper, keyIndex) { + const customEvent = document.createEvent('CustomEvent'); + customEvent.initCustomEvent('touchstart', true, true, {}); + Object.defineProperty(customEvent, 'target', { + value: { + dataset: { + key: keyIndex + } + } + }); + wrapper.element.dispatchEvent(customEvent); +} + +describe('NumberKeyboard', () => { + let wrapper; + afterEach(() => { + wrapper && wrapper.destroy(); + }); + + it('create a NumberKeyboard', () => { + wrapper = mount(NumberKeyboard, {}); + expect(wrapper.hasClass('van-number-keyboard')).to.be.true; + }); + + it('click a keyboard key', (done) => { + wrapper = mount(NumberKeyboard, {}); + + // just for coverage + wrapper.vm.handler(true); + + wrapper.vm.$on('input', value => { + expect(value).to.equal(1); + expect(wrapper.vm.active).to.equal(0); + + triggerTouch(wrapper, 'touchend'); + expect(wrapper.vm.active).to.equal(-1); + done(); + }); + + mockKeyDown(wrapper, 9); + mockKeyDown(wrapper, NaN); + mockKeyDown(wrapper, 0); + }); + + it('click delete key', (done) => { + wrapper = mount(NumberKeyboard, {}); + + const deleteSpy = sinon.spy(); + wrapper.vm.$on('delete', deleteSpy); + + mockKeyDown(wrapper, 11); + wrapper.vm.$nextTick(() => { + expect(deleteSpy.calledOnce).to.be.true; + done(); + }); + }); + + it('blur keyboard', (done) => { + wrapper = mount(NumberKeyboard, { + attachToDocument: true + }); + + const blur = sinon.spy(); + wrapper.vm.$on('blur', blur); + + triggerTouch(document.body, 'touchstart'); + wrapper.vm.$nextTick(() => { + expect(blur.calledOnce).to.be.true; + done(); + }); + }); + + it('listen to show event when has transtion', (done) => { + wrapper = mount(NumberKeyboard, { + attachToDocument: true + }); + + const show = sinon.spy(); + wrapper.vm.$on('show', show); + wrapper.vm.show = true; + + setTimeout(() => { + expect(show.calledOnce).to.be.true; + done(); + }, 800); + }); + + it('listen to show event when no transtion', (done) => { + wrapper = mount(NumberKeyboard, { + attachToDocument: true, + propsData: { + transition: false + } + }); + + const show = sinon.spy(); + wrapper.vm.$on('show', show); + wrapper.vm.show = true; + + wrapper.vm.$nextTick(() => { + expect(show.calledOnce).to.be.true; + done(); + }); + }); + + it('listen to hide event when has transtion', (done) => { + wrapper = mount(NumberKeyboard, { + attachToDocument: true, + propsData: { + show: true + } + }); + + const hide = sinon.spy(); + wrapper.vm.$on('hide', hide); + wrapper.vm.show = false; + + setTimeout(() => { + expect(hide.calledOnce).to.be.true; + done(); + }, 800); + }); + + it('listen to hide event when no transtion', (done) => { + wrapper = mount(NumberKeyboard, { + attachToDocument: true, + propsData: { + show: true, + transition: false + } + }); + + const hide = sinon.spy(); + wrapper.vm.$on('hide', hide); + wrapper.vm.show = false; + + wrapper.vm.$nextTick(() => { + expect(hide.calledOnce).to.be.true; + done(); + }); + }); +}); From c4f11baf7cceaf4109cec15e79d0e2b143bf4809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E5=98=89=E6=B6=B5?= Date: Mon, 11 Sep 2017 10:22:12 +0800 Subject: [PATCH 3/3] NumberKeyboard: fix test cases fail --- test/unit/components/number-keyboard.vue | 19 ++++++++++++++ test/unit/specs/number-keyboard.spec.js | 32 +++++++++++++++++------- 2 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 test/unit/components/number-keyboard.vue diff --git a/test/unit/components/number-keyboard.vue b/test/unit/components/number-keyboard.vue new file mode 100644 index 000000000..b6cd28b8d --- /dev/null +++ b/test/unit/components/number-keyboard.vue @@ -0,0 +1,19 @@ + + + diff --git a/test/unit/specs/number-keyboard.spec.js b/test/unit/specs/number-keyboard.spec.js index 526a65885..d096722e4 100644 --- a/test/unit/specs/number-keyboard.spec.js +++ b/test/unit/specs/number-keyboard.spec.js @@ -1,17 +1,12 @@ import NumberKeyboard from 'packages/number-keyboard'; +import NumberKeyboardKeepAlive from '../components/number-keyboard'; import { mount } from 'avoriaz'; import { triggerTouch } from '../utils'; function mockKeyDown(wrapper, keyIndex) { const customEvent = document.createEvent('CustomEvent'); customEvent.initCustomEvent('touchstart', true, true, {}); - Object.defineProperty(customEvent, 'target', { - value: { - dataset: { - key: keyIndex - } - } - }); + wrapper.element.dataset.key = keyIndex; wrapper.element.dispatchEvent(customEvent); } @@ -82,11 +77,12 @@ describe('NumberKeyboard', () => { const show = sinon.spy(); wrapper.vm.$on('show', show); wrapper.vm.show = true; + wrapper.trigger('animationend'); setTimeout(() => { expect(show.calledOnce).to.be.true; done(); - }, 800); + }, 100); }); it('listen to show event when no transtion', (done) => { @@ -118,11 +114,12 @@ describe('NumberKeyboard', () => { const hide = sinon.spy(); wrapper.vm.$on('hide', hide); wrapper.vm.show = false; + wrapper.trigger('animationend'); setTimeout(() => { expect(hide.calledOnce).to.be.true; done(); - }, 800); + }, 100); }); it('listen to hide event when no transtion', (done) => { @@ -143,4 +140,21 @@ describe('NumberKeyboard', () => { done(); }); }); + + it('keey-alive live cycle', (done) => { + wrapper = mount(NumberKeyboardKeepAlive, { + attachToDocument: true, + propsData: { + showKeyboard: true + } + }); + + expect(wrapper.find('.van-number-keyboard').length).to.equal(1); + + wrapper.vm.showKeyboard = false; + wrapper.vm.$nextTick(() => { + expect(wrapper.find('.van-number-keyboard').length).to.equal(0); + done(); + }); + }); });