Skip to content

Commit bd190bc

Browse files
committed
allow passing a target document through contexts
1 parent 2d6b78c commit bd190bc

5 files changed

Lines changed: 67 additions & 20 deletions

File tree

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

Lines changed: 32 additions & 14 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 Map<Document, HTMLStyleElement>();
5+
6+
const getStyleTag = (document: Document): HTMLStyleElement => {
7+
let element = documentStyleElementMap.get(document);
8+
console.trace('getStyleTag', document, element);
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,13 @@ const getStyleTag = (): HTMLStyleElement => {
2330
return element;
2431
};
2532

26-
let styleSheet: CSSStyleSheet;
27-
const getStyleSheet = (): CSSStyleSheet => {
33+
// let styleSheet: CSSStyleSheet;
34+
const documentStyleSheetMap = new Map<Document, CSSStyleSheet>();
35+
const getStyleSheet = (document: Document): CSSStyleSheet => {
36+
let styleSheet = documentStyleSheetMap.get(document);
37+
2838
if (!styleSheet) {
29-
const styleTag = getStyleTag();
39+
const styleTag = getStyleTag(document);
3040
const _styleSheet =
3141
styleTag.sheet ||
3242
Array.from(document.styleSheets).find(
@@ -40,24 +50,29 @@ const getStyleSheet = (): CSSStyleSheet => {
4050
styleSheet = _styleSheet;
4151
}
4252

53+
documentStyleSheetMap.set(document, styleSheet);
54+
4355
return styleSheet;
4456
};
4557

46-
type RuleAttacher = (rules: string) => () => void;
58+
type RuleAttacher = (
59+
rules: string,
60+
options: { document: Document },
61+
) => () => void;
4762

4863
const discardRules: RuleAttacher = () => () => undefined;
4964

50-
const attachRulesIntoElement: RuleAttacher = (rules) => {
51-
const element = getStyleTag();
65+
const attachRulesIntoElement: RuleAttacher = (rules, { document }) => {
66+
const element = getStyleTag(document);
5267

5368
const textNode = document.createTextNode(rules);
5469
element.appendChild(textNode);
5570

5671
return () => textNode.remove();
5772
};
5873

59-
const attachRulesIntoStyleSheet: RuleAttacher = (rules) => {
60-
const styleSheet = getStyleSheet();
74+
const attachRulesIntoStyleSheet: RuleAttacher = (rules, { document }) => {
75+
const styleSheet = getStyleSheet(document);
6176
const index = styleSheet.insertRule(
6277
`@media all{${rules}}`,
6378
styleSheet.cssRules.length,
@@ -88,11 +103,14 @@ const wrapReferenceCounting = (attacher: RuleAttacher): RuleAttacher => {
88103
window.queueMicrotask(fn);
89104
};
90105

91-
const enhancedAttacher: RuleAttacher = (content: string) => {
106+
const enhancedAttacher: RuleAttacher = (content, options) => {
92107
const id = hash(content);
93108

94109
if (!refs[id]) {
95-
const detach = attacher(content);
110+
const detach = attacher(content, {
111+
...options,
112+
document: options.document ? options.document : window.document,
113+
});
96114
let count = 0;
97115

98116
const ref = (): void => {

packages/fuselage/src/hooks/useStyle.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,21 @@ import {
55
transpile,
66
attachRules,
77
} from '@rocket.chat/css-in-js';
8-
import { useDebugValue, useInsertionEffect, useMemo } from 'react';
8+
import {
9+
createContext,
10+
useContext,
11+
useDebugValue,
12+
useInsertionEffect,
13+
useMemo,
14+
} from 'react';
15+
16+
export const StyleOptions = createContext<{
17+
document?: Document;
18+
}>({ document: window.document });
19+
20+
export const useStyleOptions = () => {
21+
return useContext(StyleOptions);
22+
};
923

1024
export const useStyle = (cssFn: cssFn | undefined, arg: unknown) => {
1125
const content = useMemo(() => (cssFn ? cssFn(arg) : undefined), [arg, cssFn]);
@@ -20,19 +34,21 @@ export const useStyle = (cssFn: cssFn | undefined, arg: unknown) => {
2034

2135
useDebugValue(className);
2236

37+
const { document } = useStyleOptions();
38+
2339
useInsertionEffect(() => {
2440
if (!content || !className) {
2541
return;
2642
}
2743

2844
const escapedClassName = escapeName(className);
2945
const transpiledContent = transpile(`.${escapedClassName}`, content);
30-
const detach = attachRules(transpiledContent);
46+
const detach = attachRules(transpiledContent, { document });
3147

3248
return () => {
3349
setTimeout(detach, 1000);
3450
};
35-
}, [className, content]);
51+
}, [className, content, document]);
3652

3753
return className;
3854
};

packages/fuselage/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ import './index.scss';
33
export * from './components';
44
export * from './styleTokens';
55

6+
export { StyleOptions } from './hooks/useStyle';
7+
68
export { Palette, __setThrowErrorOnInvalidToken__ } from './Theme';
79
export { useArrayLikeClassNameProp } from './hooks/useArrayLikeClassNameProp';

packages/styled/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export { default } from './styled';
1+
export { default, StyledOptions } from './styled';

packages/styled/src/styled.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,18 @@ import {
2020
Fragment,
2121
useDebugValue,
2222
useInsertionEffect,
23+
createContext,
24+
useContext,
2325
} from 'react';
2426

27+
export const StyledOptions = createContext<{
28+
document?: Document;
29+
}>({ document: window.document });
30+
31+
const useStyledOptions = () => {
32+
return useContext(StyledOptions);
33+
};
34+
2535
export const attachClassName = <P extends { className?: string }>(
2636
props: P,
2737
additionalClassName: string,
@@ -85,18 +95,19 @@ const styled =
8595

8696
useDebugValue(computedClassName);
8797

98+
const { document } = useStyledOptions();
8899
useInsertionEffect(() => {
89100
const escapedClassName = escapeName(computedClassName);
90101
const transpiledContent = transpile(
91102
`.${escapedClassName}`,
92103
content,
93104
);
94-
const detach = attachRules(transpiledContent);
105+
const detach = attachRules(transpiledContent, { document });
95106

96107
return () => {
97108
setTimeout(detach, 1000);
98109
};
99-
}, [computedClassName, content]);
110+
}, [computedClassName, content, document]);
100111

101112
const newProps = attachClassName(
102113
{ ref, ...props },

0 commit comments

Comments
 (0)