Skip to content

Commit 00052dc

Browse files
feat(css-in-js): Allow passing a target document to rule attacher (#1933)
Co-authored-by: Tasso Evangelista <tasso.evangelista@rocket.chat>
1 parent 4f90c69 commit 00052dc

2 files changed

Lines changed: 52 additions & 16 deletions

File tree

.changeset/smooth-deers-burn.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@rocket.chat/css-in-js": minor
3+
---
4+
5+
feat(css-in-js): Allow passing a target `document` to rule attacher

packages/css-in-js/src/sheet.ts

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,27 @@
11
import hash from '@emotion/hash';
22

33
const elementId = 'rcx-styles';
4-
let element: HTMLStyleElement;
5-
const getStyleTag = (): HTMLStyleElement => {
4+
const documentStyleElementMap = new WeakMap<Document, HTMLStyleElement>();
5+
6+
const getStyleTag = (document: Document): HTMLStyleElement => {
7+
let element = documentStyleElementMap.get(document);
8+
69
if (!element) {
710
const el = document.getElementById(elementId) as HTMLStyleElement;
811
if (el) {
9-
element = el;
10-
return element;
12+
documentStyleElementMap.set(document, el);
13+
return el;
1114
}
1215
}
1316

1417
if (!element) {
1518
element = document.createElement('style');
19+
20+
documentStyleElementMap.set(document, element);
21+
1622
element.id = elementId;
1723
element.appendChild(document.createTextNode(''));
24+
1825
if (document.head) {
1926
document.head.appendChild(element);
2027
}
@@ -23,10 +30,12 @@ const getStyleTag = (): HTMLStyleElement => {
2330
return element;
2431
};
2532

26-
let styleSheet: CSSStyleSheet;
27-
const getStyleSheet = (): CSSStyleSheet => {
33+
const documentStyleSheetMap = new WeakMap<Document, CSSStyleSheet>();
34+
const getStyleSheet = (document: Document): CSSStyleSheet => {
35+
let styleSheet = documentStyleSheetMap.get(document);
36+
2837
if (!styleSheet) {
29-
const styleTag = getStyleTag();
38+
const styleTag = getStyleTag(document);
3039
const _styleSheet =
3140
styleTag.sheet ||
3241
Array.from(document.styleSheets).find(
@@ -40,24 +49,34 @@ const getStyleSheet = (): CSSStyleSheet => {
4049
styleSheet = _styleSheet;
4150
}
4251

52+
documentStyleSheetMap.set(document, styleSheet);
53+
4354
return styleSheet;
4455
};
4556

46-
type RuleAttacher = (rules: string) => () => void;
57+
type StrictRuleAttacher = (
58+
rules: string,
59+
options: { document: Document },
60+
) => () => void;
61+
62+
type RuleAttacher = (
63+
rules: string,
64+
options?: { document?: Document },
65+
) => () => void;
4766

4867
const discardRules: RuleAttacher = () => () => undefined;
4968

50-
const attachRulesIntoElement: RuleAttacher = (rules) => {
51-
const element = getStyleTag();
69+
const attachRulesIntoElement: StrictRuleAttacher = (rules, { document }) => {
70+
const element = getStyleTag(document);
5271

5372
const textNode = document.createTextNode(rules);
5473
element.appendChild(textNode);
5574

5675
return () => textNode.remove();
5776
};
5877

59-
const attachRulesIntoStyleSheet: RuleAttacher = (rules) => {
60-
const styleSheet = getStyleSheet();
78+
const attachRulesIntoStyleSheet: StrictRuleAttacher = (rules, { document }) => {
79+
const styleSheet = getStyleSheet(document);
6180
const index = styleSheet.insertRule(
6281
`@media all{${rules}}`,
6382
styleSheet.cssRules.length,
@@ -73,8 +92,10 @@ const attachRulesIntoStyleSheet: RuleAttacher = (rules) => {
7392
};
7493
};
7594

76-
const wrapReferenceCounting = (attacher: RuleAttacher): RuleAttacher => {
77-
const refs: Record<string, { ref(): void; unref(): void }> = {};
95+
type RefCounter = Record<string, { ref(): void; unref(): void }>;
96+
97+
const wrapReferenceCounting = (attacher: StrictRuleAttacher): RuleAttacher => {
98+
const refDocumentMap = new WeakMap<Document, RefCounter>();
7899

79100
const queueMicrotask = (fn: () => void): void => {
80101
if (
@@ -88,11 +109,21 @@ const wrapReferenceCounting = (attacher: RuleAttacher): RuleAttacher => {
88109
window.queueMicrotask(fn);
89110
};
90111

91-
const enhancedAttacher: RuleAttacher = (content: string) => {
112+
const enhancedAttacher: RuleAttacher = (content, options = {}) => {
92113
const id = hash(content);
114+
const document = options.document ? options.document : window.document;
115+
116+
const refs = refDocumentMap.get(document) || {};
117+
118+
if (!refDocumentMap.has(document)) {
119+
refDocumentMap.set(document, refs);
120+
}
93121

94122
if (!refs[id]) {
95-
const detach = attacher(content);
123+
const detach = attacher(content, {
124+
...options,
125+
document: options.document ? options.document : window.document,
126+
});
96127
let count = 0;
97128

98129
const ref = (): void => {

0 commit comments

Comments
 (0)