Merge pull request #594 from mathuo/562-dockview-framework-wrappers-vuejs-angular-javascript-etc-1

feat: vue3
This commit is contained in:
mathuo 2024-05-13 19:42:45 +01:00 committed by GitHub
commit 35630e4f1c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 1494 additions and 1634 deletions

View File

@ -1,6 +1,7 @@
{ {
"packages": [ "packages": [
"packages/dockview-core", "packages/dockview-core",
"packages/dockview-vue",
"packages/dockview" "packages/dockview"
], ],
"sandboxes": [ "sandboxes": [
@ -41,4 +42,4 @@
"/packages/docs/sandboxes/javascript/vanilla-dockview" "/packages/docs/sandboxes/javascript/vanilla-dockview"
], ],
"node": "18" "node": "18"
} }

View File

@ -26,6 +26,8 @@ jobs:
working-directory: packages/dockview-core working-directory: packages/dockview-core
- run: npm run build - run: npm run build
working-directory: packages/dockview working-directory: packages/dockview
- run: npm run build
working-directory: packages/dockview-vue
- run: npm run build - run: npm run build
working-directory: packages/docs working-directory: packages/docs
- run: npm run docs - run: npm run docs

View File

@ -35,6 +35,9 @@ jobs:
- name: Publish dockview - name: Publish dockview
run: npm publish --provenance run: npm publish --provenance
working-directory: packages/dockview working-directory: packages/dockview
- name: Publish dockview-vue
run: npm publish --provenance
working-directory: packages/dockview-vue
publish-experimental: publish-experimental:
if: github.event_name == 'workflow_dispatch' if: github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -64,3 +67,6 @@ jobs:
- name: Publish dockview - name: Publish dockview
run: npm publish --provenance --tag experimental run: npm publish --provenance --tag experimental
working-directory: packages/dockview working-directory: packages/dockview
- name: Publish dockview-vue
run: npm publish --provenance --tag experimental
working-directory: packages/dockview-vue

View File

@ -16,7 +16,7 @@
"packages/*" "packages/*"
], ],
"scripts": { "scripts": {
"build": "lerna run build --scope '{dockview-core,dockview}'", "build": "lerna run build --scope '{dockview-core,dockview,dockview-vue}'",
"clean": "lerna run clean", "clean": "lerna run clean",
"docs": "typedoc", "docs": "typedoc",
"generate-docs": "node scripts/docs.mjs", "generate-docs": "node scripts/docs.mjs",

View File

@ -12,7 +12,6 @@ import { DockviewGroupPanel } from '../../dockviewGroupPanel';
import { import {
DroptargetEvent, DroptargetEvent,
Droptarget, Droptarget,
Position,
WillShowOverlayEvent, WillShowOverlayEvent,
} from '../../../dnd/droptarget'; } from '../../../dnd/droptarget';
import { DragHandler } from '../../../dnd/abstractDragHandler'; import { DragHandler } from '../../../dnd/abstractDragHandler';

View File

@ -10,11 +10,7 @@ import { VoidContainer } from './voidContainer';
import { toggleClass } from '../../../dom'; import { toggleClass } from '../../../dom';
import { DockviewPanel, IDockviewPanel } from '../../dockviewPanel'; import { DockviewPanel, IDockviewPanel } from '../../dockviewPanel';
import { DockviewComponent } from '../../dockviewComponent'; import { DockviewComponent } from '../../dockviewComponent';
import { WillShowOverlayEvent } from '../../../dnd/droptarget'; import { WillShowOverlayLocationEvent } from '../../dockviewGroupPanelModel';
import {
DockviewGroupDropLocation,
WillShowOverlayLocationEvent,
} from '../../dockviewGroupPanelModel';
import { getPanelData } from '../../../dnd/dataTransfer'; import { getPanelData } from '../../../dnd/dataTransfer';
export interface TabDropIndexEvent { export interface TabDropIndexEvent {

View File

@ -2,7 +2,6 @@ import { IDockviewComponent } from './dockviewComponent';
import { DockviewPanelApi } from '../api/dockviewPanelApi'; import { DockviewPanelApi } from '../api/dockviewPanelApi';
import { PanelInitParameters, IPanel } from '../panel/types'; import { PanelInitParameters, IPanel } from '../panel/types';
import { DockviewApi } from '../api/component.api'; import { DockviewApi } from '../api/component.api';
import { Event } from '../events';
import { Optional } from '../types'; import { Optional } from '../types';
import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel'; import { DockviewGroupPanel, IDockviewGroupPanel } from './dockviewGroupPanel';
import { DockviewPanelRenderer } from '../overlayRenderContainer'; import { DockviewPanelRenderer } from '../overlayRenderContainer';

View File

@ -1,8 +1,5 @@
import { PanelInitParameters } from '../panel/types'; import { PanelInitParameters } from '../panel/types';
import { import { IGridPanelComponentView } from './gridviewComponent';
GridviewComponent,
IGridPanelComponentView,
} from './gridviewComponent';
import { FunctionOrValue } from '../types'; import { FunctionOrValue } from '../types';
import { import {
BasePanelView, BasePanelView,

View File

@ -1,5 +1,5 @@
import { IPanel, PanelInitParameters } from '../panel/types'; import { PanelInitParameters } from '../panel/types';
import { IView, SplitViewOptions, LayoutPriority } from './splitview'; import { SplitViewOptions, LayoutPriority } from './splitview';
import { SplitviewPanel } from './splitviewPanel'; import { SplitviewPanel } from './splitviewPanel';
import { SplitviewComponent } from './splitviewComponent'; import { SplitviewComponent } from './splitviewComponent';
import { import {

View File

@ -1,6 +0,0 @@
const gulp = require('gulp');
const buildfile = require('../../scripts/build');
buildfile.init();
gulp.task('run', gulp.series(['sass']));

View File

@ -1,6 +0,0 @@
const gulp = require('gulp');
const buildfile = require('../../scripts/build');
buildfile.init();
gulp.task('run', gulp.series(['sass']));

View File

@ -4,7 +4,7 @@ const config: JestConfigWithTsJest = {
preset: 'ts-jest', preset: 'ts-jest',
roots: ['<rootDir>/packages/dockview-vue'], roots: ['<rootDir>/packages/dockview-vue'],
modulePaths: ['<rootDir>/packages/dockview-vue/src'], modulePaths: ['<rootDir>/packages/dockview-vue/src'],
displayName: { name: 'dockview', color: 'blue' }, displayName: { name: 'dockview-vue', color: 'blue' },
rootDir: '../../', rootDir: '../../',
collectCoverageFrom: [ collectCoverageFrom: [
'<rootDir>/packages/dockview-vue/src/**/*.{js,jsx,ts,tsx}', '<rootDir>/packages/dockview-vue/src/**/*.{js,jsx,ts,tsx}',

View File

@ -41,21 +41,16 @@
"README.md" "README.md"
], ],
"scripts": { "scripts": {
"build-only": "vite build", "build:js": "vite build",
"build": "npm run build:package", "build:types": "vue-tsc --project tsconfig.build-types.json --declaration --emitDeclarationOnly --outDir dist/types",
"build:bundles": "rollup -c", "build": "npm run build:js && npm run build:types",
"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/", "clean": "rimraf dist/ .build/ .rollup.cache/",
"prepublishOnly": "npm run rebuild && npm run test", "prepublishOnly": "npm run rebuild && npm run test",
"rebuild": "npm run clean && npm run build", "rebuild": "npm run clean && npm run build",
"test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview", "test": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue",
"test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview --coverage", "test:cov": "cross-env ../../node_modules/.bin/jest --selectProjects dockview-vue --coverage"
"build:types": "vue-tsc --project tsconfig.build-types.json --declaration --emitDeclarationOnly --outDir dist/types "
}, },
"dependencies": { "dependencies": {
"dockview-core": "^1.13.1" "dockview-core": "^1.13.1"
} }
} }

View File

@ -1,116 +0,0 @@
/* 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 }),
];

View File

@ -1,2 +0,0 @@
import '../dist/styles/dockview.css';
export * from '../src/index';

View File

@ -2,13 +2,6 @@
import { import {
DockviewApi, DockviewApi,
DockviewComponent, DockviewComponent,
type IContentRenderer,
type ITabRenderer,
type IWatermarkRenderer,
type IDockviewPanelProps,
type IDockviewPanelHeaderProps,
type IGroupPanelBaseProps,
type IWatermarkPanelProps,
type DockviewOptions, type DockviewOptions,
PROPERTY_KEYS, PROPERTY_KEYS,
type DockviewFrameworkOptions, type DockviewFrameworkOptions,
@ -22,13 +15,11 @@ import {
watch, watch,
onBeforeUnmount, onBeforeUnmount,
markRaw, markRaw,
toRaw,
getCurrentInstance, getCurrentInstance,
} from 'vue'; } from 'vue';
import { import {
VueContentRenderer,
VueHeaderActionsRenderer, VueHeaderActionsRenderer,
VueTabRenderer, VueRenderer,
VueWatermarkRenderer, VueWatermarkRenderer,
findComponent, findComponent,
} from '../utils'; } from '../utils';
@ -41,18 +32,6 @@ interface VueProps {
prefixHeaderActionsComponent?: string; prefixHeaderActionsComponent?: string;
} }
const VUE_PROPERTIES = (() => {
const _value: Record<keyof VueProps, undefined> = {
watermarkComponent: undefined,
defaultTabComponent: undefined,
rightHeaderActionsComponent: undefined,
leftHeaderActionsComponent: undefined,
prefixHeaderActionsComponent: undefined,
};
return Object.keys(_value) as (keyof VueProps)[];
})();
type VueEvents = { type VueEvents = {
ready: [event: DockviewReadyEvent]; ready: [event: DockviewReadyEvent];
}; };
@ -73,10 +52,6 @@ function extractCoreOptions(props: IDockviewVueProps): DockviewOptions {
const emit = defineEmits<VueEvents>(); 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 props = defineProps<IDockviewVueProps>();
const el = ref<HTMLElement | null>(null); const el = ref<HTMLElement | null>(null);
@ -105,7 +80,7 @@ onMounted(() => {
getCurrentInstance()!, getCurrentInstance()!,
options.name options.name
); );
return new VueContentRenderer(component!, getCurrentInstance()!); return new VueRenderer(component!, getCurrentInstance()!);
}, },
createTabComponent(options) { createTabComponent(options) {
let component = findComponent(getCurrentInstance()!, options.name); let component = findComponent(getCurrentInstance()!, options.name);
@ -118,7 +93,7 @@ onMounted(() => {
} }
if (component) { if (component) {
return new VueTabRenderer(component, getCurrentInstance()!); return new VueRenderer(component, getCurrentInstance()!);
} }
return undefined; return undefined;
}, },
@ -199,8 +174,6 @@ onMounted(() => {
*/ */
instance.value = markRaw(dockview); instance.value = markRaw(dockview);
console.log(getCurrentInstance());
emit('ready', { api: new DockviewApi(dockview) }); emit('ready', { api: new DockviewApi(dockview) });
}); });

View File

@ -1,9 +1,10 @@
import type { import type {
DockviewApi,
DockviewGroupPanel, DockviewGroupPanel,
DockviewPanelApi,
GroupPanelPartInitParameters, GroupPanelPartInitParameters,
IContentRenderer, IContentRenderer,
IDockviewPanelHeaderProps, IDockviewPanelHeaderProps,
IDockviewPanelProps,
IGroupHeaderProps, IGroupHeaderProps,
IHeaderActionsRenderer, IHeaderActionsRenderer,
ITabRenderer, ITabRenderer,
@ -59,12 +60,6 @@ export function findComponent(
} }
/** /**
* 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#clonevnode
* @see https://vuejs.org/api/render-function.html#mergeprops * @see https://vuejs.org/api/render-function.html#mergeprops
*/ */
@ -84,8 +79,8 @@ export function mountVueComponent<T extends Record<string, any>>(
return { return {
update: (newProps: any) => { update: (newProps: any) => {
runningProps = { ...props, newProps }; runningProps = { ...props, ...newProps };
vNode = cloneVNode(vNode, Object.freeze(runningProps)); vNode = cloneVNode(vNode, runningProps);
render(vNode, element); render(vNode, element);
}, },
dispose: () => { dispose: () => {
@ -94,78 +89,38 @@ export function mountVueComponent<T extends Record<string, any>>(
}; };
} }
export class VueContentRenderer implements IContentRenderer { abstract class AbstractVueRenderer {
private _element: HTMLElement; protected readonly _element: HTMLElement;
private _renderDisposable:
| { update: (props: any) => void; dispose: () => void }
| undefined;
get element(): HTMLElement { get element(): HTMLElement {
return this._element; return this._element;
} }
constructor( constructor(
private readonly component: VueComponent, protected readonly component: VueComponent,
private readonly parent: ComponentInternalInstance protected readonly parent: ComponentInternalInstance
) { ) {
this._element = document.createElement('div'); this._element = document.createElement('div');
this.element.className = 'dv-vue-part'; this.element.className = 'dv-vue-part';
this.element.style.height = '100%'; this.element.style.height = '100%';
this.element.style.width = '100%'; this.element.style.width = '100%';
} }
init(parameters: GroupPanelPartInitParameters): void {
const props: IDockviewPanelProps = {
params: parameters.params,
api: parameters.api,
containerApi: parameters.containerApi,
};
this._renderDisposable?.dispose();
this._renderDisposable = mountVueComponent(
this.component,
this.parent,
{ params: 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 { export class VueRenderer
private _element: HTMLElement; extends AbstractVueRenderer
implements ITabRenderer, IContentRenderer
{
private _renderDisposable: private _renderDisposable:
| { update: (props: any) => void; dispose: () => void } | { update: (props: any) => void; dispose: () => void }
| undefined; | undefined;
private _api: DockviewPanelApi | undefined;
get element(): HTMLElement { private _containerApi: DockviewApi | undefined;
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 { init(parameters: GroupPanelPartInitParameters): void {
this._api = parameters.api;
this._containerApi = parameters.containerApi;
const props: IDockviewPanelHeaderProps = { const props: IDockviewPanelHeaderProps = {
params: parameters.params, params: parameters.params,
api: parameters.api, api: parameters.api,
@ -182,9 +137,18 @@ export class VueTabRenderer implements ITabRenderer {
} }
update(event: PanelUpdateEvent<Parameters>): void { update(event: PanelUpdateEvent<Parameters>): void {
if (!this._api || !this._containerApi) {
return;
}
const params = event.params; const params = event.params;
// TODO: handle prop updates somehow? this._renderDisposable?.update({
this._renderDisposable?.update(params); params: {
params: params,
api: this._api,
containerApi: this._containerApi,
},
});
} }
dispose(): void { dispose(): void {
@ -192,8 +156,10 @@ export class VueTabRenderer implements ITabRenderer {
} }
} }
export class VueWatermarkRenderer implements IWatermarkRenderer { export class VueWatermarkRenderer
private _element: HTMLElement; extends AbstractVueRenderer
implements IWatermarkRenderer
{
private _renderDisposable: private _renderDisposable:
| { update: (props: any) => void; dispose: () => void } | { update: (props: any) => void; dispose: () => void }
| undefined; | undefined;
@ -202,16 +168,6 @@ export class VueWatermarkRenderer implements IWatermarkRenderer {
return this._element; 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 { init(parameters: WatermarkRendererInitParameters): void {
const props: IWatermarkPanelProps = { const props: IWatermarkPanelProps = {
group: parameters.group, group: parameters.group,
@ -232,9 +188,7 @@ export class VueWatermarkRenderer implements IWatermarkRenderer {
} }
update(event: PanelUpdateEvent<Parameters>): void { update(event: PanelUpdateEvent<Parameters>): void {
const params = event.params; // noop
// TODO: handle prop updates somehow?
this._renderDisposable?.update(params);
} }
dispose(): void { dispose(): void {
@ -242,8 +196,10 @@ export class VueWatermarkRenderer implements IWatermarkRenderer {
} }
} }
export class VueHeaderActionsRenderer implements IHeaderActionsRenderer { export class VueHeaderActionsRenderer
private _element: HTMLElement; extends AbstractVueRenderer
implements IHeaderActionsRenderer
{
private _renderDisposable: private _renderDisposable:
| { update: (props: any) => void; dispose: () => void } | { update: (props: any) => void; dispose: () => void }
| undefined; | undefined;
@ -253,14 +209,11 @@ export class VueHeaderActionsRenderer implements IHeaderActionsRenderer {
} }
constructor( constructor(
private readonly component: VueComponent, component: VueComponent,
private readonly parent: ComponentInternalInstance, parent: ComponentInternalInstance,
group: DockviewGroupPanel group: DockviewGroupPanel
) { ) {
this._element = document.createElement('div'); super(component, parent);
this.element.className = 'dv-vue-header-action-part';
this._element.style.width = '100%';
this._element.style.height = '100%';
} }
init(props: IGroupHeaderProps): void { init(props: IGroupHeaderProps): void {

View File

@ -5,6 +5,7 @@ import vue from '@vitejs/plugin-vue';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [vue()], plugins: [vue()],
build: { build: {
minify: false, minify: false,
lib: { lib: {
@ -13,6 +14,7 @@ export default defineConfig({
name: 'dockview-vue', name: 'dockview-vue',
// the name of the output files when the build is run // the name of the output files when the build is run
fileName: (format) => `dockview-vue.${format}.js`, fileName: (format) => `dockview-vue.${format}.js`,
formats: ['es', 'umd', 'cjs'],
}, },
rollupOptions: { rollupOptions: {
// make sure to externalize deps that shouldn't be bundled // make sure to externalize deps that shouldn't be bundled

View File

@ -3,8 +3,6 @@ import {
DockviewComponent, DockviewComponent,
DockviewWillDropEvent, DockviewWillDropEvent,
DockviewApi, DockviewApi,
IContentRenderer,
ITabRenderer,
DockviewGroupPanel, DockviewGroupPanel,
IHeaderActionsRenderer, IHeaderActionsRenderer,
DockviewDidDropEvent, DockviewDidDropEvent,
@ -16,13 +14,11 @@ import {
PROPERTY_KEYS, PROPERTY_KEYS,
DockviewComponentOptions, DockviewComponentOptions,
DockviewFrameworkOptions, DockviewFrameworkOptions,
IDockviewDisposable,
DockviewDndOverlayEvent, DockviewDndOverlayEvent,
DockviewReadyEvent, 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 { ReactWatermarkPart } from './reactWatermarkPart'; import { ReactWatermarkPart } from './reactWatermarkPart';
import { ReactHeaderActionsRendererPart } from './headerActionsRenderer'; import { ReactHeaderActionsRendererPart } from './headerActionsRenderer';

View File

@ -22,12 +22,21 @@ function onReady(event: DockviewReadyEvent) {
``` ```
</FrameworkSpecific> </FrameworkSpecific>
<FrameworkSpecific framework='Vue'>
<FrameworkSpecific framework='JavaScript'>
```tsx ```tsx
const component = new DockviewComponent({ const App = {
/** options */ name: 'App',
}); methods: {
onReady(event: DockviewReadyEvent) {
const api: DockviewApi = event.api;
},
},
template: `
<dockview-vue
@ready="onReady"
>
</dockview-vue>`,
};
``` ```
</FrameworkSpecific> </FrameworkSpecific>

View File

@ -39,6 +39,37 @@ return <DockviewReact components={components}/>
</FrameworkSpecific> </FrameworkSpecific>
<FrameworkSpecific framework='Vue'>
```tsx
const App = {
name: 'App',
components: {
'component_1': VueComponent1,
'component_2': VueComponent2,
},
methods: {
onReady(event: DockviewReadyEvent) {
event.api.addPanel({
id: 'panel_1',
component: 'component_1'
});
event.api.addPanel({
id: 'panel_2',
component: 'component_2'
});
},
},
template: `
<dockview-vue
@ready="onReady"
>
</dockview-vue>`,
};
```
</FrameworkSpecific>
Each panel has an [api](/docs/api/dockview/panelApi) which is used to control specific Each panel has an [api](/docs/api/dockview/panelApi) which is used to control specific
features on that individual panel. features on that individual panel.
The panel also has access the [group api](/docs/api/dockview/groupApi) and the container The panel also has access the [group api](/docs/api/dockview/groupApi) and the container

View File

@ -31,6 +31,32 @@ return <DockviewReact tabComponents={tabComponents}/>
``` ```
</FrameworkSpecific> </FrameworkSpecific>
<FrameworkSpecific framework='Vue'>
```tsx
const App = {
name: 'App',
components: {
'component_1': VueComponent1,
'tab_1': VueComponent2,
},
methods: {
onReady(event: DockviewReadyEvent) {
event.api.addPanel({
id: 'panel_1',
component: 'component_1',
tabComponent: 'tab_1'
});
},
},
template: `
<dockview-vue
@ready="onReady"
>
</dockview-vue>`,
};
```
</FrameworkSpecific>
<FrameworkSpecific framework='JavaScript'> <FrameworkSpecific framework='JavaScript'>
not implemented not implemented
</FrameworkSpecific> </FrameworkSpecific>
@ -51,6 +77,32 @@ return <DockviewReact defaultTabRenderer={CustomTabRenderer}/>
``` ```
</FrameworkSpecific> </FrameworkSpecific>
<FrameworkSpecific framework='Vue'>
```tsx
const App = {
name: 'App',
components: {
'component_1': VueComponent1,
'tab_1': VueComponent2,
},
methods: {
onReady(event: DockviewReadyEvent) {
event.api.addPanel({
id: 'panel_1',
component: 'component_1',
});
},
},
template: `
<dockview-vue
@ready="onReady"
:defaultTabRenderer='tab_1'
>
</dockview-vue>`,
};
```
</FrameworkSpecific>
<FrameworkSpecific framework='JavaScript'> <FrameworkSpecific framework='JavaScript'>
not implemented not implemented
</FrameworkSpecific> </FrameworkSpecific>

File diff suppressed because it is too large Load Diff

View File

@ -15,7 +15,6 @@ class Panel implements IContentRenderer {
constructor() { constructor() {
this._element = document.createElement('div'); this._element = document.createElement('div');
this._element.style.color = 'white'; this._element.style.color = 'white';
} }
@ -28,7 +27,12 @@ document.getElementById('app').className = 'dockview-theme-abyss';
const dockview = new DockviewComponent({ const dockview = new DockviewComponent({
parentElement: document.getElementById('app'), parentElement: document.getElementById('app'),
components: { default: Panel }, createComponent: (options) => {
switch (options.name) {
case 'default':
return new Panel();
}
},
}); });
const api = new DockviewApi(dockview); const api = new DockviewApi(dockview);

View File

@ -27,7 +27,7 @@ const Panel = defineComponent({
}, },
}, },
mounted() { mounted() {
const disposable = this.api.onDidTitleChange(() => { const disposable = this.params.api.onDidTitleChange(() => {
this.title = this.api.title; this.title = this.api.title;
}); });
this.title = this.api.title; this.title = this.api.title;
@ -64,14 +64,16 @@ const Tab = defineComponent({
name: 'Tab', name: 'Tab',
props: { props: {
params: { params: {
type: Object as PropType<IDockviewPanelHeaderProps>, type: Object as PropType<
IDockviewPanelHeaderProps<{ myValue: number }>
>,
required: true, required: true,
}, },
}, },
data() { data() {
return { return {
title: '', title: '',
value: null, value: this.params.params.myValue,
}; };
}, },
mounted() { mounted() {
@ -80,11 +82,12 @@ const Tab = defineComponent({
}); });
const disposable2 = this.params.api.onDidParametersChange(() => { const disposable2 = this.params.api.onDidParametersChange(() => {
this.value = this.params.myValue; console.log(this.params);
this.value = this.params.params.myValue;
}); });
this.title = this.api.title; this.title = this.api.title;
this.value = this.params.myValue; this.value = this.params.params.myValue;
return () => { return () => {
disposable.dispose(); disposable.dispose();

View File

@ -50,22 +50,35 @@ fs.writeFileSync(
// dockview // dockview
const dockviewPath = path.join(rootDir, 'packages', 'dockview', 'package.json'); const depPackages = ['dockview', 'dockview-vue'];
const dockviewPackageJson = JSON.parse(
fs.readFileSync(dockviewPath).toString()
);
dockviewPackageJson.version = version; for (const depPackage of depPackages) {
dockviewPackageJson.dependencies['dockview-core'] = dockviewPackageJson.version; const dockviewPath = path.join(
rootDir,
'packages',
depPackage,
'package.json'
);
const dockviewPackageJson = JSON.parse(
fs.readFileSync(dockviewPath).toString()
);
fs.writeFileSync(dockviewPath, JSON.stringify(dockviewPackageJson, null, 4)); dockviewPackageJson.version = version;
dockviewPackageJson.dependencies['dockview-core'] =
dockviewPackageJson.version;
// sanity check fs.writeFileSync(
dockviewPath,
JSON.stringify(dockviewPackageJson, null, 4)
);
const dvCore = JSON.parse(fs.readFileSync(dockviewCorePath).toString()); // sanity check
const dv = JSON.parse(fs.readFileSync(dockviewPath).toString());
console.log(`dockview-core version: ${dvCore.version}`); const dvCore = JSON.parse(fs.readFileSync(dockviewCorePath).toString());
console.log( const dv = JSON.parse(fs.readFileSync(dockviewPath).toString());
`dockview version: ${dv.version} dockview-core dependency version: ${dv.dependencies['dockview-core']}`
); console.log(`dockview-core version: ${dvCore.version}`);
console.log(
`${depPackage} version: ${dv.version} dockview-core dependency version: ${dv.dependencies['dockview-core']}`
);
}

View File

@ -1,9 +1,9 @@
sonar.projectKey=mathuo_dockview sonar.projectKey=mathuo_dockview
sonar.organization=dockview sonar.organization=dockview
sonar.inclusions=packages/dockview/src/**/*,packages/dockview-core/src/**/* sonar.inclusions=packages/dockview/src/**/*,packages/dockview-core/src/**/*,packages/dockview-vue/src/**/*
sonar.exclusions=packages/dockview/src/__tests__/**,packages/dockview-core/src/__tests__/** sonar.exclusions=packages/dockview/src/__tests__/**,packages/dockview-core/src/__tests__/**,packages/dockview-vue/src/__tests__/**
sonar.tests=packages/dockview/src/__tests__,packages/dockview-core/src/__tests__ sonar.tests=packages/dockview/src/__tests__,packages/dockview-core/src/__tests__,packages/dockview-vue/src/__tests__
sonar.testExecutionReportPaths=test-report.xml sonar.testExecutionReportPaths=test-report.xml
sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.javascript.lcov.reportPaths=coverage/lcov.info

View File

@ -6,6 +6,9 @@
}, },
{ {
"path": "./packages/dockview-core" "path": "./packages/dockview-core"
},
{
"path": "./packages/dockview-vue"
} }
] ]
} }