Skip to content

Instantly share code, notes, and snippets.

@iantrich
Created February 5, 2020 20:18
Show Gist options
  • Save iantrich/51e7714172bde0992c3f0e7c8fcbfbb1 to your computer and use it in GitHub Desktop.
Save iantrich/51e7714172bde0992c3f0e7c8fcbfbb1 to your computer and use it in GitHub Desktop.
const LitElement = Object.getPrototypeOf(
customElements.get("ha-panel-lovelace")
);
const html = LitElement.prototype.html;
const CUSTOM_TYPE_PREFIX = "custom:";
function addScript(url) {
const script = document.createElement("script");
script.src = url;
document.head.appendChild(script);
}
class MuuriGrid extends LitElement {
static get properties() {
return {
_config: {},
_cards: {},
_hass: {}
};
}
constructor() {
super();
addScript(
"https://unpkg.com/[email protected]/web-animations.min.js"
);
addScript("https://unpkg.com/[email protected]/hammer.min.js");
addScript("/local/muuri.min.js");
}
setConfig(config) {
if (!config || !config.cards || !Array.isArray(config.cards)) {
throw new Error("Card config incorrect");
}
this._config = config;
this._parameters = this._config.parameters || {};
this._cards = this._config.cards.map(card => {
const element = this._createCardElement(card);
return element;
});
}
set hass(hass) {
this._hass = hass;
if (!this._cards) {
return;
}
for (const element of this._cards) {
element.childNodes[0].hass = this._hass;
}
}
render() {
if (!this._config || !this._hass) {
return html``;
}
return html`
<style>
#grid {
position: relative;
}
.item {
display: block;
position: absolute;
width: calc(33% - 4px);
margin: 4px;
z-index: 1;
background: #000;
color: #fff;
box-sizing: border-box;
}
.item.large {
width: calc(66% - 4px);
}
.item.medium {
width: calc(33% - 4px);
}
.item.small {
width: calc(16.5% - 4px);
}
.item.muuri-item-dragging {
z-index: 3;
}
.item.muuri-item-releasing {
z-index: 2;
}
.item.muuri-item-hidden {
z-index: 0;
}
</style>
<div id="grid">
${this._cards}
</div>
`;
}
async updated(changedProperties) {
super.updated(changedProperties);
if (this._config && this._hass && this.isConnected && !this._loaded) {
await this.updateComplete;
//this._initialLoad();
}
}
_initialLoad() {
this._loaded = true;
const options = {
layout: {
fillGaps: true,
horizontal: false,
alignRight: false,
alignBottom: false,
rounding: false
},
dragEnabled: true
};
this.grid = new Muuri(this.shadowRoot.querySelector("#grid"), options);
}
_createCardElement(cardConfig) {
let element;
let errorConfig;
if (cardConfig.type.startsWith(CUSTOM_TYPE_PREFIX)) {
const tag = cardConfig.type.substr(CUSTOM_TYPE_PREFIX.length);
if (customElements.get(tag)) {
element = document.createElement(`${tag}`);
} else {
errorConfig = {
type: "error",
error: `Custom element doesn't exist: ${tag}.`,
cardConfig
};
element = document.createElement("hui-error-card");
element.style.display = "None";
const timer = window.setTimeout(() => {
element.style.display = "";
}, 5000);
customElements.whenDefined(tag).then(() => {
clearTimeout(timer);
//HA >= 0.86
fireEvent(element, "ll-rebuild");
//HA < 0.86
fireEvent(element, "rebuild-view");
});
}
} else {
element = document.createElement(`hui-${cardConfig.type}-card`);
}
if (errorConfig) {
element.setConfig(errorConfig);
} else {
element.setConfig(cardConfig);
}
if (this._hass) {
element.hass = this._hass;
}
element.addEventListener(
"ll-rebuild",
ev => {
ev.stopPropagation();
this._rebuildCard(element, cardConfig);
},
{
once: true
}
);
const container = document.createElement("div");
container.classList.add("item");
container.classList.add(cardConfig.size);
container.appendChild(element);
return container;
}
}
customElements.define("muuri-grid", MuuriGrid);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment