index.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. import { use } from '../utils';
  2. import { stopPropagation } from '../utils/event';
  3. import Key from './Key';
  4. const [sfc, bem, t] = use('number-keyboard');
  5. const CLOSE_KEY_TYPE = ['blue', 'big'];
  6. const DELETE_KEY_TYPE = ['delete', 'big', 'gray'];
  7. export default sfc({
  8. props: {
  9. show: Boolean,
  10. title: String,
  11. closeButtonText: String,
  12. deleteButtonText: String,
  13. safeAreaInsetBottom: Boolean,
  14. theme: {
  15. type: String,
  16. default: 'default'
  17. },
  18. extraKey: {
  19. type: String,
  20. default: ''
  21. },
  22. zIndex: {
  23. type: Number,
  24. default: 100
  25. },
  26. transition: {
  27. type: Boolean,
  28. default: true
  29. },
  30. showDeleteKey: {
  31. type: Boolean,
  32. default: true
  33. },
  34. hideOnClickOutside: {
  35. type: Boolean,
  36. default: true
  37. }
  38. },
  39. mounted() {
  40. this.handler(true);
  41. },
  42. destroyed() {
  43. this.handler(false);
  44. },
  45. activated() {
  46. this.handler(true);
  47. },
  48. deactivated() {
  49. this.handler(false);
  50. },
  51. watch: {
  52. show() {
  53. if (!this.transition) {
  54. this.$emit(this.show ? 'show' : 'hide');
  55. }
  56. }
  57. },
  58. computed: {
  59. keys() {
  60. const keys = [];
  61. for (let i = 1; i <= 9; i++) {
  62. keys.push({ text: i });
  63. }
  64. switch (this.theme) {
  65. case 'default':
  66. keys.push(
  67. { text: this.extraKey, type: ['gray'] },
  68. { text: 0 },
  69. { text: this.deleteText, type: ['gray', 'delete'] }
  70. );
  71. break;
  72. case 'custom':
  73. keys.push({ text: 0, type: ['middle'] }, { text: this.extraKey });
  74. break;
  75. }
  76. return keys;
  77. },
  78. deleteText() {
  79. return this.deleteButtonText || t('delete');
  80. }
  81. },
  82. methods: {
  83. handler(action) {
  84. /* istanbul ignore if */
  85. if (this.$isServer) {
  86. return;
  87. }
  88. if (action !== this.handlerStatus && this.hideOnClickOutside) {
  89. this.handlerStatus = action;
  90. document.body[(action ? 'add' : 'remove') + 'EventListener']('touchstart', this.onBlur);
  91. }
  92. },
  93. onBlur() {
  94. this.$emit('blur');
  95. },
  96. onClose() {
  97. this.$emit('close');
  98. this.onBlur();
  99. },
  100. onAnimationEnd() {
  101. this.$emit(this.show ? 'show' : 'hide');
  102. },
  103. onPress(text) {
  104. if (text === '') {
  105. return;
  106. }
  107. if (text === this.deleteText) {
  108. this.$emit('delete');
  109. } else if (text === this.closeButtonText) {
  110. this.onClose();
  111. } else {
  112. this.$emit('input', text);
  113. }
  114. }
  115. },
  116. render(h) {
  117. const { title, theme, onPress, closeButtonText } = this;
  118. const titleLeftSlot = this.slots('title-left');
  119. const showTitleClose = closeButtonText && theme === 'default';
  120. const showTitle = title || showTitleClose || titleLeftSlot;
  121. return (
  122. <transition name={this.transition ? 'van-slide-up' : ''}>
  123. <div
  124. vShow={this.show}
  125. style={{ zIndex: this.zIndex }}
  126. class={bem([theme, { 'safe-area-inset-bottom': this.safeAreaInsetBottom }])}
  127. onTouchstart={stopPropagation}
  128. onAnimationend={this.onAnimationEnd}
  129. onWebkitAnimationEnd={this.onAnimationEnd}
  130. >
  131. {showTitle && (
  132. <div class={[bem('title'), 'van-hairline--top']}>
  133. {titleLeftSlot && (
  134. <span class={bem('title-left')}>
  135. {titleLeftSlot}
  136. </span>
  137. )}
  138. {title && <span>{title}</span>}
  139. {showTitleClose && (
  140. <span class={bem('close')} onClick={this.onClose}>
  141. {closeButtonText}
  142. </span>
  143. )}
  144. </div>
  145. )}
  146. <div class={bem('body')}>
  147. {this.keys.map(key => (
  148. <Key key={key.text} text={key.text} type={key.type} onPress={onPress} />
  149. ))}
  150. </div>
  151. {theme === 'custom' && (
  152. <div class={bem('sidebar')}>
  153. <Key text={this.deleteText} type={DELETE_KEY_TYPE} onPress={onPress} />
  154. <Key text={closeButtonText} type={CLOSE_KEY_TYPE} onPress={onPress} />
  155. </div>
  156. )}
  157. </div>
  158. </transition>
  159. );
  160. }
  161. });