Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow any Node, including ShadowRoot, as container #2728

Merged
merged 10 commits into from Apr 28, 2022
6 changes: 6 additions & 0 deletions .changeset/five-balloons-sneeze.md
@@ -0,0 +1,6 @@
---
'@emotion/cache': patch
'@emotion/sheet': patch
---

The cache's `container` can be a `ShadowRoot`, or any other kind of `Node`
Peeja marked this conversation as resolved.
Show resolved Hide resolved
2 changes: 1 addition & 1 deletion packages/cache/README.md
Expand Up @@ -51,7 +51,7 @@ The prefix before class names. It will also be set as the value of the `data-emo

### `container`

`HTMLElement`
`Node`

A DOM node that emotion will insert all of its style tags into. This is useful for inserting styles into iframes or windows.

Expand Down
33 changes: 33 additions & 0 deletions packages/cache/__tests__/__snapshots__/index.js.snap
@@ -1,5 +1,38 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should accept container option 1`] = `
.emotion-0 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
color: blue;
}

<body>


<div
id="container"
>


<style
data-emotion="test-container"
data-s=""
>

.emotion-0{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;color:blue;}
</style>
</div>
<div>
<div
class="emotion-0"
/>
</div>
</body>
`;

exports[`should accept insertionPoint option 1`] = `
<head>

Expand Down
21 changes: 21 additions & 0 deletions packages/cache/__tests__/index.js
Expand Up @@ -34,3 +34,24 @@ it('should accept insertionPoint option', () => {

expect(document.head).toMatchSnapshot()
})

it('should accept container option', () => {
const body = safeQuerySelector('body')

body.innerHTML = `
<div id="container" />
`

const cache = createCache({
key: 'test-container',
container: safeQuerySelector('#container')
})

render(
<CacheProvider value={cache}>
<div css={{ display: 'flex', color: 'blue' }} />
</CacheProvider>
)

expect(document.body).toMatchSnapshot()
})
5 changes: 2 additions & 3 deletions packages/cache/src/index.js
Expand Up @@ -92,8 +92,7 @@ let createCache = (options: Options): EmotionCache => {
}
}
let inserted = {}
// $FlowFixMe
let container: HTMLElement
let container: Node
const nodesToHydrate = []
if (isBrowser) {
container = options.container || ((document.head: any): HTMLHeadElement)
Expand Down Expand Up @@ -250,7 +249,7 @@ let createCache = (options: Options): EmotionCache => {
key,
sheet: new StyleSheet({
key,
container: ((container: any): HTMLElement),
container: ((container: any): Node),
nonce: options.nonce,
speedy: options.speedy,
prepend: options.prepend,
Expand Down
2 changes: 1 addition & 1 deletion packages/cache/types/index.d.ts
Expand Up @@ -34,7 +34,7 @@ export interface Options {
nonce?: string
stylisPlugins?: Array<StylisPlugin>
key: string
container?: HTMLElement
container?: Node
speedy?: boolean
/** @deprecate use `insertionPoint` instead */
prepend?: boolean
Expand Down
2 changes: 1 addition & 1 deletion packages/sheet/README.md
Expand Up @@ -25,7 +25,7 @@ sheet.insert('html { color: hotpink; }')
type Options = {
nonce?: string
key: string
container: HTMLElement
container: Node
speedy?: boolean
prepend?: boolean
}
Expand Down
21 changes: 21 additions & 0 deletions packages/sheet/__tests__/__snapshots__/index.js.snap
Expand Up @@ -271,3 +271,24 @@ exports[`StyleSheet should work if insertionPoint is last element 1`] = `
<body />
</html>
`;

exports[`StyleSheet should work with a ShadowRoot container 1`] = `
<html>
<head />
<body>
<div />
</body>
</html>
`;

exports[`StyleSheet should work with a ShadowRoot container 2`] = `
HTMLCollection [
<style
data-emotion=""
data-s=""
>

html { color: hotpink; }
</style>,
]
`;
17 changes: 17 additions & 0 deletions packages/sheet/__tests__/index.js
Expand Up @@ -105,6 +105,23 @@ describe('StyleSheet', () => {
sheet.flush()
})

it('should work with a ShadowRoot container', () => {
const div = document.createElement('div')
// $FlowFixMe
document.body.appendChild(div)
const container = div.attachShadow({ mode: 'open' })
const sheet = new StyleSheet({ ...defaultOptions, container })
expect(sheet.container).toBe(container)
sheet.insert(rule)
expect(document.documentElement).toMatchSnapshot()
// The shadowRoot is not serialized in the snapshot, so we need to take a
// separate snapshot of the shadowRoot's children.
expect(container.children).toMatchSnapshot()
expect(sheet.tags).toHaveLength(1)
expect(sheet.tags[0].parentNode).toBe(container)
sheet.flush()
})

it('should accept prepend option', () => {
const head = safeQuerySelector('head')
const otherStyle = document.createElement('style')
Expand Down
4 changes: 2 additions & 2 deletions packages/sheet/src/index.js
Expand Up @@ -42,7 +42,7 @@ function sheetForTag(tag: HTMLStyleElement): CSSStyleSheet {
export type Options = {
nonce?: string,
key: string,
container: HTMLElement,
container: Node,
speedy?: boolean,
prepend?: boolean,
insertionPoint?: HTMLElement
Expand All @@ -66,7 +66,7 @@ export class StyleSheet {
isSpeedy: boolean
ctr: number
tags: HTMLStyleElement[]
container: HTMLElement
container: Node
Peeja marked this conversation as resolved.
Show resolved Hide resolved
key: string
nonce: string | void
prepend: boolean | void
Expand Down
4 changes: 2 additions & 2 deletions packages/sheet/types/index.d.ts
Expand Up @@ -4,7 +4,7 @@
export interface Options {
nonce?: string
key: string
container: HTMLElement
container: Node
speedy?: boolean
/** @deprecate use `insertionPoint` instead */
prepend?: boolean
Expand All @@ -15,7 +15,7 @@ export class StyleSheet {
isSpeedy: boolean
ctr: number
tags: Array<HTMLStyleElement>
container: HTMLElement
container: Node
key: string
nonce?: string
before?: Element | null
Peeja marked this conversation as resolved.
Show resolved Hide resolved
Expand Down