feat: add @sda/flair-elements-ui library
Angular 19+ standalone library with 61 components, 15 directives, and 8 services for decorative visual effects, animations, and micro-interactions. Components include particle systems, flow fields, aurora effects, tilt/holographic/spotlight cards, text effects, dividers, scroll animations, generative art, celebrations, image treatments, morphing shapes, terminal output, and pattern textures. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
.fl-gradient-text {
|
||||
background-clip: text;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
color: transparent;
|
||||
display: inline-block;
|
||||
transition: background-position 0.3s ease;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
Component, ChangeDetectionStrategy, input, inject,
|
||||
ElementRef, afterNextRender, DestroyRef,
|
||||
} from '@angular/core';
|
||||
import { ReducedMotionService } from '../../services/reduced-motion.service';
|
||||
import { AnimationLoopService } from '../../services/animation-loop.service';
|
||||
|
||||
@Component({
|
||||
selector: 'fl-gradient-text',
|
||||
standalone: true,
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `<ng-content />`,
|
||||
styleUrl: './fl-gradient-text.component.scss',
|
||||
host: { 'class': 'fl-gradient-text' },
|
||||
})
|
||||
export class FlGradientTextComponent {
|
||||
private el = inject(ElementRef);
|
||||
private reducedMotion = inject(ReducedMotionService);
|
||||
private animationLoop = inject(AnimationLoopService);
|
||||
private destroyRef = inject(DestroyRef);
|
||||
|
||||
// Inputs
|
||||
readonly colors = input<string[]>(['#ff6b6b', '#4ecdc4', '#45b7d1', '#f7b731']);
|
||||
readonly speed = input(1);
|
||||
readonly angle = input(45);
|
||||
|
||||
private loopCleanup: (() => void) | null = null;
|
||||
private position = 0;
|
||||
|
||||
constructor() {
|
||||
afterNextRender(() => {
|
||||
this.updateGradient();
|
||||
|
||||
if (!this.reducedMotion.reduced()) {
|
||||
const id = `gradient-text-${Math.random().toString(36).slice(2)}`;
|
||||
this.loopCleanup = this.animationLoop.register(id, (delta) => this.tick(delta));
|
||||
}
|
||||
});
|
||||
|
||||
this.destroyRef.onDestroy(() => {
|
||||
this.loopCleanup?.();
|
||||
});
|
||||
}
|
||||
|
||||
private tick(delta: number): void {
|
||||
this.position += this.speed() * delta * 50;
|
||||
this.updateGradient();
|
||||
}
|
||||
|
||||
private updateGradient(): void {
|
||||
const host = this.el.nativeElement as HTMLElement;
|
||||
const colorStops = this.colors().join(', ');
|
||||
const angle = this.angle();
|
||||
const pos = this.position % 200;
|
||||
|
||||
host.style.backgroundImage = `linear-gradient(${angle}deg, ${colorStops})`;
|
||||
host.style.backgroundSize = '200% 200%';
|
||||
host.style.backgroundPosition = `${pos}% ${pos}%`;
|
||||
}
|
||||
}
|
||||
1
src/components/fl-gradient-text/index.ts
Normal file
1
src/components/fl-gradient-text/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './fl-gradient-text.component';
|
||||
Reference in New Issue
Block a user