Skip to content

Commit

Permalink
Merge pull request #39 from dammy001/feature/add-new-props
Browse files Browse the repository at this point in the history
feat(component): add new props, migrate to pnpm, add examples, bug fix and update readme
  • Loading branch information
dammy001 authored Feb 5, 2022
2 parents e554974 + 2d47074 commit da066c7
Show file tree
Hide file tree
Showing 24 changed files with 1,781 additions and 227 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
node_modules
dist
dist
3 changes: 2 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/renovate.json
/renovate.json
examples
48 changes: 43 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,20 @@ app.mount('#app')

###### Props

| Props | #Type | #default |
| :---------: | :-------------------------------------------: | :------: |
| inputNumber | Number | 6 |
| type | String as PropType<'tel', 'password', 'text'> | 'tel' |
| className | String | '' |
| Props | #Type | #default | #description |
| :----------: | :-------------------------------------------: | :------: | :--------------------------------------------: |
| inputNumber | Number | 6 | Number for input rendered |
| type | String as PropType<'tel', 'password', 'text'> | 'tel' | Input type. Optional value: `password`, `text` |
| className | String | '' | Custom class/style for each input |
| disabled | Boolean | false | Disabled all input |
| placeholder | String | '' | Default description for each input |
| placeholders | Array | null | Default description for all inputs |

###### Events

| Name | #Description |
| :---: | :------------------------------------------------------------: |
| focus | custom focus method that passes the input event as an argument |

###### SplitInput.vue Usage

Expand Down Expand Up @@ -67,5 +76,34 @@ app.mount('#app')
</script>
```

You can also pass a ref to access the component dom and objects directly

```vue
<script setup lang="ts">
import { ref } from 'vue';
import type { ComponentPublicInstance } from 'vue';
import type { Prop } from 'vue-split-input';
const input = ref<ComponentPublicInstance<Prop> | null>(null);
const clear = () => input.value?.clearAllInput();
</script>
<template>
<split-input
ref="input"
v-model="input"
class-name="w-12 h-8 rounded-sm p-5 font-bold text-lg"
:input-number="4"
/>
<button
type="button"
@click="clear"
class="px-6 bg-blue-500 text-white text-xs ml-2"
>
CLEAR ALL
</button>
</template>
```

Thanks!
Damilare.
55 changes: 52 additions & 3 deletions components/SplitInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
:type="type"
:class="className"
v-on="computedListeners"
:disabled="disabled"
:maxlength="maxLength"
:placeholder="currentPlaceholder"
v-model="values[i - 1]"
:data-index="`${i - 1}`"
/>
Expand All @@ -33,6 +35,9 @@
ComputedRef,
onBeforeUpdate,
Ref,
nextTick,
isRef,
unref,
} from 'vue';
import { SplitInputType, Prop } from '../type';
export default defineComponent({
Expand All @@ -55,15 +60,28 @@
type: String,
default: '',
},
disabled: {
type: Boolean,
default: false,
},
placeholder: {
type: String,
default: '',
},
placeholders: {
type: Array,
default: null,
},
},
emits: ['update:modelValue'],
emits: ['update:modelValue', 'focus'],
setup: (props: Prop, { emit, attrs }: SetupContext) => {
const data: SplitInputType = reactive({
index: null,
values: [],
});
const { inputNumber, modelValue } = toRefs(props);
const { inputNumber, modelValue, placeholders, placeholder } =
toRefs<Prop>(props);
const input: Ref<HTMLInputElement[]> = ref<HTMLInputElement[]>([]);
Expand All @@ -83,16 +101,27 @@
() => input.value?.[data.index + 1],
);
const currentInput: ComputedRef<HTMLInputElement> = computed(
() => input.value?.[data.index],
);
const previousInput: ComputedRef<HTMLInputElement> = computed(
() => input.value?.[data.index - 1],
);
const currentPlaceholder: ComputedRef<string> = computed(
() =>
(isRef(placeholders) && unref(placeholders)?.[data.index]) ||
unref(placeholder),
);
const computedListeners = {
...attrs,
blur: (): any => (data.index = null),
change: (): void => emit('update:modelValue', joinedValues.value),
focus: (event: FocusEvent): void => {
data.index = [...input.value].indexOf(event.target as HTMLInputElement);
nextTick(() => emit('focus', event));
},
input: (event: InputEvent): void => {
if (event.inputType === 'insertText') {
Expand All @@ -103,24 +132,29 @@
keydown: (event: any): void => {
const cursorPosition = Number(event.target.dataset.index);
const currentValue = data.values[cursorPosition];
switch (event?.code) {
switch (event?.code || event?.key || event?.which || event?.keyCode) {
case 'ArrowDown':
case 40:
navigate(lastInput.value);
break;
case 'ArrowLeft':
case 37:
if (cursorPosition === 0 || !currentValue) {
navigate(previousInput.value);
}
break;
case 'ArrowRight':
case 39:
if (cursorPosition === 1 || !currentValue) {
navigate(nextInput.value);
}
break;
case 'ArrowUp':
case 38:
navigate(firstInput.value);
break;
case 'Backspace':
case 8:
if (cursorPosition !== 0) {
data.values[cursorPosition] = '';
navigate(previousInput.value);
Expand Down Expand Up @@ -171,11 +205,26 @@
}
};
const clearAllInput = (): void => {
data.values = [];
nextTick(() => emit('update:modelValue', joinedValues.value));
};
return {
...toRefs(data),
input,
computedListeners,
currentPlaceholder,
currentInput,
clearAllInput,
};
},
});
</script>

<style scoped>
:disabled {
pointer-events: none;
opacity: 0.5;
}
</style>
5 changes: 5 additions & 0 deletions examples/split-input-example/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
.DS_Store
dist
dist-ssr
*.local
3 changes: 3 additions & 0 deletions examples/split-input-example/.vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"recommendations": ["johnsoncodehk.volar"]
}
11 changes: 11 additions & 0 deletions examples/split-input-example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Vue 3 + Typescript + Vite

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.

## Recommended IDE Setup

- [VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=johnsoncodehk.volar)

## Type Support For `.vue` Imports in TS

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.
16 changes: 16 additions & 0 deletions examples/split-input-example/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>

<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>

</html>
23 changes: 23 additions & 0 deletions examples/split-input-example/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "split-input-example",
"version": "0.9.35",
"scripts": {
"dev": "vite --host",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview"
},
"dependencies": {
"vue": "^3.2.25",
"vue-split-input": "^0.9.35"
},
"devDependencies": {
"@vitejs/plugin-vue": "^2.0.0",
"autoprefixer": "^10.4.2",
"postcss": "^8.4.6",
"sass": "^1.49.7",
"tailwindcss": "^3.0.18",
"typescript": "^4.5.5",
"vite": "^2.7.13",
"vue-tsc": "^0.29.8"
}
}
6 changes: 6 additions & 0 deletions examples/split-input-example/postcss.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
Binary file added examples/split-input-example/public/favicon.ico
Binary file not shown.
37 changes: 37 additions & 0 deletions examples/split-input-example/src/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script setup lang="ts">
import { ref } from 'vue';
import type { Ref, ComponentPublicInstance } from 'vue';
import type { Prop } from 'vue-split-input';
const model: Ref<string> = ref('');
const focus = (event: any) => console.log(event);
const splitInputRef = ref<ComponentPublicInstance<Prop> | null>(null);
const clear = () => splitInputRef.value?.clearAllInput();
</script>

<template>
<div class="flex justify-center">
<div class="flex gap-1">
<split-input
ref="splitInputRef"
v-model="model"
:disabled="false"
class-name="w-10 h-14 bg-gray-200 text-black font-bold text-2xl text-center border-b-2 focus:select-all focus:outline-none focus:border-red-500 border-white/50"
:input-number="6"
placeholder="*"
:placeholders="['-', '-', '-']"
@focus="focus"
/>
</div>
<button
type="button"
@click="clear"
class="px-6 bg-blue-500 text-white text-xs ml-2"
>
CLEAR ALL
</button>
</div>
</template>
3 changes: 3 additions & 0 deletions examples/split-input-example/src/assets/css/app.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
Binary file added examples/split-input-example/src/assets/logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions examples/split-input-example/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference types="vite/client" />

declare module '*.vue' {
import { DefineComponent } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types
const component: DefineComponent<{}, {}, any>
export default component
}
6 changes: 6 additions & 0 deletions examples/split-input-example/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { createApp } from 'vue';
import App from './App.vue';
import SplitInput from 'vue-split-input';
import './assets/css/app.scss';

createApp(App).use(SplitInput).mount('#app');
7 changes: 7 additions & 0 deletions examples/split-input-example/tailwind.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module.exports = {
content: ['./src/**/*.{vue,html,js}'],
theme: {
extend: {},
},
plugins: [],
};
15 changes: 15 additions & 0 deletions examples/split-input-example/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
7 changes: 7 additions & 0 deletions examples/split-input-example/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';

// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue()],
});
Loading

0 comments on commit da066c7

Please sign in to comment.