Merge pull request #125 from mathuo/100-docs

chore: improve docs!
This commit is contained in:
mathuo 2022-05-29 16:49:59 +01:00 committed by GitHub
commit f563ae4fe4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 436 additions and 96 deletions

View File

@ -15,7 +15,7 @@
## ##
Please see the website: https://mathuo.github.io/dockview/docs Please see the website: https://dockview.dev
Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/ Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/

View File

@ -15,7 +15,7 @@
## ##
Please see the website: https://mathuo.github.io/dockview/docs Please see the website: https://dockview.dev
Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/ Want to inspect the latest deployment? Go to https://unpkg.com/browse/dockview@latest/

View File

@ -1,7 +0,0 @@
{
"label": "API",
"position": 2,
"link": {
"type": "generated-index"
}
}

View File

@ -0,0 +1,9 @@
{
"label": "Components",
"collapsible": true,
"collapsed": false,
"link": {
"type": "generated-index",
"title": "Components"
},
}

View File

@ -5,13 +5,14 @@ import {
} from '../../src/components/dockview/rendering'; } from '../../src/components/dockview/rendering';
import { DndDockview } from '../../src/components/dockview/dnd'; import { DndDockview } from '../../src/components/dockview/dnd';
import { EventsDockview } from '../../src/components/dockview/events'; import { EventsDockview } from '../../src/components/dockview/events';
import { ContextMenuDockview } from '../../src/components/dockview/contextMenu';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
# Dockview # Dockview
## Introduction ## Introduction
Dockview is an abstraction built on top of [Gridviews](/docs/api/gridview) where each view is a tabbed container. Dockview is an abstraction built on top of [Gridviews](/docs/api/gridview) where each view is a container of many tabbed panels.
<div <div
style={{ style={{
@ -24,16 +25,13 @@ Dockview is an abstraction built on top of [Gridviews](/docs/api/gridview) where
<SimpleDockview /> <SimpleDockview />
</div> </div>
```tsx
const panel = event.api.addPanel(...);
const anotherPanel = event.api.getPanel('somePanelid');
```
You can access the panels associated group through the `panel.group` variable. You can access the panels associated group through the `panel.group` variable.
The group will always be defined and will change if a panel is moved into another group. The group will always be defined and will change if a panel is moved into another group.
## DockviewReact Component ## DockviewReact Component
You can create a Dockview through the use of the `ReactDockview` component.
```tsx ```tsx
import { ReactDockview } from 'dockview'; import { ReactDockview } from 'dockview';
``` ```
@ -53,7 +51,10 @@ import { ReactDockview } from 'dockview';
## Dockview API ## Dockview API
```tsx The Dockview 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="Dockview API via Panel component"
const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
// props.containerApi... // props.containerApi...
@ -61,7 +62,7 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
}; };
``` ```
```tsx ```tsx title="Dockview API via the onReady callback"
const onReady = (event: DockviewReadyEvent) => { const onReady = (event: DockviewReadyEvent) => {
// event.api... // event.api...
}; };
@ -147,7 +148,7 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
### Locked group ### Locked group
Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group. Locking a group will disable all drop events for this group ensuring a user can not add additional panels to the group.
You can still add groups to a locked panel programatically using the api. You can still add groups to a locked panel programatically using the API.
```tsx ```tsx
panel.group.locked = true; panel.group.locked = true;
@ -163,7 +164,15 @@ panel.group.header.hidden = true;
### Context Menu ### Context Menu
import { ContextMenuDockview } from '../../src/components/dockview/contextMenu'; Since overriding the context menu is a such a common feature rather than defining a custom tab the `ReactDockview` component exposes the prop `onTabContextMenu`.
You can alternatively define a custom tab component for more granular control.
:::caution
The `onTabContextMenu` is intended to be removed in a future release to further simplify the library.
In the future you will be required to define a custom tab component to intercept the context menu events.
:::
<div <div
style={{ style={{

View File

@ -1,8 +1,21 @@
import { SimplePaneview } from '../../src/components/simplePaneview'; import { SimplePaneview } from '../../src/components/simplePaneview';
import { CustomHeaderPaneview } from '../../src/components/paneview/customHeader';
import { DragAndDropPaneview } from '../../src/components/paneview/dragAndDrop';
import Link from '@docusaurus/Link'; import Link from '@docusaurus/Link';
# Paneview # 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 # Introduction
<div <div
@ -16,8 +29,74 @@ import Link from '@docusaurus/Link';
<SimplePaneview /> <SimplePaneview />
</div> </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-dark"
/>
);
};
```
## PaneviewReact Component ## PaneviewReact Component
You can create a Paneview through the use of the `ReactPaneview` component.
```tsx ```tsx
import { ReactPaneview } from 'dockview'; import { ReactPaneview } from 'dockview';
``` ```
@ -34,7 +113,10 @@ import { ReactPaneview } from 'dockview';
## Paneview API ## Paneview API
```tsx 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 }>) => { const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
// props.containerApi... // props.containerApi...
@ -42,7 +124,7 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
}; };
``` ```
```tsx ```tsx title="Paneview API via the onReady callback"
const onReady = (event: GridviewReadyEvent) => { const onReady = (event: GridviewReadyEvent) => {
// event.api... // event.api...
}; };
@ -74,7 +156,7 @@ const onReady = (event: GridviewReadyEvent) => {
| toJSON | `(): SerializedPaneview` | <Link to="/docs/basics/#serialization">Serialization</Link> | | toJSON | `(): SerializedPaneview` | <Link to="/docs/basics/#serialization">Serialization</Link> |
| clear | `(): void` | Clears the current layout | | clear | `(): void` | Clears the current layout |
## Gridview Panel API ## Paneview Panel API
```tsx ```tsx
const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
@ -108,8 +190,20 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
### Custom Header ### Custom Header
The above example shows the default header and will render the `title` along with a small icon to indicate a collapsed or expanded state. You can provide a custom component to render an alternative header.
You can provide a custom 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 ```tsx
const onReady = (event: PaneviewReadyEvent) => { const onReady = (event: PaneviewReadyEvent) => {
@ -125,27 +219,12 @@ const onReady = (event: PaneviewReadyEvent) => {
}; };
``` ```
The above example shows the default header and will render the `title` along with a small icon to indicate a collapsed or expanded state. This header must be defined in the collection of components provided to the `headerComponents` props for `ReactPaneivew`
You can provide a custom header:
```tsx ```tsx
const onReady = (event: PaneviewReadyEvent) => { import { IPaneviewPanelProps } from 'dockview';
event.api.addPanel({
id: 'panel_1',
component: 'default',
headerComponent: 'myHeaderComponent',
params: {
valueA: 'A',
},
title: 'Panel 1',
});
};
```
You can define a header component and listen to the expanded state to update the component accordingly. const MyHeaderComponent = (props: IPaneviewPanelProps<{ title: string }>) => {
```tsx
const CustomHeader = (props: IPaneviewPanelProps) => {
const [expanded, setExpanded] = React.useState<boolean>( const [expanded, setExpanded] = React.useState<boolean>(
props.api.isExpanded props.api.isExpanded
); );
@ -165,7 +244,13 @@ const CustomHeader = (props: IPaneviewPanelProps) => {
}; };
return ( return (
<div> <div
style={{
padding: '10px',
height: '100%',
backgroundColor: 'rgb(60,60,60)',
}}
>
<a <a
onClick={onClick} onClick={onClick}
className={expanded ? 'expanded' : 'collapsed'} className={expanded ? 'expanded' : 'collapsed'}
@ -174,12 +259,12 @@ const CustomHeader = (props: IPaneviewPanelProps) => {
</div> </div>
); );
}; };
```
You should provide a value for the `headerComponents` React prop. const headerComponents = { myHeaderComponent: MyHeaderComponent };
```tsx
const headerComponents = { myHeaderComponent: CustomHeader };
``` ```
### Drag And Drop ### Drag And Drop
If you provide the `PaneviewReact` component with the prop `onDidDrop` you will be able to interact with custom drop events.
<DragAndDropPaneview />

View File

@ -6,9 +6,7 @@ import Link from '@docusaurus/Link';
## Introduction ## Introduction
A Splitview is a collection resizable horizontally or vertically stacked panels. A Splitview is a collection of resizable horizontally or vertically stacked panels.
The Splitview exposes a component level API through the `onReady` event and through the `props.containerApi` variable on the panel props.
A panel level API is exposed on each panel through it's props as `props.api`.
<div <div
style={{ style={{
@ -81,7 +79,7 @@ You can create a Splitview through the use of the `ReactSplitview` component.
import { ReactSplitview } from 'dockview'; import { ReactSplitview } from 'dockview';
``` ```
Using the `onReady` prop you can access to the component `api` and add panels either through deserialization or indivial addition of panels. 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 | | Property | Type | Optional | Default | Description |
| ------------------- | -------------------------------------- | -------- | ------------------------ | --------------------------------------------------------------------------- | | ------------------- | -------------------------------------- | -------- | ------------------------ | --------------------------------------------------------------------------- |
@ -96,6 +94,7 @@ Using the `onReady` prop you can access to the component `api` and add panels ei
## Splitview API ## Splitview API
The Splitview API is exposed both at the `onReady` event and on each panel through `props.containerApi`. 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" ```tsx title="Splitview API via Panel component"
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => { const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
@ -139,7 +138,7 @@ const onReady = (event: SplitviewReadyEvent) => {
## Splitview Panel API ## Splitview Panel API
The Splitview panel API is exposed on each panel and contains actions and variables specific to that panel. 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" ```tsx title="Splitview panel API via Panel component"
const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => { const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
@ -172,7 +171,7 @@ const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
## Advanced Features ## Advanced Features
Listed below are some functionality avalaible to you through both the panel and component APIs. The live demo shows examples of these in real-time. Listed below are some functionalities avalaible through both the panel and component APIs. The live demo shows examples of these in real-time.
<div <div
style={{ style={{
@ -185,7 +184,7 @@ Listed below are some functionality avalaible to you through both the panel and
### Visibility ### Visibility
A panels visibility can be controlled and monitoring through the following code. 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. A panel with visibility set to `false` will remain as a part of the components list of panels but will not be rendered.
```tsx ```tsx

View File

@ -12,7 +12,7 @@ console.log(`isCI: ${process.env.CI}`);
const config = { const config = {
title: 'Dockview', title: 'Dockview',
tagline: 'Zero dependency layout manager for React', tagline: 'Zero dependency layout manager for React',
url: 'https://your-docusaurus-test-site.com', url: 'https://dockview.dev',
baseUrl: process.env.CI ? `/` : '/', baseUrl: process.env.CI ? `/` : '/',
onBrokenLinks: 'throw', onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn', onBrokenMarkdownLinks: 'warn',
@ -87,6 +87,28 @@ const config = {
themeConfig: themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */ /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({ ({
metadata: [
{
name: 'keywords',
content: [
'react',
'components',
'typescript',
'drag-and-drop',
'reactjs',
'layout',
'drag',
'drop',
'tabs',
'dock',
'docking',
'splitter',
'docking-library',
'layout-manager',
'docking-layout',
].join(' ,'),
},
],
navbar: { navbar: {
title: 'Dockview', title: 'Dockview',
logo: { logo: {

View File

@ -0,0 +1,28 @@
.tab {
.dockview-react-tab {
display: flex;
padding: 0px 8px;
align-items: center;
height: 100%;
.dockview-react-tab-title {
padding: 0px 8px;
flex-grow: 1;
}
.dockview-react-tab-action {
padding: 0px 4px;
&:hover {
border-radius: 2px;
background-color: rgba(90, 93, 94, 0.31);
}
}
}
&.dockview-inactive-tab:not(:hover) {
.dockview-react-tab-action {
visibility: hidden;
}
}
}

View File

@ -3,65 +3,48 @@ import {
DockviewReadyEvent, DockviewReadyEvent,
IDockviewPanelHeaderProps, IDockviewPanelHeaderProps,
IDockviewPanelProps, IDockviewPanelProps,
TabContextMenuEvent,
} from 'dockview'; } from 'dockview';
import * as React from 'react'; import * as React from 'react';
import './contextMenu.scss';
//
const components = { const components = {
default: (props: IDockviewPanelProps<{ title: string }>) => { default: (props: IDockviewPanelProps<{ title: string }>) => {
return <div style={{ padding: '20px' }}>{props.params.title}</div>; return <div style={{ padding: '20px' }}>{props.params.title}</div>;
}, },
}; };
const DefaultTab = (props: IDockviewPanelHeaderProps) => { const CustomTab = (
const [active, setActive] = React.useState<boolean>(props.api.isActive); props: IDockviewPanelHeaderProps & React.DOMAttributes<HTMLDivElement>
const [groupActive, setGroupActive] = React.useState<boolean>( ) => {
props.api.isGroupActive const onClose = React.useCallback(
(event: React.MouseEvent<HTMLSpanElement>) => {
event.stopPropagation();
props.api.close();
},
[props.api]
); );
React.useEffect(() => { const onClick = React.useCallback(() => {
const disposable1 = props.api.onDidActiveChange((e) => { props.api.setActive();
setActive(e.isActive);
});
const disposable2 = props.containerApi.onDidActiveGroupChange((e) => {
setGroupActive(props.api.isGroupActive);
});
return () => {
disposable1.dispose();
disposable2.dispose();
};
}, [props.api]); }, [props.api]);
return ( return (
<div <div onClick={onClick} className="dockview-react-tab">
style={{ <span className="dockview-react-tab-title">{props.api.title}</span>
display: 'flex', <span onClick={onClose} className="dockview-react-tab-action">
padding: '0px 8px',
alignItems: 'center',
height: '100%',
}}
>
<span style={{ padding: '0px 8px', flexGrow: 1 }}>
{props.api.title}
</span>
<span
className=""
onClick={() => props.api.setActive()}
style={{
display: 'flex',
alignItems: 'center',
paddingRight: '8px',
}}
>
{'✕'} {'✕'}
</span> </span>
</div> </div>
); );
}; };
const Test = (props: IDockviewPanelHeaderProps) => {
return <CustomTab {...props} />;
};
const tabComponents = { const tabComponents = {
default: DefaultTab, default: CustomTab,
}; };
export const ContextMenuDockview = () => { export const ContextMenuDockview = () => {
@ -104,12 +87,18 @@ export const ContextMenuDockview = () => {
}); });
}; };
const onContextMenu = (event: TabContextMenuEvent) => {
event.event.preventDefault();
alert(`Content appear event fired for panel ${event.panel.id}`);
};
return ( return (
<DockviewReact <DockviewReact
components={components} components={components}
tabComponents={tabComponents} tabComponents={tabComponents}
onReady={onReady} onReady={onReady}
className="dockview-theme-dark" className="dockview-theme-dark"
onTabContextMenu={onContextMenu}
/> />
); );
}; };

View File

@ -0,0 +1,104 @@
import {
IPaneviewPanelProps,
PaneviewReact,
PaneviewReadyEvent,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IPaneviewPanelProps<{ title: string }>) => {
return (
<div
style={{
padding: '10px',
height: '100%',
backgroundColor: 'rgb(60,60,60)',
}}
>
{props.params.title}
</div>
);
},
};
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: '0px 8px',
height: '100%',
backgroundColor: 'rgb(60,60,60)',
}}
>
<span>{`Custom header for ${props.title}`}</span>
<button onClick={onClick}>
{expanded ? 'Collapse' : 'Expand'}
</button>
</div>
);
};
const headerComponents = {
myHeaderComponent: MyHeaderComponent,
};
export const CustomHeaderPaneview = () => {
const onReady = (event: PaneviewReadyEvent) => {
event.api.addPanel({
id: 'panel_1',
component: 'default',
headerComponent: 'myHeaderComponent',
params: {
title: 'Panel 1',
},
title: 'Panel 1',
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
headerComponent: 'myHeaderComponent',
params: {
title: 'Panel 2',
},
title: 'Panel 2',
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
headerComponent: 'myHeaderComponent',
params: {
title: 'Panel 3',
},
title: 'Panel 3',
});
};
return (
<PaneviewReact
components={components}
headerComponents={headerComponents}
onReady={onReady}
className="dockview-theme-dark"
/>
);
};

View File

@ -0,0 +1,102 @@
import {
IPaneviewPanelProps,
PaneviewDropEvent,
PaneviewReact,
PaneviewReadyEvent,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IPaneviewPanelProps<{ title: string }>) => {
return (
<div
style={{
padding: '10px',
height: '100%',
backgroundColor: 'rgb(60,60,60)',
}}
>
{props.params.title}
</div>
);
},
};
export const DragAndDropPaneview = () => {
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',
});
};
const onDidDrop = (event: PaneviewDropEvent) => {
const index = event.api.panels.indexOf(event.panel);
event.api.addPanel({
id: 'panel_4',
component: 'default',
params: {
title: 'Panel 4',
},
title: 'Panel 4',
index,
});
};
return (
<div>
<div>
<div
style={{
backgroundColor: 'orange',
padding: '0px 8px',
borderRadius: '4px',
width: '100px',
cursor: 'pointer',
}}
draggable={true}
>
Drag me
</div>
</div>
<div
style={{
height: '300px',
backgroundColor: 'rgb(30,30,30)',
color: 'white',
margin: '20px 0px',
}}
>
<PaneviewReact
components={components}
onReady={onReady}
onDidDrop={onDidDrop}
className="dockview-theme-dark"
/>
</div>
</div>
);
};

View File

@ -31,8 +31,8 @@ export default function Home(): JSX.Element {
const { siteConfig } = useDocusaurusContext(); const { siteConfig } = useDocusaurusContext();
return ( return (
<Layout <Layout
title={`Hello from ${siteConfig.title}`} title={`${siteConfig.title}`}
description="Description will go into a meta tag in <head />" description="A zero dependency layout mananger for React."
> >
<HomepageHeader /> <HomepageHeader />
<main className="container"> <main className="container">