@volverjs/ui-vue 0.0.9-beta.9 → 0.0.9

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 (77) hide show
  1. package/auto-imports.d.ts +2 -2
  2. package/dist/components/VvAccordion/VvAccordion.es.js +8 -7
  3. package/dist/components/VvAccordionGroup/VvAccordionGroup.es.js +8 -7
  4. package/dist/components/VvAction/VvAction.es.js +8 -7
  5. package/dist/components/VvAlert/VvAlert.es.js +8 -7
  6. package/dist/components/VvAlertGroup/VvAlertGroup.es.js +8 -7
  7. package/dist/components/VvAlertGroup/VvAlertGroup.vue.d.ts +6 -6
  8. package/dist/components/VvAlertGroup/index.d.ts +2 -2
  9. package/dist/components/VvAvatar/VvAvatar.es.js +8 -7
  10. package/dist/components/VvAvatarGroup/VvAvatarGroup.es.js +8 -7
  11. package/dist/components/VvBadge/VvBadge.es.js +8 -7
  12. package/dist/components/VvBreadcrumb/VvBreadcrumb.es.js +8 -7
  13. package/dist/components/VvButton/VvButton.es.js +8 -7
  14. package/dist/components/VvButtonGroup/VvButtonGroup.es.js +8 -7
  15. package/dist/components/VvCard/VvCard.es.js +8 -7
  16. package/dist/components/VvCheckbox/VvCheckbox.es.js +8 -7
  17. package/dist/components/VvCheckboxGroup/VvCheckboxGroup.es.js +8 -7
  18. package/dist/components/VvCombobox/VvCombobox.es.js +145 -116
  19. package/dist/components/VvCombobox/VvCombobox.umd.js +1 -1
  20. package/dist/components/VvCombobox/VvCombobox.vue.d.ts +306 -90
  21. package/dist/components/VvCombobox/index.d.ts +108 -31
  22. package/dist/components/VvDialog/VvDialog.es.js +16 -11
  23. package/dist/components/VvDialog/VvDialog.umd.js +1 -1
  24. package/dist/components/VvDropdown/VvDropdown.es.js +19 -16
  25. package/dist/components/VvDropdown/VvDropdown.umd.js +1 -1
  26. package/dist/components/VvDropdown/VvDropdown.vue.d.ts +299 -91
  27. package/dist/components/VvDropdown/index.d.ts +99 -30
  28. package/dist/components/VvDropdownAction/VvDropdownAction.es.js +8 -7
  29. package/dist/components/VvDropdownOptgroup/VvDropdownOptgroup.es.js +8 -7
  30. package/dist/components/VvDropdownOption/VvDropdownOption.es.js +8 -7
  31. package/dist/components/VvInputText/VvInputText.es.js +193 -103
  32. package/dist/components/VvInputText/VvInputText.umd.js +1 -1
  33. package/dist/components/VvInputText/VvInputText.vue.d.ts +19 -37
  34. package/dist/components/VvInputText/index.d.ts +15 -33
  35. package/dist/components/VvNav/VvNav.es.js +8 -7
  36. package/dist/components/VvProgress/VvProgress.es.js +8 -7
  37. package/dist/components/VvRadio/VvRadio.es.js +8 -7
  38. package/dist/components/VvRadioGroup/VvRadioGroup.es.js +8 -7
  39. package/dist/components/VvSelect/VvSelect.es.js +8 -7
  40. package/dist/components/VvSelect/VvSelect.vue.d.ts +1 -1
  41. package/dist/components/VvTab/VvTab.es.js +8 -7
  42. package/dist/components/VvTextarea/VvTextarea.es.js +16 -12
  43. package/dist/components/VvTextarea/VvTextarea.umd.js +1 -1
  44. package/dist/components/VvTooltip/VvTooltip.es.js +8 -7
  45. package/dist/components/index.es.js +346 -221
  46. package/dist/components/index.umd.js +1 -1
  47. package/dist/constants.d.ts +4 -0
  48. package/dist/directives/index.es.js +8 -7
  49. package/dist/directives/v-tooltip.es.js +8 -7
  50. package/dist/icons.es.js +3 -3
  51. package/dist/icons.umd.js +1 -1
  52. package/dist/props/index.d.ts +100 -31
  53. package/dist/stories/AccordionGroup/AccordionGroup.stories.d.ts +2 -2
  54. package/dist/stories/AccordionGroup/AccordionGroupSlots.stories.d.ts +18 -18
  55. package/dist/stories/Combobox/Combobox.settings.d.ts +8 -0
  56. package/dist/stories/InputText/InputText.settings.d.ts +31 -9
  57. package/dist/stories/InputText/InputText.stories.d.ts +0 -1
  58. package/dist/stories/InputText/InputTextMask.stories.d.ts +12 -0
  59. package/package.json +60 -59
  60. package/src/assets/icons/detailed.json +1 -1
  61. package/src/assets/icons/normal.json +1 -1
  62. package/src/assets/icons/simple.json +1 -1
  63. package/src/components/VvCombobox/VvCombobox.vue +40 -19
  64. package/src/components/VvCombobox/index.ts +13 -0
  65. package/src/components/VvDialog/VvDialog.vue +6 -2
  66. package/src/components/VvDropdown/VvDropdown.vue +18 -16
  67. package/src/components/VvInputText/VvInputText.vue +170 -55
  68. package/src/components/VvInputText/index.ts +32 -34
  69. package/src/components/VvTextarea/VvTextarea.vue +8 -5
  70. package/src/constants.ts +5 -0
  71. package/src/props/index.ts +7 -11
  72. package/src/stories/Combobox/Combobox.settings.ts +8 -0
  73. package/src/stories/Combobox/Combobox.test.ts +1 -1
  74. package/src/stories/InputText/InputText.settings.ts +36 -15
  75. package/src/stories/InputText/InputText.stories.ts +4 -12
  76. package/src/stories/InputText/InputText.test.ts +31 -15
  77. package/src/stories/InputText/InputTextMask.stories.ts +122 -0
@@ -12,6 +12,7 @@
12
12
 
13
13
  <script setup lang="ts">
14
14
  import type { Ref } from 'vue'
15
+ import { toRefs } from 'vue'
15
16
  import { VvComboboxProps, VvComboboxEvents } from '.'
16
17
  import VvIcon from '../VvIcon/VvIcon.vue'
17
18
  import VvDropdown from '../VvDropdown/VvDropdown.vue'
@@ -84,7 +85,7 @@
84
85
  const searchText = ref('')
85
86
  const debouncedSearchText = refDebounced(
86
87
  searchText,
87
- Number(props.debounceSearch),
88
+ computed(() => Number(props.debounceSearch)),
88
89
  )
89
90
  watch(debouncedSearchText, () =>
90
91
  emit('change:search', debouncedSearchText.value),
@@ -105,7 +106,7 @@
105
106
  expanded.value = false
106
107
  }
107
108
  const onAfterExpand = () => {
108
- if (searchable.value) {
109
+ if (propsDefaults.value.searchable) {
109
110
  if (inputSearchEl.value) {
110
111
  inputSearchEl.value.focus({
111
112
  preventScroll: true,
@@ -114,7 +115,7 @@
114
115
  }
115
116
  }
116
117
  const onAfterCollapse = () => {
117
- if (searchable.value) {
118
+ if (propsDefaults.value.searchable) {
118
119
  searchText.value = ''
119
120
  }
120
121
  }
@@ -131,7 +132,6 @@
131
132
  valid,
132
133
  invalid,
133
134
  floating,
134
- searchable,
135
135
  } = toRefs(props)
136
136
  const hasId = useUniqueId(id)
137
137
  const hasHintId = computed(() => `${hasId.value}-hint`)
@@ -139,6 +139,10 @@
139
139
  const hasSearchId = computed(() => `${hasId.value}-search`)
140
140
  const hasLabelId = computed(() => `${hasId.value}-label`)
141
141
 
142
+ // loading
143
+ const localLoading = ref(false)
144
+ const isLoading = computed(() => localLoading.value || loading.value)
145
+
142
146
  // ref
143
147
  const dropdownEl = ref()
144
148
 
@@ -162,7 +166,7 @@
162
166
  modifiers,
163
167
  computed(() => ({
164
168
  disabled: disabled.value,
165
- loading: loading.value,
169
+ loading: isLoading.value,
166
170
  readonly: readonly.value,
167
171
  'icon-before': Boolean(hasIconBefore.value),
168
172
  'icon-after': Boolean(hasIconAfter.value),
@@ -183,7 +187,18 @@
183
187
  } = useOptions(props)
184
188
 
185
189
  // options filtered by search text
186
- const filteredOptions = computed(() => {
190
+ const filteredOptions = computedAsync(async () => {
191
+ if (propsDefaults.value.searchFunction) {
192
+ localLoading.value = true
193
+ const toReturn = await Promise.resolve(
194
+ propsDefaults.value.searchFunction(
195
+ debouncedSearchText.value,
196
+ props.options,
197
+ ),
198
+ )
199
+ localLoading.value = false
200
+ return toReturn
201
+ }
187
202
  return props.options?.filter((option) => {
188
203
  return getOptionLabel(option)
189
204
  .toLowerCase()
@@ -221,12 +236,15 @@
221
236
  } else if (props.modelValue) {
222
237
  selectedValues = [props.modelValue]
223
238
  }
224
- const options = props.options.reduce((acc, value) => {
225
- if (isGroup(value)) {
226
- return [...acc, ...getOptionGrouped(value)]
227
- }
228
- return [...acc, value]
229
- }, [] as Array<Option | string>)
239
+ const options = props.options.reduce(
240
+ (acc, value) => {
241
+ if (isGroup(value)) {
242
+ return [...acc, ...getOptionGrouped(value)]
243
+ }
244
+ return [...acc, value]
245
+ },
246
+ [] as Array<Option | string>,
247
+ )
230
248
 
231
249
  return options.filter((option) => {
232
250
  if (isGroup(option)) {
@@ -304,7 +322,7 @@
304
322
  invalid: invalid.value,
305
323
  invalidLabel: propsDefaults.value.invalidLabel,
306
324
  hintLabel: propsDefaults.value.hintLabel,
307
- loading: loading.value,
325
+ loading: isLoading.value,
308
326
  loadingLabel: propsDefaults.value.loadingLabel,
309
327
  disabled: disabled.value,
310
328
  readonly: readonly.value,
@@ -333,7 +351,7 @@
333
351
  flip: propsDefaults.value.flip,
334
352
  autoPlacement: propsDefaults.value.autoPlacement,
335
353
  arrow: propsDefaults.value.arrow,
336
- autofocusFirst: searchable.value
354
+ autofocusFirst: propsDefaults.value.searchable
337
355
  ? true
338
356
  : propsDefaults.value.autofocusFirst,
339
357
  triggerWidth: propsDefaults.value.triggerWidth,
@@ -369,7 +387,7 @@
369
387
  <label
370
388
  v-if="label"
371
389
  :id="hasLabelId"
372
- :for="searchable ? hasSearchId : undefined"
390
+ :for="propsDefaults.searchable ? hasSearchId : undefined"
373
391
  >
374
392
  {{ label }}
375
393
  </label>
@@ -383,13 +401,15 @@
383
401
  @after-collapse="onAfterCollapse"
384
402
  >
385
403
  <template
386
- v-if="searchable || $slots['dropdown::before']"
404
+ v-if="
405
+ propsDefaults.searchable || $slots['dropdown::before']
406
+ "
387
407
  #before
388
408
  >
389
409
  <!-- @slot Slot before dropdown items -->
390
410
  <slot name="dropdown::before" />
391
411
  <input
392
- v-if="searchable"
412
+ v-if="propsDefaults.searchable && !disabled"
393
413
  :id="hasSearchId"
394
414
  ref="inputSearchEl"
395
415
  v-model="searchText"
@@ -460,6 +480,7 @@
460
480
  :aria-label="
461
481
  propsDefaults.deselectActionLabel
462
482
  "
483
+ type="button"
463
484
  @click.stop="onInput(option)"
464
485
  >
465
486
  <VvIcon name="close" />
@@ -483,7 +504,7 @@
483
504
  </div>
484
505
  </template>
485
506
  <template #items>
486
- <template v-if="filteredOptions.length">
507
+ <template v-if="!disabled && filteredOptions?.length">
487
508
  <template
488
509
  v-for="(option, index) in filteredOptions"
489
510
  :key="index"
@@ -565,7 +586,7 @@
565
586
  {{ propsDefaults.noOptionsLabel }}
566
587
  </slot>
567
588
  </VvDropdownOption>
568
- <VvDropdownOption v-else modifiers="inert">
589
+ <VvDropdownOption v-else-if="!disabled" modifiers="inert">
569
590
  <!-- @slot Slot for no results available -->
570
591
  <slot name="no-results">
571
592
  {{ propsDefaults.noResultsLabel }}
@@ -16,6 +16,7 @@ import {
16
16
  DropdownProps,
17
17
  LabelProps,
18
18
  } from '../../props'
19
+ import type { Option } from '../../types/generic'
19
20
 
20
21
  export const VvComboboxEvents = [
21
22
  'update:modelValue',
@@ -90,6 +91,18 @@ export const VvComboboxProps = {
90
91
  * Use input text to search on options
91
92
  */
92
93
  searchable: Boolean,
94
+ /**
95
+ * Search function to filter options
96
+ */
97
+ searchFunction: {
98
+ type: Function as PropType<
99
+ (
100
+ search: string,
101
+ options: (Option | string)[],
102
+ ) => (Option | string)[] | Promise<(Option | string)[]>
103
+ >,
104
+ default: undefined,
105
+ },
93
106
  /**
94
107
  * On searchable select is the input search placeholder
95
108
  */
@@ -49,12 +49,16 @@
49
49
  const transitioName = computed(() => `vv-dialog--${props.transition}`)
50
50
  const dialogTransitionHandlers = {
51
51
  'before-enter': () => {
52
- dialogEl.value?.showModal()
52
+ if (!dialogEl.value?.open) {
53
+ dialogEl.value?.showModal()
54
+ }
53
55
  emit('open')
54
56
  emit('before-enter')
55
57
  },
56
58
  'after-leave': () => {
57
- dialogEl.value?.close()
59
+ if (dialogEl.value?.open) {
60
+ dialogEl.value?.close()
61
+ }
58
62
  emit('close')
59
63
  emit('after-leave')
60
64
  },
@@ -25,6 +25,7 @@
25
25
  ShiftOptions,
26
26
  SizeOptions,
27
27
  } from '../../types/floating-ui'
28
+ import { Side, Strategy } from '../../constants'
28
29
 
29
30
  // props, emit and attrs
30
31
  const props = defineProps(VvDropdownProps)
@@ -96,7 +97,7 @@
96
97
  }
97
98
  } else if (props.flip) {
98
99
  if (typeof props.flip === 'boolean') {
99
- toReturn.push(flip())
100
+ toReturn.push(flip({ fallbackStrategy: 'initialPlacement' }))
100
101
  } else {
101
102
  toReturn.push(flip(props.flip as FlipOptions))
102
103
  }
@@ -157,13 +158,13 @@
157
158
 
158
159
  return toReturn
159
160
  })
160
- const { x, y, strategy, middlewareData, placement } = useFloating(
161
+ const { x, y, middlewareData, placement, strategy } = useFloating(
161
162
  referenceEl,
162
163
  floatingEl,
163
164
  {
164
165
  whileElementsMounted: (...args) => {
165
166
  return autoUpdate(...args, {
166
- animationFrame: props.strategy === 'fixed',
167
+ animationFrame: props.strategy === Strategy.fixed,
167
168
  })
168
169
  },
169
170
  placement: computed(() => props.placement),
@@ -175,16 +176,17 @@
175
176
  if (hasCustomPosition.value) {
176
177
  return undefined
177
178
  }
179
+ const width =
180
+ props.triggerWidth && referenceEl.value
181
+ ? `${referenceEl.value?.offsetWidth}px`
182
+ : undefined
178
183
  return {
179
184
  position: strategy.value,
180
185
  top: `${y.value ?? 0}px`,
181
186
  left: `${x.value ?? 0}px`,
182
- maxWidth: maxWidth.value,
187
+ maxWidth: width ? undefined : maxWidth.value,
183
188
  maxHeight: maxHeight.value,
184
- width:
185
- props.triggerWidth && referenceEl.value
186
- ? `${referenceEl.value.offsetWidth}px`
187
- : undefined,
189
+ width,
188
190
  }
189
191
  })
190
192
 
@@ -192,20 +194,20 @@
192
194
  const side = computed(
193
195
  () =>
194
196
  placement.value.split('-')[0] as
195
- | 'top'
196
- | 'right'
197
- | 'bottom'
198
- | 'left',
197
+ | Side.top
198
+ | Side.right
199
+ | Side.bottom
200
+ | Side.left,
199
201
  )
200
202
  const arrowPlacement = computed(() => {
201
203
  if (hasCustomPosition.value) {
202
204
  return undefined
203
205
  }
204
206
  const staticSide = {
205
- top: 'bottom',
206
- right: 'left',
207
- bottom: 'top',
208
- left: 'right',
207
+ [Side.top]: Side.bottom,
208
+ [Side.right]: Side.left,
209
+ [Side.bottom]: Side.top,
210
+ [Side.left]: Side.right,
209
211
  }[side.value]
210
212
  return {
211
213
  left:
@@ -6,7 +6,7 @@
6
6
 
7
7
  <script setup lang="ts">
8
8
  import type { InputHTMLAttributes } from 'vue'
9
- import { Mask } from 'maska'
9
+ import { useIMask } from 'vue-imask'
10
10
  import HintSlotFactory from '../common/HintSlot'
11
11
  import VvIcon from '../VvIcon/VvIcon.vue'
12
12
  import VvInputTextActionsFactory from '../VvInputText/VvInputTextActions'
@@ -29,12 +29,6 @@
29
29
  props,
30
30
  )
31
31
 
32
- // template refs
33
- const inputEl = ref()
34
- const innerEl = ref()
35
-
36
- defineExpose({ $inner: innerEl })
37
-
38
32
  // data
39
33
  const {
40
34
  id,
@@ -46,6 +40,12 @@
46
40
  valid,
47
41
  invalid,
48
42
  loading,
43
+ debounce,
44
+ maxlength,
45
+ minlength,
46
+ type,
47
+ iMask,
48
+ step,
49
49
  } = toRefs(props)
50
50
  const hasId = useUniqueId(id)
51
51
  const hasHintId = computed(() => `${hasId.value}-hint`)
@@ -54,35 +54,144 @@
54
54
  props.floating && isEmpty(props.placeholder) ? ' ' : props.placeholder,
55
55
  )
56
56
 
57
- // debounce
58
- const localModelValue = useDebouncedInput(
59
- modelValue,
60
- emit,
61
- props.debounce,
57
+ // template refs
58
+ const maskReady = ref(false)
59
+ const { el, mask, typed, masked, unmasked } = useIMask(
60
+ computed(
61
+ () =>
62
+ iMask?.value ?? {
63
+ mask: /./,
64
+ },
65
+ ),
62
66
  {
63
- getter: (value) => {
64
- if (mask.value) {
65
- return mask.value.masked(value ?? '')
67
+ emit,
68
+ onAccept: () => {
69
+ if (!maskReady.value) {
70
+ return
66
71
  }
67
- return value
68
- },
69
- setter: (value) => {
70
- if (mask.value) {
71
- value = mask.value.unmasked(value)
72
+ emit('update:masked', masked.value)
73
+ if (type.value === INPUT_TYPES.NUMBER) {
74
+ if (masked.value === '') {
75
+ if (
76
+ localModelValue.value === null ||
77
+ localModelValue.value === undefined
78
+ ) {
79
+ return
80
+ }
81
+ localModelValue.value = undefined
82
+ return
83
+ }
84
+ if (typeof typed.value !== 'number') {
85
+ localModelValue.value = Number(typed.value)
86
+ return
87
+ }
88
+ localModelValue.value = typed.value
89
+ return
90
+ }
91
+ if (type.value === INPUT_TYPES.DATE) {
92
+ if (
93
+ el.value instanceof HTMLInputElement &&
94
+ el.value.type === 'date'
95
+ ) {
96
+ localModelValue.value = el.value.value
97
+ return
98
+ }
99
+ let date = typed.value
100
+ if (date === null || date === '') {
101
+ if (!localModelValue.value) {
102
+ return
103
+ }
104
+ localModelValue.value = ''
105
+ return
106
+ }
107
+ if (!(date instanceof Date)) {
108
+ date = new Date(date)
109
+ }
110
+ localModelValue.value = `${date.getFullYear()}-${(
111
+ '0' +
112
+ (date.getMonth() + 1)
113
+ ).slice(-2)}-${('0' + date.getDate()).slice(-2)}`
114
+ return
115
+ }
116
+ if (type.value === INPUT_TYPES.DATETIME_LOCAL) {
117
+ if (
118
+ el.value instanceof HTMLInputElement &&
119
+ el.value.type === 'datetime-local'
120
+ ) {
121
+ localModelValue.value = el.value.value
122
+ return
123
+ }
124
+ let date = typed.value
125
+ if (date === null || date === '') {
126
+ if (!localModelValue.value) {
127
+ return
128
+ }
129
+ localModelValue.value = ''
130
+ return
131
+ }
132
+ if (!(typed.value instanceof Date)) {
133
+ date = new Date(date)
134
+ }
135
+ localModelValue.value = `${date.getFullYear()}-${(
136
+ '0' +
137
+ (date.getMonth() + 1)
138
+ ).slice(-2)}-${('0' + date.getDate()).slice(-2)}T${(
139
+ '0' + date.getHours()
140
+ ).slice(-2)}:${('0' + date.getMinutes()).slice(-2)}`
141
+ return
72
142
  }
73
- if (props.type === INPUT_TYPES.NUMBER) {
74
- return Number(value)
143
+ if (!localModelValue.value && !unmasked.value) {
144
+ return
75
145
  }
76
- return value
146
+ localModelValue.value = unmasked.value
77
147
  },
78
148
  },
79
149
  )
150
+ onMounted(() => {
151
+ if (mask.value) {
152
+ maskReady.value = true
153
+ typed.value = localModelValue.value ?? ''
154
+ }
155
+ })
156
+ watch(
157
+ () => props.modelValue,
158
+ (newValue) => {
159
+ if (mask.value) {
160
+ typed.value =
161
+ newValue && iMask?.value?.mask === Date
162
+ ? new Date(newValue)
163
+ : newValue ?? ''
164
+ }
165
+ },
166
+ )
167
+ watch(
168
+ () => props.masked,
169
+ (newValue) => {
170
+ masked.value = newValue ?? ''
171
+ },
172
+ )
173
+ const inputEl = el as Ref<HTMLInputElement>
174
+ const innerEl = ref()
175
+
176
+ defineExpose({ $inner: innerEl })
177
+
178
+ // debounce
179
+ const localModelValue = useDebouncedInput(
180
+ modelValue,
181
+ emit,
182
+ debounce?.value ?? 0,
183
+ )
80
184
 
81
185
  // focus
82
186
  const { focused } = useComponentFocus(inputEl, emit)
83
187
  const isFocused = computed(
84
188
  () => focused.value && !props.disabled && !props.readonly,
85
189
  )
190
+ watch(isFocused, (newValue) => {
191
+ if (newValue && propsDefaults.value.selectOnFocus && inputEl.value) {
192
+ inputEl.value.select()
193
+ }
194
+ })
86
195
 
87
196
  // visibility
88
197
  const isVisible = useElementVisibility(inputEl)
@@ -113,12 +222,21 @@
113
222
  const isNumber = computed(() => props.type === INPUT_TYPES.NUMBER)
114
223
  const onStepUp = () => {
115
224
  if (isClickable.value) {
225
+ if (iMask?.value) {
226
+ typed.value = typed.value + Number(step?.value ?? 1)
227
+ return
228
+ }
116
229
  inputEl.value.stepUp()
117
230
  localModelValue.value = unref(inputEl).value
118
231
  }
119
232
  }
120
233
  const onStepDown = () => {
121
234
  if (isClickable.value) {
235
+ if (iMask?.value) {
236
+ typed.value = typed.value - Number(step?.value ?? 1)
237
+
238
+ return
239
+ }
122
240
  inputEl.value.stepDown()
123
241
  localModelValue.value = unref(inputEl).value
124
242
  }
@@ -127,7 +245,7 @@
127
245
  // search
128
246
  const isSearch = computed(() => props.type === INPUT_TYPES.SEARCH)
129
247
  const onClear = () => {
130
- localModelValue.value = undefined
248
+ localModelValue.value = ''
131
249
  }
132
250
 
133
251
  // icons
@@ -153,9 +271,9 @@
153
271
 
154
272
  // count
155
273
  const { formatted: countFormatted } = useTextCount(localModelValue, {
156
- mode: props.count,
157
- upperLimit: Number(props.maxlength),
158
- lowerLimit: Number(props.minlength),
274
+ mode: count.value,
275
+ upperLimit: Number(maxlength?.value),
276
+ lowerLimit: Number(minlength?.value),
159
277
  })
160
278
 
161
279
  // tabindex
@@ -207,6 +325,9 @@
207
325
  if (isDateTime.value && !isDirty.value && !focused.value) {
208
326
  return INPUT_TYPES.TEXT
209
327
  }
328
+ if (iMask?.value) {
329
+ return INPUT_TYPES.TEXT
330
+ }
210
331
  return props.type
211
332
  })()
212
333
  const toReturn: InputHTMLAttributes = {
@@ -299,33 +420,6 @@
299
420
  props,
300
421
  )
301
422
 
302
- // mask
303
- const mask = ref()
304
- watch(
305
- [
306
- () => props.mask,
307
- () => props.type,
308
- () => props.maskEager,
309
- () => props.maskReversed,
310
- () => props.maskTokens,
311
- () => props.maskTokensReplace,
312
- ],
313
- ([newMask, newType, eager, reversed, tokens, tokensReplace]) => {
314
- if (newMask && newType === INPUT_TYPES.TEXT) {
315
- mask.value = new Mask({
316
- mask: newMask,
317
- eager,
318
- reversed,
319
- tokens,
320
- tokensReplace,
321
- })
322
- return
323
- }
324
- mask.value = undefined
325
- },
326
- { immediate: true },
327
- )
328
-
329
423
  // auto-width
330
424
  const onClickInner = () => {
331
425
  if (isClickable.value) {
@@ -343,6 +437,26 @@
343
437
  : undefined,
344
438
  }
345
439
  })
440
+
441
+ // keydown
442
+ const onKeyDown = (event: KeyboardEvent) => {
443
+ switch (event.code) {
444
+ case 'ArrowUp':
445
+ if (isNumber.value) {
446
+ onStepUp()
447
+ event.preventDefault()
448
+ }
449
+ break
450
+
451
+ case 'ArrowDown':
452
+ if (isNumber.value) {
453
+ onStepDown()
454
+ event.preventDefault()
455
+ }
456
+ break
457
+ }
458
+ emit('keydown', event)
459
+ }
346
460
  </script>
347
461
 
348
462
  <template>
@@ -368,10 +482,11 @@
368
482
  <input
369
483
  :id="hasId"
370
484
  ref="inputEl"
371
- v-model="localModelValue"
372
485
  v-bind="hasAttrs"
373
486
  :style="hasStyle"
374
487
  @keyup="emit('keyup', $event)"
488
+ @keydown="onKeyDown"
489
+ @keypress="emit('keypress', $event)"
375
490
  />
376
491
  <div
377
492
  v-if="(unit || $slots.unit) && isDirty"