Merge pull request #1372 from justinfagnani/no-bind

Code size optimizations: Replace .bind() with arrow functions, add listeners in constructors.
pull/1377/head
Konnor Rogers 2023-06-15 11:58:08 -04:00 zatwierdzone przez GitHub
commit c167bdd80f
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
15 zmienionych plików z 106 dodań i 188 usunięć

Wyświetl plik

@ -91,8 +91,6 @@ export default class SlAnimation extends ShoelaceElement {
connectedCallback() {
super.connectedCallback();
this.createAnimation();
this.handleAnimationCancel = this.handleAnimationCancel.bind(this);
this.handleAnimationFinish = this.handleAnimationFinish.bind(this);
}
disconnectedCallback() {
@ -100,17 +98,17 @@ export default class SlAnimation extends ShoelaceElement {
this.destroyAnimation();
}
private handleAnimationFinish() {
private handleAnimationFinish = () => {
this.play = false;
this.hasStarted = false;
this.emit('sl-finish');
}
};
private handleAnimationCancel() {
private handleAnimationCancel = () => {
this.play = false;
this.hasStarted = false;
this.emit('sl-cancel');
}
};
private handleSlotChange() {
this.destroyAnimation();

Wyświetl plik

@ -167,17 +167,11 @@ export default class SlButton extends ShoelaceElement implements ShoelaceFormCon
return '';
}
connectedCallback() {
super.connectedCallback();
this.handleHostClick = this.handleHostClick.bind(this);
constructor() {
super();
this.addEventListener('click', this.handleHostClick);
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('click', this.handleHostClick);
}
firstUpdated() {
if (this.isButton()) {
this.formControlController.updateValidity();
@ -204,13 +198,13 @@ export default class SlButton extends ShoelaceElement implements ShoelaceFormCon
}
}
private handleHostClick(event: MouseEvent) {
private handleHostClick = (event: MouseEvent) => {
// Prevent the click event from being emitted when the button is disabled or loading
if (this.disabled || this.loading) {
event.preventDefault();
event.stopImmediatePropagation();
}
}
};
private handleInvalid(event: Event) {
this.formControlController.setValidity(false);

Wyświetl plik

@ -132,7 +132,7 @@ export default class SlCarousel extends ShoelaceElement {
protected firstUpdated(): void {
this.initializeSlides();
this.mutationObserver = new MutationObserver(this.handleSlotChange.bind(this));
this.mutationObserver = new MutationObserver(this.handleSlotChange);
this.mutationObserver.observe(this, { childList: true, subtree: false });
}
@ -211,7 +211,7 @@ export default class SlCarousel extends ShoelaceElement {
}
}
private handleSlotChange(mutations: MutationRecord[]) {
private handleSlotChange = (mutations: MutationRecord[]) => {
const needsInitialization = mutations.some(mutation =>
[...mutation.addedNodes, ...mutation.removedNodes].some(
node => SlCarouselItem.isCarouselItem(node) && !(node as HTMLElement).hasAttribute('data-clone')
@ -223,7 +223,7 @@ export default class SlCarousel extends ShoelaceElement {
this.initializeSlides();
}
this.requestUpdate();
}
};
@watch('loop', { waitUntilFirstUpdate: true })
@watch('slidesPerPage', { waitUntilFirstUpdate: true })

Wyświetl plik

@ -20,16 +20,7 @@ export class ScrollController<T extends ScrollHost> implements ReactiveControlle
constructor(host: T) {
this.host = host;
host.addController(this);
this.handleScroll = this.handleScroll.bind(this);
this.handlePointerDown = this.handlePointerDown.bind(this);
this.handlePointerMove = this.handlePointerMove.bind(this);
this.handlePointerUp = this.handlePointerUp.bind(this);
this.handlePointerUp = this.handlePointerUp.bind(this);
this.handleTouchStart = this.handleTouchStart.bind(this);
this.handleTouchEnd = this.handleTouchEnd.bind(this);
}
async hostConnected() {
@ -58,13 +49,13 @@ export class ScrollController<T extends ScrollHost> implements ReactiveControlle
scrollContainer.removeEventListener('touchend', this.handleTouchEnd);
}
handleScroll() {
handleScroll = () => {
if (!this.scrolling) {
this.scrolling = true;
this.host.requestUpdate();
}
this.handleScrollEnd();
}
};
@debounce(100)
handleScrollEnd() {
@ -84,7 +75,7 @@ export class ScrollController<T extends ScrollHost> implements ReactiveControlle
}
}
handlePointerDown(event: PointerEvent) {
handlePointerDown = (event: PointerEvent) => {
if (event.pointerType === 'touch') {
return;
}
@ -97,9 +88,9 @@ export class ScrollController<T extends ScrollHost> implements ReactiveControlle
this.host.scrollContainer.addEventListener('pointermove', this.handlePointerMove);
}
}
};
handlePointerMove(event: PointerEvent) {
handlePointerMove = (event: PointerEvent) => {
const scrollContainer = this.host.scrollContainer;
const hasMoved = !!event.movementX || !!event.movementY;
@ -111,28 +102,28 @@ export class ScrollController<T extends ScrollHost> implements ReactiveControlle
// Ignore pointers that we are not tracking
this.handleDrag(event);
}
}
};
handlePointerUp(event: PointerEvent) {
handlePointerUp = (event: PointerEvent) => {
this.pointers.delete(event.pointerId);
this.host.scrollContainer.releasePointerCapture(event.pointerId);
if (this.pointers.size === 0) {
this.handleDragEnd();
}
}
};
handleTouchEnd(event: TouchEvent) {
handleTouchEnd = (event: TouchEvent) => {
for (const touch of event.changedTouches) {
this.pointers.delete(touch.identifier);
}
}
};
handleTouchStart(event: TouchEvent) {
handleTouchStart = (event: TouchEvent) => {
for (const touch of event.touches) {
this.pointers.add(touch.identifier);
}
}
};
handleDragStart() {
const host = this.host;

Wyświetl plik

@ -190,20 +190,12 @@ export default class SlColorPicker extends ShoelaceElement implements ShoelaceFo
return this.input.validationMessage;
}
connectedCallback() {
super.connectedCallback();
this.handleFocusIn = this.handleFocusIn.bind(this);
this.handleFocusOut = this.handleFocusOut.bind(this);
constructor() {
super();
this.addEventListener('focusin', this.handleFocusIn);
this.addEventListener('focusout', this.handleFocusOut);
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('focusin', this.handleFocusIn);
this.removeEventListener('focusout', this.handleFocusOut);
}
firstUpdated() {
this.input.updateComplete.then(() => {
this.formControlController.updateValidity();
@ -222,15 +214,15 @@ export default class SlColorPicker extends ShoelaceElement implements ShoelaceFo
});
}
private handleFocusIn() {
private handleFocusIn = () => {
this.hasFocus = true;
this.emit('sl-focus');
}
};
private handleFocusOut() {
private handleFocusOut = () => {
this.hasFocus = false;
this.emit('sl-blur');
}
};
private handleFormatToggle() {
const formats = ['hex', 'rgb', 'hsl', 'hsv'];

Wyświetl plik

@ -67,7 +67,7 @@ export default class SlDialog extends ShoelaceElement {
private readonly hasSlotController = new HasSlotController(this, 'footer');
private readonly localize = new LocalizeController(this);
private modal: Modal;
private modal = new Modal(this);
private originalTrigger: HTMLElement | null;
@query('.dialog') dialog: HTMLElement;
@ -92,12 +92,6 @@ export default class SlDialog extends ShoelaceElement {
*/
@property({ attribute: 'no-header', type: Boolean, reflect: true }) noHeader = false;
connectedCallback() {
super.connectedCallback();
this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);
this.modal = new Modal(this);
}
firstUpdated() {
this.dialog.hidden = !this.open;
@ -136,12 +130,12 @@ export default class SlDialog extends ShoelaceElement {
document.removeEventListener('keydown', this.handleDocumentKeyDown);
}
private handleDocumentKeyDown(event: KeyboardEvent) {
private handleDocumentKeyDown = (event: KeyboardEvent) => {
if (this.open && event.key === 'Escape') {
event.stopPropagation();
this.requestClose('keyboard');
}
}
};
@watch('open', { waitUntilFirstUpdate: true })
async handleOpenChange() {

Wyświetl plik

@ -75,7 +75,7 @@ export default class SlDrawer extends ShoelaceElement {
private readonly hasSlotController = new HasSlotController(this, 'footer');
private readonly localize = new LocalizeController(this);
private modal: Modal;
private modal = new Modal(this);
private originalTrigger: HTMLElement | null;
@query('.drawer') drawer: HTMLElement;
@ -109,12 +109,6 @@ export default class SlDrawer extends ShoelaceElement {
*/
@property({ attribute: 'no-header', type: Boolean, reflect: true }) noHeader = false;
connectedCallback() {
super.connectedCallback();
this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);
this.modal = new Modal(this);
}
firstUpdated() {
this.drawer.hidden = !this.open;
@ -156,12 +150,12 @@ export default class SlDrawer extends ShoelaceElement {
document.removeEventListener('keydown', this.handleDocumentKeyDown);
}
private handleDocumentKeyDown(event: KeyboardEvent) {
private handleDocumentKeyDown = (event: KeyboardEvent) => {
if (this.open && !this.contained && event.key === 'Escape') {
event.stopPropagation();
this.requestClose('keyboard');
}
}
};
@watch('open', { waitUntilFirstUpdate: true })
async handleOpenChange() {

Wyświetl plik

@ -103,10 +103,6 @@ export default class SlDropdown extends ShoelaceElement {
connectedCallback() {
super.connectedCallback();
this.handlePanelSelect = this.handlePanelSelect.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);
this.handleDocumentMouseDown = this.handleDocumentMouseDown.bind(this);
if (!this.containingElement) {
this.containingElement = this;
@ -142,7 +138,7 @@ export default class SlDropdown extends ShoelaceElement {
| undefined;
}
handleKeyDown(event: KeyboardEvent) {
private handleKeyDown = (event: KeyboardEvent) => {
// Close when escape is pressed inside an open dropdown. We need to listen on the panel itself and stop propagation
// in case any ancestors are also listening for this key.
if (this.open && event.key === 'Escape') {
@ -150,9 +146,9 @@ export default class SlDropdown extends ShoelaceElement {
this.hide();
this.focusOnTrigger();
}
}
};
handleDocumentKeyDown(event: KeyboardEvent) {
private handleDocumentKeyDown = (event: KeyboardEvent) => {
// Close when escape or tab is pressed
if (event.key === 'Escape' && this.open) {
event.stopPropagation();
@ -189,17 +185,17 @@ export default class SlDropdown extends ShoelaceElement {
}
});
}
}
};
handleDocumentMouseDown(event: MouseEvent) {
private handleDocumentMouseDown = (event: MouseEvent) => {
// Close when clicking outside of the containing element
const path = event.composedPath();
if (this.containingElement && !path.includes(this.containingElement)) {
this.hide();
}
}
};
handlePanelSelect(event: SlSelectEvent) {
private handlePanelSelect = (event: SlSelectEvent) => {
const target = event.target as HTMLElement;
// Hide the dropdown when a menu item is selected
@ -207,7 +203,7 @@ export default class SlDropdown extends ShoelaceElement {
this.hide();
this.focusOnTrigger();
}
}
};
handleTriggerClick() {
if (this.open) {

Wyświetl plik

@ -48,17 +48,11 @@ export default class SlMenuItem extends ShoelaceElement {
/** Draws the menu item in a disabled state, preventing selection. */
@property({ type: Boolean, reflect: true }) disabled = false;
connectedCallback() {
super.connectedCallback();
this.handleHostClick = this.handleHostClick.bind(this);
constructor() {
super();
this.addEventListener('click', this.handleHostClick);
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('click', this.handleHostClick);
}
private handleDefaultSlotChange() {
const textLabel = this.getTextLabel();
@ -75,13 +69,13 @@ export default class SlMenuItem extends ShoelaceElement {
}
}
private handleHostClick(event: MouseEvent) {
private handleHostClick = (event: MouseEvent) => {
// Prevent the click event from being emitted when the button is disabled or loading
if (this.disabled) {
event.preventDefault();
event.stopImmediatePropagation();
}
}
};
@watch('checked')
handleCheckedChange() {

Wyświetl plik

@ -44,7 +44,6 @@ export default class SlMutationObserver extends ShoelaceElement {
connectedCallback() {
super.connectedCallback();
this.handleMutation = this.handleMutation.bind(this);
this.mutationObserver = new MutationObserver(this.handleMutation);
@ -57,11 +56,11 @@ export default class SlMutationObserver extends ShoelaceElement {
this.stopObserver();
}
private handleMutation(mutationList: MutationRecord[]) {
private handleMutation = (mutationList: MutationRecord[]) => {
this.emit('sl-mutation', {
detail: { mutationList }
});
}
};
private startObserver() {
const observeAttributes = typeof this.attr === 'string' && this.attr.length > 0;

Wyświetl plik

@ -45,47 +45,33 @@ export default class SlRadio extends ShoelaceElement {
/** Disables the radio. */
@property({ type: Boolean, reflect: true }) disabled = false;
connectedCallback() {
super.connectedCallback();
this.handleBlur = this.handleBlur.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.setInitialAttributes();
this.addEventListeners();
}
disconnectedCallback() {
this.removeEventListeners();
}
private addEventListeners() {
constructor() {
super();
this.addEventListener('blur', this.handleBlur);
this.addEventListener('click', this.handleClick);
this.addEventListener('focus', this.handleFocus);
}
private removeEventListeners() {
this.removeEventListener('blur', this.handleBlur);
this.removeEventListener('click', this.handleClick);
this.removeEventListener('focus', this.handleFocus);
connectedCallback() {
super.connectedCallback();
this.setInitialAttributes();
}
private handleBlur() {
private handleBlur = () => {
this.hasFocus = false;
this.emit('sl-blur');
}
};
private handleClick() {
private handleClick = () => {
if (!this.disabled) {
this.checked = true;
}
}
};
private handleFocus() {
private handleFocus = () => {
this.hasFocus = true;
this.emit('sl-focus');
}
};
private setInitialAttributes() {
this.setAttribute('role', 'radio');

Wyświetl plik

@ -180,9 +180,6 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
connectedCallback() {
super.connectedCallback();
this.handleDocumentFocusIn = this.handleDocumentFocusIn.bind(this);
this.handleDocumentKeyDown = this.handleDocumentKeyDown.bind(this);
this.handleDocumentMouseDown = this.handleDocumentMouseDown.bind(this);
// Because this is a form control, it shouldn't be opened initially
this.open = false;
@ -211,15 +208,15 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
this.emit('sl-blur');
}
private handleDocumentFocusIn(event: KeyboardEvent) {
private handleDocumentFocusIn = (event: KeyboardEvent) => {
// Close when focusing out of the select
const path = event.composedPath();
if (this && !path.includes(this)) {
this.hide();
}
}
};
private handleDocumentKeyDown(event: KeyboardEvent) {
private handleDocumentKeyDown = (event: KeyboardEvent) => {
const target = event.target as HTMLElement;
const isClearButton = target.closest('.select__clear') !== null;
const isIconButton = target.closest('sl-icon-button') !== null;
@ -346,15 +343,15 @@ export default class SlSelect extends ShoelaceElement implements ShoelaceFormCon
}
}
}
}
};
private handleDocumentMouseDown(event: MouseEvent) {
private handleDocumentMouseDown = (event: MouseEvent) => {
// Close when clicking outside of the select
const path = event.composedPath();
if (this && !path.includes(this)) {
this.hide();
}
}
};
private handleLabelClick() {
this.displayInput.focus();

Wyświetl plik

@ -70,7 +70,7 @@ export default class SlTabGroup extends ShoelaceElement {
@property({ attribute: 'no-scroll-controls', type: Boolean }) noScrollControls = false;
connectedCallback() {
const whenAllDefined = Promise.allSettled([
const whenAllDefined = Promise.all([
customElements.whenDefined('sl-tab'),
customElements.whenDefined('sl-tab-panel')
]);

Wyświetl plik

@ -98,23 +98,20 @@ export default class SlTooltip extends ShoelaceElement {
*/
@property({ type: Boolean }) hoist = false;
constructor() {
super();
// TODO (justinfagnani): does this need to be done in firstUpdated for some
// reason? If so, document why in a comment.
this.addEventListener('blur', this.handleBlur, true);
this.addEventListener('focus', this.handleFocus, true);
this.addEventListener('click', this.handleClick);
this.addEventListener('keydown', this.handleKeyDown);
this.addEventListener('mouseover', this.handleMouseOver);
this.addEventListener('mouseout', this.handleMouseOut);
}
connectedCallback() {
super.connectedCallback();
this.handleBlur = this.handleBlur.bind(this);
this.handleClick = this.handleClick.bind(this);
this.handleFocus = this.handleFocus.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleMouseOver = this.handleMouseOver.bind(this);
this.handleMouseOut = this.handleMouseOut.bind(this);
this.updateComplete.then(() => {
this.addEventListener('blur', this.handleBlur, true);
this.addEventListener('focus', this.handleFocus, true);
this.addEventListener('click', this.handleClick);
this.addEventListener('keydown', this.handleKeyDown);
this.addEventListener('mouseover', this.handleMouseOver);
this.addEventListener('mouseout', this.handleMouseOut);
});
}
firstUpdated() {
@ -127,23 +124,13 @@ export default class SlTooltip extends ShoelaceElement {
}
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener('blur', this.handleBlur, true);
this.removeEventListener('focus', this.handleFocus, true);
this.removeEventListener('click', this.handleClick);
this.removeEventListener('keydown', this.handleKeyDown);
this.removeEventListener('mouseover', this.handleMouseOver);
this.removeEventListener('mouseout', this.handleMouseOut);
}
private handleBlur() {
private handleBlur = () => {
if (this.hasTrigger('focus')) {
this.hide();
}
}
};
private handleClick() {
private handleClick = () => {
if (this.hasTrigger('click')) {
if (this.open) {
this.hide();
@ -151,37 +138,37 @@ export default class SlTooltip extends ShoelaceElement {
this.show();
}
}
}
};
private handleFocus() {
private handleFocus = () => {
if (this.hasTrigger('focus')) {
this.show();
}
}
};
private handleKeyDown(event: KeyboardEvent) {
private handleKeyDown = (event: KeyboardEvent) => {
// Pressing escape when the target element has focus should dismiss the tooltip
if (this.open && event.key === 'Escape') {
event.stopPropagation();
this.hide();
}
}
};
private handleMouseOver() {
private handleMouseOver = () => {
if (this.hasTrigger('hover')) {
const delay = parseDuration(getComputedStyle(this).getPropertyValue('--show-delay'));
clearTimeout(this.hoverTimeout);
this.hoverTimeout = window.setTimeout(() => this.show(), delay);
}
}
};
private handleMouseOut() {
private handleMouseOut = () => {
if (this.hasTrigger('hover')) {
const delay = parseDuration(getComputedStyle(this).getPropertyValue('--hide-delay'));
clearTimeout(this.hoverTimeout);
this.hoverTimeout = window.setTimeout(() => this.hide(), delay);
}
}
};
private hasTrigger(triggerType: string) {
const triggers = this.trigger.split(' ');

Wyświetl plik

@ -92,18 +92,18 @@ export default class SlTree extends ShoelaceElement {
private mutationObserver: MutationObserver;
private clickTarget: SlTreeItem | null = null;
async connectedCallback() {
super.connectedCallback();
this.handleTreeChanged = this.handleTreeChanged.bind(this);
this.handleFocusIn = this.handleFocusIn.bind(this);
this.handleFocusOut = this.handleFocusOut.bind(this);
this.setAttribute('role', 'tree');
this.setAttribute('tabindex', '0');
constructor() {
super();
this.addEventListener('focusin', this.handleFocusIn);
this.addEventListener('focusout', this.handleFocusOut);
this.addEventListener('sl-lazy-change', this.handleSlotChange);
}
async connectedCallback() {
super.connectedCallback();
this.setAttribute('role', 'tree');
this.setAttribute('tabindex', '0');
await this.updateComplete;
@ -115,10 +115,6 @@ export default class SlTree extends ShoelaceElement {
super.disconnectedCallback();
this.mutationObserver.disconnect();
this.removeEventListener('focusin', this.handleFocusIn);
this.removeEventListener('focusout', this.handleFocusOut);
this.removeEventListener('sl-lazy-change', this.handleSlotChange);
}
// Generates a clone of the expand icon element to use for each tree item
@ -160,7 +156,7 @@ export default class SlTree extends ShoelaceElement {
});
};
private handleTreeChanged(mutations: MutationRecord[]) {
private handleTreeChanged = (mutations: MutationRecord[]) => {
for (const mutation of mutations) {
const addedNodes: SlTreeItem[] = [...mutation.addedNodes].filter(SlTreeItem.isTreeItem) as SlTreeItem[];
const removedNodes = [...mutation.removedNodes].filter(SlTreeItem.isTreeItem) as SlTreeItem[];
@ -172,7 +168,7 @@ export default class SlTree extends ShoelaceElement {
this.focusItem(this.getFocusableItems()[0]);
}
}
}
};
private syncTreeItems(selectedItem: SlTreeItem) {
const items = this.getAllTreeItems();
@ -322,16 +318,16 @@ export default class SlTree extends ShoelaceElement {
this.clickTarget = event.target as SlTreeItem;
}
private handleFocusOut(event: FocusEvent) {
private handleFocusOut = (event: FocusEvent) => {
const relatedTarget = event.relatedTarget as HTMLElement;
// If the element that got the focus is not in the tree
if (!relatedTarget || !this.contains(relatedTarget)) {
this.tabIndex = 0;
}
}
};
private handleFocusIn(event: FocusEvent) {
private handleFocusIn = (event: FocusEvent) => {
const target = event.target as SlTreeItem;
// If the tree has been focused, move the focus to the last focused item
@ -349,7 +345,7 @@ export default class SlTree extends ShoelaceElement {
target.tabIndex = 0;
}
}
};
private handleSlotChange() {
const items = this.getAllTreeItems();