diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index baaeb5f1d9..8f5c2e6745 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -16,7 +16,7 @@ "@umbraco-ui/uui-modal-dialog": "file:umbraco-ui-uui-modal-dialog-0.0.0.tgz", "@umbraco-ui/uui-modal-sidebar": "file:umbraco-ui-uui-modal-sidebar-0.0.0.tgz", "element-internals-polyfill": "^1.1.17", - "lit": "^2.4.1", + "lit": "^2.5.0", "lodash": "^4.17.21", "openapi-typescript-fetch": "^1.1.3", "router-slot": "^1.5.5", @@ -50,11 +50,11 @@ "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-lit": "^1.7.0", + "eslint-plugin-lit": "^1.7.1", "eslint-plugin-lit-a11y": "^2.3.0", "eslint-plugin-local-rules": "^1.3.2", "eslint-plugin-storybook": "^0.6.8", - "lit-html": "^2.4.0", + "lit-html": "^2.5.0", "msw": "^0.49.2", "msw-storybook-addon": "^1.6.3", "openapi-typescript-codegen": "^0.23.0", @@ -64,7 +64,7 @@ "tiny-glob": "^0.2.9", "typescript": "^4.9.4", "vite": "^3.2.4", - "vite-plugin-static-copy": "^0.12.0", + "vite-plugin-static-copy": "^0.13.0", "vite-tsconfig-paths": "^4.0.1", "web-component-analyzer": "^2.0.0-next.4" }, @@ -2523,9 +2523,9 @@ "dev": true }, "node_modules/@lit/reactive-element": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.1.tgz", - "integrity": "sha512-qDv4851VFSaBWzpS02cXHclo40jsbAjRXnebNXpm0uVg32kCneZPo9RYVQtrTNICtZ+1wAYHu1ZtxWSWMbKrBw==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.5.0.tgz", + "integrity": "sha512-fQh9FDK0LPTwDk+0HhSZEtb8K0LTN1wXerwpGrWA+a8tWulYRDLI4vQDWp4GOIsewn0572KYV/oZ3+492D7osA==" }, "node_modules/@mdn/browser-compat-data": { "version": "4.2.1", @@ -7001,9 +7001,8 @@ }, "node_modules/@storybook/manager-webpack4/node_modules/ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -7035,9 +7034,8 @@ }, "node_modules/@storybook/manager-webpack4/node_modules/chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -7051,9 +7049,8 @@ }, "node_modules/@storybook/manager-webpack4/node_modules/color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -7063,9 +7060,8 @@ }, "node_modules/@storybook/manager-webpack4/node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@storybook/manager-webpack4/node_modules/find-cache-dir": { "version": "3.3.2", @@ -7111,9 +7107,8 @@ }, "node_modules/@storybook/manager-webpack4/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7174,9 +7169,8 @@ }, "node_modules/@storybook/manager-webpack4/node_modules/supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -7186,9 +7180,8 @@ }, "node_modules/@storybook/mdx1-csf": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz", - "integrity": "sha512-4biZIWWzoWlCarMZmTpqcJNgo/RBesYZwGFbQeXiGYsswuvfWARZnW9RE9aUEMZ4XPn7B1N3EKkWcdcWe/K2tg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.12.11", "@babel/parser": "^7.12.11", @@ -7205,9 +7198,8 @@ }, "node_modules/@storybook/mdx1-csf/node_modules/prettier": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -7217,9 +7209,8 @@ }, "node_modules/@storybook/mdx2-csf": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-0.0.3.tgz", - "integrity": "sha512-PFhucALIP23H3D/VyA4vlDsHKEJfhbLCIullmvaSl+KTTGbn4g+IkOAsIhVx+dEHYdCqCRW53r66+D4P6A7uOA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.12.11", "@babel/parser": "^7.12.11", @@ -7232,10 +7223,9 @@ } }, "node_modules/@storybook/mdx2-csf/node_modules/@mdx-js/mdx": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.1.3.tgz", - "integrity": "sha512-ahbb47HJIJ4xnifaL06tDJiSyLEy1EhFAStO7RZIm3GTa7yGW3NGhZaj+GUCveFgl5oI54pY4BgiLmYm97y+zg==", + "version": "2.1.5", "dev": true, + "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/mdx": "^2.0.0", @@ -7262,9 +7252,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/bail": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7272,15 +7261,13 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/estree-walker": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.1.tgz", - "integrity": "sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@storybook/mdx2-csf/node_modules/is-plain-obj": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true, + "license": "MIT", "engines": { "node": ">=12" }, @@ -7289,10 +7276,9 @@ } }, "node_modules/@storybook/mdx2-csf/node_modules/remark-mdx": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.1.3.tgz", - "integrity": "sha512-3SmtXOy9+jIaVctL8Cs3VAQInjRLGOwNXfrBB9KCT+EpJpKD3PQiy0x8hUNGyjQmdyOs40BqgPU7kYtH9uoR6w==", + "version": "2.1.5", "dev": true, + "license": "MIT", "dependencies": { "mdast-util-mdx": "^2.0.0", "micromark-extension-mdxjs": "^1.0.0" @@ -7304,9 +7290,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/remark-parse": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", - "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==", "dev": true, + "license": "MIT", "dependencies": { "@types/mdast": "^3.0.0", "mdast-util-from-markdown": "^1.0.0", @@ -7319,9 +7304,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/trough": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", - "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", "dev": true, + "license": "MIT", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -7329,9 +7313,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/unified": { "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "bail": "^2.0.0", @@ -7348,9 +7331,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/unist-util-is": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz", - "integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==", "dev": true, + "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -7358,9 +7340,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/unist-util-visit": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.1.tgz", - "integrity": "sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", @@ -7373,9 +7354,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/unist-util-visit-parents": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz", - "integrity": "sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" @@ -7387,9 +7367,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/vfile": { "version": "5.3.5", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.5.tgz", - "integrity": "sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", @@ -7403,9 +7382,8 @@ }, "node_modules/@storybook/mdx2-csf/node_modules/vfile-message": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", - "integrity": "sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==", "dev": true, + "license": "MIT", "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" @@ -7420,6 +7398,7 @@ "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.14.tgz", "integrity": "sha512-MbEEgUEfrDN8Y0vzZJqPcxwWvX0l8zAsXy6d/DORP2AmwuNmnWTy++BE9YhxH6HMdM1ivRDmBbT30+KBUWhnUA==", "dev": true, + "license": "MIT", "dependencies": { "@types/npmlog": "^4.1.2", "chalk": "^4.1.0", @@ -7965,6 +7944,7 @@ "resolved": "https://registry.npmjs.org/@storybook/store/-/store-6.5.14.tgz", "integrity": "sha512-s07Vw4nbShPYwBJmVXzptuyCkrDQD3khcrKB5L7NsHHgWsm2QI0OyiPMuMbSvgipjcMc/oRqdL3tFUeFak9EMg==", "dev": true, + "license": "MIT", "dependencies": { "@storybook/addons": "6.5.14", "@storybook/client-logger": "6.5.14", @@ -8056,6 +8036,7 @@ "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.14.tgz", "integrity": "sha512-hHpr4Sya6fuEDhy7vnfD2QnL5wy1CaAK9BC0FLupndXnQyKJtygfIaUP4a0B2KntuNPbzPhclb2Hb4yM7CExmQ==", "dev": true, + "license": "MIT", "dependencies": { "core-js": "^3.8.2", "ts-dedent": "^2.0.0", @@ -8267,6 +8248,7 @@ "resolved": "https://registry.npmjs.org/@storybook/ui/-/ui-6.5.14.tgz", "integrity": "sha512-dXlCIULh8ytgdFrvVoheQLlZjAyyYmGCuw+6m+s+2yF/oUbFREG/5Zo9hDwlJ4ZiAyqNLkuwg2tnMYtjapZSog==", "dev": true, + "license": "MIT", "dependencies": { "@storybook/addons": "6.5.14", "@storybook/api": "6.5.14", @@ -8624,40 +8606,35 @@ } }, "node_modules/@storybook/web-components/node_modules/@types/node": { - "version": "16.11.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.63.tgz", - "integrity": "sha512-3OxnrEQLBz8EIIaHpg3CibmTAEGkDBcHY4fL5cnBwg2vd2yvHrUDGWxK+MlYPeXWWIoJJW79dGtU+oeBr6166Q==", - "dev": true + "version": "16.18.0", + "dev": true, + "license": "MIT" }, "node_modules/@types/accepts": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/acorn": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/estree": "*" } }, "node_modules/@types/babel__code-frame": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/babel__code-frame/-/babel__code-frame-7.0.3.tgz", - "integrity": "sha512-2TN6oiwtNjOezilFVl77zwdNPwQWaDBBCCWWxyo1ctiO3vAtd7H/aB/CBJdw9+kqq3+latD0SXoedIuHySSZWw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/body-parser": { "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" @@ -8671,18 +8648,16 @@ }, "node_modules/@types/chai-dom": { "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/chai-dom/-/chai-dom-0.0.12.tgz", - "integrity": "sha512-4rE7sDw713cV61TYzQbMrPjC4DjNk3x4vk9nAVRNXcSD4p0/5lEEfm0OgoCz5eNuWUXNKA0YiKiH/JDTuKivkA==", "dev": true, + "license": "MIT", "dependencies": { "@types/chai": "*" } }, "node_modules/@types/co-body": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/co-body/-/co-body-6.1.0.tgz", - "integrity": "sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*" @@ -8690,36 +8665,31 @@ }, "node_modules/@types/command-line-args": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", - "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/connect": { "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/content-disposition": { "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.5.tgz", - "integrity": "sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/convert-source-map": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/convert-source-map/-/convert-source-map-1.5.2.tgz", - "integrity": "sha512-tHs++ZeXer40kCF2JpE51Hg7t4HPa18B1b1Dzy96S0eCw8QKECNMYMfwa1edK/x8yCN0r4e6ewvLcc5CsVGkdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/cookie": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/cookies": { "version": "0.7.7", @@ -15601,9 +15571,9 @@ "dev": true }, "node_modules/eslint-plugin-lit": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.7.0.tgz", - "integrity": "sha512-V9cflbK3qn91BKZsqjfU0KX2bXv36VtVAty9k7D+SauR1mvmEaZpmEDT74H1PDdsuFQG+0fmoU/ufhPYlAhJxA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.7.1.tgz", + "integrity": "sha512-25rB2FPesP/b1aadT18tNKV3POkSey4IQmSgKd238Pv163S0RO5J67Nzim8L7xq0KE9jGPjfgyOivyXZ0vN4vQ==", "dev": true, "dependencies": { "parse5": "^6.0.1", @@ -20173,13 +20143,13 @@ "dev": true }, "node_modules/lit": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.4.1.tgz", - "integrity": "sha512-qohSgLiyN1cFnJG26dIiY03S4F49857A0AHQfnS0zYtnUVnD2MFvx+UT52rtXsIuNFQrnUupX+zyGSATlk1f/A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.5.0.tgz", + "integrity": "sha512-DtnUP6vR3l4Q8nRPPNBD+UxbAhwJPeky+OVbi3pdgMqm0g57xFSl1Sj64D1rIB+nVNdiVVg8YxB0hqKjvdadZA==", "dependencies": { - "@lit/reactive-element": "^1.4.0", + "@lit/reactive-element": "^1.5.0", "lit-element": "^3.2.0", - "lit-html": "^2.4.0" + "lit-html": "^2.5.0" } }, "node_modules/lit-element": { @@ -20192,9 +20162,9 @@ } }, "node_modules/lit-html": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.4.0.tgz", - "integrity": "sha512-G6qXu4JNUpY6aaF2VMfaszhO9hlWw0hOTRFDmuMheg/nDYGB+2RztUSOyrzALAbr8Nh0Y7qjhYkReh3rPnplVg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.5.0.tgz", + "integrity": "sha512-bLHosg1XL3JRUcKdSVI0sLCs0y1wWrj2sqqAN3cZ7bDDPNgmDHH29RV48x6Wz3ZmkxIupaE+z7uXSZ/pXWAO1g==", "dependencies": { "@types/trusted-types": "^2.0.2" } @@ -29388,27 +29358,27 @@ } }, "node_modules/vite-plugin-static-copy": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.12.0.tgz", - "integrity": "sha512-5a8hCjYJdf/rl8s7ct/YWt97gXdGPGNSOoJtkY5IYhbnSq04X1gTt5GpFHKfAxhHoed1Grfw3Ed13t7AjJi7gw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.13.0.tgz", + "integrity": "sha512-cln+fvKMgwNBjxQ59QVblmExZrc9gGEdRmfqcPOOGpxT5KInfpkGMvmK4L+kCAeHHSSGNU1bM7BA9PQgaAJc6g==", "dev": true, "dependencies": { "chokidar": "^3.5.3", "fast-glob": "^3.2.11", - "fs-extra": "^10.1.0", + "fs-extra": "^11.1.0", "picocolors": "^1.0.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "peerDependencies": { - "vite": "^3.0.0" + "vite": "^3.0.0 || ^4.0.0" } }, "node_modules/vite-plugin-static-copy/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -29416,7 +29386,7 @@ "universalify": "^2.0.0" }, "engines": { - "node": ">=12" + "node": ">=14.14" } }, "node_modules/vite-plugin-static-copy/node_modules/picocolors": { @@ -33085,9 +33055,9 @@ "dev": true }, "@lit/reactive-element": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.1.tgz", - "integrity": "sha512-qDv4851VFSaBWzpS02cXHclo40jsbAjRXnebNXpm0uVg32kCneZPo9RYVQtrTNICtZ+1wAYHu1ZtxWSWMbKrBw==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.5.0.tgz", + "integrity": "sha512-fQh9FDK0LPTwDk+0HhSZEtb8K0LTN1wXerwpGrWA+a8tWulYRDLI4vQDWp4GOIsewn0572KYV/oZ3+492D7osA==" }, "@mdn/browser-compat-data": { "version": "4.2.1", @@ -36249,8 +36219,6 @@ }, "ansi-styles": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "requires": { "color-convert": "^2.0.1" @@ -36270,8 +36238,6 @@ }, "chalk": { "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -36280,8 +36246,6 @@ }, "color-convert": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { "color-name": "~1.1.4" @@ -36289,8 +36253,6 @@ }, "color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, "find-cache-dir": { @@ -36327,8 +36289,6 @@ }, "has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "locate-path": { @@ -36369,8 +36329,6 @@ }, "supports-color": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -36380,8 +36338,6 @@ }, "@storybook/mdx1-csf": { "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@storybook/mdx1-csf/-/mdx1-csf-0.0.1.tgz", - "integrity": "sha512-4biZIWWzoWlCarMZmTpqcJNgo/RBesYZwGFbQeXiGYsswuvfWARZnW9RE9aUEMZ4XPn7B1N3EKkWcdcWe/K2tg==", "dev": true, "requires": { "@babel/generator": "^7.12.11", @@ -36399,16 +36355,12 @@ "dependencies": { "prettier": { "version": "2.3.0", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.3.0.tgz", - "integrity": "sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w==", "dev": true } } }, "@storybook/mdx2-csf": { "version": "0.0.3", - "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-0.0.3.tgz", - "integrity": "sha512-PFhucALIP23H3D/VyA4vlDsHKEJfhbLCIullmvaSl+KTTGbn4g+IkOAsIhVx+dEHYdCqCRW53r66+D4P6A7uOA==", "dev": true, "requires": { "@babel/generator": "^7.12.11", @@ -36422,9 +36374,7 @@ }, "dependencies": { "@mdx-js/mdx": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-2.1.3.tgz", - "integrity": "sha512-ahbb47HJIJ4xnifaL06tDJiSyLEy1EhFAStO7RZIm3GTa7yGW3NGhZaj+GUCveFgl5oI54pY4BgiLmYm97y+zg==", + "version": "2.1.5", "dev": true, "requires": { "@types/estree-jsx": "^1.0.0", @@ -36448,26 +36398,18 @@ }, "bail": { "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", "dev": true }, "estree-walker": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.1.tgz", - "integrity": "sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g==", "dev": true }, "is-plain-obj": { "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", "dev": true }, "remark-mdx": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-2.1.3.tgz", - "integrity": "sha512-3SmtXOy9+jIaVctL8Cs3VAQInjRLGOwNXfrBB9KCT+EpJpKD3PQiy0x8hUNGyjQmdyOs40BqgPU7kYtH9uoR6w==", + "version": "2.1.5", "dev": true, "requires": { "mdast-util-mdx": "^2.0.0", @@ -36476,8 +36418,6 @@ }, "remark-parse": { "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", - "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==", "dev": true, "requires": { "@types/mdast": "^3.0.0", @@ -36487,14 +36427,10 @@ }, "trough": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.1.0.tgz", - "integrity": "sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==", "dev": true }, "unified": { "version": "10.1.2", - "resolved": "https://registry.npmjs.org/unified/-/unified-10.1.2.tgz", - "integrity": "sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q==", "dev": true, "requires": { "@types/unist": "^2.0.0", @@ -36508,14 +36444,10 @@ }, "unist-util-is": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz", - "integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==", "dev": true }, "unist-util-visit": { "version": "4.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.1.tgz", - "integrity": "sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==", "dev": true, "requires": { "@types/unist": "^2.0.0", @@ -36525,8 +36457,6 @@ }, "unist-util-visit-parents": { "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz", - "integrity": "sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==", "dev": true, "requires": { "@types/unist": "^2.0.0", @@ -36535,8 +36465,6 @@ }, "vfile": { "version": "5.3.5", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.5.tgz", - "integrity": "sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ==", "dev": true, "requires": { "@types/unist": "^2.0.0", @@ -36547,8 +36475,6 @@ }, "vfile-message": { "version": "3.1.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", - "integrity": "sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==", "dev": true, "requires": { "@types/unist": "^2.0.0", @@ -37412,17 +37338,13 @@ } }, "@types/node": { - "version": "16.11.63", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.63.tgz", - "integrity": "sha512-3OxnrEQLBz8EIIaHpg3CibmTAEGkDBcHY4fL5cnBwg2vd2yvHrUDGWxK+MlYPeXWWIoJJW79dGtU+oeBr6166Q==", + "version": "16.18.0", "dev": true } } }, "@types/accepts": { "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", - "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", "dev": true, "requires": { "@types/node": "*" @@ -37430,8 +37352,6 @@ }, "@types/acorn": { "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", - "integrity": "sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ==", "dev": true, "requires": { "@types/estree": "*" @@ -37439,14 +37359,10 @@ }, "@types/babel__code-frame": { "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/babel__code-frame/-/babel__code-frame-7.0.3.tgz", - "integrity": "sha512-2TN6oiwtNjOezilFVl77zwdNPwQWaDBBCCWWxyo1ctiO3vAtd7H/aB/CBJdw9+kqq3+latD0SXoedIuHySSZWw==", "dev": true }, "@types/body-parser": { "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", "dev": true, "requires": { "@types/connect": "*", @@ -37461,8 +37377,6 @@ }, "@types/chai-dom": { "version": "0.0.12", - "resolved": "https://registry.npmjs.org/@types/chai-dom/-/chai-dom-0.0.12.tgz", - "integrity": "sha512-4rE7sDw713cV61TYzQbMrPjC4DjNk3x4vk9nAVRNXcSD4p0/5lEEfm0OgoCz5eNuWUXNKA0YiKiH/JDTuKivkA==", "dev": true, "requires": { "@types/chai": "*" @@ -37470,8 +37384,6 @@ }, "@types/co-body": { "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@types/co-body/-/co-body-6.1.0.tgz", - "integrity": "sha512-3e0q2jyDAnx/DSZi0z2H0yoZ2wt5yRDZ+P7ymcMObvq0ufWRT4tsajyO+Q1VwVWiv9PRR4W3YEjEzBjeZlhF+w==", "dev": true, "requires": { "@types/node": "*", @@ -37480,14 +37392,10 @@ }, "@types/command-line-args": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", - "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", "dev": true }, "@types/connect": { "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", "dev": true, "requires": { "@types/node": "*" @@ -37495,20 +37403,14 @@ }, "@types/content-disposition": { "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.5.tgz", - "integrity": "sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==", "dev": true }, "@types/convert-source-map": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/@types/convert-source-map/-/convert-source-map-1.5.2.tgz", - "integrity": "sha512-tHs++ZeXer40kCF2JpE51Hg7t4HPa18B1b1Dzy96S0eCw8QKECNMYMfwa1edK/x8yCN0r4e6ewvLcc5CsVGkdg==", "dev": true }, "@types/cookie": { "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", "dev": true }, "@types/cookies": { @@ -43163,9 +43065,9 @@ } }, "eslint-plugin-lit": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.7.0.tgz", - "integrity": "sha512-V9cflbK3qn91BKZsqjfU0KX2bXv36VtVAty9k7D+SauR1mvmEaZpmEDT74H1PDdsuFQG+0fmoU/ufhPYlAhJxA==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.7.1.tgz", + "integrity": "sha512-25rB2FPesP/b1aadT18tNKV3POkSey4IQmSgKd238Pv163S0RO5J67Nzim8L7xq0KE9jGPjfgyOivyXZ0vN4vQ==", "dev": true, "requires": { "parse5": "^6.0.1", @@ -46552,13 +46454,13 @@ "dev": true }, "lit": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.4.1.tgz", - "integrity": "sha512-qohSgLiyN1cFnJG26dIiY03S4F49857A0AHQfnS0zYtnUVnD2MFvx+UT52rtXsIuNFQrnUupX+zyGSATlk1f/A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/lit/-/lit-2.5.0.tgz", + "integrity": "sha512-DtnUP6vR3l4Q8nRPPNBD+UxbAhwJPeky+OVbi3pdgMqm0g57xFSl1Sj64D1rIB+nVNdiVVg8YxB0hqKjvdadZA==", "requires": { - "@lit/reactive-element": "^1.4.0", + "@lit/reactive-element": "^1.5.0", "lit-element": "^3.2.0", - "lit-html": "^2.4.0" + "lit-html": "^2.5.0" } }, "lit-element": { @@ -46571,9 +46473,9 @@ } }, "lit-html": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.4.0.tgz", - "integrity": "sha512-G6qXu4JNUpY6aaF2VMfaszhO9hlWw0hOTRFDmuMheg/nDYGB+2RztUSOyrzALAbr8Nh0Y7qjhYkReh3rPnplVg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.5.0.tgz", + "integrity": "sha512-bLHosg1XL3JRUcKdSVI0sLCs0y1wWrj2sqqAN3cZ7bDDPNgmDHH29RV48x6Wz3ZmkxIupaE+z7uXSZ/pXWAO1g==", "requires": { "@types/trusted-types": "^2.0.2" } @@ -53757,21 +53659,21 @@ } }, "vite-plugin-static-copy": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.12.0.tgz", - "integrity": "sha512-5a8hCjYJdf/rl8s7ct/YWt97gXdGPGNSOoJtkY5IYhbnSq04X1gTt5GpFHKfAxhHoed1Grfw3Ed13t7AjJi7gw==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/vite-plugin-static-copy/-/vite-plugin-static-copy-0.13.0.tgz", + "integrity": "sha512-cln+fvKMgwNBjxQ59QVblmExZrc9gGEdRmfqcPOOGpxT5KInfpkGMvmK4L+kCAeHHSSGNU1bM7BA9PQgaAJc6g==", "dev": true, "requires": { "chokidar": "^3.5.3", "fast-glob": "^3.2.11", - "fs-extra": "^10.1.0", + "fs-extra": "^11.1.0", "picocolors": "^1.0.0" }, "dependencies": { "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", + "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", "dev": true, "requires": { "graceful-fs": "^4.2.0", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 134f2221e8..b8cebd009e 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -60,7 +60,7 @@ "@umbraco-ui/uui-modal-dialog": "file:umbraco-ui-uui-modal-dialog-0.0.0.tgz", "@umbraco-ui/uui-modal-sidebar": "file:umbraco-ui-uui-modal-sidebar-0.0.0.tgz", "element-internals-polyfill": "^1.1.17", - "lit": "^2.4.1", + "lit": "^2.5.0", "lodash": "^4.17.21", "openapi-typescript-fetch": "^1.1.3", "router-slot": "^1.5.5", @@ -94,11 +94,11 @@ "eslint-config-prettier": "^8.5.0", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.26.0", - "eslint-plugin-lit": "^1.7.0", + "eslint-plugin-lit": "^1.7.1", "eslint-plugin-lit-a11y": "^2.3.0", "eslint-plugin-local-rules": "^1.3.2", "eslint-plugin-storybook": "^0.6.8", - "lit-html": "^2.4.0", + "lit-html": "^2.5.0", "msw": "^0.49.2", "msw-storybook-addon": "^1.6.3", "openapi-typescript-codegen": "^0.23.0", @@ -108,7 +108,7 @@ "tiny-glob": "^0.2.9", "typescript": "^4.9.4", "vite": "^3.2.4", - "vite-plugin-static-copy": "^0.12.0", + "vite-plugin-static-copy": "^0.13.0", "vite-tsconfig-paths": "^4.0.1", "web-component-analyzer": "^2.0.0-next.4" }, diff --git a/src/Umbraco.Web.UI.Client/public/mockServiceWorker.js b/src/Umbraco.Web.UI.Client/public/mockServiceWorker.js index 4ed73191bd..70f0a2b994 100644 --- a/src/Umbraco.Web.UI.Client/public/mockServiceWorker.js +++ b/src/Umbraco.Web.UI.Client/public/mockServiceWorker.js @@ -2,7 +2,7 @@ /* tslint:disable */ /** - * Mock Service Worker (0.49.1). + * Mock Service Worker (0.49.2). * @see https://github.com/mswjs/msw * - Please do NOT modify this file. * - Please do NOT serve this file on production. diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts index 9e8d50d4c7..7bedd2dab7 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/backoffice.element.ts @@ -32,12 +32,15 @@ import { UmbSectionStore } from '../core/stores/section.store'; import { UmbUserStore } from '../core/stores/user/user.store'; import { UmbIconStore } from '../core/stores/icon/icon.store'; import { UmbUserGroupStore } from '../core/stores/user/user-group.store'; +import { UmbCurrentUserHistoryStore } from '../core/stores/current-user-history/current-user-history.store'; import { manifests as sectionManifests } from './sections/manifests'; import { manifests as propertyEditorModelManifests } from './property-editor-models/manifests'; import { manifests as propertyEditorUIManifests } from './property-editor-uis/manifests'; import { manifests as treeManifests } from './trees/manifests'; import { manifests as editorManifests } from './editors/manifests'; import { manifests as propertyActionManifests } from './property-actions/manifests'; +import { manifests as externalLoginProviderManifests } from './external-login-providers/manifests'; +import { manifests as userDashboards } from './user-dashboards/manifests'; import { UmbContextConsumerMixin, UmbContextProviderMixin } from '@umbraco-cms/context-api'; import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestTypes } from '@umbraco-cms/models'; @@ -70,6 +73,8 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this._registerExtensions(propertyEditorModelManifests); this._registerExtensions(propertyEditorUIManifests); this._registerExtensions(propertyActionManifests); + this._registerExtensions(externalLoginProviderManifests); + this._registerExtensions(userDashboards); this._umbIconRegistry.attach(this); @@ -85,6 +90,7 @@ export class UmbBackofficeElement extends UmbContextConsumerMixin(UmbContextProv this.provideContext('umbNotificationService', new UmbNotificationService()); this.provideContext('umbModalService', new UmbModalService()); this.provideContext('umbSectionStore', new UmbSectionStore()); + this.provideContext('umbCurrentUserHistoryStore', new UmbCurrentUserHistoryStore()); } private _registerExtensions(manifests: Array | Array) { diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts index 32d31aee54..b15ac3fa35 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/components/body-layout/body-layout.element.ts @@ -1,6 +1,6 @@ -import { css, html, LitElement } from 'lit'; +import { css, html, LitElement, nothing } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; -import { customElement } from 'lit/decorators.js'; +import { customElement, property } from 'lit/decorators.js'; @customElement('umb-body-layout') export class UmbBodyLayout extends LitElement { @@ -16,15 +16,27 @@ export class UmbBodyLayout extends LitElement { } #header { - background-color: var(--uui-color-surface); + display: flex; + align-items: center; + justify-content: space-between; width: 100%; + min-height: 60px; + + background-color: var(--uui-color-surface); border-bottom: 1px solid var(--uui-color-border); box-sizing: border-box; - /* padding: 0 var(--uui-size-6); */ + } + + #headline { + display: block; + margin: 0 var(--uui-size-layout-1); + } + + #tabs { + margin-left: auto; } #main { - /* padding: 0 var(--uui-size-6); */ display: flex; flex: 1; flex-direction: column; @@ -33,27 +45,63 @@ export class UmbBodyLayout extends LitElement { #footer { display: flex; align-items: center; - height: 70px; + justify-content: space-between; width: 100%; - /*padding: 0 var(--uui-size-6);*/ + height: 54px; /* TODO: missing var(--uui-size-18);*/ border-top: 1px solid var(--uui-color-border); background-color: var(--uui-color-surface); box-sizing: border-box; } + + #actions { + display: flex; + gap: 6px; + margin: 0 var(--uui-size-layout-1); + margin-left: auto; + } `, ]; + connectedCallback() { + super.connectedCallback(); + this.shadowRoot?.removeEventListener('slotchange', this._slotChanged); + this.shadowRoot?.addEventListener('slotchange', this._slotChanged); + } + + disconnectedCallback() { + super.disconnectedCallback(); + this.shadowRoot?.removeEventListener('slotchange', this._slotChanged); + } + + private _slotChanged = (e: Event) => { + (e.target as any).style.display = + (e.target as HTMLSlotElement).assignedNodes({ flatten: true }).length > 0 ? '' : 'none'; + }; + + /** + * Renders a headline in the header. + * @public + * @type {string} + * @attr + * @default '' + */ + @property() + public headline = ''; + render() { return html` `; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts index 484d9418be..a81006ceaf 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/dashboards/examine-management/dashboard-examine-management.element.ts @@ -48,6 +48,13 @@ export class UmbDashboardExamineManagementElement extends UmbContextConsumerMixi @state() private _currentPath?: string; + /** + * + */ + constructor() { + super(); + } + private _onRouteChange() { this._currentPath = path(); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts index 34c3ca3fa1..0041e9046a 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-content/editor-content.element.ts @@ -61,7 +61,6 @@ export class UmbEditorContentElement extends UmbContextProviderMixin( #footer { margin: 0 var(--uui-size-layout-1); - flex:1 1 auto; } `, ]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts index 6b4f567f1b..7ff23cf616 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/shared/editor-entity-layout/editor-entity-layout.element.ts @@ -37,36 +37,6 @@ export class UmbEditorEntityLayout extends UmbContextConsumerMixin(UmbObserverMi height: 100%; } - #header { - display: flex; - align-items: center; - min-height: 60px; - } - - #headline { - display: block; - flex: 1 1 auto; - margin: 0 var(--uui-size-layout-1); - } - - #tabs { - margin-left: auto; - } - - #footer { - display: flex; - height: 100%; - align-items: center; - flex: 1 1 auto; - } - - #actions { - display: flex; - margin-left: auto; - gap: 6px; - margin: 0 var(--uui-size-layout-1); - } - uui-input { width: 100%; } @@ -162,7 +132,7 @@ export class UmbEditorEntityLayout extends UmbContextConsumerMixin(UmbObserverMi return html` ${this._editorViews?.length > 0 ? html` - + ${this._editorViews.map( (view: ManifestEditorView) => html` - + + ${this._renderTabs()} - + + extension.meta.editors.includes(this.alias)}> + + `; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts index 3518a12957..ffe939c570 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/editors/user/editor-user.element.ts @@ -1,5 +1,5 @@ import { UUIInputElement, UUIInputEvent } from '@umbraco-ui/uui'; -import { css, html, LitElement, nothing } from 'lit'; +import { css, html, LitElement, nothing, TemplateResult } from 'lit'; import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { customElement, property, state } from 'lit/decorators.js'; import { ifDefined } from 'lit/directives/if-defined.js'; @@ -10,13 +10,16 @@ import { UmbUserContext } from './user.context'; import { UmbUserStore } from '@umbraco-cms/stores/user/user.store'; import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; -import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; import type { ManifestEditorAction, UserDetails } from '@umbraco-cms/models'; -import { UmbObserverMixin } from '@umbraco-cms/observable-api'; import '../../property-editor-uis/content-picker/property-editor-ui-content-picker.element'; import '@umbraco-cms/components/input-user-group/input-user-group.element'; +import { umbCurrentUserService } from 'src/core/services/current-user'; +import { UmbModalService } from '@umbraco-cms/services'; +import '../shared/editor-entity-layout/editor-entity-layout.element'; +import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; @customElement('umb-editor-user') export class UmbEditorUserElement extends UmbContextProviderMixin( @@ -84,54 +87,47 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( @state() private _user?: UserDetails | null; + @state() + private _currentUser?: UserDetails | null; + @state() private _userName = ''; @property({ type: String }) entityKey = ''; - protected _userStore?: UmbUserStore; + private _userStore?: UmbUserStore; private _userContext?: UmbUserContext; + private _modalService?: UmbModalService; + private _languages = []; //TODO Add languages constructor() { super(); + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { + this._userStore = instances['umbUserStore']; + this._modalService = instances['umbModalService']; + + this._observeUser(); + }); + + this._observeCurrentUser(); this._registerEditorActions(); } - private _registerEditorActions() { - const manifests: Array = [ - { - type: 'editorAction', - alias: 'Umb.EditorAction.User.Save', - name: 'EditorActionUserSave', - loader: () => import('./actions/editor-action-user-save.element'), - meta: { - editors: ['Umb.Editor.User'], - }, - }, - ]; - - manifests.forEach((manifest) => { - if (umbExtensionsRegistry.isRegistered(manifest.alias)) return; - umbExtensionsRegistry.register(manifest); - }); - } - - connectedCallback(): void { - super.connectedCallback(); - - this.consumeContext('umbUserStore', (usersContext: UmbUserStore) => { - this._userStore = usersContext; - this._observeUser(); - }); - } - - private _observeUser() { + private async _observeCurrentUser() { if (!this._userStore) return; - this.observe(this._userStore.getByKey(this.entityKey), (user) => { + this.observe(umbCurrentUserService.currentUser, (currentUser) => { + this._currentUser = currentUser; + }); + } + + private async _observeUser() { + if (!this._userStore) return; + + this.observe(this._userStore.getByKey(this.entityKey), (user) => { this._user = user; if (!this._user) return; @@ -156,6 +152,26 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( }); } + + private _registerEditorActions() { + const manifests: Array = [ + { + type: 'editorAction', + alias: 'Umb.EditorAction.User.Save', + name: 'EditorActionUserSave', + loader: () => import('./actions/editor-action-user-save.element'), + meta: { + editors: ['Umb.Editor.User'], + }, + }, + ]; + + manifests.forEach((manifest) => { + if (umbExtensionsRegistry.isRegistered(manifest.alias)) return; + umbExtensionsRegistry.register(manifest); + }); + } + private _updateUserStatus() { if (!this._user || !this._userStore) return; @@ -210,6 +226,42 @@ export class UmbEditorUserElement extends UmbContextProviderMixin( ); } + private _changePassword() { + this._modalService?.changePassword({ requireOldPassword: umbCurrentUserService.isAdmin === false }); + } + + private _renderActionButtons() { + if (!this._user) return; + + const buttons: TemplateResult[] = []; + + if (umbCurrentUserService.isAdmin === false) return nothing; + + if (this._user?.status !== 'invited') + buttons.push( + html` + + ` + ); + + if (this._currentUser?.key !== this._user?.key) + buttons.push(html` `); + + buttons.push( + html` ` + ); + + return buttons; + } + private _renderLeftColumn() { if (!this._user) return nothing; @@ -271,16 +323,7 @@ export class UmbEditorUserElement extends UmbContextProviderMixin(
- ${this._user?.status !== 'invited' - ? html` - - ` - : nothing} - + ${this._renderActionButtons()}
Status: diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts new file mode 100644 index 0000000000..db338650e1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-extension.element.ts @@ -0,0 +1,44 @@ +import { CSSResultGroup, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { createExtensionElement } from '@umbraco-cms/extensions-api'; +import type { ManifestExternalLoginProvider } from '@umbraco-cms/models'; + +@customElement('umb-external-login-provider-extension') +export class UmbExternalLoginProviderExtensionElement extends LitElement { + static styles: CSSResultGroup = [UUITextStyles]; + + private _externalLoginProvider?: ManifestExternalLoginProvider; + + @property({ type: Object }) + public get externalLoginProvider(): ManifestExternalLoginProvider | undefined { + return this._externalLoginProvider; + } + public set externalLoginProvider(value: ManifestExternalLoginProvider | undefined) { + this._externalLoginProvider = value; + this._createElement(); + } + + @state() + private _element?: any; + + private async _createElement() { + if (!this.externalLoginProvider) return; + + try { + this._element = (await createExtensionElement(this.externalLoginProvider)) as any | undefined; + } catch (error) { + // TODO: loading JS failed so we should do some nice UI. (This does only happen if extension has a js prop, otherwise we concluded that no source was needed resolved the load.) + } + } + + render() { + return html`${this._element}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-external-login-provider-extension': UmbExternalLoginProviderExtensionElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts new file mode 100644 index 0000000000..8d502d2e98 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test.element.ts @@ -0,0 +1,44 @@ +import { css, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; + +@customElement('umb-external-login-provider-test') +export class UmbExternalLoginProviderTestElement extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + background: var(--uui-color-surface-alt); + border-radius: var(--uui-border-radius); + } + p { + margin: 0; + } + `, + ]; + + render() { + return html` + Custom External Login Provider +

This is an example of a custom external login provider using the external login provider extension point

+ + `; + } +} + +export default UmbExternalLoginProviderTestElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-external-login-provider-test': UmbExternalLoginProviderTestElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts new file mode 100644 index 0000000000..955ad87749 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/external-login-provider-test2.element.ts @@ -0,0 +1,57 @@ +import { css, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; + +@customElement('umb-external-login-provider-test2') +export class UmbExternalLoginProviderTest2Element extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + background: var(--uui-color-surface-alt); + border-radius: var(--uui-border-radius); + } + p { + margin: 0; + } + uui-input { + width: 100%; + } + `, + ]; + + render() { + return html` + Another Custom External Login Provider +

This is an example of another custom external login provider

+ + Email + + + + `; + } +} + +export default UmbExternalLoginProviderTest2Element; + +declare global { + interface HTMLElementTagNameMap { + 'umb-external-login-provider-test2': UmbExternalLoginProviderTest2Element; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts new file mode 100644 index 0000000000..bc744b5978 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/external-login-providers/manifests.ts @@ -0,0 +1,28 @@ +import type { ManifestExternalLoginProvider } from '@umbraco-cms/models'; + +export const manifests: Array = [ + { + type: 'externalLoginProvider', + alias: 'Umb.ExternalLoginProvider.Test', + name: 'Test External Login Provider', + elementName: 'umb-external-login-provider-test', + loader: () => import('./external-login-provider-test.element'), + weight: 2, + meta: { + label: 'Test External Login Provider', + pathname: 'test/test/test', + }, + }, + { + type: 'externalLoginProvider', + alias: 'Umb.ExternalLoginProvider.Test2', + name: 'Test External Login Provider 2', + elementName: 'umb-external-login-provider-test2', + loader: () => import('./external-login-provider-test2.element'), + weight: 1, + meta: { + label: 'Test External Login Provider 2', + pathname: 'test/test/test', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/header-apps/header-app-current-user.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/header-apps/header-app-current-user.element.ts index 88731d20cd..61c636b63f 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/header-apps/header-app-current-user.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/header-apps/header-app-current-user.element.ts @@ -1,9 +1,15 @@ import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; import { css, CSSResultGroup, html, LitElement } from 'lit'; -import { customElement } from 'lit/decorators.js'; +import { customElement, state } from 'lit/decorators.js'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import type { UserDetails } from '@umbraco-cms/models'; +import { UmbModalService } from '@umbraco-cms/services'; +import { umbCurrentUserService } from 'src/core/services/current-user'; @customElement('umb-header-app-current-user') -export class UmbHeaderAppCurrentUser extends LitElement { +export class UmbHeaderAppCurrentUser extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { + static styles: CSSResultGroup = [ UUITextStyles, css` @@ -13,12 +19,34 @@ export class UmbHeaderAppCurrentUser extends LitElement { `, ]; - // TODO: Get current user information. + @state() + private _currentUser?: UserDetails; + + private _modalService?: UmbModalService; + + constructor() { + super(); + this.consumeAllContexts(['umbUserStore', 'umbModalService'], (instances) => { + this._modalService = instances['umbModalService']; + this._observeCurrentUser(); + }); + } + + private async _observeCurrentUser() { + this.observe(umbCurrentUserService.currentUser, (currentUser) => { + this._currentUser = currentUser; + }); + } + + private _handleUserClick() { + this._modalService?.userSettings(); + } + render() { return html` - - + + `; } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts index 74e3136a3f..bd20977861 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/packages/views/repo/section-view-packages-repo.element.ts @@ -3,6 +3,7 @@ import { customElement } from 'lit/decorators.js'; @customElement('umb-section-view-packages-repo') export class UmbSectionViewPackagesRepoElement extends LitElement { + render() { return html` diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts index 02773427c0..94230de07c 100644 --- a/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts +++ b/src/Umbraco.Web.UI.Client/src/backoffice/sections/users/views/user-groups/editor-view-user-groups.element.ts @@ -72,8 +72,8 @@ export class UmbEditorViewUserGroupsElement extends UmbContextConsumerMixin(UmbO connectedCallback(): void { super.connectedCallback(); - this.consumeContext('umbUserGroupStore', (userStore: UmbUserGroupStore) => { - this._userGroupStore = userStore; + this.consumeContext('umbUserGroupStore', (userGroupStore: UmbUserGroupStore) => { + this._userGroupStore = userGroupStore; this._observeUserGroups(); }); } diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts new file mode 100644 index 0000000000..fed04c4737 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/manifests.ts @@ -0,0 +1,16 @@ +import type { ManifestUserDashboard } from '@umbraco-cms/models'; + +export const manifests: Array = [ + { + type: 'user-dashboard', + alias: 'Umb.UserDashboard.Test', + name: 'Test User Dashboard', + elementName: 'umb-user-dashboard-test', + loader: () => import('./user-dashboard-test.element'), + weight: 2, + meta: { + label: 'Test User Dashboard', + pathname: 'test/test/test', + }, + }, +]; diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts new file mode 100644 index 0000000000..85ad951331 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-extension.element.ts @@ -0,0 +1,44 @@ +import { CSSResultGroup, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement, property, state } from 'lit/decorators.js'; +import { createExtensionElement } from '@umbraco-cms/extensions-api'; +import type { ManifestUserDashboard } from '@umbraco-cms/models'; + +@customElement('umb-user-dashboard-extension') +export class UmbUserDashboardExtensionElement extends LitElement { + static styles: CSSResultGroup = [UUITextStyles]; + + private _userDashboard?: ManifestUserDashboard; + + @property({ type: Object }) + public get userDashboard(): ManifestUserDashboard | undefined { + return this._userDashboard; + } + public set userDashboard(value: ManifestUserDashboard | undefined) { + this._userDashboard = value; + this._createElement(); + } + + @state() + private _element?: any; + + private async _createElement() { + if (!this.userDashboard) return; + + try { + this._element = (await createExtensionElement(this.userDashboard)) as any | undefined; + } catch (error) { + // TODO: loading JS failed so we should do some nice UI. (This does only happen if extension has a js prop, otherwise we concluded that no source was needed resolved the load.) + } + } + + render() { + return html`${this._element}`; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-user-dashboard-extension': UmbUserDashboardExtensionElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts new file mode 100644 index 0000000000..ede0abf1ff --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/backoffice/user-dashboards/user-dashboard-test.element.ts @@ -0,0 +1,44 @@ +import { css, html, LitElement } from 'lit'; +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { customElement } from 'lit/decorators.js'; +import { UmbContextProviderMixin, UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; + +@customElement('umb-user-dashboard-test') +export class UmbUserDashboardTestElement extends UmbContextProviderMixin( + UmbContextConsumerMixin(UmbObserverMixin(LitElement)) +) { + static styles = [ + UUITextStyles, + css` + :host { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + padding: var(--uui-size-space-5); + border: 1px solid var(--uui-color-border); + background: var(--uui-color-positive); + color: var(--uui-color-positive-contrast); + border-radius: var(--uui-border-radius); + } + p { + margin: 0; + } + `, + ]; + + render() { + return html` + Custom User Dashboard +

This is an example of a custom user dashboard using the user dashboard extension point

+ `; + } +} + +export default UmbUserDashboardTestElement; + +declare global { + interface HTMLElementTagNameMap { + 'umb-user-dashboard-test': UmbUserDashboardTestElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts index 6acb802f75..d557400b3e 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-api/registry/extension.registry.ts @@ -15,6 +15,7 @@ import type { ManifestEditorAction, ManifestCustom, ManifestPackageView, + ManifestExternalLoginProvider, } from '../../models'; import { createExtensionElement } from '../create-extension-element.function'; import { ManifestHeaderApp } from 'src/core/extensions-registry/header-app.models'; @@ -82,6 +83,7 @@ export class UmbExtensionRegistry { extensionsOfType(type: 'packageView'): Observable>; extensionsOfType(type: 'entrypoint'): Observable>; extensionsOfType(type: 'custom'): Observable>; + extensionsOfType(type: 'externalLoginProvider'): Observable>; extensionsOfType(type: string): Observable>; extensionsOfType(type: string): Observable> { return this.extensions.pipe( diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts new file mode 100644 index 0000000000..ebc0588bc9 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/external-login-provider.models.ts @@ -0,0 +1,11 @@ +import type { ManifestElement } from './models'; + +export interface ManifestExternalLoginProvider extends ManifestElement { + type: 'externalLoginProvider'; + meta: MetaExternalLoginProvider; +} + +export interface MetaExternalLoginProvider { + label: string; + pathname: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts index 13939b8681..b528670d23 100644 --- a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/models.ts @@ -1,3 +1,5 @@ + +import type { ManifestHeaderApp } from './header-app.models'; import type { ManifestSection } from './section.models'; import type { ManifestSectionView } from './section-view.models'; import type { ManifestTree } from './tree.models'; @@ -7,9 +9,10 @@ import type { ManifestEditorAction } from './editor-action.models'; import type { ManifestEditorView } from './editor-view.models'; import type { ManifestPropertyEditorUI, ManifestPropertyEditorModel } from './property-editor.models'; import type { ManifestDashboard } from './dashboard.models'; +import type { ManifestUserDashboard } from './user-dashboard.models'; import type { ManifestPropertyAction } from './property-action.models'; import type { ManifestPackageView } from './package-view.models'; -import type { ManifestHeaderApp } from './header-app.models'; +import type { ManifestExternalLoginProvider } from './external-login-provider.models'; export * from './header-app.models'; export * from './section.models'; @@ -21,8 +24,10 @@ export * from './editor-action.models'; export * from './editor-view.models'; export * from './property-editor.models'; export * from './dashboard.models'; +export * from './user-dashboard.models'; export * from './property-action.models'; export * from './package-view.models'; +export * from './external-login-provider.models'; export type ManifestTypes = | ManifestHeaderApp @@ -36,8 +41,10 @@ export type ManifestTypes = | ManifestPropertyEditorUI | ManifestPropertyEditorModel | ManifestDashboard + | ManifestUserDashboard | ManifestPropertyAction | ManifestPackageView + | ManifestExternalLoginProvider | ManifestEntrypoint | ManifestCustom; @@ -53,9 +60,11 @@ export type ManifestStandardTypes = | 'propertyEditorUI' | 'propertyEditorModel' | 'dashboard' + | 'user-dashboard' | 'propertyAction' | 'packageView' - | 'entrypoint'; + | 'entrypoint' + | 'externalLoginProvider'; export type ManifestElementType = | ManifestSection @@ -66,9 +75,11 @@ export type ManifestElementType = | ManifestPropertyAction | ManifestPropertyEditorUI | ManifestDashboard + | ManifestUserDashboard | ManifestEditorView | ManifestEditorAction - | ManifestPackageView; + | ManifestPackageView + | ManifestExternalLoginProvider; export interface ManifestBase { type: string; diff --git a/src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts new file mode 100644 index 0000000000..166df0e24a --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/extensions-registry/user-dashboard.models.ts @@ -0,0 +1,11 @@ +import type { ManifestElement } from './models'; + +export interface ManifestUserDashboard extends ManifestElement { + type: 'user-dashboard'; + meta: MetaUserDashboard; +} + +export interface MetaUserDashboard { + label: string; + pathname: string; +} diff --git a/src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts new file mode 100644 index 0000000000..53782a9580 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/current-user/current-user.service.ts @@ -0,0 +1,30 @@ +import { BehaviorSubject, Observable } from 'rxjs'; +import { umbUsersData } from '../../mocks/data/users.data'; +import type { UserDetails } from '@umbraco-cms/models'; +import { umbracoPath } from '@umbraco-cms/utils'; + +class UmbCurrentUserService { + private _currentUser = new BehaviorSubject(umbUsersData.getAll()[0]); //TODO: Temp solution to set the first user as the current logged in user + public readonly currentUser: Observable = this._currentUser.asObservable(); + + /** + * logs out the user + * @public + * @memberof UmbCurrentUserService + */ + public logout(): void { + fetch(umbracoPath('/user/logout').toString()) + .then((res) => res.json()) + .then((data) => { + console.log('User Logged out', data); + }); + } + + public get isAdmin(): boolean { + //TODO: Find a way to figure out if current user is in the admin group + const adminUserGroupKey = 'c630d49e-4e7b-42ea-b2bc-edc0edacb6b1'; + return this._currentUser.getValue()?.userGroups.includes(adminUserGroupKey); + } +} + +export const umbCurrentUserService = new UmbCurrentUserService(); diff --git a/src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts b/src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts new file mode 100644 index 0000000000..f895dd41e2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/current-user/index.ts @@ -0,0 +1 @@ +export * from './current-user.service'; diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts new file mode 100644 index 0000000000..49e16be8d1 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-change-password.element.ts @@ -0,0 +1,113 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { UmbModalHandler } from '@umbraco-cms/services'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; + +export interface UmbModalChangePasswordData { + requireOldPassword: boolean; +} + +@customElement('umb-modal-layout-change-password') +export class UmbModalLayoutChangePasswordElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { + static styles: CSSResultGroup = [ + UUITextStyles, + css` + :host { + display: block; + width: 400px; + } + uui-input-password { + width: 100%; + } + #actions { + display: flex; + justify-content: flex-end; + margin-top: var(--uui-size-layout-2); + } + `, + ]; + + @property({ attribute: false }) + modalHandler?: UmbModalHandler; + + @property() + data?: UmbModalChangePasswordData; + + private _close() { + this.modalHandler?.close(); + } + + private _handleSubmit(e: SubmitEvent) { + e.preventDefault(); + + const form = e.target as HTMLFormElement; + if (!form) return; + + const isValid = form.checkValidity(); + if (!isValid) return; + + const formData = new FormData(form); + + const oldPassword = formData.get('oldPassword') as string; + const newPassword = formData.get('newPassword') as string; + const confirmPassword = formData.get('confirmPassword') as string; + console.log('IMPLEMENT SUBMIT', { oldPassword, newPassword, confirmPassword }); + this._close(); + } + + private _renderOldPasswordInput() { + return html` + + Old password + + + `; + } + + render() { + return html` + + +
+ ${this.data?.requireOldPassword ? this._renderOldPasswordInput() : nothing} + + New password + + + + Confirm password + + + +
+ + +
+
+
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-modal-layout-change-password': UmbModalLayoutChangePasswordElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-current-user.element.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-current-user.element.ts new file mode 100644 index 0000000000..4f932cb1a2 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/layouts/modal-layout-current-user.element.ts @@ -0,0 +1,227 @@ +import { UUITextStyles } from '@umbraco-ui/uui-css/lib'; +import { css, CSSResultGroup, html, LitElement, nothing } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { umbCurrentUserService } from '../../current-user'; +import { UmbModalHandler, UmbModalService } from '@umbraco-cms/services'; +import type { ManifestExternalLoginProvider, ManifestUserDashboard, UserDetails } from '@umbraco-cms/models'; +import { UmbObserverMixin } from '@umbraco-cms/observable-api'; +import { UmbContextConsumerMixin } from '@umbraco-cms/context-api'; +import { umbExtensionsRegistry } from '@umbraco-cms/extensions-registry'; +import '../../../../backoffice/external-login-providers/external-login-provider-extension.element'; +import '../../../../backoffice/user-dashboards/user-dashboard-extension.element'; +import { UmbCurrentUserHistoryStore, UmbCurrentUserHistoryItem } from '@umbraco-cms/stores/current-user-history/current-user-history.store'; + +@customElement('umb-modal-layout-current-user') +export class UmbModalLayoutCurrentUserElement extends UmbContextConsumerMixin(UmbObserverMixin(LitElement)) { + static styles: CSSResultGroup = [ + UUITextStyles, + css` + :host { + display: block; + } + :host, + umb-editor-entity-layout { + width: 100%; + height: 100%; + } + #main { + padding: var(--uui-size-space-5); + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + #umbraco-id-buttons { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + umb-external-login-provider-extension:not(:last-child) { + margin-bottom: var(--uui-size-space-3); + display: block; + } + #recent-history { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-3); + } + #recent-history-items { + display: flex; + flex-direction: column; + gap: var(--uui-size-space-4); + } + .history-item { + display: grid; + grid-template-columns: 32px 1fr; + grid-template-rows: 1fr; + color: var(--uui-color-interactive); + text-decoration: none; + } + .history-item uui-icon { + margin-top: 2px; + } + .history-item:hover { + color: var(--uui-color-interactive-emphasis); + } + .history-item > div { + color: inherit; + text-decoration: none; + display: flex; + flex-direction: column; + line-height: 1.4em; + } + .history-item > div > span { + font-size: var(--uui-size-4); + opacity: 0.5; + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + } + `, + ]; + + @property({ attribute: false }) + modalHandler?: UmbModalHandler; + + @state() + private _currentUser?: UserDetails; + + @state() + private _externalLoginProviders: Array = []; + + @state() + private _userDashboards: Array = []; + + @state() + private _history: Array = []; + + private _modalService?: UmbModalService; + private _currentUserHistoryStore?: UmbCurrentUserHistoryStore; + + constructor() { + super(); + this.consumeAllContexts(['umbModalService', 'umbCurrentUserHistoryStore'], (instances) => { + this._modalService = instances['umbModalService']; + this._currentUserHistoryStore = instances['umbCurrentUserHistoryStore']; + this._observeHistory(); + }); + + this._observeCurrentUser(); + this._observeExternalLoginProviders(); + this._observeUserDashboards(); + } + + private _observeExternalLoginProviders() { + this.observe( + umbExtensionsRegistry.extensionsOfType('externalLoginProvider'), + (loginProvider) => { + this._externalLoginProviders = loginProvider; + } + ); + } + + private async _observeCurrentUser() { + this.observe(umbCurrentUserService.currentUser, (currentUser) => { + this._currentUser = currentUser; + }); + } + private async _observeHistory() { + if(this._currentUserHistoryStore) { + this.observe>(this._currentUserHistoryStore.getLatestHistory(), (history) => { + this._history = history; + }); + } + } + + private _observeUserDashboards() { + this.observe(umbExtensionsRegistry.extensionsOfType('user-dashboard'), (userDashboard) => { + this._userDashboards = userDashboard; + }); + } + + private _close() { + this.modalHandler?.close(); + } + + private _edit() { + if (!this._currentUser) return; + + history.pushState(null, '', '/section/users/view/users/user/' + this._currentUser.key); //TODO Change to a tag with href and make dynamic + this._close(); + } + + private _changePassword() { + if (!this._modalService) return; + + this._modalService.changePassword({ requireOldPassword: umbCurrentUserService.isAdmin }); + } + + private _renderHistoryItem(item: UmbCurrentUserHistoryItem) { + return html` + + +
+ ${Array.isArray(item.label) ? item.label[0] : item.label} + + ${Array.isArray(item.label) + ? item.label.map((label, index) => { + if (index === 0) return; + return html` + ${label} + ${index !== item.label.length - 1 ? html`${'>'}` : nothing} + `; + }) + : nothing} + +
+
+ `; + } + + private _logout() { + umbCurrentUserService.logout(); + } + + render() { + return html` + +
+ + Your profile + Edit + Change password + + + External login providers + ${this._externalLoginProviders.map( + (provider) => + html`` + )} + +
+ ${this._userDashboards.map( + (provider) => + html`` + )} +
+ + Recent History +
+ ${this._history.reverse().map((item) => html` ${this._renderHistoryItem(item)} `)} +
+
+
+
+ Close + Logout +
+
+ `; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'umb-modal-layout-current-user': UmbModalLayoutCurrentUserElement; + } +} diff --git a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts index 3e810e3216..ffab298efd 100644 --- a/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts +++ b/src/Umbraco.Web.UI.Client/src/core/services/modal/modal.service.ts @@ -2,6 +2,8 @@ import './layouts/confirm/modal-layout-confirm.element'; import './layouts/content-picker/modal-layout-content-picker.element'; import './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; +import './layouts/modal-layout-current-user.element'; +import './layouts/modal-layout-change-password.element'; import { UUIModalSidebarSize } from '@umbraco-ui/uui-modal-sidebar'; import { BehaviorSubject, Observable } from 'rxjs'; @@ -11,6 +13,7 @@ import type { UmbModalConfirmData } from './layouts/confirm/modal-layout-confirm import type { UmbModalContentPickerData } from './layouts/content-picker/modal-layout-content-picker.element'; import type { UmbModalPropertyEditorUIPickerData } from './layouts/property-editor-ui-picker/modal-layout-property-editor-ui-picker.element'; import { UmbModalHandler } from './'; +import { UmbModalChangePasswordData } from './layouts/modal-layout-change-password.element'; export type UmbModalType = 'dialog' | 'sidebar'; @@ -68,6 +71,26 @@ export class UmbModalService { return this.open('umb-modal-layout-icon-picker', { data, type: 'sidebar', size: 'small' }); } + /** + * Opens the user settings sidebar modal + * @public + * @return {*} {UmbModalHandler} + * @memberof UmbModalService + */ + public userSettings(): UmbModalHandler { + return this.open('umb-modal-layout-current-user', { type: 'sidebar', size: 'small' }); + } + + /** + * Opens the user settings sidebar modal + * @public + * @return {*} {UmbModalHandler} + * @memberof UmbModalService + */ + public changePassword(data: UmbModalChangePasswordData): UmbModalHandler { + return this.open('umb-modal-layout-change-password', { data, type: 'dialog' }); + } + /** * Opens a modal or sidebar modal * @public diff --git a/src/Umbraco.Web.UI.Client/src/core/stores/current-user-history/current-user-history.store.ts b/src/Umbraco.Web.UI.Client/src/core/stores/current-user-history/current-user-history.store.ts new file mode 100644 index 0000000000..5865ae010c --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/core/stores/current-user-history/current-user-history.store.ts @@ -0,0 +1,63 @@ +import { BehaviorSubject, map, Observable } from 'rxjs'; + +export type UmbModelType = 'dialog' | 'sidebar'; + +export type UmbCurrentUserHistoryItem = { + path: string; + label: string | Array; + icon?: string; +}; + +export class UmbCurrentUserHistoryStore { + + private _history: BehaviorSubject> = new BehaviorSubject(>[]); + public readonly history: Observable> = this._history.asObservable(); + + constructor() { + (window as any).navigation.addEventListener('navigate', (event: any) => { + const url = new URL(event.destination.url); + const historyItem = {path: url.pathname, label: event.destination.url.split('/').pop()}; + this.push(historyItem); + }); + } + + + public getLatestHistory(): Observable> { + return this._history.pipe(map((historyItem) => + { + return historyItem.slice(-10); + } + )); + } + + /** + * Pushes a new history item to the history array + * @public + * @param {UmbCurrentUserHistoryItem} historyItem + * @memberof UmbHistoryService + */ + public push(historyItem: UmbCurrentUserHistoryItem): void { + const history = this._history.getValue(); + const lastItem = history[history.length - 1]; + + // This prevents duplicate entries in the history array. + if (!lastItem || lastItem.path !== historyItem.path) { + this._history.next([...this._history.getValue(), historyItem]); + } else { + //Update existing item + const newHistory = this._history.getValue(); + newHistory[history.length - 1] = historyItem; + this._history.next(newHistory); + } + + } + + /** + * Clears the history array + * @public + * @memberof UmbHistoryService + */ + public clear() { + this._history.next([]); + } +}