Files
catalog/ts_web/elements/sg-stat-card.ts

97 lines
2.4 KiB
TypeScript

import {
DeesElement,
customElement,
html,
property,
css,
cssManager,
type TemplateResult,
} from '@design.estate/dees-element';
import type { ISgStat } from '../interfaces.js';
declare global {
interface HTMLElementTagNameMap {
'sg-stat-card': SgStatCard;
}
}
@customElement('sg-stat-card')
export class SgStatCard extends DeesElement {
public static demo = () => html`<sg-stat-card
.title=${'Total Packages'}
.value=${1234}
.icon=${'lucide:package'}
.trend=${'up'}
.trendValue=${'+12%'}
></sg-stat-card>`;
public static demoGroups = ['Dashboard'];
@property({ type: String })
accessor title: string = '';
@property({ type: Number })
accessor value: string | number = 0;
@property({ type: String })
accessor icon: string = '';
@property({ type: String })
accessor trend: 'up' | 'down' | 'neutral' = 'neutral';
@property({ type: String })
accessor trendValue: string = '';
public static styles = [
cssManager.defaultStyles,
css`
:host {
display: block;
}
.card {
background: ${cssManager.bdTheme('#fff', '#1a1a1a')};
border: 1px solid ${cssManager.bdTheme('#e5e5e5', '#333')};
padding: 20px;
display: flex;
flex-direction: column;
gap: 8px;
}
.card-title {
font-size: 13px;
color: ${cssManager.bdTheme('#666', '#999')};
text-transform: uppercase;
letter-spacing: 0.05em;
}
.card-value {
font-size: 32px;
font-weight: 700;
color: ${cssManager.bdTheme('#111', '#fff')};
font-family: 'JetBrains Mono', monospace;
}
.card-trend {
font-size: 13px;
display: flex;
align-items: center;
gap: 4px;
}
.card-trend.up { color: #22c55e; }
.card-trend.down { color: #ef4444; }
.card-trend.neutral { color: ${cssManager.bdTheme('#999', '#666')}; }
`,
];
public render(): TemplateResult {
return html`
<div class="card">
<div class="card-title">${this.title}</div>
<div class="card-value">${this.value}</div>
${this.trendValue ? html`
<div class="card-trend ${this.trend}">
${this.trend === 'up' ? '\u2191' : this.trend === 'down' ? '\u2193' : '\u2022'}
${this.trendValue}
</div>
` : ''}
</div>
`;
}
}