🎯 Implementation Complete! This library has been extracted from the monorepo and is ready for Git submodule distribution. Features: - Standardized SCSS imports (no relative paths) - Optimized public-api.ts exports - Independent Angular library structure - Ready for consumer integration as submodule 🚀 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
99 lines
3.0 KiB
TypeScript
99 lines
3.0 KiB
TypeScript
import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
|
|
export type CardVariant = 'elevated' | 'filled' | 'outlined';
|
|
export type CardSize = 'sm' | 'md' | 'lg';
|
|
export type CardElevation = 'none' | 'sm' | 'md' | 'lg' | 'xl';
|
|
export type CardRadius = 'none' | 'sm' | 'md' | 'lg' | 'full';
|
|
export type GlassVariant = 'translucent' | 'light' | 'medium' | 'heavy' | 'frosted';
|
|
|
|
@Component({
|
|
selector: 'ui-card',
|
|
standalone: true,
|
|
imports: [CommonModule],
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
template: `
|
|
<div
|
|
[class]="cardClasses"
|
|
[style.backgroundImage]="backgroundImage"
|
|
[attr.tabindex]="clickable && !disabled ? '0' : null"
|
|
[attr.role]="clickable ? 'button' : null"
|
|
[attr.aria-disabled]="disabled"
|
|
(click)="handleClick($event)"
|
|
(keydown.enter)="handleClick($event)"
|
|
(keydown.space)="handleClick($event)"
|
|
>
|
|
@if (hasBackgroundLayer) {
|
|
<div class="card-background-layer">
|
|
<ng-content select="[slot=background]"></ng-content>
|
|
</div>
|
|
}
|
|
|
|
<div class="card-content-layer">
|
|
@if (hasHeader) {
|
|
<div class="card-header">
|
|
<ng-content select="[slot=header]"></ng-content>
|
|
</div>
|
|
}
|
|
|
|
<div class="card-body">
|
|
<ng-content></ng-content>
|
|
</div>
|
|
|
|
@if (hasFooter) {
|
|
<div class="card-footer">
|
|
<ng-content select="[slot=footer]"></ng-content>
|
|
</div>
|
|
}
|
|
</div>
|
|
|
|
@if (glass) {
|
|
<div class="card-glass-overlay"></div>
|
|
}
|
|
|
|
@if (clickable && !disabled) {
|
|
<div class="card-ripple-overlay"></div>
|
|
}
|
|
</div>
|
|
`,
|
|
styleUrl: './card.component.scss'
|
|
})
|
|
export class CardComponent {
|
|
@Input() variant: CardVariant = 'elevated';
|
|
@Input() size: CardSize = 'md';
|
|
@Input() elevation: CardElevation = 'sm';
|
|
@Input() radius: CardRadius = 'md';
|
|
@Input() disabled: boolean = false;
|
|
@Input() clickable: boolean = false;
|
|
@Input() glass: boolean = false;
|
|
@Input() glassVariant: GlassVariant = 'medium';
|
|
@Input() backgroundImage?: string;
|
|
@Input() hasBackgroundLayer: boolean = false;
|
|
@Input() hasHeader: boolean = false;
|
|
@Input() hasFooter: boolean = false;
|
|
@Input() class: string = '';
|
|
|
|
@Output() cardClick = new EventEmitter<Event>();
|
|
|
|
get cardClasses(): string {
|
|
return [
|
|
'ui-card',
|
|
`ui-card--${this.variant}`,
|
|
`ui-card--${this.size}`,
|
|
`ui-card--elevation-${this.elevation}`,
|
|
`ui-card--radius-${this.radius}`,
|
|
this.disabled ? 'ui-card--disabled' : '',
|
|
this.clickable ? 'ui-card--clickable' : '',
|
|
this.glass ? 'ui-card--glass' : '',
|
|
this.glass ? `ui-card--glass-${this.glassVariant}` : '',
|
|
this.hasBackgroundLayer ? 'ui-card--with-background' : '',
|
|
this.class
|
|
].filter(Boolean).join(' ');
|
|
}
|
|
|
|
handleClick(event: Event): void {
|
|
if (this.clickable && !this.disabled) {
|
|
this.cardClick.emit(event);
|
|
}
|
|
}
|
|
} |