UNPKG

@highloop/feedback-internal

Version:

192 lines (153 loc) 5.13 kB
import outsideClick from '@varld/outside-click'; import { HighloopFeedbackCore, events } from '../core'; import type { IData, ITheme } from '../interfaces/data'; import type { IText } from '../interfaces/text'; import { getPopoverWrapper } from '../lib/getPopoverWrapper'; export type DialogWidget = ReturnType<typeof createDialogWidget>; export type DialogWidgetOpts = Parameters<typeof createDialogWidget>[1]; export type DialogPosition = 'top' | 'bottom' | 'center'; export let createDialogWidget = ( id: string, opts: { meta?: any; apiEndpoint?: string; theme?: ITheme; demo?: IData; text?: IText; expanded?: boolean; closeOnOutsideClick?: boolean; } & ( | { position?: 'center'; blanket?: boolean; } | { position?: 'top' | 'bottom'; } ) = {} ) => { if (typeof window == 'undefined') return; let position = opts.position || 'bottom'; // Setup wrapper element let wrapper = getPopoverWrapper(); let root = document.createElement('div'); root.style.zIndex = '99998'; root.style.opacity = '0'; root.style.left = '0px'; root.style.right = '0px'; root.style.position = 'fixed'; root.style.pointerEvents = 'none'; root.style.transition = 'all 0.3s'; let inner = document.createElement('div'); inner.style.width = 'min(400px, 100vw)'; inner.style.height = 'fit-content'; inner.style.margin = '0px auto'; inner.style.overflow = 'hidden'; inner.style.boxShadow = '0 8px 30px rgba(0,0,0,0.12)'; inner.style.pointerEvents = 'none'; inner.style.transition = 'all 0.3s'; inner.style.zIndex = '99999'; if (position == 'bottom') { root.style.bottom = '-30px'; inner.style.borderTopLeftRadius = '14px'; inner.style.borderTopRightRadius = '14px'; } if (position == 'top') { root.style.top = '-30px'; inner.style.borderBottomLeftRadius = '14px'; inner.style.borderBottomRightRadius = '14px'; } if (opts.position == 'center') { root.style.top = '0px'; root.style.bottom = '0px'; root.style.display = 'flex'; root.style.justifyContent = 'center'; root.style.alignItems = 'center'; inner.style.borderRadius = '14px'; inner.style.transform = 'translateY(20px)'; if (opts.blanket) { root.style.background = 'rgba(0, 0, 0, 0.4)'; } } wrapper.appendChild(root); root.appendChild(inner); // Setup widget instance let instance = new HighloopFeedbackCore(id, { ...opts, closable: true, root: inner }); let hideTo: number; let open = () => { if (instance.isMounted) return; clearTimeout(hideTo); instance.render(); root.style.opacity = '1'; inner.style.pointerEvents = 'all'; if (position == 'bottom') { root.style.bottom = '0px'; } if (position == 'top') { root.style.top = '0px'; } if (opts.position == 'center') { inner.style.transform = 'translateY(0px)'; if (opts.blanket) { root.style.pointerEvents = 'all'; } } }; let close = () => { if (!instance.isMounted) return; root.style.opacity = '0'; inner.style.pointerEvents = 'none'; if (position == 'bottom') { root.style.bottom = '-30px'; } if (position == 'top') { root.style.top = '-30px'; } if (opts.position == 'center') { inner.style.transform = 'translateY(20px)'; if (opts.blanket) { root.style.pointerEvents = 'none'; } } hideTo = setTimeout(() => instance.destroy(), 300) as unknown as number; }; let toggle = () => (instance.isMounted ? close() : open()); let unregisterClose = instance.on(events.CLOSE, () => close()); let unregisterSubmit = instance.on(events.SUBMIT, () => setTimeout(() => close(), 3000)); let unregisterOutsideClick = opts.closeOnOutsideClick ? outsideClick([root], () => close()) : undefined; let escapeHandler = (e: KeyboardEvent) => { if (e.key === 'Escape') close(); }; document.addEventListener('keyup', escapeHandler); let innerClick = (e: MouseEvent) => e.stopPropagation(); inner.addEventListener('click', innerClick); if (opts.position == 'center' && opts.blanket) { root.addEventListener('click', close); } return { destroy: () => { document.removeEventListener('keyup', escapeHandler); if (opts.position == 'center' && opts.blanket) { root.removeEventListener('click', close); } unregisterClose(); unregisterSubmit(); if (unregisterOutsideClick) unregisterOutsideClick(); instance.destroy(); }, instance: instance, open, close, toggle, setMeta: (meta: any) => instance.setMeta(meta), setTheme: (theme: ITheme) => instance.setTheme(theme), on: <T>(type: string, handler: (d: T) => unknown) => instance.on(type, handler), once: <T>(type: string, handler: (d: T) => unknown) => instance.once(type, handler) }; };