UNPKG

@grail-ui/svelte

Version:

[![NPM](https://img.shields.io/npm/v/@grail-ui/svelte)](https://www.npmjs.com/package/@grail-ui/svelte) [![minified](https://img.shields.io/bundlephobia/min/@grail-ui/svelte)](https://bundlephobia.com/package/@grail-ui/svelte) [![minified + zipped](https:

59 lines (58 loc) 1.73 kB
import { tick } from 'svelte'; import { writable } from 'svelte/store'; export const usePortal = (node, config) => { async function move() { const { target } = config; let targetEl; if (!target) { targetEl = document.body; } else if (typeof target === 'string') { targetEl = document.querySelector(target); if (targetEl === null) { await tick(); targetEl = document.querySelector(target); } if (targetEl === null) { throw new Error(`No element found matching CSS selector: "${target}"`); } } else if (target instanceof HTMLElement) { targetEl = target; } else { throw new TypeError(`Unknown portal target type: ${target === null ? 'null' : typeof target}. Allowed types: string (CSS selector) or HTMLElement.`); } targetEl.appendChild(node); } move(); return { update(newConfig) { config = { ...newConfig }; move(); }, destroy() { node.remove(); }, }; }; export const createPortal = (config = {}) => { const target = writable(config.target); const _usePortal = (node, _config) => { const action = usePortal(node, {}); const unsubscribe = target.subscribe(($target) => { action.update({ ...config, target: $target, ..._config }); }); return { ...action, destroy() { unsubscribe(); action.destroy(); }, }; }; return { target, usePortal: _usePortal, }; };