feat(Slideover): open programmatically (#122)

This commit is contained in:
Neil Richter
2024-06-07 17:31:05 +02:00
committed by GitHub
parent 20476f4b9a
commit b886150147
7 changed files with 132 additions and 1 deletions

View File

@@ -0,0 +1,18 @@
<script lang="ts" setup>
const slideover = useSlideover()
defineProps<{
count: number
}>()
</script>
<template>
<USlideover title="This slideover was opened programmatically">
<template #footer>
<div class="flex w-full justify-between">
<p>Count: {{ count }}</p>
<UButton color="gray" label="Close" @click="slideover.close()" />
</div>
</template>
</USlideover>
</template>

View File

@@ -1,5 +1,17 @@
<script setup lang="ts">
import { LazySlideoverProgrammaticExample } from '#components'
const open = ref(false)
const slideover = useSlideover()
const count = ref(0)
const openSlideover = () => {
count.value++
slideover.open(LazySlideoverProgrammaticExample, {
description: 'And you can even provide a description!',
count: count.value
})
}
</script>
<template>
@@ -105,5 +117,7 @@ const open = ref(false)
<Placeholder class="h-full w-full" />
</template>
</USlideover>
<UButton label="Open programmatically" color="white" @click="openSlideover" />
</div>
</template>

View File

@@ -68,6 +68,9 @@ export default defineNuxtModule<ModuleOptions>({
addPlugin({
src: resolve('./runtime/plugins/modal')
})
addPlugin({
src: resolve('./runtime/plugins/slideover')
})
addComponentsDir({
path: resolve('./runtime/components'),

View File

@@ -13,7 +13,7 @@ import { toRef } from 'vue'
import { ConfigProvider, TooltipProvider, useForwardProps } from 'radix-vue'
import { reactivePick } from '@vueuse/core'
import { useId } from '#imports'
import { UToaster, UModalProvider } from '#components'
import { UToaster, UModalProvider, USlideoverProvider } from '#components'
const props = withDefaults(defineProps<ProviderProps>(), {
useId: () => useId()
@@ -33,5 +33,6 @@ const toasterProps = toRef(() => props.toaster)
</TooltipProvider>
<UModalProvider />
<USlideoverProvider />
</ConfigProvider>
</template>

View File

@@ -0,0 +1,12 @@
<script lang="ts" setup>
import { inject } from 'vue'
import { slideoverInjectionKey, useSlideover } from '../composables/useSlideover'
const slideoverState = inject(slideoverInjectionKey)
const { isOpen } = useSlideover()
</script>
<template>
<component :is="slideoverState.component" v-if="slideoverState" v-bind="slideoverState.props" v-model:open="isOpen" />
</template>

View File

@@ -0,0 +1,71 @@
import { ref, inject } from 'vue'
import type { ShallowRef, Component, InjectionKey } from 'vue'
import { createSharedComposable } from '@vueuse/core'
import type { SlideoverProps } from '#ui/types'
import type { ComponentProps } from '#ui/types/component'
export interface SlideoverState {
component: Component | string
props: SlideoverProps
}
export const slideoverInjectionKey: InjectionKey<ShallowRef<SlideoverState>> = Symbol('nuxt-ui.slideover')
function _useSlideover() {
const slideoverState = inject(slideoverInjectionKey)
const isOpen = ref(false)
function open<T extends Component>(component: T, props?: SlideoverProps & ComponentProps<T>) {
if (!slideoverState) {
throw new Error('useSlideover() is called without provider')
}
slideoverState.value = {
component,
props: props ?? {}
}
isOpen.value = true
}
async function close() {
if (!slideoverState) return
isOpen.value = false
}
function reset() {
if (!slideoverState) return
slideoverState.value = {
component: 'div',
props: {}
}
}
/**
* Allows updating the slideover props
*/
function patch<T extends Component = Record<string, never>>(props: Partial<SlideoverState & ComponentProps<T>>) {
if (!slideoverState) return
slideoverState.value = {
...slideoverState.value,
props: {
...slideoverState.value.props,
...props
}
}
}
return {
open,
close,
reset,
patch,
isOpen
}
}
export const useSlideover = createSharedComposable(_useSlideover)

View File

@@ -0,0 +1,12 @@
import { shallowRef } from 'vue'
import { defineNuxtPlugin } from '#imports'
import { slideoverInjectionKey, type SlideoverState } from '../composables/useSlideover'
export default defineNuxtPlugin((nuxtApp) => {
const slideoverState = shallowRef<SlideoverState>({
component: 'div',
props: {}
})
nuxtApp.vueApp.provide(slideoverInjectionKey, slideoverState)
})