mirror of
https://github.com/mathuo/dockview
synced 2025-08-12 20:26:03 +00:00
Merge branch 'master' of https://github.com/mathuo/dockview into 395-showdndoverlay-is-not-called-always
This commit is contained in:
commit
8da26f1484
@ -28,6 +28,7 @@
|
||||
"/packages/docs/sandboxes/rendermode-dockview",
|
||||
"/packages/docs/sandboxes/resize-dockview",
|
||||
"/packages/docs/sandboxes/resizecontainer-dockview",
|
||||
"/packages/docs/sandboxes/scrollbars-dockview",
|
||||
"/packages/docs/sandboxes/simple-dockview",
|
||||
"/packages/docs/sandboxes/simple-gridview",
|
||||
"/packages/docs/sandboxes/simple-paneview",
|
||||
@ -40,4 +41,4 @@
|
||||
"/packages/docs/sandboxes/javascript/vanilla-dockview"
|
||||
],
|
||||
"node": "18"
|
||||
}
|
||||
}
|
@ -22,20 +22,28 @@
|
||||
will-change: transform;
|
||||
pointer-events: none;
|
||||
|
||||
&.small-top {
|
||||
border-top: 1px solid var(--dv-drag-over-border-color);
|
||||
&.dv-overlay-top {
|
||||
&.dv-overlay-small-vertical {
|
||||
border-top: 1px solid var(--dv-drag-over-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.small-bottom {
|
||||
border-bottom: 1px solid var(--dv-drag-over-border-color);
|
||||
&.dv-overlay-bottom {
|
||||
&.dv-overlay-small-vertical {
|
||||
border-bottom: 1px solid var(--dv-drag-over-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.small-left {
|
||||
border-left: 1px solid var(--dv-drag-over-border-color);
|
||||
&.dv-overlay-left {
|
||||
&.dv-overlay-small-horizontal {
|
||||
border-left: 1px solid var(--dv-drag-over-border-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.small-right {
|
||||
border-right: 1px solid var(--dv-drag-over-border-color);
|
||||
&.dv-overlay-right {
|
||||
&.dv-overlay-small-horizontal {
|
||||
border-right: 1px solid var(--dv-drag-over-border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,6 @@ import { DragAndDropObserver } from './dnd';
|
||||
import { clamp } from '../math';
|
||||
import { Direction } from '../gridview/baseComponentGridview';
|
||||
|
||||
function numberOrFallback(maybeNumber: any, fallback: number): number {
|
||||
return typeof maybeNumber === 'number' ? maybeNumber : fallback;
|
||||
}
|
||||
|
||||
export function directionToPosition(direction: Direction): Position {
|
||||
switch (direction) {
|
||||
case 'above':
|
||||
@ -54,6 +50,26 @@ export type CanDisplayOverlay =
|
||||
| boolean
|
||||
| ((dragEvent: DragEvent, state: Position) => boolean);
|
||||
|
||||
export type MeasuredValue = { value: number; type: 'pixels' | 'percentage' };
|
||||
|
||||
export type DroptargetOverlayModel = {
|
||||
size?: MeasuredValue;
|
||||
activationSize?: MeasuredValue;
|
||||
};
|
||||
|
||||
const DEFAULT_ACTIVATION_SIZE: MeasuredValue = {
|
||||
value: 20,
|
||||
type: 'percentage',
|
||||
};
|
||||
|
||||
const DEFAULT_SIZE: MeasuredValue = {
|
||||
value: 50,
|
||||
type: 'percentage',
|
||||
};
|
||||
|
||||
const SMALL_WIDTH_BOUNDARY = 100;
|
||||
const SMALL_HEIGHT_BOUNDARY = 100;
|
||||
|
||||
export class Droptarget extends CompositeDisposable {
|
||||
private targetElement: HTMLElement | undefined;
|
||||
private overlayElement: HTMLElement | undefined;
|
||||
@ -76,13 +92,7 @@ export class Droptarget extends CompositeDisposable {
|
||||
private readonly options: {
|
||||
canDisplayOverlay: CanDisplayOverlay;
|
||||
acceptedTargetZones: Position[];
|
||||
overlayModel?: {
|
||||
size?: { value: number; type: 'pixels' | 'percentage' };
|
||||
activationSize?: {
|
||||
value: number;
|
||||
type: 'pixels' | 'percentage';
|
||||
};
|
||||
};
|
||||
overlayModel?: DroptargetOverlayModel;
|
||||
}
|
||||
) {
|
||||
super();
|
||||
@ -158,7 +168,7 @@ export class Droptarget extends CompositeDisposable {
|
||||
|
||||
this.toggleClasses(quadrant, width, height);
|
||||
|
||||
this.setState(quadrant);
|
||||
this._state = quadrant;
|
||||
},
|
||||
onDragLeave: () => {
|
||||
this.removeDropTarget();
|
||||
@ -189,6 +199,10 @@ export class Droptarget extends CompositeDisposable {
|
||||
this._acceptedTargetZonesSet = new Set(acceptedTargetZones);
|
||||
}
|
||||
|
||||
setOverlayModel(model: DroptargetOverlayModel): void {
|
||||
this.options.overlayModel = model;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.removeDropTarget();
|
||||
super.dispose();
|
||||
@ -202,7 +216,7 @@ export class Droptarget extends CompositeDisposable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check is the event has already been used by another instance od DropTarget
|
||||
* Check is the event has already been used by another instance of DropTarget
|
||||
*/
|
||||
private isAlreadyUsed(event: DragEvent): boolean {
|
||||
const value = (event as any)[Droptarget.USED_EVENT_ID];
|
||||
@ -218,8 +232,8 @@ export class Droptarget extends CompositeDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
const isSmallX = width < 100;
|
||||
const isSmallY = height < 100;
|
||||
const isSmallX = width < SMALL_WIDTH_BOUNDARY;
|
||||
const isSmallY = height < SMALL_HEIGHT_BOUNDARY;
|
||||
|
||||
const isLeft = quadrant === 'left';
|
||||
const isRight = quadrant === 'right';
|
||||
@ -231,22 +245,18 @@ export class Droptarget extends CompositeDisposable {
|
||||
const topClass = !isSmallY && isTop;
|
||||
const bottomClass = !isSmallY && isBottom;
|
||||
|
||||
let size = 0.5;
|
||||
let size = 1;
|
||||
|
||||
if (this.options.overlayModel?.size?.type === 'percentage') {
|
||||
size = clamp(this.options.overlayModel.size.value, 0, 100) / 100;
|
||||
}
|
||||
const sizeOptions = this.options.overlayModel?.size ?? DEFAULT_SIZE;
|
||||
|
||||
if (this.options.overlayModel?.size?.type === 'pixels') {
|
||||
if (sizeOptions.type === 'percentage') {
|
||||
size = clamp(sizeOptions.value, 0, 100) / 100;
|
||||
} else {
|
||||
if (rightClass || leftClass) {
|
||||
size =
|
||||
clamp(0, this.options.overlayModel.size.value, width) /
|
||||
width;
|
||||
size = clamp(0, sizeOptions.value, width) / width;
|
||||
}
|
||||
if (topClass || bottomClass) {
|
||||
size =
|
||||
clamp(0, this.options.overlayModel.size.value, height) /
|
||||
height;
|
||||
size = clamp(0, sizeOptions.value, height) / height;
|
||||
}
|
||||
}
|
||||
|
||||
@ -269,30 +279,16 @@ export class Droptarget extends CompositeDisposable {
|
||||
|
||||
this.overlayElement.style.transform = transform;
|
||||
|
||||
toggleClass(this.overlayElement, 'small-right', isSmallX && isRight);
|
||||
toggleClass(this.overlayElement, 'small-left', isSmallX && isLeft);
|
||||
toggleClass(this.overlayElement, 'small-top', isSmallY && isTop);
|
||||
toggleClass(this.overlayElement, 'small-bottom', isSmallY && isBottom);
|
||||
}
|
||||
|
||||
private setState(quadrant: Position): void {
|
||||
switch (quadrant) {
|
||||
case 'top':
|
||||
this._state = 'top';
|
||||
break;
|
||||
case 'left':
|
||||
this._state = 'left';
|
||||
break;
|
||||
case 'bottom':
|
||||
this._state = 'bottom';
|
||||
break;
|
||||
case 'right':
|
||||
this._state = 'right';
|
||||
break;
|
||||
case 'center':
|
||||
this._state = 'center';
|
||||
break;
|
||||
}
|
||||
toggleClass(this.overlayElement, 'dv-overlay-small-vertical', isSmallY);
|
||||
toggleClass(
|
||||
this.overlayElement,
|
||||
'dv-overlay-small-horizontal',
|
||||
isSmallX
|
||||
);
|
||||
toggleClass(this.overlayElement, 'dv-overlay-left', isLeft);
|
||||
toggleClass(this.overlayElement, 'dv-overlay-right', isRight);
|
||||
toggleClass(this.overlayElement, 'dv-overlay-top', isTop);
|
||||
toggleClass(this.overlayElement, 'dv-overlay-bottom', isBottom);
|
||||
}
|
||||
|
||||
private calculateQuadrant(
|
||||
@ -302,14 +298,11 @@ export class Droptarget extends CompositeDisposable {
|
||||
width: number,
|
||||
height: number
|
||||
): Position | null {
|
||||
const isPercentage =
|
||||
this.options.overlayModel?.activationSize === undefined ||
|
||||
this.options.overlayModel?.activationSize?.type === 'percentage';
|
||||
const activationSizeOptions =
|
||||
this.options.overlayModel?.activationSize ??
|
||||
DEFAULT_ACTIVATION_SIZE;
|
||||
|
||||
const value = numberOrFallback(
|
||||
this.options?.overlayModel?.activationSize?.value,
|
||||
20
|
||||
);
|
||||
const isPercentage = activationSizeOptions.type === 'percentage';
|
||||
|
||||
if (isPercentage) {
|
||||
return calculateQuadrantAsPercentage(
|
||||
@ -318,7 +311,7 @@ export class Droptarget extends CompositeDisposable {
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
value
|
||||
activationSizeOptions.value
|
||||
);
|
||||
}
|
||||
|
||||
@ -328,7 +321,7 @@ export class Droptarget extends CompositeDisposable {
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
value
|
||||
activationSizeOptions.value
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,12 @@ import {
|
||||
getGridLocation,
|
||||
ISerializedLeafNode,
|
||||
} from '../gridview/gridview';
|
||||
import { directionToPosition, Droptarget, Position } from '../dnd/droptarget';
|
||||
import {
|
||||
directionToPosition,
|
||||
Droptarget,
|
||||
DroptargetOverlayModel,
|
||||
Position,
|
||||
} from '../dnd/droptarget';
|
||||
import { tail, sequenceEquals, remove } from '../array';
|
||||
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
||||
import { CompositeDisposable, Disposable } from '../lifecycle';
|
||||
@ -59,6 +64,11 @@ import {
|
||||
OverlayRenderContainer,
|
||||
} from '../overlayRenderContainer';
|
||||
|
||||
const DEFAULT_ROOT_OVERLAY_MODEL: DroptargetOverlayModel = {
|
||||
activationSize: { type: 'pixels', value: 10 },
|
||||
size: { type: 'pixels', value: 20 },
|
||||
};
|
||||
|
||||
function getTheme(element: HTMLElement): string | undefined {
|
||||
function toClassList(element: HTMLElement) {
|
||||
const list: string[] = [];
|
||||
@ -215,6 +225,7 @@ export type DockviewComponentUpdateOptions = Pick<
|
||||
| 'createPrefixHeaderActionsElement'
|
||||
| 'disableFloatingGroups'
|
||||
| 'floatingGroupBounds'
|
||||
| 'rootOverlayModel'
|
||||
>;
|
||||
|
||||
export interface DockviewDropEvent extends GroupviewDropEvent {
|
||||
@ -315,6 +326,7 @@ export class DockviewComponent
|
||||
|
||||
private readonly _floatingGroups: DockviewFloatingGroupPanel[] = [];
|
||||
private readonly _popoutGroups: DockviewPopoutGroupPanel[] = [];
|
||||
private readonly _rootDropTarget: Droptarget;
|
||||
|
||||
get orientation(): Orientation {
|
||||
return this.gridview.orientation;
|
||||
@ -420,7 +432,7 @@ export class DockviewComponent
|
||||
this.options.watermarkComponent = Watermark;
|
||||
}
|
||||
|
||||
const dropTarget = new Droptarget(this.element, {
|
||||
this._rootDropTarget = new Droptarget(this.element, {
|
||||
canDisplayOverlay: (event, position) => {
|
||||
const data = getPanelData();
|
||||
|
||||
@ -459,14 +471,12 @@ export class DockviewComponent
|
||||
return false;
|
||||
},
|
||||
acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
|
||||
overlayModel: {
|
||||
activationSize: { type: 'pixels', value: 10 },
|
||||
size: { type: 'pixels', value: 20 },
|
||||
},
|
||||
overlayModel:
|
||||
this.options.rootOverlayModel ?? DEFAULT_ROOT_OVERLAY_MODEL,
|
||||
});
|
||||
|
||||
this.addDisposables(
|
||||
dropTarget.onDrop((event) => {
|
||||
this._rootDropTarget.onDrop((event) => {
|
||||
const data = getPanelData();
|
||||
|
||||
if (data) {
|
||||
@ -485,7 +495,7 @@ export class DockviewComponent
|
||||
});
|
||||
}
|
||||
}),
|
||||
dropTarget
|
||||
this._rootDropTarget
|
||||
);
|
||||
|
||||
this._api = new DockviewApi(this);
|
||||
@ -716,20 +726,24 @@ export class DockviewComponent
|
||||
}
|
||||
|
||||
updateOptions(options: DockviewComponentUpdateOptions): void {
|
||||
const hasOrientationChanged =
|
||||
const changed_orientation =
|
||||
typeof options.orientation === 'string' &&
|
||||
this.gridview.orientation !== options.orientation;
|
||||
const hasFloatingGroupOptionsChanged =
|
||||
const changed_floatingGroupBounds =
|
||||
options.floatingGroupBounds !== undefined &&
|
||||
options.floatingGroupBounds !== this.options.floatingGroupBounds;
|
||||
|
||||
const changed_rootOverlayOptions =
|
||||
options.rootOverlayModel !== undefined &&
|
||||
options.rootOverlayModel !== this.options.rootOverlayModel;
|
||||
|
||||
this._options = { ...this.options, ...options };
|
||||
|
||||
if (hasOrientationChanged) {
|
||||
if (changed_orientation) {
|
||||
this.gridview.orientation = options.orientation!;
|
||||
}
|
||||
|
||||
if (hasFloatingGroupOptionsChanged) {
|
||||
if (changed_floatingGroupBounds) {
|
||||
for (const group of this._floatingGroups) {
|
||||
switch (this.options.floatingGroupBounds) {
|
||||
case 'boundedWithinViewport':
|
||||
@ -753,6 +767,10 @@ export class DockviewComponent
|
||||
}
|
||||
}
|
||||
|
||||
if (changed_rootOverlayOptions) {
|
||||
this._rootDropTarget.setOverlayModel(options.rootOverlayModel!);
|
||||
}
|
||||
|
||||
this.layout(this.gridview.width, this.gridview.height, true);
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
> .content-container {
|
||||
flex-grow: 1;
|
||||
overflow: hidden;
|
||||
min-height: 0;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||
import { ISplitviewStyles, Orientation } from '../splitview/splitview';
|
||||
import { PanelTransfer } from '../dnd/dataTransfer';
|
||||
import { IDisposable } from '../lifecycle';
|
||||
import { Position } from '../dnd/droptarget';
|
||||
import { DroptargetOverlayModel, Position } from '../dnd/droptarget';
|
||||
import { IDockviewPanel } from './dockviewPanel';
|
||||
import {
|
||||
ComponentConstructor,
|
||||
@ -100,6 +100,7 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
||||
popoutUrl?: string;
|
||||
defaultRenderer?: DockviewPanelRenderer;
|
||||
debug?: boolean;
|
||||
rootOverlayModel?: DroptargetOverlayModel;
|
||||
}
|
||||
|
||||
export interface PanelOptions<P extends object = Parameters> {
|
||||
|
@ -55,6 +55,8 @@ export {
|
||||
Position,
|
||||
positionToDirection,
|
||||
directionToPosition,
|
||||
MeasuredValue,
|
||||
DroptargetOverlayModel,
|
||||
} from './dnd/droptarget';
|
||||
export {
|
||||
FocusEvent,
|
||||
|
@ -45,6 +45,22 @@ export abstract class Resizable extends CompositeDisposable {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._element.offsetParent) {
|
||||
/**
|
||||
* offsetParent === null is equivalent to display: none being set on the element or one
|
||||
* of it's parents. In the display: none case the size will become (0, 0) which we do
|
||||
* not want to propagate.
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent
|
||||
*
|
||||
* You could use checkVisibility() but at the time of writing it's not supported across
|
||||
* all Browsers
|
||||
*
|
||||
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/checkVisibility
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isInDocument(this._element)) {
|
||||
/**
|
||||
* since the event is dispatched through requestAnimationFrame there is a small chance
|
||||
|
@ -11,6 +11,7 @@ import {
|
||||
DockviewGroupPanel,
|
||||
IHeaderActionsRenderer,
|
||||
DockviewPanelRenderer,
|
||||
DroptargetOverlayModel,
|
||||
} from 'dockview-core';
|
||||
import { ReactPanelContentPart } from './reactContentPart';
|
||||
import { ReactPanelHeaderPart } from './reactHeaderPart';
|
||||
@ -79,6 +80,7 @@ export interface IDockviewReactProps {
|
||||
};
|
||||
debug?: boolean;
|
||||
defaultRenderer?: DockviewPanelRenderer;
|
||||
rootOverlayModel?: DroptargetOverlayModel;
|
||||
}
|
||||
|
||||
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
||||
@ -180,6 +182,7 @@ export const DockviewReact = React.forwardRef(
|
||||
floatingGroupBounds: props.floatingGroupBounds,
|
||||
defaultRenderer: props.defaultRenderer,
|
||||
debug: props.debug,
|
||||
rootOverlayModel: props.rootOverlayModel,
|
||||
});
|
||||
|
||||
const { clientWidth, clientHeight } = domRef.current;
|
||||
@ -312,6 +315,15 @@ export const DockviewReact = React.forwardRef(
|
||||
});
|
||||
}, [props.leftHeaderActionsComponent]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!dockviewRef.current) {
|
||||
return;
|
||||
}
|
||||
dockviewRef.current.updateOptions({
|
||||
rootOverlayModel: props.rootOverlayModel,
|
||||
});
|
||||
}, [props.rootOverlayModel]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!dockviewRef.current) {
|
||||
return;
|
||||
|
@ -31,6 +31,7 @@ import DockviewKeyboard from '@site/sandboxes/keyboard-dockview/src/app';
|
||||
import DockviewPopoutGroup from '@site/sandboxes/popoutgroup-dockview/src/app';
|
||||
import DockviewMaximizeGroup from '@site/sandboxes/maximizegroup-dockview/src/app';
|
||||
import DockviewRenderMode from '@site/sandboxes/rendermode-dockview/src/app';
|
||||
import DockviewScrollbars from '@site/sandboxes/scrollbars-dockview/src/app';
|
||||
|
||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||
|
||||
@ -196,6 +197,22 @@ If you refresh the page you should notice your layout is loaded as you left it.
|
||||
react={DockviewPersistance}
|
||||
/>
|
||||
|
||||
## Scrollbars
|
||||
|
||||
Scrollbars will appear if the contents of your view has a fixed height. If you are using a relative height such
|
||||
as *100%* you will need to define an inner container with the appropiate `overflow` value to allow scrollbars to appear.
|
||||
|
||||
The following container three views:
|
||||
- **Panel 1**: Sets `height: 100%` and no scrollbar appears even, the content is clipped.
|
||||
- **Panel 2**: Sets `height: 2000px` and a scrollbar does appear since a fixed height has been used.
|
||||
- **Panel 3**: Sets `height: 100%` and defines an inner component with `overflow: auto` to enable the scrollbars.
|
||||
|
||||
|
||||
<MultiFrameworkContainer
|
||||
sandboxId="scrollbars-dockview"
|
||||
react={DockviewScrollbars}
|
||||
/>
|
||||
|
||||
## Resizing
|
||||
|
||||
### Panel Resizing
|
||||
|
34
packages/docs/sandboxes/scrollbars-dockview/package.json
Normal file
34
packages/docs/sandboxes/scrollbars-dockview/package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "scrollbars-dockview",
|
||||
"description": "",
|
||||
"keywords": [
|
||||
"dockview"
|
||||
],
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.tsx",
|
||||
"dependencies": {
|
||||
"dockview": "*",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/react": "^18.0.28",
|
||||
"@types/react-dom": "^18.0.11",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"react-scripts": "*"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test --env=jsdom",
|
||||
"eject": "react-scripts eject"
|
||||
},
|
||||
"browserslist": [
|
||||
">0.2%",
|
||||
"not dead",
|
||||
"not ie <= 11",
|
||||
"not op_mini all"
|
||||
]
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is added to the
|
||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||
-->
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,100..700,0..1,-50..200" />
|
||||
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<div id="root"></div>
|
||||
<!--
|
||||
This HTML file is a template.
|
||||
If you open it directly in the browser, you will see an empty page.
|
||||
|
||||
You can add webfonts, meta tags, or analytics to this file.
|
||||
The build step will place the bundled scripts into the <body> tag.
|
||||
|
||||
To begin the development, run `npm start` or `yarn start`.
|
||||
To create a production bundle, use `npm run build` or `yarn build`.
|
||||
-->
|
||||
</body>
|
||||
|
||||
</html>
|
16
packages/docs/sandboxes/scrollbars-dockview/src/app.scss
Normal file
16
packages/docs/sandboxes/scrollbars-dockview/src/app.scss
Normal file
@ -0,0 +1,16 @@
|
||||
.group-control {
|
||||
.action {
|
||||
padding: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-radius: 2px;
|
||||
background-color: var(--dv-icon-hover-background-color);
|
||||
}
|
||||
}
|
||||
}
|
77
packages/docs/sandboxes/scrollbars-dockview/src/app.tsx
Normal file
77
packages/docs/sandboxes/scrollbars-dockview/src/app.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import {
|
||||
DockviewReact,
|
||||
DockviewReadyEvent,
|
||||
IDockviewPanelProps,
|
||||
} from 'dockview';
|
||||
import './app.scss';
|
||||
|
||||
const TEXT =
|
||||
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
|
||||
|
||||
const components = {
|
||||
fixedHeightContainer: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div style={{ height: '100%', color: 'white' }}>
|
||||
{[TEXT, '\n\n'].join('').repeat(20)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
overflowContainer: (props: IDockviewPanelProps<{ title: string }>) => {
|
||||
return (
|
||||
<div style={{ height: '2000px', overflow: 'auto', color: 'white' }}>
|
||||
{[TEXT, '\n\n'].join('').repeat(20)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
userDefinedOverflowContainer: (
|
||||
props: IDockviewPanelProps<{ title: string }>
|
||||
) => {
|
||||
return (
|
||||
<div style={{ height: '100%', color: 'white' }}>
|
||||
<div
|
||||
style={{
|
||||
height: '100%',
|
||||
color: 'white',
|
||||
overflow: 'auto',
|
||||
}}
|
||||
>
|
||||
{[TEXT, '\n\n'].join('').repeat(20)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const DockviewComponent = (props: { theme?: string }) => {
|
||||
const onReady = (event: DockviewReadyEvent) => {
|
||||
event.api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'fixedHeightContainer',
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'overflowContainer',
|
||||
title: 'Panel 2',
|
||||
position: { direction: 'right' },
|
||||
});
|
||||
|
||||
event.api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'userDefinedOverflowContainer',
|
||||
title: 'Panel 3',
|
||||
position: { direction: 'right' },
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DockviewReact
|
||||
components={components}
|
||||
onReady={onReady}
|
||||
className={props.theme || 'dockview-theme-abyss'}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default DockviewComponent;
|
20
packages/docs/sandboxes/scrollbars-dockview/src/index.tsx
Normal file
20
packages/docs/sandboxes/scrollbars-dockview/src/index.tsx
Normal file
@ -0,0 +1,20 @@
|
||||
import { StrictMode } from 'react';
|
||||
import * as ReactDOMClient from 'react-dom/client';
|
||||
import './styles.css';
|
||||
import 'dockview/dist/styles/dockview.css';
|
||||
|
||||
import App from './app';
|
||||
|
||||
const rootElement = document.getElementById('root');
|
||||
|
||||
if (rootElement) {
|
||||
const root = ReactDOMClient.createRoot(rootElement);
|
||||
|
||||
root.render(
|
||||
<StrictMode>
|
||||
<div className="app">
|
||||
<App />
|
||||
</div>
|
||||
</StrictMode>
|
||||
);
|
||||
}
|
16
packages/docs/sandboxes/scrollbars-dockview/src/styles.css
Normal file
16
packages/docs/sandboxes/scrollbars-dockview/src/styles.css
Normal file
@ -0,0 +1,16 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
18
packages/docs/sandboxes/scrollbars-dockview/tsconfig.json
Normal file
18
packages/docs/sandboxes/scrollbars-dockview/tsconfig.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "build/dist",
|
||||
"module": "esnext",
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom"],
|
||||
"sourceMap": true,
|
||||
"allowJs": true,
|
||||
"jsx": "react-jsx",
|
||||
"moduleResolution": "node",
|
||||
"rootDir": "src",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noImplicitAny": true,
|
||||
"strictNullChecks": true
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user