fix(useOverlay): improve types and docs (#4012)

Co-authored-by: Benjamin Canac <canacb1@gmail.com>
This commit is contained in:
Eugen Istoc
2025-04-29 12:09:39 -04:00
committed by GitHub
parent 195773ec7d
commit 39e29fccf1
3 changed files with 21 additions and 16 deletions

View File

@@ -504,7 +504,7 @@ const count = ref(0)
</script> </script>
``` ```
Closing a modal is now done through the `close` event. The `modal.open` method now returns a promise that resolves to the result of the modal whenever the modal is close: Closing a modal is now done through the `close` event. The `modal.open` method now returns an instance that can be used to await for the result of the modal whenever the modal is closed:
```diff ```diff
<script setup lang="ts"> <script setup lang="ts">
@@ -523,10 +523,12 @@ import { ModalExampleComponent } from '#components'
- }) - })
- } - }
+ async function openModal() { + async function openModal() {
+ const result = await modal.open(ModalExampleComponent, { + const instance = modal.open(ModalExampleComponent, {
+ count: count.value + count: count.value
+ }) + })
+ +
+ const result = await instance.result
+
+ if (result) { + if (result) {
+ toast.add({ title: 'Success!' }) + toast.add({ title: 'Success!' })
+ } + }

View File

@@ -22,14 +22,14 @@ async function openModal() {
- The `useOverlay` composable is created using `createSharedComposable`, ensuring that the same overlay state is shared across your entire application. - The `useOverlay` composable is created using `createSharedComposable`, ensuring that the same overlay state is shared across your entire application.
::note ::note
In order to return a value from the overlay, the `overlay.open()` can be awaited. In order for this to work, however, the **overlay component must emit a `close` event**. See example below for details. In order to return a value from the overlay, the `overlay.open().instance.result` can be awaited. In order for this to work, however, the **overlay component must emit a `close` event**. See example below for details.
:: ::
## API ## API
### `create(component: T, options: OverlayOptions): OverlayInstance` ### `create(component: T, options: OverlayOptions): OverlayInstance`
Creates an overlay, and returns its instance Creates an overlay, and returns a factory instance
- Parameters: - Parameters:
- `component`: The overlay component - `component`: The overlay component
@@ -38,7 +38,7 @@ Creates an overlay, and returns its instance
- `props?: ComponentProps`: An optional object of props to pass to the rendered component. - `props?: ComponentProps`: An optional object of props to pass to the rendered component.
- `destroyOnClose?: boolean` Removes the overlay from memory when closed `default: false` - `destroyOnClose?: boolean` Removes the overlay from memory when closed `default: false`
### `open(id: symbol, props?: ComponentProps<T>): Promise<any>` ### `open(id: symbol, props?: ComponentProps<T>): OpenedOverlay<T>`
Opens the overlay using its `id` Opens the overlay using its `id`
@@ -75,7 +75,7 @@ In-memory list of overlays that were created
## Overlay Instance API ## Overlay Instance API
### `open(props?: ComponentProps<T>): Promise<any>` ### `open(props?: ComponentProps<T>): Promise<OpenedOverlay<T>>`
Opens the overlay Opens the overlay
@@ -138,7 +138,7 @@ const overlay = useOverlay()
// Create with default props // Create with default props
const modalA = overlay.create(ModalA, { title: 'Welcome' }) const modalA = overlay.create(ModalA, { title: 'Welcome' })
const modalB = overlay.create(modalB) const modalB = overlay.create(ModalB)
const slideoverA = overlay.create(SlideoverA) const slideoverA = overlay.create(SlideoverA)
@@ -149,7 +149,9 @@ const openModalA = () => {
const openModalB = async () => { const openModalB = async () => {
// Open modalB, and wait for its result // Open modalB, and wait for its result
const input = await modalB.open() const modalBInstance = modalB.open()
const input = await modalBInstance.result
// Pass the result from modalB to the slideover, and open it. // Pass the result from modalB to the slideover, and open it.
slideoverA.open({ input }) slideoverA.open({ input })

View File

@@ -21,12 +21,16 @@ interface ManagedOverlayOptionsPrivate<T extends Component> {
} }
export type Overlay = OverlayOptions<Component> & ManagedOverlayOptionsPrivate<Component> export type Overlay = OverlayOptions<Component> & ManagedOverlayOptionsPrivate<Component>
interface OverlayInstance<T extends Component> extends Omit<ManagedOverlayOptionsPrivate<T>, 'component'> { type OverlayInstance<T extends Component> = Omit<ManagedOverlayOptionsPrivate<T>, 'component'> & {
id: symbol id: symbol
result: Promise<CloseEventArgType<ComponentEmit<T>>> open: (props?: ComponentProps<T>) => OpenedOverlay<T>
open: (props?: ComponentProps<T>) => Omit<OverlayInstance<T>, 'open' | 'close' | 'patch' | 'modelValue' | 'resolvePromise'>
close: (value?: any) => void close: (value?: any) => void
patch: (props: Partial<ComponentProps<T>>) => void patch: (props: Partial<ComponentProps<T>>) => void
}
type OpenedOverlay<T extends Component> = Omit<OverlayInstance<T>, 'open' | 'close' | 'patch' | 'modelValue' | 'resolvePromise'> & {
result: Promise<CloseEventArgType<ComponentEmit<T>>>
} }
function _useOverlay() { function _useOverlay() {
@@ -48,14 +52,13 @@ function _useOverlay() {
return { return {
...options, ...options,
result: new Promise(() => {}),
open: <T extends Component>(props?: ComponentProps<T>) => open(options.id, props), open: <T extends Component>(props?: ComponentProps<T>) => open(options.id, props),
close: value => close(options.id, value), close: value => close(options.id, value),
patch: <T extends Component>(props: Partial<ComponentProps<T>>) => patch(options.id, props) patch: <T extends Component>(props: Partial<ComponentProps<T>>) => patch(options.id, props)
} }
} }
const open = <T extends Component>(id: symbol, props?: ComponentProps<T>) => { const open = <T extends Component>(id: symbol, props?: ComponentProps<T>): OpenedOverlay<T> => {
const overlay = getOverlay(id) const overlay = getOverlay(id)
// If props are provided, update the overlay's props // If props are provided, update the overlay's props
@@ -70,9 +73,7 @@ function _useOverlay() {
id, id,
isMounted: overlay.isMounted, isMounted: overlay.isMounted,
isOpen: overlay.isOpen, isOpen: overlay.isOpen,
result: new Promise<any>((resolve) => { result: new Promise<any>(resolve => overlay.resolvePromise = resolve)
overlay.resolvePromise = resolve
})
} }
} }