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/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 94% rename from packages/docs/docs/api/dockview.mdx rename to packages/docs/docs/components/dockview.mdx index dc00eb9df..8bb05b64b 100644 --- a/packages/docs/docs/api/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -5,13 +5,14 @@ import { } from '../../src/components/dockview/rendering'; import { DndDockview } from '../../src/components/dockview/dnd'; import { EventsDockview } from '../../src/components/dockview/events'; +import { ContextMenuDockview } from '../../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](/docs/api/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'; ``` @@ -53,7 +51,10 @@ import { ReactDockview } from 'dockview'; ## 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,7 +62,7 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => { }; ``` -```tsx +```tsx title="Dockview API via the onReady callback" const onReady = (event: DockviewReadyEvent) => { // event.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. + +:::
+```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'; ``` @@ -34,7 +113,10 @@ import { ReactPaneview } from 'dockview'; ## 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,7 +124,7 @@ const MyComponent = (props: IGridviewPanelProps<{ title: string }>) => { }; ``` -```tsx +```tsx title="Paneview API via the onReady callback" const onReady = (event: GridviewReadyEvent) => { // event.api... }; @@ -74,7 +156,7 @@ const onReady = (event: GridviewReadyEvent) => { | 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 95% rename from packages/docs/docs/api/splitview.mdx rename to packages/docs/docs/components/splitview.mdx index b6daf2c4f..29bc25f53 100644 --- a/packages/docs/docs/api/splitview.mdx +++ b/packages/docs/docs/components/splitview.mdx @@ -6,9 +6,7 @@ import Link from '@docusaurus/Link'; ## 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.
) => { @@ -139,7 +138,7 @@ const onReady = (event: SplitviewReadyEvent) => { ## 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 }>) => { @@ -172,7 +171,7 @@ const MyComponent = (props: ISplitviewPanelProps<{ title: string }>) => { ## 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.
) => { 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); - }); - - return () => { - disposable1.dispose(); - disposable2.dispose(); - }; + const onClick = React.useCallback(() => { + props.api.setActive(); }, [props.api]); return ( -
- - {props.api.title} - - props.api.setActive()} - style={{ - display: 'flex', - alignItems: 'center', - paddingRight: '8px', - }} - > +
+ {props.api.title} + {'✕'}
); }; +const Test = (props: IDockviewPanelHeaderProps) => { + return ; +}; + const tabComponents = { - default: DefaultTab, + default: CustomTab, }; export const ContextMenuDockview = () => { @@ -104,12 +87,18 @@ export const ContextMenuDockview = () => { }); }; + const onContextMenu = (event: TabContextMenuEvent) => { + event.event.preventDefault(); + alert(`Content appear event fired for panel ${event.panel.id}`); + }; + return ( ); }; 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/pages/index.tsx b/packages/docs/src/pages/index.tsx index cf0cce898..431d507a1 100644 --- a/packages/docs/src/pages/index.tsx +++ b/packages/docs/src/pages/index.tsx @@ -31,8 +31,8 @@ export default function Home(): JSX.Element { const { siteConfig } = useDocusaurusContext(); return (