Compare commits

..
Author SHA1 Message Date
Maarten Lakerveld 2edbab08ea Correct macOS floor for Safari 26 in companion app UA regex
Safari 26 ships for macOS 14 Sonoma and 15 Sequoia, not only macOS 26, so
the SAFARI_TO_MACOS entry breaking the minimum-supported-macOS pattern
would have sent updated macOS 14/15 companion apps to the legacy build
once the modern floor reaches Safari 26.
2026-08-31 17:06:55 +02:00
Maarten Lakerveld fa30c6b99a Repair list-plugins-and-polyfills script for Babel 8
The audit script died at startup since the Babel 8 update: preset-env no
longer exposes lib/debug.js (logPlugin is now inlined locally, built on the
public getInclusionReasons helper) and babel-plugin-polyfill-corejs3 v1 no
longer ships lib/shipped-proposals.js (list inlined).

Instead of invoking the preset with a hand-mocked plugin API - the part
that kept drifting - the plugin listing now runs a real transform of an
empty file with preset-env in debug mode, declaring the same caller
capabilities as babel-loader. The polyfill listing now passes the
configured core-js version to core-js-compat, mirroring the provider's own
filtering so the report cannot list modules the installed core-js lacks.
Output is byte-identical to the direct-invocation approach. Also documents
the script in the build-scripts README.
2026-08-31 17:06:55 +02:00
Maarten Lakerveld 77eebbe041 Remove dead html_url custom panel support
html_url pointed to an HTML Import, a Polymer-era feature removed from
Chrome in 2019 and never shipped elsewhere. The loader has not handled the
html type for years (it fell through to a rejection), and core's
panel_custom integration no longer accepts the option, so the branch was
unreachable. Also drops the ha-panel-${name} legacy tag naming that was
keyed on html_url.
2026-08-31 17:06:55 +02:00
Maarten Lakerveld 3ebec556ea Remove vendor prefixes for no-longer-supported browsers
Deletes -ms- prefixes (IE/EdgeHTML only) and -webkit-/-moz- prefixed
declarations that every supported browser understands unprefixed, or that
Lightning CSS re-adds automatically from the unprefixed property in
production builds. Blocks that only had prefixed user-select now use the
standard property (previously Firefox got no user-select there at all).
Converts the four -webkit-linear-gradient() declarations - the sole
gradient syntax on those sliders - to standard linear-gradient().
2026-08-31 17:06:55 +02:00
Maarten Lakerveld a4d19bc3b0 Remove old-browser JS shims and stale ES5 build references
Drops the IE-only navigator.msMaxTouchPoints check, replaces the
toggleAttribute helper with the native method (polyfilled automatically for
Chrome < 69 in the legacy build), and removes babel excludes for the
uninstalled proxy-polyfill and unfetch packages. Updates comments that
still described the legacy build as ES5.
2026-08-31 17:06:55 +02:00
Maarten Lakerveld 567f56421b Remove keyed-es5 Terser workaround
The custom keyed directive existed because Terser with ecma: 5 miscompiled
the destructured update() parameters (#28732). The legacy build now minifies
with ecma: 2017, so the stock lit-html keyed directive works in both builds.
2026-08-31 17:06:55 +02:00
Maarten Lakerveld a45c725301 Remove web components polyfills and ES5 custom elements adapter
All supported browsers (legacy floor: Chrome 59, Safari/iOS 12, Firefox 94)
have native shadow DOM and custom elements, so the webcomponents bundle,
ShadyCSS branch, and lit polyfill-support are unreachable. The legacy build
now emits ES2017 classes, so custom-elements-es5-adapter and the
window.loadES5Adapter hook (no known third-party consumers) are removed.
Also stops shipping the never-loaded dialog-polyfill css and drops both
now-unused dependencies.
2026-08-31 17:06:55 +02:00
87 changed files with 182 additions and 581 deletions
+9 -1
View File
@@ -34,6 +34,14 @@ In production, the following responsibilities are added:
- Minify HTML
- Bundle multiple imports so that the browser can fetch less files
- Generate a second version that is ES5 compatible
- Generate a second version that is compatible with older browsers (legacy build)
Configuration for all these steps are specified in [bundle.js](bundle.js).
## Auditing browser support changes
`node build-scripts/list-plugins-and-polyfills.js` prints, per browserslist
environment (modern/legacy), the Babel transforms preset-env enables and the
Core-JS polyfills that may be injected — as collapsible markdown ready to
paste into a PR. Use it to show the bundle impact when changing
`.browserslistrc` or the Babel configuration.
+1 -3
View File
@@ -121,7 +121,7 @@ module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
ignoreModuleNotFound: true,
},
],
// Import helpers and regenerator from runtime package.
// Import helpers from runtime package.
// `moduleName` is pinned so helpers resolve from `@babel/runtime`: the
// corejs3 polyfill provider above otherwise redirects them to the
// (uninstalled) `@babel/runtime-corejs3`, which preset-env used to suppress
@@ -155,8 +155,6 @@ module.exports.babelOptions = ({ latestBuild, isTestBuild, sw }) => ({
"@lit-labs/virtualizer/polyfills",
"@webcomponents/scoped-custom-element-registry",
"element-internals-polyfill",
"proxy-polyfill",
"unfetch",
].map((p) => new RegExp(`/node_modules/${p}/`)),
],
},
+2 -2
View File
@@ -25,7 +25,7 @@ const SAFARI_TO_MACOS = {
16: [11, 0, 0],
17: [12, 0, 0],
18: [13, 0, 0],
26: [26, 0, 0],
26: [14, 0, 0],
};
const getCommonTemplateVars = () => {
@@ -89,7 +89,7 @@ const minifyHtml = (content, ext) => {
...htmlMinifierOptions,
conservativeCollapse: false,
minifyJS: terserOptions({
latestBuild: false, // Shared scripts should be ES5
latestBuild: false, // Shared scripts must satisfy the legacy targets
isTestBuild: true, // Don't need source maps
}),
}).then((wrapped) =>
-35
View File
@@ -42,37 +42,6 @@ function copyMdiIcons(staticDir) {
fs.copySync(polyPath("build/mdi"), staticPath("mdi"));
}
function copyPolyfills(staticDir) {
const staticPath = genStaticPath(staticDir);
// For custom panels using ES5 builds that don't use Babel 7+
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"),
staticPath("polyfills/")
);
// Web Component polyfills and adapters
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js"),
staticPath("polyfills/")
);
copyFileDir(
npmPath("@webcomponents/webcomponentsjs/webcomponents-bundle.js.map"),
staticPath("polyfills/")
);
// Lit polyfill support
fs.copySync(
npmPath("lit/polyfill-support.js"),
path.join(staticPath("polyfills/"), "lit-polyfill-support.js")
);
// dialog-polyfill css
copyFileDir(
npmPath("dialog-polyfill/dialog-polyfill.css"),
staticPath("polyfills/")
);
}
function copyFonts(staticDir) {
const staticPath = genStaticPath(staticDir);
// Local fonts
@@ -141,7 +110,6 @@ gulp.task("copy-static-app", async () => {
const staticDir = paths.app_output_static;
// Basic static files
fs.copySync(polyPath("public"), paths.app_output_root);
copyPolyfills(staticDir);
copyFonts(staticDir);
copyTranslations(staticDir);
copyLocaleData(staticDir);
@@ -163,7 +131,6 @@ gulp.task("copy-static-demo", async () => {
);
// Copy demo static files
fs.copySync(path.resolve(paths.demo_dir, "public"), paths.demo_output_root);
copyPolyfills(paths.demo_output_static);
await copyMapPanel(paths.demo_output_static);
copyFonts(paths.demo_output_static);
copyTranslations(paths.demo_output_static);
@@ -176,7 +143,6 @@ gulp.task("copy-static-cast", async () => {
fs.copySync(polyPath("public/static"), paths.cast_output_static);
// Copy cast static files
fs.copySync(path.resolve(paths.cast_dir, "public"), paths.cast_output_root);
copyPolyfills(paths.cast_output_static);
await copyMapPanel(paths.cast_output_static);
copyFonts(paths.cast_output_static);
copyTranslations(paths.cast_output_static);
@@ -223,7 +189,6 @@ gulp.task("copy-static-e2e-test-app", async () => {
fs.copySync(e2ePublic, paths.e2eTestApp_output_root);
}
copyPolyfills(paths.e2eTestApp_output_static);
await copyMapPanel(paths.e2eTestApp_output_static);
copyFonts(paths.e2eTestApp_output_static);
copyTranslations(paths.e2eTestApp_output_static);
+62 -27
View File
@@ -1,38 +1,55 @@
#!/usr/bin/env node
// Script to print Babel plugins and Core JS polyfills that will be used by browserslist environments
import { version as babelVersion } from "@babel/core";
import presetEnv from "@babel/preset-env";
import compilationTargets from "@babel/helper-compilation-targets";
import { transformSync } from "@babel/core";
import compilationTargets, {
getInclusionReasons,
} from "@babel/helper-compilation-targets";
import coreJSCompat from "core-js-compat";
import { logPlugin } from "@babel/preset-env/lib/debug.js";
import shippedPolyfills from "../node_modules/babel-plugin-polyfill-corejs3/lib/shipped-proposals.js";
import { babelOptions } from "./bundle.cjs";
const detailsOpen = (heading) =>
`<details>\n<summary><h4>${heading}</h4></summary>\n`;
const detailsClose = "</details>\n";
const dummyAPI = {
version: babelVersion,
// eslint-disable-next-line @typescript-eslint/no-empty-function
assertVersion: () => {},
caller: (callback) =>
callback({
name: "Dummy Bundler",
supportsStaticESM: true,
supportsDynamicImport: true,
supportsTopLevelAwait: true,
supportsExportNamespaceFrom: true,
}),
targets: () => ({}),
// Copied from @babel/preset-env's internal `logPlugin`, which Babel 8 no
// longer exposes (the package rolls up into lib/index.js and exports nothing
// but the preset). Prints an item with the targets that require it.
const logPlugin = (item, targetVersions, list) => {
const filteredList = getInclusionReasons(item, targetVersions, list);
const support = list[item];
if (!support) {
console.log(` ${item}`);
return;
}
let formattedTargets = `{`;
let first = true;
for (const target of Object.keys(filteredList)) {
if (!first) formattedTargets += `,`;
first = false;
formattedTargets += ` ${target}`;
if (support[target]) formattedTargets += ` < ${support[target]}`;
}
formattedTargets += ` }`;
console.log(` ${item} ${formattedTargets}`);
};
// Copied from babel-plugin-polyfill-corejs3's generated
// corejs3ShippedProposalsList, which v1 no longer exposes (it is inlined in
// the package's rolled-up bundle).
const shippedProposalsList = new Set([
"esnext.array.group",
"esnext.array.group-to-map",
"esnext.iterator.zip",
"esnext.iterator.zip-keyed",
"esnext.symbol.metadata",
]);
// Generate filter function based on proposal/method inputs
// Copied and adapted from babel-plugin-polyfill-corejs3/esm/index.mjs
const polyfillFilter = (method, proposals, shippedProposals) => (name) => {
if (proposals || method === "entry-global") return true;
if (shippedProposals && shippedPolyfills.default.has(name)) {
if (shippedProposals && shippedProposalsList.has(name)) {
return true;
}
if (name.startsWith("esnext.")) {
@@ -47,7 +64,9 @@ const polyfillFilter = (method, proposals, shippedProposals) => (name) => {
for (const buildType of ["Modern", "Legacy"]) {
const browserslistEnv = buildType.toLowerCase();
const babelOpts = babelOptions({ latestBuild: browserslistEnv === "modern" });
const presetEnvOpts = babelOpts.presets[0][1];
const presetEnvOpts = babelOpts.presets.find(
(preset) => Array.isArray(preset) && preset[0] === "@babel/preset-env"
)?.[1];
// Core-JS polyfills are injected by babel-plugin-polyfill-corejs3 (Babel 8
// removed preset-env's `useBuiltIns`), so read its options here.
const corejsOpts = babelOpts.plugins.find(
@@ -55,22 +74,38 @@ for (const buildType of ["Modern", "Legacy"]) {
Array.isArray(plugin) && plugin[0] === "babel-plugin-polyfill-corejs3"
)?.[1];
// Invoking preset-env in debug mode will log the included plugins
// Transforming an empty file with preset-env in debug mode logs the included
// plugins. The caller declares the same capabilities babel-loader does, so
// plugins gated on bundler support (e.g. transform-export-namespace-from)
// match the build.
presetEnvOpts.debug = true;
console.log(detailsOpen(`${buildType} Build Babel Plugins`));
presetEnv.default(dummyAPI, {
...presetEnvOpts,
browserslistEnv,
debug: true,
transformSync("", {
...babelOpts,
configFile: false,
filename: "audit.js",
caller: {
name: "list-plugins-and-polyfills",
supportsStaticESM: true,
supportsDynamicImport: true,
supportsTopLevelAwait: true,
supportsExportNamespaceFrom: true,
},
});
console.log(detailsClose);
// Manually log the Core-JS polyfills using the same technique
if (corejsOpts) {
console.log(detailsOpen(`${buildType} Build Core-JS Polyfills`));
const targets = compilationTargets.default(babelOpts?.targets, {
const targets = compilationTargets(babelOpts.targets, {
browserslistEnv,
});
const polyfillList = coreJSCompat({ targets }).list.filter(
// `version` limits the list to modules the installed core-js ships,
// mirroring the provider's own filtering.
const polyfillList = coreJSCompat({
targets,
version: corejsOpts.version,
}).list.filter(
polyfillFilter(
corejsOpts.method,
corejsOpts.proposals,
+1 -4
View File
@@ -345,10 +345,7 @@ const createRspackConfig = ({
"lit/directives/join$": "lit/directives/join.js",
"lit/directives/repeat$": "lit/directives/repeat.js",
"lit/directives/live$": "lit/directives/live.js",
"lit/directives/keyed$": latestBuild
? "lit/directives/keyed.js"
: path.resolve(__dirname, "../src/common/lit/keyed-es5.ts"),
"lit/polyfill-support$": "lit/polyfill-support.js",
"lit/directives/keyed$": "lit/directives/keyed.js",
"@lit-labs/virtualizer/layouts/grid":
"@lit-labs/virtualizer/layouts/grid.js",
"@lit-labs/virtualizer/polyfills/resize-observer-polyfill/ResizeObserver":
+1 -3
View File
@@ -15,7 +15,6 @@ import {
saveTokens,
} from "../../../../src/common/auth/token_storage";
import { atLeastVersion } from "../../../../src/common/config/version";
import { toggleAttribute } from "../../../../src/common/dom/toggle_attribute";
import "../../../../src/components/ha-button";
import "../../../../src/components/ha-icon";
import "../../../../src/components/ha-list";
@@ -197,8 +196,7 @@ class HcCast extends LitElement {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
toggleAttribute(
this,
this.toggleAttribute(
"hide-icons",
this.lovelaceViews ? !this.lovelaceViews.some((view) => view.icon) : true
);
+1 -3
View File
@@ -693,9 +693,7 @@ class HaGallery extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
--ha-sidebar-width: 300px;
--ha-sidebar-expanded-width: 300px;
--ha-sidebar-expanded-item-width: 292px;
-2
View File
@@ -90,7 +90,6 @@
"@vibrant/color": "4.0.4",
"@vvo/tzdb": "6.198.0",
"@webcomponents/scoped-custom-element-registry": "0.0.10",
"@webcomponents/webcomponentsjs": "2.8.0",
"barcode-detector": "3.2.2",
"cally": "0.9.2",
"color-name": "2.1.1",
@@ -101,7 +100,6 @@
"date-fns": "4.4.0",
"deep-clone-simple": "1.1.1",
"deep-freeze": "0.0.1",
"dialog-polyfill": "0.5.6",
"echarts": "6.1.0",
"echarts-extension-chart2music": "0.1.1",
"element-internals-polyfill": "3.0.2",
@@ -33,7 +33,6 @@ export const filterPanelStyles = css`
--ha-card-border-radius: var(--ha-border-radius-square);
}
ha-expansion-panel::part(summary) {
-webkit-user-select: none;
user-select: none;
}
.content {
+5 -10
View File
@@ -145,16 +145,11 @@ export const applyThemesOnElement = (
element.__themes = { cacheKey, keys: newTheme?.keys };
// Set and/or reset styles
if (window.ShadyCSS) {
// Use ShadyCSS if available
window.ShadyCSS.styleSubtree(/** @type {!HTMLElement} */ element, styles);
} else {
for (const s in styles) {
if (s === null) {
element.style.removeProperty(s);
} else {
element.style.setProperty(s, styles[s]);
}
for (const s in styles) {
if (s === null) {
element.style.removeProperty(s);
} else {
element.style.setProperty(s, styles[s]);
}
}
};
-25
View File
@@ -1,25 +0,0 @@
// Toggle Attribute Polyfill because it's too new for some browsers
export const toggleAttribute = (
el: HTMLElement,
name: string,
force?: boolean
) => {
if (force !== undefined) {
force = !!force;
}
if (el.hasAttribute(name)) {
if (force) {
return true;
}
el.removeAttribute(name);
return false;
}
if (force === false) {
return false;
}
el.setAttribute(name, "");
return true;
};
@@ -1 +0,0 @@
export const webComponentsSupported = "attachShadow" in Element.prototype;
-50
View File
@@ -1,50 +0,0 @@
/**
* ES5-compatible implementation of the keyed directive.
* Based on lit-html's keyed directive but written to avoid ES5 minification issues.
*
* This implementation avoids parameter destructuring in the update() method,
* which causes Terser with ecma: 5 to generate invalid references like `_k`.
*
* Used only for ES5 builds (legacy browsers). Modern builds use the original
* lit-html keyed directive.
*
* @see https://github.com/home-assistant/frontend/issues/28732
*/
import { directive, Directive } from "lit-html/directive.js";
import { setCommittedValue } from "lit-html/directive-helpers.js";
// eslint-disable-next-line lit/no-legacy-imports
import { nothing } from "lit-html";
import type { Part } from "lit-html/directive.js";
class KeyedES5 extends Directive {
private _key: unknown = nothing;
render(k: unknown, v: unknown) {
this._key = k;
return v;
}
update(part: unknown, args: [unknown, unknown]) {
const k = args[0];
const v = args[1];
if (k !== this._key) {
// Clear the part before returning a value. The one-arg form of
// setCommittedValue sets the value to a sentinel which forces a
// commit the next render.
setCommittedValue(part as Part);
this._key = k;
}
return v;
}
}
/**
* Associates a renderable value with a unique key. When the key changes, the
* previous DOM is removed and disposed before rendering the next value, even
* if the value - such as a template - is the same.
*
* This is useful for forcing re-renders of stateful components, or working
* with code that expects new data to generate new HTML elements, such as some
* animation techniques.
*/
export const keyed = directive(KeyedES5);
+1 -3
View File
@@ -1235,10 +1235,8 @@ export class HaDataTable extends LitElement {
display: none;
}
/* Hide scrollbar for IE, Edge and Firefox */
.mdc-data-table__header-row {
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
scrollbar-width: none;
}
.mdc-data-table__cell,
-2
View File
@@ -293,12 +293,10 @@ export class HaAdaptivePopover extends ScrollLockMixin(HaAdaptiveDialog) {
);
overflow: hidden;
color: var(--primary-text-color);
-webkit-backdrop-filter: var(
--ha-dialog-surface-backdrop-filter,
none
);
backdrop-filter: var(--ha-dialog-surface-backdrop-filter, none);
-webkit-user-select: text;
user-select: text;
}
-13
View File
@@ -1061,31 +1061,18 @@ ${JSON.stringify(toolCall.result, null, 2)}</pre>
position: absolute;
top: 0;
left: 0;
-webkit-animation: sk-bounce 2s infinite ease-in-out;
animation: sk-bounce 2s infinite ease-in-out;
}
.double-bounce2 {
-webkit-animation-delay: -1s;
animation-delay: -1s;
}
@-webkit-keyframes sk-bounce {
0%,
100% {
-webkit-transform: scale(0);
}
50% {
-webkit-transform: scale(1);
}
}
@keyframes sk-bounce {
0%,
100% {
transform: scale(0);
-webkit-transform: scale(0);
}
50% {
transform: scale(1);
-webkit-transform: scale(1);
}
}
-1
View File
@@ -70,7 +70,6 @@ export class HaBadge extends LitElement {
--ha-card-background,
var(--card-background-color, white)
);
-webkit-backdrop-filter: var(--ha-card-backdrop-filter, none);
backdrop-filter: var(--ha-card-backdrop-filter, none);
border-width: var(--ha-card-border-width, 1px);
box-shadow: var(--ha-card-box-shadow, none);
-2
View File
@@ -432,7 +432,6 @@ export class HaBottomSheet extends ScrollableFadeMixin(LitElement) {
}
}
wa-drawer::part(dialog)::backdrop {
-webkit-backdrop-filter: var(
--ha-bottom-sheet-scrim-backdrop-filter,
var(
--ha-dialog-scrim-backdrop-filter,
@@ -470,7 +469,6 @@ export class HaBottomSheet extends ScrollableFadeMixin(LitElement) {
var(--card-background-color, var(--ha-color-surface-default))
)
);
-webkit-backdrop-filter: var(
--ha-bottom-sheet-surface-backdrop-filter,
var(--ha-dialog-surface-backdrop-filter, none)
);
-1
View File
@@ -13,7 +13,6 @@ export class HaCard extends LitElement {
--ha-card-background,
var(--card-background-color, white)
);
-webkit-backdrop-filter: var(--ha-card-backdrop-filter, none);
backdrop-filter: var(--ha-card-backdrop-filter, none);
box-shadow: var(--ha-card-box-shadow, none);
box-sizing: border-box;
-2
View File
@@ -323,8 +323,6 @@ export class HaControlSelect extends LitElement {
.option .content span {
display: block;
width: 100%;
-webkit-hyphens: auto;
-moz-hyphens: auto;
hyphens: auto;
}
:host([vertical]) {
-2
View File
@@ -393,7 +393,6 @@ export class HaDialog extends ScrollableFadeMixin(LitElement) {
}
wa-dialog::part(dialog) {
-webkit-backdrop-filter: var(
--ha-dialog-surface-backdrop-filter,
none
);
@@ -429,7 +428,6 @@ export class HaDialog extends ScrollableFadeMixin(LitElement) {
}
wa-dialog::part(dialog)::backdrop {
-webkit-backdrop-filter: var(
--ha-dialog-scrim-backdrop-filter,
var(--dialog-backdrop-filter, none)
);
-1
View File
@@ -63,7 +63,6 @@ class HaFaded extends LitElement {
}
.faded {
cursor: pointer;
-webkit-mask-image: linear-gradient(
to bottom,
black 25%,
transparent 100%
+1 -3
View File
@@ -53,9 +53,7 @@ export class HaMarkdown extends LitElement {
display: block;
}
ha-markdown-element {
-ms-user-select: text;
-webkit-user-select: text;
-moz-user-select: text;
user-select: text;
}
ha-markdown-element > *:first-child {
margin-top: 0;
+2 -6
View File
@@ -12,7 +12,6 @@ import { customElement, property, query, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map";
import memoizeOne from "memoize-one";
import { fireEvent } from "../common/dom/fire_event";
import { toggleAttribute } from "../common/dom/toggle_attribute";
import { stringCompare } from "../common/string/compare";
import { computeRTL } from "../common/util/compute_rtl";
import { throttle } from "../common/util/throttle";
@@ -296,7 +295,7 @@ class HaSidebar extends SubscribeMixin(ScrollableFadeMixin(LitElement)) {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
if (changedProps.has("alwaysExpand")) {
toggleAttribute(this, "expanded", this.alwaysExpand);
this.toggleAttribute("expanded", this.alwaysExpand);
}
if (!changedProps.has("hass")) {
return;
@@ -665,9 +664,7 @@ class HaSidebar extends SubscribeMixin(ScrollableFadeMixin(LitElement)) {
flex-direction: column;
overflow: hidden;
overscroll-behavior: contain;
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
background-color: var(--sidebar-background-color);
width: 100%;
box-sizing: border-box;
@@ -897,7 +894,6 @@ class HaSidebar extends SubscribeMixin(ScrollableFadeMixin(LitElement)) {
}
.menu ha-icon-button {
-webkit-transform: scaleX(var(--scale-direction));
transform: scaleX(var(--scale-direction));
}
-2
View File
@@ -905,8 +905,6 @@ export class HaMap extends ReactiveElement {
#map.clickable:active,
#map:active {
cursor: grabbing;
cursor: -moz-grabbing;
cursor: -webkit-grabbing;
}
/* Only the raster fallback is inverted for dark mode, the vector style
ships its own dark cartography. */
+1 -2
View File
@@ -15,7 +15,6 @@ import { ifDefined } from "lit/directives/if-defined";
import { formatDateTimeWithSeconds } from "../../common/datetime/format_date_time";
import { relativeTime } from "../../common/datetime/relative_time";
import { fireEvent } from "../../common/dom/fire_event";
import { toggleAttribute } from "../../common/dom/toggle_attribute";
import { fullEntitiesContext } from "../../data/context";
import type { EntityRegistryEntry } from "../../data/entity/entity_registry";
import type { LogbookEntry } from "../../data/logbook";
@@ -870,7 +869,7 @@ export class HaAutomationTracer extends LitElement {
this.shadowRoot!.querySelectorAll<HaTimeline>(
"ha-timeline[data-path]"
).forEach((el) => {
toggleAttribute(el, "selected", this.selectedPath === el.dataset.path);
el.toggleAttribute("selected", this.selectedPath === el.dataset.path);
if (!this.allowPick || el.tabIndex === 0) {
return;
}
-1
View File
@@ -6,7 +6,6 @@ export interface CustomPanelConfig {
trust_external: boolean;
js_url?: string;
module_url?: string;
html_url?: string;
// When true, the panel takes care of the safe-area insets itself (e.g. it
// consumes the `--safe-area-inset-*` variables or draws into the safe area on
// purpose). Home Assistant then skips adding its own safe-area padding around
@@ -35,7 +35,6 @@ export class HaMoreInfoControlSelectContainer extends LitElement {
gap: var(--ha-space-3);
margin: auto;
overflow: auto;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
margin: -2px calc(var(--ha-space-6) * -1);
padding: 2px var(--ha-space-6);
@@ -111,7 +111,6 @@ export class HaMoreInfoStateHeader extends LitElement {
padding: var(--ha-space-1) 0;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
`;
@@ -483,8 +483,6 @@ class LightRgbColorPicker extends LitElement {
input[type="color"] {
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
border: none;
outline: none;
display: block;
@@ -191,8 +191,8 @@ class LightColorTempPicker extends LitElement {
--control-slider-thickness: 130px;
--control-slider-border-radius: var(--ha-border-radius-6xl);
--control-slider-color: var(--primary-color);
--control-slider-background: -webkit-linear-gradient(
top,
--control-slider-background: linear-gradient(
to bottom,
var(--gradient)
);
--control-slider-tooltip-font-size: var(--ha-font-size-xl);
@@ -362,7 +362,6 @@ export class HaMoreInfoViewVacuumCleanAreas extends LitElement {
border: 1px solid var(--divider-color);
cursor: pointer;
user-select: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: transparent;
overflow: hidden;
min-height: 80px;
@@ -18,9 +18,6 @@ export class HuiNotificationItemTemplate extends LitElement {
static styles = css`
.contents {
padding: 16px;
-ms-user-select: text;
-webkit-user-select: text;
-moz-user-select: text;
user-select: text;
}
+39 -77
View File
@@ -2,8 +2,6 @@ import type { Connection } from "home-assistant-js-websocket";
import type { CSSResult } from "lit";
import { fireEvent } from "../common/dom/fire_event";
import { isNavigationClick } from "../common/dom/is-navigation-click";
import { loadJS } from "../common/dom/load_resource";
import { webComponentsSupported } from "../common/feature-detect/support-web-components";
import { navigate } from "../common/navigate";
import type { CustomPanelInfo } from "../data/panel_custom";
import { baseEntrypointStyles } from "../resources/styles";
@@ -12,23 +10,6 @@ import { dropRealmCollections } from "../util/custom-panel/drop-realm-collection
import { loadCustomPanel } from "../util/custom-panel/load-custom-panel";
import { setCustomPanelProperties } from "../util/custom-panel/set-custom-panel-properties";
declare global {
interface Window {
loadES5Adapter: () => Promise<unknown>;
}
}
let es5Loaded: Promise<unknown> | undefined;
window.loadES5Adapter = () => {
if (!es5Loaded) {
es5Loaded = loadJS(
`${__STATIC_PATH__}polyfills/custom-elements-es5-adapter.js`
).catch(); // Swallow errors as it raises errors on old browsers.
}
return es5Loaded;
};
let panelEl: HTMLElement | undefined;
let initialized = false;
// Kept so we can clean up after ourselves on pagehide without depending on
@@ -66,68 +47,49 @@ function initialize(
document.head.appendChild(style);
const config = panel.config._panel_custom;
let start: Promise<unknown> = Promise.resolve();
if (!webComponentsSupported) {
start = start.then(() => {
loadJS(`${__STATIC_PATH__}polyfills/webcomponents-bundle.js`);
loadJS(`${__STATIC_PATH__}polyfills/lit-polyfill-support.js`);
});
}
loadCustomPanel(config).then(
() => {
panelEl = createCustomPanelElement(config);
if (__BUILD__ === "legacy") {
start = start.then(() => window.loadES5Adapter());
}
start
.then(() => loadCustomPanel(config))
// If our element is using es5, let it finish loading that and define element
// This avoids elements getting upgraded after being added to the DOM
.then(() => es5Loaded || Promise.resolve())
.then(
() => {
panelEl = createCustomPanelElement(config);
const forwardEvent = (ev) => {
if (window.parent.customPanel) {
fireEvent(window.parent.customPanel, ev.type, ev.detail);
}
};
panelEl!.addEventListener("hass-toggle-menu", forwardEvent);
window.addEventListener("location-changed", (ev: any) => {
if (window.parent.customPanel) {
window.parent.customPanel.navigate(
window.location.pathname,
ev.detail
);
}
});
setProperties({ panel, ...properties });
document.body.appendChild(panelEl!);
},
(err) => {
// eslint-disable-next-line
console.error(err, panel);
let errorScreen;
if (panel.url_path === "hassio") {
import("../layouts/supervisor-error-screen");
errorScreen = document.createElement(
"supervisor-error-screen"
) as any;
} else {
import("../layouts/hass-error-screen");
errorScreen = document.createElement("hass-error-screen") as any;
errorScreen.error = `Unable to load the panel source: ${err}.`;
const forwardEvent = (ev) => {
if (window.parent.customPanel) {
fireEvent(window.parent.customPanel, ev.type, ev.detail);
}
const errorStyle = document.createElement("style");
errorStyle.innerHTML = (baseEntrypointStyles as CSSResult).cssText;
document.body.appendChild(errorStyle);
errorScreen.hass = properties.hass;
document.body.appendChild(errorScreen);
};
panelEl!.addEventListener("hass-toggle-menu", forwardEvent);
window.addEventListener("location-changed", (ev: any) => {
if (window.parent.customPanel) {
window.parent.customPanel.navigate(
window.location.pathname,
ev.detail
);
}
});
setProperties({ panel, ...properties });
document.body.appendChild(panelEl!);
},
(err) => {
// eslint-disable-next-line
console.error(err, panel);
let errorScreen;
if (panel.url_path === "hassio") {
import("../layouts/supervisor-error-screen");
errorScreen = document.createElement("supervisor-error-screen") as any;
} else {
import("../layouts/hass-error-screen");
errorScreen = document.createElement("hass-error-screen") as any;
errorScreen.error = `Unable to load the panel source: ${err}.`;
}
);
const errorStyle = document.createElement("style");
errorStyle.innerHTML = (baseEntrypointStyles as CSSResult).cssText;
document.body.appendChild(errorStyle);
errorScreen.hass = properties.hass;
document.body.appendChild(errorScreen);
}
);
document.body.addEventListener("click", (ev) => {
const href = isNavigationClick(ev);
-4
View File
@@ -7,10 +7,6 @@
script.src = src;
return document.head.appendChild(script);
}
if (!("attachShadow" in Element.prototype)) {
_ls("/static/polyfills/webcomponents-bundle.js", true);
_ls("/static/polyfills/lit-polyfill-support.js", true);
}
// Modern browsers are detected primarily using the user agent string.
// A feature detection which roughly lines up with the modern targets is used
// as a fallback to guard against spoofs. It should be updated periodically.
@@ -884,7 +884,6 @@ export class HaTabsSubpageDataTable extends KeyboardShortcutMixin(LitElement) {
padding: 0 16px;
box-sizing: border-box;
overflow-x: scroll;
-ms-overflow-style: none;
scrollbar-width: none;
}
+2 -4
View File
@@ -5,7 +5,6 @@ import { customElement, property, state } from "lit/decorators";
import type { HASSDomEvent } from "../common/dom/fire_event";
import { fireEvent } from "../common/dom/fire_event";
import { listenMediaQuery } from "../common/dom/media_query";
import { toggleAttribute } from "../common/dom/toggle_attribute";
import { computeRTLDirection } from "../common/util/compute_rtl";
import "../components/ha-drawer";
import { narrowViewportContext } from "../data/context";
@@ -141,10 +140,9 @@ export class HomeAssistantMain extends LitElement {
protected updated(changedProps: PropertyValues<this>) {
super.updated(changedProps);
toggleAttribute(this, "expanded", this.hass.dockedSidebar === "docked");
this.toggleAttribute("expanded", this.hass.dockedSidebar === "docked");
toggleAttribute(
this,
this.toggleAttribute(
"modal",
this._sidebarNarrow || this._externalSidebar || this.hass.kioskMode
);
-15
View File
@@ -25,29 +25,14 @@ class OnboardingLoading extends LitElement {
border-right: 1.1em solid rgba(3, 169, 244, 0.2);
border-bottom: 1.1em solid rgba(3, 169, 244, 0.2);
border-left: 1.1em solid rgb(3, 168, 244);
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.4s infinite linear;
animation: load8 1.4s infinite linear;
}
@-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
+1 -3
View File
@@ -151,9 +151,7 @@ class PanelClimate extends LitElement {
haStyle,
css`
:host {
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
hui-view-container {
position: relative;
@@ -151,7 +151,6 @@ export class DialogSupportPackage extends LitElement {
}
table > tbody > tr {
-webkit-transition: background-color 0.25s ease;
transition: background-color 0.25s ease;
}
+7 -18
View File
@@ -1,5 +1,4 @@
import {
mdiAccessPointNetwork,
mdiAccount,
mdiBackupRestore,
mdiBadgeAccountHorizontal,
@@ -93,6 +92,13 @@ export const configSections: Record<string, PageNavigation[]> = {
component: "lovelace",
adminOnly: true,
},
{
path: "/config/voice-assistants",
translationKey: "voice_assistants",
iconPath: mdiMicrophone,
iconColor: "#3263C3",
adminOnly: true,
},
],
dashboard_external_settings: [
{
@@ -103,23 +109,6 @@ export const configSections: Record<string, PageNavigation[]> = {
},
],
dashboard_2: [
{
path: "/config/connectivity",
translationKey: "connectivity",
iconPath: mdiAccessPointNetwork,
iconColor: "#00838F",
core: true,
adminOnly: true,
},
{
path: "/config/voice-assistants",
translationKey: "voice_assistants",
iconPath: mdiMicrophone,
iconColor: "#3263C3",
adminOnly: true,
},
],
connectivity: [
{
path: "/config/matter",
iconPath:
@@ -1,80 +0,0 @@
import type { CSSResultGroup, TemplateResult } from "lit";
import { css, html, LitElement } from "lit";
import { customElement, property } from "lit/decorators";
import "../../../components/ha-card";
import "../../../layouts/hass-subpage";
import { haStyle } from "../../../resources/styles";
import type { HomeAssistant } from "../../../types";
import { configSections } from "../config-sections";
import "../dashboard/ha-config-navigation";
import "../ha-config-section";
@customElement("ha-config-connectivity")
class HaConfigConnectivity extends LitElement {
@property({ attribute: false }) public hass!: HomeAssistant;
@property({ type: Boolean }) public narrow = false;
@property({ attribute: "is-wide", type: Boolean }) public isWide = false;
protected render(): TemplateResult {
const title = this.hass.localize(
"ui.panel.config.dashboard.connectivity.main"
);
return html`
<hass-subpage
.hass=${this.hass}
back-path="/config"
.header=${title}
.narrow=${this.narrow}
>
<ha-config-section .isWide=${this.isWide} full-width>
<ha-card outlined>
<ha-config-navigation
.hass=${this.hass}
.narrow=${this.narrow}
.pages=${configSections.connectivity}
.label=${title}
></ha-config-navigation>
</ha-card>
</ha-config-section>
</hass-subpage>
`;
}
static get styles(): CSSResultGroup {
return [
haStyle,
css`
ha-config-section {
margin: auto;
margin-top: -32px;
max-width: 600px;
}
ha-card {
overflow: hidden;
margin-bottom: max(24px, var(--safe-area-inset-bottom));
}
@media all and (max-width: 600px) {
ha-card {
border-width: 1px 0;
border-radius: var(--ha-border-radius-square);
box-shadow: unset;
}
ha-config-section {
margin-top: -42px;
}
}
`,
];
}
}
declare global {
interface HTMLElementTagNameMap {
"ha-config-connectivity": HaConfigConnectivity;
}
}
@@ -24,8 +24,6 @@ class HaConfigNavigation extends LitElement {
@property({ attribute: false }) public pages!: PageNavigation[];
@property() public label?: string;
@state() private _visiblePages?: PageNavigation[];
private _hasBluetoothConfigEntries = false;
@@ -101,15 +99,16 @@ class HaConfigNavigation extends LitElement {
}
`,
}));
const label = this.label ?? this.hass.localize("panel.config");
return html`
<div class="visually-hidden" role="heading" aria-level="2">${label}</div>
<div class="visually-hidden" role="heading" aria-level="2">
${this.hass.localize("panel.config")}
</div>
<ha-config-navigation-list
has-secondary
.hass=${this.hass}
.narrow=${this.narrow}
.pages=${pages}
.label=${label}
.label=${this.hass.localize("panel.config")}
></ha-config-navigation-list>
`;
}
-4
View File
@@ -63,10 +63,6 @@ class HaPanelConfig extends HassRouterPage {
tag: "ha-config-cloud",
load: () => import("./cloud/ha-config-cloud"),
},
connectivity: {
tag: "ha-config-connectivity",
load: () => import("./connectivity/ha-config-connectivity"),
},
devices: {
tag: "ha-config-devices",
load: () => import("./devices/ha-config-devices"),
@@ -434,8 +434,6 @@ class HaScheduleForm extends LitElement {
margin: var(--ha-space-2) 0;
height: 450px;
width: 100%;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
--fc-border-color: var(--divider-color);
--fc-event-border-color: var(--divider-color);
@@ -160,7 +160,7 @@ export class BluetoothConfigDashboard extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.bluetooth.title")}
back-path="/config/connectivity"
back-path="/config"
>
<div class="container">
<ha-card class="content network-status">
@@ -52,7 +52,7 @@ export class InfraredConfigDashboard extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.infrared.title")}
back-path="/config/connectivity"
back-path="/config"
>
<div class="container">
<ha-card class="content network-status">
@@ -83,7 +83,7 @@ export class MatterConfigDashboard extends LitElement {
.narrow=${this.narrow}
.hass=${this.hass}
header="Matter"
back-path="/config/connectivity"
back-path="/config"
has-fab
>
<div class="container">
@@ -377,9 +377,7 @@ export class MQTTConfigPanel extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.nav-card {
@@ -43,7 +43,7 @@ export class RadioFrequencyConfigDashboard extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.radio_frequency.title")}
back-path="/config/connectivity"
back-path="/config"
>
<div class="container">
<ha-card class="network-status">
@@ -409,7 +409,7 @@ export class SerialConfigDashboard extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.serial.title")}
back-path="/config/connectivity"
back-path="/config"
>
<ha-icon-button
slot="toolbar-icon"
@@ -79,7 +79,7 @@ export class ThreadConfigPanel extends SubscribeMixin(LitElement) {
.narrow=${this.narrow}
.hass=${this.hass}
header="Thread"
back-path="/config/connectivity"
back-path="/config"
>
<ha-dropdown slot="toolbar-icon">
<ha-icon-button
@@ -101,7 +101,7 @@ class ZHAConfigDashboard extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.zha.network.caption")}
back-path="/config/connectivity"
back-path="/config"
>
<div class="loading">
<ha-spinner></ha-spinner>
@@ -129,7 +129,7 @@ class ZHAConfigDashboard extends LitElement {
.hass=${this.hass}
.narrow=${this.narrow}
.header=${this.hass.localize("ui.panel.config.zha.network.caption")}
back-path="/config/connectivity"
back-path="/config"
has-fab
>
<div class="container">
@@ -148,7 +148,7 @@ class ZWaveJSConfigDashboard extends SubscribeMixin(LitElement) {
.header=${this.hass.localize(
"ui.panel.config.zwave_js.navigation.general"
)}
back-path="/config/connectivity"
back-path="/config"
has-fab
>
<ha-icon-button
+1 -3
View File
@@ -344,9 +344,7 @@ export class HaConfigLogs extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.search {
position: sticky;
+1 -1
View File
@@ -191,7 +191,7 @@ export class HaConfigTags extends SubscribeMixin(LitElement) {
<hass-tabs-subpage-data-table
.hass=${this.hass}
.narrow=${this.narrow}
back-path="/config/connectivity"
back-path="/config"
.route=${this.route}
.tabs=${configSections.tags}
.columns=${this._columns(this.hass.localize)}
+1 -3
View File
@@ -163,9 +163,7 @@ class HaPanelDevEvent extends LitElement {
}
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
display: block;
height: 100%;
}
+1 -3
View File
@@ -650,9 +650,7 @@ class HaPanelDevState extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
display: block;
padding: var(--ha-space-4);
}
@@ -865,7 +865,6 @@ class HaPanelDevStatistics extends KeyboardShortcutMixin(LitElement) {
gap: var(--ha-space-4);
padding: 0 var(--ha-space-4);
overflow-x: scroll;
-ms-overflow-style: none;
scrollbar-width: none;
}
+1 -3
View File
@@ -196,9 +196,7 @@ class PanelEnergy extends LitElement {
css`
:host {
--ha-view-sections-column-max-width: 100%;
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.centered {
width: 100%;
+1 -3
View File
@@ -151,9 +151,7 @@ class PanelLight extends LitElement {
haStyle,
css`
:host {
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
hui-view-container {
position: relative;
@@ -171,7 +171,7 @@ class HuiCoverTiltPositionCardFeature
cardFeatureStyles,
css`
.gradient {
background: -webkit-linear-gradient(left, ${GRADIENT});
background: linear-gradient(to right, ${GRADIENT});
opacity: 0.6;
}
`,
@@ -159,8 +159,8 @@ class HuiLightColorTempCardFeature
cardFeatureStyles,
css`
ha-control-slider {
--control-slider-background: -webkit-linear-gradient(
left,
--control-slider-background: linear-gradient(
to right,
var(--gradient)
);
--control-slider-background-opacity: 1;
@@ -214,7 +214,6 @@ export class HuiHeadingCard extends LitElement implements LovelaceCard {
ha-card {
background: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
border: none;
box-shadow: none;
padding: 0;
@@ -332,8 +332,6 @@ export class HuiLightCard extends LitElement implements LovelaceCard {
font-size: var(--brightness-font-size);
opacity: 0;
transition: opacity 0.5s ease-in-out;
-moz-transition: opacity 0.5s ease-in-out;
-webkit-transition: opacity 0.5s ease-in-out;
}
.show_brightness {
@@ -143,7 +143,6 @@ export class HuiToggleGroupCard extends LitElement implements LovelaceCard {
ha-card {
background: none;
backdrop-filter: none;
-webkit-backdrop-filter: none;
border: none;
box-shadow: none;
height: 100%;
@@ -852,7 +852,6 @@ export class HuiEnergyPeriodSelector extends SubscribeMixin(LitElement) {
right: 0;
bottom: 0;
z-index: var(--dialog-z-index, 8);
-webkit-backdrop-filter: var(
--ha-dialog-scrim-backdrop-filter,
var(--dialog-backdrop-filter)
);
@@ -5,7 +5,6 @@ import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { DOMAINS_INPUT_ROW } from "../../../common/const";
import { stopPropagation } from "../../../common/dom/stop_propagation";
import { toggleAttribute } from "../../../common/dom/toggle_attribute";
import { computeDomain } from "../../../common/entity/compute_domain";
import "../../../components/entity/state-badge";
import "../../../components/ha-relative-time";
@@ -134,8 +133,7 @@ export class HuiGenericEntityRow extends LitElement {
protected updated(changedProps: PropertyValues<this>): void {
super.updated(changedProps);
toggleAttribute(
this,
this.toggleAttribute(
"no-secondary",
!this.secondaryText && !this.config?.secondary_info
);
@@ -95,7 +95,7 @@ export class HuiImageElement extends LitElement implements LovelaceElement {
-webkit-touch-callout: none !important;
}
hui-image {
-webkit-user-select: none !important;
user-select: none !important;
pointer-events: none;
}
div:focus {
+1 -4
View File
@@ -1336,9 +1336,7 @@ class HUIRoot extends LitElement {
haStyle,
css`
:host {
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
.header {
background-color: var(--app-header-background-color);
@@ -1351,7 +1349,6 @@ class HUIRoot extends LitElement {
0px
)
);
-webkit-backdrop-filter: var(--app-header-backdrop-filter, none);
backdrop-filter: var(--app-header-backdrop-filter, none);
padding-top: var(--safe-area-inset-top);
padding-right: var(--safe-area-inset-right);
@@ -151,9 +151,7 @@ class PanelMaintenance extends LitElement {
haStyle,
css`
:host {
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
hui-view-container {
position: relative;
+1 -3
View File
@@ -140,9 +140,7 @@ class HaProfileDashboard extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.container {
@@ -98,9 +98,7 @@ class HaProfileSectionBrowser extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.container {
@@ -72,9 +72,7 @@ class HaProfileSectionLocalization extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.container {
@@ -130,9 +130,7 @@ class HaProfileSectionPreferences extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.container {
@@ -85,9 +85,7 @@ class HaProfileSectionSecurity extends LitElement {
haStyle,
css`
:host {
-ms-user-select: initial;
-webkit-user-select: initial;
-moz-user-select: initial;
user-select: initial;
}
.container {
+1 -3
View File
@@ -249,9 +249,7 @@ class PanelSecurity extends LitElement {
haStyle,
css`
:host {
-ms-user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}
hui-view-container {
position: relative;
@@ -137,7 +137,7 @@ export class HaStateControlInfoCoverTiltPosition extends LitElement {
--control-slider-tooltip-font-size: var(--ha-font-size-xl);
}
.gradient {
background: -webkit-linear-gradient(top, ${GRADIENT});
background: linear-gradient(to bottom, ${GRADIENT});
opacity: 0.6;
}
`;
-5
View File
@@ -1635,7 +1635,6 @@
"knx": "[%key:ui::panel::config::dashboard::knx::main%]",
"insteon": "[%key:ui::panel::config::dashboard::insteon::main%]",
"voice-assistants": "[%key:ui::panel::config::dashboard::voice_assistants::main%]",
"connectivity": "[%key:ui::panel::config::dashboard::connectivity::main%]",
"ai-tasks": "[%key:ui::panel::config::ai_tasks::caption%]"
}
},
@@ -2740,10 +2739,6 @@
"main": "Dashboards",
"secondary": "Organize how you interact with your home"
},
"connectivity": {
"main": "Connectivity",
"secondary": "Communication protocols and radios for your devices"
},
"voice_assistants": {
"main": "Voice assistants",
"secondary": "Manage your voice assistants"
-9
View File
@@ -43,15 +43,6 @@ declare global {
interface Window {
// Custom panel entry point url
customPanelJS: string;
ShadyCSS: {
nativeCss: boolean;
nativeShadow: boolean;
prepareTemplate(templateElement, elementName, elementExtension);
styleElement(element);
styleSubtree(element, overrideProperties);
styleDocument(overrideProperties);
getComputedStyleValue(element, propertyName);
};
}
// for fire event
@@ -1,8 +1,2 @@
export const createCustomPanelElement = (panelConfig) => {
// Legacy support. Custom panels used to have to define element ha-panel-{name}
const tagName =
"html_url" in panelConfig
? `ha-panel-${panelConfig.name}`
: panelConfig.name;
return document.createElement(tagName);
};
export const createCustomPanelElement = (panelConfig) =>
document.createElement(panelConfig.name);
+3 -13
View File
@@ -1,19 +1,12 @@
import { loadJS, loadModule } from "../../common/dom/load_resource";
import type { CustomPanelConfig } from "../../data/panel_custom";
// Make sure we only import every JS-based panel once (HTML import has this built-in)
// Make sure we only import every JS-based panel once
const JS_CACHE = {};
export const getUrl = (
panelConfig: CustomPanelConfig
): { type: "module" | "html" | "js"; url: string } => {
if (panelConfig.html_url) {
return {
type: "html",
url: panelConfig.html_url,
};
}
): { type: "module" | "js"; url: string } => {
// if both module and JS provided, base url on frontend build
if (panelConfig.module_url && panelConfig.js_url) {
if (__BUILD__ === "modern") {
@@ -53,8 +46,5 @@ export const loadCustomPanel = (
}
return JS_CACHE[panelSource.url];
}
if (panelSource.type === "module") {
return loadModule(panelSource.url);
}
return Promise.reject("No valid url found in panel config.");
return loadModule(panelSource.url);
};
+1 -5
View File
@@ -1,5 +1 @@
export const isTouch =
"ontouchstart" in window ||
navigator.maxTouchPoints > 0 ||
// @ts-ignore
navigator.msMaxTouchPoints > 0;
export const isTouch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
-17
View File
@@ -26,7 +26,6 @@ import {
import {
appRouteSmokeGroups,
configLinks,
connectivityLinks,
moreInfoViewElements,
} from "./app/src/smoke";
@@ -592,20 +591,4 @@ test.describe("Config panel", () => {
configLinks,
getDashboard
);
// Reached by clicking through from the dashboard: the e2e harness only
// resolves config panel translations once the dashboard has mounted.
const getConnectivity = async (page) => {
const dashboard = await getDashboard(page);
await dashboard.getByRole("link", { name: /^Connectivity\b/ }).click();
const connectivity = page.locator("ha-config-connectivity");
await expect(connectivity).toBeAttached({ timeout: PANEL_TIMEOUT });
return connectivity;
};
defineLinkSmokeTests(
"connectivity links point to expected pages",
connectivityLinks,
getConnectivity
);
});
+4 -9
View File
@@ -20,15 +20,7 @@ export const configLinks: LinkSmokeCase[] = [
{ href: "/config/areas", label: "Areas, labels & zones" },
{ href: "/config/apps", label: "Apps" },
{ href: "/config/lovelace/dashboards", label: "Dashboards" },
{ href: "/config/connectivity", label: "Connectivity" },
{ href: "/config/voice-assistants", label: "Voice assistants" },
{ href: "/config/person", label: "People" },
{ href: "/config/system", label: "System" },
{ href: "/config/tools", label: "Tools" },
{ href: "/config/info", label: "About" },
];
export const connectivityLinks: LinkSmokeCase[] = [
{ href: "/config/matter", label: "Matter" },
{ href: "/config/zha", label: "Zigbee" },
{ href: "/config/zwave_js", label: "Z-Wave" },
@@ -39,6 +31,10 @@ export const connectivityLinks: LinkSmokeCase[] = [
{ href: "/config/radio-frequency", label: "Radio frequency" },
{ href: "/insteon", label: "Insteon" },
{ href: "/config/tags", label: "Tags" },
{ href: "/config/person", label: "People" },
{ href: "/config/system", label: "System" },
{ href: "/config/tools", label: "Tools" },
{ href: "/config/info", label: "About" },
];
// ── More-info dialog views ───────────────────────────────────────────────────
@@ -202,7 +198,6 @@ const CONFIG_ROUTES = routeCases([
["/config/script", "ha-config-script"],
["/config/blueprint", "ha-config-blueprint"],
["/config/cloud", "ha-config-cloud"],
["/config/connectivity", "ha-config-connectivity"],
["/config/energy", "ha-config-energy"],
["/config/hardware", "ha-config-hardware"],
["/config/labs", "ha-config-labs"],
-16
View File
@@ -6909,13 +6909,6 @@ __metadata:
languageName: node
linkType: hard
"@webcomponents/webcomponentsjs@npm:2.8.0":
version: 2.8.0
resolution: "@webcomponents/webcomponentsjs@npm:2.8.0"
checksum: 10/acba7dce2cb60f0505369247ce54eeca3efbd386b98c6cc50d7d318090f551d753b20477038983d7ead9376669b4d702effca21a24c0a1b511d42b1ea53ee9a9
languageName: node
linkType: hard
"@zeit/schemas@npm:2.36.0":
version: 2.36.0
resolution: "@zeit/schemas@npm:2.36.0"
@@ -8648,13 +8641,6 @@ __metadata:
languageName: node
linkType: hard
"dialog-polyfill@npm:0.5.6":
version: 0.5.6
resolution: "dialog-polyfill@npm:0.5.6"
checksum: 10/42428793b04fd2e0a67dfb75838703488d7d05f73663c3251441ad6ed154b8dc71d65ed03d5a0ba4a83c6167c2e6f791cbe1574d0dca37dac1405ce3816033ca
languageName: node
linkType: hard
"didyoumean2@npm:4.1.0":
version: 4.1.0
resolution: "didyoumean2@npm:4.1.0"
@@ -10418,7 +10404,6 @@ __metadata:
"@vitest/coverage-v8": "npm:4.1.11"
"@vvo/tzdb": "npm:6.198.0"
"@webcomponents/scoped-custom-element-registry": "npm:0.0.10"
"@webcomponents/webcomponentsjs": "npm:2.8.0"
babel-loader: "npm:10.1.1"
babel-plugin-polyfill-corejs3: "npm:1.0.0"
barcode-detector: "npm:3.2.2"
@@ -10434,7 +10419,6 @@ __metadata:
deep-clone-simple: "npm:1.1.1"
deep-freeze: "npm:0.0.1"
del: "npm:8.0.1"
dialog-polyfill: "npm:0.5.6"
echarts: "npm:6.1.0"
echarts-extension-chart2music: "npm:0.1.1"
element-internals-polyfill: "npm:3.0.2"