Linted the whole project with eslint
This commit was merged in pull request #3.
This commit is contained in:
501
tina/config.tsx
501
tina/config.tsx
@@ -3,320 +3,229 @@ import { contentBlockSchema } from "../components/blocks/content";
|
||||
import { featureBlockSchema } from "../components/blocks/features";
|
||||
import { heroBlockSchema } from "../components/blocks/hero";
|
||||
import { testimonialBlockSchema } from "../components/blocks/testimonial";
|
||||
import { ColorPickerInput } from "./fields/color";
|
||||
import {carouselBlockSchema} from "../components/blocks/carousel";
|
||||
import { carouselBlockSchema } from "../components/blocks/carousel";
|
||||
import { headerSchema } from "../components/layout/header";
|
||||
import { footerSchema } from "../components/layout/footer/footer";
|
||||
|
||||
const config = defineConfig({
|
||||
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID!,
|
||||
branch:
|
||||
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID!,
|
||||
branch:
|
||||
process.env.NEXT_PUBLIC_TINA_BRANCH! || // custom branch env override
|
||||
process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_REF! || // Vercel branch env
|
||||
process.env.HEAD!, // Netlify branch env
|
||||
token: process.env.TINA_TOKEN!,
|
||||
media: {
|
||||
token: process.env.TINA_TOKEN!,
|
||||
media: {
|
||||
// If you wanted cloudinary do this
|
||||
// loadCustomStore: async () => {
|
||||
// const pack = await import("next-tinacms-cloudinary");
|
||||
// return pack.TinaCloudCloudinaryMediaStore;
|
||||
// },
|
||||
// this is the config for the tina cloud media store
|
||||
tina: {
|
||||
publicFolder: "public",
|
||||
mediaRoot: "uploads",
|
||||
tina: {
|
||||
publicFolder: "public",
|
||||
mediaRoot: "uploads"
|
||||
}
|
||||
},
|
||||
},
|
||||
build: {
|
||||
publicFolder: "public", // The public asset folder for your framework
|
||||
outputFolder: "admin", // within the public folder
|
||||
},
|
||||
schema: {
|
||||
collections: [
|
||||
{
|
||||
label: "Blog Posts",
|
||||
name: "post",
|
||||
path: "content/posts",
|
||||
format: "mdx",
|
||||
ui: {
|
||||
router: ({ document }) => {
|
||||
return `/posts/${document._sys.filename}`;
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Title",
|
||||
name: "title",
|
||||
isTitle: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
name: "heroImg",
|
||||
label: "Hero Image",
|
||||
},
|
||||
{
|
||||
type: "rich-text",
|
||||
label: "Excerpt",
|
||||
name: "excerpt",
|
||||
},
|
||||
{
|
||||
type: "reference",
|
||||
label: "Author",
|
||||
name: "author",
|
||||
collections: ["author"],
|
||||
},
|
||||
{
|
||||
type: "datetime",
|
||||
label: "Posted Date",
|
||||
name: "date",
|
||||
ui: {
|
||||
dateFormat: "MMMM DD YYYY",
|
||||
timeFormat: "hh:mm A",
|
||||
build: {
|
||||
publicFolder: "public", // The public asset folder for your framework
|
||||
outputFolder: "admin" // within the public folder
|
||||
},
|
||||
schema: {
|
||||
collections: [
|
||||
{
|
||||
label: "Blog Posts",
|
||||
name: "post",
|
||||
path: "content/posts",
|
||||
format: "mdx",
|
||||
ui: {
|
||||
router: ({ document }) => {
|
||||
return `/posts/${ document._sys.filename }`;
|
||||
}
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Title",
|
||||
name: "title",
|
||||
isTitle: true,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
name: "heroImg",
|
||||
label: "Hero Image"
|
||||
},
|
||||
{
|
||||
type: "rich-text",
|
||||
label: "Excerpt",
|
||||
name: "excerpt"
|
||||
},
|
||||
{
|
||||
type: "reference",
|
||||
label: "Author",
|
||||
name: "author",
|
||||
collections: ["author"]
|
||||
},
|
||||
{
|
||||
type: "datetime",
|
||||
label: "Posted Date",
|
||||
name: "date",
|
||||
ui: {
|
||||
dateFormat: "MMMM DD YYYY",
|
||||
timeFormat: "hh:mm A"
|
||||
}
|
||||
},
|
||||
{
|
||||
type: "rich-text",
|
||||
label: "Body",
|
||||
name: "_body",
|
||||
templates: [
|
||||
{
|
||||
name: "DateTime",
|
||||
label: "Date & Time",
|
||||
inline: true,
|
||||
fields: [
|
||||
{
|
||||
name: "format",
|
||||
label: "Format",
|
||||
type: "string",
|
||||
options: ["utc", "iso", "local"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "BlockQuote",
|
||||
label: "Block Quote",
|
||||
fields: [
|
||||
{
|
||||
name: "children",
|
||||
label: "Quote",
|
||||
type: "rich-text"
|
||||
},
|
||||
{
|
||||
name: "authorName",
|
||||
label: "Author",
|
||||
type: "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "NewsletterSignup",
|
||||
label: "Newsletter Sign Up",
|
||||
fields: [
|
||||
{
|
||||
name: "children",
|
||||
label: "CTA",
|
||||
type: "rich-text"
|
||||
},
|
||||
{
|
||||
name: "placeholder",
|
||||
label: "Placeholder",
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
name: "buttonText",
|
||||
label: "Button Text",
|
||||
type: "string"
|
||||
},
|
||||
{
|
||||
name: "disclaimer",
|
||||
label: "Disclaimer",
|
||||
type: "rich-text"
|
||||
}
|
||||
],
|
||||
ui: {
|
||||
defaultItem: {
|
||||
placeholder: "Enter your email",
|
||||
buttonText: "Notify Me"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
isBody: true
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "rich-text",
|
||||
label: "Body",
|
||||
name: "_body",
|
||||
templates: [
|
||||
{
|
||||
name: "DateTime",
|
||||
label: "Date & Time",
|
||||
inline: true,
|
||||
fields: [
|
||||
{
|
||||
name: "format",
|
||||
label: "Format",
|
||||
type: "string",
|
||||
options: ["utc", "iso", "local"],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "BlockQuote",
|
||||
label: "Block Quote",
|
||||
fields: [
|
||||
{
|
||||
name: "children",
|
||||
label: "Quote",
|
||||
type: "rich-text",
|
||||
},
|
||||
{
|
||||
name: "authorName",
|
||||
label: "Author",
|
||||
type: "string",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "NewsletterSignup",
|
||||
label: "Newsletter Sign Up",
|
||||
fields: [
|
||||
{
|
||||
name: "children",
|
||||
label: "CTA",
|
||||
type: "rich-text",
|
||||
},
|
||||
{
|
||||
name: "placeholder",
|
||||
label: "Placeholder",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
name: "buttonText",
|
||||
label: "Button Text",
|
||||
type: "string",
|
||||
},
|
||||
{
|
||||
name: "disclaimer",
|
||||
label: "Disclaimer",
|
||||
type: "rich-text",
|
||||
},
|
||||
],
|
||||
{
|
||||
label: "Global",
|
||||
name: "global",
|
||||
path: "content/global",
|
||||
format: "json",
|
||||
ui: {
|
||||
defaultItem: {
|
||||
placeholder: "Enter your email",
|
||||
buttonText: "Notify Me",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
isBody: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Global",
|
||||
name: "global",
|
||||
path: "content/global",
|
||||
format: "json",
|
||||
ui: {
|
||||
global: true,
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "object",
|
||||
label: "Header",
|
||||
name: "header",
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Page Title",
|
||||
name: "pageTitle",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Title",
|
||||
name: "title",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Subtitle",
|
||||
name: "subtitle",
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
label: "Logo",
|
||||
name: "logoSrc"
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
label: "Nav Links",
|
||||
name: "nav",
|
||||
list: true,
|
||||
ui: {
|
||||
itemProps: (item) => {
|
||||
return { label: item?.label };
|
||||
},
|
||||
defaultItem: {
|
||||
href: "home",
|
||||
label: "Home",
|
||||
external: false
|
||||
},
|
||||
global: true
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Link",
|
||||
name: "href",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Label",
|
||||
name: "label",
|
||||
},
|
||||
{
|
||||
type: "boolean",
|
||||
label: "External",
|
||||
name: "external",
|
||||
}
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
label: "Footer",
|
||||
name: "footer",
|
||||
fields: [
|
||||
{
|
||||
type: "object",
|
||||
label: "Social Links",
|
||||
name: "social",
|
||||
headerSchema,
|
||||
footerSchema
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Authors",
|
||||
name: "author",
|
||||
path: "content/authors",
|
||||
format: "md",
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Facebook",
|
||||
name: "facebook",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Twitter",
|
||||
name: "twitter",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Instagram",
|
||||
name: "instagram",
|
||||
},
|
||||
{
|
||||
type: "string",
|
||||
label: "Github",
|
||||
name: "github",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Authors",
|
||||
name: "author",
|
||||
path: "content/authors",
|
||||
format: "md",
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Name",
|
||||
name: "name",
|
||||
isTitle: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
label: "Avatar",
|
||||
name: "avatar",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Pages",
|
||||
name: "page",
|
||||
path: "content/pages",
|
||||
ui: {
|
||||
router: ({ document }) => {
|
||||
if (document._sys.filename === "home") {
|
||||
return `/`;
|
||||
}
|
||||
if (document._sys.filename === "about") {
|
||||
return `/about`;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Title",
|
||||
name: "title",
|
||||
description:
|
||||
{
|
||||
type: "string",
|
||||
label: "Name",
|
||||
name: "name",
|
||||
isTitle: true,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: "image",
|
||||
label: "Avatar",
|
||||
name: "avatar"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: "Pages",
|
||||
name: "page",
|
||||
path: "content/pages",
|
||||
ui: {
|
||||
router: ({ document }) => {
|
||||
if (document._sys.filename === "home") {
|
||||
return "/";
|
||||
}
|
||||
if (document._sys.filename === "about") {
|
||||
return "/about";
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
type: "string",
|
||||
label: "Title",
|
||||
name: "title",
|
||||
description:
|
||||
"The title of the page. This is used to display the title in the CMS",
|
||||
isTitle: true,
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
list: true,
|
||||
name: "blocks",
|
||||
label: "Sections",
|
||||
ui: {
|
||||
visualSelector: true,
|
||||
},
|
||||
templates: [
|
||||
heroBlockSchema,
|
||||
// @ts-ignore
|
||||
featureBlockSchema,
|
||||
contentBlockSchema,
|
||||
testimonialBlockSchema,
|
||||
// @ts-ignore
|
||||
carouselBlockSchema
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
isTitle: true,
|
||||
required: true
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
list: true,
|
||||
name: "blocks",
|
||||
label: "Sections",
|
||||
ui: {
|
||||
visualSelector: true
|
||||
},
|
||||
templates: [
|
||||
heroBlockSchema,
|
||||
// @ts-ignore
|
||||
featureBlockSchema,
|
||||
contentBlockSchema,
|
||||
testimonialBlockSchema,
|
||||
// @ts-ignore
|
||||
carouselBlockSchema
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -2,51 +2,51 @@ import * as React from "react";
|
||||
import { wrapFieldsWithMeta } from "tinacms";
|
||||
|
||||
export const colorOptions = [
|
||||
"blue",
|
||||
"teal",
|
||||
"green",
|
||||
"yellow",
|
||||
"orange",
|
||||
"red",
|
||||
"pink",
|
||||
"purple",
|
||||
"white",
|
||||
"blue",
|
||||
"teal",
|
||||
"green",
|
||||
"yellow",
|
||||
"orange",
|
||||
"red",
|
||||
"pink",
|
||||
"purple",
|
||||
"white"
|
||||
];
|
||||
|
||||
export const ColorPickerInput = wrapFieldsWithMeta(({ input }) => {
|
||||
const inputClasses = {
|
||||
blue: "bg-blue-500 border-blue-600",
|
||||
teal: "bg-teal-500 border-teal-600",
|
||||
green: "bg-green-500 border-green-600",
|
||||
yellow: "bg-yellow-500 border-yellow-600",
|
||||
orange: "bg-orange-500 border-orange-600",
|
||||
red: "bg-red-500 border-red-600",
|
||||
pink: "bg-pink-500 border-pink-600",
|
||||
purple: "bg-purple-500 border-purple-600",
|
||||
white: "bg-white border-gray-150",
|
||||
};
|
||||
const inputClasses = {
|
||||
blue: "bg-blue-500 border-blue-600",
|
||||
teal: "bg-teal-500 border-teal-600",
|
||||
green: "bg-green-500 border-green-600",
|
||||
yellow: "bg-yellow-500 border-yellow-600",
|
||||
orange: "bg-orange-500 border-orange-600",
|
||||
red: "bg-red-500 border-red-600",
|
||||
pink: "bg-pink-500 border-pink-600",
|
||||
purple: "bg-purple-500 border-purple-600",
|
||||
white: "bg-white border-gray-150"
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<input type="text" id={input.name} className="hidden" {...input} />
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{colorOptions.map((color) => {
|
||||
return (
|
||||
<button
|
||||
className={`w-9 h-9 rounded-full shadow border ${
|
||||
inputClasses[color]
|
||||
} ${
|
||||
input.value === color
|
||||
? "ring-[3px] ring-offset-2 ring-blue-400"
|
||||
: ""
|
||||
}`}
|
||||
onClick={() => {
|
||||
input.onChange(color);
|
||||
}}
|
||||
></button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<>
|
||||
<input type="text" id={ input.name } className="hidden" { ...input } />
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
{ colorOptions.map((color) => {
|
||||
return (
|
||||
<button
|
||||
className={ `w-9 h-9 rounded-full shadow border ${
|
||||
inputClasses[color]
|
||||
} ${
|
||||
input.value === color
|
||||
? "ring-[3px] ring-offset-2 ring-blue-400"
|
||||
: ""
|
||||
}` }
|
||||
onClick={ () => {
|
||||
input.onChange(color);
|
||||
} }
|
||||
/>
|
||||
);
|
||||
}) }
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -6,129 +6,128 @@ import { Icon, IconOptions } from "../../components/util/icon";
|
||||
import { BiChevronRight } from "react-icons/bi";
|
||||
|
||||
const parseIconName = (name: string) => {
|
||||
const splitName = name.split(/(?=[A-Z])/);
|
||||
if (splitName.length > 1) {
|
||||
return splitName.slice(1).join(" ");
|
||||
} else {
|
||||
const splitName = name.split(/(?=[A-Z])/);
|
||||
if (splitName.length > 1) {
|
||||
return splitName.slice(1).join(" ");
|
||||
}
|
||||
return name;
|
||||
}
|
||||
};
|
||||
|
||||
export const IconPickerInput = wrapFieldsWithMeta(({ input }) => {
|
||||
const [filter, setFilter] = React.useState("");
|
||||
const filteredBlocks = React.useMemo(() => {
|
||||
return Object.keys(IconOptions).filter((name) => {
|
||||
return name.toLowerCase().includes(filter.toLowerCase());
|
||||
});
|
||||
}, [filter]);
|
||||
const [filter, setFilter] = React.useState("");
|
||||
const filteredBlocks = React.useMemo(() => {
|
||||
return Object.keys(IconOptions).filter((name) => {
|
||||
return name.toLowerCase().includes(filter.toLowerCase());
|
||||
});
|
||||
}, [filter]);
|
||||
|
||||
const inputLabel = Object.keys(IconOptions).includes(input.value)
|
||||
? parseIconName(input.value)
|
||||
: "Select Icon";
|
||||
const InputIcon = IconOptions[input.value] ? IconOptions[input.value] : null;
|
||||
const inputLabel = Object.keys(IconOptions).includes(input.value)
|
||||
? parseIconName(input.value)
|
||||
: "Select Icon";
|
||||
const InputIcon = IconOptions[input.value] ? IconOptions[input.value] : null;
|
||||
|
||||
return (
|
||||
<div className="relative z-[1000]">
|
||||
<input type="text" id={input.name} className="hidden" {...input} />
|
||||
<Popover>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Popover.Button as={"span"}>
|
||||
<Button
|
||||
className={`text-sm h-11 px-4 ${InputIcon ? "h-11" : "h-10"}`}
|
||||
size="custom"
|
||||
rounded="full"
|
||||
variant={open ? "secondary" : "white"}
|
||||
>
|
||||
{InputIcon && (
|
||||
<InputIcon className="w-7 mr-1 h-auto fill-current text-blue-500" />
|
||||
)}
|
||||
{inputLabel}
|
||||
{!InputIcon && (
|
||||
<BiChevronRight className="w-5 h-auto fill-current opacity-70 ml-1" />
|
||||
)}
|
||||
</Button>
|
||||
</Popover.Button>
|
||||
<div
|
||||
className="absolute w-full min-w-[192px] max-w-2xl -bottom-2 left-0 translate-y-full"
|
||||
style={{ zIndex: 1000 }}
|
||||
>
|
||||
<Transition
|
||||
enter="transition duration-150 ease-out"
|
||||
enterFrom="transform opacity-0 -translate-y-2"
|
||||
enterTo="transform opacity-100 translate-y-0"
|
||||
leave="transition duration-75 ease-in"
|
||||
leaveFrom="transform opacity-100 translate-y-0"
|
||||
leaveTo="transform opacity-0 -translate-y-2"
|
||||
>
|
||||
<Popover.Panel className="relative overflow-hidden rounded-lg shadow-lg bg-white border border-gray-150 z-50">
|
||||
{({ close }) => (
|
||||
<div className="max-h-[24rem] flex flex-col w-full h-full">
|
||||
<div className="bg-gray-50 p-2 border-b border-gray-100 z-10 shadow-sm">
|
||||
<input
|
||||
type="text"
|
||||
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"
|
||||
onClick={(event: any) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
}}
|
||||
value={filter}
|
||||
onChange={(event: any) => {
|
||||
setFilter(event.target.value);
|
||||
}}
|
||||
placeholder="Filter..."
|
||||
/>
|
||||
</div>
|
||||
{filteredBlocks.length === 0 && (
|
||||
<span className="relative text-center text-xs px-2 py-3 text-gray-300 bg-gray-50 italic">
|
||||
return (
|
||||
<div className="relative z-[1000]">
|
||||
<input type="text" id={ input.name } className="hidden" { ...input } />
|
||||
<Popover>
|
||||
{ ({ open }) => (
|
||||
<>
|
||||
<Popover.Button as={ "span" }>
|
||||
<Button
|
||||
className={ `text-sm h-11 px-4 ${ InputIcon ? "h-11" : "h-10" }` }
|
||||
size="custom"
|
||||
rounded="full"
|
||||
variant={ open ? "secondary" : "white" }
|
||||
>
|
||||
{ InputIcon && (
|
||||
<InputIcon className="w-7 mr-1 h-auto fill-current text-blue-500" />
|
||||
) }
|
||||
{ inputLabel }
|
||||
{ !InputIcon && (
|
||||
<BiChevronRight className="w-5 h-auto fill-current opacity-70 ml-1" />
|
||||
) }
|
||||
</Button>
|
||||
</Popover.Button>
|
||||
<div
|
||||
className="absolute w-full min-w-[192px] max-w-2xl -bottom-2 left-0 translate-y-full"
|
||||
style={ { zIndex: 1000 } }
|
||||
>
|
||||
<Transition
|
||||
enter="transition duration-150 ease-out"
|
||||
enterFrom="transform opacity-0 -translate-y-2"
|
||||
enterTo="transform opacity-100 translate-y-0"
|
||||
leave="transition duration-75 ease-in"
|
||||
leaveFrom="transform opacity-100 translate-y-0"
|
||||
leaveTo="transform opacity-0 -translate-y-2"
|
||||
>
|
||||
<Popover.Panel className="relative overflow-hidden rounded-lg shadow-lg bg-white border border-gray-150 z-50">
|
||||
{ ({ close }) => (
|
||||
<div className="max-h-[24rem] flex flex-col w-full h-full">
|
||||
<div className="bg-gray-50 p-2 border-b border-gray-100 z-10 shadow-sm">
|
||||
<input
|
||||
type="text"
|
||||
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"
|
||||
onClick={ (event: any) => {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
} }
|
||||
value={ filter }
|
||||
onChange={ (event: any) => {
|
||||
setFilter(event.target.value);
|
||||
} }
|
||||
placeholder="Filter..."
|
||||
/>
|
||||
</div>
|
||||
{ filteredBlocks.length === 0 && (
|
||||
<span className="relative text-center text-xs px-2 py-3 text-gray-300 bg-gray-50 italic">
|
||||
No matches found
|
||||
</span>
|
||||
)}
|
||||
{filteredBlocks.length > 0 && (
|
||||
<div className="w-full grid grid-cols-6 auto-rows-auto p-2 overflow-y-auto">
|
||||
<button
|
||||
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"
|
||||
key={"clear-input"}
|
||||
onClick={() => {
|
||||
input.onChange("");
|
||||
setFilter("");
|
||||
close();
|
||||
}}
|
||||
>
|
||||
<GoCircleSlash className="w-6 h-auto text-gray-200" />
|
||||
</button>
|
||||
{filteredBlocks.map((name) => {
|
||||
return (
|
||||
<button
|
||||
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"
|
||||
key={name}
|
||||
onClick={() => {
|
||||
input.onChange(name);
|
||||
setFilter("");
|
||||
close();
|
||||
}}
|
||||
>
|
||||
<Icon
|
||||
data={{
|
||||
name: name,
|
||||
size: "custom",
|
||||
color: "blue",
|
||||
}}
|
||||
className="w-7 h-auto"
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</span>
|
||||
) }
|
||||
{ filteredBlocks.length > 0 && (
|
||||
<div className="w-full grid grid-cols-6 auto-rows-auto p-2 overflow-y-auto">
|
||||
<button
|
||||
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"
|
||||
key={ "clear-input" }
|
||||
onClick={ () => {
|
||||
input.onChange("");
|
||||
setFilter("");
|
||||
close();
|
||||
} }
|
||||
>
|
||||
<GoCircleSlash className="w-6 h-auto text-gray-200" />
|
||||
</button>
|
||||
{ filteredBlocks.map((name) => {
|
||||
return (
|
||||
<button
|
||||
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"
|
||||
key={ name }
|
||||
onClick={ () => {
|
||||
input.onChange(name);
|
||||
setFilter("");
|
||||
close();
|
||||
} }
|
||||
>
|
||||
<Icon
|
||||
data={ {
|
||||
name: name,
|
||||
size: "custom",
|
||||
color: "blue"
|
||||
} }
|
||||
className="w-7 h-auto"
|
||||
/>
|
||||
</button>
|
||||
);
|
||||
}) }
|
||||
</div>
|
||||
) }
|
||||
</div>
|
||||
) }
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Popover.Panel>
|
||||
</Transition>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
</>
|
||||
) }
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user