@yelon/abc
Version:
Common business components of ng-yunzai.
537 lines (529 loc) • 23.4 kB
JavaScript
import { NgTemplateOutlet, CommonModule } from '@angular/common';
import * as i0 from '@angular/core';
import { inject, Injectable, ViewContainerRef, input, effect, Directive, Renderer2, ElementRef, signal, computed, model, booleanAttribute, ViewEncapsulation, ChangeDetectionStrategy, Component, NgModule, makeEnvironmentProviders, provideEnvironmentInitializer } from '@angular/core';
import { toObservable, takeUntilDestroyed } from '@angular/core/rxjs-interop';
import * as i1 from '@angular/forms';
import { FormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { of, map, combineLatest, take } from 'rxjs';
import { updateHostClass } from '@yelon/util/browser';
import { WINDOW } from '@yelon/util/token';
import { NzBadgeComponent, NzBadgeModule } from 'ng-zorro-antd/badge';
import { NzCheckboxComponent, NzCheckboxModule } from 'ng-zorro-antd/checkbox';
import { NzIconDirective, NzIconModule } from 'ng-zorro-antd/icon';
import { NzImageService, NzImageModule } from 'ng-zorro-antd/image';
import { NzRadioComponent, NzRadioModule } from 'ng-zorro-antd/radio';
import { NzTagComponent, NzTagModule } from 'ng-zorro-antd/tag';
import { NzTooltipDirective, NzTooltipModule } from 'ng-zorro-antd/tooltip';
import { deepMerge, warn } from '@yelon/util/other';
import { DomSanitizer } from '@angular/platform-browser';
import { yn } from '@yelon/theme';
import { YunzaiConfigService } from '@yelon/util/config';
import { formatDate } from '@yelon/util/date-time';
import { CurrencyService, formatMask } from '@yelon/util/format';
import { NzI18nService } from 'ng-zorro-antd/i18n';
import { NzImageModule as NzImageModule$1 } from 'ng-zorro-antd/experimental/image';
class CellService {
nzI18n = inject(NzI18nService);
currency = inject(CurrencyService);
dom = inject(DomSanitizer);
configSrv = inject(YunzaiConfigService);
globalOptions = this.configSrv.merge('cell', {
date: { format: 'yyyy-MM-dd HH:mm:ss' },
img: { size: 32 },
default: { text: '-' }
});
widgets = {
date: {
type: 'fn',
ref: (value, opt) => {
return {
text: formatDate(value, opt.date.format, {
locale: this.nzI18n.getDateLocale(),
customFormat: this.configSrv.get('themePipe')?.dateFormatCustom
})
};
}
},
mega: {
type: 'fn',
ref: (value, opt) => {
const res = this.currency.mega(value, opt.mega);
return { text: res.value, unit: res.unitI18n };
}
},
currency: {
type: 'fn',
ref: (value, opt) => {
return { text: this.currency.format(value, opt.currency) };
}
},
cny: {
type: 'fn',
ref: (value, opt) => {
return { text: this.currency.cny(value, opt.cny) };
}
},
boolean: {
type: 'fn',
ref: (value, opt) => {
return { text: this.dom.bypassSecurityTrustHtml(yn(value, opt.boolean)) };
}
},
img: {
type: 'fn',
ref: value => {
return { text: Array.isArray(value) ? value : [value] };
}
}
};
registerWidget(key, widget) {
this.widgets[key] = { type: 'widget', ref: widget };
}
getWidget(key) {
return this.widgets[key];
}
genType(value, options) {
if (options.type != null)
return options.type;
const typeOf = typeof value;
// When is timestamp
if (typeOf === 'number' && /^[0-9]{13}$/g.test(value))
return 'date';
if (value instanceof Date || options.date != null)
return 'date';
// Auto detection
if (options.widget != null)
return 'widget';
else if (options.mega != null)
return 'mega';
else if (options.currency != null)
return 'currency';
else if (options.cny != null)
return 'cny';
else if (options.img != null)
return 'img';
else if (options.link != null)
return 'link';
else if (options.html != null)
return 'html';
else if (options.badge != null)
return 'badge';
else if (options.tag != null)
return 'tag';
else if (options.checkbox != null)
return 'checkbox';
else if (options.radio != null)
return 'radio';
else if (options.enum != null)
return 'enum';
else if (typeOf === 'number')
return 'number';
else if (typeOf === 'boolean' || options.boolean != null)
return 'boolean';
else
return 'string';
}
fixOptions(options) {
return deepMerge({}, this.globalOptions, options);
}
get(value, options) {
const type = this.genType(value, { ...options });
const opt = this.fixOptions(options);
opt.type = type;
const isSafeHtml = typeof value === 'object' &&
typeof value?.getTypeName === 'function' &&
value?.getTypeName() != null;
let res = {
result: typeof value === 'object' && !isSafeHtml
? value
: { text: value == null ? '' : isSafeHtml ? value : `${value}` },
options: opt
};
const widget = this.widgets[type];
if (widget?.type === 'fn') {
res.result = widget.ref(value, opt);
}
return (typeof value === 'function' ? value(value, opt) : of(res.result)).pipe(map(text => {
res.result = text;
let dictData;
switch (type) {
case 'badge':
dictData = (opt.badge?.data ?? {})[value];
res.result = { color: 'default', ...dictData };
break;
case 'tag':
dictData = (opt.tag?.data ?? {})[value];
res.result = dictData;
break;
case 'enum':
res.result = { text: (opt.enum ?? {})[value] };
break;
case 'html':
res.safeHtml = opt.html?.safe;
break;
case 'string':
if (isSafeHtml)
res.safeHtml = 'safeHtml';
break;
}
if ((type === 'badge' || type === 'tag') && dictData?.tooltip != null) {
res.options.tooltip = dictData.tooltip;
}
if (opt.mask != null) {
res.result.text = formatMask(res.result.text, opt.mask);
}
return res;
}));
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellService, decorators: [{
type: Injectable,
args: [{ providedIn: 'root' }]
}] });
class CellHostDirective {
srv = inject(CellService);
vcr = inject(ViewContainerRef);
data = input.required(...(ngDevMode ? [{ debugName: "data" }] : []));
constructor() {
effect(() => {
const data = this.data();
const widget = data.options.widget;
const componentType = this.srv.getWidget(widget.key)?.ref;
if (componentType == null) {
if (typeof ngDevMode === 'undefined' || ngDevMode) {
warn(`cell: No widget for type "${widget.key}"`);
}
return;
}
this.vcr.clear();
const componentRef = this.vcr.createComponent(componentType);
componentRef.instance.data = data;
});
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellHostDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "20.1.3", type: CellHostDirective, isStandalone: true, selector: "[cell-widget-host]", inputs: { data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellHostDirective, decorators: [{
type: Directive,
args: [{
selector: '[cell-widget-host]'
}]
}], ctorParameters: () => [] });
class CellComponent {
srv = inject(CellService);
router = inject(Router);
renderer = inject(Renderer2);
imgSrv = inject(NzImageService);
win = inject(WINDOW);
el = inject(ElementRef).nativeElement;
destroy$;
_text = signal('', ...(ngDevMode ? [{ debugName: "_text" }] : []));
_unit = signal(undefined, ...(ngDevMode ? [{ debugName: "_unit" }] : []));
_res = signal(undefined, ...(ngDevMode ? [{ debugName: "_res" }] : []));
showDefault = computed(() => this.value() == this.safeOpt.default?.condition, ...(ngDevMode ? [{ debugName: "showDefault" }] : []));
value = model(...(ngDevMode ? [undefined, { debugName: "value" }] : []));
options = input(...(ngDevMode ? [undefined, { debugName: "options" }] : []));
loading = input(false, ...(ngDevMode ? [{ debugName: "loading", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
disabled = input(false, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
get safeOpt() {
return this._res()?.options ?? {};
}
isText = computed(() => this._res()?.safeHtml === 'text', ...(ngDevMode ? [{ debugName: "isText" }] : []));
constructor() {
combineLatest([toObservable(this.loading), toObservable(this.disabled)])
.pipe(takeUntilDestroyed())
.subscribe(() => this.setClass());
effect(() => {
const v = this.value();
const o = this.options();
this.destroy$?.unsubscribe();
this.destroy$ = this.srv
.get(v, o)
.pipe(take(1))
.subscribe(res => {
this._res.set(res);
this._text.set(res.result?.text ?? '');
this._unit.set(res.result?.unit ?? this.safeOpt?.unit);
this.setClass();
});
});
}
setClass() {
const { el, renderer } = this;
const { renderType, size, type } = this.safeOpt;
updateHostClass(el, renderer, {
[`cell`]: true,
[`cell__${renderType}`]: renderType != null,
[`cell__${size}`]: size != null,
[`cell__has-unit`]: this._unit(),
[`cell__has-default`]: this.showDefault(),
[`cell__disabled`]: this.disabled()
});
el.setAttribute('data-type', `${type}`);
}
_link(e) {
e.preventDefault();
e.stopPropagation();
if (this.disabled())
return;
const link = this.safeOpt.link;
const url = link?.url;
if (url == null)
return;
if (/https?:\/\//g.test(url)) {
this.win.open(url, link?.target);
}
else {
this.router.navigateByUrl(url);
}
}
_showImg(img) {
const config = this.safeOpt.img;
if (config == null || config.big == null)
return;
let idx = -1;
const list = this._text().map((p, index) => {
if (idx === -1 && p === img)
idx = index;
return typeof config.big === 'function' ? config.big(p) : p;
});
this.imgSrv
.preview(list.map(p => ({ src: p })), config.previewOptions)
.switchTo(idx);
}
ngOnDestroy() {
this.destroy$?.unsubscribe();
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.1.3", type: CellComponent, isStandalone: true, selector: "cell, [cell]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, exportAs: ["cell"], ngImport: i0, template: `
<ng-template #text>
res = _res();
text = _text();
(safeOpt.type) {
('checkbox') {
<label nz-checkbox [nzDisabled]="disabled()" [ngModel]="value()" (ngModelChange)="value.set($event)">
{{ safeOpt.checkbox?.label }}
</label>
}
('radio') {
<label nz-radio [nzDisabled]="disabled()" [ngModel]="value()" (ngModelChange)="value.set($event)">
{{ safeOpt.radio?.label }}
</label>
}
('link') {
<a (click)="_link($event)" [attr.target]="safeOpt.link?.target" [attr.title]="value()" [innerHTML]="text"></a>
}
('tag') {
<nz-tag [nzColor]="res?.result?.color">
<span [innerHTML]="text"></span>
</nz-tag>
}
('badge') {
<nz-badge [nzStatus]="res?.result?.color" nzText="{{ text }}" />
}
('widget') {
(res) {
<ng-template cell-widget-host [data]="res" />
}
}
('img') {
(i of $any(text); track $index) {
img = safeOpt.img;
<img
[attr.src]="i"
[attr.height]="img?.size"
[attr.width]="img?.size"
(click)="_showImg(i)"
class="img"
[class.point]="img?.big"
/>
}
}
{
(isText()) {
<span [innerText]="text" [attr.title]="value()"></span>
} {
<span [innerHTML]="text" [attr.title]="value()"></span>
}
(_unit()) {
<span class="unit">{{ _unit() }}</span>
}
}
}
</ng-template>
<ng-template #textWrap>
(showDefault()) {
{{ safeOpt.default?.text }}
} {
(safeOpt.tooltip) {
<span [nz-tooltip]="safeOpt.tooltip">
<ng-template [ngTemplateOutlet]="text" />
</span>
} {
<ng-template [ngTemplateOutlet]="text" />
}
}
</ng-template>
(loading()) {
<nz-icon nzType="loading" />
} {
<ng-template [ngTemplateOutlet]="textWrap" />
}
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: NzCheckboxComponent, selector: "[nz-checkbox]", inputs: ["nzValue", "nzAutoFocus", "nzDisabled", "nzIndeterminate", "nzChecked", "nzId", "nzName"], outputs: ["nzCheckedChange"], exportAs: ["nzCheckbox"] }, { kind: "component", type: NzRadioComponent, selector: "[nz-radio],[nz-radio-button]", inputs: ["nzValue", "nzDisabled", "nzAutoFocus", "nz-radio-button"], exportAs: ["nzRadio"] }, { kind: "directive", type: NzIconDirective, selector: "nz-icon,[nz-icon]", inputs: ["nzSpin", "nzRotate", "nzType", "nzTheme", "nzTwotoneColor", "nzIconfont"], exportAs: ["nzIcon"] }, { kind: "component", type: NzTagComponent, selector: "nz-tag", inputs: ["nzMode", "nzColor", "nzChecked", "nzBordered"], outputs: ["nzOnClose", "nzCheckedChange"], exportAs: ["nzTag"] }, { kind: "component", type: NzBadgeComponent, selector: "nz-badge", inputs: ["nzShowZero", "nzShowDot", "nzStandalone", "nzDot", "nzOverflowCount", "nzColor", "nzStyle", "nzText", "nzTitle", "nzStatus", "nzCount", "nzOffset", "nzSize"], exportAs: ["nzBadge"] }, { kind: "directive", type: NzTooltipDirective, selector: "[nz-tooltip]", inputs: ["nzTooltipTitle", "nzTooltipTitleContext", "nz-tooltip", "nzTooltipTrigger", "nzTooltipPlacement", "nzTooltipOrigin", "nzTooltipVisible", "nzTooltipMouseEnterDelay", "nzTooltipMouseLeaveDelay", "nzTooltipOverlayClassName", "nzTooltipOverlayStyle", "nzTooltipArrowPointAtCenter", "cdkConnectedOverlayPush", "nzTooltipColor"], outputs: ["nzTooltipVisibleChange"], exportAs: ["nzTooltip"] }, { kind: "ngmodule", type: NzImageModule }, { kind: "directive", type: CellHostDirective, selector: "[cell-widget-host]", inputs: ["data"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellComponent, decorators: [{
type: Component,
args: [{
selector: 'cell, [cell]',
template: `
<ng-template #text>
res = _res();
text = _text();
(safeOpt.type) {
('checkbox') {
<label nz-checkbox [nzDisabled]="disabled()" [ngModel]="value()" (ngModelChange)="value.set($event)">
{{ safeOpt.checkbox?.label }}
</label>
}
('radio') {
<label nz-radio [nzDisabled]="disabled()" [ngModel]="value()" (ngModelChange)="value.set($event)">
{{ safeOpt.radio?.label }}
</label>
}
('link') {
<a (click)="_link($event)" [attr.target]="safeOpt.link?.target" [attr.title]="value()" [innerHTML]="text"></a>
}
('tag') {
<nz-tag [nzColor]="res?.result?.color">
<span [innerHTML]="text"></span>
</nz-tag>
}
('badge') {
<nz-badge [nzStatus]="res?.result?.color" nzText="{{ text }}" />
}
('widget') {
(res) {
<ng-template cell-widget-host [data]="res" />
}
}
('img') {
(i of $any(text); track $index) {
img = safeOpt.img;
<img
[attr.src]="i"
[attr.height]="img?.size"
[attr.width]="img?.size"
(click)="_showImg(i)"
class="img"
[class.point]="img?.big"
/>
}
}
{
(isText()) {
<span [innerText]="text" [attr.title]="value()"></span>
} {
<span [innerHTML]="text" [attr.title]="value()"></span>
}
(_unit()) {
<span class="unit">{{ _unit() }}</span>
}
}
}
</ng-template>
<ng-template #textWrap>
(showDefault()) {
{{ safeOpt.default?.text }}
} {
(safeOpt.tooltip) {
<span [nz-tooltip]="safeOpt.tooltip">
<ng-template [ngTemplateOutlet]="text" />
</span>
} {
<ng-template [ngTemplateOutlet]="text" />
}
}
</ng-template>
(loading()) {
<nz-icon nzType="loading" />
} {
<ng-template [ngTemplateOutlet]="textWrap" />
}
`,
exportAs: 'cell',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
imports: [
FormsModule,
NgTemplateOutlet,
NzCheckboxComponent,
NzRadioComponent,
NzIconDirective,
NzTagComponent,
NzBadgeComponent,
NzTooltipDirective,
NzImageModule,
CellHostDirective
]
}]
}], ctorParameters: () => [] });
const COMPS = [CellComponent];
class CellModule {
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.1.3", ngImport: i0, type: CellModule, imports: [CommonModule,
FormsModule,
NzCheckboxModule,
NzRadioModule,
NzBadgeModule,
NzTagModule,
NzTooltipModule,
NzIconModule,
NzImageModule$1, CellComponent, CellHostDirective], exports: [CellComponent] });
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellModule, imports: [CommonModule,
FormsModule,
NzCheckboxModule,
NzRadioModule,
NzBadgeModule,
NzTagModule,
NzTooltipModule,
NzIconModule,
NzImageModule$1, COMPS] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.3", ngImport: i0, type: CellModule, decorators: [{
type: NgModule,
args: [{
imports: [
CommonModule,
FormsModule,
NzCheckboxModule,
NzRadioModule,
NzBadgeModule,
NzTagModule,
NzTooltipModule,
NzIconModule,
NzImageModule$1,
...COMPS,
CellHostDirective
],
exports: COMPS
}]
}] });
/**
* Just only using Standalone widgets
*/
function provideCellWidgets(...widgets) {
return makeEnvironmentProviders([
provideEnvironmentInitializer(() => {
const srv = inject(CellService);
widgets.forEach(widget => srv.registerWidget(widget.KEY, widget.type));
})
]);
}
/**
* Generated bundle index. Do not edit.
*/
export { CellComponent, CellHostDirective, CellModule, CellService, provideCellWidgets };
//# sourceMappingURL=cell.mjs.map