release(tach-typography): v0.2.0
This commit is contained in:
@@ -1,6 +1,19 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { Directive, ElementRef, Input, OnChanges, Renderer2, SimpleChanges } from "@angular/core";
|
||||
import { NzTypographyModule } from "ng-zorro-antd/typography";
|
||||
import { NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault } from "@angular/common";
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
Directive,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
inject,
|
||||
Input,
|
||||
NgModule,
|
||||
OnChanges,
|
||||
Output,
|
||||
Renderer2,
|
||||
SimpleChanges,
|
||||
} from "@angular/core";
|
||||
import { NzTypographyComponent, NzTypographyModule } from "ng-zorro-antd/typography";
|
||||
|
||||
import {
|
||||
tachTypographyClassList,
|
||||
@@ -20,6 +33,18 @@ export interface AngularTypographyRenderOptions extends TypographyRenderOptions
|
||||
preserveStyle?: Record<string, string | number>;
|
||||
}
|
||||
|
||||
export type TachTypographyHostTag = "span" | "p" | "a" | "h1" | "h2" | "h3" | "h4";
|
||||
type NonFunctionNonEmitterKeys<T> = {
|
||||
[K in keyof T]-?: T[K] extends (...args: never[]) => unknown
|
||||
? never
|
||||
: T[K] extends EventEmitter<unknown>
|
||||
? never
|
||||
: K;
|
||||
}[keyof T];
|
||||
type NzTypographyInputKey = Extract<NonFunctionNonEmitterKeys<NzTypographyComponent>, `nz${string}`>;
|
||||
export type TachTypographyNzProps = Partial<Pick<NzTypographyComponent, NzTypographyInputKey>>;
|
||||
export type TachTypographyHostProps = Record<string, unknown>;
|
||||
|
||||
const camelToKebab = (value: string): string =>
|
||||
value.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`);
|
||||
|
||||
@@ -133,8 +158,292 @@ export class TachTypographyDirective implements OnChanges {
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: "[tachTypographyNzProps]",
|
||||
standalone: true,
|
||||
})
|
||||
export class TachTypographyNzPropsDirective implements OnChanges {
|
||||
@Input() tachTypographyNzProps: TachTypographyNzProps | null | undefined;
|
||||
|
||||
private readonly appliedNzKeys = new Set<string>();
|
||||
private readonly nzTypography = inject(NzTypographyComponent, { self: true, optional: true });
|
||||
|
||||
ngOnChanges(): void {
|
||||
if (!this.nzTypography) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nzTypography = this.nzTypography as unknown as Record<string, unknown>;
|
||||
const nextProps = this.tachTypographyNzProps ?? {};
|
||||
const nextKeys = new Set<string>();
|
||||
|
||||
for (const [key, value] of Object.entries(nextProps)) {
|
||||
if (!key.startsWith("nz")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nzTypography[key] = value;
|
||||
nextKeys.add(key);
|
||||
}
|
||||
|
||||
for (const key of this.appliedNzKeys) {
|
||||
if (!nextKeys.has(key)) {
|
||||
nzTypography[key] = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
this.appliedNzKeys.clear();
|
||||
for (const key of nextKeys) {
|
||||
this.appliedNzKeys.add(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Directive({
|
||||
selector: "[tachTypographyHostProps]",
|
||||
standalone: true,
|
||||
})
|
||||
export class TachTypographyHostPropsDirective implements OnChanges {
|
||||
@Input() tachTypographyHostProps: TachTypographyHostProps | null | undefined;
|
||||
|
||||
private readonly appliedHostProps = new Map<string, "attr" | "prop">();
|
||||
|
||||
constructor(
|
||||
private readonly elementRef: ElementRef<HTMLElement>,
|
||||
private readonly renderer: Renderer2,
|
||||
) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
const nextProps = this.tachTypographyHostProps ?? {};
|
||||
const nextAppliedProps = new Map<string, "attr" | "prop">();
|
||||
|
||||
for (const [key, value] of Object.entries(nextProps)) {
|
||||
if (key === "class" || key === "className" || key === "style") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value === undefined || value === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const applyAsAttr = this.shouldApplyAsAttribute(key, value);
|
||||
if (applyAsAttr) {
|
||||
if (typeof value === "boolean") {
|
||||
if (value) {
|
||||
this.renderer.setAttribute(this.elementRef.nativeElement, key, "");
|
||||
} else {
|
||||
this.renderer.removeAttribute(this.elementRef.nativeElement, key);
|
||||
}
|
||||
} else {
|
||||
this.renderer.setAttribute(this.elementRef.nativeElement, key, String(value));
|
||||
}
|
||||
nextAppliedProps.set(key, "attr");
|
||||
continue;
|
||||
}
|
||||
|
||||
this.renderer.setProperty(this.elementRef.nativeElement, key, value);
|
||||
nextAppliedProps.set(key, "prop");
|
||||
}
|
||||
|
||||
for (const [key, kind] of this.appliedHostProps.entries()) {
|
||||
if (nextAppliedProps.has(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (kind === "attr") {
|
||||
this.renderer.removeAttribute(this.elementRef.nativeElement, key);
|
||||
} else {
|
||||
this.renderer.setProperty(this.elementRef.nativeElement, key, undefined);
|
||||
}
|
||||
}
|
||||
|
||||
this.appliedHostProps.clear();
|
||||
for (const [key, kind] of nextAppliedProps.entries()) {
|
||||
this.appliedHostProps.set(key, kind);
|
||||
}
|
||||
}
|
||||
|
||||
private shouldApplyAsAttribute(key: string, value: unknown): boolean {
|
||||
if (key.startsWith("data-") || key.startsWith("aria-")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
||||
return !this.hasPropertyOnElement(key);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private hasPropertyOnElement(key: string): boolean {
|
||||
return key in this.elementRef.nativeElement;
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: "tach-typography",
|
||||
standalone: true,
|
||||
imports: [
|
||||
NzTypographyModule,
|
||||
TachTypographyDirective,
|
||||
TachTypographyNzPropsDirective,
|
||||
TachTypographyHostPropsDirective,
|
||||
NgSwitch,
|
||||
NgSwitchCase,
|
||||
NgSwitchDefault,
|
||||
NgStyle,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `
|
||||
<ng-container [ngSwitch]="hostTag">
|
||||
<p
|
||||
*ngSwitchCase="'p'"
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</p>
|
||||
<a
|
||||
*ngSwitchCase="'a'"
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</a>
|
||||
<h1
|
||||
*ngSwitchCase="'h1'"
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</h1>
|
||||
<h2
|
||||
*ngSwitchCase="'h2'"
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</h2>
|
||||
<h3
|
||||
*ngSwitchCase="'h3'"
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</h3>
|
||||
<h4
|
||||
*ngSwitchCase="'h4'"
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</h4>
|
||||
<span
|
||||
*ngSwitchDefault
|
||||
nz-typography
|
||||
[tachTypography]="variant"
|
||||
[tachTypographyColor]="color"
|
||||
[tachTypographyWeight]="weight"
|
||||
[tachTypographyClickable]="clickable"
|
||||
[tachTypographyClassName]="className"
|
||||
[tachTypographyEllipsis]="ellipsis"
|
||||
[tachTypographyNzProps]="nzProps"
|
||||
[tachTypographyHostProps]="hostProps"
|
||||
[ngStyle]="preserveStyle"
|
||||
(click)="handleClick($event)"
|
||||
>
|
||||
<ng-content />
|
||||
</span>
|
||||
</ng-container>
|
||||
`,
|
||||
})
|
||||
export class TachTypographyComponent {
|
||||
@Input("as") hostTag: TachTypographyHostTag = "span";
|
||||
@Input() variant: TypographyVariant = "Body";
|
||||
@Input() color: TypographyColor = "primary";
|
||||
@Input() weight: TypographyWeight = "normal";
|
||||
@Input() clickable = false;
|
||||
@Input() className: string | undefined;
|
||||
@Input() ellipsis: EllipsisOptions | undefined;
|
||||
@Input() nzProps: TachTypographyNzProps | undefined;
|
||||
@Input() hostProps: TachTypographyHostProps | undefined;
|
||||
@Input() preserveStyle: Record<string, string | number> | undefined;
|
||||
|
||||
@Output() readonly tachClick = new EventEmitter<MouseEvent>();
|
||||
|
||||
handleClick(event: MouseEvent): void {
|
||||
this.tachClick.emit(event);
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
imports: [NzTypographyModule, TachTypographyDirective],
|
||||
exports: [NzTypographyModule, TachTypographyDirective],
|
||||
imports: [
|
||||
NzTypographyModule,
|
||||
TachTypographyDirective,
|
||||
TachTypographyNzPropsDirective,
|
||||
TachTypographyHostPropsDirective,
|
||||
TachTypographyComponent,
|
||||
],
|
||||
exports: [
|
||||
NzTypographyModule,
|
||||
TachTypographyDirective,
|
||||
TachTypographyNzPropsDirective,
|
||||
TachTypographyHostPropsDirective,
|
||||
TachTypographyComponent,
|
||||
],
|
||||
})
|
||||
export class TachTypographyNzModule {}
|
||||
|
||||
1
packages/tach-typography/src/angular/public-api.ts
Normal file
1
packages/tach-typography/src/angular/public-api.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./index";
|
||||
Reference in New Issue
Block a user