import { createElement, createRoot, render } from '@wordpress/element'; type SnackbarStatus = 'success' | 'error' | 'info' | 'warning'; type NoticesDeps = { wp: any; }; const NOTICE_STORE = 'core/notices'; const NOTICE_OFFSET_GAP_PX = 8; export const NOTICE_IDS = { editor: 'kayzart-editor', save: 'kayzart-save', tailwind: 'kayzart-tailwind', templateFallback: 'kayzart-template-fallback', media: 'kayzart-media', } as const; export const NOTICE_SUCCESS_DURATION_MS = 3000; export const NOTICE_ERROR_DURATION_MS = 5000; function syncNoticeOffset() { const toolbar = document.querySelector('.kayzart-toolbar') as HTMLElement | null; if (!toolbar) { return; } const base = toolbar.getBoundingClientRect().bottom + NOTICE_OFFSET_GAP_PX; const list = document.querySelector('.kayzart-noticeHost .components-snackbar-list') as HTMLElement | null; const noticeContainer = list?.querySelector('.components-snackbar-list__notices') as HTMLElement | null; const firstNotice = noticeContainer?.firstElementChild as HTMLElement | null; const noticeHeight = firstNotice?.getBoundingClientRect().height ?? 0; const offset = Math.max(0, Math.round(base + noticeHeight)); document.documentElement.style.setProperty('--kayzart-notice-offset-top', `${offset}px`); } function removeNoticeRaw(wp: any, id: string) { if (!wp?.data?.dispatch) { return; } wp.data.dispatch(NOTICE_STORE).removeNotice(id); window.setTimeout(() => { syncNoticeOffset(); }, 0); } export function createNotices(deps: NoticesDeps) { const { wp } = deps; const createSnackbar = ( status: SnackbarStatus, message: string, id?: string, autoDismissMs?: number ) => { if (!wp?.data?.dispatch) { return; } const options: Record = { type: 'snackbar', isDismissible: true, }; if (id) { options.id = id; } wp.data.dispatch(NOTICE_STORE).createNotice(status, message, options); window.setTimeout(() => { syncNoticeOffset(); }, 0); if (id && autoDismissMs) { window.setTimeout(() => { removeNoticeRaw(wp, id); }, autoDismissMs); } }; const removeNotice = (id: string) => { removeNoticeRaw(wp, id); }; const mountNotices = () => { if (!wp?.components?.SnackbarList || !wp?.data?.useSelect) { return; } if (document.querySelector('.kayzart-noticeHost')) { return; } const host = document.createElement('div'); host.className = 'kayzart-noticeHost'; document.body.append(host); const SnackbarList = wp.components.SnackbarList; const useSelect = wp.data.useSelect; const Notices = () => { const notices = useSelect((select: any) => select(NOTICE_STORE).getNotices(), []); const snackbarNotices = Array.isArray(notices) ? notices.filter((notice: any) => notice.type === 'snackbar') : []; return createElement(SnackbarList, { notices: snackbarNotices, onRemove: (id: string) => removeNotice(id), }); }; const root = typeof createRoot === 'function' ? createRoot(host) : null; const node = createElement(Notices); if (root) { root.render(node); } else { render(node, host); } window.setTimeout(() => { syncNoticeOffset(); }, 0); }; return { createSnackbar, removeNotice, mountNotices, syncNoticeOffset, }; }