mirror of
https://github.com/tenrok/maska.git
synced 2026-06-11 18:02:27 +03:00
feat!: rework for v3
- new directive format: pass options as value, bound as argument with modifiers - update and checkValue methods in MaskInput
This commit is contained in:
+34
-30
@@ -1,50 +1,54 @@
|
|||||||
import { Directive } from 'vue'
|
import { Directive, DirectiveBinding } from 'vue'
|
||||||
import { MaskaDetail, MaskInput, MaskInputOptions } from './mask-input'
|
import { MaskaDetail, MaskInput, MaskInputOptions } from './mask-input'
|
||||||
|
|
||||||
type MaskaDirective = Directive<HTMLElement, MaskaDetail | undefined>
|
type MaskaDirective = Directive<HTMLElement, MaskInputOptions | undefined>
|
||||||
|
|
||||||
const masks = new WeakMap<HTMLInputElement, MaskInput>()
|
const masks = new WeakMap<HTMLInputElement, MaskInput>()
|
||||||
|
|
||||||
const checkValue = (input: HTMLInputElement): void => {
|
// hacky way to update binding.arg without using defineExposed
|
||||||
setTimeout(() => {
|
const setArg = (binding: DirectiveBinding, value: string | boolean) => {
|
||||||
if (masks.get(input)?.needUpdateValue(input) === true) {
|
if (!binding.arg || !binding.instance) return
|
||||||
input.dispatchEvent(new CustomEvent('input'))
|
|
||||||
}
|
const inst = binding.instance as any
|
||||||
})
|
if (binding.arg in inst) {
|
||||||
|
inst[binding.arg] = value // options api
|
||||||
|
} else if (inst.$?.setupState && binding.arg in inst.$.setupState) {
|
||||||
|
inst.$.setupState[binding.arg] = value // composition api
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const vMaska: MaskaDirective = (el, binding) => {
|
export const vMaska: MaskaDirective = (el, binding) => {
|
||||||
const input = el instanceof HTMLInputElement ? el : el.querySelector('input')
|
const input = el instanceof HTMLInputElement ? el : el.querySelector('input')
|
||||||
const opts = { ...(binding.arg as MaskInputOptions) } ?? {}
|
const opts = { ...binding.value } ?? {}
|
||||||
|
|
||||||
if (input == null || input?.type === 'file') return
|
if (input == null || input?.type === 'file') return
|
||||||
|
|
||||||
checkValue(input)
|
if (binding.arg) {
|
||||||
|
const updateArg = (detail: MaskaDetail) => {
|
||||||
const existed = masks.get(input)
|
const value = binding.modifiers.unmasked
|
||||||
if (existed != null) {
|
? detail.unmasked
|
||||||
if (!existed.needUpdateOptions(input, opts)) {
|
: binding.modifiers.completed
|
||||||
return
|
? detail.completed
|
||||||
}
|
: detail.masked
|
||||||
|
setArg(binding, value)
|
||||||
existed.destroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (binding.value != null) {
|
|
||||||
const bound = binding.value
|
|
||||||
const onMaska = (detail: MaskaDetail): void => {
|
|
||||||
bound.masked = detail.masked
|
|
||||||
bound.unmasked = detail.unmasked
|
|
||||||
bound.completed = detail.completed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
opts.onMaska =
|
opts.onMaska =
|
||||||
opts.onMaska == null
|
opts.onMaska == null
|
||||||
? onMaska
|
? updateArg
|
||||||
: Array.isArray(opts.onMaska)
|
: Array.isArray(opts.onMaska)
|
||||||
? [...opts.onMaska, onMaska]
|
? [...opts.onMaska, updateArg]
|
||||||
: [opts.onMaska, onMaska]
|
: [opts.onMaska, updateArg]
|
||||||
}
|
}
|
||||||
|
|
||||||
masks.set(input, new MaskInput(input, opts))
|
let mask = masks.get(input)
|
||||||
|
if (!mask) {
|
||||||
|
mask = new MaskInput(input, opts)
|
||||||
|
masks.set(input, mask)
|
||||||
|
} else {
|
||||||
|
mask.update(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delay init to wait for v-model value
|
||||||
|
setTimeout(() => mask?.checkValue(input))
|
||||||
}
|
}
|
||||||
|
|||||||
+74
-87
@@ -2,6 +2,7 @@ import { Mask, MaskOptions } from './mask'
|
|||||||
import { parseInput } from './parser'
|
import { parseInput } from './parser'
|
||||||
|
|
||||||
type OnMaskaType = (detail: MaskaDetail) => void
|
type OnMaskaType = (detail: MaskaDetail) => void
|
||||||
|
type MaskaTarget = string | NodeListOf<HTMLInputElement> | HTMLInputElement
|
||||||
|
|
||||||
export interface MaskInputOptions extends MaskOptions {
|
export interface MaskInputOptions extends MaskOptions {
|
||||||
onMaska?: OnMaskaType | OnMaskaType[]
|
onMaska?: OnMaskaType | OnMaskaType[]
|
||||||
@@ -18,24 +19,21 @@ export interface MaskaDetail {
|
|||||||
export class MaskInput {
|
export class MaskInput {
|
||||||
readonly items = new Map<HTMLInputElement, Mask>()
|
readonly items = new Map<HTMLInputElement, Mask>()
|
||||||
|
|
||||||
constructor (
|
constructor(target: MaskaTarget, readonly options: MaskInputOptions = {}) {
|
||||||
target: string | NodeListOf<HTMLInputElement> | HTMLInputElement,
|
this.init(this.getInputs(target), this.getOptions(options))
|
||||||
readonly options: MaskInputOptions = {}
|
}
|
||||||
) {
|
|
||||||
if (typeof target === 'string') {
|
update(options: MaskInputOptions = {}): void {
|
||||||
this.init(
|
this.init(Array.from(this.items.keys()), this.getOptions(options))
|
||||||
Array.from(document.querySelectorAll(target)),
|
}
|
||||||
this.getMaskOpts(options)
|
|
||||||
)
|
checkValue(input: HTMLInputElement) {
|
||||||
} else {
|
if (input.value && input.value !== this.process(input).masked) {
|
||||||
this.init(
|
this.setMaskedValue(input, input.value)
|
||||||
'length' in target ? Array.from(target) : [target],
|
|
||||||
this.getMaskOpts(options)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy (): void {
|
destroy(): void {
|
||||||
for (const input of this.items.keys()) {
|
for (const input of this.items.keys()) {
|
||||||
input.removeEventListener('input', this.inputEvent)
|
input.removeEventListener('input', this.inputEvent)
|
||||||
input.removeEventListener('beforeinput', this.beforeinputEvent)
|
input.removeEventListener('beforeinput', this.beforeinputEvent)
|
||||||
@@ -43,50 +41,40 @@ export class MaskInput {
|
|||||||
this.items.clear()
|
this.items.clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
needUpdateOptions (input: HTMLInputElement, opts: MaskInputOptions): boolean {
|
private init(inputs: HTMLInputElement[], defaults: MaskOptions): void {
|
||||||
const mask = this.items.get(input) as Mask
|
for (const input of inputs) {
|
||||||
const maskNew = new Mask(parseInput(input, this.getMaskOpts(opts)))
|
const inited = this.items.has(input)
|
||||||
|
|
||||||
return JSON.stringify(mask.opts) !== JSON.stringify(maskNew.opts)
|
this.items.set(input, new Mask(parseInput(input, defaults)))
|
||||||
|
|
||||||
|
if (!inited) {
|
||||||
|
input.addEventListener('input', this.inputEvent)
|
||||||
|
input.addEventListener('beforeinput', this.beforeinputEvent)
|
||||||
|
this.checkValue(input)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
needUpdateValue (input: HTMLInputElement): boolean {
|
private getInputs(target: MaskaTarget): HTMLInputElement[] {
|
||||||
const value = input.dataset.maskaValue
|
if (typeof target === 'string') {
|
||||||
|
return Array.from(document.querySelectorAll(target))
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return 'length' in target ? Array.from(target) : [target]
|
||||||
(value == null && input.value !== '') ||
|
|
||||||
(value != null && value !== input.value)
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private getMaskOpts (options: MaskInputOptions): MaskOptions {
|
private getOptions(options: MaskInputOptions): MaskOptions {
|
||||||
const { onMaska, preProcess, postProcess, ...opts } = options
|
const { onMaska, preProcess, postProcess, ...opts } = options
|
||||||
|
|
||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
private init (inputs: HTMLInputElement[], defaults: MaskOptions): void {
|
private readonly beforeinputEvent = (e: InputEvent): void => {
|
||||||
for (const input of inputs) {
|
|
||||||
const mask = new Mask(parseInput(input, defaults))
|
|
||||||
this.items.set(input, mask)
|
|
||||||
|
|
||||||
if (input.value !== '') {
|
|
||||||
this.setMaskedValue(input, input.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
input.addEventListener('input', this.inputEvent)
|
|
||||||
input.addEventListener('beforeinput', this.beforeinputEvent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly beforeinputEvent = (e: Event | InputEvent): void => {
|
|
||||||
const input = e.target as HTMLInputElement
|
const input = e.target as HTMLInputElement
|
||||||
const mask = this.items.get(input) as Mask
|
const mask = this.items.get(input) as Mask
|
||||||
|
|
||||||
// delete first character in eager mask when it's the only left
|
|
||||||
if (
|
if (
|
||||||
mask.isEager() &&
|
mask.isEager() &&
|
||||||
'inputType' in e &&
|
|
||||||
e.inputType.startsWith('delete') &&
|
e.inputType.startsWith('delete') &&
|
||||||
mask.unmasked(input.value).length <= 1
|
mask.unmasked(input.value).length <= 1
|
||||||
) {
|
) {
|
||||||
@@ -95,71 +83,50 @@ export class MaskInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private readonly inputEvent = (e: Event | InputEvent): void => {
|
private readonly inputEvent = (e: Event | InputEvent): void => {
|
||||||
if (
|
if (e instanceof CustomEvent && e.type === 'input') {
|
||||||
e instanceof CustomEvent &&
|
|
||||||
e.type === 'input' &&
|
|
||||||
e.detail != null &&
|
|
||||||
typeof e.detail === 'object' &&
|
|
||||||
'masked' in e.detail
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const input = e.target as HTMLInputElement
|
const input = e.target as HTMLInputElement
|
||||||
const mask = this.items.get(input) as Mask
|
const mask = this.items.get(input) as Mask
|
||||||
const valueOld = input.value
|
const selection = input.selectionStart
|
||||||
const ss = input.selectionStart
|
let value = input.value
|
||||||
const se = input.selectionEnd
|
|
||||||
let value = valueOld
|
|
||||||
|
|
||||||
if (mask.isEager()) {
|
if (mask.isEager()) {
|
||||||
const masked = mask.masked(valueOld)
|
const masked = mask.masked(value)
|
||||||
const unmasked = mask.unmasked(valueOld)
|
const unmasked = mask.unmasked(value)
|
||||||
|
const unmaskedMasked = mask.unmasked(masked)
|
||||||
|
|
||||||
if (unmasked === '' && 'data' in e && e.data != null) {
|
if (unmasked === '' && 'data' in e && e.data != null) {
|
||||||
// empty state and something like `space` pressed
|
// empty state and something like `space` pressed
|
||||||
value = e.data
|
value = e.data
|
||||||
} else if (unmasked !== mask.unmasked(masked)) {
|
} else if (unmasked !== unmaskedMasked) {
|
||||||
value = unmasked
|
value = unmasked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setMaskedValue(input, value)
|
this.setMaskedValue(input, value)
|
||||||
|
this.updateCursor(e, selection, value)
|
||||||
|
}
|
||||||
|
|
||||||
// set caret position
|
private updateCursor(e: Event | InputEvent, s: number | null, value: string) {
|
||||||
if ('inputType' in e) {
|
if (!('inputType' in e) || s === null) return
|
||||||
if (
|
|
||||||
e.inputType.startsWith('delete') ||
|
const input = e.target as HTMLInputElement
|
||||||
(ss != null && ss < valueOld.length)
|
|
||||||
) {
|
if (e.inputType.startsWith('delete') || (s != null && s < value.length)) {
|
||||||
try {
|
try {
|
||||||
// see https://github.com/beholdr/maska/issues/118
|
input.setSelectionRange(s, s)
|
||||||
input.setSelectionRange(ss, se)
|
} catch {
|
||||||
} catch {}
|
// see https://github.com/beholdr/maska/issues/118
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private setMaskedValue (input: HTMLInputElement, value: string): void {
|
private setMaskedValue(input: HTMLInputElement, value: string): void {
|
||||||
const mask = this.items.get(input) as Mask
|
const detail = this.process(input, value)
|
||||||
|
|
||||||
if (this.options.preProcess != null) {
|
input.value = detail.masked
|
||||||
value = this.options.preProcess(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
const masked = mask.masked(value)
|
|
||||||
const unmasked = mask.unmasked(mask.isEager() ? masked : value)
|
|
||||||
const completed = mask.completed(value)
|
|
||||||
const detail = { masked, unmasked, completed }
|
|
||||||
|
|
||||||
value = masked
|
|
||||||
|
|
||||||
if (this.options.postProcess != null) {
|
|
||||||
value = this.options.postProcess(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
input.value = value
|
|
||||||
input.dataset.maskaValue = value
|
|
||||||
|
|
||||||
if (this.options.onMaska != null) {
|
if (this.options.onMaska != null) {
|
||||||
if (Array.isArray(this.options.onMaska)) {
|
if (Array.isArray(this.options.onMaska)) {
|
||||||
@@ -168,7 +135,27 @@ export class MaskInput {
|
|||||||
this.options.onMaska(detail)
|
this.options.onMaska(detail)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input.dispatchEvent(new CustomEvent<MaskaDetail>('maska', { detail }))
|
input.dispatchEvent(new CustomEvent<MaskaDetail>('maska', { detail }))
|
||||||
input.dispatchEvent(new CustomEvent<MaskaDetail>('input', { detail }))
|
input.dispatchEvent(new CustomEvent('input', { detail: detail.masked }))
|
||||||
|
}
|
||||||
|
|
||||||
|
private process(input: HTMLInputElement, value?: string): MaskaDetail {
|
||||||
|
const mask = this.items.get(input) as Mask
|
||||||
|
let valueNew = value ?? input.value
|
||||||
|
|
||||||
|
if (this.options.preProcess != null) {
|
||||||
|
valueNew = this.options.preProcess(valueNew)
|
||||||
|
}
|
||||||
|
|
||||||
|
let masked = mask.masked(valueNew)
|
||||||
|
const unmasked = mask.unmasked(mask.isEager() ? masked : valueNew)
|
||||||
|
const completed = mask.completed(valueNew)
|
||||||
|
|
||||||
|
if (this.options.postProcess != null) {
|
||||||
|
masked = this.options.postProcess(masked)
|
||||||
|
}
|
||||||
|
|
||||||
|
return { masked, unmasked, completed }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { vMaska } from '../../src'
|
||||||
|
|
||||||
|
const bound = ref(false)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<input v-maska:bound.completed data-maska="#-#-#" />
|
||||||
|
<div v-if="bound === true">Completed</div>
|
||||||
|
<div v-else>Uncompleted</div>
|
||||||
|
</template>
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive } from 'vue'
|
|
||||||
import { MaskaDetail, vMaska } from '../../src'
|
|
||||||
|
|
||||||
const bound = reactive<Partial<MaskaDetail>>({})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<input v-maska="bound" data-maska="#-#" value="123" />
|
|
||||||
<div>{{ bound.masked }}</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { MaskaDetail, vMaska } from '../../src'
|
import { vMaska } from '../../src'
|
||||||
|
|
||||||
const bound = reactive<Partial<MaskaDetail>>({})
|
const bound = ref('')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input v-maska="bound" data-maska="#-#" />
|
<input v-maska:bound.masked data-maska="#-#" />
|
||||||
<div>{{ bound.masked }}</div>
|
<div>{{ bound }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { MaskaDetail, vMaska } from '../../src'
|
import { vMaska } from '../../src'
|
||||||
|
|
||||||
const bound = reactive<Partial<MaskaDetail>>({})
|
const bound = ref('')
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input v-maska="bound" data-maska="#-#" />
|
<input v-maska:bound.unmasked data-maska="#-#" />
|
||||||
<div>{{ bound.unmasked }}</div>
|
<div>{{ bound }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,24 +1,20 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue';
|
import { MaskInputOptions, vMaska } from '../../src'
|
||||||
import { MaskaDetail, vMaska } from '../../src'
|
|
||||||
|
|
||||||
const emit = defineEmits(['mask1', 'mask2', 'mask3'])
|
const emit = defineEmits(['mask1', 'mask2', 'mask3'])
|
||||||
|
|
||||||
const bound1 = reactive({})
|
const options1 = <MaskInputOptions>{
|
||||||
const bound2 = reactive({})
|
onMaska: (detail) => emit('mask1', detail)
|
||||||
|
|
||||||
const options1 = {
|
|
||||||
onMaska: (detail: MaskaDetail) => emit('mask1', detail)
|
|
||||||
}
|
}
|
||||||
const options2 = {
|
const options2 = <MaskInputOptions>{
|
||||||
onMaska: [
|
onMaska: [
|
||||||
(detail: MaskaDetail) => emit('mask2', detail),
|
(detail) => emit('mask2', detail),
|
||||||
(detail: MaskaDetail) => emit('mask3', detail),
|
(detail) => emit('mask3', detail),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input id="input1" v-maska:[options1]="bound1" data-maska="#-#" />
|
<input id="input1" v-maska="options1" data-maska="#-#" />
|
||||||
<input id="input2" v-maska:[options2]="bound2" data-maska="#-#" />
|
<input id="input2" v-maska="options2" data-maska="#-#" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { reactive } from 'vue'
|
|
||||||
import { MaskaDetail, vMaska } from '../../src'
|
|
||||||
|
|
||||||
const bound = reactive<Partial<MaskaDetail>>({})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<input v-maska="bound" data-maska="#-#-#" />
|
|
||||||
<div v-if="bound.completed">Completed</div>
|
|
||||||
<div v-else>Uncompleted</div>
|
|
||||||
</template>
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { vMaska, MaskaDetail, MaskInputOptions } from '../../src'
|
import { MaskInputOptions, vMaska } from '../../src'
|
||||||
|
|
||||||
const bound = reactive<Partial<MaskaDetail>>({})
|
const bound = ref('')
|
||||||
const config = reactive<MaskInputOptions>({
|
const config = <MaskInputOptions>{
|
||||||
mask: 'A A',
|
mask: 'A A',
|
||||||
tokens: {
|
tokens: {
|
||||||
A: {
|
A: {
|
||||||
@@ -12,10 +12,10 @@ const config = reactive<MaskInputOptions>({
|
|||||||
transform: (chr) => chr.toUpperCase()
|
transform: (chr) => chr.toUpperCase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input v-maska:[config]="bound" />
|
<input v-maska:bound="config" />
|
||||||
<div>{{ bound.masked }}</div>
|
<div>{{ bound }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { reactive } from 'vue'
|
|
||||||
import { MaskInputOptions, vMaska } from '../../src'
|
import { MaskInputOptions, vMaska } from '../../src'
|
||||||
|
|
||||||
const config = reactive<MaskInputOptions>({
|
const config = <MaskInputOptions>{
|
||||||
preProcess: (val) => val.toUpperCase()
|
preProcess: (val) => val.toUpperCase()
|
||||||
})
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input v-maska:[config] data-maska="A A" data-maska-tokens="A:[A-Z]:multiple" />
|
<input v-maska="config" data-maska="A A" data-maska-tokens="A:[A-Z]:multiple" />
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue'
|
||||||
|
import { vMaska } from '../../src'
|
||||||
|
|
||||||
|
const initial = ref('345')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<input v-maska data-maska="#-#" id="input1" value="123" />
|
||||||
|
<input v-maska data-maska="#-#" id="input2" v-model="initial" />
|
||||||
|
</template>
|
||||||
@@ -27,7 +27,7 @@ const onMaska2 = () => {
|
|||||||
<input id="checkbox" type="checkbox" v-model="isEager" />
|
<input id="checkbox" type="checkbox" v-model="isEager" />
|
||||||
<input
|
<input
|
||||||
id="input1"
|
id="input1"
|
||||||
v-maska:[options]
|
v-maska="options"
|
||||||
data-maska="#-#"
|
data-maska="#-#"
|
||||||
v-model="value1"
|
v-model="value1"
|
||||||
@maska="onMaska1"
|
@maska="onMaska1"
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import { vMaska } from '../../src'
|
|||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
bound: {
|
bound: ''
|
||||||
masked: ''
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
@@ -16,6 +14,6 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<input v-maska="bound" data-maska="#-#" />
|
<input v-maska:bound data-maska="#-#" />
|
||||||
<div>{{ bound.masked }}</div>
|
<div>{{ bound }}</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+13
-8
@@ -2,18 +2,18 @@ import { nextTick } from 'vue'
|
|||||||
import { expect, test } from 'vitest'
|
import { expect, test } from 'vitest'
|
||||||
import { mount } from '@vue/test-utils'
|
import { mount } from '@vue/test-utils'
|
||||||
|
|
||||||
import BindInitial from './components/BindInitial.vue'
|
import BindCompleted from './components/BindCompleted.vue'
|
||||||
import BindMasked from './components/BindMasked.vue'
|
import BindMasked from './components/BindMasked.vue'
|
||||||
import BindUnmasked from './components/BindUnmasked.vue'
|
import BindUnmasked from './components/BindUnmasked.vue'
|
||||||
import Callbacks from './components/Callbacks.vue'
|
import Callbacks from './components/Callbacks.vue'
|
||||||
import ChangeValue from './components/ChangeValue.vue'
|
import ChangeValue from './components/ChangeValue.vue'
|
||||||
import Completed from './components/Completed.vue'
|
|
||||||
import Config from './components/Config.vue'
|
import Config from './components/Config.vue'
|
||||||
import Custom from './components/Custom.vue'
|
import Custom from './components/Custom.vue'
|
||||||
import DataAttr from './components/DataAttr.vue'
|
import DataAttr from './components/DataAttr.vue'
|
||||||
import Dynamic from './components/Dynamic.vue'
|
import Dynamic from './components/Dynamic.vue'
|
||||||
import Events from './components/Events.vue'
|
import Events from './components/Events.vue'
|
||||||
import Hooks from './components/Hooks.vue'
|
import Hooks from './components/Hooks.vue'
|
||||||
|
import Initial from './components/Initial.vue'
|
||||||
import Model from './components/Model.vue'
|
import Model from './components/Model.vue'
|
||||||
import Multiple from './components/Multiple.vue'
|
import Multiple from './components/Multiple.vue'
|
||||||
import Options from './components/Options.vue'
|
import Options from './components/Options.vue'
|
||||||
@@ -63,13 +63,14 @@ test('dynamic mask', async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('initial value', async () => {
|
test('initial value', async () => {
|
||||||
const wrapper = mount(BindInitial)
|
const wrapper = mount(Initial)
|
||||||
const input = wrapper.get('input')
|
const input1 = wrapper.get<HTMLInputElement>('#input1')
|
||||||
|
const input2 = wrapper.get<HTMLInputElement>('#input2')
|
||||||
|
|
||||||
await nextTick()
|
await new Promise((r) => setTimeout(r))
|
||||||
|
|
||||||
expect(input.element.value).toBe('1-2')
|
expect(input1.element.value).toBe('1-2')
|
||||||
expect(wrapper.get('div').element.textContent).toBe('1-2')
|
expect(input2.element.value).toBe('3-4')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('bind masked', async () => {
|
test('bind masked', async () => {
|
||||||
@@ -77,6 +78,7 @@ test('bind masked', async () => {
|
|||||||
const input = wrapper.get('input')
|
const input = wrapper.get('input')
|
||||||
|
|
||||||
await input.setValue('123')
|
await input.setValue('123')
|
||||||
|
|
||||||
expect(input.element.value).toBe('1-2')
|
expect(input.element.value).toBe('1-2')
|
||||||
expect(wrapper.get('div').element.textContent).toBe('1-2')
|
expect(wrapper.get('div').element.textContent).toBe('1-2')
|
||||||
})
|
})
|
||||||
@@ -86,12 +88,13 @@ test('bind unmasked', async () => {
|
|||||||
const input = wrapper.get('input')
|
const input = wrapper.get('input')
|
||||||
|
|
||||||
await input.setValue('123')
|
await input.setValue('123')
|
||||||
|
|
||||||
expect(input.element.value).toBe('1-2')
|
expect(input.element.value).toBe('1-2')
|
||||||
expect(wrapper.get('div').element.textContent).toBe('12')
|
expect(wrapper.get('div').element.textContent).toBe('12')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('bind completed', async () => {
|
test('bind completed', async () => {
|
||||||
const wrapper = mount(Completed)
|
const wrapper = mount(BindCompleted)
|
||||||
const input = wrapper.get('input')
|
const input = wrapper.get('input')
|
||||||
|
|
||||||
await input.setValue('12')
|
await input.setValue('12')
|
||||||
@@ -179,6 +182,8 @@ test('multiple inputs', async () => {
|
|||||||
await checkbox.setValue()
|
await checkbox.setValue()
|
||||||
expect(checkbox.element).toBeChecked()
|
expect(checkbox.element).toBeChecked()
|
||||||
|
|
||||||
|
await new Promise((r) => setTimeout(r))
|
||||||
|
|
||||||
expect(input.element.value).toBe('1-')
|
expect(input.element.value).toBe('1-')
|
||||||
expect(wrapper.emitted('mask1')).toHaveLength(3)
|
expect(wrapper.emitted('mask1')).toHaveLength(3)
|
||||||
expect(wrapper.emitted('mask2')).toHaveLength(1)
|
expect(wrapper.emitted('mask2')).toHaveLength(1)
|
||||||
|
|||||||
+12
-12
@@ -176,7 +176,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledOnce()
|
expect(context.onMaska).toHaveBeenCalledOnce()
|
||||||
expect(context.onMaska).toHaveBeenCalledWith({
|
expect(context.onMaska).toHaveBeenCalledWith({
|
||||||
completed: false,
|
completed: false,
|
||||||
masked: '1',
|
masked: '$1',
|
||||||
unmasked: '1'
|
unmasked: '1'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -191,7 +191,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(3)
|
expect(context.onMaska).toHaveBeenCalledTimes(3)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: false,
|
completed: false,
|
||||||
masked: '123',
|
masked: '$123',
|
||||||
unmasked: '123'
|
unmasked: '123'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -206,7 +206,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(4)
|
expect(context.onMaska).toHaveBeenCalledTimes(4)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234',
|
masked: '$1,234',
|
||||||
unmasked: '1234'
|
unmasked: '1234'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -221,7 +221,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(7)
|
expect(context.onMaska).toHaveBeenCalledTimes(7)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234567',
|
masked: '$1,234,567',
|
||||||
unmasked: '1234567'
|
unmasked: '1234567'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -236,7 +236,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(5)
|
expect(context.onMaska).toHaveBeenCalledTimes(5)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '123.4',
|
masked: '$123.4',
|
||||||
unmasked: '1234'
|
unmasked: '1234'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -251,7 +251,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(6)
|
expect(context.onMaska).toHaveBeenCalledTimes(6)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '123.45',
|
masked: '$123.45',
|
||||||
unmasked: '12345'
|
unmasked: '12345'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -266,7 +266,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(7)
|
expect(context.onMaska).toHaveBeenCalledTimes(7)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '123.45',
|
masked: '$123.45',
|
||||||
unmasked: '12345'
|
unmasked: '12345'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -281,7 +281,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(8)
|
expect(context.onMaska).toHaveBeenCalledTimes(8)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234.56',
|
masked: '$1,234.56',
|
||||||
unmasked: '123456'
|
unmasked: '123456'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -296,7 +296,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(8)
|
expect(context.onMaska).toHaveBeenCalledTimes(8)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234.56',
|
masked: '$1,234.56',
|
||||||
unmasked: '123456'
|
unmasked: '123456'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -311,7 +311,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(8)
|
expect(context.onMaska).toHaveBeenCalledTimes(8)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234.5',
|
masked: '$1,234.5',
|
||||||
unmasked: '12345'
|
unmasked: '12345'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -326,7 +326,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(9)
|
expect(context.onMaska).toHaveBeenCalledTimes(9)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234.',
|
masked: '$1,234.',
|
||||||
unmasked: '1234'
|
unmasked: '1234'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -341,7 +341,7 @@ describe('test hooks', () => {
|
|||||||
expect(context.onMaska).toHaveBeenCalledTimes(10)
|
expect(context.onMaska).toHaveBeenCalledTimes(10)
|
||||||
expect(context.onMaska).toHaveBeenLastCalledWith({
|
expect(context.onMaska).toHaveBeenLastCalledWith({
|
||||||
completed: true,
|
completed: true,
|
||||||
masked: '1234',
|
masked: '$1,234',
|
||||||
unmasked: '1234'
|
unmasked: '1234'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user