mirror of
https://github.com/mathuo/dockview
synced 2025-02-09 01:45:45 +00:00
Merge pull request #541 from mathuo/538-interested-in-porting-dockview-to-vuejs
feat: Vue 3 Support
This commit is contained in:
commit
6ca39ba58b
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -7,7 +7,8 @@
|
|||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"redhat.vscode-yaml",
|
"redhat.vscode-yaml",
|
||||||
"dbaeumer.vscode-eslint",
|
"dbaeumer.vscode-eslint",
|
||||||
"editorconfig.editorconfig"
|
"editorconfig.editorconfig",
|
||||||
|
"vue.volar"
|
||||||
],
|
],
|
||||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||||
"unwantedRecommendations": []
|
"unwantedRecommendations": []
|
||||||
|
12
package.json
12
package.json
@ -45,6 +45,9 @@
|
|||||||
"@types/react-dom": "^18.2.18",
|
"@types/react-dom": "^18.2.18",
|
||||||
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
"@typescript-eslint/eslint-plugin": "^6.17.0",
|
||||||
"@typescript-eslint/parser": "^6.17.0",
|
"@typescript-eslint/parser": "^6.17.0",
|
||||||
|
"@vitejs/plugin-vue": "^5.0.4",
|
||||||
|
"@vue/tsconfig": "^0.5.1",
|
||||||
|
"concurrently": "^8.2.2",
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"fs-extra": "^11.2.0",
|
"fs-extra": "^11.2.0",
|
||||||
@ -66,9 +69,16 @@
|
|||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"typedoc": "^0.25.6",
|
"typedoc": "^0.25.6",
|
||||||
"typescript": "^5.3.3"
|
"typescript": "^5.3.3",
|
||||||
|
"vite": "^5.1.5",
|
||||||
|
"vue": "^3.4.21",
|
||||||
|
"vue-sfc-loader": "^0.1.0",
|
||||||
|
"vue-tsc": "^2.0.5"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18.0"
|
"node": ">=18.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"ag-grid-vue3": "^31.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
56
packages/dockview-angular/README.md
Normal file
56
packages/dockview-angular/README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<div align="center">
|
||||||
|
<h1>dockview</h1>
|
||||||
|
|
||||||
|
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews with ReactJS support written in TypeScript</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||||
|
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
|
||||||
|
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||||
|
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||||
|
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||||
|
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview)
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
Please see the website: https://dockview.dev
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Serialization / deserialization with full layout management
|
||||||
|
- Support for split-views, grid-views and 'dockable' views
|
||||||
|
- Themeable and customizable
|
||||||
|
- Tab and Group docking / Drag n' Drop
|
||||||
|
- Popout Windows
|
||||||
|
- Floating Groups
|
||||||
|
- Extensive API
|
||||||
|
- Supports Shadow DOMs
|
||||||
|
- High test coverage
|
||||||
|
- Documentation website with live examples
|
||||||
|
- Transparent builds and Code Analysis
|
||||||
|
- Security at mind - verifed publishing and builds through GitHub Actions
|
||||||
|
|
||||||
|
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
Dockview has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. You can install dockview from [npm](https://www.npmjs.com/package/dockview).
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install --save dockview
|
||||||
|
```
|
||||||
|
|
||||||
|
Within your project you must import or reference the stylesheet at `dockview/dist/styles/dockview.css` and attach a theme.
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import '~dockview/dist/styles/dockview.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
You should also attach a dockview theme to an element containing your components. For example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body classname="dockview-theme-dark"></body>
|
||||||
|
```
|
6
packages/dockview-angular/gulpfile.js
Normal file
6
packages/dockview-angular/gulpfile.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const gulp = require('gulp');
|
||||||
|
const buildfile = require('../../scripts/build');
|
||||||
|
|
||||||
|
buildfile.init();
|
||||||
|
|
||||||
|
gulp.task('run', gulp.series(['sass']));
|
34
packages/dockview-angular/jest.config.ts
Normal file
34
packages/dockview-angular/jest.config.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { JestConfigWithTsJest } from 'ts-jest';
|
||||||
|
|
||||||
|
const config: JestConfigWithTsJest = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
roots: ['<rootDir>/packages/dockview-angular'],
|
||||||
|
modulePaths: ['<rootDir>/packages/dockview-angular/src'],
|
||||||
|
displayName: { name: 'dockview-angular', color: 'blue' },
|
||||||
|
rootDir: '../../',
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'<rootDir>/packages/dockview-angular/src/**/*.{js,jsx,ts,tsx}',
|
||||||
|
],
|
||||||
|
setupFiles: [
|
||||||
|
// '<rootDir>/packages/dockview-angular/src/__tests__/__mocks__/resizeObserver.js',
|
||||||
|
],
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
|
||||||
|
coveragePathIgnorePatterns: ['/node_modules/'],
|
||||||
|
modulePathIgnorePatterns: [
|
||||||
|
// '<rootDir>/packages/dockview-angular/src/__tests__/__mocks__',
|
||||||
|
// '<rootDir>/packages/dockview-angular/src/__tests__/__test_utils__',
|
||||||
|
],
|
||||||
|
coverageDirectory: '<rootDir>/packages/dockview-angular/coverage/',
|
||||||
|
testResultsProcessor: 'jest-sonar-reporter',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.tsx?$': [
|
||||||
|
'ts-jest',
|
||||||
|
{
|
||||||
|
tsconfig: '<rootDir>/tsconfig.test.json',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
59
packages/dockview-angular/package.json
Normal file
59
packages/dockview-angular/package.json
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"name": "dockview-angular",
|
||||||
|
"version": "0.0.0-beta-0",
|
||||||
|
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||||
|
"keywords": [
|
||||||
|
"splitview",
|
||||||
|
"split-view",
|
||||||
|
"gridview",
|
||||||
|
"grid-view",
|
||||||
|
"dockview",
|
||||||
|
"dock-view",
|
||||||
|
"grid",
|
||||||
|
"tabs",
|
||||||
|
"layout",
|
||||||
|
"layout manager",
|
||||||
|
"dock layout",
|
||||||
|
"dock",
|
||||||
|
"docking",
|
||||||
|
"splitter",
|
||||||
|
"drag-and-drop",
|
||||||
|
"drag",
|
||||||
|
"drop",
|
||||||
|
"react",
|
||||||
|
"react-component"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/mathuo/dockview",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/mathuo/dockview/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mathuo/dockview.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"author": "https://github.com/mathuo",
|
||||||
|
"main": "./dist/cjs/index.js",
|
||||||
|
"module": "./dist/esm/index.js",
|
||||||
|
"types": "./dist/cjs/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "npm run build:package && npm run build:bundles",
|
||||||
|
"build:bundles": "rollup -c",
|
||||||
|
"build:cjs": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.json --verbose --extendedDiagnostics",
|
||||||
|
"build:css": "gulp sass",
|
||||||
|
"build:esm": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.esm.json --verbose --extendedDiagnostics",
|
||||||
|
"build:package": "npm run build:cjs && npm run build:esm && npm run build:css",
|
||||||
|
"clean": "rimraf dist/ .build/ .rollup.cache/",
|
||||||
|
"prepublishOnly": "npm run rebuild && npm run test",
|
||||||
|
"rebuild": "npm run clean && npm run build",
|
||||||
|
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview",
|
||||||
|
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dockview-core": "^1.10.1"
|
||||||
|
}
|
||||||
|
}
|
113
packages/dockview-angular/rollup.config.js
Normal file
113
packages/dockview-angular/rollup.config.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const { join } = require('path');
|
||||||
|
const typescript = require('@rollup/plugin-typescript');
|
||||||
|
const terser = require('@rollup/plugin-terser');
|
||||||
|
const postcss = require('rollup-plugin-postcss');
|
||||||
|
const nodeResolve = require('@rollup/plugin-node-resolve');
|
||||||
|
|
||||||
|
const { name, version, homepage, license } = require('./package.json');
|
||||||
|
const main = join(__dirname, './scripts/rollupEntryTarget.ts');
|
||||||
|
const mainNoStyles = join(__dirname, './src/index.ts');
|
||||||
|
const outputDir = join(__dirname, 'dist');
|
||||||
|
|
||||||
|
function outputFile(format, isMinified, withStyles) {
|
||||||
|
let filename = join(outputDir, name);
|
||||||
|
|
||||||
|
if (format !== 'umd') {
|
||||||
|
filename += `.${format}`;
|
||||||
|
}
|
||||||
|
if (isMinified) {
|
||||||
|
filename += '.min';
|
||||||
|
}
|
||||||
|
if (!withStyles) {
|
||||||
|
filename += '.noStyle';
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${filename}.js`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInput(options) {
|
||||||
|
const { withStyles } = options;
|
||||||
|
|
||||||
|
if (withStyles) {
|
||||||
|
return main;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainNoStyles;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBundle(format, options) {
|
||||||
|
const { withStyles, isMinified } = options;
|
||||||
|
const input = getInput(options);
|
||||||
|
const file = outputFile(format, isMinified, withStyles);
|
||||||
|
|
||||||
|
const external = [];
|
||||||
|
|
||||||
|
const output = {
|
||||||
|
file,
|
||||||
|
format,
|
||||||
|
sourcemap: true,
|
||||||
|
globals: {},
|
||||||
|
banner: [
|
||||||
|
`/**`,
|
||||||
|
` * ${name}`,
|
||||||
|
` * @version ${version}`,
|
||||||
|
` * @link ${homepage}`,
|
||||||
|
` * @license ${license}`,
|
||||||
|
` */`,
|
||||||
|
].join('\n'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
nodeResolve({
|
||||||
|
include: ['node_modules/dockview-core/**'],
|
||||||
|
}),
|
||||||
|
typescript({
|
||||||
|
tsconfig: 'tsconfig.esm.json',
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isMinified) {
|
||||||
|
plugins.push(terser());
|
||||||
|
}
|
||||||
|
if (withStyles) {
|
||||||
|
plugins.push(postcss());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'umd') {
|
||||||
|
output['name'] = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
external.push('react', 'react-dom');
|
||||||
|
|
||||||
|
if (format === 'umd') {
|
||||||
|
output.globals['react'] = 'React';
|
||||||
|
output.globals['react-dom'] = 'ReactDOM';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
plugins,
|
||||||
|
external,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
// amd
|
||||||
|
createBundle('amd', { withStyles: false, isMinified: false }),
|
||||||
|
createBundle('amd', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('amd', { withStyles: false, isMinified: true }),
|
||||||
|
createBundle('amd', { withStyles: true, isMinified: true }),
|
||||||
|
// umd
|
||||||
|
createBundle('umd', { withStyles: false, isMinified: false }),
|
||||||
|
createBundle('umd', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('umd', { withStyles: false, isMinified: true }),
|
||||||
|
createBundle('umd', { withStyles: true, isMinified: true }),
|
||||||
|
// cjs
|
||||||
|
createBundle('cjs', { withStyles: true, isMinified: false }),
|
||||||
|
// esm
|
||||||
|
createBundle('esm', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('esm', { withStyles: true, isMinified: true }),
|
||||||
|
];
|
2
packages/dockview-angular/scripts/rollupEntryTarget.ts
Normal file
2
packages/dockview-angular/scripts/rollupEntryTarget.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import '../dist/styles/dockview.css';
|
||||||
|
export * from '../src/index';
|
5
packages/dockview-angular/src/__tests__/empty.spec.ts
Normal file
5
packages/dockview-angular/src/__tests__/empty.spec.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
describe('empty', () => {
|
||||||
|
test('that passes', () => {
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
1
packages/dockview-angular/src/index.ts
Normal file
1
packages/dockview-angular/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from 'dockview-core';
|
14
packages/dockview-angular/tsconfig.esm.json
Normal file
14
packages/dockview-angular/tsconfig.esm.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "ES2020",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"target": "es6",
|
||||||
|
"outDir": "dist/esm",
|
||||||
|
"tsBuildInfoFile": ".build/tsconfig.tsbuildinfo.esm",
|
||||||
|
"jsx": "react",
|
||||||
|
"rootDir": "src"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["**/node_modules", "src/__tests__"]
|
||||||
|
}
|
11
packages/dockview-angular/tsconfig.json
Normal file
11
packages/dockview-angular/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist/cjs",
|
||||||
|
"tsBuildInfoFile": ".build/tsconfig.tsbuildinfo.cjs",
|
||||||
|
"jsx": "react",
|
||||||
|
"rootDir": "src"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["**/node_modules", "src/__tests__"]
|
||||||
|
}
|
5
packages/dockview-angular/typedoc.json
Normal file
5
packages/dockview-angular/typedoc.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": ["../../typedoc.base.json"],
|
||||||
|
"entryPoints": ["src/index.ts"],
|
||||||
|
"exclude": ["**/dist/**"]
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-core",
|
"name": "dockview-core",
|
||||||
"version": "1.12.0",
|
"version": "1.12.0",
|
||||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support",
|
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"splitview",
|
"splitview",
|
||||||
"split-view",
|
"split-view",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import * as React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* useful utility type to erase readonly signatures for testing purposes
|
* useful utility type to erase readonly signatures for testing purposes
|
||||||
|
@ -2,7 +2,7 @@ import { fireEvent } from '@testing-library/dom';
|
|||||||
import { Emitter, Event } from '../../../../events';
|
import { Emitter, Event } from '../../../../events';
|
||||||
import { ContentContainer } from '../../../../dockview/components/panel/content';
|
import { ContentContainer } from '../../../../dockview/components/panel/content';
|
||||||
import {
|
import {
|
||||||
GroupPanelContentPartInitParameters,
|
GroupPanelPartInitParameters,
|
||||||
IContentRenderer,
|
IContentRenderer,
|
||||||
} from '../../../../dockview/types';
|
} from '../../../../dockview/types';
|
||||||
import { CompositeDisposable } from '../../../../lifecycle';
|
import { CompositeDisposable } from '../../../../lifecycle';
|
||||||
@ -20,18 +20,13 @@ class TestContentRenderer
|
|||||||
{
|
{
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
|
|
||||||
readonly _onDidFocus = new Emitter<void>();
|
|
||||||
readonly _onDidBlur = new Emitter<void>();
|
|
||||||
readonly onDidFocus: Event<void> = this._onDidFocus.event;
|
|
||||||
readonly onDidBlur: Event<void> = this._onDidBlur.event;
|
|
||||||
|
|
||||||
constructor(public id: string) {
|
constructor(public id: string) {
|
||||||
super();
|
super();
|
||||||
this.element = document.createElement('div');
|
this.element = document.createElement('div');
|
||||||
this.element.id = id;
|
this.element.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
init(parameters: GroupPanelContentPartInitParameters): void {
|
init(parameters: GroupPanelPartInitParameters): void {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,16 +105,6 @@ describe('contentContainer', () => {
|
|||||||
expect(focus).toBe(1);
|
expect(focus).toBe(1);
|
||||||
expect(blur).toBe(1);
|
expect(blur).toBe(1);
|
||||||
|
|
||||||
// renderer explicitly asks for focus
|
|
||||||
contentRenderer._onDidFocus.fire();
|
|
||||||
expect(focus).toBe(2);
|
|
||||||
expect(blur).toBe(1);
|
|
||||||
|
|
||||||
// renderer explicitly looses focus
|
|
||||||
contentRenderer._onDidBlur.fire();
|
|
||||||
expect(focus).toBe(2);
|
|
||||||
expect(blur).toBe(2);
|
|
||||||
|
|
||||||
const contentRenderer2 = new TestContentRenderer('id-2');
|
const contentRenderer2 = new TestContentRenderer('id-2');
|
||||||
|
|
||||||
const panel2 = {
|
const panel2 = {
|
||||||
@ -130,25 +115,19 @@ describe('contentContainer', () => {
|
|||||||
} as Partial<IDockviewPanel>;
|
} as Partial<IDockviewPanel>;
|
||||||
|
|
||||||
cut.openPanel(panel2 as IDockviewPanel);
|
cut.openPanel(panel2 as IDockviewPanel);
|
||||||
expect(focus).toBe(2);
|
// expect(focus).toBe(2);
|
||||||
expect(blur).toBe(2);
|
// expect(blur).toBe(1);
|
||||||
|
|
||||||
// previous renderer events should no longer be attached to container
|
|
||||||
contentRenderer._onDidFocus.fire();
|
|
||||||
contentRenderer._onDidBlur.fire();
|
|
||||||
expect(focus).toBe(2);
|
|
||||||
expect(blur).toBe(2);
|
|
||||||
|
|
||||||
// new panel recieves focus
|
// new panel recieves focus
|
||||||
fireEvent.focus(contentRenderer2.element);
|
fireEvent.focus(contentRenderer2.element);
|
||||||
expect(focus).toBe(3);
|
expect(focus).toBe(2);
|
||||||
expect(blur).toBe(2);
|
expect(blur).toBe(1);
|
||||||
|
|
||||||
// new panel looses focus
|
// new panel looses focus
|
||||||
fireEvent.blur(contentRenderer2.element);
|
fireEvent.blur(contentRenderer2.element);
|
||||||
jest.runAllTimers();
|
jest.runAllTimers();
|
||||||
expect(focus).toBe(3);
|
expect(focus).toBe(2);
|
||||||
expect(blur).toBe(3);
|
expect(blur).toBe(2);
|
||||||
|
|
||||||
disposable.dispose();
|
disposable.dispose();
|
||||||
});
|
});
|
||||||
|
@ -18,6 +18,7 @@ import {
|
|||||||
} from '../../dockview/components/titlebar/tabsContainer';
|
} from '../../dockview/components/titlebar/tabsContainer';
|
||||||
import { fromPartial } from '@total-typescript/shoehorn';
|
import { fromPartial } from '@total-typescript/shoehorn';
|
||||||
import { DockviewApi } from '../../api/component.api';
|
import { DockviewApi } from '../../api/component.api';
|
||||||
|
import { DockviewDndOverlayEvent } from '../../dockview/options';
|
||||||
|
|
||||||
class PanelContentPartTest implements IContentRenderer {
|
class PanelContentPartTest implements IContentRenderer {
|
||||||
element: HTMLElement = document.createElement('div');
|
element: HTMLElement = document.createElement('div');
|
||||||
@ -2040,7 +2041,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 1000);
|
dockview.layout(1000, 1000);
|
||||||
@ -2147,7 +2147,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 1000);
|
dockview.layout(1000, 1000);
|
||||||
@ -2289,7 +2288,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 1000);
|
dockview.layout(1000, 1000);
|
||||||
@ -2418,7 +2416,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 1000);
|
dockview.layout(1000, 1000);
|
||||||
@ -2467,66 +2464,6 @@ describe('dockviewComponent', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('orthogonal realigment #5', () => {
|
|
||||||
const container = document.createElement('div');
|
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
|
||||||
parentElement: container,
|
|
||||||
components: {
|
|
||||||
default: PanelContentPartTest,
|
|
||||||
},
|
|
||||||
tabComponents: {
|
|
||||||
test_tab_id: PanelTabPartTest,
|
|
||||||
},
|
|
||||||
orientation: Orientation.VERTICAL,
|
|
||||||
});
|
|
||||||
|
|
||||||
dockview.layout(1000, 1000);
|
|
||||||
|
|
||||||
expect(dockview.orientation).toBe(Orientation.VERTICAL);
|
|
||||||
|
|
||||||
dockview.addPanel({
|
|
||||||
id: 'panel1',
|
|
||||||
component: 'default',
|
|
||||||
position: {
|
|
||||||
direction: 'left',
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
|
|
||||||
|
|
||||||
expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({
|
|
||||||
activeGroup: '1',
|
|
||||||
grid: {
|
|
||||||
root: {
|
|
||||||
type: 'branch',
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
type: 'leaf',
|
|
||||||
data: {
|
|
||||||
views: ['panel1'],
|
|
||||||
id: '1',
|
|
||||||
activeView: 'panel1',
|
|
||||||
},
|
|
||||||
size: 1000,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
size: 1000,
|
|
||||||
},
|
|
||||||
height: 1000,
|
|
||||||
width: 1000,
|
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
},
|
|
||||||
panels: {
|
|
||||||
panel1: {
|
|
||||||
id: 'panel1',
|
|
||||||
contentComponent: 'default',
|
|
||||||
title: 'panel1',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('that a empty component has no groups', () => {
|
test('that a empty component has no groups', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
@ -2538,7 +2475,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(dockview.groups.length).toBe(0);
|
expect(dockview.groups.length).toBe(0);
|
||||||
@ -2555,7 +2491,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(dockview.groups.length).toBe(0);
|
expect(dockview.groups.length).toBe(0);
|
||||||
@ -2595,7 +2530,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({
|
expect(JSON.parse(JSON.stringify(dockview.toJSON()))).toEqual({
|
||||||
@ -2624,7 +2558,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(100, 100);
|
dockview.layout(100, 100);
|
||||||
@ -2711,7 +2644,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(100, 100);
|
dockview.layout(100, 100);
|
||||||
@ -2774,7 +2706,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
|
expect(dockview.orientation).toBe(Orientation.HORIZONTAL);
|
||||||
@ -2865,7 +2796,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -2897,7 +2827,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -2922,8 +2851,6 @@ describe('dockviewComponent', () => {
|
|||||||
test('that external dnd events do not trigger the top-level center dnd target unless empty', () => {
|
test('that external dnd events do not trigger the top-level center dnd target unless empty', () => {
|
||||||
const container = document.createElement('div');
|
const container = document.createElement('div');
|
||||||
|
|
||||||
const showDndOverlay = jest.fn().mockReturnValue(true);
|
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
const dockview = new DockviewComponent({
|
||||||
parentElement: container,
|
parentElement: container,
|
||||||
components: {
|
components: {
|
||||||
@ -2932,8 +2859,13 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
});
|
||||||
showDndOverlay: showDndOverlay,
|
|
||||||
|
let events: DockviewDndOverlayEvent[] = [];
|
||||||
|
|
||||||
|
dockview.onUnhandledDragOverEvent((e) => {
|
||||||
|
events.push(e);
|
||||||
|
e.accept();
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -2973,13 +2905,11 @@ describe('dockviewComponent', () => {
|
|||||||
});
|
});
|
||||||
fireEvent(dockview.element, eventLeft);
|
fireEvent(dockview.element, eventLeft);
|
||||||
|
|
||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(events[0].nativeEvent).toBe(eventLeft);
|
||||||
nativeEvent: eventLeft,
|
expect(events[0].position).toBe('left');
|
||||||
position: 'left',
|
expect(events[0].target).toBe('edge');
|
||||||
target: 'edge',
|
expect(events[0].getData).toBe(getPanelData);
|
||||||
getData: getPanelData,
|
expect(events.length).toBe(1);
|
||||||
});
|
|
||||||
expect(showDndOverlay).toBeCalledTimes(1);
|
|
||||||
|
|
||||||
// right
|
// right
|
||||||
|
|
||||||
@ -2992,13 +2922,11 @@ describe('dockviewComponent', () => {
|
|||||||
});
|
});
|
||||||
fireEvent(dockview.element, eventRight);
|
fireEvent(dockview.element, eventRight);
|
||||||
|
|
||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(events[1].nativeEvent).toBe(eventRight);
|
||||||
nativeEvent: eventRight,
|
expect(events[1].position).toBe('right');
|
||||||
position: 'right',
|
expect(events[1].target).toBe('edge');
|
||||||
target: 'edge',
|
expect(events[1].getData).toBe(getPanelData);
|
||||||
getData: getPanelData,
|
expect(events.length).toBe(2);
|
||||||
});
|
|
||||||
expect(showDndOverlay).toBeCalledTimes(2);
|
|
||||||
|
|
||||||
// top
|
// top
|
||||||
|
|
||||||
@ -3011,13 +2939,11 @@ describe('dockviewComponent', () => {
|
|||||||
});
|
});
|
||||||
fireEvent(dockview.element, eventTop);
|
fireEvent(dockview.element, eventTop);
|
||||||
|
|
||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(events[2].nativeEvent).toBe(eventTop);
|
||||||
nativeEvent: eventTop,
|
expect(events[2].position).toBe('top');
|
||||||
position: 'top',
|
expect(events[2].target).toBe('edge');
|
||||||
target: 'edge',
|
expect(events[2].getData).toBe(getPanelData);
|
||||||
getData: getPanelData,
|
expect(events.length).toBe(3);
|
||||||
});
|
|
||||||
expect(showDndOverlay).toBeCalledTimes(3);
|
|
||||||
|
|
||||||
// top
|
// top
|
||||||
|
|
||||||
@ -3030,13 +2956,11 @@ describe('dockviewComponent', () => {
|
|||||||
});
|
});
|
||||||
fireEvent(dockview.element, eventBottom);
|
fireEvent(dockview.element, eventBottom);
|
||||||
|
|
||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(events[3].nativeEvent).toBe(eventBottom);
|
||||||
nativeEvent: eventBottom,
|
expect(events[3].position).toBe('bottom');
|
||||||
position: 'bottom',
|
expect(events[3].target).toBe('edge');
|
||||||
target: 'edge',
|
expect(events[3].getData).toBe(getPanelData);
|
||||||
getData: getPanelData,
|
expect(events.length).toBe(4);
|
||||||
});
|
|
||||||
expect(showDndOverlay).toBeCalledTimes(4);
|
|
||||||
|
|
||||||
// center
|
// center
|
||||||
|
|
||||||
@ -3050,7 +2974,7 @@ describe('dockviewComponent', () => {
|
|||||||
fireEvent(dockview.element, eventCenter);
|
fireEvent(dockview.element, eventCenter);
|
||||||
|
|
||||||
// expect not to be called for center
|
// expect not to be called for center
|
||||||
expect(showDndOverlay).toBeCalledTimes(4);
|
expect(events.length).toBe(4);
|
||||||
|
|
||||||
dockview.removePanel(panel1);
|
dockview.removePanel(panel1);
|
||||||
dockview.removePanel(panel2);
|
dockview.removePanel(panel2);
|
||||||
@ -3066,13 +2990,11 @@ describe('dockviewComponent', () => {
|
|||||||
});
|
});
|
||||||
fireEvent(dockview.element, eventCenter2);
|
fireEvent(dockview.element, eventCenter2);
|
||||||
|
|
||||||
expect(showDndOverlay).toHaveBeenCalledWith({
|
expect(events[4].nativeEvent).toBe(eventCenter2);
|
||||||
nativeEvent: eventTop,
|
expect(events[4].position).toBe('center');
|
||||||
position: 'center',
|
expect(events[4].target).toBe('edge');
|
||||||
target: 'edge',
|
expect(events[4].getData).toBe(getPanelData);
|
||||||
getData: getPanelData,
|
expect(events.length).toBe(5);
|
||||||
});
|
|
||||||
expect(showDndOverlay).toBeCalledTimes(5);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('that dragging a tab triggers onWillDragPanel', () => {
|
test('that dragging a tab triggers onWillDragPanel', () => {
|
||||||
@ -3086,7 +3008,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3126,7 +3047,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3167,7 +3087,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3257,7 +3176,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3380,7 +3298,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(dockview.disableResizing).toBeFalsy();
|
expect(dockview.disableResizing).toBeFalsy();
|
||||||
@ -3398,7 +3315,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
disableAutoResizing: true,
|
disableAutoResizing: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3417,7 +3333,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3445,7 +3360,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3488,7 +3402,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3531,7 +3444,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3582,7 +3494,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3633,7 +3544,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3684,7 +3594,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3743,7 +3652,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3786,7 +3694,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3829,7 +3736,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3880,7 +3786,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3931,7 +3836,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -3982,7 +3886,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4041,7 +3944,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4092,7 +3994,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4142,7 +4043,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4193,7 +4093,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4243,7 +4142,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4283,7 +4181,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4322,7 +4219,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4362,7 +4258,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4423,7 +4318,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4462,7 +4356,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4495,7 +4388,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4568,7 +4460,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
dockview.layout(1000, 500);
|
dockview.layout(1000, 500);
|
||||||
@ -4613,7 +4504,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
panel1 = dockview.addPanel({
|
panel1 = dockview.addPanel({
|
||||||
@ -4667,7 +4557,6 @@ describe('dockviewComponent', () => {
|
|||||||
tabComponents: {
|
tabComponents: {
|
||||||
test_tab_id: PanelTabPartTest,
|
test_tab_id: PanelTabPartTest,
|
||||||
},
|
},
|
||||||
orientation: Orientation.HORIZONTAL,
|
|
||||||
});
|
});
|
||||||
const api = new DockviewApi(dockview);
|
const api = new DockviewApi(dockview);
|
||||||
|
|
||||||
|
@ -641,7 +641,6 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
return {
|
return {
|
||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
|
||||||
parentElement: document.createElement('div'),
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
@ -649,6 +648,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
onDidRemovePanel: jest.fn(),
|
onDidRemovePanel: jest.fn(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const accessor = new accessorMock() as DockviewComponent;
|
const accessor = new accessorMock() as DockviewComponent;
|
||||||
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
const groupviewMock = jest.fn<Partial<DockviewGroupPanelModel>, []>(
|
||||||
() => {
|
() => {
|
||||||
@ -678,6 +678,12 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
new groupPanelMock() as DockviewGroupPanel
|
new groupPanelMock() as DockviewGroupPanel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
cut.onUnhandledDragOverEvent(() => {
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
|
||||||
const element = container
|
const element = container
|
||||||
.getElementsByClassName('content-container')
|
.getElementsByClassName('content-container')
|
||||||
.item(0)!;
|
.item(0)!;
|
||||||
@ -690,7 +696,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
fireEvent.dragEnter(element);
|
fireEvent.dragEnter(element);
|
||||||
fireEvent.dragOver(element);
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
expect(accessor.options.showDndOverlay).toBeCalledTimes(1);
|
expect(counter).toBe(1);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
element.getElementsByClassName('drop-target-dropzone').length
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
@ -702,7 +708,6 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
return {
|
return {
|
||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: () => true,
|
|
||||||
parentElement: document.createElement('div'),
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
@ -739,6 +744,10 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
new groupPanelMock() as DockviewGroupPanel
|
new groupPanelMock() as DockviewGroupPanel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
cut.onUnhandledDragOverEvent((e) => {
|
||||||
|
e.accept();
|
||||||
|
});
|
||||||
|
|
||||||
const element = container
|
const element = container
|
||||||
.getElementsByClassName('content-container')
|
.getElementsByClassName('content-container')
|
||||||
.item(0)!;
|
.item(0)!;
|
||||||
@ -794,7 +803,6 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
return {
|
return {
|
||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
|
||||||
parentElement: document.createElement('div'),
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
@ -833,6 +841,12 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
new groupPanelMock() as DockviewGroupPanel
|
new groupPanelMock() as DockviewGroupPanel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
cut.onUnhandledDragOverEvent(() => {
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
|
||||||
cut.openPanel(new TestPanel('panel1', panelApi));
|
cut.openPanel(new TestPanel('panel1', panelApi));
|
||||||
|
|
||||||
const element = container
|
const element = container
|
||||||
@ -852,7 +866,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
fireEvent.dragEnter(element);
|
fireEvent.dragEnter(element);
|
||||||
fireEvent.dragOver(element);
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
expect(accessor.options.showDndOverlay).toBeCalledTimes(0);
|
expect(counter).toBe(0);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
element.getElementsByClassName('drop-target-dropzone').length
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
@ -864,7 +878,6 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
return {
|
return {
|
||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
|
||||||
parentElement: document.createElement('div'),
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
@ -903,6 +916,12 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
new groupPanelMock() as DockviewGroupPanel
|
new groupPanelMock() as DockviewGroupPanel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
cut.onUnhandledDragOverEvent(() => {
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
|
||||||
cut.openPanel(new TestPanel('panel1', panelApi));
|
cut.openPanel(new TestPanel('panel1', panelApi));
|
||||||
cut.openPanel(new TestPanel('panel2', panelApi));
|
cut.openPanel(new TestPanel('panel2', panelApi));
|
||||||
|
|
||||||
@ -923,7 +942,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
fireEvent.dragEnter(element);
|
fireEvent.dragEnter(element);
|
||||||
fireEvent.dragOver(element);
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
expect(accessor.options.showDndOverlay).toBeCalledTimes(0);
|
expect(counter).toBe(0);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
element.getElementsByClassName('drop-target-dropzone').length
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
@ -935,7 +954,6 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
return {
|
return {
|
||||||
id: 'testcomponentid',
|
id: 'testcomponentid',
|
||||||
options: {
|
options: {
|
||||||
showDndOverlay: jest.fn(),
|
|
||||||
parentElement: document.createElement('div'),
|
parentElement: document.createElement('div'),
|
||||||
},
|
},
|
||||||
getPanel: jest.fn(),
|
getPanel: jest.fn(),
|
||||||
@ -974,6 +992,12 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
new groupPanelMock() as DockviewGroupPanel
|
new groupPanelMock() as DockviewGroupPanel
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let counter = 0;
|
||||||
|
|
||||||
|
cut.onUnhandledDragOverEvent(() => {
|
||||||
|
counter++;
|
||||||
|
});
|
||||||
|
|
||||||
cut.openPanel(new TestPanel('panel1', panelApi));
|
cut.openPanel(new TestPanel('panel1', panelApi));
|
||||||
cut.openPanel(new TestPanel('panel2', panelApi));
|
cut.openPanel(new TestPanel('panel2', panelApi));
|
||||||
|
|
||||||
@ -994,7 +1018,7 @@ describe('dockviewGroupPanelModel', () => {
|
|||||||
fireEvent.dragEnter(element);
|
fireEvent.dragEnter(element);
|
||||||
fireEvent.dragOver(element);
|
fireEvent.dragOver(element);
|
||||||
|
|
||||||
expect(accessor.options.showDndOverlay).toBeCalledTimes(1);
|
expect(counter).toBe(1);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
element.getElementsByClassName('drop-target-dropzone').length
|
element.getElementsByClassName('drop-target-dropzone').length
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
AddGroupOptions,
|
AddGroupOptions,
|
||||||
AddPanelOptions,
|
AddPanelOptions,
|
||||||
|
DockviewDndOverlayEvent,
|
||||||
MovementOptions,
|
MovementOptions,
|
||||||
} from '../dockview/options';
|
} from '../dockview/options';
|
||||||
import { Parameters } from '../panel/types';
|
import { Parameters } from '../panel/types';
|
||||||
@ -695,6 +696,10 @@ export class DockviewApi implements CommonApi<SerializedDockview> {
|
|||||||
return this.component.onWillDragPanel;
|
return this.component.onWillDragPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get onUnhandledDragOverEvent(): Event<DockviewDndOverlayEvent> {
|
||||||
|
return this.component.onUnhandledDragOverEvent;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All panel objects.
|
* All panel objects.
|
||||||
*/
|
*/
|
||||||
|
@ -1,12 +1,17 @@
|
|||||||
import { Position, positionToDirection } from '../dnd/droptarget';
|
import { Position, positionToDirection } from '../dnd/droptarget';
|
||||||
import { DockviewComponent } from '../dockview/dockviewComponent';
|
import { DockviewComponent } from '../dockview/dockviewComponent';
|
||||||
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
import { DockviewGroupPanel } from '../dockview/dockviewGroupPanel';
|
||||||
import { DockviewGroupLocation } from '../dockview/dockviewGroupPanelModel';
|
import {
|
||||||
|
DockviewGroupChangeEvent,
|
||||||
|
DockviewGroupLocation,
|
||||||
|
} from '../dockview/dockviewGroupPanelModel';
|
||||||
import { Emitter, Event } from '../events';
|
import { Emitter, Event } from '../events';
|
||||||
|
import { MutableDisposable } from '../lifecycle';
|
||||||
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
|
import { GridviewPanelApi, GridviewPanelApiImpl } from './gridviewPanelApi';
|
||||||
|
|
||||||
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
export interface DockviewGroupPanelApi extends GridviewPanelApi {
|
||||||
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent>;
|
||||||
|
readonly onDidActivePanelChange: Event<DockviewGroupChangeEvent>;
|
||||||
readonly location: DockviewGroupLocation;
|
readonly location: DockviewGroupLocation;
|
||||||
/**
|
/**
|
||||||
* If you require the Window object
|
* If you require the Window object
|
||||||
@ -27,6 +32,8 @@ export interface DockviewGroupPanelFloatingChangeEvent {
|
|||||||
const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
|
const NOT_INITIALIZED_MESSAGE = 'DockviewGroupPanelApiImpl not initialized';
|
||||||
|
|
||||||
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
||||||
|
private readonly _mutableDisposable = new MutableDisposable();
|
||||||
|
|
||||||
private _group: DockviewGroupPanel | undefined;
|
private _group: DockviewGroupPanel | undefined;
|
||||||
|
|
||||||
readonly _onDidLocationChange =
|
readonly _onDidLocationChange =
|
||||||
@ -34,6 +41,10 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
|
readonly onDidLocationChange: Event<DockviewGroupPanelFloatingChangeEvent> =
|
||||||
this._onDidLocationChange.event;
|
this._onDidLocationChange.event;
|
||||||
|
|
||||||
|
private readonly _onDidActivePanelChange =
|
||||||
|
new Emitter<DockviewGroupChangeEvent>();
|
||||||
|
readonly onDidActivePanelChange = this._onDidActivePanelChange.event;
|
||||||
|
|
||||||
get location(): DockviewGroupLocation {
|
get location(): DockviewGroupLocation {
|
||||||
if (!this._group) {
|
if (!this._group) {
|
||||||
throw new Error(NOT_INITIALIZED_MESSAGE);
|
throw new Error(NOT_INITIALIZED_MESSAGE);
|
||||||
@ -44,7 +55,11 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
constructor(id: string, private readonly accessor: DockviewComponent) {
|
constructor(id: string, private readonly accessor: DockviewComponent) {
|
||||||
super(id, '__dockviewgroup__');
|
super(id, '__dockviewgroup__');
|
||||||
|
|
||||||
this.addDisposables(this._onDidLocationChange);
|
this.addDisposables(
|
||||||
|
this._onDidLocationChange,
|
||||||
|
this._onDidActivePanelChange,
|
||||||
|
this._mutableDisposable
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(): void {
|
close(): void {
|
||||||
@ -116,5 +131,19 @@ export class DockviewGroupPanelApiImpl extends GridviewPanelApiImpl {
|
|||||||
|
|
||||||
initialize(group: DockviewGroupPanel): void {
|
initialize(group: DockviewGroupPanel): void {
|
||||||
this._group = group;
|
this._group = group;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO: Annoying initialization order caveat
|
||||||
|
*
|
||||||
|
* Due to the order on initialization we know that the model isn't defined until later in the same stack-frame of setup.
|
||||||
|
* By queuing a microtask we can ensure the setup is completed within the same stack-frame, but after everything else has
|
||||||
|
* finished ensuring the `model` is defined.
|
||||||
|
*/
|
||||||
|
queueMicrotask(() => {
|
||||||
|
this._mutableDisposable.value =
|
||||||
|
this._group!.model.onDidActivePanelChange((event) => {
|
||||||
|
this._onDidActivePanelChange.fire(event);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,9 +68,10 @@ export function positionToDirection(position: Position): Direction {
|
|||||||
|
|
||||||
export type Position = 'top' | 'bottom' | 'left' | 'right' | 'center';
|
export type Position = 'top' | 'bottom' | 'left' | 'right' | 'center';
|
||||||
|
|
||||||
export type CanDisplayOverlay =
|
export type CanDisplayOverlay = (
|
||||||
| boolean
|
dragEvent: DragEvent,
|
||||||
| ((dragEvent: DragEvent, state: Position) => boolean);
|
state: Position
|
||||||
|
) => boolean;
|
||||||
|
|
||||||
export type MeasuredValue = { value: number; type: 'pixels' | 'percentage' };
|
export type MeasuredValue = { value: number; type: 'pixels' | 'percentage' };
|
||||||
|
|
||||||
@ -170,6 +171,11 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.options.canDisplayOverlay(e, quadrant)) {
|
||||||
|
this.removeDropTarget();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const willShowOverlayEvent = new WillShowOverlayEvent({
|
const willShowOverlayEvent = new WillShowOverlayEvent({
|
||||||
nativeEvent: e,
|
nativeEvent: e,
|
||||||
position: quadrant,
|
position: quadrant,
|
||||||
@ -186,16 +192,6 @@ export class Droptarget extends CompositeDisposable {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof this.options.canDisplayOverlay === 'boolean') {
|
|
||||||
if (!this.options.canDisplayOverlay) {
|
|
||||||
this.removeDropTarget();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (!this.options.canDisplayOverlay(e, quadrant)) {
|
|
||||||
this.removeDropTarget();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.markAsUsed(e);
|
this.markAsUsed(e);
|
||||||
|
|
||||||
if (!this.targetElement) {
|
if (!this.targetElement) {
|
||||||
|
@ -157,9 +157,6 @@ export class ContentContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (doRender) {
|
if (doRender) {
|
||||||
const _onDidFocus = panel.view.content.onDidFocus;
|
|
||||||
const _onDidBlur = panel.view.content.onDidBlur;
|
|
||||||
|
|
||||||
const focusTracker = trackFocus(container);
|
const focusTracker = trackFocus(container);
|
||||||
const disposable = new CompositeDisposable();
|
const disposable = new CompositeDisposable();
|
||||||
|
|
||||||
@ -169,17 +166,6 @@ export class ContentContainer
|
|||||||
focusTracker.onDidBlur(() => this._onDidBlur.fire())
|
focusTracker.onDidBlur(() => this._onDidBlur.fire())
|
||||||
);
|
);
|
||||||
|
|
||||||
if (_onDidFocus) {
|
|
||||||
disposable.addDisposables(
|
|
||||||
_onDidFocus(() => this._onDidFocus.fire())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (_onDidBlur) {
|
|
||||||
disposable.addDisposables(
|
|
||||||
_onDidBlur(() => this._onDidBlur.fire())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.disposable.value = disposable;
|
this.disposable.value = disposable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
} from '../dnd/droptarget';
|
} from '../dnd/droptarget';
|
||||||
import { tail, sequenceEquals, remove } from '../array';
|
import { tail, sequenceEquals, remove } from '../array';
|
||||||
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
import { DockviewPanel, IDockviewPanel } from './dockviewPanel';
|
||||||
import { CompositeDisposable, Disposable, IDisposable } from '../lifecycle';
|
import { CompositeDisposable, Disposable } from '../lifecycle';
|
||||||
import { Event, Emitter, addDisposableWindowListener } from '../events';
|
import { Event, Emitter, addDisposableWindowListener } from '../events';
|
||||||
import { Watermark } from './components/watermark/watermark';
|
import { Watermark } from './components/watermark/watermark';
|
||||||
import { IWatermarkRenderer, GroupviewPanelState } from './types';
|
import { IWatermarkRenderer, GroupviewPanelState } from './types';
|
||||||
@ -23,6 +23,9 @@ import {
|
|||||||
AddGroupOptions,
|
AddGroupOptions,
|
||||||
AddPanelOptions,
|
AddPanelOptions,
|
||||||
DockviewComponentOptions,
|
DockviewComponentOptions,
|
||||||
|
DockviewDndOverlayEvent,
|
||||||
|
DockviewOptions,
|
||||||
|
DockviewUnhandledDragOverEvent,
|
||||||
isGroupOptionsWithGroup,
|
isGroupOptionsWithGroup,
|
||||||
isGroupOptionsWithPanel,
|
isGroupOptionsWithPanel,
|
||||||
isPanelOptionsWithGroup,
|
isPanelOptionsWithGroup,
|
||||||
@ -233,25 +236,6 @@ function typeValidate(data: SerializedDockview): void {
|
|||||||
typeValidate2(grid.root, '.grid.root');
|
typeValidate2(grid.root, '.grid.root');
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DockviewComponentUpdateOptions = Pick<
|
|
||||||
DockviewComponentOptions,
|
|
||||||
| 'orientation'
|
|
||||||
| 'components'
|
|
||||||
| 'frameworkComponents'
|
|
||||||
| 'tabComponents'
|
|
||||||
| 'frameworkTabComponents'
|
|
||||||
| 'showDndOverlay'
|
|
||||||
| 'watermarkFrameworkComponent'
|
|
||||||
| 'defaultTabComponent'
|
|
||||||
| 'createLeftHeaderActionsElement'
|
|
||||||
| 'createRightHeaderActionsElement'
|
|
||||||
| 'createPrefixHeaderActionsElement'
|
|
||||||
| 'disableFloatingGroups'
|
|
||||||
| 'floatingGroupBounds'
|
|
||||||
| 'rootOverlayModel'
|
|
||||||
| 'disableDnd'
|
|
||||||
>;
|
|
||||||
|
|
||||||
type MoveGroupOptions = {
|
type MoveGroupOptions = {
|
||||||
from: { group: DockviewGroupPanel };
|
from: { group: DockviewGroupPanel };
|
||||||
to: { group: DockviewGroupPanel; position: Position };
|
to: { group: DockviewGroupPanel; position: Position };
|
||||||
@ -286,8 +270,9 @@ export interface IDockviewComponent extends IBaseGrid<DockviewGroupPanel> {
|
|||||||
readonly onDidRemoveGroup: Event<DockviewGroupPanel>;
|
readonly onDidRemoveGroup: Event<DockviewGroupPanel>;
|
||||||
readonly onDidAddGroup: Event<DockviewGroupPanel>;
|
readonly onDidAddGroup: Event<DockviewGroupPanel>;
|
||||||
readonly onDidActiveGroupChange: Event<DockviewGroupPanel | undefined>;
|
readonly onDidActiveGroupChange: Event<DockviewGroupPanel | undefined>;
|
||||||
|
readonly onUnhandledDragOverEvent: Event<DockviewDndOverlayEvent>;
|
||||||
readonly options: DockviewComponentOptions;
|
readonly options: DockviewComponentOptions;
|
||||||
updateOptions(options: DockviewComponentUpdateOptions): void;
|
updateOptions(options: DockviewOptions): void;
|
||||||
moveGroupOrPanel(options: MoveGroupOrPanelOptions): void;
|
moveGroupOrPanel(options: MoveGroupOrPanelOptions): void;
|
||||||
moveGroup(options: MoveGroupOptions): void;
|
moveGroup(options: MoveGroupOptions): void;
|
||||||
doSetGroupActive: (group: DockviewGroupPanel, skipFocus?: boolean) => void;
|
doSetGroupActive: (group: DockviewGroupPanel, skipFocus?: boolean) => void;
|
||||||
@ -354,6 +339,11 @@ export class DockviewComponent
|
|||||||
readonly onWillShowOverlay: Event<WillShowOverlayLocationEvent> =
|
readonly onWillShowOverlay: Event<WillShowOverlayLocationEvent> =
|
||||||
this._onWillShowOverlay.event;
|
this._onWillShowOverlay.event;
|
||||||
|
|
||||||
|
private readonly _onUnhandledDragOverEvent =
|
||||||
|
new Emitter<DockviewDndOverlayEvent>();
|
||||||
|
readonly onUnhandledDragOverEvent: Event<DockviewDndOverlayEvent> =
|
||||||
|
this._onUnhandledDragOverEvent.event;
|
||||||
|
|
||||||
private readonly _onDidRemovePanel = new Emitter<IDockviewPanel>();
|
private readonly _onDidRemovePanel = new Emitter<IDockviewPanel>();
|
||||||
readonly onDidRemovePanel: Event<IDockviewPanel> =
|
readonly onDidRemovePanel: Event<IDockviewPanel> =
|
||||||
this._onDidRemovePanel.event;
|
this._onDidRemovePanel.event;
|
||||||
@ -436,8 +426,10 @@ export class DockviewComponent
|
|||||||
constructor(options: DockviewComponentOptions) {
|
constructor(options: DockviewComponentOptions) {
|
||||||
super({
|
super({
|
||||||
proportionalLayout: true,
|
proportionalLayout: true,
|
||||||
orientation: options.orientation ?? Orientation.HORIZONTAL,
|
orientation: Orientation.HORIZONTAL,
|
||||||
styles: options.styles,
|
styles: options.hideBorders
|
||||||
|
? { separatorBorder: 'transparent' }
|
||||||
|
: undefined,
|
||||||
parentElement: options.parentElement,
|
parentElement: options.parentElement,
|
||||||
disableAutoResizing: options.disableAutoResizing,
|
disableAutoResizing: options.disableAutoResizing,
|
||||||
locked: options.locked,
|
locked: options.locked,
|
||||||
@ -467,6 +459,7 @@ export class DockviewComponent
|
|||||||
this._onDidAddGroup,
|
this._onDidAddGroup,
|
||||||
this._onDidRemoveGroup,
|
this._onDidRemoveGroup,
|
||||||
this._onDidActiveGroupChange,
|
this._onDidActiveGroupChange,
|
||||||
|
this._onUnhandledDragOverEvent,
|
||||||
this.onDidAdd((event) => {
|
this.onDidAdd((event) => {
|
||||||
if (!this._moving) {
|
if (!this._moving) {
|
||||||
this._onDidAddGroup.fire(event);
|
this._onDidAddGroup.fire(event);
|
||||||
@ -547,25 +540,25 @@ export class DockviewComponent
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.options.showDndOverlay) {
|
if (position === 'center' && this.gridview.length !== 0) {
|
||||||
if (position === 'center' && this.gridview.length !== 0) {
|
/**
|
||||||
/**
|
* for external events only show the four-corner drag overlays, disable
|
||||||
* for external events only show the four-corner drag overlays, disable
|
* the center position so that external drag events can fall through to the group
|
||||||
* the center position so that external drag events can fall through to the group
|
* and panel drop target handlers
|
||||||
* and panel drop target handlers
|
*/
|
||||||
*/
|
return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.options.showDndOverlay({
|
|
||||||
nativeEvent: event,
|
|
||||||
position: position,
|
|
||||||
target: 'edge',
|
|
||||||
getData: getPanelData,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
const firedEvent = new DockviewUnhandledDragOverEvent(
|
||||||
|
event,
|
||||||
|
'edge',
|
||||||
|
position,
|
||||||
|
getPanelData
|
||||||
|
);
|
||||||
|
|
||||||
|
this._onUnhandledDragOverEvent.fire(firedEvent);
|
||||||
|
|
||||||
|
return firedEvent.isAccepted;
|
||||||
},
|
},
|
||||||
acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
|
acceptedTargetZones: ['top', 'bottom', 'left', 'right', 'center'],
|
||||||
overlayModel:
|
overlayModel:
|
||||||
@ -1052,24 +1045,17 @@ export class DockviewComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateOptions(options: DockviewComponentUpdateOptions): void {
|
updateOptions(options: Partial<DockviewComponentOptions>): void {
|
||||||
const changed_orientation =
|
|
||||||
typeof options.orientation === 'string' &&
|
|
||||||
this.gridview.orientation !== options.orientation;
|
|
||||||
const changed_floatingGroupBounds =
|
const changed_floatingGroupBounds =
|
||||||
options.floatingGroupBounds !== undefined &&
|
'floatingGroupBounds' in options &&
|
||||||
options.floatingGroupBounds !== this.options.floatingGroupBounds;
|
options.floatingGroupBounds !== this.options.floatingGroupBounds;
|
||||||
|
|
||||||
const changed_rootOverlayOptions =
|
const changed_rootOverlayOptions =
|
||||||
options.rootOverlayModel !== undefined &&
|
'rootOverlayModel' in options &&
|
||||||
options.rootOverlayModel !== this.options.rootOverlayModel;
|
options.rootOverlayModel !== this.options.rootOverlayModel;
|
||||||
|
|
||||||
this._options = { ...this.options, ...options };
|
this._options = { ...this.options, ...options };
|
||||||
|
|
||||||
if (changed_orientation) {
|
|
||||||
this.gridview.orientation = options.orientation!;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed_floatingGroupBounds) {
|
if (changed_floatingGroupBounds) {
|
||||||
for (const group of this._floatingGroups) {
|
for (const group of this._floatingGroups) {
|
||||||
switch (this.options.floatingGroupBounds) {
|
switch (this.options.floatingGroupBounds) {
|
||||||
@ -2162,6 +2148,9 @@ export class DockviewComponent
|
|||||||
|
|
||||||
this._onWillShowOverlay.fire(event);
|
this._onWillShowOverlay.fire(event);
|
||||||
}),
|
}),
|
||||||
|
view.model.onUnhandledDragOverEvent((event) => {
|
||||||
|
this._onUnhandledDragOverEvent.fire(event);
|
||||||
|
}),
|
||||||
view.model.onDidAddPanel((event) => {
|
view.model.onDidAddPanel((event) => {
|
||||||
if (this._moving) {
|
if (this._moving) {
|
||||||
return;
|
return;
|
||||||
|
@ -31,7 +31,11 @@ import {
|
|||||||
import { IWatermarkRenderer } from './types';
|
import { IWatermarkRenderer } from './types';
|
||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { IDockviewPanel } from './dockviewPanel';
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
import { IHeaderActionsRenderer } from './options';
|
import {
|
||||||
|
DockviewDndOverlayEvent,
|
||||||
|
DockviewUnhandledDragOverEvent,
|
||||||
|
IHeaderActionsRenderer,
|
||||||
|
} from './options';
|
||||||
import { OverlayRenderContainer } from '../overlayRenderContainer';
|
import { OverlayRenderContainer } from '../overlayRenderContainer';
|
||||||
import { TitleEvent } from '../api/dockviewPanelApi';
|
import { TitleEvent } from '../api/dockviewPanelApi';
|
||||||
|
|
||||||
@ -310,6 +314,11 @@ export class DockviewGroupPanelModel
|
|||||||
readonly onDidActivePanelChange: Event<DockviewGroupChangeEvent> =
|
readonly onDidActivePanelChange: Event<DockviewGroupChangeEvent> =
|
||||||
this._onDidActivePanelChange.event;
|
this._onDidActivePanelChange.event;
|
||||||
|
|
||||||
|
private readonly _onUnhandledDragOverEvent =
|
||||||
|
new Emitter<DockviewDndOverlayEvent>();
|
||||||
|
readonly onUnhandledDragOverEvent: Event<DockviewDndOverlayEvent> =
|
||||||
|
this._onUnhandledDragOverEvent.event;
|
||||||
|
|
||||||
private readonly _api: DockviewApi;
|
private readonly _api: DockviewApi;
|
||||||
|
|
||||||
get element(): HTMLElement {
|
get element(): HTMLElement {
|
||||||
@ -491,7 +500,8 @@ export class DockviewGroupPanelModel
|
|||||||
this._onWillDrop,
|
this._onWillDrop,
|
||||||
this._onDidAddPanel,
|
this._onDidAddPanel,
|
||||||
this._onDidRemovePanel,
|
this._onDidRemovePanel,
|
||||||
this._onDidActivePanelChange
|
this._onDidActivePanelChange,
|
||||||
|
this._onUnhandledDragOverEvent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -536,45 +546,48 @@ export class DockviewGroupPanelModel
|
|||||||
this.setActive(this.isActive, true);
|
this.setActive(this.isActive, true);
|
||||||
this.updateContainer();
|
this.updateContainer();
|
||||||
|
|
||||||
if (this.accessor.options.createRightHeaderActionsElement) {
|
if (this.accessor.options.headerRightActionComponent) {
|
||||||
this._rightHeaderActions =
|
this._rightHeaderActions =
|
||||||
this.accessor.options.createRightHeaderActionsElement(
|
this.accessor.options.headerRightActionComponent(
|
||||||
this.groupPanel
|
this.groupPanel
|
||||||
);
|
);
|
||||||
this.addDisposables(this._rightHeaderActions);
|
this.addDisposables(this._rightHeaderActions);
|
||||||
this._rightHeaderActions.init({
|
this._rightHeaderActions.init({
|
||||||
containerApi: this._api,
|
containerApi: this._api,
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
|
group: this.groupPanel,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setRightActionsElement(
|
this.tabsContainer.setRightActionsElement(
|
||||||
this._rightHeaderActions.element
|
this._rightHeaderActions.element
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.accessor.options.createLeftHeaderActionsElement) {
|
if (this.accessor.options.headerLeftActionComponent) {
|
||||||
this._leftHeaderActions =
|
this._leftHeaderActions =
|
||||||
this.accessor.options.createLeftHeaderActionsElement(
|
this.accessor.options.headerLeftActionComponent(
|
||||||
this.groupPanel
|
this.groupPanel
|
||||||
);
|
);
|
||||||
this.addDisposables(this._leftHeaderActions);
|
this.addDisposables(this._leftHeaderActions);
|
||||||
this._leftHeaderActions.init({
|
this._leftHeaderActions.init({
|
||||||
containerApi: this._api,
|
containerApi: this._api,
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
|
group: this.groupPanel,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setLeftActionsElement(
|
this.tabsContainer.setLeftActionsElement(
|
||||||
this._leftHeaderActions.element
|
this._leftHeaderActions.element
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.accessor.options.createPrefixHeaderActionsElement) {
|
if (this.accessor.options.headerPrefixActionComponent) {
|
||||||
this._prefixHeaderActions =
|
this._prefixHeaderActions =
|
||||||
this.accessor.options.createPrefixHeaderActionsElement(
|
this.accessor.options.headerPrefixActionComponent(
|
||||||
this.groupPanel
|
this.groupPanel
|
||||||
);
|
);
|
||||||
this.addDisposables(this._prefixHeaderActions);
|
this.addDisposables(this._prefixHeaderActions);
|
||||||
this._prefixHeaderActions.init({
|
this._prefixHeaderActions.init({
|
||||||
containerApi: this._api,
|
containerApi: this._api,
|
||||||
api: this.groupPanel.api,
|
api: this.groupPanel.api,
|
||||||
|
group: this.groupPanel,
|
||||||
});
|
});
|
||||||
this.tabsContainer.setPrefixActionsElement(
|
this.tabsContainer.setPrefixActionsElement(
|
||||||
this._prefixHeaderActions.element
|
this._prefixHeaderActions.element
|
||||||
@ -853,10 +866,8 @@ export class DockviewGroupPanelModel
|
|||||||
this._panels.splice(index, 1);
|
this._panels.splice(index, 1);
|
||||||
|
|
||||||
if (this.mostRecentlyUsed.includes(panel)) {
|
if (this.mostRecentlyUsed.includes(panel)) {
|
||||||
this.mostRecentlyUsed.splice(
|
const index = this.mostRecentlyUsed.indexOf(panel);
|
||||||
this.mostRecentlyUsed.indexOf(panel),
|
this.mostRecentlyUsed.splice(index, 1);
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const disposable = this._panelDisposables.get(panel.id);
|
const disposable = this._panelDisposables.get(panel.id);
|
||||||
@ -977,17 +988,17 @@ export class DockviewGroupPanelModel
|
|||||||
position: Position,
|
position: Position,
|
||||||
target: DockviewGroupDropLocation
|
target: DockviewGroupDropLocation
|
||||||
): boolean {
|
): boolean {
|
||||||
// custom overlay handler
|
const firedEvent = new DockviewUnhandledDragOverEvent(
|
||||||
if (this.accessor.options.showDndOverlay) {
|
event,
|
||||||
return this.accessor.options.showDndOverlay({
|
target,
|
||||||
nativeEvent: event,
|
position,
|
||||||
target,
|
getPanelData,
|
||||||
group: this.accessor.getPanel(this.id)!,
|
this.accessor.getPanel(this.id)!
|
||||||
position,
|
);
|
||||||
getData: getPanelData,
|
|
||||||
});
|
this._onUnhandledDragOverEvent.fire(firedEvent);
|
||||||
}
|
|
||||||
return false;
|
return firedEvent.isAccepted;
|
||||||
}
|
}
|
||||||
|
|
||||||
private handleDropEvent(
|
private handleDropEvent(
|
||||||
|
@ -44,7 +44,7 @@ export class DockviewPanelModel implements IDockviewPanelModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init(params: GroupPanelPartInitParameters): void {
|
init(params: GroupPanelPartInitParameters): void {
|
||||||
this.content.init({ ...params, tab: this.tab });
|
this.content.init(params);
|
||||||
this.tab.init(params);
|
this.tab.init(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
packages/dockview-core/src/dockview/framework.ts
Normal file
43
packages/dockview-core/src/dockview/framework.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { DockviewApi } from '../api/component.api';
|
||||||
|
import { DockviewGroupPanelApi } from '../api/dockviewGroupPanelApi';
|
||||||
|
import { DockviewPanelApi } from '../api/dockviewPanelApi';
|
||||||
|
import { PanelParameters } from '../framwork';
|
||||||
|
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
|
|
||||||
|
export interface IGroupPanelBaseProps<T extends { [index: string]: any } = any>
|
||||||
|
extends PanelParameters<T> {
|
||||||
|
api: DockviewPanelApi;
|
||||||
|
containerApi: DockviewApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IDockviewPanelHeaderProps<
|
||||||
|
T extends { [index: string]: any } = any
|
||||||
|
> = IGroupPanelBaseProps<T>;
|
||||||
|
|
||||||
|
export type IDockviewPanelProps<T extends { [index: string]: any } = any> =
|
||||||
|
IGroupPanelBaseProps<T>;
|
||||||
|
|
||||||
|
export interface IDockviewHeaderActionsProps {
|
||||||
|
api: DockviewGroupPanelApi;
|
||||||
|
containerApi: DockviewApi;
|
||||||
|
panels: IDockviewPanel[];
|
||||||
|
activePanel: IDockviewPanel | undefined;
|
||||||
|
isGroupActive: boolean;
|
||||||
|
group: DockviewGroupPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGroupHeaderProps {
|
||||||
|
api: DockviewGroupPanelApi;
|
||||||
|
containerApi: DockviewApi;
|
||||||
|
group: IDockviewGroupPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IWatermarkPanelProps {
|
||||||
|
containerApi: DockviewApi;
|
||||||
|
group?: IDockviewGroupPanel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DockviewReadyEvent {
|
||||||
|
api: DockviewApi;
|
||||||
|
}
|
@ -9,25 +9,24 @@ import {
|
|||||||
} from './types';
|
} from './types';
|
||||||
import { Parameters } from '../panel/types';
|
import { Parameters } from '../panel/types';
|
||||||
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
import { DockviewGroupPanel } from './dockviewGroupPanel';
|
||||||
import { ISplitviewStyles, Orientation } from '../splitview/splitview';
|
|
||||||
import { PanelTransfer } from '../dnd/dataTransfer';
|
import { PanelTransfer } from '../dnd/dataTransfer';
|
||||||
import { IDisposable } from '../lifecycle';
|
import { IDisposable } from '../lifecycle';
|
||||||
import { DroptargetOverlayModel, Position } from '../dnd/droptarget';
|
import { DroptargetOverlayModel, Position } from '../dnd/droptarget';
|
||||||
import { DockviewGroupDropLocation, GroupOptions } from './dockviewGroupPanelModel';
|
import {
|
||||||
|
DockviewGroupDropLocation,
|
||||||
|
GroupOptions,
|
||||||
|
} from './dockviewGroupPanelModel';
|
||||||
import { IDockviewPanel } from './dockviewPanel';
|
import { IDockviewPanel } from './dockviewPanel';
|
||||||
import {
|
import {
|
||||||
ComponentConstructor,
|
ComponentConstructor,
|
||||||
FrameworkFactory,
|
FrameworkFactory,
|
||||||
} from '../panel/componentFactory';
|
} from '../panel/componentFactory';
|
||||||
import { DockviewGroupPanelApi } from '../api/dockviewGroupPanelApi';
|
|
||||||
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
import { DockviewPanelRenderer } from '../overlayRenderContainer';
|
||||||
|
import { IGroupHeaderProps } from './framework';
|
||||||
|
|
||||||
export interface IHeaderActionsRenderer extends IDisposable {
|
export interface IHeaderActionsRenderer extends IDisposable {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
init(params: {
|
init(params: IGroupHeaderProps): void;
|
||||||
containerApi: DockviewApi;
|
|
||||||
api: DockviewGroupPanelApi;
|
|
||||||
}): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupPanelFrameworkComponentFactory {
|
export interface GroupPanelFrameworkComponentFactory {
|
||||||
@ -42,54 +41,15 @@ export interface TabContextMenuEvent {
|
|||||||
panel: IDockviewPanel;
|
panel: IDockviewPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DockviewRenderFunctions {
|
|
||||||
tabComponents?: {
|
|
||||||
[componentName: string]: ComponentConstructor<ITabRenderer>;
|
|
||||||
};
|
|
||||||
components?: {
|
|
||||||
[componentName: string]: ComponentConstructor<IContentRenderer>;
|
|
||||||
};
|
|
||||||
frameworkTabComponents?: {
|
|
||||||
[componentName: string]: any;
|
|
||||||
};
|
|
||||||
frameworkComponents?: {
|
|
||||||
[componentName: string]: any;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ViewFactoryData {
|
export interface ViewFactoryData {
|
||||||
content: string;
|
content: string;
|
||||||
tab?: string;
|
tab?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DockviewDndOverlayEvent {
|
export interface DockviewOptions {
|
||||||
nativeEvent: DragEvent;
|
|
||||||
target: DockviewGroupDropLocation;
|
|
||||||
position: Position;
|
|
||||||
group?: DockviewGroupPanel;
|
|
||||||
getData: () => PanelTransfer | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
|
||||||
disableAutoResizing?: boolean;
|
disableAutoResizing?: boolean;
|
||||||
watermarkComponent?: WatermarkConstructor;
|
hideBorders?: boolean;
|
||||||
watermarkFrameworkComponent?: any;
|
|
||||||
frameworkComponentFactory?: GroupPanelFrameworkComponentFactory;
|
|
||||||
orientation?: Orientation;
|
|
||||||
styles?: ISplitviewStyles;
|
|
||||||
defaultTabComponent?: string;
|
|
||||||
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
|
||||||
createRightHeaderActionsElement?: (
|
|
||||||
group: DockviewGroupPanel
|
|
||||||
) => IHeaderActionsRenderer;
|
|
||||||
createLeftHeaderActionsElement?: (
|
|
||||||
group: DockviewGroupPanel
|
|
||||||
) => IHeaderActionsRenderer;
|
|
||||||
createPrefixHeaderActionsElement?: (
|
|
||||||
group: DockviewGroupPanel
|
|
||||||
) => IHeaderActionsRenderer;
|
|
||||||
singleTabMode?: 'fullwidth' | 'default';
|
singleTabMode?: 'fullwidth' | 'default';
|
||||||
parentElement: HTMLElement;
|
|
||||||
disableFloatingGroups?: boolean;
|
disableFloatingGroups?: boolean;
|
||||||
floatingGroupBounds?:
|
floatingGroupBounds?:
|
||||||
| 'boundedWithinViewport'
|
| 'boundedWithinViewport'
|
||||||
@ -105,6 +65,91 @@ export interface DockviewComponentOptions extends DockviewRenderFunctions {
|
|||||||
disableDnd?: boolean;
|
disableDnd?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface DockviewDndOverlayEvent {
|
||||||
|
nativeEvent: DragEvent;
|
||||||
|
target: DockviewGroupDropLocation;
|
||||||
|
position: Position;
|
||||||
|
group?: DockviewGroupPanel;
|
||||||
|
getData: () => PanelTransfer | undefined;
|
||||||
|
//
|
||||||
|
isAccepted: boolean;
|
||||||
|
accept(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class DockviewUnhandledDragOverEvent implements DockviewDndOverlayEvent {
|
||||||
|
private _isAccepted = false;
|
||||||
|
|
||||||
|
get isAccepted(): boolean {
|
||||||
|
return this._isAccepted;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
readonly nativeEvent: DragEvent,
|
||||||
|
readonly target: DockviewGroupDropLocation,
|
||||||
|
readonly position: Position,
|
||||||
|
readonly getData: () => PanelTransfer | undefined,
|
||||||
|
readonly group?: DockviewGroupPanel
|
||||||
|
) {}
|
||||||
|
|
||||||
|
accept(): void {
|
||||||
|
this._isAccepted = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PROPERTY_KEYS: (keyof DockviewOptions)[] = (() => {
|
||||||
|
/**
|
||||||
|
* by readong the keys from an empty value object TypeScript will error
|
||||||
|
* when we add or remove new properties to `DockviewOptions`
|
||||||
|
*/
|
||||||
|
const properties: Record<keyof DockviewOptions, undefined> = {
|
||||||
|
disableAutoResizing: undefined,
|
||||||
|
hideBorders: undefined,
|
||||||
|
singleTabMode: undefined,
|
||||||
|
disableFloatingGroups: undefined,
|
||||||
|
floatingGroupBounds: undefined,
|
||||||
|
popoutUrl: undefined,
|
||||||
|
defaultRenderer: undefined,
|
||||||
|
debug: undefined,
|
||||||
|
rootOverlayModel: undefined,
|
||||||
|
locked: undefined,
|
||||||
|
disableDnd: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Object.keys(properties) as (keyof DockviewOptions)[];
|
||||||
|
})();
|
||||||
|
|
||||||
|
export interface DockviewFrameworkOptions {
|
||||||
|
headerRightActionComponent?: (
|
||||||
|
group: DockviewGroupPanel
|
||||||
|
) => IHeaderActionsRenderer;
|
||||||
|
headerLeftActionComponent?: (
|
||||||
|
group: DockviewGroupPanel
|
||||||
|
) => IHeaderActionsRenderer;
|
||||||
|
headerPrefixActionComponent?: (
|
||||||
|
group: DockviewGroupPanel
|
||||||
|
) => IHeaderActionsRenderer;
|
||||||
|
tabComponents?: {
|
||||||
|
[componentName: string]: ComponentConstructor<ITabRenderer>;
|
||||||
|
};
|
||||||
|
components?: {
|
||||||
|
[componentName: string]: ComponentConstructor<IContentRenderer>;
|
||||||
|
};
|
||||||
|
frameworkTabComponents?: {
|
||||||
|
[componentName: string]: any;
|
||||||
|
};
|
||||||
|
frameworkComponents?: {
|
||||||
|
[componentName: string]: any;
|
||||||
|
};
|
||||||
|
parentElement: HTMLElement;
|
||||||
|
defaultTabComponent?: string;
|
||||||
|
watermarkComponent?: WatermarkConstructor;
|
||||||
|
watermarkFrameworkComponent?: any;
|
||||||
|
frameworkComponentFactory?: GroupPanelFrameworkComponentFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DockviewComponentOptions = DockviewOptions &
|
||||||
|
DockviewFrameworkOptions;
|
||||||
|
|
||||||
export interface PanelOptions<P extends object = Parameters> {
|
export interface PanelOptions<P extends object = Parameters> {
|
||||||
component: string;
|
component: string;
|
||||||
tabComponent?: string;
|
tabComponent?: string;
|
||||||
|
@ -18,11 +18,6 @@ export interface GroupPanelPartInitParameters
|
|||||||
containerApi: DockviewApi;
|
containerApi: DockviewApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GroupPanelContentPartInitParameters
|
|
||||||
extends GroupPanelPartInitParameters {
|
|
||||||
tab: ITabRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WatermarkRendererInitParameters {
|
export interface WatermarkRendererInitParameters {
|
||||||
containerApi: DockviewApi;
|
containerApi: DockviewApi;
|
||||||
group?: IDockviewGroupPanel;
|
group?: IDockviewGroupPanel;
|
||||||
@ -31,7 +26,7 @@ export interface WatermarkRendererInitParameters {
|
|||||||
export interface IWatermarkRenderer
|
export interface IWatermarkRenderer
|
||||||
extends Optional<
|
extends Optional<
|
||||||
Omit<IPanel, 'id' | 'init'>,
|
Omit<IPanel, 'id' | 'init'>,
|
||||||
'dispose' | 'update' | 'layout' | 'toJSON'
|
'dispose' | 'update' | 'layout' | 'toJSON' | 'focus'
|
||||||
> {
|
> {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
init: (params: WatermarkRendererInitParameters) => void;
|
init: (params: WatermarkRendererInitParameters) => void;
|
||||||
@ -41,7 +36,7 @@ export interface IWatermarkRenderer
|
|||||||
export interface ITabRenderer
|
export interface ITabRenderer
|
||||||
extends Optional<
|
extends Optional<
|
||||||
Omit<IPanel, 'id'>,
|
Omit<IPanel, 'id'>,
|
||||||
'dispose' | 'update' | 'layout' | 'toJSON'
|
'dispose' | 'update' | 'layout' | 'toJSON' | 'focus'
|
||||||
> {
|
> {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
init(parameters: GroupPanelPartInitParameters): void;
|
init(parameters: GroupPanelPartInitParameters): void;
|
||||||
@ -50,12 +45,10 @@ export interface ITabRenderer
|
|||||||
export interface IContentRenderer
|
export interface IContentRenderer
|
||||||
extends Optional<
|
extends Optional<
|
||||||
Omit<IPanel, 'id'>,
|
Omit<IPanel, 'id'>,
|
||||||
'dispose' | 'update' | 'layout' | 'toJSON'
|
'dispose' | 'update' | 'layout' | 'toJSON' | 'focus'
|
||||||
> {
|
> {
|
||||||
readonly element: HTMLElement;
|
readonly element: HTMLElement;
|
||||||
readonly onDidFocus?: Event<void>;
|
init(parameters: GroupPanelPartInitParameters): void;
|
||||||
readonly onDidBlur?: Event<void>;
|
|
||||||
init(parameters: GroupPanelContentPartInitParameters): void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// watermark component
|
// watermark component
|
||||||
|
6
packages/dockview-core/src/framwork.ts
Normal file
6
packages/dockview-core/src/framwork.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { Parameters } from "./panel/types";
|
||||||
|
|
||||||
|
export interface PanelParameters<T extends {} = Parameters> {
|
||||||
|
params: T;
|
||||||
|
}
|
||||||
|
|
@ -23,19 +23,28 @@ export {
|
|||||||
export * from './paneview/paneview';
|
export * from './paneview/paneview';
|
||||||
export * from './gridview/gridview';
|
export * from './gridview/gridview';
|
||||||
export { GridviewComponentOptions } from './gridview/options';
|
export { GridviewComponentOptions } from './gridview/options';
|
||||||
export * from './dockview/dockviewGroupPanelModel';
|
|
||||||
export * from './gridview/baseComponentGridview';
|
export * from './gridview/baseComponentGridview';
|
||||||
|
|
||||||
export * from './paneview/draggablePaneviewPanel';
|
export * from './paneview/draggablePaneviewPanel';
|
||||||
|
|
||||||
export * from './dockview/components/panel/content';
|
export * from './dockview/components/panel/content';
|
||||||
export * from './dockview/components/tab/tab';
|
export * from './dockview/components/tab/tab';
|
||||||
|
export * from './dockview/dockviewGroupPanelModel';
|
||||||
export {
|
export {
|
||||||
TabDragEvent,
|
TabDragEvent,
|
||||||
GroupDragEvent,
|
GroupDragEvent,
|
||||||
} from './dockview/components/titlebar/tabsContainer';
|
} from './dockview/components/titlebar/tabsContainer';
|
||||||
export * from './dockview/types';
|
export * from './dockview/types';
|
||||||
export * from './dockview/dockviewGroupPanel';
|
export * from './dockview/dockviewGroupPanel';
|
||||||
|
export {
|
||||||
|
IGroupPanelBaseProps,
|
||||||
|
IDockviewPanelHeaderProps,
|
||||||
|
IDockviewPanelProps,
|
||||||
|
IDockviewHeaderActionsProps,
|
||||||
|
IGroupHeaderProps,
|
||||||
|
IWatermarkPanelProps,
|
||||||
|
DockviewReadyEvent,
|
||||||
|
} from './dockview/framework';
|
||||||
|
|
||||||
export * from './dockview/options';
|
export * from './dockview/options';
|
||||||
export * from './dockview/dockviewPanel';
|
export * from './dockview/dockviewPanel';
|
||||||
|
56
packages/dockview-react/README.md
Normal file
56
packages/dockview-react/README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<div align="center">
|
||||||
|
<h1>dockview</h1>
|
||||||
|
|
||||||
|
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews with ReactJS support written in TypeScript</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||||
|
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
|
||||||
|
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||||
|
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||||
|
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||||
|
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview)
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
Please see the website: https://dockview.dev
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Serialization / deserialization with full layout management
|
||||||
|
- Support for split-views, grid-views and 'dockable' views
|
||||||
|
- Themeable and customizable
|
||||||
|
- Tab and Group docking / Drag n' Drop
|
||||||
|
- Popout Windows
|
||||||
|
- Floating Groups
|
||||||
|
- Extensive API
|
||||||
|
- Supports Shadow DOMs
|
||||||
|
- High test coverage
|
||||||
|
- Documentation website with live examples
|
||||||
|
- Transparent builds and Code Analysis
|
||||||
|
- Security at mind - verifed publishing and builds through GitHub Actions
|
||||||
|
|
||||||
|
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
Dockview has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. You can install dockview from [npm](https://www.npmjs.com/package/dockview).
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install --save dockview
|
||||||
|
```
|
||||||
|
|
||||||
|
Within your project you must import or reference the stylesheet at `dockview/dist/styles/dockview.css` and attach a theme.
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import '~dockview/dist/styles/dockview.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
You should also attach a dockview theme to an element containing your components. For example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body classname="dockview-theme-dark"></body>
|
||||||
|
```
|
6
packages/dockview-react/gulpfile.js
Normal file
6
packages/dockview-react/gulpfile.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const gulp = require('gulp');
|
||||||
|
const buildfile = require('../../scripts/build');
|
||||||
|
|
||||||
|
buildfile.init();
|
||||||
|
|
||||||
|
gulp.task('run', gulp.series(['sass']));
|
34
packages/dockview-react/jest.config.ts
Normal file
34
packages/dockview-react/jest.config.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { JestConfigWithTsJest } from 'ts-jest';
|
||||||
|
|
||||||
|
const config: JestConfigWithTsJest = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
roots: ['<rootDir>/packages/dockview-react'],
|
||||||
|
modulePaths: ['<rootDir>/packages/dockview-react/src'],
|
||||||
|
displayName: { name: 'dockview-react', color: 'blue' },
|
||||||
|
rootDir: '../../',
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'<rootDir>/packages/dockview-react/src/**/*.{js,jsx,ts,tsx}',
|
||||||
|
],
|
||||||
|
setupFiles: [
|
||||||
|
// '<rootDir>/packages/dockview-react/src/__tests__/__mocks__/resizeObserver.js',
|
||||||
|
],
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
|
||||||
|
coveragePathIgnorePatterns: ['/node_modules/'],
|
||||||
|
modulePathIgnorePatterns: [
|
||||||
|
// '<rootDir>/packages/dockview-react/src/__tests__/__mocks__',
|
||||||
|
// '<rootDir>/packages/dockview-react/src/__tests__/__test_utils__',
|
||||||
|
],
|
||||||
|
coverageDirectory: '<rootDir>/packages/dockview-react/coverage/',
|
||||||
|
testResultsProcessor: 'jest-sonar-reporter',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.tsx?$': [
|
||||||
|
'ts-jest',
|
||||||
|
{
|
||||||
|
tsconfig: '<rootDir>/tsconfig.test.json',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
59
packages/dockview-react/package.json
Normal file
59
packages/dockview-react/package.json
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"name": "dockview-react",
|
||||||
|
"version": "0.0.0-beta-0",
|
||||||
|
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||||
|
"keywords": [
|
||||||
|
"splitview",
|
||||||
|
"split-view",
|
||||||
|
"gridview",
|
||||||
|
"grid-view",
|
||||||
|
"dockview",
|
||||||
|
"dock-view",
|
||||||
|
"grid",
|
||||||
|
"tabs",
|
||||||
|
"layout",
|
||||||
|
"layout manager",
|
||||||
|
"dock layout",
|
||||||
|
"dock",
|
||||||
|
"docking",
|
||||||
|
"splitter",
|
||||||
|
"drag-and-drop",
|
||||||
|
"drag",
|
||||||
|
"drop",
|
||||||
|
"react",
|
||||||
|
"react-component"
|
||||||
|
],
|
||||||
|
"homepage": "https://github.com/mathuo/dockview",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/mathuo/dockview/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mathuo/dockview.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"author": "https://github.com/mathuo",
|
||||||
|
"main": "./dist/cjs/index.js",
|
||||||
|
"module": "./dist/esm/index.js",
|
||||||
|
"types": "./dist/cjs/index.d.ts",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build": "npm run build:package && npm run build:bundles",
|
||||||
|
"build:bundles": "rollup -c",
|
||||||
|
"build:cjs": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.json --verbose --extendedDiagnostics",
|
||||||
|
"build:css": "gulp sass",
|
||||||
|
"build:esm": "cross-env ../../node_modules/.bin/tsc --build ./tsconfig.esm.json --verbose --extendedDiagnostics",
|
||||||
|
"build:package": "npm run build:cjs && npm run build:esm && npm run build:css",
|
||||||
|
"clean": "rimraf dist/ .build/ .rollup.cache/",
|
||||||
|
"prepublishOnly": "npm run rebuild && npm run test",
|
||||||
|
"rebuild": "npm run clean && npm run build",
|
||||||
|
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview",
|
||||||
|
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dockview": "^1.10.1"
|
||||||
|
}
|
||||||
|
}
|
113
packages/dockview-react/rollup.config.js
Normal file
113
packages/dockview-react/rollup.config.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const { join } = require('path');
|
||||||
|
const typescript = require('@rollup/plugin-typescript');
|
||||||
|
const terser = require('@rollup/plugin-terser');
|
||||||
|
const postcss = require('rollup-plugin-postcss');
|
||||||
|
const nodeResolve = require('@rollup/plugin-node-resolve');
|
||||||
|
|
||||||
|
const { name, version, homepage, license } = require('./package.json');
|
||||||
|
const main = join(__dirname, './scripts/rollupEntryTarget.ts');
|
||||||
|
const mainNoStyles = join(__dirname, './src/index.ts');
|
||||||
|
const outputDir = join(__dirname, 'dist');
|
||||||
|
|
||||||
|
function outputFile(format, isMinified, withStyles) {
|
||||||
|
let filename = join(outputDir, name);
|
||||||
|
|
||||||
|
if (format !== 'umd') {
|
||||||
|
filename += `.${format}`;
|
||||||
|
}
|
||||||
|
if (isMinified) {
|
||||||
|
filename += '.min';
|
||||||
|
}
|
||||||
|
if (!withStyles) {
|
||||||
|
filename += '.noStyle';
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${filename}.js`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInput(options) {
|
||||||
|
const { withStyles } = options;
|
||||||
|
|
||||||
|
if (withStyles) {
|
||||||
|
return main;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainNoStyles;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBundle(format, options) {
|
||||||
|
const { withStyles, isMinified } = options;
|
||||||
|
const input = getInput(options);
|
||||||
|
const file = outputFile(format, isMinified, withStyles);
|
||||||
|
|
||||||
|
const external = [];
|
||||||
|
|
||||||
|
const output = {
|
||||||
|
file,
|
||||||
|
format,
|
||||||
|
sourcemap: true,
|
||||||
|
globals: {},
|
||||||
|
banner: [
|
||||||
|
`/**`,
|
||||||
|
` * ${name}`,
|
||||||
|
` * @version ${version}`,
|
||||||
|
` * @link ${homepage}`,
|
||||||
|
` * @license ${license}`,
|
||||||
|
` */`,
|
||||||
|
].join('\n'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
nodeResolve({
|
||||||
|
include: ['node_modules/dockview-core/**'],
|
||||||
|
}),
|
||||||
|
typescript({
|
||||||
|
tsconfig: 'tsconfig.esm.json',
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isMinified) {
|
||||||
|
plugins.push(terser());
|
||||||
|
}
|
||||||
|
if (withStyles) {
|
||||||
|
plugins.push(postcss());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'umd') {
|
||||||
|
output['name'] = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
external.push('react', 'react-dom');
|
||||||
|
|
||||||
|
if (format === 'umd') {
|
||||||
|
output.globals['react'] = 'React';
|
||||||
|
output.globals['react-dom'] = 'ReactDOM';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
plugins,
|
||||||
|
external,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
// amd
|
||||||
|
createBundle('amd', { withStyles: false, isMinified: false }),
|
||||||
|
createBundle('amd', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('amd', { withStyles: false, isMinified: true }),
|
||||||
|
createBundle('amd', { withStyles: true, isMinified: true }),
|
||||||
|
// umd
|
||||||
|
createBundle('umd', { withStyles: false, isMinified: false }),
|
||||||
|
createBundle('umd', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('umd', { withStyles: false, isMinified: true }),
|
||||||
|
createBundle('umd', { withStyles: true, isMinified: true }),
|
||||||
|
// cjs
|
||||||
|
createBundle('cjs', { withStyles: true, isMinified: false }),
|
||||||
|
// esm
|
||||||
|
createBundle('esm', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('esm', { withStyles: true, isMinified: true }),
|
||||||
|
];
|
2
packages/dockview-react/scripts/rollupEntryTarget.ts
Normal file
2
packages/dockview-react/scripts/rollupEntryTarget.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import '../dist/styles/dockview.css';
|
||||||
|
export * from '../src/index';
|
5
packages/dockview-react/src/__tests__/empty.spec.ts
Normal file
5
packages/dockview-react/src/__tests__/empty.spec.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
describe('empty', () => {
|
||||||
|
test('that passes', () => {
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
0
packages/dockview-react/src/index.scss
Normal file
0
packages/dockview-react/src/index.scss
Normal file
1
packages/dockview-react/src/index.ts
Normal file
1
packages/dockview-react/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from 'dockview';
|
14
packages/dockview-react/tsconfig.esm.json
Normal file
14
packages/dockview-react/tsconfig.esm.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "ES2020",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"target": "es6",
|
||||||
|
"outDir": "dist/esm",
|
||||||
|
"tsBuildInfoFile": ".build/tsconfig.tsbuildinfo.esm",
|
||||||
|
"jsx": "react",
|
||||||
|
"rootDir": "src"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["**/node_modules", "src/__tests__"]
|
||||||
|
}
|
11
packages/dockview-react/tsconfig.json
Normal file
11
packages/dockview-react/tsconfig.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.base.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"outDir": "dist/cjs",
|
||||||
|
"tsBuildInfoFile": ".build/tsconfig.tsbuildinfo.cjs",
|
||||||
|
"jsx": "react",
|
||||||
|
"rootDir": "src"
|
||||||
|
},
|
||||||
|
"include": ["src"],
|
||||||
|
"exclude": ["**/node_modules", "src/__tests__"]
|
||||||
|
}
|
5
packages/dockview-react/typedoc.json
Normal file
5
packages/dockview-react/typedoc.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": ["../../typedoc.base.json"],
|
||||||
|
"entryPoints": ["src/index.ts"],
|
||||||
|
"exclude": ["**/dist/**"]
|
||||||
|
}
|
56
packages/dockview-vue/README.md
Normal file
56
packages/dockview-vue/README.md
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<div align="center">
|
||||||
|
<h1>dockview</h1>
|
||||||
|
|
||||||
|
<p>Zero dependency layout manager supporting tabs, groups, grids and splitviews with ReactJS support written in TypeScript</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
[![npm version](https://badge.fury.io/js/dockview.svg)](https://www.npmjs.com/package/dockview)
|
||||||
|
[![npm](https://img.shields.io/npm/dm/dockview)](https://www.npmjs.com/package/dockview)
|
||||||
|
[![CI Build](https://github.com/mathuo/dockview/workflows/CI/badge.svg)](https://github.com/mathuo/dockview/actions?query=workflow%3ACI)
|
||||||
|
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=coverage)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||||
|
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=mathuo_dockview&metric=alert_status)](https://sonarcloud.io/summary/overall?id=mathuo_dockview)
|
||||||
|
[![Bundle Phobia](https://badgen.net/bundlephobia/minzip/dockview)](https://bundlephobia.com/result?p=dockview)
|
||||||
|
|
||||||
|
##
|
||||||
|
|
||||||
|
Please see the website: https://dockview.dev
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Serialization / deserialization with full layout management
|
||||||
|
- Support for split-views, grid-views and 'dockable' views
|
||||||
|
- Themeable and customizable
|
||||||
|
- Tab and Group docking / Drag n' Drop
|
||||||
|
- Popout Windows
|
||||||
|
- Floating Groups
|
||||||
|
- Extensive API
|
||||||
|
- Supports Shadow DOMs
|
||||||
|
- High test coverage
|
||||||
|
- Documentation website with live examples
|
||||||
|
- Transparent builds and Code Analysis
|
||||||
|
- Security at mind - verifed publishing and builds through GitHub Actions
|
||||||
|
|
||||||
|
Want to verify our builds? Go [here](https://www.npmjs.com/package/dockview#Provenance).
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
Dockview has a peer dependency on `react >= 16.8.0` and `react-dom >= 16.8.0`. You can install dockview from [npm](https://www.npmjs.com/package/dockview).
|
||||||
|
|
||||||
|
```
|
||||||
|
npm install --save dockview
|
||||||
|
```
|
||||||
|
|
||||||
|
Within your project you must import or reference the stylesheet at `dockview/dist/styles/dockview.css` and attach a theme.
|
||||||
|
|
||||||
|
```css
|
||||||
|
@import '~dockview/dist/styles/dockview.css';
|
||||||
|
```
|
||||||
|
|
||||||
|
You should also attach a dockview theme to an element containing your components. For example:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<body classname="dockview-theme-dark"></body>
|
||||||
|
```
|
6
packages/dockview-vue/gulpfile.js
Normal file
6
packages/dockview-vue/gulpfile.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
const gulp = require('gulp');
|
||||||
|
const buildfile = require('../../scripts/build');
|
||||||
|
|
||||||
|
buildfile.init();
|
||||||
|
|
||||||
|
gulp.task('run', gulp.series(['sass']));
|
34
packages/dockview-vue/jest.config.ts
Normal file
34
packages/dockview-vue/jest.config.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { JestConfigWithTsJest } from 'ts-jest';
|
||||||
|
|
||||||
|
const config: JestConfigWithTsJest = {
|
||||||
|
preset: 'ts-jest',
|
||||||
|
roots: ['<rootDir>/packages/dockview-vue'],
|
||||||
|
modulePaths: ['<rootDir>/packages/dockview-vue/src'],
|
||||||
|
displayName: { name: 'dockview', color: 'blue' },
|
||||||
|
rootDir: '../../',
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'<rootDir>/packages/dockview-vue/src/**/*.{js,jsx,ts,tsx}',
|
||||||
|
],
|
||||||
|
setupFiles: [
|
||||||
|
// '<rootDir>/packages/dockview-vue/src/__tests__/__mocks__/resizeObserver.js',
|
||||||
|
],
|
||||||
|
setupFilesAfterEnv: ['<rootDir>/jest-setup.ts'],
|
||||||
|
coveragePathIgnorePatterns: ['/node_modules/'],
|
||||||
|
modulePathIgnorePatterns: [
|
||||||
|
// '<rootDir>/packages/dockview-vue/src/__tests__/__mocks__',
|
||||||
|
// '<rootDir>/packages/dockview-vue/src/__tests__/__test_utils__',
|
||||||
|
],
|
||||||
|
coverageDirectory: '<rootDir>/packages/dockview-vue/coverage/',
|
||||||
|
testResultsProcessor: 'jest-sonar-reporter',
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
transform: {
|
||||||
|
'^.+\\.tsx?$': [
|
||||||
|
'ts-jest',
|
||||||
|
{
|
||||||
|
tsconfig: '<rootDir>/tsconfig.test.json',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
61
packages/dockview-vue/package.json
Normal file
61
packages/dockview-vue/package.json
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"name": "dockview-vue",
|
||||||
|
"version": "0.0.0-beta-0",
|
||||||
|
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||||
|
"keywords": [
|
||||||
|
"splitview",
|
||||||
|
"split-view",
|
||||||
|
"gridview",
|
||||||
|
"grid-view",
|
||||||
|
"dockview",
|
||||||
|
"dock-view",
|
||||||
|
"grid",
|
||||||
|
"tabs",
|
||||||
|
"layout",
|
||||||
|
"layout manager",
|
||||||
|
"dock layout",
|
||||||
|
"dock",
|
||||||
|
"docking",
|
||||||
|
"splitter",
|
||||||
|
"drag-and-drop",
|
||||||
|
"drag",
|
||||||
|
"drop",
|
||||||
|
"react",
|
||||||
|
"react-component"
|
||||||
|
],
|
||||||
|
"main": "dist/dockview-vue.umd.js",
|
||||||
|
"module": "dist/dockview-vue.es.js",
|
||||||
|
"types": "dist/types/index.d.ts",
|
||||||
|
"homepage": "https://github.com/mathuo/dockview",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/mathuo/dockview/issues"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/mathuo/dockview.git"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"author": "https://github.com/mathuo",
|
||||||
|
"files": [
|
||||||
|
"dist",
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"build-only": "vite build",
|
||||||
|
"build": "npm run build:package && npm run build:bundles",
|
||||||
|
"build:bundles": "rollup -c",
|
||||||
|
"build:cjs": "cross-env ../../node_modules/.bin/vue-tsc --build ./tsconfig.json --verbose --extendedDiagnostics",
|
||||||
|
"build:css": "gulp sass",
|
||||||
|
"build:esm": "cross-env ../../node_modules/.bin/vue-tsc --build ./tsconfig.esm.json --verbose --extendedDiagnostics",
|
||||||
|
"build:package": "npm run build-only && npm run build:types",
|
||||||
|
"clean": "rimraf dist/ .build/ .rollup.cache/",
|
||||||
|
"prepublishOnly": "npm run rebuild && npm run test",
|
||||||
|
"rebuild": "npm run clean && npm run build",
|
||||||
|
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview",
|
||||||
|
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage",
|
||||||
|
"build:types": "vue-tsc --project tsconfig.build-types.json --declaration --emitDeclarationOnly --outDir dist/types "
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"dockview-core": "^1.10.1"
|
||||||
|
}
|
||||||
|
}
|
116
packages/dockview-vue/rollup.config.js
Normal file
116
packages/dockview-vue/rollup.config.js
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const { join } = require('path');
|
||||||
|
const typescript = require('@rollup/plugin-typescript');
|
||||||
|
const terser = require('@rollup/plugin-terser');
|
||||||
|
const postcss = require('rollup-plugin-postcss');
|
||||||
|
const nodeResolve = require('@rollup/plugin-node-resolve');
|
||||||
|
const vue = require('@vitejs/plugin-vue');
|
||||||
|
|
||||||
|
const { name, version, homepage, license } = require('./package.json');
|
||||||
|
const main = join(__dirname, './scripts/rollupEntryTarget.ts');
|
||||||
|
const mainNoStyles = join(__dirname, './src/index.ts');
|
||||||
|
const outputDir = join(__dirname, 'dist');
|
||||||
|
|
||||||
|
function outputFile(format, isMinified, withStyles) {
|
||||||
|
let filename = join(outputDir, name);
|
||||||
|
|
||||||
|
if (format !== 'umd') {
|
||||||
|
filename += `.${format}`;
|
||||||
|
}
|
||||||
|
if (isMinified) {
|
||||||
|
filename += '.min';
|
||||||
|
}
|
||||||
|
if (!withStyles) {
|
||||||
|
filename += '.noStyle';
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${filename}.js`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInput(options) {
|
||||||
|
const { withStyles } = options;
|
||||||
|
|
||||||
|
if (withStyles) {
|
||||||
|
return main;
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainNoStyles;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createBundle(format, options) {
|
||||||
|
const { withStyles, isMinified } = options;
|
||||||
|
const input = getInput(options);
|
||||||
|
const file = outputFile(format, isMinified, withStyles);
|
||||||
|
|
||||||
|
const external = [];
|
||||||
|
|
||||||
|
const output = {
|
||||||
|
file,
|
||||||
|
format,
|
||||||
|
sourcemap: true,
|
||||||
|
globals: {},
|
||||||
|
banner: [
|
||||||
|
`/**`,
|
||||||
|
` * ${name}`,
|
||||||
|
` * @version ${version}`,
|
||||||
|
` * @link ${homepage}`,
|
||||||
|
` * @license ${license}`,
|
||||||
|
` */`,
|
||||||
|
].join('\n'),
|
||||||
|
};
|
||||||
|
|
||||||
|
const plugins = [
|
||||||
|
nodeResolve({
|
||||||
|
include: ['node_modules/dockview-core/**'],
|
||||||
|
}),
|
||||||
|
|
||||||
|
typescript({
|
||||||
|
tsconfig: 'tsconfig.config.json',
|
||||||
|
}),
|
||||||
|
vue({}),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (isMinified) {
|
||||||
|
plugins.push(terser());
|
||||||
|
}
|
||||||
|
if (withStyles) {
|
||||||
|
plugins.push(postcss());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (format === 'umd') {
|
||||||
|
output['name'] = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
external.push('react', 'react-dom');
|
||||||
|
|
||||||
|
if (format === 'umd') {
|
||||||
|
output.globals['react'] = 'React';
|
||||||
|
output.globals['react-dom'] = 'ReactDOM';
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
input,
|
||||||
|
output,
|
||||||
|
plugins,
|
||||||
|
external,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
// amd
|
||||||
|
createBundle('amd', { withStyles: false, isMinified: false }),
|
||||||
|
createBundle('amd', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('amd', { withStyles: false, isMinified: true }),
|
||||||
|
createBundle('amd', { withStyles: true, isMinified: true }),
|
||||||
|
// umd
|
||||||
|
createBundle('umd', { withStyles: false, isMinified: false }),
|
||||||
|
createBundle('umd', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('umd', { withStyles: false, isMinified: true }),
|
||||||
|
createBundle('umd', { withStyles: true, isMinified: true }),
|
||||||
|
// cjs
|
||||||
|
createBundle('cjs', { withStyles: true, isMinified: false }),
|
||||||
|
// esm
|
||||||
|
createBundle('esm', { withStyles: true, isMinified: false }),
|
||||||
|
createBundle('esm', { withStyles: true, isMinified: true }),
|
||||||
|
];
|
2
packages/dockview-vue/scripts/rollupEntryTarget.ts
Normal file
2
packages/dockview-vue/scripts/rollupEntryTarget.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import '../dist/styles/dockview.css';
|
||||||
|
export * from '../src/index';
|
5
packages/dockview-vue/src/__tests__/empty.spec.ts
Normal file
5
packages/dockview-vue/src/__tests__/empty.spec.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
describe('empty', () => {
|
||||||
|
test('that passes', () => {
|
||||||
|
expect(true).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
316
packages/dockview-vue/src/dockview/dockview.vue
Normal file
316
packages/dockview-vue/src/dockview/dockview.vue
Normal file
@ -0,0 +1,316 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
DockviewApi,
|
||||||
|
DockviewComponent,
|
||||||
|
type IContentRenderer,
|
||||||
|
type ITabRenderer,
|
||||||
|
type IWatermarkRenderer,
|
||||||
|
type IDockviewPanelProps,
|
||||||
|
type IDockviewPanelHeaderProps,
|
||||||
|
type IGroupPanelBaseProps,
|
||||||
|
type IWatermarkPanelProps,
|
||||||
|
type DockviewOptions,
|
||||||
|
PROPERTY_KEYS,
|
||||||
|
type DockviewFrameworkOptions,
|
||||||
|
type DockviewReadyEvent,
|
||||||
|
} from 'dockview-core';
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
onMounted,
|
||||||
|
defineProps,
|
||||||
|
defineEmits,
|
||||||
|
watch,
|
||||||
|
onBeforeUnmount,
|
||||||
|
markRaw,
|
||||||
|
toRaw,
|
||||||
|
getCurrentInstance,
|
||||||
|
} from 'vue';
|
||||||
|
import {
|
||||||
|
VueContentRenderer,
|
||||||
|
VueHeaderActionsRenderer,
|
||||||
|
VueTabRenderer,
|
||||||
|
VueWatermarkRenderer,
|
||||||
|
type VueComponent,
|
||||||
|
} from '../utils';
|
||||||
|
|
||||||
|
interface VueProps {
|
||||||
|
components: Record<string, VueComponent<IDockviewPanelProps>>;
|
||||||
|
tabComponents?: Record<string, VueComponent<IDockviewPanelHeaderProps>>;
|
||||||
|
watermarkComponent?: VueComponent<IWatermarkPanelProps>;
|
||||||
|
defaultTabComponent?: VueComponent<IDockviewPanelHeaderProps>;
|
||||||
|
rightHeaderActionsComponent?: VueComponent<IGroupPanelBaseProps>;
|
||||||
|
leftHeaderActionsComponent?: VueComponent<IGroupPanelBaseProps>;
|
||||||
|
prefixHeaderActionsComponent?: VueComponent<IGroupPanelBaseProps>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VUE_PROPERTIES = (() => {
|
||||||
|
const _value: Record<keyof VueProps, undefined> = {
|
||||||
|
components: undefined,
|
||||||
|
tabComponents: undefined,
|
||||||
|
watermarkComponent: undefined,
|
||||||
|
defaultTabComponent: undefined,
|
||||||
|
rightHeaderActionsComponent: undefined,
|
||||||
|
leftHeaderActionsComponent: undefined,
|
||||||
|
prefixHeaderActionsComponent: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Object.keys(_value) as (keyof VueProps)[];
|
||||||
|
})();
|
||||||
|
|
||||||
|
type VueEvents = {
|
||||||
|
ready: [event: DockviewReadyEvent];
|
||||||
|
};
|
||||||
|
|
||||||
|
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
||||||
|
|
||||||
|
export type IDockviewVueProps = DockviewOptions & VueProps;
|
||||||
|
|
||||||
|
function extractCoreOptions(props: IDockviewVueProps): DockviewOptions {
|
||||||
|
const coreOptions = (PROPERTY_KEYS as (keyof DockviewOptions)[]).reduce(
|
||||||
|
(obj, key) => {
|
||||||
|
(obj as any)[key] = props[key];
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
{} as Partial<DockviewOptions>
|
||||||
|
);
|
||||||
|
|
||||||
|
return coreOptions as DockviewOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const emit = defineEmits<VueEvents>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Anything here that is a Vue.js component should not be reactive
|
||||||
|
* i.e. markRaw(toRaw(...))
|
||||||
|
*/
|
||||||
|
const props = defineProps<IDockviewVueProps>();
|
||||||
|
|
||||||
|
const el = ref<HTMLElement | null>(null);
|
||||||
|
const instance = ref<DockviewComponent | null>(null);
|
||||||
|
|
||||||
|
|
||||||
|
PROPERTY_KEYS.forEach((coreOptionKey) => {
|
||||||
|
watch(
|
||||||
|
() => props[coreOptionKey],
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.updateOptions({ [coreOptionKey]: newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.components,
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.updateOptions({ frameworkComponents: newValue });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [props.tabComponents, props.defaultTabComponent],
|
||||||
|
([newTabComponents, newDefaultTabComponent], oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
const frameworkTabComponents = newTabComponents ?? {};
|
||||||
|
|
||||||
|
if (newDefaultTabComponent) {
|
||||||
|
frameworkTabComponents[DEFAULT_REACT_TAB] =
|
||||||
|
newDefaultTabComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.value.updateOptions({
|
||||||
|
defaultTabComponent: newDefaultTabComponent
|
||||||
|
? DEFAULT_REACT_TAB
|
||||||
|
: undefined,
|
||||||
|
frameworkTabComponents,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.watermarkComponent,
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.updateOptions({
|
||||||
|
watermarkFrameworkComponent: newValue,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.leftHeaderActionsComponent,
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.updateOptions({
|
||||||
|
headerLeftActionComponent: newValue
|
||||||
|
? (group) => {
|
||||||
|
return new VueHeaderActionsRenderer(
|
||||||
|
newValue as VueComponent,
|
||||||
|
getCurrentInstance()!,
|
||||||
|
group
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.rightHeaderActionsComponent,
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.updateOptions({
|
||||||
|
headerRightActionComponent: newValue
|
||||||
|
? (group) => {
|
||||||
|
return new VueHeaderActionsRenderer(
|
||||||
|
newValue as VueComponent,
|
||||||
|
getCurrentInstance()!,
|
||||||
|
group
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.prefixHeaderActionsComponent,
|
||||||
|
(newValue, oldValue) => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.updateOptions({
|
||||||
|
headerPrefixActionComponent: newValue
|
||||||
|
? (group) => {
|
||||||
|
return new VueHeaderActionsRenderer(
|
||||||
|
newValue as VueComponent,getCurrentInstance()!,
|
||||||
|
group
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (!el.value) {
|
||||||
|
throw new Error('element is not mounted');
|
||||||
|
}
|
||||||
|
|
||||||
|
const frameworkTabComponents = props.tabComponents ?? {};
|
||||||
|
|
||||||
|
if (props.defaultTabComponent) {
|
||||||
|
frameworkTabComponents[DEFAULT_REACT_TAB] = props.defaultTabComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
const frameworkOptions: DockviewFrameworkOptions = {
|
||||||
|
parentElement: el.value,
|
||||||
|
frameworkComponentFactory: {
|
||||||
|
content: {
|
||||||
|
createComponent: (
|
||||||
|
id: string,
|
||||||
|
componentId: string,
|
||||||
|
component: any
|
||||||
|
): IContentRenderer => {
|
||||||
|
return new VueContentRenderer(component,getCurrentInstance()!);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tab: {
|
||||||
|
createComponent: (
|
||||||
|
id: string,
|
||||||
|
componentId: string,
|
||||||
|
component: any
|
||||||
|
): ITabRenderer => {
|
||||||
|
return new VueTabRenderer(component,getCurrentInstance()!);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watermark: {
|
||||||
|
createComponent: (
|
||||||
|
id: string,
|
||||||
|
componentId: string,
|
||||||
|
component: any
|
||||||
|
): IWatermarkRenderer => {
|
||||||
|
return new VueWatermarkRenderer(component,getCurrentInstance()!);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// action: {
|
||||||
|
// createComponent: (id: string, componentId: string, component: any): IWatermarkRenderer => {
|
||||||
|
// return new VueHeaderActionRenderer(component)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
frameworkComponents: props.components,
|
||||||
|
frameworkTabComponents,
|
||||||
|
headerLeftActionComponent: props.leftHeaderActionsComponent
|
||||||
|
? (group) => {
|
||||||
|
return new VueHeaderActionsRenderer(
|
||||||
|
props.leftHeaderActionsComponent as VueComponent,getCurrentInstance()!,
|
||||||
|
group
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
headerPrefixActionComponent: props.prefixHeaderActionsComponent
|
||||||
|
? (group) => {
|
||||||
|
return new VueHeaderActionsRenderer(
|
||||||
|
props.prefixHeaderActionsComponent as VueComponent,getCurrentInstance()!,
|
||||||
|
group
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
headerRightActionComponent: props.rightHeaderActionsComponent
|
||||||
|
? (group) => {
|
||||||
|
return new VueHeaderActionsRenderer(
|
||||||
|
props.rightHeaderActionsComponent as VueComponent,getCurrentInstance()!,
|
||||||
|
group
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
defaultTabComponent: props.defaultTabComponent
|
||||||
|
? DEFAULT_REACT_TAB
|
||||||
|
: undefined,
|
||||||
|
watermarkFrameworkComponent:props.watermarkComponent
|
||||||
|
};
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
...extractCoreOptions(props),
|
||||||
|
...frameworkOptions,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { clientWidth, clientHeight } = el.value;
|
||||||
|
dockview.layout(clientWidth, clientHeight);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* !!! THIS IS VERY IMPORTANT
|
||||||
|
*
|
||||||
|
* Since we store a reference to `DockviewComponent` within the Vue.js world Vue.js will 'deeply Proxyify' the object
|
||||||
|
* since this is how Vue.js does its reactivity magic.
|
||||||
|
*
|
||||||
|
* We do not want Vue.js to touch the `DockviewComponent` reference since it does not need to be reactive in accordance
|
||||||
|
* to the Vue.js reactivity model and since `DockviewComponent` is written in plain TypeScript allowing Vue.js
|
||||||
|
* to proxify the reference will cause all kinds of unexpected issues
|
||||||
|
*
|
||||||
|
* @see https://vuejs.org/guide/extras/reactivity-in-depth.html
|
||||||
|
* @see https://vuejs.org/api/reactivity-advanced.html#markraw
|
||||||
|
*/
|
||||||
|
instance.value = markRaw(dockview);
|
||||||
|
|
||||||
|
|
||||||
|
emit('ready', { api: new DockviewApi(dockview) });
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (instance.value) {
|
||||||
|
instance.value.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div ref="el" />
|
||||||
|
</template>
|
5
packages/dockview-vue/src/index.ts
Normal file
5
packages/dockview-vue/src/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export * from 'dockview-core';
|
||||||
|
|
||||||
|
import DockviewVue from './dockview/dockview.vue';
|
||||||
|
export { DockviewVue };
|
||||||
|
export * from './dockview/dockview.vue';
|
255
packages/dockview-vue/src/utils.ts
Normal file
255
packages/dockview-vue/src/utils.ts
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
import type {
|
||||||
|
DockviewGroupPanel,
|
||||||
|
GroupPanelPartInitParameters,
|
||||||
|
IContentRenderer,
|
||||||
|
IGroupHeaderProps,
|
||||||
|
IHeaderActionsRenderer,
|
||||||
|
ITabRenderer,
|
||||||
|
IWatermarkRenderer,
|
||||||
|
PanelUpdateEvent,
|
||||||
|
Parameters,
|
||||||
|
WatermarkRendererInitParameters,
|
||||||
|
} from 'dockview-core';
|
||||||
|
import {
|
||||||
|
createVNode,
|
||||||
|
type ComponentOptionsBase,
|
||||||
|
render,
|
||||||
|
cloneVNode,
|
||||||
|
mergeProps,
|
||||||
|
type DefineComponent,
|
||||||
|
type ComponentInternalInstance,
|
||||||
|
} from 'vue';
|
||||||
|
|
||||||
|
export type ComponentInterface = ComponentOptionsBase<
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any,
|
||||||
|
any
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type VueComponent<T = any> = DefineComponent<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TODO List
|
||||||
|
*
|
||||||
|
* 1. handle vue context-ish stuff (appContext? provides?)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @see https://vuejs.org/api/render-function.html#clonevnode
|
||||||
|
* @see https://vuejs.org/api/render-function.html#mergeprops
|
||||||
|
*/
|
||||||
|
export function mountVueComponent<T extends Record<string, any>>(
|
||||||
|
component: VueComponent<T>,
|
||||||
|
parent: ComponentInternalInstance,
|
||||||
|
props: T,
|
||||||
|
element: HTMLElement
|
||||||
|
) {
|
||||||
|
let vNode = createVNode(component, Object.freeze(props));
|
||||||
|
|
||||||
|
vNode.appContext = parent.appContext;
|
||||||
|
|
||||||
|
render(vNode, element);
|
||||||
|
|
||||||
|
let runningProps = props;
|
||||||
|
|
||||||
|
return {
|
||||||
|
update: (newProps: any) => {
|
||||||
|
runningProps = { ...props, newProps };
|
||||||
|
vNode = cloneVNode(vNode, Object.freeze(runningProps));
|
||||||
|
render(vNode, element);
|
||||||
|
},
|
||||||
|
dispose: () => {
|
||||||
|
render(null, element);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VueContentRenderer implements IContentRenderer {
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _renderDisposable:
|
||||||
|
| { update: (props: any) => void; dispose: () => void }
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
get element(): HTMLElement {
|
||||||
|
return this._element;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly component: VueComponent,
|
||||||
|
private readonly parent: ComponentInternalInstance
|
||||||
|
) {
|
||||||
|
this._element = document.createElement('div');
|
||||||
|
this.element.className = 'dv-vue-part';
|
||||||
|
this.element.style.height = '100%';
|
||||||
|
this.element.style.width = '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
init(parameters: GroupPanelPartInitParameters): void {
|
||||||
|
const props = {
|
||||||
|
params: parameters.params,
|
||||||
|
api: parameters.api,
|
||||||
|
containerApi: parameters.containerApi,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
this._renderDisposable = mountVueComponent(
|
||||||
|
this.component,
|
||||||
|
this.parent,
|
||||||
|
props,
|
||||||
|
this.element
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(event: PanelUpdateEvent<Parameters>): void {
|
||||||
|
const params = event.params;
|
||||||
|
// TODO: handle prop updates somehow?
|
||||||
|
this._renderDisposable?.update(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
focus(): void {
|
||||||
|
// TODO: make optional on interface
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VueTabRenderer implements ITabRenderer {
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _renderDisposable:
|
||||||
|
| { update: (props: any) => void; dispose: () => void }
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
get element(): HTMLElement {
|
||||||
|
return this._element;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly component: VueComponent,
|
||||||
|
private readonly parent: ComponentInternalInstance
|
||||||
|
) {
|
||||||
|
this._element = document.createElement('div');
|
||||||
|
this.element.className = 'dv-vue-part';
|
||||||
|
this.element.style.height = '100%';
|
||||||
|
this.element.style.width = '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
init(parameters: GroupPanelPartInitParameters): void {
|
||||||
|
const props = {
|
||||||
|
params: parameters.params,
|
||||||
|
api: parameters.api,
|
||||||
|
containerApi: parameters.containerApi,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
this._renderDisposable = mountVueComponent(
|
||||||
|
this.component,
|
||||||
|
this.parent,
|
||||||
|
props,
|
||||||
|
this.element
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(event: PanelUpdateEvent<Parameters>): void {
|
||||||
|
const params = event.params;
|
||||||
|
// TODO: handle prop updates somehow?
|
||||||
|
this._renderDisposable?.update(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VueWatermarkRenderer implements IWatermarkRenderer {
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _renderDisposable:
|
||||||
|
| { update: (props: any) => void; dispose: () => void }
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
get element(): HTMLElement {
|
||||||
|
return this._element;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly component: VueComponent,
|
||||||
|
private readonly parent: ComponentInternalInstance
|
||||||
|
) {
|
||||||
|
this._element = document.createElement('div');
|
||||||
|
this.element.className = 'dv-vue-part';
|
||||||
|
this.element.style.height = '100%';
|
||||||
|
this.element.style.width = '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
init(parameters: WatermarkRendererInitParameters): void {
|
||||||
|
const props = {
|
||||||
|
group: parameters.group,
|
||||||
|
containerApi: parameters.containerApi,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
this._renderDisposable = mountVueComponent(
|
||||||
|
this.component,
|
||||||
|
this.parent,
|
||||||
|
props,
|
||||||
|
this.element
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateParentGroup(group: DockviewGroupPanel, visible: boolean): void {
|
||||||
|
// TODO: make optional on interface
|
||||||
|
}
|
||||||
|
|
||||||
|
update(event: PanelUpdateEvent<Parameters>): void {
|
||||||
|
const params = event.params;
|
||||||
|
// TODO: handle prop updates somehow?
|
||||||
|
this._renderDisposable?.update(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VueHeaderActionsRenderer implements IHeaderActionsRenderer {
|
||||||
|
private _element: HTMLElement;
|
||||||
|
private _renderDisposable:
|
||||||
|
| { update: (props: any) => void; dispose: () => void }
|
||||||
|
| undefined;
|
||||||
|
|
||||||
|
get element(): HTMLElement {
|
||||||
|
return this._element;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly component: VueComponent,
|
||||||
|
private readonly parent: ComponentInternalInstance,
|
||||||
|
group: DockviewGroupPanel
|
||||||
|
) {
|
||||||
|
this._element = document.createElement('div');
|
||||||
|
this.element.className = 'dv-vue-header-action-part';
|
||||||
|
this._element.style.width = '100%';
|
||||||
|
this._element.style.height = '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
init(params: IGroupHeaderProps): void {
|
||||||
|
console.log(params);
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
this._renderDisposable = mountVueComponent(
|
||||||
|
this.component,
|
||||||
|
this.parent,
|
||||||
|
{ ...params },
|
||||||
|
this.element
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this._renderDisposable?.dispose();
|
||||||
|
}
|
||||||
|
}
|
10
packages/dockview-vue/tsconfig.app.json
Normal file
10
packages/dockview-vue/tsconfig.app.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// tsconfig.app.json
|
||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.json",
|
||||||
|
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
||||||
|
"exclude": ["src/**/__tests__/*", "src/**/*.cy.ts"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"baseUrl": "."
|
||||||
|
}
|
||||||
|
}
|
10
packages/dockview-vue/tsconfig.build-types.json
Normal file
10
packages/dockview-vue/tsconfig.build-types.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
// tsconfig.build-types.json
|
||||||
|
{
|
||||||
|
"include": ["src/**/*"],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"**/*.cy.ts",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/__tests__/**/*"
|
||||||
|
]
|
||||||
|
}
|
9
packages/dockview-vue/tsconfig.config.json
Normal file
9
packages/dockview-vue/tsconfig.config.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
// tsconfig.config.json
|
||||||
|
{
|
||||||
|
"extends": "@vue/tsconfig/tsconfig.json",
|
||||||
|
"include": ["vite.config.*", "vitest.config.*", "cypress.config.*"],
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true,
|
||||||
|
"types": ["node"]
|
||||||
|
}
|
||||||
|
}
|
5
packages/dockview-vue/tsconfig.json
Normal file
5
packages/dockview-vue/tsconfig.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// tsconfig.json
|
||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [{ "path": "./tsconfig.config.json" }, { "path": "./tsconfig.app.json" }]
|
||||||
|
}
|
5
packages/dockview-vue/typedoc.json
Normal file
5
packages/dockview-vue/typedoc.json
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"extends": ["../../typedoc.base.json"],
|
||||||
|
"entryPoints": ["src/index.ts"],
|
||||||
|
"exclude": ["**/dist/**"]
|
||||||
|
}
|
30
packages/dockview-vue/vite.config.ts
Normal file
30
packages/dockview-vue/vite.config.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { defineConfig } from 'vite';
|
||||||
|
import { resolve } from 'path';
|
||||||
|
import vue from '@vitejs/plugin-vue';
|
||||||
|
|
||||||
|
// https://vitejs.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [vue()],
|
||||||
|
build: {
|
||||||
|
lib: {
|
||||||
|
// src/indext.ts is where we have exported the component(s)
|
||||||
|
entry: resolve(__dirname, 'src/index.ts'),
|
||||||
|
name: 'dockview-vue',
|
||||||
|
// the name of the output files when the build is run
|
||||||
|
fileName: (format) => `dockview-vue.${format}.js`,
|
||||||
|
},
|
||||||
|
rollupOptions: {
|
||||||
|
// make sure to externalize deps that shouldn't be bundled
|
||||||
|
// into your library
|
||||||
|
external: ['vue', 'dockview-core'],
|
||||||
|
output: {
|
||||||
|
// Provide global variables to use in the UMD build
|
||||||
|
// for externalized deps
|
||||||
|
globals: {
|
||||||
|
vue: 'Vue',
|
||||||
|
['dockview-core']: 'DockviewCore',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview",
|
"name": "dockview",
|
||||||
"version": "1.12.0",
|
"version": "1.12.0",
|
||||||
"description": "Zero dependency layout manager supporting tabs, grids and splitviews with ReactJS support",
|
"description": "Zero dependency layout manager supporting tabs, grids and splitviews",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"splitview",
|
"splitview",
|
||||||
"split-view",
|
"split-view",
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { act, render, waitFor } from '@testing-library/react';
|
import { act, render, waitFor } from '@testing-library/react';
|
||||||
import { DockviewApi, IDockviewPanel } from 'dockview-core';
|
|
||||||
import {
|
import {
|
||||||
IDockviewPanelProps,
|
DockviewApi,
|
||||||
DockviewReact,
|
|
||||||
DockviewReadyEvent,
|
DockviewReadyEvent,
|
||||||
} from '../../dockview/dockview';
|
IDockviewPanel,
|
||||||
import { PanelCollection } from '../../types';
|
IDockviewPanelProps,
|
||||||
|
} from 'dockview-core';
|
||||||
|
import { DockviewReact } from '../../dockview/dockview';
|
||||||
import { setMockRefElement } from '../__test_utils__/utils';
|
import { setMockRefElement } from '../__test_utils__/utils';
|
||||||
|
|
||||||
describe('gridview react', () => {
|
describe('gridview react', () => {
|
||||||
let components: PanelCollection<IDockviewPanelProps>;
|
let components: Record<
|
||||||
|
string,
|
||||||
|
React.FunctionComponent<IDockviewPanelProps>
|
||||||
|
>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
components = {
|
components = {
|
||||||
|
@ -6,11 +6,13 @@ import {
|
|||||||
GridviewReact,
|
GridviewReact,
|
||||||
GridviewReadyEvent,
|
GridviewReadyEvent,
|
||||||
} from '../../gridview/gridview';
|
} from '../../gridview/gridview';
|
||||||
import { PanelCollection } from '../../types';
|
|
||||||
import { setMockRefElement } from '../__test_utils__/utils';
|
import { setMockRefElement } from '../__test_utils__/utils';
|
||||||
|
|
||||||
describe('gridview react', () => {
|
describe('gridview react', () => {
|
||||||
let components: PanelCollection<IGridviewPanelProps>;
|
let components: Record<
|
||||||
|
string,
|
||||||
|
React.FunctionComponent<IGridviewPanelProps>
|
||||||
|
>
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
components = {
|
components = {
|
||||||
|
@ -6,11 +6,13 @@ import {
|
|||||||
PaneviewReact,
|
PaneviewReact,
|
||||||
PaneviewReadyEvent,
|
PaneviewReadyEvent,
|
||||||
} from '../../paneview/paneview';
|
} from '../../paneview/paneview';
|
||||||
import { PanelCollection } from '../../types';
|
|
||||||
import { setMockRefElement } from '../__test_utils__/utils';
|
import { setMockRefElement } from '../__test_utils__/utils';
|
||||||
|
|
||||||
describe('gridview react', () => {
|
describe('gridview react', () => {
|
||||||
let components: PanelCollection<IPaneviewPanelProps>;
|
let components: Record<
|
||||||
|
string,
|
||||||
|
React.FunctionComponent<IPaneviewPanelProps>
|
||||||
|
>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
components = {
|
components = {
|
||||||
|
@ -6,11 +6,13 @@ import {
|
|||||||
SplitviewReact,
|
SplitviewReact,
|
||||||
SplitviewReadyEvent,
|
SplitviewReadyEvent,
|
||||||
} from '../../splitview/splitview';
|
} from '../../splitview/splitview';
|
||||||
import { PanelCollection } from '../../types';
|
|
||||||
import { setMockRefElement } from '../__test_utils__/utils';
|
import { setMockRefElement } from '../__test_utils__/utils';
|
||||||
|
|
||||||
describe('splitview react', () => {
|
describe('splitview react', () => {
|
||||||
let components: PanelCollection<ISplitviewPanelProps>;
|
let components: Record<
|
||||||
|
string,
|
||||||
|
React.FunctionComponent<ISplitviewPanelProps>
|
||||||
|
>;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
components = {
|
components = {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { IDockviewPanelHeaderProps } from './dockview';
|
|
||||||
import { CloseButton } from '../svg';
|
import { CloseButton } from '../svg';
|
||||||
|
import { IDockviewPanelHeaderProps } from 'dockview-core';
|
||||||
|
|
||||||
export type IDockviewDefaultTabProps = IDockviewPanelHeaderProps &
|
export type IDockviewDefaultTabProps = IDockviewPanelHeaderProps &
|
||||||
React.DOMAttributes<HTMLDivElement> & {
|
React.DOMAttributes<HTMLDivElement> & {
|
||||||
|
@ -2,28 +2,31 @@ import React from 'react';
|
|||||||
import {
|
import {
|
||||||
DockviewComponent,
|
DockviewComponent,
|
||||||
DockviewWillDropEvent,
|
DockviewWillDropEvent,
|
||||||
DockviewDndOverlayEvent,
|
|
||||||
GroupPanelFrameworkComponentFactory,
|
GroupPanelFrameworkComponentFactory,
|
||||||
DockviewPanelApi,
|
|
||||||
DockviewApi,
|
DockviewApi,
|
||||||
IContentRenderer,
|
IContentRenderer,
|
||||||
ITabRenderer,
|
ITabRenderer,
|
||||||
DockviewGroupPanel,
|
DockviewGroupPanel,
|
||||||
IHeaderActionsRenderer,
|
IHeaderActionsRenderer,
|
||||||
DockviewPanelRenderer,
|
|
||||||
DroptargetOverlayModel,
|
|
||||||
DockviewDidDropEvent,
|
DockviewDidDropEvent,
|
||||||
|
IWatermarkPanelProps,
|
||||||
|
IDockviewHeaderActionsProps,
|
||||||
|
IDockviewPanelHeaderProps,
|
||||||
|
IDockviewPanelProps,
|
||||||
|
DockviewOptions,
|
||||||
|
PROPERTY_KEYS,
|
||||||
|
DockviewComponentOptions,
|
||||||
|
DockviewFrameworkOptions,
|
||||||
|
IDockviewDisposable,
|
||||||
|
DockviewDndOverlayEvent,
|
||||||
|
DockviewReadyEvent,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { ReactPanelContentPart } from './reactContentPart';
|
import { ReactPanelContentPart } from './reactContentPart';
|
||||||
import { ReactPanelHeaderPart } from './reactHeaderPart';
|
import { ReactPanelHeaderPart } from './reactHeaderPart';
|
||||||
|
|
||||||
import { ReactPortalStore, usePortalsLifecycle } from '../react';
|
import { ReactPortalStore, usePortalsLifecycle } from '../react';
|
||||||
import { IWatermarkPanelProps, ReactWatermarkPart } from './reactWatermarkPart';
|
import { ReactWatermarkPart } from './reactWatermarkPart';
|
||||||
import { PanelCollection, PanelParameters } from '../types';
|
import { ReactHeaderActionsRendererPart } from './headerActionsRenderer';
|
||||||
import {
|
|
||||||
IDockviewHeaderActionsProps,
|
|
||||||
ReactHeaderActionsRendererPart,
|
|
||||||
} from './headerActionsRenderer';
|
|
||||||
|
|
||||||
function createGroupControlElement(
|
function createGroupControlElement(
|
||||||
component: React.FunctionComponent<IDockviewHeaderActionsProps> | undefined,
|
component: React.FunctionComponent<IDockviewHeaderActionsProps> | undefined,
|
||||||
@ -40,54 +43,81 @@ function createGroupControlElement(
|
|||||||
: undefined;
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IGroupPanelBaseProps<T extends { [index: string]: any } = any>
|
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
||||||
extends PanelParameters<T> {
|
|
||||||
api: DockviewPanelApi;
|
|
||||||
containerApi: DockviewApi;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type IDockviewPanelHeaderProps<
|
export interface IDockviewReactProps extends DockviewOptions {
|
||||||
T extends { [index: string]: any } = any
|
|
||||||
> = IGroupPanelBaseProps<T>;
|
|
||||||
|
|
||||||
export type IDockviewPanelProps<T extends { [index: string]: any } = any> =
|
|
||||||
IGroupPanelBaseProps<T>;
|
|
||||||
|
|
||||||
export interface DockviewReadyEvent {
|
|
||||||
api: DockviewApi;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDockviewReactProps {
|
|
||||||
onReady: (event: DockviewReadyEvent) => void;
|
|
||||||
components: PanelCollection<IDockviewPanelProps>;
|
|
||||||
tabComponents?: PanelCollection<IDockviewPanelHeaderProps>;
|
|
||||||
watermarkComponent?: React.FunctionComponent<IWatermarkPanelProps>;
|
|
||||||
onDidDrop?: (event: DockviewDidDropEvent) => void;
|
|
||||||
onWillDrop?: (event: DockviewWillDropEvent) => void;
|
|
||||||
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
|
||||||
hideBorders?: boolean;
|
|
||||||
className?: string;
|
className?: string;
|
||||||
disableAutoResizing?: boolean;
|
tabComponents?: Record<
|
||||||
|
string,
|
||||||
|
React.FunctionComponent<IDockviewPanelHeaderProps>
|
||||||
|
>;
|
||||||
|
components: Record<string, React.FunctionComponent<IDockviewPanelProps>>;
|
||||||
|
watermarkComponent?: React.FunctionComponent<IWatermarkPanelProps>;
|
||||||
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
||||||
rightHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
rightHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
||||||
leftHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
leftHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
||||||
prefixHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
prefixHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
||||||
singleTabMode?: 'fullwidth' | 'default';
|
//
|
||||||
disableFloatingGroups?: boolean;
|
onReady: (event: DockviewReadyEvent) => void;
|
||||||
floatingGroupBounds?:
|
onDidDrop?: (event: DockviewDidDropEvent) => void;
|
||||||
| 'boundedWithinViewport'
|
onWillDrop?: (event: DockviewWillDropEvent) => void;
|
||||||
| {
|
/**
|
||||||
minimumHeightWithinViewport?: number;
|
* @deprecated use `api.onUnhandledDragOverEvent` instead. This will be removed in the next release.
|
||||||
minimumWidthWithinViewport?: number;
|
*/
|
||||||
};
|
showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
||||||
debug?: boolean;
|
|
||||||
defaultRenderer?: DockviewPanelRenderer;
|
|
||||||
rootOverlayModel?: DroptargetOverlayModel;
|
|
||||||
locked?: boolean;
|
|
||||||
disableDnd?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_REACT_TAB = 'props.defaultTabComponent';
|
function extractCoreOptions(props: IDockviewReactProps): DockviewOptions {
|
||||||
|
const coreOptions = (PROPERTY_KEYS as (keyof DockviewOptions)[]).reduce(
|
||||||
|
(obj, key) => {
|
||||||
|
obj[key] = props[key] as any;
|
||||||
|
return obj;
|
||||||
|
},
|
||||||
|
{} as Partial<DockviewComponentOptions>
|
||||||
|
);
|
||||||
|
|
||||||
|
return coreOptions as DockviewOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFrameworkFactory(
|
||||||
|
addPortal: (portal: React.ReactPortal) => IDockviewDisposable
|
||||||
|
): GroupPanelFrameworkComponentFactory {
|
||||||
|
return {
|
||||||
|
content: {
|
||||||
|
createComponent: (
|
||||||
|
_id: string,
|
||||||
|
componentId: string,
|
||||||
|
component: React.FunctionComponent<IDockviewPanelProps>
|
||||||
|
): IContentRenderer => {
|
||||||
|
return new ReactPanelContentPart(componentId, component, {
|
||||||
|
addPortal,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tab: {
|
||||||
|
createComponent: (
|
||||||
|
_id: string,
|
||||||
|
componentId: string,
|
||||||
|
component: React.FunctionComponent<IDockviewPanelHeaderProps>
|
||||||
|
): ITabRenderer => {
|
||||||
|
return new ReactPanelHeaderPart(componentId, component, {
|
||||||
|
addPortal,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watermark: {
|
||||||
|
createComponent: (
|
||||||
|
_id: string,
|
||||||
|
componentId: string,
|
||||||
|
component: React.FunctionComponent<{}>
|
||||||
|
) => {
|
||||||
|
return new ReactWatermarkPart(componentId, component, {
|
||||||
|
addPortal,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export const DockviewReact = React.forwardRef(
|
export const DockviewReact = React.forwardRef(
|
||||||
(props: IDockviewReactProps, ref: React.ForwardedRef<HTMLDivElement>) => {
|
(props: IDockviewReactProps, ref: React.ForwardedRef<HTMLDivElement>) => {
|
||||||
@ -97,57 +127,37 @@ export const DockviewReact = React.forwardRef(
|
|||||||
|
|
||||||
React.useImperativeHandle(ref, () => domRef.current!, []);
|
React.useImperativeHandle(ref, () => domRef.current!, []);
|
||||||
|
|
||||||
|
const prevProps = React.useRef<Partial<IDockviewReactProps>>({});
|
||||||
|
|
||||||
|
React.useEffect(
|
||||||
|
() => {
|
||||||
|
const changes: Partial<DockviewOptions> = {};
|
||||||
|
|
||||||
|
PROPERTY_KEYS.forEach((propKey) => {
|
||||||
|
const key = propKey as keyof DockviewOptions;
|
||||||
|
const propValue = props[key];
|
||||||
|
|
||||||
|
if (propValue !== prevProps.current[key]) {
|
||||||
|
changes[key] = propValue as any;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (dockviewRef.current) {
|
||||||
|
dockviewRef.current.updateOptions(changes);
|
||||||
|
} else {
|
||||||
|
// not yet fully initialized
|
||||||
|
}
|
||||||
|
|
||||||
|
prevProps.current = props;
|
||||||
|
},
|
||||||
|
PROPERTY_KEYS.map((key) => props[key])
|
||||||
|
);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!domRef.current) {
|
if (!domRef.current) {
|
||||||
return () => {
|
return;
|
||||||
// noop
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const factory: GroupPanelFrameworkComponentFactory = {
|
|
||||||
content: {
|
|
||||||
createComponent: (
|
|
||||||
_id: string,
|
|
||||||
componentId: string,
|
|
||||||
component: React.FunctionComponent<IDockviewPanelProps>
|
|
||||||
): IContentRenderer => {
|
|
||||||
return new ReactPanelContentPart(
|
|
||||||
componentId,
|
|
||||||
component,
|
|
||||||
{
|
|
||||||
addPortal,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tab: {
|
|
||||||
createComponent: (
|
|
||||||
_id: string,
|
|
||||||
componentId: string,
|
|
||||||
component: React.FunctionComponent<IDockviewPanelHeaderProps>
|
|
||||||
): ITabRenderer => {
|
|
||||||
return new ReactPanelHeaderPart(
|
|
||||||
componentId,
|
|
||||||
component,
|
|
||||||
{
|
|
||||||
addPortal,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
watermark: {
|
|
||||||
createComponent: (
|
|
||||||
_id: string,
|
|
||||||
componentId: string,
|
|
||||||
component: React.FunctionComponent<{}>
|
|
||||||
) => {
|
|
||||||
return new ReactWatermarkPart(componentId, component, {
|
|
||||||
addPortal,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const frameworkTabComponents = props.tabComponents ?? {};
|
const frameworkTabComponents = props.tabComponents ?? {};
|
||||||
|
|
||||||
if (props.defaultTabComponent) {
|
if (props.defaultTabComponent) {
|
||||||
@ -155,40 +165,32 @@ export const DockviewReact = React.forwardRef(
|
|||||||
props.defaultTabComponent;
|
props.defaultTabComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
const frameworkOptions: DockviewFrameworkOptions = {
|
||||||
parentElement: domRef.current,
|
headerLeftActionComponent: createGroupControlElement(
|
||||||
frameworkComponentFactory: factory,
|
|
||||||
frameworkComponents: props.components,
|
|
||||||
disableAutoResizing: props.disableAutoResizing,
|
|
||||||
frameworkTabComponents,
|
|
||||||
watermarkFrameworkComponent: props.watermarkComponent,
|
|
||||||
defaultTabComponent: props.defaultTabComponent
|
|
||||||
? DEFAULT_REACT_TAB
|
|
||||||
: undefined,
|
|
||||||
styles: props.hideBorders
|
|
||||||
? { separatorBorder: 'transparent' }
|
|
||||||
: undefined,
|
|
||||||
showDndOverlay: props.showDndOverlay,
|
|
||||||
createLeftHeaderActionsElement: createGroupControlElement(
|
|
||||||
props.leftHeaderActionsComponent,
|
props.leftHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
createRightHeaderActionsElement: createGroupControlElement(
|
headerRightActionComponent: createGroupControlElement(
|
||||||
props.rightHeaderActionsComponent,
|
props.rightHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
createPrefixHeaderActionsElement: createGroupControlElement(
|
headerPrefixActionComponent: createGroupControlElement(
|
||||||
props.prefixHeaderActionsComponent,
|
props.prefixHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
singleTabMode: props.singleTabMode,
|
frameworkTabComponents,
|
||||||
disableFloatingGroups: props.disableFloatingGroups,
|
frameworkComponents: props.components,
|
||||||
floatingGroupBounds: props.floatingGroupBounds,
|
frameworkComponentFactory: createFrameworkFactory(addPortal),
|
||||||
defaultRenderer: props.defaultRenderer,
|
parentElement: domRef.current,
|
||||||
debug: props.debug,
|
defaultTabComponent: props.defaultTabComponent
|
||||||
rootOverlayModel: props.rootOverlayModel,
|
? DEFAULT_REACT_TAB
|
||||||
locked: props.locked,
|
: undefined,
|
||||||
disableDnd: props.disableDnd,
|
watermarkFrameworkComponent: props.watermarkComponent,
|
||||||
|
};
|
||||||
|
|
||||||
|
const dockview = new DockviewComponent({
|
||||||
|
...extractCoreOptions(props),
|
||||||
|
...frameworkOptions,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { clientWidth, clientHeight } = domRef.current;
|
const { clientWidth, clientHeight } = domRef.current;
|
||||||
@ -205,24 +207,6 @@ export const DockviewReact = React.forwardRef(
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dockviewRef.current.locked = !!props.locked;
|
|
||||||
}, [props.locked]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
dockviewRef.current.updateOptions({
|
|
||||||
disableDnd: props.disableDnd,
|
|
||||||
});
|
|
||||||
}, [props.disableDnd]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return () => {
|
return () => {
|
||||||
@ -241,6 +225,26 @@ export const DockviewReact = React.forwardRef(
|
|||||||
};
|
};
|
||||||
}, [props.onDidDrop]);
|
}, [props.onDidDrop]);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!dockviewRef.current) {
|
||||||
|
return () => {
|
||||||
|
// noop
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const disposable = dockviewRef.current.onUnhandledDragOverEvent(
|
||||||
|
(event) => {
|
||||||
|
if (props.showDndOverlay?.(event)) {
|
||||||
|
event.accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
disposable.dispose();
|
||||||
|
};
|
||||||
|
}, [props.showDndOverlay]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return () => {
|
return () => {
|
||||||
@ -268,15 +272,6 @@ export const DockviewReact = React.forwardRef(
|
|||||||
});
|
});
|
||||||
}, [props.components]);
|
}, [props.components]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dockviewRef.current.updateOptions({
|
|
||||||
floatingGroupBounds: props.floatingGroupBounds,
|
|
||||||
});
|
|
||||||
}, [props.floatingGroupBounds]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return;
|
return;
|
||||||
@ -286,33 +281,6 @@ export const DockviewReact = React.forwardRef(
|
|||||||
});
|
});
|
||||||
}, [props.watermarkComponent]);
|
}, [props.watermarkComponent]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dockviewRef.current.updateOptions({
|
|
||||||
showDndOverlay: props.showDndOverlay,
|
|
||||||
});
|
|
||||||
}, [props.showDndOverlay]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dockviewRef.current.updateOptions({
|
|
||||||
frameworkTabComponents: props.tabComponents,
|
|
||||||
});
|
|
||||||
}, [props.tabComponents]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dockviewRef.current.updateOptions({
|
|
||||||
disableFloatingGroups: props.disableFloatingGroups,
|
|
||||||
});
|
|
||||||
}, [props.disableFloatingGroups]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return;
|
return;
|
||||||
@ -331,14 +299,14 @@ export const DockviewReact = React.forwardRef(
|
|||||||
: undefined,
|
: undefined,
|
||||||
frameworkTabComponents,
|
frameworkTabComponents,
|
||||||
});
|
});
|
||||||
}, [props.defaultTabComponent]);
|
}, [props.tabComponents, props.defaultTabComponent]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (!dockviewRef.current) {
|
if (!dockviewRef.current) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dockviewRef.current.updateOptions({
|
dockviewRef.current.updateOptions({
|
||||||
createRightHeaderActionsElement: createGroupControlElement(
|
headerRightActionComponent: createGroupControlElement(
|
||||||
props.rightHeaderActionsComponent,
|
props.rightHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
@ -350,7 +318,7 @@ export const DockviewReact = React.forwardRef(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dockviewRef.current.updateOptions({
|
dockviewRef.current.updateOptions({
|
||||||
createLeftHeaderActionsElement: createGroupControlElement(
|
headerLeftActionComponent: createGroupControlElement(
|
||||||
props.leftHeaderActionsComponent,
|
props.leftHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
@ -362,16 +330,7 @@ export const DockviewReact = React.forwardRef(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dockviewRef.current.updateOptions({
|
dockviewRef.current.updateOptions({
|
||||||
rootOverlayModel: props.rootOverlayModel,
|
headerRightActionComponent: createGroupControlElement(
|
||||||
});
|
|
||||||
}, [props.rootOverlayModel]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (!dockviewRef.current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dockviewRef.current.updateOptions({
|
|
||||||
createPrefixHeaderActionsElement: createGroupControlElement(
|
|
||||||
props.prefixHeaderActionsComponent,
|
props.prefixHeaderActionsComponent,
|
||||||
{ addPortal }
|
{ addPortal }
|
||||||
),
|
),
|
||||||
|
@ -1,25 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactPart, ReactPortalStore } from '../react';
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
import {
|
import {
|
||||||
IDockviewPanel,
|
|
||||||
DockviewCompositeDisposable,
|
DockviewCompositeDisposable,
|
||||||
DockviewMutableDisposable,
|
DockviewMutableDisposable,
|
||||||
DockviewApi,
|
DockviewApi,
|
||||||
DockviewGroupPanel,
|
DockviewGroupPanel,
|
||||||
DockviewGroupPanelApi,
|
DockviewGroupPanelApi,
|
||||||
PanelUpdateEvent,
|
PanelUpdateEvent,
|
||||||
|
IHeaderActionsRenderer,
|
||||||
|
IDockviewHeaderActionsProps,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
|
|
||||||
export interface IDockviewHeaderActionsProps {
|
export class ReactHeaderActionsRendererPart implements IHeaderActionsRenderer {
|
||||||
api: DockviewGroupPanelApi;
|
|
||||||
containerApi: DockviewApi;
|
|
||||||
panels: IDockviewPanel[];
|
|
||||||
activePanel: IDockviewPanel | undefined;
|
|
||||||
isGroupActive: boolean;
|
|
||||||
group: DockviewGroupPanel;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ReactHeaderActionsRendererPart {
|
|
||||||
private mutableDisposable = new DockviewMutableDisposable();
|
private mutableDisposable = new DockviewMutableDisposable();
|
||||||
private _element: HTMLElement;
|
private _element: HTMLElement;
|
||||||
private _part?: ReactPart<IDockviewHeaderActionsProps>;
|
private _part?: ReactPart<IDockviewHeaderActionsProps>;
|
||||||
@ -32,10 +24,6 @@ export class ReactHeaderActionsRendererPart {
|
|||||||
return this._part;
|
return this._part;
|
||||||
}
|
}
|
||||||
|
|
||||||
get group(): DockviewGroupPanel {
|
|
||||||
return this._group;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly component: React.FunctionComponent<IDockviewHeaderActionsProps>,
|
private readonly component: React.FunctionComponent<IDockviewHeaderActionsProps>,
|
||||||
private readonly reactPortalStore: ReactPortalStore,
|
private readonly reactPortalStore: ReactPortalStore,
|
||||||
@ -47,11 +35,7 @@ export class ReactHeaderActionsRendererPart {
|
|||||||
this._element.style.width = '100%';
|
this._element.style.width = '100%';
|
||||||
}
|
}
|
||||||
|
|
||||||
focus(): void {
|
init(parameters: {
|
||||||
// TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(parameters: {
|
|
||||||
containerApi: DockviewApi;
|
containerApi: DockviewApi;
|
||||||
api: DockviewGroupPanelApi;
|
api: DockviewGroupPanelApi;
|
||||||
}): void {
|
}): void {
|
||||||
@ -85,15 +69,15 @@ export class ReactHeaderActionsRendererPart {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public update(event: PanelUpdateEvent): void {
|
dispose(): void {
|
||||||
this._part?.update(event.params);
|
|
||||||
}
|
|
||||||
|
|
||||||
public dispose(): void {
|
|
||||||
this.mutableDisposable.dispose();
|
this.mutableDisposable.dispose();
|
||||||
this._part?.dispose();
|
this._part?.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(event: PanelUpdateEvent): void {
|
||||||
|
this._part?.update(event.params);
|
||||||
|
}
|
||||||
|
|
||||||
private updatePanels(): void {
|
private updatePanels(): void {
|
||||||
this.update({ params: { panels: this._group.model.panels } });
|
this.update({ params: { panels: this._group.model.panels } });
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactPart, ReactPortalStore } from '../react';
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
import { IDockviewPanelProps } from '../dockview/dockview';
|
|
||||||
import {
|
import {
|
||||||
DockviewEmitter,
|
DockviewEmitter,
|
||||||
DockviewEvent,
|
DockviewEvent,
|
||||||
PanelUpdateEvent,
|
PanelUpdateEvent,
|
||||||
IContentRenderer,
|
IContentRenderer,
|
||||||
GroupPanelContentPartInitParameters,
|
GroupPanelPartInitParameters,
|
||||||
|
IDockviewPanelProps,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
|
|
||||||
export class ReactPanelContentPart implements IContentRenderer {
|
export class ReactPanelContentPart implements IContentRenderer {
|
||||||
@ -38,7 +38,7 @@ export class ReactPanelContentPart implements IContentRenderer {
|
|||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
public init(parameters: GroupPanelContentPartInitParameters): void {
|
public init(parameters: GroupPanelPartInitParameters): void {
|
||||||
this.part = new ReactPart(
|
this.part = new ReactPart(
|
||||||
this.element,
|
this.element,
|
||||||
this.reactPortalStore,
|
this.reactPortalStore,
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { ReactPart, ReactPortalStore } from '../react';
|
import { ReactPart, ReactPortalStore } from '../react';
|
||||||
import { IGroupPanelBaseProps } from './dockview';
|
|
||||||
import {
|
import {
|
||||||
PanelUpdateEvent,
|
PanelUpdateEvent,
|
||||||
ITabRenderer,
|
ITabRenderer,
|
||||||
GroupPanelPartInitParameters,
|
GroupPanelPartInitParameters,
|
||||||
|
IGroupPanelBaseProps,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
|
|
||||||
export class ReactPanelHeaderPart implements ITabRenderer {
|
export class ReactPanelHeaderPart implements ITabRenderer {
|
||||||
|
@ -6,16 +6,9 @@ import {
|
|||||||
GroupPanelPartInitParameters,
|
GroupPanelPartInitParameters,
|
||||||
IWatermarkRenderer,
|
IWatermarkRenderer,
|
||||||
WatermarkRendererInitParameters,
|
WatermarkRendererInitParameters,
|
||||||
DockviewApi,
|
IWatermarkPanelProps,
|
||||||
IDockviewGroupPanel,
|
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
|
|
||||||
export interface IWatermarkPanelProps {
|
|
||||||
containerApi: DockviewApi;
|
|
||||||
group?: IDockviewGroupPanel;
|
|
||||||
close: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ReactWatermarkPart implements IWatermarkRenderer {
|
export class ReactWatermarkPart implements IWatermarkRenderer {
|
||||||
private _element: HTMLElement;
|
private _element: HTMLElement;
|
||||||
private part?: ReactPart<IWatermarkPanelProps>;
|
private part?: ReactPart<IWatermarkPanelProps>;
|
||||||
@ -44,11 +37,6 @@ export class ReactWatermarkPart implements IWatermarkRenderer {
|
|||||||
{
|
{
|
||||||
group: parameters.group,
|
group: parameters.group,
|
||||||
containerApi: parameters.containerApi,
|
containerApi: parameters.containerApi,
|
||||||
close: () => {
|
|
||||||
if (parameters.group) {
|
|
||||||
parameters.containerApi.removeGroup(parameters.group);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,7 @@ import {
|
|||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { ReactGridPanelView } from './view';
|
import { ReactGridPanelView } from './view';
|
||||||
import { usePortalsLifecycle } from '../react';
|
import { usePortalsLifecycle } from '../react';
|
||||||
import { PanelCollection, PanelParameters } from '../types';
|
import { PanelParameters } from '../types';
|
||||||
|
|
||||||
export interface GridviewReadyEvent {
|
export interface GridviewReadyEvent {
|
||||||
api: GridviewApi;
|
api: GridviewApi;
|
||||||
}
|
}
|
||||||
@ -23,7 +22,7 @@ export interface IGridviewPanelProps<T extends { [index: string]: any } = any>
|
|||||||
export interface IGridviewReactProps {
|
export interface IGridviewReactProps {
|
||||||
orientation?: Orientation;
|
orientation?: Orientation;
|
||||||
onReady: (event: GridviewReadyEvent) => void;
|
onReady: (event: GridviewReadyEvent) => void;
|
||||||
components: PanelCollection<IGridviewPanelProps>;
|
components: Record<string, React.FunctionComponent<IGridviewPanelProps>>;
|
||||||
hideBorders?: boolean;
|
hideBorders?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
proportionalLayout?: boolean;
|
proportionalLayout?: boolean;
|
||||||
|
@ -4,8 +4,6 @@ export * from './dockview/dockview';
|
|||||||
export * from './dockview/defaultTab';
|
export * from './dockview/defaultTab';
|
||||||
export * from './splitview/splitview';
|
export * from './splitview/splitview';
|
||||||
export * from './gridview/gridview';
|
export * from './gridview/gridview';
|
||||||
export { IDockviewHeaderActionsProps } from './dockview/headerActionsRenderer';
|
|
||||||
export { IWatermarkPanelProps } from './dockview/reactWatermarkPart';
|
|
||||||
export * from './paneview/paneview';
|
export * from './paneview/paneview';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
export * from './react';
|
export * from './react';
|
||||||
|
@ -9,7 +9,7 @@ import {
|
|||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { usePortalsLifecycle } from '../react';
|
import { usePortalsLifecycle } from '../react';
|
||||||
import { PanePanelSection } from './view';
|
import { PanePanelSection } from './view';
|
||||||
import { PanelCollection, PanelParameters } from '../types';
|
import { PanelParameters } from '../types';
|
||||||
|
|
||||||
export interface PaneviewReadyEvent {
|
export interface PaneviewReadyEvent {
|
||||||
api: PaneviewApi;
|
api: PaneviewApi;
|
||||||
@ -24,8 +24,11 @@ export interface IPaneviewPanelProps<T extends { [index: string]: any } = any>
|
|||||||
|
|
||||||
export interface IPaneviewReactProps {
|
export interface IPaneviewReactProps {
|
||||||
onReady: (event: PaneviewReadyEvent) => void;
|
onReady: (event: PaneviewReadyEvent) => void;
|
||||||
components: PanelCollection<IPaneviewPanelProps>;
|
components: Record<string, React.FunctionComponent<IPaneviewPanelProps>>;
|
||||||
headerComponents?: PanelCollection<IPaneviewPanelProps>;
|
headerComponents?: Record<
|
||||||
|
string,
|
||||||
|
React.FunctionComponent<IPaneviewPanelProps>
|
||||||
|
>;
|
||||||
className?: string;
|
className?: string;
|
||||||
disableAutoResizing?: boolean;
|
disableAutoResizing?: boolean;
|
||||||
disableDnd?: boolean;
|
disableDnd?: boolean;
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
Orientation,
|
Orientation,
|
||||||
} from 'dockview-core';
|
} from 'dockview-core';
|
||||||
import { usePortalsLifecycle } from '../react';
|
import { usePortalsLifecycle } from '../react';
|
||||||
import { PanelCollection, PanelParameters } from '../types';
|
import { PanelParameters } from '../types';
|
||||||
import { ReactPanelView } from './view';
|
import { ReactPanelView } from './view';
|
||||||
|
|
||||||
export interface SplitviewReadyEvent {
|
export interface SplitviewReadyEvent {
|
||||||
@ -23,7 +23,7 @@ export interface ISplitviewPanelProps<T extends { [index: string]: any } = any>
|
|||||||
export interface ISplitviewReactProps {
|
export interface ISplitviewReactProps {
|
||||||
orientation?: Orientation;
|
orientation?: Orientation;
|
||||||
onReady: (event: SplitviewReadyEvent) => void;
|
onReady: (event: SplitviewReadyEvent) => void;
|
||||||
components: PanelCollection<ISplitviewPanelProps>;
|
components: Record<string, React.FunctionComponent<ISplitviewPanelProps>>;
|
||||||
proportionalLayout?: boolean;
|
proportionalLayout?: boolean;
|
||||||
hideBorders?: boolean;
|
hideBorders?: boolean;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
import * as React from 'react';
|
|
||||||
import { Parameters } from 'dockview-core';
|
import { Parameters } from 'dockview-core';
|
||||||
|
|
||||||
export interface PanelCollection<T extends object> {
|
|
||||||
[name: string]: React.FunctionComponent<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface PanelParameters<T extends {} = Parameters> {
|
export interface PanelParameters<T extends {} = Parameters> {
|
||||||
params: T;
|
params: T;
|
||||||
}
|
}
|
||||||
|
2
packages/docs/.gitignore
vendored
2
packages/docs/.gitignore
vendored
@ -18,3 +18,5 @@
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
|
|
||||||
|
/static/templates
|
||||||
|
41
packages/docs/blog/2024-04-19-dockview-1.13.0.md
Normal file
41
packages/docs/blog/2024-04-19-dockview-1.13.0.md
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
slug: dockview-1.13.0-release
|
||||||
|
title: Dockview 1.13.0
|
||||||
|
tags: [release]
|
||||||
|
---
|
||||||
|
|
||||||
|
# Release Notes
|
||||||
|
|
||||||
|
Please reference docs @ [dockview.dev](https://dockview.dev).
|
||||||
|
|
||||||
|
## 🚀 Features
|
||||||
|
|
||||||
|
- Add `onDidActivePanelChange` event to group api [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
|
||||||
|
## 🛠 Miscs
|
||||||
|
|
||||||
|
- Create framework packages in preperation for multiple framework support [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
These are still in active development and will be offically support soon.
|
||||||
|
|
||||||
|
- Create `dockview-react` package
|
||||||
|
- Create `dockview-angular` package
|
||||||
|
- Create `dockview-vue` package
|
||||||
|
|
||||||
|
- Move various type definitions from `dockview` to `dockview-core` in preperation for multiple framework support [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
|
||||||
|
- Move `IGroupPanelBaseProps` from `dockview` to `dockview-core`
|
||||||
|
- Move `IDockviewPanelHeaderProps` from `dockview` to `dockview-core`
|
||||||
|
- Move `IDockviewPanelProps` from `dockview` to `dockview-core`
|
||||||
|
- Move `IDockviewHeaderActionsProps ` from `dockview` to `dockview-core`
|
||||||
|
- Move `IGroupHeaderProps` from `dockview` to `dockview-core`
|
||||||
|
- Move `IWatermarkPanelProps` from `dockview` to `dockview-core`
|
||||||
|
- Move `DockviewReadyEvent` from `dockview` to `dockview-core`
|
||||||
|
|
||||||
|
- [dockview] Depreciate `canDisplayOverlay` in favour of the `onUnhandledDragOverEvent` api event [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
|
||||||
|
## 🔥 Breaking changes
|
||||||
|
|
||||||
|
- [dockview-core] Replace DockviewComponent `canDisplayOverlay` option with `onUnhandledDragOverEvent` event [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
- [dockview-core] Rename `createRightHeaderActionsElement` to `headerRightActionComponent` [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
- [dockview-core] Rename `createLeftHeaderActionsElement` to `headerLeftActionComponent` [#541](https://github.com/mathuo/dockview/pull/541)
|
||||||
|
- [dockview-core] Rename `createPrefixHeaderActionsElement` to `headerPrefixActionComponent` [#541](https://github.com/mathuo/dockview/pull/541)
|
@ -3,12 +3,11 @@ title: Nested Instances
|
|||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import NestedDockview from '@site/sandboxes/nested-dockview/src/app';
|
|
||||||
|
|
||||||
# Nested Dockviews
|
# Nested Dockviews
|
||||||
|
|
||||||
You can safely create multiple dockview instances within one page and nest dockviews within other dockviews.
|
You can safely create multiple dockview instances within one page and nest dockviews within other dockviews.
|
||||||
If you wish to interact with the drop event from one dockview instance in another dockview instance you can implement the `showDndOverlay` and `onDidDrop` props on `DockviewReact`.
|
If you wish to interact with the drop event from one dockview instance in another dockview instance you can implement the `showDndOverlay` and `onDidDrop` props on `DockviewReact`.
|
||||||
|
|
||||||
<MultiFrameworkContainer sandboxId="nested-dockview" react={NestedDockview} />
|
<CodeRunner id="dockview/nested" />
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
title: Constraints
|
title: Constraints
|
||||||
---
|
---
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef'
|
import { DocRef } from '@site/src/components/ui/reference/docRef'
|
||||||
|
|
||||||
:::warning
|
:::warning
|
||||||
@ -13,5 +12,5 @@ Constraints come with several caveats. They are not serialized with layouts and
|
|||||||
|
|
||||||
## Live Example
|
## Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/constraints"/>
|
<CodeRunner id="dockview/constraints"/>
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
title: Group Controls
|
title: Group Controls
|
||||||
---
|
---
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
This section describes how you can customize the header component of each group.
|
This section describes how you can customize the header component of each group.
|
||||||
@ -39,5 +38,5 @@ return <DockviewReact
|
|||||||
|
|
||||||
## Live Example
|
## Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/group-actions"/>
|
<CodeRunner id="dockview/group-actions"/>
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ title: Floating Groups
|
|||||||
---
|
---
|
||||||
|
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
This section describes floating groups.
|
This section describes floating groups.
|
||||||
@ -76,4 +75,4 @@ You can check whether a group is floating via the `group.api.location` property.
|
|||||||
|
|
||||||
## Live Example
|
## Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/floating-groups"/>
|
<CodeRunner id="dockview/floating-groups"/>
|
||||||
|
@ -3,7 +3,6 @@ title: Hidden Header
|
|||||||
---
|
---
|
||||||
|
|
||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
You may wish to hide the header section of a group. This can achieved through the `hidden` variable on `panel.group.header`.
|
You may wish to hide the header section of a group. This can achieved through the `hidden` variable on `panel.group.header`.
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
title: Locked Groups
|
title: Locked Groups
|
||||||
---
|
---
|
||||||
|
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import DockviewLockedGroup from '@site/sandboxes/lockedgroup-dockview/src/app';
|
|
||||||
|
|
||||||
## Locked group
|
## Locked group
|
||||||
|
|
||||||
@ -21,7 +20,4 @@ panel.group.locked = 'no-drop-target';
|
|||||||
Use `true` to keep drop zones top, right, bottom, left for the group. Use `no-drop-target` to disable all drop zones. For you to get a
|
Use `true` to keep drop zones top, right, bottom, left for the group. Use `no-drop-target` to disable all drop zones. For you to get a
|
||||||
better understanding of what this means, try and drag the panels in the example below to the locked groups.
|
better understanding of what this means, try and drag the panels in the example below to the locked groups.
|
||||||
|
|
||||||
<MultiFrameworkContainer
|
<CodeRunner id="dockview/locked"/>
|
||||||
sandboxId="lockedgroup-dockview"
|
|
||||||
react={DockviewLockedGroup}
|
|
||||||
/>
|
|
||||||
|
@ -3,7 +3,6 @@ title: Maximized Groups
|
|||||||
---
|
---
|
||||||
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
|
|
||||||
This section described how to maxmimize groups.
|
This section described how to maxmimize groups.
|
||||||
|
|
||||||
@ -51,7 +50,7 @@ The methods exist on the panel `api` object for convenience.
|
|||||||
|
|
||||||
## Live Examples
|
## Live Examples
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/maximize-group"/>
|
<CodeRunner id="dockview/maximize-group"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
title: Popout Windows
|
title: Popout Windows
|
||||||
---
|
---
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
This section describes have to create popout windows.
|
This section describes have to create popout windows.
|
||||||
@ -57,4 +56,4 @@ in it's original location within the grid. If the dock cannot determine the orig
|
|||||||
choose a new location.
|
choose a new location.
|
||||||
|
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/popout-group"/>
|
<CodeRunner id="dockview/popout-group"/>
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
title: Resizing
|
title: Resizing
|
||||||
---
|
---
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
<DocRef declaration="DockviewGroupPanelApi" methods={['height', 'width', 'setSize', 'onDidDimensionsChange']} />
|
<DocRef declaration="DockviewGroupPanelApi" methods={['height', 'width', 'setSize', 'onDidDimensionsChange']} />
|
||||||
@ -34,4 +33,4 @@ props.api.group.api.setSize({
|
|||||||
You can see an example invoking both approaches below.
|
You can see an example invoking both approaches below.
|
||||||
|
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/resize"/>
|
<CodeRunner framework="react" id="dockview/resize"/>
|
||||||
|
@ -5,7 +5,6 @@ title: Locked
|
|||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
|
|
||||||
This section describes how to lock the dock to prevent movement.
|
This section describes how to lock the dock to prevent movement.
|
||||||
|
|
||||||
@ -13,4 +12,4 @@ This section describes how to lock the dock to prevent movement.
|
|||||||
You may want to combine this with `disableDnd={true}` to provide a locked grid with no dnd funtionality. See [Disable Dnd](/docs/core/dnd/disable) for more.
|
You may want to combine this with `disableDnd={true}` to provide a locked grid with no dnd funtionality. See [Disable Dnd](/docs/core/dnd/disable) for more.
|
||||||
:::
|
:::
|
||||||
|
|
||||||
<LiveExample framework='react' id='dockview/locked'/>
|
<CodeRunner id='dockview/locked'/>
|
||||||
|
@ -3,8 +3,6 @@ title: Overview
|
|||||||
sidebar_position: 0
|
sidebar_position: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
|
|
||||||
This section provided a core overview.
|
This section provided a core overview.
|
||||||
|
|
||||||
The component takes a collection of [Options](/docs/api/dockview/options) as inputs and
|
The component takes a collection of [Options](/docs/api/dockview/options) as inputs and
|
||||||
@ -33,10 +31,3 @@ const component = new DockviewComponent({
|
|||||||
```
|
```
|
||||||
</FrameworkSpecific>
|
</FrameworkSpecific>
|
||||||
|
|
||||||
## Container Resizing
|
|
||||||
|
|
||||||
The component will automatically resize to it's container.
|
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/resize-container"/>
|
|
||||||
|
|
||||||
# Disposal Pattern
|
|
||||||
|
@ -4,7 +4,7 @@ sidebar_position: 1
|
|||||||
---
|
---
|
||||||
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
|
|
||||||
This section describes how to add a new panel and the options you can provide.
|
This section describes how to add a new panel and the options you can provide.
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ api.addPanel({
|
|||||||
api.setTitle('my_new_custom_title');
|
api.setTitle('my_new_custom_title');
|
||||||
```
|
```
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/update-title" height={250}/>
|
<CodeRunner id="dockview/update-title" height={250}/>
|
||||||
|
|
||||||
## Provide a custom Tab renderer
|
## Provide a custom Tab renderer
|
||||||
|
|
||||||
|
@ -4,11 +4,9 @@ sidebar_postiion: 5
|
|||||||
---
|
---
|
||||||
|
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||||
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import RenderingDockview from '@site/sandboxes/rendering-dockview/src/app';
|
import RenderingDockview from '@site/sandboxes/rendering-dockview/src/app';
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
|
|
||||||
|
|
||||||
Rendering type is an important consideration when creating your application and whether your panels should be destroyed when hidden.
|
Rendering type is an important consideration when creating your application and whether your panels should be destroyed when hidden.
|
||||||
|
|
||||||
:::info
|
:::info
|
||||||
@ -70,7 +68,7 @@ api.addPanel({
|
|||||||
|
|
||||||
## Live Example
|
## Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/render-mode"/>
|
<CodeRunner id="dockview/render-mode"/>
|
||||||
|
|
||||||
|
|
||||||
By default `DockviewReact` only adds to the DOM those panels that are visible,
|
By default `DockviewReact` only adds to the DOM those panels that are visible,
|
||||||
@ -130,3 +128,4 @@ Toggling the checkbox you can see that when you only render those panels which a
|
|||||||
sandboxId="rendering-dockview"
|
sandboxId="rendering-dockview"
|
||||||
react={RenderingDockview}
|
react={RenderingDockview}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ title: Resizing
|
|||||||
|
|
||||||
This section describes how to programatically resize a panel.
|
This section describes how to programatically resize a panel.
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
<DocRef declaration="DockviewPanelApi" methods={['height', 'width', 'setSize', 'onDidDimensionsChange']} />
|
<DocRef declaration="DockviewPanelApi" methods={['height', 'width', 'setSize', 'onDidDimensionsChange']} />
|
||||||
@ -37,4 +37,4 @@ props.api.group.api.setSize({
|
|||||||
|
|
||||||
You can see an example invoking both approaches below.
|
You can see an example invoking both approaches below.
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/resize"/>
|
<CodeRunner id="dockview/resize"/>
|
||||||
|
@ -4,7 +4,7 @@ sidebar_position: 2
|
|||||||
---
|
---
|
||||||
|
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||||
import CustomHeadersDockview from '@site/sandboxes/customheader-dockview/src/app';
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import DockviewNative from '@site/sandboxes/fullwidthtab-dockview/src/app';
|
import DockviewNative from '@site/sandboxes/fullwidthtab-dockview/src/app';
|
||||||
import { attach as attachNativeDockview } from '@site/sandboxes/javascript/fullwidthtab-dockview/src/app';
|
import { attach as attachNativeDockview } from '@site/sandboxes/javascript/fullwidthtab-dockview/src/app';
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
@ -99,10 +99,7 @@ As a simple example the below attaches a custom event handler for the context me
|
|||||||
The below example uses a custom tab renderer to reigster a popover when the user right clicked on a tab.
|
The below example uses a custom tab renderer to reigster a popover when the user right clicked on a tab.
|
||||||
This still makes use of the `DockviewDefaultTab` since it's only a minor change.
|
This still makes use of the `DockviewDefaultTab` since it's only a minor change.
|
||||||
|
|
||||||
<MultiFrameworkContainer
|
<CodeRunner id="dockview/custom-header"/>
|
||||||
sandboxId="customheader-dockview"
|
|
||||||
react={CustomHeadersDockview}
|
|
||||||
/>
|
|
||||||
|
|
||||||
## Full Width Tab
|
## Full Width Tab
|
||||||
|
|
||||||
@ -126,15 +123,7 @@ return <DockviewReactComponent singleTabMode="fullwidth" />
|
|||||||
typescript={attachNativeDockview}
|
typescript={attachNativeDockview}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
import DockviewTabheight from '@site/sandboxes/tabheight-dockview/src/app';
|
|
||||||
import { attach as attachTabHeightDockview } from '@site/sandboxes/javascript/tabheight-dockview/src/app';
|
|
||||||
|
|
||||||
## Tab Height
|
## Tab Height
|
||||||
|
|
||||||
Tab height can be controlled through CSS.
|
Tab height can be controlled through CSS.
|
||||||
|
|
||||||
<MultiFrameworkContainer
|
|
||||||
sandboxId="tabheight-dockview"
|
|
||||||
react={DockviewTabheight}
|
|
||||||
typescript={attachTabHeightDockview}
|
|
||||||
/>
|
|
||||||
|
@ -43,4 +43,4 @@ panel.api.updateParameters({
|
|||||||
|
|
||||||
## Live Example
|
## Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/update-parameters"/>
|
<CodeRunner id="dockview/update-parameters"/>
|
||||||
|
@ -2,8 +2,6 @@
|
|||||||
title: Scrolling
|
title: Scrolling
|
||||||
---
|
---
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
|
|
||||||
It's important to understand how to configure the scrollbar within a panel.
|
It's important to understand how to configure the scrollbar within a panel.
|
||||||
|
|
||||||
A panel will appear with a scrollbar if the the contents of your view has a fixed height.
|
A panel will appear with a scrollbar if the the contents of your view has a fixed height.
|
||||||
@ -17,4 +15,4 @@ The following example contains three views:
|
|||||||
- **Panel 2** (`height: 2000px`): A scrollbar does appear since a fixed height has been used.
|
- **Panel 2** (`height: 2000px`): A scrollbar does appear since a fixed height has been used.
|
||||||
- **Panel 3**: `height: 100%` and a child component with `overflow: auto` which will enable scrollbars.
|
- **Panel 3**: `height: 100%` and a child component with `overflow: auto` which will enable scrollbars.
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/scrollbars"/>
|
<CodeRunner id="dockview/scrollbars"/>
|
||||||
|
@ -2,8 +2,7 @@
|
|||||||
title: Loading State
|
title: Loading State
|
||||||
---
|
---
|
||||||
|
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
This section described loading a dock layout.
|
This section described loading a dock layout.
|
||||||
@ -43,5 +42,6 @@ return <DockviewComponent onReady={onReady}/>;
|
|||||||
|
|
||||||
# Live Example
|
# Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/layout"/>
|
<CodeRunner id="dockview/layout"/>
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
title: Saving State
|
title: Saving State
|
||||||
---
|
---
|
||||||
|
|
||||||
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
This section describes how to serialize a dockview instance.
|
This section describes how to serialize a dockview instance.
|
||||||
@ -39,5 +37,4 @@ return <DockviewComponent onReady={onReady}/>
|
|||||||
|
|
||||||
# Live Example
|
# Live Example
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/layout"/>
|
<CodeRunner id="dockview/layout"/>
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ title: Watermark
|
|||||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||||
|
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
|
||||||
|
|
||||||
When there is nothing else to display.
|
When there is nothing else to display.
|
||||||
|
|
||||||
@ -28,4 +27,4 @@ The following properties can be set to configure the behaviours of floating grou
|
|||||||
|
|
||||||
## Live Examples
|
## Live Examples
|
||||||
|
|
||||||
<LiveExample framework="react" id="dockview/watermark"/>
|
<CodeRunner id="dockview/watermark"/>
|
||||||
|
@ -5,6 +5,4 @@ sidebar_position: 3
|
|||||||
|
|
||||||
A *tabview* can be created using a dock and preventing some default behaviours.
|
A *tabview* can be created using a dock and preventing some default behaviours.
|
||||||
|
|
||||||
import LiveExample from '@site/src/components/ui/exampleFrame';
|
<CodeRunner id='dockview/tabview' />
|
||||||
|
|
||||||
<LiveExample framework='react' id='dockview/tabview' />
|
|
||||||
|
@ -7,7 +7,7 @@ sidebar_position: 0
|
|||||||
Learn how to install Dockview for a selection of frameworks.
|
Learn how to install Dockview for a selection of frameworks.
|
||||||
|
|
||||||
<FrameworkSpecific framework='JavaScript'>
|
<FrameworkSpecific framework='JavaScript'>
|
||||||
Firstly, install the `dockvire-core` library:
|
Firstly, install the `dockview-core` library:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npm install dockview-core
|
npm install dockview-core
|
||||||
@ -21,3 +21,4 @@ Firstly, install the `dockview` library:
|
|||||||
npm install dockview
|
npm install dockview
|
||||||
```
|
```
|
||||||
</FrameworkSpecific>
|
</FrameworkSpecific>
|
||||||
|
|
||||||
|
@ -5,9 +5,7 @@ description: Gridview Documentation
|
|||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||||
import SimpleGridview from '@site/sandboxes/simple-gridview/src/app';
|
import SimpleGridview from '@site/sandboxes/simple-gridview/src/app';
|
||||||
import EditorGridview from '@site/sandboxes/editor-gridview/src/app';
|
import EditorGridview from '@site/sandboxes/editor-gridview/src/app';
|
||||||
// import SimpleGridview from '@site/sandboxes/simple-gridview/src/app';
|
|
||||||
import { EventsGridview } from '@site/src/components/gridview/events';
|
import { EventsGridview } from '@site/src/components/gridview/events';
|
||||||
// import IDEExample from '@site/sandboxes/ide-example/src/app';
|
|
||||||
import Link from '@docusaurus/Link';
|
import Link from '@docusaurus/Link';
|
||||||
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
import { DocRef } from '@site/src/components/ui/reference/docRef';
|
||||||
|
|
||||||
|
@ -4,10 +4,9 @@ sidebar_position: 0
|
|||||||
---
|
---
|
||||||
|
|
||||||
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
import { MultiFrameworkContainer } from '@site/src/components/ui/container';
|
||||||
|
import { CodeRunner } from '@site/src/components/ui/codeRunner';
|
||||||
|
|
||||||
import SimpleDockview from '@site/sandboxes/simple-dockview/src/app';
|
|
||||||
import DockviewExampleApp from '@site/sandboxes/example-app-dockview/src/app';
|
import DockviewExampleApp from '@site/sandboxes/example-app-dockview/src/app';
|
||||||
import { attach as attachSimpleDockview } from '@site/sandboxes/javascript/simple-dockview/src/app';
|
|
||||||
|
|
||||||
|
|
||||||
<MultiFrameworkContainer
|
<MultiFrameworkContainer
|
||||||
@ -20,11 +19,7 @@ import { attach as attachSimpleDockview } from '@site/sandboxes/javascript/simpl
|
|||||||
|
|
||||||
Dockview is an abstraction built on top of [Gridviews](./gridview) where each view is a container of many tabbed panels.
|
Dockview is an abstraction built on top of [Gridviews](./gridview) where each view is a container of many tabbed panels.
|
||||||
|
|
||||||
<MultiFrameworkContainer
|
<CodeRunner id="dockview/basic"/>
|
||||||
sandboxId="simple-dockview"
|
|
||||||
react={SimpleDockview}
|
|
||||||
typescript={attachSimpleDockview}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
|
|
||||||
@ -60,19 +55,3 @@ const MyComponent = (props: IDockviewPanelProps<{ title: string }>) => {
|
|||||||
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
return <div>{`My first panel has the title: ${props.params.title}`}</div>;
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user