mirror of
https://github.com/mathuo/dockview
synced 2025-03-09 15:32:03 +00:00
Merge branch 'master' of https://github.com/mathuo/dockview into 849-improved-dnd-overlay-model
This commit is contained in:
commit
3530c9896e
@ -2,7 +2,7 @@
|
||||
"packages": [
|
||||
"packages/*"
|
||||
],
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"npmClient": "yarn",
|
||||
"command": {
|
||||
"publish": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dockview-angular",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||
"keywords": [
|
||||
"splitview",
|
||||
@ -54,6 +54,6 @@
|
||||
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"dockview-core": "^3.0.2"
|
||||
"dockview-core": "^3.2.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dockview-core",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||
"keywords": [
|
||||
"splitview",
|
||||
|
@ -1102,7 +1102,9 @@ describe('dockviewComponent', () => {
|
||||
disposable.dispose();
|
||||
});
|
||||
|
||||
test('events flow', () => {
|
||||
test('events flow', async () => {
|
||||
window.open = () => setupMockWindow();
|
||||
|
||||
dockview.layout(1000, 1000);
|
||||
|
||||
let events: {
|
||||
@ -1295,7 +1297,42 @@ describe('dockviewComponent', () => {
|
||||
expect(dockview.size).toBe(0);
|
||||
expect(dockview.totalPanels).toBe(0);
|
||||
|
||||
events = [];
|
||||
|
||||
const panel8 = dockview.addPanel({
|
||||
id: 'panel8',
|
||||
component: 'default',
|
||||
});
|
||||
const panel9 = dockview.addPanel({
|
||||
id: 'panel9',
|
||||
component: 'default',
|
||||
floating: true,
|
||||
});
|
||||
const panel10 = dockview.addPanel({
|
||||
id: 'panel10',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
expect(await dockview.addPopoutGroup(panel10)).toBeTruthy();
|
||||
|
||||
expect(events).toEqual([
|
||||
{ type: 'ADD_GROUP', group: panel8.group },
|
||||
{ type: 'ADD_PANEL', panel: panel8 },
|
||||
{ type: 'ACTIVE_GROUP', group: panel8.group },
|
||||
{ type: 'ACTIVE_PANEL', panel: panel8 },
|
||||
{ type: 'ADD_GROUP', group: panel9.group },
|
||||
{ type: 'ADD_PANEL', panel: panel9 },
|
||||
{ type: 'ACTIVE_GROUP', group: panel9.group },
|
||||
{ type: 'ACTIVE_PANEL', panel: panel9 },
|
||||
{ type: 'ADD_PANEL', panel: panel10 },
|
||||
{ type: 'ACTIVE_PANEL', panel: panel10 },
|
||||
{ type: 'ADD_GROUP', group: panel10.group },
|
||||
]);
|
||||
|
||||
events = [];
|
||||
disposable.dispose();
|
||||
|
||||
expect(events.length).toBe(0);
|
||||
});
|
||||
|
||||
test('that removing a panel from a group reflects in the dockviewcomponent when searching for a panel', () => {
|
||||
@ -5696,6 +5733,42 @@ describe('dockviewComponent', () => {
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
test('dispose of dockview instance when popup is open', async () => {
|
||||
const container = document.createElement('div');
|
||||
|
||||
window.open = () => setupMockWindow();
|
||||
|
||||
const dockview = new DockviewComponent(container, {
|
||||
createComponent(options) {
|
||||
switch (options.name) {
|
||||
case 'default':
|
||||
return new PanelContentPartTest(
|
||||
options.id,
|
||||
options.name
|
||||
);
|
||||
default:
|
||||
throw new Error(`unsupported`);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
dockview.layout(1000, 500);
|
||||
|
||||
dockview.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
const panel2 = dockview.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
});
|
||||
|
||||
expect(await dockview.addPopoutGroup(panel2.group)).toBeTruthy();
|
||||
|
||||
dockview.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('maximized group', () => {
|
||||
|
@ -29,12 +29,6 @@ export class DefaultTab extends CompositeDisposable implements ITabRenderer {
|
||||
this._element.appendChild(this._content);
|
||||
this._element.appendChild(this.action);
|
||||
|
||||
this.addDisposables(
|
||||
addDisposableListener(this.action, 'pointerdown', (ev) => {
|
||||
ev.preventDefault();
|
||||
})
|
||||
);
|
||||
|
||||
this.render();
|
||||
}
|
||||
|
||||
|
@ -50,8 +50,8 @@ export class Tab extends CompositeDisposable {
|
||||
private readonly dropTarget: Droptarget;
|
||||
private content: ITabRenderer | undefined = undefined;
|
||||
|
||||
private readonly _onChanged = new Emitter<MouseEvent>();
|
||||
readonly onChanged: Event<MouseEvent> = this._onChanged.event;
|
||||
private readonly _onPointDown = new Emitter<MouseEvent>();
|
||||
readonly onPointerDown: Event<MouseEvent> = this._onPointDown.event;
|
||||
|
||||
private readonly _onDropped = new Emitter<DroptargetEvent>();
|
||||
readonly onDrop: Event<DroptargetEvent> = this._onDropped.event;
|
||||
@ -112,7 +112,7 @@ export class Tab extends CompositeDisposable {
|
||||
this.onWillShowOverlay = this.dropTarget.onWillShowOverlay;
|
||||
|
||||
this.addDisposables(
|
||||
this._onChanged,
|
||||
this._onPointDown,
|
||||
this._onDropped,
|
||||
this._onDragStart,
|
||||
dragHandler.onDragStart((event) => {
|
||||
@ -137,11 +137,7 @@ export class Tab extends CompositeDisposable {
|
||||
}),
|
||||
dragHandler,
|
||||
addDisposableListener(this._element, 'pointerdown', (event) => {
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
this._onChanged.fire(event);
|
||||
this._onPointDown.fire(event);
|
||||
}),
|
||||
this.dropTarget.onDrop((event) => {
|
||||
this._onDropped.fire(event);
|
||||
|
@ -286,6 +286,10 @@ export class TabsContainer
|
||||
|
||||
const tabToRemove = this.tabs.splice(index, 1)[0];
|
||||
|
||||
if (!tabToRemove) {
|
||||
throw new Error(`dockview: Tab not found`);
|
||||
}
|
||||
|
||||
const { value, disposable } = tabToRemove;
|
||||
|
||||
disposable.dispose();
|
||||
@ -316,7 +320,11 @@ export class TabsContainer
|
||||
tab.onDragStart((event) => {
|
||||
this._onTabDragStart.fire({ nativeEvent: event, panel });
|
||||
}),
|
||||
tab.onChanged((event) => {
|
||||
tab.onPointerDown((event) => {
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
const isFloatingGroupsEnabled =
|
||||
!this.accessor.options.disableFloatingGroups;
|
||||
|
||||
@ -345,14 +353,12 @@ export class TabsContainer
|
||||
return;
|
||||
}
|
||||
|
||||
const isLeftClick = event.button === 0;
|
||||
|
||||
if (!isLeftClick || event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.group.activePanel !== panel) {
|
||||
this.group.model.openPanel(panel);
|
||||
switch (event.button) {
|
||||
case 0: // left click or touch
|
||||
if (this.group.activePanel !== panel) {
|
||||
this.group.model.openPanel(panel);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}),
|
||||
tab.onDrop((event) => {
|
||||
|
@ -853,6 +853,10 @@ export class DockviewComponent
|
||||
),
|
||||
overlayRenderContainer,
|
||||
Disposable.from(() => {
|
||||
if (this.isDisposed) {
|
||||
return; // cleanup may run after instance is disposed
|
||||
}
|
||||
|
||||
if (
|
||||
isGroupAddedToDom &&
|
||||
this.getPanel(referenceGroup.id)
|
||||
|
@ -118,15 +118,16 @@
|
||||
touch-action: none;
|
||||
background-color: var(--dv-sash-color, transparent);
|
||||
|
||||
&:not(.disabled):active {
|
||||
transition: background-color 0.1s ease-in-out;
|
||||
background-color: var(--dv-active-sash-color, transparent);
|
||||
}
|
||||
|
||||
&:not(.disabled):active,
|
||||
&:not(.disabled):hover {
|
||||
background-color: var(--dv-active-sash-color, transparent);
|
||||
transition: background-color 0.1s ease-in-out;
|
||||
transition-delay: 0.5s;
|
||||
transition-property: background-color;
|
||||
transition-timing-function: ease-in-out;
|
||||
transition-duration: var(
|
||||
--dv-active-sash-transition-duration,
|
||||
0.1s
|
||||
);
|
||||
transition-delay: var(--dv-active-sash-transition-delay, 0.5s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
--dv-tab-margin: 0;
|
||||
--dv-sash-color: transparent;
|
||||
--dv-active-sash-color: transparent;
|
||||
--dv-active-sash-transition-duration: 0.1s;
|
||||
--dv-active-sash-transition-delay: 0.5s;
|
||||
}
|
||||
|
||||
@mixin dockview-theme-dark-mixin {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dockview-react",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||
"keywords": [
|
||||
"splitview",
|
||||
@ -54,6 +54,6 @@
|
||||
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-react --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"dockview": "^3.0.2"
|
||||
"dockview": "^3.2.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dockview-vue",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||
"keywords": [
|
||||
"splitview",
|
||||
@ -52,7 +52,7 @@
|
||||
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"dockview-core": "^3.0.2"
|
||||
"dockview-core": "^3.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.4.0"
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dockview",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||
"keywords": [
|
||||
"splitview",
|
||||
@ -54,7 +54,7 @@
|
||||
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"dockview-core": "^3.0.2"
|
||||
"dockview-core": "^3.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
|
@ -10,7 +10,9 @@ import { Disposable } from 'dockview-core/dist/cjs/lifecycle';
|
||||
describe('defaultTab', () => {
|
||||
test('has close button by default', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
onDidTitleChange: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -30,7 +32,9 @@ describe('defaultTab', () => {
|
||||
test('that title is displayed', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
title: 'test_title',
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
onDidTitleChange: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -84,7 +88,9 @@ describe('defaultTab', () => {
|
||||
|
||||
test('has no close button when hideClose=true', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
onDidTitleChange: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -105,7 +111,9 @@ describe('defaultTab', () => {
|
||||
test('that settings closeActionOverride skips api.close()', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
close: jest.fn(),
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
onDidTitleChange: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -134,7 +142,9 @@ describe('defaultTab', () => {
|
||||
test('that clicking close calls api.close()', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
close: jest.fn(),
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
onDidTitleChange: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -158,7 +168,9 @@ describe('defaultTab', () => {
|
||||
|
||||
test('has close button when hideClose=false', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
onDidTitleChange: jest
|
||||
.fn()
|
||||
.mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
@ -175,32 +187,4 @@ describe('defaultTab', () => {
|
||||
const element = await screen.getByTestId('dockview-dv-default-tab');
|
||||
expect(element.querySelector('.dv-default-tab-action')).toBeTruthy();
|
||||
});
|
||||
|
||||
test('that pointerDown on close button prevents panel becoming active', async () => {
|
||||
const api = fromPartial<DockviewPanelApi>({
|
||||
setActive: jest.fn(),
|
||||
onDidTitleChange: jest.fn().mockImplementation(() => Disposable.NONE),
|
||||
});
|
||||
const containerApi = fromPartial<DockviewApi>({});
|
||||
const params = {};
|
||||
|
||||
render(
|
||||
<DockviewDefaultTab
|
||||
api={api}
|
||||
containerApi={containerApi}
|
||||
params={params}
|
||||
/>
|
||||
);
|
||||
|
||||
const element = await screen.getByTestId('dockview-dv-default-tab');
|
||||
const btn = element.querySelector(
|
||||
'.dv-default-tab-action'
|
||||
) as HTMLElement;
|
||||
|
||||
fireEvent.pointerDown(btn);
|
||||
expect(api.setActive).toHaveBeenCalledTimes(0);
|
||||
|
||||
fireEvent.click(element);
|
||||
expect(api.setActive).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
|
@ -32,10 +32,15 @@ export const DockviewDefaultTab: React.FunctionComponent<
|
||||
params: _params,
|
||||
hideClose,
|
||||
closeActionOverride,
|
||||
onPointerDown,
|
||||
onPointerUp,
|
||||
onPointerLeave,
|
||||
...rest
|
||||
}) => {
|
||||
const title = useTitle(api);
|
||||
|
||||
const isMiddleMouseButton = React.useRef<boolean>(false);
|
||||
|
||||
const onClose = React.useCallback(
|
||||
(event: React.MouseEvent<HTMLSpanElement>) => {
|
||||
event.preventDefault();
|
||||
@ -49,37 +54,52 @@ export const DockviewDefaultTab: React.FunctionComponent<
|
||||
[api, closeActionOverride]
|
||||
);
|
||||
|
||||
const onPointerDown = React.useCallback((e: React.MouseEvent) => {
|
||||
e.preventDefault();
|
||||
const onBtnPointerDown = React.useCallback((event: React.MouseEvent) => {
|
||||
event.preventDefault();
|
||||
}, []);
|
||||
|
||||
const onClick = React.useCallback(
|
||||
(event: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (event.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
api.setActive();
|
||||
|
||||
if (rest.onClick) {
|
||||
rest.onClick(event);
|
||||
}
|
||||
const _onPointerDown = React.useCallback(
|
||||
(event: React.PointerEvent<HTMLDivElement>) => {
|
||||
isMiddleMouseButton.current = event.button === 1;
|
||||
onPointerDown?.(event);
|
||||
},
|
||||
[api, rest.onClick]
|
||||
[onPointerDown]
|
||||
);
|
||||
|
||||
const _onPointerUp = React.useCallback(
|
||||
(event: React.PointerEvent<HTMLDivElement>) => {
|
||||
if (isMiddleMouseButton && event.button === 1 && !hideClose) {
|
||||
isMiddleMouseButton.current = false;
|
||||
onClose(event);
|
||||
}
|
||||
|
||||
onPointerUp?.(event);
|
||||
},
|
||||
[onPointerUp, onClose, hideClose]
|
||||
);
|
||||
|
||||
const _onPointerLeave = React.useCallback(
|
||||
(event: React.PointerEvent<HTMLDivElement>) => {
|
||||
isMiddleMouseButton.current = false;
|
||||
onPointerLeave?.(event);
|
||||
},
|
||||
[onPointerLeave]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="dockview-dv-default-tab"
|
||||
{...rest}
|
||||
onClick={onClick}
|
||||
onPointerDown={_onPointerDown}
|
||||
onPointerUp={_onPointerUp}
|
||||
onPointerLeave={_onPointerLeave}
|
||||
className="dv-default-tab"
|
||||
>
|
||||
<span className="dv-default-tab-content">{title}</span>
|
||||
{!hideClose && (
|
||||
<div
|
||||
className="dv-default-tab-action"
|
||||
onPointerDown={onPointerDown}
|
||||
onPointerDown={onBtnPointerDown}
|
||||
onClick={onClose}
|
||||
>
|
||||
<CloseButton />
|
||||
|
22
packages/docs/blog/2025-02-02-dockview-3.1.0.md
Normal file
22
packages/docs/blog/2025-02-02-dockview-3.1.0.md
Normal file
@ -0,0 +1,22 @@
|
||||
---
|
||||
slug: dockview-3.1.0-release
|
||||
title: Dockview 3.1.0
|
||||
tags: [release]
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
Please reference docs @ [dockview.dev](https://dockview.dev).
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- Close tab with middle mouse button [#847](https://github.com/mathuo/dockview/pull/847)
|
||||
|
||||
## 🛠 Miscs
|
||||
|
||||
- Bug: Fix crash on navigation with open popout group [#835](https://github.com/mathuo/dockview/pull/848) [#845](https://github.com/mathuo/dockview/pull/845)
|
||||
- Bug: Subscribe to `onDidAcitvePanelChange` immediately, rather than deferred to `queueMicrotask` [#843](https://github.com/mathuo/dockview/pull/843)
|
||||
- Bug: Minor theme fixup [#831](https://github.com/mathuo/dockview/pull/831)
|
||||
|
||||
## 🔥 Breaking changes
|
||||
|
18
packages/docs/blog/2025-02-09-dockview-3.1.1.md
Normal file
18
packages/docs/blog/2025-02-09-dockview-3.1.1.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
slug: dockview-3.1.1-release
|
||||
title: Dockview 3.1.1
|
||||
tags: [release]
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
Please reference docs @ [dockview.dev](https://dockview.dev).
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
## 🛠 Miscs
|
||||
|
||||
- Bug: Fix Middle mouse button to close tab [#835](https://github.com/mathuo/dockview/issues/853)
|
||||
|
||||
## 🔥 Breaking changes
|
||||
|
18
packages/docs/blog/2025-02-12-dockview-3.2.0.md
Normal file
18
packages/docs/blog/2025-02-12-dockview-3.2.0.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
slug: dockview-3.2.0-release
|
||||
title: Dockview 3.2.0
|
||||
tags: [release]
|
||||
---
|
||||
|
||||
# Release Notes
|
||||
|
||||
Please reference docs @ [dockview.dev](https://dockview.dev).
|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- Add CSS properties `--dv-active-sash-transition-duration` and `--dv-active-sash-transition-delay` [#835](https://github.com/mathuo/dockview/issues/859)
|
||||
|
||||
## 🛠 Miscs
|
||||
|
||||
## 🔥 Breaking changes
|
||||
|
@ -184,17 +184,8 @@ const config = {
|
||||
label: 'API',
|
||||
},
|
||||
{ to: '/blog', label: 'Blog', position: 'left' },
|
||||
{ href: '/templates', target:"_blank", label: 'Examples', position: 'left' },
|
||||
{ to: '/demo', label: 'Demo', position: 'left' },
|
||||
// {
|
||||
// to: 'https://dockview.dev/typedocs',
|
||||
// label: 'TSDoc',
|
||||
// position: 'left',
|
||||
// },
|
||||
|
||||
// {
|
||||
// type: 'docsVersionDropdown',
|
||||
// position: 'right',
|
||||
// },
|
||||
{
|
||||
href: 'https://github.com/mathuo/dockview',
|
||||
position: 'right',
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dockview-docs",
|
||||
"version": "3.0.2",
|
||||
"version": "3.2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "npm run build-templates && docusaurus build",
|
||||
@ -38,7 +38,7 @@
|
||||
"ag-grid-react": "^31.0.2",
|
||||
"axios": "^1.6.3",
|
||||
"clsx": "^2.1.0",
|
||||
"dockview": "^3.0.2",
|
||||
"dockview": "^3.2.0",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-laag": "^2.0.5",
|
||||
|
@ -1,7 +1,6 @@
|
||||
import fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { argv } from 'process';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
@ -86,7 +85,8 @@ function createIndexHTML(options) {
|
||||
.map(([key, value]) => `"${key}": "${value}"`)
|
||||
.join(',\n')}`
|
||||
)
|
||||
.replace('{{app}}', options.app);
|
||||
.replace('{{app}}', options.app)
|
||||
.replace('{{githubLink}}', options.githubUrl)
|
||||
}
|
||||
|
||||
const input_dir = path.join(__dirname, '../templates');
|
||||
@ -97,6 +97,8 @@ const FRAMEWORKS = ['react', 'vue', 'typescript'];
|
||||
|
||||
const list = [];
|
||||
|
||||
const githubUrl = "https://github.com/mathuo/dockview/tree/master/packages/docs/templates"
|
||||
|
||||
for (const component of COMPONENTS) {
|
||||
const componentDir = path.join(input_dir, component);
|
||||
|
||||
@ -115,6 +117,9 @@ for (const component of COMPONENTS) {
|
||||
path.join(componentDir, folder, framework, 'src'),
|
||||
path.join(output, component, folder, framework, 'src')
|
||||
);
|
||||
|
||||
const templateGithubUrl = `${githubUrl}/${component}/${folder}/${framework}/src`
|
||||
|
||||
const template = createIndexHTML({
|
||||
title: `Dockview | ${folder} ${framework}`,
|
||||
app:
|
||||
@ -127,6 +132,7 @@ for (const component of COMPONENTS) {
|
||||
USE_LOCAL_CDN ? 'local' : 'remote'
|
||||
],
|
||||
},
|
||||
githubUrl: templateGithubUrl
|
||||
});
|
||||
fs.writeFileSync(
|
||||
path.join(output, component, folder, framework, 'index.html'),
|
||||
|
@ -12,7 +12,7 @@
|
||||
<style media="only screen">
|
||||
html,
|
||||
body,
|
||||
#app {
|
||||
#root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
@ -22,6 +22,26 @@
|
||||
BlinkMacSystemFont, Segoe UI, Roboto;
|
||||
}
|
||||
|
||||
#header {
|
||||
height: 25px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#header-btn {
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
#gh-logo {
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: calc(100% - 25px);
|
||||
}
|
||||
|
||||
html {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -31,7 +51,7 @@
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 16px;
|
||||
padding: 8px;
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
@ -62,9 +82,18 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app">
|
||||
<script type="systemjs-module" src="import:{{app}}"></script>
|
||||
<div id="root">
|
||||
<div id="header">
|
||||
<a target="_blank" rel="noopener noreferrer" href="{{githubLink}}">
|
||||
<button id="header-btn">
|
||||
View Source
|
||||
</button>
|
||||
</a>
|
||||
<img id="gh-logo" src="https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png"/>
|
||||
</div>
|
||||
<div id="app"></div>
|
||||
</div>
|
||||
<script type="systemjs-module" src="import:{{app}}"></script>
|
||||
<object
|
||||
id="loading-spinner"
|
||||
style="
|
||||
|
23
packages/docs/templates/dockview/group-actions/typescript/src/index.css
vendored
Normal file
23
packages/docs/templates/dockview/group-actions/typescript/src/index.css
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
.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 .dockview-groupcontrol-demo-group-active {
|
||||
padding: 0px 8px;
|
||||
}
|
||||
|
||||
.dockview-groupcontrol-demo .dockview-groupcontrol-demo-active-panel {
|
||||
color: yellow;
|
||||
padding: 0px 8px;
|
||||
}
|
||||
|
178
packages/docs/templates/dockview/group-actions/typescript/src/index.ts
vendored
Normal file
178
packages/docs/templates/dockview/group-actions/typescript/src/index.ts
vendored
Normal file
@ -0,0 +1,178 @@
|
||||
import 'dockview-core/dist/styles/dockview.css';
|
||||
import {
|
||||
createDockview,
|
||||
DockviewGroupPanel,
|
||||
GroupPanelPartInitParameters,
|
||||
IContentRenderer,
|
||||
IGroupHeaderProps,
|
||||
IHeaderActionsRenderer,
|
||||
} from 'dockview-core';
|
||||
import './index.css';
|
||||
|
||||
class Panel implements IContentRenderer {
|
||||
private readonly _element: HTMLElement;
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this._element = document.createElement('div');
|
||||
this._element.style.display = 'flex';
|
||||
this._element.style.justifyContent = 'center';
|
||||
this._element.style.alignItems = 'center';
|
||||
this._element.style.color = 'gray';
|
||||
this._element.style.height = '100%';
|
||||
}
|
||||
|
||||
init(parameters: GroupPanelPartInitParameters): void {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
class PrefixHeader implements IHeaderActionsRenderer {
|
||||
private readonly _element: HTMLElement;
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
constructor(group: DockviewGroupPanel) {
|
||||
this._element = document.createElement('div');
|
||||
this._element.className = 'dockview-groupcontrol-demo';
|
||||
this._element.innerText = '🌲';
|
||||
}
|
||||
|
||||
init(parameters: IGroupHeaderProps): void {
|
||||
//
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
class RightHeaderActions implements IHeaderActionsRenderer {
|
||||
private readonly _element: HTMLElement;
|
||||
private readonly _disposables: (() => void)[] = [];
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
constructor(group: DockviewGroupPanel) {
|
||||
this._element = document.createElement('div');
|
||||
this._element.className = 'dockview-groupcontrol-demo';
|
||||
}
|
||||
|
||||
init(parameters: IGroupHeaderProps): void {
|
||||
const group = parameters.group;
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.className = 'dockview-groupcontrol-demo-group-active';
|
||||
|
||||
this._element.appendChild(span);
|
||||
|
||||
const d1 = group.api.onDidActiveChange(() => {
|
||||
span.style.background = group.api.isActive ? 'green' : 'red';
|
||||
span.innerText = `${
|
||||
group.api.isActive ? 'Group Active' : 'Group Inactive'
|
||||
}`;
|
||||
});
|
||||
|
||||
span.style.background = group.api.isActive ? 'green' : 'red';
|
||||
span.innerText = `${
|
||||
group.api.isActive ? 'Group Active' : 'Group Inactive'
|
||||
}`;
|
||||
|
||||
this._disposables.push(() => d1.dispose());
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.forEach((dispose) => dispose());
|
||||
}
|
||||
}
|
||||
|
||||
class LeftHeaderActions implements IHeaderActionsRenderer {
|
||||
private readonly _element: HTMLElement;
|
||||
private readonly _disposables: (() => void)[] = [];
|
||||
|
||||
get element(): HTMLElement {
|
||||
return this._element;
|
||||
}
|
||||
|
||||
constructor(group: DockviewGroupPanel) {
|
||||
console.log('group', group);
|
||||
this._element = document.createElement('div');
|
||||
this._element.className = 'dockview-groupcontrol-demo';
|
||||
}
|
||||
|
||||
init(parameters: IGroupHeaderProps): void {
|
||||
const group = parameters.group;
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.className = 'dockview-groupcontrol-demo-active-panel';
|
||||
|
||||
this._element.appendChild(span);
|
||||
|
||||
const d1 = group.api.onDidActivePanelChange((event) => {
|
||||
console.log('event', event);
|
||||
span.innerText = `activePanel: ${event.panel?.id || 'null'}`;
|
||||
});
|
||||
|
||||
console.log('group.activePanel', group.activePanel);
|
||||
|
||||
span.innerText = `activePanel: ${group.activePanel?.id || 'null'}`;
|
||||
|
||||
this._disposables.push(() => d1.dispose());
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this._disposables.forEach((dispose) => dispose());
|
||||
}
|
||||
}
|
||||
|
||||
const api = createDockview(document.getElementById('app'), {
|
||||
className: 'dockview-theme-abyss',
|
||||
createComponent: (options): IContentRenderer => {
|
||||
switch (options.name) {
|
||||
case 'default':
|
||||
return new Panel();
|
||||
default:
|
||||
throw new Error('Panel not found');
|
||||
}
|
||||
},
|
||||
createPrefixHeaderActionComponent: (group): IHeaderActionsRenderer => {
|
||||
return new PrefixHeader(group);
|
||||
},
|
||||
createLeftHeaderActionComponent: (group): IHeaderActionsRenderer => {
|
||||
return new LeftHeaderActions(group);
|
||||
},
|
||||
createRightHeaderActionComponent: (group): IHeaderActionsRenderer => {
|
||||
return new RightHeaderActions(group);
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_1',
|
||||
component: 'default',
|
||||
title: 'Panel 1',
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_2',
|
||||
component: 'default',
|
||||
title: 'Panel 2',
|
||||
position: {
|
||||
direction: 'right',
|
||||
},
|
||||
});
|
||||
|
||||
api.addPanel({
|
||||
id: 'panel_3',
|
||||
component: 'default',
|
||||
title: 'Panel 3',
|
||||
position: {
|
||||
direction: 'below',
|
||||
},
|
||||
});
|
Loading…
Reference in New Issue
Block a user