From 9e8b0fddd403d5a3ec0bced426dd729d30f12ff7 Mon Sep 17 00:00:00 2001 From: mathuo <6710312+mathuo@users.noreply.github.com> Date: Thu, 16 Feb 2023 21:54:35 +0700 Subject: [PATCH] chore: docs for release v1.6.0 --- .../docs/blog/2023-02-28-dockview-1.6.0.mdx | 33 ++ packages/docs/docs/components/dockview.mdx | 332 +++++++++++++----- .../src/components/HomepageFeatures/index.tsx | 2 +- .../src/components/dockview/customHeaders.tsx | 2 +- .../docs/src/components/dockview/demo.tsx | 25 +- .../src/components/dockview/groupControl.scss | 17 + .../src/components/dockview/groupControl.tsx | 103 ++++++ .../docs/src/components/dockview/native.scss | 34 ++ .../docs/src/components/dockview/native.tsx | 259 ++++++++++++++ .../src/components/dockview/rendering.tsx | 8 +- .../docs/src/components/dockview/resize.tsx | 26 +- .../docs/static/img/add_to_empty_space.svg | 20 ++ packages/docs/static/img/add_to_group.svg | 25 ++ packages/docs/static/img/add_to_tab.svg | 20 ++ packages/docs/static/img/dockview_grid_3.svg | 61 ++++ packages/docs/static/img/drop_positions.svg | 45 +++ .../docs/static/img/magnet_drop_positions.svg | 53 +++ 17 files changed, 964 insertions(+), 101 deletions(-) create mode 100644 packages/docs/blog/2023-02-28-dockview-1.6.0.mdx create mode 100644 packages/docs/src/components/dockview/groupControl.scss create mode 100644 packages/docs/src/components/dockview/groupControl.tsx create mode 100644 packages/docs/src/components/dockview/native.scss create mode 100644 packages/docs/src/components/dockview/native.tsx create mode 100644 packages/docs/static/img/add_to_empty_space.svg create mode 100644 packages/docs/static/img/add_to_group.svg create mode 100644 packages/docs/static/img/add_to_tab.svg create mode 100644 packages/docs/static/img/dockview_grid_3.svg create mode 100644 packages/docs/static/img/drop_positions.svg create mode 100644 packages/docs/static/img/magnet_drop_positions.svg diff --git a/packages/docs/blog/2023-02-28-dockview-1.6.0.mdx b/packages/docs/blog/2023-02-28-dockview-1.6.0.mdx new file mode 100644 index 000000000..83883bc20 --- /dev/null +++ b/packages/docs/blog/2023-02-28-dockview-1.6.0.mdx @@ -0,0 +1,33 @@ +--- +slug: dockview-1.6.0-release +title: Dockview 1.6.0 +tags: [release] +--- + +import Link from '@docusaurus/Link'; + +# Release Notes + +Please reference to docs @ [dockview.dev](https://dockview.dev). +If you feel anything is missing or unclear please let me know. + +## 🚀 Features + +- magnetic dnd controls [#177](https://github.com/mathuo/dockview/pull/177) +- group dnd [#171](https://github.com/mathuo/dockview/pull/171) +- full width tabs [#171](https://github.com/mathuo/dockview/pull/177) +- addPanel improvements +- update parameters via panel.api.updateParameters +- allow dnd on empty groups [#168](https://github.com/mathuo/dockview/pull/168) + +## 🛠 Miscs + +- Update dependencies including the dev dependencies for dockview and all dependencies for the docs website. + [#180](https://github.com/mathuo/dockview/pull/180) +- A variety of internal changes including file name changes +- Improve internal dnd control logic to handle a wider variety of cases +- Various doc enhancements @ [dockview.dev](https://dockview.dev) + +## 🔥 Breaking changes + +- addEmptyGroup renamed to addGroup diff --git a/packages/docs/docs/components/dockview.mdx b/packages/docs/docs/components/dockview.mdx index 0faa319cf..0e941796c 100644 --- a/packages/docs/docs/components/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -13,7 +13,13 @@ import { ContextMenuDockview } from '@site/src/components/dockview/contextMenu'; import { NestedDockview } from '@site/src/components/dockview/nested'; import { CustomHeadersDockview } from '@site/src/components/dockview/customHeaders'; import { ResizeDockview } from '@site/src/components/dockview/resize'; +import { DockviewGroupControl } from '@site/src/components/dockview/groupControl'; +import { + DockviewNative, + DockviewNative2, +} from '@site/src/components/dockview/native'; import Link from '@docusaurus/Link'; +import useBaseUrl from '@docusaurus/useBaseUrl'; # Dockview @@ -43,17 +49,21 @@ You can create a Dockview through the use of the `ReactDockview` component. 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 | -| 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 | +| onDidDrop | Event | Yes | false | | +| showDndOverlay | Event | Yes | false | | +| defaultTabComponent | object | Yes | | | +| groupControlComponent | object | Yes | | | +| tabHeight | number | Yes | | | +| singleTabMode | 'fullwidth' \| 'default' | Yes | 'default' | | ## Dockview API @@ -101,13 +111,13 @@ const onReady = (event: DockviewReadyEvent) => { | | | | | addPanel | `addPanel(options: AddPanelOptions): IDockviewPanel` | | | getPanel | `(id: string) \| IDockviewPanel \| undefined` | | -| addEmptyGroup | `(options? AddGroupOptions): void` | | +| addGroup | `(options? AddGroupOptions): void` | | | closeAllGroups | `(): void` | | | removeGroup | `(group: GroupPanel): void` | | | getGroup | `(id: string): GroupPanel \| undefined` | | | | | | | getTabHeight | `(): number \| undefined` | | -| setTabHeight | `(hegiht: number \| undefined): void` | | +| setTabHeight | `(height: number \| undefined): void` | | | updateOptions | `(options:SplitviewComponentUpdateOptions): void` | | | focus | `(): void` | | | layout | `(width: number, height:number): void` | Auto Resizing | @@ -125,66 +135,139 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { }; ``` -| 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` | | +| 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` | | +| 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` | | + +## Essential Features + +### Add Panel + +Using the dockview 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 `DockviewReactComponent` component. + +You can optionally provide a `tabComponent` parameters to the `addPanel` method which will render the tab using a custom renderer. +You will have registered this using the `tabComponents` prop of the `DockviewReactComponent` component. + +```ts +const panel = api.addPanel({ + id: 'my_unique_panel_id', + component: 'my_component', + tabComponent: 'my_tab_component', +}); +``` + +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', + }, +}); + +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 optionally accepts either a `referencePanel` or `referenceGroup` which can be the associated id as a string + or the panel/group object reference. +- 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 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', + }, +}); +``` ## Advanced Features ### Resizing via API -Each Dockview is comprised of a number of groups, each of which have a number of panels. -Logically most people would want to resize a panel but practically this really translates to resizing the group to which the panel belongs. +Each Dockview contains of a number of groups and each group has a number of panels. +Logically a user may want to resize a panel, but this translates to resizing the group which contains that panel. -From the api you can access the panels group object (`props.group`) which exposes it's own api object (`props.groups.api`). -This api is largly similar to the Gridview API. - -To resize an individual panel you could create a snippet similar to below. +You can set the size of a panel using `props.api.setSize(...)`. +You can also set the size of the group associated with the panel using `props.api.group.api.setSize(...)` although this isn't recommended +due to the clunky syntax. ```tsx -const onResizePanel = () => { - props.api.group.api.setSize({ - height: 100, - }); -}; +// it's mandatory to provide either a height or a width, providing both is optional +props.api.setSize({ + height: 100, + width: 200, +}); + +// you could also resize the panels group, although not recommended it achieved the same result +props.api.group.api.setSize({ + height: 100, + width: 200, +}); ``` -```tsx -const onResizePanel = () => { - props.api.group.api.setSize({ - width: 100, - }); -}; -``` - -Here is a working example of resizing panels via these API methods. +You can see an example invoking both approaches below. ### 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. +Locking a group will disable all drop events for this group ensuring no additional panels can be added to the group through drop events. +You can still add groups to a locked panel programatically using the API though. ```tsx panel.group.locked = true; @@ -192,7 +275,7 @@ 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`. +You may wish to hide the header section of a group. This can achieved through the `hidden` variable on `panel.group.header`. ```tsx panel.group.header.hidden = true; @@ -200,13 +283,11 @@ panel.group.header.hidden = true; ### Custom Tab Headers -You can provide custom renderers for your tab headers. +You can provide custom renderers for your tab headers for maximum customization. A default implementation of `DockviewDefaultTab` is provided should you only wish to attach minor changes and events that do not alter the default behaviour, for example to add a custom context menu event handler. -You are also free to define a custom renderer entirely from scratch and not make use of the `DockviewDefaultTab` component. - ```tsx title="Attaching a custom context menu event handlers to a custom header" import { IDockviewPanelHeaderProps, DockviewDefaultTab } from 'dockview'; @@ -219,7 +300,8 @@ const MyCustomheader = (props: IDockviewPanelHeaderProps) => { }; ``` -To use a custom renderer you can must register a collection of tab components +You are also free to define a custom renderer entirely from scratch and not make use of the `DockviewDefaultTab` component. +To use a custom renderer you can must register a collection of tab components. ```tsx const tabComponents = { @@ -233,7 +315,7 @@ return ; api.addPanel({ id: 'panel_1', component: 'default', - tabComponent: 'myCustomHeader', // <-- + tabComponent: 'myCustomHeader', // <-- your registered renderers title: 'Panel 1', }); ``` @@ -246,26 +328,35 @@ You can also override the default tab renderer which will be used when no `tabCo As a simple example the below attachs a custom event handler for the context menu on all tabs as a default tab renderer +The below example uses a custom tab renderer to reigster a popover when the user right clicked on a tab. +This still makes use of the `DockviewDefaultTab` since it's only a minor change. + -### Rendering +### Panel 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. +By default `DockviewReact` only adds to the DOM those panels that are visible, +if a panel is not the active tab and not shown the contents of the hidden panel will be removed from the DOM. -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: +However the React Components associated with each panel are only created once and will always exist for as long as the panel exists, hidden or not. -```tsx -import { PanelApi } from 'dockview'; +> For example this means that any hooks in those components will run whether the panel is visible or not which may lead to excessive background work depending +> on the panels implementation. + +This is the default behaviour to ensure the greatest flexibility for the user but through the panels `props.api` you can listen to the visiblity state of the panel +and write additional logic to optimize your application. + +For example if you wanted to unmount the React Components when the panel is not visible you could create a Higher-Order-Component that listens to the panels +visiblity state and only renders the panel when visible. + +```tsx title="Only rendering the React Component when the panel is visible, otherwise rendering a null React Component" +import { IDockviewPanelProps } from 'dockview'; import * as React from 'react'; -function RenderWhenVisible< - T extends { api: Pick } ->(component: React.FunctionComponent) { - const HigherOrderComponent = (props: T) => { +function RenderWhenVisible( + component: React.FunctionComponent +) { + const HigherOrderComponent = (props: IDockviewPanelProps) => { const [visible, setVisible] = React.useState( props.api.isVisible ); @@ -291,10 +382,10 @@ function RenderWhenVisible< ``` ```tsx -const component = RenderWhenVisible(MyComponent); +const components = { default: 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. +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 a tab onto another tab to place it inbetween existing tabs. + + + +> Drag a tab to the right of the last tab to place it after the existing tabs. + + + +> Drag a group onto an existing group to merge the two groups. + +
+ + +
+ +> Drag into the left/right/top/bottom target zone of a panel to create a new group in the selected direction. + +> Drag into the center of a panel to add to that group. + +> Drag to the edge of the dockview component to create a new group on the selected edge. + +#### Extended behaviours + +For interaction with the Drag events directly the component exposes some method to help determine whether external drag events should be interacted with or not. ```tsx /** @@ -375,3 +499,51 @@ const Component: React.FunctionComponent = () => { return ; ``` + +As a simple example the below uses the `groupControlComponent` to render a small control that indicates whether the group +is active and which panel is active in that group. + +```tsx +const GroupControlComponent = (props: IDockviewGroupControlProps) => { + const isGroupActive = props.isGroupActive; + const activePanel = props.activePanel; + + return ( +
+ + {isGroupActive ? 'Group Active' : 'Group Inactive'} + + {`activePanel: ${ + activePanel?.id || 'null' + }`} +
+ ); +}; +``` + + + +### Full width tabs + +`DockviewReactComponent` accepts the prop `singleTabMode`. If set `singleTabMode=fullwidth` then when there is only one tab in a group this tab will expand +to the entire width of the group. For example: + +> This can be conmbined with Locked Groups to create an application that feels more like a Window Manager +> rather than a collection of groups and tabs. + +```tsx + +``` + + + +### Example + +hello + + diff --git a/packages/docs/src/components/HomepageFeatures/index.tsx b/packages/docs/src/components/HomepageFeatures/index.tsx index cd8efbf61..bad899c47 100644 --- a/packages/docs/src/components/HomepageFeatures/index.tsx +++ b/packages/docs/src/components/HomepageFeatures/index.tsx @@ -11,7 +11,7 @@ type FeatureItem = { const FeatureList: FeatureItem[] = [ { title: '', - Svg: require('@site/static/img/dockview_grid_2.svg').default, + Svg: require('@site/static/img/dockview_grid_3.svg').default, description: ( <>
diff --git a/packages/docs/src/components/dockview/customHeaders.tsx b/packages/docs/src/components/dockview/customHeaders.tsx index 8494cdefb..08e5b85b1 100644 --- a/packages/docs/src/components/dockview/customHeaders.tsx +++ b/packages/docs/src/components/dockview/customHeaders.tsx @@ -84,7 +84,7 @@ export const CustomHeadersDockview = () => { position: { referencePanel: 'panel_7', direction: 'within' }, }); - event.api.addEmptyGroup(); + event.api.addGroup(); }; return ( diff --git a/packages/docs/src/components/dockview/demo.tsx b/packages/docs/src/components/dockview/demo.tsx index 88410fc6d..c8ce7aadc 100644 --- a/packages/docs/src/components/dockview/demo.tsx +++ b/packages/docs/src/components/dockview/demo.tsx @@ -209,9 +209,8 @@ const Icon = (props: { }; const Button = () => { - const [position, setPosition] = React.useState< - { x: number; y: number } | undefined - >(undefined); + const [position, setPosition] = + React.useState<{ x: number; y: number } | undefined>(undefined); const close = () => setPosition(undefined); @@ -316,19 +315,19 @@ export const DockviewDemo = () => { position: { referencePanel: 'panel_7', direction: 'within' }, }); - event.api.addEmptyGroup(); + event.api.addGroup(); event.api.getPanel('panel_1').api.setActive(); - setInterval(() => { - event.api.getPanel('panel_1').update({ - params: { - params: { - title: Date.now().toString(), - }, - }, - }); - }, 1000); + // setInterval(() => { + // event.api.getPanel('panel_1').update({ + // params: { + // params: { + // title: Date.now().toString(), + // }, + // }, + // }); + // }, 1000); }; return ( diff --git a/packages/docs/src/components/dockview/groupControl.scss b/packages/docs/src/components/dockview/groupControl.scss new file mode 100644 index 000000000..9a9d5bce1 --- /dev/null +++ b/packages/docs/src/components/dockview/groupControl.scss @@ -0,0 +1,17 @@ +.dockview-groupcontrol-demo { + height: 100%; + display: flex; + align-items: center; + color: white; + background-color: black; + padding-left: 8px; + + .dockview-groupcontrol-demo-group-active { + padding: 0px 8px; + } + + .dockview-groupcontrol-demo-active-panel { + color: yellow; + padding: 0px 8px; + } +} diff --git a/packages/docs/src/components/dockview/groupControl.tsx b/packages/docs/src/components/dockview/groupControl.tsx new file mode 100644 index 000000000..1279b5092 --- /dev/null +++ b/packages/docs/src/components/dockview/groupControl.tsx @@ -0,0 +1,103 @@ +import {} from '@site/../dockview/dist/cjs/dnd/droptarget'; +import { + DockviewReact, + DockviewReadyEvent, + IDockviewGroupControlProps, + IDockviewPanelProps, +} from 'dockview'; +import * as React from 'react'; +import './groupControl.scss'; + +const components = { + default: (props: IDockviewPanelProps<{ title: string; x?: number }>) => { + return ( +
+ {`${props.params.title}`} + {props.params.x && {` ${props.params.x}`}} +
+ ); + }, +}; + +const GroupControlComponent = (props: IDockviewGroupControlProps) => { + const isGroupActive = props.isGroupActive; + const activePanel = props.activePanel; + + return ( +
+ + {isGroupActive ? 'Group Active' : 'Group Inactive'} + + {`activePanel: ${ + activePanel?.id || 'null' + }`} +
+ ); +}; + +export const DockviewGroupControl = () => { + const onReady = (event: DockviewReadyEvent) => { + const panel1 = event.api.addPanel({ + id: 'panel_1', + component: 'default', + tabComponent: 'default', + params: { + title: 'Window 1', + }, + }); + + const panel2 = event.api.addPanel({ + id: 'panel_2', + component: 'default', + tabComponent: 'default', + params: { + title: 'Window 2', + }, + position: { + direction: 'right', + }, + }); + + const panel3 = event.api.addPanel({ + id: 'panel_3', + component: 'default', + tabComponent: 'default', + params: { + title: 'Window 3', + }, + position: { + direction: 'below', + }, + }); + }; + + return ( +
+ +
+ ); +}; diff --git a/packages/docs/src/components/dockview/native.scss b/packages/docs/src/components/dockview/native.scss new file mode 100644 index 000000000..03d7d8c35 --- /dev/null +++ b/packages/docs/src/components/dockview/native.scss @@ -0,0 +1,34 @@ +.nested-dockview { + position: relative; + ::after { + content: ''; + position: absolute; + top: 0px; + left: 0px; + height: 1px; + width: 100%; + background-color: var(--dv-separator-border); + } +} + +.header-title { + padding: 0px 8px; +} + +.my-custom-tab { + padding: 0px 8px; + width: 100%; + display: flex; + height: 100%; + align-items: center; + background-color: var(--dv-tabs-and-actions-container-background-color); + + .my-custom-tab-icon { + font-size: 16px; + + &:hover { + border-radius: 2px; + background-color: var(--dv-icon-hover-background-color); + } + } +} diff --git a/packages/docs/src/components/dockview/native.tsx b/packages/docs/src/components/dockview/native.tsx new file mode 100644 index 000000000..f0a62997d --- /dev/null +++ b/packages/docs/src/components/dockview/native.tsx @@ -0,0 +1,259 @@ +import { + CanDisplayOverlay, + Droptarget, + DropTargetDirections, +} from '@site/../dockview/dist/cjs/dnd/droptarget'; +import { + DockviewDndOverlayEvent, + DockviewDropEvent, + DockviewReact, + DockviewReadyEvent, + GridviewReact, + GridviewReadyEvent, + IDockviewPanelProps, + IGridviewPanelProps, + Position, + Direction, + IDockviewPanelHeaderProps, +} from 'dockview'; +import * as React from 'react'; +import './native.scss'; + +class CustomDndTraget { + private data: any; + + static SINGLETON = new CustomDndTraget(); + + setData(t: T): void { + this.data = t; + } + + getData(): T { + return this.data; + } + + clearData(): void { + this.data = null; + } +} + +type CustomDescriptor = { + type: 'CUSTOM'; + id: string; +}; + +function isCustomDescriptor(obj: any): obj is CustomDescriptor { + return ( + typeof obj === 'object' && (obj as CustomDescriptor).type === 'CUSTOM' + ); +} + +function convertPositionToDirection(position: Position): Direction { + switch (position) { + case Position.Left: + return 'left'; + + case Position.Right: + return 'right'; + + case Position.Bottom: + return 'below'; + + case Position.Top: + return 'above'; + + case Position.Center: + return 'within'; + } +} + +const components = { + default: (props: IDockviewPanelProps<{ title: string; x?: number }>) => { + return ( +
+ {`${props.params.title}`} + {props.params.x && {` ${props.params.x}`}} +
+ ); + }, + isolatedApp: ( + props: IDockviewPanelProps<{ title: string; x?: number }> + ) => { + const onReady = (event: DockviewReadyEvent) => { + const panel1 = event.api.addPanel({ + id: 'panel_1', + component: 'default', + params: { + title: 'Tab 1', + }, + }); + const panel2 = event.api.addPanel({ + id: 'panel_2', + component: 'default', + params: { + title: 'Tab 2', + }, + }); + const panel3 = event.api.addPanel({ + id: 'panel_3', + component: 'default', + params: { + title: 'Tab 3', + }, + }); + }; + return ( + + ); + }, +}; + +const tabComponents = { + default: (props: IDockviewPanelHeaderProps<{ title: string }>) => { + return ( +
+ {props.params.title} + + + + chrome_minimize + + + chrome_maximize + + + close + +
+ ); + }, +}; + +export const DockviewNative = () => { + const onReady = (event: DockviewReadyEvent) => { + const panel1 = event.api.addPanel({ + id: 'panel_1', + component: 'default', + tabComponent: 'default', + params: { + title: 'Window 1', + }, + }); + panel1.group.locked = true; + + const panel2 = event.api.addPanel({ + id: 'panel_2', + component: 'default', + tabComponent: 'default', + params: { + title: 'Window 2', + }, + position: { + direction: 'right', + }, + }); + panel2.group.locked = true; + + const panel3 = event.api.addPanel({ + id: 'panel_3', + component: 'default', + tabComponent: 'default', + params: { + title: 'Window 3', + }, + position: { + direction: 'below', + }, + }); + panel3.group.locked = true; + }; + + return ( +
+ +
+ ); +}; + +export const DockviewNative2 = () => { + const onReady = (event: DockviewReadyEvent) => { + const panel1 = event.api.addPanel({ + id: 'panel_1', + component: 'isolatedApp', + tabComponent: 'default', + params: { + title: 'Window 1', + }, + }); + panel1.group.locked = true; + + const panel2 = event.api.addPanel({ + id: 'panel_2', + component: 'isolatedApp', + tabComponent: 'default', + params: { + title: 'Window 2', + }, + position: { + direction: 'right', + }, + }); + panel2.group.locked = true; + + const panel3 = event.api.addPanel({ + id: 'panel_3', + component: 'isolatedApp', + tabComponent: 'default', + params: { + title: 'Window 3', + }, + position: { + direction: 'below', + }, + }); + panel3.group.locked = true; + }; + + return ( +
+ +
+ ); +}; diff --git a/packages/docs/src/components/dockview/rendering.tsx b/packages/docs/src/components/dockview/rendering.tsx index 78f775423..18b1b3ebf 100644 --- a/packages/docs/src/components/dockview/rendering.tsx +++ b/packages/docs/src/components/dockview/rendering.tsx @@ -13,10 +13,10 @@ const renderVisibleComponentsOnlyAtom = atom({ default: false, }); -function RenderWhenVisible< - T extends { api: Pick } ->(component: React.FunctionComponent) { - const HigherOrderComponent = (props: T) => { +function RenderWhenVisible( + component: React.FunctionComponent +) { + const HigherOrderComponent = (props: IDockviewPanelProps) => { const [visible, setVisible] = React.useState( props.api.isVisible ); diff --git a/packages/docs/src/components/dockview/resize.tsx b/packages/docs/src/components/dockview/resize.tsx index eaff93af3..a6e68cfb4 100644 --- a/packages/docs/src/components/dockview/resize.tsx +++ b/packages/docs/src/components/dockview/resize.tsx @@ -23,13 +23,24 @@ const Default = (props: IDockviewPanelProps) => { step={1} /> +
@@ -42,13 +53,24 @@ const Default = (props: IDockviewPanelProps) => { step={1} /> +
diff --git a/packages/docs/static/img/add_to_empty_space.svg b/packages/docs/static/img/add_to_empty_space.svg new file mode 100644 index 000000000..da2c2f446 --- /dev/null +++ b/packages/docs/static/img/add_to_empty_space.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/add_to_group.svg b/packages/docs/static/img/add_to_group.svg new file mode 100644 index 000000000..e8f2ab88d --- /dev/null +++ b/packages/docs/static/img/add_to_group.svg @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/add_to_tab.svg b/packages/docs/static/img/add_to_tab.svg new file mode 100644 index 000000000..bdc5acf49 --- /dev/null +++ b/packages/docs/static/img/add_to_tab.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/dockview_grid_3.svg b/packages/docs/static/img/dockview_grid_3.svg new file mode 100644 index 000000000..fb70b1897 --- /dev/null +++ b/packages/docs/static/img/dockview_grid_3.svg @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/drop_positions.svg b/packages/docs/static/img/drop_positions.svg new file mode 100644 index 000000000..365e7f609 --- /dev/null +++ b/packages/docs/static/img/drop_positions.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/docs/static/img/magnet_drop_positions.svg b/packages/docs/static/img/magnet_drop_positions.svg new file mode 100644 index 000000000..a82f693b0 --- /dev/null +++ b/packages/docs/static/img/magnet_drop_positions.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +