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:
Giuliano Silvestro
2026-03-09 10:24:52 +10:00
commit daf6182e94
230 changed files with 10642 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
:host {
display: inline-block;
width: 200px;
height: 200px;
}
.fl-frequency-rings__svg {
width: 100%;
height: 100%;
circle {
animation: fl-frequency-rings-pulse 2s ease-in-out infinite;
transform-origin: center;
will-change: transform, opacity;
}
}
@keyframes fl-frequency-rings-pulse {
0%, 100% {
transform: scale(1);
opacity: 0.8;
}
50% {
transform: scale(1.15);
opacity: 0.3;
}
}
:host.fl-frequency-rings--reduced-motion {
.fl-frequency-rings__svg circle {
animation: none;
}
}

View File

@@ -0,0 +1,60 @@
import {
Component, ChangeDetectionStrategy, input, inject, computed,
DestroyRef,
} from '@angular/core';
import { ReducedMotionService } from '../../services/reduced-motion.service';
@Component({
selector: 'fl-frequency-rings',
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<svg class="fl-frequency-rings__svg" viewBox="0 0 200 200">
@for (ring of ringData(); track ring.index) {
<circle
cx="100"
cy="100"
[attr.r]="ring.radius"
fill="none"
[attr.stroke]="color()"
[attr.stroke-width]="ring.strokeWidth"
[attr.opacity]="ring.opacity"
[style.animation-duration.s]="ring.duration"
[style.animation-delay.s]="ring.delay"
/>
}
</svg>
`,
styleUrl: './fl-frequency-rings.component.scss',
host: {
'class': 'fl-frequency-rings',
'[class.fl-frequency-rings--reduced-motion]': 'reducedMotion.reduced()',
},
})
export class FlFrequencyRingsComponent {
private reducedMotion = inject(ReducedMotionService);
private destroyRef = inject(DestroyRef);
// Inputs
readonly rings = input(5);
readonly color = input('#3b82f6');
readonly speed = input(1);
readonly baseRadius = input(20);
// Computed
readonly ringData = computed(() => {
const count = this.rings();
const base = this.baseRadius();
const spd = this.speed();
return Array.from({ length: count }, (_, i) => {
const radius = base + i * 15;
const opacity = 1 - (i / count) * 0.7;
const strokeWidth = 2 - (i / count) * 1;
const duration = (2 + i * 0.3) / spd;
const delay = -i * 0.2;
return { index: i, radius, opacity, strokeWidth, duration, delay };
});
});
}

View File

@@ -0,0 +1 @@
export * from './fl-frequency-rings.component';