190 lines
5.4 KiB
TypeScript
190 lines
5.4 KiB
TypeScript
import {
|
|
DeesElement,
|
|
customElement,
|
|
html,
|
|
css,
|
|
cssManager,
|
|
property,
|
|
type TemplateResult,
|
|
} from '@design.estate/dees-element';
|
|
|
|
declare global {
|
|
interface HTMLElementTagNameMap {
|
|
'sz-stat-card': SzStatCard;
|
|
}
|
|
}
|
|
|
|
@customElement('sz-stat-card')
|
|
export class SzStatCard extends DeesElement {
|
|
public static demo = () => html`
|
|
<style>
|
|
.demo-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 16px;
|
|
padding: 24px;
|
|
max-width: 800px;
|
|
}
|
|
</style>
|
|
<div class="demo-grid">
|
|
<sz-stat-card
|
|
label="Total Services"
|
|
value="7"
|
|
icon="server"
|
|
></sz-stat-card>
|
|
<sz-stat-card
|
|
label="Running"
|
|
value="7"
|
|
icon="check"
|
|
variant="success"
|
|
></sz-stat-card>
|
|
<sz-stat-card
|
|
label="Stopped"
|
|
value="0"
|
|
icon="stop"
|
|
></sz-stat-card>
|
|
<sz-stat-card
|
|
label="Docker"
|
|
value="Running"
|
|
icon="container"
|
|
variant="success"
|
|
valueBadge
|
|
></sz-stat-card>
|
|
</div>
|
|
`;
|
|
|
|
public static demoGroups = ['Dashboard'];
|
|
|
|
@property({ type: String })
|
|
public accessor label: string = '';
|
|
|
|
@property({ type: String })
|
|
public accessor value: string = '';
|
|
|
|
@property({ type: String })
|
|
public accessor icon: string = '';
|
|
|
|
@property({ type: String })
|
|
public accessor variant: 'default' | 'success' | 'warning' | 'error' = 'default';
|
|
|
|
@property({ type: Boolean })
|
|
public accessor valueBadge: boolean = false;
|
|
|
|
public static styles = [
|
|
cssManager.defaultStyles,
|
|
css`
|
|
:host {
|
|
display: block;
|
|
height: 100%;
|
|
}
|
|
|
|
.card {
|
|
background: ${cssManager.bdTheme('#ffffff', '#09090b')};
|
|
border: 1px solid ${cssManager.bdTheme('#e4e4e7', '#27272a')};
|
|
border-radius: 8px;
|
|
padding: 20px;
|
|
transition: all 200ms ease;
|
|
height: 100%;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.card:hover {
|
|
border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
|
|
box-shadow: 0 4px 12px ${cssManager.bdTheme('rgba(0,0,0,0.05)', 'rgba(0,0,0,0.2)')};
|
|
}
|
|
|
|
.header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.label {
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
}
|
|
|
|
.icon {
|
|
width: 20px;
|
|
height: 20px;
|
|
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
}
|
|
|
|
.value {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
color: ${cssManager.bdTheme('#18181b', '#fafafa')};
|
|
line-height: 1.2;
|
|
}
|
|
|
|
.value.success {
|
|
color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
|
|
}
|
|
|
|
.value.warning {
|
|
color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
|
|
}
|
|
|
|
.value.error {
|
|
color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
|
|
}
|
|
|
|
.badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
padding: 4px 12px;
|
|
border-radius: 9999px;
|
|
font-size: 14px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.badge.success {
|
|
background: ${cssManager.bdTheme('#dcfce7', 'rgba(34, 197, 94, 0.2)')};
|
|
color: ${cssManager.bdTheme('#16a34a', '#22c55e')};
|
|
}
|
|
|
|
.badge.warning {
|
|
background: ${cssManager.bdTheme('#fef9c3', 'rgba(250, 204, 21, 0.2)')};
|
|
color: ${cssManager.bdTheme('#ca8a04', '#facc15')};
|
|
}
|
|
|
|
.badge.error {
|
|
background: ${cssManager.bdTheme('#fee2e2', 'rgba(239, 68, 68, 0.2)')};
|
|
color: ${cssManager.bdTheme('#dc2626', '#ef4444')};
|
|
}
|
|
|
|
.badge.default {
|
|
background: ${cssManager.bdTheme('#f4f4f5', '#27272a')};
|
|
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
|
}
|
|
`,
|
|
];
|
|
|
|
public render(): TemplateResult {
|
|
const valueClass = this.valueBadge ? `badge ${this.variant}` : `value ${this.variant}`;
|
|
|
|
return html`
|
|
<div class="card">
|
|
<div class="header">
|
|
<span class="label">${this.label}</span>
|
|
${this.renderIcon()}
|
|
</div>
|
|
<div class="${valueClass}">${this.value}</div>
|
|
</div>
|
|
`;
|
|
}
|
|
|
|
private renderIcon(): TemplateResult {
|
|
const icons: Record<string, TemplateResult> = {
|
|
server: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><rect x="2" y="2" width="20" height="8" rx="2" ry="2"></rect><rect x="2" y="14" width="20" height="8" rx="2" ry="2"></rect><line x1="6" y1="6" x2="6.01" y2="6"></line><line x1="6" y1="18" x2="6.01" y2="18"></line></svg>`,
|
|
check: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"></polyline></svg>`,
|
|
stop: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"></circle><line x1="10" y1="15" x2="10" y2="9"></line><line x1="14" y1="15" x2="14" y2="9"></line></svg>`,
|
|
container: html`<svg class="icon" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path></svg>`,
|
|
};
|
|
|
|
return icons[this.icon] || html``;
|
|
}
|
|
}
|