diff --git a/packages/dockview-core/src/dnd/overlay.ts b/packages/dockview-core/src/dnd/overlay.ts index 1b69e6a46..236726f1b 100644 --- a/packages/dockview-core/src/dnd/overlay.ts +++ b/packages/dockview-core/src/dnd/overlay.ts @@ -40,6 +40,14 @@ export class Overlay extends CompositeDisposable { private static MINIMUM_HEIGHT = 20; private static MINIMUM_WIDTH = 20; + set minimumInViewportWidth(value: number | undefined) { + this.options.minimumInViewportWidth = value; + } + + set minimumInViewportHeight(value: number | undefined) { + this.options.minimumInViewportHeight = value; + } + constructor( private readonly options: { height: number; @@ -109,7 +117,10 @@ export class Overlay extends CompositeDisposable { const xOffset = Math.max(0, this.getMinimumWidth(overlayRect.width)); // a minimum height of minimumViewportHeight must be inside the viewport - const yOffset = Math.max(0, this.getMinimumHeight(overlayRect.height)); + const yOffset = + typeof this.options.minimumInViewportHeight === 'number' + ? Math.max(0, this.getMinimumHeight(overlayRect.height)) + : 0; const left = clamp( overlayRect.left - containerRect.left, @@ -376,7 +387,9 @@ export class Overlay extends CompositeDisposable { height = clamp( y - top, - top < 0 && this.options.minimumInViewportHeight + top < 0 && + typeof this.options + .minimumInViewportHeight === 'number' ? -top + this.options.minimumInViewportHeight : Overlay.MINIMUM_HEIGHT, @@ -413,7 +426,9 @@ export class Overlay extends CompositeDisposable { width = clamp( x - left, - left < 0 && this.options.minimumInViewportWidth + left < 0 && + typeof this.options + .minimumInViewportWidth === 'number' ? -left + this.options.minimumInViewportWidth : Overlay.MINIMUM_WIDTH, diff --git a/packages/dockview-core/src/dockview/dockviewComponent.ts b/packages/dockview-core/src/dockview/dockviewComponent.ts index 5038567cb..13486ebd9 100644 --- a/packages/dockview-core/src/dockview/dockviewComponent.ts +++ b/packages/dockview-core/src/dockview/dockviewComponent.ts @@ -52,6 +52,8 @@ import { IDockviewFloatingGroupPanel, } from './dockviewFloatingGroupPanel'; +const DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE = 100; + export interface PanelReference { update: (event: { params: { [key: string]: any } }) => void; remove: () => void; @@ -87,7 +89,7 @@ export type DockviewComponentUpdateOptions = Pick< | 'createLeftHeaderActionsElement' | 'createRightHeaderActionsElement' | 'disableFloatingGroups' - | 'floatingGroupsPosition' + | 'floatingGroupBounds' >; export interface DockviewDropEvent extends GroupviewDropEvent { @@ -361,15 +363,17 @@ export class DockviewComponent left: overlayLeft, top: overlayTop, minimumInViewportWidth: - this.options.floatingGroupsPosition === 'boundedWithinViewport' + this.options.floatingGroupBounds === 'boundedWithinViewport' ? undefined - : this.options.floatingGroupsPosition - ?.minimumWidthWithinViewport ?? 100, + : this.options.floatingGroupBounds + ?.minimumWidthWithinViewport ?? + DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE, minimumInViewportHeight: - this.options.floatingGroupsPosition === 'boundedWithinViewport' + this.options.floatingGroupBounds === 'boundedWithinViewport' ? undefined - : this.options.floatingGroupsPosition - ?.minimumHeightWithinViewport ?? 100, + : this.options.floatingGroupBounds + ?.minimumHeightWithinViewport ?? + DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE, }); const el = group.element.querySelector('.void-container'); @@ -465,6 +469,9 @@ export class DockviewComponent const hasOrientationChanged = typeof options.orientation === 'string' && this.gridview.orientation !== options.orientation; + const hasFloatingGroupOptionsChanged = + typeof options.floatingGroupBounds !== undefined && + options.floatingGroupBounds !== this.options.floatingGroupBounds; this._options = { ...this.options, ...options }; @@ -472,6 +479,30 @@ export class DockviewComponent this.gridview.orientation = options.orientation!; } + if (hasFloatingGroupOptionsChanged) { + for (const group of this.floatingGroups) { + switch (this.options.floatingGroupBounds) { + case 'boundedWithinViewport': + group.overlay.minimumInViewportHeight = undefined; + group.overlay.minimumInViewportWidth = undefined; + break; + case undefined: + group.overlay.minimumInViewportHeight = + DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE; + group.overlay.minimumInViewportWidth = + DEFAULT_FLOATING_GROUP_OVERFLOW_SIZE; + break; + default: + group.overlay.minimumInViewportHeight = + this.options.floatingGroupBounds?.minimumHeightWithinViewport; + group.overlay.minimumInViewportWidth = + this.options.floatingGroupBounds?.minimumWidthWithinViewport; + } + + group.overlay.setBounds({}); + } + } + this.layout(this.gridview.width, this.gridview.height, true); } diff --git a/packages/dockview-core/src/dockview/options.ts b/packages/dockview-core/src/dockview/options.ts index 3c29be581..920737a06 100644 --- a/packages/dockview-core/src/dockview/options.ts +++ b/packages/dockview-core/src/dockview/options.ts @@ -87,7 +87,7 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions { singleTabMode?: 'fullwidth' | 'default'; parentElement?: HTMLElement; disableFloatingGroups?: boolean; - floatingGroupsPosition?: + floatingGroupBounds?: | 'boundedWithinViewport' | { minimumHeightWithinViewport?: number; diff --git a/packages/dockview/src/dockview/dockview.tsx b/packages/dockview/src/dockview/dockview.tsx index b491f077e..7c6bcc435 100644 --- a/packages/dockview/src/dockview/dockview.tsx +++ b/packages/dockview/src/dockview/dockview.tsx @@ -69,7 +69,7 @@ export interface IDockviewReactProps { leftHeaderActionsComponent?: React.FunctionComponent; singleTabMode?: 'fullwidth' | 'default'; disableFloatingGroups?: boolean; - floatingGroupsPosition?: + floatingGroupBounds?: | 'boundedWithinViewport' | { minimumHeightWithinViewport?: number; @@ -168,7 +168,7 @@ export const DockviewReact = React.forwardRef( ), singleTabMode: props.singleTabMode, disableFloatingGroups: props.disableFloatingGroups, - floatingGroupsPosition: props.floatingGroupsPosition, + floatingGroupBounds: props.floatingGroupBounds, }); const { clientWidth, clientHeight } = domRef.current; @@ -217,9 +217,9 @@ export const DockviewReact = React.forwardRef( return; } dockviewRef.current.updateOptions({ - floatingGroupsPosition: props.floatingGroupsPosition, + floatingGroupBounds: props.floatingGroupBounds, }); - }, [props.floatingGroupsPosition]); + }, [props.floatingGroupBounds]); React.useEffect(() => { if (!dockviewRef.current) { diff --git a/packages/docs/docs/components/dockview.mdx b/packages/docs/docs/components/dockview.mdx index 18904de45..923009036 100644 --- a/packages/docs/docs/components/dockview.mdx +++ b/packages/docs/docs/components/dockview.mdx @@ -401,6 +401,12 @@ Floating groups can be interacted with whilst holding the `shift` key activating Floating groups can be programatically added through the dockview `api` method `api.addFloatingGroup(...)` and you can check whether a group is floating via the `group.api.isFloating` property. See examples for full code. +You can control the bounding box of floating groups through the optional `floatingGroupBounds` options: + +- `boundedWithinViewport` will force the entire floating group to be bounded within the docks viewport. +- `{minimumHeightWithinViewport?: number, minimumWidthWithinViewport?: number}` sets the respective dimension minimums that must appears within the docks viewport +- If no options are provided the defaults of `100px` minimum height and width within the viewport are set. + { setApi(event.api); }; + const [options, setOptions] = React.useState< + 'boundedWithinViewport' | undefined + >(undefined); + return (
{ > Add Floating Group +