migrate inputs to signals & remove inputs/index.ts
This commit is contained in:
parent
d595a22db1
commit
f3faa6a6cc
@ -3,7 +3,6 @@ export * from './lib/dialog';
|
||||
export * from './lib/form';
|
||||
export * from './lib/listing';
|
||||
export * from './lib/help-mode';
|
||||
export * from './lib/inputs';
|
||||
export * from './lib/services';
|
||||
export * from './lib/loading';
|
||||
export * from './lib/error';
|
||||
|
||||
@ -1,14 +1,16 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { ChevronButtonComponent, IconButtonComponent } from '../buttons';
|
||||
import { ChevronButtonComponent } from '../buttons/chevron-button/chevron-button.component';
|
||||
import { IconButtonComponent } from '../buttons/icon-button/icon-button.component';
|
||||
import { PreventDefaultDirective } from '../directives/prevent-default.directive';
|
||||
import { StopPropagationDirective } from '../directives/stop-propagation.directive';
|
||||
import { InputWithActionComponent } from '../inputs/input-with-action/input-with-action.component';
|
||||
import { QuickFiltersComponent } from './quick-filters/quick-filters.component';
|
||||
import { SingleFilterComponent } from './single-filter/single-filter.component';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { PreventDefaultDirective, StopPropagationDirective } from '../directives';
|
||||
import { InputWithActionComponent } from '../inputs';
|
||||
|
||||
const components = [QuickFiltersComponent, SingleFilterComponent];
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Component, computed, effect, input, output, signal, untracked } from '@angular/core';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { MatCheckbox } from '@angular/material/checkbox';
|
||||
import { ChevronButtonComponent, CircleButtonComponent, IconButtonComponent } from '../../buttons';
|
||||
import { StopPropagationDirective } from '../../directives';
|
||||
import { InputWithActionComponent } from '../../inputs';
|
||||
import { InputWithActionComponent } from '../../inputs/input-with-action/input-with-action.component';
|
||||
import { SimpleFilterOption } from '../models/simple-filter-option';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
<div [class.row]="displayInRow" class="iqser-input-group">
|
||||
@for (option of options; track option) {
|
||||
<div [class.row]="displayInRow()" class="iqser-input-group">
|
||||
@for (option of options(); track option) {
|
||||
<div
|
||||
(click)="toggleOption(option)"
|
||||
[class.active]="option.value === value?.value"
|
||||
[class.active]="isSelected(option)"
|
||||
[class.disabled]="option.disabled"
|
||||
[id]="groupId(option)"
|
||||
[matTooltipPosition]="'above'"
|
||||
[matTooltip]="option.tooltip || '' | translate"
|
||||
[ngClass]="{ 'mb-8': !displayInRow, 'mr-8': displayInRow }"
|
||||
[ngClass]="{ 'mb-8': !displayInRow(), 'mr-8': displayInRow() }"
|
||||
class="option pointer"
|
||||
>
|
||||
@if (option.icon) {
|
||||
@ -15,7 +15,9 @@
|
||||
<mat-icon [svgIcon]="option.icon" class="icon"></mat-icon>
|
||||
<div class="text">
|
||||
<label class="details-radio-label pointer">{{ option.label | translate: option.descriptionParams }}</label>
|
||||
|
||||
<span class="hint">{{ option.description | translate: option.descriptionParams | replaceNbsp }}</span>
|
||||
|
||||
@if (option.extraOption && !option.extraOption.hidden && isSelected(option)) {
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox
|
||||
@ -27,6 +29,7 @@
|
||||
>
|
||||
{{ option.extraOption.label | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
@if (option.extraOption.description) {
|
||||
<span
|
||||
[innerHTML]="option.extraOption.description | translate"
|
||||
@ -36,6 +39,7 @@
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (isSelected(option)) {
|
||||
<mat-icon class="checked" svgIcon="iqser:radio-selected"></mat-icon>
|
||||
}
|
||||
@ -43,8 +47,10 @@
|
||||
} @else {
|
||||
<div class="flex-align-items-center mb-8">
|
||||
<iqser-round-checkbox [active]="isSelected(option)" class="mr-6"></iqser-round-checkbox>
|
||||
|
||||
<label class="details-radio-label pointer">{{ option.label | translate }}</label>
|
||||
</div>
|
||||
|
||||
<span class="hint">{{ option.description | translate }}</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { NgClass } from '@angular/common';
|
||||
import { booleanAttribute, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { booleanAttribute, Component, input, output } from '@angular/core';
|
||||
import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
@ -40,12 +40,12 @@ import { DetailsRadioOption } from './details-radio-option';
|
||||
],
|
||||
})
|
||||
export class DetailsRadioComponent<I> extends FormFieldComponent<DetailsRadioOption<I>> {
|
||||
@Input({ required: true }) options: DetailsRadioOption<I>[] = [];
|
||||
@Input({ transform: booleanAttribute }) displayInRow = false;
|
||||
readonly options = input.required<DetailsRadioOption<I>[]>();
|
||||
readonly displayInRow = input(false, { transform: booleanAttribute });
|
||||
|
||||
@Output() readonly extraOptionChanged: EventEmitter<DetailsRadioOption<I>> = new EventEmitter();
|
||||
readonly extraOptionChanged = output<DetailsRadioOption<I>>();
|
||||
|
||||
toggleOption(option: DetailsRadioOption<I>): void {
|
||||
toggleOption(option: DetailsRadioOption<I>) {
|
||||
if (option.value !== this._value?.value && !option.disabled) {
|
||||
this.markAsTouched();
|
||||
const currentlyChecked = this.value?.value === option.value;
|
||||
@ -54,15 +54,20 @@ export class DetailsRadioComponent<I> extends FormFieldComponent<DetailsRadioOpt
|
||||
}
|
||||
}
|
||||
|
||||
groupId(option: DetailsRadioOption<I>): string {
|
||||
groupId(option: DetailsRadioOption<I>) {
|
||||
return (option.id ?? option.label.replace('.', '-')) + '-checkbox-details-input';
|
||||
}
|
||||
|
||||
isSelected(option: DetailsRadioOption<I>): boolean {
|
||||
isSelected(option: DetailsRadioOption<I>) {
|
||||
return option.value === this.value?.value;
|
||||
}
|
||||
|
||||
emitExtraOption(): void {
|
||||
emitExtraOption() {
|
||||
if (!this.value) {
|
||||
console.error('Extra option selected but the value is undefined');
|
||||
return;
|
||||
}
|
||||
|
||||
this.extraOptionChanged.emit(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,37 +1,46 @@
|
||||
<div [class.datepicker-wrapper]="isDate" [ngClass]="classList" class="iqser-input-group">
|
||||
@if (label) {
|
||||
<label> {{ label }} </label>
|
||||
<div [class.datepicker-wrapper]="isDate()" [ngClass]="classList()" class="iqser-input-group">
|
||||
@if (label()) {
|
||||
<label> {{ label() }} </label>
|
||||
}
|
||||
|
||||
@if (isDate) {
|
||||
@if (isDate()) {
|
||||
<input
|
||||
(ngModelChange)="onChange($event)"
|
||||
[(ngModel)]="input"
|
||||
[disabled]="disabled"
|
||||
[id]="id"
|
||||
[id]="id()"
|
||||
[matDatepicker]="picker"
|
||||
[placeholder]="placeholder || 'dd/mm/yy'"
|
||||
[placeholder]="placeholder() || 'dd/mm/yy'"
|
||||
iqserStopPropagation
|
||||
/>
|
||||
|
||||
<mat-datepicker-toggle [for]="picker" matSuffix>
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="iqser:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
|
||||
<mat-datepicker #picker (closed)="onCloseDatepicker()" (opened)="onOpenDatepicker()"></mat-datepicker>
|
||||
}
|
||||
|
||||
@if (isText) {
|
||||
@if (isText()) {
|
||||
<input
|
||||
(ngModelChange)="onChange($event)"
|
||||
[(ngModel)]="input"
|
||||
[disabled]="disabled"
|
||||
[id]="id"
|
||||
[placeholder]="placeholder || ''"
|
||||
[id]="id()"
|
||||
[placeholder]="placeholder() || ''"
|
||||
iqserStopPropagation
|
||||
type="text"
|
||||
/>
|
||||
}
|
||||
|
||||
@if (isNumber) {
|
||||
<input (ngModelChange)="onChange($event)" [(ngModel)]="input" [disabled]="disabled" [id]="id" iqserStopPropagation type="number" />
|
||||
@if (isNumber()) {
|
||||
<input
|
||||
(ngModelChange)="onChange($event)"
|
||||
[(ngModel)]="input"
|
||||
[disabled]="disabled"
|
||||
[id]="id()"
|
||||
iqserStopPropagation
|
||||
type="number"
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { FormFieldComponent } from '../form-field/form-field-component.directive';
|
||||
import { NgClass } from '@angular/common';
|
||||
import { ChangeDetectionStrategy, Component, computed, input, model, output } from '@angular/core';
|
||||
import { FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { StopPropagationDirective } from '../../directives';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
import { StopPropagationDirective } from '../../directives';
|
||||
import { FormFieldComponent } from '../form-field/form-field-component.directive';
|
||||
|
||||
const InputTypes = {
|
||||
export const InputTypes = {
|
||||
DATE: 'DATE',
|
||||
NUMBER: 'NUMBER',
|
||||
TEXT: 'TEXT',
|
||||
@ -39,28 +39,20 @@ type DynamicInput = number | string | Date;
|
||||
imports: [NgClass, FormsModule, MatDatepickerModule, StopPropagationDirective, MatIconModule, MatInputModule],
|
||||
})
|
||||
export class DynamicInputComponent extends FormFieldComponent<DynamicInput> {
|
||||
@Input() label?: string;
|
||||
@Input({ required: true }) type!: InputType;
|
||||
@Input() placeholder?: string;
|
||||
@Input() id?: string;
|
||||
@Input() classList = '';
|
||||
@Input() input!: DynamicInput;
|
||||
@Output() readonly closedDatepicker = new EventEmitter<boolean>();
|
||||
readonly label = input<string>();
|
||||
readonly type = input.required<InputType>();
|
||||
readonly placeholder = input<string>();
|
||||
readonly id = input<string>();
|
||||
readonly classList = input('');
|
||||
readonly input = model<DynamicInput>();
|
||||
readonly closedDatepicker = output<boolean>();
|
||||
|
||||
get isDate() {
|
||||
return this.type === InputTypes.DATE;
|
||||
}
|
||||
|
||||
get isNumber() {
|
||||
return this.type === InputTypes.NUMBER;
|
||||
}
|
||||
|
||||
get isText() {
|
||||
return this.type === InputTypes.TEXT;
|
||||
}
|
||||
readonly isDate = computed(() => this.type() === InputTypes.DATE);
|
||||
readonly isNumber = computed(() => this.type() === InputTypes.NUMBER);
|
||||
readonly isText = computed(() => this.type() === InputTypes.TEXT);
|
||||
|
||||
writeValue(input: DynamicInput): void {
|
||||
this.input = input;
|
||||
this.input.set(input);
|
||||
}
|
||||
|
||||
onCloseDatepicker() {
|
||||
|
||||
@ -1,48 +1,53 @@
|
||||
@if (!editing) {
|
||||
@if (showPreview) {
|
||||
<div>
|
||||
{{ value }}
|
||||
</div>
|
||||
@if (!_editing()) {
|
||||
@if (showPreview()) {
|
||||
<div>{{ value() }}</div>
|
||||
}
|
||||
|
||||
<div class="flex">
|
||||
@if (canEdit) {
|
||||
@if (canEdit()) {
|
||||
<iqser-circle-button
|
||||
(action)="editing = true"
|
||||
[tooltip]="editTooltip"
|
||||
[type]="buttonsType"
|
||||
[attr.help-mode-key]="helpModeKey"
|
||||
[tooltip]="editTooltip()"
|
||||
[type]="buttonsType()"
|
||||
[attr.help-mode-key]="helpModeKey()"
|
||||
class="edit-button"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
}
|
||||
|
||||
<ng-content select="[slot=editing]"></ng-content>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (editing) {
|
||||
} @else {
|
||||
<form (submit)="saveValue()">
|
||||
<div [class]="'iqser-input-group ' + class">
|
||||
@if (!parentId) {
|
||||
<input (ngModelChange)="newValue = $event" [ngModel]="value" [placeholder]="placeholder" name="name" />
|
||||
<div [class]="'iqser-input-group ' + class()">
|
||||
@if (!parentId()) {
|
||||
<input (ngModelChange)="newValue = $event" [ngModel]="value()" [placeholder]="placeholder()" name="name" />
|
||||
} @else {
|
||||
<textarea
|
||||
(ngModelChange)="newValue = $event"
|
||||
[ngModel]="value"
|
||||
[placeholder]="placeholder"
|
||||
[id]="id"
|
||||
[ngModel]="value()"
|
||||
[placeholder]="placeholder()"
|
||||
[id]="id()"
|
||||
name="name"
|
||||
[style.width]="this.textArea.width + 'px'"
|
||||
[style.height]="this.textArea.height + 'px'"
|
||||
[style.width]="textArea.width + 'px'"
|
||||
[style.height]="textArea.height + 'px'"
|
||||
></textarea>
|
||||
}
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="flex">
|
||||
<iqser-circle-button (action)="saveValue()" [tooltip]="saveTooltip" [type]="buttonsType" icon="iqser:check"></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
(action)="saveValue()"
|
||||
[tooltip]="saveTooltip()"
|
||||
[type]="buttonsType()"
|
||||
icon="iqser:check"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="editing = false"
|
||||
[tooltip]="cancelTooltip"
|
||||
[type]="buttonsType"
|
||||
[tooltip]="cancelTooltip()"
|
||||
[type]="buttonsType()"
|
||||
icon="iqser:close"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
|
||||
@ -1,43 +1,41 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, OnChanges, Output, SimpleChanges } from '@angular/core';
|
||||
import { booleanAttribute, ChangeDetectionStrategy, Component, input, OnChanges, output, signal, SimpleChanges } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
import { CircleButtonComponent, CircleButtonType, CircleButtonTypes } from '../../buttons';
|
||||
import { CircleButtonComponent } from '../../buttons/circle-button/circle-button.component';
|
||||
import { CircleButtonType, CircleButtonTypes } from '../../buttons/types/circle-button.type';
|
||||
|
||||
@Component({
|
||||
selector: 'iqser-editable-input [value]',
|
||||
selector: 'iqser-editable-input',
|
||||
templateUrl: './editable-input.component.html',
|
||||
styleUrls: ['./editable-input.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: true,
|
||||
imports: [CircleButtonComponent, FormsModule],
|
||||
host: {
|
||||
'[class.editing]': '_editing()',
|
||||
},
|
||||
})
|
||||
export class EditableInputComponent implements OnChanges {
|
||||
@Input() id?: string;
|
||||
@Input() parentId?: string;
|
||||
@Input() value!: string;
|
||||
@Input() editTooltip?: string;
|
||||
@Input() saveTooltip?: string;
|
||||
@Input() cancelTooltip?: string;
|
||||
@Input() placeholder = '';
|
||||
@Input() class?: string;
|
||||
@Input() showPreview = true;
|
||||
@Input() canEdit = true;
|
||||
@Input() buttonsType: CircleButtonType = CircleButtonTypes.default;
|
||||
@Input() helpModeKey: string = '';
|
||||
@Input() lastChild = false;
|
||||
@Output() readonly save = new EventEmitter<string>();
|
||||
protected readonly _editing = signal(false);
|
||||
readonly id = input<string>();
|
||||
readonly parentId = input<string>();
|
||||
readonly value = input.required<string>();
|
||||
readonly editTooltip = input('');
|
||||
readonly saveTooltip = input('');
|
||||
readonly cancelTooltip = input('');
|
||||
readonly placeholder = input('');
|
||||
readonly class = input<string>();
|
||||
readonly showPreview = input(true, { transform: booleanAttribute });
|
||||
readonly canEdit = input(true, { transform: booleanAttribute });
|
||||
readonly buttonsType = input<CircleButtonType>(CircleButtonTypes.default);
|
||||
readonly helpModeKey = input('');
|
||||
readonly lastChild = input(false, { transform: booleanAttribute });
|
||||
readonly save = output<string>();
|
||||
textArea?: { width: number; height: number };
|
||||
newValue = '';
|
||||
|
||||
private _editing = false;
|
||||
|
||||
@HostBinding('class.editing')
|
||||
get editing(): boolean {
|
||||
return this._editing;
|
||||
}
|
||||
|
||||
set editing(value: boolean) {
|
||||
this._editing = value;
|
||||
this.newValue = this.value;
|
||||
this._editing.set(value);
|
||||
this.newValue = this.value();
|
||||
}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges): void {
|
||||
@ -51,12 +49,12 @@ export class EditableInputComponent implements OnChanges {
|
||||
|
||||
setTextAreaSize() {
|
||||
setTimeout(() => {
|
||||
const element = document.getElementById(this.id as string) as HTMLElement;
|
||||
const parentElement = document.getElementById(this.parentId as string) as HTMLElement;
|
||||
const element = document.getElementById(this.id() as string) as HTMLElement;
|
||||
const parentElement = document.getElementById(this.parentId() as string) as HTMLElement;
|
||||
const width = parentElement.offsetWidth - 98;
|
||||
let height = (this.lastChild ? parentElement.offsetHeight : element.offsetHeight) - 16;
|
||||
if (this.lastChild) {
|
||||
const lastChildIndex = Number(this.id?.split('-')[2]);
|
||||
let height = (this.lastChild() ? parentElement.offsetHeight : element.offsetHeight) - 16;
|
||||
if (this.lastChild()) {
|
||||
const lastChildIndex = Number(this.id()?.split('-')[2]);
|
||||
height = height - lastChildIndex * element.offsetHeight;
|
||||
}
|
||||
this.textArea = { width, height };
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
export * from './round-checkbox/round-checkbox.component';
|
||||
export * from './editable-input/editable-input.component';
|
||||
export * from './input-with-action/input-with-action.component';
|
||||
export * from './details-radio/details-radio.component';
|
||||
export * from './details-radio/details-radio-option';
|
||||
export * from './form-field/form-field-component.directive';
|
||||
export * from './dynamic-input/dynamic-input.component';
|
||||
@ -1,34 +1,33 @@
|
||||
<form (submit)="executeAction()" [style.max-width]="computedWidth" [style.width]="computedWidth" class="iqser-input-group">
|
||||
<form (submit)="executeAction()" [style.max-width]="_computedWidth()" [style.width]="_computedWidth()" class="iqser-input-group">
|
||||
<input
|
||||
(ngModelChange)="valueChange.emit($event)"
|
||||
[(ngModel)]="value"
|
||||
[autocomplete]="autocomplete"
|
||||
[disabled]="disabled"
|
||||
[id]="inputId"
|
||||
[autocomplete]="autocomplete()"
|
||||
[disabled]="disabled()"
|
||||
[id]="inputId()"
|
||||
[ngModelOptions]="{ standalone: true }"
|
||||
[placeholder]="placeholder"
|
||||
[placeholder]="placeholder()"
|
||||
class="with-icon mt-0"
|
||||
type="text"
|
||||
/>
|
||||
|
||||
@if (hint) {
|
||||
<span class="hint">{{ hint }}</span>
|
||||
@if (hint()) {
|
||||
<span class="hint">{{ hint() }}</span>
|
||||
}
|
||||
|
||||
@if (isSearch && !hasContent) {
|
||||
@if (_isSearch() && !_hasContent()) {
|
||||
<mat-icon class="icon-right" svgIcon="iqser:search"></mat-icon>
|
||||
}
|
||||
|
||||
@if (isSearch && hasContent) {
|
||||
<iqser-circle-button (action)="reset()" [buttonId]="inputId + '-clear'" icon="iqser:close"></iqser-circle-button>
|
||||
@if (_isSearch() && _hasContent()) {
|
||||
<iqser-circle-button (action)="reset()" [buttonId]="inputId() + '-clear'" icon="iqser:close"></iqser-circle-button>
|
||||
}
|
||||
|
||||
@if (!isSearch) {
|
||||
@if (icon(); as icon) {
|
||||
<iqser-circle-button
|
||||
(action)="executeAction()"
|
||||
[buttonId]="actionButtonId"
|
||||
[disabled]="!hasContent"
|
||||
[icon]="icon!"
|
||||
[buttonId]="actionButtonId()"
|
||||
[disabled]="!_hasContent()"
|
||||
[icon]="icon"
|
||||
></iqser-circle-button>
|
||||
}
|
||||
</form>
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { randomString } from '../../utils';
|
||||
import { booleanAttribute, ChangeDetectionStrategy, Component, computed, input, model, output } from '@angular/core';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { CircleButtonComponent } from '../../buttons';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
|
||||
import { CircleButtonComponent } from '../../buttons/circle-button/circle-button.component';
|
||||
import { randomString } from '../../utils/functions';
|
||||
|
||||
@Component({
|
||||
selector: 'iqser-input-with-action',
|
||||
templateUrl: './input-with-action.component.html',
|
||||
@ -14,41 +14,27 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
imports: [FormsModule, MatIconModule, CircleButtonComponent],
|
||||
})
|
||||
export class InputWithActionComponent {
|
||||
@Input() inputId = `${randomString() + '-search-input'}`;
|
||||
@Input() actionButtonId = `${randomString() + '-action-input'}`;
|
||||
@Input() placeholder = '';
|
||||
@Input() hint?: string;
|
||||
@Input() width: number | 'full' = 250;
|
||||
@Input() icon?: string;
|
||||
@Input() autocomplete: 'on' | 'off' = 'on';
|
||||
@Input() value = '';
|
||||
@Input() disabled = false;
|
||||
@Output() readonly action = new EventEmitter<string>();
|
||||
@Output() readonly valueChange = new EventEmitter<string>();
|
||||
readonly inputId = input(`${randomString() + '-search-input'}`);
|
||||
readonly actionButtonId = input(`${randomString() + '-action-input'}`);
|
||||
readonly placeholder = input('');
|
||||
readonly hint = input<string>();
|
||||
readonly width = input<number | 'full'>(250);
|
||||
protected readonly _computedWidth = computed(() => (this.width() === 'full' ? '100%' : `${this.width()}px`));
|
||||
readonly icon = input<string>();
|
||||
protected readonly _isSearch = computed(() => !this.icon());
|
||||
readonly autocomplete = input<'on' | 'off'>('on');
|
||||
readonly value = model('');
|
||||
protected readonly _hasContent = computed(() => !!this.value()?.length);
|
||||
readonly disabled = input(false, { transform: booleanAttribute });
|
||||
readonly action = output<string>();
|
||||
|
||||
get hasContent(): boolean {
|
||||
return !!this.value?.length;
|
||||
reset() {
|
||||
this.value.set('');
|
||||
}
|
||||
|
||||
get computedWidth(): string {
|
||||
return this.width === 'full' ? '100%' : `${this.width}px`;
|
||||
}
|
||||
|
||||
get isSearch(): boolean {
|
||||
return !this.icon;
|
||||
}
|
||||
|
||||
constructor(private readonly _changeDetectorRef: ChangeDetectorRef) {}
|
||||
|
||||
reset(): void {
|
||||
this.value = '';
|
||||
this.valueChange.emit(this.value);
|
||||
this._changeDetectorRef.markForCheck();
|
||||
}
|
||||
|
||||
executeAction(): void {
|
||||
if (this.hasContent) {
|
||||
this.action.emit(this.value);
|
||||
executeAction() {
|
||||
if (this._hasContent()) {
|
||||
this.action.emit(this.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
<div
|
||||
#wrapper
|
||||
[class.active]="active && !indeterminate"
|
||||
[class.inactive]="!active && !indeterminate"
|
||||
[class.indeterminate]="indeterminate"
|
||||
[class.with-bg]="type === 'with-bg'"
|
||||
[class.active]="active() && !indeterminate()"
|
||||
[class.inactive]="!active() && !indeterminate()"
|
||||
[class.indeterminate]="indeterminate()"
|
||||
[class.with-bg]="type() === 'with-bg'"
|
||||
class="wrapper"
|
||||
>
|
||||
@if (active && !indeterminate) {
|
||||
@if (active() && !indeterminate()) {
|
||||
<mat-icon svgIcon="iqser:radio-selected"></mat-icon>
|
||||
}
|
||||
@if (indeterminate) {
|
||||
|
||||
@if (indeterminate()) {
|
||||
<mat-icon svgIcon="iqser:radio-indeterminate"></mat-icon>
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { booleanAttribute, ChangeDetectionStrategy, Component, ElementRef, HostBinding, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { booleanAttribute, ChangeDetectionStrategy, Component, effect, ElementRef, input, numberAttribute, viewChild } from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
|
||||
@Component({
|
||||
@ -9,18 +9,17 @@ import { MatIconModule } from '@angular/material/icon';
|
||||
standalone: true,
|
||||
imports: [MatIconModule],
|
||||
})
|
||||
export class RoundCheckboxComponent implements OnInit {
|
||||
@Input() size = 20;
|
||||
@Input({ transform: booleanAttribute }) active = false;
|
||||
@Input() indeterminate = false;
|
||||
@Input() type: 'default' | 'with-bg' = 'default';
|
||||
@HostBinding('class.disabled')
|
||||
@Input()
|
||||
disabled = false;
|
||||
export class RoundCheckboxComponent {
|
||||
protected readonly _wrapper = viewChild.required('wrapper', { read: ElementRef });
|
||||
readonly size = input(20, { transform: numberAttribute });
|
||||
readonly active = input(false, { transform: booleanAttribute });
|
||||
readonly indeterminate = input(false, { transform: booleanAttribute });
|
||||
readonly type = input<'default' | 'with-bg'>('default');
|
||||
readonly disabled = input(false, { transform: booleanAttribute });
|
||||
|
||||
@ViewChild('wrapper', { static: true }) private readonly _wrapper!: ElementRef;
|
||||
|
||||
ngOnInit(): void {
|
||||
(this._wrapper.nativeElement as HTMLElement).style.setProperty('--size', `${this.size}px`);
|
||||
constructor() {
|
||||
effect(() => {
|
||||
(this._wrapper().nativeElement as HTMLElement).style.setProperty('--size', `${this.size()}px`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,8 @@ import { CircleButtonComponent, IconButtonComponent } from '../buttons';
|
||||
import { HasScrollbarDirective, SyncWidthDirective } from '../directives';
|
||||
import { EmptyStateComponent } from '../empty-state';
|
||||
import { IqserFiltersModule, PopupFilterComponent } from '../filtering';
|
||||
import { InputWithActionComponent, RoundCheckboxComponent } from '../inputs';
|
||||
import { InputWithActionComponent } from '../inputs/input-with-action/input-with-action.component';
|
||||
import { RoundCheckboxComponent } from '../inputs/round-checkbox/round-checkbox.component';
|
||||
import { SnakeCasePipe } from '../pipes/snake-case.pipe';
|
||||
import { PageHeaderComponent } from './page-header/page-header.component';
|
||||
import { ScrollButtonComponent } from './scroll-button/scroll-button.component';
|
||||
|
||||
@ -3,7 +3,7 @@ import { ChangeDetectionStrategy, Component, inject, Input, TemplateRef } from '
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { SyncWidthDirective } from '../../directives';
|
||||
import { FilterService, IqserFiltersModule } from '../../filtering';
|
||||
import { RoundCheckboxComponent } from '../../inputs';
|
||||
import { RoundCheckboxComponent } from '../../inputs/round-checkbox/round-checkbox.component';
|
||||
import { Id, IListable, ListingMode, ListingModes, TableColumnConfig } from '../models';
|
||||
import { EntitiesService, ListingService } from '../services';
|
||||
import { TableColumnNameComponent } from '../table-column-name/table-column-name.component';
|
||||
|
||||
@ -14,11 +14,13 @@ import {
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { combineLatest } from 'rxjs';
|
||||
import { filter, map, tap } from 'rxjs/operators';
|
||||
import { CircleButtonComponent, CircleButtonTypes } from '../../../buttons';
|
||||
import { RoundCheckboxComponent } from '../../../inputs';
|
||||
import { ContextComponent, Debounce } from '../../../utils';
|
||||
import { IListable } from '../../models';
|
||||
import { ListingService } from '../../services';
|
||||
import { CircleButtonComponent } from '../../../buttons/circle-button/circle-button.component';
|
||||
import { CircleButtonTypes } from '../../../buttons/types/circle-button.type';
|
||||
import { RoundCheckboxComponent } from '../../../inputs/round-checkbox/round-checkbox.component';
|
||||
import { ContextComponent } from '../../../utils/context.component';
|
||||
import { Debounce } from '../../../utils/decorators/debounce.decorator';
|
||||
import { IListable } from '../../models/listable';
|
||||
import { ListingService } from '../../services/listing.service';
|
||||
import { WorkflowColumn } from '../models/workflow-column.model';
|
||||
|
||||
interface ColumnHeaderContext {
|
||||
|
||||
@ -2,6 +2,9 @@ import { combineLatest, Observable, of } from 'rxjs';
|
||||
import { map, startWith } from 'rxjs/operators';
|
||||
import { ValuesOf } from './types/utility-types';
|
||||
|
||||
/**
|
||||
* @deprecated Switch to signals instead
|
||||
*/
|
||||
export class ContextComponent<T> {
|
||||
componentContext$: Observable<T> | null = of({} as T);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user