import { Directive, EventEmitter, Input, Output } from "@angular/core"; import { coerceBooleanProperty } from "@angular/cdk/coercion"; // import {getMdSortDuplicateMdSortableIdError, getMdSortHeaderMissingIdError} from './sort-errors'; export type SortDirection = "asc" | "desc" | ""; export interface SamSortable { id: string; start: "asc" | "desc"; disableClear: boolean; } export interface Sort { active: string; direction: SortDirection; } /** Container for SamSortables to manage the sort state and provide default sort parameters. */ @Directive({ selector: "[samSort]", standalone: false, }) export class SamSortDirective { /** Collection of all registered sortables that this directive manages. */ sortables = new Map(); /* tslint:disable */ /** The id of the most recently sorted SamSortable. */ @Input("samSortActive") active: string; /** * The direction to set when an SamSortable is initially sorted. * May be overriden by the SamSortable's sort start. */ @Input("samSortStart") start: "asc" | "desc" = "asc"; /** The sort direction of the currently active SamSortable. */ @Input("samSortDirection") direction: SortDirection = ""; /** * Whether to disable the user from clearing the sort by finishing the sort direction cycle. * May be overriden by the SamSortable's disable clear input. */ @Input("samSortDisableClear") get disableClear() { return this._disableClear; } set disableClear(v) { this._disableClear = coerceBooleanProperty(v); } /* tslint:enable */ private _disableClear: boolean; /** Event emitted when the user changes either the active sort or sort direction. */ @Output() samSortChange = new EventEmitter(); /** * Register function to be used by the contained SamSortables. Adds the SamSortable to the * collection of SamSortables. */ register(sortable: SamSortable) { if (!sortable.id) { throw new Error("Missing Sort Header ID error"); } if (this.sortables.has(sortable.id)) { throw new Error("Duplicate Sort Header ID error: " + sortable.id); } this.sortables.set(sortable.id, sortable); } /** * Unregister function to be used by the contained SamSortables. Removes the SamSortable from the * collection of contained SamSortables. */ deregister(sortable: SamSortable) { this.sortables.delete(sortable.id); } /** Sets the active sort id and determines the new sort direction. */ sort(sortable: SamSortable) { if (this.active !== sortable.id) { this.active = sortable.id; this.direction = sortable.start ? sortable.start : this.start; } else { this.direction = this.getNextSortDirection(sortable); } this.samSortChange.next({ active: this.active, direction: this.direction }); } /** Returns the next sort direction of the active sortable, checking for potential overrides. */ getNextSortDirection(sortable: SamSortable): SortDirection { if (!sortable) { return ""; } // Get the sort direction cycle with the potential sortable overrides. const disableClear = sortable.disableClear != null ? sortable.disableClear : this.disableClear; const sortDirectionCycle = getSortDirectionCycle( sortable.start || this.start, disableClear ); // Get and return the next direction in the cycle let nextDirectionIndex = sortDirectionCycle.indexOf(this.direction) + 1; if (nextDirectionIndex >= sortDirectionCycle.length) { nextDirectionIndex = 0; } return sortDirectionCycle[nextDirectionIndex]; } } /** Returns the sort direction cycle to use given the provided parameters of order and clear. */ function getSortDirectionCycle( start: "asc" | "desc", disableClear: boolean ): SortDirection[] { const sortOrder: SortDirection[] = ["asc", "desc"]; if (start === "desc") { sortOrder.reverse(); } if (!disableClear) { sortOrder.push(""); } return sortOrder; }