├── .gitignore ├── .gitattributes ├── hacs.json ├── webpack.config.js ├── test ├── configuration.yaml ├── docker-compose.yaml └── lovelace.yaml ├── package.json ├── LICENSE.txt ├── README.md ├── src └── main.js └── template-entity-row.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | template-entity-row.js binary 2 | package-lock.json binary 3 | -------------------------------------------------------------------------------- /hacs.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "template-entity-row", 3 | "render_readme": true, 4 | "homeassistant": "0.107.0b1" 5 | } 6 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | entry: './src/main.js', 5 | mode: 'production', 6 | output: { 7 | filename: 'template-entity-row.js', 8 | path: path.resolve(__dirname) 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /test/configuration.yaml: -------------------------------------------------------------------------------- 1 | default_config: 2 | 3 | demo: 4 | 5 | lovelace: 6 | mode: storage 7 | dashboards: 8 | lovelace-yaml: 9 | mode: yaml 10 | title: yaml 11 | filename: lovelace.yaml 12 | 13 | input_boolean: 14 | test: 15 | 16 | sensor: 17 | - platform: time_date 18 | display_options: 19 | - time 20 | - date 21 | - date_time 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "template-entity-row", 3 | "private": true, 4 | "version": "1.1.1", 5 | "description": "", 6 | "scripts": { 7 | "build": "webpack", 8 | "watch": "webpack --watch --mode=development", 9 | "update-card-tools": "npm uninstall card-tools && npm install thomasloven/lovelace-card-tools" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "github.com:thomasloven/lovelace-template-entity-row" 14 | }, 15 | "keywords": [], 16 | "author": "Thomas Lovén", 17 | "license": "MIT", 18 | "devDependencies": { 19 | "webpack": "^4.44.2", 20 | "webpack-cli": "^3.3.12" 21 | }, 22 | "dependencies": { 23 | "card-tools": "github:thomasloven/lovelace-card-tools" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Thomas Lovén 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /test/docker-compose.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # Docker services for testing Home Assistant integrations and plugins 3 | # 4 | # Automaatically sets up configuration adds a user and skips the onboarding 5 | # 6 | # Username: dev 7 | # Password: dev 8 | # 9 | # Two services, 'prod' and 'dev' run the latest production and dev docker images respectively. 10 | # 11 | # Start with 12 | # $ docker-compose up prod 13 | # or 14 | # $ docker-compose up dev 15 | # 16 | # When done, clean up with 17 | # $ docker-compose rm -f 18 | # 19 | 20 | x-files: &x-files 21 | - ../template-entity-row.js:/config/www/template-entity-row.js 22 | - ./configuration.yaml:/config/configuration.yaml 23 | - ./lovelace.yaml:/config/lovelace.yaml 24 | - ./views:/config/views 25 | - ./themes:/config/themes 26 | 27 | x-command: &x-command | 28 | bash -c ' 29 | hass --script ensure_config -c /config && 30 | hass --script auth -c /config add dev dev && 31 | echo " 32 | { 33 | \"data\": { 34 | \"done\": [ 35 | \"user\", 36 | \"core_config\", 37 | \"integration\" 38 | ] 39 | }, 40 | \"key\": \"onboarding\", 41 | \"version\": 3 42 | } 43 | " > /config/.storage/onboarding && 44 | 45 | echo " 46 | { 47 | \"data\": { 48 | \"items\": [ 49 | { 50 | \"id\": \"1\", 51 | \"type\": \"module\", 52 | \"url\": \"/local/template-entity-row.js\" 53 | } 54 | ] 55 | }, 56 | \"key\": \"lovelace_resources\", 57 | \"version\": 1 58 | } 59 | " > /config/.storage/lovelace_resources && 60 | 61 | hass -v -c /config' 62 | 63 | version: '3.5' 64 | services: 65 | 66 | prod: &base_service 67 | image: homeassistant/home-assistant:latest 68 | volumes: *x-files 69 | ports: 70 | - "5001:8123" 71 | command: *x-command 72 | 73 | dev: 74 | <<: *base_service 75 | image: homeassistant/home-assistant:dev 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # template-entity-row 2 | 3 | [![hacs_badge](https://img.shields.io/badge/HACS-Default-orange.svg)](https://github.com/custom-components/hacs) 4 | 5 | Display whatever you want in an entities card row. 6 | 7 | For installation instructions [see this guide](https://github.com/thomasloven/hass-config/wiki/Lovelace-Plugins). 8 | 9 | Install `template-entity-row.js` as a `module`. 10 | 11 | ```yaml 12 | resources: 13 | - url: /local/template-entity-row.js 14 | type: module 15 | ``` 16 | 17 | ## Usage example 18 | 19 | **Note:** This is *not* a card. It's a row for an [entities](https://www.home-assistant.io/lovelace/entities/). 20 | 21 | ![Skärminspelning 2020-01-03 kl 23 03 16 mov](https://user-images.githubusercontent.com/1299821/71752529-b627b000-2e7f-11ea-87ad-3b8f2d2cfe99.gif) 22 | ```yaml 23 | type: entities 24 | title: Default 25 | entities: 26 | - light.bed_light 27 | - entity: input_boolean.car_home 28 | - type: custom:template-entity-row 29 | icon: mdi:lamp 30 | name: "The light is {{states('light.bed_light')}} but nobody's" 31 | state: "{% if is_state('input_boolean.car_home', 'on')%} home {% else %} away {% endif %}" 32 | secondary: "It's {{states('sensor.time')}}" 33 | active: "{{ is_state('light.bed_light', 'off') }}" 34 | - type: custom:template-entity-row 35 | icon: mdi:car 36 | name: Hi there 37 | condition: "{{is_state('input_boolean.car_home', 'on')}}" 38 | ``` 39 | 40 | ## Options 41 | - `icon`, `name`, `state`, `secondary`, `image` selects what icon, name, state, secondary_info text and entity_picture to display respectively. 42 | - `active` if this evaluates to "true", the icon gets the color `--paper-item-icon-active-color`. Otherwise `--paper-item-icon-color`. 43 | - `entity` if this evaluates to an entity id, `icon`, `name`, `state` and `image` will be taken from that entity unless manually overridden. Specifying an `entity` will also let you use [`action`](https://www.home-assistant.io/lovelace/entities/#options-for-entities). 44 | - `condition` if this is set but does not evaluate to "true", the row is not displayed. 45 | 46 | All options accept [jinja2 templates](https://www.home-assistant.io/docs/configuration/templating/). 47 | 48 | Jinja templates have access to a few special variables. Those are: 49 | 50 | - `config` - an object containing the card configuration 51 | - `user` - the username of the currently logged in user 52 | - `browser` - the deviceID of the current browser (see [browser_mod](https://github.com/thomasloven/hass-browser_mod)). 53 | - `hash` - the hash part of the current URL. 54 | 55 | In evaluated templates the function `_()` (underscore) will localize the `` to the current language. 56 | E.g. `_(state.binary_sensor.motion.off)` will be replaced with `Clear` if your language is set to English. 57 | 58 | To find the available keys, open your browsers console, type in the following and press Enter: 59 | ```javascript 60 | document.querySelector("home-assistant").hass.resources 61 | ``` 62 | 63 | # FAQ 64 | 65 | ### Why does this look weird? 66 | Because you're not using it correctly. This is **not** a card. It's an entity row, and is meant to be used *inside* the [entities card](https://www.home-assistant.io/lovelace/entities/) 67 | 68 | --- 69 | Buy Me A Coffee 70 | -------------------------------------------------------------------------------- /test/lovelace.yaml: -------------------------------------------------------------------------------- 1 | title: Template-entity-row 2 | views: 3 | - title: Main 4 | cards: 5 | - type: entities 6 | title: Static 7 | entities: 8 | - light.bed_light 9 | 10 | - type: section 11 | label: icon 12 | - type: custom:template-entity-row 13 | icon: mdi:cog 14 | 15 | - type: section 16 | label: name 17 | - type: custom:template-entity-row 18 | name: Name 19 | 20 | - type: section 21 | label: state 22 | - type: custom:template-entity-row 23 | state: state 24 | 25 | - type: section 26 | label: secondary 27 | - type: custom:template-entity-row 28 | secondary: secondary 29 | 30 | - type: section 31 | label: image 32 | - type: custom:template-entity-row 33 | image: https://placekitten.com/50/50 34 | 35 | 36 | - type: entities 37 | title: Entity based 38 | entities: 39 | 40 | - type: custom:template-entity-row 41 | entity: light.bed_light 42 | 43 | - type: section 44 | label: icon 45 | - type: custom:template-entity-row 46 | entity: light.bed_light 47 | icon: mdi:cog 48 | 49 | - type: section 50 | label: name 51 | - type: custom:template-entity-row 52 | entity: light.bed_light 53 | name: name 54 | 55 | - type: section 56 | label: state 57 | - type: custom:template-entity-row 58 | entity: light.bed_light 59 | state: state 60 | 61 | - type: section 62 | label: secondary 63 | - type: custom:template-entity-row 64 | entity: light.bed_light 65 | secondary: secondary 66 | 67 | - type: section 68 | label: image 69 | - type: custom:template-entity-row 70 | entity: light.bed_light 71 | image: https://placekitten.com/50/50 72 | 73 | - type: section 74 | label: condition 75 | - type: custom:template-entity-row 76 | entity: light.bed_light 77 | condition: "{{is_state('input_boolean.test', 'on')}}" 78 | 79 | - type: entities 80 | title: Templates 81 | entities: 82 | - entity: input_boolean.test 83 | 84 | - type: section 85 | label: icon 86 | - type: custom:template-entity-row 87 | icon: "{% if is_state('input_boolean.test', 'on') %} mdi:cog {% else %} mdi:cog-outline {% endif %}" 88 | 89 | - type: section 90 | label: name 91 | - type: custom:template-entity-row 92 | name: "Name for{% if is_state('input_boolean.test', 'on') %} active {% else %} inactive {% endif %}state" 93 | 94 | - type: section 95 | label: state 96 | - type: custom:template-entity-row 97 | state: "[{{states('input_boolean.test')}}]" 98 | 99 | - type: section 100 | label: secondary 101 | - type: custom:template-entity-row 102 | secondary: "{{states('sensor.time')}} {{states('input_boolean.test')}}" 103 | 104 | - type: section 105 | label: image 106 | - type: custom:template-entity-row 107 | image: | 108 | {% set animal = 'kitten' if is_state('input_boolean.test', 'off') else 'bear' -%} 109 | https://place{{animal}}.com/100/100 110 | 111 | - type: section 112 | label: active 113 | - type: custom:template-entity-row 114 | icon: mdi:cog 115 | active: "{{is_state('input_boolean.test', 'on')}}" 116 | 117 | - type: section 118 | label: condition 119 | - type: custom:template-entity-row 120 | name: conditional 121 | condition: "{{is_state('input_boolean.test', 'on')}}" 122 | 123 | - type: section 124 | label: color (undocumented) 125 | - type: custom:template-entity-row 126 | icon: mdi:cog 127 | color: "rgb{{state_attr('light.bed_light', 'rgb_color')}}" 128 | active: "true" 129 | 130 | - type: entities 131 | title: Demo 132 | entities: 133 | - entity: input_boolean.test 134 | - type: custom:template-entity-row 135 | icon: mdi:lamp 136 | name: "The light is {{states('light.bed_light')}} but nobody's" 137 | state: "{% if is_state('input_boolean.test', 'on')%} home {% else %} away {% endif %}" 138 | secondary: "It's {{states('sensor.time')}}" 139 | active: "{{ is_state('light.bed_light', 'off') }}" 140 | - type: custom:template-entity-row 141 | icon: mdi:car 142 | name: Hi there 143 | condition: "{{is_state('input_boolean.car_home', 'on')}}" 144 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import {LitElement, html, css } from "card-tools/src/lit-element"; 2 | import {subscribeRenderTemplate, hasTemplate} from "card-tools/src/templates"; 3 | import { bindActionHandler } from "card-tools/src/action"; 4 | 5 | const OPTIONS = [ 6 | "icon", 7 | "active", 8 | "name", 9 | "secondary", 10 | "state", 11 | "condition", 12 | "image", 13 | "entity", 14 | // Secret option - 15 | // Set color to a hs-color value ("[,]") 16 | // with hue in the range 0-360 and saturation 0-100. 17 | // Works only if entity is unset and active is set. 18 | "color", 19 | ] 20 | 21 | class TemplateEntityRow extends LitElement { 22 | 23 | static get properties() { 24 | return { 25 | hass: {}, 26 | state: {}, 27 | }; 28 | } 29 | 30 | setConfig(config) { 31 | this._config = {...config}; 32 | this.config = this._config; 33 | this.state = {...this._config}; 34 | 35 | let entity_ids = this._config.entity_ids; 36 | if(!entity_ids && this._config.entity && !hasTemplate(this._config.entity)) 37 | entity_ids = [this._config.entity]; 38 | for(const k of OPTIONS) { 39 | if(this._config[k] && hasTemplate(this._config[k])) { 40 | subscribeRenderTemplate(null, (res) => { 41 | this.state[k] = res; 42 | this.requestUpdate(); 43 | }, { 44 | template: this._config[k], 45 | variables: {config: this._config}, 46 | entity_ids, 47 | }); 48 | } 49 | } 50 | } 51 | 52 | async firstUpdated() { 53 | const gen_row = this.shadowRoot.querySelector("#staging hui-generic-entity-row"); 54 | if(!gen_row) return; 55 | await gen_row.updateComplete; 56 | this._action = gen_row._handleAction; 57 | const options = { 58 | hasHold: this._config.hold_action !== undefined && this._config.hold_action.action !== undefined, 59 | hasDoubleClick: this._config.hold_action !== undefined && this._config.hold_action.action !== undefined, 60 | } 61 | bindActionHandler(this.shadowRoot.querySelector("state-badge"), options); 62 | bindActionHandler(this.shadowRoot.querySelector(".info"), options); 63 | } 64 | 65 | _actionHandler(ev) { 66 | if(this._action) return this._action(ev); 67 | } 68 | 69 | render() { 70 | const base = this.hass.states[this.state.entity]; 71 | const entity = base && JSON.parse(JSON.stringify(base)) || { 72 | entity_id: "light.", 73 | attributes: {icon: "no:icon"}, 74 | }; 75 | 76 | const icon = this.state.icon !== undefined 77 | ? this.state.icon || "no:icon" 78 | : undefined; 79 | ; 80 | const image = this.state.image; 81 | const name = this.state.name !== undefined 82 | ? this.state.name 83 | : base ? base.attributes.friendly_name || base.entity_id : undefined 84 | ; 85 | const secondary = this.state.secondary; 86 | const state = this.state.state !== undefined 87 | ? this.state.state 88 | : entity ? entity.state : undefined 89 | ; 90 | const active = this.state.active !== undefined 91 | ? String(this.state.active).toLowerCase() === "true" 92 | : undefined 93 | ; 94 | 95 | if(active !== undefined) { 96 | entity.attributes.brightness = 255; 97 | } 98 | 99 | const color = this.state.color !== undefined 100 | ? this.state.color 101 | : active === undefined 102 | ? undefined 103 | : active 104 | ? "var(--paper-item-icon-active-color, #fdd835)" 105 | : "var(--paper-item-icon-color, #44739e)" 106 | ; 107 | 108 | return html` 109 |
110 | 119 |
123 | ${name} 124 |
125 | ${secondary} 126 |
127 |
128 |
129 | ${state} 130 |
131 |
132 |
133 | 137 | 138 |
139 | `; 140 | } 141 | 142 | static get styles() { 143 | const HuiGenericEntityRow = customElements.get('hui-generic-entity-row'); 144 | let style = HuiGenericEntityRow.styles; 145 | style.cssText = style.cssText 146 | .replace(":host", "#wrapper") 147 | + ` 148 | .state { 149 | text-align: right; 150 | } 151 | #wrapper { 152 | min-height: 40px; 153 | } 154 | #wrapper.hidden { 155 | display: none; 156 | } 157 | #staging { 158 | display: none; 159 | } 160 | `; 161 | return style; 162 | } 163 | } 164 | 165 | if(!customElements.get("template-entity-row")) { 166 | customElements.define("template-entity-row", TemplateEntityRow); 167 | const pjson = require('../package.json'); 168 | console.info(`%cTEMPLATE-ENTITY-ROW ${pjson.version} IS INSTALLED`, 169 | "color: green; font-weight: bold", 170 | ""); 171 | } 172 | -------------------------------------------------------------------------------- /template-entity-row.js: -------------------------------------------------------------------------------- 1 | !function(t){var e={};function i(o){if(e[o])return e[o].exports;var n=e[o]={i:o,l:!1,exports:{}};return t[o].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.m=t,i.c=e,i.d=function(t,e,o){i.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},i.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.t=function(t,e){if(1&e&&(t=i(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(i.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var n in t)i.d(o,n,function(e){return t[e]}.bind(null,n));return o},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=1)}([function(t){t.exports=JSON.parse('{"name":"template-entity-row","private":true,"version":"1.1.1","description":"","scripts":{"build":"webpack","watch":"webpack --watch --mode=development","update-card-tools":"npm uninstall card-tools && npm install thomasloven/lovelace-card-tools"},"repository":{"type":"git","url":"github.com:thomasloven/lovelace-template-entity-row"},"keywords":[],"author":"Thomas Lovén","license":"MIT","devDependencies":{"webpack":"^4.41.5","webpack-cli":"^3.3.10"},"dependencies":{"card-tools":"github:thomasloven/lovelace-card-tools"}}')},function(t,e,i){"use strict";i.r(e);const o=customElements.get("home-assistant-main")?Object.getPrototypeOf(customElements.get("home-assistant-main")):Object.getPrototypeOf(customElements.get("hui-view")),n=o.prototype.html;o.prototype.css;function s(){return document.querySelector("hc-main")?document.querySelector("hc-main").hass:document.querySelector("home-assistant")?document.querySelector("home-assistant").hass:void 0}const a="lovelace-player-device-id";function r(){if(!localStorage[a]){const t=()=>Math.floor(1e5*(1+Math.random())).toString(16).substring(1);window.fully&&"function"==typeof fully.getDeviceId?localStorage[a]=fully.getDeviceId():localStorage[a]=`${t()}${t()}-${t()}${t()}`}return localStorage[a]}let c=r();const l=new URLSearchParams(window.location.search);var d;function u(t){return!!String(t).includes("{%")||(!!String(t).includes("{{")||void 0)}function h(t,e,i,o=!0){t||(t=s().connection);let n={user:s().user.name,browser:c,hash:location.hash.substr(1)||" ",...i.variables},a=i.template,r=i.entity_ids;return t.subscribeMessage(t=>{if(o){let i=String(t.result);const o=/_\([^)]*\)/g;i=i.replace(o,t=>s().localize(t.substring(2,t.length-1))||t),e(i)}else e(t.result)},{type:"render_template",template:a,variables:n,entity_ids:r})}function g(t,e={}){return customElements.whenDefined("long-press").then(()=>{document.body.querySelector("long-press").bind(t)}),customElements.whenDefined("action-handler").then(()=>{document.body.querySelector("action-handler").bind(t,e)}),t}l.get("deviceID")&&null!==(d=l.get("deviceID"))&&("clear"===d?localStorage.removeItem(a):localStorage[a]=d,c=r());const p=["icon","active","name","secondary","state","condition","image","entity","color"];class f extends o{static get properties(){return{hass:{},state:{}}}setConfig(t){this._config={...t},this.config=this._config,this.state={...this._config};let e=this._config.entity_ids;e||!this._config.entity||u(this._config.entity)||(e=[this._config.entity]);for(const t of p)this._config[t]&&u(this._config[t])&&h(null,e=>{this.state[t]=e,this.requestUpdate()},{template:this._config[t],variables:{config:this._config},entity_ids:e})}async firstUpdated(){const t=this.shadowRoot.querySelector("#staging hui-generic-entity-row");if(!t)return;await t.updateComplete,this._action=t._handleAction;const e={hasHold:void 0!==this._config.hold_action&&void 0!==this._config.hold_action.action,hasDoubleClick:void 0!==this._config.hold_action&&void 0!==this._config.hold_action.action};g(this.shadowRoot.querySelector("state-badge"),e),g(this.shadowRoot.querySelector(".info"),e)}_actionHandler(t){if(this._action)return this._action(t)}render(){const t=this.hass.states[this.state.entity],e=t&&JSON.parse(JSON.stringify(t))||{entity_id:"light.",attributes:{icon:"no:icon"}},i=void 0!==this.state.icon?this.state.icon||"no:icon":void 0,o=this.state.image,s=void 0!==this.state.name?this.state.name:t?t.attributes.friendly_name||t.entity_id:void 0,a=this.state.secondary,r=void 0!==this.state.state?this.state.state:e?e.state:void 0,c=void 0!==this.state.active?"true"===String(this.state.active).toLowerCase():void 0;void 0!==c&&(e.attributes.brightness=255);const l=void 0!==this.state.color?this.state.color:void 0===c?void 0:c?"var(--paper-item-icon-active-color, #fdd835)":"var(--paper-item-icon-color, #44739e)";return n` 2 |
3 | 12 |
16 | ${s} 17 |
18 | ${a} 19 |
20 |
21 |
22 | ${r} 23 |
24 |
25 |
26 | 30 | 31 |
32 | `}static get styles(){let t=customElements.get("hui-generic-entity-row").styles;return t.cssText=t.cssText.replace(":host","#wrapper")+"\n .state {\n text-align: right;\n }\n #wrapper {\n min-height: 40px;\n }\n #wrapper.hidden {\n display: none;\n }\n #staging {\n display: none;\n }\n ",t}}if(!customElements.get("template-entity-row")){customElements.define("template-entity-row",f);const t=i(0);console.info(`%cTEMPLATE-ENTITY-ROW ${t.version} IS INSTALLED`,"color: green; font-weight: bold","")}}]); --------------------------------------------------------------------------------