Spaces:
Running
Running
import { useEffect, useRef, useState } from "react"; | |
import { FormattedMessage, useIntl } from "react-intl"; | |
import { Icons } from "@/components/svg/icons"; | |
import { IconItem } from "@/types/editor"; | |
import { Input } from "@/components/input"; | |
import { | |
useResults, | |
useSingleSearch, | |
} from "@/components/search/hooks/useSearch"; | |
import { ListItem } from "@/components/editor-icons/comps/list/list-item"; | |
import { Empty } from "@/components/empty"; | |
import { ArrowLeftIcon } from "@heroicons/react/solid"; | |
import { ArrowRightIcon } from "@heroicons/react/solid"; | |
import { useClickAway } from "react-use"; | |
import classNames from "classnames"; | |
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; | |
import { faTrash } from "@fortawesome/free-solid-svg-icons"; | |
export const IconPicker = ({ | |
icon, | |
onSelect, | |
children, | |
}: { | |
onSelect: (i?: string) => void; | |
icon?: string; | |
children?: React.ReactNode; | |
}) => { | |
const [open, setOpen] = useState(false); | |
const svgRef = useRef<any>(null); | |
const container = useRef<HTMLDivElement>(null); | |
const intl = useIntl(); | |
const [viewBox, setViewBox] = useState<string>("0 0 24 24"); | |
const [search, setSearch] = useState<any>(""); | |
useSingleSearch(search); | |
const { results, page, maxPage, totalItems, setPage } = useResults(21); | |
const findIcon = Icons?.find((i: IconItem) => icon === i.name); | |
const IconComponent = findIcon?.component as any; | |
useEffect(() => { | |
return setViewBox( | |
svgRef?.current?.getAttribute("viewBox") ?? "0 0 200 200" | |
); | |
}, [icon]); | |
useClickAway(container, () => setOpen(false)); | |
return ( | |
<div ref={container} className="relative"> | |
<div | |
className="border border-dark-300 rounded-lg w-10 h-10 flex items-center justify-center hover:bg-green hover:bg-opacity-40 hover:border-green cursor-pointer" | |
onClick={() => setOpen(!open)} | |
> | |
<svg | |
width={16} | |
height={16} | |
fill="white" | |
viewBox={viewBox} | |
style={{ minWidth: 16, minHeight: 16 }} | |
> | |
<IconComponent ref={svgRef as any} /> | |
</svg> | |
</div> | |
<div | |
className={classNames( | |
"w-full fixed lg:absolute lg:w-[420px] p-6 min-h-[350px] rounded-lg bg-dark-default left-0 bottom-0 lg:left-12 lg:top-0 transform lg:-translate-y-1/2 shadow-xl border-2 border-dark-200 border-opacity-20 z-[11]", | |
{ | |
"opacity-0 pointer-events-none": !open, | |
} | |
)} | |
> | |
<Input | |
value={search} | |
type="text" | |
placeholder="Search for an icon" | |
className="bg-dark-600 rounded p-3 text-sm text-white placeholder-dark-200" | |
onChange={setSearch as any} | |
/> | |
<div className="flex jlg:items-start flex-wrap justify-start mt-3 gap-2 lg:gap-3"> | |
{results?.map((result: any, key: number) => ( | |
<ListItem | |
key={key} | |
icon={result} | |
fill={result?.defaultColor} | |
onSelect={(icon) => { | |
// if (icon?.isPremium && !user?.id) return setOpen(true); | |
// onSelect(icon); | |
onSelect(icon.name); | |
}} | |
/> | |
))} | |
{results?.length === 0 && ( | |
<Empty | |
title="Clyde is disappointed..." | |
description="...there is no icon that matches your search :(" | |
action={() => { | |
// if (!user?.id) return login(); | |
// send to api a request; | |
}} | |
button="Ask for a new Icon" | |
/> | |
)} | |
</div> | |
{results?.length > 0 && ( | |
<div className="flex items-center justify-between gap-4 mt-10"> | |
<button | |
disabled={page <= 1} | |
className="w-full lg:w-auto group border-2 border-darkGreen bg-darkGreen text-white font-medium tracking-wide px-3.5 py-2 text-sm flex items-center justify-center gap-2 rounded-lg hover:bg-opacity-90 hover:border-opacity-0 disabled:bg-dark-100 disabled:bg-opacity-20 disabled:border-dark-100 disabled:border-opacity-0 disabled:text-dark-200 disabled:cursor-not-allowed" | |
onClick={() => setPage(page - 1)} | |
> | |
<ArrowLeftIcon className="w-4 text-white group-disabled:text-dark-200" /> | |
</button> | |
<div className="hidden items-center justify-center gap-2 lg:flex"> | |
<p className="text-dark-100 font-medium text-sm"> | |
<FormattedMessage | |
id="iconsEditor.editor.listIcons.pagination.total" | |
values={{ | |
page: () => page, | |
maxPage: () => maxPage, | |
}} | |
/> | |
</p> | |
</div> | |
<button | |
disabled={page === maxPage} | |
className="w-full lg:w-auto group border-2 border-darkGreen bg-darkGreen text-white font-medium tracking-wide px-3.5 py-2 text-sm flex items-center justify-center gap-2 rounded-lg hover:bg-opacity-90 hover:border-opacity-0 disabled:bg-dark-100 disabled:bg-opacity-20 disabled:border-dark-100 disabled:border-opacity-0 disabled:text-dark-200 disabled:cursor-not-allowed" | |
onClick={page >= maxPage ? () => {} : () => setPage(page + 1)} | |
> | |
<ArrowRightIcon className="w-4 text-white group-disabled:text-dark-200" /> | |
</button> | |
</div> | |
)} | |
</div> | |
</div> | |
); | |
}; | |