mirror of
https://github.com/mathuo/dockview
synced 2025-05-08 20:48:28 +00:00
feat: framework support
This commit is contained in:
parent
e147255fcd
commit
db747f1ead
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-angular",
|
"name": "dockview-angular",
|
||||||
"version": "0.0.0-beta-0",
|
"version": "0.0.0-beta-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,121 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import {
|
|
||||||
DockviewApi,
|
|
||||||
DockviewComponent,
|
|
||||||
type DockviewDndOverlayEvent,
|
|
||||||
type DockviewPanelRenderer,
|
|
||||||
type DroptargetOverlayModel,
|
|
||||||
type IContentRenderer,
|
|
||||||
type ITabRenderer,
|
|
||||||
type IWatermarkRenderer
|
|
||||||
} from 'dockview-core'
|
|
||||||
import { ref, onMounted, watch, onBeforeUnmount } from 'vue'
|
|
||||||
import {
|
|
||||||
VueContentRenderer,
|
|
||||||
VueTabRenderer,
|
|
||||||
VueWatermarkRenderer,
|
|
||||||
type ComponentInterface
|
|
||||||
} from './utils'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
// onReady: (event: DockviewReadyEvent) => void;
|
|
||||||
components: Record<string, any>
|
|
||||||
tabComponents?: Record<string, any>
|
|
||||||
// watermarkComponent?: React.FunctionComponent<IWatermarkPanelProps>;
|
|
||||||
// onDidDrop?: (event: DockviewDidDropEvent) => void;
|
|
||||||
// onWillDrop?: (event: DockviewWillDropEvent) => void;
|
|
||||||
// showDndOverlay?: (event: DockviewDndOverlayEvent) => boolean;
|
|
||||||
hideBorders?: boolean;
|
|
||||||
className?: string;
|
|
||||||
disableAutoResizing?: boolean;
|
|
||||||
// defaultTabComponent?: React.FunctionComponent<IDockviewPanelHeaderProps>;
|
|
||||||
// rightHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
|
||||||
// leftHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
|
||||||
// prefixHeaderActionsComponent?: React.FunctionComponent<IDockviewHeaderActionsProps>;
|
|
||||||
singleTabMode?: 'fullwidth' | 'default';
|
|
||||||
disableFloatingGroups?: boolean;
|
|
||||||
floatingGroupBounds?:
|
|
||||||
| 'boundedWithinViewport'
|
|
||||||
| {
|
|
||||||
minimumHeightWithinViewport?: number;
|
|
||||||
minimumWidthWithinViewport?: number;
|
|
||||||
};
|
|
||||||
debug?: boolean;
|
|
||||||
defaultRenderer?: DockviewPanelRenderer;
|
|
||||||
rootOverlayModel?: DroptargetOverlayModel
|
|
||||||
locked?: boolean;
|
|
||||||
disableDnd?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Emits {
|
|
||||||
(event: 'ready', value: { api: DockviewApi }): void
|
|
||||||
(event: 'showDndOverlay', value: DockviewDndOverlayEvent):void
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<Props>()
|
|
||||||
|
|
||||||
const emit = defineEmits<Emits>()
|
|
||||||
|
|
||||||
const el = ref<HTMLElement | null>(null)
|
|
||||||
const instance = ref<DockviewComponent | null>(null)
|
|
||||||
|
|
||||||
watch(() => props.components, (newValue, oldValue) => {
|
|
||||||
if (instance.value) {
|
|
||||||
instance.value.updateOptions({ components: newValue })
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
if (!el.value) {
|
|
||||||
throw new Error('element is not mounted')
|
|
||||||
}
|
|
||||||
|
|
||||||
const dockview = new DockviewComponent({
|
|
||||||
parentElement: el.value,
|
|
||||||
frameworkComponentFactory: {
|
|
||||||
content: {
|
|
||||||
createComponent: (id: string, componentId: string, component: any): IContentRenderer => {
|
|
||||||
console.log('dockview-vue: createComponent')
|
|
||||||
|
|
||||||
return new VueContentRenderer(component as ComponentInterface)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tab: {
|
|
||||||
createComponent: (id: string, componentId: string, component: any): ITabRenderer => {
|
|
||||||
return new VueTabRenderer(component as ComponentInterface)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watermark: {
|
|
||||||
createComponent: (id: string, componentId: string, component: any): IWatermarkRenderer => {
|
|
||||||
return new VueWatermarkRenderer(component as ComponentInterface)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
frameworkComponents: props.components,
|
|
||||||
disableAutoResizing: props.disableAutoResizing,
|
|
||||||
frameworkTabComponents: props.tabComponents,
|
|
||||||
singleTabMode: props.singleTabMode,
|
|
||||||
disableFloatingGroups: props.disableFloatingGroups,
|
|
||||||
floatingGroupBounds: props.floatingGroupBounds,
|
|
||||||
defaultRenderer: props.defaultRenderer,
|
|
||||||
debug: props.debug,
|
|
||||||
rootOverlayModel: props.rootOverlayModel,
|
|
||||||
locked: props.locked,
|
|
||||||
disableDnd: props.disableDnd,
|
|
||||||
})
|
|
||||||
|
|
||||||
instance.value = dockview
|
|
||||||
emit("ready", { api: new DockviewApi(dockview) })
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
if (instance.value) {
|
|
||||||
instance.value.dispose()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<div ref="el" />
|
|
||||||
</template>
|
|
@ -1,151 +0,0 @@
|
|||||||
import type {
|
|
||||||
DockviewGroupPanel,
|
|
||||||
GroupPanelPartInitParameters,
|
|
||||||
IContentRenderer,
|
|
||||||
ITabRenderer,
|
|
||||||
IWatermarkRenderer,
|
|
||||||
PanelUpdateEvent,
|
|
||||||
Parameters,
|
|
||||||
WatermarkRendererInitParameters
|
|
||||||
} from 'dockview-core'
|
|
||||||
import { createVNode, type ComponentOptionsBase, render, cloneVNode, mergeProps } from 'vue'
|
|
||||||
|
|
||||||
export type ComponentInterface = ComponentOptionsBase<any, any, any, any, any, any, any, any>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(component: ComponentInterface, props: any, element: HTMLElement) {
|
|
||||||
let vNode = createVNode(component, props)
|
|
||||||
|
|
||||||
render(vNode, element)
|
|
||||||
|
|
||||||
return {
|
|
||||||
update: (newProps: any) => {
|
|
||||||
vNode = cloneVNode(vNode, mergeProps(props, newProps))
|
|
||||||
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: ComponentInterface) {
|
|
||||||
this._element = document.createElement('div')
|
|
||||||
this.element.className = 'dv-vue-part'
|
|
||||||
}
|
|
||||||
|
|
||||||
init(parameters: GroupPanelPartInitParameters): void {
|
|
||||||
const props = {
|
|
||||||
params: parameters.params,
|
|
||||||
api: parameters.api,
|
|
||||||
containerApi: parameters.containerApi
|
|
||||||
}
|
|
||||||
|
|
||||||
this._renderDisposable?.dispose()
|
|
||||||
this._renderDisposable = mountVueComponent(this.component, 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: ComponentInterface) {
|
|
||||||
this._element = document.createElement('div')
|
|
||||||
this.element.className = 'dv-vue-part'
|
|
||||||
}
|
|
||||||
|
|
||||||
init(parameters: GroupPanelPartInitParameters): void {
|
|
||||||
const props = {
|
|
||||||
params: parameters.params,
|
|
||||||
api: parameters.api,
|
|
||||||
containerApi: parameters.containerApi
|
|
||||||
}
|
|
||||||
|
|
||||||
this._renderDisposable?.dispose()
|
|
||||||
this._renderDisposable = mountVueComponent(this.component, 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: ComponentInterface) {
|
|
||||||
this._element = document.createElement('div')
|
|
||||||
this.element.className = 'dv-vue-part'
|
|
||||||
}
|
|
||||||
|
|
||||||
init(parameters: WatermarkRendererInitParameters): void {
|
|
||||||
const props = {
|
|
||||||
group: parameters.group,
|
|
||||||
containerApi: parameters.containerApi
|
|
||||||
}
|
|
||||||
|
|
||||||
this._renderDisposable?.dispose()
|
|
||||||
this._renderDisposable = mountVueComponent(this.component, 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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-core",
|
"name": "dockview-core",
|
||||||
"version": "1.10.1",
|
"version": "1.10.1",
|
||||||
"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,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-react",
|
"name": "dockview-react",
|
||||||
"version": "0.0.0-beta-0",
|
"version": "0.0.0-beta-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,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview-vue",
|
"name": "dockview-vue",
|
||||||
"version": "0.0.0-beta-0",
|
"version": "0.0.0-beta-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,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "dockview",
|
"name": "dockview",
|
||||||
"version": "1.10.1",
|
"version": "1.10.1",
|
||||||
"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",
|
||||||
|
Loading…
Reference in New Issue
Block a user