Skip to content

Instantly share code, notes, and snippets.

@thepassle
Last active September 22, 2019 14:26
Show Gist options
  • Save thepassle/c7773a2909b4ed60d7fa19851da2e9d8 to your computer and use it in GitHub Desktop.
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
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);
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