diff --git a/src/Input.ts b/src/Input.ts index 1ec137a8..a3a1e78c 100644 --- a/src/Input.ts +++ b/src/Input.ts @@ -27,6 +27,7 @@ export type InputOptions = { placeholder?: string; value?: string; maxLength?: number; + secure?: boolean; align?: 'left' | 'center' | 'right'; padding?: Padding; cleanOnFocus?: boolean; @@ -34,6 +35,8 @@ export type InputOptions = { addMask?: boolean; }; +const SECURE_CHARACTER = '*'; + /** * Container-based component that creates an input to read the user's text. * @example @@ -52,6 +55,8 @@ export class Input extends Container { protected _bg?: Container | NineSliceSprite | Graphics; protected inputMask: Container | NineSliceSprite | Graphics; protected _cursor: Sprite; + protected _value: string = ''; + protected _secure: boolean; protected inputField: PixiText; protected placeholder: PixiText; protected editing = false; @@ -109,6 +114,7 @@ export class Input extends Container { this.options = options; this.padding = options.padding; + this._secure = options.secure ?? false; this.cursor = 'text'; this.interactive = true; @@ -287,11 +293,11 @@ export class Input extends Container { } protected _delete(): void { - if (!this.editing || this.value.length === 0) return; - const array = this.value.split(''); + const length = this.value.length; + + if (!this.editing || length === 0) return; - array.pop(); - this.value = array.join(''); + this.value = this.value.substring(0, length - 1); this.onChange.emit(this.value); } @@ -453,9 +459,13 @@ export class Input extends Container { /** Sets the input text. */ set value(text: string) { - this.inputField.text = text; + const textLength = text.length; - if (text.length !== 0) { + this._value = text; + this.inputField.text = this.secure ? SECURE_CHARACTER.repeat(textLength) : text; + + if (textLength !== 0) + { this.placeholder.visible = false; } else { this.placeholder.visible = !this.editing; @@ -466,7 +476,18 @@ export class Input extends Container { /** Return text of the input. */ get value(): string { - return this.inputField.text; + return this._value; + } + + set secure(val: boolean) { + this._secure = val; + + // Update text based on secure state (useful for show/hide password implementations) + this.value = this._value; + } + + get secure(): boolean { + return this._secure; } /** diff --git a/src/stories/input/InputGraphics.stories.ts b/src/stories/input/InputGraphics.stories.ts index a631057d..01648f7b 100644 --- a/src/stories/input/InputGraphics.stories.ts +++ b/src/stories/input/InputGraphics.stories.ts @@ -9,6 +9,7 @@ import { action } from '@storybook/addon-actions'; const args = { text: '', placeholder: 'Enter text', + secure: false, align: ['center', 'left', 'right'], textColor: '#000000', backgroundColor: '#F1D583', @@ -29,31 +30,29 @@ const args = { onChange: action('Change'), }; -export const UseGraphics: StoryFn = ( - { - text, - amount, - border, - textColor, - fontSize, - backgroundColor, - borderColor, - width, - height, - radius, - maxLength, - align, - placeholder, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - onChange, - cleanOnFocus, - addMask, - }, - context, -) => +export const UseGraphics: StoryFn = ({ + text, + amount, + border, + textColor, + fontSize, + backgroundColor, + borderColor, + width, + height, + radius, + maxLength, + align, + placeholder, + secure, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + onChange, + cleanOnFocus, + addMask +}, context) => new PixiStory({ context, init: (view) => { @@ -75,6 +74,7 @@ export const UseGraphics: StoryFn = ( - { - text, - amount, - paddingTop, - paddingRight, - paddingBottom, - paddingLeft, - textColor, - fontSize, - maxLength, - align, - placeholder, - addMask, - onChange, - }, - context, -) => +export const UseSprite: StoryFn = ({ + text, + amount, + paddingTop, + paddingRight, + paddingBottom, + paddingLeft, + textColor, + fontSize, + maxLength, + align, + placeholder, + secure, + addMask, + onChange +}, context) => new PixiStory({ context, init: (view) => { @@ -63,6 +62,7 @@ export const UseSprite: StoryFn