diff --git a/README.md b/README.md index 99f82bc..e8071a5 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ Lovelace Button card for your entities. - [Configuration Templates](#configuration-templates) - [General](#general) - [Merging state by id](#merging-state-by-id) + - [Variables](#variables) - [Installation](#installation) - [Manual Installation](#manual-installation) - [Installation and tracking with hacs](#installation-and-tracking-with-hacs) @@ -111,6 +112,7 @@ Lovelace Button card for your entities. | `lock` | object | optional | See [Lock Object](#lock-object) | Displays a lock on the button | | `layout` | string | optional | See [Layout](#Layout) | The layout of the button can be modified using this option | | `custom_fields` | object | optional | See [Custom Fields](#Custom-Fields) | +| `variables` | object | optional | See [Variables](#Variables) | ### Action @@ -254,12 +256,14 @@ Those are the configuration fields which support templating: * Everything field in `*_action` * The confirmation text (`confirmation.text`) * The lock being enabled or not (`lock.enabled`) +* all the `card` parameters in a `custom_field` Inside the javascript code, you'll have access to those variables: * `entity`: The current entity object, if the entity is defined in the card * `states`: An object with all the states of all the entities (equivalent to `hass.states`) * `user`: The user object (equivalent to `hass.user`) * `hass`: The complete `hass` object +* `variables`: an object containing all your variables defined in the configuration. See [Variables](#variables) See [here](#templates-support) for some examples or [here](#custom-fields) for some crazy advanced stuff using templates! @@ -706,6 +710,31 @@ state: value: 25 ``` +#### Variables + +You can add variables to your templates and overload them in the instance of your button card. This lets you easily work with templates without the need to redefine everything for a small change. +An exemple below: +```yaml +button_card_templates: + variable_test: + var_name: "var_value" + var_name2: "var_value2" + +[...] + +- type: custom:button-card + template: variable_test + entity: sensor.test + name: '[[[ return variables.var_name ]]]' # The name will be "var_value" + +- type: custom:button-card + template: variable_test + entity: sensor.test + variables: + var_name: "My local Value" + name: '[[[ return variables.var_name ]]]' # The name will be "My local Value" +``` + ## Installation ### Manual Installation diff --git a/package-lock.json b/package-lock.json index 3e52395..ef3b97f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1073,11 +1073,6 @@ "dev": true, "optional": true }, - "bowser": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.7.0.tgz", - "integrity": "sha512-aIlMvstvu8x+34KEiOHD3AsBgdrzg6sxALYiukOWhFvGMbQI6TRP/iY0LMhUrHs56aD6P1G0Z7h45PUJaa5m9w==" - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3395,12 +3390,12 @@ } }, "jest-worker": { - "version": "24.6.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.6.0.tgz", - "integrity": "sha512-jDwgW5W9qGNvpI1tNnvajh0a5IE/PuGLFmHk6aR/BZFz8tSgGw17GsDPXAJ6p91IvYDjOw8GpFbvvZGAK+DPQQ==", + "version": "24.9.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-24.9.0.tgz", + "integrity": "sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw==", "dev": true, "requires": { - "merge-stream": "^1.0.1", + "merge-stream": "^2.0.0", "supports-color": "^6.1.0" }, "dependencies": { @@ -3618,13 +3613,10 @@ "optional": true }, "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true }, "merge2": { "version": "1.3.0", @@ -3822,9 +3814,9 @@ } }, "npm": { - "version": "6.12.0", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.12.0.tgz", - "integrity": "sha512-juj5VkB3/k+PWbJUnXD7A/8oc8zLusDnK/sV9PybSalsbOVOTIp5vSE0rz5rQ7BsmUgQS47f/L2GYQnWXaKgnQ==", + "version": "6.13.4", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.4.tgz", + "integrity": "sha512-vTcUL4SCg3AzwInWTbqg1OIaOXlzKSS8Mb8kc5avwrJpcvevDA5J9BhYSuei+fNs3pwOp4lzA5x2FVDXACvoXA==", "dev": true, "requires": { "JSONStream": "^1.3.5", @@ -3833,12 +3825,12 @@ "ansistyles": "~0.1.3", "aproba": "^2.0.0", "archy": "~1.0.0", - "bin-links": "^1.1.3", + "bin-links": "^1.1.6", "bluebird": "^3.5.5", "byte-size": "^5.0.1", "cacache": "^12.0.3", "call-limit": "^1.1.1", - "chownr": "^1.1.2", + "chownr": "^1.1.3", "ci-info": "^2.0.0", "cli-columns": "^3.1.2", "cli-table3": "^0.5.1", @@ -3854,9 +3846,9 @@ "find-npm-prefix": "^1.0.2", "fs-vacuum": "~1.2.10", "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.2.1", + "gentle-fs": "^2.3.0", "glob": "^7.1.4", - "graceful-fs": "^4.2.2", + "graceful-fs": "^4.2.3", "has-unicode": "~2.0.1", "hosted-git-info": "^2.8.5", "iferr": "^1.0.2", @@ -3869,7 +3861,7 @@ "is-cidr": "^3.0.0", "json-parse-better-errors": "^1.0.2", "lazy-property": "~1.0.0", - "libcipm": "^4.0.4", + "libcipm": "^4.0.7", "libnpm": "^3.0.1", "libnpmaccess": "^3.0.2", "libnpmhook": "^5.0.3", @@ -3903,25 +3895,25 @@ "npm-install-checks": "^3.0.2", "npm-lifecycle": "^3.1.4", "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.4", + "npm-packlist": "^1.4.7", "npm-pick-manifest": "^3.0.2", "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.0", + "npm-registry-fetch": "^4.0.2", "npm-user-validate": "~1.0.0", "npmlog": "~4.1.2", "once": "~1.4.0", "opener": "^1.5.1", "osenv": "^0.1.5", - "pacote": "^9.5.8", + "pacote": "^9.5.11", "path-is-inside": "~1.0.2", "promise-inflight": "~1.0.1", "qrcode-terminal": "^0.12.0", "query-string": "^6.8.2", "qw": "~1.0.1", "read": "~1.0.7", - "read-cmd-shim": "^1.0.4", + "read-cmd-shim": "^1.0.5", "read-installed": "~4.0.3", - "read-package-json": "^2.1.0", + "read-package-json": "^2.1.1", "read-package-tree": "^5.3.1", "readable-stream": "^3.4.0", "readdir-scoped-modules": "^1.1.0", @@ -3936,7 +3928,7 @@ "sorted-union-stream": "~2.1.3", "ssri": "^6.0.1", "stringify-package": "^1.0.1", - "tar": "^4.4.12", + "tar": "^4.4.13", "text-table": "~0.2.0", "tiny-relative-date": "^1.3.0", "uid-number": "0.0.6", @@ -3944,7 +3936,7 @@ "unique-filename": "^1.1.1", "unpipe": "~1.0.0", "update-notifier": "^2.5.0", - "uuid": "^3.3.2", + "uuid": "^3.3.3", "validate-npm-package-license": "^3.0.4", "validate-npm-package-name": "~3.0.0", "which": "^1.3.1", @@ -4115,14 +4107,15 @@ } }, "bin-links": { - "version": "1.1.3", + "version": "1.1.6", "bundled": true, "dev": true, "requires": { "bluebird": "^3.5.3", "cmd-shim": "^3.0.0", - "gentle-fs": "^2.0.1", + "gentle-fs": "^2.3.0", "graceful-fs": "^4.1.15", + "npm-normalize-package-bin": "^1.0.0", "write-file-atomic": "^2.3.0" } }, @@ -4227,7 +4220,7 @@ } }, "chownr": { - "version": "1.1.2", + "version": "1.1.3", "bundled": true, "dev": true }, @@ -4873,7 +4866,7 @@ }, "dependencies": { "minipass": { - "version": "2.8.6", + "version": "2.9.0", "bundled": true, "dev": true, "requires": { @@ -4981,12 +4974,13 @@ "dev": true }, "gentle-fs": { - "version": "2.2.1", + "version": "2.3.0", "bundled": true, "dev": true, "requires": { "aproba": "^1.1.2", "chownr": "^1.1.2", + "cmd-shim": "^3.0.3", "fs-vacuum": "^1.2.10", "graceful-fs": "^4.1.11", "iferr": "^0.1.5", @@ -5077,7 +5071,7 @@ } }, "graceful-fs": { - "version": "4.2.2", + "version": "4.2.3", "bundled": true, "dev": true }, @@ -5148,7 +5142,7 @@ } }, "https-proxy-agent": { - "version": "2.2.2", + "version": "2.2.4", "bundled": true, "dev": true, "requires": { @@ -5178,7 +5172,7 @@ "dev": true }, "ignore-walk": { - "version": "3.0.1", + "version": "3.0.3", "bundled": true, "dev": true, "requires": { @@ -5432,7 +5426,7 @@ } }, "libcipm": { - "version": "4.0.4", + "version": "4.0.7", "bundled": true, "dev": true, "requires": { @@ -5735,7 +5729,7 @@ } }, "make-fetch-happen": { - "version": "5.0.0", + "version": "5.0.2", "bundled": true, "dev": true, "requires": { @@ -5743,7 +5737,7 @@ "cacache": "^12.0.0", "http-cache-semantics": "^3.8.1", "http-proxy-agent": "^2.1.0", - "https-proxy-agent": "^2.2.1", + "https-proxy-agent": "^2.2.3", "lru-cache": "^5.1.1", "mississippi": "^3.0.0", "node-fetch-npm": "^2.0.2", @@ -5796,30 +5790,25 @@ "bundled": true, "dev": true }, - "minipass": { - "version": "2.3.3", + "minizlib": { + "version": "1.3.3", "bundled": true, "dev": true, "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "minipass": "^2.9.0" }, "dependencies": { - "yallist": { - "version": "3.0.2", + "minipass": { + "version": "2.9.0", "bundled": true, - "dev": true + "dev": true, + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } } } }, - "minizlib": { - "version": "1.2.2", - "bundled": true, - "dev": true, - "requires": { - "minipass": "^2.2.1" - } - }, "mississippi": { "version": "3.0.0", "bundled": true, @@ -5958,9 +5947,12 @@ } }, "npm-bundled": { - "version": "1.0.6", + "version": "1.1.1", "bundled": true, - "dev": true + "dev": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } }, "npm-cache-filename": { "version": "1.0.2", @@ -5995,6 +5987,11 @@ "bundled": true, "dev": true }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, "npm-package-arg": { "version": "6.1.1", "bundled": true, @@ -6007,7 +6004,7 @@ } }, "npm-packlist": { - "version": "1.4.4", + "version": "1.4.7", "bundled": true, "dev": true, "requires": { @@ -6036,7 +6033,7 @@ } }, "npm-registry-fetch": { - "version": "4.0.0", + "version": "4.0.2", "bundled": true, "dev": true, "requires": { @@ -6045,7 +6042,15 @@ "figgy-pudding": "^3.4.1", "lru-cache": "^5.1.1", "make-fetch-happen": "^5.0.0", - "npm-package-arg": "^6.1.0" + "npm-package-arg": "^6.1.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "bundled": true, + "dev": true + } } }, "npm-run-path": { @@ -6181,7 +6186,7 @@ } }, "pacote": { - "version": "9.5.8", + "version": "9.5.11", "bundled": true, "dev": true, "requires": { @@ -6199,6 +6204,7 @@ "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.12", "npm-pick-manifest": "^3.0.0", @@ -6217,7 +6223,7 @@ }, "dependencies": { "minipass": { - "version": "2.3.5", + "version": "2.9.0", "bundled": true, "dev": true, "requires": { @@ -6450,7 +6456,7 @@ } }, "read-cmd-shim": { - "version": "1.0.4", + "version": "1.0.5", "bundled": true, "dev": true, "requires": { @@ -6472,7 +6478,7 @@ } }, "read-package-json": { - "version": "2.1.0", + "version": "2.1.1", "bundled": true, "dev": true, "requires": { @@ -6480,7 +6486,7 @@ "graceful-fs": "^4.1.2", "json-parse-better-errors": "^1.0.1", "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "npm-normalize-package-bin": "^1.0.0" } }, "read-package-tree": { @@ -6655,28 +6661,23 @@ "bundled": true, "dev": true }, - "slash": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, "slide": { "version": "1.1.6", "bundled": true, "dev": true }, "smart-buffer": { - "version": "4.0.2", + "version": "4.1.0", "bundled": true, "dev": true }, "socks": { - "version": "2.3.2", + "version": "2.3.3", "bundled": true, "dev": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "4.0.2" + "ip": "1.1.5", + "smart-buffer": "^4.1.0" } }, "socks-proxy-agent": { @@ -6922,7 +6923,7 @@ } }, "tar": { - "version": "4.4.12", + "version": "4.4.13", "bundled": true, "dev": true, "requires": { @@ -6936,7 +6937,7 @@ }, "dependencies": { "minipass": { - "version": "2.8.6", + "version": "2.9.0", "bundled": true, "dev": true, "requires": { @@ -7123,7 +7124,7 @@ } }, "uuid": { - "version": "3.3.2", + "version": "3.3.3", "bundled": true, "dev": true }, @@ -8305,15 +8306,33 @@ } }, "rollup-plugin-terser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-4.0.4.tgz", - "integrity": "sha512-wPANT5XKVJJ8RDUN0+wIr7UPd0lIXBo4UdJ59VmlPCtlFsE20AM+14pe+tk7YunCsWEiuzkDBY3QIkSCjtrPXg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.1.3.tgz", + "integrity": "sha512-FuFuXE5QUJ7snyxHLPp/0LFXJhdomKlIx/aK7Tg88Yubsx/UU/lmInoJafXJ4jwVVNcORJ1wRUC5T9cy5yk0wA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "jest-worker": "^24.0.0", - "serialize-javascript": "^1.6.1", - "terser": "^3.14.1" + "jest-worker": "^24.6.0", + "rollup-pluginutils": "^2.8.1", + "serialize-javascript": "^2.1.2", + "terser": "^4.1.0" + }, + "dependencies": { + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "requires": { + "estree-walker": "^0.6.1" + } + } } }, "rollup-plugin-typescript2": { @@ -8985,9 +9004,9 @@ "dev": true }, "serialize-javascript": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-1.7.0.tgz", - "integrity": "sha512-ke8UG8ulpFOxO8f8gRYabHQe/ZntKlcig2Mp+8+URDP1D8vJZ0KUt7LYo07q25Z/+JVSgpr/cui9PIp5H6/+nA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz", + "integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==", "dev": true }, "set-value": { @@ -9432,14 +9451,14 @@ } }, "terser": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.17.0.tgz", - "integrity": "sha512-/FQzzPJmCpjAH9Xvk2paiWrFq+5M6aVOf+2KRbwhByISDX/EujxsK+BAvrhb6H+2rtrLCHK9N01wO014vrIwVQ==", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.5.1.tgz", + "integrity": "sha512-lH9zLIbX8PRBEFCTvfHGCy0s9HEKnNso1Dx9swSopF3VUnFLB8DpQ61tHxoofovNC/sG0spajJM3EIIRSTByiQ==", "dev": true, "requires": { - "commander": "^2.19.0", + "commander": "^2.20.0", "source-map": "~0.6.1", - "source-map-support": "~0.5.10" + "source-map-support": "~0.5.12" }, "dependencies": { "source-map": { @@ -9449,9 +9468,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.12.tgz", - "integrity": "sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", diff --git a/package.json b/package.json index 686e453..39aca28 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "eslint": "^5.16.0", "eslint-config-airbnb-base": "^13.2.0", "eslint-plugin-import": "^2.18.2", - "npm": "^6.12.0", + "npm": "^6.13.4", "pre-commit": "^1.2.2", "prettier": "^1.18.2", "rollup": "^1.25.0", @@ -50,7 +50,7 @@ "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-json": "^4.0.0", "rollup-plugin-node-resolve": "^4.2.4", - "rollup-plugin-terser": "^4.0.4", + "rollup-plugin-terser": "^5.1.3", "rollup-plugin-typescript2": "^0.20.1", "ts-lit-plugin": "^1.1.9", "typescript": "^3.6.4", @@ -58,7 +58,6 @@ }, "dependencies": { "@ctrl/tinycolor": "^2.5.4", - "bowser": "^2.7.0", "custom-card-helpers": "^1.2.7", "home-assistant-js-websocket": "^3.4.0", "lit-element": "^2.2.1", diff --git a/src/button-card.ts b/src/button-card.ts index 24e825f..6220121 100644 --- a/src/button-card.ts +++ b/src/button-card.ts @@ -42,6 +42,7 @@ import { getLightColorBasedOnTemperature, mergeDeep, mergeStatesById, + getLovelaceCast, } from './helpers'; import { styles } from './styles'; import myComputeStateDisplay from './compute_state_display'; @@ -215,9 +216,17 @@ class ButtonCard extends LitElement { private _evalTemplate(state: HassEntity | undefined, func: any): any { /* eslint no-new-func: 0 */ - return new Function('states', 'entity', 'user', 'hass', + return new Function('states', 'entity', 'user', 'hass', 'variables', `'use strict'; ${func}`) - .call(this, this.hass!.states, state, this.hass!.user, this.hass); + .call(this, this.hass!.states, state, this.hass!.user, this.hass, this.config!.variables); + } + + private _objectEvalTemplate( + state: HassEntity | undefined, + obj: any | undefined, + ) { + const objClone = JSON.parse(JSON.stringify(obj)); + return this._getTemplateOrValue(state, objClone); } private _getTemplateOrValue( @@ -226,6 +235,12 @@ class ButtonCard extends LitElement { ): any | undefined { if (['number', 'boolean'].includes(typeof value)) return value; if (!value) return value; + if (['object'].includes(typeof value)) { + Object.keys(value).forEach((key) => { + value[key] = this._getTemplateOrValue(state, value[key]); + }); + return value; + } const trimmed = value.trim(); if ( trimmed.substring(0, 3) === '[[[' @@ -503,7 +518,7 @@ class ButtonCard extends LitElement { if (!value.card) { fields[key] = this._getTemplateOrValue(state, value); } else { - cards[key] = value.card; + cards[key] = this._objectEvalTemplate(state, value.card); } }); } @@ -513,7 +528,7 @@ class ButtonCard extends LitElement { if (!value!.card) { fields[key] = this._getTemplateOrValue(state, value); } else { - cards[key] = value.card; + cards[key] = this._objectEvalTemplate(state, value.card); } }); } @@ -654,6 +669,7 @@ class ButtonCard extends LitElement { style=${styleMap(cardStyle)} @ha-click="${this._handleTap}" @ha-hold="${this._handleHold}" + @ha-released="${this._handleHoldReleased}" @ha-dblclick=${this._handleDblTap} .hasDblClick=${this.config!.double_tap_action!.action !== 'none'} .repeat=${ifDefined(this.config!.hold_action!.repeat)} @@ -781,7 +797,7 @@ class ButtonCard extends LitElement { throw new Error('Invalid configuration'); } - const ll = getLovelace(); + const ll = getLovelace() || getLovelaceCast(); let template: ButtonCardConfig = { ...config }; let tplName: string | undefined = template.template; let mergedStateConfig: StateConfig[] | undefined = config.state; @@ -868,6 +884,11 @@ class ButtonCard extends LitElement { handleClick(this, this.hass!, this._evalActions(config, 'hold_action'), true, false); } + private _handleHoldReleased(ev): void { + const config = ev.target.config; + handleClick(this, this.hass!, this._evalActions(config, 'hold_released_action'), true, false); + } + private _handleDblTap(ev): void { const config = ev.target.config; handleClick(this, this.hass!, this._evalActions(config, 'double_tap_action'), false, true); @@ -929,6 +950,5 @@ class ButtonCard extends LitElement { private _stopPropagation(ev) { ev.stopPropagation(); - console.log('BRRRR'); } } diff --git a/src/helpers.ts b/src/helpers.ts index 93930a2..1e08eb7 100644 --- a/src/helpers.ts +++ b/src/helpers.ts @@ -156,3 +156,17 @@ export function mergeStatesById( } return resultStateConfigs; } + +export function getLovelaceCast() { + let root: any = document.querySelector('hc-main'); + root = root && root.shadowRoot; + root = root && root.querySelector('hc-lovelace'); + root = root && root.shadowRoot; + root = root && root.querySelector('hui-view'); + if (root) { + const ll = root.lovelace; + ll.current_view = root.___curView; + return ll; + } + return null; +} diff --git a/src/long-press.ts b/src/long-press.ts index 39bbec5..3abf15f 100644 --- a/src/long-press.ts +++ b/src/long-press.ts @@ -1,5 +1,4 @@ import { directive, PropertyPart } from 'lit-html'; -import Bowser from 'bowser'; // See https://github.com/home-assistant/home-assistant-polymer/pull/2457 // on how to undo mwc -> paper migration // import '@material/mwc-ripple'; @@ -127,6 +126,9 @@ class LongPress extends HTMLElement implements LongPress { this.repeatTimeout = setInterval(() => { element.dispatchEvent(new Event('ha-hold')); }, element.repeat); + }else{ + // only fire onces when hold down is detected + element.dispatchEvent(new Event('ha-hold')); } }, this.holdTime); @@ -155,7 +157,7 @@ class LongPress extends HTMLElement implements LongPress { this.timer = undefined; if (this.held) { if (!element.repeat) { - element.dispatchEvent(new Event('ha-hold')); + element.dispatchEvent(new Event('ha-released')); } } else if (element.hasDblClick) { if (this.nbClicks === 0) { @@ -178,18 +180,14 @@ class LongPress extends HTMLElement implements LongPress { window.setTimeout(() => (this.cooldownEnd = false), 100); }; - const br = Bowser.getParser(window.navigator.userAgent); - const isCrazyBrowser = br.satisfies({ - mobile: { - safari: '>=13', - }, - }); - const ios13 = new RegExp('^13\\..*', 'gm'); - const isCrazyBrowser2 = br.getOSName() === 'iOS' && (br.getOSVersion().match(ios13) ? true : false); element.addEventListener('touchstart', clickStart, { passive: true }); element.addEventListener('touchend', clickEnd); element.addEventListener('touchcancel', clickEnd); - if (!isCrazyBrowser && !isCrazyBrowser2) { + // avoid double click on iPad OS... + const isIpadOS = navigator.platform === 'MacIntel' + && navigator.maxTouchPoints > 1 + && !window.MSStream; + if (!isIpadOS) { element.addEventListener('mousedown', clickStart, { passive: true }); element.addEventListener('click', clickEnd); } diff --git a/src/styles.ts b/src/styles.ts index bda12d5..91d9377 100644 --- a/src/styles.ts +++ b/src/styles.ts @@ -9,6 +9,14 @@ export const styles = css` display: flex; justify-content: center; align-items: center; + + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Safari */ + -khtml-user-select: none; /* Konqueror HTML */ + -moz-user-select: none; /* Old versions of Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; /* Non-prefixed version, currently + supported by Chrome, Opera and Firefox */ } ha-card.disabled { pointer-events: none; diff --git a/src/types.ts b/src/types.ts index 8ba805a..664765e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -33,6 +33,7 @@ export interface ButtonCardConfig { color_on: string; color_off: string; custom_fields?: CustomFields; + variables?: Variables; } export type Layout = 'vertical' @@ -98,3 +99,7 @@ export interface CssStyleConfig { export interface CustomFields { [key: string]: any; } + +export interface Variables { + [key: string]: any; +}