const LUMA_MEDIA_VERSION = '0.1.0'; class LumaMediaCard extends HTMLElement { set hass(hass) { this._hass = hass; this._render(); } setConfig(config) { if (!config.entity) throw new Error('Entity is required'); this._config = { entity: config.entity, name: config.name || '', size: config.size || '1x2', accent_color: config.accent_color || '', icon: config.icon || '', tap_action: config.tap_action || { action: 'more-info' }, hold_action: config.hold_action || { action: 'more-info' }, ...config }; this._render(); } getCardSize() { return 4; } static getStubConfig() { return { entity: '', name: '', size: '1x2' }; } connectedCallback() { if (!this.shadowRoot) this.attachShadow({ mode: 'open' }); this._render(); } _getState() { return this._hass?.states?.[this._config?.entity]; } _isActive() { const s = this._getState(); return s && (s.state === 'playing' || s.state === 'paused'); } _getAccent() { if (this._config?.accent_color) return this._config.accent_color; const s = this._getState(); if (!s) return '#bbbbbb'; switch (s.state) { case 'playing': return '#9b7ddb'; case 'paused': return 'rgba(125,155,219,0.7)'; default: return 'rgba(187,187,187,0.5)'; } } _handleClick() { if (!this._hass || !this._config) return; const ev = new Event('hass-more-info', { composed: true }); ev.detail = { entityId: this._config.entity }; this.dispatchEvent(ev); } _render() { if (!this.shadowRoot || !this._config) return; const s = this._getState(); const isActive = this._isActive(); const accent = this._getAccent(); const icon = this._config.icon || 'mdi:music'; const title = s?.attributes?.media_title || this._config.name || s?.attributes?.friendly_name || ''; const artist = s?.attributes?.media_artist || ''; const volume = Math.round((s?.attributes?.volume_level || 0) * 100); const state = s?.state || 'off'; const statusLabel = { playing: 'Playing', paused: 'Paused', idle: 'Idle' }[state] || 'Off'; const volLabel = isActive ? `Vol ${volume}%` : 'Off'; this.shadowRoot.innerHTML = `
${title}
${artist ? `
${artist}
` : ''}
${statusLabel}
${volLabel}
`; this.shadowRoot.querySelector('.card').addEventListener('click', () => this._handleClick()); } } customElements.define('luma-media-card', LumaMediaCard); window.customCards = window.customCards || []; window.customCards.push({ type: 'luma-media-card', name: 'Luma Media', description: 'Luma-style media player card with album art placeholder.', preview: true }); console.info(`%c LUMA-MEDIA-CARD %c v${LUMA_MEDIA_VERSION} `, 'background:#9b7ddb;color:#111;font-weight:bold', 'background:#161a22;color:#9b7ddb');