Stepper.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. var __defProp = Object.defineProperty;
  2. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  3. var __getOwnPropNames = Object.getOwnPropertyNames;
  4. var __hasOwnProp = Object.prototype.hasOwnProperty;
  5. var __export = (target, all) => {
  6. for (var name2 in all)
  7. __defProp(target, name2, { get: all[name2], enumerable: true });
  8. };
  9. var __copyProps = (to, from, except, desc) => {
  10. if (from && typeof from === "object" || typeof from === "function") {
  11. for (let key of __getOwnPropNames(from))
  12. if (!__hasOwnProp.call(to, key) && key !== except)
  13. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  14. }
  15. return to;
  16. };
  17. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  18. var stdin_exports = {};
  19. __export(stdin_exports, {
  20. default: () => stdin_default
  21. });
  22. module.exports = __toCommonJS(stdin_exports);
  23. var import_vue = require("vue");
  24. var import_vue2 = require("vue");
  25. var import_utils = require("../utils");
  26. var import_use = require("@vant/use");
  27. const [name, bem] = (0, import_utils.createNamespace)("stepper");
  28. const LONG_PRESS_INTERVAL = 200;
  29. const LONG_PRESS_START_TIME = 600;
  30. const isEqual = (value1, value2) => String(value1) === String(value2);
  31. const stepperProps = {
  32. min: (0, import_utils.makeNumericProp)(1),
  33. max: (0, import_utils.makeNumericProp)(Infinity),
  34. name: (0, import_utils.makeNumericProp)(""),
  35. step: (0, import_utils.makeNumericProp)(1),
  36. theme: String,
  37. integer: Boolean,
  38. disabled: Boolean,
  39. showPlus: import_utils.truthProp,
  40. showMinus: import_utils.truthProp,
  41. showInput: import_utils.truthProp,
  42. longPress: import_utils.truthProp,
  43. allowEmpty: Boolean,
  44. modelValue: import_utils.numericProp,
  45. inputWidth: import_utils.numericProp,
  46. buttonSize: import_utils.numericProp,
  47. placeholder: String,
  48. disablePlus: Boolean,
  49. disableMinus: Boolean,
  50. disableInput: Boolean,
  51. beforeChange: Function,
  52. defaultValue: (0, import_utils.makeNumericProp)(1),
  53. decimalLength: import_utils.numericProp
  54. };
  55. var stdin_default = (0, import_vue2.defineComponent)({
  56. name,
  57. props: stepperProps,
  58. emits: ["plus", "blur", "minus", "focus", "change", "overlimit", "update:modelValue"],
  59. setup(props, {
  60. emit
  61. }) {
  62. const format = (value) => {
  63. const {
  64. min,
  65. max,
  66. allowEmpty,
  67. decimalLength
  68. } = props;
  69. if (allowEmpty && value === "") {
  70. return value;
  71. }
  72. value = (0, import_utils.formatNumber)(String(value), !props.integer);
  73. value = value === "" ? 0 : +value;
  74. value = Number.isNaN(value) ? +min : value;
  75. value = Math.max(Math.min(+max, value), +min);
  76. if ((0, import_utils.isDef)(decimalLength)) {
  77. value = value.toFixed(+decimalLength);
  78. }
  79. return value;
  80. };
  81. const getInitialValue = () => {
  82. var _a;
  83. const defaultValue = (_a = props.modelValue) != null ? _a : props.defaultValue;
  84. const value = format(defaultValue);
  85. if (!isEqual(value, props.modelValue)) {
  86. emit("update:modelValue", value);
  87. }
  88. return value;
  89. };
  90. let actionType;
  91. const inputRef = (0, import_vue2.ref)();
  92. const current = (0, import_vue2.ref)(getInitialValue());
  93. const minusDisabled = (0, import_vue2.computed)(() => props.disabled || props.disableMinus || current.value <= +props.min);
  94. const plusDisabled = (0, import_vue2.computed)(() => props.disabled || props.disablePlus || current.value >= +props.max);
  95. const inputStyle = (0, import_vue2.computed)(() => ({
  96. width: (0, import_utils.addUnit)(props.inputWidth),
  97. height: (0, import_utils.addUnit)(props.buttonSize)
  98. }));
  99. const buttonStyle = (0, import_vue2.computed)(() => (0, import_utils.getSizeStyle)(props.buttonSize));
  100. const check = () => {
  101. const value = format(current.value);
  102. if (!isEqual(value, current.value)) {
  103. current.value = value;
  104. }
  105. };
  106. const setValue = (value) => {
  107. if (props.beforeChange) {
  108. (0, import_utils.callInterceptor)(props.beforeChange, {
  109. args: [value],
  110. done() {
  111. current.value = value;
  112. }
  113. });
  114. } else {
  115. current.value = value;
  116. }
  117. };
  118. const onChange = () => {
  119. if (actionType === "plus" && plusDisabled.value || actionType === "minus" && minusDisabled.value) {
  120. emit("overlimit", actionType);
  121. return;
  122. }
  123. const diff = actionType === "minus" ? -props.step : +props.step;
  124. const value = format((0, import_utils.addNumber)(+current.value, diff));
  125. setValue(value);
  126. emit(actionType);
  127. };
  128. const onInput = (event) => {
  129. const input = event.target;
  130. const {
  131. value
  132. } = input;
  133. const {
  134. decimalLength
  135. } = props;
  136. let formatted = (0, import_utils.formatNumber)(String(value), !props.integer);
  137. if ((0, import_utils.isDef)(decimalLength) && formatted.includes(".")) {
  138. const pair = formatted.split(".");
  139. formatted = `${pair[0]}.${pair[1].slice(0, +decimalLength)}`;
  140. }
  141. if (props.beforeChange) {
  142. input.value = String(current.value);
  143. } else if (!isEqual(value, formatted)) {
  144. input.value = formatted;
  145. }
  146. const isNumeric = formatted === String(+formatted);
  147. setValue(isNumeric ? +formatted : formatted);
  148. };
  149. const onFocus = (event) => {
  150. var _a;
  151. if (props.disableInput) {
  152. (_a = inputRef.value) == null ? void 0 : _a.blur();
  153. } else {
  154. emit("focus", event);
  155. }
  156. };
  157. const onBlur = (event) => {
  158. const input = event.target;
  159. const value = format(input.value);
  160. input.value = String(value);
  161. current.value = value;
  162. (0, import_vue2.nextTick)(() => {
  163. emit("blur", event);
  164. (0, import_utils.resetScroll)();
  165. });
  166. };
  167. let isLongPress;
  168. let longPressTimer;
  169. const longPressStep = () => {
  170. longPressTimer = setTimeout(() => {
  171. onChange();
  172. longPressStep();
  173. }, LONG_PRESS_INTERVAL);
  174. };
  175. const onTouchStart = () => {
  176. if (props.longPress) {
  177. isLongPress = false;
  178. clearTimeout(longPressTimer);
  179. longPressTimer = setTimeout(() => {
  180. isLongPress = true;
  181. onChange();
  182. longPressStep();
  183. }, LONG_PRESS_START_TIME);
  184. }
  185. };
  186. const onTouchEnd = (event) => {
  187. if (props.longPress) {
  188. clearTimeout(longPressTimer);
  189. if (isLongPress) {
  190. (0, import_utils.preventDefault)(event);
  191. }
  192. }
  193. };
  194. const onMousedown = (event) => {
  195. if (props.disableInput) {
  196. (0, import_utils.preventDefault)(event);
  197. }
  198. };
  199. const createListeners = (type) => ({
  200. onClick: (event) => {
  201. (0, import_utils.preventDefault)(event);
  202. actionType = type;
  203. onChange();
  204. },
  205. onTouchstartPassive: () => {
  206. actionType = type;
  207. onTouchStart();
  208. },
  209. onTouchend: onTouchEnd,
  210. onTouchcancel: onTouchEnd
  211. });
  212. (0, import_vue2.watch)(() => [props.max, props.min, props.integer, props.decimalLength], check);
  213. (0, import_vue2.watch)(() => props.modelValue, (value) => {
  214. if (!isEqual(value, current.value)) {
  215. current.value = format(value);
  216. }
  217. });
  218. (0, import_vue2.watch)(current, (value) => {
  219. emit("update:modelValue", value);
  220. emit("change", value, {
  221. name: props.name
  222. });
  223. });
  224. (0, import_use.useCustomFieldValue)(() => props.modelValue);
  225. return () => (0, import_vue.createVNode)("div", {
  226. "role": "group",
  227. "class": bem([props.theme])
  228. }, [(0, import_vue.withDirectives)((0, import_vue.createVNode)("button", (0, import_vue.mergeProps)({
  229. "type": "button",
  230. "style": buttonStyle.value,
  231. "class": [bem("minus", {
  232. disabled: minusDisabled.value
  233. }), {
  234. [import_utils.HAPTICS_FEEDBACK]: !minusDisabled.value
  235. }],
  236. "aria-disabled": minusDisabled.value || void 0
  237. }, createListeners("minus")), null), [[import_vue.vShow, props.showMinus]]), (0, import_vue.withDirectives)((0, import_vue.createVNode)("input", {
  238. "ref": inputRef,
  239. "type": props.integer ? "tel" : "text",
  240. "role": "spinbutton",
  241. "class": bem("input"),
  242. "value": current.value,
  243. "style": inputStyle.value,
  244. "disabled": props.disabled,
  245. "readonly": props.disableInput,
  246. "inputmode": props.integer ? "numeric" : "decimal",
  247. "placeholder": props.placeholder,
  248. "aria-valuemax": props.max,
  249. "aria-valuemin": props.min,
  250. "aria-valuenow": current.value,
  251. "onBlur": onBlur,
  252. "onInput": onInput,
  253. "onFocus": onFocus,
  254. "onMousedown": onMousedown
  255. }, null), [[import_vue.vShow, props.showInput]]), (0, import_vue.withDirectives)((0, import_vue.createVNode)("button", (0, import_vue.mergeProps)({
  256. "type": "button",
  257. "style": buttonStyle.value,
  258. "class": [bem("plus", {
  259. disabled: plusDisabled.value
  260. }), {
  261. [import_utils.HAPTICS_FEEDBACK]: !plusDisabled.value
  262. }],
  263. "aria-disabled": plusDisabled.value || void 0
  264. }, createListeners("plus")), null), [[import_vue.vShow, props.showPlus]])]);
  265. }
  266. });