TaxonomySection.js (9531B)
1 import { PanelBody, PanelRow } from '@wordpress/components' 2 import classNames from 'classnames' 3 import { useTemplatesStore } from '../state/Templates' 4 import { __ } from '@wordpress/i18n' 5 import { 6 useState, useEffect, useRef, useCallback, 7 } from '@wordpress/element' 8 import { useTaxonomyStore } from '../state/Taxonomies' 9 10 export default function TaxonomySection({ taxonomy: [title, data] }) { 11 const updateTaxonomies = useTemplatesStore(state => state.updateTaxonomies) 12 const resetTaxonomy = useTemplatesStore(state => state.resetTaxonomy) 13 const searchParams = useTemplatesStore(state => state.searchParams) 14 const openedTaxonomies = useTaxonomyStore(state => state.openedTaxonomies) 15 const toggleOpenedTaxonomy = useTaxonomyStore(state => state.toggleOpenedTaxonomy) 16 const [pageTwoTerms, setPageTwoTerms] = useState({}) 17 const [taxListHeight, setTaxListHeight] = useState({}) 18 const pageTwo = useRef() 19 const pageOneFocus = useRef() 20 const pageTwoFocus = useRef() 21 const firstUpdate = useRef(true) 22 23 // This will check whether the term is current (either child or top level/has no child) 24 // And then it will search children so the parent is also marked as selected 25 const isCurrentTax = (tax) => searchParams?.taxonomies[title] === tax.term 26 || tax.children?.filter((t) => { 27 return t.term === searchParams?.taxonomies[title] 28 }).length > 0 29 30 // Todo: memo this 31 const isAvailableOnCurrentType = useCallback((tax) => { 32 if (Object.prototype.hasOwnProperty.call(tax, 'children')) { 33 return tax.children.filter((t) => t?.type.includes(searchParams.type)).length 34 } 35 return tax?.type?.includes(searchParams.type) 36 }, [searchParams.type]) 37 38 useEffect(() => { 39 if (firstUpdate.current) { 40 firstUpdate.current = false 41 return 42 } 43 setPageTwoTerms({}) 44 }, [searchParams.type]) 45 46 useEffect(() => { 47 if (Object.keys(pageTwoTerms).length) { 48 setTimeout(() => { 49 requestAnimationFrame(() => { 50 setTaxListHeight(pageTwo.current.clientHeight) 51 pageTwoFocus.current.focus() 52 }) 53 }, 200) 54 return 55 } 56 setTaxListHeight('auto') 57 }, [pageTwoTerms]) 58 59 useEffect(() => { 60 const notSupported = !Object.values(data).filter((tax) => isAvailableOnCurrentType(tax)).length 61 // Reset taxonomies that aren't supported on a type 62 notSupported && resetTaxonomy(title) 63 }, [resetTaxonomy, title, isAvailableOnCurrentType, data]) 64 65 // Return early if 1. No data or 2. Children don't match this type 66 if (!Object.keys(data).length || !Object.values(data).filter((tax) => isAvailableOnCurrentType(tax)).length) { 67 return '' 68 } 69 70 const theTitle = title.replace('tax_', '').replace(/_/g , ' ').replace(/\b\w/g, l => l.toUpperCase()) 71 return <PanelBody 72 title={theTitle} 73 initialOpen={openedTaxonomies.includes(title)} 74 onToggle={(value) => toggleOpenedTaxonomy(title, value)}> 75 <PanelRow> 76 <div className="overflow-hidden w-full relative" style={{ 77 height: taxListHeight, 78 }}> 79 <ul className={classNames('p-1 m-0 w-full transform transition duration-200', { 80 '-translate-x-full': Object.keys(pageTwoTerms).length, 81 })}> 82 <li className="m-0"> 83 <button 84 type="button" 85 className="text-left cursor-pointer w-full flex justify-between items-center py-1.5 m-0 leading-none hover:text-wp-theme-500 bg-transparent transition duration-200 button-focus" 86 ref={pageOneFocus} 87 onClick={() => { 88 updateTaxonomies({ 89 [title]: searchParams.type === 'pattern' && title === 'tax_categories' 90 ? 'Default' 91 : '', 92 }) 93 }}> 94 <span className={classNames({ 95 'text-wp-theme-500': (!searchParams.taxonomies[title]?.length || searchParams?.taxonomies[title] === 'Default'), 96 })}> 97 {searchParams.type === 'pattern' && title === 'tax_categories' 98 ? __('Default', 'extendify-sdk') 99 : __('All', 'extendify-sdk')} 100 </span> 101 </button> 102 </li> 103 {Object.values(data) 104 .filter((tax) => isAvailableOnCurrentType(tax)) 105 .sort((prev, next) => prev.term.localeCompare(next.term)) 106 .map((tax) => 107 <li className="m-0 w-full" key={tax.term}> 108 <button 109 type="button" 110 className="text-left cursor-pointer w-full flex justify-between items-center py-1.5 m-0 leading-none bg-transparent hover:text-wp-theme-500 transition duration-200 button-focus" 111 onClick={() => { 112 if (Object.prototype.hasOwnProperty.call(tax, 'children')) { 113 setPageTwoTerms(tax) 114 return 115 } 116 updateTaxonomies({ 117 [title]: tax.term, 118 }) 119 }}> 120 <span className={classNames({ 121 'text-wp-theme-500': isCurrentTax(tax), 122 })}> 123 {tax.term} 124 </span> 125 {Object.prototype.hasOwnProperty.call(tax, 'children') && <span className="text-black"> 126 <svg width="8" height="14" viewBox="0 0 8 14" className="stroke-current" fill="none" xmlns="http://www.w3.org/2000/svg"> 127 <path d="M1 12.5L6 6.99998L1 1.5" strokeWidth="1.5"/> 128 </svg> 129 </span>} 130 </button> 131 </li>) 132 } 133 </ul> 134 <ul ref={pageTwo} className={classNames('p-1 m-0 w-full transform transition duration-200 absolute top-0 right-0', { 135 'translate-x-full': !Object.keys(pageTwoTerms).length, 136 })}> 137 {Object.values(pageTwoTerms).length > 0 && <li className="m-0"> 138 <button 139 type="button" 140 className="text-left cursor-pointer font-bold flex space-x-4 items-center py-2 pr-4 m-0leading-none hover:text-wp-theme-500 bg-transparent transition duration-200 button-focus" 141 ref={pageTwoFocus} 142 onClick={() => { 143 setPageTwoTerms({}) 144 pageOneFocus.current.focus() 145 }}> 146 <svg className="stroke-current transform rotate-180" width="8" height="14" viewBox="0 0 8 14" fill="none" xmlns="http://www.w3.org/2000/svg"> 147 <path d="M1 12.5L6 6.99998L1 1.5" strokeWidth="1.5"/> 148 </svg> 149 <span>{pageTwoTerms.term}</span> 150 </button> 151 </li> } 152 {Object.values(pageTwoTerms).length 153 && Object.values(pageTwoTerms.children) 154 .filter((tax) => isAvailableOnCurrentType(tax)) 155 .sort((prev, next) => prev.term.localeCompare(next.term)) 156 .map((childTax) => 157 <li className="m-0 pl-6 w-full flex justify-between items-center" key={childTax.term}> 158 <button 159 type="button" 160 className="text-left cursor-pointer w-full flex justify-between items-center py-1.5 m-0 leading-none bg-transparent hover:text-wp-theme-500 transition duration-200 button-focus" 161 onClick={() => { 162 updateTaxonomies({ 163 [title]: childTax.term, 164 }) 165 }}> 166 <span className={classNames({ 167 'text-wp-theme-500': isCurrentTax(childTax), 168 })}> 169 {childTax.term} 170 </span> 171 </button> 172 </li>) 173 } 174 </ul> 175 </div> 176 </PanelRow> 177 </PanelBody> 178 }