diff --git a/package-lock.json b/package-lock.json index ee69893..b95f252 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ }, "devDependencies": { "@babel/core": "7.23.9", - "@fltri/eslint-config": "1.2.3", + "@fltri/eslint-config": "1.2.4", "@material/mwc-ripple": "0.27.0", "@material/tab-bar": "14.0.0", "@rollup/plugin-babel": "6.0.4", @@ -35,7 +35,7 @@ "@types/hammerjs": "2.0.45", "@types/jest": "29.5.12", "@typescript-eslint/parser": "5.62.0", - "eslint": "8.56.0", + "eslint": "8.57.0", "eslint-import-resolver-typescript": "3.6.1", "eslint-plugin-import": "2.29.1", "eslint-plugin-jest": "27.9.0", @@ -597,29 +597,29 @@ } }, "node_modules/@eslint/js": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz", - "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@fltri/eslint-config": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@fltri/eslint-config/-/eslint-config-1.2.3.tgz", - "integrity": "sha512-xBgJo0zh7pmU515VAik0EvTg2iazpb81KwL6mr8aBN6Sj5b5cBP2ECZFgeOqc80tolpfB4ZLOMXjRDCbGSF81A==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@fltri/eslint-config/-/eslint-config-1.2.4.tgz", + "integrity": "sha512-ttY8AoianOrRR4c9nNx0iFg0X+ZtRjcuF7kD7sM3ZluuNC3IK7NOPJxfXYcQOw9BSU7ga6fMCxfFM/qhE/awGg==", "dev": true, "dependencies": { "@typescript-eslint/eslint-plugin": "7.0.1", - "@typescript-eslint/parser": "7.0.1", + "@typescript-eslint/parser": "7.0.2", "eslint-plugin-better-styled-components": "1.1.2", "eslint-plugin-extended": "0.2.0", "eslint-plugin-jest": "27.9.0", "eslint-plugin-json": "3.1.0", - "eslint-plugin-mocha": "10.1.0", + "eslint-plugin-mocha": "10.3.0", "eslint-plugin-react": "7.33.2", - "eslint-plugin-unicorn": "48.0.1", + "eslint-plugin-unicorn": "51.0.1", "glob-parent": "6.0.2", "hosted-git-info": "7.0.1", "normalize-url": "8.0.0", @@ -689,15 +689,15 @@ } }, "node_modules/@fltri/eslint-config/node_modules/@typescript-eslint/parser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", - "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.2.tgz", + "integrity": "sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.0.1", - "@typescript-eslint/types": "7.0.1", - "@typescript-eslint/typescript-estree": "7.0.1", - "@typescript-eslint/visitor-keys": "7.0.1", + "@typescript-eslint/scope-manager": "7.0.2", + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/typescript-estree": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", "debug": "^4.3.4" }, "engines": { @@ -716,6 +716,81 @@ } } }, + "node_modules/@fltri/eslint-config/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz", + "integrity": "sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@fltri/eslint-config/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.2.tgz", + "integrity": "sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA==", + "dev": true, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@fltri/eslint-config/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz", + "integrity": "sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.0.2", + "@typescript-eslint/visitor-keys": "7.0.2", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@fltri/eslint-config/node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz", + "integrity": "sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.0.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@fltri/eslint-config/node_modules/@typescript-eslint/scope-manager": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", @@ -852,31 +927,6 @@ "balanced-match": "^1.0.0" } }, - "node_modules/@fltri/eslint-config/node_modules/eslint-plugin-jest": { - "version": "27.9.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.9.0.tgz", - "integrity": "sha512-QIT7FH7fNmd9n4se7FFKHbsLKGQiw885Ds6Y/sxKgCZ6natwCsXdgPOADnYVxN2QrRweF0FZWbJ6S7Rsn7llug==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "^5.10.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", - "eslint": "^7.0.0 || ^8.0.0", - "jest": "*" - }, - "peerDependenciesMeta": { - "@typescript-eslint/eslint-plugin": { - "optional": true - }, - "jest": { - "optional": true - } - } - }, "node_modules/@fltri/eslint-config/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -926,13 +976,13 @@ "dev": true }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.13", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", - "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", "dev": true, "dependencies": { - "@humanwhocodes/object-schema": "^2.0.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { @@ -952,9 +1002,9 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", - "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", + "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", "dev": true }, "node_modules/@isaacs/cliui": { @@ -3136,9 +3186,10 @@ "license": "MIT" }, "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "dev": true, - "license": "MIT" + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true }, "node_modules/@types/resolve": { "version": "1.20.2", @@ -3981,9 +4032,9 @@ } }, "node_modules/browserslist": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz", - "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "dev": true, "funding": [ { @@ -4000,8 +4051,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001565", - "electron-to-chromium": "^1.4.601", + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", "node-releases": "^2.0.14", "update-browserslist-db": "^1.0.13" }, @@ -4077,9 +4128,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001570", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001570.tgz", - "integrity": "sha512-+3e0ASu4sw1SWaoCtvPeyXp+5PsjigkSt8OXZbF9StH5pQWbxEjLAZE3n8Aup5udop1uRiKA7a4utUk/uoSpUw==", + "version": "1.0.30001589", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001589.tgz", + "integrity": "sha512-vNQWS6kI+q6sBlHbh71IIeC+sRwK2N3EDySc/updIGhIee2x5z00J4c1242/5/d6EpEMdOnk/m+6tuk4/tcsqg==", "dev": true, "funding": [ { @@ -4141,8 +4192,9 @@ }, "node_modules/clean-regexp": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", "dev": true, - "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -4247,6 +4299,19 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true }, + "node_modules/core-js-compat": { + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.36.0.tgz", + "integrity": "sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw==", + "dev": true, + "dependencies": { + "browserslist": "^4.22.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/create-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", @@ -4456,9 +4521,9 @@ "dev": true }, "node_modules/electron-to-chromium": { - "version": "1.4.615", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.615.tgz", - "integrity": "sha512-/bKPPcgZVUziECqDc+0HkT87+0zhaWSZHNXqF8FLd2lQcptpmUFwoCSWjCdOng9Gdq+afKArPdEg/0ZW461Eng==", + "version": "1.4.681", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.681.tgz", + "integrity": "sha512-1PpuqJUFWoXZ1E54m8bsLPVYwIVCRzvaL+n5cjigGga4z854abDnFRc+cTa2th4S79kyGqya/1xoR7h+Y5G5lg==", "dev": true }, "node_modules/emittery": { @@ -4632,16 +4697,16 @@ } }, "node_modules/eslint": { - "version": "8.56.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz", - "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.56.0", - "@humanwhocodes/config-array": "^0.11.13", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "@ungap/structured-clone": "^1.2.0", @@ -4882,12 +4947,13 @@ } }, "node_modules/eslint-plugin-mocha": { - "version": "10.1.0", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.3.0.tgz", + "integrity": "sha512-IWzbg2K6B1Q7h37Ih4zMyW+nhmw1JvUlHlbCUUUu6PfOOAUGCB0gxmvv7/U+TQQ6e8yHUv+q7KMdIIum4bx+PA==", "dev": true, - "license": "MIT", "dependencies": { "eslint-utils": "^3.0.0", - "rambda": "^7.1.0" + "rambda": "^7.4.0" }, "engines": { "node": ">=14.0.0" @@ -4965,19 +5031,21 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "48.0.1", + "version": "51.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz", + "integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==", "dev": true, - "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^3.8.0", + "@eslint/eslintrc": "^2.1.4", + "ci-info": "^4.0.0", "clean-regexp": "^1.0.0", + "core-js-compat": "^3.34.0", "esquery": "^1.5.0", "indent-string": "^4.0.0", "is-builtin-module": "^3.2.1", "jsesc": "^3.0.2", - "lodash": "^4.17.21", "pluralize": "^8.0.0", "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", @@ -4992,13 +5060,29 @@ "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" }, "peerDependencies": { - "eslint": ">=8.44.0" + "eslint": ">=8.56.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/ci-info": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "engines": { + "node": ">=8" } }, "node_modules/eslint-plugin-unicorn/node_modules/jsesc": { "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", "dev": true, - "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -5008,8 +5092,9 @@ }, "node_modules/eslint-plugin-unicorn/node_modules/lru-cache": { "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -5018,9 +5103,10 @@ } }, "node_modules/eslint-plugin-unicorn/node_modules/semver": { - "version": "7.5.4", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, - "license": "ISC", "dependencies": { "lru-cache": "^6.0.0" }, @@ -5033,8 +5119,9 @@ }, "node_modules/eslint-plugin-unicorn/node_modules/yallist": { "version": "4.0.0", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/eslint-scope": { "version": "7.2.2", @@ -5913,8 +6000,9 @@ }, "node_modules/indent-string": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8" } @@ -8386,8 +8474,9 @@ }, "node_modules/min-indent": { "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -8462,8 +8551,9 @@ }, "node_modules/normalize-package-data": { "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -8473,13 +8563,15 @@ }, "node_modules/normalize-package-data/node_modules/hosted-git-info": { "version": "2.8.9", - "dev": true, - "license": "ISC" + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true }, "node_modules/normalize-package-data/node_modules/semver": { "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", "dev": true, - "license": "ISC", "bin": { "semver": "bin/semver" } @@ -8895,8 +8987,9 @@ }, "node_modules/pluralize": { "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true, - "license": "MIT", "engines": { "node": ">=4" } @@ -9052,8 +9145,9 @@ }, "node_modules/rambda": { "version": "7.5.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true }, "node_modules/randombytes": { "version": "2.1.0", @@ -9071,8 +9165,9 @@ }, "node_modules/read-pkg": { "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", "dev": true, - "license": "MIT", "dependencies": { "@types/normalize-package-data": "^2.4.0", "normalize-package-data": "^2.5.0", @@ -9085,8 +9180,9 @@ }, "node_modules/read-pkg-up": { "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", "dev": true, - "license": "MIT", "dependencies": { "find-up": "^4.1.0", "read-pkg": "^5.2.0", @@ -9101,8 +9197,9 @@ }, "node_modules/read-pkg-up/node_modules/find-up": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, - "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -9113,8 +9210,9 @@ }, "node_modules/read-pkg-up/node_modules/locate-path": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, - "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -9124,8 +9222,9 @@ }, "node_modules/read-pkg-up/node_modules/p-limit": { "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, - "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -9138,8 +9237,9 @@ }, "node_modules/read-pkg-up/node_modules/p-locate": { "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, - "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -9149,16 +9249,18 @@ }, "node_modules/read-pkg-up/node_modules/type-fest": { "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } }, "node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -9185,8 +9287,9 @@ }, "node_modules/regexp-tree": { "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", "dev": true, - "license": "MIT", "bin": { "regexp-tree": "bin/regexp-tree" } @@ -9222,8 +9325,9 @@ }, "node_modules/regjsparser": { "version": "0.10.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", + "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", "dev": true, - "license": "BSD-2-Clause", "dependencies": { "jsesc": "~0.5.0" }, @@ -9233,6 +9337,8 @@ }, "node_modules/regjsparser/node_modules/jsesc": { "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", "dev": true, "bin": { "jsesc": "bin/jsesc" @@ -9616,31 +9722,35 @@ }, "node_modules/spdx-correct": { "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, - "license": "Apache-2.0", "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "dev": true, - "license": "CC-BY-3.0" + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true }, "node_modules/spdx-expression-parse": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", "dev": true, - "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.13", - "dev": true, - "license": "CC0-1.0" + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", + "dev": true }, "node_modules/sprintf-js": { "version": "1.0.3", @@ -9811,8 +9921,9 @@ }, "node_modules/strip-indent": { "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", "dev": true, - "license": "MIT", "dependencies": { "min-indent": "^1.0.0" }, @@ -10267,8 +10378,9 @@ }, "node_modules/validate-npm-package-license": { "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, - "license": "Apache-2.0", "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" diff --git a/package.json b/package.json index b2dba81..55534a0 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ }, "devDependencies": { "@babel/core": "7.23.9", - "@fltri/eslint-config": "1.2.3", + "@fltri/eslint-config": "1.2.4", "@material/mwc-ripple": "0.27.0", "@material/tab-bar": "14.0.0", "@rollup/plugin-babel": "6.0.4", @@ -62,7 +62,7 @@ "@types/hammerjs": "2.0.45", "@types/jest": "29.5.12", "@typescript-eslint/parser": "5.62.0", - "eslint": "8.56.0", + "eslint": "8.57.0", "eslint-import-resolver-typescript": "3.6.1", "eslint-plugin-import": "2.29.1", "eslint-plugin-jest": "27.9.0", diff --git a/src/cards/trash-card/container/cards.ts b/src/cards/trash-card/container/cards.ts new file mode 100644 index 0000000..91ee387 --- /dev/null +++ b/src/cards/trash-card/container/cards.ts @@ -0,0 +1,72 @@ +import { LitElement, css, html, nothing } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; + +import '../items/card'; + +import type { TrashCardConfig } from '../trash-card-config'; +import type { HassEntity } from 'home-assistant-js-websocket'; +import type { CalendarItem } from '../../../utils/calendarItem'; +import type { HomeAssistant } from '../../../utils/ha'; + +@customElement(`${TRASH_CARD_NAME}-cards-container`) +class Cards extends LitElement { + @state() private readonly items?: CalendarItem[]; + + @state() private readonly hass?: HomeAssistant; + + @state() private readonly config?: TrashCardConfig; + + public render () { + if (!this.config || !this.hass || !this.config.entity) { + return nothing; + } + + const entityId = this.config.entity; + const stateObj = this.hass.states[entityId] as HassEntity | undefined; + + if (!stateObj || !this.items || this.items.length === 0) { + return nothing; + } + + const itemsPerRow = this.config.items_per_row ?? 1; + + const cssStyleMap = styleMap({ + // eslint-disable-next-line @typescript-eslint/naming-convention + 'grid-template-columns': `repeat(${itemsPerRow}, calc(calc(100% - ${(itemsPerRow - 1) * 5}px) / ${itemsPerRow}))` + }); + + return html` +
+ ${this.items.map(item => html` + + + `)} +
+ `; + } + + public static get styles () { + return [ + css` + .card-container { + display: grid; + grid-auto-rows: 1fr; + grid-gap: var(--grid-card-gap, 2px); + } + trash-card-item-card { + grid-row: auto / span 1; + } + ` + ]; + } +} + +export { + Cards +}; diff --git a/src/cards/trash-card/container/chips.ts b/src/cards/trash-card/container/chips.ts new file mode 100644 index 0000000..32352db --- /dev/null +++ b/src/cards/trash-card/container/chips.ts @@ -0,0 +1,85 @@ +import { LitElement, css, html, nothing } from 'lit'; +import { defaultHaCardStyle } from '../../../utils/defaultHaCardStyle'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; + +import '../items/chip'; + +import type { HomeAssistant } from '../../../utils/ha'; +import type { TrashCardConfig } from '../trash-card-config'; +import type { HassEntity } from 'home-assistant-js-websocket'; +import type { CalendarItem } from '../../../utils/calendarItem'; + +@customElement(`${TRASH_CARD_NAME}-chips-container`) +class Chips extends LitElement { + @state() private readonly items?: CalendarItem[]; + + @state() private readonly hass?: HomeAssistant; + + @state() private readonly config?: TrashCardConfig; + + public render () { + if (!this.config || !this.hass || !this.config.entity) { + return nothing; + } + + const entityId = this.config.entity; + const stateObj = this.hass.states[entityId] as HassEntity | undefined; + + if (!stateObj || !this.items || this.items.length === 0) { + return nothing; + } + + return html` +
+ ${this.items.map(item => html` + + + `)} +
+ `; + } + + public static get styles () { + return [ + defaultHaCardStyle, + css` + .chip-container { + display: flex; + flex-direction: row; + align-items: flex-start; + justify-content: flex-start; + flex-wrap: wrap; + margin-bottom: calc(-1 * var(--chip-spacing)); + } + .chip-container.align-end { + justify-content: flex-end; + } + .chip-container.align-center { + justify-content: center; + } + .chip-container.align-justify { + justify-content: space-between; + } + .chip-container * { + margin-bottom: var(--chip-spacing); + } + .chip-container *:not(:last-child) { + margin-right: var(--chip-spacing); + } + .chip-container[rtl] *:not(:last-child) { + margin-right: initial; + margin-left: var(--chip-spacing); + } + ` + ]; + } +} + +export { + Chips +}; diff --git a/src/cards/trash-card/container/debug.ts b/src/cards/trash-card/container/debug.ts new file mode 100644 index 0000000..5a44fba --- /dev/null +++ b/src/cards/trash-card/container/debug.ts @@ -0,0 +1,69 @@ +import { LitElement, css, html, nothing } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; +import { defaultHaCardStyle } from '../../../utils/defaultHaCardStyle'; + +import '../elements/title'; +import '../items/logrow'; + +import type { Debugger } from '../../../utils/debugger'; + +@customElement(`${TRASH_CARD_NAME}-debug-container`) +class Debug extends LitElement { + @state() private readonly debugger?: Debugger; + + protected copyDebugLogToClipboard (ev: CustomEvent): void { + ev.stopPropagation(); + // eslint-disable-next-line @typescript-eslint/no-floating-promises + navigator.clipboard.writeText(JSON.stringify(this.debugger?.getLogs() ?? {})). + then(() => { + // eslint-disable-next-line no-alert + alert('Debug data copied to clipboard'); + }); + } + + public render () { + if (!this.debugger) { + return nothing; + } + + return html` + + DEBUG LOG + + + + + +
+ ${this.debugger.getLogs().map(item => html` + + `)} +
+
`; + } + + public static get styles () { + return [ + defaultHaCardStyle, + css` + .debug-container { + margin-bottom: 5px; + border: rgb(var(--rgb-pink)) dotted 1px; + opacity: 0.7; + } + ` + ]; + } +} + +export { + Debug +}; diff --git a/src/cards/trash-card/container/index.ts b/src/cards/trash-card/container/index.ts new file mode 100644 index 0000000..5ce981d --- /dev/null +++ b/src/cards/trash-card/container/index.ts @@ -0,0 +1,3 @@ +import './cards'; +import './chips'; +import './debug'; diff --git a/src/cards/trash-card/elements/base.ts b/src/cards/trash-card/elements/base.ts deleted file mode 100644 index f66b70a..0000000 --- a/src/cards/trash-card/elements/base.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { HomeAssistant } from '../../../utils/ha'; -import type { TrashCardConfig } from '../trash-card-config'; - -class Base { - protected readonly config?: TrashCardConfig; - - public hass?: HomeAssistant; - - public constructor (config?: TrashCardConfig, hass?: HomeAssistant) { - this.config = config; - this.hass = hass; - } -} - -export { - Base -}; diff --git a/src/cards/trash-card/elements/card.ts b/src/cards/trash-card/elements/card.ts deleted file mode 100644 index 624af5b..0000000 --- a/src/cards/trash-card/elements/card.ts +++ /dev/null @@ -1,135 +0,0 @@ -import { Base } from './base'; -import { actionHandler, computeRTL, hasAction } from 'lovelace-mushroom/src/ha'; -import { css, html, nothing } from 'lit'; -import { computeAppearance } from 'lovelace-mushroom/src/utils/appearance'; -import { computeRgbColor } from 'lovelace-mushroom/src/utils/colors'; -import { classMap } from 'lit/directives/class-map.js'; -import { styleMap } from 'lit/directives/style-map.js'; -import { getDateString } from '../../../utils/getDateString'; - -import type { CalendarItem } from '../../../utils/calendarItem'; -import type { HassEntity } from 'home-assistant-js-websocket'; - -class Card extends Base { - public renderItems (items?: CalendarItem[]) { - if (!this.config || !this.hass || !this.config.entity) { - return nothing; - } - - const entityId = this.config.entity; - const stateObj = this.hass.states[entityId] as HassEntity | undefined; - - if (!stateObj || !items || items.length === 0) { - return nothing; - } - - const itemsPerRow = this.config.items_per_row ?? 1; - - const cssStyleMap = styleMap({ - // eslint-disable-next-line @typescript-eslint/naming-convention - 'grid-template-columns': `repeat(${itemsPerRow}, calc(calc(100% - ${(itemsPerRow - 1) * 5}px) / ${itemsPerRow}))` - }); - - return html` -
- ${items.map(item => this.renderItem(item))} -
- `; - } - - public renderItem (item: CalendarItem) { - if (!this.config || !this.hass || !this.config.entity) { - return nothing; - } - - const entityId = this.config.entity; - const stateObj = this.hass.states[entityId] as HassEntity | undefined; - - if (!stateObj) { - return nothing; - } - - const appearance = computeAppearance(this.config); - - const rtl = computeRTL(this.hass); - - const { label } = item; - const color = item.color ?? 'disabled'; - - const backgroundStyle = {}; - - if (this.config.color_mode !== 'icon' && color !== 'disabled') { - const rgbColor = computeRgbColor(color); - - backgroundStyle['background-color'] = `rgba(${rgbColor}, 0.5)`; - } - - const secondary = getDateString(item, this.config.hide_time_range ?? false, this.config, this.hass); - - const cssClassMap = classMap({ - // eslint-disable-next-line @typescript-eslint/naming-convention - 'fill-container': appearance.fill_container, - fullsize: this.config.full_size === true - }); - - return html` - - - - ${this.renderIcon(item)} - - - - - `; - } - - // eslint-disable-next-line class-methods-use-this - protected renderIcon (item: CalendarItem) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - const icon = item.icon ?? 'mdi:delete-outline'; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - const iconColor = item.color ?? 'disabled'; - - const iconStyle = { - // eslint-disable-next-line @typescript-eslint/naming-convention - '--icon-color': `rgba(var(--white-color), 0.5)` - }; - - if (this.config?.color_mode === 'icon') { - const rgbColor = computeRgbColor(iconColor); - - iconStyle['--icon-color'] = `rgba(${rgbColor}, 1)`; - } - - return html``; - } - - public static getStyles () { - return [ - css` - .card-container ha-state-icon { - color: var(--icon-color); - } - ` - ]; - } -} - -export { - Card -}; diff --git a/src/cards/trash-card/elements/chip.ts b/src/cards/trash-card/elements/chip.ts deleted file mode 100644 index 156cb19..0000000 --- a/src/cards/trash-card/elements/chip.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { Base } from './base'; -import { computeRTL } from 'lovelace-mushroom/src/ha'; -import { css, html, nothing } from 'lit'; -import { computeRgbColor } from 'lovelace-mushroom/src/utils/colors'; -import { styleMap } from 'lit/directives/style-map.js'; -import { getDateString } from '../../../utils/getDateString'; - -import type { CalendarItem } from '../../../utils/calendarItem'; -import type { HassEntity } from 'home-assistant-js-websocket'; - -class Chip extends Base { - public renderItems (items?: CalendarItem[]) { - if (!this.config || !this.hass || !this.config.entity) { - return nothing; - } - - const entityId = this.config.entity; - const stateObj = this.hass.states[entityId] as HassEntity | undefined; - - if (!stateObj || !items || items.length === 0) { - return nothing; - } - - const itemsPerRow = this.config.items_per_row ?? 1; - - const cssStyleMap = styleMap({ - // eslint-disable-next-line @typescript-eslint/naming-convention - 'grid-template-columns': `repeat(${itemsPerRow}, calc(calc(100% - ${(itemsPerRow - 1) * 5}px) / ${itemsPerRow}))` - }); - - return html` -
- ${items.map(item => this.renderItem(item))} -
- `; - } - - public renderItem (item: CalendarItem) { - if (!this.config || !this.hass || !this.config.entity) { - return nothing; - } - - const entityId = this.config.entity; - const stateObj = this.hass.states[entityId] as HassEntity | undefined; - - if (!stateObj) { - return nothing; - } - - const rtl = computeRTL(this.hass); - - const color = item.color ?? 'disabled'; - - const backgroundStyle = {}; - - if (this.config.color_mode !== 'icon' && color !== 'disabled') { - const rgbColor = computeRgbColor(color); - - backgroundStyle['--chip-background'] = `rgba(${rgbColor}, 0.5)`; - } - - const content = getDateString(item, this.config.hide_time_range ?? false, this.config, this.hass); - - return html` - - ${this.renderIcon(item)} - ${content} - - `; - } - - // eslint-disable-next-line class-methods-use-this - protected renderIcon (item: CalendarItem) { - const icon = item.icon ?? 'mdi:delete-outline'; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - const iconColor = item.color ?? 'disabled'; - - const iconStyle = {}; - - if (this.config?.color_mode === 'icon') { - const rgbColor = computeRgbColor(iconColor); - - iconStyle['--icon-color'] = `rgba(${rgbColor}, 1)`; - } - - return html``; - } - - public static getStyles () { - return [ - css` - .chip-container ha-card { - background: none; - box-shadow: none; - border-radius: 0; - border: none; - } - .chip-container { - display: flex; - flex-direction: row; - align-items: flex-start; - justify-content: flex-start; - flex-wrap: wrap; - margin-bottom: calc(-1 * var(--chip-spacing)); - } - .chip-container.align-end { - justify-content: flex-end; - } - .chip-container.align-center { - justify-content: center; - } - .chip-container.align-justify { - justify-content: space-between; - } - .chip-container * { - margin-bottom: var(--chip-spacing); - } - .chip-container *:not(:last-child) { - margin-right: var(--chip-spacing); - } - .chip-container[rtl] *:not(:last-child) { - margin-right: initial; - margin-left: var(--chip-spacing); - } - - mushroom-chip { - cursor: pointer; - } - .chip-container mushroom-chip ha-state-icon { - color: var(--icon-color); - margin-bottom: 0px; - } - .chip-container mushroom-chip span { - margin-bottom: 0px; - } - ` - ]; - } -} - -export { - Chip -}; diff --git a/src/cards/trash-card/elements/debug.ts b/src/cards/trash-card/elements/debug.ts deleted file mode 100644 index b95ebfa..0000000 --- a/src/cards/trash-card/elements/debug.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { LitElement, css, html, nothing } from 'lit'; -import { customElement, state } from 'lit/decorators.js'; -import { TRASH_CARD_NAME } from '../const'; -import { defaultHaCardStyle } from '../../../utils/defaultHaCardStyle'; - -import type { Debugger } from '../../../utils/debugger'; - -@customElement(`${TRASH_CARD_NAME}-debug-card`) -class Debug extends LitElement { - @state() private readonly debugger?: Debugger; - - protected copyDebugLogToClipboard (ev: CustomEvent): void { - ev.stopPropagation(); - // eslint-disable-next-line @typescript-eslint/no-floating-promises - navigator.clipboard.writeText(JSON.stringify(this.debugger?.getLogs() ?? {})). - then(() => { - // eslint-disable-next-line no-alert - alert('Debug data copied to clipboard'); - }); - } - - public render () { - if (!this.debugger) { - return nothing; - } - - return html` -
-
-

DEBUG LOG

- - - -
-
- ${this.debugger.getLogs().map(({ message, data }) => html` - -
- ${message} -
-
- ${JSON.stringify(data, undefined, 2)} -
- - `)} -
-
-
`; - } - - public static get styles () { - return [ - defaultHaCardStyle, - css` - .debug-container { - word-wrap: break-word; - word-break: break-all; - margin-bottom: 5px; - border: rgb(var(--rgb-pink)) dotted 1px; - opacity: 0.7; - } - .debug-container .title { - display: grid; - color: rgb(var(--rgb-pink)); - grid-template-columns: auto 50px - } - .debug-container .debug-content { - overflow-y: scroll; - } - .debug-container .debug-content code { - margin-top: 10px; - margin-bottom: 10px; - white-space: pre-wrap; - font-size: 12px; - } - .debug-panel .header { - padding-left: 8px; - } - .debug-panel .content { - padding: 8px; - } - ` - ]; - } -} - -export { - Debug -}; diff --git a/src/cards/trash-card/elements/icon.ts b/src/cards/trash-card/elements/icon.ts new file mode 100644 index 0000000..2a29946 --- /dev/null +++ b/src/cards/trash-card/elements/icon.ts @@ -0,0 +1,45 @@ +import { LitElement, css, html, nothing } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; + +import type { HomeAssistant } from '../../../utils/ha'; +import type { CardStyleConfig } from '../trash-card-config'; +import type { CalendarItem } from '../../../utils/calendarItem'; + +@customElement(`${TRASH_CARD_NAME}-element-icon`) +class ItemCard extends LitElement { + @state() private readonly item?: CalendarItem; + + @state() private readonly hass?: HomeAssistant; + + @state() private readonly config?: CardStyleConfig; + + public render () { + if (!this.item || !this.config) { + return nothing; + } + + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + const icon = this.item.icon ?? 'mdi:delete-outline'; + + return html``; + } + + public static get styles () { + return [ + css` + ha-state-icon { + color: var(--trash-card-icon-color); + } + ` + ]; + } +} + +export { + ItemCard +}; diff --git a/src/cards/trash-card/elements/title.ts b/src/cards/trash-card/elements/title.ts new file mode 100644 index 0000000..9bb8cb8 --- /dev/null +++ b/src/cards/trash-card/elements/title.ts @@ -0,0 +1,31 @@ +import { LitElement, css, html } from 'lit'; +import { customElement } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; + +@customElement(`${TRASH_CARD_NAME}-title`) +class Debug extends LitElement { + // eslint-disable-next-line class-methods-use-this + public render () { + return html` +
+

+
+
`; + } + + public static get styles () { + return [ + css` + .title { + display: grid; + color: rgb(var(--rgb-pink)); + grid-template-columns: auto 50px + } + ` + ]; + } +} + +export { + Debug +}; diff --git a/src/cards/trash-card/formSchemas.ts b/src/cards/trash-card/formSchemas.ts index eff7afb..db160a2 100644 --- a/src/cards/trash-card/formSchemas.ts +++ b/src/cards/trash-card/formSchemas.ts @@ -4,9 +4,10 @@ import type { TrashCardConfig } from './trash-card-config'; import type { HaFormSchema } from '../../utils/form/ha-form'; import type setupCustomlocalize from '../../localize'; -const getPatternOthersSchema = () => [ +const getPatternOthersSchema = (localize: (key: string, ...args: any) => string) => [ { name: 'icon', + label: localize(`ui.panel.lovelace.editor.card.generic.icon`), selector: { icon: {} }, @@ -14,11 +15,12 @@ const getPatternOthersSchema = () => [ }, { name: 'color', + label: localize(`ui.panel.lovelace.editor.card.tile.color`), selector: { ui_color: {}} } ]; -const getPatternSchema = (customLocalize: ReturnType) => [ +const getPatternSchema = (customLocalize: ReturnType, localize: (key: string, ...args: any) => string) => [ { label: customLocalize(`editor.card.trash.pattern.fields.label`), name: 'label', @@ -26,7 +28,7 @@ const getPatternSchema = (customLocalize: ReturnType text: {} } }, - ...getPatternOthersSchema(), + ...getPatternOthersSchema(localize), { label: customLocalize(`editor.card.trash.pattern.fields.pattern`), name: 'pattern', @@ -36,7 +38,7 @@ const getPatternSchema = (customLocalize: ReturnType } ]; -const getSchema = (customLocalize: ReturnType, currentValues: TrashCardConfig) => { +const getSchema = (customLocalize: ReturnType, currentValues: TrashCardConfig, localize: (key: string, ...args: any) => string) => { const settings: HaFormSchema[] = [ { @@ -44,8 +46,14 @@ const getSchema = (customLocalize: ReturnType, curre name: '', schema: [ - { name: 'filter_events', selector: { boolean: {}}}, - { name: 'drop_todayevents_from', + { + name: 'filter_events', + label: customLocalize(`editor.card.generic.filter_events`), + selector: { boolean: {}} + }, + { + name: 'drop_todayevents_from', + label: customLocalize(`editor.card.generic.drop_todayevents_from`), default: { hours: 11, minutes: 0, @@ -54,9 +62,11 @@ const getSchema = (customLocalize: ReturnType, curre selector: { time: { } - }}, + } + }, { name: 'next_days', + label: customLocalize(`editor.card.generic.next_days`), selector: { number: { min: 1, @@ -115,9 +125,21 @@ const getSchema = (customLocalize: ReturnType, curre } } }, - { name: 'hide_time_range', selector: { boolean: { }}}, - { name: 'use_summary', selector: { boolean: {}}}, - { name: 'event_grouping', selector: { boolean: { default: true }}}, + { + name: 'hide_time_range', + label: customLocalize(`editor.card.generic.hide_time_range`), + selector: { boolean: { }} + }, + { + name: 'use_summary', + label: customLocalize(`editor.card.generic.use_summary`), + selector: { boolean: {}} + }, + { + name: 'event_grouping', + label: customLocalize(`editor.card.generic.event_grouping`), + selector: { boolean: { default: true }} + }, { name: 'color_mode', label: customLocalize(`editor.form.color_mode.title`), @@ -138,7 +160,11 @@ const getSchema = (customLocalize: ReturnType, curre type: 'grid', name: '', schema: [ - { name: 'layout', selector: { mush_layout: {}}} + { + name: 'layout', + label: customLocalize(`editor.card.generic.layout`), + selector: { mush_layout: {}} + } ] }, { @@ -146,14 +172,21 @@ const getSchema = (customLocalize: ReturnType, curre name: '', schema: [ - { name: 'full_size', selector: { boolean: {}}}, - { name: 'items_per_row', + { + name: 'full_size', + label: customLocalize(`editor.card.generic.full_size`), + selector: { boolean: {}} + }, + { + name: 'items_per_row', + label: localize(`ui.panel.lovelace.editor.card.grid.columns`), selector: { number: { min: 1, max: 6, step: 1, mode: 'box' - }}} + }} + } ] }] as HaFormSchema[] : [] as HaFormSchema[] diff --git a/src/cards/trash-card/items/card.ts b/src/cards/trash-card/items/card.ts new file mode 100644 index 0000000..b75e975 --- /dev/null +++ b/src/cards/trash-card/items/card.ts @@ -0,0 +1,86 @@ +import { computeRTL } from 'lovelace-mushroom/src/ha'; +import { LitElement, css, html, nothing } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; +import { getDateString } from '../../../utils/getDateString'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; +import { defaultHaCardStyle } from '../../../utils/defaultHaCardStyle'; +import { getColoredStyle } from '../../../utils/getColoredStyle'; + +import '../elements/icon'; + +import type { CardStyleConfig } from '../trash-card-config'; +import type { CalendarItem } from '../../../utils/calendarItem'; +import type { HomeAssistant } from '../../../utils/ha'; + +@customElement(`${TRASH_CARD_NAME}-item-card`) +class ItemCard extends LitElement { + @state() private readonly item?: CalendarItem; + + @state() private readonly hass?: HomeAssistant; + + @state() private readonly config?: CardStyleConfig; + + public render () { + if (!this.hass || !this.item || !this.config) { + return nothing; + } + + // eslint-disable-next-line prefer-destructuring + const item = this.item; + + const rtl = computeRTL(this.hass); + + const { color_mode, hide_time_range, day_style, layout } = this.config; + + const { label } = item; + + const style = { + ...getColoredStyle(color_mode, item) + }; + + const secondary = getDateString(item, hide_time_range ?? false, day_style, this.hass); + + return html` + + + + + + + + + `; + } + + public static get styles () { + return [ + defaultHaCardStyle, + css` + ha-card { + justify-content: space-between; + height: 100%; + background: var(--trash-card-background, + var(--ha-card-background, + var(--card-background-color, #fff) + ) + ); + } + ` + ]; + } +} + +export { + ItemCard +}; diff --git a/src/cards/trash-card/items/chip.ts b/src/cards/trash-card/items/chip.ts new file mode 100644 index 0000000..2da3fcf --- /dev/null +++ b/src/cards/trash-card/items/chip.ts @@ -0,0 +1,73 @@ +import { computeRTL } from 'lovelace-mushroom/src/ha'; +import { LitElement, css, html, nothing } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; +import { getDateString } from '../../../utils/getDateString'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; +import { getColoredStyle } from '../../../utils/getColoredStyle'; + +import '../elements/icon'; + +import type { CardStyleConfig } from '../trash-card-config'; +import type { CalendarItem } from '../../../utils/calendarItem'; +import type { HomeAssistant } from '../../../utils/ha'; + +@customElement(`${TRASH_CARD_NAME}-item-chip`) +class ItemChip extends LitElement { + @state() private readonly item?: CalendarItem; + + @state() private readonly hass?: HomeAssistant; + + @state() private readonly config?: CardStyleConfig; + + public render () { + if (!this.hass || !this.item || !this.config) { + return nothing; + } + + // eslint-disable-next-line prefer-destructuring + const item = this.item; + + const rtl = computeRTL(this.hass); + + const { color_mode, hide_time_range, day_style } = this.config; + + const style = { + ...getColoredStyle(color_mode, item) + }; + + const content = getDateString(item, hide_time_range ?? false, day_style, this.hass); + + return html` + + + ${content ? html`${content}` : nothing} + `; + } + + public static get styles () { + return [ + css` + mushroom-chip { + --chip-background: var(--trash-card-background, + var(--ha-card-background, + var(--card-background-color, #fff) + ) + ); + } + ` + ]; + } +} + +export { + ItemChip +}; diff --git a/src/cards/trash-card/items/logrow.ts b/src/cards/trash-card/items/logrow.ts new file mode 100644 index 0000000..c84d4b4 --- /dev/null +++ b/src/cards/trash-card/items/logrow.ts @@ -0,0 +1,48 @@ +import { LitElement, css, html, nothing } from 'lit'; +import { customElement, state } from 'lit/decorators.js'; +import { TRASH_CARD_NAME } from '../const'; + +import type { DebuggerData } from '../../../utils/debugger'; + +@customElement(`${TRASH_CARD_NAME}-logrow`) +class LogRow extends LitElement { + @state() private readonly item?: DebuggerData; + + public render () { + if (!this.item) { + return nothing; + } + + // eslint-disable-next-line prefer-destructuring + const { message, data } = this.item; + + return html` + +
+ ${message} +
+ ${JSON.stringify(data, undefined, 2)} + `; + } + + public static get styles () { + return [ + css` + .container.expanded { + padding: 8px; + } + code { + display: block; + margin-top: 10px; + margin-bottom: 10px; + white-space: pre-wrap; + font-size: 12px; + } + ` + ]; + } +} + +export { + LogRow +}; diff --git a/src/cards/trash-card/trash-card-config.ts b/src/cards/trash-card/trash-card-config.ts index 5664e29..80fa7e2 100644 --- a/src/cards/trash-card/trash-card-config.ts +++ b/src/cards/trash-card/trash-card-config.ts @@ -46,7 +46,8 @@ type EntityWithOutIcon = Omit; debug?: boolean; }; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment, @typescript-eslint/prefer-ts-expect-error + type CardStyleConfig = Pick; + const entityCardConfigStruct = assign( defaultConfigStruct, object({ @@ -121,6 +122,7 @@ export { }; export type { - TrashCardConfig + TrashCardConfig, + CardStyleConfig }; diff --git a/src/cards/trash-card/trash-card-editor.ts b/src/cards/trash-card/trash-card-editor.ts index d1c64d3..3b553de 100644 --- a/src/cards/trash-card/trash-card-editor.ts +++ b/src/cards/trash-card/trash-card-editor.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/unbound-method */ import { assert } from 'superstruct'; import { computeDarkMode } from '../../utils/computeDarkMode'; -import { GENERIC_LABELS } from 'lovelace-mushroom/src/utils/form/generic-fields'; import memoizeOne from 'memoize-one'; import setupCustomlocalize from '../../localize'; import { TRASH_CARD_EDITOR_NAME } from './const'; @@ -11,6 +10,8 @@ import { entityCardConfigStruct } from './trash-card-config'; import { getPatternOthersSchema, getPatternSchema, getSchema } from './formSchemas'; import { fireEvent } from '../../utils/fireEvent'; +import './trash-card-pattern-editor'; + import type { HASSDomEvent, LovelaceCardEditor } from 'lovelace-mushroom/src/ha'; import type { TrashCardConfig } from './trash-card-config'; import type { CSSResultGroup, PropertyValues } from 'lit'; @@ -18,8 +19,6 @@ import type { HomeAssistant } from '../../utils/ha'; import type { SubElementEditorConfig } from './trash-card-pattern-editor'; import type { HaFormSchema } from '../../utils/form/ha-form'; -import './trash-card-pattern-editor'; - declare global { // eslint-disable-next-line @typescript-eslint/naming-convention interface HASSDomEvents { @@ -30,28 +29,12 @@ declare global { } } -const OTHER_LABELS = new Set([ - 'next_days', - 'filter_events', - 'full_size', - 'drop_todayevents_from', - 'use_summary', - 'day_style', - 'card_style', - 'hide_time_range', - 'event_grouping' -]); - @customElement(TRASH_CARD_EDITOR_NAME) class TrashCardEditor extends LitElement implements LovelaceCardEditor { @property({ attribute: false }) public hass?: HomeAssistant; - // eslint-disable-next-line @typescript-eslint/naming-convention @state() private config?: TrashCardConfig; - @property() private readonly selectedTabIndex = 0; - - // eslint-disable-next-line @typescript-eslint/naming-convention @state() private subElementEditorConfig?: SubElementEditorConfig; @state() private readonly schema = memoizeOne(getSchema); @@ -60,11 +43,8 @@ class TrashCardEditor extends LitElement implements LovelaceCardEditor { assert(config, entityCardConfigStruct); this.config = { - // eslint-disable-next-line @typescript-eslint/naming-convention event_grouping: true, - // eslint-disable-next-line @typescript-eslint/naming-convention drop_todayevents_from: '10:00:00', - // eslint-disable-next-line @typescript-eslint/naming-convention next_days: 2, settings: { organic: { @@ -84,7 +64,6 @@ class TrashCardEditor extends LitElement implements LovelaceCardEditor { }, ...config.settings }, - // eslint-disable-next-line @typescript-eslint/naming-convention day_style: 'default', card_style: 'card', color_mode: 'background', @@ -108,39 +87,18 @@ class TrashCardEditor extends LitElement implements LovelaceCardEditor { private readonly computeLabel = (schema: HaFormSchema) => { if (!this.hass) { - return schema.name; - } - - const customLocalize = setupCustomlocalize(this.hass); - - if (schema.label) { return schema.label; } - if (GENERIC_LABELS.includes(schema.name) || OTHER_LABELS.has(schema.name)) { - return customLocalize(`editor.card.generic.${schema.name}`); - } - - if (schema.name === 'items_per_row') { - return this.hass.localize('ui.panel.lovelace.editor.card.grid.columns'); - } - if (schema.name === 'icon') { - return this.hass.localize('ui.panel.lovelace.editor.card.generic.icon'); - } - if (schema.name === 'color') { - return this.hass.localize('ui.panel.lovelace.editor.card.tile.color'); - } - - return this.hass.localize(`ui.panel.lovelace.editor.card.generic.${schema.name}`); + return schema.label ?? ''; }; - // eslint-disable-next-line class-methods-use-this private readonly computeHelper = (schema: HaFormSchema) => { - if (schema.helper) { - return schema.helper; + if (!this.hass) { + return schema.name; } - return ''; + return schema.helper ?? ''; }; private editDetailElement (ev: HASSDomEvent<{ subElementConfig: SubElementEditorConfig }>): void { @@ -156,8 +114,8 @@ class TrashCardEditor extends LitElement implements LovelaceCardEditor { if (this.subElementEditorConfig) { const patternSchema = this.subElementEditorConfig.key === 'others' ? - getPatternOthersSchema() : - getPatternSchema(customLocalize); + getPatternOthersSchema(this.hass.localize) : + getPatternSchema(customLocalize, this.hass.localize); return html`
@@ -228,7 +186,7 @@ class TrashCardEditor extends LitElement implements LovelaceCardEditor { } const customLocalize = setupCustomlocalize(this.hass); - const schema = this.schema(customLocalize, this.config); + const schema = this.schema(customLocalize, this.config, this.hass.localize); return html` { + public static async getConfigElement () { await import('./trash-card-editor'); - return document.createElement(TRASH_CARD_EDITOR_NAME) as LovelaceCardEditor; + return document.createElement(TRASH_CARD_EDITOR_NAME); } public static async getStubConfig (hass: HomeAssistant): Promise> { @@ -61,11 +52,6 @@ export class TrashCard extends LitElement implements LovelaceCard { private lastChanged?: Date; - // eslint-disable-next-line class-methods-use-this - public getCardSize (): number | Promise { - return 1; - } - public setConfig (config: TrashCardConfig): void { this.config = { // eslint-disable-next-line @typescript-eslint/naming-convention @@ -91,7 +77,7 @@ export class TrashCard extends LitElement implements LovelaceCard { } protected fetchCurrentTrashData () { - if (!this.hass) { + if (!this.hass || !this.config || !this.debugger) { return; } @@ -100,60 +86,18 @@ export class TrashCard extends LitElement implements LovelaceCard { const start = getDayFromDate(this.startDate); const end = getDayFromDate(this.endDate); - const uri = `calendars/${this.config?.entity}?start=${start}&end=${end}`; - - const dropAfter = isTodayAfter(new Date(), this.config!.drop_todayevents_from ?? '10:00:00'); + const dropAfter = isTodayAfter(new Date(), this.config.drop_todayevents_from ?? '10:00:00'); + const timezoneOffset = getTimeZoneOffset(); // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.hass. - callApi('GET', uri). - then((response): CalendarEvent[] => { - if (this.debugger) { - this.debugger.reset(); - this.debugger.log(`timezone`, getTimeZoneOffset()); - this.debugger.log(`calendar data`, response); - } - - return normaliseEvents(response); - }). - then((data: CalendarEvent[]): CalendarEvent[] => { - const now = new Date(); - - if (this.debugger) { - this.debugger.log(`normaliseEvents`, data); - this.debugger.log(`dropAfter`, dropAfter); - this.debugger.log(`now`, now); - } - - return findActiveEvents(data, { - config: { - settings: this.config!.settings!, - // eslint-disable-next-line @typescript-eslint/naming-convention - filter_events: this.config!.filter_events - }, - dropAfter, - now - }); - }). - then((data: CalendarEvent[]): CalendarItem[] => { - if (this.debugger) { - this.debugger.log(`activeElements`, data); - } - - return eventsToItems(data, { - settings: this.config!.settings!, - useSummary: Boolean(this.config!.use_summary) - }); - }). - then((data: CalendarItem[]): CalendarItem[] => { - if (this.debugger) { - this.debugger.log(`eventsToItems`, data); - } - - return !this.config!.event_grouping ? - data : - filterDuplicatedItems(data); - }). + getCalendarData( + this.hass, + this.config.entity!, + { start, end, dropAfter }, + this.debugger, + this.config, + timezoneOffset + ). then((data: CalendarItem[]) => { this.currentItems = data; this.lastChanged = new Date(); @@ -168,7 +112,9 @@ export class TrashCard extends LitElement implements LovelaceCard { if (changedProps.has('currentItems')) { return true; } + changedProps.delete('currentItems'); + if (!this.lastChanged || changedProps.has('config') || Date.now() - this.lastChanged.getTime() > this.getRefreshRate()) { this.fetchCurrentTrashData(); } @@ -177,47 +123,26 @@ export class TrashCard extends LitElement implements LovelaceCard { } protected render () { - if (!this.config || !this.hass || !this.config.entity) { + if (!this.config || !this.hass) { return nothing; } - const entityId = this.config.entity; - const stateObj = this.hass.states[entityId] as HassEntity | undefined; - const items = this.currentItems; - - if (!stateObj || !items || items.length === 0) { - return this.config.debug ? html`` : nothing; + if (!this.currentItems || this.currentItems.length === 0) { + return this.config.debug ? html`` : nothing; } - const elementInstance = this.config.card_style === 'chip' ? - new Chip(this.config, this.hass) : - new Card(this.config, this.hass); - return html` - ${this.config.debug ? html`` : ``} - ${elementInstance.renderItems(items)} - `; - } - - public static get styles (): CSSResultGroup { - return [ - defaultHaCardStyle, - ...Chip.getStyles(), - ...Card.getStyles(), - css` - div { - display: grid; - grid-gap:5px; - } - ha-card.fullsize { - margin-left: -17px; - margin-right: -17px; - margin-top: -4px; - } - mushroom-state-item { - cursor: pointer; - } - ` - ]; + ${this.config.debug ? html`` : ``} + ${this.config.card_style === 'chip' ? + html`` : + html``}`; } } diff --git a/src/translations/fr.json b/src/translations/fr.json index 991de5b..b4a78f1 100644 --- a/src/translations/fr.json +++ b/src/translations/fr.json @@ -10,21 +10,21 @@ "title": "Afficher l'heure de l'événement en tant que", "values": { "default": "Date", - "compteur": "jours jusqu'à" + "counter": "jours jusqu'à" } }, "card_style": { "title": "Représenter comme", "values": { - "card" : "carte standard", - "chip" : "carte à puce" + "card": "carte standard", + "chip": "carte à puce" } }, "color_mode": { - "title" : "Appliquer une couleur à", - "values" : { - "background" : "Contexte", - "icon" : "Icône" + "title": "Appliquer une couleur à", + "values": { + "background": "Contexte", + "icon": "Icône" } }, "layout_picker": { diff --git a/src/translations/hu.json b/src/translations/hu.json index 00b449c..2f47990 100644 --- a/src/translations/hu.json +++ b/src/translations/hu.json @@ -63,7 +63,7 @@ "edit": "szerkeszt", "delete": "töröl", "type": { - "organic": "komposztálható", + "organic": "Komposztálható", "paper": "Papír", "recycle": "Újrahasznosítható", "waste": "Szemét", diff --git a/src/utils/debugger.ts b/src/utils/debugger.ts index 1f38f82..8a7e07a 100644 --- a/src/utils/debugger.ts +++ b/src/utils/debugger.ts @@ -1,5 +1,10 @@ +interface DebuggerData { + message: string; + data: any; +} + class Debugger { - protected data: { message: string; data: any }[] = []; + protected data: DebuggerData[] = []; public reset () { this.data = []; @@ -16,6 +21,11 @@ class Debugger { return this.data; } } + export { Debugger }; + +export type { + DebuggerData +}; diff --git a/src/utils/getCalendarData.ts b/src/utils/getCalendarData.ts new file mode 100644 index 0000000..971f932 --- /dev/null +++ b/src/utils/getCalendarData.ts @@ -0,0 +1,61 @@ +import { eventsToItems } from './eventsToItems'; +import { findActiveEvents } from './findActiveEvents'; +import { normaliseEvents } from './normaliseEvents'; +import { filterDuplicatedItems } from './filterDuplicatedItems'; + +import type { Debugger } from './debugger'; +import type { HomeAssistant } from './ha'; +import type { RawCalendarEvent } from './calendarEvents'; +import type { TrashCardConfig } from '../cards/trash-card/trash-card-config'; + +const getCalendarData = async ( + hass: HomeAssistant, + calendar: string, + { start, end, dropAfter }: { start: string; end: string; dropAfter: boolean }, + debuggerInstance: Debugger, + config: TrashCardConfig, + timezoneOffset: string +) => { + const uri = `calendars/${calendar}?start=${start}&end=${end}`; + + const rawCalendarEvents = await hass.callApi('GET', uri); + + debuggerInstance.reset(); + debuggerInstance.log(`timezone`, timezoneOffset); + debuggerInstance.log(`calendar data`, rawCalendarEvents); + + const normalisedEvents = normaliseEvents(rawCalendarEvents, timezoneOffset); + + const now = new Date(); + + debuggerInstance.log(`normaliseEvents`, normalisedEvents); + debuggerInstance.log(`dropAfter`, dropAfter); + debuggerInstance.log(`now`, now); + + const activeEvents = findActiveEvents(normalisedEvents, { + config: { + settings: config.settings!, + // eslint-disable-next-line @typescript-eslint/naming-convention + filter_events: config.filter_events + }, + dropAfter, + now + }); + + debuggerInstance.log(`activeElements`, activeEvents); + + const eventItems = eventsToItems(activeEvents, { + settings: config.settings!, + useSummary: Boolean(config.use_summary) + }); + + debuggerInstance.log(`eventsToItems`, eventItems); + + return !config.event_grouping ? + eventItems : + filterDuplicatedItems(eventItems); +}; + +export { + getCalendarData +}; diff --git a/src/utils/getColoredStyle.ts b/src/utils/getColoredStyle.ts new file mode 100644 index 0000000..bfb9d18 --- /dev/null +++ b/src/utils/getColoredStyle.ts @@ -0,0 +1,23 @@ +import { getRgbColor } from './getRgbColor'; + +import type { CalendarItem } from './calendarItem'; +import type { TrashCardConfig } from '../cards/trash-card/trash-card-config'; + +const getColoredStyle = (mode: TrashCardConfig['color_mode'], item: CalendarItem) => { + const color = item.color ?? 'disabled'; + + const style = {}; + const rgbColor = getRgbColor(color); + + if (mode === 'icon') { + style['--trash-card-icon-color'] = `rgba(${rgbColor})`; + } else { + style['--trash-card-background'] = `rgba(${rgbColor}, .7)`; + } + + return style; +}; + +export { + getColoredStyle +}; diff --git a/src/utils/getDateString.ts b/src/utils/getDateString.ts index ffdbcc5..166146d 100644 --- a/src/utils/getDateString.ts +++ b/src/utils/getDateString.ts @@ -5,8 +5,8 @@ import type { TrashCardConfig } from '../cards/trash-card/trash-card-config'; import type { HomeAssistant } from './ha'; import type { CalendarItem } from './calendarItem'; -const getDateString = (item: CalendarItem, excludeTime?: boolean, config?: TrashCardConfig, hass?: HomeAssistant): string => { - if (!hass || !config) { +const getDateString = (item: CalendarItem, excludeTime?: boolean, dayStyle?: TrashCardConfig['day_style'], hass?: HomeAssistant): string => { + if (!hass) { return ''; } @@ -42,7 +42,7 @@ const getDateString = (item: CalendarItem, excludeTime?: boolean, config?: Trash return `${customLocalize(`${key}`).replace('', startTime ?? '').replace('', endTime ?? '')}`; } - if (config.day_style === 'counter') { + if (dayStyle === 'counter') { const oneDay = 24 * 60 * 60 * 1_000; const todayMorning = new Date(); diff --git a/src/utils/getRgbColor.ts b/src/utils/getRgbColor.ts new file mode 100644 index 0000000..eed39bf --- /dev/null +++ b/src/utils/getRgbColor.ts @@ -0,0 +1,11 @@ +const getRgbColor = (color: string) => { + if ([ 'primary', 'accent' ].includes(color)) { + return `var(--rgb-${color}-color)`; + } + + return `var(--rgb-${color})`; +}; + +export { + getRgbColor +}; diff --git a/src/utils/normaliseEvents.test.ts b/src/utils/normaliseEvents.test.ts index cc37c06..d891f17 100644 --- a/src/utils/normaliseEvents.test.ts +++ b/src/utils/normaliseEvents.test.ts @@ -7,13 +7,14 @@ import type { RawCalendarEvent } from './calendarEvents'; describe('normaliseEvents', (): void => { test('normaliseEvents', async () => { - const result = normaliseEvents(calendarEvents as RawCalendarEvent[]); + const timezoneOffset = getTimeZoneOffset(); + const result = normaliseEvents(calendarEvents as RawCalendarEvent[], timezoneOffset); const expectedResult = [ { date: { - start: new Date(`2023-12-10T00:00:00${getTimeZoneOffset()}`), - end: new Date(`2023-12-11T00:00:00${getTimeZoneOffset()}`) + start: new Date(`2023-12-10T00:00:00${timezoneOffset}`), + end: new Date(`2023-12-11T00:00:00${timezoneOffset}`) }, isWholeDayEvent: true, content: { diff --git a/src/utils/normaliseEvents.ts b/src/utils/normaliseEvents.ts index 745649c..baf2696 100644 --- a/src/utils/normaliseEvents.ts +++ b/src/utils/normaliseEvents.ts @@ -1,8 +1,6 @@ -import { getTimeZoneOffset } from './getTimeZoneOffset'; - import type { CalendarEvent, RawCalendarEvent } from './calendarEvents'; -const normaliseEvents = (events: RawCalendarEvent[]): CalendarEvent[] => { +const normaliseEvents = (events: RawCalendarEvent[], timezoneOffset: string): CalendarEvent[] => { const beginingTime = new Date(); beginingTime.setUTCHours(0); @@ -11,7 +9,7 @@ const normaliseEvents = (events: RawCalendarEvent[]): CalendarEvent[] => { beginingTime.setMilliseconds(0); const isoDateString = beginingTime.toISOString(); - const timeAtZero = `${isoDateString.slice(isoDateString.indexOf(`T`), -1)}${getTimeZoneOffset()}`; + const timeAtZero = `${isoDateString.slice(isoDateString.indexOf(`T`), -1)}${timezoneOffset}`; return events. map((item): CalendarEvent => ({