diff --git a/.hgignore b/.hgignore index b269c5fd6959..343853737325 100644 --- a/.hgignore +++ b/.hgignore @@ -170,9 +170,6 @@ _OPT\.OBJ/ ^tools/browsertime/node_modules/ ^tools/lint/eslint/eslint-plugin-mozilla/node_modules/ ^browser/components/newtab/node_modules/ -^toolkit/content/vendor/lit/node_modules/ -# Bug 1790483 Ignore lit - development only for now. -^toolkit/content/widgets/vendor/lit.all.mjs ^tools/esmify/node_modules/ # Ignore talos virtualenv and tp5n files. diff --git a/browser/components/storybook/mach_commands.py b/browser/components/storybook/mach_commands.py index faf4f5b8e917..d4ffa312b0e6 100644 --- a/browser/components/storybook/mach_commands.py +++ b/browser/components/storybook/mach_commands.py @@ -37,12 +37,6 @@ def storybook_launch(command_context): description="Install Storybook node dependencies.", ) def storybook_install(command_context): - # Bug 1790483: First, we need to make sure lit is installed - run_mach( - command_context, - "npm", - args=["run", "vendor", "--prefix=toolkit/content/vendor/lit"], - ) return run_npm(command_context, args=["ci"]) diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index 3ca2ad460372..d44125ba7c12 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -112,6 +112,8 @@ toolkit.jar: content/global/elements/videocontrols.js (widgets/videocontrols.js) content/global/elements/tree.js (widgets/tree.js) content/global/elements/wizard.js (widgets/wizard.js) + content/global/vendor/lit.all.mjs (widgets/vendor/lit.all.mjs) + content/global/lit-utils.mjs (widgets/lit-utils.mjs) content/global/neterror/aboutNetErrorCodes.js (neterror/aboutNetErrorCodes.js) content/global/neterror/supportpages/connection-not-secure.html (neterror/supportpages/connection-not-secure.html) content/global/neterror/supportpages/time-errors.html (neterror/supportpages/time-errors.html) diff --git a/toolkit/content/vendor/lit/0001-disable-terser-step.patch b/toolkit/content/vendor/lit/0001-disable-terser-step.patch new file mode 100644 index 000000000000..244f528d4c2f --- /dev/null +++ b/toolkit/content/vendor/lit/0001-disable-terser-step.patch @@ -0,0 +1,52 @@ +From 1f0db62374e62965f521c3a44c31c947f702d53d Mon Sep 17 00:00:00 2001 +From: Mark Striemer +Date: Wed, 16 Nov 2022 22:54:20 -0600 +Subject: [PATCH 1/2] disable terser step + +--- + rollup-common.js | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/rollup-common.js b/rollup-common.js +index ebe4b406..6fcac21a 100644 +--- a/rollup-common.js ++++ b/rollup-common.js +@@ -345,7 +345,7 @@ export function litProdConfig({ + virtual({ + [nameCacheSeederInfile]: nameCacheSeederContents, + }), +- terser(nameCacheSeederTerserOptions), ++ // terser(nameCacheSeederTerserOptions), + skipBundleOutput, + ], + }, +@@ -395,7 +395,7 @@ export function litProdConfig({ + // This plugin automatically composes the existing TypeScript -> raw JS + // sourcemap with the raw JS -> minified JS one that we're generating here. + sourcemaps(), +- terser(terserOptions), ++ // terser(terserOptions), + summary({ + showBrotliSize: true, + showGzippedSize: true, +@@ -466,7 +466,7 @@ export function litProdConfig({ + // references properties from reactive-element which will + // otherwise have different names. The default export that + // lit-element will use is minified. +- terser(terserOptions), ++ // terser(terserOptions), + summary({ + showBrotliSize: true, + showGzippedSize: true, +@@ -533,7 +533,7 @@ const litMonoBundleConfig = ({ + // This plugin automatically composes the existing TypeScript -> raw JS + // sourcemap with the raw JS -> minified JS one that we're generating here. + sourcemaps(), +- terser(terserOptions), ++ // terser(terserOptions), + summary({ + showBrotliSize: true, + showGzippedSize: true, +-- +2.32.0 (Apple Git-132) + diff --git a/toolkit/content/vendor/lit/0002-use-DOMParser-not-innerHTML.patch b/toolkit/content/vendor/lit/0002-use-DOMParser-not-innerHTML.patch new file mode 100644 index 000000000000..63a489df5b68 --- /dev/null +++ b/toolkit/content/vendor/lit/0002-use-DOMParser-not-innerHTML.patch @@ -0,0 +1,43 @@ +From e2fb71a850fda2d1f02a19d41a3db1cd7cf8618d Mon Sep 17 00:00:00 2001 +From: Mark Striemer +Date: Wed, 16 Nov 2022 23:07:57 -0600 +Subject: [PATCH 2/2] use DOMParser not innerHTML= + +--- + packages/lit-html/src/lit-html.ts | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +diff --git a/packages/lit-html/src/lit-html.ts b/packages/lit-html/src/lit-html.ts +index 51941fdf..13914ca7 100644 +--- a/packages/lit-html/src/lit-html.ts ++++ b/packages/lit-html/src/lit-html.ts +@@ -14,6 +14,8 @@ const NODE_MODE = false; + // Use window for browser builds because IE11 doesn't have globalThis. + const global = NODE_MODE ? globalThis : window; + ++const __moz_domParser = new DOMParser(); ++ + /** + * Contains types that are part of the unstable debug API. + * +@@ -1017,9 +1019,14 @@ class Template { + // Overridden via `litHtmlPolyfillSupport` to provide platform support. + /** @nocollapse */ + static createElement(html: TrustedHTML, _options?: RenderOptions) { +- const el = d.createElement('template'); +- el.innerHTML = html as unknown as string; +- return el; ++ const doc = __moz_domParser.parseFromString( ++ ``, ++ 'text/html' ++ ); ++ return document.importNode( ++ doc.querySelector('template') as HTMLTemplateElement, ++ true ++ ); + } + } + +-- +2.32.0 (Apple Git-132) + diff --git a/toolkit/content/vendor/lit/LICENSE b/toolkit/content/vendor/lit/LICENSE index c8ed22676f58..be7a97b60d79 100644 --- a/toolkit/content/vendor/lit/LICENSE +++ b/toolkit/content/vendor/lit/LICENSE @@ -25,4 +25,4 @@ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/toolkit/content/vendor/lit/README.md b/toolkit/content/vendor/lit/README.md index 81f640b75ebe..138c28a8b0da 100644 --- a/toolkit/content/vendor/lit/README.md +++ b/toolkit/content/vendor/lit/README.md @@ -21,11 +21,26 @@ import { classMap, LitElement } from "../vendor/lit.all.mjs"; ## To update the lit bundle -Using `mach`s `npm` you can update the bundle with: +Vendoring runs off of the latest tag in the https://github.com/lit/lit repo. If +the latest tag is a lit@ tag then running the vendor command will update to that +version. If the latest tag isn't for lit@, you may need to bundle manually. See +the moz.yaml file for instructions. + +### Using mach vendor ``` -cd toolkit/content/vendor/lit -../../../../mach npm run vendor +./mach vendor toolkit/content/vendor/lit/moz.yaml +hg ci -m "Update to lit@" ``` -Then commit the changes. +### Manually updating the bundle + +To manually update, you'll need to checkout a copy of lit/lit, find the tag you +want and manually run our import commands. + + 1. Clone https://github.com/lit/lit outside of moz-central + 2. Copy *.patch from this directory into the lit repo + 3. git apply *.patch + 4. npm install && npm run build + 5. Copy packages/lit/lit-all.min.js to toolkit/content/widgets/vendor/lit.all.mjs + 6. hg ci -m "Update to lit@" diff --git a/toolkit/content/vendor/lit/bundle-lit.sh b/toolkit/content/vendor/lit/bundle-lit.sh new file mode 100755 index 000000000000..532b48337f5e --- /dev/null +++ b/toolkit/content/vendor/lit/bundle-lit.sh @@ -0,0 +1,9 @@ +#!/bin/bash +cp *.patch lit/ +cd lit +git apply *.patch +../../../../../mach npm install +../../../../../mach npm run build +cp packages/lit/lit-all.min.js ../../../widgets/vendor/lit.all.mjs +rm -rf * .* +cp ../LICENSE . diff --git a/toolkit/content/vendor/lit/index.mjs b/toolkit/content/vendor/lit/index.mjs deleted file mode 100644 index 1588d1f62440..000000000000 --- a/toolkit/content/vendor/lit/index.mjs +++ /dev/null @@ -1,20 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ -/* eslint-disable import/no-unassigned-import */ -/* eslint-disable import/no-unresolved */ - -export * from "lit"; -export * from "lit/directives/async-append.js"; -export * from "lit/directives/async-replace.js"; -export * from "lit/directives/cache.js"; -export * from "lit/directives/class-map.js"; -export * from "lit/directives/guard.js"; -export * from "lit/directives/if-defined.js"; -export * from "lit/directives/live.js"; -export * from "lit/directives/ref.js"; -export * from "lit/directives/repeat.js"; -export * from "lit/directives/style-map.js"; -export * from "lit/directives/template-content.js"; -export * from "lit/directives/until.js"; -export * from "lit/decorators.js"; diff --git a/toolkit/content/vendor/lit/lit-html-no-inner-html.patch b/toolkit/content/vendor/lit/lit-html-no-inner-html.patch deleted file mode 100644 index a6128c9ddbc6..000000000000 --- a/toolkit/content/vendor/lit/lit-html-no-inner-html.patch +++ /dev/null @@ -1,17 +0,0 @@ ---- lit.all.mjs -+++ lit.all.mjs.patched -@@ -358,8 +358,12 @@ - } - } - static createElement(t7, i9) { -- const s8 = h2.createElement("template"); -- return s8.innerHTML = t7, s8; -+ const parser = new DOMParser(); -+ const doc = parser.parseFromString( -+ ``, -+ "text/html" -+ ); -+ return document.importNode(doc.querySelector("template"), true); - } - }; - function P(t7, i9, s8 = t7, e14) { diff --git a/toolkit/content/vendor/lit/lit/LICENSE b/toolkit/content/vendor/lit/lit/LICENSE new file mode 100644 index 000000000000..be7a97b60d79 --- /dev/null +++ b/toolkit/content/vendor/lit/lit/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2017 Google LLC. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/toolkit/content/vendor/lit/moz.yaml b/toolkit/content/vendor/lit/moz.yaml index 0997a244b168..381f52e9e2d6 100644 --- a/toolkit/content/vendor/lit/moz.yaml +++ b/toolkit/content/vendor/lit/moz.yaml @@ -10,5 +10,24 @@ origin: "Lit is a simple library for building fast, lightweight web components." url: "https://github.com/lit/lit" license: "BSD-3-Clause" - release: "2.4.0" - revision: "lit@2.4.0" + release: "lit@2.4.0" + revision: "1e1e2e00e3ff655e6f48a42b2e739f47dc681420" + + +# Since this tracks the latest tag, it's possible that lit isn't the latest tag +# in lit/lit. In that case we may need to manually update lit. See README.md for +# more info. +vendoring: + url: "https://github.com/lit/lit" + source-hosting: github + tracking: tag + # lit/lit is a monorepo that publishes multiple packages. The tags for lit + # are formatted as "lit@2.4.1". + # tag-prefix: 'lit@' + + vendor-directory: toolkit/content/vendor/lit/lit + + update-actions: + - action: run-script + script: '{yaml_dir}/bundle-lit.sh' + cwd: '{yaml_dir}' diff --git a/toolkit/content/vendor/lit/package-lock.json b/toolkit/content/vendor/lit/package-lock.json deleted file mode 100644 index 3d6b6e5e22a1..000000000000 --- a/toolkit/content/vendor/lit/package-lock.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "name": "vendor-lit", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "vendor-lit", - "version": "1.0.0", - "license": "MPL-2.0", - "dependencies": { - "lit": "^2.4.0" - }, - "devDependencies": { - "esbuild": "^0.15.10", - "mkdirp": "^1.0.4" - } - }, - "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==" - }, - "node_modules/@types/trusted-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", - "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" - }, - "node_modules/esbuild": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.10.tgz", - "integrity": "sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.15.10", - "@esbuild/linux-loong64": "0.15.10", - "esbuild-android-64": "0.15.10", - "esbuild-android-arm64": "0.15.10", - "esbuild-darwin-64": "0.15.10", - "esbuild-darwin-arm64": "0.15.10", - "esbuild-freebsd-64": "0.15.10", - "esbuild-freebsd-arm64": "0.15.10", - "esbuild-linux-32": "0.15.10", - "esbuild-linux-64": "0.15.10", - "esbuild-linux-arm": "0.15.10", - "esbuild-linux-arm64": "0.15.10", - "esbuild-linux-mips64le": "0.15.10", - "esbuild-linux-ppc64le": "0.15.10", - "esbuild-linux-riscv64": "0.15.10", - "esbuild-linux-s390x": "0.15.10", - "esbuild-netbsd-64": "0.15.10", - "esbuild-openbsd-64": "0.15.10", - "esbuild-sunos-64": "0.15.10", - "esbuild-windows-32": "0.15.10", - "esbuild-windows-64": "0.15.10", - "esbuild-windows-arm64": "0.15.10" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz", - "integrity": "sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/lit": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.4.0.tgz", - "integrity": "sha512-fdgzxEtLrZFQU/BqTtxFQCLwlZd9bdat+ltzSFjvWkZrs7eBmeX0L5MHUMb3kYIkuS8Xlfnii/iI5klirF8/Xg==", - "dependencies": { - "@lit/reactive-element": "^1.4.0", - "lit-element": "^3.2.0", - "lit-html": "^2.4.0" - } - }, - "node_modules/lit-element": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.2.tgz", - "integrity": "sha512-6ZgxBR9KNroqKb6+htkyBwD90XGRiqKDHVrW/Eh0EZ+l+iC+u+v+w3/BA5NGi4nizAVHGYvQBHUDuSmLjPp7NQ==", - "dependencies": { - "@lit/reactive-element": "^1.3.0", - "lit-html": "^2.2.0" - } - }, - "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==", - "dependencies": { - "@types/trusted-types": "^2.0.2" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - } - }, - "dependencies": { - "@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==" - }, - "@types/trusted-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.2.tgz", - "integrity": "sha512-F5DIZ36YVLE+PN+Zwws4kJogq47hNgX3Nx6WyDJ3kcplxyke3XIzB8uK5n/Lpm1HBsbGzd6nmGehL8cPekP+Tg==" - }, - "esbuild": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.10.tgz", - "integrity": "sha512-N7wBhfJ/E5fzn/SpNgX+oW2RLRjwaL8Y0ezqNqhjD6w0H2p0rDuEz2FKZqpqLnO8DCaWumKe8dsC/ljvVSSxng==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.15.10", - "@esbuild/linux-loong64": "0.15.10", - "esbuild-android-64": "0.15.10", - "esbuild-android-arm64": "0.15.10", - "esbuild-darwin-64": "0.15.10", - "esbuild-darwin-arm64": "0.15.10", - "esbuild-freebsd-64": "0.15.10", - "esbuild-freebsd-arm64": "0.15.10", - "esbuild-linux-32": "0.15.10", - "esbuild-linux-64": "0.15.10", - "esbuild-linux-arm": "0.15.10", - "esbuild-linux-arm64": "0.15.10", - "esbuild-linux-mips64le": "0.15.10", - "esbuild-linux-ppc64le": "0.15.10", - "esbuild-linux-riscv64": "0.15.10", - "esbuild-linux-s390x": "0.15.10", - "esbuild-netbsd-64": "0.15.10", - "esbuild-openbsd-64": "0.15.10", - "esbuild-sunos-64": "0.15.10", - "esbuild-windows-32": "0.15.10", - "esbuild-windows-64": "0.15.10", - "esbuild-windows-arm64": "0.15.10" - } - }, - "esbuild-windows-64": { - "version": "0.15.10", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.10.tgz", - "integrity": "sha512-2H0gdsyHi5x+8lbng3hLbxDWR7mKHWh5BXZGKVG830KUmXOOWFE2YKJ4tHRkejRduOGDrBvHBriYsGtmTv3ntA==", - "dev": true, - "optional": true - }, - "lit": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lit/-/lit-2.4.0.tgz", - "integrity": "sha512-fdgzxEtLrZFQU/BqTtxFQCLwlZd9bdat+ltzSFjvWkZrs7eBmeX0L5MHUMb3kYIkuS8Xlfnii/iI5klirF8/Xg==", - "requires": { - "@lit/reactive-element": "^1.4.0", - "lit-element": "^3.2.0", - "lit-html": "^2.4.0" - } - }, - "lit-element": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.2.2.tgz", - "integrity": "sha512-6ZgxBR9KNroqKb6+htkyBwD90XGRiqKDHVrW/Eh0EZ+l+iC+u+v+w3/BA5NGi4nizAVHGYvQBHUDuSmLjPp7NQ==", - "requires": { - "@lit/reactive-element": "^1.3.0", - "lit-html": "^2.2.0" - } - }, - "lit-html": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.4.0.tgz", - "integrity": "sha512-G6qXu4JNUpY6aaF2VMfaszhO9hlWw0hOTRFDmuMheg/nDYGB+2RztUSOyrzALAbr8Nh0Y7qjhYkReh3rPnplVg==", - "requires": { - "@types/trusted-types": "^2.0.2" - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - } - } -} diff --git a/toolkit/content/vendor/lit/package.json b/toolkit/content/vendor/lit/package.json deleted file mode 100644 index 5d727785da0b..000000000000 --- a/toolkit/content/vendor/lit/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "vendor-lit", - "version": "1.0.0", - "description": "Vendor the lit package", - "main": "index.mjs", - "scripts": { - "build": "esbuild index.mjs --bundle --outfile=lit.all.mjs --format=esm --legal-comments=inline", - "patch": "patch lit.all.mjs lit-html-no-inner-html.patch", - "mv-dest": "mkdirp ../../widgets/vendor && mv lit.all.mjs ../../widgets/vendor/lit.all.mjs", - "vendor": "npm ci && npm run build && npm run patch && npm run mv-dest", - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "MPL-2.0", - "dependencies": { - "lit": "^2.4.0" - }, - "devDependencies": { - "esbuild": "^0.15.10", - "mkdirp": "^1.0.4" - } -} diff --git a/toolkit/content/widgets/fx-toggle/fx-toggle.mjs b/toolkit/content/widgets/fx-toggle/fx-toggle.mjs index ebda9ded034a..df277db6686f 100644 --- a/toolkit/content/widgets/fx-toggle/fx-toggle.mjs +++ b/toolkit/content/widgets/fx-toggle/fx-toggle.mjs @@ -2,8 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at htp://mozilla.org/MPL/2.0/. */ -// Bug 1790483: Lit is not bundled yet, this is dev only. -// eslint-disable-next-line import/no-unresolved import { html, ifDefined } from "../vendor/lit.all.mjs"; import { MozLitElement } from "../lit-utils.mjs"; diff --git a/toolkit/content/widgets/fx-toggle/fx-toggle.stories.mjs b/toolkit/content/widgets/fx-toggle/fx-toggle.stories.mjs index 7b4ce521c140..edf748ce4ff9 100644 --- a/toolkit/content/widgets/fx-toggle/fx-toggle.stories.mjs +++ b/toolkit/content/widgets/fx-toggle/fx-toggle.stories.mjs @@ -2,8 +2,6 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// Bug 1790483: Lit is not bundled yet, this is dev only. -// eslint-disable-next-line import/no-unresolved import { html, ifDefined } from "../vendor/lit.all.mjs"; // eslint-disable-next-line import/no-unassigned-import import "./fx-toggle.mjs"; diff --git a/toolkit/content/widgets/lit-utils.mjs b/toolkit/content/widgets/lit-utils.mjs index 815a2d9b594f..38dbaaa04f2b 100644 --- a/toolkit/content/widgets/lit-utils.mjs +++ b/toolkit/content/widgets/lit-utils.mjs @@ -2,9 +2,25 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ -// Bug 1790483: Lit is not bundled yet, this is dev only. -// eslint-disable-next-line import/no-unresolved -import { query, queryAll, LitElement } from "./vendor/lit.all.mjs"; +import { LitElement } from "./vendor/lit.all.mjs"; + +/** + * Helper for our replacement of @query. Used with `static queries` property. + * + * https://github.com/lit/lit/blob/main/packages/reactive-element/src/decorators/query.ts + */ +function query(el, selector) { + return () => el.renderRoot.querySelector(selector); +} + +/** + * Helper for our replacement of @queryAll. Used with `static queries` property. + * + * https://github.com/lit/lit/blob/main/packages/reactive-element/src/decorators/query-all.ts + */ +function queryAll(el, selector) { + return () => el.renderRoot.querySelectorAll(selector); +} /** * MozLitElement provides extensions to the lit-provided LitElement class. @@ -72,9 +88,13 @@ export class MozLitElement extends LitElement { if (queries) { for (let [name, selector] of Object.entries(queries)) { if (selector.all) { - queryAll(selector.all)(this, name); + Object.defineProperty(this, name, { + get: queryAll(this, selector.all), + }); } else { - query(selector)(this, name); + Object.defineProperty(this, name, { + get: query(this, selector), + }); } } } diff --git a/toolkit/content/widgets/vendor/lit.all.mjs b/toolkit/content/widgets/vendor/lit.all.mjs new file mode 100644 index 000000000000..c0fe47dc3984 --- /dev/null +++ b/toolkit/content/widgets/vendor/lit.all.mjs @@ -0,0 +1,4491 @@ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const NODE_MODE$1 = false; +const global$2 = window; +/** + * Whether the current browser supports `adoptedStyleSheets`. + */ +const supportsAdoptingStyleSheets = global$2.ShadowRoot && + (global$2.ShadyCSS === undefined || global$2.ShadyCSS.nativeShadow) && + 'adoptedStyleSheets' in Document.prototype && + 'replace' in CSSStyleSheet.prototype; +const constructionToken = Symbol(); +const cssTagCache = new WeakMap(); +/** + * A container for a string of CSS text, that may be used to create a CSSStyleSheet. + * + * CSSResult is the return value of `css`-tagged template literals and + * `unsafeCSS()`. In order to ensure that CSSResults are only created via the + * `css` tag and `unsafeCSS()`, CSSResult cannot be constructed directly. + */ +class CSSResult { + constructor(cssText, strings, safeToken) { + // This property needs to remain unminified. + this['_$cssResult$'] = true; + if (safeToken !== constructionToken) { + throw new Error('CSSResult is not constructable. Use `unsafeCSS` or `css` instead.'); + } + this.cssText = cssText; + this._strings = strings; + } + // This is a getter so that it's lazy. In practice, this means stylesheets + // are not created until the first element instance is made. + get styleSheet() { + // If `supportsAdoptingStyleSheets` is true then we assume CSSStyleSheet is + // constructable. + let styleSheet = this._styleSheet; + const strings = this._strings; + if (supportsAdoptingStyleSheets && styleSheet === undefined) { + const cacheable = strings !== undefined && strings.length === 1; + if (cacheable) { + styleSheet = cssTagCache.get(strings); + } + if (styleSheet === undefined) { + (this._styleSheet = styleSheet = new CSSStyleSheet()).replaceSync(this.cssText); + if (cacheable) { + cssTagCache.set(strings, styleSheet); + } + } + } + return styleSheet; + } + toString() { + return this.cssText; + } +} +const textFromCSSResult = (value) => { + // This property needs to remain unminified. + if (value['_$cssResult$'] === true) { + return value.cssText; + } + else if (typeof value === 'number') { + return value; + } + else { + throw new Error(`Value passed to 'css' function must be a 'css' function result: ` + + `${value}. Use 'unsafeCSS' to pass non-literal values, but take care ` + + `to ensure page security.`); + } +}; +/** + * Wrap a value for interpolation in a {@linkcode css} tagged template literal. + * + * This is unsafe because untrusted CSS text can be used to phone home + * or exfiltrate data to an attacker controlled site. Take care to only use + * this with trusted input. + */ +const unsafeCSS = (value) => new CSSResult(typeof value === 'string' ? value : String(value), undefined, constructionToken); +/** + * A template literal tag which can be used with LitElement's + * {@linkcode LitElement.styles} property to set element styles. + * + * For security reasons, only literal string values and number may be used in + * embedded expressions. To incorporate non-literal values {@linkcode unsafeCSS} + * may be used inside an expression. + */ +const css = (strings, ...values) => { + const cssText = strings.length === 1 + ? strings[0] + : values.reduce((acc, v, idx) => acc + textFromCSSResult(v) + strings[idx + 1], strings[0]); + return new CSSResult(cssText, strings, constructionToken); +}; +/** + * Applies the given styles to a `shadowRoot`. When Shadow DOM is + * available but `adoptedStyleSheets` is not, styles are appended to the + * `shadowRoot` to [mimic spec behavior](https://wicg.github.io/construct-stylesheets/#using-constructed-stylesheets). + * Note, when shimming is used, any styles that are subsequently placed into + * the shadowRoot should be placed *before* any shimmed adopted styles. This + * will match spec behavior that gives adopted sheets precedence over styles in + * shadowRoot. + */ +const adoptStyles = (renderRoot, styles) => { + if (supportsAdoptingStyleSheets) { + renderRoot.adoptedStyleSheets = styles.map((s) => s instanceof CSSStyleSheet ? s : s.styleSheet); + } + else { + styles.forEach((s) => { + const style = document.createElement('style'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const nonce = global$2['litNonce']; + if (nonce !== undefined) { + style.setAttribute('nonce', nonce); + } + style.textContent = s.cssText; + renderRoot.appendChild(style); + }); + } +}; +const cssResultFromStyleSheet = (sheet) => { + let cssText = ''; + for (const rule of sheet.cssRules) { + cssText += rule.cssText; + } + return unsafeCSS(cssText); +}; +const getCompatibleStyle = supportsAdoptingStyleSheets || + (NODE_MODE$1 ) + ? (s) => s + : (s) => s instanceof CSSStyleSheet ? cssResultFromStyleSheet(s) : s; + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _d$1; +var _e; +const global$1 = window; +const trustedTypes$1 = global$1 + .trustedTypes; +// Temporary workaround for https://crbug.com/993268 +// Currently, any attribute starting with "on" is considered to be a +// TrustedScript source. Such boolean attributes must be set to the equivalent +// trusted emptyScript value. +const emptyStringForBooleanAttribute$1 = trustedTypes$1 + ? trustedTypes$1.emptyScript + : ''; +const polyfillSupport$2 = global$1.reactiveElementPolyfillSupport; +/* + * When using Closure Compiler, JSCompiler_renameProperty(property, object) is + * replaced at compile time by the munged name for object[property]. We cannot + * alias this function, so we have to use a small shim that has the same + * behavior when not compiling. + */ +/*@__INLINE__*/ +const JSCompiler_renameProperty = (prop, _obj) => prop; +const defaultConverter = { + toAttribute(value, type) { + switch (type) { + case Boolean: + value = value ? emptyStringForBooleanAttribute$1 : null; + break; + case Object: + case Array: + // if the value is `null` or `undefined` pass this through + // to allow removing/no change behavior. + value = value == null ? value : JSON.stringify(value); + break; + } + return value; + }, + fromAttribute(value, type) { + let fromValue = value; + switch (type) { + case Boolean: + fromValue = value !== null; + break; + case Number: + fromValue = value === null ? null : Number(value); + break; + case Object: + case Array: + // Do *not* generate exception when invalid JSON is set as elements + // don't normally complain on being mis-configured. + // TODO(sorvell): Do generate exception in *dev mode*. + try { + // Assert to adhere to Bazel's "must type assert JSON parse" rule. + fromValue = JSON.parse(value); + } + catch (e) { + fromValue = null; + } + break; + } + return fromValue; + }, +}; +/** + * Change function that returns true if `value` is different from `oldValue`. + * This method is used as the default for a property's `hasChanged` function. + */ +const notEqual = (value, old) => { + // This ensures (old==NaN, value==NaN) always returns false + return old !== value && (old === old || value === value); +}; +const defaultPropertyDeclaration = { + attribute: true, + type: String, + converter: defaultConverter, + reflect: false, + hasChanged: notEqual, +}; +/** + * The Closure JS Compiler doesn't currently have good support for static + * property semantics where "this" is dynamic (e.g. + * https://github.com/google/closure-compiler/issues/3177 and others) so we use + * this hack to bypass any rewriting by the compiler. + */ +const finalized = 'finalized'; +/** + * Base element class which manages element properties and attributes. When + * properties change, the `update` method is asynchronously called. This method + * should be supplied by subclassers to render updates as desired. + * @noInheritDoc + */ +class ReactiveElement extends HTMLElement { + constructor() { + super(); + this.__instanceProperties = new Map(); + /** + * True if there is a pending update as a result of calling `requestUpdate()`. + * Should only be read. + * @category updates + */ + this.isUpdatePending = false; + /** + * Is set to `true` after the first update. The element code cannot assume + * that `renderRoot` exists before the element `hasUpdated`. + * @category updates + */ + this.hasUpdated = false; + /** + * Name of currently reflecting property + */ + this.__reflectingProperty = null; + this._initialize(); + } + /** + * Adds an initializer function to the class that is called during instance + * construction. + * + * This is useful for code that runs against a `ReactiveElement` + * subclass, such as a decorator, that needs to do work for each + * instance, such as setting up a `ReactiveController`. + * + * ```ts + * const myDecorator = (target: typeof ReactiveElement, key: string) => { + * target.addInitializer((instance: ReactiveElement) => { + * // This is run during construction of the element + * new MyController(instance); + * }); + * } + * ``` + * + * Decorating a field will then cause each instance to run an initializer + * that adds a controller: + * + * ```ts + * class MyElement extends LitElement { + * @myDecorator foo; + * } + * ``` + * + * Initializers are stored per-constructor. Adding an initializer to a + * subclass does not add it to a superclass. Since initializers are run in + * constructors, initializers will run in order of the class hierarchy, + * starting with superclasses and progressing to the instance's class. + * + * @nocollapse + */ + static addInitializer(initializer) { + var _a; + (_a = this._initializers) !== null && _a !== void 0 ? _a : (this._initializers = []); + this._initializers.push(initializer); + } + /** + * Returns a list of attributes corresponding to the registered properties. + * @nocollapse + * @category attributes + */ + static get observedAttributes() { + // note: piggy backing on this to ensure we're finalized. + this.finalize(); + const attributes = []; + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + this.elementProperties.forEach((v, p) => { + const attr = this.__attributeNameForProperty(p, v); + if (attr !== undefined) { + this.__attributeToPropertyMap.set(attr, p); + attributes.push(attr); + } + }); + return attributes; + } + /** + * Creates a property accessor on the element prototype if one does not exist + * and stores a {@linkcode PropertyDeclaration} for the property with the + * given options. The property setter calls the property's `hasChanged` + * property option or uses a strict identity check to determine whether or not + * to request an update. + * + * This method may be overridden to customize properties; however, + * when doing so, it's important to call `super.createProperty` to ensure + * the property is setup correctly. This method calls + * `getPropertyDescriptor` internally to get a descriptor to install. + * To customize what properties do when they are get or set, override + * `getPropertyDescriptor`. To customize the options for a property, + * implement `createProperty` like this: + * + * ```ts + * static createProperty(name, options) { + * options = Object.assign(options, {myOption: true}); + * super.createProperty(name, options); + * } + * ``` + * + * @nocollapse + * @category properties + */ + static createProperty(name, options = defaultPropertyDeclaration) { + // if this is a state property, force the attribute to false. + if (options.state) { + // Cast as any since this is readonly. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + options.attribute = false; + } + // Note, since this can be called by the `@property` decorator which + // is called before `finalize`, we ensure finalization has been kicked off. + this.finalize(); + this.elementProperties.set(name, options); + // Do not generate an accessor if the prototype already has one, since + // it would be lost otherwise and that would never be the user's intention; + // Instead, we expect users to call `requestUpdate` themselves from + // user-defined accessors. Note that if the super has an accessor we will + // still overwrite it + if (!options.noAccessor && !this.prototype.hasOwnProperty(name)) { + const key = typeof name === 'symbol' ? Symbol() : `__${name}`; + const descriptor = this.getPropertyDescriptor(name, key, options); + if (descriptor !== undefined) { + Object.defineProperty(this.prototype, name, descriptor); + } + } + } + /** + * Returns a property descriptor to be defined on the given named property. + * If no descriptor is returned, the property will not become an accessor. + * For example, + * + * ```ts + * class MyElement extends LitElement { + * static getPropertyDescriptor(name, key, options) { + * const defaultDescriptor = + * super.getPropertyDescriptor(name, key, options); + * const setter = defaultDescriptor.set; + * return { + * get: defaultDescriptor.get, + * set(value) { + * setter.call(this, value); + * // custom action. + * }, + * configurable: true, + * enumerable: true + * } + * } + * } + * ``` + * + * @nocollapse + * @category properties + */ + static getPropertyDescriptor(name, key, options) { + return { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + get() { + return this[key]; + }, + set(value) { + const oldValue = this[name]; + this[key] = value; + this.requestUpdate(name, oldValue, options); + }, + configurable: true, + enumerable: true, + }; + } + /** + * Returns the property options associated with the given property. + * These options are defined with a `PropertyDeclaration` via the `properties` + * object or the `@property` decorator and are registered in + * `createProperty(...)`. + * + * Note, this method should be considered "final" and not overridden. To + * customize the options for a given property, override + * {@linkcode createProperty}. + * + * @nocollapse + * @final + * @category properties + */ + static getPropertyOptions(name) { + return this.elementProperties.get(name) || defaultPropertyDeclaration; + } + /** + * Creates property accessors for registered properties, sets up element + * styling, and ensures any superclasses are also finalized. Returns true if + * the element was finalized. + * @nocollapse + */ + static finalize() { + if (this.hasOwnProperty(finalized)) { + return false; + } + this[finalized] = true; + // finalize any superclasses + const superCtor = Object.getPrototypeOf(this); + superCtor.finalize(); + this.elementProperties = new Map(superCtor.elementProperties); + // initialize Map populated in observedAttributes + this.__attributeToPropertyMap = new Map(); + // make any properties + // Note, only process "own" properties since this element will inherit + // any properties defined on the superClass, and finalization ensures + // the entire prototype chain is finalized. + if (this.hasOwnProperty(JSCompiler_renameProperty('properties'))) { + const props = this.properties; + // support symbols in properties (IE11 does not support this) + const propKeys = [ + ...Object.getOwnPropertyNames(props), + ...Object.getOwnPropertySymbols(props), + ]; + // This for/of is ok because propKeys is an array + for (const p of propKeys) { + // note, use of `any` is due to TypeScript lack of support for symbol in + // index types + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.createProperty(p, props[p]); + } + } + this.elementStyles = this.finalizeStyles(this.styles); + return true; + } + /** + * Takes the styles the user supplied via the `static styles` property and + * returns the array of styles to apply to the element. + * Override this method to integrate into a style management system. + * + * Styles are deduplicated preserving the _last_ instance in the list. This + * is a performance optimization to avoid duplicated styles that can occur + * especially when composing via subclassing. The last item is kept to try + * to preserve the cascade order with the assumption that it's most important + * that last added styles override previous styles. + * + * @nocollapse + * @category styles + */ + static finalizeStyles(styles) { + const elementStyles = []; + if (Array.isArray(styles)) { + // Dedupe the flattened array in reverse order to preserve the last items. + // Casting to Array works around TS error that + // appears to come from trying to flatten a type CSSResultArray. + const set = new Set(styles.flat(Infinity).reverse()); + // Then preserve original order by adding the set items in reverse order. + for (const s of set) { + elementStyles.unshift(getCompatibleStyle(s)); + } + } + else if (styles !== undefined) { + elementStyles.push(getCompatibleStyle(styles)); + } + return elementStyles; + } + /** + * Returns the property name for the given attribute `name`. + * @nocollapse + */ + static __attributeNameForProperty(name, options) { + const attribute = options.attribute; + return attribute === false + ? undefined + : typeof attribute === 'string' + ? attribute + : typeof name === 'string' + ? name.toLowerCase() + : undefined; + } + /** + * Internal only override point for customizing work done when elements + * are constructed. + * + * @internal + */ + _initialize() { + var _a; + this.__updatePromise = new Promise((res) => (this.enableUpdating = res)); + this._$changedProperties = new Map(); + this.__saveInstanceProperties(); + // ensures first update will be caught by an early access of + // `updateComplete` + this.requestUpdate(); + (_a = this.constructor._initializers) === null || _a === void 0 ? void 0 : _a.forEach((i) => i(this)); + } + /** + * Registers a `ReactiveController` to participate in the element's reactive + * update cycle. The element automatically calls into any registered + * controllers during its lifecycle callbacks. + * + * If the element is connected when `addController()` is called, the + * controller's `hostConnected()` callback will be immediately called. + * @category controllers + */ + addController(controller) { + var _a, _b; + ((_a = this.__controllers) !== null && _a !== void 0 ? _a : (this.__controllers = [])).push(controller); + // If a controller is added after the element has been connected, + // call hostConnected. Note, re-using existence of `renderRoot` here + // (which is set in connectedCallback) to avoid the need to track a + // first connected state. + if (this.renderRoot !== undefined && this.isConnected) { + (_b = controller.hostConnected) === null || _b === void 0 ? void 0 : _b.call(controller); + } + } + /** + * Removes a `ReactiveController` from the element. + * @category controllers + */ + removeController(controller) { + var _a; + // Note, if the indexOf is -1, the >>> will flip the sign which makes the + // splice do nothing. + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.splice(this.__controllers.indexOf(controller) >>> 0, 1); + } + /** + * Fixes any properties set on the instance before upgrade time. + * Otherwise these would shadow the accessor and break these properties. + * The properties are stored in a Map which is played back after the + * constructor runs. Note, on very old versions of Safari (<=9) or Chrome + * (<=41), properties created for native platform properties like (`id` or + * `name`) may not have default values set in the element constructor. On + * these browsers native properties appear on instances and therefore their + * default value will overwrite any element default (e.g. if the element sets + * this.id = 'id' in the constructor, the 'id' will become '' since this is + * the native platform default). + */ + __saveInstanceProperties() { + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + this.constructor.elementProperties.forEach((_v, p) => { + if (this.hasOwnProperty(p)) { + this.__instanceProperties.set(p, this[p]); + delete this[p]; + } + }); + } + /** + * Returns the node into which the element should render and by default + * creates and returns an open shadowRoot. Implement to customize where the + * element's DOM is rendered. For example, to render into the element's + * childNodes, return `this`. + * + * @return Returns a node into which to render. + * @category rendering + */ + createRenderRoot() { + var _a; + const renderRoot = (_a = this.shadowRoot) !== null && _a !== void 0 ? _a : this.attachShadow(this.constructor.shadowRootOptions); + adoptStyles(renderRoot, this.constructor.elementStyles); + return renderRoot; + } + /** + * On first connection, creates the element's renderRoot, sets up + * element styling, and enables updating. + * @category lifecycle + */ + connectedCallback() { + var _a; + // create renderRoot before first update. + if (this.renderRoot === undefined) { + this.renderRoot = this.createRenderRoot(); + } + this.enableUpdating(true); + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostConnected) === null || _a === void 0 ? void 0 : _a.call(c); }); + } + /** + * Note, this method should be considered final and not overridden. It is + * overridden on the element instance with a function that triggers the first + * update. + * @category updates + */ + enableUpdating(_requestedUpdate) { } + /** + * Allows for `super.disconnectedCallback()` in extensions while + * reserving the possibility of making non-breaking feature additions + * when disconnecting at some point in the future. + * @category lifecycle + */ + disconnectedCallback() { + var _a; + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostDisconnected) === null || _a === void 0 ? void 0 : _a.call(c); }); + } + /** + * Synchronizes property values when attributes change. + * + * Specifically, when an attribute is set, the corresponding property is set. + * You should rarely need to implement this callback. If this method is + * overridden, `super.attributeChangedCallback(name, _old, value)` must be + * called. + * + * See [using the lifecycle callbacks](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements#using_the_lifecycle_callbacks) + * on MDN for more information about the `attributeChangedCallback`. + * @category attributes + */ + attributeChangedCallback(name, _old, value) { + this._$attributeToProperty(name, value); + } + __propertyToAttribute(name, value, options = defaultPropertyDeclaration) { + var _a; + const attr = this.constructor.__attributeNameForProperty(name, options); + if (attr !== undefined && options.reflect === true) { + const converter = ((_a = options.converter) === null || _a === void 0 ? void 0 : _a.toAttribute) !== + undefined + ? options.converter + : defaultConverter; + const attrValue = converter.toAttribute(value, options.type); + // Track if the property is being reflected to avoid + // setting the property again via `attributeChangedCallback`. Note: + // 1. this takes advantage of the fact that the callback is synchronous. + // 2. will behave incorrectly if multiple attributes are in the reaction + // stack at time of calling. However, since we process attributes + // in `update` this should not be possible (or an extreme corner case + // that we'd like to discover). + // mark state reflecting + this.__reflectingProperty = name; + if (attrValue == null) { + this.removeAttribute(attr); + } + else { + this.setAttribute(attr, attrValue); + } + // mark state not reflecting + this.__reflectingProperty = null; + } + } + /** @internal */ + _$attributeToProperty(name, value) { + var _a; + const ctor = this.constructor; + // Note, hint this as an `AttributeMap` so closure clearly understands + // the type; it has issues with tracking types through statics + const propName = ctor.__attributeToPropertyMap.get(name); + // Use tracking info to avoid reflecting a property value to an attribute + // if it was just set because the attribute changed. + if (propName !== undefined && this.__reflectingProperty !== propName) { + const options = ctor.getPropertyOptions(propName); + const converter = typeof options.converter === 'function' + ? { fromAttribute: options.converter } + : ((_a = options.converter) === null || _a === void 0 ? void 0 : _a.fromAttribute) !== undefined + ? options.converter + : defaultConverter; + // mark state reflecting + this.__reflectingProperty = propName; + this[propName] = converter.fromAttribute(value, options.type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ); + // mark state not reflecting + this.__reflectingProperty = null; + } + } + /** + * Requests an update which is processed asynchronously. This should be called + * when an element should update based on some state not triggered by setting + * a reactive property. In this case, pass no arguments. It should also be + * called when manually implementing a property setter. In this case, pass the + * property `name` and `oldValue` to ensure that any configured property + * options are honored. + * + * @param name name of requesting property + * @param oldValue old value of requesting property + * @param options property options to use instead of the previously + * configured options + * @category updates + */ + requestUpdate(name, oldValue, options) { + let shouldRequestUpdate = true; + // If we have a property key, perform property update steps. + if (name !== undefined) { + options = + options || + this.constructor.getPropertyOptions(name); + const hasChanged = options.hasChanged || notEqual; + if (hasChanged(this[name], oldValue)) { + if (!this._$changedProperties.has(name)) { + this._$changedProperties.set(name, oldValue); + } + // Add to reflecting properties set. + // Note, it's important that every change has a chance to add the + // property to `_reflectingProperties`. This ensures setting + // attribute + property reflects correctly. + if (options.reflect === true && this.__reflectingProperty !== name) { + if (this.__reflectingProperties === undefined) { + this.__reflectingProperties = new Map(); + } + this.__reflectingProperties.set(name, options); + } + } + else { + // Abort the request if the property should not be considered changed. + shouldRequestUpdate = false; + } + } + if (!this.isUpdatePending && shouldRequestUpdate) { + this.__updatePromise = this.__enqueueUpdate(); + } + // Note, since this no longer returns a promise, in dev mode we return a + // thenable which warns if it's called. + return undefined; + } + /** + * Sets up the element to asynchronously update. + */ + async __enqueueUpdate() { + this.isUpdatePending = true; + try { + // Ensure any previous update has resolved before updating. + // This `await` also ensures that property changes are batched. + await this.__updatePromise; + } + catch (e) { + // Refire any previous errors async so they do not disrupt the update + // cycle. Errors are refired so developers have a chance to observe + // them, and this can be done by implementing + // `window.onunhandledrejection`. + Promise.reject(e); + } + const result = this.scheduleUpdate(); + // If `scheduleUpdate` returns a Promise, we await it. This is done to + // enable coordinating updates with a scheduler. Note, the result is + // checked to avoid delaying an additional microtask unless we need to. + if (result != null) { + await result; + } + return !this.isUpdatePending; + } + /** + * Schedules an element update. You can override this method to change the + * timing of updates by returning a Promise. The update will await the + * returned Promise, and you should resolve the Promise to allow the update + * to proceed. If this method is overridden, `super.scheduleUpdate()` + * must be called. + * + * For instance, to schedule updates to occur just before the next frame: + * + * ```ts + * override protected async scheduleUpdate(): Promise { + * await new Promise((resolve) => requestAnimationFrame(() => resolve())); + * super.scheduleUpdate(); + * } + * ``` + * @category updates + */ + scheduleUpdate() { + return this.performUpdate(); + } + /** + * Performs an element update. Note, if an exception is thrown during the + * update, `firstUpdated` and `updated` will not be called. + * + * Call `performUpdate()` to immediately process a pending update. This should + * generally not be needed, but it can be done in rare cases when you need to + * update synchronously. + * + * Note: To ensure `performUpdate()` synchronously completes a pending update, + * it should not be overridden. In LitElement 2.x it was suggested to override + * `performUpdate()` to also customizing update scheduling. Instead, you should now + * override `scheduleUpdate()`. For backwards compatibility with LitElement 2.x, + * scheduling updates via `performUpdate()` continues to work, but will make + * also calling `performUpdate()` to synchronously process updates difficult. + * + * @category updates + */ + performUpdate() { + var _b; + // Abort any update if one is not pending when this is called. + // This can happen if `performUpdate` is called early to "flush" + // the update. + if (!this.isUpdatePending) { + return; + } + // create renderRoot before first update. + if (!this.hasUpdated) ; + // Mixin instance properties once, if they exist. + if (this.__instanceProperties) { + // Use forEach so this works even if for/of loops are compiled to for loops + // expecting arrays + // eslint-disable-next-line @typescript-eslint/no-explicit-any + this.__instanceProperties.forEach((v, p) => (this[p] = v)); + this.__instanceProperties = undefined; + } + let shouldUpdate = false; + const changedProperties = this._$changedProperties; + try { + shouldUpdate = this.shouldUpdate(changedProperties); + if (shouldUpdate) { + this.willUpdate(changedProperties); + (_b = this.__controllers) === null || _b === void 0 ? void 0 : _b.forEach((c) => { var _a; return (_a = c.hostUpdate) === null || _a === void 0 ? void 0 : _a.call(c); }); + this.update(changedProperties); + } + else { + this.__markUpdated(); + } + } + catch (e) { + // Prevent `firstUpdated` and `updated` from running when there's an + // update exception. + shouldUpdate = false; + // Ensure element can accept additional updates after an exception. + this.__markUpdated(); + throw e; + } + // The update is no longer considered pending and further updates are now allowed. + if (shouldUpdate) { + this._$didUpdate(changedProperties); + } + } + /** + * Invoked before `update()` to compute values needed during the update. + * + * Implement `willUpdate` to compute property values that depend on other + * properties and are used in the rest of the update process. + * + * ```ts + * willUpdate(changedProperties) { + * // only need to check changed properties for an expensive computation. + * if (changedProperties.has('firstName') || changedProperties.has('lastName')) { + * this.sha = computeSHA(`${this.firstName} ${this.lastName}`); + * } + * } + * + * render() { + * return html`SHA: ${this.sha}`; + * } + * ``` + * + * @category updates + */ + willUpdate(_changedProperties) { } + // Note, this is an override point for polyfill-support. + // @internal + _$didUpdate(changedProperties) { + var _a; + (_a = this.__controllers) === null || _a === void 0 ? void 0 : _a.forEach((c) => { var _a; return (_a = c.hostUpdated) === null || _a === void 0 ? void 0 : _a.call(c); }); + if (!this.hasUpdated) { + this.hasUpdated = true; + this.firstUpdated(changedProperties); + } + this.updated(changedProperties); + } + __markUpdated() { + this._$changedProperties = new Map(); + this.isUpdatePending = false; + } + /** + * Returns a Promise that resolves when the element has completed updating. + * The Promise value is a boolean that is `true` if the element completed the + * update without triggering another update. The Promise result is `false` if + * a property was set inside `updated()`. If the Promise is rejected, an + * exception was thrown during the update. + * + * To await additional asynchronous work, override the `getUpdateComplete` + * method. For example, it is sometimes useful to await a rendered element + * before fulfilling this Promise. To do this, first await + * `super.getUpdateComplete()`, then any subsequent state. + * + * @return A promise of a boolean that resolves to true if the update completed + * without triggering another update. + * @category updates + */ + get updateComplete() { + return this.getUpdateComplete(); + } + /** + * Override point for the `updateComplete` promise. + * + * It is not safe to override the `updateComplete` getter directly due to a + * limitation in TypeScript which means it is not possible to call a + * superclass getter (e.g. `super.updateComplete.then(...)`) when the target + * language is ES5 (https://github.com/microsoft/TypeScript/issues/338). + * This method should be overridden instead. For example: + * + * ```ts + * class MyElement extends LitElement { + * override async getUpdateComplete() { + * const result = await super.getUpdateComplete(); + * await this._myChild.updateComplete; + * return result; + * } + * } + * ``` + * + * @return A promise of a boolean that resolves to true if the update completed + * without triggering another update. + * @category updates + */ + getUpdateComplete() { + return this.__updatePromise; + } + /** + * Controls whether or not `update()` should be called when the element requests + * an update. By default, this method always returns `true`, but this can be + * customized to control when to update. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + shouldUpdate(_changedProperties) { + return true; + } + /** + * Updates the element. This method reflects property values to attributes. + * It can be overridden to render and keep updated element DOM. + * Setting properties inside this method will *not* trigger + * another update. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + update(_changedProperties) { + if (this.__reflectingProperties !== undefined) { + // Use forEach so this works even if for/of loops are compiled to for + // loops expecting arrays + this.__reflectingProperties.forEach((v, k) => this.__propertyToAttribute(k, this[k], v)); + this.__reflectingProperties = undefined; + } + this.__markUpdated(); + } + /** + * Invoked whenever the element is updated. Implement to perform + * post-updating tasks via DOM APIs, for example, focusing an element. + * + * Setting properties inside this method will trigger the element to update + * again after this update cycle completes. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + updated(_changedProperties) { } + /** + * Invoked when the element is first updated. Implement to perform one time + * work on the element after update. + * + * ```ts + * firstUpdated() { + * this.renderRoot.getElementById('my-text-area').focus(); + * } + * ``` + * + * Setting properties inside this method will trigger the element to update + * again after this update cycle completes. + * + * @param _changedProperties Map of changed properties with old values + * @category updates + */ + firstUpdated(_changedProperties) { } +} +_e = finalized; +/** + * Marks class as having finished creating properties. + */ +ReactiveElement[_e] = true; +/** + * Memoized list of all element properties, including any superclass properties. + * Created lazily on user subclasses when finalizing the class. + * @nocollapse + * @category properties + */ +ReactiveElement.elementProperties = new Map(); +/** + * Memoized list of all element styles. + * Created lazily on user subclasses when finalizing the class. + * @nocollapse + * @category styles + */ +ReactiveElement.elementStyles = []; +/** + * Options used when calling `attachShadow`. Set this property to customize + * the options for the shadowRoot; for example, to create a closed + * shadowRoot: `{mode: 'closed'}`. + * + * Note, these options are used in `createRenderRoot`. If this method + * is customized, options should be respected if possible. + * @nocollapse + * @category rendering + */ +ReactiveElement.shadowRootOptions = { mode: 'open' }; +// Apply polyfills if available +polyfillSupport$2 === null || polyfillSupport$2 === void 0 ? void 0 : polyfillSupport$2({ ReactiveElement }); +// IMPORTANT: do not change the property name or the assignment expression. +// This line will be used in regexes to search for ReactiveElement usage. +((_d$1 = global$1.reactiveElementVersions) !== null && _d$1 !== void 0 ? _d$1 : (global$1.reactiveElementVersions = [])).push('1.4.1'); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +var _d; +// Use window for browser builds because IE11 doesn't have globalThis. +const global = window; +const __moz_domParser = new DOMParser(); +const wrap$1 = (node) => node; +const trustedTypes = global.trustedTypes; +/** + * Our TrustedTypePolicy for HTML which is declared using the html template + * tag function. + * + * That HTML is a developer-authored constant, and is parsed with innerHTML + * before any untrusted expressions have been mixed in. Therefor it is + * considered safe by construction. + */ +const policy = trustedTypes + ? trustedTypes.createPolicy('lit-html', { + createHTML: (s) => s, + }) + : undefined; +// Added to an attribute name to mark the attribute as bound so we can find +// it easily. +const boundAttributeSuffix = '$lit$'; +// This marker is used in many syntactic positions in HTML, so it must be +// a valid element name and attribute name. We don't support dynamic names (yet) +// but this at least ensures that the parse tree is closer to the template +// intention. +const marker = `lit$${String(Math.random()).slice(9)}$`; +// String used to tell if a comment is a marker comment +const markerMatch = '?' + marker; +// Text used to insert a comment marker node. We use processing instruction +// syntax because it's slightly smaller, but parses as a comment node. +const nodeMarker = `<${markerMatch}>`; +const d = document; +// Creates a dynamic marker. We never have to search for these in the DOM. +const createMarker$1 = (v = '') => d.createComment(v); +const isPrimitive$1 = (value) => value === null || (typeof value != 'object' && typeof value != 'function'); +const isArray = Array.isArray; +const isIterable = (value) => isArray(value) || + // eslint-disable-next-line @typescript-eslint/no-explicit-any + typeof (value === null || value === void 0 ? void 0 : value[Symbol.iterator]) === 'function'; +const SPACE_CHAR = `[ \t\n\f\r]`; +const ATTR_VALUE_CHAR = `[^ \t\n\f\r"'\`<>=]`; +const NAME_CHAR = `[^\\s"'>=/]`; +// These regexes represent the five parsing states that we care about in the +// Template's HTML scanner. They match the *end* of the state they're named +// after. +// Depending on the match, we transition to a new state. If there's no match, +// we stay in the same state. +// Note that the regexes are stateful. We utilize lastIndex and sync it +// across the multiple regexes used. In addition to the five regexes below +// we also dynamically create a regex to find the matching end tags for raw +// text elements. +/** + * End of text is: `<` followed by: + * (comment start) or (tag) or (dynamic tag binding) + */ +const textEndRegex = /<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g; +const COMMENT_START = 1; +const TAG_NAME = 2; +const DYNAMIC_TAG_NAME = 3; +const commentEndRegex = /-->/g; +/** + * Comments not started with `--my-button-color` + prop = prop + .replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g, '-$&') + .toLowerCase(); + return style + `${prop}:${value};`; + }, ''); + } + update(part, [styleInfo]) { + const { style } = part.element; + if (this._previousStyleProperties === undefined) { + this._previousStyleProperties = new Set(); + for (const name in styleInfo) { + this._previousStyleProperties.add(name); + } + return this.render(styleInfo); + } + // Remove old properties that no longer exist in styleInfo + // We use forEach() instead of for-of so that re don't require down-level + // iteration. + this._previousStyleProperties.forEach((name) => { + // If the name isn't in styleInfo or it's null/undefined + if (styleInfo[name] == null) { + this._previousStyleProperties.delete(name); + if (name.includes('-')) { + style.removeProperty(name); + } + else { + // Note reset using empty string (vs null) as IE11 does not always + // reset via null (https://developer.mozilla.org/en-US/docs/Web/API/ElementCSSInlineStyle/style#setting_styles) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + style[name] = ''; + } + } + }); + // Add or update properties + for (const name in styleInfo) { + const value = styleInfo[name]; + if (value != null) { + this._previousStyleProperties.add(name); + if (name.includes('-')) { + style.setProperty(name, value); + } + else { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + style[name] = value; + } + } + } + return noChange; + } +} +/** + * A directive that applies CSS properties to an element. + * + * `styleMap` can only be used in the `style` attribute and must be the only + * expression in the attribute. It takes the property names in the + * {@link StyleInfo styleInfo} object and adds the property values as CSS + * properties. Property names with dashes (`-`) are assumed to be valid CSS + * property names and set on the element's style object using `setProperty()`. + * Names without dashes are assumed to be camelCased JavaScript property names + * and set on the element's style object using property assignment, allowing the + * style object to translate JavaScript-style names to CSS property names. + * + * For example `styleMap({backgroundColor: 'red', 'border-top': '5px', '--size': + * '0'})` sets the `background-color`, `border-top` and `--size` properties. + * + * @param styleInfo + * @see {@link https://lit.dev/docs/templates/directives/#stylemap styleMap code samples on Lit.dev} + */ +const styleMap = directive(StyleMapDirective); + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +class TemplateContentDirective extends Directive { + constructor(partInfo) { + super(partInfo); + if (partInfo.type !== PartType.CHILD) { + throw new Error('templateContent can only be used in child bindings'); + } + } + render(template) { + if (this._previousTemplate === template) { + return noChange; + } + this._previousTemplate = template; + return document.importNode(template.content, true); + } +} +/** + * Renders the content of a template element as HTML. + * + * Note, the template should be developer controlled and not user controlled. + * Rendering a user-controlled template with this directive + * could lead to cross-site-scripting vulnerabilities. + */ +const templateContent = directive(TemplateContentDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const HTML_RESULT = 1; +class UnsafeHTMLDirective extends Directive { + constructor(partInfo) { + super(partInfo); + this._value = nothing; + if (partInfo.type !== PartType.CHILD) { + throw new Error(`${this.constructor.directiveName}() can only be used in child bindings`); + } + } + render(value) { + if (value === nothing || value == null) { + this._templateResult = undefined; + return (this._value = value); + } + if (value === noChange) { + return value; + } + if (typeof value != 'string') { + throw new Error(`${this.constructor.directiveName}() called with a non-string value`); + } + if (value === this._value) { + return this._templateResult; + } + this._value = value; + const strings = [value]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + strings.raw = strings; + // WARNING: impersonating a TemplateResult like this is extremely + // dangerous. Third-party directives should not do this. + return (this._templateResult = { + // Cast to a known set of integers that satisfy ResultType so that we + // don't have to export ResultType and possibly encourage this pattern. + // This property needs to remain unminified. + ['_$litType$']: this.constructor + .resultType, + strings, + values: [], + }); + } +} +UnsafeHTMLDirective.directiveName = 'unsafeHTML'; +UnsafeHTMLDirective.resultType = HTML_RESULT; +/** + * Renders the result as HTML, rather than text. + * + * The values `undefined`, `null`, and `nothing`, will all result in no content + * (empty string) being rendered. + * + * Note, this is unsafe to use with any user-provided input that hasn't been + * sanitized or escaped, as it may lead to cross-site-scripting + * vulnerabilities. + */ +const unsafeHTML = directive(UnsafeHTMLDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const SVG_RESULT = 2; +class UnsafeSVGDirective extends UnsafeHTMLDirective { +} +UnsafeSVGDirective.directiveName = 'unsafeSVG'; +UnsafeSVGDirective.resultType = SVG_RESULT; +/** + * Renders the result as SVG, rather than text. + * + * The values `undefined`, `null`, and `nothing`, will all result in no content + * (empty string) being rendered. + * + * Note, this is unsafe to use with any user-provided input that hasn't been + * sanitized or escaped, as it may lead to cross-site-scripting + * vulnerabilities. + */ +const unsafeSVG = directive(UnsafeSVGDirective); + +/** + * @license + * Copyright 2017 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +const isPromise = (x) => { + return !isPrimitive(x) && typeof x.then === 'function'; +}; +// Effectively infinity, but a SMI. +const _infinity = 0x3fffffff; +class UntilDirective extends AsyncDirective { + constructor() { + super(...arguments); + this.__lastRenderedIndex = _infinity; + this.__values = []; + this.__weakThis = new PseudoWeakRef(this); + this.__pauser = new Pauser(); + } + render(...args) { + var _a; + return (_a = args.find((x) => !isPromise(x))) !== null && _a !== void 0 ? _a : noChange; + } + update(_part, args) { + const previousValues = this.__values; + let previousLength = previousValues.length; + this.__values = args; + const weakThis = this.__weakThis; + const pauser = this.__pauser; + // If our initial render occurs while disconnected, ensure that the pauser + // and weakThis are in the disconnected state + if (!this.isConnected) { + this.disconnected(); + } + for (let i = 0; i < args.length; i++) { + // If we've rendered a higher-priority value already, stop. + if (i > this.__lastRenderedIndex) { + break; + } + const value = args[i]; + // Render non-Promise values immediately + if (!isPromise(value)) { + this.__lastRenderedIndex = i; + // Since a lower-priority value will never overwrite a higher-priority + // synchronous value, we can stop processing now. + return value; + } + // If this is a Promise we've already handled, skip it. + if (i < previousLength && value === previousValues[i]) { + continue; + } + // We have a Promise that we haven't seen before, so priorities may have + // changed. Forget what we rendered before. + this.__lastRenderedIndex = _infinity; + previousLength = 0; + // Note, the callback avoids closing over `this` so that the directive + // can be gc'ed before the promise resolves; instead `this` is retrieved + // from `weakThis`, which can break the hard reference in the closure when + // the directive disconnects + Promise.resolve(value).then(async (result) => { + // If we're disconnected, wait until we're (maybe) reconnected + // The while loop here handles the case that the connection state + // thrashes, causing the pauser to resume and then get re-paused + while (pauser.get()) { + await pauser.get(); + } + // If the callback gets here and there is no `this`, it means that the + // directive has been disconnected and garbage collected and we don't + // need to do anything else + const _this = weakThis.deref(); + if (_this !== undefined) { + const index = _this.__values.indexOf(value); + // If state.values doesn't contain the value, we've re-rendered without + // the value, so don't render it. Then, only render if the value is + // higher-priority than what's already been rendered. + if (index > -1 && index < _this.__lastRenderedIndex) { + _this.__lastRenderedIndex = index; + _this.setValue(result); + } + } + }); + } + return noChange; + } + disconnected() { + this.__weakThis.disconnect(); + this.__pauser.pause(); + } + reconnected() { + this.__weakThis.reconnect(this); + this.__pauser.resume(); + } +} +/** + * Renders one of a series of values, including Promises, to a Part. + * + * Values are rendered in priority order, with the first argument having the + * highest priority and the last argument having the lowest priority. If a + * value is a Promise, low-priority values will be rendered until it resolves. + * + * The priority of values can be used to create placeholder content for async + * data. For example, a Promise with pending content can be the first, + * highest-priority, argument, and a non_promise loading indicator template can + * be used as the second, lower-priority, argument. The loading indicator will + * render immediately, and the primary content will render when the Promise + * resolves. + * + * Example: + * + * ```js + * const content = fetch('./content.txt').then(r => r.text()); + * html`${until(content, html`Loading...`)}` + * ``` + */ +const until = directive(UntilDirective); +/** + * The type of the class that powers this directive. Necessary for naming the + * directive's return type. + */ +// export type {UntilDirective}; + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +function when(condition, trueCase, falseCase) { + return condition ? trueCase() : falseCase === null || falseCase === void 0 ? void 0 : falseCase(); +} + +/** + * @license + * Copyright 2020 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +/** + * Prevents JSON injection attacks. + * + * The goals of this brand: + * 1) fast to check + * 2) code is small on the wire + * 3) multiple versions of Lit in a single page will all produce mutually + * interoperable StaticValues + * 4) normal JSON.parse (without an unusual reviver) can not produce a + * StaticValue + * + * Symbols satisfy (1), (2), and (4). We use Symbol.for to satisfy (3), but + * we don't care about the key, so we break ties via (2) and use the empty + * string. + */ +const brand = Symbol.for(''); +/** Safely extracts the string part of a StaticValue. */ +const unwrapStaticValue = (value) => { + if ((value === null || value === void 0 ? void 0 : value.r) !== brand) { + return undefined; + } + return value === null || value === void 0 ? void 0 : value['_$litStatic$']; +}; +/** + * Wraps a string so that it behaves like part of the static template + * strings instead of a dynamic value. + * + * Users must take care to ensure that adding the static string to the template + * results in well-formed HTML, or else templates may break unexpectedly. + * + * Note that this function is unsafe to use on untrusted content, as it will be + * directly parsed into HTML. Do not pass user input to this function + * without sanitizing it. + * + * Static values can be changed, but they will cause a complete re-render + * since they effectively create a new template. + */ +const unsafeStatic = (value) => ({ + ['_$litStatic$']: value, + r: brand, +}); +const textFromStatic = (value) => { + if (value['_$litStatic$'] !== undefined) { + return value['_$litStatic$']; + } + else { + throw new Error(`Value passed to 'literal' function must be a 'literal' result: ${value}. Use 'unsafeStatic' to pass non-literal values, but + take care to ensure page security.`); + } +}; +/** + * Tags a string literal so that it behaves like part of the static template + * strings instead of a dynamic value. + * + * The only values that may be used in template expressions are other tagged + * `literal` results or `unsafeStatic` values (note that untrusted content + * should never be passed to `unsafeStatic`). + * + * Users must take care to ensure that adding the static string to the template + * results in well-formed HTML, or else templates may break unexpectedly. + * + * Static values can be changed, but they will cause a complete re-render since + * they effectively create a new template. + */ +const literal = (strings, ...values) => ({ + ['_$litStatic$']: values.reduce((acc, v, idx) => acc + textFromStatic(v) + strings[idx + 1], strings[0]), + r: brand, +}); +const stringsCache = new Map(); +/** + * Wraps a lit-html template tag (`html` or `svg`) to add static value support. + */ +const withStatic = (coreTag) => (strings, ...values) => { + const l = values.length; + let staticValue; + let dynamicValue; + const staticStrings = []; + const dynamicValues = []; + let i = 0; + let hasStatics = false; + let s; + while (i < l) { + s = strings[i]; + // Collect any unsafeStatic values, and their following template strings + // so that we treat a run of template strings and unsafe static values as + // a single template string. + while (i < l && + ((dynamicValue = values[i]), + (staticValue = unwrapStaticValue(dynamicValue))) !== undefined) { + s += staticValue + strings[++i]; + hasStatics = true; + } + dynamicValues.push(dynamicValue); + staticStrings.push(s); + i++; + } + // If the last value isn't static (which would have consumed the last + // string), then we need to add the last string. + if (i === l) { + staticStrings.push(strings[l]); + } + if (hasStatics) { + const key = staticStrings.join('$$lit$$'); + strings = stringsCache.get(key); + if (strings === undefined) { + // Beware: in general this pattern is unsafe, and doing so may bypass + // lit's security checks and allow an attacker to execute arbitrary + // code and inject arbitrary content. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + staticStrings.raw = staticStrings; + stringsCache.set(key, (strings = staticStrings)); + } + values = dynamicValues; + } + return coreTag(strings, ...values); +}; +/** + * Interprets a template literal as an HTML template that can efficiently + * render to and update a container. + * + * Includes static value support from `lit-html/static.js`. + */ +const html = withStatic(html$1); +/** + * Interprets a template literal as an SVG template that can efficiently + * render to and update a container. + * + * Includes static value support from `lit-html/static.js`. + */ +const svg = withStatic(svg$1); + +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: BSD-3-Clause + */ +if (!window.litDisableBundleWarning) { + console.warn('Lit has been loaded from a bundle that combines all core features into ' + + 'a single file. To reduce transfer size and parsing cost, consider ' + + 'using the `lit` npm package directly in your project.'); +} + +export { AsyncDirective, AsyncReplaceDirective, CSSResult, Directive, LitElement, PartType, ReactiveElement, TemplateResultType, UnsafeHTMLDirective, UntilDirective, UpdatingElement, _$LE, _$LH, adoptStyles, asyncAppend, asyncReplace, cache, choose, classMap, clearPart, createRef, css, defaultConverter, directive, getCommittedValue, getCompatibleStyle, getDirectiveClass, guard, html$1 as html, ifDefined, insertPart, isDirectiveResult, isPrimitive, isServer, isSingleExpression, isTemplateResult, join, keyed, literal, live, map, noChange, notEqual, nothing, range, ref, removePart, render, repeat, setChildPartValue, setCommittedValue, html as staticHtml, svg as staticSvg, styleMap, supportsAdoptingStyleSheets, svg$1 as svg, templateContent, unsafeCSS, unsafeHTML, unsafeSVG, unsafeStatic, until, when, withStatic }; +//# sourceMappingURL=lit-all.min.js.map