From b886150147afbde882003fb5dc710a5975b633cd Mon Sep 17 00:00:00 2001 From: Neil Richter Date: Fri, 7 Jun 2024 17:31:05 +0200 Subject: [PATCH] feat(Slideover): open programmatically (#122) --- .../SlideoverProgrammaticExample.vue | 18 +++++ playground/pages/slideover.vue | 14 ++++ src/module.ts | 3 + src/runtime/components/App.vue | 3 +- src/runtime/components/SlideoverProvider.vue | 12 ++++ src/runtime/composables/useSlideover.ts | 71 +++++++++++++++++++ src/runtime/plugins/slideover.ts | 12 ++++ 7 files changed, 132 insertions(+), 1 deletion(-) create mode 100644 playground/components/SlideoverProgrammaticExample.vue create mode 100644 src/runtime/components/SlideoverProvider.vue create mode 100644 src/runtime/composables/useSlideover.ts create mode 100644 src/runtime/plugins/slideover.ts diff --git a/playground/components/SlideoverProgrammaticExample.vue b/playground/components/SlideoverProgrammaticExample.vue new file mode 100644 index 00000000..c087f7e6 --- /dev/null +++ b/playground/components/SlideoverProgrammaticExample.vue @@ -0,0 +1,18 @@ + + + diff --git a/playground/pages/slideover.vue b/playground/pages/slideover.vue index 1f26011c..54e32439 100644 --- a/playground/pages/slideover.vue +++ b/playground/pages/slideover.vue @@ -1,5 +1,17 @@ + + diff --git a/src/module.ts b/src/module.ts index c5773c5c..13c930b3 100644 --- a/src/module.ts +++ b/src/module.ts @@ -68,6 +68,9 @@ export default defineNuxtModule({ addPlugin({ src: resolve('./runtime/plugins/modal') }) + addPlugin({ + src: resolve('./runtime/plugins/slideover') + }) addComponentsDir({ path: resolve('./runtime/components'), diff --git a/src/runtime/components/App.vue b/src/runtime/components/App.vue index 2010e0bd..28684c5c 100644 --- a/src/runtime/components/App.vue +++ b/src/runtime/components/App.vue @@ -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(), { useId: () => useId() @@ -33,5 +33,6 @@ const toasterProps = toRef(() => props.toaster) + diff --git a/src/runtime/components/SlideoverProvider.vue b/src/runtime/components/SlideoverProvider.vue new file mode 100644 index 00000000..7dd54445 --- /dev/null +++ b/src/runtime/components/SlideoverProvider.vue @@ -0,0 +1,12 @@ + + + diff --git a/src/runtime/composables/useSlideover.ts b/src/runtime/composables/useSlideover.ts new file mode 100644 index 00000000..731784cd --- /dev/null +++ b/src/runtime/composables/useSlideover.ts @@ -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> = Symbol('nuxt-ui.slideover') + +function _useSlideover() { + const slideoverState = inject(slideoverInjectionKey) + + const isOpen = ref(false) + + function open(component: T, props?: SlideoverProps & ComponentProps) { + 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>(props: Partial>) { + if (!slideoverState) return + + slideoverState.value = { + ...slideoverState.value, + props: { + ...slideoverState.value.props, + ...props + } + } + } + + return { + open, + close, + reset, + patch, + isOpen + } +} + +export const useSlideover = createSharedComposable(_useSlideover) diff --git a/src/runtime/plugins/slideover.ts b/src/runtime/plugins/slideover.ts new file mode 100644 index 00000000..f24d1d9d --- /dev/null +++ b/src/runtime/plugins/slideover.ts @@ -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({ + component: 'div', + props: {} + }) + + nuxtApp.vueApp.provide(slideoverInjectionKey, slideoverState) +})