@taiga-ui/cdk
Version:
Base library for creating Angular components and applications using Taiga UI principles regarding of actual visual appearance
204 lines (197 loc) • 8.37 kB
JavaScript
import * as i0 from '@angular/core';
import { inject, signal, ChangeDetectorRef, computed, untracked, Directive, Input, INJECTOR, ViewContainerRef, ViewChild, Injectable } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { NgControl, NgModel } from '@angular/forms';
import { EMPTY_FUNCTION } from '@taiga-ui/cdk/constants';
import { TUI_FALLBACK_VALUE } from '@taiga-ui/cdk/tokens';
import { tuiProvide } from '@taiga-ui/cdk/utils';
import { identity, Subject, delay, startWith, map, filter, distinctUntilChanged, switchMap, merge, EMPTY } from 'rxjs';
class TuiValueTransformer {
}
function tuiValueTransformerFrom(token) {
return {
provide: TuiValueTransformer,
useFactory: () => inject(token).valueTransformer,
};
}
class TuiNonNullableValueTransformer extends TuiValueTransformer {
fromControlValue(value) {
this.prevValue = value;
return value;
}
toControlValue(value) {
this.prevValue = value ?? this.prevValue;
return this.prevValue;
}
}
const TUI_IDENTITY_VALUE_TRANSFORMER = {
fromControlValue: identity,
toControlValue: identity,
};
const FLAGS = { self: true, optional: true };
/**
* Basic ControlValueAccessor class to build form components upon
*/
class TuiControl {
constructor() {
this.fallback = inject(TUI_FALLBACK_VALUE, FLAGS);
this.refresh$ = new Subject();
this.pseudoInvalid = signal(null);
this.internal = signal(this.fallback);
this.control = inject(NgControl, { self: true });
this.cdr = inject(ChangeDetectorRef);
this.transformer = inject(TuiValueTransformer, FLAGS) ?? TUI_IDENTITY_VALUE_TRANSFORMER;
this.value = computed(() => this.internal() ?? this.fallback);
this.readOnly = signal(false);
this.touched = signal(false);
this.status = signal(undefined);
this.disabled = computed(() => this.status() === 'DISABLED');
this.interactive = computed(() => !this.disabled() && !this.readOnly());
this.invalid = computed(() => this.pseudoInvalid() !== null
? !!this.pseudoInvalid() && this.interactive()
: this.interactive() && this.touched() && this.status() === 'INVALID');
this.mode = computed(() =>
// eslint-disable-next-line no-nested-ternary
this.readOnly() ? 'readonly' : this.invalid() ? 'invalid' : 'valid');
this.onTouched = EMPTY_FUNCTION;
this.onChange = EMPTY_FUNCTION;
this.control.valueAccessor = this;
this.refresh$
.pipe(delay(0), startWith(null), map(() => this.control.control), filter(Boolean), distinctUntilChanged(), switchMap((c) => merge(c.valueChanges, c.statusChanges, c.events || EMPTY).pipe(startWith(null))), takeUntilDestroyed())
.subscribe(() => this.update());
}
set readOnlySetter(readOnly) {
this.readOnly.set(readOnly);
}
set invalidSetter(invalid) {
this.pseudoInvalid.set(invalid);
}
registerOnChange(onChange) {
this.refresh$.next();
this.onChange = (value) => {
const internal = untracked(() => this.internal());
if (value === internal) {
return;
}
onChange(this.transformer.toControlValue(value));
this.internal.set(value);
this.update();
};
}
registerOnTouched(onTouched) {
this.onTouched = () => {
onTouched();
this.update();
};
}
setDisabledState() {
this.update();
}
writeValue(value) {
// TODO: https://github.com/angular/angular/issues/14988
const safe = this.control instanceof NgModel ? this.control.model : value;
this.internal.set(this.transformer.fromControlValue(safe));
this.update();
}
update() {
this.status.set(this.control.control?.status);
this.touched.set(!!this.control.control?.touched);
this.cdr.markForCheck();
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiControl, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiControl, inputs: { readOnlySetter: ["readOnly", "readOnlySetter"], invalidSetter: ["invalid", "invalidSetter"] }, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiControl, decorators: [{
type: Directive
}], ctorParameters: function () { return []; }, propDecorators: { readOnlySetter: [{
type: Input,
args: ['readOnly']
}], invalidSetter: [{
type: Input,
args: ['invalid']
}] } });
function tuiAsControl(control) {
return tuiProvide(TuiControl, control);
}
/// <reference types="@taiga-ui/tsconfig/ng-dev-mode" />
/// <reference types="@taiga-ui/tsconfig/ng-dev-mode" />
/**
* Abstract class for host element for dynamically created portals.
*/
class TuiPortals {
constructor() {
this.injector = inject(INJECTOR);
this.nothing = inject(TuiPortalService).attach(this);
}
addComponentChild(component) {
const injector = component.createInjector(this.injector);
const ref = this.vcr.createComponent(component.component, { injector });
ref.changeDetectorRef.detectChanges();
return ref;
}
addTemplateChild(templateRef, context) {
return this.vcr.createEmbeddedView(templateRef, context);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiPortals, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiPortals, viewQueries: [{ propertyName: "vcr", first: true, predicate: ["viewContainer"], descendants: true, read: ViewContainerRef }], ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiPortals, decorators: [{
type: Directive
}], propDecorators: { vcr: [{
type: ViewChild,
args: ['viewContainer', { read: ViewContainerRef }]
}] } });
/**
* Abstract service for displaying portals
*/
class TuiPortalService {
attach(host) {
this.host = host;
}
add(component) {
return this.safeHost.addComponentChild(component);
}
remove({ hostView }) {
this.removeTemplate(hostView);
}
addTemplate(templateRef, context) {
return this.safeHost.addTemplateChild(templateRef, context);
}
removeTemplate(viewRef) {
if (!viewRef.destroyed) {
viewRef.destroy();
}
}
get safeHost() {
if (!this.host) {
throw new TuiNoHostException();
}
return this.host;
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiPortalService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiPortalService }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiPortalService, decorators: [{
type: Injectable
}] });
function tuiAsPortal(portal) {
return tuiProvide(TuiPortalService, portal);
}
class TuiNoHostException extends Error {
constructor() {
super(ngDevMode
? 'Portals cannot be used without TuiPortalHostComponent; perhaps you forgot to wrap your application with tui-root.'
: '');
}
}
class TuiValidationError {
constructor(message, context = {}) {
this.message = message;
this.context = context;
}
}
/**
* Generated bundle index. Do not edit.
*/
export { TUI_IDENTITY_VALUE_TRANSFORMER, TuiControl, TuiNoHostException, TuiNonNullableValueTransformer, TuiPortalService, TuiPortals, TuiValidationError, TuiValueTransformer, tuiAsControl, tuiAsPortal, tuiValueTransformerFrom };
//# sourceMappingURL=taiga-ui-cdk-classes.mjs.map