vdesign-ui 0.1.24 → 0.2.0-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/components/activityviews/index.vue +14 -12
  2. package/dist/components/button/index.vue +1 -1
  3. package/dist/components/checkbox/checkbox-group/index.vue +2 -1
  4. package/dist/components/checkbox/index.vue +19 -20
  5. package/dist/components/dialog/index.vue +15 -11
  6. package/dist/components/dropdown/index.vue +43 -31
  7. package/dist/components/empty/404-dark.png +0 -0
  8. package/dist/components/empty/404.png +0 -0
  9. package/dist/components/empty/index.vue +30 -2
  10. package/dist/components/empty/network-dark.png +0 -0
  11. package/dist/components/empty/network.png +0 -0
  12. package/dist/components/empty/nocoupons-dark.png +0 -0
  13. package/dist/components/empty/nocoupons.png +0 -0
  14. package/dist/components/empty/nodata-dark.png +0 -0
  15. package/dist/components/empty/nodata.png +0 -0
  16. package/dist/components/empty/nomargin-dark.png +0 -0
  17. package/dist/components/empty/nomargin.png +0 -0
  18. package/dist/components/empty/nonotice-dark.png +0 -0
  19. package/dist/components/empty/nonotice.png +0 -0
  20. package/dist/components/empty/noocomments-dark.png +0 -0
  21. package/dist/components/empty/noocomments.png +0 -0
  22. package/dist/components/empty/noorders-dark.png +0 -0
  23. package/dist/components/empty/noorders.png +0 -0
  24. package/dist/components/empty/noposition-dark.png +0 -0
  25. package/dist/components/empty/noposition.png +0 -0
  26. package/dist/components/empty/nosearch-dark.png +0 -0
  27. package/dist/components/empty/nosearch.png +0 -0
  28. package/dist/components/footer/index.vue +5 -1
  29. package/dist/components/footnav/footnav-item/index.vue +11 -42
  30. package/dist/components/footnav/index.vue +13 -27
  31. package/dist/components/headnav/index.vue +52 -35
  32. package/dist/components/icon/font/iconfont.css +62 -952
  33. package/dist/components/icon/font/iconfont.js +1 -1
  34. package/dist/components/icon/index.vue +26 -18
  35. package/dist/components/input/index.vue +107 -109
  36. package/dist/components/input/search/index.vue +18 -22
  37. package/dist/components/input/stepper/index.vue +32 -26
  38. package/dist/components/input/style.less +20 -33
  39. package/dist/components/list/index.vue +57 -69
  40. package/dist/components/list/style.less +20 -92
  41. package/dist/components/loading/img_status_loading_white_ani.svg +155 -0
  42. package/dist/components/loading/img_status_refresh_ani.svg +158 -0
  43. package/dist/components/loading/index.vue +21 -11
  44. package/dist/components/loading/style.less +1 -1
  45. package/dist/components/mixins/clickoutside.js +81 -81
  46. package/dist/components/pagebreak/index.vue +21 -14
  47. package/dist/components/radio/index.vue +164 -135
  48. package/dist/components/radio/radio-group/index.vue +40 -52
  49. package/dist/components/result/index.vue +1 -2
  50. package/dist/components/selector/index.vue +49 -31
  51. package/dist/components/selector/style.less +14 -0
  52. package/dist/components/step-item/index.vue +2 -2
  53. package/dist/components/tabs/index.vue +55 -32
  54. package/dist/components/tabs/tab/index.vue +13 -16
  55. package/dist/components/tag/index.vue +18 -4
  56. package/dist/components/tag/style.less +2 -2
  57. package/dist/components/title/index.vue +11 -8
  58. package/dist/components/title/style.less +6 -0
  59. package/dist/img/img_status_loading_white_ani.b56fcfae.svg +155 -0
  60. package/dist/img/img_status_refresh_ani.d0e59f12.svg +158 -0
  61. package/dist/token.css +8 -0
  62. package/dist/vdesign-ui.common.js +1362 -1170
  63. package/dist/vdesign-ui.css +1 -1
  64. package/dist/vdesign-ui.umd.js +1362 -1170
  65. package/dist/vdesign-ui.umd.min.js +3 -3
  66. package/package.json +1 -1
  67. package/dist/components/loading/loading.png +0 -0
  68. package/dist/components/loading/refresh.png +0 -0
  69. package/dist/img/404-dark.775df5bb.png +0 -0
  70. package/dist/img/network-dark.11a147bb.png +0 -0
  71. package/dist/img/nodata-dark.b0ea0e39.png +0 -0
@@ -1,18 +1,23 @@
1
1
  <template>
2
- <svg v-if="svg" class="vd-iconfont vd-svg-icon" :class="[`vd-icon-${name}`, size ? `vd-icon-${size}` : '']"
3
- :style="{ fill: color }" @click="$emit('click', $event)">
4
- <use :xlink:href="`#vd-icon-${name}`" />
5
- </svg>
6
- <i v-else-if="name" class="vd-iconfont"
7
- :class="[isImage(name) ? '' : `vd-icon-${name}`, size ? `vd-icon-${size}` : '']" :style="{ color }"
8
- @click="$emit('click', $event)">
9
- <img class="vd-img-icon" v-if="isImage(name)" :src="name" />
10
- </i>
2
+ <span>
3
+ <template v-if="name">
4
+ <svg v-if="isSvg" class="vd-iconfont vd-svg-icon" :class="[`vd-icon-${name}`, sizeClass]" :style="{ fill: color }"
5
+ @click="$emit('click', $event)">
6
+ <use :xlink:href="`#vd-icon-${name}`" />
7
+ </svg>
8
+ <i v-else class="vd-iconfont" :class="[isImage ? '' : `vd-icon-${name}`, sizeClass]" :style="{ color }"
9
+ @click="$emit('click', $event)">
10
+ <img class="vd-img-icon" v-if="isImage" :src="name" />
11
+ </i>
12
+ </template>
13
+ <slot v-else></slot>
14
+ </span>
11
15
  </template>
12
16
 
13
17
  <script>
14
- import './font/iconfont.js'
15
18
  import "./font/iconfont.css";
19
+ import "./font/iconfont.js";
20
+
16
21
  export default {
17
22
  name: 'vd-icon',
18
23
  props: {
@@ -28,16 +33,19 @@ export default {
28
33
  type: String,
29
34
  default: '',
30
35
  },
31
- svg: {
32
- type: Boolean,
33
- default: false,
34
- }
35
36
  },
36
- methods: {
37
- isImage(name) {
38
- return name ? name.indexOf('/') !== -1 : false;
37
+ computed: {
38
+ isImage() {
39
+ return this.name.includes('/');
40
+ },
41
+ isSvg() {
42
+ // 判断是否为 SVG 图标,依据 name 是否以 '.svg' 结尾
43
+ return this.name.endsWith('_svg');
44
+ },
45
+ sizeClass() {
46
+ return this.size ? `vd-icon-${this.size}` : '';
39
47
  }
40
- },
48
+ }
41
49
  }
42
50
  </script>
43
51
 
@@ -1,34 +1,17 @@
1
1
  <template>
2
2
  <div :class="wrapClasses" class="vd-input">
3
- <template v-if="inputTextArea || type !== 'textarea'">
4
- <span v-if="prefix || $slots.prefix" class="vd-input-form__prefix" :class="borderRightClasses">
3
+ <!-- 前缀,还有前缀右边框 -->
4
+ <span v-if="hasPrefix" class="vd-input-form__prefix" :class="borderRightClasses">
5
5
  <slot name="prefix">{{ prefix }}</slot>
6
6
  </span>
7
- <input
8
- v-if="!inputTextArea"
9
- ref="input"
10
- v-bind="$attrs"
11
- :type="passwordIcon ? (passwordVisible ? 'text' : 'password') : type"
12
- :class="inputClasses"
13
- :disabled="disabled"
14
- :placeholder="placeholder"
15
- :value="currentValue"
16
- @input="handleInput"
17
- @focus="handleFocus"
18
- @blur="handleBlur"
19
- />
20
-
21
7
  <textarea
22
- v-else
8
+ v-if="type === 'textarea'"
23
9
  ref="textarea"
24
10
  v-bind="$attrs"
25
- :id="elementId"
26
- :wrap="wrap"
27
- :type="type"
28
11
  :rows="rows"
29
12
  :class="inputClasses"
30
13
  :disabled="disabled"
31
- :placeholder="placeholder"
14
+ :readonly="readonly"
32
15
  :value="currentValue"
33
16
  @focus="handleFocus"
34
17
  @blur="handleBlur"
@@ -36,71 +19,58 @@
36
19
  :style="textareaStyles"
37
20
  >
38
21
  </textarea>
22
+ <input
23
+ v-else
24
+ ref="input"
25
+ v-bind="$attrs"
26
+ :type="passwordIcon ? (passwordVisible ? 'text' : 'password') : type"
27
+ :class="inputClasses"
28
+ :disabled="disabled"
29
+ :readonly="readonly"
30
+ :value="currentValue"
31
+ @input="handleInput"
32
+ @focus="handleFocus"
33
+ @blur="handleBlur"
34
+ />
35
+
36
+ <!-- 右侧功能区域 -->
37
+
39
38
  <div
40
- v-if="suffix || $slots.suffix || append || $slots.append || isWordLimitVisible"
39
+ v-if="showRightSection"
41
40
  class="vd-input-form__right"
42
41
  >
43
- <span v-if="suffix || $slots.suffix" class="vd-input-form__suffix">
44
- <slot name="suffix">
45
- <vd-icon name="icon_btn_clean" @click="handleClear"></vd-icon>
46
- </slot>
42
+ <!-- 清除按钮 -->
43
+ <span v-if="showClear" class="vd-input-form__suffix">
44
+ <vd-icon name="icon_btn_clean" @mousedown.prevent.native="handleClear"></vd-icon>
47
45
  </span>
48
- <span v-if="append || $slots.append" class="vd-input-form__append">
46
+ <!-- (大数字的时候)设计要求的自定义文字 -->
47
+ <span v-if="hasAppend" class="vd-input-form__append">
49
48
  <slot name="append">{{ append }}</slot>
50
49
  </span>
50
+ <!-- 字数限制 -->
51
51
  <div
52
52
  v-if="isWordLimitVisible"
53
- :class="[
54
- 'vd-input__word-limit',
55
- { 'vd-input__word-limit--error': isOverLimit },
56
- ]"
53
+ :class="wordLimitClasses"
57
54
  >
58
55
  <span>{{ textLength }}</span
59
56
  >/<span>{{ upperLimit }}</span>
60
57
  </div>
61
58
  </div>
59
+ <!-- 密码的时候,单独的清空按钮 -->
62
60
  <span
63
- v-if="passwordClose || passwordIcon"
61
+ v-if="showPasswordControls"
64
62
  class="vd-input-form__password"
65
63
  >
66
- <span v-if="passwordClose" class="vd-input-form__password--close">
67
- <vd-icon name="icon_btn_close" @click="handleClear"></vd-icon>
64
+ <span v-if="showPasswordClear" class="vd-input-form__password--close">
65
+ <vd-icon name="icon_btn_close" @mousedown.prevent.native="handleClear"></vd-icon>
68
66
  </span>
69
- <span v-if="passwordIcon" class="vd-input-form__password--password">
67
+ <span v-if="showPasswordIcon" class="vd-input-form__password--password">
70
68
  <vd-icon
71
69
  :name="passwordVisible ? 'icon_btn_eye' : 'icon_btn_eye_close'"
72
70
  @click="handlePasswordVisible"
73
71
  ></vd-icon>
74
72
  </span>
75
73
  </span>
76
- </template>
77
- <template v-else>
78
- <textarea
79
- ref="textarea"
80
- :type="type"
81
- v-bind="$attrs"
82
- :wrap="wrap"
83
- :class="inputClasses"
84
- :disabled="disabled"
85
- :placeholder="placeholder"
86
- :value="currentValue"
87
- :rows="rows"
88
- :name="name"
89
- @input="handleInput"
90
- :style="textareaStyles"
91
- >
92
- </textarea>
93
- <div
94
- v-if="isWordLimitVisible"
95
- :class="[
96
- 'vd-input__word-limit',
97
- { 'vd-input__word-limit--error': isOverLimit },
98
- ]"
99
- >
100
- <span>{{ textLength }}</span
101
- >/<span>{{ upperLimit }}</span>
102
- </div>
103
- </template>
104
74
  </div>
105
75
  </template>
106
76
 
@@ -111,26 +81,26 @@ const prefixCls = "vd-input";
111
81
  export default {
112
82
  name: "vd-input",
113
83
  props: {
84
+ value: {
85
+ type: [String, Number],
86
+ default: "",
87
+ },
114
88
  type: {
115
89
  type: String,
116
90
  default: "text",
117
91
  },
118
92
  prefix: {
119
93
  type: [Boolean, String],
94
+ default: ''
120
95
  },
121
96
  borderRight: {
122
97
  type: Boolean,
123
98
  default: true
124
99
  },
125
- suffix: {
126
- type: Boolean,
127
- },
128
100
  // 设计如此,单独的文字
129
101
  append: {
130
- type: Boolean,
131
- },
132
- placeholder: {
133
- type: String,
102
+ type: [Boolean, String],
103
+ default: ''
134
104
  },
135
105
  error: {
136
106
  type: Boolean,
@@ -144,27 +114,17 @@ export default {
144
114
  passwordClose: {
145
115
  type: Boolean,
146
116
  },
147
- passwordType: {
148
- type: String,
149
- default: "icon_btn_eye_close",
150
- },
117
+ // 输入框类型 表单类型,常规输入库,搜索框
151
118
  form: {
152
119
  type: String,
153
120
  },
154
121
  disabled: {
155
122
  type: Boolean,
156
123
  },
157
- value: {
158
- type: [String, Number],
159
- default: "",
160
- },
161
124
  rows: {
162
125
  type: Number,
163
126
  default: 2,
164
127
  },
165
- name: {
166
- type: String,
167
- },
168
128
  // 设计如此多行textarea,跟input属性一样
169
129
  inputTextArea: {
170
130
  type: Boolean,
@@ -180,29 +140,66 @@ export default {
180
140
  type: [Boolean, Object],
181
141
  default: false,
182
142
  },
183
- elementId: {
184
- type: String,
185
- },
186
- wrap: {
187
- type: String,
188
- default: "soft",
189
- },
190
143
  // 新增0118
191
144
  showWordLimit: {
192
145
  type: Boolean,
193
146
  default: false,
194
147
  },
148
+ clearable:Boolean,
149
+ readonly:Boolean
195
150
  },
196
151
  data() {
197
152
  return {
198
153
  focusClass: false,
199
154
  currentValue: this.value,
200
- isOnComposition: false,
201
155
  textareaStyles: {},
202
156
  passwordVisible: false,
157
+ focused: false,
203
158
  };
204
159
  },
205
160
  computed: {
161
+ hasPrefix() {
162
+ return (this.prefix !== undefined && this.prefix !== '') || this.$slots.prefix;
163
+ },
164
+ // 是否显示右侧区域
165
+ showRightSection() {
166
+ return this.showClear || this.hasAppend || this.isWordLimitVisible;
167
+ },
168
+ // 是否有附加内容
169
+ hasAppend() {
170
+ return (this.append !== undefined && this.append !== '') || this.$slots.append;
171
+ },
172
+ // 是否显示清除按钮(假设已经在 computed 中定义)
173
+ showClear() {
174
+ return (
175
+ this.clearable &&
176
+ this.focused &&
177
+ this.currentValue !== '' &&
178
+ !this.disabled &&
179
+ !this.readonly
180
+ );
181
+ },
182
+ wordLimitClasses() {
183
+ return [
184
+ 'vd-input__word-limit',
185
+ { 'vd-input__word-limit--error': this.isOverLimit },
186
+ ];
187
+ },
188
+ showPasswordClear() {
189
+ return (
190
+ this.passwordClose &&
191
+ this.focused &&
192
+ this.currentValue !== '' &&
193
+ !this.disabled &&
194
+ !this.readonly
195
+ );
196
+ },
197
+ showPasswordIcon() {
198
+ return this.passwordIcon && this.type === 'password';
199
+ },
200
+ showPasswordControls() {
201
+ return this.showPasswordClear || this.showPasswordIcon;
202
+ },
206
203
  wrapClasses() {
207
204
  return [
208
205
  {
@@ -212,7 +209,7 @@ export default {
212
209
  [`${prefixCls}-${this.type}--warning`]: this.warning,
213
210
  [`${prefixCls}--bigsize`]: this.bigSize,
214
211
  [`${prefixCls}--error`]: this.error,
215
- [`${prefixCls}--active`]: this.focusClass,
212
+ [`${prefixCls}--active`]: this.focused,
216
213
  [`${prefixCls}-inputarea`]: this.inputTextArea,
217
214
  "vd-hairline--bottom": this.hairline,
218
215
  "vd-textarea-auto": this.inputTextArea,
@@ -235,6 +232,7 @@ export default {
235
232
  },
236
233
  ];
237
234
  },
235
+ // 当前输入的文本长度
238
236
  textLength() {
239
237
  if (typeof this.value === "number") {
240
238
  return String(this.value).length;
@@ -257,37 +255,34 @@ export default {
257
255
  },
258
256
  methods: {
259
257
  handleFocus(event) {
260
- if (this.form) {
261
- this.focusClass = true;
262
- }
258
+ this.focused = true;
263
259
  this.$emit("focus", event);
260
+
261
+ if (this.readonly) {
262
+ this.blur();
263
+ }
264
264
  },
265
265
  handleBlur(event) {
266
- if (this.form) {
267
- this.focusClass = false;
268
- }
266
+ this.focused = false;
269
267
  this.$emit("blur", event);
270
268
  },
271
269
  focus() {
272
270
  if (this.type === "textarea") {
273
- this.$refs.textarea.focus();
271
+ this.$refs.textarea && this.$refs.textarea.focus();
274
272
  } else {
275
- this.$refs.input.focus();
273
+ this.$refs.input && this.$refs.input.focus();
276
274
  }
277
275
  },
278
276
  blur() {
279
277
  if (this.type === "textarea") {
280
- this.$refs.textarea.blur();
278
+ this.$refs.textarea && this.$refs.textarea.blur();
281
279
  } else {
282
- this.$refs.input.blur();
280
+ this.$refs.input && this.$refs.input.blur();
283
281
  }
284
282
  },
285
283
 
286
284
  handleInput(event) {
287
- if (this.isOnComposition) return;
288
285
  let value = event.target.value;
289
- if (this.number && value !== "")
290
- value = Number.isNaN(Number(value)) ? value : Number(value);
291
286
  this.$emit("input", value);
292
287
  this.setCurrentValue(value);
293
288
  this.$emit("change", event);
@@ -295,18 +290,16 @@ export default {
295
290
 
296
291
  setCurrentValue(value) {
297
292
  if (value === this.currentValue) return;
293
+ this.currentValue = value;
298
294
  this.$nextTick(() => {
299
295
  this.resizeTextarea();
300
296
  });
301
- this.currentValue = value;
302
297
  },
303
298
  resizeTextarea() {
304
- const autosize = this.autosize;
305
- if (!autosize || this.type !== "textarea") {
306
- return false;
299
+ if (!this.autosize || this.type !== "textarea") {
300
+ return;
307
301
  }
308
- const minRows = autosize.minRows;
309
- const maxRows = autosize.maxRows;
302
+ const { minRows, maxRows } = this.autosize;
310
303
  this.textareaStyles = calcTextareaHeight(
311
304
  this.$refs.textarea,
312
305
  minRows,
@@ -319,7 +312,12 @@ export default {
319
312
  this.setCurrentValue("");
320
313
  this.$emit("change", e);
321
314
  this.$emit("clear");
315
+ this.$nextTick(() => {
316
+ this.focus();
317
+ });
322
318
  },
319
+
320
+ // 切换密码显示状态
323
321
  handlePasswordVisible() {
324
322
  this.passwordVisible = !this.passwordVisible;
325
323
  this.$nextTick(() => {
@@ -6,19 +6,15 @@
6
6
  <vd-icon name="icon_nav_search"></vd-icon>
7
7
  </slot>
8
8
  </span>
9
- <!-- <input :type="type" :class="inputClasses" :placeholder="placeholder"> -->
10
9
  <vd-input
11
- v-bind="$attrs"
12
- v-on="listeners"
13
- form="search"
14
- :hairline = "false"
10
+ v-bind="$attrs"
11
+ v-on="inputListeners"
12
+ :value="value"
13
+ :type="type"
14
+ :clearable="clearable"
15
+ form="search"
16
+ :hairline="false"
15
17
  ></vd-input>
16
- <span v-if="suffix || $slots.suffix" class="vd-search__suffix">
17
- <slot name="suffix">
18
- <vd-icon v-if="suffix" name="icon_btn_clean"></vd-icon>
19
- </slot>
20
- </span>
21
-
22
18
  </div>
23
19
  <span class="vd-search__action" v-if="$slots.default">
24
20
  <slot></slot>
@@ -27,20 +23,22 @@
27
23
  </template>
28
24
 
29
25
  <script>
30
- const prefixCls = 'vd-search';
31
26
  export default {
32
27
  name: 'vd-search',
33
28
  inheritAttrs: false,
34
29
  props: {
30
+ value: [String, Number],
35
31
  type: {
36
32
  type: String,
37
33
  default: 'text'
38
34
  },
39
- prefix: {
35
+ clearable: {
40
36
  type: Boolean,
37
+ default: false,
41
38
  },
42
- suffix: {
39
+ prefix: {
43
40
  type: Boolean,
41
+ default: true, // 默认显示前缀图标
44
42
  },
45
43
  },
46
44
  data() {
@@ -48,19 +46,17 @@ export default {
48
46
  }
49
47
  },
50
48
  computed: {
51
- inputClasses() {
52
- return [
53
- `${prefixCls}__control`
54
- ]
55
- },
56
- listeners() {
49
+ inputListeners() {
57
50
  return {
58
51
  ...this.$listeners,
52
+ input: this.onInput,
59
53
  };
60
- }
54
+ },
61
55
  },
62
56
  methods: {
63
-
57
+ onInput(value) {
58
+ this.$emit('input', value);
59
+ },
64
60
  }
65
61
  }
66
62
  </script>
@@ -2,8 +2,15 @@
2
2
  <div class="vd-stepper" :class="wrapClasses">
3
3
  <vd-button v-if="!position" :class="minusButtonClass" icon="icon_btn_reduce" size="small"
4
4
  @click="onChange('minus')"></vd-button>
5
- <input type="number" :class="inputClasses" :disabled="disabled" :value="currentValue" :placeholder="placeholder" @input="onInput"
6
- @blur="onBlur">
5
+ <input
6
+ type="number"
7
+ :class="inputClasses"
8
+ :disabled="disabled"
9
+ :value="currentValue"
10
+ :placeholder="placeholder"
11
+ @input="onInput"
12
+ @blur="onBlur"
13
+ >
7
14
  <vd-button v-if="position === 'right'" class="vd-stepper__minus" icon="icon_btn_reduce" size="small"
8
15
  @click="onChange('minus')"></vd-button>
9
16
  <vd-button :class="plusButtonClass" icon="icon_btn_add" size="small"
@@ -21,7 +28,7 @@ export default {
21
28
  props: {
22
29
  value: null,
23
30
  integer: Boolean,
24
- position: String,
31
+ position: String,
25
32
  inputCenter: Boolean,
26
33
  disabled: Boolean,
27
34
  theme: String,
@@ -37,16 +44,21 @@ export default {
37
44
  type: [String, Number],
38
45
  default: 1
39
46
  },
40
- placeholder:String
47
+ placeholder: String
41
48
  },
42
49
  data() {
43
- const value = this.range(this.isDef(this.value) ? this.value : this.defaultValue);
44
- if (value !== +this.value) {
45
- this.$emit('input', value);
50
+ let value;
51
+ if (this.isDef(this.value)) {
52
+ value = this.range(this.value);
53
+ if (value !== this.value) {
54
+ this.$emit('input', value);
55
+ }
56
+ } else {
57
+ value = '';
46
58
  }
47
59
  return {
48
60
  currentValue: value,
49
- }
61
+ };
50
62
  },
51
63
  computed: {
52
64
  inputClasses() {
@@ -60,7 +72,6 @@ export default {
60
72
  [`${prefixCls}--disabled`]: this.disabled,
61
73
  [`${prefixCls}--${this.theme}`]: this.theme,
62
74
  [`${prefixCls}--center`]: this.inputCenter
63
-
64
75
  }
65
76
  ]
66
77
  },
@@ -72,13 +83,6 @@ export default {
72
83
  const hairlineClass = this.language === 'ar' ? 'vd-hairline--right' : 'vd-hairline--left';
73
84
  return `vd-stepper__plus ${hairlineClass}`;
74
85
  }
75
- // minusDisabled() {
76
- // return this.disabled || this.currentValue <= this.min;
77
- // },
78
-
79
- // plusDisabled() {
80
- // return this.disabled || this.currentValue >= this.max;
81
- // }
82
86
  },
83
87
  watch: {
84
88
  value(val) {
@@ -86,7 +90,6 @@ export default {
86
90
  this.currentValue = this.format(val);
87
91
  }
88
92
  },
89
-
90
93
  currentValue(val) {
91
94
  this.$emit('input', val);
92
95
  this.$emit('change', val);
@@ -94,36 +97,39 @@ export default {
94
97
  },
95
98
  methods: {
96
99
  format(value) {
100
+ if (value === '' || value === null || value === undefined) {
101
+ return '';
102
+ }
97
103
  value = String(value).replace(/[^0-9.-]/g, '');
98
- return value === '' ? 0 : this.integer ? Math.floor(value) : +value;
104
+ return this.integer ? Math.floor(value) : +value;
99
105
  },
100
-
101
106
  // limit value range
102
107
  range(value) {
103
- return Math.max(Math.min(this.max, this.format(value)), this.min);
108
+ value = this.format(value);
109
+ if (value === '') {
110
+ return value;
111
+ }
112
+ return Math.max(Math.min(this.max, value), this.min);
104
113
  },
105
-
106
114
  onInput(event) {
107
115
  const { value } = event.target;
108
116
  const formatted = this.format(value);
109
- if (+value !== formatted) {
117
+ if (value !== String(formatted)) {
110
118
  event.target.value = formatted;
111
119
  }
112
120
  this.currentValue = formatted;
113
121
  },
114
-
115
122
  onChange(type) {
116
123
  if (this[`${type}Disabled`]) {
117
124
  this.$emit('overlimit', type);
118
125
  return;
119
126
  }
120
127
  const diff = type === 'minus' ? -this.step : +this.step;
121
- const value = Math.round((this.currentValue + diff) * 100) / 100;
128
+ let value = this.currentValue === '' ? 0 : this.currentValue;
129
+ value = Math.round((value + diff) * 100) / 100;
122
130
  this.currentValue = this.range(value);
123
-
124
131
  this.$emit(type);
125
132
  },
126
-
127
133
  onBlur(event) {
128
134
  this.currentValue = this.range(this.currentValue);
129
135
  this.$emit('blur', event);