mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-18 00:55:35 +00:00
@uppy/dashboard: fix form appending for shadow dom (#6031)
Fixes #6028
I've also added `private/dev/dashboard_shadow.html` to more easily test
ShadowDOM-specific bugs.
I looked into writing a test case under
`packages/@uppy/dashboard/src/index.browser.test.ts` but couldn't get it
to work locally on Windows.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Ensure FileCard’s hidden form is appended/cleaned up in the correct
root (Document body or ShadowRoot) using a ref-derived root node, and
add a patch changeset.
>
> - **@uppy/dashboard – FileCard**:
> - Append hidden `form` to the correct root using `getRootNode()`
(handles Light DOM/iframes via `Document.body`, and Shadow DOM via
`ShadowRoot`).
> - Add `domRef` to root element to detect rendering context; attach
`ref` and update effect accordingly.
> - Clean up by removing the `form` from its actual `parentNode`.
> - **Release**:
> - Add changeset for patch: `Fix form appending for shadow dom`.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
edf81e871c. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
---------
Co-authored-by: Murderlon <merlijn@soverin.net>
This commit is contained in:
parent
b1e33bcef7
commit
5e166a101d
2 changed files with 32 additions and 3 deletions
5
.changeset/funny-insects-clean.md
Normal file
5
.changeset/funny-insects-clean.md
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"@uppy/dashboard": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix form appending for shadow dom
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { nanoid } from 'nanoid/non-secure'
|
import { nanoid } from 'nanoid/non-secure'
|
||||||
import { useCallback, useEffect, useState } from 'preact/hooks'
|
import { useCallback, useEffect, useRef, useState } from 'preact/hooks'
|
||||||
import getFileTypeIcon from '../../utils/getFileTypeIcon.js'
|
import getFileTypeIcon from '../../utils/getFileTypeIcon.js'
|
||||||
import ignoreEvent from '../../utils/ignoreEvent.js'
|
import ignoreEvent from '../../utils/ignoreEvent.js'
|
||||||
import FilePreview from '../FilePreview.js'
|
import FilePreview from '../FilePreview.js'
|
||||||
|
|
@ -66,14 +66,37 @@ export default function FileCard(props: $TSFixMe) {
|
||||||
return formEl
|
return formEl
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// We need to know where Uppy is being rendered
|
||||||
|
const domRef = useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
document.body.appendChild(form)
|
/**
|
||||||
|
* Use the "rootNode" of whereever Uppy is rendered, falling back
|
||||||
|
* to `window.document` if domRef isn't initialized for some reason
|
||||||
|
*/
|
||||||
|
const rootNode = domRef.current?.getRootNode() ?? (document as Node)
|
||||||
|
/**
|
||||||
|
* This is the case for the Light DOM and <iframes>.
|
||||||
|
* In these scenarios, we don't want to append a child to an
|
||||||
|
* <html> element, but to the <body>
|
||||||
|
*/
|
||||||
|
if (rootNode instanceof Document) {
|
||||||
|
rootNode.body.appendChild(form)
|
||||||
|
}
|
||||||
|
// This is the case for the Shadow DOM
|
||||||
|
else if (rootNode instanceof ShadowRoot) {
|
||||||
|
rootNode.appendChild(form)
|
||||||
|
}
|
||||||
|
// Everything else (realistically there isn't)
|
||||||
|
else {
|
||||||
|
rootNode.appendChild(form)
|
||||||
|
}
|
||||||
form.addEventListener('submit', handleSave)
|
form.addEventListener('submit', handleSave)
|
||||||
return () => {
|
return () => {
|
||||||
form.removeEventListener('submit', handleSave)
|
form.removeEventListener('submit', handleSave)
|
||||||
// check if form is still in the DOM before removing
|
// check if form is still in the DOM before removing
|
||||||
if (form.parentNode) {
|
if (form.parentNode) {
|
||||||
document.body.removeChild(form)
|
form.parentNode.removeChild(form)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [form, handleSave])
|
}, [form, handleSave])
|
||||||
|
|
@ -87,6 +110,7 @@ export default function FileCard(props: $TSFixMe) {
|
||||||
onDragLeave={ignoreEvent}
|
onDragLeave={ignoreEvent}
|
||||||
onDrop={ignoreEvent}
|
onDrop={ignoreEvent}
|
||||||
onPaste={ignoreEvent}
|
onPaste={ignoreEvent}
|
||||||
|
ref={domRef}
|
||||||
>
|
>
|
||||||
<div className="uppy-DashboardContent-bar">
|
<div className="uppy-DashboardContent-bar">
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue