UNPKG

@nextcloud/vue

Version:
1 lines 3.66 kB
{"version":3,"file":"index.mjs","sources":["../../../src/functions/dialog/index.ts"],"sourcesContent":["/**\n * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport type { Component } from 'vue'\n\nimport { createApp } from 'vue'\n\ntype ComponentProps<T extends Component> = T extends new (...args: any) => { $props: infer P }\n\t? P\n\t: never\n\ntype DialogComponent<T extends Component> = 'onClose' extends keyof ComponentProps<T>\n\t? T\n\t: 'Please provide a Dialog Component that supports `@close` event'\n\n/**\n * Event payload array normalized to a single value when payload has only one argument,\n * including one optional argument\n */\ntype NormalizedPayload<T> = T extends []\n\t? void\n\t: T extends [infer F]\n\t\t? F\n\t\t: T extends { length: 0 | 1, 0?: infer F }\n\t\t\t? F | undefined\n\t\t\t: T\n\ntype ClosePayload<T> = T extends { onClose?: (...args: infer P) => any }\n\t? P\n\t: never\n\ntype SpawnDialogOptions = {\n\t/**\n\t * Container to mount the dialog to\n\t *\n\t * @default document.body\n\t */\n\tcontainer?: Element | string\n}\n\n/**\n * Spawn a single-use Vue dialog instance to get the result when it is closed\n *\n * @param dialog - Dialog component to spawn\n * @param props - Props to pass to the dialog instance\n * @param options - Spawning options\n * @return Promise resolved with the `close` event payload\n */\nexport function spawnDialog<\n\tC extends Component,\n\tE extends ClosePayload<ComponentProps<C>>,\n>(dialog: DialogComponent<C>, props: Partial<ComponentProps<C>> = {}, options: SpawnDialogOptions = {}): Promise<NormalizedPayload<E>> {\n\tlet { container } = options\n\n\t// For backwards compatibility try to use container from props\n\tif ('container' in props && typeof props.container === 'string') {\n\t\tcontainer ??= props.container\n\t}\n\n\t// Resolve container to an Element or fallback to document.body\n\tconst resolvedContainer = (typeof container === 'string' && document.querySelector(container)) || document.body\n\n\t// Create root container element for the dialog\n\tconst element = resolvedContainer.appendChild(document.createElement('div'))\n\n\treturn new Promise((resolve, reject) => {\n\t\tconst app = createApp(dialog as Component, {\n\t\t\t...props,\n\t\t\t// If dialog has no `container` prop passing a falsy value does nothing\n\t\t\t// Otherwise it is expected that `null` disables teleport and mounts dialog in place like NcDialog/NcModal\n\t\t\tcontainer: null,\n\t\t\tonClose(...rest: E) {\n\t\t\t\tconst payload = (rest.length > 1 ? rest : rest[0]) as NormalizedPayload<E>\n\n\t\t\t\tapp.unmount()\n\t\t\t\telement.remove()\n\t\t\t\tresolve(payload)\n\t\t\t},\n\t\t\t'onVue:unmounted': () => {\n\t\t\t\tapp.unmount()\n\t\t\t\telement.remove()\n\t\t\t\treject(new Error('Dialog was unmounted without close event'))\n\t\t\t},\n\t\t})\n\n\t\tapp.mount(element)\n\t})\n}\n"],"names":[],"mappings":";AAmDO,SAAS,YAGd,QAA4B,QAAoC,CAAA,GAAI,UAA8B,CAAA,GAAmC;AACtI,MAAI,EAAE,cAAc;AAGpB,MAAI,eAAe,SAAS,OAAO,MAAM,cAAc,UAAU;AAChE,kBAAc,MAAM;AAAA,EACrB;AAGA,QAAM,oBAAqB,OAAO,cAAc,YAAY,SAAS,cAAc,SAAS,KAAM,SAAS;AAG3G,QAAM,UAAU,kBAAkB,YAAY,SAAS,cAAc,KAAK,CAAC;AAE3E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACvC,UAAM,MAAM,UAAU,QAAqB;AAAA,MAC1C,GAAG;AAAA;AAAA;AAAA,MAGH,WAAW;AAAA,MACX,WAAW,MAAS;AACnB,cAAM,UAAW,KAAK,SAAS,IAAI,OAAO,KAAK,CAAC;AAEhD,YAAI,QAAA;AACJ,gBAAQ,OAAA;AACR,gBAAQ,OAAO;AAAA,MAChB;AAAA,MACA,mBAAmB,MAAM;AACxB,YAAI,QAAA;AACJ,gBAAQ,OAAA;AACR,eAAO,IAAI,MAAM,0CAA0C,CAAC;AAAA,MAC7D;AAAA,IAAA,CACA;AAED,QAAI,MAAM,OAAO;AAAA,EAClB,CAAC;AACF;"}