Last active
September 22, 2019 14:26
-
-
Save thepassle/c7773a2909b4ed60d7fa19851da2e9d8 to your computer and use it in GitHub Desktop.
Add shadowDOM to a Preact Hooks component and use Constructible StyleSheets if available
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Shadow, css } from './Shadow.js'; | |
import { useState } from './web_modules/preact/hooks.js'; | |
import { html } from '../web_modules/htm/preact.js'; | |
const styles = css` | |
h1 { color: red; } | |
`; | |
function MyHook() { | |
const [count, setCount] = useState(0); | |
return html` | |
<h1>Count: ${count}</h1> | |
<button onClick=${() => setCount(count+1)}>click me!</button> | |
`; | |
} | |
export default Shadow(MyHook, styles); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, render } from "../web_modules/htm/preact.js"; | |
/** @type {boolean} */ | |
const supportsAdoptingStyleSheets = | |
('adoptedStyleSheets' in Document.prototype) && | |
('replace' in CSSStyleSheet.prototype); | |
/** | |
* Sets a string of css rules to the documents adoptedStyleSheets | |
* @param {TemplateStringsArray} strings - css rules | |
*/ | |
export const css = (strings) => { | |
if(supportsAdoptingStyleSheets) { | |
const sheet = new CSSStyleSheet(); | |
sheet.replace(strings.join("")); | |
return sheet; | |
} else { | |
const styleTag = document.createElement('style'); | |
styleTag.innerHTML = strings.join(""); | |
return styleTag; | |
} | |
}; | |
/** | |
* Creates a shadowRoot and adds styles as a style tag or Constructible StyleSheet | |
* @param {() => {}} Comp - your component | |
* @param {CSSStyleSheet | Node} styles - style rules | |
* @mixinFunction | |
*/ | |
export const Shadow = (ComponentClass, styles = css``) => class Shadow extends Component { | |
setup(node) { | |
this.shadow = node.attachShadow({mode: 'open'}); | |
this._component = render(html`<${ComponentClass} ...${this.props}/>`, this.shadow); | |
if(styles instanceof CSSStyleSheet) { | |
this.shadow.adoptedStyleSheets = [...this.shadow.adoptedStyleSheets, styles]; | |
} else { | |
this.shadow.appendChild(styles); | |
} | |
} | |
render() { | |
return html`<div ref=${this.setup.bind(this)}/>`; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment