Skip to content

Commit 312dc48

Browse files
authored
refactor(masked-input): Cleaned up internal state and derived components (#1875)
1 parent c895a30 commit 312dc48

File tree

6 files changed

+320
-276
lines changed

6 files changed

+320
-276
lines changed

src/components/date-time-input/date-time-input.ts

Lines changed: 56 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { partMap } from '../common/part-map.js';
2222
import type { IgcInputComponentEventMap } from '../input/input-base.js';
2323
import {
2424
IgcMaskInputBaseComponent,
25-
type MaskRange,
25+
type MaskSelection,
2626
} from '../mask-input/mask-input-base.js';
2727
import IgcValidationContainerComponent from '../validation-container/validation-container.js';
2828
import {
@@ -213,15 +213,6 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
213213
}
214214
}
215215

216-
@watch('prompt', { waitUntilFirstUpdate: true })
217-
protected promptChange(): void {
218-
if (!this.prompt) {
219-
this.prompt = this.parser.prompt;
220-
} else {
221-
this.parser.prompt = this.prompt;
222-
}
223-
}
224-
225216
protected get hasDateParts(): boolean {
226217
const parts =
227218
this._inputDateParts ||
@@ -250,11 +241,11 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
250241
private get targetDatePart(): DatePart | undefined {
251242
let result: DatePart | undefined;
252243

253-
if (this.focused) {
244+
if (this._focused) {
254245
const partType = this._inputDateParts.find(
255246
(p) =>
256-
p.start <= this.inputSelection.start &&
257-
this.inputSelection.start <= p.end &&
247+
p.start <= this._inputSelection.start &&
248+
this._inputSelection.start <= p.end &&
258249
p.type !== DateParts.Literal
259250
)?.type as string as DatePart;
260251

@@ -307,7 +298,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
307298
return;
308299
}
309300

310-
const { start, end } = this.inputSelection;
301+
const { start, end } = this._inputSelection;
311302
const newValue = this.trySpinValue(targetPart, delta);
312303
this.value = newValue;
313304
this.updateComplete.then(() => this.input.setSelectionRange(start, end));
@@ -321,88 +312,87 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
321312
return;
322313
}
323314

324-
const { start, end } = this.inputSelection;
315+
const { start, end } = this._inputSelection;
325316
const newValue = this.trySpinValue(targetPart, delta, true);
326317
this.value = newValue;
327318
this.updateComplete.then(() => this.input.setSelectionRange(start, end));
328319
}
329320

330321
/** Clears the input element of user input. */
331322
public clear(): void {
332-
this.maskedValue = '';
323+
this._maskedValue = '';
333324
this.value = null;
334325
}
335326

336327
protected setToday() {
337328
this.value = new Date();
338-
this.handleInput();
329+
this._fireInputEvent();
339330
}
340331

341332
protected updateMask() {
342-
if (this.focused) {
343-
this.maskedValue = this.getMaskedValue();
333+
if (this._focused) {
334+
this._maskedValue = this.getMaskedValue();
344335
} else {
345336
if (!DateTimeUtil.isValidDate(this.value)) {
346-
this.maskedValue = '';
337+
this._maskedValue = '';
347338
return;
348339
}
349340

350341
const format = this.displayFormat || this.inputFormat;
351342

352343
if (this.displayFormat) {
353-
this.maskedValue = DateTimeUtil.formatDate(
344+
this._maskedValue = DateTimeUtil.formatDate(
354345
this.value,
355346
this.locale,
356347
format,
357348
true
358349
);
359350
} else if (this.inputFormat) {
360-
this.maskedValue = DateTimeUtil.formatDate(
351+
this._maskedValue = DateTimeUtil.formatDate(
361352
this.value,
362353
this.locale,
363354
format
364355
);
365356
} else {
366-
this.maskedValue = this.value.toLocaleString();
357+
this._maskedValue = this.value.toLocaleString();
367358
}
368359
}
369360
}
370361

371-
protected override handleInput() {
362+
private _fireInputEvent(): void {
372363
this._setTouchedState();
373364
this.emitEvent('igcInput', { detail: this.value?.toString() });
374365
}
375366

376367
protected handleDragLeave() {
377-
if (!this.focused) {
368+
if (!this._focused) {
378369
this.updateMask();
379370
}
380371
}
381372

382373
protected handleDragEnter() {
383-
if (!this.focused) {
384-
this.maskedValue = this.getMaskedValue();
374+
if (!this._focused) {
375+
this._maskedValue = this.getMaskedValue();
385376
}
386377
}
387378

388-
protected async updateInput(string: string, range: MaskRange) {
389-
const { value, end } = this.parser.replace(
390-
this.maskedValue,
391-
string,
392-
range.start,
393-
range.end
394-
);
379+
protected async _updateInput(
380+
text: string,
381+
{ start, end }: MaskSelection
382+
): Promise<void> {
383+
const result = this._parser.replace(this._maskedValue, text, start, end);
395384

396-
this.maskedValue = value;
385+
this._maskedValue = result.value;
397386

398387
this.updateValue();
399388
this.requestUpdate();
400389

401-
if (range.start !== this.inputFormat.length) {
402-
this.handleInput();
390+
if (start !== this.inputFormat.length) {
391+
this._fireInputEvent();
403392
}
393+
404394
await this.updateComplete;
405-
this.input.setSelectionRange(end, end);
395+
this.input.setSelectionRange(result.end, result.end);
406396
}
407397

408398
private trySpinValue(
@@ -451,7 +441,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
451441
(dp) => dp.type === DateParts.AmPm
452442
);
453443
if (formatPart !== undefined) {
454-
amPmFromMask = this.maskedValue.substring(
444+
amPmFromMask = this._maskedValue.substring(
455445
formatPart!.start,
456446
formatPart!.end
457447
);
@@ -465,16 +455,16 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
465455

466456
@eventOptions({ passive: false })
467457
private async onWheel(event: WheelEvent) {
468-
if (!this.focused || this.readOnly) {
458+
if (!this._focused || this.readOnly) {
469459
return;
470460
}
471461

472462
event.preventDefault();
473463
event.stopPropagation();
474464

475-
const { start, end } = this.inputSelection;
465+
const { start, end } = this._inputSelection;
476466
event.deltaY > 0 ? this.stepDown() : this.stepUp();
477-
this.handleInput();
467+
this._fireInputEvent();
478468

479469
await this.updateComplete;
480470
this.setSelectionRange(start, end);
@@ -496,12 +486,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
496486
'0'
497487
);
498488

499-
this._mask = newMask.includes('tt')
500-
? newMask.replace(/tt/g, 'LL')
501-
: newMask;
502-
503-
this.parser.mask = this._mask;
504-
this.parser.prompt = this.prompt;
489+
this.mask = newMask.includes('tt') ? newMask.replace(/tt/g, 'LL') : newMask;
505490

506491
if (!this.placeholder || oldFormat === this.placeholder) {
507492
this.placeholder = value;
@@ -515,7 +500,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
515500
}
516501

517502
private getMaskedValue(): string {
518-
let mask = this.emptyMask;
503+
let mask = this._parser.emptyMask;
519504

520505
if (DateTimeUtil.isValidDate(this.value)) {
521506
for (const part of this._inputDateParts) {
@@ -529,7 +514,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
529514
this.value
530515
);
531516

532-
mask = this.parser.replace(
517+
mask = this._parser.replace(
533518
mask,
534519
targetValue,
535520
part.start,
@@ -539,16 +524,16 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
539524
return mask;
540525
}
541526

542-
return this.maskedValue === '' ? mask : this.maskedValue;
527+
return this._maskedValue === '' ? mask : this._maskedValue;
543528
}
544529

545530
private isComplete(): boolean {
546-
return !this.maskedValue.includes(this.prompt);
531+
return !this._maskedValue.includes(this.prompt);
547532
}
548533

549534
private updateValue(): void {
550535
if (this.isComplete()) {
551-
const parsedDate = this.parseDate(this.maskedValue);
536+
const parsedDate = this.parseDate(this._maskedValue);
552537
this.value = DateTimeUtil.isValidDate(parsedDate) ? parsedDate : null;
553538
} else {
554539
this.value = null;
@@ -560,7 +545,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
560545
}
561546

562547
private getNewPosition(value: string, direction = 0): number {
563-
const cursorPos = this.selection.start;
548+
const cursorPos = this._maskSelection.start;
564549

565550
if (!direction) {
566551
// Last literal before the current cursor position or start of input value
@@ -578,7 +563,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
578563
}
579564

580565
protected async handleFocus() {
581-
this.focused = true;
566+
this._focused = true;
582567

583568
if (this.readOnly) {
584569
return;
@@ -588,7 +573,7 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
588573
const areFormatsDifferent = this.displayFormat !== this.inputFormat;
589574

590575
if (!this.value) {
591-
this.maskedValue = this.emptyMask;
576+
this._maskedValue = this._parser.emptyMask;
592577
await this.updateComplete;
593578
this.select();
594579
} else if (areFormatsDifferent) {
@@ -597,18 +582,18 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
597582
}
598583

599584
protected handleBlur() {
600-
const isEmptyMask = this.maskedValue === this.emptyMask;
585+
const isEmptyMask = this._maskedValue === this._parser.emptyMask;
601586

602-
this.focused = false;
587+
this._focused = false;
603588

604589
if (!(this.isComplete() || isEmptyMask)) {
605-
const parse = this.parseDate(this.maskedValue);
590+
const parse = this.parseDate(this._maskedValue);
606591

607592
if (parse) {
608593
this.value = parse;
609594
} else {
610595
this.value = null;
611-
this.maskedValue = '';
596+
this._maskedValue = '';
612597
}
613598
} else {
614599
this.updateMask();
@@ -630,9 +615,9 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
630615

631616
protected async keyboardSpin(direction: 'up' | 'down') {
632617
direction === 'up' ? this.stepUp() : this.stepDown();
633-
this.handleInput();
618+
this._fireInputEvent();
634619
await this.updateComplete;
635-
this.setSelectionRange(this.selection.start, this.selection.end);
620+
this.setSelectionRange(this._maskSelection.start, this._maskSelection.end);
636621
}
637622

638623
protected override renderInput() {
@@ -641,22 +626,22 @@ export default class IgcDateTimeInputComponent extends EventEmitterMixin<
641626
type="text"
642627
part=${partMap(this.resolvePartNames('input'))}
643628
name=${ifDefined(this.name)}
644-
.value=${live(this.maskedValue)}
645-
.placeholder=${live(this.placeholder || this.emptyMask)}
629+
.value=${live(this._maskedValue)}
630+
.placeholder=${this.placeholder || this._parser.emptyMask}
646631
?readonly=${this.readOnly}
647632
?disabled=${this.disabled}
648633
@blur=${this.handleBlur}
649634
@focus=${this.handleFocus}
650-
@input=${super.handleInput}
635+
@input=${this._handleInput}
651636
@wheel=${this.onWheel}
652-
@keydown=${super.handleKeydown}
653-
@click=${this.handleClick}
654-
@cut=${this.handleCut}
655-
@compositionstart=${this.handleCompositionStart}
656-
@compositionend=${this.handleCompositionEnd}
637+
@keydown=${this._setMaskSelection}
638+
@click=${this._handleClick}
639+
@cut=${this._setMaskSelection}
640+
@compositionstart=${this._handleCompositionStart}
641+
@compositionend=${this._handleCompositionEnd}
657642
@dragenter=${this.handleDragEnter}
658643
@dragleave=${this.handleDragLeave}
659-
@dragstart=${this.handleDragStart}
644+
@dragstart=${this._setMaskSelection}
660645
/>
661646
`;
662647
}

0 commit comments

Comments
 (0)