Skip to content

Commit da066c7

Browse files
authored
Merge pull request #39 from dammy001/feature/add-new-props
feat(component): add new props, migrate to pnpm, add examples, bug fix and update readme
2 parents e554974 + 2d47074 commit da066c7

24 files changed

+1781
-227
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
node_modules
2-
dist
2+
dist

.npmignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
/renovate.json
1+
/renovate.json
2+
examples

README.md

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,20 @@ app.mount('#app')
3333

3434
###### Props
3535

36-
| Props | #Type | #default |
37-
| :---------: | :-------------------------------------------: | :------: |
38-
| inputNumber | Number | 6 |
39-
| type | String as PropType<'tel', 'password', 'text'> | 'tel' |
40-
| className | String | '' |
36+
| Props | #Type | #default | #description |
37+
| :----------: | :-------------------------------------------: | :------: | :--------------------------------------------: |
38+
| inputNumber | Number | 6 | Number for input rendered |
39+
| type | String as PropType<'tel', 'password', 'text'> | 'tel' | Input type. Optional value: `password`, `text` |
40+
| className | String | '' | Custom class/style for each input |
41+
| disabled | Boolean | false | Disabled all input |
42+
| placeholder | String | '' | Default description for each input |
43+
| placeholders | Array | null | Default description for all inputs |
44+
45+
###### Events
46+
47+
| Name | #Description |
48+
| :---: | :------------------------------------------------------------: |
49+
| focus | custom focus method that passes the input event as an argument |
4150

4251
###### SplitInput.vue Usage
4352

@@ -67,5 +76,34 @@ app.mount('#app')
6776
</script>
6877
```
6978

79+
You can also pass a ref to access the component dom and objects directly
80+
81+
```vue
82+
<script setup lang="ts">
83+
import { ref } from 'vue';
84+
import type { ComponentPublicInstance } from 'vue';
85+
import type { Prop } from 'vue-split-input';
86+
87+
const input = ref<ComponentPublicInstance<Prop> | null>(null);
88+
const clear = () => input.value?.clearAllInput();
89+
</script>
90+
91+
<template>
92+
<split-input
93+
ref="input"
94+
v-model="input"
95+
class-name="w-12 h-8 rounded-sm p-5 font-bold text-lg"
96+
:input-number="4"
97+
/>
98+
<button
99+
type="button"
100+
@click="clear"
101+
class="px-6 bg-blue-500 text-white text-xs ml-2"
102+
>
103+
CLEAR ALL
104+
</button>
105+
</template>
106+
```
107+
70108
Thanks!
71109
Damilare.

components/SplitInput.vue

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
:type="type"
1414
:class="className"
1515
v-on="computedListeners"
16+
:disabled="disabled"
1617
:maxlength="maxLength"
18+
:placeholder="currentPlaceholder"
1719
v-model="values[i - 1]"
1820
:data-index="`${i - 1}`"
1921
/>
@@ -33,6 +35,9 @@
3335
ComputedRef,
3436
onBeforeUpdate,
3537
Ref,
38+
nextTick,
39+
isRef,
40+
unref,
3641
} from 'vue';
3742
import { SplitInputType, Prop } from '../type';
3843
export default defineComponent({
@@ -55,15 +60,28 @@
5560
type: String,
5661
default: '',
5762
},
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+
},
5875
},
59-
emits: ['update:modelValue'],
76+
emits: ['update:modelValue', 'focus'],
6077
setup: (props: Prop, { emit, attrs }: SetupContext) => {
6178
const data: SplitInputType = reactive({
6279
index: null,
6380
values: [],
6481
});
6582
66-
const { inputNumber, modelValue } = toRefs(props);
83+
const { inputNumber, modelValue, placeholders, placeholder } =
84+
toRefs<Prop>(props);
6785
6886
const input: Ref<HTMLInputElement[]> = ref<HTMLInputElement[]>([]);
6987
@@ -83,16 +101,27 @@
83101
() => input.value?.[data.index + 1],
84102
);
85103
104+
const currentInput: ComputedRef<HTMLInputElement> = computed(
105+
() => input.value?.[data.index],
106+
);
107+
86108
const previousInput: ComputedRef<HTMLInputElement> = computed(
87109
() => input.value?.[data.index - 1],
88110
);
89111
112+
const currentPlaceholder: ComputedRef<string> = computed(
113+
() =>
114+
(isRef(placeholders) && unref(placeholders)?.[data.index]) ||
115+
unref(placeholder),
116+
);
117+
90118
const computedListeners = {
91119
...attrs,
92120
blur: (): any => (data.index = null),
93121
change: (): void => emit('update:modelValue', joinedValues.value),
94122
focus: (event: FocusEvent): void => {
95123
data.index = [...input.value].indexOf(event.target as HTMLInputElement);
124+
nextTick(() => emit('focus', event));
96125
},
97126
input: (event: InputEvent): void => {
98127
if (event.inputType === 'insertText') {
@@ -103,24 +132,29 @@
103132
keydown: (event: any): void => {
104133
const cursorPosition = Number(event.target.dataset.index);
105134
const currentValue = data.values[cursorPosition];
106-
switch (event?.code) {
135+
switch (event?.code || event?.key || event?.which || event?.keyCode) {
107136
case 'ArrowDown':
137+
case 40:
108138
navigate(lastInput.value);
109139
break;
110140
case 'ArrowLeft':
141+
case 37:
111142
if (cursorPosition === 0 || !currentValue) {
112143
navigate(previousInput.value);
113144
}
114145
break;
115146
case 'ArrowRight':
147+
case 39:
116148
if (cursorPosition === 1 || !currentValue) {
117149
navigate(nextInput.value);
118150
}
119151
break;
120152
case 'ArrowUp':
153+
case 38:
121154
navigate(firstInput.value);
122155
break;
123156
case 'Backspace':
157+
case 8:
124158
if (cursorPosition !== 0) {
125159
data.values[cursorPosition] = '';
126160
navigate(previousInput.value);
@@ -171,11 +205,26 @@
171205
}
172206
};
173207
208+
const clearAllInput = (): void => {
209+
data.values = [];
210+
nextTick(() => emit('update:modelValue', joinedValues.value));
211+
};
212+
174213
return {
175214
...toRefs(data),
176215
input,
177216
computedListeners,
217+
currentPlaceholder,
218+
currentInput,
219+
clearAllInput,
178220
};
179221
},
180222
});
181223
</script>
224+
225+
<style scoped>
226+
:disabled {
227+
pointer-events: none;
228+
opacity: 0.5;
229+
}
230+
</style>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"recommendations": ["johnsoncodehk.volar"]
3+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Vue 3 + Typescript + Vite
2+
3+
This template should help get you started developing with Vue 3 and Typescript in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
4+
5+
## Recommended IDE Setup
6+
7+
- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)
8+
9+
## Type Support For `.vue` Imports in TS
10+
11+
Since TypeScript cannot handle type information for `.vue` imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in `.vue` imports (for example to get props validation when using manual `h(...)` calls), you can enable Volar's `.vue` type support plugin by running `Volar: Switch TS Plugin on/off` from VSCode command palette.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
<link rel="icon" href="/favicon.ico" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
8+
<title>Vite App</title>
9+
</head>
10+
11+
<body>
12+
<div id="app"></div>
13+
<script type="module" src="/src/main.ts"></script>
14+
</body>
15+
16+
</html>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "split-input-example",
3+
"version": "0.9.35",
4+
"scripts": {
5+
"dev": "vite --host",
6+
"build": "vue-tsc --noEmit && vite build",
7+
"preview": "vite preview"
8+
},
9+
"dependencies": {
10+
"vue": "^3.2.25",
11+
"vue-split-input": "^0.9.35"
12+
},
13+
"devDependencies": {
14+
"@vitejs/plugin-vue": "^2.0.0",
15+
"autoprefixer": "^10.4.2",
16+
"postcss": "^8.4.6",
17+
"sass": "^1.49.7",
18+
"tailwindcss": "^3.0.18",
19+
"typescript": "^4.5.5",
20+
"vite": "^2.7.13",
21+
"vue-tsc": "^0.29.8"
22+
}
23+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
plugins: {
3+
tailwindcss: {},
4+
autoprefixer: {},
5+
},
6+
}

0 commit comments

Comments
 (0)