173 lines
5.1 KiB
TypeScript
173 lines
5.1 KiB
TypeScript
const TIMEOUT_ERROR = "SELECTTREE-TIMEOUT";
|
|
|
|
export async function await_element(el, hard = false) {
|
|
if (el.localName?.includes("-"))
|
|
await customElements.whenDefined(el.localName);
|
|
if (el.updateComplete) await el.updateComplete;
|
|
if (hard) {
|
|
if (el.pageRendered) await el.pageRendered;
|
|
if (el._panelState) {
|
|
let rounds = 0;
|
|
while (el._panelState !== "loaded" && rounds++ < 5)
|
|
await new Promise((r) => setTimeout(r, 100));
|
|
}
|
|
}
|
|
}
|
|
|
|
async function _selectTree(root, path, all = false) {
|
|
let el = [root];
|
|
if (typeof path === "string") {
|
|
path = path.split(/(\$| )/);
|
|
}
|
|
while (path[path.length - 1] === "") path.pop();
|
|
for (const [i, p] of path.entries()) {
|
|
const e = el[0];
|
|
if (!e) return null;
|
|
|
|
if (!p.trim().length) continue;
|
|
|
|
await_element(e);
|
|
el = p === "$" ? [e.shadowRoot] : e.querySelectorAll(p);
|
|
}
|
|
return all ? el : el[0];
|
|
}
|
|
|
|
export async function selectTree(root, path, all = false, timeout = 10000) {
|
|
return Promise.race([
|
|
_selectTree(root, path, all),
|
|
new Promise((_, reject) =>
|
|
setTimeout(() => reject(new Error(TIMEOUT_ERROR)), timeout)
|
|
),
|
|
]).catch((err) => {
|
|
if (!err.message || err.message !== TIMEOUT_ERROR) throw err;
|
|
return null;
|
|
});
|
|
}
|
|
|
|
export async function hass_base_el() {
|
|
await Promise.race([
|
|
customElements.whenDefined("home-assistant"),
|
|
customElements.whenDefined("hc-main"),
|
|
]);
|
|
|
|
const element = customElements.get("home-assistant")
|
|
? "home-assistant"
|
|
: "hc-main";
|
|
|
|
while (!document.querySelector(element))
|
|
await new Promise((r) => window.setTimeout(r, 100));
|
|
return document.querySelector(element);
|
|
}
|
|
|
|
export async function hass() {
|
|
const base: any = await hass_base_el();
|
|
while (!base.hass) await new Promise((r) => window.setTimeout(r, 100));
|
|
return base.hass;
|
|
}
|
|
|
|
export async function provideHass(el) {
|
|
const base: any = await hass_base_el();
|
|
base.provideHass(el);
|
|
}
|
|
|
|
export const loadLoadCardHelpers = async () => {
|
|
if (window.loadCardHelpers !== undefined) return;
|
|
|
|
await customElements.whenDefined("partial-panel-resolver");
|
|
const ppResolver = document.createElement("partial-panel-resolver");
|
|
const routes = (ppResolver as any).getRoutes([
|
|
{
|
|
component_name: "lovelace",
|
|
url_path: "a",
|
|
},
|
|
]);
|
|
await routes?.routes?.a?.load?.();
|
|
};
|
|
|
|
export const loadHaForm = async () => {
|
|
if (customElements.get("ha-form")) return;
|
|
await loadLoadCardHelpers();
|
|
const helpers = await window.loadCardHelpers();
|
|
if (!helpers) return;
|
|
const card = await helpers.createCardElement({ type: "button" });
|
|
if (!card) return;
|
|
await card.constructor.getConfigElement();
|
|
};
|
|
|
|
// Loads in ha-config-dashboard which is used to copy styling
|
|
// Also provides ha-settings-row
|
|
export const loadConfigDashboard = async () => {
|
|
await customElements.whenDefined("partial-panel-resolver");
|
|
const ppResolver = document.createElement("partial-panel-resolver");
|
|
const routes = (ppResolver as any).getRoutes([
|
|
{
|
|
component_name: "config",
|
|
url_path: "a",
|
|
},
|
|
]);
|
|
await routes?.routes?.a?.load?.();
|
|
await customElements.whenDefined("ha-panel-config");
|
|
const configRouter: any = document.createElement("ha-panel-config");
|
|
await configRouter?.routerOptions?.routes?.dashboard?.load?.(); // Load ha-config-dashboard
|
|
await configRouter?.routerOptions?.routes?.cloud?.load?.(); // Load ha-settings-row
|
|
await configRouter?.routerOptions?.routes?.entities?.load?.(); // Load ha-data-table
|
|
await customElements.whenDefined("ha-config-dashboard");
|
|
};
|
|
|
|
export const loadDeveloperToolsTemplate = async () => {
|
|
await customElements.whenDefined("partial-panel-resolver");
|
|
await customElements.whenDefined("partial-panel-resolver");
|
|
const ppResolver = document.createElement("partial-panel-resolver");
|
|
const routes = (ppResolver as any).getRoutes([
|
|
{
|
|
component_name: "developer-tools",
|
|
url_path: "a",
|
|
},
|
|
]);
|
|
await routes?.routes?.a?.load?.();
|
|
const dtRouter: any = document.createElement("developer-tools-router");
|
|
await dtRouter?.routerOptions?.routes?.template?.load?.();
|
|
await customElements.whenDefined("developer-tools-template");
|
|
};
|
|
|
|
export function throttle(timeout) {
|
|
return function (target, propertyKey, descriptor) {
|
|
const fn = descriptor.value;
|
|
let cooldown = undefined;
|
|
descriptor.value = function (...rest) {
|
|
if (cooldown) return;
|
|
cooldown = setTimeout(() => (cooldown = undefined), timeout);
|
|
return fn.bind(this)(...rest);
|
|
};
|
|
};
|
|
}
|
|
|
|
export function runOnce(restart = false) {
|
|
return function (target, propertyKey, descriptor) {
|
|
const fn = descriptor.value;
|
|
let running = undefined;
|
|
const newfn = function (...rest) {
|
|
if (restart && running === false) running = true;
|
|
if (running !== undefined) return;
|
|
running = false;
|
|
|
|
const retval = fn.bind(this)(...rest);
|
|
if (running) {
|
|
running = undefined;
|
|
return newfn.bind(this)(...rest);
|
|
} else {
|
|
running = undefined;
|
|
return retval;
|
|
}
|
|
};
|
|
descriptor.value = newfn;
|
|
};
|
|
}
|
|
|
|
export async function waitRepeat(fn, times, delay) {
|
|
while (times--) {
|
|
fn();
|
|
await new Promise((r) => setTimeout(r, delay));
|
|
}
|
|
}
|