diff --git a/packages/html/src/define/audio/minimal-skin.tailwind.ts b/packages/html/src/define/audio/minimal-skin.tailwind.ts
index 42ba24da..6fd15cc2 100644
--- a/packages/html/src/define/audio/minimal-skin.tailwind.ts
+++ b/packages/html/src/define/audio/minimal-skin.tailwind.ts
@@ -1,4 +1,3 @@
-import { ReactiveElement } from '@videojs/element';
import { renderIcon } from '@videojs/icons/render/minimal';
import { playbackRate } from '@videojs/skins/default/tailwind/audio.tailwind';
import {
@@ -17,9 +16,10 @@ import {
time,
tooltipState,
} from '@videojs/skins/minimal/tailwind/audio.tailwind';
+import { createTemplate } from '@videojs/utils/dom';
import { cn } from '@videojs/utils/style';
import { safeDefine } from '../safe-define';
-import { SkinMixin } from '../skin-mixin';
+import { SkinElement } from '../skin-element';
// Side-effect imports: register all custom elements used in the template.
import '../media/container';
@@ -137,9 +137,9 @@ function getTemplateHTML() {
`;
}
-export class MinimalAudioSkinTailwindElement extends SkinMixin(ReactiveElement) {
+export class MinimalAudioSkinTailwindElement extends SkinElement {
static readonly tagName = 'audio-minimal-skin-tailwind';
- static getTemplateHTML = getTemplateHTML;
+ static template = createTemplate(getTemplateHTML());
}
safeDefine(MinimalAudioSkinTailwindElement);
diff --git a/packages/html/src/define/audio/minimal-skin.ts b/packages/html/src/define/audio/minimal-skin.ts
index 1cef15b3..24540a9c 100644
--- a/packages/html/src/define/audio/minimal-skin.ts
+++ b/packages/html/src/define/audio/minimal-skin.ts
@@ -1,7 +1,7 @@
-import { ReactiveElement } from '@videojs/element';
import { renderIcon } from '@videojs/icons/render/minimal';
+import { createShadowStyle, createTemplate } from '@videojs/utils/dom';
import { safeDefine } from '../safe-define';
-import { createStyles, SkinMixin } from '../skin-mixin';
+import { SkinElement } from '../skin-element';
import styles from './minimal-skin.css?inline';
// Side-effect imports: register all custom elements used in the template.
@@ -118,10 +118,10 @@ function getTemplateHTML() {
`;
}
-export class MinimalAudioSkinElement extends SkinMixin(ReactiveElement) {
+export class MinimalAudioSkinElement extends SkinElement {
static readonly tagName = 'audio-minimal-skin';
- static styles = createStyles(styles);
- static getTemplateHTML = getTemplateHTML;
+ static styles = createShadowStyle(styles);
+ static template = createTemplate(getTemplateHTML());
}
safeDefine(MinimalAudioSkinElement);
diff --git a/packages/html/src/define/audio/skin.tailwind.ts b/packages/html/src/define/audio/skin.tailwind.ts
index 4e90fe52..177c8fb3 100644
--- a/packages/html/src/define/audio/skin.tailwind.ts
+++ b/packages/html/src/define/audio/skin.tailwind.ts
@@ -1,4 +1,3 @@
-import { ReactiveElement } from '@videojs/element';
import { renderIcon } from '@videojs/icons/render';
import {
button,
@@ -17,9 +16,10 @@ import {
time,
tooltipState,
} from '@videojs/skins/default/tailwind/audio.tailwind';
+import { createTemplate } from '@videojs/utils/dom';
import { cn } from '@videojs/utils/style';
import { safeDefine } from '../safe-define';
-import { SkinMixin } from '../skin-mixin';
+import { SkinElement } from '../skin-element';
// Side-effect imports: register all custom elements used in the template.
import '../media/container';
@@ -132,9 +132,9 @@ function getTemplateHTML() {
`;
}
-export class AudioSkinTailwindElement extends SkinMixin(ReactiveElement) {
+export class AudioSkinTailwindElement extends SkinElement {
static readonly tagName = 'audio-skin-tailwind';
- static getTemplateHTML = getTemplateHTML;
+ static template = createTemplate(getTemplateHTML());
}
safeDefine(AudioSkinTailwindElement);
diff --git a/packages/html/src/define/audio/skin.ts b/packages/html/src/define/audio/skin.ts
index 7af08ed7..0de80f85 100644
--- a/packages/html/src/define/audio/skin.ts
+++ b/packages/html/src/define/audio/skin.ts
@@ -1,7 +1,7 @@
-import { ReactiveElement } from '@videojs/element';
import { renderIcon } from '@videojs/icons/render';
+import { createShadowStyle, createTemplate } from '@videojs/utils/dom';
import { safeDefine } from '../safe-define';
-import { createStyles, SkinMixin } from '../skin-mixin';
+import { SkinElement } from '../skin-element';
import styles from './skin.css?inline';
// Side-effect imports: register all custom elements used in the template.
@@ -113,10 +113,10 @@ function getTemplateHTML() {
`;
}
-export class AudioSkinElement extends SkinMixin(ReactiveElement) {
+export class AudioSkinElement extends SkinElement {
static readonly tagName = 'audio-skin';
- static styles = createStyles(styles);
- static getTemplateHTML = getTemplateHTML;
+ static styles = createShadowStyle(styles);
+ static template = createTemplate(getTemplateHTML());
}
safeDefine(AudioSkinElement);
diff --git a/packages/html/src/define/background/skin.ts b/packages/html/src/define/background/skin.ts
index 9c2a4ebf..739397d9 100644
--- a/packages/html/src/define/background/skin.ts
+++ b/packages/html/src/define/background/skin.ts
@@ -1,18 +1,10 @@
import { ReactiveElement } from '@videojs/element';
-import { namedNodeMapToObject } from '@videojs/utils/dom';
+import { ensureGlobalStyle, namedNodeMapToObject } from '@videojs/utils/dom';
import { safeDefine } from '../safe-define';
import styles from './skin.css?inline';
const STYLES_ID = '__media-background-styles';
-function ensureBackgroundStyles(): void {
- if (document.getElementById(STYLES_ID)) return;
- const style = document.createElement('style');
- style.id = STYLES_ID;
- style.textContent = styles;
- document.head.appendChild(style);
-}
-
function getTemplateHTML(_attrs: Record) {
return /*html*/ `
@@ -31,7 +23,7 @@ export class BackgroundVideoSkinElement extends ReactiveElement {
constructor() {
super();
- ensureBackgroundStyles();
+ ensureGlobalStyle(STYLES_ID, styles);
if (!this.shadowRoot) {
this.attachShadow((this.constructor as typeof BackgroundVideoSkinElement).shadowRootOptions);
diff --git a/packages/html/src/define/skin-element.ts b/packages/html/src/define/skin-element.ts
new file mode 100644
index 00000000..13e17591
--- /dev/null
+++ b/packages/html/src/define/skin-element.ts
@@ -0,0 +1,45 @@
+import { ReactiveElement } from '@videojs/element';
+import {
+ applyShadowStyles,
+ createShadowStyle,
+ ensureGlobalStyle,
+ renderTemplate,
+ type ShadowStyle,
+} from '@videojs/utils/dom';
+import rootStyles from './base.css?inline';
+import sharedStyles from './shared.css?inline';
+
+const STYLES_ID = '__media-styles';
+const sharedSheet = createShadowStyle(sharedStyles);
+
+/**
+ * Base element for skin definitions. Attaches a shadow root, clones
+ * `static template` into it, and applies shared + per-skin styles
+ * via `adoptedStyleSheets` (or `