| 1 |
/** |
| 2 |
* WordPress Dependencies |
| 3 |
*/ |
| 4 |
import classnames from "classnames"; |
| 5 |
import { __ } from "@wordpress/i18n"; |
| 6 |
import { Button } from "@wordpress/components"; |
| 7 |
import { map, isEmpty, debounce } from "lodash"; |
| 8 |
import { useState, useEffect } from "react"; |
| 9 |
/** |
| 10 |
* Custom Imports |
| 11 |
*/ |
| 12 |
import { tablebergIcons } from "./icons"; |
| 13 |
import type { IconsLibraryProps, IconSvgData } from "./"; |
| 14 |
|
| 15 |
export interface IconsLibraryContentProps extends IconsLibraryProps { |
| 16 |
search: string; |
| 17 |
subCategoryFilter: string; |
| 18 |
mainCategoryFilter: string; |
| 19 |
} |
| 20 |
|
| 21 |
function extractSvgData(icon: JSX.Element): IconSvgData { |
| 22 |
const props = icon.props as { |
| 23 |
viewBox?: string; |
| 24 |
children?: { props?: { d?: string } }; |
| 25 |
}; |
| 26 |
return { |
| 27 |
viewBox: props.viewBox ?? "0 0 24 24", |
| 28 |
path: props.children?.props?.d ?? "", |
| 29 |
}; |
| 30 |
} |
| 31 |
|
| 32 |
const debouncedSetValue = debounce((val, setVal) => { |
| 33 |
setVal(val); |
| 34 |
}, 500); |
| 35 |
function Content(props: IconsLibraryContentProps) { |
| 36 |
const [icons, setIcons] = useState([]); |
| 37 |
const [debouncedSearch, setDebouncedSearch] = useState(""); |
| 38 |
|
| 39 |
const { value, search, onSelect, subCategoryFilter, mainCategoryFilter } = |
| 40 |
props; |
| 41 |
|
| 42 |
const mergeIcons = (filteredIcons: any) => { |
| 43 |
let finalIcons = []; |
| 44 |
for (let i = 0; i < filteredIcons.length; i++) { |
| 45 |
finalIcons.push(...filteredIcons[i]); |
| 46 |
} |
| 47 |
return finalIcons; |
| 48 |
}; |
| 49 |
useEffect(() => { |
| 50 |
const iconObj = tablebergIcons.find( |
| 51 |
obj => obj.type === mainCategoryFilter |
| 52 |
); |
| 53 |
if (search.trim() === "") { |
| 54 |
const preparedIcons = iconObj?.icons.filter(icon => { |
| 55 |
return icon?.categories?.includes(subCategoryFilter); |
| 56 |
}); |
| 57 |
if (subCategoryFilter.includes("all-")) { |
| 58 |
setIcons(iconObj?.icons as any); |
| 59 |
} else { |
| 60 |
setIcons(preparedIcons as any); |
| 61 |
} |
| 62 |
} else { |
| 63 |
const preparedIcons = tablebergIcons.map(iconPack => { |
| 64 |
const iconPackIcons = iconPack?.icons.filter(icon => { |
| 65 |
return icon?.title |
| 66 |
.toLocaleLowerCase() |
| 67 |
.trim() |
| 68 |
?.includes(search.toLocaleLowerCase().trim()); |
| 69 |
}); |
| 70 |
return iconPackIcons; |
| 71 |
}); |
| 72 |
setIcons(mergeIcons(preparedIcons) as any); |
| 73 |
} |
| 74 |
}, [subCategoryFilter, mainCategoryFilter, debouncedSearch]); |
| 75 |
useEffect(() => { |
| 76 |
debouncedSetValue(search, setDebouncedSearch); |
| 77 |
}, [search]); |
| 78 |
|
| 79 |
const isNoResults = isEmpty(icons); |
| 80 |
|
| 81 |
return ( |
| 82 |
<div className="tableberg_icon_library_content_wrapper"> |
| 83 |
<div |
| 84 |
key={debouncedSearch} |
| 85 |
className={classnames("tableberg_icon_library_content", { |
| 86 |
"no-results": isNoResults, |
| 87 |
})} |
| 88 |
> |
| 89 |
{map(icons, (icon: any) => { |
| 90 |
return ( |
| 91 |
<Button |
| 92 |
key={icon?.name} |
| 93 |
className={`tableberg_icon_library_item`} |
| 94 |
onClick={() => |
| 95 |
onSelect({ |
| 96 |
iconName: icon.name, |
| 97 |
svg: extractSvgData(icon.icon), |
| 98 |
}) |
| 99 |
} |
| 100 |
isPressed={icon?.name === value} |
| 101 |
> |
| 102 |
<span className="tableberg_icon_list_item"> |
| 103 |
{icon.icon} |
| 104 |
</span> |
| 105 |
<span className="tableberg_list_item_title"> |
| 106 |
{icon?.title ?? icon?.name} |
| 107 |
</span> |
| 108 |
</Button> |
| 109 |
); |
| 110 |
})} |
| 111 |
{isNoResults && <p>{__("No icons found.", "tableberg")}</p>} |
| 112 |
</div> |
| 113 |
</div> |
| 114 |
); |
| 115 |
} |
| 116 |
|
| 117 |
export default Content; |
| 118 |
|