NumberKeyboard.mjs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. import { ref, watch, computed, Teleport, Transition, defineComponent, createVNode as _createVNode, vShow as _vShow, mergeProps as _mergeProps, withDirectives as _withDirectives } from "vue";
  2. import { truthProp, numericProp, getZIndexStyle, makeStringProp, makeNumericProp, stopPropagation, createNamespace, HAPTICS_FEEDBACK } from "../utils/index.mjs";
  3. import { useClickAway } from "@vant/use";
  4. import NumberKeyboardKey from "./NumberKeyboardKey.mjs";
  5. const [name, bem] = createNamespace("number-keyboard");
  6. const numberKeyboardProps = {
  7. show: Boolean,
  8. title: String,
  9. theme: makeStringProp("default"),
  10. zIndex: numericProp,
  11. teleport: [String, Object],
  12. maxlength: makeNumericProp(Infinity),
  13. modelValue: makeStringProp(""),
  14. transition: truthProp,
  15. blurOnClose: truthProp,
  16. showDeleteKey: truthProp,
  17. randomKeyOrder: Boolean,
  18. closeButtonText: String,
  19. deleteButtonText: String,
  20. closeButtonLoading: Boolean,
  21. hideOnClickOutside: truthProp,
  22. safeAreaInsetBottom: truthProp,
  23. extraKey: {
  24. type: [String, Array],
  25. default: ""
  26. }
  27. };
  28. function shuffle(array) {
  29. for (let i = array.length - 1; i > 0; i--) {
  30. const j = Math.floor(Math.random() * (i + 1));
  31. const temp = array[i];
  32. array[i] = array[j];
  33. array[j] = temp;
  34. }
  35. return array;
  36. }
  37. var stdin_default = defineComponent({
  38. name,
  39. inheritAttrs: false,
  40. props: numberKeyboardProps,
  41. emits: ["show", "hide", "blur", "input", "close", "delete", "update:modelValue"],
  42. setup(props, {
  43. emit,
  44. slots,
  45. attrs
  46. }) {
  47. const root = ref();
  48. const genBasicKeys = () => {
  49. const keys2 = Array(9).fill("").map((_, i) => ({
  50. text: i + 1
  51. }));
  52. if (props.randomKeyOrder) {
  53. shuffle(keys2);
  54. }
  55. return keys2;
  56. };
  57. const genDefaultKeys = () => [...genBasicKeys(), {
  58. text: props.extraKey,
  59. type: "extra"
  60. }, {
  61. text: 0
  62. }, {
  63. text: props.showDeleteKey ? props.deleteButtonText : "",
  64. type: props.showDeleteKey ? "delete" : ""
  65. }];
  66. const genCustomKeys = () => {
  67. const keys2 = genBasicKeys();
  68. const {
  69. extraKey
  70. } = props;
  71. const extraKeys = Array.isArray(extraKey) ? extraKey : [extraKey];
  72. if (extraKeys.length === 0) {
  73. keys2.push({
  74. text: 0,
  75. wider: true
  76. });
  77. } else if (extraKeys.length === 1) {
  78. keys2.push({
  79. text: 0,
  80. wider: true
  81. }, {
  82. text: extraKeys[0],
  83. type: "extra"
  84. });
  85. } else if (extraKeys.length === 2) {
  86. keys2.push({
  87. text: extraKeys[0],
  88. type: "extra"
  89. }, {
  90. text: 0
  91. }, {
  92. text: extraKeys[1],
  93. type: "extra"
  94. });
  95. }
  96. return keys2;
  97. };
  98. const keys = computed(() => props.theme === "custom" ? genCustomKeys() : genDefaultKeys());
  99. const onBlur = () => {
  100. if (props.show) {
  101. emit("blur");
  102. }
  103. };
  104. const onClose = () => {
  105. emit("close");
  106. if (props.blurOnClose) {
  107. onBlur();
  108. }
  109. };
  110. const onAnimationEnd = () => emit(props.show ? "show" : "hide");
  111. const onPress = (text, type) => {
  112. if (text === "") {
  113. if (type === "extra") {
  114. onBlur();
  115. }
  116. return;
  117. }
  118. const value = props.modelValue;
  119. if (type === "delete") {
  120. emit("delete");
  121. emit("update:modelValue", value.slice(0, value.length - 1));
  122. } else if (type === "close") {
  123. onClose();
  124. } else if (value.length < +props.maxlength) {
  125. emit("input", text);
  126. emit("update:modelValue", value + text);
  127. }
  128. };
  129. const renderTitle = () => {
  130. const {
  131. title,
  132. theme,
  133. closeButtonText
  134. } = props;
  135. const leftSlot = slots["title-left"];
  136. const showClose = closeButtonText && theme === "default";
  137. const showTitle = title || showClose || leftSlot;
  138. if (!showTitle) {
  139. return;
  140. }
  141. return _createVNode("div", {
  142. "class": bem("header")
  143. }, [leftSlot && _createVNode("span", {
  144. "class": bem("title-left")
  145. }, [leftSlot()]), title && _createVNode("h2", {
  146. "class": bem("title")
  147. }, [title]), showClose && _createVNode("button", {
  148. "type": "button",
  149. "class": [bem("close"), HAPTICS_FEEDBACK],
  150. "onClick": onClose
  151. }, [closeButtonText])]);
  152. };
  153. const renderKeys = () => keys.value.map((key) => {
  154. const keySlots = {};
  155. if (key.type === "delete") {
  156. keySlots.default = slots.delete;
  157. }
  158. if (key.type === "extra") {
  159. keySlots.default = slots["extra-key"];
  160. }
  161. return _createVNode(NumberKeyboardKey, {
  162. "key": key.text,
  163. "text": key.text,
  164. "type": key.type,
  165. "wider": key.wider,
  166. "color": key.color,
  167. "onPress": onPress
  168. }, keySlots);
  169. });
  170. const renderSidebar = () => {
  171. if (props.theme === "custom") {
  172. return _createVNode("div", {
  173. "class": bem("sidebar")
  174. }, [props.showDeleteKey && _createVNode(NumberKeyboardKey, {
  175. "large": true,
  176. "text": props.deleteButtonText,
  177. "type": "delete",
  178. "onPress": onPress
  179. }, {
  180. default: slots.delete
  181. }), _createVNode(NumberKeyboardKey, {
  182. "large": true,
  183. "text": props.closeButtonText,
  184. "type": "close",
  185. "color": "blue",
  186. "loading": props.closeButtonLoading,
  187. "onPress": onPress
  188. }, null)]);
  189. }
  190. };
  191. watch(() => props.show, (value) => {
  192. if (!props.transition) {
  193. emit(value ? "show" : "hide");
  194. }
  195. });
  196. if (props.hideOnClickOutside) {
  197. useClickAway(root, onBlur, {
  198. eventName: "touchstart"
  199. });
  200. }
  201. return () => {
  202. const Title = renderTitle();
  203. const Content = _createVNode(Transition, {
  204. "name": props.transition ? "van-slide-up" : ""
  205. }, {
  206. default: () => [_withDirectives(_createVNode("div", _mergeProps({
  207. "ref": root,
  208. "style": getZIndexStyle(props.zIndex),
  209. "class": bem({
  210. unfit: !props.safeAreaInsetBottom,
  211. "with-title": !!Title
  212. }),
  213. "onAnimationend": onAnimationEnd,
  214. "onTouchstartPassive": stopPropagation
  215. }, attrs), [Title, _createVNode("div", {
  216. "class": bem("body")
  217. }, [_createVNode("div", {
  218. "class": bem("keys")
  219. }, [renderKeys()]), renderSidebar()])]), [[_vShow, props.show]])]
  220. });
  221. if (props.teleport) {
  222. return _createVNode(Teleport, {
  223. "to": props.teleport
  224. }, {
  225. default: () => [Content]
  226. });
  227. }
  228. return Content;
  229. };
  230. }
  231. });
  232. export {
  233. stdin_default as default,
  234. numberKeyboardProps
  235. };