Files
ui-essentials/src/lib/components/data-display/card/card.component.ts
Jules 0a0cade343 Initial commit - Angular library: ui-essentials
🎯 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>
2025-09-11 21:12:46 +10:00

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);
}
}
}