mirror of
https://github.com/mathuo/dockview
synced 2025-01-22 09:25:57 +00:00
chore: remove old docs
This commit is contained in:
parent
83b01a9a66
commit
e46a586044
@ -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"
|
||||
}
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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();
|
||||
},
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -1,3 +0,0 @@
|
||||
.skinny-tabs {
|
||||
--dv-tabs-and-actions-container-height: 20px;
|
||||
}
|
@ -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();
|
||||
},
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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();
|
||||
},
|
||||
};
|
||||
}
|
@ -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);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
@ -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>
|
||||
);
|
||||
};
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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>
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
}
|
@ -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>
|
||||
);
|
||||
};
|
@ -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>
|
||||
);
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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>;
|
||||
};
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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>
|
||||
);
|
||||
};
|
@ -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
|
||||
}
|
||||
}
|
@ -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"
|
||||
]
|
||||
}
|
@ -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>
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
@ -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>
|
||||
);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
color: white;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
.app {
|
||||
height: 100%;
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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
Loading…
Reference in New Issue
Block a user