Skip to content

Commit

Permalink
fix #852
Browse files Browse the repository at this point in the history
  • Loading branch information
uNmAnNeR committed Apr 27, 2023
1 parent 27c5774 commit 0556e53
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 22 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"build": "npm run build:core && npm run build:plugins",
"build:core": "rimraf --glob \"packages/imask/{dist,esm}\" && lerna run build --scope=imask",
"build:react": "rimraf --glob \"packages/react-imask/{dist,esm}\" && lerna run build --scope=react-imask",
"build:angular": "rimraf --glob \"packages/angular-imask/dist\" && lerna run build --scope=angular-imask",
"build:plugins": "rimraf --glob \"packages/!(imask)/{dist,esm}\" && lerna run build --ignore=imask",
"test": "lerna run test --parallel",
"make": "npm run test && npm run build",
Expand Down
3 changes: 1 addition & 2 deletions packages/angular-imask/example/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Component } from '@angular/core';
import { IMaskDirective, IMASK_FACTORY } from 'angular-imask';
import { IMASK_FACTORY } from 'angular-imask';
import { NumberIMaskFactory } from './number-imask-factory';

@Component({
selector: 'app-root',
standalone: true,
imports: [IMaskDirective],
providers: [
{provide: IMASK_FACTORY, useClass: NumberIMaskFactory} // it's optional
],
Expand Down
19 changes: 19 additions & 0 deletions packages/angular-imask/example/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { IMaskModule } from 'angular-imask';

import { AppComponent } from './app.component';


@NgModule({
declarations: [
AppComponent
],
imports: [
IMaskModule,
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
2 changes: 1 addition & 1 deletion packages/angular-imask/example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>Example</title>
<title>Angular IMask Example</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
Expand Down
45 changes: 27 additions & 18 deletions packages/angular-imask/src/imask.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
import { NG_VALUE_ACCESSOR, ControlValueAccessor, COMPOSITION_BUFFER_MODE } from '@angular/forms';
import { IMASK_FACTORY } from './imask-factory-token';

export
type Falsy = false | 0 | "" | null | undefined;

export const MASKEDINPUT_VALUE_ACCESSOR: Provider = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => IMaskDirective),
Expand All @@ -27,7 +30,13 @@ export const DEFAULT_IMASK_ELEMENT = (elementRef: any) => elementRef.nativeEleme
},
providers: [MASKEDINPUT_VALUE_ACCESSOR],
})
export class IMaskDirective<Opts extends IMask.AnyMaskedOptions> implements ControlValueAccessor, AfterViewInit, OnDestroy, OnChanges {
export class IMaskDirective<
Opts extends IMask.AnyMaskedOptions,
Unmask extends ('typed' | boolean) = false,
Value = Unmask extends 'typed' ? IMask.InputMask<Opts>['typedValue'] :
Unmask extends Falsy ? IMask.InputMask<Opts>['value'] :
IMask.InputMask<Opts>['unmaskedValue']
> implements ControlValueAccessor, AfterViewInit, OnDestroy, OnChanges {
maskRef?: IMask.InputMask<Opts>;
onTouched: any = () => {};
onChange: any = () => {};
Expand All @@ -43,28 +52,28 @@ export class IMaskDirective<Opts extends IMask.AnyMaskedOptions> implements Cont
private _compositionMode = inject(COMPOSITION_BUFFER_MODE, {optional: true}) ?? !this._isAndroid();

@Input() imask?: Opts;
@Input() unmask?: boolean|'typed';
@Input() unmask?: Unmask;
@Input() imaskElement: (elementRef: ElementRef, directiveRef: any) => IMask.MaskElement = DEFAULT_IMASK_ELEMENT;
@Output() accept = new EventEmitter<void>();
@Output() complete = new EventEmitter<void>();
@Output() accept = new EventEmitter<Value>();
@Output() complete = new EventEmitter<Value>();

get element () {
return this.imaskElement(this._elementRef, this);
}

get maskValue (): any {
if (!this.maskRef) return this.element.value;
get maskValue (): Value {
if (!this.maskRef) return this.element.value as unknown as Value;

if (this.unmask === 'typed') return this.maskRef.typedValue;
if (this.unmask) return this.maskRef.unmaskedValue;
return this.maskRef.value;
if (this.unmask === 'typed') return this.maskRef.typedValue as unknown as Value;
if (this.unmask) return this.maskRef.unmaskedValue as unknown as Value;
return this.maskRef.value as unknown as Value;
}

set maskValue (value: any) {
set maskValue (value: Value) {
if (this.maskRef) {
if (this.unmask === 'typed') this.maskRef.typedValue = value;
else if (this.unmask) this.maskRef.unmaskedValue = value;
else this.maskRef.value = value;
if (this.unmask === 'typed') this.maskRef.typedValue = value as unknown as IMask.MaskedTypedValue<Opts['mask']>;
else if (this.unmask) this.maskRef.unmaskedValue = value as unknown as IMask.InputMask<Opts>['unmaskedValue'];
else this.maskRef.value = value as unknown as IMask.InputMask<Opts>['value'];
} else {
this._renderer.setProperty(this.element, 'value', value);
}
Expand Down Expand Up @@ -105,18 +114,18 @@ export class IMaskDirective<Opts extends IMask.AnyMaskedOptions> implements Cont
this.complete.complete();
}

beginWrite (value: any): void {
beginWrite (value: Value): void {
this._writing = true;
this._writingValue = value;
}

endWrite (): any {
endWrite (): Value {
this._writing = false;
return this._writingValue;
}

writeValue(value: any) {
value = value == null && this.unmask !== 'typed' ? '' : value;
writeValue(value: Value) {
value = (value == null && this.unmask !== 'typed' ? '' : value) as Value;

if (this.maskRef) {
this.beginWrite(value);
Expand All @@ -141,7 +150,7 @@ export class IMaskDirective<Opts extends IMask.AnyMaskedOptions> implements Cont
}

private initMask () {
this.maskRef = this._factory.create(this.element, this.imask as Opts)
this.maskRef = this._factory.create(this.element, this.imask)
.on('accept', this._onAccept.bind(this))
.on('complete', this._onComplete.bind(this));
}
Expand Down
2 changes: 1 addition & 1 deletion packages/react-imask/src/mixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ export default function IMaskMixin<
}

set maskValue (value: Value) {
value = (value == null ? '' : value) as Value;
value = (value == null && this.props.unmask !== 'typed' ? '' : value) as Value;
if (this.props.unmask === 'typed') this.maskRef.typedValue = value as unknown as IMask.MaskedTypedValue<Opts['mask']>;
else if (this.props.unmask) this.maskRef.unmaskedValue = value as unknown as IMask.InputMask<Opts>['unmaskedValue'];
else this.maskRef.value = value as unknown as IMask.InputMask<Opts>['value'];
Expand Down

0 comments on commit 0556e53

Please sign in to comment.