UNPKG

@igo2/common

Version:
447 lines (440 loc) 19.7 kB
import * as i0 from '@angular/core'; import { EventEmitter, HostListener, Output, Input, Directive, ContentChildren, Component, NgModule } from '@angular/core'; import { NgClass } from '@angular/common'; import * as i1 from '@angular/material/list'; import { MatListModule } from '@angular/material/list'; import { ClickoutDirective } from '@igo2/common/clickout'; class ListItemDirective { renderer; el; static focusedCls = 'igo-list-item-focused'; static selectedCls = 'igo-list-item-selected'; static disabledCls = 'igo-list-item-disabled'; get color() { return this._color; } set color(value) { this._color = value; } _color = 'primary'; get focused() { return this._focused; } set focused(value) { if (value === this._focused) { return; } if (this.disabled) { return; } value ? this.beforeFocus.emit(this) : this.beforeUnfocus.emit(this); this._focused = value; if (this.selected !== true) { this.toggleFocusedClass(); } value ? this.focus.emit(this) : this.unfocus.emit(this); } _focused = false; get selected() { return this._selected; } set selected(value) { if (value === this._selected) { return; } if (this.disabled) { return; } value ? this.beforeSelect.emit(this) : this.beforeUnselect.emit(this); this._selected = value; this._focused = value; this.toggleSelectedClass(); value ? this.select.emit(this) : this.unselect.emit(this); } _selected = false; get disabled() { return this._disabled; } set disabled(value) { if (value === this._disabled) { return; } if (value === true) { this.selected = false; } value ? this.beforeDisable.emit(this) : this.beforeEnable.emit(this); this._disabled = value; this.toggleDisabledClass(); value ? this.disable.emit(this) : this.enable.emit(this); } _disabled = false; beforeSelect = new EventEmitter(); beforeFocus = new EventEmitter(); beforeUnselect = new EventEmitter(); beforeUnfocus = new EventEmitter(); beforeDisable = new EventEmitter(); beforeEnable = new EventEmitter(); focus = new EventEmitter(); unfocus = new EventEmitter(); select = new EventEmitter(); unselect = new EventEmitter(); disable = new EventEmitter(); enable = new EventEmitter(); onClick() { this.selected = true; } constructor(renderer, el) { this.renderer = renderer; this.el = el; } getOffsetTop() { const padding = 5; return this.el.nativeElement.offsetTop - padding; } toggleFocusedClass() { if (this.focused) { this.addCls(ListItemDirective.focusedCls); } else { this.removeCls(ListItemDirective.focusedCls); } } toggleSelectedClass() { if (this.selected) { this.addCls(ListItemDirective.selectedCls); this.removeCls(ListItemDirective.focusedCls); } else { this.removeCls(ListItemDirective.selectedCls); } } toggleDisabledClass() { if (this.disabled) { this.addCls(ListItemDirective.disabledCls); } else { this.removeCls(ListItemDirective.disabledCls); } } addCls(cls) { this.renderer.addClass(this.el.nativeElement, cls); } removeCls(cls) { this.renderer.removeClass(this.el.nativeElement, cls); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ListItemDirective, deps: [{ token: i0.Renderer2 }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.2.15", type: ListItemDirective, isStandalone: true, selector: "[igoListItem]", inputs: { color: "color", focused: "focused", selected: "selected", disabled: "disabled" }, outputs: { beforeSelect: "beforeSelect", beforeFocus: "beforeFocus", beforeUnselect: "beforeUnselect", beforeUnfocus: "beforeUnfocus", beforeDisable: "beforeDisable", beforeEnable: "beforeEnable", focus: "focus", unfocus: "unfocus", select: "select", unselect: "unselect", disable: "disable", enable: "enable" }, host: { listeners: { "click": "onClick()" } }, ngImport: i0 }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ListItemDirective, decorators: [{ type: Directive, args: [{ selector: '[igoListItem]', standalone: true }] }], ctorParameters: () => [{ type: i0.Renderer2 }, { type: i0.ElementRef }], propDecorators: { color: [{ type: Input }], focused: [{ type: Input }], selected: [{ type: Input }], disabled: [{ type: Input }], beforeSelect: [{ type: Output }], beforeFocus: [{ type: Output }], beforeUnselect: [{ type: Output }], beforeUnfocus: [{ type: Output }], beforeDisable: [{ type: Output }], beforeEnable: [{ type: Output }], focus: [{ type: Output }], unfocus: [{ type: Output }], select: [{ type: Output }], unselect: [{ type: Output }], disable: [{ type: Output }], enable: [{ type: Output }], onClick: [{ type: HostListener, args: ['click'] }] } }); class ListComponent { el; get navigation() { return this._navigation; } set navigation(value) { this._navigation = value; } _navigation = true; get selection() { return this._selection; } set selection(value) { this._selection = value; } _selection = true; get selectedItem() { return this._selectedItem; } set selectedItem(value) { this.focusedItem = value; this._selectedItem = value; } _selectedItem; get focusedItem() { return this._focusedItem; } set focusedItem(value) { this._focusedItem = value; } _focusedItem; navigationEnabled; listItems$$; subscriptions = []; listItems; handleKeyboardEvent(event) { // It would be nice to be able to unsubscribe to the event // completely but until ES7 this won't be possible because // document events are not observables if (this.navigationEnabled) { if (event.key === 'ArrowUp' || event.key === 'ArrowDown') { event.preventDefault(); this.navigate(event.key); } else if (event.key === 'Enter') { this.select(this.focusedItem); } } } constructor(el) { this.el = el; } ngOnInit() { this.enableNavigation(); } ngAfterViewInit() { if (this.listItems.length) { this.init(); } this.listItems$$ = this.listItems.changes.subscribe(() => this.init()); } ngOnDestroy() { this.listItems$$.unsubscribe(); } focus(item) { if (!this.selection) { return; } this.unfocus(); // We need to make this check because dynamic // lists such as in the search results list may fail if (item !== undefined) { item.focused = true; } } unfocus() { if (this.focusedItem !== undefined) { this.focusedItem.focused = false; } this.focusedItem = undefined; } focusNext() { const items = this.listItems.toArray(); let item; const igoList = this.el.nativeElement; let disabled = true; let index = this.getFocusedIndex(); if (index === undefined) { index = -1; } while (disabled && index < items.length - 1) { index += 1; item = items[index]; disabled = item.disabled; } if (item !== undefined) { this.focus(item); } if (!items[index + 1]) { igoList.scrollTop = igoList.scrollHeight - igoList.clientHeight; return; } if (item !== undefined && !this.isScrolledIntoView(item.el.nativeElement)) { igoList.scrollTop = item.el.nativeElement.offsetTop + item.el.nativeElement.children[0].offsetHeight - igoList.clientHeight; } } focusPrevious() { const items = this.listItems.toArray(); let item; const igoList = this.el.nativeElement; let disabled = true; let index = this.getFocusedIndex(); while (disabled && index > 0) { index -= 1; item = items[index]; disabled = item.disabled; } if (item !== undefined) { this.focus(item); } if (!items[index - 1]) { igoList.scrollTop = 0; return; } if (item !== undefined && !this.isScrolledIntoView(item.el.nativeElement)) { const padding = 3; igoList.scrollTop = item.el.nativeElement.offsetTop - padding; } } select(item) { if (!this.selection) { return; } this.unselect(); if (item !== undefined) { item.selected = true; } } unselect() { this.unfocus(); if (this.selectedItem !== undefined) { this.selectedItem.selected = false; } this.selectedItem = undefined; } enableNavigation() { if (this.navigation) { this.navigationEnabled = true; } } disableNavigation() { this.navigationEnabled = false; } scrollToItem(item) { this.el.nativeElement.scrollTop = item.getOffsetTop(); } isScrolledIntoView(elem) { const docViewTop = this.el.nativeElement.scrollTop + this.el.nativeElement.offsetTop; const docViewBottom = docViewTop + this.el.nativeElement.clientHeight; const elemTop = elem.offsetTop; const elemBottom = elemTop + elem.children[0].offsetHeight; return elemBottom <= docViewBottom && elemTop >= docViewTop; } init() { this.subscribe(); this.selectedItem = this.findSelectedItem(); this.focusedItem = this.findFocusedItem(); this.enableNavigation(); } subscribe() { this.unsubscribe(); this.listItems.toArray().forEach((item) => { this.subscriptions.push(item.beforeSelect.subscribe((item2) => this.handleItemBeforeSelect(item2))); this.subscriptions.push(item.select.subscribe((item2) => this.handleItemSelect(item2))); this.subscriptions.push(item.beforeFocus.subscribe((item2) => this.handleItemBeforeFocus(item2))); this.subscriptions.push(item.focus.subscribe((item2) => this.handleItemFocus(item2))); }, this); } unsubscribe() { this.subscriptions.forEach((sub) => sub.unsubscribe()); this.subscriptions = []; } handleItemBeforeFocus(item) { if (item !== this.focusedItem) { this.unfocus(); } } handleItemFocus(item) { this.focusedItem = item; } handleItemBeforeSelect(item) { if (item !== this.focusedItem) { this.unselect(); } } handleItemSelect(item) { this.selectedItem = item; } findSelectedItem() { return this.listItems.toArray().find((item) => item.selected); } findFocusedItem() { return this.listItems.toArray().find((item) => item.focused); } getFocusedIndex() { return this.listItems .toArray() .findIndex((item) => item === this.focusedItem); } navigate(key) { switch (key) { case 'ArrowUp': this.focusPrevious(); break; case 'ArrowDown': this.focusNext(); break; default: break; } } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ListComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.15", type: ListComponent, isStandalone: true, selector: "igo-list", inputs: { navigation: "navigation", selection: "selection" }, host: { listeners: { "document:keydown": "handleKeyboardEvent($event)", "document:enter": "handleKeyboardEvent($event)" } }, queries: [{ propertyName: "listItems", predicate: ListItemDirective, descendants: true }], ngImport: i0, template: "<mat-list\n igoClickout\n [ngClass]=\"{ selectable: selection }\"\n (clickout)=\"disableNavigation()\"\n (click)=\"enableNavigation()\"\n>\n <ng-content></ng-content>\n</mat-list>\n", styles: [":host{display:block;height:100%;overflow:auto;position:relative}:host mat-list{padding-top:0}:host ::ng-deep [igolistitem][color=primary].igo-list-item-selected>mat-list-item{background-color:var(--mat-sys-primary-fixed);color:var(--mat-sys-on-primary-fixed)}:host ::ng-deep [igolistitem][color=primary]:not(.igo-list-item-disabled):hover>mat-list-item,:host ::ng-deep [igolistitem][color=primary].igo-list-item-focused>mat-list-item{background-color:var(--mat-sys-primary-fixed-dim);color:var(--mat-sys-on-primary-fixed)}:host ::ng-deep [igolistitem][color=accent].igo-list-item-selected>mat-list-item{background-color:var(--mat-sys-secondary-fixed-dim);color:var(--mat-sys-on-secondary-fixed)}:host ::ng-deep [igolistitem][color=accent]:not(.igo-list-item-disabled):hover>mat-list-item,:host ::ng-deep [igolistitem][color=accent].igo-list-item-focused>mat-list-item{background-color:var(--mat-sys-secondary-fixed);color:var(--mat-sys-on-secondary-fixed)}:host ::ng-deep [igolistitem].igo-list-item-disabled>mat-list-item{color:#00000061}:host ::ng-deep [igolistitem]:focus{outline:none}:host ::ng-deep .mat-mdc-list .mat-mdc-list-item .mdc-list-item__primary-text{white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;max-height:36px;line-height:18px;-webkit-box-orient:vertical;-webkit-line-clamp:2}:host ::ng-deep .mat-mdc-list .mat-mdc-list-item.mdc-list-item--with-leading-icon{height:48px}:host ::ng-deep .mat-mdc-list ::ng-deep igo-collapsible>.mat-mdc-list-item>.mdc-list-item__primary-text>.mat-mdc-list-item{font-weight:700;opacity:.9}:host ::ng-deep mat-list.selectable ::ng-deep [igolistitem]:not(.igo-list-item-disabled) mat-list-item:hover{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: MatListModule }, { kind: "component", type: i1.MatList, selector: "mat-list", exportAs: ["matList"] }, { kind: "directive", type: ClickoutDirective, selector: "[igoClickout]", outputs: ["clickout"] }, { kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: ListComponent, decorators: [{ type: Component, args: [{ selector: 'igo-list', imports: [MatListModule, ClickoutDirective, NgClass], template: "<mat-list\n igoClickout\n [ngClass]=\"{ selectable: selection }\"\n (clickout)=\"disableNavigation()\"\n (click)=\"enableNavigation()\"\n>\n <ng-content></ng-content>\n</mat-list>\n", styles: [":host{display:block;height:100%;overflow:auto;position:relative}:host mat-list{padding-top:0}:host ::ng-deep [igolistitem][color=primary].igo-list-item-selected>mat-list-item{background-color:var(--mat-sys-primary-fixed);color:var(--mat-sys-on-primary-fixed)}:host ::ng-deep [igolistitem][color=primary]:not(.igo-list-item-disabled):hover>mat-list-item,:host ::ng-deep [igolistitem][color=primary].igo-list-item-focused>mat-list-item{background-color:var(--mat-sys-primary-fixed-dim);color:var(--mat-sys-on-primary-fixed)}:host ::ng-deep [igolistitem][color=accent].igo-list-item-selected>mat-list-item{background-color:var(--mat-sys-secondary-fixed-dim);color:var(--mat-sys-on-secondary-fixed)}:host ::ng-deep [igolistitem][color=accent]:not(.igo-list-item-disabled):hover>mat-list-item,:host ::ng-deep [igolistitem][color=accent].igo-list-item-focused>mat-list-item{background-color:var(--mat-sys-secondary-fixed);color:var(--mat-sys-on-secondary-fixed)}:host ::ng-deep [igolistitem].igo-list-item-disabled>mat-list-item{color:#00000061}:host ::ng-deep [igolistitem]:focus{outline:none}:host ::ng-deep .mat-mdc-list .mat-mdc-list-item .mdc-list-item__primary-text{white-space:normal;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;max-height:36px;line-height:18px;-webkit-box-orient:vertical;-webkit-line-clamp:2}:host ::ng-deep .mat-mdc-list .mat-mdc-list-item.mdc-list-item--with-leading-icon{height:48px}:host ::ng-deep .mat-mdc-list ::ng-deep igo-collapsible>.mat-mdc-list-item>.mdc-list-item__primary-text>.mat-mdc-list-item{font-weight:700;opacity:.9}:host ::ng-deep mat-list.selectable ::ng-deep [igolistitem]:not(.igo-list-item-disabled) mat-list-item:hover{cursor:pointer}\n"] }] }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { navigation: [{ type: Input }], selection: [{ type: Input }], listItems: [{ type: ContentChildren, args: [ListItemDirective, { descendants: true }] }], handleKeyboardEvent: [{ type: HostListener, args: ['document:keydown', ['$event']] }, { type: HostListener, args: ['document:enter', ['$event']] }] } }); /** * @deprecated import the components/directives directly or LIST_DIRECTIVES for the set */ class IgoListModule { static forRoot() { return { ngModule: IgoListModule, providers: [] }; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoListModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.15", ngImport: i0, type: IgoListModule, imports: [ListItemDirective, ListComponent], exports: [ListItemDirective, ListComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoListModule, imports: [ListComponent] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.15", ngImport: i0, type: IgoListModule, decorators: [{ type: NgModule, args: [{ imports: [ListItemDirective, ListComponent], exports: [ListItemDirective, ListComponent] }] }] }); const LIST_DIRECTIVES = [ListItemDirective, ListComponent]; /** * Generated bundle index. Do not edit. */ export { IgoListModule, LIST_DIRECTIVES, ListComponent, ListItemDirective }; //# sourceMappingURL=igo2-common-list.mjs.map