-
-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Migrate to Vue3 #51
Comments
I will check later this week if i can help with this migration <script setup lang="ts">
import { ref, nextTick, onMounted, onUpdated } from 'vue'
import LuminoWidget from './lumino-widget'
import { BoxPanel, DockPanel, Widget } from '@lumino/widgets'
interface Props {
/**
* Prop to customize the tab title. Defaults to name.
* If a component does not have the $component.$tabTitleProp
* set, then we still revert to the old default $component.name.
*/
tabTitleProp?: string
}
const props = withDefaults(defineProps<Props>(), {
tabTitleProp: 'name'
})
const emit = defineEmits(['lumino:activated', 'lumino:deleted'])
// define a ref to the slot element
const slot = ref<HTMLElement | null>(null)
// define a ref to the slot element
const container = ref<HTMLElement | null>(null)
const widgets = ref<string[]>([])
/**
* Data for the Lumino component
*/
const main = new BoxPanel({ direction: 'left-to-right', spacing: 0 })
const dock = new DockPanel()
/**
* React to a deleted event.
*
* @param customEvent {
* detail: {
* id: string,
* name: string,
* closable: boolean
* }
* }}
*/
function onWidgetActivated(customEvent: CustomEvent) {
emit('lumino:activated', customEvent.detail)
}
/**
* React to a deleted event.
*
* @param customEvent {
* detail: {
* id: string,
* name: string,
* closable: boolean
* }
* }}
*/
function onWidgetDeleted(customEvent: CustomEvent) {
const id = customEvent.detail.id
widgets.value.splice(widgets.value.indexOf(id), 1)
document
.getElementById(id)
?.removeEventListener('lumino:deleted', (event) => onWidgetDeleted(event as CustomEvent))
document
.getElementById(id)
?.removeEventListener('lumino:activated', (event) => onWidgetDeleted(event as CustomEvent))
emit('lumino:deleted', customEvent.detail)
}
/**
* Create a widget.
*
* @param id {String} - widget ID
* @param name {String} - widget name
*/
function addWidget(id: string, name: string) {
widgets.value.push(id)
const luminoWidget = new LuminoWidget(id, name, /* closable */ true)
dock.addWidget(luminoWidget)
nextTick(() => {
document
.getElementById(id)
?.addEventListener('lumino:activated', (event) => onWidgetActivated(event as CustomEvent))
document
.getElementById(id)
?.addEventListener('lumino:deleted', (event) => onWidgetDeleted(event as CustomEvent))
})
}
/**
* Iterates through the component children, looking for newly created
* components, and then creates a related Lumino Widget for this component.
*/
function syncWidgets() {
const widgetList = slot.value?.children
if (!widgetList) return
for (const widget of widgetList) {
const id = widget.id
if (widgets.value.includes(id)) continue
const name = widget.getAttribute(props.tabTitleProp as string) || ''
addWidget(id, name)
nextTick(() => {
document.getElementById(id)?.appendChild(widget)
})
}
}
/**
* Here we define the ID's for the Lumino DOM elements, and add the Dock panel to the main
* Box panel. In the next tick of Vue, the DOM element and the Vue element/ref are attached.
*/
onMounted(() => {
dock.id = 'dock'
main.id = 'main'
main.addWidget(dock)
window.onresize = () => {
main.update()
}
BoxPanel.setStretch(dock, 1)
if (container.value) {
Widget.attach(main, container.value)
syncWidgets()
}
})
/**
* Every time a new child element is added to the slot, this method will
* be called. It will iterate the children elements looking for new ones
* to add.
*
* The removal is handled via event listeners from Lumino.
*/
onUpdated(() => {
syncWidgets()
})
</script>
<template>
<div id="workflow-panel">
<div id="main" ref="container" class="pa-4 fill-height"></div>
<div v-show="false" ref="slot">
<slot></slot>
</div>
</div>
</template>
<styles lang="scss">
#workflow-panel {
height: 100%;
#main {
height: 100%;
.content {
min-width: 300px;
min-height: 300px;
display: flex;
flex-direction: column;
padding: 0;
border: 1px solid #c0c0c0;
border-top: none;
background: white;
position: relative;
overflow: auto;
}
.p-BoxPanel {
flex: 1 1 auto;
}
}
}
</styles> this should do the trick for until the migration is finished |
Thank you @nelsonpjunior ! |
@kinow @nelsonpjunior In my project, I used this package and @nelsonpjunior's Vue3 component, but meet some problems:
so, inspired by your guys, I wrote a Vue3 version: and I used it in this project: Thank you all again. |
Hi @novrain If you'd like to send a PR we can merge your changes. Otherwise, this project was created to be used in Cylc. I left the project and haven't had time to update it. But another dev updated it in Cylc, using Vue3 and the teleport. At some point I will have a look at his changes, at Vue 3 and upgrade this package (or someone could send a PR for that too). Cheers |
PR's welcome, otherwise done whenever I have plenty spare time.
The text was updated successfully, but these errors were encountered: