Skip to content

Commit

Permalink
feat!: drop legacy fallbacks for Firefox < 91 (#756)
Browse files Browse the repository at this point in the history
  • Loading branch information
nsbarsukov authored Dec 12, 2023
1 parent b9e63f3 commit 4495942
Show file tree
Hide file tree
Showing 12 changed files with 65 additions and 164 deletions.
165 changes: 58 additions & 107 deletions projects/core/src/lib/mask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import {
getLineSelection,
getNotEmptySelection,
getWordSelection,
isBeforeInputEventSupported,
isEventProducingCharacter,
isRedo,
isUndo,
maskitoPipe,
Expand Down Expand Up @@ -53,73 +51,58 @@ export class Maskito extends MaskHistory {
}
});

if (isBeforeInputEventSupported(element)) {
this.eventListener.listen('beforeinput', event => {
const isForward = event.inputType.includes('Forward');

this.updateHistory(this.elementState);

switch (event.inputType) {
// historyUndo/historyRedo will not be triggered if value was modified programmatically
case 'historyUndo':
event.preventDefault();

return this.undo();
case 'historyRedo':
event.preventDefault();

return this.redo();
case 'deleteByCut':
case 'deleteContentBackward':
case 'deleteContentForward':
return this.handleDelete({
event,
isForward,
selection: getNotEmptySelection(this.elementState, isForward),
});
case 'deleteWordForward':
case 'deleteWordBackward':
return this.handleDelete({
event,
isForward,
selection: getWordSelection(this.elementState, isForward),
force: true,
});
case 'deleteSoftLineBackward':
case 'deleteSoftLineForward':
case 'deleteHardLineBackward':
case 'deleteHardLineForward':
return this.handleDelete({
event,
isForward,
selection: getLineSelection(this.elementState, isForward),
force: true,
});
case 'insertCompositionText':
return; // will be handled inside `compositionend` event
case 'insertLineBreak':
return this.handleEnter(event);
case 'insertFromPaste':
case 'insertText':
case 'insertFromDrop':
default:
return this.handleInsert(event, event.data || '');
}
});
} else {
/** TODO: drop it after browser support bump (Firefox 87+)
* Also, replace union types `Event | TypedInputEvent` with `TypedInputEvent` inside:
*** {@link handleDelete}
*** {@link handleInsert}
*/
this.eventListener.listen('keydown', event => this.handleKeydown(event));
this.eventListener.listen('paste', event =>
this.handleInsert(
event,
event.clipboardData?.getData('text/plain') || '',
),
);
}
this.eventListener.listen('beforeinput', event => {
const isForward = event.inputType.includes('Forward');

this.updateHistory(this.elementState);

switch (event.inputType) {
// historyUndo/historyRedo will not be triggered if value was modified programmatically
case 'historyUndo':
event.preventDefault();

return this.undo();
case 'historyRedo':
event.preventDefault();

return this.redo();
case 'deleteByCut':
case 'deleteContentBackward':
case 'deleteContentForward':
return this.handleDelete({
event,
isForward,
selection: getNotEmptySelection(this.elementState, isForward),
});
case 'deleteWordForward':
case 'deleteWordBackward':
return this.handleDelete({
event,
isForward,
selection: getWordSelection(this.elementState, isForward),
force: true,
});
case 'deleteSoftLineBackward':
case 'deleteSoftLineForward':
case 'deleteHardLineBackward':
case 'deleteHardLineForward':
return this.handleDelete({
event,
isForward,
selection: getLineSelection(this.elementState, isForward),
force: true,
});
case 'insertCompositionText':
return; // will be handled inside `compositionend` event
case 'insertLineBreak':
return this.handleEnter(event);
case 'insertFromPaste':
case 'insertText':
case 'insertFromDrop':
default:
return this.handleInsert(event, event.data || '');
}
});

this.eventListener.listen('input', ({inputType}) => {
if (inputType === 'insertCompositionText') {
Expand Down Expand Up @@ -193,11 +176,7 @@ export class Maskito extends MaskHistory {
data: null,
},
): void {
const globalObject = typeof window !== 'undefined' ? window : globalThis;

// TODO: replace `globalObject` with `globalThis` after bumping Firefox to 65+
// @see https://caniuse.com/?search=globalThis
if (globalObject?.InputEvent) {
if (globalThis?.InputEvent) {
this.element.dispatchEvent(
new InputEvent('input', {
...eventInit,
Expand All @@ -208,36 +187,13 @@ export class Maskito extends MaskHistory {
}
}

private handleKeydown(event: KeyboardEvent): void {
const pressedKey = event.key;
const isForward = pressedKey === 'Delete';

switch (pressedKey) {
case 'Backspace':
case 'Delete':
return this.handleDelete({
event,
isForward,
selection: getNotEmptySelection(this.elementState, isForward),
});
case 'Enter':
return this.handleEnter(event);
}

if (!isEventProducingCharacter(event)) {
return;
}

this.handleInsert(event, pressedKey);
}

private handleDelete({
event,
selection,
isForward,
force = false,
}: {
event: Event | TypedInputEvent;
event: TypedInputEvent;
selection: SelectionRange;
isForward: boolean;
force?: boolean;
Expand Down Expand Up @@ -277,19 +233,14 @@ export class Maskito extends MaskHistory {
return this.updateSelectionRange(isForward ? [to, to] : [from, from]);
}

// TODO: drop it when `event: Event | TypedInputEvent` => `event: TypedInputEvent`
const inputTypeFallback = isForward
? 'deleteContentForward'
: 'deleteContentBackward';

this.updateElementState(newElementState, {
inputType: 'inputType' in event ? event.inputType : inputTypeFallback,
inputType: event.inputType,
data: null,
});
this.updateHistory(newElementState);
}

private handleInsert(event: Event | TypedInputEvent, data: string): void {
private handleInsert(event: TypedInputEvent, data: string): void {
const initialElementState = this.elementState;
const {elementState, data: insertedText = data} = this.preprocessor(
{
Expand Down Expand Up @@ -320,13 +271,13 @@ export class Maskito extends MaskHistory {

this.updateElementState(newElementState, {
data,
inputType: 'inputType' in event ? event.inputType : 'insertText',
inputType: event.inputType,
});
this.updateHistory(newElementState);
}
}

private handleEnter(event: Event): void {
private handleEnter(event: TypedInputEvent): void {
if (this.isTextArea) {
this.handleInsert(event, '\n');
}
Expand Down
16 changes: 0 additions & 16 deletions projects/core/src/lib/utils/dom/is-before-input-event-supported.ts

This file was deleted.

11 changes: 0 additions & 11 deletions projects/core/src/lib/utils/dom/is-event-producing-character.ts

This file was deleted.

4 changes: 2 additions & 2 deletions projects/core/src/lib/utils/get-word-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export function getWordSelection(
'',
];
const nearestWordEndIndex = valueAfterSelectionStart
.replace(LEADING_SPACES_REG, '') // TODO replace with `String.trimStart` after bumping Firefox to 61+
.trimStart()
.search(SPACE_REG);

return [
Expand All @@ -34,7 +34,7 @@ export function getWordSelection(
const valueBeforeSelectionEnd = value.slice(0, to);
const [trailingSpaces] = valueBeforeSelectionEnd.match(TRAILING_SPACES_REG) || [''];
const selectedWordLength = valueBeforeSelectionEnd
.replace(TRAILING_SPACES_REG, '') // TODO replace with `String.trimEnd` after bumping Firefox to 61+
.trimEnd()
.split('')
.reverse()
.findIndex(char => char.match(SPACE_REG));
Expand Down
2 changes: 0 additions & 2 deletions projects/core/src/lib/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export * from './dom/event-listener';
export * from './dom/history-events';
export * from './dom/is-before-input-event-supported';
export * from './dom/is-event-producing-character';
export * from './element-states-equality';
export * from './get-line-selection';
export * from './get-not-empty-selection';
Expand Down
3 changes: 1 addition & 2 deletions projects/kit/src/lib/utils/date/parse-date-string.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {MaskitoDateSegments} from '../../types';
import {getObjectFromEntries} from '../get-object-from-entries';

export function parseDateString(
dateString: string,
Expand All @@ -20,7 +19,7 @@ export function parseDateString(
),
};

return getObjectFromEntries(
return Object.fromEntries(
Object.entries(dateSegments)
.filter(([_, value]) => Boolean(value))
.sort(([a], [b]) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {MaskitoDateSegments} from '../../types';
import {getObjectFromEntries} from '../get-object-from-entries';
import {getDateSegmentValueLength} from './date-segment-value-length';

export function raiseSegmentValueToMin(
Expand All @@ -8,7 +7,7 @@ export function raiseSegmentValueToMin(
): Partial<MaskitoDateSegments> {
const segmentsLength = getDateSegmentValueLength(fullMode);

return getObjectFromEntries(
return Object.fromEntries(
Object.entries<string>(segments).map(([key, value]: [string, string]) => {
const segmentLength =
segmentsLength[key as keyof Partial<MaskitoDateSegments>];
Expand Down
16 changes: 0 additions & 16 deletions projects/kit/src/lib/utils/get-object-from-entries.ts

This file was deleted.

1 change: 0 additions & 1 deletion projects/kit/src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export * from './date/validate-date-string';
export * from './escape-reg-exp';
export * from './find-common-beginning-substr';
export * from './get-focused';
export * from './get-object-from-entries';
export * from './identity';
export * from './is-empty';
export * from './pad-with-zeroes-until-valid';
3 changes: 1 addition & 2 deletions projects/kit/src/lib/utils/time/pad-time-segments.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {TIME_SEGMENT_VALUE_LENGTHS} from '../../constants';
import {MaskitoTimeSegments} from '../../types';
import {getObjectFromEntries} from '../get-object-from-entries';

export function padTimeSegments(
timeSegments: MaskitoTimeSegments<number | string>,
Expand All @@ -13,7 +12,7 @@ export function padTimeSegments(
export function padTimeSegments(
timeSegments: Partial<MaskitoTimeSegments<number | string>>,
): Partial<MaskitoTimeSegments> {
return getObjectFromEntries(
return Object.fromEntries(
Object.entries(timeSegments).map(([segmentName, segmentValue]) => [
segmentName,
`${segmentValue}`.padEnd(
Expand Down
3 changes: 1 addition & 2 deletions projects/kit/src/lib/utils/time/parse-time-string.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {MaskitoTimeSegments} from '../../types';
import {getObjectFromEntries} from '../get-object-from-entries';

/**
* @param timeString can be with/without fixed characters
Expand All @@ -14,7 +13,7 @@ export function parseTimeString(timeString: string): Partial<MaskitoTimeSegments
milliseconds: onlyDigits.slice(6, 9),
};

return getObjectFromEntries(
return Object.fromEntries(
Object.entries(timeSegments).filter(([_, value]) => Boolean(value)),
);
}
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"module": "es2020",
"jsx": "react-jsx",
"target": "es2015",
"lib": ["es2017", "es2018.asynciterable", "dom"],
"lib": ["es2017", "es2018.asynciterable", "es2019.object", "es2019.string", "dom"],
"checkJs": false,
"paths": {
"@demo/constants": ["projects/demo/src/app/constants/index.ts"],
Expand Down

0 comments on commit 4495942

Please sign in to comment.