Skip to content

Commit

Permalink
fix(text-field): fixed a bug where the internal value change listener…
Browse files Browse the repository at this point in the history
… was not safely guarding types (#824)
  • Loading branch information
DRiFTy17 authored Feb 14, 2025
1 parent e4bd264 commit 6456fdf
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
10 changes: 10 additions & 0 deletions src/lib/core/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,3 +333,13 @@ export function task(duration = 0): Promise<void> {
export function frame(): Promise<void> {
return new Promise<void>(resolve => requestAnimationFrame(() => resolve()));
}

/**
* Determines if an object is an instance of a specific type.
* @param obj The object to test.
* @param name The name of the type to test against.
* @returns `true` if the object is an instance of the type, otherwise `false`.
*/
export function isInstanceOf<T>(obj: any, name: string): obj is T {
return Object.prototype.toString.call(obj) === `[object ${name}]`;
}
26 changes: 19 additions & 7 deletions src/lib/text-field/text-field-core.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { isInstanceOf } from '../core/utils/utils';
import { FieldLabelPosition, FIELD_CONSTANTS } from '../field';
import { BaseFieldCore, IBaseFieldCore } from '../field/base/base-field-core';
import { ITextFieldAdapter, TextFieldAdapter } from './text-field-adapter';
Expand All @@ -13,7 +14,7 @@ export class TextFieldCore extends BaseFieldCore<ITextFieldAdapter> implements I
private _slotChangeListener: EventListener = this._onSlotChange.bind(this);
private _inputAttributeListener: TextFieldInputAttributeObserver = this._onInputAttributeChange.bind(this);
private _valueChangeListener: TextFieldValueChangeListener = this._onValueChange.bind(this);
private _inputListener: EventListener = this._onValueChange.bind(this);
private _inputListener: EventListener = this._onInputChange.bind(this);
private _clearButtonClickListener: EventListener = (evt: PointerEvent) => this._onClearButtonClick(evt);

constructor(protected _adapter: TextFieldAdapter) {
Expand Down Expand Up @@ -82,15 +83,26 @@ export class TextFieldCore extends BaseFieldCore<ITextFieldAdapter> implements I
}
}

private _onValueChange(evt: InputEvent): void {
let force;
/** Responds to the `input` event from the <input> element. */
private _onInputChange(evt: InputEvent & { target: HTMLInputElement }): void {
let floatLabel;

// Handle the special case where a number input allows invalid characters
if ((evt.target as HTMLInputElement | undefined)?.type === 'number' && (evt.data != null || (evt.target as HTMLInputElement).validity.badInput)) {
force = true;
// Handle the special case where a number input allows invalid characters to be entered.
// In this case, we need to force the label to float.
if (isInstanceOf<InputEvent>(evt, InputEvent.name) && evt.target.type === 'number' && (evt.data != null || evt.target.validity.badInput)) {
floatLabel = true;
}

this._tryFloatLabel(force);
this._syncValueChange({ floatLabel });
}

/** Called from the `value` property setter on the <input> element. */
private _onValueChange(): void {
this._syncValueChange();
}

private _syncValueChange({ floatLabel = undefined }: { floatLabel?: boolean } = {}): void {
this._tryFloatLabel(floatLabel);
this._toggleClearButtonVisibility();
}

Expand Down

0 comments on commit 6456fdf

Please sign in to comment.