@igo2/common
Version:
447 lines (440 loc) • 19.7 kB
JavaScript
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