index.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. "use strict";
  2. var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
  3. exports.__esModule = true;
  4. exports.default = void 0;
  5. var _babelHelperVueJsxMergeProps = _interopRequireDefault(require("@vue/babel-helper-vue-jsx-merge-props"));
  6. var _utils = require("../utils");
  7. var _resetScroll = require("../utils/dom/reset-scroll");
  8. var _event = require("../utils/dom/event");
  9. var _number = require("../utils/format/number");
  10. var _number2 = require("../utils/validate/number");
  11. var _field = require("../mixins/field");
  12. var _createNamespace = (0, _utils.createNamespace)('stepper'),
  13. createComponent = _createNamespace[0],
  14. bem = _createNamespace[1];
  15. var LONG_PRESS_START_TIME = 600;
  16. var LONG_PRESS_INTERVAL = 200;
  17. function equal(value1, value2) {
  18. return String(value1) === String(value2);
  19. } // add num and avoid float number
  20. function add(num1, num2) {
  21. var cardinal = Math.pow(10, 10);
  22. return Math.round((num1 + num2) * cardinal) / cardinal;
  23. }
  24. var _default = createComponent({
  25. mixins: [_field.FieldMixin],
  26. props: {
  27. value: null,
  28. theme: String,
  29. integer: Boolean,
  30. disabled: Boolean,
  31. allowEmpty: Boolean,
  32. inputWidth: [Number, String],
  33. buttonSize: [Number, String],
  34. asyncChange: Boolean,
  35. placeholder: String,
  36. disablePlus: Boolean,
  37. disableMinus: Boolean,
  38. disableInput: Boolean,
  39. decimalLength: [Number, String],
  40. name: {
  41. type: [Number, String],
  42. default: ''
  43. },
  44. min: {
  45. type: [Number, String],
  46. default: 1
  47. },
  48. max: {
  49. type: [Number, String],
  50. default: Infinity
  51. },
  52. step: {
  53. type: [Number, String],
  54. default: 1
  55. },
  56. defaultValue: {
  57. type: [Number, String],
  58. default: 1
  59. },
  60. showPlus: {
  61. type: Boolean,
  62. default: true
  63. },
  64. showMinus: {
  65. type: Boolean,
  66. default: true
  67. },
  68. showInput: {
  69. type: Boolean,
  70. default: true
  71. },
  72. longPress: {
  73. type: Boolean,
  74. default: true
  75. }
  76. },
  77. data: function data() {
  78. var _this$value;
  79. var defaultValue = (_this$value = this.value) != null ? _this$value : this.defaultValue;
  80. var value = this.format(defaultValue);
  81. if (!equal(value, this.value)) {
  82. this.$emit('input', value);
  83. }
  84. return {
  85. currentValue: value
  86. };
  87. },
  88. computed: {
  89. minusDisabled: function minusDisabled() {
  90. return this.disabled || this.disableMinus || this.currentValue <= +this.min;
  91. },
  92. plusDisabled: function plusDisabled() {
  93. return this.disabled || this.disablePlus || this.currentValue >= +this.max;
  94. },
  95. inputStyle: function inputStyle() {
  96. var style = {};
  97. if (this.inputWidth) {
  98. style.width = (0, _utils.addUnit)(this.inputWidth);
  99. }
  100. if (this.buttonSize) {
  101. style.height = (0, _utils.addUnit)(this.buttonSize);
  102. }
  103. return style;
  104. },
  105. buttonStyle: function buttonStyle() {
  106. if (this.buttonSize) {
  107. var size = (0, _utils.addUnit)(this.buttonSize);
  108. return {
  109. width: size,
  110. height: size
  111. };
  112. }
  113. }
  114. },
  115. watch: {
  116. max: 'check',
  117. min: 'check',
  118. integer: 'check',
  119. decimalLength: 'check',
  120. value: function value(val) {
  121. if (!equal(val, this.currentValue)) {
  122. this.currentValue = this.format(val);
  123. }
  124. },
  125. currentValue: function currentValue(val) {
  126. this.$emit('input', val);
  127. this.$emit('change', val, {
  128. name: this.name
  129. });
  130. }
  131. },
  132. methods: {
  133. check: function check() {
  134. var val = this.format(this.currentValue);
  135. if (!equal(val, this.currentValue)) {
  136. this.currentValue = val;
  137. }
  138. },
  139. // formatNumber illegal characters
  140. formatNumber: function formatNumber(value) {
  141. return (0, _number.formatNumber)(String(value), !this.integer);
  142. },
  143. format: function format(value) {
  144. if (this.allowEmpty && value === '') {
  145. return value;
  146. }
  147. value = this.formatNumber(value); // format range
  148. value = value === '' ? 0 : +value;
  149. value = (0, _number2.isNaN)(value) ? this.min : value;
  150. value = Math.max(Math.min(this.max, value), this.min); // format decimal
  151. if ((0, _utils.isDef)(this.decimalLength)) {
  152. value = value.toFixed(this.decimalLength);
  153. }
  154. return value;
  155. },
  156. onInput: function onInput(event) {
  157. var value = event.target.value;
  158. var formatted = this.formatNumber(value); // limit max decimal length
  159. if ((0, _utils.isDef)(this.decimalLength) && formatted.indexOf('.') !== -1) {
  160. var pair = formatted.split('.');
  161. formatted = pair[0] + "." + pair[1].slice(0, this.decimalLength);
  162. }
  163. if (!equal(value, formatted)) {
  164. event.target.value = formatted;
  165. } // perfer number type
  166. if (formatted === String(+formatted)) {
  167. formatted = +formatted;
  168. }
  169. this.emitChange(formatted);
  170. },
  171. emitChange: function emitChange(value) {
  172. if (this.asyncChange) {
  173. this.$emit('input', value);
  174. this.$emit('change', value, {
  175. name: this.name
  176. });
  177. } else {
  178. this.currentValue = value;
  179. }
  180. },
  181. onChange: function onChange() {
  182. var type = this.type;
  183. if (this[type + "Disabled"]) {
  184. this.$emit('overlimit', type);
  185. return;
  186. }
  187. var diff = type === 'minus' ? -this.step : +this.step;
  188. var value = this.format(add(+this.currentValue, diff));
  189. this.emitChange(value);
  190. this.$emit(type);
  191. },
  192. onFocus: function onFocus(event) {
  193. // readonly not work in lagacy mobile safari
  194. if (this.disableInput && this.$refs.input) {
  195. this.$refs.input.blur();
  196. } else {
  197. this.$emit('focus', event);
  198. }
  199. },
  200. onBlur: function onBlur(event) {
  201. var value = this.format(event.target.value);
  202. event.target.value = value;
  203. this.currentValue = value;
  204. this.$emit('blur', event);
  205. (0, _resetScroll.resetScroll)();
  206. },
  207. longPressStep: function longPressStep() {
  208. var _this = this;
  209. this.longPressTimer = setTimeout(function () {
  210. _this.onChange();
  211. _this.longPressStep(_this.type);
  212. }, LONG_PRESS_INTERVAL);
  213. },
  214. onTouchStart: function onTouchStart() {
  215. var _this2 = this;
  216. if (!this.longPress) {
  217. return;
  218. }
  219. clearTimeout(this.longPressTimer);
  220. this.isLongPress = false;
  221. this.longPressTimer = setTimeout(function () {
  222. _this2.isLongPress = true;
  223. _this2.onChange();
  224. _this2.longPressStep();
  225. }, LONG_PRESS_START_TIME);
  226. },
  227. onTouchEnd: function onTouchEnd(event) {
  228. if (!this.longPress) {
  229. return;
  230. }
  231. clearTimeout(this.longPressTimer);
  232. if (this.isLongPress) {
  233. (0, _event.preventDefault)(event);
  234. }
  235. },
  236. onMousedown: function onMousedown(event) {
  237. // fix mobile safari page scroll down issue
  238. // see: https://github.com/youzan/vant/issues/7690
  239. if (this.disableInput) {
  240. event.preventDefault();
  241. }
  242. }
  243. },
  244. render: function render() {
  245. var _this3 = this;
  246. var h = arguments[0];
  247. var createListeners = function createListeners(type) {
  248. return {
  249. on: {
  250. click: function click(e) {
  251. // disable double tap scrolling on mobile safari
  252. e.preventDefault();
  253. _this3.type = type;
  254. _this3.onChange();
  255. },
  256. touchstart: function touchstart() {
  257. _this3.type = type;
  258. _this3.onTouchStart();
  259. },
  260. touchend: _this3.onTouchEnd,
  261. touchcancel: _this3.onTouchEnd
  262. }
  263. };
  264. };
  265. return h("div", {
  266. "class": bem([this.theme])
  267. }, [h("button", (0, _babelHelperVueJsxMergeProps.default)([{
  268. "directives": [{
  269. name: "show",
  270. value: this.showMinus
  271. }],
  272. "attrs": {
  273. "type": "button"
  274. },
  275. "style": this.buttonStyle,
  276. "class": bem('minus', {
  277. disabled: this.minusDisabled
  278. })
  279. }, createListeners('minus')])), h("input", {
  280. "directives": [{
  281. name: "show",
  282. value: this.showInput
  283. }],
  284. "ref": "input",
  285. "attrs": {
  286. "type": this.integer ? 'tel' : 'text',
  287. "role": "spinbutton",
  288. "disabled": this.disabled,
  289. "readonly": this.disableInput,
  290. "inputmode": this.integer ? 'numeric' : 'decimal',
  291. "placeholder": this.placeholder,
  292. "aria-valuemax": this.max,
  293. "aria-valuemin": this.min,
  294. "aria-valuenow": this.currentValue
  295. },
  296. "class": bem('input'),
  297. "domProps": {
  298. "value": this.currentValue
  299. },
  300. "style": this.inputStyle,
  301. "on": {
  302. "input": this.onInput,
  303. "focus": this.onFocus,
  304. "blur": this.onBlur,
  305. "mousedown": this.onMousedown
  306. }
  307. }), h("button", (0, _babelHelperVueJsxMergeProps.default)([{
  308. "directives": [{
  309. name: "show",
  310. value: this.showPlus
  311. }],
  312. "attrs": {
  313. "type": "button"
  314. },
  315. "style": this.buttonStyle,
  316. "class": bem('plus', {
  317. disabled: this.plusDisabled
  318. })
  319. }, createListeners('plus')]))]);
  320. }
  321. });
  322. exports.default = _default;