Skip to content

Commit

Permalink
type inference for update options
Browse files Browse the repository at this point in the history
  • Loading branch information
uNmAnNeR committed Jun 23, 2023
1 parent 6b8ff46 commit fedec15
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 12 deletions.
4 changes: 2 additions & 2 deletions packages/angular-imask/src/imask.directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { type InputMask, type InputMaskElement, type FactoryArg, type NormalizedOpts } from 'imask';
import { type InputMask, type InputMaskElement, type FactoryArg, type UpdateOpts } from 'imask';
import { isPlatformBrowser } from '@angular/common';
import {
Directive, ElementRef, Input, Output, forwardRef, Provider, Renderer2,
Expand Down Expand Up @@ -97,7 +97,7 @@ export class IMaskDirective<
if (!changes['imask'] || !this._viewInitialized) return;

if (this.imask) {
if (this.maskRef) this.maskRef.updateOptions(this.imask as Partial<NormalizedOpts<Opts>>);
if (this.maskRef) this.maskRef.updateOptions(this.imask as UpdateOpts<Opts>);
else {
this.initMask();
this.onChange(this.maskValue);
Expand Down
6 changes: 3 additions & 3 deletions packages/imask/src/controls/input.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { objectIncludes, DIRECTION, type Selection } from '../core/utils';
import ActionDetails from '../core/action-details';
import createMask, { type NormalizedOpts, maskedClass, type FactoryArg, type FactoryReturnMasked } from '../masked/factory';
import createMask, { type UpdateOpts, maskedClass, type FactoryArg, type FactoryReturnMasked } from '../masked/factory';
import Masked from '../masked/base';
import MaskElement from './mask-element';
import HTMLInputMaskElement, { type InputElement } from './html-input-mask-element';
Expand Down Expand Up @@ -207,14 +207,14 @@ class InputMask<Opts extends FactoryArg> {
}

/** Updates options with deep equal check, recreates {@link Masked} model if mask type changes */
updateOptions(opts: Partial<NormalizedOpts<Opts>>) {
updateOptions(opts: UpdateOpts<Opts>) {
const { mask, ...restOpts } = opts;

const updateMask = !this.maskEquals(mask);
const updateOpts = !objectIncludes(this.masked, restOpts);

if (updateMask) this.mask = mask;
if (updateOpts) this.masked.updateOptions(restOpts);
if (updateOpts) this.masked.updateOptions(restOpts); // TODO

if (updateMask || updateOpts) this.updateControl();
}
Expand Down
3 changes: 2 additions & 1 deletion packages/imask/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ export {
type FactoryReturnMasked,
type FactoryStaticOpts,
type FactoryStaticReturnMasked,
type NormalizedOpts
type NormalizedOpts,
type UpdateOpts,
} from './masked/factory';
export { default as MaskedFunction, type MaskedFunctionOptions } from './masked/function';
export { default as MaskedNumber, type MaskedNumberOptions } from './masked/number';
Expand Down
63 changes: 63 additions & 0 deletions packages/imask/src/masked/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,69 @@ type FactoryOpts = FactoryConstructorOpts | FactoryInstanceOpts | FactoryStaticO
export
type FactoryArg = Masked | FactoryOpts | FactoryStaticOpts['mask'];


export
type UpdateStaticOpts<Opts extends FactoryStaticOpts> =
Opts extends MaskedEnumOptions ? MaskedEnumOptions :
Opts extends MaskedRangeOptions ? MaskedRangeOptions :
Opts extends MaskedDynamicOptions ? MaskedDynamicOptions :
Opts extends MaskedPatternOptions ? MaskedPatternOptions :
Opts extends MaskedNumberOptions ? MaskedNumberOptions :
Opts extends MaskedRegExpOptions ? MaskedRegExpOptions :
Opts extends MaskedFunctionOptions ? MaskedFunctionOptions :
Opts extends MaskedDateOptions ? MaskedDateOptions :
never
;

type UpdateAnyOpts = Record<string, any>;

export
type UpdateInstanceOpts<M extends Masked> =
M extends MaskedRegExp ? MaskedRegExpOptions :
M extends MaskedPattern ? MaskedPatternOptions :
M extends MaskedFunction ? MaskedFunctionOptions :
M extends MaskedDate ? MaskedDateOptions :
M extends MaskedNumber ? MaskedNumberOptions :
M extends MaskedDynamic ? MaskedDynamicOptions :
M extends MaskedRange ? MaskedRangeOptions :
M extends MaskedEnum ? MaskedEnumOptions :
UpdateAnyOpts
;

export
type UpdateConstructorOpts<M extends FactoryConstructorOpts> =
M extends { mask: typeof MaskedDate } ? MaskedDateOptions :
M extends { mask: typeof MaskedNumber } ? MaskedNumberOptions :
M extends { mask: typeof MaskedEnum } ? MaskedEnumOptions :
M extends { mask: typeof MaskedRange } ? MaskedRangeOptions :
M extends { mask: typeof MaskedRegExp } ? MaskedRegExpOptions :
M extends { mask: typeof MaskedFunction } ? MaskedFunctionOptions :
M extends { mask: typeof MaskedPattern } ? MaskedPatternOptions :
M extends { mask: typeof MaskedDynamic } ? MaskedDynamicOptions :
UpdateAnyOpts
;

export
type UpdateStaticMaskOpts<M extends FactoryStaticOpts['mask']> =
M extends MaskedDateFactoryOptions['mask'] ? MaskedDateOptions :
M extends MaskedNumberOptions['mask'] ? MaskedNumberOptions :
M extends MaskedPatternOptions['mask'] ? MaskedPatternOptions :
M extends MaskedDynamicOptions['mask'] ? MaskedDynamicOptions :
M extends MaskedRegExpOptions['mask'] ? MaskedRegExpOptions :
M extends MaskedFunctionOptions['mask'] ? MaskedFunctionOptions :
never
;

export
type UpdateOpts<Opts extends FactoryArg> = Partial<
Opts extends Masked ? UpdateInstanceOpts<Opts> :
Opts extends FactoryStaticOpts['mask'] ? UpdateStaticMaskOpts<Opts> :
Opts extends FactoryStaticOpts ? UpdateStaticOpts<Opts> :
Opts extends FactoryInstanceOpts ? UpdateInstanceOpts<Opts['mask']> :
Opts extends FactoryConstructorOpts ? UpdateConstructorOpts<Opts> :
UpdateAnyOpts
>;

export
type FactoryReturnMasked<Opts extends FactoryArg> =
Opts extends Masked ? Opts :
Expand Down
6 changes: 3 additions & 3 deletions packages/svelte-imask/src/action.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import IMask, { type FactoryArg, type InputMask, type NormalizedOpts } from 'imask';
import IMask, { type FactoryArg, type InputMask, type UpdateOpts } from 'imask';


function fireEvent<Opts extends FactoryArg> (el: HTMLElement, eventName: string, data: InputMask<Opts>) {
Expand Down Expand Up @@ -26,11 +26,11 @@ function IMaskAction<Opts extends FactoryArg> (el: HTMLElement, opts: Opts) {
}
}

function update (opts: InputMask<Opts> | Opts | Partial<NormalizedOpts<Opts>>): void {
function update (opts: InputMask<Opts> | Opts | UpdateOpts<Opts>): void {
if (!opts) return destroy();

if (opts instanceof IMask.InputMask) maskRef = opts;
else if (maskRef) maskRef.updateOptions(opts as Partial<NormalizedOpts<Opts>>);
else if (maskRef) maskRef.updateOptions(opts as UpdateOpts<Opts>);
else maskRef = initMask(el, opts as Opts);
}

Expand Down
6 changes: 3 additions & 3 deletions packages/vue-imask/src/directive.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import IMask, { type InputElement, type InputMask, type FactoryArg, type NormalizedOpts } from 'imask';
import IMask, { type InputElement, type InputMask, type FactoryArg, type UpdateOpts } from 'imask';
import { isVue3 } from 'vue-demi';


Expand All @@ -13,10 +13,10 @@ export default {
initMask(el, options);
},

[isVue3 ? 'updated' : 'update']: <Opts extends FactoryArg>(el: DirectiveMaskElement<Opts>, { value: options }: { value: Opts | Partial<NormalizedOpts<Opts>> }) => {
[isVue3 ? 'updated' : 'update']: <Opts extends FactoryArg>(el: DirectiveMaskElement<Opts>, { value: options }: { value: Opts | UpdateOpts<Opts> }) => {
if (options) {
if (el.maskRef) {
el.maskRef.updateOptions(options as Partial<NormalizedOpts<Opts>>);
el.maskRef.updateOptions(options as UpdateOpts<Opts>);
if (el.value !== el.maskRef.value) el.maskRef._onChange();
}
else initMask(el, options as Opts);
Expand Down

0 comments on commit fedec15

Please sign in to comment.