mirror of
https://github.com/mathuo/dockview
synced 2025-01-22 09:25:57 +00:00
parent
5ca1cc5e62
commit
ffddc95602
@ -20,8 +20,10 @@
|
||||
"/packages/docs/sandboxes/keyboard-dockview",
|
||||
"/packages/docs/sandboxes/layout-dockview",
|
||||
"/packages/docs/sandboxes/lockedgroup-dockview",
|
||||
"/packages/docs/sandboxes/maximizegroup-dockview",
|
||||
"/packages/docs/sandboxes/nativeapp-dockview",
|
||||
"/packages/docs/sandboxes/nested-dockview",
|
||||
"/packages/docs/sandboxes/popoutgroup-dockview",
|
||||
"/packages/docs/sandboxes/rendering-dockview",
|
||||
"/packages/docs/sandboxes/rendermode-dockview",
|
||||
"/packages/docs/sandboxes/resize-dockview",
|
||||
|
25
README.md
25
README.md
@ -1,13 +1,14 @@
|
||||
<div align="center">
|
||||
<h1>dockview</h1>
|
||||
|
||||
<p>Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support written in TypeScript</p>
|
||||
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews with ReactJS support written in TypeScript</p>
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
|
||||
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
@ -21,16 +22,20 @@ Please see the website: https://dockview.dev
|
||||
|
||||
## Features
|
||||
|
||||
- Simple splitviews, nested splitviews (i.e. gridviews) supporting full layout managment with
|
||||
dockable and tabular views
|
||||
- Extensive API support at the component level and view level
|
||||
- Themable and customizable
|
||||
- Serialization / deserialization support
|
||||
- Tabular docking and Drag and Drop support
|
||||
- Floating groups, customized header bars and tab
|
||||
- Documentation and examples
|
||||
- Serialization / deserialization with full layout management
|
||||
- Support for split-views, grid-views and 'dockable' views
|
||||
- Themeable and customizable
|
||||
- Tab and Group docking / Drag n' Drop
|
||||
- Popout Windows
|
||||
- Floating Groups
|
||||
- Extensive API
|
||||
- Supports Shadow DOMs
|
||||
- High test coverage
|
||||
- Documentation website with live examples
|
||||
- Transparent builds and Code Analysis
|
||||
- Security at mind - verifed publishing and builds through GitHub Actions
|
||||
|
||||
Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/
|
||||
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
|
||||
|
||||
## Quick start
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
---
|
||||
|
||||
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
|
||||
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
@ -15,24 +16,30 @@
|
||||
|
||||
##
|
||||
|
||||
![](packages/docs/static/img/splashscreen.gif)
|
||||
|
||||
Please see the website: https://dockview.dev
|
||||
|
||||
## Features
|
||||
|
||||
- Simple splitviews, nested splitviews (i.e. gridviews) supporting full layout managment with
|
||||
dockable and tabular views
|
||||
- Extensive API support at the component level and view level
|
||||
- Themable and customizable
|
||||
- Serialization / deserialization support
|
||||
- Tabular docking and Drag and Drop support
|
||||
- Floating groups, customized header bars and tab
|
||||
- Documentation and examples
|
||||
- Serialization / deserialization with full layout management
|
||||
- Support for split-views, grid-views and 'dockable' views
|
||||
- Themeable and customizable
|
||||
- Tab and Group docking / Drag n' Drop
|
||||
- Popout Windows
|
||||
- Floating Groups
|
||||
- Extensive API
|
||||
- Supports Shadow DOMs
|
||||
- High test coverage
|
||||
- Documentation website with live examples
|
||||
- Transparent builds and Code Analysis
|
||||
- Security at mind - verifed publishing and builds through GitHub Actions
|
||||
|
||||
Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview-core@latest/
|
||||
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
|
||||
|
||||
## Quick start
|
||||
|
||||
You can install dockview-core from [npm](https://www.npmjs.com/package/dockview-core).
|
||||
Dockview has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. You can install dockview from [npm](https://www.npmjs.com/package/dockview-core).
|
||||
|
||||
```
|
||||
npm install --save dockview-core
|
||||
|
@ -240,7 +240,7 @@ export function getDomNodePagePosition(domNode: Element): {
|
||||
export function isInDocument(element: Element): boolean {
|
||||
let currentElement: Element | ParentNode = element;
|
||||
|
||||
while (currentElement && currentElement.parentNode) {
|
||||
while (currentElement?.parentNode) {
|
||||
if (currentElement.parentNode === document) {
|
||||
return true;
|
||||
} else if (currentElement.parentNode instanceof DocumentFragment) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
---
|
||||
|
||||
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
|
||||
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||
@ -19,16 +20,20 @@ Please see the website: https://dockview.dev
|
||||
|
||||
## Features
|
||||
|
||||
- Simple splitviews, nested splitviews (i.e. gridviews) supporting full layout managment with
|
||||
dockable and tabular views
|
||||
- Extensive API support at the component level and view level
|
||||
- Themable and customizable
|
||||
- Serialization / deserialization support
|
||||
- Tabular docking and Drag and Drop support
|
||||
- Floating groups, customized header bars and tab
|
||||
- Documentation and examples
|
||||
- Serialization / deserialization with full layout management
|
||||
- Support for split-views, grid-views and 'dockable' views
|
||||
- Themeable and customizable
|
||||
- Tab and Group docking / Drag n' Drop
|
||||
- Popout Windows
|
||||
- Floating Groups
|
||||
- Extensive API
|
||||
- Supports Shadow DOMs
|
||||
- High test coverage
|
||||
- Documentation website with live examples
|
||||
- Transparent builds and Code Analysis
|
||||
- Security at mind - verifed publishing and builds through GitHub Actions
|
||||
|
||||
Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/
|
||||
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
|
||||
|
||||
## Quick start
|
||||
|
||||
|
@ -16,6 +16,8 @@ Please reference to docs @ [dockview.dev](https://dockview.dev).
|
||||
|
||||
- Advanced panel rendering configurations [#397](https://github.com/mathuo/dockview/issues/397)
|
||||
|
||||
- Support for rendering within Shadow DOM elements [#425](https://github.com/mathuo/dockview/issues/425)
|
||||
|
||||
## 🛠 Miscs
|
||||
|
||||
- Remove hover effect on inactive drag handles [#392](https://github.com/mathuo/dockview/pull/392)
|
@ -29,6 +29,7 @@ import DockviewFloating from '@site/sandboxes/floatinggroup-dockview/src/app';
|
||||
import DockviewLockedGroup from '@site/sandboxes/lockedgroup-dockview/src/app';
|
||||
import DockviewKeyboard from '@site/sandboxes/keyboard-dockview/src/app';
|
||||
import DockviewPopoutGroup from '@site/sandboxes/popoutgroup-dockview/src/app';
|
||||
import DockviewMaximizeGroup from '@site/sandboxes/maximizegroup-dockview/src/app';
|
||||
import DockviewRenderMode from '@site/sandboxes/rendermode-dockview/src/app';
|
||||
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
@ -403,7 +404,7 @@ To programatically move the popout group back into the main grid you can use the
|
||||
|
||||
```tsx
|
||||
// option 1: add absolutely to the right-side of the grid
|
||||
props.group.api.moveTo({position: 'right'});
|
||||
props.group.api.moveTo({ position: 'right' });
|
||||
|
||||
// option 2: create a new group and move the contents of the popout group to it
|
||||
const group = props.containerApi.addGroup();
|
||||
@ -418,12 +419,44 @@ props.group.api.moveTo({ group });
|
||||
|
||||
## Maximized Groups
|
||||
|
||||
To maximize a group you can all
|
||||
To maximize a group from the component `api`:
|
||||
|
||||
```tsx
|
||||
// maximize a specified group
|
||||
api.maxmimizeGroup(group);
|
||||
|
||||
// check whether a specific group is maximized
|
||||
const result: boolean = api.isMaximizedGroup(group);
|
||||
|
||||
// if there is any maximized group exit the maximized state
|
||||
exitMaximizedGroup();
|
||||
|
||||
// is there a maximized group
|
||||
const result: boolean = hasMaximizedGroup();
|
||||
```
|
||||
|
||||
The following methods are available on both the panel and group `api` objects:
|
||||
|
||||
> `api.<method>` is equivalent to `api.group.api.<method>` for all of these methods. The methods exist on the panel `api` object for convenience.
|
||||
|
||||
```ts
|
||||
// maximize the group
|
||||
api.maximize();
|
||||
|
||||
// is this group maximized (if another group is maximized this method will still return false)
|
||||
const result: boolean = api.isMaxmized();
|
||||
|
||||
// exit only if this group is maximzied (if another group is maxmized this has no affect)
|
||||
api.exitMaximized();
|
||||
```
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="maximizegroup-dockview"
|
||||
react={DockviewMaximizeGroup}
|
||||
/>
|
||||
|
||||
|
||||
## Panels
|
||||
|
||||
### Add Panel
|
||||
@ -667,9 +700,9 @@ Toggling the checkbox you can see that when you only render those panels which a
|
||||
You can provide custom renderers for your tab headers for maximum customization.
|
||||
A default implementation of `DockviewDefaultTab` is provided should you only wish to attach minor
|
||||
changes and events that do not alter the default behaviour, for example to add a custom context menu event
|
||||
handler.
|
||||
handler or to hide the close button.
|
||||
|
||||
The `DockviewDefaulTab` component accepts a `hideClose` prop if you wish only to hide the close button.
|
||||
The `DockviewDefaultTab` component accepts a `hideClose` prop if you wish only to hide the close button.
|
||||
|
||||
```tsx title="Attaching a custom context menu event handlers to a custom header"
|
||||
import { IDockviewPanelHeaderProps, DockviewDefaultTab } from 'dockview';
|
||||
@ -679,7 +712,7 @@ const MyCustomheader = (props: IDockviewPanelHeaderProps) => {
|
||||
event.preventDefault();
|
||||
alert('context menu');
|
||||
};
|
||||
return <DockviewDefaultTab onContextMenu={onContextMenu} {...props} />;
|
||||
return <DockviewDefaultTab onContextMenu={onContextMenu} hideClose={true} {...props} />;
|
||||
};
|
||||
```
|
||||
|
||||
@ -900,16 +933,17 @@ iFrames required special attention because of a particular behaviour in how iFra
|
||||
|
||||
You can find many examples of discussions on this. Two reputable forums for example are linked [here](https://bugzilla.mozilla.org/show_bug.cgi?id=254144) and [here](https://github.com/whatwg/html/issues/5484).
|
||||
|
||||
The problem with iFrames and `dockview` is that when you hide or move a panel that panels DOM element may be moved within the DOM or removed from the DOM completely.
|
||||
If your panel contains an iFrame then that iFrame will reload after being re-positioned within the DOM tree and all state in that iFrame will most likely be lost.
|
||||
To ensure iFrames work as expected you should render them in panels with `renderer: 'always'` to ensure they are never removed from the DOM, alternatively set the defaultRenderer to `always`.
|
||||
|
||||
`dockview` does not provide a built-in solution to this because it's too specific of a problem to include in the library.
|
||||
However the below example does show an implementation of a higher-order component `HoistedDockviewPanel`that you could use to work around this problems and make iFrames behave in `dockview`.
|
||||
> See the **Panel Rendering** section for more information of render modes.
|
||||
|
||||
What the higher-order component is doing is to hoist the panels contents into a DOM element that is always present and then `position: absolute` that element to match the dimensions of it's linked panel.
|
||||
The visibility of these hoisted elements is then controlled through some exposed api methods to hide elements that shouldn't be currently shown.
|
||||
|
||||
You should open this example in CodeSandbox using the provided link to understand the code and make use of this implemention if required.
|
||||
```tsx title="Example of a panel using an alternative renderer"
|
||||
api.addPanel({
|
||||
id: 'my_panel_id',
|
||||
component: 'my_component',
|
||||
renderer: 'always',
|
||||
});
|
||||
```
|
||||
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="iframe-dockview"
|
||||
|
@ -7,6 +7,8 @@ description: Contributing
|
||||
|
||||
# Project description
|
||||
|
||||
Pre-requisites: Node >=18, Yarn
|
||||
|
||||
Dockview is a layout manager library designed to provide a complete layouting solution.
|
||||
It is written in plain TypeScript and can be used without any framework although
|
||||
an extensive React wrapper has always and will always be provided for those using the React framework.
|
||||
|
@ -3,10 +3,12 @@ sidebar_position: 0
|
||||
description: A zero dependency layout manager supporting ReactJS and Vanilla TypeScript
|
||||
---
|
||||
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
|
||||
import { SimpleSplitview } from '@site/src/components/simpleSplitview';
|
||||
import { SimpleGridview } from '@site/src/components/simpleGridview';
|
||||
import { SimplePaneview } from '@site/src/components/simplePaneview';
|
||||
import SimpleDockview from '@site/sandboxes/simple-dockview/src/app';
|
||||
import DockviewDemo from '@site/sandboxes/demo-dockview/src/app';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Introduction
|
||||
@ -34,16 +36,11 @@ There are 4 components you may want to use:
|
||||
<h2>Dockview</h2>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleDockview />
|
||||
</div>
|
||||
<MultiFrameworkContainer
|
||||
height={500}
|
||||
sandboxId="demo-dockview"
|
||||
react={DockviewDemo}
|
||||
/>
|
||||
|
||||
<Link to="./components/splitview">
|
||||
<h2>Splitview</h2>
|
||||
|
@ -31,74 +31,13 @@ const headerComponents = {
|
||||
},
|
||||
};
|
||||
|
||||
const Popover = (props: {
|
||||
children: React.ReactNode;
|
||||
position?: { x: number; y: number };
|
||||
close: () => void;
|
||||
}) => {
|
||||
const uuid = React.useMemo(() => v4(), []);
|
||||
|
||||
React.useEffect(() => {
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
props.close();
|
||||
}
|
||||
};
|
||||
const listener2 = (event: MouseEvent) => {
|
||||
let target = event.target;
|
||||
|
||||
while (target) {
|
||||
if (target instanceof HTMLElement) {
|
||||
if (target.classList.contains(uuid)) {
|
||||
return;
|
||||
} else {
|
||||
target = target.parentElement;
|
||||
}
|
||||
} else {
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
|
||||
props.close();
|
||||
};
|
||||
window.addEventListener('keypress', listener);
|
||||
window.addEventListener('mousedown', listener2);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keypress', listener);
|
||||
window.removeEventListener('mousedown', listener2);
|
||||
};
|
||||
}, [props.close, uuid]);
|
||||
|
||||
if (!props.position) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
<div
|
||||
className={uuid}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: props.position.y,
|
||||
left: props.position.x,
|
||||
background: 'white',
|
||||
border: '1px solid black',
|
||||
zIndex: 99,
|
||||
padding: '10px',
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</div>,
|
||||
document.body
|
||||
);
|
||||
};
|
||||
|
||||
const Icon = (props: {
|
||||
icon: string;
|
||||
title?: string;
|
||||
onClick?: (event: React.MouseEvent) => void;
|
||||
}) => {
|
||||
return (
|
||||
<div className="action" onClick={props.onClick}>
|
||||
<div title={props.title} className="action" onClick={props.onClick}>
|
||||
<span
|
||||
style={{ fontSize: 'inherit' }}
|
||||
className="material-symbols-outlined"
|
||||
@ -124,54 +63,44 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
||||
return groupControlsComponents[props.activePanel.id];
|
||||
}, [props.isGroupActive, props.activePanel]);
|
||||
|
||||
// const [icon, setIcon] = React.useState<string>(
|
||||
// props.containerApi.hasMaximizedGroup()
|
||||
// ? 'collapse_content'
|
||||
// : 'expand_content'
|
||||
// );
|
||||
const [isMaximized, setIsMaximized] = React.useState<boolean>(
|
||||
props.containerApi.hasMaximizedGroup()
|
||||
);
|
||||
|
||||
// const [popoutIcon, setPopoutIcon] = React.useState<string>(
|
||||
// props.api.location === 'popout' ? 'close_fullscreen' : 'open_in_new'
|
||||
// );
|
||||
const [isPopout, setIsPopout] = React.useState<boolean>(
|
||||
props.api.location === 'popout'
|
||||
);
|
||||
|
||||
// React.useEffect(() => {
|
||||
// const disposable = props.containerApi.onDidMaxmizedGroupChange(() => {
|
||||
// setIcon(
|
||||
// props.containerApi.hasMaximizedGroup()
|
||||
// ? 'collapse_content'
|
||||
// : 'expand_content'
|
||||
// );
|
||||
// });
|
||||
React.useEffect(() => {
|
||||
const disposable = props.containerApi.onDidMaxmizedGroupChange(() => {
|
||||
setIsMaximized(props.containerApi.hasMaximizedGroup());
|
||||
});
|
||||
|
||||
// const disposable2 = props.api.onDidLocationChange(() => {
|
||||
// setPopoutIcon(
|
||||
// props.api.location === 'popout'
|
||||
// ? 'close_fullscreen'
|
||||
// : 'open_in_new'
|
||||
// );
|
||||
// });
|
||||
const disposable2 = props.api.onDidLocationChange(() => {
|
||||
setIsPopout(props.api.location === 'popout');
|
||||
});
|
||||
|
||||
// return () => {
|
||||
// disposable.dispose();
|
||||
// disposable2.dispose();
|
||||
// };
|
||||
// }, [props.containerApi]);
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
disposable2.dispose();
|
||||
};
|
||||
}, [props.containerApi]);
|
||||
|
||||
// const onClick = () => {
|
||||
// if (props.containerApi.hasMaximizedGroup()) {
|
||||
// props.containerApi.exitMaxmizedGroup();
|
||||
// } else {
|
||||
// props.activePanel?.api.maximize();
|
||||
// }
|
||||
// };
|
||||
const onClick = () => {
|
||||
if (props.containerApi.hasMaximizedGroup()) {
|
||||
props.containerApi.exitMaxmizedGroup();
|
||||
} else {
|
||||
props.activePanel?.api.maximize();
|
||||
}
|
||||
};
|
||||
|
||||
// const onClick2 = () => {
|
||||
// if (props.api.location !== 'popout') {
|
||||
// props.containerApi.addPopoutGroup(props.group);
|
||||
// } else {
|
||||
// props.api.moveTo({ position: 'right' });
|
||||
// }
|
||||
// };
|
||||
const onClick2 = () => {
|
||||
if (props.api.location !== 'popout') {
|
||||
props.containerApi.addPopoutGroup(props.group);
|
||||
} else {
|
||||
props.api.moveTo({ position: 'right' });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
@ -186,8 +115,18 @@ const RightControls = (props: IDockviewHeaderActionsProps) => {
|
||||
>
|
||||
{props.isGroupActive && <Icon icon="star" />}
|
||||
{Component && <Component />}
|
||||
{/* <Icon icon={popoutIcon} onClick={onClick2} />
|
||||
<Icon icon={icon} onClick={onClick} /> */}
|
||||
<Icon
|
||||
title={isPopout ? 'Close Window' : 'Open In New Window'}
|
||||
icon={isPopout ? 'close_fullscreen' : 'open_in_new'}
|
||||
onClick={onClick2}
|
||||
/>
|
||||
{!isPopout && (
|
||||
<Icon
|
||||
title={isMaximized ? 'Minimize View' : 'Maximize View'}
|
||||
icon={isMaximized ? 'collapse_content' : 'expand_content'}
|
||||
onClick={onClick}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -241,45 +180,62 @@ const PrefixHeaderControls = (props: IDockviewHeaderActionsProps) => {
|
||||
|
||||
const DockviewDemo = (props: { theme?: string }) => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
const panel1 = event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
title: 'Panel 2',
|
||||
position: { referencePanel: 'panel_1', direction: 'right' },
|
||||
position: { referencePanel: panel1 },
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
title: 'Panel 3',
|
||||
position: { referencePanel: 'panel_2', direction: 'below' },
|
||||
position: { referencePanel: panel1 },
|
||||
});
|
||||
event.api.addPanel({
|
||||
|
||||
const panel4 = event.api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
title: 'Panel 4',
|
||||
position: { referencePanel: 'panel_3', direction: 'right' },
|
||||
position: { referencePanel: panel1, direction: 'right' },
|
||||
});
|
||||
event.api.addPanel({
|
||||
|
||||
const panel5 = event.api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
title: 'Panel 5',
|
||||
position: { referencePanel: 'panel_3', direction: 'below' },
|
||||
position: { referencePanel: panel4 },
|
||||
});
|
||||
event.api.addPanel({
|
||||
|
||||
const panel6 = event.api.addPanel({
|
||||
id: 'panel_6',
|
||||
component: 'default',
|
||||
title: 'Panel 6',
|
||||
position: { referencePanel: 'panel_3', direction: 'right' },
|
||||
position: { referencePanel: panel5, direction: 'below' },
|
||||
});
|
||||
|
||||
event.api.getPanel('panel_1')!.api.setActive();
|
||||
const panel7 = event.api.addPanel({
|
||||
id: 'panel_7',
|
||||
component: 'default',
|
||||
title: 'Panel 7',
|
||||
position: { referencePanel: panel6, direction: 'left' },
|
||||
});
|
||||
|
||||
console.log(event.api.toJSON());
|
||||
event.api.addPanel({
|
||||
id: 'panel8',
|
||||
component: 'default',
|
||||
title: 'Panel 8',
|
||||
position: { referencePanel: panel7, direction: 'below' },
|
||||
});
|
||||
|
||||
panel1.api.setActive();
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -1,25 +1,11 @@
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import { DockviewReact, DockviewReadyEvent } from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { HoistedDockviewPanel } from './hoistedDockviewPanel';
|
||||
|
||||
const components = {
|
||||
iframeComponent: (props: IDockviewPanelProps<{ color: string }>) => {
|
||||
return (
|
||||
<div style={{ height: '100%', overflow: 'auto' }}>
|
||||
<div style={{ height: '1000px', color: 'white' }}>
|
||||
{props.api.title}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
iframeComponent: () => {
|
||||
return (
|
||||
<iframe
|
||||
style={{
|
||||
// pointerEvents: 'none',
|
||||
// border: 'none',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
}}
|
||||
|
@ -1,92 +0,0 @@
|
||||
import { IDockviewPanelProps } from 'dockview';
|
||||
import * as React from 'react';
|
||||
import * as ReactDOM from 'react-dom';
|
||||
|
||||
// get absolute position of element allowing for scroll position
|
||||
function getDomNodePagePosition(domNode: HTMLElement): {
|
||||
left: number;
|
||||
top: number;
|
||||
width: number;
|
||||
height: number;
|
||||
} {
|
||||
const { left, top, width, height } = domNode.getBoundingClientRect();
|
||||
return {
|
||||
left: left + window.scrollX,
|
||||
top: top + window.scrollY,
|
||||
width: width,
|
||||
height: height,
|
||||
};
|
||||
}
|
||||
|
||||
function toggleVisibility(element: HTMLElement, isVisible: boolean) {
|
||||
element.style.visibility = isVisible ? 'visible' : 'hidden';
|
||||
}
|
||||
|
||||
export const HoistedDockviewPanel = <T extends object>(
|
||||
DockviewPanelComponent: React.FC<IDockviewPanelProps<T>>
|
||||
) => {
|
||||
return (props: IDockviewPanelProps<T>) => {
|
||||
const ref = React.useRef<HTMLDivElement>(null);
|
||||
const innerRef = React.useRef<HTMLDivElement>(null);
|
||||
|
||||
const positionHoistedPanel = () => {
|
||||
if (!ref.current || !innerRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { left, top, height, width } = getDomNodePagePosition(
|
||||
ref.current.parentElement! // use the parent element to determine our size
|
||||
);
|
||||
|
||||
innerRef.current.style.left = `${left}px`;
|
||||
innerRef.current.style.top = `${top}px`;
|
||||
innerRef.current.style.height = `${height}px`;
|
||||
innerRef.current.style.width = `${width}px`;
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!innerRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
const disposable1 = props.api.onDidVisibilityChange((event) => {
|
||||
if (!innerRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
toggleVisibility(innerRef.current, event.isVisible); // subsequent checks of visibility
|
||||
});
|
||||
|
||||
const disposable2 = props.api.onDidDimensionsChange(() => {
|
||||
positionHoistedPanel();
|
||||
});
|
||||
|
||||
positionHoistedPanel();
|
||||
|
||||
return () => {
|
||||
disposable1.dispose(); // cleanup
|
||||
disposable2.dispose();
|
||||
};
|
||||
}, [props.api]);
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
{ReactDOM.createPortal(
|
||||
<div
|
||||
/** you may want to mark these elements with some kind of attribute id */
|
||||
ref={innerRef}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
overflow: 'hidden',
|
||||
zIndex: 999,
|
||||
pointerEvents: 'none', // prevent this wrapper contain stealing events
|
||||
}}
|
||||
>
|
||||
<DockviewPanelComponent {...props} />
|
||||
</div>,
|
||||
document.body // <-- you may choose to mount these 'global' elements to anywhere you see suitable
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
32
packages/docs/sandboxes/maximizegroup-dockview/package.json
Normal file
32
packages/docs/sandboxes/maximizegroup-dockview/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "maximizegroup-dockview",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.tsx",
|
||||
"dependencies": {
|
||||
"dockview": "*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"typescript": "^4.9.5",
|
||||
"react-scripts": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
252
packages/docs/sandboxes/maximizegroup-dockview/src/app.tsx
Normal file
252
packages/docs/sandboxes/maximizegroup-dockview/src/app.tsx
Normal file
@ -0,0 +1,252 @@
|
||||
import {
|
||||
DockviewApi,
|
||||
DockviewGroupPanel,
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewHeaderActionsProps,
|
||||
IDockviewPanelProps,
|
||||
SerializedDockview,
|
||||
} from 'dockview';
|
||||
import * as React from 'react';
|
||||
import { Icon } from './utils';
|
||||
|
||||
const components = {
|
||||
default: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: '100%',
|
||||
padding: '20px',
|
||||
background: 'var(--dv-group-view-background-color)',
|
||||
}}
|
||||
>
|
||||
{props.params.title}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const counter = (() => {
|
||||
let i = 0;
|
||||
|
||||
return {
|
||||
next: () => ++i,
|
||||
};
|
||||
})();
|
||||
|
||||
function loadDefaultLayout(api: DockviewApi) {
|
||||
api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_4',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_5',
|
||||
component: 'default',
|
||||
position: { direction: 'right' },
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_6',
|
||||
component: 'default',
|
||||
});
|
||||
}
|
||||
|
||||
let panelCount = 0;
|
||||
|
||||
function safeParse<T>(value: any): T | null {
|
||||
try {
|
||||
return JSON.parse(value) as T;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const useLocalStorage = <T,>(
|
||||
key: string
|
||||
): [T | null, (setter: T | null) => void] => {
|
||||
const [state, setState] = React.useState<T | null>(
|
||||
safeParse(localStorage.getItem(key))
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const _state = localStorage.getItem('key');
|
||||
try {
|
||||
if (_state !== null) {
|
||||
setState(JSON.parse(_state));
|
||||
}
|
||||
} catch (err) {
|
||||
//
|
||||
}
|
||||
}, [key]);
|
||||
|
||||
return [
|
||||
state,
|
||||
(_state: T | null) => {
|
||||
if (_state === null) {
|
||||
localStorage.removeItem(key);
|
||||
} else {
|
||||
localStorage.setItem(key, JSON.stringify(_state));
|
||||
setState(_state);
|
||||
}
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
export const App = (props: { theme?: string }) => {
|
||||
const [api, setApi] = React.useState<DockviewApi>();
|
||||
const [layout, setLayout] =
|
||||
useLocalStorage<SerializedDockview>('floating.layout');
|
||||
|
||||
const [disableFloatingGroups, setDisableFloatingGroups] =
|
||||
React.useState<boolean>(false);
|
||||
|
||||
const load = (api: DockviewApi) => {
|
||||
api.clear();
|
||||
if (layout) {
|
||||
try {
|
||||
api.fromJSON(layout);
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
api.clear();
|
||||
loadDefaultLayout(api);
|
||||
}
|
||||
} else {
|
||||
loadDefaultLayout(api);
|
||||
}
|
||||
};
|
||||
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
load(event.api);
|
||||
setApi(event.api);
|
||||
};
|
||||
|
||||
const [options, setOptions] = React.useState<
|
||||
'boundedWithinViewport' | undefined
|
||||
>(undefined);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
height: '100%',
|
||||
}}
|
||||
>
|
||||
<div style={{ height: '25px' }}>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (api) {
|
||||
setLayout(api.toJSON());
|
||||
}
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
if (api) {
|
||||
load(api);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Load
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
api!.clear();
|
||||
setLayout(null);
|
||||
}}
|
||||
>
|
||||
Clear
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
flexGrow: 1,
|
||||
}}
|
||||
>
|
||||
<DockviewReact
|
||||
onReady={onReady}
|
||||
components={components}
|
||||
watermarkComponent={Watermark}
|
||||
leftHeaderActionsComponent={LeftComponent}
|
||||
rightHeaderActionsComponent={RightComponent}
|
||||
disableFloatingGroups={disableFloatingGroups}
|
||||
floatingGroupBounds={options}
|
||||
className={`${props.theme || 'dockview-theme-abyss'}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const LeftComponent = (props: IDockviewHeaderActionsProps) => {
|
||||
const onClick = () => {
|
||||
props.containerApi.addPanel({
|
||||
id: (++panelCount).toString(),
|
||||
title: `Tab ${panelCount}`,
|
||||
component: 'default',
|
||||
position: { referenceGroup: props.group },
|
||||
});
|
||||
};
|
||||
return (
|
||||
<div style={{ height: '100%', color: 'white', padding: '0px 4px' }}>
|
||||
<Icon onClick={onClick} icon={'add'} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||
const [maximized, setMaximized] = React.useState<boolean>(
|
||||
props.api.isMaximized()
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.containerApi.onDidMaxmizedGroupChange(() => {
|
||||
setMaximized(props.api.isMaximized());
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, [props.containerApi]);
|
||||
|
||||
const onClick = () => {
|
||||
if (maximized) {
|
||||
props.api.exitMaximized();
|
||||
} else {
|
||||
props.api.maximize();
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div style={{ height: '100%', color: 'white', padding: '0px 4px' }}>
|
||||
<Icon
|
||||
onClick={onClick}
|
||||
icon={maximized ? 'jump_to_element' : 'back_to_tab'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
|
||||
const Watermark = () => {
|
||||
return <div style={{ color: 'white', padding: '8px' }}>watermark</div>;
|
||||
};
|
20
packages/docs/sandboxes/maximizegroup-dockview/src/index.tsx
Normal file
20
packages/docs/sandboxes/maximizegroup-dockview/src/index.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { StrictMode } from 'react';
|
||||
import * as ReactDOMClient from 'react-dom/client';
|
||||
import './styles.css';
|
||||
import 'dockview/dist/styles/dockview.css';
|
||||
|
||||
import App from './app';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
if (rootElement) {
|
||||
const root = ReactDOMClient.createRoot(rootElement);
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<div className="app">
|
||||
<App />
|
||||
</div>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
30
packages/docs/sandboxes/maximizegroup-dockview/src/utils.tsx
Normal file
30
packages/docs/sandboxes/maximizegroup-dockview/src/utils.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export const Icon = (props: {
|
||||
icon: string;
|
||||
title?: string;
|
||||
onClick?: (event: React.MouseEvent) => void;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
title={props.title}
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
width: '30px',
|
||||
height: '100%',
|
||||
|
||||
fontSize: '18px',
|
||||
}}
|
||||
onClick={props.onClick}
|
||||
>
|
||||
<span
|
||||
style={{ fontSize: 'inherit', cursor: 'pointer' }}
|
||||
className="material-symbols-outlined"
|
||||
>
|
||||
{props.icon}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
};
|
18
packages/docs/sandboxes/maximizegroup-dockview/tsconfig.json
Normal file
18
packages/docs/sandboxes/maximizegroup-dockview/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "build/dist",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom"],
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "src",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
.nested-dockview {
|
||||
position: relative;
|
||||
::after {
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
|
@ -108,7 +108,7 @@ const useLocalStorage = <T,>(
|
||||
];
|
||||
};
|
||||
|
||||
export const DockviewPersistance = (props: { theme?: string }) => {
|
||||
export const App = (props: { theme?: string }) => {
|
||||
const [api, setApi] = React.useState<DockviewApi>();
|
||||
const [layout, setLayout] =
|
||||
useLocalStorage<SerializedDockview>('floating.layout');
|
||||
@ -218,9 +218,9 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.group.api.onDidLocationChange(
|
||||
(event) => [setPopout(event.location === 'popout')]
|
||||
);
|
||||
const disposable = props.group.api.onDidLocationChange((event) => [
|
||||
setPopout(event.location === 'popout'),
|
||||
]);
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
@ -232,7 +232,9 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||
const group = props.containerApi.addGroup();
|
||||
props.group.api.moveTo({ group });
|
||||
} else {
|
||||
props.containerApi.addPopoutGroup(props.group);
|
||||
props.containerApi.addPopoutGroup(props.group, {
|
||||
popoutUrl: '/popout/index.html',
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@ -246,7 +248,7 @@ const RightComponent = (props: IDockviewHeaderActionsProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default DockviewPersistance;
|
||||
export default App;
|
||||
|
||||
const Watermark = () => {
|
||||
return <div style={{ color: 'white', padding: '8px' }}>watermark</div>;
|
||||
|
@ -62,11 +62,11 @@ const FeatureList: FeatureItem[] = [
|
||||
</div>
|
||||
<div className="feature-banner">
|
||||
<h3 className="feature-banner-header">
|
||||
Floating Group Support
|
||||
Floating and Popout Groups
|
||||
</h3>
|
||||
<p className="feature-banner-content">
|
||||
Built-in support for floating groups with a supporting
|
||||
api for progmatic control.
|
||||
Built-in support for floating groups and groups in new
|
||||
windows with a supporting api for progmatic control.
|
||||
</p>
|
||||
</div>
|
||||
<div className="feature-banner">
|
||||
|
@ -26,7 +26,7 @@ export const Introduction = () => {
|
||||
<div style={{ padding: '20px' }}>
|
||||
<BrowserHeader />
|
||||
<MultiFrameworkContainer
|
||||
height={500}
|
||||
height={750}
|
||||
sandboxId="demo-dockview"
|
||||
react={DockviewDemo}
|
||||
/>
|
||||
|
@ -54,6 +54,7 @@ export const CodeSandboxButton = (props: {
|
||||
<a
|
||||
href={url}
|
||||
target={'_blank'}
|
||||
rel='noopener'
|
||||
className="codesandbox-button-content"
|
||||
>
|
||||
<span
|
||||
|
BIN
packages/docs/static/img/splashscreen.gif
vendored
BIN
packages/docs/static/img/splashscreen.gif
vendored
Binary file not shown.
Before Width: | Height: | Size: 455 KiB After Width: | Height: | Size: 655 KiB |
@ -1,114 +0,0 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
description: How to get started with Dockview
|
||||
---
|
||||
|
||||
import { SimpleSplitview } from '@site/src/components/simpleSplitview';
|
||||
import { SimpleSplitview2 } from '@site/src/components/simpleSplitview2';
|
||||
|
||||
# Basics
|
||||
|
||||
This section will take you through a number of concepts that can be applied to all dockview components.
|
||||
|
||||
## Panels
|
||||
|
||||
The below examples use `ReactSplitview` but the logic holds for `ReactPaneview`, `ReactGridview` and `ReactDockview` using their respective implementations and interfaces.
|
||||
All components require you to provide an `onReady` prop which you can use to build and control your component.
|
||||
|
||||
### Adding a panel with parameters
|
||||
|
||||
You can pass parameters to a panel through the `params` object
|
||||
|
||||
```tsx
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'myComponent',
|
||||
params: {
|
||||
title: 'My Title',
|
||||
},
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
and you can access those properties through the `props.params` object. The TypeScript interface accepts an optional generic type `T` that corresponds to the params objects type.
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
There are two types of API you will interact with using `dockview`.
|
||||
|
||||
- The `panel API` is accessible via `props.api` in user defined panels and via the `.api` variable found on panel instances. This API contains actions and variable related to the the individual panel.
|
||||
- The `container API` is accessible via `event.api` in the `onReady` events and `props.containerApi` in user defined panels. This API contains actions and variable related to the component as a whole.
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidActiveChange((event) => {
|
||||
console.log(`is panel active: ${event.isActive}`);
|
||||
});
|
||||
return () => {
|
||||
disposable.dispose(); // remember to dispose of any subscriptions
|
||||
};
|
||||
}, [props.api]);
|
||||
const addAnotherPanel = React.useCallback(() => {
|
||||
props.containerApi.addPanel({
|
||||
id: 'another_id',
|
||||
component: 'anotherComponent',
|
||||
});
|
||||
}, [props.containerApi]);
|
||||
return (
|
||||
<div>
|
||||
<span>{`My first panel has the title: ${props.params.title}`}</span>
|
||||
<button onClick={addAnotherPanel}>Add Panel</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Serialization
|
||||
|
||||
All components support `toJSON(): T` which returns a Typed object representation of the components state. This same Typed object can be used to deserialize a view using `fromJSON(object: T): void`.
|
||||
|
||||
## Auto resizing
|
||||
|
||||
`SplitviewReact`, `GridviewReact`, `PaneviewReact` and `DockviewReact` will all automatically resize to fill the size of their parent element.
|
||||
Internally this is achieved using a [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver) which some users may need to polyfill.
|
||||
You can disable this by settings the `disableAutoResizing` prop to be `true`.
|
||||
|
||||
You can manually resize a component using the API method `layout(width: number, height: number): void`.
|
||||
An advanced case may use this in conjunction with `disableAutoResizing=true` to allow a parent component to have ultimate control over the dimensions of the component.
|
||||
|
||||
## Events
|
||||
|
||||
Many API properties can be listened on using the `Event` pattern. For example `api.onDidFocusChange(() => {...})`.
|
||||
You should dispose of any event listeners you create cleaning up any listeners you would have created.
|
||||
|
||||
```tsx
|
||||
React.useEffect(() => {
|
||||
const disposable = api.onDidFocusChange(() => {
|
||||
// write some code
|
||||
});
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
```
|
||||
|
||||
## Proportional layout
|
||||
|
||||
The `proportionalLayout` property indicates the expected behaviour of the component as it's container resizes, should all views resize equally or should just one view expand to fill the new space. `proportionalLayout` can be set as a property on `SplitviewReact` and `GridviewReact` components.
|
||||
Although not configurable on `DockviewReact` and `PaneviewReact` these both behave as if `proportionalLayout=true` was set for them.
|
||||
|
||||
<SimpleSplitview2 proportional={false} />
|
||||
|
||||
<SimpleSplitview2 proportional={true} />
|
||||
|
||||
## Browser support
|
||||
|
||||
dockview is intended to support all major browsers. Some users may require a polyfill for [ResizeObserver](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).
|
@ -1,120 +0,0 @@
|
||||
---
|
||||
description: Gridview Documentation
|
||||
---
|
||||
|
||||
import { SimpleGridview } from '@site/src/components/simpleGridview';
|
||||
import { EventsGridview } from '@site/src/components/gridview/events';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Gridview
|
||||
|
||||
## Introduction
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleGridview />
|
||||
</div>
|
||||
|
||||
## GridviewReact Component
|
||||
|
||||
```tsx
|
||||
import { ReactGridview } from 'dockview';
|
||||
```
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | ------------------------------------ | -------- | ---------------------- | ------------------------------------------------------------------------ |
|
||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||
| components | object | No | | |
|
||||
| orientation | Orientation | Yes | Orientation.HORIZONTAL | |
|
||||
| proportionalLayout | boolean | Yes | true | See <Link to="../basics/#proportional-layout">Proportional layout</Link> |
|
||||
| hideBorders | boolean | Yes | false | |
|
||||
| className | string | Yes | '' | |
|
||||
| disableAutoResizing | boolean | Yes | false | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
|
||||
## Gridview API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumHeight | `number` | |
|
||||
| maximumHeight | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| length | `number` | Number of panels |
|
||||
| panels | `ISplitviewPanel[]` | all panels |
|
||||
| orientation | `Orientation` | |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | Fires on layout change |
|
||||
| onDidLayoutFromJSON | `Event<void>` | Fires of layout change caused by a fromJSON deserialization call |
|
||||
| onDidAddPanel | `Event<IGridviewPanel>` | Fires when a view is added |
|
||||
| onDidRemovePanel | `Event<IGridviewPanel>` | Fires when a view is removed |
|
||||
| onDidActivePanelChange | `Event<IGridviewPanel \| undefined>` | Fires when the active group changes |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddComponentOptions): IGridviewPanel` | |
|
||||
| removePanel | `(panel: IGridviewPanel, sizing?: Sizing): void` | |
|
||||
| movePanel | `(panel: IGridviewPanel, options: {direction: Direction, refernece:string, size?: number}): void` | |
|
||||
| getPanel | `(id: string) \| IGridviewPanel \| undefined` | |
|
||||
| | | |
|
||||
| updateOptions | `(options:SplitviewComponentUpdateOptions): void` | |
|
||||
| focus | `(): void` | Focus the active panel, if exists |
|
||||
| layout | `(width: number, height:number): void` | <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedGridview): void` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedGridview` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Gridview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | ---------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| isVisible | `boolean` | Is panel visible |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| | | |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | |
|
||||
| | | |
|
||||
| setVisible | `(isVisible: boolean): void` | |
|
||||
| setActive | `(): void` | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: SizeEvent): void` | |
|
||||
|
||||
## Events
|
||||
|
||||
`GridviewReact` exposes a number of events that the developer can listen to and below is a simple example with a log panel showing those events that occur.
|
||||
|
||||
<EventsGridview />
|
@ -1,285 +0,0 @@
|
||||
---
|
||||
description: Paneview Documentation
|
||||
---
|
||||
|
||||
import { SimplePaneview } from '@site/src/components/simplePaneview';
|
||||
import { CustomHeaderPaneview } from '@site/src/components/paneview/customHeader';
|
||||
import { DragAndDropPaneview } from '@site/src/components/paneview/dragAndDrop';
|
||||
import { SideBySidePaneview } from '@site/src/components/paneview/sideBySide';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Paneview
|
||||
|
||||
A paneview is a collapsed collection of vertically stacked panels and panel headers.
|
||||
The panel header will always remain visible however the panel will only be visible when the panel is expanded.
|
||||
|
||||
:::info
|
||||
|
||||
Paneview panels can be re-ordered by dragging and dropping the panel headers.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '400px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimplePaneview />
|
||||
</div>
|
||||
|
||||
```tsx title="Simple Paneview example"
|
||||
import {
|
||||
IPaneviewPanelProps,
|
||||
PaneviewReact,
|
||||
PaneviewReadyEvent,
|
||||
} from 'dockview';
|
||||
|
||||
const components = {
|
||||
default: (props: IPaneviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgb(60,60,60)',
|
||||
}}
|
||||
>
|
||||
{props.params.title}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
SimplePaneview = () => {
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
title: 'Panel 2',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
title: 'Panel 3',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
components={components}
|
||||
headerComponents={headerComponents}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-abyss"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## PaneviewReact Component
|
||||
|
||||
You can create a Paneview through the use of the `ReactPaneview` component.
|
||||
|
||||
```tsx
|
||||
import { ReactPaneview } from 'dockview';
|
||||
```
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | ------------------------------------ | -------- | ------- | -------------------------------------------------------- |
|
||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||
| components | object | No | | |
|
||||
| headerComponents | object | Yes | | |
|
||||
| className | string | Yes | '' | |
|
||||
| disableAutoResizing | boolean | Yes | false | <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| disableDnd | boolean | Yes | false | |
|
||||
| onDidDrop | Event | Yes | | |
|
||||
|
||||
## Paneview API
|
||||
|
||||
The Paneview API is exposed both at the `onReady` event and on each panel through `props.containerApi`.
|
||||
Through this API you can control general features of the component and access all added panels.
|
||||
|
||||
```tsx title="Paneview API via Panel component"
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx title="Paneview API via the onReady callback"
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumSize | `number` | The sum of the `minimumSize` property for each panel |
|
||||
| maximumSize | `number` | The sum of the `maximumSize` property for each panel |
|
||||
| length | `number` | Number of panels |
|
||||
| panels | `IPaneviewPanel[]` | All panels |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | Fires on layout change |
|
||||
| onDidLayoutFromJSON | `Event<void>` | Fires of layout change caused by a fromJSON deserialization call |
|
||||
| onDidAddView | `Event<IPaneviewPanel>` | Fires when a view is added |
|
||||
| onDidRemoveView | `Event<IPaneviewPanel>` | Fires when a view is removed |
|
||||
| onDidDrop | `Event<PaneviewDropEvent` | Fires on an external drop event (See <Link to="./paneview/#drag-and-drop">Drag and Drop</Link>) |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddPaneviewComponentOptions): IPaneviewPanel` | |
|
||||
| removePanel | `(panel: IPaneviewPanel): void` | |
|
||||
| movePanel | `(from: number, to: number): void` | |
|
||||
| getPanel | `(id:string): IPaneviewPanel \| undefined` | |
|
||||
| | | |
|
||||
| focus | `(): void` | Focus the active panel, if exists |
|
||||
| layout | `(width: number, height:number): void` | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedPaneview): void` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedPaneview` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Paneview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | ---------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| isVisible | `boolean` | Is panel visible |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| | |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | |
|
||||
| | |
|
||||
| setVisible | `(isVisible: boolean): void` | |
|
||||
| setActive | `(): void` | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: SizeEvent): void` | |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Custom Header
|
||||
|
||||
You can provide a custom component to render an alternative header.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '400px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<CustomHeaderPaneview />
|
||||
</div>
|
||||
|
||||
You can provide a `headerComponent` option when creating a panel to tell the library to use a custom header component.
|
||||
|
||||
```tsx
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
headerComponent: 'myHeaderComponent',
|
||||
params: {
|
||||
valueA: 'A',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
This header must be defined in the collection of components provided to the `headerComponents` props for `ReactPaneivew`
|
||||
|
||||
```tsx
|
||||
import { IPaneviewPanelProps } from 'dockview';
|
||||
|
||||
const MyHeaderComponent = (props: IPaneviewPanelProps<{ title: string }>) => {
|
||||
const [expanded, setExpanded] = React.useState<boolean>(
|
||||
props.api.isExpanded
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidExpansionChange((event) => {
|
||||
setExpanded(event.isExpanded);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onClick = () => {
|
||||
props.api.setExpanded(!expanded);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgb(60,60,60)',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
onClick={onClick}
|
||||
className={expanded ? 'expanded' : 'collapsed'}
|
||||
/>
|
||||
<span>{props.params.title}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const headerComponents = { myHeaderComponent: MyHeaderComponent };
|
||||
```
|
||||
|
||||
### Drag And Drop
|
||||
|
||||
If you provide the `PaneviewReact` component with the prop `onDidDrop` you will be able to interact with custom drop events.
|
||||
|
||||
<DragAndDropPaneview />
|
||||
|
||||
### Interactions
|
||||
|
||||
You can safely create multiple paneview instances within one page. They will not interact with each other by default.
|
||||
|
||||
If you wish to interact with the drop event from one paneview instance in another paneview instance you can implement the `showDndOverlay` and `onDidDrop` props on `PaneviewReact`.
|
||||
|
||||
As an example see how dragging a header from one control to another will only trigger an interactable event for the developer if the checkbox is enabled.
|
||||
|
||||
<SideBySidePaneview />
|
@ -1,246 +0,0 @@
|
||||
---
|
||||
description: Splitview Documentation
|
||||
---
|
||||
|
||||
import { SimpleSplitview } from '@site/src/components/simpleSplitview';
|
||||
import { SplitviewExample1 } from '@site/src/components/splitview/active';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Splitview
|
||||
|
||||
## Introduction
|
||||
|
||||
A Splitview is a collection of resizable horizontally or vertically stacked panels.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '100px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview />
|
||||
</div>
|
||||
|
||||
```tsx title="Simple Splitview example"
|
||||
import {
|
||||
ISplitviewPanelProps,
|
||||
Orientation,
|
||||
SplitviewReact,
|
||||
SplitviewReadyEvent,
|
||||
} from 'dockview';
|
||||
|
||||
const components = {
|
||||
default: (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const SimpleSplitview = () => {
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SplitviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
orientation={Orientation.HORIZONTAL}
|
||||
className="dockview-theme-abyss"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## SplitviewReact Component
|
||||
|
||||
You can create a Splitview through the use of the `ReactSplitview` component.
|
||||
|
||||
```tsx
|
||||
import { ReactSplitview } from 'dockview';
|
||||
```
|
||||
|
||||
Using the `onReady` prop you can access to the component `api` and add panels either through deserialization or the individual addition of panels.
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| ------------------- | -------------------------------------- | -------- | ------------------------ | ------------------------------------------------------------------------ |
|
||||
| onReady | `(event: SplitviewReadyEvent) => void` | No | | Function |
|
||||
| components | `Record<string, ISplitviewPanelProps>` | No | | Panel renderers |
|
||||
| orientation | `Orientation` | Yes | `Orientation.HORIZONTAL` | Orientation of the Splitview |
|
||||
| proportionalLayout | `boolean` | Yes | `true` | See <Link to="../basics/#proportional-layout">Proportional layout</Link> |
|
||||
| hideBorders | `boolean` | Yes | `false` | Hide the borders between panels |
|
||||
| className | `string` | Yes | `''` | Attaches a classname |
|
||||
| disableAutoResizing | `boolean` | Yes | `false` | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
|
||||
## Splitview API
|
||||
|
||||
The Splitview API is exposed both at the `onReady` event and on each panel through `props.containerApi`.
|
||||
Through this API you can control general features of the component and access all added panels.
|
||||
|
||||
```tsx title="Splitview API via Panel component"
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx title="Splitview API via the onReady callback"
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumSize | `number` | The sum of the `minimumSize` property for each panel |
|
||||
| maximumSize | `number` | The sum of the `maximumSize` property for each panel |
|
||||
| length | `number` | Number of panels |
|
||||
| panels | `ISplitviewPanel[]` | All panels |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | Fires on layout change |
|
||||
| onDidLayoutFromJSON | `Event<void>` | Fires of layout change caused by a fromJSON deserialization call |
|
||||
| onDidAddView | `Event<IView>` | Fires when a view is added |
|
||||
| onDidRemoveView | `Event<IView>` | Fires when a view is removed |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddSplitviewComponentOptions): ISplitviewPanel` | |
|
||||
| removePanel | `(panel: ISplitviewPanel, sizing?: Sizing): void` | |
|
||||
| getPanel | `(id:string): ISplitviewPanel \| undefined` | |
|
||||
| movePanel | `(from: number, to: number): void` | |
|
||||
| | |
|
||||
| updateOptions | `(options: SplitviewComponentUpdateOptions): void` | |
|
||||
| focus | `(): void` | Focus the active panel, if exists |
|
||||
| layout | `(width: number, height:number): void` | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedSplitview): void` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedSplitview` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
|
||||
## Splitview Panel API
|
||||
|
||||
The Splitview panel API is exposed on each panel containing actions and variables specific to that panel.
|
||||
|
||||
```tsx title="Splitview panel API via Panel component"
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focsed |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| isVisible | `boolean` | Is panel visible |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| | | |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | Fires when panel dimensions change |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | Fire when panel is focused and blurred |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | Fires when the panels visiblity property is changed (see <Link to="./splitview/#visibility">Panel Visibility</Link>) |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | Fires when the panels active property is changed (see <Link to="./splitview/#active">Active Panel</Link>) |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | Fires when the panels size contrainsts change (see <Link to="./splitview/#contraints">Panel Constraints</Link>) |
|
||||
| | | |
|
||||
| setVisible | `(isVisible: boolean): void` | |
|
||||
| setActive | `(): void` | |
|
||||
| | | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: PanelSizeEvent): void` | |
|
||||
|
||||
## Advanced Features
|
||||
|
||||
Listed below are some functionalities avalaible through both the panel and component APIs. The live demo shows examples of these in real-time.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '200px',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SplitviewExample1 />
|
||||
</div>
|
||||
|
||||
### Visibility
|
||||
|
||||
A panels visibility can be controlled and monitored through the following code.
|
||||
A panel with visibility set to `false` will remain as a part of the components list of panels but will not be rendered.
|
||||
|
||||
```tsx
|
||||
const disposable = props.api.onDidVisibilityChange(({ isVisible }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setVisible(true);
|
||||
```
|
||||
|
||||
### Active
|
||||
|
||||
Only one panel in the `splitview` can be the active panel at any one time.
|
||||
Setting a panel as active will set all the others as inactive.
|
||||
A focused panel is always the active panel but an active panel is not always focused.
|
||||
|
||||
```tsx
|
||||
const disposable = props.api.onDidActiveChange(({ isActive }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setActive();
|
||||
```
|
||||
|
||||
### Contraints
|
||||
|
||||
When adding a panel you can specify pixel size contraints
|
||||
|
||||
```tsx
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
minimumSize: 100,
|
||||
maximumSize: 1000,
|
||||
});
|
||||
```
|
||||
|
||||
These contraints can be updated throughout the lifecycle of the `splitview` using the panel API
|
||||
|
||||
```tsx
|
||||
props.api.onDidConstraintsChange(({ maximumSize, minimumSize }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setConstraints({
|
||||
maximumSize: 200,
|
||||
minimumSize: 400,
|
||||
});
|
||||
```
|
149
packages/docs/versioned_docs/version-1.7.6/index.mdx
vendored
149
packages/docs/versioned_docs/version-1.7.6/index.mdx
vendored
@ -1,149 +0,0 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
description: A zero dependency layout manager built for React
|
||||
---
|
||||
|
||||
import { SimpleSplitview } from '@site/src/components/simpleSplitview';
|
||||
import { SimpleGridview } from '@site/src/components/simpleGridview';
|
||||
import { SimplePaneview } from '@site/src/components/simplePaneview';
|
||||
import SimpleDockview from '@site/sandboxes/simple-dockview/src/app';
|
||||
|
||||
# Introduction
|
||||
|
||||
**dockview** is a zero dependency layout manager that supports tab, grids and splitviews.
|
||||
|
||||
## Features
|
||||
|
||||
- Themable and customizable
|
||||
- Support for the serialization and deserialization of layouts
|
||||
- Drag and drop support
|
||||
|
||||
## Quick start
|
||||
|
||||
`dockview` has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. To install `dockview` you can run:
|
||||
|
||||
```shell
|
||||
npm install dockview
|
||||
```
|
||||
|
||||
You must also import the dockview stylesheet found under [`dockview/dict/styles/dockview.css`](https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css),
|
||||
depending on your solution this might be:
|
||||
|
||||
```css
|
||||
@import './node_modules/dockview/dist/styles/dockview.css';
|
||||
```
|
||||
|
||||
A dark and light theme are provided, one of these classes (or a custom theme) must be attached at any point above your components in the HTML tree. To cover the entire web page you might attach the class to the `body` component:
|
||||
|
||||
```html
|
||||
<body classname="dockview-theme-abyss">
|
||||
...
|
||||
</body>
|
||||
<body classname="dockview-theme-light">
|
||||
...
|
||||
</body>
|
||||
```
|
||||
|
||||
There are 4 components you may want to use:
|
||||
|
||||
Splitview
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '100px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview />
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleGridview />
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimplePaneview />
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleDockview />
|
||||
</div>
|
||||
|
||||
```tsx
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
PanelCollection,
|
||||
IDockviewPanelProps,
|
||||
IDockviewPanelHeaderProps,
|
||||
} from 'dockview';
|
||||
|
||||
const components: PanelCollection<IDockviewPanelProps> = {
|
||||
default: (props: IDockviewPanelProps<{ someProps: string }>) => {
|
||||
return <div>{props.params.someProps}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
const headers: PanelCollection<IDockviewPanelHeaderProps> = {
|
||||
customTab: (props: IDockviewPanelHeaderProps) => {
|
||||
return (
|
||||
<div>
|
||||
<span>{props.api.title}</span>
|
||||
<span onClick={() => props.api.close()}>{'[x]'}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const Component = () => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel1',
|
||||
component: 'default',
|
||||
tabComponent: 'customTab', // optional custom header
|
||||
params: {
|
||||
someProps: 'Hello',
|
||||
},
|
||||
});
|
||||
event.api.addPanel({
|
||||
id: 'panel2',
|
||||
component: 'default',
|
||||
params: {
|
||||
someProps: 'World',
|
||||
},
|
||||
position: { referencePanel: 'panel1', direction: 'below' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
tabComponents={headers} // optional headers renderer
|
||||
onReady={onReady}
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
@ -2,6 +2,7 @@
|
||||
"label": "Components",
|
||||
"collapsible": true,
|
||||
"collapsed": false,
|
||||
"position": 2,
|
||||
"link": {
|
||||
"type": "generated-index",
|
||||
"title": "Components"
|
@ -2,10 +2,7 @@
|
||||
description: Dockview Documentation
|
||||
---
|
||||
|
||||
import {
|
||||
Container,
|
||||
MultiFrameworkContainer,
|
||||
} from '@site/src/components/ui/container';
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
|
||||
import Link from '@docusaurus/Link';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
@ -28,6 +25,14 @@ import DockviewExternalDnd from '@site/sandboxes/externaldnd-dockview/src/app';
|
||||
import DockviewResizeContainer from '@site/sandboxes/resizecontainer-dockview/src/app';
|
||||
import DockviewTabheight from '@site/sandboxes/tabheight-dockview/src/app';
|
||||
import DockviewWithIFrames from '@site/sandboxes/iframe-dockview/src/app';
|
||||
import DockviewFloating from '@site/sandboxes/floatinggroup-dockview/src/app';
|
||||
import DockviewLockedGroup from '@site/sandboxes/lockedgroup-dockview/src/app';
|
||||
import DockviewKeyboard from '@site/sandboxes/keyboard-dockview/src/app';
|
||||
import DockviewPopoutGroup from '@site/sandboxes/popoutgroup-dockview/src/app';
|
||||
import DockviewMaximizeGroup from '@site/sandboxes/maximizegroup-dockview/src/app';
|
||||
import DockviewRenderMode from '@site/sandboxes/rendermode-dockview/src/app';
|
||||
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
import { attach as attachDockviewVanilla } from '@site/sandboxes/javascript/vanilla-dockview/src/app';
|
||||
import { attach as attachSimpleDockview } from '@site/sandboxes/javascript/simple-dockview/src/app';
|
||||
@ -55,24 +60,12 @@ Dockview is an abstraction built on top of [Gridviews](./gridview) where each vi
|
||||
|
||||
You can create a Dockview through the use of the `DockviewReact` component.
|
||||
|
||||
```tsx
|
||||
import { DockviewReact } from 'dockview';
|
||||
```
|
||||
|
||||
| Property | Type | Optional | Default | Description |
|
||||
| --------------------- | ------------------------------------ | -------- | --------- | ------------------------------------------------------------ |
|
||||
| onReady | (event: SplitviewReadyEvent) => void | No | | |
|
||||
| components | object | No | | |
|
||||
| tabComponents | object | Yes | | |
|
||||
| watermarkComponent | object | Yes | | |
|
||||
| hideBorders | boolean | Yes | false | |
|
||||
| className | string | Yes | '' | |
|
||||
| disableAutoResizing | boolean | Yes | false | See <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| onDidDrop | Event | Yes | false | |
|
||||
| showDndOverlay | Event | Yes | false | |
|
||||
| defaultTabComponent | object | Yes | | |
|
||||
| groupControlComponent | object | Yes | | |
|
||||
| singleTabMode | 'fullwidth' \| 'default' | Yes | 'default' | |
|
||||
<p style={{ fontSize: '1.3em' }}>
|
||||
<span>{'All of these are React props available through the '}</span>
|
||||
<code>DockviewReact</code>
|
||||
<span>{' component.'}</span>
|
||||
</p>
|
||||
<DocRef declaration="IDockviewReactProps" />
|
||||
|
||||
## Dockview API
|
||||
|
||||
@ -93,44 +86,19 @@ const onReady = (event: DockviewReadyEvent) => {
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ---------------------------------------------------- | -------------------------------------------------------- |
|
||||
| height | `number` | Component pixel height |
|
||||
| width | `number` | Component pixel width |
|
||||
| minimumHeight | `number` | |
|
||||
| maximumHeight | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| maximumWidth | `number` | |
|
||||
| length | `number` | Number of panels |
|
||||
| size | `number` | Number of Groups |
|
||||
| panels | `IDockviewPanel[]` | |
|
||||
| groups | `GroupPanel[]` | |
|
||||
| activePanel | `IDockviewPanel \| undefined` | |
|
||||
| activeGroup | `IDockviewPanel \| undefined` | |
|
||||
| | | |
|
||||
| onDidLayoutChange | `Event<void>` | |
|
||||
| onDidLayoutFromJSON | `Event<void>` | |
|
||||
| onDidAddGroup | `Event<GroupPanel>` | |
|
||||
| onDidRemoveGroup | `Event<GroupPanel>` | |
|
||||
| onDidActiveGroupChange | `Event<GroupPanel \| undefined>` | |
|
||||
| onDidAddPanel | `Event<IDockviewPanel>` | |
|
||||
| onDidRemovePanel | `Event<IDockviewPanel>` | |
|
||||
| onDidActivePanelChange | `Event<IDockviewPanel \| undefined>` | |
|
||||
| onDidDrop | `Event<DockviewDropEvent` | |
|
||||
| | | |
|
||||
| addPanel | `addPanel(options: AddPanelOptions): IDockviewPanel` | |
|
||||
| getPanel | `(id: string) \| IDockviewPanel \| undefined` | |
|
||||
| addGroup | `(options? AddGroupOptions): void` | |
|
||||
| closeAllGroups | `(): void` | |
|
||||
| removeGroup | `(group: GroupPanel): void` | |
|
||||
| getGroup | `(id: string): GroupPanel \| undefined` | |
|
||||
| | | |
|
||||
| updateOptions | `(options:SplitviewComponentUpdateOptions): void` | |
|
||||
| focus | `(): void` | |
|
||||
| layout | `(width: number, height:number): void` | <Link to="../basics/#auto-resizing">Auto Resizing</Link> |
|
||||
| fromJSON | `(data: SerializedDockview): void` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| toJSON | `(): SerializedDockview` | <Link to="../basics/#serialization">Serialization</Link> |
|
||||
| clear | `(): void` | Clears the current layout |
|
||||
<p style={{ fontSize: '1.3em' }}>
|
||||
<span>{'All of these methods are available through the '}</span>
|
||||
<code>api</code>
|
||||
<span>{' property of '}</span>
|
||||
<code>DockviewComponent</code>
|
||||
<span>{' and the '}</span>
|
||||
<code>containerApi</code>
|
||||
<span>{' property of '}</span>
|
||||
<code>IDockviewPanel</code>
|
||||
<span>.</span>
|
||||
</p>
|
||||
|
||||
<DocRef declaration="DockviewApi" />
|
||||
|
||||
## Dockview Panel API
|
||||
|
||||
@ -142,29 +110,34 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
};
|
||||
```
|
||||
|
||||
| Property | Type | Description |
|
||||
| ---------------------- | ----------------------------------------------------------- | ---------------- |
|
||||
| id | `string` | Panel id |
|
||||
| isFocused | `boolean` | Is panel focused |
|
||||
| isActive | `boolean` | Is panel active |
|
||||
| width | `number` | Panel width |
|
||||
| height | `number` | Panel height |
|
||||
| onDidDimensionsChange | `Event<PanelDimensionChangeEvent>` | |
|
||||
| onDidFocusChange | `Event<FocusEvent>` | |
|
||||
| onDidVisibilityChange | `Event<VisibilityEvent>` | |
|
||||
| onDidActiveChange | `Event<ActiveEvent>` | |
|
||||
| setActive | `(): void` | |
|
||||
| | | |
|
||||
| onDidConstraintsChange | `onDidConstraintsChange: Event<PanelConstraintChangeEvent>` | |
|
||||
| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | |
|
||||
| setSize | `(event: SizeEvent): void` | |
|
||||
| | | |
|
||||
| group | `GroupPanel | undefined` |
|
||||
| isGroupActive | `boolean` | |
|
||||
| title | `string` | |
|
||||
| suppressClosable | `boolean` | |
|
||||
| close | `(): void` | |
|
||||
| setTitle | `(title: string): void` | |
|
||||
<p style={{ fontSize: '1.3em' }}>
|
||||
<span>{'All of these are methods are available through the '}</span>
|
||||
<code>api</code>
|
||||
<span>{' property of '}</span>
|
||||
<code>IDockviewPanel</code>
|
||||
<span>.</span>
|
||||
</p>
|
||||
|
||||
<DocRef declaration="DockviewPanelApi" />
|
||||
|
||||
## Theme
|
||||
|
||||
As well as importing the `dockview` stylesheet you must provide a class-based theme somewhere in your application. For example.
|
||||
|
||||
```tsx
|
||||
// Providing a theme directly through the DockviewReact component props
|
||||
<DockviewReact className="dockview-theme-dark" />
|
||||
|
||||
// Providing a theme somewhere in the DOM tree
|
||||
<div className="dockview-theme-dark">
|
||||
<div>
|
||||
{/**... */}
|
||||
<DockviewReact />
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can find more details on theming <Link to="../theme">here</Link>.
|
||||
|
||||
## Layout Persistance
|
||||
|
||||
@ -218,9 +191,10 @@ const onReady = (event: DockviewReadyEvent) => {
|
||||
Here is an example using the above code loading from and saving to localStorage.
|
||||
If you refresh the page you should notice your layout is loaded as you left it.
|
||||
|
||||
<Container sandboxId="layout-dockview">
|
||||
<DockviewPersistance />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="layout-dockview"
|
||||
react={DockviewPersistance}
|
||||
/>
|
||||
|
||||
## Resizing
|
||||
|
||||
@ -249,17 +223,16 @@ props.api.group.api.setSize({
|
||||
|
||||
You can see an example invoking both approaches below.
|
||||
|
||||
<Container sandboxId="resize-dockview">
|
||||
<ResizeDockview />
|
||||
</Container>
|
||||
<MultiFrameworkContainer sandboxId="resize-dockview" react={ResizeDockview} />
|
||||
|
||||
### Container Resizing
|
||||
|
||||
The component will automatically resize to it's container.
|
||||
|
||||
<Container sandboxId="resizecontainer-dockview">
|
||||
<DockviewResizeContainer />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="resizecontainer-dockview"
|
||||
react={DockviewResizeContainer}
|
||||
/>
|
||||
|
||||
## Watermark
|
||||
|
||||
@ -267,9 +240,10 @@ When the dockview is empty you may want to display some fallback content, this i
|
||||
By default there the watermark has no content but you can provide as a prop to `DockviewReact` a `watermarkComponent`
|
||||
which will be rendered when there are no panels or groups.
|
||||
|
||||
<Container sandboxId="watermark-dockview">
|
||||
<DockviewWatermark />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="watermark-dockview"
|
||||
react={DockviewWatermark}
|
||||
/>
|
||||
|
||||
## Drag And Drop
|
||||
|
||||
@ -346,9 +320,11 @@ return (
|
||||
);
|
||||
```
|
||||
|
||||
<Container sandboxId="dnd-dockview">
|
||||
<DndDockview />
|
||||
</Container>
|
||||
### Intercepting Drag Events
|
||||
|
||||
You can intercept drag events to attach your own metadata using the `onWillDragPanel` and `onWillDragGroup` api methods.
|
||||
|
||||
<MultiFrameworkContainer sandboxId="dnd-dockview" react={DndDockview} />
|
||||
|
||||
### Third Party Dnd Libraries
|
||||
|
||||
@ -356,9 +332,130 @@ This shows a simple example of a third-party library used inside a panel that re
|
||||
and drop functionalities. This examples serves to show that `dockview` doesn't interfer with
|
||||
any drag and drop logic for other controls.
|
||||
|
||||
<Container>
|
||||
<DockviewExternalDnd />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="externaldnd-dockview"
|
||||
react={DockviewExternalDnd}
|
||||
/>
|
||||
|
||||
## Floating Groups
|
||||
|
||||
Dockview has built-in support for floating groups. Each floating container can contain a single group with many panels
|
||||
and you can have as many floating containers as needed. You cannot dock multiple groups together in the same floating container.
|
||||
|
||||
Floating groups can be interacted with whilst holding the `shift` key activating the `event.shiftKey` boolean property on `KeyboardEvent` events.
|
||||
|
||||
> Float an existing tab by holding `shift` whilst interacting with the tab
|
||||
|
||||
<img style={{ width: '60%' }} src={useBaseUrl('/img/float_add.svg')} />
|
||||
|
||||
> Move a floating tab by holding `shift` whilst moving the cursor or dragging the empty
|
||||
> header space
|
||||
|
||||
<img style={{ width: '60%' }} src={useBaseUrl('/img/float_move.svg')} />
|
||||
|
||||
> Move an entire floating group by holding `shift` whilst dragging the empty header space
|
||||
|
||||
<img style={{ width: '60%' }} src={useBaseUrl('/img/float_group.svg')} />
|
||||
|
||||
Floating groups can be programatically added through the dockview `api` method `api.addFloatingGroup(...)` and you can check whether
|
||||
a group is floating via the `group.api.location` property. See examples for full code.
|
||||
|
||||
You can control the bounding box of floating groups through the optional `floatingGroupBounds` options:
|
||||
|
||||
- `boundedWithinViewport` will force the entire floating group to be bounded within the docks viewport.
|
||||
- `{minimumHeightWithinViewport?: number, minimumWidthWithinViewport?: number}` sets the respective dimension minimums that must appears within the docks viewport
|
||||
- If no options are provided the defaults of `100px` minimum height and width within the viewport are set.
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="floatinggroup-dockview"
|
||||
react={DockviewFloating}
|
||||
/>
|
||||
|
||||
## Popout Groups
|
||||
|
||||
Dockview has built-in support for opening groups in new Windows.
|
||||
Each popout window can contain a single group with many panels and you can have as many popout
|
||||
windows as needed. You cannot dock multiple groups together in the same window.
|
||||
|
||||
Popout windows require your website to have a blank `.html` page that can be used, by default this is set to `/popout.html` but
|
||||
can be configured to match requirements.
|
||||
|
||||
```tsx title="Open new popout group from the component api"
|
||||
api.addPopoutGroup(
|
||||
group,
|
||||
// the second arguments (options) is optional
|
||||
{
|
||||
popoutUrl:"/popout.html",
|
||||
box: { left: 0, top: 0, height: 200, width: 300 }
|
||||
});
|
||||
```
|
||||
|
||||
> If you do not provide `options.popoutUrl` a default of `/popout.html` is used and if `options.box` is not provided
|
||||
the view will be places according to it's currently position.
|
||||
|
||||
From within a panel you may say
|
||||
|
||||
```tsx
|
||||
props.containerApi.addPopoutGroup(props.api.group);
|
||||
```
|
||||
|
||||
To programatically move the popout group back into the main grid you can use the `moveTo` method in many ways, one of the following would suffice
|
||||
|
||||
```tsx
|
||||
// option 1: add absolutely to the right-side of the grid
|
||||
props.group.api.moveTo({ position: 'right' });
|
||||
|
||||
// option 2: create a new group and move the contents of the popout group to it
|
||||
const group = props.containerApi.addGroup();
|
||||
props.group.api.moveTo({ group });
|
||||
```
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="popoutgroup-dockview"
|
||||
react={DockviewPopoutGroup}
|
||||
/>
|
||||
|
||||
## Maximized Groups
|
||||
|
||||
To maximize a group from the component `api`:
|
||||
|
||||
```tsx
|
||||
// maximize a specified group
|
||||
api.maxmimizeGroup(group);
|
||||
|
||||
// check whether a specific group is maximized
|
||||
const result: boolean = api.isMaximizedGroup(group);
|
||||
|
||||
// if there is any maximized group exit the maximized state
|
||||
exitMaximizedGroup();
|
||||
|
||||
// is there a maximized group
|
||||
const result: boolean = hasMaximizedGroup();
|
||||
```
|
||||
|
||||
The following methods are available on both the panel and group `api` objects:
|
||||
|
||||
> `api.<method>` is equivalent to `api.group.api.<method>` for all of these methods. The methods exist on the panel `api` object for convenience.
|
||||
|
||||
```ts
|
||||
// maximize the group
|
||||
api.maximize();
|
||||
|
||||
// is this group maximized (if another group is maximized this method will still return false)
|
||||
const result: boolean = api.isMaxmized();
|
||||
|
||||
// exit only if this group is maximzied (if another group is maxmized this has no affect)
|
||||
api.exitMaximized();
|
||||
```
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="maximizegroup-dockview"
|
||||
react={DockviewMaximizeGroup}
|
||||
/>
|
||||
|
||||
|
||||
## Panels
|
||||
|
||||
@ -416,7 +513,7 @@ Finally `addPanel` accepts a `position` object which tells dockview where to pla
|
||||
- This object accepts a `direction` property which dictates where,
|
||||
relative to the provided reference the new panel will be placed.
|
||||
|
||||
> If neither a `referencePanel` or `referenceGroup` then the provided `direction` will be treated as absolute.
|
||||
> If neither a `referencePanel` or `referenceGroup` is provided then the `direction` will be treated as absolute.
|
||||
|
||||
> If no `direction` is provided the library will place the new panel in a pre-determined position.
|
||||
|
||||
@ -436,6 +533,23 @@ const panel2 = api.addPanel({
|
||||
});
|
||||
```
|
||||
|
||||
To add a floating panel you should include the `floating` variable which can be either a `boolean` or an object defining it's bounds.
|
||||
These bounds are relative to the dockview component.
|
||||
|
||||
```ts
|
||||
const panel1 = api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
floating: true,
|
||||
});
|
||||
|
||||
const panel2 = api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
floating: { x: 10, y: 10, width: 300, height: 300 },
|
||||
});
|
||||
```
|
||||
|
||||
### Update Panel
|
||||
|
||||
You can programatically update the `params` passed through to the panel through the panal api using `api.updateParameters`.
|
||||
@ -470,20 +584,69 @@ panel.api.updateParameters({
|
||||
});
|
||||
```
|
||||
|
||||
### Move panel
|
||||
|
||||
You can programatically move a panel using the panel `api`.
|
||||
|
||||
```ts
|
||||
panel.api.moveTo({ group, position, index });
|
||||
```
|
||||
|
||||
An equivalent method for moving groups is avaliable on the group `api`.
|
||||
|
||||
```ts
|
||||
const group = panel.api.group;
|
||||
group.api.moveTo({ group, position });
|
||||
```
|
||||
|
||||
### Remove panel
|
||||
|
||||
You can programatically remove a panel using the panel `api`.
|
||||
|
||||
```ts
|
||||
panel.api.close();
|
||||
```
|
||||
|
||||
Given a reference to the panel you can also use the component `api` to remove it.
|
||||
|
||||
```ts
|
||||
const panel = api.getPanel('myPanel');
|
||||
api.removePanel(panel);
|
||||
```
|
||||
|
||||
### Panel Rendering
|
||||
|
||||
#### Render Mode
|
||||
|
||||
Dockview has two rendering modes `onlyWhenVisible` (default) and `always`. A rendering mode can be defined through the `renderer` prop to `DockviewReact` or at an individual panel level when added where
|
||||
the panel declaration takes precedence if both are defined. Rendering modes defined at the panel level are persisted, those defined at the `DockviewReact` level are not persisted.
|
||||
|
||||
- `onlyWhenVisible` mode is the default mode. In this mode when a panel is no longer visible through either it's visiblity being hidden or it not being the active panel within a group the panels HTMLElement is removed
|
||||
from the DOM and any DOM state such as scrollbar positions will be lost. If you are using any ResizeObservers to measure size this will result both zero height and width as the HTMLElement no longer belongs to the DOM.
|
||||
This design allows for maximum performance at some cost.
|
||||
- `always` mode. In this mode when panels become hidden the HTMLElement is not destroyed so all DOM state such as scrollbar positions will be maintained. This is implemented by rendering each panel as an absolutely positioned
|
||||
HTMLElement and hidden the HTMLElement with `display: none` when it should be hidden.
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={500}
|
||||
sandboxId="rendermode-dockview"
|
||||
react={DockviewRenderMode}
|
||||
/>
|
||||
|
||||
####
|
||||
|
||||
By default `DockviewReact` only adds to the DOM those panels that are visible,
|
||||
if a panel is not the active tab and not shown the contents of the hidden panel will be removed from the DOM.
|
||||
|
||||
However the React Components associated with each panel are only created once and will always exist for as long as the panel exists, hidden or not.
|
||||
When a panel is in `onlyWhenVisible` render mode this only affects the contents within the DOM. The lifecycle of that panel instance is still maintained.
|
||||
The React Components associated with each panel are only created once and will always exist for as long as the panel exists, hidden or not.
|
||||
|
||||
> For example this means that any hooks in those components will run whether the panel is visible or not which may lead to excessive background work depending
|
||||
> e.g. This means that any hooks in those components will run whether the panel is visible or not which may lead to excessive background work depending
|
||||
> on the panels implementation.
|
||||
|
||||
This is the default behaviour to ensure the greatest flexibility for the user but through the panels `props.api` you can listen to the visiblity state of the panel
|
||||
and write additional logic to optimize your application.
|
||||
You can listen to the visiblity state of the panel and write additional logic to optimize your application if required, although this is an advanced case.
|
||||
|
||||
For example if you wanted to unmount the React Components when the panel is not visible you could create a Higher-Order-Component that listens to the panels
|
||||
If you wanted to unmount the React Components when the panel is not visible you could create a Higher-Order-Component that listens to the panels
|
||||
visiblity state and only renders the panel when visible.
|
||||
|
||||
```tsx title="Only rendering the React Component when the panel is visible, otherwise rendering a null React Component"
|
||||
@ -524,9 +687,11 @@ const components = { default: RenderWhenVisible(MyComponent) };
|
||||
|
||||
Toggling the checkbox you can see that when you only render those panels which are visible the underling React component is destroyed when it becomes hidden and re-created when it becomes visible.
|
||||
|
||||
<Container sandboxId="rendering-dockview">
|
||||
<RenderingDockview renderVisibleOnly={false} />
|
||||
</Container>
|
||||
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="rendering-dockview"
|
||||
react={RenderingDockview}
|
||||
/>
|
||||
|
||||
## Headers
|
||||
|
||||
@ -535,7 +700,9 @@ Toggling the checkbox you can see that when you only render those panels which a
|
||||
You can provide custom renderers for your tab headers for maximum customization.
|
||||
A default implementation of `DockviewDefaultTab` is provided should you only wish to attach minor
|
||||
changes and events that do not alter the default behaviour, for example to add a custom context menu event
|
||||
handler.
|
||||
handler or to hide the close button.
|
||||
|
||||
The `DockviewDefaultTab` component accepts a `hideClose` prop if you wish only to hide the close button.
|
||||
|
||||
```tsx title="Attaching a custom context menu event handlers to a custom header"
|
||||
import { IDockviewPanelHeaderProps, DockviewDefaultTab } from 'dockview';
|
||||
@ -545,7 +712,7 @@ const MyCustomheader = (props: IDockviewPanelHeaderProps) => {
|
||||
event.preventDefault();
|
||||
alert('context menu');
|
||||
};
|
||||
return <DockviewDefaultTab onContextMenu={onContextMenu} {...props} />;
|
||||
return <DockviewDefaultTab onContextMenu={onContextMenu} hideClose={true} {...props} />;
|
||||
};
|
||||
```
|
||||
|
||||
@ -580,9 +747,10 @@ As a simple example the below attaches a custom event handler for the context me
|
||||
The below example uses a custom tab renderer to reigster a popover when the user right clicked on a tab.
|
||||
This still makes use of the `DockviewDefaultTab` since it's only a minor change.
|
||||
|
||||
<Container sandboxId="customheader-dockview">
|
||||
<CustomHeadersDockview />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="customheader-dockview"
|
||||
react={CustomHeadersDockview}
|
||||
/>
|
||||
|
||||
### Default Tab Title
|
||||
|
||||
@ -605,9 +773,10 @@ api.setTitle('my_new_custom_title');
|
||||
|
||||
> Note this only works when using the default tab implementation.
|
||||
|
||||
<Container sandboxId="updatetitle-dockview">
|
||||
<DockviewSetTitle />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="updatetitle-dockview"
|
||||
react={DockviewSetTitle}
|
||||
/>
|
||||
|
||||
### Custom Tab Title
|
||||
|
||||
@ -679,26 +848,38 @@ You can still add groups to a locked panel programatically using the API though.
|
||||
|
||||
```tsx
|
||||
panel.group.locked = true;
|
||||
|
||||
// Or
|
||||
|
||||
panel.group.locked = 'no-drop-target';
|
||||
```
|
||||
|
||||
Use `true` to keep drop zones top, right, bottom, left for the group. Use `no-drop-target` to disable all drop zones. For you to get a
|
||||
better understanding of what this means, try and drag the panels in the example below to the locked groups.
|
||||
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="lockedgroup-dockview"
|
||||
react={DockviewLockedGroup}
|
||||
/>
|
||||
|
||||
### Group Controls Panel
|
||||
|
||||
`DockviewReact` accepts a prop `groupControlComponent` which expects a React component whos props are `IDockviewGroupControlProps`.
|
||||
This control will be rendered inside the header bar on the right hand side for each group of tabs.
|
||||
`DockviewReact` accepts `leftHeaderActionsComponent`, `rightHeaderActionsComponent` and `prefixHeaderActionsComponent` which expect a React component with props `IDockviewHeaderActionsProps`.
|
||||
These controls are rendered to left and right side of the space to the right of the tabs in the header bar as well as before the first tab in the case of the prefix header prop.
|
||||
|
||||
```tsx
|
||||
const Component: React.FunctionComponent<IDockviewGroupControlProps> = () => {
|
||||
const Component: React.FunctionComponent<IDockviewHeaderActionsProps> = () => {
|
||||
return <div>{'...'}</div>;
|
||||
};
|
||||
|
||||
return <DockviewReact {...props} groupControlComponent={Component} />;
|
||||
return <DockviewReact {...props} leftHeaderActionsComponent={Component} rightHeaderActionsComponent={...} />;
|
||||
```
|
||||
|
||||
As a simple example the below uses the `groupControlComponent` to render a small control that indicates whether the group
|
||||
is active and which panel is active in that group.
|
||||
|
||||
```tsx
|
||||
const GroupControlComponent = (props: IDockviewGroupControlProps) => {
|
||||
const RightHeaderActionsComponent = (props: IDockviewHeaderActionsProps) => {
|
||||
const isGroupActive = props.isGroupActive;
|
||||
const activePanel = props.activePanel;
|
||||
|
||||
@ -720,9 +901,10 @@ const GroupControlComponent = (props: IDockviewGroupControlProps) => {
|
||||
};
|
||||
```
|
||||
|
||||
<Container sandboxId="groupcontrol-dockview">
|
||||
<DockviewGroupControl />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="groupcontrol-dockview"
|
||||
react={DockviewGroupControl}
|
||||
/>
|
||||
|
||||
### Constraints
|
||||
|
||||
@ -736,9 +918,12 @@ api.group.api.setConstraints(...)
|
||||
> If you specific a constraint on a group and move a panel within that group to another group it will no
|
||||
> longer be subject to those constraints since those constraints were on the group and not on the individual panel.
|
||||
|
||||
<Container height={500} sandboxId="constraints-dockview">
|
||||
<DockviewConstraints />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
height={500}
|
||||
sandboxId="constraints-dockview"
|
||||
react={DockviewConstraints}
|
||||
/>
|
||||
|
||||
|
||||
## iFrames
|
||||
|
||||
@ -748,55 +933,54 @@ iFrames required special attention because of a particular behaviour in how iFra
|
||||
|
||||
You can find many examples of discussions on this. Two reputable forums for example are linked [here](https://bugzilla.mozilla.org/show_bug.cgi?id=254144) and [here](https://github.com/whatwg/html/issues/5484).
|
||||
|
||||
The problem with iFrames and `dockview` is that when you hide or move a panel that panels DOM element may be moved within the DOM or removed from the DOM completely.
|
||||
If your panel contains an iFrame then that iFrame will reload after being re-positioned within the DOM tree and all state in that iFrame will most likely be lost.
|
||||
To ensure iFrames work as expected you should render them in panels with `renderer: 'always'` to ensure they are never removed from the DOM, alternatively set the defaultRenderer to `always`.
|
||||
|
||||
`dockview` does not provide a built-in solution to this because it's too specific of a problem to include in the library.
|
||||
However the below example does show an implementation of a higher-order component `HoistedDockviewPanel`that you could use to work around this problems and make iFrames behave in `dockview`.
|
||||
> See the **Panel Rendering** section for more information of render modes.
|
||||
|
||||
What the higher-order component is doing is to hoist the panels contents into a DOM element that is always present and then `position: absolute` that element to match the dimensions of it's linked panel.
|
||||
The visibility of these hoisted elements is then controlled through some exposed api methods to hide elements that shouldn't be currently shown.
|
||||
```tsx title="Example of a panel using an alternative renderer"
|
||||
api.addPanel({
|
||||
id: 'my_panel_id',
|
||||
component: 'my_component',
|
||||
renderer: 'always',
|
||||
});
|
||||
```
|
||||
|
||||
You should open this example in CodeSandbox using the provided link to understand the code and make use of this implemention if required.
|
||||
|
||||
<Container sandboxId="iframe-dockview" height={600}>
|
||||
<DockviewWithIFrames />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="iframe-dockview"
|
||||
height={600}
|
||||
react={DockviewWithIFrames}
|
||||
/>
|
||||
|
||||
## Events
|
||||
|
||||
A simple example showing events fired by `dockviewz that can be interacted with.
|
||||
|
||||
<Container height={600} sandboxId="events-dockview">
|
||||
<EventsDockview />
|
||||
</Container>
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="events-dockview"
|
||||
react={EventsDockview}
|
||||
/>
|
||||
|
||||
## Advanced Examples
|
||||
## Keyboard Navigation
|
||||
|
||||
Keyboard shortcuts
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="keyboard-dockview"
|
||||
react={DockviewKeyboard}
|
||||
/>
|
||||
|
||||
### Nested Dockviews
|
||||
|
||||
You can safely create multiple dockview instances within one page and nest dockviews within other dockviews.
|
||||
If you wish to interact with the drop event from one dockview instance in another dockview instance you can implement the `showDndOverlay` and `onDidDrop` props on `DockviewReact`.
|
||||
|
||||
<Container sandboxId="nested-dockview">
|
||||
<NestedDockview />
|
||||
</Container>
|
||||
<MultiFrameworkContainer sandboxId="nested-dockview" react={NestedDockview} />
|
||||
|
||||
### Window-like mananger with tabs
|
||||
|
||||
<DockviewNative2 />
|
||||
|
||||
## Vanilla JS
|
||||
<MultiFrameworkContainer sandboxId="nativeapp-dockview" react={DockviewNative2} />
|
||||
|
||||
> Note: This section is experimental and support for Vanilla JS is a work in progress.
|
||||
|
||||
The `dockview` package contains `ReactJS` wrappers for the core library.
|
||||
The core library is published as an independant package under the name `dockview-core` which you can install standalone.
|
||||
|
||||
> When using `dockview` there is no need to also install `dockview-core`.
|
||||
> `dockview-core` is a dependency of `dockview` and automatically installed during the installation process of `dockview` via `npm install dockview`.
|
||||
|
||||
<Container
|
||||
sandboxId="typescript/vanilla-dockview"
|
||||
injectVanillaJS={attachDockviewVanilla}
|
||||
/>
|
235
packages/docs/versioned_docs/version-1.9.0/components/gridview.mdx
vendored
Normal file
235
packages/docs/versioned_docs/version-1.9.0/components/gridview.mdx
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
---
|
||||
description: Gridview Documentation
|
||||
---
|
||||
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
import SimpleGridview from '@site/sandboxes/simple-gridview/src/app';
|
||||
import EditorGridview from '@site/sandboxes/editor-gridview/src/app';
|
||||
// import SimpleGridview from '@site/sandboxes/simple-gridview/src/app';
|
||||
import { EventsGridview } from '@site/src/components/gridview/events';
|
||||
// import IDEExample from '@site/sandboxes/ide-example/src/app';
|
||||
import Link from '@docusaurus/Link';
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
# Gridview
|
||||
|
||||
Gridview is a collection of nested splitviews and is the foundation for the [Dockview](./dockview) component.
|
||||
Gridview serves a purpose when you want only the nested splitviews with no tabs and no headers.
|
||||
|
||||
## Introduction
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="simple-gridview"
|
||||
react={SimpleGridview}
|
||||
/>
|
||||
|
||||
## GridviewReact Component
|
||||
|
||||
```tsx
|
||||
import { ReactGridview } from 'dockview';
|
||||
```
|
||||
|
||||
<DocRef declaration="IGridviewReactProps" />
|
||||
|
||||
## Gridview API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
<DocRef declaration="GridviewApi" />
|
||||
|
||||
## Gridview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
<DocRef declaration="GridviewPanelApi" />
|
||||
|
||||
## Resizing
|
||||
|
||||
### Panel Resizing
|
||||
|
||||
You can set the size of a panel using `props.api.setSize(...)`.
|
||||
|
||||
```tsx
|
||||
// it's mandatory to provide either a height or a width, providing both is optional
|
||||
props.api.setSize({
|
||||
height: 100,
|
||||
width: 200,
|
||||
});
|
||||
```
|
||||
|
||||
You can update any constraints on the panel. All parameters are optional.
|
||||
|
||||
```tsx
|
||||
props.api.setConstraints({
|
||||
minimumHeight: 100,
|
||||
maximumHeight: 1000
|
||||
minimumWidth: 100,
|
||||
maximumWidth: 1000
|
||||
});
|
||||
```
|
||||
|
||||
You can hide a panel by setting it's visibility to `false`. Hidden panels retain their size
|
||||
at the point of being hidden, if made visible again they will try to resize to the remembered size.
|
||||
|
||||
```tsx
|
||||
props.api.setVisible(false);
|
||||
```
|
||||
|
||||
## Panels
|
||||
|
||||
### Add Panel
|
||||
|
||||
Using the gridview API you can access the `addPanel` method which returns an instance of the created panel.
|
||||
The minimum method signature is:
|
||||
|
||||
```ts
|
||||
const panel = api.addPanel({
|
||||
id: 'my_unique_panel_id',
|
||||
component: 'my_component',
|
||||
});
|
||||
```
|
||||
|
||||
where `id` is the unique id of the panel and `component` is the implenentation which
|
||||
will be used to render the panel. You will have registered this using the `components` prop of the `GridviewReactComponent` component.
|
||||
|
||||
You can pass bounding constraints to limit the size of the panel.
|
||||
|
||||
```ts
|
||||
const panel = api.addPanel({
|
||||
id: 'my_unique_panel_id',
|
||||
component: 'my_component',
|
||||
minimumHeight: 100,
|
||||
maximumHeight: 1000,
|
||||
minimumWidth: 100,
|
||||
maximumWidth: 1000,
|
||||
});
|
||||
```
|
||||
|
||||
You can pass a `snap` parameter which will hide the panel when an attempt is made to move it beyond a minimum width or height if one exists.
|
||||
|
||||
```ts
|
||||
const panel = api.addPanel({
|
||||
id: 'my_unique_panel_id',
|
||||
component: 'my_component',
|
||||
minimumHeight: 100,
|
||||
snap: true,
|
||||
});
|
||||
```
|
||||
|
||||
You can pass a `priority` parameter which will keep the panel a certain priority when being resized. This is useful when you know you want this
|
||||
panel to always take the first available or last available space. The default is `LayoutPriority.Normal` which defers space allocations to the libraries discression.
|
||||
|
||||
```ts
|
||||
const panel = api.addPanel({
|
||||
id: 'my_unique_panel_id',
|
||||
component: 'my_component',
|
||||
minimumHeight: 100,
|
||||
priority: LayoutPriority.High,
|
||||
});
|
||||
```
|
||||
|
||||
You can pass properties to the panel using the `params` key.
|
||||
You can update these properties through the panels `api` object and its `updateParameters` method.
|
||||
|
||||
```ts
|
||||
const panel = api.addPanel({
|
||||
id: 'my_unique_panel_id',
|
||||
component: 'my_component',
|
||||
params: {
|
||||
myCustomKey: 'my_custom_value',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
panel.api.updateParameters({
|
||||
myCustomKey: 'my_custom_value',
|
||||
myOtherCustomKey: 'my_other_custom_key',
|
||||
});
|
||||
```
|
||||
|
||||
> Note `updateParameters` does not accept partial parameter updates, you should call it with the entire set of parameters
|
||||
> you want the panel to receive.
|
||||
|
||||
Finally `addPanel` accepts a `position` object which tells dockview where to place the panel.
|
||||
|
||||
- This object accepts a `referencePanel` which can be the associated id as a string
|
||||
or the panel object reference.
|
||||
- This object accepts a `direction` property which dictates where,
|
||||
relative to the provided reference the new panel will be placed.
|
||||
|
||||
> If a `referencePanel` is not passed then the `direction` will be treated as absolute.
|
||||
|
||||
> If no `direction` is provided the library will place the new panel in a pre-determined position.
|
||||
|
||||
```ts
|
||||
const panel = api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
const panel2 = api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
position: {
|
||||
referencePanel: panel1,
|
||||
direction: 'right',
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
> Note `updateParameters` does not accept partial parameter updates, you should call it with the entire set of parameters
|
||||
> you want the panel to receive.
|
||||
|
||||
## Theme
|
||||
|
||||
As well as importing the `dockview` stylesheet you must provide a class-based theme somewhere in your application. For example.
|
||||
|
||||
```tsx
|
||||
// Providing a theme directly through the DockviewReact component props
|
||||
<GridviewReact className="dockview-theme-dark" />
|
||||
|
||||
// Providing a theme somewhere in the DOM tree
|
||||
<div className="dockview-theme-dark">
|
||||
<div>
|
||||
{/**... */}
|
||||
<GridviewReact />
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can find more details on theming <Link to="../theme">here</Link>.
|
||||
|
||||
## Events
|
||||
|
||||
`GridviewReact` exposes a number of events that the developer can listen to and below is a simple example with a log panel showing those events that occur.
|
||||
|
||||
<EventsGridview />
|
||||
|
||||
## Complex Example
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={600}
|
||||
sandboxId="editor-gridview"
|
||||
react={EditorGridview}
|
||||
hideThemePicker={true}
|
||||
/>
|
228
packages/docs/versioned_docs/version-1.9.0/components/paneview.mdx
vendored
Normal file
228
packages/docs/versioned_docs/version-1.9.0/components/paneview.mdx
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
---
|
||||
description: Paneview Documentation
|
||||
---
|
||||
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
import SimplePaneview from '@site/sandboxes/simple-paneview/src/app';
|
||||
import { CustomHeaderPaneview } from '@site/src/components/paneview/customHeader';
|
||||
import { DragAndDropPaneview } from '@site/src/components/paneview/dragAndDrop';
|
||||
import { SideBySidePaneview } from '@site/src/components/paneview/sideBySide';
|
||||
import Link from '@docusaurus/Link';
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
# Paneview
|
||||
|
||||
A paneview is a collapsed collection of vertically stacked panels and panel headers.
|
||||
The panel header will always remain visible however the panel will only be visible when the panel is expanded.
|
||||
|
||||
:::info
|
||||
|
||||
Paneview panels can be re-ordered by dragging and dropping the panel headers.
|
||||
|
||||
:::
|
||||
|
||||
---
|
||||
|
||||
# Introduction
|
||||
|
||||
<MultiFrameworkContainer sandboxId="simple-paneview" react={SimplePaneview} />
|
||||
|
||||
```tsx title="Simple Paneview example"
|
||||
import {
|
||||
IPaneviewPanelProps,
|
||||
PaneviewReact,
|
||||
PaneviewReadyEvent,
|
||||
} from 'dockview';
|
||||
|
||||
const components = {
|
||||
default: (props: IPaneviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgb(60,60,60)',
|
||||
}}
|
||||
>
|
||||
{props.params.title}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
SimplePaneview = () => {
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
title: 'Panel 2',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
title: 'Panel 3',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<PaneviewReact
|
||||
components={components}
|
||||
headerComponents={headerComponents}
|
||||
onReady={onReady}
|
||||
className="dockview-theme-abyss"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## PaneviewReact Component
|
||||
|
||||
You can create a Paneview through the use of the `ReactPaneview` component.
|
||||
|
||||
```tsx
|
||||
import { ReactPaneview } from 'dockview';
|
||||
```
|
||||
|
||||
<DocRef declaration="IPaneviewReactProps" />
|
||||
|
||||
## Paneview API
|
||||
|
||||
The Paneview API is exposed both at the `onReady` event and on each panel through `props.containerApi`.
|
||||
Through this API you can control general features of the component and access all added panels.
|
||||
|
||||
```tsx title="Paneview API via Panel component"
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx title="Paneview API via the onReady callback"
|
||||
const onReady = (event: GridviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
<DocRef declaration="PaneviewApi" />
|
||||
|
||||
## Paneview Panel API
|
||||
|
||||
```tsx
|
||||
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
<DocRef declaration="PaneviewPanelApi" />
|
||||
|
||||
## Advanced Features
|
||||
|
||||
### Custom Header
|
||||
|
||||
You can provide a custom component to render an alternative header.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '400px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<CustomHeaderPaneview />
|
||||
</div>
|
||||
|
||||
You can provide a `headerComponent` option when creating a panel to tell the library to use a custom header component.
|
||||
|
||||
```tsx
|
||||
const onReady = (event: PaneviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
headerComponent: 'myHeaderComponent',
|
||||
params: {
|
||||
valueA: 'A',
|
||||
},
|
||||
title: 'Panel 1',
|
||||
});
|
||||
};
|
||||
```
|
||||
|
||||
This header must be defined in the collection of components provided to the `headerComponents` props for `ReactPaneivew`
|
||||
|
||||
```tsx
|
||||
import { IPaneviewPanelProps } from 'dockview';
|
||||
|
||||
const MyHeaderComponent = (props: IPaneviewPanelProps<{ title: string }>) => {
|
||||
const [expanded, setExpanded] = React.useState<boolean>(
|
||||
props.api.isExpanded
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const disposable = props.api.onDidExpansionChange((event) => {
|
||||
setExpanded(event.isExpanded);
|
||||
});
|
||||
|
||||
return () => {
|
||||
disposable.dispose();
|
||||
};
|
||||
}, []);
|
||||
|
||||
const onClick = () => {
|
||||
props.api.setExpanded(!expanded);
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
padding: '10px',
|
||||
height: '100%',
|
||||
backgroundColor: 'rgb(60,60,60)',
|
||||
}}
|
||||
>
|
||||
<a
|
||||
onClick={onClick}
|
||||
className={expanded ? 'expanded' : 'collapsed'}
|
||||
/>
|
||||
<span>{props.params.title}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const headerComponents = { myHeaderComponent: MyHeaderComponent };
|
||||
```
|
||||
|
||||
### Drag And Drop
|
||||
|
||||
If you provide the `PaneviewReact` component with the prop `onDidDrop` you will be able to interact with custom drop events.
|
||||
|
||||
<DragAndDropPaneview />
|
||||
|
||||
### Interactions
|
||||
|
||||
You can safely create multiple paneview instances within one page. They will not interact with each other by default.
|
||||
|
||||
If you wish to interact with the drop event from one paneview instance in another paneview instance you can implement the `showDndOverlay` and `onDidDrop` props on `PaneviewReact`.
|
||||
|
||||
As an example see how dragging a header from one control to another will only trigger an interactable event for the developer if the checkbox is enabled.
|
||||
|
||||
<SideBySidePaneview />
|
196
packages/docs/versioned_docs/version-1.9.0/components/splitview.mdx
vendored
Normal file
196
packages/docs/versioned_docs/version-1.9.0/components/splitview.mdx
vendored
Normal file
@ -0,0 +1,196 @@
|
||||
---
|
||||
description: Splitview Documentation
|
||||
---
|
||||
|
||||
import { SimpleSplitview } from '@site/src/components/simpleSplitview';
|
||||
import { SplitviewExample1 } from '@site/src/components/splitview/active';
|
||||
import Link from '@docusaurus/Link';
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
# Splitview
|
||||
|
||||
## Introduction
|
||||
|
||||
A Splitview is a collection of resizable horizontally or vertically stacked panels.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '100px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview />
|
||||
</div>
|
||||
|
||||
```tsx title="Simple Splitview example"
|
||||
import {
|
||||
ISplitviewPanelProps,
|
||||
Orientation,
|
||||
SplitviewReact,
|
||||
SplitviewReadyEvent,
|
||||
} from 'dockview';
|
||||
|
||||
const components = {
|
||||
default: (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
|
||||
},
|
||||
};
|
||||
|
||||
export const SimpleSplitview = () => {
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 1',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 2',
|
||||
},
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
params: {
|
||||
title: 'Panel 3',
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<SplitviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
orientation={Orientation.HORIZONTAL}
|
||||
className="dockview-theme-abyss"
|
||||
/>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## SplitviewReact Component
|
||||
|
||||
You can create a Splitview through the use of the `ReactSplitview` component.
|
||||
|
||||
```tsx
|
||||
import { ReactSplitview } from 'dockview';
|
||||
```
|
||||
|
||||
Using the `onReady` prop you can access to the component `api` and add panels either through deserialization or the individual addition of panels.
|
||||
|
||||
<DocRef declaration="ISplitviewReactProps" />
|
||||
|
||||
## Splitview API
|
||||
|
||||
The Splitview API is exposed both at the `onReady` event and on each panel through `props.containerApi`.
|
||||
Through this API you can control general features of the component and access all added panels.
|
||||
|
||||
```tsx title="Splitview API via Panel component"
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
// props.containerApi...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
```tsx title="Splitview API via the onReady callback"
|
||||
const onReady = (event: SplitviewReadyEvent) => {
|
||||
// event.api...
|
||||
};
|
||||
```
|
||||
|
||||
<DocRef declaration="SplitviewApi" />
|
||||
|
||||
## Splitview Panel API
|
||||
|
||||
The Splitview panel API is exposed on each panel containing actions and variables specific to that panel.
|
||||
|
||||
```tsx title="Splitview panel API via Panel component"
|
||||
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
|
||||
// props.api...
|
||||
|
||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
<DocRef declaration="SplitviewPanelApi" />
|
||||
|
||||
## Advanced Features
|
||||
|
||||
Listed below are some functionalities avalaible through both the panel and component APIs. The live demo shows examples of these in real-time.
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '200px',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SplitviewExample1 />
|
||||
</div>
|
||||
|
||||
### Visibility
|
||||
|
||||
A panels visibility can be controlled and monitored through the following code.
|
||||
A panel with visibility set to `false` will remain as a part of the components list of panels but will not be rendered.
|
||||
|
||||
```tsx
|
||||
const disposable = props.api.onDidVisibilityChange(({ isVisible }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setVisible(true);
|
||||
```
|
||||
|
||||
### Active
|
||||
|
||||
Only one panel in the `splitview` can be the active panel at any one time.
|
||||
Setting a panel as active will set all the others as inactive.
|
||||
A focused panel is always the active panel but an active panel is not always focused.
|
||||
|
||||
```tsx
|
||||
const disposable = props.api.onDidActiveChange(({ isActive }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setActive();
|
||||
```
|
||||
|
||||
### Contraints
|
||||
|
||||
When adding a panel you can specify pixel size contraints
|
||||
|
||||
```tsx
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
minimumSize: 100,
|
||||
maximumSize: 1000,
|
||||
});
|
||||
```
|
||||
|
||||
These contraints can be updated throughout the lifecycle of the `splitview` using the panel API
|
||||
|
||||
```tsx
|
||||
props.api.onDidConstraintsChange(({ maximumSize, minimumSize }) => {
|
||||
//
|
||||
});
|
||||
```
|
||||
|
||||
```tsx
|
||||
api.setConstraints({
|
||||
maximumSize: 200,
|
||||
minimumSize: 400,
|
||||
});
|
||||
```
|
54
packages/docs/versioned_docs/version-1.9.0/contributing.mdx
vendored
Normal file
54
packages/docs/versioned_docs/version-1.9.0/contributing.mdx
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
description: Contributing
|
||||
---
|
||||
|
||||
# Contributing
|
||||
|
||||
# Project description
|
||||
|
||||
Pre-requisites: Node >=18, Yarn
|
||||
|
||||
Dockview is a layout manager library designed to provide a complete layouting solution.
|
||||
It is written in plain TypeScript and can be used without any framework although
|
||||
an extensive React wrapper has always and will always be provided for those using the React framework.
|
||||
|
||||
The project is hosted on GitHub and developed within a Monorepo powered by [Lerna](https://github.com/lerna/lerna).
|
||||
It is developed using the `yarn` package manager since at the time of creation `yarn` was far superior when it came to managing monorepos.
|
||||
The Monorepo contains three packages:
|
||||
|
||||
#### packages/dockview-core
|
||||
|
||||
The core project is entirely written in plain TypeScript without any frameworks or dependencies and it's source-code can be found
|
||||
within the `dockview-core` package which is also published to npm.
|
||||
|
||||
#### packages/dockview
|
||||
|
||||
A complete collection of React components for use through the React framework to use dockview seamlessly
|
||||
and is published to npm. It depends explicitly on `dockview-core` so there is no need to additionally install `dockview-core`.
|
||||
|
||||
> Dockview was originally a React-only library which is why the React version maintains the name `dockview` after
|
||||
> splitting the core logic into a seperate package named `dockview-core`.
|
||||
|
||||
#### packages/docs
|
||||
|
||||
This package contains the code for this documentation website and examples hosted through **CodeSandbox**. It is **not** a published package on npm.
|
||||
|
||||
# Run the project locally
|
||||
|
||||
1. After you have cloned the project from GitHub run `yarn` at the root of the project which will install all project dependencies.
|
||||
2. In order build `packages/dockview-core` then `packages/dockview`.
|
||||
3. Run the docs website through `npm run start` in the `packages/docs` directory and go to _http://localhost:3000_ which
|
||||
will now be running the local copy of `dockview` that you have just built.
|
||||
|
||||
### Examples
|
||||
|
||||
All examples can be found under [**packages/docs/sandboxes**](https://github.com/mathuo/dockview/tree/master/packages/docs/sandboxes).
|
||||
Each example is an independently runnable example through **CodeSandbox**.
|
||||
Through the documentation you will see links to runnable **CodeSandbox** examples.
|
||||
|
||||
## FAQ
|
||||
|
||||
#### Are there any plans to publish wrapper libraries for other frameworks such as Angular and Vue?
|
||||
|
||||
Currently no but this is open for contributors to try.
|
88
packages/docs/versioned_docs/version-1.9.0/index.mdx
vendored
Normal file
88
packages/docs/versioned_docs/version-1.9.0/index.mdx
vendored
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
sidebar_position: 0
|
||||
description: A zero dependency layout manager supporting ReactJS and Vanilla TypeScript
|
||||
---
|
||||
|
||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||
|
||||
import { SimpleSplitview } from '@site/src/components/simpleSplitview';
|
||||
import { SimpleGridview } from '@site/src/components/simpleGridview';
|
||||
import { SimplePaneview } from '@site/src/components/simplePaneview';
|
||||
import DockviewDemo from '@site/sandboxes/demo-dockview/src/app';
|
||||
import Link from '@docusaurus/Link';
|
||||
|
||||
# Introduction
|
||||
|
||||
**dockview** is a zero dependency layout manager that supports tab, grids and splitviews.
|
||||
|
||||
## Quick start
|
||||
|
||||
`dockview` has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. To install `dockview` you can run:
|
||||
|
||||
```shell
|
||||
npm install dockview
|
||||
```
|
||||
|
||||
You must also import the dockview stylesheet found under [`dockview/dict/styles/dockview.css`](https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css),
|
||||
depending on your solution this might be:
|
||||
|
||||
```css
|
||||
@import './node_modules/dockview/dist/styles/dockview.css';
|
||||
```
|
||||
|
||||
There are 4 components you may want to use:
|
||||
|
||||
<Link to="./components/dockview">
|
||||
<h2>Dockview</h2>
|
||||
</Link>
|
||||
|
||||
<MultiFrameworkContainer
|
||||
height={500}
|
||||
sandboxId="demo-dockview"
|
||||
react={DockviewDemo}
|
||||
/>
|
||||
|
||||
<Link to="./components/splitview">
|
||||
<h2>Splitview</h2>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '100px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleSplitview />
|
||||
</div>
|
||||
|
||||
<Link to="./components/gridview">
|
||||
<h2>Gridview</h2>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimpleGridview />
|
||||
</div>
|
||||
|
||||
<Link to="./components/paneview">
|
||||
<h2>Paneview</h2>
|
||||
</Link>
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<SimplePaneview />
|
||||
</div>
|
@ -1,29 +1,31 @@
|
||||
---
|
||||
sidebar_position: 3
|
||||
sidebar_position: 1
|
||||
description: Theming Dockview Components
|
||||
---
|
||||
|
||||
import { CustomCSSDockview } from '@site/src/components/dockview/customCss';
|
||||
|
||||
# Theme
|
||||
|
||||
## Introduction
|
||||
|
||||
`dockview` requires some css to work correctly.
|
||||
The css is exported as one file under [`dockview/dict/styles/dockview.css`](https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css)
|
||||
and depending can be imported
|
||||
`dockview` requires some CSS to work correctly.
|
||||
The CSS is exported as one file under [`dockview/dict/styles/dockview.css`](https://unpkg.com/browse/dockview@latest/dist/styles/dockview.css)
|
||||
and should be imported at some point in your application
|
||||
|
||||
```css
|
||||
```css title="Example import with .css file"
|
||||
@import './node_modules/dockview/dist/styles/dockview.css';
|
||||
```
|
||||
|
||||
## Provided themes
|
||||
|
||||
The following are provided as classes that you can attached to your components for themeing
|
||||
`dockview` comes with a number of themes which are all CSS classes and can be found [here](https://github.com/mathuo/dockview/blob/master/packages/dockview-core/src/theme.scss).
|
||||
To use a `dockview` theme the CSS must encapsulate the component. The current list of themes is:
|
||||
|
||||
- `.dockview-theme-light`
|
||||
- `.dockview-theme-dark`
|
||||
- `.dockview-theme-abyss`
|
||||
- `dockview-theme-dark`
|
||||
- `dockview-theme-light`
|
||||
- `dockview-theme-vs`
|
||||
- `dockview-theme-abyss`
|
||||
- `dockview-theme-dracula`
|
||||
- `dockview-theme-replit`
|
||||
|
||||
## Customizing Theme
|
||||
|
||||
@ -58,11 +60,16 @@ and are free to build your own themes based on these css properties.
|
||||
| | |
|
||||
| --dv-separator-border | |
|
||||
| --dv-paneview-header-border-color | |
|
||||
| | |
|
||||
| --dv-icon-hover-background-color | |
|
||||
| --dv-floating-box-shadow | |
|
||||
| --dv-active-sash-color | |
|
||||
| --dv-background-color | |
|
||||
|
||||
You can further customise the theme through adjusting class properties but this is up you.
|
||||
As an example if you wanted to add a bottom border to the tab container for an active group in the `DockviewReact` component you could write:
|
||||
For example if you wanted to add a bottom border to the tab container for an active group in the `DockviewReact` component you could write:
|
||||
|
||||
```css
|
||||
```css title="Additional CSS to show a bottom border on active groups"
|
||||
.groupview {
|
||||
&.active-group {
|
||||
> .tabs-and-actions-container {
|
||||
@ -76,14 +83,3 @@ As an example if you wanted to add a bottom border to the tab container for an a
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
<div
|
||||
style={{
|
||||
height: '300px',
|
||||
backgroundColor: 'rgb(30,30,30)',
|
||||
color: 'white',
|
||||
margin: '20px 0px',
|
||||
}}
|
||||
>
|
||||
<CustomCSSDockview />
|
||||
</div>
|
@ -1,4 +1,4 @@
|
||||
[
|
||||
"1.8.4",
|
||||
"1.7.6"
|
||||
"1.9.0",
|
||||
"1.8.4"
|
||||
]
|
||||
|
Loading…
Reference in New Issue
Block a user