Last active
September 3, 2024 15:14
-
-
Save grischard/ce5b9707652b67e81bc6957911f2324a to your computer and use it in GitHub Desktop.
Swatch beats Home Assistant
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class SwatchBeatBase extends HTMLElement { | |
connectedCallback() { | |
this.interval = setInterval(() => this.updateBeats(), 86); | |
} | |
disconnectedCallback() { | |
clearInterval(this.interval); | |
} | |
updateBeats() { | |
const now = new Date(); | |
const beats = ( | |
(((now.getUTCHours() * 3600 + | |
now.getUTCMinutes() * 60 + | |
now.getUTCSeconds()) * | |
1000 + | |
now.getUTCMilliseconds() + | |
3600000) % | |
86400000) / | |
86400 | |
).toFixed(3); | |
this.render(beats); | |
} | |
render(beats) { | |
throw new Error('Method "render(beats)" must be implemented'); | |
} | |
} | |
class SwatchBeatCard extends SwatchBeatBase { | |
set hass(hass) { | |
if (!this.content) { | |
const card = document.createElement("hui-badge"); | |
card.header = "Swatch Internet Beats"; | |
this.content = document.createElement("div"); | |
this.content.id = "swatch-beat"; | |
this.content.className = "card-content"; | |
card.appendChild(this.content); | |
this.appendChild(card); | |
} | |
this.updateBeats(); | |
} | |
render(beats) { | |
this.content.innerHTML = `@${beats}`; | |
} | |
setConfig(config) { | |
this.config = config; | |
} | |
getCardSize() { | |
return 1; | |
} | |
} | |
class SwatchBeatBadge extends SwatchBeatBase { | |
setConfig() {} | |
set hass(hass) { | |
this._hass = hass; | |
if (!this.shadowRoot) { | |
this.attachShadow({mode: "open" }); | |
this.shadowRoot.innerHTML = ` | |
<style> | |
:host { | |
--badge-color: var(--state-inactive-color); | |
-webkit-tap-highlight-color: transparent; | |
} | |
.badge.error { | |
--badge-color: var(--red-color); | |
} | |
.badge { | |
position: relative; | |
--ha-ripple-color: var(--badge-color); | |
--ha-ripple-hover-opacity: 0.04; | |
--ha-ripple-pressed-opacity: 0.12; | |
transition: | |
box-shadow 180ms ease-in-out, | |
border-color 180ms ease-in-out; | |
display: flex; | |
flex-direction: row; | |
align-items: center; | |
justify-content: center; | |
gap: 8px; | |
height: var(--ha-badge-size, 36px); | |
min-width: var(--ha-badge-size, 36px); | |
padding: 0px 8px; | |
box-sizing: border-box; | |
width: auto; | |
border-radius: var( | |
--ha-badge-border-radius, | |
calc(var(--ha-badge-size, 36px) / 2) | |
); | |
background: var( | |
--ha-card-background, | |
var(--card-background-color, white) | |
); | |
-webkit-backdrop-filter: var(--ha-card-backdrop-filter, none); | |
backdrop-filter: var(--ha-card-backdrop-filter, none); | |
border-width: var(--ha-card-border-width, 1px); | |
box-shadow: var(--ha-card-box-shadow, none); | |
border-style: solid; | |
border-color: var( | |
--ha-card-border-color, | |
var(--divider-color, #e0e0e0) | |
); | |
--mdc-icon-size: 18px; | |
text-align: center; | |
font-family: Roboto; | |
} | |
.badge:focus-visible { | |
--shadow-default: var(--ha-card-box-shadow, 0 0 0 0 transparent); | |
--shadow-focus: 0 0 0 1px var(--badge-color); | |
border-color: var(--badge-color); | |
box-shadow: var(--shadow-default), var(--shadow-focus); | |
} | |
button, | |
[role="button"] { | |
cursor: pointer; | |
} | |
button:focus, | |
[role="button"]:focus { | |
outline: none; | |
} | |
.badge.active { | |
--badge-color: var(--primary-color); | |
} | |
.info { | |
display: flex; | |
flex-direction: column; | |
align-items: flex-start; | |
padding-right: 4px; | |
padding-inline-end: 4px; | |
padding-inline-start: initial; | |
} | |
.label { | |
font-size: 10px; | |
font-style: normal; | |
font-weight: 500; | |
line-height: 10px; | |
letter-spacing: 0.1px; | |
color: var(--secondary-text-color); | |
} | |
.content { | |
font-size: 12px; | |
font-style: normal; | |
font-weight: 500; | |
line-height: 16px; | |
letter-spacing: 0.1px; | |
color: var(--primary-text-color); | |
} | |
ha-icon, | |
ha-state-icon, | |
ha-svg-icon { | |
color: var(--badge-color); | |
line-height: 0; | |
} | |
img { | |
width: 30px; | |
height: 30px; | |
border-radius: 50%; | |
object-fit: cover; | |
overflow: hidden; | |
} | |
.badge.no-info { | |
padding: 0; | |
} | |
.badge:not(.no-icon):not(.no-info) img { | |
margin-left: -6px; | |
margin-inline-start: -6px; | |
margin-inline-end: initial; | |
} | |
.badge.no-icon .info { | |
padding-right: 4px; | |
padding-left: 4px; | |
padding-inline-end: 4px; | |
padding-inline-start: 4px; | |
} | |
.content { | |
display: flex; | |
flex-direction: column; | |
align-items: flex-start; | |
padding-right: 4px; | |
padding-inline-end: 4px; | |
padding-inline-start: initial; | |
} | |
.name { | |
font-size: 10px; | |
font-style: normal; | |
font-weight: 500; | |
line-height: 10px; | |
letter-spacing: 0.1px; | |
color: var(--secondary-text-color); | |
} | |
</style> | |
<div style="" class="badge active complete " role="button" tabindex="0"> | |
<ha-ripple aria-hidden="true"></ha-ripple> | |
<ha-icon icon="mdi:at"></ha-icon> | |
<span class="content"> | |
<span class="name">Beats</span> | |
<span class="state"> | |
<state-display></state-display> | |
</span> | |
</span> | |
</div> | |
`; | |
this.beatsDisplay = this.shadowRoot.querySelector('state-display'); | |
// this.beatsDisplay = document.createElement("div"); | |
// this.shadowRoot.appendChild(this.beatsDisplay); | |
// this.content.setAttribute("style", ""); | |
// this.content.className = "badge active standard"; | |
// this.content.setAttribute("role", "button"); | |
// this.content.setAttribute("tabindex", "0"); | |
// // Ripple effect? | |
// const ripple = document.createElement("ha-ripple"); | |
// ripple.setAttribute("aria-hidden", "true"); | |
// const surface = document.createElement("div"); | |
// surface.className = "surface"; | |
// ripple.appendChild(surface); | |
// this.content.appendChild(ripple); | |
// // State icon | |
// const stateIcon = document.createElement("ha-state-icon"); | |
// const haIcon = document.createElement("ha-icon"); | |
// haIcon.setAttribute("icon", "mdi:at"); // Using mdi:at icon | |
// stateIcon.appendChild(haIcon); | |
// this.content.appendChild(stateIcon); | |
// // Content | |
// const contentSpan = document.createElement("span"); | |
// contentSpan.className = "content"; | |
// // Name | |
// const nameSpan = document.createElement("span"); | |
// nameSpan.className = "name"; | |
// nameSpan.textContent = "beat"; // Set the name of your badge | |
// contentSpan.appendChild(nameSpan); | |
// // State | |
// const stateSpan = document.createElement("span"); | |
// stateSpan.className = "state"; | |
// this.beatsDisplay = document.createElement("state-display"); | |
// stateSpan.appendChild(this.beatsDisplay); | |
// contentSpan.appendChild(stateSpan); | |
// this.content.appendChild(contentSpan); | |
// this.appendChild(this.content); | |
} | |
this.updateBeats(); | |
} | |
render(beats) { | |
if (this.beatsDisplay) { | |
this.beatsDisplay.textContent = `${beats}`; | |
} | |
} | |
setConfig(config) { | |
this.config = config; | |
} | |
} | |
customElements.define("swatch-beat-badge", SwatchBeatBadge); | |
customElements.define("swatch-beat-card", SwatchBeatCard); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment