diff --git a/updateCustomFiles.ps1 b/updateCustomFiles.ps1 new file mode 100644 index 00000000..5a853ee9 --- /dev/null +++ b/updateCustomFiles.ps1 @@ -0,0 +1,7 @@ +Invoke-WebRequest https://raw.githubusercontent.com/thomasloven/lovelace-fold-entity-row/master/fold-entity-row.js -OutFile .\www\fold-entity-row.js +Invoke-WebRequest https://raw.githubusercontent.com/thomasloven/lovelace-card-tools/master/card-tools.js -OutFile .\www\card-tools.js +Invoke-WebRequest https://raw.githubusercontent.com/thomasloven/lovelace-slider-entity-row/master/slider-entity-row.js -OutFile .\www\slider-entity-row.js +Invoke-WebRequest https://raw.githubusercontent.com/thomasloven/lovelace-state-switch/master/state-switch.js -OutFile .\www\state-switch.js +Invoke-WebRequest https://raw.githubusercontent.com/thomasloven/lovelace-auto-entities/master/auto-entities.js -OutFile .\www\auto-entities.js +Invoke-WebRequest https://raw.githubusercontent.com/ciotlosm/custom-lovelace/master/plan-coordinates/plan-coordinates.js -OutFile .\www\custom-lovelace\plan-coordinates\plan-coordinates.js +Invoke-WebRequest https://raw.githubusercontent.com/custom-cards/config-template-card/master/dist/config-template-card.js -OutFile .\www\config-template-card.js \ No newline at end of file diff --git a/www/auto-entities.js b/www/auto-entities.js index 1b55821d..179c9a60 100644 --- a/www/auto-entities.js +++ b/www/auto-entities.js @@ -1,225 +1,225 @@ customElements.whenDefined('card-tools').then(() => { - class AutoEntities extends cardTools.LitElement { - - setConfig(config) { - if(!config || !config.card) - throw new Error("Invalid configuration"); - - this._config = config; - this.data = {}; - - this.entities = this.get_entities() || []; - this.card = cardTools.createCard(Object.assign({entities: this.entities}, config.card)); - } - - - match(pattern, str){ - if (typeof(str) === "string" && typeof(pattern) === "string") { - if((pattern.startsWith('/') && pattern.endsWith('/')) || pattern.indexOf('*') !== -1) { - if(pattern[0] !== '/') { - pattern = pattern.replace(/\./g, '\.'); - pattern = pattern.replace(/\*/g, '.*'); - pattern = `/^${pattern}$/`; - } - var regex = new RegExp(pattern.substr(1).slice(0,-1)); - return regex.test(str); - } +class AutoEntities extends cardTools.LitElement { + + setConfig(config) { + if(!config || !config.card) + throw new Error("Invalid configuration"); + + this._config = config; + this.data = {}; + + this.entities = this.get_entities() || []; + this.card = cardTools.createCard(Object.assign({entities: this.entities}, config.card)); + } + + + match(pattern, str){ + if (typeof(str) === "string" && typeof(pattern) === "string") { + if((pattern.startsWith('/') && pattern.endsWith('/')) || pattern.indexOf('*') !== -1) { + if(pattern[0] !== '/') { + pattern = pattern.replace(/\./g, '\.'); + pattern = pattern.replace(/\*/g, '.*'); + pattern = `/^${pattern}$/`; } - if(typeof(pattern) === "string") { - if(pattern.indexOf(":") !== -1 && typeof(str) === "object") { - while(pattern.indexOf(":") !== -1) - { - str = str[pattern.split(":")[0]]; - pattern = pattern.substr(pattern.indexOf(":")+1, pattern.length); - } - } - if(pattern.startsWith("<=")) return parseFloat(str) <= parseFloat(pattern.substr(2)); - if(pattern.startsWith(">=")) return parseFloat(str) >= parseFloat(pattern.substr(2)); - if(pattern.startsWith("<")) return parseFloat(str) < parseFloat(pattern.substr(1)); - if(pattern.startsWith(">")) return parseFloat(str) > parseFloat(pattern.substr(1)); - if(pattern.startsWith("!")) return parseFloat(str) != parseFloat(pattern.substr(1)); - if(pattern.startsWith("=")) return parseFloat(str) == parseFloat(pattern.substr(1)); + var regex = new RegExp(pattern.substr(1).slice(0,-1)); + return regex.test(str); + } + } + if(typeof(pattern) === "string") { + if(pattern.indexOf(":") !== -1 && typeof(str) === "object") { + while(pattern.indexOf(":") !== -1) + { + str = str[pattern.split(":")[0]]; + pattern = pattern.substr(pattern.indexOf(":")+1, pattern.length); } - return str === pattern; } - - match_filter(hass, entities, filter) { - let retval = []; - let count = -1; - entities.forEach((i) => { - count++; - if(!hass.states) return; - const e = (typeof(i) === "string")?hass.states[i]:hass.states[i.entity]; - if(!e) return; - - let unmatched = false; - Object.keys(filter).forEach((filterKey) => { - const key = filterKey.split(" ")[0]; - const value = filter[filterKey]; - switch(key) { - case "options": - break; - case "domain": - if(!this.match(value, e.entity_id.split('.')[0])) - unmatched = true; - break; - case "state": - if(!this.match(value, e.state)) - unmatched = true; - break; - case "entity_id": - if(!this.match(value, e.entity_id)) - unmatched = true; - break; - case "name": - if(!e.attributes.friendly_name - || !this.match(value, e.attributes.friendly_name) - ) - unmatched = true; - break; - case "area": - let found = false; - this.data.areas.forEach((a) => { + if(pattern.startsWith("<=")) return parseFloat(str) <= parseFloat(pattern.substr(2)); + if(pattern.startsWith(">=")) return parseFloat(str) >= parseFloat(pattern.substr(2)); + if(pattern.startsWith("<")) return parseFloat(str) < parseFloat(pattern.substr(1)); + if(pattern.startsWith(">")) return parseFloat(str) > parseFloat(pattern.substr(1)); + if(pattern.startsWith("!")) return parseFloat(str) != parseFloat(pattern.substr(1)); + if(pattern.startsWith("=")) return parseFloat(str) == parseFloat(pattern.substr(1)); + } + return str === pattern; + } + + match_filter(hass, entities, filter) { + let retval = []; + let count = -1; + entities.forEach((i) => { + count++; + if(!hass.states) return; + const e = (typeof(i) === "string")?hass.states[i]:hass.states[i.entity]; + if(!e) return; + + let unmatched = false; + Object.keys(filter).forEach((filterKey) => { + const key = filterKey.split(" ")[0]; + const value = filter[filterKey]; + switch(key) { + case "options": + break; + case "domain": + if(!this.match(value, e.entity_id.split('.')[0])) + unmatched = true; + break; + case "state": + if(!this.match(value, e.state)) + unmatched = true; + break; + case "entity_id": + if(!this.match(value, e.entity_id)) + unmatched = true; + break; + case "name": + if(!e.attributes.friendly_name + || !this.match(value, e.attributes.friendly_name) + ) + unmatched = true; + break; + case "area": + let found = false; + this.data.areas.forEach((a) => { + if(found) return; + if(this.match(value, a.name)) { + this.data.devices.forEach((d) => { if(found) return; - if(this.match(value, a.name)) { - this.data.devices.forEach((d) => { + if(d.area_id && d.area_id === a.area_id) { + this.data.entities.forEach((en) => { if(found) return; - if(d.area_id && d.area_id === a.area_id) { - this.data.entities.forEach((en) => { - if(found) return; - if(en.device_id === d.id && en.entity_id === e.entity_id) { - found = true; - } - }); + if(en.device_id === d.id && en.entity_id === e.entity_id) { + found = true; } }); } }); - if(!found) unmatched = true; - break; - case "group": - if(!value.startsWith("group.") - || !hass.states[value] - || !hass.states[value].attributes.entity_id - || !hass.states[value].attributes.entity_id.includes(e.entity_id) - ) - unmatched = true; - break; - case "attributes": - Object.keys(value).forEach((entityKey) => { - const k = entityKey.split(" ")[0]; - const v = value[entityKey]; - if(!e.attributes[k] - || !this.match(v, e.attributes[k]) - ) - unmatched = true; - }); - break; - default: - unmatched = true; - } - }); - if(!unmatched) retval.push(count); - }); - return retval; - } - - get_entities() - { - let entities = []; - if(this._config.entities) - this._config.entities.forEach((e) => entities.push(e)); - - if(this._hass && this._config.filter) { - - if(this._config.filter.include){ - this._config.filter.include.forEach((f) => { - const add = this.match_filter(this._hass, Object.keys(this._hass.states), f); - let toAdd = []; - add.forEach((i) => { - toAdd.push(Object.assign({entity: Object.keys(this._hass.states)[i]}, f.options)); - }); - toAdd.sort((a,b) => { - if (a.entity < b.entity) return -1; - if (a.entity > b.entity) return 1; - return 0; - }); - toAdd.forEach((i) => entities.push(i)); - }); - } - - if(this._config.filter.exclude) { - this._config.filter.exclude.forEach((f) => { - const remove = this.match_filter(this._hass, entities, f); - for(var i = remove.length-1; i >= 0; i--) - { - entities.splice(remove[i],1); } }); - } - } - return entities; - } - - createRenderRoot() { - return this; - } - render() { - if(this.entities.length === 0 && this._config.show_empty === false) - return cardTools.LitHtml``; - return cardTools.LitHtml` -
${this.card}
- `; - } - - async get_data(hass) { - try { - this.data.areas = await hass.callWS({type: "config/area_registry/list"}); - this.data.devices = await hass.callWS({type: "config/device_registry/list"}); - this.data.entities = await hass.callWS({type: "config/entity_registry/list"}); - } catch (err) { - } - } - - _compare_arrays(a,b) { - if(a === b) return true; - if(a == null || b == null) return false; - if(a.length != b.length) return false; - for(var i = 0; i < a.length; i++) { - if(a[i] !== b[i]) { - return false; - } + if(!found) unmatched = true; + break; + case "group": + if(!value.startsWith("group.") + || !hass.states[value] + || !hass.states[value].attributes.entity_id + || !hass.states[value].attributes.entity_id.includes(e.entity_id) + ) + unmatched = true; + break; + case "attributes": + Object.keys(value).forEach((entityKey) => { + const k = entityKey.split(" ")[0]; + const v = value[entityKey]; + if(!e.attributes[k] + || !this.match(v, e.attributes[k]) + ) + unmatched = true; + }); + break; + default: + unmatched = true; } - return true; + }); + if(!unmatched) retval.push(count); + }); + return retval; + } + + get_entities() + { + let entities = []; + if(this._config.entities) + this._config.entities.forEach((e) => entities.push(e)); + + if(this._hass && this._config.filter) { + + if(this._config.filter.include){ + this._config.filter.include.forEach((f) => { + const add = this.match_filter(this._hass, Object.keys(this._hass.states), f); + let toAdd = []; + add.forEach((i) => { + toAdd.push(Object.assign({entity: Object.keys(this._hass.states)[i]}, f.options)); + }); + toAdd.sort((a,b) => { + if (a.entity < b.entity) return -1; + if (a.entity > b.entity) return 1; + return 0; + }); + toAdd.forEach((i) => entities.push(i)); + }); } - - set hass(hass) { - this._hass = hass; - this.get_data(hass).then(() => { - if(this.card) + + if(this._config.filter.exclude) { + this._config.filter.exclude.forEach((f) => { + const remove = this.match_filter(this._hass, entities, f); + for(var i = remove.length-1; i >= 0; i--) { - this.card.hass = this._hass; - } - - const oldEntities = this.entities.map((e) => e.entity); - this.entities = this.get_entities() || []; - const newEntities = this.entities.map((e) => e.entity); - - if(!this._compare_arrays(oldEntities, newEntities)) { - this.card.setConfig(Object.assign({entities: this.entities}, this._config.card)); - this.requestUpdate(); + entities.splice(remove[i],1); } }); } - } - - customElements.define('auto-entities', AutoEntities); + return entities; + } + + createRenderRoot() { + return this; + } + render() { + if(this.entities.length === 0 && this._config.show_empty === false) + return cardTools.LitHtml``; + return cardTools.LitHtml` +
${this.card}
+ `; + } + + async get_data(hass) { + try { + this.data.areas = await hass.callWS({type: "config/area_registry/list"}); + this.data.devices = await hass.callWS({type: "config/device_registry/list"}); + this.data.entities = await hass.callWS({type: "config/entity_registry/list"}); + } catch (err) { + } + } + + _compare_arrays(a,b) { + if(a === b) return true; + if(a == null || b == null) return false; + if(a.length != b.length) return false; + for(var i = 0; i < a.length; i++) { + if(a[i] !== b[i]) { + return false; + } + } + return true; + } + + set hass(hass) { + this._hass = hass; + this.get_data(hass).then(() => { + if(this.card) + { + this.card.hass = this._hass; + } + + const oldEntities = this.entities.map((e) => e.entity); + this.entities = this.get_entities() || []; + const newEntities = this.entities.map((e) => e.entity); + + if(!this._compare_arrays(oldEntities, newEntities)) { + this.card.setConfig(Object.assign({entities: this.entities}, this._config.card)); + this.requestUpdate(); + } }); - - window.setTimeout(() => { - if(customElements.get('card-tools')) return; - customElements.define('auto-entities', class extends HTMLElement{ - setConfig() { throw new Error("Can't find card-tools. See https://github.com/thomasloven/lovelace-card-tools");} - }); - }, 2000); \ No newline at end of file + } + +} + +customElements.define('auto-entities', AutoEntities); +}); + +window.setTimeout(() => { + if(customElements.get('card-tools')) return; + customElements.define('auto-entities', class extends HTMLElement{ + setConfig() { throw new Error("Can't find card-tools. See https://github.com/thomasloven/lovelace-card-tools");} + }); +}, 2000); diff --git a/www/card-tools.js b/www/card-tools.js index 288485f2..a6087491 100644 --- a/www/card-tools.js +++ b/www/card-tools.js @@ -9,30 +9,43 @@ class { } } + static deprecationWarning() { + if(window.cardTools_deprecationWarning) return; + console.warn("One or more of your lovelace plugins are using the functions cardTools.litElement(), cardTools.litHtml() or cardTools.hass(). Those are replaced with better alternatives and will be removed a some point in the future.") + console.warn("If you are a plugin developer, make sure you are using the new functions (see documentation)."); + console.warn("If you are a plugin user, feel free to ignore this warning (or poke the developer of your plugins - not me though, I already know about this).") + console.warn("Best regards / thomasloven - " + (document.currentScript && document.currentScript.src)); + window.cardTools_deprecationWarning = true; + } + static get LitElement() { return Object.getPrototypeOf(customElements.get('home-assistant-main')); } static litElement() { // Backwards compatibility - deprecated + this.deprecationWarning(); return this.LitElement; } static get LitHtml() { - return this.litElement().prototype.html; + return this.LitElement.prototype.html; } static litHtml() { // Backwards compatibility - deprecated + this.deprecationWarning(); return this.LitHtml; } static get LitCSS() { - return this.litElement().prototype.css; + return this.LitElement.prototype.css; } static get hass() { var hass = function() { // Backwards compatibility - deprecated + this.deprecationWarning(); return hass; } for (var k in document.querySelector('home-assistant').hass) hass[k] = document.querySelector('home-assistant').hass[k]; + hass.original = document.querySelector('home-assistant').hass; return hass; } @@ -51,7 +64,7 @@ class { root = root && root.querySelector("home-assistant-main"); root = root && root.shadowRoot; root = root && root.querySelector("app-drawer-layout partial-panel-resolver"); - root = root && root.shadowRoot; + root = root && root.shadowRoot || root; root = root && root.querySelector("ha-panel-lovelace"); root = root && root.shadowRoot; root = root && root.querySelector("hui-root"); @@ -68,7 +81,7 @@ class { root = root && root.querySelector("home-assistant-main"); root = root && root.shadowRoot; root = root && root.querySelector("app-drawer-layout partial-panel-resolver"); - root = root && root.shadowRoot; + root = root && root.shadowRoot || root; root = root && root.querySelector("ha-panel-lovelace") root = root && root.shadowRoot; root = root && root.querySelector("hui-root") @@ -408,4 +421,4 @@ var cardTools = customElements.get('card-tools'); console.info(`%cCARD-TOOLS IS INSTALLED %cDeviceID: ${customElements.get('card-tools').deviceID}`, "color: green; font-weight: bold", -""); \ No newline at end of file +""); diff --git a/www/config-template-card.js b/www/config-template-card.js index abd53766..a7a82832 100644 --- a/www/config-template-card.js +++ b/www/config-template-card.js @@ -12,6 +12,41 @@ MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +} + +var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +function __rest(s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +} function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; @@ -20,6 +55,136 @@ function __decorate(decorators, target, key, desc) { return c > 3 && r && Object.defineProperty(target, key, r), r; } +function __param(paramIndex, decorator) { + return function (target, key) { decorator(target, key, paramIndex); } +} + +function __metadata(metadataKey, metadataValue) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); +} + +function __awaiter(thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +} + +function __generator(thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +} + +function __exportStar(m, exports) { + for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; +} + +function __values(o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +} + +function __read(o, n) { + var m = typeof Symbol === "function" && o[Symbol.iterator]; + if (!m) return o; + var i = m.call(o), r, ar = [], e; + try { + while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); + } + catch (error) { e = { error: error }; } + finally { + try { + if (r && !r.done && (m = i["return"])) m.call(i); + } + finally { if (e) throw e.error; } + } + return ar; +} + +function __spread() { + for (var ar = [], i = 0; i < arguments.length; i++) + ar = ar.concat(__read(arguments[i])); + return ar; +} + +function __await(v) { + return this instanceof __await ? (this.v = v, this) : new __await(v); +} + +function __asyncGenerator(thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +} + +function __asyncDelegator(o) { + var i, p; + return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; + function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; } +} + +function __asyncValues(o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +} + +function __makeTemplateObject(cooked, raw) { + if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } + return cooked; +}; + +function __importStar(mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; + result.default = mod; + return result; +} + +function __importDefault(mod) { + return (mod && mod.__esModule) ? mod : { default: mod }; +} + /** * @license * Copyright (c) 2017 The Polymer Project Authors. All rights reserved. @@ -34,6 +199,32 @@ function __decorate(decorators, target, key, desc) { * http://polymer.github.io/PATENTS.txt */ const directives = new WeakMap(); +/** + * Brands a function as a directive so that lit-html will call the function + * during template rendering, rather than passing as a value. + * + * @param f The directive factory function. Must be a function that returns a + * function of the signature `(part: Part) => void`. The returned function will + * be called with the part object + * + * @example + * + * ``` + * import {directive, html} from 'lit-html'; + * + * const immutable = directive((v) => (part) => { + * if (part.value !== v) { + * part.setValue(v) + * } + * }); + * ``` + */ +// tslint:disable-next-line:no-any +const directive = (f) => ((...args) => { + const d = f(...args); + directives.set(d, true); + return d; +}); const isDirective = (o) => { return typeof o === 'function' && directives.has(o); }; @@ -57,6 +248,20 @@ const isDirective = (o) => { const isCEPolyfill = window.customElements !== undefined && window.customElements.polyfillWrapFlushCallback !== undefined; +/** + * Reparents nodes, starting from `startNode` (inclusive) to `endNode` + * (exclusive), into another container (could be the same container), before + * `beforeNode`. If `beforeNode` is null, it appends the nodes to the + * container. + */ +const reparentNodes = (container, start, end = null, before = null) => { + let node = start; + while (node !== end) { + const n = node.nextSibling; + container.insertBefore(node, before); + node = n; + } +}; /** * Removes nodes, starting from `startNode` (inclusive) to `endNode` * (exclusive), from `container`. @@ -442,6 +647,26 @@ class TemplateResult { return template; } } +/** + * A TemplateResult for SVG fragments. + * + * This class wraps HTMl in an `` tag in order to parse its contents in the + * SVG namespace, then modifies the template to remove the `` tag so that + * clones only container the original fragment. + */ +class SVGTemplateResult extends TemplateResult { + getHTML() { + return `${super.getHTML()}`; + } + getTemplateElement() { + const template = super.getTemplateElement(); + const content = template.content; + const svgElement = content.firstChild; + content.removeChild(svgElement); + reparentNodes(content, svgElement.firstChild); + return template; + } +} /** * @license @@ -1027,6 +1252,11 @@ const render = (result, container, options) => { * render to and update a container. */ const html = (strings, ...values) => new TemplateResult(strings, values, 'html', defaultTemplateProcessor); +/** + * Interprets a template literal as an SVG template that can efficiently + * render to and update a container. + */ +const svg = (strings, ...values) => new SVGTemplateResult(strings, values, 'svg', defaultTemplateProcessor); /** * @license @@ -2050,6 +2280,94 @@ function property(options) { legacyProperty(options, protoOrDescriptor, name) : standardProperty(options, protoOrDescriptor); } +/** + * A property decorator that converts a class property into a getter that + * executes a querySelector on the element's renderRoot. + */ +const query = _query((target, selector) => target.querySelector(selector)); +/** + * A property decorator that converts a class property into a getter + * that executes a querySelectorAll on the element's renderRoot. + */ +const queryAll = _query((target, selector) => target.querySelectorAll(selector)); +const legacyQuery = (descriptor, proto, name) => { + Object.defineProperty(proto, name, descriptor); +}; +const standardQuery = (descriptor, element) => ({ + kind: 'method', + placement: 'prototype', + key: element.key, + descriptor, +}); +/** + * Base-implementation of `@query` and `@queryAll` decorators. + * + * @param queryFn exectute a `selector` (ie, querySelector or querySelectorAll) + * against `target`. + * @suppress {visibility} The descriptor accesses an internal field on the + * element. + */ +function _query(queryFn) { + return (selector) => (protoOrDescriptor, + // tslint:disable-next-line:no-any decorator + name) => { + const descriptor = { + get() { + return queryFn(this.renderRoot, selector); + }, + enumerable: true, + configurable: true, + }; + return (name !== undefined) ? + legacyQuery(descriptor, protoOrDescriptor, name) : + standardQuery(descriptor, protoOrDescriptor); + }; +} +const standardEventOptions = (options, element) => { + return Object.assign({}, element, { finisher(clazz) { + Object.assign(clazz.prototype[element.key], options); + } }); +}; +const legacyEventOptions = +// tslint:disable-next-line:no-any legacy decorator +(options, proto, name) => { + Object.assign(proto[name], options); +}; +/** + * Adds event listener options to a method used as an event listener in a + * lit-html template. + * + * @param options An object that specifis event listener options as accepted by + * `EventTarget#addEventListener` and `EventTarget#removeEventListener`. + * + * Current browsers support the `capture`, `passive`, and `once` options. See: + * https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Parameters + * + * @example + * + * class MyElement { + * + * clicked = false; + * + * render() { + * return html`
`; + * } + * + * @eventOptions({capture: true}) + * _onClick(e) { + * this.clicked = true; + * } + * } + */ +const eventOptions = (options) => +// Return value typed as any to prevent TypeScript from complaining that +// standard decorator function signature does not match TypeScript decorator +// signature +// TODO(kschaaf): unclear why it was only failing on this decorator and not +// the others +((protoOrDescriptor, name) => (name !== undefined) ? + legacyEventOptions(options, protoOrDescriptor, name) : + standardEventOptions(options, protoOrDescriptor)); /** @license @@ -2063,6 +2381,63 @@ found at http://polymer.github.io/PATENTS.txt */ const supportsAdoptingStyleSheets = ('adoptedStyleSheets' in Document.prototype) && ('replace' in CSSStyleSheet.prototype); +const constructionToken = Symbol(); +class CSSResult { + constructor(cssText, safeToken) { + if (safeToken !== constructionToken) { + throw new Error('CSSResult is not constructable. Use `unsafeCSS` or `css` instead.'); + } + this.cssText = cssText; + } + // Note, this is a getter so that it's lazy. In practice, this means + // stylesheets are not created until the first element instance is made. + get styleSheet() { + if (this._styleSheet === undefined) { + // Note, if `adoptedStyleSheets` is supported then we assume CSSStyleSheet + // is constructable. + if (supportsAdoptingStyleSheets) { + this._styleSheet = new CSSStyleSheet(); + this._styleSheet.replaceSync(this.cssText); + } + else { + this._styleSheet = null; + } + } + return this._styleSheet; + } + toString() { + return this.cssText; + } +} +/** + * Wrap a value for interpolation in a css tagged template literal. + * + * This is unsafe because untrusted CSS text can be used to phone home + * or exfiltrate data to an attacker controlled site. Take care to only use + * this with trusted input. + */ +const unsafeCSS = (value) => { + return new CSSResult(String(value), constructionToken); +}; +const textFromCSSResult = (value) => { + if (value instanceof CSSResult) { + return value.cssText; + } + else { + throw new Error(`Value passed to 'css' function must be a 'css' function result: ${value}. Use 'unsafeCSS' to pass non-literal values, but + take care to ensure page security.`); + } +}; +/** + * Template tag which which can be used with LitElement's `style` property to + * set element styles. For security reasons, only literal string values may be + * used. To incorporate non-literal values `unsafeCSS` may be used inside a + * template string part. + */ +const css = (strings, ...values) => { + const cssText = values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]); + return new CSSResult(cssText, constructionToken); +}; /** * @license @@ -2286,7 +2661,7 @@ const fireEvent = (node, type, detail, options) => { let ConfigTemplateCard = class ConfigTemplateCard extends LitElement { setConfig(config) { - if (!config || !config.config || !config.config.type) { + if (!config || !config.card || !config.card.type) { throw new Error("Invalid configuration"); } this._config = config; @@ -2311,7 +2686,7 @@ let ConfigTemplateCard = class ConfigTemplateCard extends LitElement { } // this.hass.states // this.hass.user.name - let cardConfig = deepcopy(this._config.config); + let cardConfig = deepcopy(this._config.card); cardConfig = this._evaluateConfig(cardConfig); // console.log(this._config.config); // console.log(cardConfig); @@ -2357,6 +2732,11 @@ let ConfigTemplateCard = class ConfigTemplateCard extends LitElement { _evaluateTemplate(template) { const user = this.hass.user; const states = this.hass.states; + const vars = []; + for (const v in this._config.variables) { + const newV = eval(this._config.variables[v]); + vars.push(newV); + } return eval(template.substring(2, template.length - 1)); } createThing(cardConfig) { diff --git a/www/fold-entity-row.js b/www/fold-entity-row.js index cb7e3b99..62503ec8 100644 --- a/www/fold-entity-row.js +++ b/www/fold-entity-row.js @@ -1,144 +1,144 @@ customElements.whenDefined('card-tools').then(() => { - class FoldEntityRow extends cardTools.litElement() { - - static get properties() { - return { - _closed: Boolean, - }; - } - - render() { - return cardTools.litHtml()` - ${this._renderStyle()} -