Skip to content

Commit

Permalink
feat(stylesheets): Sheets now persist
Browse files Browse the repository at this point in the history
  • Loading branch information
calebdwilliams committed Jan 20, 2019
1 parent 5801d62 commit decaf7c
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 8 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ class TestEl extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.adoptedStyleSheets = [everythingTomato];
}

connectedCallback() {
this.shadowRoot.innerHTML = `<h1>This will be tomato colored, too</h1>`;
this.shadowRoot.adoptedStyleSheets = [everythingTomato];
}
}

Expand Down
51 changes: 45 additions & 6 deletions adoptedStyleSheets.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,35 @@
(function() {
'use strict';

console.clear();
const supportsAdoptedStyleSheets = 'adoptedStyleSheets' in document;
if (!supportsAdoptedStyleSheets) {
const node = Symbol('constructible style sheets');
const constructed = Symbol('constructed');
const removalListener = Symbol('listener');
const iframe = document.createElement('iframe');
const mutationCallback = mutations => {
mutations.forEach(mutation => {
const { removedNodes } = mutation;
removedNodes.forEach(removed => {
if (removed[constructed]) {
setTimeout(() => {
removed[constructed].appendChild(removed);
});
}
});
});
};
const observer = new MutationObserver(mutationCallback);
observer.observe(document.body, { childList: true });
iframe.hidden = true;
document.body.appendChild(iframe);

const appendContent = (location, sheet) => {
const clone = sheet[node]._sheet.cloneNode(true);
location.body ? location = location.body : null;
location.appendChild(clone);
clone[constructed] = location;
sheet[node]._adopters.push({ location, clone });
location.appendChild(clone);
return clone;
};

Expand All @@ -21,6 +38,19 @@
adopter.clone.innerHTML = sheet[node]._sheet.innerHTML;
});
};

const onShadowRemoval = (root, observer) => event => {
const shadowRoot = event.target.shadowRoot;
if (shadowRoot && shadowRoot.adoptedStyleSheets.length) {
const adoptedStyleSheets = shadowRoot.adoptedStyleSheets;
adoptedStyleSheets
.map(sheet => sheet[node])
.map(sheet => {
sheet._adopters = sheet._adopters.filter(adopter => adopter.location !== shadowRoot);
});
}
observer.disconnect();
};

class _StyleSheet {
constructor() {
Expand Down Expand Up @@ -61,19 +91,28 @@
return this._adopted || [];
},
set(sheets) {
const observer = new MutationObserver(mutationCallback);
observer.observe(this, { childList: true });
if (!Array.isArray(sheets)) {
throw new TypeError('Adopted style sheets must be an Array');
}
sheets.forEach(sheet => {
if (!sheet instanceof CSSStyleSheet) {
throw new TypeError('sdkfljdslfkj');
throw new TypeError('Adopted style sheets must be of type CSSStyleSheet');
}
});
const uniqueSheets = [...new Set(sheets)];
this._adopted = uniqueSheets;
sheets.forEach(sheet => {
appendContent(this, sheet);
});

if (this.isConnected) {
sheets.forEach(sheet => {
appendContent(this, sheet);
});
}

const removalListener = onShadowRemoval(this, observer);
this[removalListener] = removalListener;
this.addEventListener('DOMNodeRemoved', removalListener, true);
}
};

Expand Down
2 changes: 1 addition & 1 deletion adoptedStyleSheets.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit decaf7c

Please sign in to comment.