import * as plugins from '../plugins.js'; import { DeesElement, property, html, customElement, type TemplateResult, css, cssManager, unsafeCSS, } from '@design.estate/dees-element'; import type { IStatusHistoryPoint } from '../interfaces/index.js'; import * as sharedStyles from '../styles/shared.styles.js'; import './internal/uplinternal-miniheading.js'; import { demoFunc } from './upl-statuspage-statusdetails.demo.js'; declare global { interface HTMLElementTagNameMap { 'upl-statuspage-statusdetails': UplStatuspageStatusdetails; } } @customElement('upl-statuspage-statusdetails') export class UplStatuspageStatusdetails extends DeesElement { public static demo = demoFunc; @property({ type: Array }) accessor historyData: IStatusHistoryPoint[] = []; @property({ type: Array }) accessor dataPoints: IStatusHistoryPoint[] = []; @property({ type: String }) accessor serviceId: string = ''; @property({ type: String }) accessor serviceName: string = 'Service'; @property({ type: Boolean }) accessor loading: boolean = false; @property({ type: Number }) accessor hoursToShow: number = 48; constructor() { super(); } public static styles = [ plugins.domtools.elementBasic.staticStyles, sharedStyles.commonStyles, css` :host { position: relative; display: block; background: transparent; font-family: ${unsafeCSS(sharedStyles.fonts.base)}; color: ${sharedStyles.colors.text.primary}; } .container { max-width: 1200px; margin: 0 auto; padding: 0 ${unsafeCSS(sharedStyles.spacing.lg)} ${unsafeCSS(sharedStyles.spacing.lg)} ${unsafeCSS(sharedStyles.spacing.lg)}; } .graph-wrapper { display: flex; flex-direction: column; gap: 4px; } .graph-container { position: relative; animation: fadeIn 0.3s ${unsafeCSS(sharedStyles.easings.default)}; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } .mainbox { background: transparent; border: none; border-radius: 0; padding: 0; } .mainbox .barContainer { position: relative; display: flex; gap: 2px; padding: ${unsafeCSS(sharedStyles.spacing.sm)}; background: ${cssManager.bdTheme('#fafafa', '#0a0a0a')}; border: 1px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')}; border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)}; overflow: hidden; height: 40px; } .mainbox .barContainer .bar { flex: 1; height: 100%; cursor: pointer; transition: all ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)}; position: relative; border-radius: 3px; animation: barGrow 0.4s ${unsafeCSS(sharedStyles.easings.default)} both; animation-delay: calc(var(--bar-index, 0) * 8ms); transform-origin: bottom; } @keyframes barGrow { from { transform: scaleY(0); opacity: 0; } to { transform: scaleY(1); opacity: 1; } } .mainbox .barContainer .bar:hover { transform: scaleY(1.15); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15); z-index: 1; } .mainbox .barContainer .bar.operational { background: ${cssManager.bdTheme('#22c55e', '#22c55e')}; } .mainbox .barContainer .bar.degraded { background: ${cssManager.bdTheme('#fbbf24', '#fbbf24')}; } .mainbox .barContainer .bar.partial_outage { background: ${cssManager.bdTheme('#f87171', '#f87171')}; } .mainbox .barContainer .bar.major_outage { background: ${cssManager.bdTheme('#ef4444', '#ef4444')}; } .mainbox .barContainer .bar.maintenance { background: ${cssManager.bdTheme('#60a5fa', '#60a5fa')}; } .mainbox .barContainer .bar.no-data { background: ${cssManager.bdTheme('#e5e7eb', '#27272a')}; opacity: 0.6; } .time-labels { display: flex; justify-content: space-between; padding: 0; margin-top: ${unsafeCSS(sharedStyles.spacing.xs)}; font-size: 10px; color: ${cssManager.bdTheme('#9ca3af', '#71717a')}; font-family: ${unsafeCSS(sharedStyles.fonts.base)}; opacity: 0.8; } .tooltip { position: absolute; background: ${cssManager.bdTheme('#0a0a0a', '#fafafa')}; color: ${cssManager.bdTheme('#fafafa', '#0a0a0a')}; padding: 8px 12px; border-radius: ${unsafeCSS(sharedStyles.borderRadius.base)}; font-size: 11px; pointer-events: none; opacity: 0; transition: opacity ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)}, transform ${unsafeCSS(sharedStyles.durations.fast)} ${unsafeCSS(sharedStyles.easings.default)}; z-index: 50; white-space: nowrap; box-shadow: ${unsafeCSS(sharedStyles.shadows.lg)}; line-height: 1.5; transform: translateY(4px); } .tooltip.visible { opacity: 1; transform: translateY(0); } .tooltip-time { font-weight: 600; display: block; margin-bottom: 2px; } .tooltip-stat { font-size: 10px; opacity: 0.9; } .loading-skeleton { display: flex; gap: 1px; height: 24px; } .loading-skeleton .skeleton-bar { flex: 1; height: 100%; background: ${cssManager.bdTheme('#f3f4f6', '#27272a')}; animation: pulse 2s infinite; } @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } @keyframes loading { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } @media (max-width: 640px) { .container { padding: 0 ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.md)} ${unsafeCSS(sharedStyles.spacing.md)}; } .graph-container { padding: ${unsafeCSS(sharedStyles.spacing.sm)}; } .mainbox .barContainer { height: 32px; padding: ${unsafeCSS(sharedStyles.spacing.xs)}; } .time-labels { font-size: 9px; } .stats-row { font-size: 11px; flex-direction: column; gap: ${unsafeCSS(sharedStyles.spacing.sm)}; align-items: flex-start; } } `, ]; public render(): TemplateResult { return html`