feat: fix dnd firefox bug

+ simplify tab rendering and remove support for HOC Dockview components
  since it's not a great implementation - can find another solution if
  required
This commit is contained in:
mathuo 2022-05-09 21:23:23 +01:00
parent df52c808ab
commit bb247e1303
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
7 changed files with 14 additions and 172 deletions

View File

@ -7,67 +7,6 @@ import { addDisposableListener } from '../../../events';
import { PanelUpdateEvent } from '../../../panel/types';
import { GroupPanel } from '../../../groupview/groupviewPanel';
export class WrappedTab implements ITabRenderer {
private readonly _element: HTMLElement;
constructor(private readonly renderer: ITabRenderer) {
this._element = document.createElement('element');
this.show();
}
get innerRenderer() {
return this.renderer;
}
get element() {
return this._element;
}
get id() {
return this.renderer.id;
}
show() {
if (!this.renderer.element.parentElement) {
this._element.appendChild(this.renderer.element);
}
}
hide() {
if (this.renderer.element.parentElement) {
this.renderer.element.remove();
}
}
layout(width: number, height: number): void {
this.renderer.layout(width, height);
}
update(event: PanelUpdateEvent): void {
this.renderer.update(event);
}
toJSON(): object {
return this.renderer.toJSON();
}
focus(): void {
this.renderer.focus();
}
init(parameters: GroupPanelPartInitParameters): void {
this.renderer.init(parameters);
}
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void {
this.renderer.updateParentGroup(group, isPanelVisible);
}
dispose() {
this.renderer.dispose();
}
}
export class DefaultTab extends CompositeDisposable implements ITabRenderer {
private _element: HTMLElement;
@ -148,10 +87,16 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
}
public updateParentGroup(group: GroupPanel, isPanelVisible: boolean) {
const changed =
this._isPanelVisible !== isPanelVisible ||
this._isGroupActive !== group.isActive;
this._isPanelVisible = isPanelVisible;
this._isGroupActive = group.isActive;
this.render();
if (changed) {
this.render();
}
}
public layout(_width: number, _height: number) {

View File

@ -1,4 +1,4 @@
import { DefaultTab, WrappedTab } from './components/tab/defaultTab';
import { DefaultTab } from './components/tab/defaultTab';
import {
GroupPanelPartInitParameters,
IActionsRenderer,
@ -22,7 +22,7 @@ export interface IGroupPanelView extends IDisposable {
export class DefaultGroupPanelView implements IGroupPanelView {
private readonly _content: IContentRenderer;
private readonly _tab: WrappedTab;
private readonly _tab: ITabRenderer;
private readonly _actions: IActionsRenderer | undefined;
get content() {
@ -43,7 +43,7 @@ export class DefaultGroupPanelView implements IGroupPanelView {
actions?: IActionsRenderer;
}) {
this._content = renderers.content;
this._tab = new WrappedTab(renderers.tab ?? new DefaultTab());
this._tab = renderers.tab ?? new DefaultTab();
this._actions =
renderers.actions ||
(this.content.actions
@ -78,10 +78,7 @@ export class DefaultGroupPanelView implements IGroupPanelView {
toJSON(): {} {
return {
content: this.content.toJSON(),
tab:
this.tab.innerRenderer instanceof DefaultTab
? undefined
: this.tab.toJSON(),
tab: this.tab instanceof DefaultTab ? undefined : this.tab.toJSON(),
};
}

View File

@ -5,7 +5,6 @@ import { PanelInitParameters, IPanel } from '../panel/types';
import { DockviewApi } from '../api/component.api';
import { GroupPanel } from './groupviewPanel';
import { Event } from '../events';
import { WrappedTab } from '../dockview/components/tab/defaultTab';
export interface IRenderable {
id: string;
@ -28,7 +27,7 @@ export interface GroupPanelPartInitParameters
export interface GroupPanelContentPartInitParameters
extends GroupPanelPartInitParameters {
tab: WrappedTab;
tab: ITabRenderer;
}
export interface IWatermarkRenderer extends IPanel {
@ -54,7 +53,6 @@ export interface IContentRenderer extends IPanel {
readonly onDidBlur?: Event<void>;
updateParentGroup(group: GroupPanel, isPanelVisible: boolean): void;
init(parameters: GroupPanelContentPartInitParameters): void;
close?(): Promise<boolean>;
}
// watermark component

View File

@ -1,89 +0,0 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { isReactElement, ReactPartContext } from '../react';
import { ReactContentPartContext } from './reactContentPart';
interface WithChildren {
children: React.ReactNode;
}
const Tab: React.FunctionComponent<WithChildren> = (props: WithChildren) => {
return <>{props.children}</>;
};
const Content: React.FunctionComponent<WithChildren> = (
props: WithChildren
) => {
return <>{props.children}</>;
};
const Actions: React.FunctionComponent<WithChildren> = (
props: WithChildren
) => {
return <>{props.children}</>;
};
function isValidComponent(element: React.ReactElement) {
return [Content, Actions, Tab].find((comp) => element.type === comp);
}
const Panel: React.FunctionComponent<WithChildren> = (props: WithChildren) => {
const context = React.useContext(
ReactPartContext
) as ReactContentPartContext;
const sections = React.useMemo(() => {
const childs =
React.Children.map(props.children, (_) => _)?.filter(
isReactElement
) || [];
const isInvalid = !!childs.find((_) => !isValidComponent(_));
if (isInvalid) {
throw new Error(
'Children of DockviewComponents.Panel must be one of the following: DockviewComponents.Content, DockviewComponents.Actions, DockviewComponents.Tab'
);
}
const body = childs.find((_) => _.type === Content);
const actions = childs.find((_) => _.type === Actions);
const tab = childs.find((_) => _.type === Tab);
return { body, actions, tab };
}, [props.children]);
React.useEffect(() => {
/**
* hide or show the default tab behavior based on whether we want to override
* with our own React tab.
*/
if (sections.tab) {
context.tabPortalElement.hide();
} else {
context.tabPortalElement.show();
}
}, [sections.tab]);
return (
<>
{sections.actions &&
ReactDOM.createPortal(
sections.actions,
context.actionsPortalElement
)}
{sections.tab &&
ReactDOM.createPortal(
sections.tab,
context.tabPortalElement.element
)}
{sections.body || props.children}
</>
);
};
export const DockviewComponents = {
Tab,
Content,
Actions,
Panel,
};

View File

@ -2,6 +2,7 @@ import * as React from 'react';
import {
IContentRenderer,
GroupPanelContentPartInitParameters,
ITabRenderer,
} from '../../groupview/types';
import { ReactPart, ReactPortalStore } from '../react';
import { IDockviewPanelProps } from '../dockview/dockview';
@ -10,7 +11,6 @@ import { DockviewPanelApi } from '../../api/groupPanelApi';
import { DockviewApi } from '../../api/component.api';
import { GroupPanel } from '../../groupview/groupviewPanel';
import { Emitter, Event } from '../../events';
import { WrappedTab } from '../../dockview/components/tab/defaultTab';
export interface IGroupPanelActionbarProps {
api: DockviewPanelApi;
@ -21,7 +21,7 @@ export interface ReactContentPartContext {
api: DockviewPanelApi;
containerApi: DockviewApi;
actionsPortalElement: HTMLElement;
tabPortalElement: WrappedTab;
tabPortalElement: ITabRenderer;
}
export class ReactPanelContentPart implements IContentRenderer {
@ -104,10 +104,6 @@ export class ReactPanelContentPart implements IContentRenderer {
// noop
}
public close(): Promise<boolean> {
return Promise.resolve(true);
}
public dispose() {
this._onDidFocus.dispose();
this._onDidBlur.dispose();

View File

@ -99,10 +99,6 @@ export class ReactContentRenderer implements IContentRenderer {
this._hostedContainer.layout(this.element);
}
public close(): Promise<boolean> {
return Promise.resolve(true);
}
public dispose() {
this.part?.dispose();
}

View File

@ -1,5 +1,4 @@
export * from './dockview/dockview';
export * from './dockview/components';
export * from './splitview/splitview';
export * from './gridview/gridview';
export * from './dockview/reactContentPart';