UNPKG

@vaadin/grid

Version:

A free, flexible and high-quality Web Component for showing large amounts of tabular data

131 lines (114 loc) 3.33 kB
/** * @license * Copyright (c) 2016 - 2026 Vaadin Ltd. * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/ */ /** * A mixin providing common sorter functionality. */ export const GridSorterMixin = (superClass) => class GridSorterMixinClass extends superClass { static get properties() { return { /** * JS Path of the property in the item used for sorting the data. */ path: { type: String, }, /** * How to sort the data. * Possible values are `asc` to use an ascending algorithm, `desc` to sort the data in * descending direction, or `null` for not sorting the data. */ direction: { type: String, reflectToAttribute: true, notify: true, value: null, sync: true, }, /** * @type {number | null} * @protected */ _order: { type: Number, value: null, sync: true, }, }; } static get observers() { return ['_pathOrDirectionChanged(path, direction)']; } /** @protected */ ready() { super.ready(); this.addEventListener('click', this._onClick.bind(this)); } /** @protected */ connectedCallback() { super.connectedCallback(); if (this._grid) { this._grid.__applySorters(); } else { this.__dispatchSorterChangedEvenIfPossible(); } } /** @protected */ disconnectedCallback() { super.disconnectedCallback(); if (!this.parentNode && this._grid) { this._grid.__removeSorters([this]); } else if (this._grid) { this._grid.__applySorters(); } } /** @private */ _pathOrDirectionChanged() { this.__dispatchSorterChangedEvenIfPossible(); } /** @private */ __dispatchSorterChangedEvenIfPossible() { if (this.path === undefined || this.direction === undefined || !this.isConnected) { return; } this.dispatchEvent( new CustomEvent('sorter-changed', { detail: { shiftClick: Boolean(this._shiftClick), fromSorterClick: Boolean(this._fromSorterClick) }, bubbles: true, composed: true, }), ); // Cleaning up as a programatically sorting can be done after some user interaction this._fromSorterClick = false; this._shiftClick = false; } /** @private */ _getDisplayOrder(order) { return order === null ? '' : order + 1; } /** @private */ _onClick(e) { if (e.defaultPrevented) { // Something else has already handled the click event, do nothing. return; } const activeElement = this.getRootNode().activeElement; if (this !== activeElement && this.contains(activeElement)) { // Some focusable content inside the sorter was clicked, do nothing. return; } e.preventDefault(); this._shiftClick = e.shiftKey; this._fromSorterClick = true; if (this.direction === 'asc') { this.direction = 'desc'; } else if (this.direction === 'desc') { this.direction = null; } else { this.direction = 'asc'; } } };