diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml index 8c2940ca5..11c1bcc85 100644 --- a/.github/workflows/deploy-docs.yml +++ b/.github/workflows/deploy-docs.yml @@ -4,8 +4,6 @@ on: schedule: - cron: '0 3 * * *' # every day at 3 am UTC -# on: [push] - jobs: deploy-nightly-demo-app: runs-on: ubuntu-latest @@ -28,11 +26,13 @@ jobs: ${{ runner.os }}-node- - run: yarn install - working-directory: docs + - run: lerna bootstrap - run: yarn build - working-directory: docs + working-directory: packages/dockview + - run: yarn build + working-directory: packages/docs - run: npm run deploy-docs - working-directory: docs + working-directory: packages/docs - name: Deploy 🚀 uses: JamesIves/github-pages-deploy-action@3.7.1 with: diff --git a/README.md b/README.md index 1983f0c99..214dc0e75 100644 --- a/README.md +++ b/README.md @@ -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/ diff --git a/packages/dockview/README.md b/packages/dockview/README.md index 1983f0c99..214dc0e75 100644 --- a/packages/dockview/README.md +++ b/packages/dockview/README.md @@ -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/ diff --git a/packages/docs/docs/api/_category_.json b/packages/docs/docs/api/_category_.json deleted file mode 100644 index 234c2c6d5..000000000 --- a/packages/docs/docs/api/_category_.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "label": "API", - "position": 2, - "link": { - "type": "generated-index" - } -} diff --git a/packages/docs/docs/basics.mdx b/packages/docs/docs/basics.mdx index 2ad80bb6d..2cadf65bf 100644 --- a/packages/docs/docs/basics.mdx +++ b/packages/docs/docs/basics.mdx @@ -2,8 +2,8 @@ sidebar_position: 1 --- -import { SimpleSplitview } from '../src/components/simpleSplitview'; -import { SimpleSplitview2 } from '../src/components/simpleSplitview2'; +import { SimpleSplitview } from '@site/src/components/simpleSplitview'; +import { SimpleSplitview2 } from '@site/src/components/simpleSplitview2'; # Basics diff --git a/packages/docs/docs/components/_category_.json b/packages/docs/docs/components/_category_.json new file mode 100644 index 000000000..1cdf26b6f --- /dev/null +++ b/packages/docs/docs/components/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Components", + "collapsible": true, + "collapsed": false, + "link": { + "type": "generated-index", + "title": "Components" + }, +} diff --git a/packages/docs/docs/api/dockview.mdx b/packages/docs/docs/components/dockview.mdx similarity index 85% rename from packages/docs/docs/api/dockview.mdx rename to packages/docs/docs/components/dockview.mdx index dc00eb9df..b2e7e5d47 100644 --- a/packages/docs/docs/api/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -1,17 +1,18 @@ -import { SimpleDockview } from '../../src/components/simpleDockview'; +import { SimpleDockview } from '@site/src/components/simpleDockview'; import { RenderingDockview, Checkbox, -} from '../../src/components/dockview/rendering'; -import { DndDockview } from '../../src/components/dockview/dnd'; -import { EventsDockview } from '../../src/components/dockview/events'; +} from '@site/src/components/dockview/rendering'; +import { DndDockview } from '@site/src/components/dockview/dnd'; +import { EventsDockview } from '@site/src/components/dockview/events'; +import { ContextMenuDockview } from '@site/src/components/dockview/contextMenu'; import Link from '@docusaurus/Link'; # Dockview ## 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](./gridview) where each view is a container of many tabbed panels.
-```tsx -const panel = event.api.addPanel(...); -const anotherPanel = event.api.getPanel('somePanelid'); -``` - 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. ## DockviewReact Component +You can create a Dockview through the use of the `ReactDockview` component. + ```tsx import { ReactDockview } 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 Auto Resizing | -| onTabContextMenu | Event | Yes | false | | -| onDidDrop | Event | Yes | false | | -| showDndOverlay | Event | Yes | false | | +| 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 Auto Resizing | +| onTabContextMenu | Event | Yes | false | | +| onDidDrop | Event | Yes | false | | +| showDndOverlay | Event | Yes | false | | ## 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 }>) => { // props.containerApi... @@ -61,52 +62,52 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { }; ``` -```tsx +```tsx title="Dockview API via the onReady callback" const onReady = (event: DockviewReadyEvent) => { // 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 | -| size | `number` | Number of Groups | -| panels | `IDockviewPanel[]` | | -| groups | `GroupPanel[]` | | -| activePanel | `IDockviewPanel \| undefined` | | -| activeGroup | `IDockviewPanel \| undefined` | | -| | | | -| onDidLayoutChange | `Event` | | -| onDidLayoutFromJSON | `Event` | | -| onDidAddGroup | `Event` | | -| onDidRemoveGroup | `Event` | | -| onDidActiveGroupChange | `Event` | | -| onDidAddPanel | `Event` | | -| onDidRemovePanel | `Event` | | -| onDidActivePanelChange | `Event` | | -| onDidDrop | `EventAuto Resizing | -| fromJSON | `(data: SerializedDockview): void` | Serialization | -| toJSON | `(): SerializedDockview` | Serialization | -| clear | `(): void` | Clears the current layout | +| 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` | | +| onDidLayoutFromJSON | `Event` | | +| onDidAddGroup | `Event` | | +| onDidRemoveGroup | `Event` | | +| onDidActiveGroupChange | `Event` | | +| onDidAddPanel | `Event` | | +| onDidRemovePanel | `Event` | | +| onDidActivePanelChange | `Event` | | +| onDidDrop | `EventAuto Resizing | +| fromJSON | `(data: SerializedDockview): void` | Serialization | +| toJSON | `(): SerializedDockview` | Serialization | +| clear | `(): void` | Clears the current layout | ## Dockview Panel API @@ -147,7 +148,7 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { ### Locked 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 panel.group.locked = true; @@ -163,7 +164,15 @@ panel.group.header.hidden = true; ### 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. + +:::
void | No | | | -| components | object | No | | | -| orientation | Orientation | Yes | Orientation.HORIZONTAL | | -| proportionalLayout | boolean | Yes | true | See Proportional layout | -| hideBorders | boolean | Yes | false | | -| className | string | Yes | '' | | -| disableAutoResizing | boolean | Yes | false | See Auto Resizing | +| Property | Type | Optional | Default | Description | +| ------------------- | ------------------------------------ | -------- | ---------------------- | ------------------------------------------------------------------------ | +| onReady | (event: SplitviewReadyEvent) => void | No | | | +| components | object | No | | | +| orientation | Orientation | Yes | Orientation.HORIZONTAL | | +| proportionalLayout | boolean | Yes | true | See Proportional layout | +| hideBorders | boolean | Yes | false | | +| className | string | Yes | '' | | +| disableAutoResizing | boolean | Yes | false | See Auto Resizing | ## Gridview API @@ -74,9 +74,9 @@ const onReady = (event: GridviewReadyEvent) => { | | | | | updateOptions | `(options:SplitviewComponentUpdateOptions): void` | | | focus | `(): void` | Focus the active panel, if exists | -| layout | `(width: number, height:number): void` | Auto Resizing | -| fromJSON | `(data: SerializedGridview): void` | Serialization | -| toJSON | `(): SerializedGridview` | Serialization | +| layout | `(width: number, height:number): void` | Auto Resizing | +| fromJSON | `(data: SerializedGridview): void` | Serialization | +| toJSON | `(): SerializedGridview` | Serialization | | clear | `(): void` | Clears the current layout | ## Gridview Panel API diff --git a/packages/docs/docs/api/paneview.mdx b/packages/docs/docs/components/paneview.mdx similarity index 59% rename from packages/docs/docs/api/paneview.mdx rename to packages/docs/docs/components/paneview.mdx index 5030c11dd..82ede4f23 100644 --- a/packages/docs/docs/api/paneview.mdx +++ b/packages/docs/docs/components/paneview.mdx @@ -1,8 +1,21 @@ -import { SimplePaneview } from '../../src/components/simplePaneview'; +import { SimplePaneview } from '@site/src/components/simplePaneview'; +import { CustomHeaderPaneview } from '@site/src/components/paneview/customHeader'; +import { DragAndDropPaneview } from '@site/src/components/paneview/dragAndDrop'; 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
+```tsx title="Simple Paneview example" +import { + IPaneviewPanelProps, + PaneviewReact, + PaneviewReadyEvent, +} from 'dockview'; + +const components = { + default: (props: IPaneviewPanelProps<{ title: string }>) => { + return ( +
+ {props.params.title} +
+ ); + }, +}; + +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 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 | Auto Resizing | -| disableDnd | boolean | Yes | false | | -| onDidDrop | Event | Yes | | | +| Property | Type | Optional | Default | Description | +| ------------------- | ------------------------------------ | -------- | ------- | -------------------------------------------------------- | +| onReady | (event: SplitviewReadyEvent) => void | No | | | +| components | object | No | | | +| headerComponents | object | Yes | | | +| className | string | Yes | '' | | +| disableAutoResizing | boolean | Yes | false | Auto Resizing | +| disableDnd | boolean | Yes | false | | +| onDidDrop | Event | Yes | | | ## 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 }>) => { // props.containerApi... @@ -42,39 +124,39 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { }; ``` -```tsx +```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` | Fires on layout change | -| onDidLayoutFromJSON | `Event` | Fires of layout change caused by a fromJSON deserialization call | -| onDidAddView | `Event` | Fires when a view is added | -| onDidRemoveView | `Event` | Fires when a view is removed | -| onDidDrop | `EventDrag and Drop) | -| | | | -| 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 Auto Resizing | -| fromJSON | `(data: SerializedPaneview): void` | Serialization | -| toJSON | `(): SerializedPaneview` | Serialization | -| clear | `(): void` | Clears the current layout | +| 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` | Fires on layout change | +| onDidLayoutFromJSON | `Event` | Fires of layout change caused by a fromJSON deserialization call | +| onDidAddView | `Event` | Fires when a view is added | +| onDidRemoveView | `Event` | Fires when a view is removed | +| onDidDrop | `EventDrag and Drop) | +| | | | +| 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 Auto Resizing | +| fromJSON | `(data: SerializedPaneview): void` | Serialization | +| toJSON | `(): SerializedPaneview` | Serialization | +| clear | `(): void` | Clears the current layout | -## Gridview Panel API +## Paneview Panel API ```tsx const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { @@ -108,8 +190,20 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { ### 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 header: +You can provide a custom component to render an alternative header. + +
+ +
+ +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) => { @@ -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. -You can provide a custom header: +This header must be defined in the collection of components provided to the `headerComponents` props for `ReactPaneivew` ```tsx -const onReady = (event: PaneviewReadyEvent) => { - event.api.addPanel({ - id: 'panel_1', - component: 'default', - headerComponent: 'myHeaderComponent', - params: { - valueA: 'A', - }, - title: 'Panel 1', - }); -}; -``` +import { IPaneviewPanelProps } from 'dockview'; -You can define a header component and listen to the expanded state to update the component accordingly. - -```tsx -const CustomHeader = (props: IPaneviewPanelProps) => { +const MyHeaderComponent = (props: IPaneviewPanelProps<{ title: string }>) => { const [expanded, setExpanded] = React.useState( props.api.isExpanded ); @@ -165,7 +244,13 @@ const CustomHeader = (props: IPaneviewPanelProps) => { }; return ( -
+ ); }; -``` -You should provide a value for the `headerComponents` React prop. - -```tsx -const headerComponents = { myHeaderComponent: CustomHeader }; +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. + + diff --git a/packages/docs/docs/api/splitview.mdx b/packages/docs/docs/components/splitview.mdx similarity index 83% rename from packages/docs/docs/api/splitview.mdx rename to packages/docs/docs/components/splitview.mdx index b6daf2c4f..5c6f0ad8a 100644 --- a/packages/docs/docs/api/splitview.mdx +++ b/packages/docs/docs/components/splitview.mdx @@ -1,14 +1,12 @@ -import { SimpleSplitview } from '../../src/components/simpleSplitview'; -import { SplitviewExample1 } from '../../src/components/splitview/active'; +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 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`. +A Splitview is a collection of resizable horizontally or vertically stacked panels.
void` | No | | Function | -| components | `Record` | No | | Panel renderers | -| orientation | `Orientation` | Yes | `Orientation.HORIZONTAL` | Orientation of the Splitview | -| proportionalLayout | `boolean` | Yes | `true` | See Proportional layout | -| hideBorders | `boolean` | Yes | `false` | Hide the borders between panels | -| className | `string` | Yes | `''` | Attaches a classname | -| disableAutoResizing | `boolean` | Yes | `false` | See Auto Resizing | +| Property | Type | Optional | Default | Description | +| ------------------- | -------------------------------------- | -------- | ------------------------ | ------------------------------------------------------------------------ | +| onReady | `(event: SplitviewReadyEvent) => void` | No | | Function | +| components | `Record` | No | | Panel renderers | +| orientation | `Orientation` | Yes | `Orientation.HORIZONTAL` | Orientation of the Splitview | +| proportionalLayout | `boolean` | Yes | `true` | See Proportional layout | +| hideBorders | `boolean` | Yes | `false` | Hide the borders between panels | +| className | `string` | Yes | `''` | Attaches a classname | +| disableAutoResizing | `boolean` | Yes | `false` | See Auto Resizing | ## 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 }>) => { @@ -132,14 +131,14 @@ const onReady = (event: SplitviewReadyEvent) => { | | | | updateOptions | `(options: SplitviewComponentUpdateOptions): void` | | | focus | `(): void` | Focus the active panel, if exists | -| layout | `(width: number, height:number): void` | See Auto Resizing | -| fromJSON | `(data: SerializedSplitview): void` | Serialization | -| toJSON | `(): SerializedSplitview` | Serialization | +| layout | `(width: number, height:number): void` | See Auto Resizing | +| fromJSON | `(data: SerializedSplitview): void` | Serialization | +| toJSON | `(): SerializedSplitview` | Serialization | | clear | `(): void` | Clears the current layout | ## 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" const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => { @@ -149,30 +148,30 @@ 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` | Fires when panel dimensions change | -| onDidFocusChange | `Event` | Fire when panel is focused and blurred | -| onDidVisibilityChange | `Event` | Fires when the panels visiblity property is changed (see Panel Visibility) | -| onDidActiveChange | `Event` | Fires when the panels active property is changed (see Active Panel) | -| onDidConstraintsChange | `onDidConstraintsChange: Event` | Fires when the panels size contrainsts change (see Panel Constraints) | -| | | | -| setVisible | `(isVisible: boolean): void` | | -| setActive | `(): void` | | -| | | | -| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | | -| setSize | `(event: PanelSizeEvent): void` | | +| 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` | Fires when panel dimensions change | +| onDidFocusChange | `Event` | Fire when panel is focused and blurred | +| onDidVisibilityChange | `Event` | Fires when the panels visiblity property is changed (see Panel Visibility) | +| onDidActiveChange | `Event` | Fires when the panels active property is changed (see Active Panel) | +| onDidConstraintsChange | `onDidConstraintsChange: Event` | Fires when the panels size contrainsts change (see Panel Constraints) | +| | | | +| setVisible | `(isVisible: boolean): void` | | +| setActive | `(): void` | | +| | | | +| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | | +| setSize | `(event: PanelSizeEvent): void` | | ## 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.
>; - description: JSX.Element; + title: string; + Svg: React.ComponentType>; + description: JSX.Element; }; const FeatureList: FeatureItem[] = [ - { - title: 'Easy to Use', - Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, - description: ( - <> - Docusaurus was designed from the ground up to be easily installed and - used to get your website up and running quickly. - - ), - }, - { - title: 'Focus on What Matters', - Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, - description: ( - <> - Docusaurus lets you focus on your docs, and we'll do the chores. Go - ahead and move your docs into the docs directory. - - ), - }, - { - title: 'Powered by React', - Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, - description: ( - <> - Extend or customize your website layout by reusing React. Docusaurus can - be extended while reusing the same header and footer. - - ), - }, + { + title: '', + Svg: require('@site/static/img/dockview_grid_2.svg').default, + description: ( + <> +
+

+ Serialziable Layouts +

+

+ Add and remove panels using the provided api or use the + serialization method to persist layouts. +

+
+
+

+ Customizable Theme +

+

+ Adjust a numbero of provided CSS Properties for a simple + change or target specific classes for a more customized + approach. +

+
+
+

+ Choose Your Control +

+

+ Choose from a simple splitview, a gridview, collapsable + panes or a full docking solution. Combine multiple for + more complex layouts. +

+
+ + ), + }, + { + title: '', + Svg: require('@site/static/img/dockview_splash_2.svg').default, + description: ( + <> +
+

Drag And Drop

+

+ Drag and Drop to position your layout and interact with + external drag events too. +

+
+
+

Zero Dependencies

+

+ Zero dependencies, that's all. +

+
+
+

+ Code Quality and Transparency +

+

+ All of the code is run through Sonarcloud Code Analyis + which along with the source code and high test coverage + can be viewed from the Github page. +

+
+ + ), + }, ]; -function Feature({title, Svg, description}: FeatureItem) { - return ( -
-
- -
-
-

{title}

-

{description}

-
-
- ); +function Feature({ title, Svg, description }: FeatureItem) { + return ( +
+ +
+

{title}

+

{description}

+
+
+ ); } export default function HomepageFeatures(): JSX.Element { - return ( -
-
-
- {FeatureList.map((props, idx) => ( - - ))} -
-
-
- ); + return ( +
+
+
+ {FeatureList.map((props, idx) => ( + + ))} +
+
+
+ ); } diff --git a/packages/docs/src/components/HomepageFeatures/styles.module.css b/packages/docs/src/components/HomepageFeatures/styles.module.css index b248eb2e5..edcd49b21 100644 --- a/packages/docs/src/components/HomepageFeatures/styles.module.css +++ b/packages/docs/src/components/HomepageFeatures/styles.module.css @@ -6,6 +6,6 @@ } .featureSvg { - height: 200px; - width: 200px; + height: 400px; + width: 400px; } diff --git a/packages/docs/src/components/dockview/api.ts b/packages/docs/src/components/dockview/api.ts new file mode 100644 index 000000000..713a4dda2 --- /dev/null +++ b/packages/docs/src/components/dockview/api.ts @@ -0,0 +1,72 @@ +import axios from 'axios'; + +const EXCHANGE_URL = 'https://api.exchange.coinbase.com'; + +const URL = 'https://api.coinbase.com/v2'; + +export interface Currency { + id: string; + name: string; + min_size: string; + max_precision: string; + status: string; + details: { + type: string; + symbol: string; + sort_order: number; + push_payment_methods: string[]; + display_name: string; + group_types: string[]; + }; +} + +export interface Price { + data: { base: string; currency: string; amount: string }; +} + +export async function allCurrencies(): Promise { + try { + const response = await axios.get( + `${EXCHANGE_URL}/currencies`, + { + headers: { Accept: 'application/json' }, + } + ); + + return response.data; + } catch (err) { + return []; + } +} + +export async function getCurrencies(id: string): Promise { + try { + const response = await axios.get( + `${EXCHANGE_URL}/currencies/${id}`, + { + headers: { Accept: 'application/json' }, + } + ); + + return response.data; + } catch (err) { + return null; + } +} + +export async function getPrice(base: string, quote: string) { + try { + const response = await axios.get( + `${URL}/prices/${base}-${quote}/buy`, + { + headers: { Accept: 'application/json' }, + } + ); + + return response.data; + } catch (err) { + return null; + } +} + +export const CURRENCIES = ['BTC', 'ETH', 'LTC']; diff --git a/packages/docs/src/components/dockview/contextMenu.scss b/packages/docs/src/components/dockview/contextMenu.scss new file mode 100644 index 000000000..cf8da3cf0 --- /dev/null +++ b/packages/docs/src/components/dockview/contextMenu.scss @@ -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; + } + } +} diff --git a/packages/docs/src/components/dockview/contextMenu.tsx b/packages/docs/src/components/dockview/contextMenu.tsx index cac359aa3..9cabb1d5a 100644 --- a/packages/docs/src/components/dockview/contextMenu.tsx +++ b/packages/docs/src/components/dockview/contextMenu.tsx @@ -3,65 +3,59 @@ import { DockviewReadyEvent, IDockviewPanelHeaderProps, IDockviewPanelProps, + TabContextMenuEvent, } from 'dockview'; import * as React from 'react'; +import './contextMenu.scss'; -// const components = { default: (props: IDockviewPanelProps<{ title: string }>) => { return
{props.params.title}
; }, }; -const DefaultTab = (props: IDockviewPanelHeaderProps) => { - const [active, setActive] = React.useState(props.api.isActive); - const [groupActive, setGroupActive] = React.useState( - props.api.isGroupActive +const CustomTab = ( + props: IDockviewPanelHeaderProps & React.DOMAttributes +) => { + const onClose = React.useCallback( + (event: React.MouseEvent) => { + event.stopPropagation(); + props.api.close(); + }, + [props.api] ); - React.useEffect(() => { - const disposable1 = props.api.onDidActiveChange((e) => { - setActive(e.isActive); - }); - const disposable2 = props.containerApi.onDidActiveGroupChange((e) => { - setGroupActive(props.api.isGroupActive); - }); + const onClick = React.useCallback( + (event: React.MouseEvent) => { + props.api.setActive(); - return () => { - disposable1.dispose(); - disposable2.dispose(); - }; - }, [props.api]); + if (props.onClick) { + props.onClick(event); + } + }, + [props.api, props.onClick] + ); return ( -
- - {props.api.title} - - props.api.setActive()} - style={{ - display: 'flex', - alignItems: 'center', - paddingRight: '8px', - }} - > +
+ {props.api.title} + {'✕'}
); }; +const Test = (props: IDockviewPanelHeaderProps) => { + const onContextMenu = (event: React.MouseEvent) => { + event.preventDefault(); + alert('hiya'); + }; + return ; +}; + const tabComponents = { - default: DefaultTab, + default: Test, }; export const ContextMenuDockview = () => { @@ -104,12 +98,18 @@ export const ContextMenuDockview = () => { }); }; + const onContextMenu = (event: TabContextMenuEvent) => { + event.event.preventDefault(); + alert(`Content appear event fired for panel ${event.panel.id}`); + }; + return ( ); }; diff --git a/packages/docs/src/components/dockview/demo.scss b/packages/docs/src/components/dockview/demo.scss new file mode 100644 index 000000000..9508b208e --- /dev/null +++ b/packages/docs/src/components/dockview/demo.scss @@ -0,0 +1,15 @@ +.news-panel { + height: 100%; + overflow: auto; + + .story { + display: flex; + flex-direction: column; + justify-content: start; + + .link { + color: white !important; + font-size: 11px; + } + } +} diff --git a/packages/docs/src/components/dockview/demo.tsx b/packages/docs/src/components/dockview/demo.tsx new file mode 100644 index 000000000..4683de1cc --- /dev/null +++ b/packages/docs/src/components/dockview/demo.tsx @@ -0,0 +1,186 @@ +import { + DockviewReact, + DockviewReadyEvent, + IDockviewPanelProps, +} from 'dockview'; +import * as React from 'react'; +import { CURRENCIES, Currency, getCurrencies, getPrice } from './api'; +import './demo.scss'; + +const CurrencyRow = (props: { currency: Currency }) => { + const [price, setPrice] = React.useState(); + + React.useEffect(() => { + getPrice(props.currency.id, 'USD').then((result) => { + setPrice(Number(result.data.amount)); + }); + }, [props.currency]); + + return ( + <> +
{props.currency.id}
+
{`${typeof price === 'number' ? `$${price}` : '-'}`}
+ + ); +}; + +const Currencies = () => { + const [currencies, setCurrencies] = React.useState([]); + + React.useEffect(() => { + Promise.all(CURRENCIES.map(getCurrencies)).then((results) => { + setCurrencies(results.filter(Boolean)); + }); + }, []); + + return ( +
+
+ {currencies.map((currency) => ( + + ))} +
+
+ ); +}; + +import axios from 'axios'; + +type Article = { + id: 15255; + title: string; + url: string; + imageUrl: string; + newsSite: string; + summary: string; + publishedAt: string; + updatedAt: string; + featured: boolean; + launches: any[]; + events: any[]; +}; + +async function getStories(): Promise { + const response = await axios.get( + 'https://api.spaceflightnewsapi.net/v3/articles' + ); + + return response.data; +} + +const News = () => { + const [stories, setStories] = React.useState([]); + + React.useEffect(() => { + getStories().then(setStories); + }, []); + + return ( +
+ ); +}; + +const components = { + default: (props: IDockviewPanelProps<{ title: string }>) => { + return
{props.params.title}
; + }, + currencies: Currencies, + news: News, +}; + +export const DockviewDemo = () => { + const onReady = (event: DockviewReadyEvent) => { + // event.api.addPanel({ + // id: 'currencies', + // component: 'currencies', + // title: 'Prices', + // }); + + // event.api.addPanel({ + // id: 'news', + // component: 'news', + // title: 'News', + // }); + + event.api.addPanel({ + id: 'panel_1', + component: 'default', + title: 'Panel 1', + }); + event.api.addPanel({ + id: 'panel_2', + component: 'default', + title: 'Panel 2', + }); + event.api.addPanel({ + id: 'panel_3', + component: 'default', + title: 'Panel 3', + }); + event.api.addPanel({ + id: 'panel_4', + component: 'default', + title: 'Panel 4', + position: { referencePanel: 'panel_3', direction: 'right' }, + }); + event.api.addPanel({ + id: 'panel_5', + component: 'default', + title: 'Panel 5', + position: { referencePanel: 'panel_4', direction: 'within' }, + }); + const panel6 = event.api.addPanel({ + id: 'panel_6', + component: 'default', + title: 'Panel 6', + position: { referencePanel: 'panel_4', direction: 'below' }, + }); + panel6.group.locked = true; + panel6.group.header.hidden = true; + 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' }, + }); + }; + + return ( + + ); +}; diff --git a/packages/docs/src/components/paneview/customHeader.tsx b/packages/docs/src/components/paneview/customHeader.tsx new file mode 100644 index 000000000..cdfb28b95 --- /dev/null +++ b/packages/docs/src/components/paneview/customHeader.tsx @@ -0,0 +1,104 @@ +import { + IPaneviewPanelProps, + PaneviewReact, + PaneviewReadyEvent, +} from 'dockview'; +import * as React from 'react'; + +const components = { + default: (props: IPaneviewPanelProps<{ title: string }>) => { + return ( +
+ {props.params.title} +
+ ); + }, +}; + +const MyHeaderComponent = (props: IPaneviewPanelProps<{ title: string }>) => { + const [expanded, setExpanded] = React.useState( + props.api.isExpanded + ); + + React.useEffect(() => { + const disposable = props.api.onDidExpansionChange((event) => { + setExpanded(event.isExpanded); + }); + + return () => { + disposable.dispose(); + }; + }, []); + + const onClick = () => { + props.api.setExpanded(!expanded); + }; + + return ( +
+ {`Custom header for ${props.title}`} + +
+ ); +}; + +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 ( + + ); +}; diff --git a/packages/docs/src/components/paneview/dragAndDrop.tsx b/packages/docs/src/components/paneview/dragAndDrop.tsx new file mode 100644 index 000000000..3130ec4bd --- /dev/null +++ b/packages/docs/src/components/paneview/dragAndDrop.tsx @@ -0,0 +1,102 @@ +import { + IPaneviewPanelProps, + PaneviewDropEvent, + PaneviewReact, + PaneviewReadyEvent, +} from 'dockview'; +import * as React from 'react'; + +const components = { + default: (props: IPaneviewPanelProps<{ title: string }>) => { + return ( +
+ {props.params.title} +
+ ); + }, +}; + +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 ( +
+
+
+ Drag me +
+
+
+ +
+
+ ); +}; diff --git a/packages/docs/src/css/custom.css b/packages/docs/src/css/custom.css index 9a917885e..b9359e759 100644 --- a/packages/docs/src/css/custom.css +++ b/packages/docs/src/css/custom.css @@ -6,13 +6,13 @@ /* You can override the default Infima variables here. */ :root { - --ifm-color-primary: #2e8555; - --ifm-color-primary-dark: #29784c; - --ifm-color-primary-darker: #277148; - --ifm-color-primary-darkest: #205d3b; - --ifm-color-primary-light: #33925d; - --ifm-color-primary-lighter: #359962; - --ifm-color-primary-lightest: #3cad6e; + --ifm-color-primary: #21222c; + --ifm-color-primary-dark: #1e1f28; + --ifm-color-primary-darker: #1c1d25; + --ifm-color-primary-darkest: #17181f; + --ifm-color-primary-light: #242530; + --ifm-color-primary-lighter: #262733; + --ifm-color-primary-lightest: #2b2c39; --ifm-code-font-size: 95%; --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); } @@ -29,4 +29,9 @@ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); } +body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Ubuntu, Cantarell, Helvetica, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Android Emoji", EmojiSymbols, "EmojiOne Mozilla", "Twemoji Mozilla", "Segoe UI Symbol", "Noto Color Emoji" +html +} + @import "~dockview/dist/styles/dockview.css" diff --git a/packages/docs/src/pages/index.scss b/packages/docs/src/pages/index.scss new file mode 100644 index 000000000..b85b289b7 --- /dev/null +++ b/packages/docs/src/pages/index.scss @@ -0,0 +1,27 @@ +.badge-container { + img:not(:first-child) { + padding-left: 10px; + } +} + +.dockview-feature-panel { + max-width: 1000px; + display: flex; + padding: 20px; + justify-content: space-around; + + .feature-banner { + .feature-banner-header { + // font-size: 1.25em; + } + + .feature-banner-content { + } + } +} + +.dockview-feature { + &:nth-child(2n) { + flex-direction: row-reverse; + } +} diff --git a/packages/docs/src/pages/index.tsx b/packages/docs/src/pages/index.tsx index cf0cce898..2aa59dde5 100644 --- a/packages/docs/src/pages/index.tsx +++ b/packages/docs/src/pages/index.tsx @@ -5,7 +5,9 @@ import Link from '@docusaurus/Link'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import styles from './index.module.css'; import HomepageFeatures from '@site/src/components/HomepageFeatures'; -import { SimpleDockview } from '../components/simpleDockview'; +import { DockviewDemo } from '../components/dockview/demo'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import './index.scss'; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); @@ -27,19 +29,46 @@ function HomepageHeader() { ); } +function HomepageHeader2() { + const { siteConfig } = useDocusaurusContext(); + return ( +
+
+ +

{siteConfig.title}

+ {/*
+ + + + +
*/} +

{siteConfig.tagline}

+
+ + Get Started + +
+
+
+ ); +} + export default function Home(): JSX.Element { const { siteConfig } = useDocusaurusContext(); return ( - +
-
- + +
+
- {/* */}
); diff --git a/packages/docs/static/img/dockview_grid.svg b/packages/docs/static/img/dockview_grid.svg new file mode 100644 index 000000000..791252c6a --- /dev/null +++ b/packages/docs/static/img/dockview_grid.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/dockview_grid_2.svg b/packages/docs/static/img/dockview_grid_2.svg new file mode 100644 index 000000000..c11c8f403 --- /dev/null +++ b/packages/docs/static/img/dockview_grid_2.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/dockview_logo.ico b/packages/docs/static/img/dockview_logo.ico new file mode 100644 index 000000000..0d5b20831 Binary files /dev/null and b/packages/docs/static/img/dockview_logo.ico differ diff --git a/packages/docs/static/img/dockview_logo.svg b/packages/docs/static/img/dockview_logo.svg new file mode 100644 index 000000000..6d9865310 --- /dev/null +++ b/packages/docs/static/img/dockview_logo.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/dockview_splash_2.svg b/packages/docs/static/img/dockview_splash_2.svg new file mode 100644 index 000000000..1158f6c8d --- /dev/null +++ b/packages/docs/static/img/dockview_splash_2.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/versioned_docs/version-1.4.3/basics.mdx b/packages/docs/versioned_docs/version-1.4.3/basics.mdx new file mode 100644 index 000000000..2cadf65bf --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/basics.mdx @@ -0,0 +1,117 @@ +--- +sidebar_position: 1 +--- + +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
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +## 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 ( +
+ {`My first panel has the title: ${props.params.title}`} + +
+ ); +}; +``` + +### 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. + + + + + +## 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). diff --git a/packages/docs/versioned_docs/version-1.4.3/components/_category_.json b/packages/docs/versioned_docs/version-1.4.3/components/_category_.json new file mode 100644 index 000000000..1cdf26b6f --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/components/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Components", + "collapsible": true, + "collapsed": false, + "link": { + "type": "generated-index", + "title": "Components" + }, +} diff --git a/packages/docs/versioned_docs/version-1.4.3/components/dockview.mdx b/packages/docs/versioned_docs/version-1.4.3/components/dockview.mdx new file mode 100644 index 000000000..b2e7e5d47 --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/components/dockview.mdx @@ -0,0 +1,294 @@ +import { SimpleDockview } from '@site/src/components/simpleDockview'; +import { + RenderingDockview, + Checkbox, +} from '@site/src/components/dockview/rendering'; +import { DndDockview } from '@site/src/components/dockview/dnd'; +import { EventsDockview } from '@site/src/components/dockview/events'; +import { ContextMenuDockview } from '@site/src/components/dockview/contextMenu'; +import Link from '@docusaurus/Link'; + +# Dockview + +## Introduction + +Dockview is an abstraction built on top of [Gridviews](./gridview) where each view is a container of many tabbed panels. + +
+ +
+ +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. + +## DockviewReact Component + +You can create a Dockview through the use of the `ReactDockview` component. + +```tsx +import { ReactDockview } 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 Auto Resizing | +| onTabContextMenu | Event | Yes | false | | +| onDidDrop | Event | Yes | false | | +| showDndOverlay | Event | Yes | false | | + +## Dockview API + +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 }>) => { + // props.containerApi... + + return
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +```tsx title="Dockview API via the onReady callback" +const onReady = (event: DockviewReadyEvent) => { + // 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 | +| size | `number` | Number of Groups | +| panels | `IDockviewPanel[]` | | +| groups | `GroupPanel[]` | | +| activePanel | `IDockviewPanel \| undefined` | | +| activeGroup | `IDockviewPanel \| undefined` | | +| | | | +| onDidLayoutChange | `Event` | | +| onDidLayoutFromJSON | `Event` | | +| onDidAddGroup | `Event` | | +| onDidRemoveGroup | `Event` | | +| onDidActiveGroupChange | `Event` | | +| onDidAddPanel | `Event` | | +| onDidRemovePanel | `Event` | | +| onDidActivePanelChange | `Event` | | +| onDidDrop | `EventAuto Resizing | +| fromJSON | `(data: SerializedDockview): void` | Serialization | +| toJSON | `(): SerializedDockview` | Serialization | +| clear | `(): void` | Clears the current layout | + +## Dockview Panel API + +```tsx +const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { + // props.api... + + return
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +| Property | Type | Description | +| ---------------------- | ----------------------------------------------------------- | --------------- | +| id | `string` | Panel id | +| isFocused | `boolean` | Is panel focsed | +| isActive | `boolean` | Is panel active | +| width | `number` | Panel width | +| height | `number` | Panel height | +| onDidDimensionsChange | `Event` | | +| onDidFocusChange | `Event` | | +| onDidVisibilityChange | `Event` | | +| onDidActiveChange | `Event` | | +| setActive | `(): void` | | +| | | | +| onDidConstraintsChange | `onDidConstraintsChange: Event` | | +| setConstraints | `(value: PanelConstraintChangeEvent2): void;` | | +| setSize | `(event: SizeEvent): void` | | +| | | | +| group | `GroupPanel | undefined` | +| isGroupActive | `boolean` | | +| title | `string` | | +| suppressClosable | `boolean` | | +| close | `(): void` | | +| setTitle | `(title: string): void` | | + +## Advanced Features + +### Locked 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. + +```tsx +panel.group.locked = true; +``` + +### Group header + +You may wish to hide the header section of a group. This can achieved through setting the `hidden` variable on `panel.group.header`. + +```tsx +panel.group.header.hidden = true; +``` + +### Context Menu + +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. + +::: + +
+ +
+ +### Rendering + +Although `DockviewReact` will only add those tabs that are visible to the DOM all associated React Components for each tab including those that +are not initially visible will be created. +This will mean that any hooks in those components will run and if you running expensive operations in the tabs you may end up doing a lot of initial +work for what are hidden tabs. + +This is the default behaviour to ensure the greatest flexibility for the user but you can create a Higher-Order component wrapping your components that +will ensure the component is only created if the tab is visible as below: + +```tsx +import { PanelApi } from 'dockview'; +import * as React from 'react'; + +function RenderWhenVisible< + T extends { api: Pick } +>(component: React.FunctionComponent) { + const HigherOrderComponent = (props: T) => { + const [visible, setVisible] = React.useState( + props.api.isVisible + ); + + React.useEffect(() => { + const disposable = props.api.onDidVisibilityChange((event) => + setVisible(event.isVisible) + ); + + return () => { + disposable.dispose(); + }; + }, [props.api]); + + if (!visible) { + return null; + } + + return React.createElement(component, props); + }; + return HigherOrderComponent; +} +``` + +```tsx +const component = RenderWhenVisible(MyComponent); +``` + +Through 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. + + +
+ +
+ +### Drag And Drop + +The component exposes some method to help determine whether external drag events should be interacted with or not. + +```tsx +/** + * called when an ondrop event which does not originate from the dockview libray and + * passes the showDndOverlay condition occurs + **/ +const onDidDrop = (event: DockviewDropEvent) => { + const { group } = event; + + event.api.addPanel({ + id: 'test', + component: 'default', + position: { + referencePanel: group.activePanel.id, + direction: 'within', + }, + }); +}; + +/** + * called for drag over events which do not originate from the dockview library + * allowing the developer to decide where the overlay should be shown for a + * particular drag event + **/ +const showDndOverlay = (event: DockviewDndOverlayEvent) => { + return true; +}; + +return ( + +); +``` + + + +### Events + + diff --git a/packages/docs/versioned_docs/version-1.4.3/components/gridview.mdx b/packages/docs/versioned_docs/version-1.4.3/components/gridview.mdx new file mode 100644 index 000000000..5816d5fae --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/components/gridview.mdx @@ -0,0 +1,116 @@ +import { SimpleGridview } from '@site/src/components/simpleGridview'; +import { EventsGridview } from '@site/src/components/gridview/events'; +import Link from '@docusaurus/Link'; + +# Gridview + +## Introduction + +
+ +
+ +## 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 Proportional layout | +| hideBorders | boolean | Yes | false | | +| className | string | Yes | '' | | +| disableAutoResizing | boolean | Yes | false | See Auto Resizing | + +## Gridview API + +```tsx +const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { + // props.containerApi... + + return
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +```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` | Fires on layout change | +| onDidLayoutFromJSON | `Event` | Fires of layout change caused by a fromJSON deserialization call | +| onDidAddPanel | `Event` | Fires when a view is added | +| onDidRemovePanel | `Event` | Fires when a view is removed | +| onDidActivePanelChange | `Event` | 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` | Auto Resizing | +| fromJSON | `(data: SerializedGridview): void` | Serialization | +| toJSON | `(): SerializedGridview` | Serialization | +| clear | `(): void` | Clears the current layout | + +## Gridview Panel API + +```tsx +const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { + // props.api... + + return
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +| 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` | | +| onDidFocusChange | `Event` | | +| onDidVisibilityChange | `Event` | | +| onDidActiveChange | `Event` | | +| onDidConstraintsChange | `onDidConstraintsChange: Event` | | +| | | | +| 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. + + diff --git a/packages/docs/versioned_docs/version-1.4.3/components/paneview.mdx b/packages/docs/versioned_docs/version-1.4.3/components/paneview.mdx new file mode 100644 index 000000000..82ede4f23 --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/components/paneview.mdx @@ -0,0 +1,270 @@ +import { SimplePaneview } from '@site/src/components/simplePaneview'; +import { CustomHeaderPaneview } from '@site/src/components/paneview/customHeader'; +import { DragAndDropPaneview } from '@site/src/components/paneview/dragAndDrop'; +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 + +
+ +
+ +```tsx title="Simple Paneview example" +import { + IPaneviewPanelProps, + PaneviewReact, + PaneviewReadyEvent, +} from 'dockview'; + +const components = { + default: (props: IPaneviewPanelProps<{ title: string }>) => { + return ( +
+ {props.params.title} +
+ ); + }, +}; + +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 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 | Auto Resizing | +| 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
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +```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` | Fires on layout change | +| onDidLayoutFromJSON | `Event` | Fires of layout change caused by a fromJSON deserialization call | +| onDidAddView | `Event` | Fires when a view is added | +| onDidRemoveView | `Event` | Fires when a view is removed | +| onDidDrop | `EventDrag and Drop) | +| | | | +| 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 Auto Resizing | +| fromJSON | `(data: SerializedPaneview): void` | Serialization | +| toJSON | `(): SerializedPaneview` | Serialization | +| clear | `(): void` | Clears the current layout | + +## Paneview Panel API + +```tsx +const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { + // props.api... + + return
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +| 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` | | +| onDidFocusChange | `Event` | | +| onDidVisibilityChange | `Event` | | +| onDidActiveChange | `Event` | | +| onDidConstraintsChange | `onDidConstraintsChange: Event` | | +| | | +| 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. + +
+ +
+ +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( + props.api.isExpanded + ); + + React.useEffect(() => { + const disposable = props.api.onDidExpansionChange((event) => { + setExpanded(event.isExpanded); + }); + + return () => { + disposable.dispose(); + }; + }, []); + + const onClick = () => { + props.api.setExpanded(!expanded); + }; + + return ( + + ); +}; + +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. + + diff --git a/packages/docs/versioned_docs/version-1.4.3/components/splitview.mdx b/packages/docs/versioned_docs/version-1.4.3/components/splitview.mdx new file mode 100644 index 000000000..5c6f0ad8a --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/components/splitview.mdx @@ -0,0 +1,242 @@ +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. + +
+ +
+ +```tsx title="Simple Splitview example" +import { + ISplitviewPanelProps, + Orientation, + SplitviewReact, + SplitviewReadyEvent, +} from 'dockview'; + +const components = { + default: (props: ISplitviewPanelProps<{ title: string }>) => { + return
{props.params.title}
; + }, +}; + +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 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` | No | | Panel renderers | +| orientation | `Orientation` | Yes | `Orientation.HORIZONTAL` | Orientation of the Splitview | +| proportionalLayout | `boolean` | Yes | `true` | See Proportional layout | +| hideBorders | `boolean` | Yes | `false` | Hide the borders between panels | +| className | `string` | Yes | `''` | Attaches a classname | +| disableAutoResizing | `boolean` | Yes | `false` | See Auto Resizing | + +## 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
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +```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` | Fires on layout change | +| onDidLayoutFromJSON | `Event` | Fires of layout change caused by a fromJSON deserialization call | +| onDidAddView | `Event` | Fires when a view is added | +| onDidRemoveView | `Event` | 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 Auto Resizing | +| fromJSON | `(data: SerializedSplitview): void` | Serialization | +| toJSON | `(): SerializedSplitview` | Serialization | +| 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
{`My first panel has the title: ${props.params.title}`}
; +}; +``` + +| 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` | Fires when panel dimensions change | +| onDidFocusChange | `Event` | Fire when panel is focused and blurred | +| onDidVisibilityChange | `Event` | Fires when the panels visiblity property is changed (see Panel Visibility) | +| onDidActiveChange | `Event` | Fires when the panels active property is changed (see Active Panel) | +| onDidConstraintsChange | `onDidConstraintsChange: Event` | Fires when the panels size contrainsts change (see Panel Constraints) | +| | | | +| 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. + +
+ +
+ +### 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, +}); +``` diff --git a/packages/docs/versioned_docs/version-1.4.3/index.mdx b/packages/docs/versioned_docs/version-1.4.3/index.mdx new file mode 100644 index 000000000..5f680279d --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/index.mdx @@ -0,0 +1,150 @@ +--- +sidebar_position: 0 +--- + +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/src/components/simpleDockview'; + +# Dockview + +## 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 + + ... + + + ... + +``` + +There are 4 components you may want to use: + +Splitview + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +```tsx +import { + DockviewReact, + DockviewReadyEvent, + PanelCollection, + IDockviewPanelProps, + IDockviewPanelHeaderProps, +} from 'dockview'; + +const components: PanelCollection = { + default: (props: IDockviewPanelProps<{ someProps: string }>) => { + return
{props.params.someProps}
; + }, +}; + +const headers: PanelCollection = { + customTab: (props: IDockviewPanelHeaderProps) => { + return ( +
+ {props.api.title} + props.api.close()}>{'[x]'} +
+ ); + }, +}; + +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 ( + + ); +}; +``` diff --git a/packages/docs/versioned_docs/version-1.4.3/theme.mdx b/packages/docs/versioned_docs/version-1.4.3/theme.mdx new file mode 100644 index 000000000..912280116 --- /dev/null +++ b/packages/docs/versioned_docs/version-1.4.3/theme.mdx @@ -0,0 +1,80 @@ +--- +sidebar_position: 3 +--- + +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 + +```css +@import './node_modules/dockview/dist/styles/dockview.css'; +``` + +## Customizing Theme + +`dockview` supports theming through the use of css properties. +You can view the built-in themes at [`dockview/src/theme.scss`](https://github.com/mathuo/dockview/blob/master/packages/dockview/src/theme.scss) +and are free to build your own themes based on these css properties. + +| CSS Property | Description | +| ---------------------------------------------------- | ----------- | +| --dv-paneview-active-outline-color | | +| --dv-tabs-and-actions-container-font-size | | +| --dv-tabs-and-actions-container-height | | +| --dv-tab-close-icon | | +| --dv-drag-over-background-color | | +| --dv-drag-over-border-color | | +| --dv-tabs-container-scrollbar-color | | +| | | +| --dv-group-view-background-color | | +| | | +| --dv-tabs-and-actions-container-background-color | | +| | | +| --dv-activegroup-visiblepanel-tab-background-color | | +| --dv-activegroup-hiddenpanel-tab-background-color | | +| --dv-inactivegroup-visiblepanel-tab-background-color | | +| --dv-inactivegroup-hiddenpanel-tab-background-color | | +| --dv-tab-divider-color | | +| | | +| --dv-activegroup-visiblepanel-tab-color | | +| --dv-activegroup-hiddenpanel-tab-color | | +| --dv-inactivegroup-visiblepanel-tab-color | | +| --dv-inactivegroup-hiddenpanel-tab-color | | +| | | +| --dv-separator-border | | +| --dv-paneview-header-border-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: + +```css +.groupview { + &.active-group { + > .tabs-and-actions-container { + border-bottom: 2px solid var(--dv-activegroup-visiblepanel-tab-background-color); + } + } + &.inactive-group { + > .tabs-and-actions-container { + border-bottom: 2px solid var(--dv-inactivegroup-visiblepanel-tab-background-color); + } + } +} +``` + +
+ +
diff --git a/packages/docs/versioned_sidebars/version-1.4.3-sidebars.json b/packages/docs/versioned_sidebars/version-1.4.3-sidebars.json new file mode 100644 index 000000000..caea0c03b --- /dev/null +++ b/packages/docs/versioned_sidebars/version-1.4.3-sidebars.json @@ -0,0 +1,8 @@ +{ + "tutorialSidebar": [ + { + "type": "autogenerated", + "dirName": "." + } + ] +} diff --git a/packages/docs/versions.json b/packages/docs/versions.json new file mode 100644 index 000000000..89b30e174 --- /dev/null +++ b/packages/docs/versions.json @@ -0,0 +1,3 @@ +[ + "1.4.3" +]