icon.tsx (5933B)
1 import * as React from "react"; 2 import { Button, ChevronDownIcon, classNames, wrapFieldsWithMeta } from "tinacms"; 3 import { Icon, IconOptions } from "../../components/util/icon"; 4 import {BiChevronRight} from "react-icons/bi" 5 import {GoCircleSlash} from "react-icons/go" 6 import { Popover, Transition } from "@headlessui/react"; 7 8 const parseIconName = (name: string) => { 9 const splitName = name.split(/(?=[A-Z])/); 10 if (splitName.length > 1) { 11 return splitName.slice(1).join(" "); 12 } else { 13 return name; 14 } 15 }; 16 17 export const IconPickerInput = wrapFieldsWithMeta(({ input }) => { 18 const [filter, setFilter] = React.useState(""); 19 const filteredBlocks = React.useMemo(() => { 20 return Object.keys(IconOptions).filter((name) => { 21 return name.toLowerCase().includes(filter.toLowerCase()); 22 }); 23 }, [filter]); 24 25 const inputLabel = Object.keys(IconOptions).includes(input.value) 26 ? parseIconName(input.value) 27 : "Select Icon"; 28 const InputIcon = IconOptions[input.value] ? IconOptions[input.value] : null; 29 30 return ( 31 <div className="relative z-[1000]"> 32 <input type="text" id={input.name} className="hidden" {...input} /> 33 <Popover> 34 {({ open }) => ( 35 <> 36 <Popover.Button> 37 <Button 38 className={`text-sm h-11 px-4 ${InputIcon ? "h-11" : "h-10"}`} 39 size="custom" 40 rounded="full" 41 variant={open ? "secondary" : "white"} 42 > 43 {InputIcon && ( 44 <InputIcon className="w-7 mr-1 h-auto fill-current text-blue-500" /> 45 )} 46 {inputLabel} 47 {!InputIcon && ( 48 <BiChevronRight className="w-5 h-auto fill-current opacity-70 ml-1" /> 49 )} 50 </Button> 51 </Popover.Button> 52 <div 53 className="absolute w-full min-w-[192px] max-w-2xl -bottom-2 left-0 translate-y-full" 54 style={{ zIndex: 1000 }} 55 > 56 <Transition 57 enter="transition duration-150 ease-out" 58 enterFrom="transform opacity-0 -translate-y-2" 59 enterTo="transform opacity-100 translate-y-0" 60 leave="transition duration-75 ease-in" 61 leaveFrom="transform opacity-100 translate-y-0" 62 leaveTo="transform opacity-0 -translate-y-2" 63 > 64 <Popover.Panel className="relative overflow-hidden rounded-lg shadow-lg bg-white border border-gray-150 z-50"> 65 {({ close }) => ( 66 <div className="max-h-[24rem] flex flex-col w-full h-full"> 67 <div className="bg-gray-50 p-2 border-b border-gray-100 z-10 shadow-sm"> 68 <input 69 type="text" 70 className="bg-white text-sm rounded-sm border border-gray-100 shadow-inner py-1.5 px-2.5 w-full block placeholder-gray-200" 71 onClick={(event: any) => { 72 event.stopPropagation(); 73 event.preventDefault(); 74 }} 75 value={filter} 76 onChange={(event: any) => { 77 setFilter(event.target.value); 78 }} 79 placeholder="Filter..." 80 /> 81 </div> 82 {filteredBlocks.length === 0 && ( 83 <span className="relative text-center text-xs px-2 py-3 text-gray-300 bg-gray-50 italic"> 84 No matches found 85 </span> 86 )} 87 {filteredBlocks.length > 0 && ( 88 <div className="w-full grid grid-cols-6 auto-rows-auto p-2 overflow-y-auto"> 89 <button 90 className="relative rounded-lg text-center text-xs py-2 px-3 flex-1 outline-none transition-all ease-out duration-150 hover:text-blue-500 focus:text-blue-500 focus:bg-gray-50 hover:bg-gray-50" 91 key={"clear-input"} 92 onClick={() => { 93 input.onChange(""); 94 setFilter(""); 95 close(); 96 }} 97 > 98 <GoCircleSlash className="w-6 h-auto text-gray-200" /> 99 </button> 100 {filteredBlocks.map((name) => { 101 return ( 102 <button 103 className="relative flex items-center justify-center rounded-lg text-center text-xs py-2 px-3 flex-1 outline-none transition-all ease-out duration-150 hover:text-blue-500 focus:text-blue-500 focus:bg-gray-50 hover:bg-gray-50" 104 key={name} 105 onClick={() => { 106 input.onChange(name); 107 setFilter(""); 108 close(); 109 }} 110 > 111 <Icon 112 data={{ 113 name: name, 114 size: "custom", 115 color: "blue", 116 }} 117 className="w-7 h-auto" 118 /> 119 </button> 120 ); 121 })} 122 </div> 123 )} 124 </div> 125 )} 126 </Popover.Panel> 127 </Transition> 128 </div> 129 </> 130 )} 131 </Popover> 132 </div> 133 ); 134 });