diff --git a/README.md b/README.md index d4e7dab..a960cde 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ const Greeting = ({ name = 'World' }) => (

Hello, {name}!

); -register(Greeting, 'x-greeting', ['name'], { shadow: true, mode: 'open' }); -// ^ ^ ^ ^ ^ -// | HTML tag name | use shadow-dom | +register(Greeting, 'x-greeting', ['name'], { shadow: true, mode: 'open', adoptedStyleSheets: [] }); +// ^ ^ ^ ^ ^ ^ +// | HTML tag name | use shadow-dom | use adoptedStyleSheets // Component definition Observed attributes Encapsulation mode for the shadow DOM tree ``` diff --git a/src/index.js b/src/index.js index ea157a5..355cb68 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,7 @@ import { h, cloneElement, render, hydrate } from 'preact'; /** * @typedef {import('preact').FunctionComponent | import('preact').ComponentClass | import('preact').FunctionalComponent } ComponentDefinition - * @typedef {{ shadow: false } | { shadow: true, mode?: 'open' | 'closed' }} Options + * @typedef {{ shadow: false } | { shadow: true, mode?: 'open' | 'closed', adoptedStyleSheets?: CSSStyleSheet[] }} Options * @typedef {HTMLElement & { _root: ShadowRoot | HTMLElement, _vdomComponent: ComponentDefinition, _vdom: ReturnType | null }} PreactCustomElement */ @@ -47,6 +47,11 @@ export default function register(Component, tagName, propNames, options) { options && options.shadow ? inst.attachShadow({ mode: options.mode || 'open' }) : inst; + + if (options && options.adoptedStyleSheets) { + inst._root.adoptedStyleSheets = options.adoptedStyleSheets; + } + return inst; } PreactElement.prototype = Object.create(HTMLElement.prototype); diff --git a/src/index.test.jsx b/src/index.test.jsx index b1a7592..ada8273 100644 --- a/src/index.test.jsx +++ b/src/index.test.jsx @@ -309,4 +309,28 @@ describe('web components', () => { assert.equal(myForm.elements[0].tagName, 'X-FORM-ASSOCIATED-CLASS'); assert.equal(myForm.elements[2].tagName, 'X-FORM-ASSOCIATED-FUNCTION'); }); + + it('supports the `adoptedStyleSheets` option', async () => { + function AdoptedStyleSheets() { + return
Adopted Style Sheets
; + } + + const sheet = new CSSStyleSheet(); + sheet.replaceSync('.styled-child { color: red; }'); + + registerElement(AdoptedStyleSheets, 'x-adopted-style-sheets', [], { + shadow: true, + adoptedStyleSheets: [sheet], + }); + + root.innerHTML = ``; + + const child = document + .querySelector('x-adopted-style-sheets') + .shadowRoot + .querySelector('.styled-child'); + + const style = getComputedStyle(child); + assert.equal(style.color, 'rgb(255, 0, 0)'); + }); });