mirror of
https://github.com/mathuo/dockview
synced 2025-02-08 17:35:44 +00:00
feat: framework support
This commit is contained in:
parent
e147255fcd
commit
db747f1ead
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dockview-angular",
|
||||
"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": [
|
||||
"splitview",
|
||||
"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",
|
||||
"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": [
|
||||
"splitview",
|
||||
"split-view",
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dockview-react",
|
||||
"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": [
|
||||
"splitview",
|
||||
"split-view",
|
||||
@ -56,4 +56,4 @@
|
||||
"dependencies": {
|
||||
"dockview": "^1.10.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dockview-vue",
|
||||
"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": [
|
||||
"splitview",
|
||||
"split-view",
|
||||
@ -58,4 +58,4 @@
|
||||
"dependencies": {
|
||||
"dockview-core": "^1.10.1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dockview",
|
||||
"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": [
|
||||
"splitview",
|
||||
"split-view",
|
||||
|
Loading…
Reference in New Issue
Block a user