chore(eslint): add strict-boolean-expressions rule (#25768)

This commit is contained in:
Amanda Johnston
2022-08-23 11:50:02 -05:00
committed by GitHub
parent d75386baef
commit ae6aa0cb8e
38 changed files with 101 additions and 82 deletions

View File

@ -1,2 +1,5 @@
src/components/slides/swiper/swiper.bundle.js src/components/slides/swiper/swiper.bundle.js
src/components.d.ts src/components.d.ts
**/test/**/*.spec.ts
**/test/**/*.spec.tsx
**/test/**/e2e.ts

View File

@ -13,7 +13,8 @@ module.exports = {
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": "latest", "ecmaVersion": "latest",
"sourceType": "module" "sourceType": "module",
"project": "tsconfig.json"
}, },
"plugins": [ "plugins": [
"@typescript-eslint" "@typescript-eslint"
@ -29,6 +30,14 @@ module.exports = {
], ],
"no-useless-catch": "off", "no-useless-catch": "off",
"@typescript-eslint/no-non-null-assertion": "off", "@typescript-eslint/no-non-null-assertion": "off",
"no-case-declarations": "off" "no-case-declarations": "off",
"@typescript-eslint/strict-boolean-expressions": [
"warn",
{
"allowNullableBoolean": true,
"allowNullableString": true,
"allowAny": true
}
]
} }
}; };

View File

@ -173,7 +173,7 @@ export class AccordionGroup implements ComponentInterface {
* to the array. * to the array.
*/ */
if (multiple) { if (multiple) {
const groupValue = value || []; const groupValue = value ?? [];
const processedValue = Array.isArray(groupValue) ? groupValue : [groupValue]; const processedValue = Array.isArray(groupValue) ? groupValue : [groupValue];
const valueExists = processedValue.find((v) => v === accordionValue); const valueExists = processedValue.find((v) => v === accordionValue);
if (valueExists === undefined && accordionValue !== undefined) { if (valueExists === undefined && accordionValue !== undefined) {
@ -188,7 +188,7 @@ export class AccordionGroup implements ComponentInterface {
* out of the values array or unset the value. * out of the values array or unset the value.
*/ */
if (multiple) { if (multiple) {
const groupValue = value || []; const groupValue = value ?? [];
const processedValue = Array.isArray(groupValue) ? groupValue : [groupValue]; const processedValue = Array.isArray(groupValue) ? groupValue : [groupValue];
this.value = processedValue.filter((v) => v !== accordionValue); this.value = processedValue.filter((v) => v !== accordionValue);
} else { } else {

View File

@ -157,11 +157,9 @@ export class Accordion implements ComponentInterface {
} }
// This is not defined in unit tests // This is not defined in unit tests
const ionItem = if (slot.assignedElements === undefined) return;
slot.assignedElements &&
(slot.assignedElements().find((el) => el.tagName === 'ION-ITEM') as HTMLIonItemElement | undefined);
return ionItem; return slot.assignedElements().find((el) => el.tagName === 'ION-ITEM') as HTMLIonItemElement | undefined;
}; };
private setAria = (expanded = false) => { private setAria = (expanded = false) => {

View File

@ -241,7 +241,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
handler: i.handler, handler: i.handler,
min: i.min, min: i.min,
max: i.max, max: i.max,
cssClass: i.cssClass || '', cssClass: i.cssClass ?? '',
attributes: i.attributes || {}, attributes: i.attributes || {},
tabindex: i.type === 'radio' && i !== focusable ? -1 : 0, tabindex: i.type === 'radio' && i !== focusable ? -1 : 0,
} as AlertInput) } as AlertInput)

View File

@ -182,7 +182,7 @@ Please upvote https://github.com/ionic-team/ionic-framework/issues/25668 if you
* Both ion-datetime and ion-datetime-button default * Both ion-datetime and ion-datetime-button default
* to today's date and time if no value is set. * to today's date and time if no value is set.
*/ */
const parsedDatetime = parseDate(value || getToday()) as DatetimeParts; const parsedDatetime = parseDate(value ?? getToday()) as DatetimeParts;
const use24Hour = is24Hour(locale, hourCycle); const use24Hour = is24Hour(locale, hourCycle);
// TODO(FW-1865) - Remove once FW-1831 is fixed. // TODO(FW-1865) - Remove once FW-1831 is fixed.

View File

@ -1150,8 +1150,8 @@ export class Datetime implements ComponentInterface {
} }
private processValue = (value?: string | string[] | null) => { private processValue = (value?: string | string[] | null) => {
this.highlightActiveParts = !!value; this.highlightActiveParts = value !== null && value !== undefined;
let valueToProcess = parseDate(value || getToday()); let valueToProcess = parseDate(value ?? getToday());
const { minParts, maxParts, multiple } = this; const { minParts, maxParts, multiple } = this;
if (!multiple && Array.isArray(value)) { if (!multiple && Array.isArray(value)) {
@ -1438,7 +1438,8 @@ export class Datetime implements ComponentInterface {
* If we have selected a day already, then default the column * If we have selected a day already, then default the column
* to that value. Otherwise, default it to today. * to that value. Otherwise, default it to today.
*/ */
const todayString = workingParts.day const todayString =
workingParts.day !== null
? `${workingParts.year}-${workingParts.month}-${workingParts.day}` ? `${workingParts.year}-${workingParts.month}-${workingParts.day}`
: `${todayParts.year}-${todayParts.month}-${todayParts.day}`; : `${todayParts.year}-${todayParts.month}-${todayParts.day}`;
@ -1566,7 +1567,7 @@ export class Datetime implements ComponentInterface {
class="day-column" class="day-column"
color={this.color} color={this.color}
items={days} items={days}
value={(workingParts.day || this.todayParts.day) ?? undefined} value={(workingParts.day !== null ? workingParts.day : this.todayParts.day) ?? undefined}
onIonChange={(ev: CustomEvent) => { onIonChange={(ev: CustomEvent) => {
// TODO(FW-1823) Remove this when iOS 14 support is dropped. // TODO(FW-1823) Remove this when iOS 14 support is dropped.
// Due to a Safari 14 issue we need to destroy // Due to a Safari 14 issue we need to destroy
@ -1689,12 +1690,14 @@ export class Datetime implements ComponentInterface {
return []; return [];
} }
const valueIsDefined = this.value !== null && this.value !== undefined;
const { hoursData, minutesData, dayPeriodData } = getTimeColumnsData( const { hoursData, minutesData, dayPeriodData } = getTimeColumnsData(
this.locale, this.locale,
this.workingParts, this.workingParts,
this.hourCycle, this.hourCycle,
this.value ? this.minParts : undefined, valueIsDefined ? this.minParts : undefined,
this.value ? this.maxParts : undefined, valueIsDefined ? this.maxParts : undefined,
this.parsedHourValues, this.parsedHourValues,
this.parsedMinuteValues this.parsedMinuteValues
); );

View File

@ -14,12 +14,12 @@ export const isSameDay = (baseParts: DatetimeParts, compareParts: DatetimeParts)
* Returns true is the selected day is before the reference day. * Returns true is the selected day is before the reference day.
*/ */
export const isBefore = (baseParts: DatetimeParts, compareParts: DatetimeParts) => { export const isBefore = (baseParts: DatetimeParts, compareParts: DatetimeParts) => {
return ( return !!(
baseParts.year < compareParts.year || baseParts.year < compareParts.year ||
(baseParts.year === compareParts.year && baseParts.month < compareParts.month) || (baseParts.year === compareParts.year && baseParts.month < compareParts.month) ||
(baseParts.year === compareParts.year && (baseParts.year === compareParts.year &&
baseParts.month === compareParts.month && baseParts.month === compareParts.month &&
baseParts.day && baseParts.day !== null &&
baseParts.day < compareParts.day!) baseParts.day < compareParts.day!)
); );
}; };
@ -28,12 +28,12 @@ export const isBefore = (baseParts: DatetimeParts, compareParts: DatetimeParts)
* Returns true is the selected day is after the reference day. * Returns true is the selected day is after the reference day.
*/ */
export const isAfter = (baseParts: DatetimeParts, compareParts: DatetimeParts) => { export const isAfter = (baseParts: DatetimeParts, compareParts: DatetimeParts) => {
return ( return !!(
baseParts.year > compareParts.year || baseParts.year > compareParts.year ||
(baseParts.year === compareParts.year && baseParts.month > compareParts.month) || (baseParts.year === compareParts.year && baseParts.month > compareParts.month) ||
(baseParts.year === compareParts.year && (baseParts.year === compareParts.year &&
baseParts.month === compareParts.month && baseParts.month === compareParts.month &&
baseParts.day && baseParts.day !== null &&
baseParts.day > compareParts.day!) baseParts.day > compareParts.day!)
); );
}; };
@ -45,7 +45,7 @@ export const warnIfValueOutOfBounds = (
) => { ) => {
const valueArray = Array.isArray(value) ? value : [value]; const valueArray = Array.isArray(value) ? value : [value];
for (const val of valueArray) { for (const val of valueArray) {
if ((min && isBefore(val, min)) || (max && isAfter(val, max))) { if ((min !== undefined && isBefore(val, min)) || (max !== undefined && isAfter(val, max))) {
printIonWarning( printIonWarning(
'The value provided to ion-datetime is out of bounds.\n\n' + 'The value provided to ion-datetime is out of bounds.\n\n' +
`Min: ${JSON.stringify(min)}\n` + `Min: ${JSON.stringify(min)}\n` +

View File

@ -353,8 +353,14 @@ export const getDayColumnData = (
* Otherwise, fallback to the max/min days in a month. * Otherwise, fallback to the max/min days in a month.
*/ */
const numDaysInMonth = getNumDaysInMonth(month, year); const numDaysInMonth = getNumDaysInMonth(month, year);
const maxDay = maxParts?.day && maxParts.year === year && maxParts.month === month ? maxParts.day : numDaysInMonth; const maxDay =
const minDay = minParts?.day && minParts.year === year && minParts.month === month ? minParts.day : 1; maxParts?.day !== null && maxParts?.day !== undefined && maxParts.year === year && maxParts.month === month
? maxParts.day
: numDaysInMonth;
const minDay =
minParts?.day !== null && minParts?.day !== undefined && minParts.year === year && minParts.month === month
? minParts.day
: 1;
if (dayValues !== undefined) { if (dayValues !== undefined) {
let processedDays = dayValues; let processedDays = dayValues;
@ -394,8 +400,8 @@ export const getYearColumnData = (
} }
} else { } else {
const { year } = refParts; const { year } = refParts;
const maxYear = maxParts?.year || year; const maxYear = maxParts?.year ?? year;
const minYear = minParts?.year || year - 100; const minYear = minParts?.year ?? year - 100;
for (let i = maxYear; i >= minYear; i--) { for (let i = maxYear; i >= minYear; i--) {
processedYears.push(i); processedYears.push(i);

View File

@ -129,7 +129,8 @@ export const getLocalizedDateTime = (
refParts: DatetimeParts, refParts: DatetimeParts,
options: Intl.DateTimeFormatOptions options: Intl.DateTimeFormatOptions
): string => { ): string => {
const timeString = !!refParts.hour && !!refParts.minute ? ` ${refParts.hour}:${refParts.minute}` : ''; const timeString =
refParts.hour !== undefined && refParts.minute !== undefined ? ` ${refParts.hour}:${refParts.minute}` : '';
const date = new Date(`${refParts.month}/${refParts.day}/${refParts.year}${timeString} GMT+0000`); const date = new Date(`${refParts.month}/${refParts.day}/${refParts.year}${timeString} GMT+0000`);
return new Intl.DateTimeFormat(locale, { ...options, timeZone: 'UTC' }).format(date); return new Intl.DateTimeFormat(locale, { ...options, timeZone: 'UTC' }).format(date);
}; };

View File

@ -40,17 +40,16 @@ export const createHeaderIndex = (headerEl: HTMLElement | undefined): HeaderInde
return { return {
el: headerEl, el: headerEl,
toolbars: toolbars: Array.from(toolbars).map((toolbar: any) => {
Array.from(toolbars).map((toolbar: any) => {
const ionTitleEl = toolbar.querySelector('ion-title'); const ionTitleEl = toolbar.querySelector('ion-title');
return { return {
el: toolbar, el: toolbar,
background: toolbar.shadowRoot!.querySelector('.toolbar-background'), background: toolbar.shadowRoot!.querySelector('.toolbar-background'),
ionTitleEl, ionTitleEl,
innerTitleEl: ionTitleEl ? ionTitleEl.shadowRoot!.querySelector('.toolbar-title') : null, innerTitleEl: ionTitleEl ? ionTitleEl.shadowRoot!.querySelector('.toolbar-title') : null,
ionButtonsEl: Array.from(toolbar.querySelectorAll('ion-buttons')) || [], ionButtonsEl: Array.from(toolbar.querySelectorAll('ion-buttons')),
} as ToolbarIndex; } as ToolbarIndex;
}) || [], }),
} as HeaderIndex; } as HeaderIndex;
}; };

View File

@ -58,7 +58,9 @@ export class InfiniteScrollContent implements ComponentInterface {
<ion-spinner name={this.loadingSpinner} /> <ion-spinner name={this.loadingSpinner} />
</div> </div>
)} )}
{this.loadingText && <div class="infinite-loading-text" innerHTML={sanitizeDOMString(this.loadingText)} />} {this.loadingText !== undefined && (
<div class="infinite-loading-text" innerHTML={sanitizeDOMString(this.loadingText)} />
)}
</div> </div>
</Host> </Host>
); );

View File

@ -210,7 +210,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
// appear as clickable to screen readers // appear as clickable to screen readers
// https://github.com/ionic-team/ionic-framework/issues/22011 // https://github.com/ionic-team/ionic-framework/issues/22011
const input = this.getFirstInput(); const input = this.getFirstInput();
if (input && !this.clickListener) { if (input !== undefined && !this.clickListener) {
this.clickListener = (ev: Event) => this.delegateFocus(ev, input); this.clickListener = (ev: Event) => this.delegateFocus(ev, input);
this.el.addEventListener('click', this.clickListener); this.el.addEventListener('click', this.clickListener);
} }
@ -218,7 +218,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
disconnectedCallback() { disconnectedCallback() {
const input = this.getFirstInput(); const input = this.getFirstInput();
if (input && this.clickListener) { if (input !== undefined && this.clickListener) {
this.el.removeEventListener('click', this.clickListener); this.el.removeEventListener('click', this.clickListener);
this.clickListener = undefined; this.clickListener = undefined;
} }

View File

@ -214,7 +214,7 @@ export class Loading implements ComponentInterface, OverlayInterface {
</div> </div>
)} )}
{message && <div class="loading-content" innerHTML={sanitizeDOMString(message)}></div>} {message !== undefined && <div class="loading-content" innerHTML={sanitizeDOMString(message)}></div>}
</div> </div>
<div tabindex="0"></div> <div tabindex="0"></div>

View File

@ -704,7 +704,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
this.currentTransition = dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, { this.currentTransition = dismiss(this, data, role, 'modalLeave', iosLeaveAnimation, mdLeaveAnimation, {
presentingEl: this.presentingElement, presentingEl: this.presentingElement,
currentBreakpoint: this.currentBreakpoint || this.initialBreakpoint, currentBreakpoint: this.currentBreakpoint !== undefined || this.initialBreakpoint,
backdropBreakpoint: this.backdropBreakpoint, backdropBreakpoint: this.backdropBreakpoint,
}); });

View File

@ -794,7 +794,7 @@ export class Nav implements NavOutlet {
destroyQueue = []; destroyQueue = [];
for (let i = removeStart; i < removeStart + removeCount; i++) { for (let i = removeStart; i < removeStart + removeCount; i++) {
const view = this.views[i]; const view = this.views[i];
if (view && view !== enteringView && view !== leavingView) { if (view !== undefined && view !== enteringView && view !== leavingView) {
destroyQueue.push(view); destroyQueue.push(view);
} }
} }

View File

@ -351,7 +351,7 @@ export class PickerColumnCmp implements ComponentInterface {
return; return;
} }
const selectedIndex = clamp(min, this.col.selectedIndex || 0, max); const selectedIndex = clamp(min, this.col.selectedIndex ?? 0, max);
if (this.col.prevSelected !== selectedIndex || forceRefresh) { if (this.col.prevSelected !== selectedIndex || forceRefresh) {
const y = selectedIndex * this.optHeight * -1; const y = selectedIndex * this.optHeight * -1;
this.velocity = 0; this.velocity = 0;

View File

@ -320,7 +320,7 @@ export class Range implements ComponentInterface {
this.ionKnobMoveEnd.emit({ value: ensureValueInBounds(this.value) }); this.ionKnobMoveEnd.emit({ value: ensureValueInBounds(this.value) });
}; };
private getValue(): RangeValue { private getValue(): RangeValue {
const value = this.value || 0; const value = this.value ?? 0;
if (this.dualKnobs) { if (this.dualKnobs) {
if (typeof value === 'object') { if (typeof value === 'object') {
return value; return value;

View File

@ -93,7 +93,7 @@ export class RefresherContent implements ComponentInterface {
<ion-icon icon={this.pullingIcon} lazy={false}></ion-icon> <ion-icon icon={this.pullingIcon} lazy={false}></ion-icon>
</div> </div>
)} )}
{this.pullingText && ( {this.pullingText !== undefined && (
<div class="refresher-pulling-text" innerHTML={sanitizeDOMString(this.pullingText)}></div> <div class="refresher-pulling-text" innerHTML={sanitizeDOMString(this.pullingText)}></div>
)} )}
</div> </div>
@ -103,7 +103,7 @@ export class RefresherContent implements ComponentInterface {
<ion-spinner name={this.refreshingSpinner}></ion-spinner> <ion-spinner name={this.refreshingSpinner}></ion-spinner>
</div> </div>
)} )}
{this.refreshingText && ( {this.refreshingText !== undefined && (
<div class="refresher-refreshing-text" innerHTML={sanitizeDOMString(this.refreshingText)}></div> <div class="refresher-refreshing-text" innerHTML={sanitizeDOMString(this.refreshingText)}></div>
)} )}
</div> </div>

View File

@ -577,7 +577,7 @@ export class Refresher implements ComponentInterface {
// best to do any DOM read/writes only when absolutely necessary // best to do any DOM read/writes only when absolutely necessary
// if multi-touch then get out immediately // if multi-touch then get out immediately
const ev = detail.event as TouchEvent; const ev = detail.event as TouchEvent;
if (ev.touches && ev.touches.length > 1) { if (ev.touches !== undefined && ev.touches.length > 1) {
return; return;
} }

View File

@ -13,9 +13,7 @@ export const moveReorderItem = async (
) => { ) => {
try { try {
const reorderItem = const reorderItem =
parentSelectors && parentSelectors.length > 0 parentSelectors.length > 0 ? await (await queryDeep(page, ...parentSelectors)).$(id) : await page.$(id);
? await (await queryDeep(page, ...parentSelectors)).$(id)
: await page.$(id);
if (!reorderItem) { if (!reorderItem) {
throw new Error('Reorder Item is undefined'); throw new Error('Reorder Item is undefined');

View File

@ -396,7 +396,7 @@ export class Searchbar implements ComponentInterface {
const cancelButton = (this.el.shadowRoot || this.el).querySelector('.searchbar-cancel-button') as HTMLElement; const cancelButton = (this.el.shadowRoot || this.el).querySelector('.searchbar-cancel-button') as HTMLElement;
const shouldShowCancel = this.shouldShowCancelButton(); const shouldShowCancel = this.shouldShowCancelButton();
if (cancelButton && shouldShowCancel !== this.isCancelVisible) { if (cancelButton !== null && shouldShowCancel !== this.isCancelVisible) {
const cancelStyle = cancelButton.style; const cancelStyle = cancelButton.style;
this.isCancelVisible = shouldShowCancel; this.isCancelVisible = shouldShowCancel;
if (shouldShowCancel) { if (shouldShowCancel) {

View File

@ -447,9 +447,9 @@ export class Segment implements ComponentInterface {
case 'last': case 'last':
return buttons[buttons.length - 1]; return buttons[buttons.length - 1];
case 'next': case 'next':
return buttons[currIndex + 1] || buttons[0]; return buttons[currIndex + 1] ?? buttons[0];
case 'previous': case 'previous':
return buttons[currIndex - 1] || buttons[buttons.length - 1]; return buttons[currIndex - 1] ?? buttons[buttons.length - 1];
default: default:
return null; return null;
} }

View File

@ -50,7 +50,7 @@ export class Spinner implements ComponentInterface {
const self = this; const self = this;
const mode = getIonMode(self); const mode = getIonMode(self);
const spinnerName = self.getName(); const spinnerName = self.getName();
const spinner = SPINNERS[spinnerName] || SPINNERS['lines']; const spinner = SPINNERS[spinnerName] ?? SPINNERS['lines'];
const duration = typeof self.duration === 'number' && self.duration > 10 ? self.duration : spinner.dur; const duration = typeof self.duration === 'number' && self.duration > 10 ? self.duration : spinner.dur;
const svgs: any[] = []; const svgs: any[] = [];

View File

@ -97,7 +97,7 @@ export const doRender = (
nodeRender(child, cell, i); nodeRender(child, cell, i);
} else { } else {
const newChild = createNode(el, cell.type); const newChild = createNode(el, cell.type);
child = nodeRender(newChild, cell, i) || newChild; child = nodeRender(newChild, cell, i) ?? newChild;
child.classList.add('virtual-item'); child.classList.add('virtual-item');
el.appendChild(child!); el.appendChild(child!);
} }
@ -132,7 +132,7 @@ export const doRender = (
const createNode = (el: HTMLElement, type: CellType): HTMLElement | null => { const createNode = (el: HTMLElement, type: CellType): HTMLElement | null => {
const template = getTemplate(el, type); const template = getTemplate(el, type);
if (template && el.ownerDocument) { if (template && el.ownerDocument !== null) {
return el.ownerDocument.importNode(template.content, true).children[0] as HTMLElement; return el.ownerDocument.importNode(template.content, true).children[0] as HTMLElement;
} }
return null; return null;

View File

@ -306,7 +306,7 @@ export class VirtualScroll implements ComponentInterface {
const { contentEl, scrollEl, el } = this; const { contentEl, scrollEl, el } = this;
let topOffset = 0; let topOffset = 0;
let node: HTMLElement | null = el; let node: HTMLElement | null = el;
while (node && node !== contentEl) { while (node !== null && node !== contentEl) {
topOffset += node.offsetTop; topOffset += node.offsetTop;
node = node.offsetParent as HTMLElement; node = node.offsetParent as HTMLElement;
} }
@ -386,7 +386,7 @@ export class VirtualScroll implements ComponentInterface {
} }
private updateState() { private updateState() {
const shouldEnable = !!(this.scrollEl && this.cells); const shouldEnable = !!(this.scrollEl && this.cells.length > 0);
if (shouldEnable !== this.isEnabled) { if (shouldEnable !== this.isEnabled) {
this.enableScrollEvents(shouldEnable); this.enableScrollEvents(shouldEnable);
if (shouldEnable) { if (shouldEnable) {

View File

@ -131,7 +131,7 @@ export const createKeyframeStylesheet = (
return existingStylesheet; return existingStylesheet;
} }
const stylesheet = (element.ownerDocument || document).createElement('style'); const stylesheet = (element.ownerDocument ?? document).createElement('style');
stylesheet.id = keyframeName; stylesheet.id = keyframeName;
stylesheet.textContent = `@${keyframePrefix}keyframes ${keyframeName} { ${keyframeRules} } @${keyframePrefix}keyframes ${keyframeName}-alt { ${keyframeRules} }`; stylesheet.textContent = `@${keyframePrefix}keyframes ${keyframeName} { ${keyframeRules} } @${keyframePrefix}keyframes ${keyframeName}-alt { ${keyframeRules} }`;

View File

@ -13,7 +13,7 @@ export const ION_CONTENT_CLASS_SELECTOR = '.ion-content-scroll-host';
*/ */
const ION_CONTENT_SELECTOR = `${ION_CONTENT_ELEMENT_SELECTOR}, ${ION_CONTENT_CLASS_SELECTOR}`; const ION_CONTENT_SELECTOR = `${ION_CONTENT_ELEMENT_SELECTOR}, ${ION_CONTENT_CLASS_SELECTOR}`;
export const isIonContent = (el: Element) => el && el.tagName === ION_CONTENT_TAG_NAME; export const isIonContent = (el: Element) => el.tagName === ION_CONTENT_TAG_NAME;
/** /**
* Waits for the element host fully initialize before * Waits for the element host fully initialize before

View File

@ -39,7 +39,7 @@ export const startFocusVisible = (rootEl?: HTMLElement) => {
} }
}; };
const onFocusin = (ev: Event) => { const onFocusin = (ev: Event) => {
if (keyboardMode && ev.composedPath) { if (keyboardMode && ev.composedPath !== undefined) {
const toFocus = ev.composedPath().filter((el: any) => { const toFocus = ev.composedPath().filter((el: any) => {
if (el.classList) { if (el.classList) {
return el.classList.contains(ION_FOCUSABLE); return el.classList.contains(ION_FOCUSABLE);

View File

@ -9,7 +9,7 @@ class GestureController {
* Creates a gesture delegate based on the GestureConfig passed * Creates a gesture delegate based on the GestureConfig passed
*/ */
createGesture(config: GestureConfig): GestureDelegate { createGesture(config: GestureConfig): GestureDelegate {
return new GestureDelegate(this, this.newID(), config.name, config.priority || 0, !!config.disableScroll); return new GestureDelegate(this, this.newID(), config.name, config.priority ?? 0, !!config.disableScroll);
} }
/** /**

View File

@ -119,7 +119,7 @@ export const createGesture = (config: GestureConfig): Gesture => {
}; };
const tryToCapturePan = (): boolean => { const tryToCapturePan = (): boolean => {
if (gesture && !gesture.capture()) { if (!gesture.capture()) {
return false; return false;
} }
hasCapturedPan = true; hasCapturedPan = true;

View File

@ -8,7 +8,7 @@ export interface ScrollData {
} }
export const getScrollData = (componentEl: HTMLElement, contentEl: HTMLElement, keyboardHeight: number): ScrollData => { export const getScrollData = (componentEl: HTMLElement, contentEl: HTMLElement, keyboardHeight: number): ScrollData => {
const itemEl = (componentEl.closest('ion-item,[ion-item]') as HTMLElement) || componentEl; const itemEl = (componentEl.closest('ion-item,[ion-item]') as HTMLElement) ?? componentEl;
return calcScrollData( return calcScrollData(
itemEl.getBoundingClientRect(), itemEl.getBoundingClientRect(),
contentEl.getBoundingClientRect(), contentEl.getBoundingClientRect(),

View File

@ -104,10 +104,10 @@ export const startTapClick = (config: Config) => {
const addActivated = (el: HTMLElement, x: number, y: number) => { const addActivated = (el: HTMLElement, x: number, y: number) => {
lastActivated = Date.now(); lastActivated = Date.now();
el.classList.add(ACTIVATED); el.classList.add(ACTIVATED);
if (!useRippleEffect) return;
const rippleEffect = useRippleEffect && getRippleEffect(el); const rippleEffect = getRippleEffect(el);
// eslint-disable-next-line @typescript-eslint/prefer-optional-chain if (rippleEffect !== null) {
if (rippleEffect && rippleEffect.addRipple) {
removeRipple(); removeRipple();
activeRipple = rippleEffect.addRipple(x, y); activeRipple = rippleEffect.addRipple(x, y);
} }
@ -164,7 +164,7 @@ export const startTapClick = (config: Config) => {
}; };
const getActivatableTarget = (ev: UIEvent): any => { const getActivatableTarget = (ev: UIEvent): any => {
if (ev.composedPath) { if (ev.composedPath !== undefined) {
/** /**
* composedPath returns EventTarget[]. However, * composedPath returns EventTarget[]. However,
* objects other than Element can be targets too. * objects other than Element can be targets too.

View File

@ -1,7 +1,7 @@
import type { EventSpy } from '../page/event-spy'; import type { EventSpy } from '../page/event-spy';
export function toHaveReceivedEvent(eventSpy: EventSpy) { export function toHaveReceivedEvent(eventSpy: EventSpy) {
if (!eventSpy) { if (eventSpy === undefined || eventSpy === null) {
return { return {
message: () => `expected spy to have received event, but it was not defined`, message: () => `expected spy to have received event, but it was not defined`,
pass: false, pass: false,

View File

@ -4,7 +4,7 @@ import deepEqual from 'fast-deep-equal';
import type { EventSpy } from '../page/event-spy'; import type { EventSpy } from '../page/event-spy';
export function toHaveReceivedEventDetail(eventSpy: EventSpy, eventDetail: any) { export function toHaveReceivedEventDetail(eventSpy: EventSpy, eventDetail: any) {
if (!eventSpy) { if (eventSpy === null || eventSpy === undefined) {
return { return {
message: () => `toHaveReceivedEventDetail event spy is null`, message: () => `toHaveReceivedEventDetail event spy is null`,
pass: false, pass: false,
@ -26,7 +26,7 @@ export function toHaveReceivedEventDetail(eventSpy: EventSpy, eventDetail: any)
}; };
} }
if (!eventSpy.lastEvent) { if (eventSpy.lastEvent === null || eventSpy.lastEvent === undefined) {
return { return {
message: () => `event "${eventSpy.eventName}" was not received`, message: () => `event "${eventSpy.eventName}" was not received`,
pass: false, pass: false,

View File

@ -27,11 +27,11 @@ export class EventSpy {
} }
get firstEvent() { get firstEvent() {
return this.events[0] || null; return this.events[0] ?? null;
} }
get lastEvent() { get lastEvent() {
return this.events[this.events.length - 1] || null; return this.events[this.events.length - 1] ?? null;
} }
public next() { public next() {
@ -39,7 +39,7 @@ export class EventSpy {
this.cursor++; this.cursor++;
const next = this.events[cursor]; const next = this.events[cursor];
if (next) { if (next !== undefined) {
return Promise.resolve(next); return Promise.resolve(next);
} else { } else {
/** /**

View File

@ -287,12 +287,12 @@ export const iosTransitionAnimation = (navEl: HTMLElement, opts: TransitionOptio
rootAnimation rootAnimation
.addElement(enteringEl) .addElement(enteringEl)
.duration(opts.duration || DURATION) .duration((opts.duration ?? 0) || DURATION)
.easing(opts.easing || EASING) .easing(opts.easing || EASING)
.fill('both') .fill('both')
.beforeRemoveClass('ion-page-invisible'); .beforeRemoveClass('ion-page-invisible');
if (leavingEl && navEl) { if (leavingEl && navEl !== null && navEl !== undefined) {
const navDecorAnimation = createAnimation(); const navDecorAnimation = createAnimation();
navDecorAnimation.addElement(navEl); navDecorAnimation.addElement(navEl);
rootAnimation.addAnimation(navDecorAnimation); rootAnimation.addAnimation(navDecorAnimation);

View File

@ -19,10 +19,10 @@ export const mdTransitionAnimation = (_: HTMLElement, opts: TransitionOptions):
// animate the component itself // animate the component itself
if (backDirection) { if (backDirection) {
rootTransition.duration(opts.duration || 200).easing('cubic-bezier(0.47,0,0.745,0.715)'); rootTransition.duration((opts.duration ?? 0) || 200).easing('cubic-bezier(0.47,0,0.745,0.715)');
} else { } else {
rootTransition rootTransition
.duration(opts.duration || 280) .duration((opts.duration ?? 0) || 280)
.easing('cubic-bezier(0.36,0.66,0.04,1)') .easing('cubic-bezier(0.36,0.66,0.04,1)')
.fromTo('transform', `translateY(${OFF_BOTTOM})`, `translateY(${CENTER})`) .fromTo('transform', `translateY(${OFF_BOTTOM})`, `translateY(${CENTER})`)
.fromTo('opacity', 0.01, 1); .fromTo('opacity', 0.01, 1);
@ -38,7 +38,7 @@ export const mdTransitionAnimation = (_: HTMLElement, opts: TransitionOptions):
// setup leaving view // setup leaving view
if (leavingEl && backDirection) { if (leavingEl && backDirection) {
// leaving content // leaving content
rootTransition.duration(opts.duration || 200).easing('cubic-bezier(0.47,0,0.745,0.715)'); rootTransition.duration((opts.duration ?? 0) || 200).easing('cubic-bezier(0.47,0,0.745,0.715)');
const leavingPage = createAnimation(); const leavingPage = createAnimation();
leavingPage leavingPage