Merge pull request #353 from mathuo/352-documentation-improvements

352 documentation improvements
This commit is contained in:
mathuo 2023-10-06 20:02:52 +01:00 committed by GitHub
commit 3803bfa13a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 5300 additions and 2056 deletions

View File

@ -9,6 +9,7 @@
"/packages/docs/sandboxes/demo-dockview",
"/packages/docs/sandboxes/dnd-dockview",
"/packages/docs/sandboxes/dockview-app",
"/packages/docs/sandboxes/editor-gridview",
"/packages/docs/sandboxes/events-dockview",
"/packages/docs/sandboxes/externaldnd-dockview",
"/packages/docs/sandboxes/floatinggroup-dockview",
@ -26,6 +27,7 @@
"/packages/docs/sandboxes/resize-dockview",
"/packages/docs/sandboxes/resizecontainer-dockview",
"/packages/docs/sandboxes/simple-dockview",
"/packages/docs/sandboxes/simple-gridview",
"/packages/docs/sandboxes/simple-paneview",
"/packages/docs/sandboxes/tabheight-dockview",
"/packages/docs/sandboxes/updatetitle-dockview",

1
.gitignore vendored
View File

@ -14,3 +14,4 @@ test-report.xml
yarn-error.log
/build
/docs/
/generated/

View File

@ -21,7 +21,8 @@
"version-beta-build": "lerna version prerelease --preid beta",
"publish-app": "lerna publish",
"docs": "typedoc",
"package-docs": "node scripts/package-docs.js"
"package-docs": "node scripts/package-docs.js",
"generate-docs": "node scripts/docs.mjs"
},
"repository": {
"type": "git",
@ -68,5 +69,7 @@
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1"
},
"dependencies": {}
"dependencies": {
"@microsoft/tsdoc": "^0.14.2"
}
}

View File

@ -62,7 +62,6 @@
"postcss": "^8.4.21",
"rimraf": "^4.1.2",
"rollup": "^3.15.0",
"rollup-plugin-postcss": "^4.0.2",
"typedoc": "^0.23.25"
"rollup-plugin-postcss": "^4.0.2"
}
}

View File

@ -26,6 +26,10 @@ export * from './paneview/draggablePaneviewPanel';
export * from './dockview/components/panel/content';
export * from './dockview/components/tab/tab';
export {
TabDragEvent,
GroupDragEvent,
} from './dockview/components/titlebar/tabsContainer';
export * from './dockview/types';
export * from './dockview/dockviewGroupPanel';

View File

@ -0,0 +1,33 @@
---
slug: dockview-1.8.4-release
title: Dockview 1.8.4
tags: [release]
---
# Release Notes
Please reference to docs @ [dockview.dev](https://dockview.dev).
## 🚀 Features
- Optional header actions before tabs list [#338](https://github.com/mathuo/dockview/issues/338)
## 🛠 Miscs
- Bug: Recover from corrupted layouts gracefully [#341](https://github.com/mathuo/dockview/issues/341)
- Bug: Fix floating group resizing within nested tabs [#344](https://github.com/mathuo/dockview/issues/344)
- Bug: Progmatic resizing priority [#350](https://github.com/mathuo/dockview/issues/350)
- Bug: Incorrect disposal of deeply nested gridview [#356](https://github.com/mathuo/dockview/issues/356)
- Splitview separator stlye restored on deserialize step [#358](https://github.com/mathuo/dockview/issues/358)
- Docs: Additional Docs [#347](https://github.com/mathuo/dockview/issues/347)
- Docs: Additional Docs [#336](https://github.com/mathuo/dockview/issues/336)
- Docs: Additional Docs [#352](https://github.com/mathuo/dockview/issues/352)
## 🔥 Breaking changes

View File

@ -30,6 +30,8 @@ import DockviewLockedGroup from '@site/sandboxes/lockedgroup-dockview/src/app';
import IDEExample from '@site/sandboxes/ide-example/src/app';
import DockviewKeyboard from '@site/sandboxes/keyboard-dockview/src/app';
import { DocRef, Markdown } 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';
import { attach as attachTabHeightDockview } from '@site/sandboxes/javascript/tabheight-dockview/src/app';
@ -56,26 +58,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 | |
| onDidDrop | Event | Yes | false | |
| showDndOverlay | Event | Yes | false | |
| defaultTabComponent | object | Yes | | |
| leftHeaderActionsComponent | object | Yes | | |
| rightHeaderActionsComponent | object | Yes | | |
| prefixHeaderActionsComponent | 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
@ -96,44 +84,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` | |
| fromJSON | `(data: SerializedDockview): void` | |
| toJSON | `(): SerializedDockview` | |
| 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
@ -145,28 +108,15 @@ 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` | |
| 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
@ -476,7 +426,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.

View File

@ -2,24 +2,27 @@
description: Gridview Documentation
---
import { SimpleGridview } from '@site/src/components/simpleGridview';
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
<div
style={{
height: '300px',
backgroundColor: 'rgb(30,30,30)',
color: 'white',
margin: '20px 0px',
}}
>
<SimpleGridview />
</div>
<MultiFrameworkContainer
height={600}
sandboxId="simple-gridview"
react={SimpleGridview}
/>
## GridviewReact Component
@ -27,15 +30,7 @@ import Link from '@docusaurus/Link';
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 | |
| hideBorders | boolean | Yes | false | |
| className | string | Yes | '' | |
| disableAutoResizing | boolean | Yes | false | > |
<DocRef declaration="IGridviewReactProps" />
## Gridview API
@ -53,35 +48,7 @@ const onReady = (event: GridviewReadyEvent) => {
};
```
| 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` | |
| fromJSON | `(data: SerializedGridview): void` | |
| toJSON | `(): SerializedGridview` | |
| clear | `(): void` | Clears the current layout |
<DocRef declaration="GridviewApi" />
## Gridview Panel API
@ -93,28 +60,176 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
};
```
| 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` | |
<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}
/>

View File

@ -8,6 +8,7 @@ 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
@ -98,15 +99,7 @@ You can create a Paneview through the use of the `ReactPaneview` component.
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 | |
| disableDnd | boolean | Yes | false | |
| onDidDrop | Event | Yes | | |
<DocRef declaration="IPaneviewReactProps" />
## Paneview API
@ -127,31 +120,7 @@ const onReady = (event: GridviewReadyEvent) => {
};
```
| 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` | |
| fromJSON | `(data: SerializedPaneview): void` | |
| toJSON | `(): SerializedPaneview` | |
| clear | `(): void` | Clears the current layout |
<DocRef declaration="PaneviewApi" />
## Paneview Panel API
@ -163,25 +132,7 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => {
};
```
| 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` | |
<DocRef declaration="PaneviewPanelApi" />
## Advanced Features

View File

@ -5,6 +5,7 @@ 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
@ -85,15 +86,7 @@ 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` | |
| hideBorders | `boolean` | Yes | `false` | Hide the borders between panels |
| className | `string` | Yes | `''` | Attaches a classname |
| disableAutoResizing | `boolean` | Yes | `false` | |
<DocRef declaration="ISplitviewReactProps" />
## Splitview API
@ -114,31 +107,7 @@ const onReady = (event: SplitviewReadyEvent) => {
};
```
| 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` | |
| fromJSON | `(data: SerializedSplitview): void` | |
| toJSON | `(): SerializedSplitview` | |
| clear | `(): void` | Clears the current layout |
<DocRef declaration="SplitviewApi" />
## Splitview Panel API
@ -152,26 +121,7 @@ const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => {
};
```
| 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` | |
<DocRef declaration="SplitviewPanelApi" />
## Advanced Features

View File

@ -60,6 +60,11 @@ 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.
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:

View File

@ -1,8 +1,9 @@
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require('prism-react-renderer/themes/github');
const darkCodeTheme = require('prism-react-renderer/themes/dracula');
const lightCodeTheme = require('prism-react-renderer/themes/nightOwlLight');
// const lightCodeTheme = require('prism-react-renderer/themes/dracula');
const darkCodeTheme = require('prism-react-renderer/themes/vsDark');
const path = require('path');
@ -206,7 +207,7 @@ const config = {
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ['java', 'markdown', 'latex'],
additionalLanguages: ['markdown', 'latex'],
magicComments: [
{
className: 'theme-code-block-highlighted-line',

View File

@ -15,11 +15,13 @@
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "^2.4.0",
"@docusaurus/module-type-aliases": "^2.4.0",
"@docusaurus/preset-classic": "^2.4.0",
"@docusaurus/core": "^2.4.3",
"@docusaurus/module-type-aliases": "^2.4.3",
"@docusaurus/preset-classic": "^2.4.3",
"@mdx-js/react": "^1.6.22",
"@minoru/react-dnd-treeview": "^3.4.3",
"@radix-ui/react-popover": "^1.0.7",
"@radix-ui/react-icons": "^1.3.0",
"axios": "^1.3.3",
"clsx": "^1.2.1",
"dockview": "^1.8.3",
@ -33,22 +35,13 @@
"xml2js": "^0.4.23"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "2.3.1",
"@tsconfig/docusaurus": "^1.0.6",
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"@types/uuid": "^9.0.0",
"docusaurus-plugin-sass": "^0.2.3",
"fs-extra": "^11.1.0",
"install": "^0.13.0",
"sass": "^1.58.1",
"typescript": "^4.9.5"
},
"resolutions": {
"react": "17.0.2",
"react-dom": "17.0.2",
"@types/react": "17.0.35",
"@types/react-dom": "17.0.11"
"install": "^0.13.0"
},
"browserslist": {
"production": [

View File

@ -219,11 +219,13 @@ const DockviewDemo = (props: { theme?: string }) => {
id: 'panel_2',
component: 'default',
title: 'Panel 2',
position: { referencePanel: 'panel_1', direction: 'right' },
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
title: 'Panel 3',
position: { referencePanel: 'panel_2', direction: 'below' },
});
event.api.addPanel({
id: 'panel_4',
@ -235,42 +237,18 @@ const DockviewDemo = (props: { theme?: string }) => {
id: 'panel_5',
component: 'default',
title: 'Panel 5',
position: { referencePanel: 'panel_4', direction: 'within' },
position: { referencePanel: 'panel_3', direction: 'below' },
});
event.api.addPanel({
id: 'panel_6',
component: 'default',
title: 'Panel 6',
position: { referencePanel: 'panel_4', direction: 'below' },
});
event.api.addPanel({
id: 'panel_7',
component: 'default',
title: 'Panel 7',
position: { referencePanel: 'panel_6', direction: 'right' },
});
event.api.addPanel({
id: 'panel_8',
component: 'default',
title: 'Panel 8',
position: { referencePanel: 'panel_7', direction: 'within' },
});
event.api.addPanel({
id: 'panel_9',
component: 'default',
title: 'Panel 9',
floating: { width: 450, height: 250 },
});
event.api.addPanel({
id: 'panel_10',
component: 'default',
title: 'Panel 10',
position: { referencePanel: 'panel_9' },
position: { referencePanel: 'panel_3', direction: 'right' },
});
event.api.getPanel('panel_1')!.api.setActive();
console.log(event.api.toJSON());
};
return (

View File

@ -0,0 +1,32 @@
{
"name": "editor-gridview",
"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"
]
}

View File

@ -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>

View File

@ -0,0 +1,3 @@
.simple-gridview-example {
--dv-active-sash-color: #007acc;
}

View File

@ -0,0 +1,213 @@
import {
GridviewApi,
GridviewReact,
GridviewReadyEvent,
IGridviewPanelProps,
LayoutPriority,
Orientation,
SerializedGridviewComponent,
} from 'dockview';
import * as React from 'react';
import './app.scss';
const components = {
default: (props: IGridviewPanelProps<{ title: string }>) => {
return (
<div style={{ padding: '20px', color: 'white' }}>
{props.params.title}
</div>
);
},
header: (props: IGridviewPanelProps) => {
return (
<div style={{ backgroundColor: '#3C3C3C', height: '100%' }}></div>
);
},
footer: (props: IGridviewPanelProps) => {
return (
<div style={{ backgroundColor: '#007ACC', height: '100%' }}></div>
);
},
sidebar: (props: IGridviewPanelProps) => {
return (
<div style={{ backgroundColor: '#333333', height: '100%' }}></div>
);
},
'left-expander': (props: IGridviewPanelProps) => {
return (
<div style={{ backgroundColor: '#252526', height: '100%' }}></div>
);
},
'right-expander': (props: IGridviewPanelProps) => {
return (
<div style={{ backgroundColor: '#252526', height: '100%' }}></div>
);
},
main: (props: IGridviewPanelProps) => {
return (
<div
style={{
backgroundColor: '#1E1E1E',
height: '100%',
color: 'white',
display: 'flex',
justifyContent: 'center',
flexDirection: 'column',
fontSize: '0.8em',
padding: '10px',
}}
>
<div>{'This entire mockup is built using a gridview.'}</div>
<div>{`Press 'Ctrl+B' to toggle the left sidebar and 'Ctrl+Alt+B' to toggle the right sidebar or manually resize them.`}</div>
</div>
);
},
};
const serializedGridview: SerializedGridviewComponent = {
grid: {
root: {
type: 'branch',
data: [
{
type: 'leaf',
data: {
id: 'header-id',
component: 'header',
minimumHeight: 30,
maximumHeight: 30,
},
},
{
type: 'branch',
data: [
{
type: 'leaf',
data: {
id: 'sidebar-id',
component: 'sidebar',
minimumWidth: 30,
maximumWidth: 30,
},
},
{
type: 'leaf',
data: {
id: 'left-expander-id',
component: 'left-expander',
minimumWidth: 100,
snap: true,
},
},
{
type: 'leaf',
size: 100,
data: {
id: 'main-id',
component: 'main',
minimumWidth: 100,
minimumHeight: 100,
/**
* it's important to give the main content a high layout priority as we want
* the main layout to have priority when allocating new space
*/
priority: LayoutPriority.High,
},
},
{
type: 'leaf',
data: {
id: 'right-expander-id',
component: 'right-expander',
snap: true,
minimumWidth: 100,
},
},
],
},
{
type: 'leaf',
data: {
id: 'footer-id',
component: 'footer',
minimumHeight: 30,
maximumHeight: 30,
},
},
],
},
width: 1000,
height: 1000,
orientation: Orientation.VERTICAL,
},
};
export const App: React.FC = (props: { theme?: string }) => {
const [api, setApi] = React.useState<GridviewApi>();
const onReady = (event: GridviewReadyEvent) => {
event.api.fromJSON(serializedGridview);
setApi(event.api);
};
const onKeyDown = (event: React.KeyboardEvent) => {
if (!api) {
return;
}
console.log(event);
const leftExpander = api.getPanel('left-expander-id');
const rightExpander = api.getPanel('right-expander-id');
if (!leftExpander || !rightExpander) {
return;
}
switch (event.key) {
case 'b':
if (event.ctrlKey) {
if (event.altKey) {
// toggle right
rightExpander.api.setVisible(
!rightExpander.api.isVisible
);
if (rightExpander.api.width === 0) {
rightExpander.api.setSize({ width: 150 });
}
} else {
// toggle left
leftExpander.api.setVisible(
!leftExpander.api.isVisible
);
if (leftExpander.api.width === 0) {
leftExpander.api.setSize({ width: 150 });
}
}
}
}
};
return (
<div
tabIndex={-1}
className="simple-gridview-example"
onKeyDown={onKeyDown}
style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
>
<div style={{ flexGrow: 1 }}>
<GridviewReact
components={components}
onReady={onReady}
hideBorders={true}
orientation={Orientation.VERTICAL}
className={props.theme || 'dockview-theme-abyss'}
/>
</div>
</div>
);
};
export default App;

View 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>
);
}

View File

@ -0,0 +1,16 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View 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
}
}

View File

@ -22,16 +22,6 @@ const components = {
};
}, [props.api]);
React.useEffect(() => {
if (!active) {
return;
}
requestAnimationFrame(() => {
ref.current?.focus();
});
}, [active]);
return (
<div
className="keyboard-example-panel"
@ -52,15 +42,6 @@ const components = {
{' to nativgate between tabs.'}
</div>
<div style={{ padding: '10px 0px' }}>
<div>
{
'This input box should take focus when the panel is active to demonsrate managed focus'
}
<input ref={ref} type="text" />
</div>
</div>
<div>
<span>{'isPanelActive: '}</span>
<span>{active ? 'true' : 'false'}</span>

View File

@ -0,0 +1,32 @@
{
"name": "simple-gridview",
"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"
]
}

View File

@ -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>

View File

@ -0,0 +1,3 @@
.simple-gridview-example {
--dv-active-sash-color: #007acc;
}

View File

@ -0,0 +1,145 @@
import {
GridviewApi,
GridviewReact,
GridviewReadyEvent,
IGridviewPanelProps,
LayoutPriority,
Orientation,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IGridviewPanelProps<{ title: string }>) => {
return (
<div style={{ padding: '20px', color: 'white' }}>
{props.params.title}
</div>
);
},
};
export const App: React.FC = (props: { theme?: string }) => {
const [api, setApi] = React.useState<GridviewApi>();
const onReady = (event: GridviewReadyEvent) => {
const panel1 = event.api.addPanel({
id: 'panel_1',
component: 'default',
params: {
title: 'Panel 1',
},
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
params: {
title: 'Panel 2',
},
priority: LayoutPriority.High,
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
params: {
title: 'Panel 3',
},
});
event.api.addPanel({
id: 'panel_4',
component: 'default',
params: {
title: 'Panel 4',
},
position: { referencePanel: 'panel_2', direction: 'right' },
});
event.api.addPanel({
id: 'panel_5',
component: 'default',
params: {
title: 'Panel 5',
},
position: { referencePanel: 'panel_3', direction: 'right' },
});
event.api.addPanel({
id: 'panel_6',
component: 'default',
params: {
title: 'Panel 6',
},
position: { referencePanel: 'panel_5', direction: 'below' },
minimumWidth: 10,
});
event.api.addPanel({
id: 'panel_7',
component: 'default',
params: {
title: 'Panel 7',
},
position: { referencePanel: 'panel_6', direction: 'right' },
minimumWidth: 10,
});
event.api.addPanel({
id: 'panel_8',
component: 'default',
params: {
title: 'Panel 8',
},
position: { referencePanel: 'panel_6', direction: 'right' },
minimumWidth: 10,
});
setApi(event.api);
};
return (
<div
style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
>
<div>
<button
onClick={() => {
if (!api) {
return;
}
const panel = api.getPanel('panel_3');
if (!panel) {
return;
}
// panel.api.setVisible(!panel.api.isVisible);
if (panel.height === 0) {
panel.api.setSize({ height: 200 });
} else {
panel.api.setSize({ height: 0 });
}
}}
>
Resize
</button>
</div>
<div style={{ flexGrow: 1 }}>
<GridviewReact
components={components}
onReady={onReady}
// proportionalLayout={false}
orientation={Orientation.VERTICAL}
className={props.theme || 'dockview-theme-abyss'}
/>
</div>
</div>
);
};
export default App;

View 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>
);
}

View File

@ -0,0 +1,16 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View 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
}
}

View File

@ -32,7 +32,10 @@ const CloseButton = () =>
path: 'M22.5581 50.9938V30.1717L4.65116 19.869V31.7386L12.8536 36.4939V45.4198L22.5581 50.9938ZM27.2093 51.1162L37.0931 45.4226V36.2851L45.3488 31.501V19.7801L27.2093 30.2529V51.1162ZM42.9633 15.7867L33.4288 10.2615L25.0571 15.1193L16.6219 10.2567L7.00237 15.8557L24.9542 26.1842L42.9633 15.7867ZM0 43.4008V14.5498L24.9974 0L50 14.4887V43.3552L24.9969 57.7584L0 43.4008Z',
});
export const CodeSandboxButton = (props: { id: string }) => {
export const CodeSandboxButton = (props: {
id: string;
hideThemePicker?: boolean;
}) => {
const url = React.useMemo(() => {
if (!props.id) {
return '';
@ -42,7 +45,7 @@ export const CodeSandboxButton = (props: { id: string }) => {
return (
<>
<ThemePicker />
{!props.hideThemePicker && <ThemePicker />}
<span
className="codesandbox-button"
style={{ display: 'flex', alignItems: 'center' }}

View File

@ -149,6 +149,7 @@ export const MultiFrameworkContainer2 = (props: {
typescript?: (parent: HTMLElement) => { dispose: () => void };
sandboxId: string;
height?: number;
hideThemePicker?: boolean;
}) => {
const ref = React.useRef<HTMLDivElement>(null);
@ -266,7 +267,10 @@ export const MultiFrameworkContainer2 = (props: {
)}
</div>
<span style={{ flexGrow: 1 }} />
<CodeSandboxButton id={sandboxId} />
<CodeSandboxButton
id={sandboxId}
hideThemePicker={props.hideThemePicker}
/>
</div>
</>
);
@ -277,6 +281,7 @@ export const MultiFrameworkContainer = (props: {
typescript?: (parent: HTMLElement) => { dispose: () => void };
sandboxId: string;
height?: number;
hideThemePicker?: boolean;
}) => {
return (
<BrowserOnly>

View File

@ -0,0 +1,40 @@
.doc-ref-table {
width: 100%;
border-collapse: collapse;
display: table;
table-layout: fixed;
thead {
text-align: left;
background-color: inherit;
tr {
border: none;
}
}
overflow: hidden;
th,
td {
border: none;
padding: none;
text-align: left;
}
tr {
background-color: inherit !important;
}
.theme-code-block {
margin-bottom: unset;
pre {
box-sizing: border-box;
overflow: auto !important;
code {
padding: 8px;
}
}
}
}

View File

@ -0,0 +1,109 @@
import * as React from 'react';
import CodeBlock from '@theme/CodeBlock';
import './docRef.scss';
export interface DocRefProps {
declaration: string;
}
import docsJson from '../../../generated/api.output.json';
type DocsContent = { kind: string; text: string; tag?: string };
type DocsJson = {
[index: string]: Array<{
name: string;
signature: string;
comment?: {
summary?: DocsContent[];
blockTags?: Array<{ tag: string; content: DocsContent }>;
};
type: string;
}>;
};
export const Markdown = (props: { children: string }) => {
return <span>{props.children}</span>;
};
export const DocRef = (props: DocRefProps) => {
const docs = React.useMemo(
() => (docsJson as DocsJson)[props.declaration],
[props.declaration]
);
if (!docs) {
return null;
}
return (
<div>
<table className="doc-ref-table">
<tbody>
{docs.map((doc) => {
return (
<tr>
<th
style={{
width: '30%',
display: 'flex',
}}
>
<div
style={{
// width: '30%',
display: 'flex',
flexDirection: 'column',
alignItems: 'start',
}}
>
<h6
style={{
fontFamily: 'monospace',
fontSize: '1.2em',
}}
>
{doc.name}
</h6>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'start',
}}
>
{/* <span
style={{
fontSize: '0.75em',
color: 'var(--ifm-color-content-secondary)',
}}
>
{'Type'}
</span>
<span
style={{
color: 'var(--ifm-color-primary)',
}}
>
{doc.type}
</span> */}
</div>
</div>
</th>
<th
// style={{ width: '70%' }}
>
{/* <div>{'-'}</div> */}
<div>
<CodeBlock language="tsx">
{doc.signature}
</CodeBlock>
</div>
</th>
</tr>
);
})}
</tbody>
</table>
</div>
);
};

View File

@ -0,0 +1,171 @@
import { ReactPropDocsTable } from '../referenceTable';
import * as React from 'react';
export default () => (
<ReactPropDocsTable
title="Dockview API"
url="https://dockview.dev/typedocs/classes/dockview_core.DockviewApi.html"
data={[
{
property: 'id',
propertyDescription:
'The unique id associated with the dock instance',
type: 'string',
},
{
property: 'width',
type: 'number',
},
{
property: 'height',
type: 'number',
},
{
property: 'minimumHeight',
type: 'number',
},
{
property: 'maximumHeight',
type: 'number',
},
{
property: 'minimumWidth',
type: 'number',
},
{
property: 'maximumWidth',
type: 'number',
},
{
property: 'size',
propertyDescription: 'Total number of groups',
type: 'number',
},
{
property: 'totalPanels',
propertyDescription: 'Total number of panels',
type: 'number',
},
{
property: 'onDidActiveGroupChange',
type: 'Event<DockviewGroupPanel | undefined>',
},
{
property: 'onDidAddGroup',
type: 'Event<DockviewGroupPanel>',
},
{
property: 'onDidRemoveGroup',
type: 'Event<DockviewGroupPanel>',
},
{
property: 'onDidActivePanelChange',
type: 'Event<IDockviewPanel | undefined>',
},
{
property: 'onDidAddPanel',
type: 'Event<IDockviewPanel>',
},
{
property: 'onDidRemovePanel',
type: 'Event<IDockviewPanel>',
},
{
property: 'onDidLayoutFromJSON',
type: 'Event<void>',
},
{
property: 'onDidLayoutChange',
type: 'Event<void>',
},
{
property: 'onDidDrop',
type: 'Event<DockviewDropEvent>',
},
{
property: 'onWillDragGroup',
type: 'Event<GroupDragEvent>',
},
{
property: 'onWillDragPanel',
type: 'Event<TabDragEvent>',
},
{
property: 'panels',
type: 'IDockviewPanel[]',
},
{
property: 'groups',
type: 'DockviewGroupPanel[]',
},
{
property: 'activePanel',
type: 'IDockviewPanel | undefined',
},
{
property: 'activeGroup',
type: 'DockviewGroupPanel | undefined',
},
{
property: 'focus',
type: '(): void',
},
{
property: 'getPanel',
type: '(id: string): IDockviewPanel | undefined',
},
{
property: 'layout',
type: '(width: number, height: number): void',
},
{
property: 'addPanel',
type: 'addPanel(options: AddPanelOptions): void',
},
{
property: 'removePanel',
type: '(panel: IDockviewPanel): void',
},
{
property: 'addGroup',
type: '(options?: AddGroupOptions): DockviewGroupPanel',
},
{
property: 'moveToNext',
type: '(options?: MovementOptions): void',
},
{
property: 'moveToPrevious',
type: '(options?: MovementOptions): void',
},
{
property: 'closeAllGroups',
type: '(): void',
},
{
property: 'removeGroup',
type: '(group: IDockviewGroupPanel): void ',
},
{
property: 'getGroup',
type: '(id: string): DockviewGroupPanel | undefined',
},
{
property: 'addFloatingGroup',
type: '(item: IDockviewPanel | DockviewGroupPanel, coord?: { x: number, y: number }): void',
},
{
property: 'fromJSON',
type: '(data: SerializedDockview): void',
},
{
property: 'toJSON',
type: '(): SerializedDockview ',
},
{
property: 'clear',
type: '(): void',
},
]}
/>
);

View File

@ -0,0 +1,103 @@
import { ReactPropDocsTable } from '../referenceTable';
import * as React from 'react';
export default () => (
<ReactPropDocsTable
title="Dockview Panel API"
url="https://dockview.dev/typedocs/interfaces/dockview_core.DockviewPanelApi.html"
data={[
{
property: 'group',
type: 'DockviewGroupPanel',
},
{
property: 'isGroupActive',
type: 'boolean',
},
{
property: 'title',
type: 'string | undefined',
},
{
property: 'group',
type: 'DockviewGroupPanel',
},
{
property: 'onDidActiveGroupChange',
type: 'Event<void>',
},
{
property: 'onDidGroupChange',
type: 'Event<void>',
},
{
property: 'close',
type: '(): void',
},
{
property: 'setTitle',
type: '(title: string): void',
},
{
property: 'moveTo',
type: '(options: { group: DockviewGroupPanel, position?: Position, index?: number }): void',
},
{
property: 'setSize',
type: '(event: SizeEvent): void',
},
{
property: 'onDidDimensionsChange',
type: 'Event<PanelDimensionChangeEvent>',
},
{
property: 'onDidFocusChange',
type: 'Event<FocusEvent>',
},
{
property: 'onDidVisibilityChange',
type: 'Event<VisibilityEvent>',
},
{
property: 'onDidActiveChange',
type: 'Event<ActiveEvent>',
},
{
property: 'setVisible',
type: '(isVisible: boolean): void',
},
{
property: 'setActive',
type: '(): void',
},
{
property: 'updateParameters',
type: '(parameters: Parameters): void',
},
{
property: 'id',
type: 'string',
},
{
property: 'isFocused',
type: 'boolean',
},
{
property: 'isActive',
type: 'boolean',
},
{
property: 'isVisible',
type: 'boolean',
},
{
property: 'width',
type: 'number',
},
{
property: 'height',
type: 'number',
},
]}
/>
);

View File

@ -0,0 +1,64 @@
.ref-table {
font-size: 12px;
width: 100%;
border-collapse: collapse;
line-height: 20px;
button {
all: unset;
}
code {
padding: 0px 4px;
margin: 0px 4px;
}
.ref-table-icon {
cursor: pointer;
}
.ref-table-property {
width: 30%;
}
.ref-table-type {
width: 50%;
}
.ref-table-default {
width: 20%;
}
thead {
text-align: left;
background-color: inherit;
tr {
border: none;
}
}
th,
td {
border: none;
padding: none;
}
tr {
background-color: inherit !important;
}
}
.ref-table-popover {
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
box-shadow: hsl(206 22% 7% / 35%) 0px 10px 38px -10px,
hsl(206 22% 7% / 20%) 0px 10px 20px -15px;
animation-duration: 400ms;
animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
will-change: transform, opacity;
background-color: var(--ifm-background-surface-color);
color: var(--ifm-font-color-base);
}

View File

@ -1,42 +1,196 @@
import * as React from 'react';
import './referenceTable.scss';
export interface ReferenceProps {
props: {
prop: string;
title?: string;
url?: string;
data: {
property: string;
propertyDescription?: string;
default?: string;
type: string;
typeDescription?: string;
}[];
}
export const ReferenceTable = (props: ReferenceProps) => {
import * as Popover from '@radix-ui/react-popover';
import { InfoCircledIcon } from '@radix-ui/react-icons';
export const ReactPropDocsTable = (props: ReferenceProps) => {
return (
<table style={{ fontSize: '14px' }}>
<thead>
<tr>
<th>Property</th>
<th>Type</th>
<th>Default</th>
</tr>
</thead>
<tbody>
{props.props.map((property) => {
return (
<tr key={property.prop}>
<td>
<code>{property.prop}</code>
</td>
<td>
<code>{property.type}</code>
</td>
<td>
{property.default !== undefined && (
<code>{property.default}</code>
)}
</td>
</tr>
);
})}
</tbody>
</table>
<div>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
{props.title && <span>{props.title}</span>}
{props.url && (
<button>
<a href={props.url}>{'See API documentation'}</a>
</button>
)}
</div>
<table className="ref-table">
<thead>
<tr>
<th className="ref-table-property">Property</th>
<th className="ref-table-type">Type</th>
<th className="ref-table-default">Default</th>
</tr>
</thead>
<tbody>
{props.data.map((item) => {
return (
<tr key={item.property}>
<td className="ref-table-property">
<span
style={{
display: 'flex',
alignItems: 'center',
}}
>
<code>{item.property}</code>
{item.propertyDescription && (
<Popover.Root>
<Popover.Trigger>
<InfoCircledIcon className="ref-table-icon" />
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="ref-table-popover">
<div>
{
item.propertyDescription
}
</div>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
)}
</span>
</td>
<td className="ref-table-type">
<span
style={{
display: 'flex',
alignItems: 'center',
}}
>
<code>{item.type}</code>
{item.typeDescription && (
<Popover.Root>
<Popover.Trigger>
<InfoCircledIcon className="ref-table-icon" />
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="ref-table-popover">
<div>
<code>
{
item.typeDescription
}
</code>
</div>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
)}
</span>
</td>
<td className="ref-table-default">
{item.default ? (
<code>{item.default}</code>
) : (
<span>{'-'}</span>
)}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
};
export const ClassDocsTable = (props: ReferenceProps) => {
return (
<div>
<div>{props.title && <span>{props.title}</span>}</div>
<table className="ref-table">
<thead>
<tr>
<th className="ref-table-property">Property</th>
<th className="ref-table-type">Type</th>
<th className="ref-table-default">Default</th>
</tr>
</thead>
<tbody>
{props.data.map((item) => {
return (
<tr key={item.property}>
<td className="ref-table-property">
<span
style={{
display: 'flex',
alignItems: 'center',
}}
>
<code>{item.property}</code>
{item.propertyDescription && (
<Popover.Root>
<Popover.Trigger>
<InfoCircledIcon className="ref-table-icon" />
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="ref-table-popover">
<div>
{
item.propertyDescription
}
</div>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
)}
</span>
</td>
<td className="ref-table-type">
<span
style={{
display: 'flex',
alignItems: 'center',
}}
>
<code>{item.type}</code>
{item.typeDescription && (
<Popover.Root>
<Popover.Trigger>
<InfoCircledIcon className="ref-table-icon" />
</Popover.Trigger>
<Popover.Portal>
<Popover.Content className="ref-table-popover">
<div>
<code>
{
item.typeDescription
}
</code>
</div>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
)}
</span>
</td>
<td className="ref-table-default">
{item.default ? (
<code>{item.default}</code>
) : (
<span>{'-'}</span>
)}
</td>
</tr>
);
})}
</tbody>
</table>
</div>
);
};

File diff suppressed because it is too large Load Diff

View File

@ -3,35 +3,10 @@ import clsx from 'clsx';
import Layout from '@theme/Layout';
import Link from '@docusaurus/Link';
import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
import styles from './index.module.css';
import HomepageFeatures from '@site/src/components/HomepageFeatures';
import useBaseUrl from '@docusaurus/useBaseUrl';
import DockviewDemo from '@site/sandboxes/demo-dockview/src/app';
import DockviewDemo2 from '@site/sandboxes/dockview-app/src/app';
import { MultiFrameworkContainer } from '../components/ui/container';
import { BrowserHeader } from '../components/ui/browserHeader';
import './index.scss';
import { Introduction } from '../components/HomepageFeatures/introduction';
function HomepageHeader() {
const { siteConfig } = useDocusaurusContext();
return (
<header className={clsx('hero hero--primary', styles.heroBanner)}>
<div className="container">
<h1 className="hero__title">{siteConfig.title}</h1>
<p className="hero__subtitle">{siteConfig.tagline}</p>
<div className={styles.buttons}>
<Link
className="button button--secondary button--lg"
to={useBaseUrl('docs/')}
>
Get Started
</Link>
</div>
</div>
</header>
);
}
import styles from './index.module.css';
import './index.scss';
function HomepageHeader2() {
const { siteConfig } = useDocusaurusContext();
@ -74,6 +49,7 @@ export default function Home(): JSX.Element {
description={`${siteConfig.description}`}
>
<HomepageHeader2 />
<main className="container">
<Introduction />
</main>

View File

@ -1,7 +1,8 @@
{
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
}
// This file is not used in compilation. It is here just for a nice editor experience.
"extends": "@tsconfig/docusaurus/tsconfig.json",
"compilerOptions": {
"baseUrl": ".",
"resolveJsonModule": true
}
}

399
scripts/docs.mjs Normal file
View File

@ -0,0 +1,399 @@
import { execSync } from 'child_process';
import { readFileSync, existsSync, writeFileSync } from 'fs';
import { ReflectionKind } from 'typedoc';
/**
* #region inputs
*/
// typedoc output
const TYPEDOC_OUTPUT_FILE = './generated/typedoc.output.json';
// doc output
const API_OUTPUT_FILE = './packages/docs/src/generated/api.output.json';
// declarations to document (e.g. class names, interface names)
const DOCUMENT_LIST = [
// dockview
'DockviewApi',
'IDockviewReactProps',
'DockviewPanelApi',
// splitview
'SplitviewApi',
'ISplitviewReactProps',
'SplitviewPanelApi',
// gridview
'GridviewApi',
'IGridviewReactProps',
'GridviewPanelApi',
// paneview
'PaneviewApi',
'IPaneviewReactProps',
'PaneviewPanelApi',
];
const EXPORT_REMAPPING = {
Event: 'DockviewEvent',
Emitter: 'DockviewEmitter',
IDisposable: 'IDockviewDisposable',
MutableDisposable: 'DockviewMutableDisposable',
CompositeDisposable: 'DockviewCompositeDisposable',
};
const SKIP_DOC = ['Event'];
/**
* #region generating Typedoc output
*/
console.log('running docs');
if (!existsSync(TYPEDOC_OUTPUT_FILE)) {
execSync(
`typedoc --json ${TYPEDOC_OUTPUT_FILE}`,
(error, stdout, stderr) => {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
}
);
}
const content = JSON.parse(readFileSync(TYPEDOC_OUTPUT_FILE));
const dockviewCore = content.children.find(
(child) => child.name === 'dockview-core'
);
const dockview = content.children.find((child) => child.name === 'dockview');
const declarations = [dockviewCore, dockview]
.flatMap((item) =>
item.children.filter((child) => DOCUMENT_LIST.includes(child.name))
)
.filter(Boolean);
/**
* #region parsing of TypeDoc output
*/
function findType(type, packageName) {
if (EXPORT_REMAPPING[type]) {
type = EXPORT_REMAPPING[type];
}
const packageObject = content.children.find(
(child) => child.name === packageName
);
const typeObject = packageObject.children.find(
(child) => child.name === type
);
return getFunction(typeObject, [], { includeMetadata: false });
}
// minimal parsing logic, add cases as required
function getType(type, metadata, options) {
switch (type.type) {
case 'union':
return {
signature: [...type.types]
.reverse()
.map((t) => getType(t, metadata, options).signature)
.join(' | '),
};
case 'intrinsic':
return { signature: type.name };
case 'reference':
if (
options.includeMetadata &&
type.package &&
typeof type.target !== 'object'
) {
metadata.push({ name: type.name, package: type.package });
}
if (Array.isArray(type.typeArguments)) {
return {
signature: `${type.name}<${type.typeArguments
.map((typeArgument) => {
return getType(typeArgument, metadata, options)
.signature;
})
.join(', ')}>`,
};
}
return { signature: `${type.name}` };
case 'array':
return {
signature: `${
getType(type.elementType, metadata, options).signature
}[]`,
};
case 'reflection':
if (type.declaration.children) {
return {
signature: `{ ${type.declaration.children
.map(
(child) =>
`${child.name}: ${
getType(child.type, metadata, options)
.signature
}`
)
.join(', ')} }`,
};
}
if (type.declaration.signatures) {
if (type.declaration.signatures.length > 1) {
// code this case if it ever happens
throw new Error(`unhandled signatures.length > 1`);
}
if (type.declaration.signatures[0].parameters) {
let _parameters = '';
const { parameters } = type.declaration.signatures[0];
for (let i = 0; i < parameters.length; i++) {
const { type, name, flags, defaultValue } =
parameters[i];
const isOptional = flags.isOptional === true;
const { signature } = getType(type, metadata, options);
_parameters += `${name}${
isOptional ? '?' : ''
}: ${signature}${
defaultValue !== undefined
? ` = ${defaultValue}`
: ''
}`;
if (i !== parameters.length - 1) {
_parameters += ', ';
}
}
return {
signature: `(${_parameters}): ${
getType(
type.declaration.signatures[0].type,
metadata,
options
).signature
}`,
};
}
return {
signature: getType(
type.declaration.signatures[0].type,
metadata,
options
).signature,
};
}
if (type.declaration.indexSignature) {
let _parameters = '';
const { parameters } = type.declaration.indexSignature;
for (let i = 0; i < parameters.length; i++) {
const { type, name, flags, defaultValue } = parameters[i];
const isOptional = flags.isOptional === true;
_parameters += `${name}${isOptional ? '?' : ''}: ${
getType(type, metadata, options).signature
}${defaultValue !== undefined ? ` = ${defaultValue}` : ''}`;
if (i !== parameters.length - 1) {
_parameters += ', ';
}
}
return {
signature: `{ [${parameters}]: ${getType(
type.declaration.indexSignature.type,
metadata,
options
)}}`,
};
}
throw new Error('unhandled case');
case 'literal':
return { signature: `'${type.value}'` };
default:
throw new Error(`unhandled type ${type.type}`);
}
}
// minimal parsing logic, add cases as required
function getFunction(
method,
metadata = [],
options = { includeMetadata: true }
) {
switch (method.kind) {
case ReflectionKind.Accessor: {
const { getSignature, name } = method;
const { type, comment } = getSignature;
const metadata = [];
const { signature } = getType(type, metadata, options);
return {
name,
signature,
comment,
type: 'accessor',
metadata: metadata.length > 0 ? metadata : undefined,
};
}
case ReflectionKind.Property: {
const { type, name, comment } = method;
const metadata = [];
const { signature } = getType(type, metadata, options);
return {
name,
signature,
comment,
type: 'property',
metadata: metadata.length > 0 ? metadata : undefined,
};
}
case ReflectionKind.Interface: {
const { type, name, comment, children } = method;
let signature = `interface ${name} {`;
if (children) {
for (const child of children) {
signature += `\n\t${
child.flags.isReadonly ? 'readonly ' : ''
}${child.name}: ${
getFunction(child, metadata, options).signature
};`;
}
}
signature += `\n}`;
return {
name,
signature,
comment,
type: 'interface',
metadata: metadata.length > 0 ? metadata : undefined,
};
}
case ReflectionKind.Method: {
const { signatures, comment } = method;
if (signatures.length > 1) {
throw new Error(`signatures.length > 1`);
}
const { name, parameters, type, typeParameter } = signatures[0];
let _typeParameter = '';
if (Array.isArray(typeParameter)) {
for (let i = 0; i < typeParameter.length; i++) {
const item = typeParameter[i];
const { signature } = getType(item.type, metadata, options);
_typeParameter += `<${item.name}`;
if (item.type) {
_typeParameter += ` extends ${signature}`;
}
if (item.default) {
_typeParameter += ` = ${
getType(item.default, metadata, options).signature
}`;
}
_typeParameter += `>`;
if (i !== typeParameter.length - 1) {
_typeParameter += ', ';
}
}
}
let _parameters = '';
if (Array.isArray(parameters)) {
for (let i = 0; i < parameters.length; i++) {
const { type, name, flags, defaultValue } = parameters[i];
const isOptional = flags.isOptional === true;
const { signature } = getType(type, metadata, options);
_parameters += `${name}${
isOptional ? '?' : ''
}: ${signature}${
defaultValue !== undefined ? ` = ${defaultValue}` : ''
}`;
if (i !== parameters.length - 1) {
_parameters += ', ';
}
}
}
return {
name,
comment,
signature: `${_typeParameter}(${_parameters}): ${
getType(type, metadata, options).signature
}`,
type: 'method',
metadata: metadata.length > 0 ? metadata : undefined,
};
}
}
}
function createDocument(declarations) {
const documentation = {};
for (const declaration of declarations) {
const { children, name } = declaration;
documentation[name] = [];
for (const child of children) {
try {
const { flags } = child;
if (flags.isPrivate) {
continue;
}
const documentationPart = getFunction(child, [], {
includeMetadata: false,
});
if (documentationPart) {
if (documentationPart.metadata) {
documentationPart.metadata = documentationPart.metadata
.filter(({ name }) => !SKIP_DOC.includes(name))
.map((item) => {
return findType(item.name, item.package);
});
}
documentation[name].push(documentationPart);
}
} catch (err) {
console.error('error', err, child);
process.exit(-1);
}
}
}
return documentation;
}
const documentation = createDocument(declarations);
writeFileSync(API_OUTPUT_FILE, JSON.stringify(documentation, null, 4));

3679
yarn.lock

File diff suppressed because it is too large Load Diff