chore: remove old docs

This commit is contained in:
mathuo 2024-11-15 20:36:26 +00:00
parent 83b01a9a66
commit e46a586044
No known key found for this signature in database
GPG Key ID: C6EEDEFD6CA07281
209 changed files with 0 additions and 9925 deletions

View File

@ -6,41 +6,6 @@
"packages/dockview"
],
"sandboxes": [
"/packages/docs/sandboxes/constraints-dockview",
"/packages/docs/sandboxes/customheader-dockview",
"/packages/docs/sandboxes/demo-dockview",
"/packages/docs/sandboxes/dnd-dockview",
"/packages/docs/sandboxes/dockview-app",
"/packages/docs/sandboxes/editor-gridview",
"/packages/docs/sandboxes/events-dockview",
"/packages/docs/sandboxes/externaldnd-dockview",
"/packages/docs/sandboxes/floatinggroup-dockview",
"/packages/docs/sandboxes/fullwidthtab-dockview",
"/packages/docs/sandboxes/headeractions-dockview",
"/packages/docs/sandboxes/groupcontol-dockview",
"/packages/docs/sandboxes/iframe-dockview",
"/packages/docs/sandboxes/keyboard-dockview",
"/packages/docs/sandboxes/layout-dockview",
"/packages/docs/sandboxes/lockedgroup-dockview",
"/packages/docs/sandboxes/maximizegroup-dockview",
"/packages/docs/sandboxes/nativeapp-dockview",
"/packages/docs/sandboxes/nested-dockview",
"/packages/docs/sandboxes/popoutgroup-dockview",
"/packages/docs/sandboxes/rendering-dockview",
"/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",
"/packages/docs/sandboxes/tabheight-dockview",
"/packages/docs/sandboxes/updatetitle-dockview",
"/packages/docs/sandboxes/watermark-dockview",
"/packages/docs/sandboxes/javascript/fullwidthtab-dockview",
"/packages/docs/sandboxes/javascript/simple-dockview",
"/packages/docs/sandboxes/javascript/tabheight-dockview",
"/packages/docs/sandboxes/javascript/vanilla-dockview"
],
"node": "18"
}

View File

@ -1,32 +0,0 @@
{
"name": "customheader-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,122 +0,0 @@
import {
DockviewDefaultTab,
DockviewReact,
DockviewReadyEvent,
IDockviewPanelHeaderProps,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
interface CustomProps {
valueA: string;
}
const components = {
default: (props: IDockviewPanelProps<CustomProps>) => {
return <div style={{ padding: '20px' }}>{props.api.title}</div>;
},
};
const headerComponents = {
default: (props: IDockviewPanelHeaderProps<CustomProps>) => {
const onContextMenu = (event: React.MouseEvent) => {
event.preventDefault();
alert(
`This custom header was parsed the params ${JSON.stringify(
props.params
)}`
);
};
return <DockviewDefaultTab onContextMenu={onContextMenu} {...props} />;
},
};
const CustomHeadersDockview = (props: { theme?: string }) => {
const onReady = (event: DockviewReadyEvent) => {
event.api.addPanel({
id: 'panel_1',
component: 'default',
title: 'Panel 1',
params: {
valueA: 'test value',
},
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
title: 'Panel 2',
params: {
valueA: 'test value',
},
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
title: 'Panel 3',
params: {
valueA: 'test value',
},
});
event.api.addPanel({
id: 'panel_4',
component: 'default',
title: 'Panel 4',
position: { referencePanel: 'panel_3', direction: 'right' },
params: {
valueA: 'test value',
},
});
event.api.addPanel({
id: 'panel_5',
component: 'default',
title: 'Panel 5',
position: { referencePanel: 'panel_4', direction: 'within' },
params: {
valueA: 'test value',
},
});
const panel6 = event.api.addPanel({
id: 'panel_6',
component: 'default',
title: 'Panel 6',
position: { referencePanel: 'panel_4', direction: 'below' },
params: {
valueA: 'test value',
},
});
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' },
params: {
valueA: 'test value',
},
});
event.api.addPanel({
id: 'panel_8',
component: 'default',
title: 'Panel 8',
position: { referencePanel: 'panel_7', direction: 'within' },
params: {
valueA: 'test value',
},
});
event.api.addGroup();
};
return (
<DockviewReact
components={components}
defaultTabComponent={headerComponents.default}
onReady={onReady}
className={`${props.theme || 'dockview-theme-abyss'}`}
/>
);
};
export default CustomHeadersDockview;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "events-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,346 +0,0 @@
import {
Orientation,
DockviewReact,
DockviewReadyEvent,
DockviewApi,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
import { Console, Line } from './console';
const components = {
default: (props: IDockviewPanelProps<{ title: string }>) => {
return <div style={{ padding: '20px' }}>{props.params.title}</div>;
},
};
const EventsDockview = (props: { theme?: string }) => {
const [lines, setLines] = React.useState<Line[]>([]);
const [checked, setChecked] = React.useState<boolean>(false);
const [api, setApi] = React.useState<DockviewApi | undefined>();
React.useEffect(() => {
if (!api) {
return () => {
//noop
};
}
const disposables = [
api.onDidAddPanel((panel) => {
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `onDidAddPanel: ${panel.id}`,
},
]);
}),
api.onDidRemovePanel((panel) => {
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `onDidRemovePanel: ${panel.id}`,
},
]);
}),
api.onDidActivePanelChange((panel) => {
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `onDidActivePanelChange: ${panel?.id}`,
},
]);
}),
api.onDidAddGroup((panel) => {
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `onDidAddGroup: ${panel.id}`,
},
]);
}),
api.onDidRemoveGroup((panel) => {
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `onDidRemoveGroup: ${panel.id}`,
},
]);
}),
api.onDidActiveGroupChange((panel) => {
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `onDidActiveGroupChange: ${panel?.id}`,
},
]);
}),
api.onDidLayoutChange((panel) => {
setLines((lines) => [
...lines,
{ timestamp: new Date(), text: `onDidLayoutChange` },
]);
}),
api.onDidLayoutFromJSON((panel) => {
setLines((lines) => [
...lines,
{ timestamp: new Date(), text: `onDidLayoutFromJSON` },
]);
}),
];
return () => {
disposables.forEach((disposable) => disposable.dispose());
};
}, [api]);
React.useEffect(() => {
if (!api) {
return;
}
setLines((lines) => [
...lines,
{
timestamp: new Date(),
text: `Rebuilding view fromJSON:${checked}`,
css: { color: 'yellow', backgroundColor: 'grey' },
},
]);
if (checked) {
api.fromJSON({
grid: {
root: {
type: 'branch',
data: [
{
type: 'leaf',
data: {
views: ['panel_1', 'panel_2', 'panel_3'],
activeView: 'panel_3',
id: '77',
},
size: 262,
},
{
type: 'branch',
data: [
{
type: 'leaf',
data: {
views: ['panel_5'],
activeView: 'panel_5',
id: '79',
},
size: 100,
},
{
type: 'leaf',
data: {
views: ['panel_6', 'panel_8'],
activeView: 'panel_8',
id: '80',
},
size: 100,
},
{
type: 'leaf',
data: {
views: ['panel_7'],
activeView: 'panel_7',
id: '81',
},
size: 100,
},
],
size: 262,
},
{
type: 'leaf',
data: {
views: ['panel_4'],
activeView: 'panel_4',
id: '78',
},
size: 263.75,
},
],
size: 300,
},
width: 787.75,
height: 300,
orientation: Orientation.HORIZONTAL,
},
panels: {
panel_1: {
id: 'panel_1',
contentComponent: 'default',
params: { title: 'Panel 1' },
title: 'panel_1',
},
panel_2: {
id: 'panel_2',
contentComponent: 'default',
params: { title: 'Panel 2' },
title: 'panel_2',
},
panel_3: {
id: 'panel_3',
contentComponent: 'default',
params: { title: 'Panel 3' },
title: 'panel_3',
},
panel_4: {
id: 'panel_4',
contentComponent: 'default',
params: { title: 'Panel 4' },
title: 'panel_4',
},
panel_5: {
id: 'panel_5',
contentComponent: 'default',
params: { title: 'Panel 5' },
title: 'panel_5',
},
panel_6: {
id: 'panel_6',
contentComponent: 'default',
params: { title: 'Panel 6' },
title: 'panel_6',
},
panel_8: {
id: 'panel_8',
contentComponent: 'default',
params: { title: 'Panel 8' },
title: 'panel_8',
},
panel_7: {
id: 'panel_7',
contentComponent: 'default',
params: { title: 'Panel 7' },
title: 'panel_7',
},
},
activeGroup: '80',
});
return;
}
api.clear();
api.addPanel({
id: 'panel_1',
component: 'default',
params: {
title: 'Panel 1',
},
});
api.addPanel({
id: 'panel_2',
component: 'default',
params: {
title: 'Panel 2',
},
});
api.addPanel({
id: 'panel_3',
component: 'default',
params: {
title: 'Panel 3',
},
});
api.addPanel({
id: 'panel_4',
component: 'default',
params: {
title: 'Panel 4',
},
position: { referencePanel: 'panel_1', direction: 'right' },
});
api.addPanel({
id: 'panel_5',
component: 'default',
params: {
title: 'Panel 5',
},
position: { referencePanel: 'panel_3', direction: 'right' },
});
api.addPanel({
id: 'panel_6',
component: 'default',
params: {
title: 'Panel 6',
},
position: { referencePanel: 'panel_5', direction: 'below' },
});
api.addPanel({
id: 'panel_7',
component: 'default',
params: {
title: 'Panel 7',
},
position: { referencePanel: 'panel_6', direction: 'below' },
});
api.addPanel({
id: 'panel_8',
component: 'default',
params: {
title: 'Panel 8',
},
position: { referencePanel: 'panel_6', direction: 'within' },
});
}, [api, checked]);
const onReady = (event: DockviewReadyEvent) => {
setApi(event.api);
};
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
height: '100%',
}}
>
<div>
<label>
<input
type="checkbox"
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>
<span>{'fromJSON'}</span>
</label>
<button onClick={() => setLines([])}>Clear logs</button>
</div>
<div style={{ flexGrow: 1 }}>
<DockviewReact
components={components}
onReady={onReady}
className={`${props.theme || 'dockview-theme-abyss'}`}
/>
</div>
<div style={{ height: '200px', paddingTop: '5px' }}>
<Console lines={lines} />
</div>
</div>
);
};
export default EventsDockview;

View File

@ -1,27 +0,0 @@
.console-container {
background-color: black;
color: white;
padding-left: 8px;
max-height: 200px;
overflow-y: scroll;
overflow-x: auto;
.console-line {
height: 20px;
line-height: 20px;
font-size: 13px;
border-bottom: 1px solid rgb(30, 30, 30);
display: flex;
padding-left: 4px;
.console-line-timestamp {
color: lightgray;
padding-right: 4px;
}
.console-line-text {
padding: 0px 4px;
flex-grow: 1;
}
}
}

View File

@ -1,52 +0,0 @@
import * as React from 'react';
import './console.scss';
const formatTime = (now: Date) => {
const pad = (x: number) => (x < 10 ? `0${x}` : `${x}`);
return `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(
now.getSeconds()
)}.${now.getMilliseconds()}`;
};
export interface Line {
timestamp: Date;
text: string;
css?: React.CSSProperties;
}
export interface IConsoleProps {
lines: Line[];
}
export const Console = (props: IConsoleProps) => {
const ref = React.useRef<HTMLDivElement>(null);
React.useLayoutEffect(() => {
if (!ref.current) {
return;
}
ref.current.scrollTop = Math.max(
0,
ref.current.scrollHeight - ref.current.clientHeight
);
}, [props.lines]);
return (
<div ref={ref} className="console-container">
{props.lines.map((line, i) => {
return (
<div key={i} className="console-line">
<span className="console-line-timestamp">
{formatTime(line.timestamp)}
</span>
<span className="console-line-text" style={line.css}>
{line.text}
</span>
</div>
);
})}
</div>
);
};

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "focus-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,125 +0,0 @@
import {
DockviewApi,
DockviewReact,
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IDockviewPanelProps) => {
React.useEffect(() => {
const d1 = props.api.onWillFocus((event) => {
console.log('willFocus');
});
const d2 = props.api.onDidActiveChange((event) => {
console.log(props.api.title, event, 'active');
});
const d3 = props.api.onDidActiveGroupChange((event) => {
console.log(
props.api.title,
props.api.group.api.isActive,
'active-group'
);
});
const d4 = props.api.onDidGroupChange((event) => {
console.log(
props.api.title,
props.api.group.id,
'group-change'
);
});
return () => {
d1.dispose();
d2.dispose();
d3.dispose();
};
}, [props.api]);
return (
<div style={{ padding: '20px', color: 'white' }}>
{props.api.title}
</div>
);
},
};
export const App: React.FC = (props: { theme?: string }) => {
const [api, setApi] = React.useState<DockviewApi>();
const onReady = (event: DockviewReadyEvent) => {
setApi(event.api);
event.api.addPanel({
id: 'panel_1',
title: 'Panel 1',
component: 'default',
});
event.api.addPanel({
id: 'panel_2',
title: 'Panel 2',
component: 'default',
});
// event.api.onDidAddPanel((event) => {
// console.log('add panel', event);
// });
// event.api.onDidActivePanelChange((event) => {
// console.log('active panel', event);
// });
// event.api.onDidRemovePanel((event) => {
// console.log('remove panel', event);
// });
};
return (
<div
style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
>
<div>
<button
onClick={() => {
api?.getPanel('panel_1')?.focus();
}}
>
{'Focus Panel 1'}
</button>
<button
onClick={() => {
api?.getPanel('panel_2')?.focus();
}}
>
{'Focus Panel 2'}
</button>
<button
onClick={() => {
api?.getPanel('panel_1')?.api.setActive();
}}
>
{'Active Panel 1'}
</button>
<button
onClick={() => {
api?.getPanel('panel_2')?.api.setActive();
}}
>
{'Active Panel 2'}
</button>
</div>
<div style={{ flexGrow: 1 }}>
<DockviewReact
components={components}
onReady={onReady}
className={props.theme || 'dockview-theme-abyss'}
/>
</div>
</div>
);
};
export default App;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,28 +0,0 @@
{
"name": "javascript-simple-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.ts",
"dependencies": {
"dockview-core": "*"
},
"devDependencies": {
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,120 +0,0 @@
import {
DockviewComponent,
IContentRenderer,
IGroupPanelInitParameters,
PanelUpdateEvent,
Parameters,
} from 'dockview-core';
class DefaultPanel implements IContentRenderer {
private _element: HTMLElement;
get element(): HTMLElement {
return this._element;
}
constructor() {
this._element = document.createElement('div');
this._element.style.padding = '20px';
this._element.style.color = 'white';
}
init(params: IGroupPanelInitParameters): void {
this._element.textContent = params.params.title;
}
update(event: PanelUpdateEvent<Parameters>): void {
this._element.textContent = event.params.title;
}
}
export function attach(parent: HTMLElement): {
dispose: () => void;
} {
const element = document.createElement('div');
element.className = 'dockview-theme-abyss';
element.style.height = '100%';
element.style.width = '100%';
const dockview = new DockviewComponent({
components: {
default: DefaultPanel,
},
parentElement: element,
});
parent.appendChild(element);
const { clientWidth, clientHeight } = parent;
dockview.layout(clientWidth, clientHeight);
const panel = dockview.addPanel({
id: 'panel_1',
component: 'default',
params: {
title: 'Panel 1',
},
});
panel.group.locked = true;
panel.group.header.hidden = true;
dockview.addPanel({
id: 'panel_2',
component: 'default',
params: {
title: 'Panel 2',
},
});
dockview.addPanel({
id: 'panel_3',
component: 'default',
params: {
title: 'Panel 3',
},
});
dockview.addPanel({
id: 'panel_4',
component: 'default',
params: {
title: 'Panel 4',
},
position: { referencePanel: 'panel_1', direction: 'right' },
});
const panel5 = dockview.addPanel({
id: 'panel_5',
component: 'default',
params: {
title: 'Panel 5',
},
position: { referencePanel: 'panel_3', direction: 'right' },
});
dockview.addPanel({
id: 'panel_6',
component: 'default',
params: {
title: 'Panel 6',
},
position: { referencePanel: 'panel_5', direction: 'below' },
});
dockview.addPanel({
id: 'panel_7',
component: 'default',
params: {
title: 'Panel 7',
},
position: { referencePanel: 'panel_6', direction: 'right' },
});
return {
dispose: () => {
dockview.dispose();
element.remove();
},
};
}

View File

@ -1,10 +0,0 @@
import './styles.css';
import 'dockview-core/dist/styles/dockview.css';
import { attach } from './app';
const rootElement = document.getElementById('root');
if (rootElement) {
attach(rootElement);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,28 +0,0 @@
{
"name": "javascript-tabheight-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.ts",
"dependencies": {
"dockview-core": "*"
},
"devDependencies": {
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,3 +0,0 @@
.skinny-tabs {
--dv-tabs-and-actions-container-height: 20px;
}

View File

@ -1,110 +0,0 @@
import {
DockviewComponent,
IContentRenderer,
IGroupPanelInitParameters,
PanelUpdateEvent,
Parameters,
} from 'dockview-core';
import './app.scss';
class DefaultPanel implements IContentRenderer {
private _element: HTMLElement;
get element(): HTMLElement {
return this._element;
}
constructor() {
this._element = document.createElement('div');
this._element.style.padding = '20px';
this._element.style.color = 'white';
}
init(params: IGroupPanelInitParameters): void {
this._element.textContent = params.params.title;
}
update(event: PanelUpdateEvent<Parameters>): void {
this._element.textContent = event.params.title;
}
}
export function attach(parent: HTMLElement): {
dispose: () => void;
} {
const element = document.createElement('div');
element.className = 'dockview-theme-abyss skinny-tabs';
element.style.height = '100%';
element.style.width = '100%';
const dockview = new DockviewComponent({
components: {
default: DefaultPanel,
},
parentElement: element,
});
parent.appendChild(element);
const { clientWidth, clientHeight } = parent;
dockview.layout(clientWidth, clientHeight);
dockview.addPanel({
id: 'panel_1',
component: 'default',
params: {
title: 'Panel 1',
},
});
dockview.addPanel({
id: 'panel_2',
component: 'default',
params: {
title: 'Panel 2',
},
});
dockview.addPanel({
id: 'panel_3',
component: 'default',
params: {
title: 'Panel 3',
},
position: { referencePanel: 'panel_1', direction: 'right' },
});
dockview.addPanel({
id: 'panel_4',
component: 'default',
params: {
title: 'Panel 4',
},
position: { referencePanel: 'panel_3', direction: 'right' },
});
dockview.addPanel({
id: 'panel_5',
component: 'default',
params: {
title: 'Panel 5',
},
position: { referencePanel: 'panel_4', direction: 'below' },
});
dockview.addPanel({
id: 'panel_6',
component: 'default',
params: {
title: 'Panel 6',
},
position: { referencePanel: 'panel_5', direction: 'right' },
});
return {
dispose: () => {
dockview.dispose();
element.remove();
},
};
}

View File

@ -1,10 +0,0 @@
import './styles.css';
import 'dockview-core/dist/styles/dockview.css';
import { attach } from './app';
const rootElement = document.getElementById('root');
if (rootElement) {
attach(rootElement);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,28 +0,0 @@
{
"name": "javascript-vanilla-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.ts",
"dependencies": {
"dockview-core": "*"
},
"devDependencies": {
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,80 +0,0 @@
import {
DockviewComponent,
IContentRenderer,
IGroupPanelInitParameters,
} from 'dockview-core';
class DefaultPanel implements IContentRenderer {
private _element: HTMLElement;
get element(): HTMLElement {
return this._element;
}
constructor() {
this._element = document.createElement('div');
}
init(params: IGroupPanelInitParameters): void {
//
}
}
export function attach(parent: HTMLElement): {
dispose: () => void;
} {
const element = document.createElement('div');
element.className = 'dockview-theme-abyss';
element.style.height = '100%';
element.style.width = '100%';
const dockview = new DockviewComponent({
components: {
default: DefaultPanel,
},
parentElement: element,
});
parent.appendChild(element);
const panel1 = dockview.addPanel({
id: 'panel_1',
title: 'Panel 1',
component: 'default',
});
const panel2 = dockview.addPanel({
id: 'panel_2',
title: 'Panel 2',
component: 'default',
position: {
referencePanel: panel1,
direction: 'right',
},
});
const panel3 = dockview.addPanel({
id: 'panel_3',
title: 'Panel 3',
component: 'default',
position: {
referenceGroup: panel2.group,
},
});
const pane4 = dockview.addPanel({
id: 'panel_4',
title: 'Panel 4',
component: 'default',
position: {
direction: 'below',
},
});
return {
dispose: () => {
dockview.dispose();
element.remove();
},
};
}

View File

@ -1,10 +0,0 @@
import './styles.css';
import 'dockview-core/dist/styles/dockview.css';
import { attach } from './app';
const rootElement = document.getElementById('root');
if (rootElement) {
attach(rootElement);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "lockedgroup-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,71 +0,0 @@
import {
DockviewReact,
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IDockviewPanelProps<{ title: string }>) => {
return (
<div style={{ padding: '20px', color: 'white' }}>
{props.params.title}
</div>
);
},
};
export const App: React.FC = (props: { theme?: string }) => {
const onReady = (event: DockviewReadyEvent) => {
const panel1 = event.api.addPanel({
id: 'locked1',
component: 'default',
params: {
title: 'Locked',
},
});
panel1.group.locked = true;
panel1.group.header.hidden = true;
event.api.addPanel({
id: 'Drag me',
component: 'default',
params: {
title: '',
},
position: { referencePanel: 'locked1', direction: 'right' },
});
event.api.addPanel({
id: 'Drag me too',
component: 'default',
params: {
title: '',
},
position: { referencePanel: 'Drag me', direction: 'right' },
});
const panel3 = event.api.addPanel({
id: 'locked2',
component: 'default',
params: {
title: 'Locked with no drop target',
},
position: { referencePanel: 'Drag me too', direction: 'right' },
});
panel3.group.locked = 'no-drop-target';
panel3.group.header.hidden = true;
};
return (
<DockviewReact
components={components}
onReady={onReady}
className={props.theme || 'dockview-theme-abyss'}
/>
);
};
export default App;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "nested-dockview",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,12 +0,0 @@
.nested-dockview {
position: relative;
&::after {
content: '';
position: absolute;
top: 0px;
left: 0px;
height: 1px;
width: 100%;
background-color: var(--dv-separator-border);
}
}

View File

@ -1,95 +0,0 @@
import {
DockviewDndOverlayEvent,
DockviewDropEvent,
DockviewReact,
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
import './app.scss';
const InnerDockview = () => {
const onReady = (event: DockviewReadyEvent) => {
event.api.addPanel({
id: 'panel_1',
component: 'default',
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
});
};
return (
<DockviewReact
onReady={onReady}
components={components}
className="nested-dockview"
/>
);
};
const components = {
default: (props: IDockviewPanelProps<{ title: string }>) => {
return (
<div
style={{
height: '100%',
padding: '20px',
background: 'var(--dv-group-view-background-color)',
}}
>
{props.params.title}
</div>
);
},
innerDockview: InnerDockview,
};
const NestedDockview = (props: { theme?: string }) => {
const onReady = (event: DockviewReadyEvent) => {
event.api.addPanel({
id: 'panel_1',
component: 'default',
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
});
event.api.addPanel({
id: 'panel_3',
component: 'innerDockview',
position: { referencePanel: 'panel_2', direction: 'right' },
});
};
const showDndOverlay = (event: DockviewDndOverlayEvent) => {
// console.log(event.getData());
return false;
};
const onDidDrop = (event: DockviewDropEvent) => {
// event.getData();
};
return (
<DockviewReact
onReady={onReady}
components={components}
className={`${props.theme || 'dockview-theme-abyss'}`}
showDndOverlay={showDndOverlay}
onDidDrop={onDidDrop}
/>
);
};
export default NestedDockview;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "dockview.constraints",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,148 +0,0 @@
import {
DockviewApi,
DockviewReact,
DockviewReadyEvent,
GridConstraintChangeEvent,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IDockviewPanelProps) => {
const [contraints, setContraints] =
React.useState<GridConstraintChangeEvent | null>(null);
React.useEffect(() => {
props.api.group.api.onDidConstraintsChange((event) => {
setContraints(event);
});
}, []);
const onClick = () => {
props.api.group.api.setConstraints({
maximumWidth: 300,
maximumHeight: 300,
});
};
return (
<div
style={{
height: '100%',
padding: '20px',
background: 'var(--dv-group-view-background-color)',
color: 'white',
}}
>
<button onClick={onClick}>Set</button>
{contraints && (
<div style={{ fontSize: '13px' }}>
{typeof contraints.maximumHeight === 'number' && (
<div
style={{
border: '1px solid grey',
margin: '2px',
padding: '1px',
}}
>
<span
style={{ color: 'grey' }}
>{`Maximum Height: `}</span>
<span>{`${contraints.maximumHeight}px`}</span>
</div>
)}
{typeof contraints.minimumHeight === 'number' && (
<div
style={{
border: '1px solid grey',
margin: '2px',
padding: '1px',
}}
>
<span
style={{ color: 'grey' }}
>{`Minimum Height: `}</span>
<span>{`${contraints.minimumHeight}px`}</span>
</div>
)}
{typeof contraints.maximumWidth === 'number' && (
<div
style={{
border: '1px solid grey',
margin: '2px',
padding: '1px',
}}
>
<span
style={{ color: 'grey' }}
>{`Maximum Width: `}</span>
<span>{`${contraints.maximumWidth}px`}</span>
</div>
)}
{typeof contraints.minimumWidth === 'number' && (
<div
style={{
border: '1px solid grey',
margin: '2px',
padding: '1px',
}}
>
<span
style={{ color: 'grey' }}
>{`Minimum Width: `}</span>
<span>{`${contraints.minimumWidth}px`}</span>
</div>
)}
</div>
)}
</div>
);
},
};
const App = (props: { theme?: string }) => {
const [api, setApi] = React.useState<DockviewApi>();
const onReady = (event: DockviewReadyEvent) => {
const panel1 = event.api.addPanel({
id: 'panel_1',
component: 'default',
});
const panel2 = event.api.addPanel({
id: 'panel_2',
component: 'default',
position: {
referencePanel: panel1,
direction: 'right',
},
});
const panel3 = event.api.addPanel({
id: 'panel_3',
component: 'default',
position: {
referencePanel: panel2,
direction: 'right',
},
});
const panel4 = event.api.addPanel({
id: 'panel_4',
component: 'default',
position: {
direction: 'below',
},
});
};
return (
<DockviewReact
onReady={onReady}
components={components}
className={`${props.theme || 'dockview-theme-abyss'}`}
/>
);
};
export default App;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,34 +0,0 @@
{
"name": "dockview.demo",
"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"
]
}

View File

@ -1,45 +0,0 @@
<!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>

View File

@ -1,96 +0,0 @@
.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);
}
}
}
.data-table {
table {
font-size: 11px;
th {
padding: 0px 8px;
}
}
}
.action-container {
display: flex;
padding: 4px 0px;
overflow: auto;
button {
height: 25px;
display: flex;
align-items: center;
justify-content: center;
background-color: #1c254a;
color: white;
border: none;
cursor: pointer;
outline: 1px solid #4c65d4;
&:hover {
background-color: #222e62;
}
}
.text-button {
margin: 0px 4px;
}
.button-action {
margin: 0px 4px;
// display: flex;
.selected {
background-color: #4864dc;
}
}
.button-group {
button {
margin-right: 0px;
}
}
.demo-button {
min-width: 50px;
padding: 0px 2px;
border-radius: 0px;
display: flex;
flex-grow: 1;
align-items: center;
outline: 1px solid #4c65d4;
}
.demo-icon-button {
outline: 1px solid #4c65d4;
flex-grow: 1;
display: flex;
align-items: center;
border-radius: 0px;
padding: 0px 4px;
border: none;
cursor: pointer;
&:disabled {
color: gray;
cursor: help;
}
span {
font-size: 16px;
}
}
}

View File

@ -1,431 +0,0 @@
import {
DockviewDefaultTab,
DockviewReact,
DockviewReadyEvent,
IDockviewPanelHeaderProps,
IDockviewPanelProps,
DockviewApi,
} from 'dockview';
import * as React from 'react';
import './app.scss';
import { defaultConfig } from './defaultLayout';
import { GridActions } from './gridActions';
import { PanelActions } from './panelActions';
import { GroupActions } from './groupActions';
import { LeftControls, PrefixHeaderControls, RightControls } from './controls';
import { Table, usePanelApiMetadata } from './debugPanel';
const DebugContext = React.createContext<boolean>(false);
const Option = (props: {
title: string;
onClick: () => void;
value: string;
}) => {
return (
<div>
<span>{`${props.title}: `}</span>
<button onClick={props.onClick}>{props.value}</button>
</div>
);
};
const components = {
default: (props: IDockviewPanelProps) => {
const isDebug = React.useContext(DebugContext);
const metadata = usePanelApiMetadata(props.api);
return (
<div
style={{
height: '100%',
overflow: 'auto',
position: 'relative',
padding: 5,
border: isDebug ? '2px dashed orange' : '',
}}
>
<span
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%,-50%)',
pointerEvents: 'none',
fontSize: '42px',
opacity: 0.5,
}}
>
{props.api.title}
</span>
{isDebug && (
<div style={{ fontSize: '0.8em' }}>
<Option
title="Panel Rendering Mode"
value={metadata.renderer.value}
onClick={() =>
props.api.setRenderer(
props.api.renderer === 'always'
? 'onlyWhenVisible'
: 'always'
)
}
/>
<Table data={metadata} />
</div>
)}
</div>
);
},
nested: (props: IDockviewPanelProps) => {
return (
<DockviewReact
components={components}
onReady={(event: DockviewReadyEvent) => {
event.api.addPanel({ id: 'panel_1', component: 'default' });
event.api.addPanel({ id: 'panel_2', component: 'default' });
event.api.addPanel({
id: 'panel_3',
component: 'default',
floating: true,
});
}}
className={'dockview-theme-abyss'}
/>
);
},
iframe: (props: IDockviewPanelProps) => {
return (
<iframe
onMouseDown={() => {
if (!props.api.isActive) {
props.api.setActive();
}
}}
style={{
width: '100%',
height: '100%',
}}
src="https://dockview.dev"
/>
);
},
};
const headerComponents = {
default: (props: IDockviewPanelHeaderProps) => {
const onContextMenu = (event: React.MouseEvent) => {
event.preventDefault();
alert('context menu');
};
return <DockviewDefaultTab onContextMenu={onContextMenu} {...props} />;
},
};
const colors = [
'rgba(255,0,0,0.2)',
'rgba(0,255,0,0.2)',
'rgba(0,0,255,0.2)',
'rgba(255,255,0,0.2)',
'rgba(0,255,255,0.2)',
'rgba(255,0,255,0.2)',
];
let count = 0;
const WatermarkComponent = () => {
return <div>custom watermark</div>;
};
const DockviewDemo = (props: { theme?: string }) => {
const [logLines, setLogLines] = React.useState<
{ text: string; timestamp?: Date; backgroundColor?: string }[]
>([]);
const [panels, setPanels] = React.useState<string[]>([]);
const [groups, setGroups] = React.useState<string[]>([]);
const [api, setApi] = React.useState<DockviewApi>();
const [activePanel, setActivePanel] = React.useState<string>();
const [activeGroup, setActiveGroup] = React.useState<string>();
const [pending, setPending] = React.useState<
{ text: string; timestamp?: Date }[]
>([]);
const addLogLine = (message: string) => {
setPending((line) => [
{ text: message, timestamp: new Date() },
...line,
]);
};
React.useLayoutEffect(() => {
if (pending.length === 0) {
return;
}
const color = colors[count++ % colors.length];
setLogLines((lines) => [
...pending.map((_) => ({ ..._, backgroundColor: color })),
...lines,
]);
setPending([]);
}, [pending]);
const onReady = (event: DockviewReadyEvent) => {
setApi(event.api);
event.api.onDidAddPanel((event) => {
setPanels((_) => [..._, event.id]);
addLogLine(`Panel Added ${event.id}`);
});
event.api.onDidActivePanelChange((event) => {
setActivePanel(event?.id);
addLogLine(`Panel Activated ${event?.id}`);
});
event.api.onDidRemovePanel((event) => {
setPanels((_) => {
const next = [..._];
next.splice(
next.findIndex((x) => x === event.id),
1
);
return next;
});
addLogLine(`Panel Removed ${event.id}`);
});
event.api.onDidAddGroup((event) => {
setGroups((_) => [..._, event.id]);
addLogLine(`Group Added ${event.id}`);
});
event.api.onDidMovePanel((event) => {
addLogLine(`Panel Moved ${event.panel.id}`);
});
event.api.onDidRemoveGroup((event) => {
setGroups((_) => {
const next = [..._];
next.splice(
next.findIndex((x) => x === event.id),
1
);
return next;
});
addLogLine(`Group Removed ${event.id}`);
});
event.api.onDidActiveGroupChange((event) => {
setActiveGroup(event?.id);
addLogLine(`Group Activated ${event?.id}`);
});
const state = localStorage.getItem('dv-demo-state');
if (state) {
try {
event.api.fromJSON(JSON.parse(state));
return;
} catch {
localStorage.removeItem('dv-demo-state');
}
return;
}
defaultConfig(event.api);
};
const [watermark, setWatermark] = React.useState<boolean>(false);
const [gapCheck, setGapCheck] = React.useState<boolean>(false);
const css = React.useMemo(() => {
if (!gapCheck) {
return {};
}
return {
'--dv-group-gap-size': '0.5rem',
'--demo-border': '5px dashed purple',
} as React.CSSProperties;
}, [gapCheck]);
const [showLogs, setShowLogs] = React.useState<boolean>(false);
const [debug, setDebug] = React.useState<boolean>(false);
return (
<div
style={{
height: '100%',
display: 'flex',
flexDirection: 'column',
flexGrow: 1,
padding: '8px',
backgroundColor: 'rgba(0,0,50,0.25)',
borderRadius: '8px',
position: 'relative',
...css,
}}
>
<div>
<GridActions
api={api}
toggleCustomWatermark={() => setWatermark(!watermark)}
hasCustomWatermark={watermark}
/>
{api && (
<PanelActions
api={api}
panels={panels}
activePanel={activePanel}
/>
)}
{api && (
<GroupActions
api={api}
groups={groups}
activeGroup={activeGroup}
/>
)}
{/* <div>
<button
onClick={() => {
setGapCheck(!gapCheck);
}}
>
{gapCheck ? 'Disable Gap Check' : 'Enable Gap Check'}
</button>
</div> */}
</div>
<div
className="action-container"
style={{
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center',
padding: '4px',
}}
>
<button
onClick={() => {
setDebug(!debug);
}}
>
<span className="material-symbols-outlined">
engineering
</span>
</button>
<button
onClick={() => {
setShowLogs(!showLogs);
}}
>
<span style={{ paddingRight: '4px' }}>
{`${showLogs ? 'Hide' : 'Show'} Events Log`}
</span>
<span className="material-symbols-outlined">terminal</span>
</button>
</div>
<div
style={{
flexGrow: 1,
height: 0,
display: 'flex',
}}
>
<div
style={{
flexGrow: 1,
overflow: 'hidden',
height: '100%',
display: 'flex',
}}
>
<DebugContext.Provider value={debug}>
<DockviewReact
components={components}
defaultTabComponent={headerComponents.default}
rightHeaderActionsComponent={RightControls}
leftHeaderActionsComponent={LeftControls}
prefixHeaderActionsComponent={PrefixHeaderControls}
watermarkComponent={
watermark ? WatermarkComponent : undefined
}
onReady={onReady}
className={props.theme || 'dockview-theme-abyss'}
/>
</DebugContext.Provider>
</div>
{showLogs && (
<div
style={{
width: '400px',
backgroundColor: 'black',
color: 'white',
overflow: 'auto',
fontFamily: 'monospace',
marginLeft: '10px',
flexShrink: 0,
}}
>
{logLines.map((line, i) => {
return (
<div
style={{
height: '30px',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
fontSize: '13px',
display: 'flex',
alignItems: 'center',
backgroundColor: line.backgroundColor,
}}
key={i}
>
<span
style={{
display: 'flex',
alignItems: 'center',
minWidth: '20px',
maxWidth: '20px',
color: 'gray',
borderRight: '1px solid gray',
marginRight: '4px',
paddingLeft: '4px',
height: '100%',
}}
>
{logLines.length - i}
</span>
<span>
{line.timestamp && (
<span
style={{
fontSize: '0.7em',
padding: '0px 2px',
}}
>
{line.timestamp
.toISOString()
.substring(11, 23)}
</span>
)}
<span>{line.text}</span>
</span>
</div>
);
})}
</div>
)}
</div>
</div>
);
};
export default DockviewDemo;

View File

@ -1,148 +0,0 @@
import { IDockviewHeaderActionsProps } from 'dockview';
import * as React from 'react';
import { nextId } from './defaultLayout';
const Icon = (props: {
icon: string;
title?: string;
onClick?: (event: React.MouseEvent) => void;
}) => {
return (
<div title={props.title} className="action" onClick={props.onClick}>
<span
style={{ fontSize: 'inherit' }}
className="material-symbols-outlined"
>
{props.icon}
</span>
</div>
);
};
const groupControlsComponents: Record<string, React.FC> = {
panel_1: () => {
return <Icon icon="file_download" />;
},
};
export const RightControls = (props: IDockviewHeaderActionsProps) => {
const Component = React.useMemo(() => {
if (!props.isGroupActive || !props.activePanel) {
return null;
}
return groupControlsComponents[props.activePanel.id];
}, [props.isGroupActive, props.activePanel]);
const [isMaximized, setIsMaximized] = React.useState<boolean>(
props.containerApi.hasMaximizedGroup()
);
const [isPopout, setIsPopout] = React.useState<boolean>(
props.api.location.type === 'popout'
);
React.useEffect(() => {
const disposable = props.containerApi.onDidMaximizedGroupChange(() => {
setIsMaximized(props.containerApi.hasMaximizedGroup());
});
const disposable2 = props.api.onDidLocationChange(() => {
setIsPopout(props.api.location.type === 'popout');
});
return () => {
disposable.dispose();
disposable2.dispose();
};
}, [props.containerApi]);
const onClick = () => {
if (props.containerApi.hasMaximizedGroup()) {
props.containerApi.exitMaximizedGroup();
} else {
props.activePanel?.api.maximize();
}
};
const onClick2 = () => {
if (props.api.location.type !== 'popout') {
props.containerApi.addPopoutGroup(props.group);
} else {
props.api.moveTo({ position: 'right' });
}
};
return (
<div
className="group-control"
style={{
display: 'flex',
alignItems: 'center',
padding: '0px 8px',
height: '100%',
color: 'var(--dv-activegroup-visiblepanel-tab-color)',
}}
>
{props.isGroupActive && <Icon icon="star" />}
{Component && <Component />}
<Icon
title={isPopout ? 'Close Window' : 'Open In New Window'}
icon={isPopout ? 'close_fullscreen' : 'open_in_new'}
onClick={onClick2}
/>
{!isPopout && (
<Icon
title={isMaximized ? 'Minimize View' : 'Maximize View'}
icon={isMaximized ? 'collapse_content' : 'expand_content'}
onClick={onClick}
/>
)}
</div>
);
};
export const LeftControls = (props: IDockviewHeaderActionsProps) => {
const onClick = () => {
props.containerApi.addPanel({
id: `id_${Date.now().toString()}`,
component: 'default',
title: `Tab ${nextId()}`,
position: {
referenceGroup: props.group,
},
});
};
return (
<div
className="group-control"
style={{
display: 'flex',
alignItems: 'center',
padding: '0px 8px',
height: '100%',
color: 'var(--dv-activegroup-visiblepanel-tab-color)',
}}
>
<Icon onClick={onClick} icon="add" />
</div>
);
};
export const PrefixHeaderControls = (props: IDockviewHeaderActionsProps) => {
return (
<div
className="group-control"
style={{
display: 'flex',
alignItems: 'center',
padding: '0px 8px',
height: '100%',
color: 'var(--dv-activegroup-visiblepanel-tab-color)',
}}
>
<Icon icon="Menu" />
</div>
);
};

View File

@ -1,164 +0,0 @@
import {
DockviewGroupLocation,
DockviewPanelApi,
DockviewPanelRenderer,
} from 'dockview';
import * as React from 'react';
export interface PanelApiMetadata {
isActive: {
value: boolean;
count: number;
};
isVisible: {
value: boolean;
count: number;
};
renderer: {
value: DockviewPanelRenderer;
count: number;
};
isGroupActive: {
value: boolean;
count: number;
};
groupChanged: {
count: number;
};
location: {
value: DockviewGroupLocation;
count: number;
};
didFocus: {
count: number;
};
dimensions: {
count: number;
value: { height: number; width: number };
};
}
export const Table = (props: { data: PanelApiMetadata }) => {
return (
<div className="data-table">
<table>
<tr>
<th>{'Key'}</th>
<th>{'Count'}</th>
<th>{'Value'}</th>
</tr>
{Object.entries(props.data).map(([key, value]) => {
return (
<tr key={key}>
<th>{key}</th>
<th>{value.count}</th>
<th>{JSON.stringify(value.value, null, 4)}</th>
</tr>
);
})}
</table>
</div>
);
};
export function usePanelApiMetadata(api: DockviewPanelApi): PanelApiMetadata {
const [state, setState] = React.useState<PanelApiMetadata>({
isActive: { value: api.isActive, count: 0 },
isVisible: { value: api.isVisible, count: 0 },
renderer: { value: api.renderer, count: 0 },
isGroupActive: { value: api.isGroupActive, count: 0 },
groupChanged: { count: 0 },
location: { value: api.location, count: 0 },
didFocus: { count: 0 },
dimensions: {
count: 0,
value: { height: api.height, width: api.width },
},
});
React.useEffect(() => {
const d1 = api.onDidActiveChange((event) => {
setState((_) => ({
..._,
isActive: {
value: event.isActive,
count: _.isActive.count + 1,
},
}));
});
const d2 = api.onDidActiveGroupChange((event) => {
setState((_) => ({
..._,
isGroupActive: {
value: event.isActive,
count: _.isGroupActive.count + 1,
},
}));
});
const d3 = api.onDidDimensionsChange((event) => {
setState((_) => ({
..._,
dimensions: {
count: _.dimensions.count + 1,
value: { height: event.height, width: event.width },
},
}));
});
const d4 = api.onDidFocusChange((event) => {
setState((_) => ({
..._,
didFocus: {
count: _.didFocus.count + 1,
},
}));
});
const d5 = api.onDidGroupChange((event) => {
setState((_) => ({
..._,
groupChanged: {
count: _.groupChanged.count + 1,
},
}));
});
const d7 = api.onDidLocationChange((event) => {
setState((_) => ({
..._,
location: {
value: event.location,
count: _.location.count + 1,
},
}));
});
const d8 = api.onDidRendererChange((event) => {
setState((_) => ({
..._,
renderer: {
value: event.renderer,
count: _.renderer.count + 1,
},
}));
});
const d9 = api.onDidVisibilityChange((event) => {
setState((_) => ({
..._,
isVisible: {
value: event.isVisible,
count: _.isVisible.count + 1,
},
}));
});
return () => {
d1.dispose();
d2.dispose();
d3.dispose();
d4.dispose();
d5.dispose();
d7.dispose();
d8.dispose();
d9.dispose();
};
}, [api]);
return state;
}

View File

@ -1,67 +0,0 @@
import { DockviewApi } from 'dockview';
export const nextId = (() => {
let counter = 0;
return () => counter++;
})();
export function defaultConfig(api: DockviewApi) {
const panel1 = api.addPanel({
id: 'panel_1',
component: 'default',
renderer: 'always',
title: 'Panel 1',
});
api.addPanel({
id: 'panel_2',
component: 'default',
title: 'Panel 2',
position: { referencePanel: panel1 },
});
api.addPanel({
id: 'panel_3',
component: 'default',
title: 'Panel 3',
position: { referencePanel: panel1 },
});
const panel4 = api.addPanel({
id: 'panel_4',
component: 'default',
title: 'Panel 4',
position: { referencePanel: panel1, direction: 'right' },
});
const panel5 = api.addPanel({
id: 'panel_5',
component: 'default',
title: 'Panel 5',
position: { referencePanel: panel4 },
});
const panel6 = api.addPanel({
id: 'panel_6',
component: 'default',
title: 'Panel 6',
position: { referencePanel: panel5, direction: 'below' },
});
const panel7 = api.addPanel({
id: 'panel_7',
component: 'default',
title: 'Panel 7',
position: { referencePanel: panel6, direction: 'left' },
});
api.addPanel({
id: 'panel8',
component: 'default',
title: 'Panel 8',
position: { referencePanel: panel7, direction: 'below' },
});
panel1.api.setActive();
}

View File

@ -1,216 +0,0 @@
import { DockviewApi } from 'dockview';
import * as React from 'react';
import { defaultConfig, nextId } from './defaultLayout';
import { createRoot, Root } from 'react-dom/client';
import { PanelBuilder } from './panelBuilder';
let mount = document.querySelector('.popover-anchor') as HTMLElement | null;
if (!mount) {
mount = document.createElement('div');
mount.className = 'popover-anchor';
document.body.insertBefore(mount, document.body.firstChild);
}
const PopoverComponent = (props: {
close: () => void;
component: React.FC<{ close: () => void }>;
}) => {
const ref = React.useRef<HTMLDivElement>(null);
React.useEffect(() => {
const handler = (ev: MouseEvent) => {
let target = ev.target as HTMLElement;
while (target.parentElement) {
if (target === ref.current) {
return;
}
target = target.parentElement;
}
props.close();
};
window.addEventListener('mousedown', handler);
return () => {
window.removeEventListener('mousedown', handler);
};
}, []);
return (
<div
style={{
position: 'absolute',
top: 0,
left: 0,
zIndex: 9999,
height: '100%',
width: '100%',
}}
>
<div
ref={ref}
style={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%,-50%)',
backgroundColor: 'black',
color: 'white',
padding: 10,
}}
>
<props.component close={props.close} />
</div>
</div>
);
};
function usePopover() {
return {
open: (Component: React.FC<{ close: () => void }>) => {
const el = document.createElement('div');
mount!.appendChild(el);
const root = createRoot(el);
root.render(
<PopoverComponent
component={Component}
close={() => {
root.unmount();
el.remove();
}}
/>
);
},
};
}
export const GridActions = (props: {
api?: DockviewApi;
hasCustomWatermark: boolean;
toggleCustomWatermark: () => void;
}) => {
const onClear = () => {
props.api?.clear();
};
const onLoad = () => {
const state = localStorage.getItem('dv-demo-state');
if (state) {
try {
props.api?.fromJSON(JSON.parse(state));
} catch (err) {
console.error('failed to load state', err);
localStorage.removeItem('dv-demo-state');
}
}
};
const onSave = () => {
if (props.api) {
console.log(props.api.toJSON());
localStorage.setItem(
'dv-demo-state',
JSON.stringify(props.api.toJSON())
);
}
};
const onReset = () => {
if (props.api) {
try {
props.api.clear();
defaultConfig(props.api);
} catch (err) {
localStorage.removeItem('dv-demo-state');
}
}
};
const popover = usePopover();
const onAddPanel = (options?: { advanced: boolean }) => {
if (options?.advanced) {
popover.open(({ close }) => {
return <PanelBuilder api={props.api!} done={close} />;
});
} else {
props.api?.addPanel({
id: `id_${Date.now().toString()}`,
component: 'default',
title: `Tab ${nextId()}`,
renderer: 'always',
});
}
};
const onAddGroup = () => {
props.api?.addGroup();
};
const [gap, setGap] = React.useState(0);
React.useEffect(() => {
props.api?.setGap(gap);
}, [gap, props.api]);
return (
<div className="action-container">
<div className="button-group">
<button className="text-button" onClick={() => onAddPanel()}>
Add Panel
</button>
<button
className="demo-icon-button"
onClick={() => onAddPanel({ advanced: true })}
>
<span className="material-symbols-outlined">tune</span>
</button>
</div>
<button className="text-button" onClick={onAddGroup}>
Add Group
</button>
<span className="button-action">
<button
className={
props.hasCustomWatermark
? 'demo-button selected'
: 'demo-button'
}
onClick={props.toggleCustomWatermark}
>
Use Custom Watermark
</button>
</span>
<button className="text-button" onClick={onClear}>
Clear
</button>
<button className="text-button" onClick={onLoad}>
Load
</button>
<button className="text-button" onClick={onSave}>
Save
</button>
<button className="text-button" onClick={onReset}>
Reset
</button>
<span style={{ flexGrow: 1 }} />
<div style={{ display: 'flex' }}>
<span style={{ paddingRight: '4px' }}>Group Gap</span>
<input
style={{ width: 40 }}
type="number"
min={0}
max={99}
step={1}
value={gap}
onChange={(event) => setGap(Number(event.target.value))}
/>
</div>
</div>
);
};

View File

@ -1,189 +0,0 @@
import {
DockviewApi,
DockviewGroupLocation,
DockviewGroupPanel,
} from 'dockview';
import * as React from 'react';
const GroupAction = (props: {
groupId: string;
groups: string[];
api: DockviewApi;
activeGroup?: string;
}) => {
const onClick = () => {
props.api?.getGroup(props.groupId)?.focus();
};
const isActive = props.activeGroup === props.groupId;
const [group, setGroup] = React.useState<DockviewGroupPanel | undefined>(
undefined
);
React.useEffect(() => {
const disposable = props.api.onDidLayoutFromJSON(() => {
setGroup(props.api.getGroup(props.groupId));
});
setGroup(props.api.getGroup(props.groupId));
return () => {
disposable.dispose();
};
}, [props.api, props.groupId]);
const [location, setLocation] =
React.useState<DockviewGroupLocation | null>(null);
const [isMaximized, setIsMaximized] = React.useState<boolean>(false);
const [isVisible, setIsVisible] = React.useState<boolean>(true);
React.useEffect(() => {
if (!group) {
setLocation(null);
return;
}
const disposable = group.api.onDidLocationChange((event) => {
setLocation(event.location);
});
const disposable2 = props.api.onDidMaximizedGroupChange(() => {
setIsMaximized(group.api.isMaximized());
});
const disposable3 = group.api.onDidVisibilityChange(() => {
setIsVisible(group.api.isVisible);
});
setLocation(group.api.location);
setIsMaximized(group.api.isMaximized());
setIsVisible(group.api.isVisible);
return () => {
disposable.dispose();
disposable2.dispose();
disposable3.dispose();
};
}, [group]);
return (
<div className="button-action">
<div style={{ display: 'flex' }}>
<button
onClick={onClick}
className={
isActive ? 'demo-button selected' : 'demo-button'
}
>
{props.groupId}
</button>
</div>
<div style={{ display: 'flex' }}>
<button
className={
location?.type === 'floating'
? 'demo-icon-button selected'
: 'demo-icon-button'
}
onClick={() => {
if (group) {
props.api.addFloatingGroup(group, {
width: 400,
height: 300,
x: 50,
y: 50,
position: {
bottom: 50,
right: 50,
},
});
}
}}
>
<span className="material-symbols-outlined">ad_group</span>
</button>
<button
className={
location?.type === 'popout'
? 'demo-icon-button selected'
: 'demo-icon-button'
}
onClick={() => {
if (group) {
props.api.addPopoutGroup(group);
}
}}
>
<span className="material-symbols-outlined">
open_in_new
</span>
</button>
<button
className={
isMaximized
? 'demo-icon-button selected'
: 'demo-icon-button'
}
onClick={() => {
if (group) {
if (group.api.isMaximized()) {
group.api.exitMaximized();
} else {
group.api.maximize();
}
}
}}
>
<span className="material-symbols-outlined">
fullscreen
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
console.log(group);
if (group) {
if (group.api.isVisible) {
group.api.setVisible(false);
} else {
group.api.setVisible(true);
}
}
}}
>
<span className="material-symbols-outlined">
{isVisible ? 'visibility' : 'visibility_off'}
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api?.getGroup(props.groupId);
panel?.api.close();
}}
>
<span className="material-symbols-outlined">close</span>
</button>
</div>
</div>
);
};
export const GroupActions = (props: {
groups: string[];
api: DockviewApi;
activeGroup?: string;
}) => {
return (
<div className="action-container">
{props.groups.map((groupId) => {
return (
<GroupAction key={groupId} {...props} groupId={groupId} />
);
})}
</div>
);
};

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,138 +0,0 @@
import { DockviewApi, IDockviewPanel } from 'dockview';
import * as React from 'react';
const PanelAction = (props: {
panels: string[];
api: DockviewApi;
activePanel?: string;
panelId: string;
}) => {
const onClick = () => {
props.api.getPanel(props.panelId)?.focus();
};
React.useEffect(() => {
const panel = props.api.getPanel(props.panelId);
if (panel) {
const disposable = panel.api.onDidVisibilityChange((event) => {
setVisible(event.isVisible);
});
setVisible(panel.api.isVisible);
return () => {
disposable.dispose();
};
}
}, [props.api, props.panelId]);
const [panel, setPanel] = React.useState<IDockviewPanel | undefined>(
undefined
);
React.useEffect(() => {
const list = [
props.api.onDidLayoutFromJSON(() => {
setPanel(props.api.getPanel(props.panelId));
}),
];
if (panel) {
const disposable = panel.api.onDidVisibilityChange((event) => {
setVisible(event.isVisible);
});
setVisible(panel.api.isVisible);
list.push(disposable);
}
setPanel(props.api.getPanel(props.panelId));
return () => {
list.forEach((l) => l.dispose());
};
}, [props.api, props.panelId]);
const [visible, setVisible] = React.useState<boolean>(true);
return (
<div className="button-action">
<div style={{ display: 'flex' }}>
<button
className={
props.activePanel === props.panelId
? 'demo-button selected'
: 'demo-button'
}
onClick={onClick}
>
{props.panelId}
</button>
</div>
<div style={{ display: 'flex' }}>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api.getPanel(props.panelId);
if (panel) {
props.api.addFloatingGroup(panel, {
position: {
width: 400,
height: 300,
bottom: 50,
right: 50,
},
});
}
}}
>
<span className="material-symbols-outlined">ad_group</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api.getPanel(props.panelId);
if (panel) {
props.api.addPopoutGroup(panel);
}
}}
>
<span className="material-symbols-outlined">
open_in_new
</span>
</button>
<button
className="demo-icon-button"
onClick={() => {
const panel = props.api.getPanel(props.panelId);
panel?.api.close();
}}
>
<span className="material-symbols-outlined">close</span>
</button>
<button
title="Panel visiblity cannot be edited manually."
disabled={true}
className="demo-icon-button"
>
<span className="material-symbols-outlined">
{visible ? 'visibility' : 'visibility_off'}
</span>
</button>
</div>
</div>
);
};
export const PanelActions = (props: {
panels: string[];
api: DockviewApi;
activePanel?: string;
}) => {
return (
<div className="action-container">
{props.panels.map((id) => {
return <PanelAction key={id} {...props} panelId={id} />;
})}
</div>
);
};

View File

@ -1,115 +0,0 @@
import { DockviewApi } from 'dockview';
import * as React from 'react';
import { nextId } from './defaultLayout';
export const PanelBuilder = (props: { api: DockviewApi; done: () => void }) => {
const [parameters, setParameters] = React.useState<{
initialWidth?: number;
initialHeight?: number;
maximumHeight?: number;
maximumWidth?: number;
minimumHeight?: number;
minimumWidth?: number;
}>({});
return (
<div>
<div
style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr',
}}
>
<div>{'Initial Width'}</div>
<input
type="number"
value={parameters.initialWidth}
onChange={(event) =>
setParameters((_) => ({
..._,
initialWidth: Number(event.target.value),
}))
}
/>
<div>{'Initial Height'}</div>
<input
type="number"
value={parameters.initialHeight}
onChange={(event) =>
setParameters((_) => ({
..._,
initialHeight: Number(event.target.value),
}))
}
/>
<div>{'Maximum Width'}</div>
<input
type="number"
value={parameters.maximumWidth}
onChange={(event) =>
setParameters((_) => ({
..._,
maximumWidth: Number(event.target.value),
}))
}
/>
<div>{'Maximum Height'}</div>
<input
type="number"
value={parameters.maximumHeight}
onChange={(event) =>
setParameters((_) => ({
..._,
maximumHeight: Number(event.target.value),
}))
}
/>
<div>{'Minimum Width'}</div>
<input
type="number"
value={parameters.minimumWidth}
onChange={(event) =>
setParameters((_) => ({
..._,
minimumWidth: Number(event.target.value),
}))
}
/>
<div>{'Minimum Height'}</div>
<input
type="number"
value={parameters.minimumHeight}
onChange={(event) =>
setParameters((_) => ({
..._,
minimumHeight: Number(event.target.value),
}))
}
/>
</div>
<div>
<button
onClick={() => {
props.done();
}}
>
Cancel
</button>
<button
onClick={() => {
props.api?.addPanel({
id: `id_${Date.now().toString()}`,
component: 'default',
title: `Tab ${nextId()}`,
renderer: 'always',
...parameters,
});
props.done();
}}
>
Go
</button>
</div>
</div>
);
};

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "dockview.dnd-events",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,142 +0,0 @@
import {
DockviewApi,
DockviewReact,
DockviewReadyEvent,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
const Default = (props: IDockviewPanelProps) => {
return (
<div style={{ height: '100%' }}>
<div>{props.api.title}</div>
</div>
);
};
const components = {
default: Default,
};
const Component = (props: { theme?: string }) => {
const [disablePanelDrag, setDisablePanelDrag] =
React.useState<boolean>(false);
const [disableGroupDrag, setDisableGroupDrag] =
React.useState<boolean>(false);
const [disableOverlay, setDisableOverlay] = React.useState<boolean>(false);
const [api, setApi] = React.useState<DockviewApi>();
React.useEffect(() => {
if (!api) {
return;
}
const disposables = [
api.onWillDragPanel((e) => {
if (!disablePanelDrag) {
return;
}
e.nativeEvent.preventDefault();
}),
api.onWillDragGroup((e) => {
if (!disableGroupDrag) {
return;
}
e.nativeEvent.preventDefault();
}),
api.onWillShowOverlay((e) => {
console.log(e);
if (!disableOverlay) {
return;
}
e.preventDefault();
}),
api.onWillDrop((e) => {
//
}),
api.onDidDrop((e) => {
//
}),
];
return () => {
disposables.forEach((disposable) => {
disposable.dispose();
});
};
}, [api, disablePanelDrag, disableGroupDrag, disableOverlay]);
const onReady = (event: DockviewReadyEvent) => {
setApi(event.api);
event.api.addPanel({
id: 'panel_1',
component: 'default',
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
position: {
direction: 'right',
referencePanel: 'panel_1',
},
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
position: {
direction: 'below',
referencePanel: 'panel_1',
},
});
event.api.addPanel({
id: 'panel_4',
component: 'default',
});
event.api.addPanel({
id: 'panel_5',
component: 'default',
});
};
return (
<div
style={{ display: 'flex', flexDirection: 'column', height: '100%' }}
>
<div>
<button
onClick={() => setDisablePanelDrag(!disablePanelDrag)}
>{`Panel Drag: ${
disablePanelDrag ? 'disabled' : 'enabled'
}`}</button>
<button
onClick={() => setDisableGroupDrag(!disableGroupDrag)}
>{`Group Drag: ${
disableGroupDrag ? 'disabled' : 'enabled'
}`}</button>
<button
onClick={() => setDisableOverlay(!disableOverlay)}
>{`Overlay: ${
disableOverlay ? 'disabled' : 'enabled'
}`}</button>
</div>
<div style={{ flexGrow: 1 }}>
<DockviewReact
className={`${props.theme || 'dockview-theme-abyss'}`}
onReady={onReady}
components={components}
/>
</div>
</div>
);
};
export default Component;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "dockview.dnd-external",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,192 +0,0 @@
import {
DockviewApi,
DockviewDndOverlayEvent,
DockviewDidDropEvent,
DockviewReact,
DockviewReadyEvent,
IDockviewPanelProps,
positionToDirection,
} from 'dockview';
import * as React from 'react';
const components = {
default: (props: IDockviewPanelProps<{ title: string }>) => {
return (
<div style={{ padding: '20px' }}>
<div>{props.params.title}</div>
</div>
);
},
};
const DraggableElement = () => (
<span
tabIndex={-1}
onDragStart={(event) => {
if (event.dataTransfer) {
event.dataTransfer.effectAllowed = 'move';
event.dataTransfer.setData('text/plain', 'nothing');
}
}}
style={{
backgroundColor: 'orange',
padding: '0px 8px',
borderRadius: '4px',
width: '100px',
cursor: 'pointer',
}}
draggable={true}
>
Drag me into the dock
</span>
);
const DndDockview = (props: { renderVisibleOnly: boolean; theme?: string }) => {
const [api, setApi] = React.useState<DockviewApi>();
React.useEffect(() => {
if (!api) {
return;
}
api.addPanel({
id: 'panel_1',
component: 'default',
params: {
title: 'Panel 1',
},
});
api.addPanel({
id: 'panel_2',
component: 'default',
params: {
title: 'Panel 2',
},
});
api.addPanel({
id: 'panel_3',
component: 'default',
params: {
title: 'Panel 3',
},
});
api.addPanel({
id: 'panel_4',
component: 'default',
params: {
title: 'Panel 4',
},
position: { referencePanel: 'panel_1', direction: 'right' },
});
const panelDragDisposable = api.onWillDragPanel((event) => {
const dataTransfer = event.nativeEvent.dataTransfer;
if (dataTransfer) {
dataTransfer.setData(
'text/plain',
'Some custom panel data transfer data'
);
dataTransfer.setData(
'text/json',
'{text: "Some custom panel data transfer data"}'
);
}
});
const groupDragDisposable = api.onWillDragGroup((event) => {
const dataTransfer = event.nativeEvent.dataTransfer;
if (dataTransfer) {
dataTransfer.setData(
'text/plain',
'Some custom group data transfer data'
);
dataTransfer.setData(
'text/json',
'{text: "Some custom group data transfer data"}'
);
}
});
return () => {
panelDragDisposable.dispose();
groupDragDisposable.dispose();
};
}, [api]);
const onReady = (event: DockviewReadyEvent) => {
setApi(event.api);
};
const onDidDrop = (event: DockviewDidDropEvent) => {
event.api.addPanel({
id: 'test',
component: 'default',
position: {
direction: positionToDirection(event.position),
referenceGroup: event.group || undefined,
},
});
};
const showDndOverlay = (event: DockviewDndOverlayEvent) => {
return true;
};
const onDrop = (event: React.DragEvent) => {
const dataTransfer = event.dataTransfer;
let text = 'The following dataTransfer data was found:\n';
for (let i = 0; i < dataTransfer.items.length; i++) {
const item = dataTransfer.items[i];
const value = dataTransfer.getData(item.type);
text += `type=${item.type},data=${value}\n`;
}
alert(text);
};
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
height: '100%',
}}
>
<div style={{ margin: '2px 0px' }}>
<DraggableElement />
<div
style={{
padding: '0px 4px',
backgroundColor: 'black',
borderRadius: '2px',
color: 'white',
}}
onDrop={onDrop}
>
Drop a tab or group here to inspect the attached metadata
</div>
</div>
<DockviewReact
components={components}
onReady={onReady}
className={`${props.theme || 'dockview-theme-abyss'}`}
onDidDrop={onDidDrop}
showDndOverlay={showDndOverlay}
rootOverlayModel={{
size: { value: 100, type: 'pixels' },
activationSize: { value: 5, type: 'percentage' },
}}
/>
</div>
);
};
export default DndDockview;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "dockview.floating-groups",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,301 +0,0 @@
import {
DockviewApi,
DockviewGroupPanel,
DockviewReact,
DockviewReadyEvent,
IDockviewHeaderActionsProps,
IDockviewPanelProps,
SerializedDockview,
} from 'dockview';
import * as React from 'react';
import { Icon } from './utils';
const components = {
default: (props: IDockviewPanelProps<{ title: string }>) => {
return (
<div
style={{
height: '100%',
padding: '20px',
background: 'var(--dv-group-view-background-color)',
}}
>
{props.params.title}
</div>
);
},
};
const counter = (() => {
let i = 0;
return {
next: () => ++i,
};
})();
function loadDefaultLayout(api: DockviewApi) {
api.addPanel({
id: 'panel_1',
component: 'default',
});
api.addPanel({
id: 'panel_2',
component: 'default',
});
api.addPanel({
id: 'panel_3',
component: 'default',
});
const panel4 = api.addPanel({
id: 'panel_4',
component: 'default',
floating: true,
});
api.addPanel({
id: 'panel_5',
component: 'default',
floating: false,
position: { referencePanel: panel4 },
});
api.addPanel({
id: 'panel_6',
component: 'default',
});
}
let panelCount = 0;
function addPanel(api: DockviewApi) {
api.addPanel({
id: (++panelCount).toString(),
title: `Tab ${panelCount}`,
component: 'default',
});
}
function addFloatingPanel2(api: DockviewApi) {
api.addPanel({
id: (++panelCount).toString(),
title: `Tab ${panelCount}`,
component: 'default',
floating: { width: 250, height: 150, left: 50, top: 50 },
});
}
function safeParse<T>(value: any): T | null {
try {
return JSON.parse(value) as T;
} catch (err) {
return null;
}
}
const useLocalStorage = <T,>(
key: string
): [T | null, (setter: T | null) => void] => {
const [state, setState] = React.useState<T | null>(
safeParse(localStorage.getItem(key))
);
React.useEffect(() => {
const _state = localStorage.getItem('key');
try {
if (_state !== null) {
setState(JSON.parse(_state));
}
} catch (err) {
//
}
}, [key]);
return [
state,
(_state: T | null) => {
if (_state === null) {
localStorage.removeItem(key);
} else {
localStorage.setItem(key, JSON.stringify(_state));
setState(_state);
}
},
];
};
export const DockviewPersistence = (props: { theme?: string }) => {
const [api, setApi] = React.useState<DockviewApi>();
const [layout, setLayout] =
useLocalStorage<SerializedDockview>('floating.layout');
const [disableFloatingGroups, setDisableFloatingGroups] =
React.useState<boolean>(false);
const load = (api: DockviewApi) => {
api.clear();
if (layout) {
try {
api.fromJSON(layout);
} catch (err) {
console.error(err);
api.clear();
loadDefaultLayout(api);
}
} else {
loadDefaultLayout(api);
}
};
const onReady = (event: DockviewReadyEvent) => {
load(event.api);
setApi(event.api);
};
const [options, setOptions] = React.useState<
'boundedWithinViewport' | undefined
>(undefined);
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
height: '100%',
}}
>
<div style={{ height: '25px' }}>
<button
onClick={() => {
if (api) {
setLayout(api.toJSON());
}
}}
>
Save
</button>
<button
onClick={() => {
if (api) {
load(api);
}
}}
>
Load
</button>
<button
onClick={() => {
api!.clear();
setLayout(null);
}}
>
Clear
</button>
<button
onClick={() => {
addFloatingPanel2(api!);
}}
>
Add Floating Group
</button>
<button
onClick={() => {
setOptions(
options === undefined
? 'boundedWithinViewport'
: undefined
);
}}
>
{`Bounds: ${options ? 'Within' : 'Overflow'}`}
</button>
<button
onClick={() => {
setDisableFloatingGroups((x) => !x);
}}
>
{`${
disableFloatingGroups ? 'Enable' : 'Disable'
} floating groups`}
</button>
</div>
<div
style={{
flexGrow: 1,
}}
>
<DockviewReact
onReady={onReady}
components={components}
watermarkComponent={Watermark}
leftHeaderActionsComponent={LeftComponent}
rightHeaderActionsComponent={RightComponent}
disableFloatingGroups={disableFloatingGroups}
floatingGroupBounds={options}
className={`${props.theme || 'dockview-theme-abyss'}`}
/>
</div>
</div>
);
};
const LeftComponent = (props: IDockviewHeaderActionsProps) => {
const onClick = () => {
addPanel(props.containerApi);
};
return (
<div style={{ height: '100%', color: 'white', padding: '0px 4px' }}>
<Icon onClick={onClick} icon={'add'} />
</div>
);
};
const RightComponent = (props: IDockviewHeaderActionsProps) => {
const [floating, setFloating] = React.useState<boolean>(
props.api.location.type === 'floating'
);
React.useEffect(() => {
const disposable = props.group.api.onDidLocationChange((event) => {
setFloating(event.location.type === 'floating');
});
return () => {
disposable.dispose();
};
}, [props.group.api]);
const onClick = () => {
if (floating) {
const group = props.containerApi.addGroup();
props.group.api.moveTo({ group });
} else {
props.containerApi.addFloatingGroup(props.group, {
position: {
width: 400,
height: 300,
bottom: 50,
right: 50,
},
});
}
};
return (
<div style={{ height: '100%', color: 'white', padding: '0px 4px' }}>
<Icon
onClick={onClick}
icon={floating ? 'jump_to_element' : 'back_to_tab'}
/>
</div>
);
};
export default DockviewPersistence;
const Watermark = () => {
return <div style={{ color: 'white', padding: '8px' }}>watermark</div>;
};

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,30 +0,0 @@
import * as React from 'react';
export const Icon = (props: {
icon: string;
title?: string;
onClick?: (event: React.MouseEvent) => void;
}) => {
return (
<div
title={props.title}
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '30px',
height: '100%',
fontSize: '18px',
}}
onClick={props.onClick}
>
<span
style={{ fontSize: 'inherit', cursor: 'pointer' }}
className="material-symbols-outlined"
>
{props.icon}
</span>
</div>
);
};

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "dockview.group-actions",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

View File

@ -1,44 +0,0 @@
<!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>

View File

@ -1,20 +0,0 @@
.dockview-groupcontrol-demo {
height: 100%;
display: flex;
align-items: center;
color: white;
background-color: black;
padding: 0px 8px;
margin: 1px;
border: 1px dotted orange;
.dockview-groupcontrol-demo-group-active {
padding: 0px 8px;
}
.dockview-groupcontrol-demo-active-panel {
color: yellow;
padding: 0px 8px;
}
}

View File

@ -1,102 +0,0 @@
import {
DockviewReact,
DockviewReadyEvent,
IDockviewHeaderActionsProps,
IDockviewPanelProps,
} from 'dockview';
import * as React from 'react';
import './app.scss';
const components = {
default: (props: IDockviewPanelProps<{ title: string; x?: number }>) => {
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: 'gray',
height: '100%',
}}
>
<span>{`${props.api.title}`}</span>
</div>
);
},
};
const RightHeaderActions = (props: IDockviewHeaderActionsProps) => {
const isGroupActive = props.isGroupActive;
return (
<div className="dockview-groupcontrol-demo">
<span
className="dockview-groupcontrol-demo-group-active"
style={{
background: isGroupActive ? 'green' : 'red',
}}
>
{isGroupActive ? 'Group Active' : 'Group Inactive'}
</span>
</div>
);
};
const LeftHeaderActions = (props: IDockviewHeaderActionsProps) => {
const activePanel = props.activePanel;
return (
<div className="dockview-groupcontrol-demo">
<span className="dockview-groupcontrol-demo-active-panel">{`activePanel: ${
activePanel?.id || 'null'
}`}</span>
</div>
);
};
const PrefixHeader = (props: IDockviewHeaderActionsProps) => {
const activePanel = props.activePanel;
return <div className="dockview-groupcontrol-demo">{'🌲'}</div>;
};
const DockviewGroupControl = (props: { theme: string }) => {
const onReady = (event: DockviewReadyEvent) => {
event.api.addPanel({
id: 'panel_1',
component: 'default',
title: 'Panel 1',
});
event.api.addPanel({
id: 'panel_2',
component: 'default',
title: 'Panel 2',
position: {
direction: 'right',
},
});
event.api.addPanel({
id: 'panel_3',
component: 'default',
title: 'Panel 3',
position: {
direction: 'below',
},
});
};
return (
<DockviewReact
onReady={onReady}
components={components}
prefixHeaderActionsComponent={PrefixHeader}
leftHeaderActionsComponent={LeftHeaderActions}
rightHeaderActionsComponent={RightHeaderActions}
className={`${props.theme || 'dockview-theme-abyss'}`}
/>
);
};
export default DockviewGroupControl;

View File

@ -1,20 +0,0 @@
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>
);
}

View File

@ -1,16 +0,0 @@
body {
margin: 0px;
color: white;
font-family: sans-serif;
text-align: center;
}
#root {
height: 100vh;
width: 100vw;
}
.app {
height: 100%;
}

View File

@ -1,18 +0,0 @@
{
"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
}
}

View File

@ -1,32 +0,0 @@
{
"name": "dockview.layout",
"description": "",
"keywords": [
"dockview"
],
"version": "1.0.0",
"main": "src/index.tsx",
"dependencies": {
"dockview": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.0.28",
"@types/react-dom": "^18.0.11",
"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"
]
}

Some files were not shown because too many files have changed in this diff Show More