ngx-mat-table-multi-sort 18.0.0-pre.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # ngx-mat-table-multi-sort
2
+
3
+ An Angular library that adds multi-sort capability to the Angular Material table.
4
+
5
+ [![Continuous Integration](https://github.com/pgerke/ngx-mat-table-multi-sort/actions/workflows/ci.yml/badge.svg)](https://github.com/pgerke/ngx-mat-table-multi-sort/actions/workflows/ci.yml)
6
+ [![codecov](https://codecov.io/gh/pgerke/ngx-mat-table-multi-sort/graph/badge.svg?token=MDIEOFNUYR)](https://codecov.io/gh/pgerke/ngx-mat-table-multi-sort)
7
+ [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=pgerke_ngx-mat-table-multi-sort&metric=alert_status&token=1114974e75c8639e88919fd32d36163e5c3c851c)](https://sonarcloud.io/summary/new_code?id=pgerke_ngx-mat-table-multi-sort)
8
+ ![Dependencies](https://img.shields.io/librariesio/release/npm/ngx-mat-table-multi-sort)
9
+ ![npm](https://img.shields.io/npm/v/ngx-mat-table-multi-sort)
10
+ ![License](https://img.shields.io/github/license/pgerke/ngx-mat-table-multi-sort)
11
+
12
+ ## Features
13
+
14
+ - Extend the Angular Material Table to support multiple sorting
15
+ - Supports Angular 18 and 19. Supporting all actively supported Angular versions is planned (see [#5](https://github.com/pgerke/ngx-mat-table-multi-sort/issues/5))
16
+ - Batteries included: The repository contains a demo application that can help you integrate the library with your project
17
+ - 100% covered by automated unit tests and secured by static code analysis
18
+
19
+ ## How to use this library
20
+
21
+ **Prerequisite:** You have created an application using a supported version of Angular and Angular Material
22
+
23
+ 1. In your Angular application run `npm install ngx-mat-table-multi-sort` to add the library to your dependencies
24
+ 1. In the template, replace the `matSort` directive with the `matMultiSort` directive.
25
+ 1. Also replace the `mat-sort-header` directive with the `mat-multi-sort-header` directive in the column definitions.
26
+ 1. In the component definition use `MatMultiSortTableDataSource<T>` as your datasource type instead of `MatTableDataSource<T>`.
27
+ 1. Also change the type of the sorter from `MatSort` to `MatMultiSortDirective`
28
+ 1. If you are using standalone components, add the `MatMultiSortDirective` and `MatMultiSortHeaderComponent` to your component's imports array. Otherwise add them to the NgModule that declares your component.
29
+ 1. Done! 🎉
30
+
31
+ Enjoy multi-sorting your Angular Material data table!
32
+
33
+ ## Demo
34
+
35
+ The demo application is hosted on [GitHub pages](https://pgerke.github.io/ngx-mat-table-multi-sort/). You can also clone the repository and run the demo locally.
36
+
37
+ 1. Clone the repository to your local machine
38
+ 1. Run `npm install` to restore the dependencies
39
+ 1. Start the demo application by running `npm run start:demo`
40
+ 1. When compilation is completed, the application is running on `http://localhost:4200`
41
+
42
+ ## License
43
+
44
+ The project is subject to the MIT license unless otherwise noted. A copy can be found [here](./LICENSE.md).
45
+
46
+ ## Changelog
47
+
48
+ Please refer to the [changelog](./CHANGELOG.md) document or the [release notes](https://github.com/pgerke/ngx-mat-table-multi-sort/releases) in GitHub.
49
+
50
+ ## I found a bug, what do I do?
51
+
52
+ We are happy to hear any feedback regarding the library or its implementation, be it critizism, praise or rants. Please create a [GitHub issue](https://github.com/pgerke/ngx-mat-table-multi-sort/issues) if you would like to contact us.
53
+
54
+ We would especially appreciate, if you could report any issues you encounter while using the library. Issues we know about, we can probably fix.
55
+
56
+ If you want to submit a bug report, please check if the issue you have has already been reported. If you want to contribute additional information to the issue, please add it to the existing issue instead of creating another one. Duplicate issues will take time from bugfixing and thus delay a fix.
57
+
58
+ While creating a bug report, please make it easy for us to fix it by giving us all the details you have about the issue. Always include the version of the library and a short concise description of the issue. Besides that, there are a few other pieces of information that help tracking down bugs:
59
+
60
+ - The system environment in which the issue occurred (e.g. node version)
61
+ - Some steps to reproduce the issue, e.g. a code snippet
62
+ - The expected behaviour and how the failed failed to meet that expectation
63
+ - Anything else you think we might need
64
+
65
+ ## I have a feature request, what do I do?
66
+
67
+ Please create a [GitHub issue](https://github.com/pgerke/ngx-mat-table-multi-sort/issues)!
68
+
69
+ ## Acknowledgements
70
+
71
+ This library was inspired by the work in [ngx-multi-sort-table](https://github.com/Maxl94/ngx-multi-sort-table). While it was created from scratch and is an independent implementation tailored to specific use cases, their ideas and approach provided valuable guidance in its creation. Many thanks for their contributions to the open-source community!
72
+
73
+ <hr>
74
+
75
+ Made with ❤️ by [Michaela Andermann](https://github.com/michix99) and [Philip Gerke](https://github.com/pgerke)
@@ -0,0 +1,52 @@
1
+ import { NgIf } from "@angular/common";
2
+ import { Component, inject, ViewEncapsulation } from "@angular/core";
3
+ import { MatSort, MatSortHeader } from "@angular/material/sort";
4
+ import { MatMultiSortDirective } from "../mat-multi-sort.directive";
5
+ import * as i0 from "@angular/core";
6
+ export class MatMultiSortHeaderComponent extends MatSortHeader {
7
+ _sort = inject(MatMultiSortDirective, {
8
+ optional: true,
9
+ });
10
+ /**
11
+ * Retrieves the sort direction for the current column.
12
+ *
13
+ * @returns {SortDirection} The sort direction for the column identified by this.id.
14
+ */
15
+ get sortDirection() {
16
+ return this._sort.getSortDirection(this.id);
17
+ }
18
+ /**
19
+ * Gets the sort index for the current column.
20
+ *
21
+ * @returns {number} The index of the sort order for this column.
22
+ */
23
+ get sortIndex() {
24
+ return this._sort.getSortIndex(this.id);
25
+ }
26
+ _getAriaSortAttribute() {
27
+ if (!this._isSorted()) {
28
+ return "none";
29
+ }
30
+ return this.sortDirection === "asc" ? "ascending" : "descending";
31
+ }
32
+ _isSorted() {
33
+ return this.sortIndex > -1;
34
+ }
35
+ _toggleOnInteraction() {
36
+ if (this._isDisabled())
37
+ return;
38
+ super._toggleOnInteraction();
39
+ }
40
+ _updateArrowDirection() {
41
+ this._arrowDirection = this._isSorted()
42
+ ? this.sortDirection
43
+ : this.start || this._sort.start;
44
+ }
45
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
46
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: MatMultiSortHeaderComponent, isStandalone: true, selector: "[mat-multi-sort-header]", providers: [{ provide: MatSort, useExisting: MatMultiSortDirective }], exportAs: ["matMultiSortHeader"], usesInheritance: true, ngImport: i0, template: "<!--\n We set the `tabindex` on an element inside the table header, rather than the header itself,\n because of a bug in NVDA where having a `tabindex` on a `th` breaks keyboard navigation in the\n table (see https://github.com/nvaccess/nvda/issues/7718). This allows for the header to both\n be focusable, and have screen readers read out its `aria-sort` state. We prefer this approach\n over having a button with an `aria-label` inside the header, because the button's `aria-label`\n will be read out as the user is navigating the table's cell (see #13012).\n\n The approach is based off of: https://dequeuniversity.com/library/aria/tables/sf-sortable-grid\n-->\n<div\n class=\"mat-sort-header-container mat-focus-indicator\"\n [class.mat-sort-header-sorted]=\"_isSorted()\"\n [class.mat-sort-header-position-before]=\"arrowPosition === 'before'\"\n [attr.tabindex]=\"_isDisabled() ? null : 0\"\n [attr.role]=\"_isDisabled() ? null : 'button'\">\n <!--\n TODO(crisbeto): this div isn't strictly necessary, but we have to keep it due to a large\n number of screenshot diff failures. It should be removed eventually. Note that the difference\n isn't visible with a shorter header, but once it breaks up into multiple lines, this element\n causes it to be center-aligned, whereas removing it will keep the text to the left.\n -->\n <div class=\"mat-sort-header-content\">\n <ng-content></ng-content>\n </div>\n\n <!-- Disable animations while a current animation is running -->\n @if (_renderArrow()) {\n <div\n class=\"mat-sort-header-arrow\"\n [@arrowOpacity]=\"_getArrowViewState()\"\n [@arrowPosition]=\"_getArrowViewState()\"\n [@allowChildren]=\"_getArrowDirectionState()\"\n (@arrowPosition.start)=\"_disableViewStateAnimation = true\"\n (@arrowPosition.done)=\"_disableViewStateAnimation = false\">\n <div class=\"mat-sort-header-stem\"></div>\n <div\n class=\"mat-sort-header-indicator\"\n [@indicator]=\"_getArrowDirectionState()\">\n <div\n class=\"mat-sort-header-pointer-left\"\n [@leftPointer]=\"_getArrowDirectionState()\"></div>\n <div\n class=\"mat-sort-header-pointer-right\"\n [@rightPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-middle\"></div>\n </div>\n </div>\n }\n <div *ngIf=\"_isSorted()\" class=\"mat-sort-header-counter\">\n {{ sortIndex + 1 }}\n </div>\n</div>\n", styles: [".mat-sort-header-container{display:flex;cursor:pointer;align-items:center;letter-spacing:normal;outline:0}[mat-sort-header].cdk-keyboard-focused .mat-sort-header-container,[mat-sort-header].cdk-program-focused .mat-sort-header-container{border-bottom:solid 1px currentColor}.mat-sort-header-disabled .mat-sort-header-container{cursor:default}.mat-sort-header-container:before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px) * -1)}.mat-sort-header-content{text-align:center;display:flex;align-items:center}.mat-sort-header-position-before{flex-direction:row-reverse}.mat-sort-header-arrow{height:12px;width:12px;min-width:12px;position:relative;display:flex;color:var(--mat-sort-arrow-color, var(--mat-app-on-surface));opacity:0}.mat-sort-header-arrow,[dir=rtl] .mat-sort-header-position-before .mat-sort-header-arrow{margin:0 0 0 6px}.mat-sort-header-position-before .mat-sort-header-arrow,[dir=rtl] .mat-sort-header-arrow{margin:0 6px 0 0}.mat-sort-header-stem{background:currentColor;height:10px;width:2px;margin:auto;display:flex;align-items:center}.cdk-high-contrast-active .mat-sort-header-stem{width:0;border-left:solid 2px}.mat-sort-header-indicator{width:100%;height:2px;display:flex;align-items:center;position:absolute;top:0;left:0}.mat-sort-header-pointer-middle{margin:auto;height:2px;width:2px;background:currentColor;transform:rotate(45deg)}.cdk-high-contrast-active .mat-sort-header-pointer-middle{width:0;height:0;border-top:solid 2px;border-left:solid 2px}.mat-sort-header-pointer-left,.mat-sort-header-pointer-right{background:currentColor;width:6px;height:2px;position:absolute;top:0}.cdk-high-contrast-active .mat-sort-header-pointer-left,.cdk-high-contrast-active .mat-sort-header-pointer-right{width:0;height:0;border-left:solid 6px;border-top:solid 2px}.mat-sort-header-pointer-left{transform-origin:right;left:0}.mat-sort-header-pointer-right{transform-origin:left;right:0}.mat-sort-header-counter{color:var(--mat-sort-arrow-color, var(--mat-sys-on-surface))}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None });
47
+ }
48
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortHeaderComponent, decorators: [{
49
+ type: Component,
50
+ args: [{ selector: "[mat-multi-sort-header]", exportAs: "matMultiSortHeader", imports: [NgIf], providers: [{ provide: MatSort, useExisting: MatMultiSortDirective }], encapsulation: ViewEncapsulation.None, standalone: true, template: "<!--\n We set the `tabindex` on an element inside the table header, rather than the header itself,\n because of a bug in NVDA where having a `tabindex` on a `th` breaks keyboard navigation in the\n table (see https://github.com/nvaccess/nvda/issues/7718). This allows for the header to both\n be focusable, and have screen readers read out its `aria-sort` state. We prefer this approach\n over having a button with an `aria-label` inside the header, because the button's `aria-label`\n will be read out as the user is navigating the table's cell (see #13012).\n\n The approach is based off of: https://dequeuniversity.com/library/aria/tables/sf-sortable-grid\n-->\n<div\n class=\"mat-sort-header-container mat-focus-indicator\"\n [class.mat-sort-header-sorted]=\"_isSorted()\"\n [class.mat-sort-header-position-before]=\"arrowPosition === 'before'\"\n [attr.tabindex]=\"_isDisabled() ? null : 0\"\n [attr.role]=\"_isDisabled() ? null : 'button'\">\n <!--\n TODO(crisbeto): this div isn't strictly necessary, but we have to keep it due to a large\n number of screenshot diff failures. It should be removed eventually. Note that the difference\n isn't visible with a shorter header, but once it breaks up into multiple lines, this element\n causes it to be center-aligned, whereas removing it will keep the text to the left.\n -->\n <div class=\"mat-sort-header-content\">\n <ng-content></ng-content>\n </div>\n\n <!-- Disable animations while a current animation is running -->\n @if (_renderArrow()) {\n <div\n class=\"mat-sort-header-arrow\"\n [@arrowOpacity]=\"_getArrowViewState()\"\n [@arrowPosition]=\"_getArrowViewState()\"\n [@allowChildren]=\"_getArrowDirectionState()\"\n (@arrowPosition.start)=\"_disableViewStateAnimation = true\"\n (@arrowPosition.done)=\"_disableViewStateAnimation = false\">\n <div class=\"mat-sort-header-stem\"></div>\n <div\n class=\"mat-sort-header-indicator\"\n [@indicator]=\"_getArrowDirectionState()\">\n <div\n class=\"mat-sort-header-pointer-left\"\n [@leftPointer]=\"_getArrowDirectionState()\"></div>\n <div\n class=\"mat-sort-header-pointer-right\"\n [@rightPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-middle\"></div>\n </div>\n </div>\n }\n <div *ngIf=\"_isSorted()\" class=\"mat-sort-header-counter\">\n {{ sortIndex + 1 }}\n </div>\n</div>\n", styles: [".mat-sort-header-container{display:flex;cursor:pointer;align-items:center;letter-spacing:normal;outline:0}[mat-sort-header].cdk-keyboard-focused .mat-sort-header-container,[mat-sort-header].cdk-program-focused .mat-sort-header-container{border-bottom:solid 1px currentColor}.mat-sort-header-disabled .mat-sort-header-container{cursor:default}.mat-sort-header-container:before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px) * -1)}.mat-sort-header-content{text-align:center;display:flex;align-items:center}.mat-sort-header-position-before{flex-direction:row-reverse}.mat-sort-header-arrow{height:12px;width:12px;min-width:12px;position:relative;display:flex;color:var(--mat-sort-arrow-color, var(--mat-app-on-surface));opacity:0}.mat-sort-header-arrow,[dir=rtl] .mat-sort-header-position-before .mat-sort-header-arrow{margin:0 0 0 6px}.mat-sort-header-position-before .mat-sort-header-arrow,[dir=rtl] .mat-sort-header-arrow{margin:0 6px 0 0}.mat-sort-header-stem{background:currentColor;height:10px;width:2px;margin:auto;display:flex;align-items:center}.cdk-high-contrast-active .mat-sort-header-stem{width:0;border-left:solid 2px}.mat-sort-header-indicator{width:100%;height:2px;display:flex;align-items:center;position:absolute;top:0;left:0}.mat-sort-header-pointer-middle{margin:auto;height:2px;width:2px;background:currentColor;transform:rotate(45deg)}.cdk-high-contrast-active .mat-sort-header-pointer-middle{width:0;height:0;border-top:solid 2px;border-left:solid 2px}.mat-sort-header-pointer-left,.mat-sort-header-pointer-right{background:currentColor;width:6px;height:2px;position:absolute;top:0}.cdk-high-contrast-active .mat-sort-header-pointer-left,.cdk-high-contrast-active .mat-sort-header-pointer-right{width:0;height:0;border-left:solid 6px;border-top:solid 2px}.mat-sort-header-pointer-left{transform-origin:right;left:0}.mat-sort-header-pointer-right{transform-origin:left;right:0}.mat-sort-header-counter{color:var(--mat-sort-arrow-color, var(--mat-sys-on-surface))}\n"] }]
51
+ }] });
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LW11bHRpLXNvcnQtaGVhZGVyLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9saWIvbWF0LW11bHRpLXNvcnQtaGVhZGVyL21hdC1tdWx0aS1zb3J0LWhlYWRlci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL21hdC1tdWx0aS1zb3J0LWhlYWRlci9tYXQtbXVsdGktc29ydC1oZWFkZXIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFVLGlCQUFpQixFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFpQixNQUFNLHdCQUF3QixDQUFDO0FBQy9FLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDOztBQVlwRSxNQUFNLE9BQU8sMkJBQ1gsU0FBUSxhQUFhO0lBR0gsS0FBSyxHQUEwQixNQUFNLENBQ3JELHFCQUFxQixFQUNyQjtRQUNFLFFBQVEsRUFBRSxJQUFJO0tBQ2YsQ0FDRCxDQUFDO0lBRUg7Ozs7T0FJRztJQUNILElBQUksYUFBYTtRQUNmLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDOUMsQ0FBQztJQUVEOzs7O09BSUc7SUFDSCxJQUFJLFNBQVM7UUFDWCxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztJQUMxQyxDQUFDO0lBRVEscUJBQXFCO1FBQzVCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsQ0FBQztZQUN0QixPQUFPLE1BQU0sQ0FBQztRQUNoQixDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsYUFBYSxLQUFLLEtBQUssQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxZQUFZLENBQUM7SUFDbkUsQ0FBQztJQUVRLFNBQVM7UUFDaEIsT0FBTyxJQUFJLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzdCLENBQUM7SUFFUSxvQkFBb0I7UUFDM0IsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQUUsT0FBTztRQUUvQixLQUFLLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRVEscUJBQXFCO1FBQzVCLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFDLFNBQVMsRUFBRTtZQUNyQyxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWE7WUFDcEIsQ0FBQyxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7SUFDckMsQ0FBQzt3R0FuRFUsMkJBQTJCOzRGQUEzQiwyQkFBMkIsc0VBTjNCLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxxQkFBcUIsRUFBRSxDQUFDLG1GQ1R2RSw0N0VBcURBLGdoRUQ3Q1ksSUFBSTs7NEZBT0gsMkJBQTJCO2tCQVZ2QyxTQUFTOytCQUNFLHlCQUF5QixZQUN6QixvQkFBb0IsV0FDckIsQ0FBQyxJQUFJLENBQUMsYUFDSixDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxXQUFXLEVBQUUscUJBQXFCLEVBQUUsQ0FBQyxpQkFHdEQsaUJBQWlCLENBQUMsSUFBSSxjQUN6QixJQUFJIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTmdJZiB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcbmltcG9ydCB7IENvbXBvbmVudCwgaW5qZWN0LCBPbkluaXQsIFZpZXdFbmNhcHN1bGF0aW9uIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcbmltcG9ydCB7IE1hdFNvcnQsIE1hdFNvcnRIZWFkZXIsIFNvcnREaXJlY3Rpb24gfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvc29ydFwiO1xuaW1wb3J0IHsgTWF0TXVsdGlTb3J0RGlyZWN0aXZlIH0gZnJvbSBcIi4uL21hdC1tdWx0aS1zb3J0LmRpcmVjdGl2ZVwiO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6IFwiW21hdC1tdWx0aS1zb3J0LWhlYWRlcl1cIiwgLy8gZXNsaW50LWRpc2FibGUtbGluZSBAYW5ndWxhci1lc2xpbnQvY29tcG9uZW50LXNlbGVjdG9yXG4gIGV4cG9ydEFzOiBcIm1hdE11bHRpU29ydEhlYWRlclwiLFxuICBpbXBvcnRzOiBbTmdJZl0sXG4gIHByb3ZpZGVyczogW3sgcHJvdmlkZTogTWF0U29ydCwgdXNlRXhpc3Rpbmc6IE1hdE11bHRpU29ydERpcmVjdGl2ZSB9XSxcbiAgdGVtcGxhdGVVcmw6IFwiLi9tYXQtbXVsdGktc29ydC1oZWFkZXIuY29tcG9uZW50Lmh0bWxcIixcbiAgc3R5bGVVcmw6IFwiLi9tYXQtbXVsdGktc29ydC1oZWFkZXIuY29tcG9uZW50LnNjc3NcIixcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgTWF0TXVsdGlTb3J0SGVhZGVyQ29tcG9uZW50XG4gIGV4dGVuZHMgTWF0U29ydEhlYWRlclxuICBpbXBsZW1lbnRzIE9uSW5pdFxue1xuICBvdmVycmlkZSByZWFkb25seSBfc29ydDogTWF0TXVsdGlTb3J0RGlyZWN0aXZlID0gaW5qZWN0KFxuICAgIE1hdE11bHRpU29ydERpcmVjdGl2ZSxcbiAgICB7XG4gICAgICBvcHRpb25hbDogdHJ1ZSxcbiAgICB9XG4gICkhO1xuXG4gIC8qKlxuICAgKiBSZXRyaWV2ZXMgdGhlIHNvcnQgZGlyZWN0aW9uIGZvciB0aGUgY3VycmVudCBjb2x1bW4uXG4gICAqXG4gICAqIEByZXR1cm5zIHtTb3J0RGlyZWN0aW9ufSBUaGUgc29ydCBkaXJlY3Rpb24gZm9yIHRoZSBjb2x1bW4gaWRlbnRpZmllZCBieSB0aGlzLmlkLlxuICAgKi9cbiAgZ2V0IHNvcnREaXJlY3Rpb24oKTogU29ydERpcmVjdGlvbiB7XG4gICAgcmV0dXJuIHRoaXMuX3NvcnQuZ2V0U29ydERpcmVjdGlvbih0aGlzLmlkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXRzIHRoZSBzb3J0IGluZGV4IGZvciB0aGUgY3VycmVudCBjb2x1bW4uXG4gICAqXG4gICAqIEByZXR1cm5zIHtudW1iZXJ9IFRoZSBpbmRleCBvZiB0aGUgc29ydCBvcmRlciBmb3IgdGhpcyBjb2x1bW4uXG4gICAqL1xuICBnZXQgc29ydEluZGV4KCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3NvcnQuZ2V0U29ydEluZGV4KHRoaXMuaWQpO1xuICB9XG5cbiAgb3ZlcnJpZGUgX2dldEFyaWFTb3J0QXR0cmlidXRlKCk6IFwibm9uZVwiIHwgXCJhc2NlbmRpbmdcIiB8IFwiZGVzY2VuZGluZ1wiIHtcbiAgICBpZiAoIXRoaXMuX2lzU29ydGVkKCkpIHtcbiAgICAgIHJldHVybiBcIm5vbmVcIjtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zb3J0RGlyZWN0aW9uID09PSBcImFzY1wiID8gXCJhc2NlbmRpbmdcIiA6IFwiZGVzY2VuZGluZ1wiO1xuICB9XG5cbiAgb3ZlcnJpZGUgX2lzU29ydGVkKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnNvcnRJbmRleCA+IC0xO1xuICB9XG5cbiAgb3ZlcnJpZGUgX3RvZ2dsZU9uSW50ZXJhY3Rpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2lzRGlzYWJsZWQoKSkgcmV0dXJuO1xuXG4gICAgc3VwZXIuX3RvZ2dsZU9uSW50ZXJhY3Rpb24oKTtcbiAgfVxuXG4gIG92ZXJyaWRlIF91cGRhdGVBcnJvd0RpcmVjdGlvbigpOiB2b2lkIHtcbiAgICB0aGlzLl9hcnJvd0RpcmVjdGlvbiA9IHRoaXMuX2lzU29ydGVkKClcbiAgICAgID8gdGhpcy5zb3J0RGlyZWN0aW9uXG4gICAgICA6IHRoaXMuc3RhcnQgfHwgdGhpcy5fc29ydC5zdGFydDtcbiAgfVxufVxuIiwiPCEtLVxuICBXZSBzZXQgdGhlIGB0YWJpbmRleGAgb24gYW4gZWxlbWVudCBpbnNpZGUgdGhlIHRhYmxlIGhlYWRlciwgcmF0aGVyIHRoYW4gdGhlIGhlYWRlciBpdHNlbGYsXG4gIGJlY2F1c2Ugb2YgYSBidWcgaW4gTlZEQSB3aGVyZSBoYXZpbmcgYSBgdGFiaW5kZXhgIG9uIGEgYHRoYCBicmVha3Mga2V5Ym9hcmQgbmF2aWdhdGlvbiBpbiB0aGVcbiAgdGFibGUgKHNlZSBodHRwczovL2dpdGh1Yi5jb20vbnZhY2Nlc3MvbnZkYS9pc3N1ZXMvNzcxOCkuIFRoaXMgYWxsb3dzIGZvciB0aGUgaGVhZGVyIHRvIGJvdGhcbiAgYmUgZm9jdXNhYmxlLCBhbmQgaGF2ZSBzY3JlZW4gcmVhZGVycyByZWFkIG91dCBpdHMgYGFyaWEtc29ydGAgc3RhdGUuIFdlIHByZWZlciB0aGlzIGFwcHJvYWNoXG4gIG92ZXIgaGF2aW5nIGEgYnV0dG9uIHdpdGggYW4gYGFyaWEtbGFiZWxgIGluc2lkZSB0aGUgaGVhZGVyLCBiZWNhdXNlIHRoZSBidXR0b24ncyBgYXJpYS1sYWJlbGBcbiAgd2lsbCBiZSByZWFkIG91dCBhcyB0aGUgdXNlciBpcyBuYXZpZ2F0aW5nIHRoZSB0YWJsZSdzIGNlbGwgKHNlZSAjMTMwMTIpLlxuXG4gIFRoZSBhcHByb2FjaCBpcyBiYXNlZCBvZmYgb2Y6IGh0dHBzOi8vZGVxdWV1bml2ZXJzaXR5LmNvbS9saWJyYXJ5L2FyaWEvdGFibGVzL3NmLXNvcnRhYmxlLWdyaWRcbi0tPlxuPGRpdlxuICBjbGFzcz1cIm1hdC1zb3J0LWhlYWRlci1jb250YWluZXIgbWF0LWZvY3VzLWluZGljYXRvclwiXG4gIFtjbGFzcy5tYXQtc29ydC1oZWFkZXItc29ydGVkXT1cIl9pc1NvcnRlZCgpXCJcbiAgW2NsYXNzLm1hdC1zb3J0LWhlYWRlci1wb3NpdGlvbi1iZWZvcmVdPVwiYXJyb3dQb3NpdGlvbiA9PT0gJ2JlZm9yZSdcIlxuICBbYXR0ci50YWJpbmRleF09XCJfaXNEaXNhYmxlZCgpID8gbnVsbCA6IDBcIlxuICBbYXR0ci5yb2xlXT1cIl9pc0Rpc2FibGVkKCkgPyBudWxsIDogJ2J1dHRvbidcIj5cbiAgPCEtLVxuICAgIFRPRE8oY3Jpc2JldG8pOiB0aGlzIGRpdiBpc24ndCBzdHJpY3RseSBuZWNlc3NhcnksIGJ1dCB3ZSBoYXZlIHRvIGtlZXAgaXQgZHVlIHRvIGEgbGFyZ2VcbiAgICBudW1iZXIgb2Ygc2NyZWVuc2hvdCBkaWZmIGZhaWx1cmVzLiBJdCBzaG91bGQgYmUgcmVtb3ZlZCBldmVudHVhbGx5LiBOb3RlIHRoYXQgdGhlIGRpZmZlcmVuY2VcbiAgICBpc24ndCB2aXNpYmxlIHdpdGggYSBzaG9ydGVyIGhlYWRlciwgYnV0IG9uY2UgaXQgYnJlYWtzIHVwIGludG8gbXVsdGlwbGUgbGluZXMsIHRoaXMgZWxlbWVudFxuICAgIGNhdXNlcyBpdCB0byBiZSBjZW50ZXItYWxpZ25lZCwgd2hlcmVhcyByZW1vdmluZyBpdCB3aWxsIGtlZXAgdGhlIHRleHQgdG8gdGhlIGxlZnQuXG4gIC0tPlxuICA8ZGl2IGNsYXNzPVwibWF0LXNvcnQtaGVhZGVyLWNvbnRlbnRcIj5cbiAgICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG4gIDwvZGl2PlxuXG4gIDwhLS0gRGlzYWJsZSBhbmltYXRpb25zIHdoaWxlIGEgY3VycmVudCBhbmltYXRpb24gaXMgcnVubmluZyAtLT5cbiAgQGlmIChfcmVuZGVyQXJyb3coKSkge1xuICAgIDxkaXZcbiAgICAgIGNsYXNzPVwibWF0LXNvcnQtaGVhZGVyLWFycm93XCJcbiAgICAgIFtAYXJyb3dPcGFjaXR5XT1cIl9nZXRBcnJvd1ZpZXdTdGF0ZSgpXCJcbiAgICAgIFtAYXJyb3dQb3NpdGlvbl09XCJfZ2V0QXJyb3dWaWV3U3RhdGUoKVwiXG4gICAgICBbQGFsbG93Q2hpbGRyZW5dPVwiX2dldEFycm93RGlyZWN0aW9uU3RhdGUoKVwiXG4gICAgICAoQGFycm93UG9zaXRpb24uc3RhcnQpPVwiX2Rpc2FibGVWaWV3U3RhdGVBbmltYXRpb24gPSB0cnVlXCJcbiAgICAgIChAYXJyb3dQb3NpdGlvbi5kb25lKT1cIl9kaXNhYmxlVmlld1N0YXRlQW5pbWF0aW9uID0gZmFsc2VcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJtYXQtc29ydC1oZWFkZXItc3RlbVwiPjwvZGl2PlxuICAgICAgPGRpdlxuICAgICAgICBjbGFzcz1cIm1hdC1zb3J0LWhlYWRlci1pbmRpY2F0b3JcIlxuICAgICAgICBbQGluZGljYXRvcl09XCJfZ2V0QXJyb3dEaXJlY3Rpb25TdGF0ZSgpXCI+XG4gICAgICAgIDxkaXZcbiAgICAgICAgICBjbGFzcz1cIm1hdC1zb3J0LWhlYWRlci1wb2ludGVyLWxlZnRcIlxuICAgICAgICAgIFtAbGVmdFBvaW50ZXJdPVwiX2dldEFycm93RGlyZWN0aW9uU3RhdGUoKVwiPjwvZGl2PlxuICAgICAgICA8ZGl2XG4gICAgICAgICAgY2xhc3M9XCJtYXQtc29ydC1oZWFkZXItcG9pbnRlci1yaWdodFwiXG4gICAgICAgICAgW0ByaWdodFBvaW50ZXJdPVwiX2dldEFycm93RGlyZWN0aW9uU3RhdGUoKVwiPjwvZGl2PlxuICAgICAgICA8ZGl2IGNsYXNzPVwibWF0LXNvcnQtaGVhZGVyLXBvaW50ZXItbWlkZGxlXCI+PC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgfVxuICA8ZGl2ICpuZ0lmPVwiX2lzU29ydGVkKClcIiBjbGFzcz1cIm1hdC1zb3J0LWhlYWRlci1jb3VudGVyXCI+XG4gICAge3sgc29ydEluZGV4ICsgMSB9fVxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
@@ -0,0 +1,68 @@
1
+ import { MatTableDataSource } from "@angular/material/table";
2
+ /**
3
+ * Sorts two items based on multiple sorting criteria.
4
+ *
5
+ * @description To do this, we iterate over each sort level and compare the values of the active column. If the values are equal, we move to the next sort level. If all sort levels are equal, we return 0.
6
+ *
7
+ * @template T - The type of the items being sorted.
8
+ * @param {T} a - The first item to compare.
9
+ * @param {T} b - The second item to compare.
10
+ * @param {Sort[]} sorts - An array of sorting criteria, where each criterion specifies the property to sort by and the direction of sorting.
11
+ * @returns {number} - A negative number if `a` should come before `b`, a positive number if `a` should come after `b`, or 0 if they are considered equal.
12
+ */
13
+ export function MultiCriterionSort(a, b, sorts) {
14
+ for (const { active, direction } of sorts) {
15
+ const aValue = a[active];
16
+ const bValue = b[active];
17
+ const comparison = compareValues(aValue, bValue);
18
+ if (comparison !== 0) {
19
+ return direction === "desc" ? -comparison : comparison;
20
+ }
21
+ }
22
+ return 0; // If all comparisons are equal, preserve original order
23
+ }
24
+ function compareValues(aValue, bValue) {
25
+ if (aValue == null && bValue != null)
26
+ return 1;
27
+ if (aValue != null && bValue == null)
28
+ return -1;
29
+ if (aValue == null && bValue == null)
30
+ return 0;
31
+ if (typeof aValue === "string" && typeof bValue === "string") {
32
+ return aValue.localeCompare(bValue);
33
+ }
34
+ if (aValue > bValue)
35
+ return 1;
36
+ if (aValue < bValue)
37
+ return -1;
38
+ return 0;
39
+ }
40
+ /**
41
+ * A data source class that extends `MatTableDataSource` to support multi-column sorting.
42
+ *
43
+ * @template T The type of data that the table displays.
44
+ * @template P The type of paginator used, defaults to `MatPaginator`.
45
+ *
46
+ * @extends MatTableDataSource<T, P>
47
+ */
48
+ export class MatMultiSortTableDataSource extends MatTableDataSource {
49
+ get sort() {
50
+ return super.sort;
51
+ }
52
+ set sort(sort) {
53
+ super.sort = sort;
54
+ }
55
+ constructor(initialData) {
56
+ super(initialData);
57
+ // Set the default sort function
58
+ this.sortData = (data) => this.sortDataFunction(data);
59
+ }
60
+ sortDataFunction(data) {
61
+ // Return the data if there is no sort
62
+ if (!this.sort?._sorts.length)
63
+ return data;
64
+ // Sort the data:
65
+ return data.sort((a, b) => MultiCriterionSort(a, b, this.sort._sorts));
66
+ }
67
+ }
68
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LW11bHRpLXNvcnQtdGFibGUtZGF0YS1zb3VyY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvbGliL21hdC1tdWx0aS1zb3J0LXRhYmxlLWRhdGEtc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRzdEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLFVBQVUsa0JBQWtCLENBQUksQ0FBSSxFQUFFLENBQUksRUFBRSxLQUFhO0lBQzdELEtBQUssTUFBTSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUMxQyxNQUFNLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBaUIsQ0FBQyxDQUFDO1FBQ3BDLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBQyxNQUFpQixDQUFDLENBQUM7UUFFcEMsTUFBTSxVQUFVLEdBQUcsYUFBYSxDQUFDLE1BQU0sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUVqRCxJQUFJLFVBQVUsS0FBSyxDQUFDLEVBQUUsQ0FBQztZQUNyQixPQUFPLFNBQVMsS0FBSyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7UUFDekQsQ0FBQztJQUNILENBQUM7SUFFRCxPQUFPLENBQUMsQ0FBQyxDQUFDLHdEQUF3RDtBQUNwRSxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUksTUFBUyxFQUFFLE1BQVM7SUFDNUMsSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLE1BQU0sSUFBSSxJQUFJO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDL0MsSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLE1BQU0sSUFBSSxJQUFJO1FBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUNoRCxJQUFJLE1BQU0sSUFBSSxJQUFJLElBQUksTUFBTSxJQUFJLElBQUk7UUFBRSxPQUFPLENBQUMsQ0FBQztJQUUvQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLEVBQUUsQ0FBQztRQUM3RCxPQUFPLE1BQU0sQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQUksTUFBTSxHQUFHLE1BQU07UUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5QixJQUFJLE1BQU0sR0FBRyxNQUFNO1FBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztJQUMvQixPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxPQUFPLDJCQUdYLFNBQVEsa0JBQXdCO0lBQ2hDLElBQWEsSUFBSTtRQUNmLE9BQU8sS0FBSyxDQUFDLElBQTZCLENBQUM7SUFDN0MsQ0FBQztJQUNELElBQWEsSUFBSSxDQUFDLElBQWtDO1FBQ2xELEtBQUssQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxZQUFZLFdBQWlCO1FBQzNCLEtBQUssQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUNuQixnQ0FBZ0M7UUFDaEMsSUFBSSxDQUFDLFFBQVEsR0FBRyxDQUFDLElBQUksRUFBTyxFQUFFLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxJQUFTO1FBQ2hDLHNDQUFzQztRQUN0QyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsTUFBTTtZQUFFLE9BQU8sSUFBSSxDQUFDO1FBRTNDLGlCQUFpQjtRQUNqQixPQUFPLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxJQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUMxRSxDQUFDO0NBQ0YiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNYXRQYWdpbmF0b3IgfSBmcm9tIFwiQGFuZ3VsYXIvbWF0ZXJpYWwvcGFnaW5hdG9yXCI7XG5pbXBvcnQgeyBTb3J0IH0gZnJvbSBcIkBhbmd1bGFyL21hdGVyaWFsL3NvcnRcIjtcbmltcG9ydCB7IE1hdFRhYmxlRGF0YVNvdXJjZSB9IGZyb20gXCJAYW5ndWxhci9tYXRlcmlhbC90YWJsZVwiO1xuaW1wb3J0IHsgTWF0TXVsdGlTb3J0RGlyZWN0aXZlIH0gZnJvbSBcIi4vbWF0LW11bHRpLXNvcnQuZGlyZWN0aXZlXCI7XG5cbi8qKlxuICogU29ydHMgdHdvIGl0ZW1zIGJhc2VkIG9uIG11bHRpcGxlIHNvcnRpbmcgY3JpdGVyaWEuXG4gKlxuICogQGRlc2NyaXB0aW9uIFRvIGRvIHRoaXMsIHdlIGl0ZXJhdGUgb3ZlciBlYWNoIHNvcnQgbGV2ZWwgYW5kIGNvbXBhcmUgdGhlIHZhbHVlcyBvZiB0aGUgYWN0aXZlIGNvbHVtbi4gSWYgdGhlIHZhbHVlcyBhcmUgZXF1YWwsIHdlIG1vdmUgdG8gdGhlIG5leHQgc29ydCBsZXZlbC4gSWYgYWxsIHNvcnQgbGV2ZWxzIGFyZSBlcXVhbCwgd2UgcmV0dXJuIDAuXG4gKlxuICogQHRlbXBsYXRlIFQgLSBUaGUgdHlwZSBvZiB0aGUgaXRlbXMgYmVpbmcgc29ydGVkLlxuICogQHBhcmFtIHtUfSBhIC0gVGhlIGZpcnN0IGl0ZW0gdG8gY29tcGFyZS5cbiAqIEBwYXJhbSB7VH0gYiAtIFRoZSBzZWNvbmQgaXRlbSB0byBjb21wYXJlLlxuICogQHBhcmFtIHtTb3J0W119IHNvcnRzIC0gQW4gYXJyYXkgb2Ygc29ydGluZyBjcml0ZXJpYSwgd2hlcmUgZWFjaCBjcml0ZXJpb24gc3BlY2lmaWVzIHRoZSBwcm9wZXJ0eSB0byBzb3J0IGJ5IGFuZCB0aGUgZGlyZWN0aW9uIG9mIHNvcnRpbmcuXG4gKiBAcmV0dXJucyB7bnVtYmVyfSAtIEEgbmVnYXRpdmUgbnVtYmVyIGlmIGBhYCBzaG91bGQgY29tZSBiZWZvcmUgYGJgLCBhIHBvc2l0aXZlIG51bWJlciBpZiBgYWAgc2hvdWxkIGNvbWUgYWZ0ZXIgYGJgLCBvciAwIGlmIHRoZXkgYXJlIGNvbnNpZGVyZWQgZXF1YWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBNdWx0aUNyaXRlcmlvblNvcnQ8VD4oYTogVCwgYjogVCwgc29ydHM6IFNvcnRbXSk6IG51bWJlciB7XG4gIGZvciAoY29uc3QgeyBhY3RpdmUsIGRpcmVjdGlvbiB9IG9mIHNvcnRzKSB7XG4gICAgY29uc3QgYVZhbHVlID0gYVthY3RpdmUgYXMga2V5b2YgVF07XG4gICAgY29uc3QgYlZhbHVlID0gYlthY3RpdmUgYXMga2V5b2YgVF07XG5cbiAgICBjb25zdCBjb21wYXJpc29uID0gY29tcGFyZVZhbHVlcyhhVmFsdWUsIGJWYWx1ZSk7XG5cbiAgICBpZiAoY29tcGFyaXNvbiAhPT0gMCkge1xuICAgICAgcmV0dXJuIGRpcmVjdGlvbiA9PT0gXCJkZXNjXCIgPyAtY29tcGFyaXNvbiA6IGNvbXBhcmlzb247XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIDA7IC8vIElmIGFsbCBjb21wYXJpc29ucyBhcmUgZXF1YWwsIHByZXNlcnZlIG9yaWdpbmFsIG9yZGVyXG59XG5cbmZ1bmN0aW9uIGNvbXBhcmVWYWx1ZXM8VD4oYVZhbHVlOiBULCBiVmFsdWU6IFQpOiBudW1iZXIge1xuICBpZiAoYVZhbHVlID09IG51bGwgJiYgYlZhbHVlICE9IG51bGwpIHJldHVybiAxO1xuICBpZiAoYVZhbHVlICE9IG51bGwgJiYgYlZhbHVlID09IG51bGwpIHJldHVybiAtMTtcbiAgaWYgKGFWYWx1ZSA9PSBudWxsICYmIGJWYWx1ZSA9PSBudWxsKSByZXR1cm4gMDtcblxuICBpZiAodHlwZW9mIGFWYWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB0eXBlb2YgYlZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIGFWYWx1ZS5sb2NhbGVDb21wYXJlKGJWYWx1ZSk7XG4gIH1cblxuICBpZiAoYVZhbHVlID4gYlZhbHVlKSByZXR1cm4gMTtcbiAgaWYgKGFWYWx1ZSA8IGJWYWx1ZSkgcmV0dXJuIC0xO1xuICByZXR1cm4gMDtcbn1cblxuLyoqXG4gKiBBIGRhdGEgc291cmNlIGNsYXNzIHRoYXQgZXh0ZW5kcyBgTWF0VGFibGVEYXRhU291cmNlYCB0byBzdXBwb3J0IG11bHRpLWNvbHVtbiBzb3J0aW5nLlxuICpcbiAqIEB0ZW1wbGF0ZSBUIFRoZSB0eXBlIG9mIGRhdGEgdGhhdCB0aGUgdGFibGUgZGlzcGxheXMuXG4gKiBAdGVtcGxhdGUgUCBUaGUgdHlwZSBvZiBwYWdpbmF0b3IgdXNlZCwgZGVmYXVsdHMgdG8gYE1hdFBhZ2luYXRvcmAuXG4gKlxuICogQGV4dGVuZHMgTWF0VGFibGVEYXRhU291cmNlPFQsIFA+XG4gKi9cbmV4cG9ydCBjbGFzcyBNYXRNdWx0aVNvcnRUYWJsZURhdGFTb3VyY2U8XG4gIFQsXG4gIFAgZXh0ZW5kcyBNYXRQYWdpbmF0b3IgPSBNYXRQYWdpbmF0b3IsXG4+IGV4dGVuZHMgTWF0VGFibGVEYXRhU291cmNlPFQsIFA+IHtcbiAgb3ZlcnJpZGUgZ2V0IHNvcnQoKTogTWF0TXVsdGlTb3J0RGlyZWN0aXZlIHwgbnVsbCB7XG4gICAgcmV0dXJuIHN1cGVyLnNvcnQgYXMgTWF0TXVsdGlTb3J0RGlyZWN0aXZlO1xuICB9XG4gIG92ZXJyaWRlIHNldCBzb3J0KHNvcnQ6IE1hdE11bHRpU29ydERpcmVjdGl2ZSB8IG51bGwpIHtcbiAgICBzdXBlci5zb3J0ID0gc29ydDtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKGluaXRpYWxEYXRhPzogVFtdKSB7XG4gICAgc3VwZXIoaW5pdGlhbERhdGEpO1xuICAgIC8vIFNldCB0aGUgZGVmYXVsdCBzb3J0IGZ1bmN0aW9uXG4gICAgdGhpcy5zb3J0RGF0YSA9IChkYXRhKTogVFtdID0+IHRoaXMuc29ydERhdGFGdW5jdGlvbihkYXRhKTtcbiAgfVxuXG4gIHByaXZhdGUgc29ydERhdGFGdW5jdGlvbihkYXRhOiBUW10pOiBUW10ge1xuICAgIC8vIFJldHVybiB0aGUgZGF0YSBpZiB0aGVyZSBpcyBubyBzb3J0XG4gICAgaWYgKCF0aGlzLnNvcnQ/Ll9zb3J0cy5sZW5ndGgpIHJldHVybiBkYXRhO1xuXG4gICAgLy8gU29ydCB0aGUgZGF0YTpcbiAgICByZXR1cm4gZGF0YS5zb3J0KChhLCBiKSA9PiBNdWx0aUNyaXRlcmlvblNvcnQoYSwgYiwgdGhpcy5zb3J0IS5fc29ydHMpKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,60 @@
1
+ import { Directive } from "@angular/core";
2
+ import { MatSort, } from "@angular/material/sort";
3
+ import * as i0 from "@angular/core";
4
+ export class MatMultiSortDirective extends MatSort {
5
+ _sorts = [];
6
+ /**
7
+ * Retrieves the sort direction for a given column ID.
8
+ *
9
+ * @param id - The ID of the column to get the sort direction for.
10
+ * @returns The sort direction ('asc', 'desc', or '') for the specified column ID.
11
+ */
12
+ getSortDirection(id) {
13
+ const sort = this._sorts.find((e) => e.active === id);
14
+ return sort ? sort.direction : "";
15
+ }
16
+ /**
17
+ * Gets the sort index of the given column ID.
18
+ *
19
+ * @param id - The ID of the column to get the sort index for.
20
+ * @returns The sort index of the column, or -1 if the column is not active.
21
+ */
22
+ getSortIndex(id) {
23
+ return this._sorts.findIndex((e) => e.active === id);
24
+ }
25
+ sort(sortable) {
26
+ this.active = sortable.id;
27
+ this.direction = this.getSortDirection(sortable.id);
28
+ const index = this.getSortIndex(sortable.id);
29
+ // If the column is not active, add it to the list of active columns.
30
+ if (index < 0) {
31
+ this.direction = sortable.start ? sortable.start : this.start;
32
+ this._sorts.push({ active: this.active, direction: this.direction });
33
+ }
34
+ else {
35
+ // If the column is active, update the direction or remove it if the direction is empty.
36
+ this.direction = this.getNextSortDirection(sortable);
37
+ if (!this.direction) {
38
+ this._sorts.splice(index, 1);
39
+ }
40
+ else {
41
+ this._sorts[index].direction = this.direction;
42
+ }
43
+ }
44
+ this.sortChange.emit({ active: this.active, direction: this.direction });
45
+ }
46
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
47
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: MatMultiSortDirective, isStandalone: true, selector: "[matMultiSort]", host: { classAttribute: "mat-sort" }, exportAs: ["matMultiSort"], usesInheritance: true, ngImport: i0 });
48
+ }
49
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortDirective, decorators: [{
50
+ type: Directive,
51
+ args: [{
52
+ selector: "[matMultiSort]",
53
+ exportAs: "matMultiSort",
54
+ host: {
55
+ class: "mat-sort",
56
+ },
57
+ standalone: true,
58
+ }]
59
+ }] });
60
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWF0LW11bHRpLXNvcnQuZGlyZWN0aXZlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9tYXQtbXVsdGktc29ydC5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxQyxPQUFPLEVBQ0wsT0FBTyxHQUlSLE1BQU0sd0JBQXdCLENBQUM7O0FBVWhDLE1BQU0sT0FBTyxxQkFBc0IsU0FBUSxPQUFPO0lBQ3ZDLE1BQU0sR0FBVyxFQUFFLENBQUM7SUFFN0I7Ozs7O09BS0c7SUFDSCxnQkFBZ0IsQ0FBQyxFQUFVO1FBQ3pCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsTUFBTSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1FBQ3RELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksWUFBWSxDQUFDLEVBQVU7UUFDNUIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxFQUFFLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRVEsSUFBSSxDQUFDLFFBQXFCO1FBQ2pDLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUMxQixJQUFJLENBQUMsU0FBUyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFN0MscUVBQXFFO1FBQ3JFLElBQUksS0FBSyxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1lBQzlELElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZFLENBQUM7YUFBTSxDQUFDO1lBQ04sd0ZBQXdGO1lBQ3hGLElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ3JELElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7Z0JBQ3BCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztZQUMvQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQztZQUNoRCxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDO0lBQzNFLENBQUM7d0dBNUNVLHFCQUFxQjs0RkFBckIscUJBQXFCOzs0RkFBckIscUJBQXFCO2tCQVJqQyxTQUFTO21CQUFDO29CQUNULFFBQVEsRUFBRSxnQkFBZ0I7b0JBQzFCLFFBQVEsRUFBRSxjQUFjO29CQUN4QixJQUFJLEVBQUU7d0JBQ0osS0FBSyxFQUFFLFVBQVU7cUJBQ2xCO29CQUNELFVBQVUsRUFBRSxJQUFJO2lCQUNqQiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IERpcmVjdGl2ZSB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XG5pbXBvcnQge1xuICBNYXRTb3J0LFxuICBNYXRTb3J0YWJsZSxcbiAgU29ydCxcbiAgU29ydERpcmVjdGlvbixcbn0gZnJvbSBcIkBhbmd1bGFyL21hdGVyaWFsL3NvcnRcIjtcblxuQERpcmVjdGl2ZSh7XG4gIHNlbGVjdG9yOiBcIlttYXRNdWx0aVNvcnRdXCIsXG4gIGV4cG9ydEFzOiBcIm1hdE11bHRpU29ydFwiLFxuICBob3N0OiB7XG4gICAgY2xhc3M6IFwibWF0LXNvcnRcIixcbiAgfSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgTWF0TXVsdGlTb3J0RGlyZWN0aXZlIGV4dGVuZHMgTWF0U29ydCB7XG4gIHJlYWRvbmx5IF9zb3J0czogU29ydFtdID0gW107XG5cbiAgLyoqXG4gICAqIFJldHJpZXZlcyB0aGUgc29ydCBkaXJlY3Rpb24gZm9yIGEgZ2l2ZW4gY29sdW1uIElELlxuICAgKlxuICAgKiBAcGFyYW0gaWQgLSBUaGUgSUQgb2YgdGhlIGNvbHVtbiB0byBnZXQgdGhlIHNvcnQgZGlyZWN0aW9uIGZvci5cbiAgICogQHJldHVybnMgVGhlIHNvcnQgZGlyZWN0aW9uICgnYXNjJywgJ2Rlc2MnLCBvciAnJykgZm9yIHRoZSBzcGVjaWZpZWQgY29sdW1uIElELlxuICAgKi9cbiAgZ2V0U29ydERpcmVjdGlvbihpZDogc3RyaW5nKTogU29ydERpcmVjdGlvbiB7XG4gICAgY29uc3Qgc29ydCA9IHRoaXMuX3NvcnRzLmZpbmQoKGUpID0+IGUuYWN0aXZlID09PSBpZCk7XG4gICAgcmV0dXJuIHNvcnQgPyBzb3J0LmRpcmVjdGlvbiA6IFwiXCI7XG4gIH1cblxuICAvKipcbiAgICogR2V0cyB0aGUgc29ydCBpbmRleCBvZiB0aGUgZ2l2ZW4gY29sdW1uIElELlxuICAgKlxuICAgKiBAcGFyYW0gaWQgLSBUaGUgSUQgb2YgdGhlIGNvbHVtbiB0byBnZXQgdGhlIHNvcnQgaW5kZXggZm9yLlxuICAgKiBAcmV0dXJucyBUaGUgc29ydCBpbmRleCBvZiB0aGUgY29sdW1uLCBvciAtMSBpZiB0aGUgY29sdW1uIGlzIG5vdCBhY3RpdmUuXG4gICAqL1xuICBwdWJsaWMgZ2V0U29ydEluZGV4KGlkOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9zb3J0cy5maW5kSW5kZXgoKGUpID0+IGUuYWN0aXZlID09PSBpZCk7XG4gIH1cblxuICBvdmVycmlkZSBzb3J0KHNvcnRhYmxlOiBNYXRTb3J0YWJsZSk6IHZvaWQge1xuICAgIHRoaXMuYWN0aXZlID0gc29ydGFibGUuaWQ7XG4gICAgdGhpcy5kaXJlY3Rpb24gPSB0aGlzLmdldFNvcnREaXJlY3Rpb24oc29ydGFibGUuaWQpO1xuICAgIGNvbnN0IGluZGV4ID0gdGhpcy5nZXRTb3J0SW5kZXgoc29ydGFibGUuaWQpO1xuXG4gICAgLy8gSWYgdGhlIGNvbHVtbiBpcyBub3QgYWN0aXZlLCBhZGQgaXQgdG8gdGhlIGxpc3Qgb2YgYWN0aXZlIGNvbHVtbnMuXG4gICAgaWYgKGluZGV4IDwgMCkge1xuICAgICAgdGhpcy5kaXJlY3Rpb24gPSBzb3J0YWJsZS5zdGFydCA/IHNvcnRhYmxlLnN0YXJ0IDogdGhpcy5zdGFydDtcbiAgICAgIHRoaXMuX3NvcnRzLnB1c2goeyBhY3RpdmU6IHRoaXMuYWN0aXZlLCBkaXJlY3Rpb246IHRoaXMuZGlyZWN0aW9uIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB0aGUgY29sdW1uIGlzIGFjdGl2ZSwgdXBkYXRlIHRoZSBkaXJlY3Rpb24gb3IgcmVtb3ZlIGl0IGlmIHRoZSBkaXJlY3Rpb24gaXMgZW1wdHkuXG4gICAgICB0aGlzLmRpcmVjdGlvbiA9IHRoaXMuZ2V0TmV4dFNvcnREaXJlY3Rpb24oc29ydGFibGUpO1xuICAgICAgaWYgKCF0aGlzLmRpcmVjdGlvbikge1xuICAgICAgICB0aGlzLl9zb3J0cy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5fc29ydHNbaW5kZXhdLmRpcmVjdGlvbiA9IHRoaXMuZGlyZWN0aW9uO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuc29ydENoYW5nZS5lbWl0KHsgYWN0aXZlOiB0aGlzLmFjdGl2ZSwgZGlyZWN0aW9uOiB0aGlzLmRpcmVjdGlvbiB9KTtcbiAgfVxufVxuIl19
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ export * from './public-api';
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LW1hdC10YWJsZS1tdWx0aS1zb3J0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL25neC1tYXQtdGFibGUtbXVsdGktc29ydC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsY0FBYyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBHZW5lcmF0ZWQgYnVuZGxlIGluZGV4LiBEbyBub3QgZWRpdC5cbiAqL1xuXG5leHBvcnQgKiBmcm9tICcuL3B1YmxpYy1hcGknO1xuIl19
@@ -0,0 +1,7 @@
1
+ /*
2
+ * Public API Surface of lib
3
+ */
4
+ export * from "./lib/mat-multi-sort.directive";
5
+ export * from "./lib/mat-multi-sort-table-data-source";
6
+ export * from "./lib/mat-multi-sort-header/mat-multi-sort-header.component";
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wdWJsaWMtYXBpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBRUgsY0FBYyxnQ0FBZ0MsQ0FBQztBQUMvQyxjQUFjLHdDQUF3QyxDQUFDO0FBQ3ZELGNBQWMsNkRBQTZELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogUHVibGljIEFQSSBTdXJmYWNlIG9mIGxpYlxuICovXG5cbmV4cG9ydCAqIGZyb20gXCIuL2xpYi9tYXQtbXVsdGktc29ydC5kaXJlY3RpdmVcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2xpYi9tYXQtbXVsdGktc29ydC10YWJsZS1kYXRhLXNvdXJjZVwiO1xuZXhwb3J0ICogZnJvbSBcIi4vbGliL21hdC1tdWx0aS1zb3J0LWhlYWRlci9tYXQtbXVsdGktc29ydC1oZWFkZXIuY29tcG9uZW50XCI7XG4iXX0=
@@ -0,0 +1,187 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Directive, inject, Component, ViewEncapsulation } from '@angular/core';
3
+ import { MatSort, MatSortHeader } from '@angular/material/sort';
4
+ import { MatTableDataSource } from '@angular/material/table';
5
+ import { NgIf } from '@angular/common';
6
+
7
+ class MatMultiSortDirective extends MatSort {
8
+ _sorts = [];
9
+ /**
10
+ * Retrieves the sort direction for a given column ID.
11
+ *
12
+ * @param id - The ID of the column to get the sort direction for.
13
+ * @returns The sort direction ('asc', 'desc', or '') for the specified column ID.
14
+ */
15
+ getSortDirection(id) {
16
+ const sort = this._sorts.find((e) => e.active === id);
17
+ return sort ? sort.direction : "";
18
+ }
19
+ /**
20
+ * Gets the sort index of the given column ID.
21
+ *
22
+ * @param id - The ID of the column to get the sort index for.
23
+ * @returns The sort index of the column, or -1 if the column is not active.
24
+ */
25
+ getSortIndex(id) {
26
+ return this._sorts.findIndex((e) => e.active === id);
27
+ }
28
+ sort(sortable) {
29
+ this.active = sortable.id;
30
+ this.direction = this.getSortDirection(sortable.id);
31
+ const index = this.getSortIndex(sortable.id);
32
+ // If the column is not active, add it to the list of active columns.
33
+ if (index < 0) {
34
+ this.direction = sortable.start ? sortable.start : this.start;
35
+ this._sorts.push({ active: this.active, direction: this.direction });
36
+ }
37
+ else {
38
+ // If the column is active, update the direction or remove it if the direction is empty.
39
+ this.direction = this.getNextSortDirection(sortable);
40
+ if (!this.direction) {
41
+ this._sorts.splice(index, 1);
42
+ }
43
+ else {
44
+ this._sorts[index].direction = this.direction;
45
+ }
46
+ }
47
+ this.sortChange.emit({ active: this.active, direction: this.direction });
48
+ }
49
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
50
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.13", type: MatMultiSortDirective, isStandalone: true, selector: "[matMultiSort]", host: { classAttribute: "mat-sort" }, exportAs: ["matMultiSort"], usesInheritance: true, ngImport: i0 });
51
+ }
52
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortDirective, decorators: [{
53
+ type: Directive,
54
+ args: [{
55
+ selector: "[matMultiSort]",
56
+ exportAs: "matMultiSort",
57
+ host: {
58
+ class: "mat-sort",
59
+ },
60
+ standalone: true,
61
+ }]
62
+ }] });
63
+
64
+ /**
65
+ * Sorts two items based on multiple sorting criteria.
66
+ *
67
+ * @description To do this, we iterate over each sort level and compare the values of the active column. If the values are equal, we move to the next sort level. If all sort levels are equal, we return 0.
68
+ *
69
+ * @template T - The type of the items being sorted.
70
+ * @param {T} a - The first item to compare.
71
+ * @param {T} b - The second item to compare.
72
+ * @param {Sort[]} sorts - An array of sorting criteria, where each criterion specifies the property to sort by and the direction of sorting.
73
+ * @returns {number} - A negative number if `a` should come before `b`, a positive number if `a` should come after `b`, or 0 if they are considered equal.
74
+ */
75
+ function MultiCriterionSort(a, b, sorts) {
76
+ for (const { active, direction } of sorts) {
77
+ const aValue = a[active];
78
+ const bValue = b[active];
79
+ const comparison = compareValues(aValue, bValue);
80
+ if (comparison !== 0) {
81
+ return direction === "desc" ? -comparison : comparison;
82
+ }
83
+ }
84
+ return 0; // If all comparisons are equal, preserve original order
85
+ }
86
+ function compareValues(aValue, bValue) {
87
+ if (aValue == null && bValue != null)
88
+ return 1;
89
+ if (aValue != null && bValue == null)
90
+ return -1;
91
+ if (aValue == null && bValue == null)
92
+ return 0;
93
+ if (typeof aValue === "string" && typeof bValue === "string") {
94
+ return aValue.localeCompare(bValue);
95
+ }
96
+ if (aValue > bValue)
97
+ return 1;
98
+ if (aValue < bValue)
99
+ return -1;
100
+ return 0;
101
+ }
102
+ /**
103
+ * A data source class that extends `MatTableDataSource` to support multi-column sorting.
104
+ *
105
+ * @template T The type of data that the table displays.
106
+ * @template P The type of paginator used, defaults to `MatPaginator`.
107
+ *
108
+ * @extends MatTableDataSource<T, P>
109
+ */
110
+ class MatMultiSortTableDataSource extends MatTableDataSource {
111
+ get sort() {
112
+ return super.sort;
113
+ }
114
+ set sort(sort) {
115
+ super.sort = sort;
116
+ }
117
+ constructor(initialData) {
118
+ super(initialData);
119
+ // Set the default sort function
120
+ this.sortData = (data) => this.sortDataFunction(data);
121
+ }
122
+ sortDataFunction(data) {
123
+ // Return the data if there is no sort
124
+ if (!this.sort?._sorts.length)
125
+ return data;
126
+ // Sort the data:
127
+ return data.sort((a, b) => MultiCriterionSort(a, b, this.sort._sorts));
128
+ }
129
+ }
130
+
131
+ class MatMultiSortHeaderComponent extends MatSortHeader {
132
+ _sort = inject(MatMultiSortDirective, {
133
+ optional: true,
134
+ });
135
+ /**
136
+ * Retrieves the sort direction for the current column.
137
+ *
138
+ * @returns {SortDirection} The sort direction for the column identified by this.id.
139
+ */
140
+ get sortDirection() {
141
+ return this._sort.getSortDirection(this.id);
142
+ }
143
+ /**
144
+ * Gets the sort index for the current column.
145
+ *
146
+ * @returns {number} The index of the sort order for this column.
147
+ */
148
+ get sortIndex() {
149
+ return this._sort.getSortIndex(this.id);
150
+ }
151
+ _getAriaSortAttribute() {
152
+ if (!this._isSorted()) {
153
+ return "none";
154
+ }
155
+ return this.sortDirection === "asc" ? "ascending" : "descending";
156
+ }
157
+ _isSorted() {
158
+ return this.sortIndex > -1;
159
+ }
160
+ _toggleOnInteraction() {
161
+ if (this._isDisabled())
162
+ return;
163
+ super._toggleOnInteraction();
164
+ }
165
+ _updateArrowDirection() {
166
+ this._arrowDirection = this._isSorted()
167
+ ? this.sortDirection
168
+ : this.start || this._sort.start;
169
+ }
170
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortHeaderComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
171
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: MatMultiSortHeaderComponent, isStandalone: true, selector: "[mat-multi-sort-header]", providers: [{ provide: MatSort, useExisting: MatMultiSortDirective }], exportAs: ["matMultiSortHeader"], usesInheritance: true, ngImport: i0, template: "<!--\n We set the `tabindex` on an element inside the table header, rather than the header itself,\n because of a bug in NVDA where having a `tabindex` on a `th` breaks keyboard navigation in the\n table (see https://github.com/nvaccess/nvda/issues/7718). This allows for the header to both\n be focusable, and have screen readers read out its `aria-sort` state. We prefer this approach\n over having a button with an `aria-label` inside the header, because the button's `aria-label`\n will be read out as the user is navigating the table's cell (see #13012).\n\n The approach is based off of: https://dequeuniversity.com/library/aria/tables/sf-sortable-grid\n-->\n<div\n class=\"mat-sort-header-container mat-focus-indicator\"\n [class.mat-sort-header-sorted]=\"_isSorted()\"\n [class.mat-sort-header-position-before]=\"arrowPosition === 'before'\"\n [attr.tabindex]=\"_isDisabled() ? null : 0\"\n [attr.role]=\"_isDisabled() ? null : 'button'\">\n <!--\n TODO(crisbeto): this div isn't strictly necessary, but we have to keep it due to a large\n number of screenshot diff failures. It should be removed eventually. Note that the difference\n isn't visible with a shorter header, but once it breaks up into multiple lines, this element\n causes it to be center-aligned, whereas removing it will keep the text to the left.\n -->\n <div class=\"mat-sort-header-content\">\n <ng-content></ng-content>\n </div>\n\n <!-- Disable animations while a current animation is running -->\n @if (_renderArrow()) {\n <div\n class=\"mat-sort-header-arrow\"\n [@arrowOpacity]=\"_getArrowViewState()\"\n [@arrowPosition]=\"_getArrowViewState()\"\n [@allowChildren]=\"_getArrowDirectionState()\"\n (@arrowPosition.start)=\"_disableViewStateAnimation = true\"\n (@arrowPosition.done)=\"_disableViewStateAnimation = false\">\n <div class=\"mat-sort-header-stem\"></div>\n <div\n class=\"mat-sort-header-indicator\"\n [@indicator]=\"_getArrowDirectionState()\">\n <div\n class=\"mat-sort-header-pointer-left\"\n [@leftPointer]=\"_getArrowDirectionState()\"></div>\n <div\n class=\"mat-sort-header-pointer-right\"\n [@rightPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-middle\"></div>\n </div>\n </div>\n }\n <div *ngIf=\"_isSorted()\" class=\"mat-sort-header-counter\">\n {{ sortIndex + 1 }}\n </div>\n</div>\n", styles: [".mat-sort-header-container{display:flex;cursor:pointer;align-items:center;letter-spacing:normal;outline:0}[mat-sort-header].cdk-keyboard-focused .mat-sort-header-container,[mat-sort-header].cdk-program-focused .mat-sort-header-container{border-bottom:solid 1px currentColor}.mat-sort-header-disabled .mat-sort-header-container{cursor:default}.mat-sort-header-container:before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px) * -1)}.mat-sort-header-content{text-align:center;display:flex;align-items:center}.mat-sort-header-position-before{flex-direction:row-reverse}.mat-sort-header-arrow{height:12px;width:12px;min-width:12px;position:relative;display:flex;color:var(--mat-sort-arrow-color, var(--mat-app-on-surface));opacity:0}.mat-sort-header-arrow,[dir=rtl] .mat-sort-header-position-before .mat-sort-header-arrow{margin:0 0 0 6px}.mat-sort-header-position-before .mat-sort-header-arrow,[dir=rtl] .mat-sort-header-arrow{margin:0 6px 0 0}.mat-sort-header-stem{background:currentColor;height:10px;width:2px;margin:auto;display:flex;align-items:center}.cdk-high-contrast-active .mat-sort-header-stem{width:0;border-left:solid 2px}.mat-sort-header-indicator{width:100%;height:2px;display:flex;align-items:center;position:absolute;top:0;left:0}.mat-sort-header-pointer-middle{margin:auto;height:2px;width:2px;background:currentColor;transform:rotate(45deg)}.cdk-high-contrast-active .mat-sort-header-pointer-middle{width:0;height:0;border-top:solid 2px;border-left:solid 2px}.mat-sort-header-pointer-left,.mat-sort-header-pointer-right{background:currentColor;width:6px;height:2px;position:absolute;top:0}.cdk-high-contrast-active .mat-sort-header-pointer-left,.cdk-high-contrast-active .mat-sort-header-pointer-right{width:0;height:0;border-left:solid 6px;border-top:solid 2px}.mat-sort-header-pointer-left{transform-origin:right;left:0}.mat-sort-header-pointer-right{transform-origin:left;right:0}.mat-sort-header-counter{color:var(--mat-sort-arrow-color, var(--mat-sys-on-surface))}\n"], dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None });
172
+ }
173
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: MatMultiSortHeaderComponent, decorators: [{
174
+ type: Component,
175
+ args: [{ selector: "[mat-multi-sort-header]", exportAs: "matMultiSortHeader", imports: [NgIf], providers: [{ provide: MatSort, useExisting: MatMultiSortDirective }], encapsulation: ViewEncapsulation.None, standalone: true, template: "<!--\n We set the `tabindex` on an element inside the table header, rather than the header itself,\n because of a bug in NVDA where having a `tabindex` on a `th` breaks keyboard navigation in the\n table (see https://github.com/nvaccess/nvda/issues/7718). This allows for the header to both\n be focusable, and have screen readers read out its `aria-sort` state. We prefer this approach\n over having a button with an `aria-label` inside the header, because the button's `aria-label`\n will be read out as the user is navigating the table's cell (see #13012).\n\n The approach is based off of: https://dequeuniversity.com/library/aria/tables/sf-sortable-grid\n-->\n<div\n class=\"mat-sort-header-container mat-focus-indicator\"\n [class.mat-sort-header-sorted]=\"_isSorted()\"\n [class.mat-sort-header-position-before]=\"arrowPosition === 'before'\"\n [attr.tabindex]=\"_isDisabled() ? null : 0\"\n [attr.role]=\"_isDisabled() ? null : 'button'\">\n <!--\n TODO(crisbeto): this div isn't strictly necessary, but we have to keep it due to a large\n number of screenshot diff failures. It should be removed eventually. Note that the difference\n isn't visible with a shorter header, but once it breaks up into multiple lines, this element\n causes it to be center-aligned, whereas removing it will keep the text to the left.\n -->\n <div class=\"mat-sort-header-content\">\n <ng-content></ng-content>\n </div>\n\n <!-- Disable animations while a current animation is running -->\n @if (_renderArrow()) {\n <div\n class=\"mat-sort-header-arrow\"\n [@arrowOpacity]=\"_getArrowViewState()\"\n [@arrowPosition]=\"_getArrowViewState()\"\n [@allowChildren]=\"_getArrowDirectionState()\"\n (@arrowPosition.start)=\"_disableViewStateAnimation = true\"\n (@arrowPosition.done)=\"_disableViewStateAnimation = false\">\n <div class=\"mat-sort-header-stem\"></div>\n <div\n class=\"mat-sort-header-indicator\"\n [@indicator]=\"_getArrowDirectionState()\">\n <div\n class=\"mat-sort-header-pointer-left\"\n [@leftPointer]=\"_getArrowDirectionState()\"></div>\n <div\n class=\"mat-sort-header-pointer-right\"\n [@rightPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-middle\"></div>\n </div>\n </div>\n }\n <div *ngIf=\"_isSorted()\" class=\"mat-sort-header-counter\">\n {{ sortIndex + 1 }}\n </div>\n</div>\n", styles: [".mat-sort-header-container{display:flex;cursor:pointer;align-items:center;letter-spacing:normal;outline:0}[mat-sort-header].cdk-keyboard-focused .mat-sort-header-container,[mat-sort-header].cdk-program-focused .mat-sort-header-container{border-bottom:solid 1px currentColor}.mat-sort-header-disabled .mat-sort-header-container{cursor:default}.mat-sort-header-container:before{margin:calc(calc(var(--mat-focus-indicator-border-width, 3px) + 2px) * -1)}.mat-sort-header-content{text-align:center;display:flex;align-items:center}.mat-sort-header-position-before{flex-direction:row-reverse}.mat-sort-header-arrow{height:12px;width:12px;min-width:12px;position:relative;display:flex;color:var(--mat-sort-arrow-color, var(--mat-app-on-surface));opacity:0}.mat-sort-header-arrow,[dir=rtl] .mat-sort-header-position-before .mat-sort-header-arrow{margin:0 0 0 6px}.mat-sort-header-position-before .mat-sort-header-arrow,[dir=rtl] .mat-sort-header-arrow{margin:0 6px 0 0}.mat-sort-header-stem{background:currentColor;height:10px;width:2px;margin:auto;display:flex;align-items:center}.cdk-high-contrast-active .mat-sort-header-stem{width:0;border-left:solid 2px}.mat-sort-header-indicator{width:100%;height:2px;display:flex;align-items:center;position:absolute;top:0;left:0}.mat-sort-header-pointer-middle{margin:auto;height:2px;width:2px;background:currentColor;transform:rotate(45deg)}.cdk-high-contrast-active .mat-sort-header-pointer-middle{width:0;height:0;border-top:solid 2px;border-left:solid 2px}.mat-sort-header-pointer-left,.mat-sort-header-pointer-right{background:currentColor;width:6px;height:2px;position:absolute;top:0}.cdk-high-contrast-active .mat-sort-header-pointer-left,.cdk-high-contrast-active .mat-sort-header-pointer-right{width:0;height:0;border-left:solid 6px;border-top:solid 2px}.mat-sort-header-pointer-left{transform-origin:right;left:0}.mat-sort-header-pointer-right{transform-origin:left;right:0}.mat-sort-header-counter{color:var(--mat-sort-arrow-color, var(--mat-sys-on-surface))}\n"] }]
176
+ }] });
177
+
178
+ /*
179
+ * Public API Surface of lib
180
+ */
181
+
182
+ /**
183
+ * Generated bundle index. Do not edit.
184
+ */
185
+
186
+ export { MatMultiSortDirective, MatMultiSortHeaderComponent, MatMultiSortTableDataSource, MultiCriterionSort };
187
+ //# sourceMappingURL=ngx-mat-table-multi-sort.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-mat-table-multi-sort.mjs","sources":["../../../src/lib/mat-multi-sort.directive.ts","../../../src/lib/mat-multi-sort-table-data-source.ts","../../../src/lib/mat-multi-sort-header/mat-multi-sort-header.component.ts","../../../src/lib/mat-multi-sort-header/mat-multi-sort-header.component.html","../../../src/public-api.ts","../../../src/ngx-mat-table-multi-sort.ts"],"sourcesContent":["import { Directive } from \"@angular/core\";\nimport {\n MatSort,\n MatSortable,\n Sort,\n SortDirection,\n} from \"@angular/material/sort\";\n\n@Directive({\n selector: \"[matMultiSort]\",\n exportAs: \"matMultiSort\",\n host: {\n class: \"mat-sort\",\n },\n standalone: true,\n})\nexport class MatMultiSortDirective extends MatSort {\n readonly _sorts: Sort[] = [];\n\n /**\n * Retrieves the sort direction for a given column ID.\n *\n * @param id - The ID of the column to get the sort direction for.\n * @returns The sort direction ('asc', 'desc', or '') for the specified column ID.\n */\n getSortDirection(id: string): SortDirection {\n const sort = this._sorts.find((e) => e.active === id);\n return sort ? sort.direction : \"\";\n }\n\n /**\n * Gets the sort index of the given column ID.\n *\n * @param id - The ID of the column to get the sort index for.\n * @returns The sort index of the column, or -1 if the column is not active.\n */\n public getSortIndex(id: string): number {\n return this._sorts.findIndex((e) => e.active === id);\n }\n\n override sort(sortable: MatSortable): void {\n this.active = sortable.id;\n this.direction = this.getSortDirection(sortable.id);\n const index = this.getSortIndex(sortable.id);\n\n // If the column is not active, add it to the list of active columns.\n if (index < 0) {\n this.direction = sortable.start ? sortable.start : this.start;\n this._sorts.push({ active: this.active, direction: this.direction });\n } else {\n // If the column is active, update the direction or remove it if the direction is empty.\n this.direction = this.getNextSortDirection(sortable);\n if (!this.direction) {\n this._sorts.splice(index, 1);\n } else {\n this._sorts[index].direction = this.direction;\n }\n }\n\n this.sortChange.emit({ active: this.active, direction: this.direction });\n }\n}\n","import { MatPaginator } from \"@angular/material/paginator\";\nimport { Sort } from \"@angular/material/sort\";\nimport { MatTableDataSource } from \"@angular/material/table\";\nimport { MatMultiSortDirective } from \"./mat-multi-sort.directive\";\n\n/**\n * Sorts two items based on multiple sorting criteria.\n *\n * @description To do this, we iterate over each sort level and compare the values of the active column. If the values are equal, we move to the next sort level. If all sort levels are equal, we return 0.\n *\n * @template T - The type of the items being sorted.\n * @param {T} a - The first item to compare.\n * @param {T} b - The second item to compare.\n * @param {Sort[]} sorts - An array of sorting criteria, where each criterion specifies the property to sort by and the direction of sorting.\n * @returns {number} - A negative number if `a` should come before `b`, a positive number if `a` should come after `b`, or 0 if they are considered equal.\n */\nexport function MultiCriterionSort<T>(a: T, b: T, sorts: Sort[]): number {\n for (const { active, direction } of sorts) {\n const aValue = a[active as keyof T];\n const bValue = b[active as keyof T];\n\n const comparison = compareValues(aValue, bValue);\n\n if (comparison !== 0) {\n return direction === \"desc\" ? -comparison : comparison;\n }\n }\n\n return 0; // If all comparisons are equal, preserve original order\n}\n\nfunction compareValues<T>(aValue: T, bValue: T): number {\n if (aValue == null && bValue != null) return 1;\n if (aValue != null && bValue == null) return -1;\n if (aValue == null && bValue == null) return 0;\n\n if (typeof aValue === \"string\" && typeof bValue === \"string\") {\n return aValue.localeCompare(bValue);\n }\n\n if (aValue > bValue) return 1;\n if (aValue < bValue) return -1;\n return 0;\n}\n\n/**\n * A data source class that extends `MatTableDataSource` to support multi-column sorting.\n *\n * @template T The type of data that the table displays.\n * @template P The type of paginator used, defaults to `MatPaginator`.\n *\n * @extends MatTableDataSource<T, P>\n */\nexport class MatMultiSortTableDataSource<\n T,\n P extends MatPaginator = MatPaginator,\n> extends MatTableDataSource<T, P> {\n override get sort(): MatMultiSortDirective | null {\n return super.sort as MatMultiSortDirective;\n }\n override set sort(sort: MatMultiSortDirective | null) {\n super.sort = sort;\n }\n\n constructor(initialData?: T[]) {\n super(initialData);\n // Set the default sort function\n this.sortData = (data): T[] => this.sortDataFunction(data);\n }\n\n private sortDataFunction(data: T[]): T[] {\n // Return the data if there is no sort\n if (!this.sort?._sorts.length) return data;\n\n // Sort the data:\n return data.sort((a, b) => MultiCriterionSort(a, b, this.sort!._sorts));\n }\n}\n","import { NgIf } from \"@angular/common\";\nimport { Component, inject, OnInit, ViewEncapsulation } from \"@angular/core\";\nimport { MatSort, MatSortHeader, SortDirection } from \"@angular/material/sort\";\nimport { MatMultiSortDirective } from \"../mat-multi-sort.directive\";\n\n@Component({\n selector: \"[mat-multi-sort-header]\", // eslint-disable-line @angular-eslint/component-selector\n exportAs: \"matMultiSortHeader\",\n imports: [NgIf],\n providers: [{ provide: MatSort, useExisting: MatMultiSortDirective }],\n templateUrl: \"./mat-multi-sort-header.component.html\",\n styleUrl: \"./mat-multi-sort-header.component.scss\",\n encapsulation: ViewEncapsulation.None,\n standalone: true,\n})\nexport class MatMultiSortHeaderComponent\n extends MatSortHeader\n implements OnInit\n{\n override readonly _sort: MatMultiSortDirective = inject(\n MatMultiSortDirective,\n {\n optional: true,\n }\n )!;\n\n /**\n * Retrieves the sort direction for the current column.\n *\n * @returns {SortDirection} The sort direction for the column identified by this.id.\n */\n get sortDirection(): SortDirection {\n return this._sort.getSortDirection(this.id);\n }\n\n /**\n * Gets the sort index for the current column.\n *\n * @returns {number} The index of the sort order for this column.\n */\n get sortIndex(): number {\n return this._sort.getSortIndex(this.id);\n }\n\n override _getAriaSortAttribute(): \"none\" | \"ascending\" | \"descending\" {\n if (!this._isSorted()) {\n return \"none\";\n }\n\n return this.sortDirection === \"asc\" ? \"ascending\" : \"descending\";\n }\n\n override _isSorted(): boolean {\n return this.sortIndex > -1;\n }\n\n override _toggleOnInteraction(): void {\n if (this._isDisabled()) return;\n\n super._toggleOnInteraction();\n }\n\n override _updateArrowDirection(): void {\n this._arrowDirection = this._isSorted()\n ? this.sortDirection\n : this.start || this._sort.start;\n }\n}\n","<!--\n We set the `tabindex` on an element inside the table header, rather than the header itself,\n because of a bug in NVDA where having a `tabindex` on a `th` breaks keyboard navigation in the\n table (see https://github.com/nvaccess/nvda/issues/7718). This allows for the header to both\n be focusable, and have screen readers read out its `aria-sort` state. We prefer this approach\n over having a button with an `aria-label` inside the header, because the button's `aria-label`\n will be read out as the user is navigating the table's cell (see #13012).\n\n The approach is based off of: https://dequeuniversity.com/library/aria/tables/sf-sortable-grid\n-->\n<div\n class=\"mat-sort-header-container mat-focus-indicator\"\n [class.mat-sort-header-sorted]=\"_isSorted()\"\n [class.mat-sort-header-position-before]=\"arrowPosition === 'before'\"\n [attr.tabindex]=\"_isDisabled() ? null : 0\"\n [attr.role]=\"_isDisabled() ? null : 'button'\">\n <!--\n TODO(crisbeto): this div isn't strictly necessary, but we have to keep it due to a large\n number of screenshot diff failures. It should be removed eventually. Note that the difference\n isn't visible with a shorter header, but once it breaks up into multiple lines, this element\n causes it to be center-aligned, whereas removing it will keep the text to the left.\n -->\n <div class=\"mat-sort-header-content\">\n <ng-content></ng-content>\n </div>\n\n <!-- Disable animations while a current animation is running -->\n @if (_renderArrow()) {\n <div\n class=\"mat-sort-header-arrow\"\n [@arrowOpacity]=\"_getArrowViewState()\"\n [@arrowPosition]=\"_getArrowViewState()\"\n [@allowChildren]=\"_getArrowDirectionState()\"\n (@arrowPosition.start)=\"_disableViewStateAnimation = true\"\n (@arrowPosition.done)=\"_disableViewStateAnimation = false\">\n <div class=\"mat-sort-header-stem\"></div>\n <div\n class=\"mat-sort-header-indicator\"\n [@indicator]=\"_getArrowDirectionState()\">\n <div\n class=\"mat-sort-header-pointer-left\"\n [@leftPointer]=\"_getArrowDirectionState()\"></div>\n <div\n class=\"mat-sort-header-pointer-right\"\n [@rightPointer]=\"_getArrowDirectionState()\"></div>\n <div class=\"mat-sort-header-pointer-middle\"></div>\n </div>\n </div>\n }\n <div *ngIf=\"_isSorted()\" class=\"mat-sort-header-counter\">\n {{ sortIndex + 1 }}\n </div>\n</div>\n","/*\n * Public API Surface of lib\n */\n\nexport * from \"./lib/mat-multi-sort.directive\";\nexport * from \"./lib/mat-multi-sort-table-data-source\";\nexport * from \"./lib/mat-multi-sort-header/mat-multi-sort-header.component\";\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Generated bundle index. Do not edit.
3
+ */
4
+ /// <amd-module name="ngx-mat-table-multi-sort" />
5
+ export * from './public-api';
@@ -0,0 +1,25 @@
1
+ import { OnInit } from "@angular/core";
2
+ import { MatSortHeader, SortDirection } from "@angular/material/sort";
3
+ import { MatMultiSortDirective } from "../mat-multi-sort.directive";
4
+ import * as i0 from "@angular/core";
5
+ export declare class MatMultiSortHeaderComponent extends MatSortHeader implements OnInit {
6
+ readonly _sort: MatMultiSortDirective;
7
+ /**
8
+ * Retrieves the sort direction for the current column.
9
+ *
10
+ * @returns {SortDirection} The sort direction for the column identified by this.id.
11
+ */
12
+ get sortDirection(): SortDirection;
13
+ /**
14
+ * Gets the sort index for the current column.
15
+ *
16
+ * @returns {number} The index of the sort order for this column.
17
+ */
18
+ get sortIndex(): number;
19
+ _getAriaSortAttribute(): "none" | "ascending" | "descending";
20
+ _isSorted(): boolean;
21
+ _toggleOnInteraction(): void;
22
+ _updateArrowDirection(): void;
23
+ static ɵfac: i0.ɵɵFactoryDeclaration<MatMultiSortHeaderComponent, never>;
24
+ static ɵcmp: i0.ɵɵComponentDeclaration<MatMultiSortHeaderComponent, "[mat-multi-sort-header]", ["matMultiSortHeader"], {}, {}, never, ["*"], true, never>;
25
+ }
@@ -0,0 +1,30 @@
1
+ import { MatPaginator } from "@angular/material/paginator";
2
+ import { Sort } from "@angular/material/sort";
3
+ import { MatTableDataSource } from "@angular/material/table";
4
+ import { MatMultiSortDirective } from "./mat-multi-sort.directive";
5
+ /**
6
+ * Sorts two items based on multiple sorting criteria.
7
+ *
8
+ * @description To do this, we iterate over each sort level and compare the values of the active column. If the values are equal, we move to the next sort level. If all sort levels are equal, we return 0.
9
+ *
10
+ * @template T - The type of the items being sorted.
11
+ * @param {T} a - The first item to compare.
12
+ * @param {T} b - The second item to compare.
13
+ * @param {Sort[]} sorts - An array of sorting criteria, where each criterion specifies the property to sort by and the direction of sorting.
14
+ * @returns {number} - A negative number if `a` should come before `b`, a positive number if `a` should come after `b`, or 0 if they are considered equal.
15
+ */
16
+ export declare function MultiCriterionSort<T>(a: T, b: T, sorts: Sort[]): number;
17
+ /**
18
+ * A data source class that extends `MatTableDataSource` to support multi-column sorting.
19
+ *
20
+ * @template T The type of data that the table displays.
21
+ * @template P The type of paginator used, defaults to `MatPaginator`.
22
+ *
23
+ * @extends MatTableDataSource<T, P>
24
+ */
25
+ export declare class MatMultiSortTableDataSource<T, P extends MatPaginator = MatPaginator> extends MatTableDataSource<T, P> {
26
+ get sort(): MatMultiSortDirective | null;
27
+ set sort(sort: MatMultiSortDirective | null);
28
+ constructor(initialData?: T[]);
29
+ private sortDataFunction;
30
+ }
@@ -0,0 +1,22 @@
1
+ import { MatSort, MatSortable, Sort, SortDirection } from "@angular/material/sort";
2
+ import * as i0 from "@angular/core";
3
+ export declare class MatMultiSortDirective extends MatSort {
4
+ readonly _sorts: Sort[];
5
+ /**
6
+ * Retrieves the sort direction for a given column ID.
7
+ *
8
+ * @param id - The ID of the column to get the sort direction for.
9
+ * @returns The sort direction ('asc', 'desc', or '') for the specified column ID.
10
+ */
11
+ getSortDirection(id: string): SortDirection;
12
+ /**
13
+ * Gets the sort index of the given column ID.
14
+ *
15
+ * @param id - The ID of the column to get the sort index for.
16
+ * @returns The sort index of the column, or -1 if the column is not active.
17
+ */
18
+ getSortIndex(id: string): number;
19
+ sort(sortable: MatSortable): void;
20
+ static ɵfac: i0.ɵɵFactoryDeclaration<MatMultiSortDirective, never>;
21
+ static ɵdir: i0.ɵɵDirectiveDeclaration<MatMultiSortDirective, "[matMultiSort]", ["matMultiSort"], {}, {}, never, never, true, never>;
22
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "ngx-mat-table-multi-sort",
3
+ "version": "18.0.0-pre.0",
4
+ "preview": true,
5
+ "license": "MIT",
6
+ "author": {
7
+ "email": "info@philipgerke.com",
8
+ "name": "Philip Gerke",
9
+ "url": "https://www.philipgerke.com"
10
+ },
11
+ "maintainers": [
12
+ {
13
+ "name": "Philip Gerke",
14
+ "email": "info@philipgerke.com",
15
+ "url": "https://github.com/pgerke"
16
+ },
17
+ {
18
+ "name": "Michaela Andermann",
19
+ "url": "https://github.com/michix99"
20
+ }
21
+ ],
22
+ "repository": {
23
+ "type": "git",
24
+ "url": "git+https://github.com/pgerke/ngx-mat-table-multi-sort.git"
25
+ },
26
+ "bugs": {
27
+ "url": "https://github.com/pgerke/ngx-mat-table-multi-sort/issues"
28
+ },
29
+ "dependencies": {
30
+ "tslib": "^2.8.1"
31
+ },
32
+ "peerDependencies": {
33
+ "@angular/common": "^18.0.0",
34
+ "@angular/core": "^18.0.0",
35
+ "@angular/animations": "^18.0.0",
36
+ "@angular/cdk": "^18.0.0",
37
+ "@angular/forms": "^18.0.0",
38
+ "@angular/material": "^18.0.0"
39
+ },
40
+ "sideEffects": false,
41
+ "module": "fesm2022/ngx-mat-table-multi-sort.mjs",
42
+ "typings": "index.d.ts",
43
+ "exports": {
44
+ "./package.json": {
45
+ "default": "./package.json"
46
+ },
47
+ ".": {
48
+ "types": "./index.d.ts",
49
+ "esm2022": "./esm2022/ngx-mat-table-multi-sort.mjs",
50
+ "esm": "./esm2022/ngx-mat-table-multi-sort.mjs",
51
+ "default": "./fesm2022/ngx-mat-table-multi-sort.mjs"
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,3 @@
1
+ export * from "./lib/mat-multi-sort.directive";
2
+ export * from "./lib/mat-multi-sort-table-data-source";
3
+ export * from "./lib/mat-multi-sort-header/mat-multi-sort-header.component";