From 85f0ad161a51f98aadfd87bd836d3681df368ab1 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Tue, 29 Jul 2025 13:00:10 +0200 Subject: [PATCH] stateSet polyfill --- src/components/ha-button.ts | 10 +++++ src/resources/polyfills/stateset.ts | 57 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/resources/polyfills/stateset.ts diff --git a/src/components/ha-button.ts b/src/components/ha-button.ts index d696de4dd2..74a42843e1 100644 --- a/src/components/ha-button.ts +++ b/src/components/ha-button.ts @@ -2,6 +2,8 @@ import Button from "@awesome.me/webawesome/dist/components/button/button"; import { css, type CSSResultGroup } from "lit"; import { customElement } from "lit/decorators"; +import { StateSet } from "../resources/polyfills/stateset"; + export type Appearance = "accent" | "filled" | "outlined" | "plain"; /** @@ -36,6 +38,14 @@ export type Appearance = "accent" | "filled" | "outlined" | "plain"; export class HaButton extends Button { variant: "brand" | "neutral" | "success" | "warning" | "danger" = "brand"; + attachInternals() { + const internals = super.attachInternals(); + Object.defineProperty(internals, "states", { + value: new StateSet(this, internals.states), + }); + return internals; + } + static get styles(): CSSResultGroup { return [ Button.styles, diff --git a/src/resources/polyfills/stateset.ts b/src/resources/polyfills/stateset.ts new file mode 100644 index 0000000000..88bacf6648 --- /dev/null +++ b/src/resources/polyfills/stateset.ts @@ -0,0 +1,57 @@ +// A small polyfill for CSSStateSet +export class StateSet extends Set { + private _el: Element; + + private _existing: null | Set = null; + + constructor(el: Element, existing: Set | null = null) { + super(); + this._el = el; + this._existing = existing; + } + + add(state: string) { + super.add(state); + const existing = this._existing; + if (existing) { + try { + existing.add(state); + } catch { + existing.add(`--${state}`); + } + } else { + this._el.setAttribute(`state-${state}`, ""); + } + return this; + } + + delete(state: string) { + super.delete(state); + const existing = this._existing; + if (existing) { + existing.delete(state); + existing.delete(`--${state}`); + } else { + this._el.removeAttribute(`state-${state}`); + } + return true; + } + + has(state: string) { + return super.has(state); + } + + clear() { + for (const state of this) this.delete(state); + } +} +const replaceSync = CSSStyleSheet.prototype.replaceSync; +Object.defineProperty(CSSStyleSheet.prototype, "replaceSync", { + value: function (text) { + text = text.replace( + /:state\(([^)]+)\)/g, + ":where(:state($1), :--$1, [state-$1])" + ); + replaceSync.call(this, text); + }, +});