@deepkit/desktop-ui
Version:
Library for desktop UI widgets in Angular 10+
211 lines (188 loc) • 6.11 kB
text/typescript
/*
* Deepkit Framework
* Copyright (C) 2021 Deepkit UG, Marc J. Schmidt
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the MIT License.
*
* You should have received a copy of the MIT License along with this program.
*/
import { booleanAttribute, Component, computed, contentChild, ContentChild, contentChildren, Directive, ElementRef, HostBinding, HostListener, input, OnDestroy, TemplateRef, viewChild } from '@angular/core';
import { ngValueAccessor, ValueAccessorBase } from '../../core/form';
import { DropdownComponent, DropdownItemComponent, DropdownSplitterComponent, OpenDropdownDirective } from '../button/dropdown.component';
import { ButtonComponent, ButtonGroupComponent } from '../button/button.component';
import { NgTemplateOutlet } from '@angular/common';
import { IconComponent } from '../icon/icon.component';
import { injectElementRef } from '../app/utils';
/**
* Necessary directive to get a dynamic rendered option.
*
* ```html
* <dui-option>
* <ng-container *dynamicOption>
* {{item.fieldName | date}}
* </ng-container>
* </dui-option>
* ```
*/
export class DynamicOptionDirective {
constructor(
public template: TemplateRef<any>,
) {
}
}
/**
* Directive to create an option in the select dropdown.
*
* ```html
* <dui-select>
* <dui-option value="1">Option 1</dui-option>
* </dui-select>
*/
export class OptionDirective {
value = input<any>();
disabled = input<boolean>(false);
dynamic?: DynamicOptionDirective;
constructor(public element: ElementRef) {
}
}
/**
* Directive to create a separator in the select dropdown.
*
* ```html
* <dui-select>
* <dui-option value="1">Option 1</dui-option>
* <dui-option-separator></dui-option-separator>
* <dui-option value="2">Option 2</dui-option>
* </dui-select>
*/
export class OptionSeparatorDirective {
constructor() {
}
}
export class SelectBoxComponent<T> extends ValueAccessorBase<T> implements OnDestroy {
placeholder = input<string>('');
/**
* Different textured styled.
*/
textured = input(false, { transform: booleanAttribute });
/**
* Smaller text and height.
*/
small = input(false, { transform: booleanAttribute });
button = contentChild(ButtonComponent);
options = contentChildren(OptionDirective, { descendants: true });
dropdown = viewChild.required('dropdown', { read: DropdownComponent });
public label: string = '';
optionsValueMap = computed(() => {
const map = new Map<T | undefined, OptionDirective>();
for (const option of this.options()) {
if (!(option instanceof OptionDirective)) continue;
map.set(option.value(), option);
}
return map;
});
element = injectElementRef();
constructor() {
super();
}
protected isSeparator(item: any): boolean {
return item instanceof OptionSeparatorDirective;
}
select(value: T) {
this.setValue(value);
this.touch();
this.dropdown().close();
}
protected onClick() {
if (this.disabled()) return;
if (this.button()) return;
this.dropdown().toggle();
}
open() {
this.dropdown()?.open();
}
protected get isSelected(): boolean {
return this.value() !== undefined;
}
}