zammad/app/frontend/shared/components/DynamicInitializer/DynamicInitializer.vue
2026-01-02 15:41:09 +02:00

72 lines
1.7 KiB
Vue

<!-- Copyright (C) 2012-2026 Zammad Foundation, https://zammad-foundation.org/ -->
<script setup lang="ts">
import { useEventListener } from '@vueuse/core'
import { markRaw, shallowRef } from 'vue'
import { Events } from './manage.ts'
import type { DestroyComponentData, PushComponentData } from './types.ts'
import type { TransitionProps } from 'vue'
const props = defineProps<{
/**
* Name of a group of components that will be pushed to with unique ID.
*/
name: string
/**
* Transition, if any.
*/
transition?: TransitionProps
}>()
const components = shallowRef<PushComponentData[]>([])
useEventListener(window, Events.Push, ({ detail }: CustomEvent<PushComponentData>) => {
if (detail.name !== props.name) return
components.value = [
...components.value,
{
...detail,
cmp: markRaw(detail.cmp),
},
]
})
useEventListener(window, Events.Destroy, ({ detail }: CustomEvent<DestroyComponentData>) => {
if (detail.name !== props.name) return
if (!detail.id) {
components.value = []
return
}
components.value = components.value.filter(
(item) => !(item.name === detail.name && item.id === detail.id),
)
})
</script>
<template>
<TransitionGroup v-if="transition" v-bind="transition">
<Component
:is="cmp"
v-for="{ cmp, name: cmpName, id, props: cmpProps } in components"
:key="`${cmpName}-${id}`"
v-bind="cmpProps"
/>
</TransitionGroup>
<template v-else-if="!$slots.default">
<Component
:is="cmp"
v-for="{ cmp, name: cmpName, id, props: cmpProps } in components"
:key="`${cmpName}-${id}`"
v-bind="cmpProps"
/>
</template>
<slot v-else :components="components" />
</template>