mirror of
https://github.com/mathuo/dockview
synced 2025-02-08 17:35:44 +00:00
bug: disable iframes within shadowdom during dnd
This commit is contained in:
parent
429177436e
commit
a4b9255f43
@ -112,8 +112,11 @@ export function isAncestor(
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getElementsByTagName(tag: string): HTMLElement[] {
|
||||
return Array.prototype.slice.call(document.getElementsByTagName(tag), 0);
|
||||
export function getElementsByTagName(
|
||||
tag: string,
|
||||
document: ParentNode
|
||||
): HTMLElement[] {
|
||||
return Array.prototype.slice.call(document.querySelectorAll(tag), 0);
|
||||
}
|
||||
|
||||
export interface IFocusTracker extends IDisposable {
|
||||
@ -288,10 +291,29 @@ export function addTestId(element: HTMLElement, id: string): void {
|
||||
element.setAttribute('data-testid', id);
|
||||
}
|
||||
|
||||
export function disableIframePointEvents() {
|
||||
export function disableIframePointEvents(rootNode: ParentNode = document) {
|
||||
const includeShadowDom = true;
|
||||
|
||||
const shadowRoots = [];
|
||||
|
||||
if (includeShadowDom) {
|
||||
const items = rootNode.querySelectorAll('*');
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
const item = items[i];
|
||||
if (item.shadowRoot) {
|
||||
shadowRoots.push(item.shadowRoot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const iframes: HTMLElement[] = [
|
||||
...getElementsByTagName('iframe'),
|
||||
...getElementsByTagName('webview'),
|
||||
...getElementsByTagName('iframe', rootNode),
|
||||
...getElementsByTagName('webview', rootNode),
|
||||
...shadowRoots.flatMap((root) => [
|
||||
...getElementsByTagName('iframe', root),
|
||||
...getElementsByTagName('webview', root),
|
||||
]),
|
||||
];
|
||||
|
||||
const original = new WeakMap<HTMLElement, string>(); // don't hold onto HTMLElement references longer than required
|
||||
|
@ -7,6 +7,7 @@ import {
|
||||
DockviewApi,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom/client';
|
||||
import './app.scss';
|
||||
import { defaultConfig } from './defaultLayout';
|
||||
import { GridActions } from './gridActions';
|
||||
@ -30,6 +31,20 @@ const Option = (props: {
|
||||
);
|
||||
};
|
||||
|
||||
const ShadowIframe = (props: IDockviewPanelProps) => {
|
||||
return (
|
||||
<iframe
|
||||
onMouseDown={() => {
|
||||
if (!props.api.isActive) {
|
||||
props.api.setActive();
|
||||
}
|
||||
}}
|
||||
style={{ border: 'none', width: '100%', height: '100%' }}
|
||||
src="https://dockview.dev"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps) => {
|
||||
const isDebug = React.useContext(DebugContext);
|
||||
@ -105,6 +120,7 @@ const components = {
|
||||
}
|
||||
}}
|
||||
style={{
|
||||
border: 'none',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
@ -112,6 +128,33 @@ const components = {
|
||||
/>
|
||||
);
|
||||
},
|
||||
shadowDom: (props: IDockviewPanelProps) => {
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!ref.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const shadow = ref.current.attachShadow({
|
||||
mode: 'open',
|
||||
});
|
||||
|
||||
const shadowRoot = document.createElement('div');
|
||||
shadowRoot.style.height = '100%';
|
||||
shadow.appendChild(shadowRoot);
|
||||
|
||||
const root = ReactDOM.createRoot(shadowRoot);
|
||||
|
||||
root.render(<ShadowIframe {...props} />);
|
||||
|
||||
return () => {
|
||||
root.unmount();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return <div style={{ height: '100%' }} ref={ref}></div>;
|
||||
},
|
||||
};
|
||||
|
||||
const headerComponents = {
|
||||
@ -208,7 +251,7 @@ const DockviewDemo = (props: { theme?: string }) => {
|
||||
|
||||
event.api.onDidMaximizedGroupChange((event) => {
|
||||
addLogLine(
|
||||
`Group Maximized Changed ${event.view.id} [${event.isMaximized}]`
|
||||
`Group Maximized Changed ${event.group.id} [${event.isMaximized}]`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -132,7 +132,10 @@ export const GridActions = (props: {
|
||||
|
||||
const popover = usePopover();
|
||||
|
||||
const onAddPanel = (options?: { advanced: boolean }) => {
|
||||
const onAddPanel = (options?: {
|
||||
advanced: boolean;
|
||||
component?: string;
|
||||
}) => {
|
||||
if (options?.advanced) {
|
||||
popover.open(({ close }) => {
|
||||
return <PanelBuilder api={props.api!} done={close} />;
|
||||
@ -140,7 +143,7 @@ export const GridActions = (props: {
|
||||
} else {
|
||||
props.api?.addPanel({
|
||||
id: `id_${Date.now().toString()}`,
|
||||
component: 'default',
|
||||
component: options?.component ?? 'default',
|
||||
title: `Tab ${nextId()}`,
|
||||
renderer: 'always',
|
||||
});
|
||||
@ -170,6 +173,22 @@ export const GridActions = (props: {
|
||||
<span className="material-symbols-outlined">tune</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="button-group">
|
||||
<button
|
||||
className="text-button"
|
||||
onClick={() =>
|
||||
onAddPanel({ component: 'shadowDom', advanced: false })
|
||||
}
|
||||
>
|
||||
Add Panel 2
|
||||
</button>
|
||||
<button
|
||||
className="demo-icon-button"
|
||||
onClick={() => onAddPanel({ advanced: true })}
|
||||
>
|
||||
<span className="material-symbols-outlined">tune</span>
|
||||
</button>
|
||||
</div>
|
||||
<button className="text-button" onClick={onAddGroup}>
|
||||
Add Group
|
||||
</button>
|
||||
|
@ -75,9 +75,9 @@ const PanelAction = (props: {
|
||||
const panel = props.api.getPanel(props.panelId);
|
||||
if (panel) {
|
||||
props.api.addFloatingGroup(panel, {
|
||||
width: 400,
|
||||
height: 300,
|
||||
position: {
|
||||
width: 400,
|
||||
height: 300,
|
||||
bottom: 50,
|
||||
right: 50,
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user