[new feature] NumberKeyboard: add delete slot (#3499)

This commit is contained in:
neverland 2019-06-13 19:23:51 +08:00 committed by GitHub
parent 639450709f
commit efa2e0c5d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 149 additions and 62 deletions

View File

@ -4,7 +4,8 @@ const [sfc, bem] = use('key');
export default sfc({ export default sfc({
props: { props: {
type: Array, type: String,
theme: Array,
text: [String, Number] text: [String, Number]
}, },
@ -16,9 +17,17 @@ export default sfc({
computed: { computed: {
className() { className() {
const types = this.type.slice(0); const classNames = this.theme.slice(0);
this.active && types.push('active');
return bem(types); if (this.active) {
classNames.push('active');
}
if (this.type) {
classNames.push(this.type);
}
return bem(classNames);
} }
}, },
@ -32,7 +41,7 @@ export default sfc({
}, },
onClick() { onClick() {
this.$emit('press', this.text); this.$emit('press', this.text, this.type);
} }
}, },
@ -49,7 +58,7 @@ export default sfc({
onTouchend={onBlur} onTouchend={onBlur}
onTouchcancel={onBlur} onTouchcancel={onBlur}
> >
{this.text} {this.slots('default') || this.text}
</i> </i>
); );
} }

View File

@ -92,4 +92,5 @@ export default {
| Name | Description | | Name | Description |
|------|------| |------|------|
| delete | Custom delete button content |
| title-left | Custom title left content | | title-left | Custom title left content |

View File

@ -4,8 +4,8 @@ import { BindEventMixin } from '../mixins/bind-event';
import Key from './Key'; import Key from './Key';
const [sfc, bem, t] = use('number-keyboard'); const [sfc, bem, t] = use('number-keyboard');
const CLOSE_KEY_TYPE = ['blue', 'big']; const CLOSE_KEY_THEME = ['blue', 'big'];
const DELETE_KEY_TYPE = ['delete', 'big', 'gray']; const DELETE_KEY_THEME = ['delete', 'big', 'gray'];
export default sfc({ export default sfc({
mixins: [ mixins: [
@ -66,13 +66,13 @@ export default sfc({
switch (this.theme) { switch (this.theme) {
case 'default': case 'default':
keys.push( keys.push(
{ text: this.extraKey, type: ['gray'] }, { text: this.extraKey, theme: ['gray'] },
{ text: 0 }, { text: 0 },
{ text: this.deleteText, type: ['gray', 'delete'] } { text: this.deleteText, theme: ['gray'], type: 'delete' }
); );
break; break;
case 'custom': case 'custom':
keys.push({ text: 0, type: ['middle'] }, { text: this.extraKey }); keys.push({ text: 0, theme: ['middle'] }, { text: this.extraKey });
break; break;
} }
@ -98,14 +98,14 @@ export default sfc({
this.$emit(this.show ? 'show' : 'hide'); this.$emit(this.show ? 'show' : 'hide');
}, },
onPress(text) { onPress(text, type) {
if (text === '') { if (text === '') {
return; return;
} }
if (text === this.deleteText) { if (type === 'delete') {
this.$emit('delete'); this.$emit('delete');
} else if (text === this.closeButtonText) { } else if (type === 'close') {
this.onClose(); this.onClose();
} else { } else {
this.$emit('input', text); this.$emit('input', text);
@ -132,6 +132,37 @@ export default sfc({
</div> </div>
); );
const Keys = this.keys.map(key => (
<Key
key={key.text}
text={key.text}
type={key.type}
theme={key.theme}
onPress={onPress}
>
{key.type === 'delete' && this.slots('delete')}
</Key>
));
const Sidebar = theme === 'custom' && (
<div class={bem('sidebar')}>
<Key
text={this.deleteText}
type="delete"
theme={DELETE_KEY_THEME}
onPress={onPress}
>
{this.slots('delete')}
</Key>
<Key
text={closeButtonText}
type="close"
theme={CLOSE_KEY_THEME}
onPress={onPress}
/>
</div>
);
return ( return (
<transition name={this.transition ? 'van-slide-up' : ''}> <transition name={this.transition ? 'van-slide-up' : ''}>
<div <div
@ -143,17 +174,8 @@ export default sfc({
onWebkitAnimationEnd={this.onAnimationEnd} onWebkitAnimationEnd={this.onAnimationEnd}
> >
{Title} {Title}
<div class={bem('body')}> <div class={bem('body')}>{Keys}</div>
{this.keys.map(key => ( {Sidebar}
<Key key={key.text} text={key.text} type={key.type} onPress={onPress} />
))}
</div>
{theme === 'custom' && (
<div class={bem('sidebar')}>
<Key text={this.deleteText} type={DELETE_KEY_TYPE} onPress={onPress} />
<Key text={closeButtonText} type={CLOSE_KEY_TYPE} onPress={onPress} />
</div>
)}
</div> </div>
</transition> </transition>
); );

View File

@ -15,7 +15,7 @@ exports[`renders demo correctly 1`] = `
</span></button> </span></button>
<div class="van-number-keyboard van-number-keyboard--custom van-number-keyboard--safe-area-inset-bottom" style="z-index: 100; display: none;" name="van-slide-up"> <div class="van-number-keyboard van-number-keyboard--custom van-number-keyboard--safe-area-inset-bottom" style="z-index: 100; display: none;" name="van-slide-up">
<div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--middle">0</i><i role="button" tabindex="0" class="van-hairline van-key">.</i></div> <div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--middle">0</i><i role="button" tabindex="0" class="van-hairline van-key">.</i></div>
<div class="van-number-keyboard__sidebar"><i role="button" tabindex="0" class="van-hairline van-key van-key--delete van-key--big van-key--gray">删除</i><i role="button" tabindex="0" class="van-hairline van-key van-key--blue van-key--big">完成</i></div> <div class="van-number-keyboard__sidebar"><i role="button" tabindex="0" class="van-hairline van-key van-key--delete van-key--big van-key--gray van-key--delete">删除</i><i role="button" tabindex="0" class="van-hairline van-key van-key--blue van-key--big van-key--close">完成</i></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,26 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`focus on key 1`] = `
<div class="van-number-keyboard van-number-keyboard--default" style="z-index: 100; display: none;" name="van-slide-up">
<div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key van-key--active">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray"></i><i role="button" tabindex="0" class="van-hairline van-key">0</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray van-key--delete">删除</i></div>
</div>
`;
exports[`focus on key 2`] = `
<div class="van-number-keyboard van-number-keyboard--default" style="z-index: 100; display: none;" name="van-slide-up">
<div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray"></i><i role="button" tabindex="0" class="van-hairline van-key">0</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray van-key--delete">删除</i></div>
</div>
`;
exports[`render title 1`] = `
<div class="van-number-keyboard van-number-keyboard--default" style="z-index: 100; display: none;" name="van-slide-up">
<div class="van-number-keyboard__title van-hairline--top"><span>Title</span><span role="button" tabindex="0" class="van-number-keyboard__close">Close</span></div>
<div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray"></i><i role="button" tabindex="0" class="van-hairline van-key">0</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray van-key--delete">删除</i></div>
</div>
`;
exports[`title-left slot 1`] = ` exports[`title-left slot 1`] = `
<div class="van-number-keyboard van-number-keyboard--default" style="z-index: 100;" name="van-slide-up"> <div class="van-number-keyboard van-number-keyboard--default" style="z-index: 100; display: none;" name="van-slide-up">
<div class="van-number-keyboard__title van-hairline--top"><span class="van-number-keyboard__title-left">Custom Title Left</span></div> <div class="van-number-keyboard__title van-hairline--top"><span class="van-number-keyboard__title-left">Custom Title Left</span></div>
<div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray"></i><i role="button" tabindex="0" class="van-hairline van-key">0</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray van-key--delete">删除</i></div> <div class="van-number-keyboard__body"><i role="button" tabindex="0" class="van-hairline van-key">1</i><i role="button" tabindex="0" class="van-hairline van-key">2</i><i role="button" tabindex="0" class="van-hairline van-key">3</i><i role="button" tabindex="0" class="van-hairline van-key">4</i><i role="button" tabindex="0" class="van-hairline van-key">5</i><i role="button" tabindex="0" class="van-hairline van-key">6</i><i role="button" tabindex="0" class="van-hairline van-key">7</i><i role="button" tabindex="0" class="van-hairline van-key">8</i><i role="button" tabindex="0" class="van-hairline van-key">9</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray"></i><i role="button" tabindex="0" class="van-hairline van-key">0</i><i role="button" tabindex="0" class="van-hairline van-key van-key--gray van-key--delete">删除</i></div>
</div> </div>

View File

@ -1,5 +1,5 @@
import NumberKeyboard from '..'; import NumberKeyboard from '..';
import { mount } from '../../../test/utils'; import { mount, trigger } from '../../../test/utils';
test('click number key', () => { test('click number key', () => {
const wrapper = mount(NumberKeyboard, { const wrapper = mount(NumberKeyboard, {
@ -9,7 +9,10 @@ test('click number key', () => {
} }
}); });
wrapper.findAll('.van-key').at(0).trigger('click'); wrapper
.findAll('.van-key')
.at(0)
.trigger('click');
expect(wrapper.emitted('input')[0][0]).toEqual(1); expect(wrapper.emitted('input')[0][0]).toEqual(1);
wrapper.destroy(); wrapper.destroy();
@ -17,10 +20,22 @@ test('click number key', () => {
it('click delete key', () => { it('click delete key', () => {
const wrapper = mount(NumberKeyboard); const wrapper = mount(NumberKeyboard);
wrapper.findAll('.van-key').at(11).trigger('click'); wrapper
.findAll('.van-key')
.at(11)
.trigger('click');
expect(wrapper.emitted('delete')).toBeTruthy(); expect(wrapper.emitted('delete')).toBeTruthy();
}); });
it('click empty key', () => {
const wrapper = mount(NumberKeyboard);
wrapper
.findAll('.van-key')
.at(9)
.trigger('click');
expect(wrapper.emitted('input')).toBeFalsy();
});
test('click close button', () => { test('click close button', () => {
const wrapper = mount(NumberKeyboard, { const wrapper = mount(NumberKeyboard, {
propsData: { propsData: {
@ -29,31 +44,13 @@ test('click close button', () => {
} }
}); });
wrapper.findAll('.van-key').at(12).trigger('click'); wrapper
.findAll('.van-key')
.at(12)
.trigger('click');
expect(wrapper.emitted('close')).toBeTruthy(); expect(wrapper.emitted('close')).toBeTruthy();
}); });
test('keey-alive live cycle', () => {
const wrapper = mount({
template: `
<keep-alive>
<number-keyboard v-if="show" />
</keep-alive>
`,
props: ['show'],
components: { NumberKeyboard }
}, {
attachToDocument: true,
propsData: {
show: true
}
});
expect(wrapper.vm.$el).toBeTruthy();
wrapper.vm.show = false;
expect(wrapper.vm.el).toBeFalsy();
});
test('listen to show/hide event when has transtion', () => { test('listen to show/hide event when has transtion', () => {
const wrapper = mount(NumberKeyboard); const wrapper = mount(NumberKeyboard);
wrapper.vm.show = true; wrapper.vm.show = true;
@ -76,18 +73,56 @@ test('listen to show event when no transtion', () => {
expect(wrapper.emitted('hide')).toBeTruthy(); expect(wrapper.emitted('hide')).toBeTruthy();
}); });
test('title-left slot', () => { test('render title', () => {
const wrapper = mount({ const wrapper = mount(NumberKeyboard, {
template: ` propsData: {
<number-keyboard show> title: 'Title',
<template v-slot:title-left>Custom Title Left</template> closeButtonText: 'Close'
</number-keyboard>
`
}, {
components: {
NumberKeyboard
} }
}); });
expect(wrapper).toMatchSnapshot(); expect(wrapper).toMatchSnapshot();
}); });
test('title-left slot', () => {
const wrapper = mount(NumberKeyboard, {
scopedSlots: {
'title-left': () => 'Custom Title Left'
}
});
expect(wrapper).toMatchSnapshot();
});
test('hideOnClickOutside', () => {
const wrapper = mount(NumberKeyboard, {
propsData: {
show: true
}
});
trigger(document.body, 'touchstart');
expect(wrapper.emitted('blur')).toBeTruthy();
});
test('disable hideOnClickOutside', () => {
const wrapper = mount(NumberKeyboard, {
propsData: {
show: true,
hideOnClickOutside: false
}
});
trigger(document.body, 'touchstart');
expect(wrapper.emitted('blur')).toBeFalsy();
});
test('focus on key', () => {
const wrapper = mount(NumberKeyboard);
const key = wrapper.find('.van-key');
trigger(key, 'touchstart');
expect(wrapper).toMatchSnapshot();
trigger(key, 'touchend');
expect(wrapper).toMatchSnapshot();
});

View File

@ -93,4 +93,5 @@ export default {
| 名称 | 说明 | | 名称 | 说明 |
|------|------| |------|------|
| delete | 自定义删除按钮内容 |
| title-left | 自定义标题栏左侧内容 | | title-left | 自定义标题栏左侧内容 |