diff --git a/libraries/ui-library/package.json b/libraries/ui-library/package.json index 3b07ed585..12f3dd27f 100644 --- a/libraries/ui-library/package.json +++ b/libraries/ui-library/package.json @@ -36,7 +36,8 @@ }, "dependencies": { "@stencil/core": "^4.12.6", - "@types/resize-observer-browser": "^0.1.5" + "@types/resize-observer-browser": "^0.1.5", + "imask": "^7.6.1" }, "devDependencies": { "@fontsource/noto-sans": "^4.5.11", diff --git a/libraries/ui-library/src/components/six-input/index.html b/libraries/ui-library/src/components/six-input/index.html index 9e8ef7b58..dd221067b 100644 --- a/libraries/ui-library/src/components/six-input/index.html +++ b/libraries/ui-library/src/components/six-input/index.html @@ -334,6 +334,40 @@

Events Disclaimer

}); + +

Masks

+ +

Sometimes inputs need to be masked in order to enforce a certain format.

+

Use the mask attribute to apply a simple mask.

+ + + +

Use the setMask method to apply more complex masks

+ + + + + +

For more info on the format of the mask object passed to setMask() and the mask attribute, take a look at https://imask.js.org/ launch

+ + + warning + When masking a input, it's value will contain any additional characters added by the mask. + diff --git a/libraries/ui-library/src/components/six-input/six-input.tsx b/libraries/ui-library/src/components/six-input/six-input.tsx index 438617025..28ef0ed5f 100644 --- a/libraries/ui-library/src/components/six-input/six-input.tsx +++ b/libraries/ui-library/src/components/six-input/six-input.tsx @@ -4,6 +4,7 @@ import { hasSlot } from '../../utils/slot'; import { EmptyPayload } from '../../utils/types'; import { EventListeners } from '../../utils/event-listeners'; import { submitForm } from '../../utils/form'; +import IMask, { FactoryArg, InputMask } from 'imask'; const ICON_SIZES: Record<'small' | 'medium' | 'large', 'xSmall' | 'small' | 'medium'> = { large: 'medium', @@ -52,6 +53,8 @@ export class SixInput { private errorTextId = `input-error-text-${id}`; private nativeInput?: HTMLInputElement; private eventListeners = new EventListeners(); + private inputMask?: InputMask; + private maskOptions?: FactoryArg; @Element() host!: HTMLSixInputElement; @@ -106,6 +109,9 @@ export class SixInput { /** A pattern to validate input against. */ @Prop({ reflect: true }) pattern?: string; + /** Applies a simple mask to the input element. Use setMask(maskOptions) if more options are needed */ + @Prop({ reflect: true, attribute: 'mask' }) textMask?: string; + /** * Internal: Styles the input for the dropdown filter search. */ @@ -191,6 +197,15 @@ export class SixInput { this.eventListeners.forward('six-input-blur', 'blur', this.host); } + componentDidRender() { + if (this.textMask) { + this.maskOptions = { mask: this.textMask }; + } + if (!this.inputMask && this.maskOptions && this.type === 'text') { + this.inputMask = IMask(this.nativeInput, this.maskOptions); + } + } + componentWillLoad() { this.handleSlotChange(); } @@ -198,6 +213,9 @@ export class SixInput { disconnectedCallback() { this.host.shadowRoot?.removeEventListener('slotchange', this.handleSlotChange); this.eventListeners.removeAll(); + if (this.inputMask) { + this.inputMask.destroy(); + } } /** Sets focus on the input. */ @@ -247,10 +265,16 @@ export class SixInput { } } + /** Applies a mask on the input element. Requires a mask options object as argument, See https://imask.js.org/guide.html#masked for syntax and examples */ + @Method() + async setMask(maskOptions: FactoryArg) { + this.maskOptions = maskOptions; + } + private handleChange = (event: Event) => { event.stopPropagation(); if (this.nativeInput != null) { - this.value = this.nativeInput.value; + this.updateValueWhenHandlingEvent(); this.sixChange.emit(); } }; @@ -258,7 +282,8 @@ export class SixInput { private handleInput = (event: Event) => { event.stopPropagation(); if (this.nativeInput != null) { - this.value = this.nativeInput.value; + this.inputMask?._onInput(event); + this.updateValueWhenHandlingEvent(); this.sixInput.emit(); } }; @@ -275,6 +300,7 @@ export class SixInput { private handleClearClick = (event: MouseEvent) => { this.value = ''; + this.inputMask?.updateValue(); this.sixClear.emit(); this.sixInput.emit(); this.sixChange.emit(); @@ -309,6 +335,14 @@ export class SixInput { return (this.value ?? '').toString(); } + private getDisplayValue(): string { + return this.inputMask ? (this.inputMask.displayValue ?? '').toString() : this.getValue(); + } + + private updateValueWhenHandlingEvent(): void { + this.value = this.inputMask ? this.inputMask.value : this.nativeInput!.value; + } + render() { return (