|
13 | 13 | :type="type" |
14 | 14 | :class="className" |
15 | 15 | v-on="computedListeners" |
| 16 | + :disabled="disabled" |
16 | 17 | :maxlength="maxLength" |
| 18 | + :placeholder="currentPlaceholder" |
17 | 19 | v-model="values[i - 1]" |
18 | 20 | :data-index="`${i - 1}`" |
19 | 21 | /> |
|
33 | 35 | ComputedRef, |
34 | 36 | onBeforeUpdate, |
35 | 37 | Ref, |
| 38 | + nextTick, |
| 39 | + isRef, |
| 40 | + unref, |
36 | 41 | } from 'vue'; |
37 | 42 | import { SplitInputType, Prop } from '../type'; |
38 | 43 | export default defineComponent({ |
|
55 | 60 | type: String, |
56 | 61 | default: '', |
57 | 62 | }, |
| 63 | + disabled: { |
| 64 | + type: Boolean, |
| 65 | + default: false, |
| 66 | + }, |
| 67 | + placeholder: { |
| 68 | + type: String, |
| 69 | + default: '', |
| 70 | + }, |
| 71 | + placeholders: { |
| 72 | + type: Array, |
| 73 | + default: null, |
| 74 | + }, |
58 | 75 | }, |
59 | | - emits: ['update:modelValue'], |
| 76 | + emits: ['update:modelValue', 'focus'], |
60 | 77 | setup: (props: Prop, { emit, attrs }: SetupContext) => { |
61 | 78 | const data: SplitInputType = reactive({ |
62 | 79 | index: null, |
63 | 80 | values: [], |
64 | 81 | }); |
65 | 82 |
|
66 | | - const { inputNumber, modelValue } = toRefs(props); |
| 83 | + const { inputNumber, modelValue, placeholders, placeholder } = |
| 84 | + toRefs<Prop>(props); |
67 | 85 |
|
68 | 86 | const input: Ref<HTMLInputElement[]> = ref<HTMLInputElement[]>([]); |
69 | 87 |
|
|
83 | 101 | () => input.value?.[data.index + 1], |
84 | 102 | ); |
85 | 103 |
|
| 104 | + const currentInput: ComputedRef<HTMLInputElement> = computed( |
| 105 | + () => input.value?.[data.index], |
| 106 | + ); |
| 107 | +
|
86 | 108 | const previousInput: ComputedRef<HTMLInputElement> = computed( |
87 | 109 | () => input.value?.[data.index - 1], |
88 | 110 | ); |
89 | 111 |
|
| 112 | + const currentPlaceholder: ComputedRef<string> = computed( |
| 113 | + () => |
| 114 | + (isRef(placeholders) && unref(placeholders)?.[data.index]) || |
| 115 | + unref(placeholder), |
| 116 | + ); |
| 117 | +
|
90 | 118 | const computedListeners = { |
91 | 119 | ...attrs, |
92 | 120 | blur: (): any => (data.index = null), |
93 | 121 | change: (): void => emit('update:modelValue', joinedValues.value), |
94 | 122 | focus: (event: FocusEvent): void => { |
95 | 123 | data.index = [...input.value].indexOf(event.target as HTMLInputElement); |
| 124 | + nextTick(() => emit('focus', event)); |
96 | 125 | }, |
97 | 126 | input: (event: InputEvent): void => { |
98 | 127 | if (event.inputType === 'insertText') { |
|
103 | 132 | keydown: (event: any): void => { |
104 | 133 | const cursorPosition = Number(event.target.dataset.index); |
105 | 134 | const currentValue = data.values[cursorPosition]; |
106 | | - switch (event?.code) { |
| 135 | + switch (event?.code || event?.key || event?.which || event?.keyCode) { |
107 | 136 | case 'ArrowDown': |
| 137 | + case 40: |
108 | 138 | navigate(lastInput.value); |
109 | 139 | break; |
110 | 140 | case 'ArrowLeft': |
| 141 | + case 37: |
111 | 142 | if (cursorPosition === 0 || !currentValue) { |
112 | 143 | navigate(previousInput.value); |
113 | 144 | } |
114 | 145 | break; |
115 | 146 | case 'ArrowRight': |
| 147 | + case 39: |
116 | 148 | if (cursorPosition === 1 || !currentValue) { |
117 | 149 | navigate(nextInput.value); |
118 | 150 | } |
119 | 151 | break; |
120 | 152 | case 'ArrowUp': |
| 153 | + case 38: |
121 | 154 | navigate(firstInput.value); |
122 | 155 | break; |
123 | 156 | case 'Backspace': |
| 157 | + case 8: |
124 | 158 | if (cursorPosition !== 0) { |
125 | 159 | data.values[cursorPosition] = ''; |
126 | 160 | navigate(previousInput.value); |
|
171 | 205 | } |
172 | 206 | }; |
173 | 207 |
|
| 208 | + const clearAllInput = (): void => { |
| 209 | + data.values = []; |
| 210 | + nextTick(() => emit('update:modelValue', joinedValues.value)); |
| 211 | + }; |
| 212 | +
|
174 | 213 | return { |
175 | 214 | ...toRefs(data), |
176 | 215 | input, |
177 | 216 | computedListeners, |
| 217 | + currentPlaceholder, |
| 218 | + currentInput, |
| 219 | + clearAllInput, |
178 | 220 | }; |
179 | 221 | }, |
180 | 222 | }); |
181 | 223 | </script> |
| 224 | + |
| 225 | +<style scoped> |
| 226 | + :disabled { |
| 227 | + pointer-events: none; |
| 228 | + opacity: 0.5; |
| 229 | + } |
| 230 | +</style> |
0 commit comments