mirror of
https://github.com/mathuo/dockview
synced 2025-07-25 19:36:01 +00:00
feat: autoresize views
This commit is contained in:
parent
7d21f9f19e
commit
64c24dca55
@ -13,9 +13,10 @@ module.exports = {
|
|||||||
collectCoverageFrom:[
|
collectCoverageFrom:[
|
||||||
"<rootDir>/packages/splitview/src/**/*.{js,jsx,ts,tsx}",
|
"<rootDir>/packages/splitview/src/**/*.{js,jsx,ts,tsx}",
|
||||||
],
|
],
|
||||||
|
setupFiles: ["<rootDir>/packages/splitview/src/__tests__/__mocks__/resizeObserver.js"],
|
||||||
coveragePathIgnorePatterns: [
|
coveragePathIgnorePatterns: [
|
||||||
"/node_modules/",
|
"/node_modules/",
|
||||||
"<rootDir>packages/splitview/src/__tests__/",
|
|
||||||
],
|
],
|
||||||
|
modulePathIgnorePatterns: ["<rootDir>/packages/splitview/src/__tests__/__mocks__",],
|
||||||
coverageDirectory: "coverage"
|
coverageDirectory: "coverage"
|
||||||
}
|
}
|
||||||
|
5
packages/splitview/package-lock.json
generated
5
packages/splitview/package-lock.json
generated
@ -620,6 +620,11 @@
|
|||||||
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"resize-observer-polyfill": {
|
||||||
|
"version": "1.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
|
||||||
|
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
|
||||||
|
},
|
||||||
"resolve": {
|
"resolve": {
|
||||||
"version": "1.17.0",
|
"version": "1.17.0",
|
||||||
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz",
|
||||||
|
@ -59,5 +59,8 @@
|
|||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"react": ">=16.8.0",
|
"react": ">=16.8.0",
|
||||||
"react-dom": ">=16.8.0"
|
"react-dom": ">=16.8.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"resize-observer-polyfill": "^1.5.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
jest.mock('resize-observer-polyfill', () => ({
|
||||||
|
__esModule: true,
|
||||||
|
default: jest.fn().mockImplementation(() => ({
|
||||||
|
observe: jest.fn(),
|
||||||
|
unobserve: jest.fn(),
|
||||||
|
disconnect: jest.fn(),
|
||||||
|
})),
|
||||||
|
}));
|
@ -5,6 +5,26 @@ import {
|
|||||||
addDisposableWindowListener,
|
addDisposableWindowListener,
|
||||||
} from './events';
|
} from './events';
|
||||||
import { IDisposable, CompositeDisposable } from './lifecycle';
|
import { IDisposable, CompositeDisposable } from './lifecycle';
|
||||||
|
import ResizeObserver from 'resize-observer-polyfill';
|
||||||
|
|
||||||
|
export function watchElementResize(
|
||||||
|
element: HTMLElement,
|
||||||
|
cb: (entry: ResizeObserverEntry) => void
|
||||||
|
): IDisposable {
|
||||||
|
const observer = new ResizeObserver((entires) => {
|
||||||
|
const element = entires[0];
|
||||||
|
cb(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(element);
|
||||||
|
|
||||||
|
return {
|
||||||
|
dispose: () => {
|
||||||
|
observer.unobserve(element);
|
||||||
|
observer.disconnect();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function isHTMLElement(o: any): o is HTMLElement {
|
export function isHTMLElement(o: any): o is HTMLElement {
|
||||||
if (typeof HTMLElement === 'object') {
|
if (typeof HTMLElement === 'object') {
|
||||||
|
@ -16,6 +16,7 @@ import { DockviewApi } from '../../api/component.api';
|
|||||||
import { ReactWatermarkPart } from './reactWatermarkPart';
|
import { ReactWatermarkPart } from './reactWatermarkPart';
|
||||||
import { PanelCollection } from '../types';
|
import { PanelCollection } from '../types';
|
||||||
import { IDisposable } from '../../lifecycle';
|
import { IDisposable } from '../../lifecycle';
|
||||||
|
import { watchElementResize } from '../../dom';
|
||||||
|
|
||||||
export interface ActionsbarReference<P> extends IDisposable {
|
export interface ActionsbarReference<P> extends IDisposable {
|
||||||
update(params: Partial<P>): void;
|
update(params: Partial<P>): void;
|
||||||
@ -56,6 +57,7 @@ export interface IDockviewReactProps {
|
|||||||
onTabContextMenu?: (event: TabContextMenuEvent) => void;
|
onTabContextMenu?: (event: TabContextMenuEvent) => void;
|
||||||
hideBorders?: boolean;
|
hideBorders?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
disableAutoResizing?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DockviewReact: React.FunctionComponent<IDockviewReactProps> = (
|
export const DockviewReact: React.FunctionComponent<IDockviewReactProps> = (
|
||||||
@ -63,9 +65,25 @@ export const DockviewReact: React.FunctionComponent<IDockviewReactProps> = (
|
|||||||
) => {
|
) => {
|
||||||
const domRef = React.useRef<HTMLDivElement>(null);
|
const domRef = React.useRef<HTMLDivElement>(null);
|
||||||
const dockviewRef = React.useRef<DockviewComponent>();
|
const dockviewRef = React.useRef<DockviewComponent>();
|
||||||
|
|
||||||
const [portals, addPortal] = usePortalsLifecycle();
|
const [portals, addPortal] = usePortalsLifecycle();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (props.disableAutoResizing) {
|
||||||
|
return () => {
|
||||||
|
//
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const watcher = watchElementResize(domRef.current, (entry) => {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
dockviewRef.current?.layout(width, height);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
watcher.dispose();
|
||||||
|
};
|
||||||
|
}, [props.disableAutoResizing]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const factory: GroupPanelFrameworkComponentFactory = {
|
const factory: GroupPanelFrameworkComponentFactory = {
|
||||||
content: {
|
content: {
|
||||||
@ -121,7 +139,7 @@ export const DockviewReact: React.FunctionComponent<IDockviewReactProps> = (
|
|||||||
domRef.current?.appendChild(dockview.element);
|
domRef.current?.appendChild(dockview.element);
|
||||||
dockview.deserializer = new ReactPanelDeserialzier(dockview);
|
dockview.deserializer = new ReactPanelDeserialzier(dockview);
|
||||||
|
|
||||||
dockview.resizeToFit();
|
// dockview.resizeToFit();
|
||||||
|
|
||||||
if (props.onReady) {
|
if (props.onReady) {
|
||||||
props.onReady({ api: new DockviewApi(dockview) });
|
props.onReady({ api: new DockviewApi(dockview) });
|
||||||
|
@ -9,6 +9,7 @@ import { ReactGridPanelView } from './view';
|
|||||||
import { usePortalsLifecycle } from '../react';
|
import { usePortalsLifecycle } from '../react';
|
||||||
import { GridviewApi } from '../../api/component.api';
|
import { GridviewApi } from '../../api/component.api';
|
||||||
import { PanelCollection } from '../types';
|
import { PanelCollection } from '../types';
|
||||||
|
import { watchElementResize } from '../../dom';
|
||||||
|
|
||||||
export interface GridviewReadyEvent {
|
export interface GridviewReadyEvent {
|
||||||
api: GridviewApi;
|
api: GridviewApi;
|
||||||
@ -27,6 +28,7 @@ export interface IGridviewReactProps {
|
|||||||
hideBorders?: boolean;
|
hideBorders?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
proportionalLayout?: boolean;
|
proportionalLayout?: boolean;
|
||||||
|
disableAutoResizing?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const GridviewReact: React.FunctionComponent<IGridviewReactProps> = (
|
export const GridviewReact: React.FunctionComponent<IGridviewReactProps> = (
|
||||||
@ -37,7 +39,26 @@ export const GridviewReact: React.FunctionComponent<IGridviewReactProps> = (
|
|||||||
const [portals, addPortal] = usePortalsLifecycle();
|
const [portals, addPortal] = usePortalsLifecycle();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const gridview = new GridviewComponent(domRef.current!, {
|
if (props.disableAutoResizing) {
|
||||||
|
return () => {
|
||||||
|
//
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const watcher = watchElementResize(domRef.current, (entry) => {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
gridviewRef.current?.layout(width, height);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
watcher.dispose();
|
||||||
|
};
|
||||||
|
}, [props.disableAutoResizing]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
const element = document.createElement('div');
|
||||||
|
|
||||||
|
const gridview = new GridviewComponent(element, {
|
||||||
proportionalLayout: !!props.proportionalLayout,
|
proportionalLayout: !!props.proportionalLayout,
|
||||||
orientation: props.orientation,
|
orientation: props.orientation,
|
||||||
frameworkComponents: props.components,
|
frameworkComponents: props.components,
|
||||||
@ -53,6 +74,8 @@ export const GridviewReact: React.FunctionComponent<IGridviewReactProps> = (
|
|||||||
: undefined,
|
: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
domRef.current?.appendChild(gridview.element);
|
||||||
|
|
||||||
if (props.onReady) {
|
if (props.onReady) {
|
||||||
props.onReady({ api: new GridviewApi(gridview) });
|
props.onReady({ api: new GridviewApi(gridview) });
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import { usePortalsLifecycle } from '../react';
|
|||||||
import { PaneviewApi } from '../../api/component.api';
|
import { PaneviewApi } from '../../api/component.api';
|
||||||
import { PanelBody, PanelHeader } from './view';
|
import { PanelBody, PanelHeader } from './view';
|
||||||
import { PanelCollection } from '../types';
|
import { PanelCollection } from '../types';
|
||||||
|
import { watchElementResize } from '../../dom';
|
||||||
|
|
||||||
export interface PaneviewReadyEvent {
|
export interface PaneviewReadyEvent {
|
||||||
api: PaneviewApi;
|
api: PaneviewApi;
|
||||||
@ -25,6 +26,7 @@ export interface IPaneviewReactProps {
|
|||||||
components?: PanelCollection<IPaneviewPanelProps>;
|
components?: PanelCollection<IPaneviewPanelProps>;
|
||||||
headerComponents?: PanelCollection<IPaneviewPanelProps>;
|
headerComponents?: PanelCollection<IPaneviewPanelProps>;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
disableAutoResizing?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PaneviewReact: React.FunctionComponent<IPaneviewReactProps> = (
|
export const PaneviewReact: React.FunctionComponent<IPaneviewReactProps> = (
|
||||||
@ -34,6 +36,23 @@ export const PaneviewReact: React.FunctionComponent<IPaneviewReactProps> = (
|
|||||||
const paneviewRef = React.useRef<IPaneviewComponent>();
|
const paneviewRef = React.useRef<IPaneviewComponent>();
|
||||||
const [portals, addPortal] = usePortalsLifecycle();
|
const [portals, addPortal] = usePortalsLifecycle();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (props.disableAutoResizing) {
|
||||||
|
return () => {
|
||||||
|
//
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const watcher = watchElementResize(domRef.current, (entry) => {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
paneviewRef.current?.layout(width, height);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
watcher.dispose();
|
||||||
|
};
|
||||||
|
}, [props.disableAutoResizing]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const paneview = new PaneviewComponent(domRef.current!, {
|
const paneview = new PaneviewComponent(domRef.current!, {
|
||||||
frameworkComponents: props.components,
|
frameworkComponents: props.components,
|
||||||
|
@ -9,6 +9,7 @@ import { Orientation } from '../../splitview/core/splitview';
|
|||||||
import { usePortalsLifecycle } from '../react';
|
import { usePortalsLifecycle } from '../react';
|
||||||
import { PanelCollection } from '../types';
|
import { PanelCollection } from '../types';
|
||||||
import { ReactPanelView } from './view';
|
import { ReactPanelView } from './view';
|
||||||
|
import { watchElementResize } from '../../dom';
|
||||||
|
|
||||||
export interface SplitviewReadyEvent {
|
export interface SplitviewReadyEvent {
|
||||||
api: SplitviewApi;
|
api: SplitviewApi;
|
||||||
@ -27,6 +28,7 @@ export interface ISplitviewReactProps {
|
|||||||
proportionalLayout?: boolean;
|
proportionalLayout?: boolean;
|
||||||
hideBorders?: boolean;
|
hideBorders?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
disableAutoResizing?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SplitviewReact: React.FunctionComponent<ISplitviewReactProps> = (
|
export const SplitviewReact: React.FunctionComponent<ISplitviewReactProps> = (
|
||||||
@ -36,6 +38,23 @@ export const SplitviewReact: React.FunctionComponent<ISplitviewReactProps> = (
|
|||||||
const splitviewRef = React.useRef<ISplitviewComponent>();
|
const splitviewRef = React.useRef<ISplitviewComponent>();
|
||||||
const [portals, addPortal] = usePortalsLifecycle();
|
const [portals, addPortal] = usePortalsLifecycle();
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (props.disableAutoResizing) {
|
||||||
|
return () => {
|
||||||
|
//
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const watcher = watchElementResize(domRef.current, (entry) => {
|
||||||
|
const { width, height } = entry.contentRect;
|
||||||
|
splitviewRef.current?.layout(width, height);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
watcher.dispose();
|
||||||
|
};
|
||||||
|
}, [props.disableAutoResizing]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const splitview = new SplitviewComponent(domRef.current!, {
|
const splitview = new SplitviewComponent(domRef.current!, {
|
||||||
orientation: props.orientation,
|
orientation: props.orientation,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user