| 1 |
import { Dialog } from '@headlessui/react'; |
| 2 |
import { updateOption } from '@library/api/WPApi'; |
| 3 |
import { ModalContent } from '@library/components/ModalContent'; |
| 4 |
import { Sidebar } from '@library/components/sidebar/Sidebar'; |
| 5 |
import { Topbar } from '@library/components/topbar/Topbar'; |
| 6 |
import { useGlobalsStore } from '@library/state/global'; |
| 7 |
import { useSiteSettingsStore } from '@library/state/site'; |
| 8 |
import { useUserStore } from '@library/state/user'; |
| 9 |
import { insertBlocks } from '@library/util/insert'; |
| 10 |
import { useActivityStore } from '@shared/state/activity'; |
| 11 |
import { dispatch, select } from '@wordpress/data'; |
| 12 |
import { useEffect, useLayoutEffect, useRef } from '@wordpress/element'; |
| 13 |
import { __ } from '@wordpress/i18n'; |
| 14 |
import { motion } from 'framer-motion'; |
| 15 |
|
| 16 |
const isNewPage = window?.location?.pathname?.includes('post-new.php'); |
| 17 |
|
| 18 |
export const Modal = () => { |
| 19 |
const { incrementActivity } = useActivityStore(); |
| 20 |
const { open, setOpen } = useGlobalsStore(); |
| 21 |
const { updateUserOption, openOnNewPage } = useUserStore(); |
| 22 |
const { category, incrementImports } = useSiteSettingsStore(); |
| 23 |
const { createNotice } = dispatch('core/notices'); |
| 24 |
const once = useRef(false); |
| 25 |
|
| 26 |
const onClose = () => setOpen(false); |
| 27 |
const insertPattern = async (blocks) => { |
| 28 |
await insertBlocks(blocks); |
| 29 |
incrementImports(); |
| 30 |
onClose(); |
| 31 |
createNotice('info', __('Pattern added', 'extendify-local'), { |
| 32 |
isDismissible: true, |
| 33 |
type: 'snackbar', |
| 34 |
}); |
| 35 |
// update the general options to reflect the new pattern |
| 36 |
await updateOption('extendify_check_for_image_imports', true); |
| 37 |
}; |
| 38 |
|
| 39 |
useLayoutEffect(() => { |
| 40 |
if (open || once.current) return; |
| 41 |
once.current = true; |
| 42 |
if (openOnNewPage && isNewPage) { |
| 43 |
// Minimize HC if its open |
| 44 |
window.dispatchEvent(new CustomEvent('extendify-hc:minimize')); |
| 45 |
incrementActivity('library-auto-open'); |
| 46 |
setOpen(true); |
| 47 |
return; |
| 48 |
} |
| 49 |
const search = new URLSearchParams(window.location.search); |
| 50 |
if (search.has('ext-open')) { |
| 51 |
setOpen(true); |
| 52 |
incrementActivity('library-search-param-auto-open'); |
| 53 |
} |
| 54 |
}, [openOnNewPage, setOpen, incrementActivity, open]); |
| 55 |
|
| 56 |
useEffect(() => { |
| 57 |
const search = new URLSearchParams(window.location.search); |
| 58 |
|
| 59 |
if (search.has('ext-close')) { |
| 60 |
setOpen(false); |
| 61 |
search.delete('ext-close'); |
| 62 |
window.history.replaceState( |
| 63 |
{}, |
| 64 |
'', |
| 65 |
`${window.location.pathname}?${search.toString()}`, |
| 66 |
); |
| 67 |
} |
| 68 |
}, [setOpen, incrementActivity]); |
| 69 |
|
| 70 |
useEffect(() => { |
| 71 |
const handleOpen = () => setOpen(true); |
| 72 |
const handleClose = () => setOpen(false); |
| 73 |
window.addEventListener('extendify::open-library', handleOpen); |
| 74 |
window.addEventListener('extendify::close-library', handleClose); |
| 75 |
return () => { |
| 76 |
window.removeEventListener('extendify::open-library', handleOpen); |
| 77 |
window.removeEventListener('extendify::close-library', handleClose); |
| 78 |
}; |
| 79 |
}, [setOpen, open]); |
| 80 |
|
| 81 |
useEffect(() => { |
| 82 |
if (!open) return; |
| 83 |
const welcomeGuide = |
| 84 |
select('core/edit-post').isFeatureActive('welcomeGuide'); |
| 85 |
if (welcomeGuide) { |
| 86 |
dispatch('core/edit-post').toggleFeature('welcomeGuide'); |
| 87 |
} |
| 88 |
}, [open]); |
| 89 |
|
| 90 |
if (!open) return null; |
| 91 |
|
| 92 |
return ( |
| 93 |
<Dialog |
| 94 |
className="extendify-library extendify-library-modal" |
| 95 |
open={open} |
| 96 |
static |
| 97 |
onClose={() => undefined} |
| 98 |
> |
| 99 |
<div className="absolute mx-auto h-full w-full md:p-8 inset-0"> |
| 100 |
<div |
| 101 |
className="fixed inset-0 bg-black/30" |
| 102 |
style={{ backdropFilter: 'blur(2px)' }} |
| 103 |
aria-hidden="true" |
| 104 |
/> |
| 105 |
<motion.div |
| 106 |
key="library-modal" |
| 107 |
initial={{ y: 30, opacity: 0 }} |
| 108 |
animate={{ y: 0, opacity: 1 }} |
| 109 |
exit={{ y: 0, opacity: 0 }} |
| 110 |
transition={{ duration: 0.3 }} |
| 111 |
className="relative mx-auto h-full w-full max-w-[1600px] bg-white shadow-2xl sm:flex sm:overflow-hidden" |
| 112 |
> |
| 113 |
<Dialog.Title className="sr-only"> |
| 114 |
{__('Design Patterns', 'extendify-local')} |
| 115 |
</Dialog.Title> |
| 116 |
<Sidebar /> |
| 117 |
<div className="relative flex w-full flex-col bg-[#FAFAFA]"> |
| 118 |
<Topbar |
| 119 |
openOnNewPage={openOnNewPage} |
| 120 |
updateUserOption={updateUserOption} |
| 121 |
onClose={onClose} |
| 122 |
/> |
| 123 |
<div |
| 124 |
id="extendify-library-patterns-list" |
| 125 |
className="relative grow overflow-y-auto" |
| 126 |
> |
| 127 |
<ModalContent insertPattern={insertPattern} category={category} /> |
| 128 |
</div> |
| 129 |
</div> |
| 130 |
</motion.div> |
| 131 |
</div> |
| 132 |
</Dialog> |
| 133 |
); |
| 134 |
}; |
| 135 |
|