enzostvs's picture
enzostvs HF Staff
Upload 172 files
9cd6ddb verified
import { useState } from "react";
import { useIntl } from "react-intl";
import { Input } from "@/components/input";
import { Label } from "@/components/label";
import { Collapse } from "@/components/collapse";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faGripVertical } from "@fortawesome/free-solid-svg-icons";
import { ChevronDownIcon } from "@heroicons/react/solid";
import { ChevronRightIcon } from "@heroicons/react/solid";
import classNames from "classnames";
import { TrashIcon } from "@heroicons/react/solid";
import { useUpdateEffect } from "react-use";
import { PlusIcon } from "@heroicons/react/solid";
import { ColorPicker } from "@/components/color-picker";
import { Switch } from "@/components/switch";
import { PaperAirplaneIcon } from "@heroicons/react/solid";
import { rgbaToHex } from "@/utils";
import { useMessage } from "@/components/message-editor/useMessage";
export default function EmbedsEditor() {
const intl = useIntl();
const [message, setMessage] = useState({
content: "",
embeds: [],
buttons: [],
});
const [webhookUrl, setWebhookUrl] = useState("");
const { post } = useMessage();
return (
<div className="bg-dark-600 w-full flex-col lg:flex-row flex min-h-screen">
<div className="w-full lg:w-1/2 mx-auto flex flex-col justify-center px-6 lg:px-4 py-10 max-w-2xl">
<div className="grid grid-cols-2 gap-x-6 gap-y-5 w-full">
<div className="bg-dark-400 rounded-lg p-4 w-full col-span-2 flex items-center justify-between gap-6">
<Input
value={webhookUrl}
placeholder="Webhook URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-100 focus:ring-[3px] ring-blue ring-opacity-80"
onChange={(url) => setWebhookUrl(url as string)}
/>
<button
className="bg-blue hover:bg-opacity-80 text-white font-semibold flex items-center gap-2 px-4 py-3 rounded-md text-sm whitespace-nowrap"
onClick={() => post(webhookUrl, message)}
>
<PaperAirplaneIcon className="w-4 rotate-90" />
Send message
</button>
</div>
<Form message={message} setMessage={setMessage} />
</div>
</div>
<div className="bg-dark-500 border-l-[2px] border-dark-400 p-10 top-0 sticky w-full lg:w-1/2 h-screen">
<p className="text-red bg-red bg-opacity-10 px-4 py-3 rounded-md text-center font-semibold">
preview will be here
</p>
</div>
</div>
);
}
const Form = ({
message,
setMessage,
}: {
message: any;
setMessage: (e: any) => void;
}) => {
return (
<>
<Collapse
open={true}
title="Author and Content"
parentClassName="col-span-2"
onOpenClassName="rounded-b-none"
className="bg-blue rounded-lg p-4 text-white font-sans text-base uppercase tracking-wider font-semibold"
>
<div className="bg-dark-400 rounded-b-lg p-5 grid grid-cols-2 gap-4">
<div>
<Label className="mb-2.5">
Username
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{message?.username?.length ?? 0}/80
</span>
</Label>
<Input
value={message?.username}
placeholder="Username"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-100 focus:ring-[3px] ring-blue ring-opacity-80"
onChange={(username) => setMessage({ ...message, username })}
/>
</div>
<div>
<Label className="mb-2.5">Avatar URL</Label>
<Input
value={message?.avatar_url}
placeholder="Avatar URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-100 focus:ring-[3px] ring-blue ring-opacity-80"
onChange={(avatar_url) => setMessage({ ...message, avatar_url })}
/>
</div>
<div className="col-span-2">
<Label className="mb-2.5">
CONTENT{" "}
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{message?.content?.length ?? 0}/2000
</span>
</Label>
<Input
type="textarea"
value={message.content}
placeholder="Content"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-100 focus:ring-[3px] ring-blue ring-opacity-80"
onChange={(content) => setMessage({ ...message, content })}
/>
</div>
</div>
</Collapse>
<Collapse
open={true}
title={
<p>
Embeds{" "}
<span className="text-sm opacity-60 ml-2">
{message?.embeds?.length ?? 0} / 10
</span>
</p>
}
parentClassName="col-span-2"
onOpenClassName="rounded-b-none"
className="bg-blue rounded-lg p-4 text-white font-sans text-base uppercase tracking-wider font-semibold"
>
<div className="bg-dark-400 rounded-b-lg p-5 grid grid-cols-1 gap-4">
<Embeds
embeds={message?.embeds}
setEmbeds={(embeds) => setMessage({ ...message, embeds })}
/>
</div>
</Collapse>
<Collapse
open={true}
title={
<p>
Link Buttons
<span className="text-sm opacity-60 ml-2">
{message?.buttons?.length ?? 0} / 25
</span>
</p>
}
parentClassName="col-span-2"
onOpenClassName="rounded-b-none"
className="bg-blue rounded-lg p-4 text-white font-sans text-base uppercase tracking-wider font-semibold"
>
<div className="bg-dark-400 rounded-b-lg p-5 grid grid-cols-1 gap-4">
<Buttons
buttons={message?.buttons}
setButtons={(buttons) => setMessage({ ...message, buttons })}
/>
</div>
</Collapse>
</>
);
};
const Embeds = ({
embeds,
setEmbeds,
}: {
embeds: any[];
setEmbeds: (e: any) => void;
}) => {
const [open, setOpen] = useState(0);
const onDelete = (i: number) => {
const newEmbeds = embeds ?? [];
newEmbeds.splice(i, 1);
setEmbeds(newEmbeds);
};
const setEmbed = (embed: any, index: number) => {
const newEmbeds = embeds ?? [];
newEmbeds[index] = embed;
setEmbeds(newEmbeds);
};
useUpdateEffect(() => setOpen(embeds?.length - 1), [embeds]);
return (
<>
{embeds?.map((embed: any, i: number) => (
<div key={i} className="flex">
<div
className="h-full w-[3px] rounded-l-lg"
style={{ backgroundColor: embed?.color ?? "#fff" }}
/>
<div className="bg-[#2f3136] rounded-r-lg w-full">
<div
className={classNames(
"px-4 pt-4 pb-2 flex justify-between items-center text-white font-semibold cursor-pointer",
{
"!pb-4": open !== i,
}
)}
onClick={() => setOpen(open === i ? -1 : i)}
>
<div className="flex items-center justify-start gap-1 flex-1">
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open === i,
})}
/>
<p>Embed {i + 1}</p>
</div>
<div
className="flex items-center justify-end gap-2"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<TrashIcon
className="w-5 hover:text-danger"
onClick={() => onDelete(i)}
/>
</div>
</div>
{open === i && (
<div className="px-4 pb-4 grid grid-cols-2 gap-2">
<Author
author={embed?.author}
setAuthor={(author) => setEmbed({ ...embed, author }, i)}
/>
<Body
embed={embed}
setEmbed={(embed) => setEmbed({ ...embed }, i)}
/>
<Fields
fields={embed?.fields}
setFields={(fields) => setEmbed({ ...embed, fields }, i)}
/>
<Images
embed={embed}
setEmbed={(newEmbed) => setEmbed({ ...newEmbed }, i)}
/>
<Footer
embed={embed}
setEmbed={(newEmbed) => setEmbed({ ...newEmbed }, i)}
/>
</div>
)}
</div>
{embeds?.length > 1 && (
<div className="flex items-center justify-center">
<FontAwesomeIcon
icon={faGripVertical}
className="w-8 text-dark-100"
/>
</div>
)}
</div>
))}
<div className="w-full flex gap-3">
<button
className="bg-transparent flex items-center gap-2 border-2 border-dashed border-darkGreen group rounded-md text-darkGreen hover:border-solid bg-opacity-10 hover:text-white transition-all duration-200 px-4 py-3 text-sm font-semibold relative z-1"
onClick={() => {
setEmbeds([
...(embeds ?? []),
{
color: "#ff00ff",
},
]);
}}
>
<PlusIcon className="w-4" />
Add Embed
<div className="absolute left-0 h-full top-0 bg-darkGreen z-[-1] group-hover:w-full w-0 transition-all duration-200" />
</button>
<button
className="bg-transparent flex items-center gap-2 border-2 border-dashed border-danger group rounded-md text-danger hover:border-solid bg-opacity-10 hover:text-white transition-all duration-200 px-4 py-3 text-sm font-semibold relative z-1"
onClick={() => setEmbeds([])}
>
<TrashIcon className="w-4" />
Clear embeds
<div className="absolute left-0 h-full top-0 bg-danger z-[-1] group-hover:w-full w-0 transition-all duration-200" />
</button>
</div>
</>
);
};
const Buttons = ({
buttons,
setButtons,
}: {
buttons: any[];
setButtons: (e: any) => void;
}) => {
const [open, setOpen] = useState(0);
const onDelete = (i: number) => {
const newButtons = buttons ?? [];
newButtons.splice(i, 1);
setButtons(newButtons);
};
const setButton = (button: any, index: number) => {
const newButtons = buttons ?? [];
newButtons[index] = button;
setButtons(newButtons);
};
useUpdateEffect(() => setOpen(buttons?.length - 1), [buttons]);
return (
<>
{buttons?.map((button: any, i: number) => (
<div key={i} className="flex">
<div className="bg-[#2f3136] rounded-r-lg w-full">
<div
className={classNames(
"px-4 pt-4 pb-2 flex justify-between items-center text-white font-semibold cursor-pointer",
{
"!pb-4": open !== i,
}
)}
onClick={() => setOpen(open === i ? -1 : i)}
>
<div className="flex items-center justify-start gap-1 flex-1">
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open === i,
})}
/>
<p>Button {i + 1}</p>
</div>
<div
className="flex items-center justify-end gap-2"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<TrashIcon
className="w-5 hover:text-danger"
onClick={() => onDelete(i)}
/>
</div>
</div>
{open === i && (
<div className="px-4 pb-4 grid grid-cols-2 gap-2">
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">
Title
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{button?.label?.length ?? 0}/80
</span>
</Label>
<Input
value={button?.label}
placeholder="Label"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(label) => setButton({ ...button, label }, i)}
/>
</div>
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">URL</Label>
<Input
value={button?.url}
placeholder="Label"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(url) => setButton({ ...button, url }, i)}
/>
</div>
<div className="col-span-2 grid grid-cols-2 gap-4 mt-1">
<div>
<Label className="mb-2.5 !text-xs">Native Emoji</Label>
<Input
value={button?.emoji?.name}
placeholder="Native Emoji"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(name) =>
setButton(
{
...button,
emoji: { ...button?.emoji?.button, name },
},
i
)
}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Custom Emoji</Label>
<Input
value={button?.emoji?.id}
placeholder="Custom Emoji"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(id) =>
setButton(
{
...button,
emoji: { ...button?.emoji?.button, id },
},
i
)
}
/>
</div>
</div>
</div>
)}
</div>
{buttons?.length > 1 && (
<div className="flex items-center justify-center">
<FontAwesomeIcon
icon={faGripVertical}
className="w-8 text-dark-100"
/>
</div>
)}
</div>
))}
<div className="w-full flex gap-3">
<button
className="bg-transparent flex items-center gap-2 border-2 border-dashed border-darkGreen group rounded-md text-darkGreen hover:border-solid bg-opacity-10 hover:text-white transition-all duration-200 px-4 py-3 text-sm font-semibold relative z-1"
onClick={() => {
setButtons([
...(buttons ?? []),
{
label: "New Button",
type: 2,
style: 5,
},
]);
}}
>
<PlusIcon className="w-4" />
Add button
<div className="absolute left-0 h-full top-0 bg-darkGreen z-[-1] group-hover:w-full w-0 transition-all duration-200" />
</button>
<button
className="bg-transparent flex items-center gap-2 border-2 border-dashed border-danger group rounded-md text-danger hover:border-solid bg-opacity-10 hover:text-white transition-all duration-200 px-4 py-3 text-sm font-semibold relative z-1"
onClick={() => setButtons([])}
>
<TrashIcon className="w-4" />
Clear buttons
<div className="absolute left-0 h-full top-0 bg-danger z-[-1] group-hover:w-full w-0 transition-all duration-200" />
</button>
</div>
</>
);
};
const Author = ({
author,
setAuthor,
}: {
author: any;
setAuthor: (a: any) => void;
}) => {
const [open, setOpen] = useState(true);
return (
<div className="col-span-2">
<div
className="text-white text-sm font-semibold tracking-wider flex items-center justify-start gap-1 cursor-pointer hover:bg-dark-400 px-2 py-1.5 rounded"
onClick={() => setOpen(!open)}
>
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open,
})}
/>
Author
</div>
{open && (
<div className="grid grid-cols-2 gap-4 mt-2 pl-3">
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">
Author
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{author?.name?.length ?? 0}/256
</span>
</Label>
<Input
value={author?.name}
placeholder="Author name"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(name) => setAuthor({ ...author, name })}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Author URL</Label>
<Input
value={author?.url}
placeholder="Author URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(url) => setAuthor({ ...author, url })}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Author Icon URL</Label>
<Input
value={author?.icon_url}
placeholder="Author Icon URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(icon_url) => setAuthor({ ...author, icon_url })}
/>
</div>
</div>
)}
</div>
);
};
const Body = ({
embed,
setEmbed,
}: {
embed: any;
setEmbed: (a: any) => void;
}) => {
const [open, setOpen] = useState(true);
return (
<div className="col-span-2">
<div
className="text-white text-sm font-semibold tracking-wider flex items-center justify-start gap-1 cursor-pointer hover:bg-dark-400 px-2 py-1.5 rounded"
onClick={() => setOpen(!open)}
>
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open,
})}
/>
Body
</div>
{open && (
<div className="grid grid-cols-2 gap-x-4 gap-y-3 mt-2 pl-3">
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">
Title
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{embed?.title?.length ?? 0}/256
</span>
</Label>
<Input
value={embed?.title}
placeholder="Title"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(title) => setEmbed({ ...embed, title })}
/>
</div>
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">
Description{" "}
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{embed?.description?.length ?? 0}/4096
</span>
</Label>
<Input
type="textarea"
value={embed.description}
placeholder="Content"
className="bg-dark-600 bg-opacity-80 rounded-md p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(description) => setEmbed({ ...embed, description })}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Title URL</Label>
<Input
value={embed?.url}
placeholder="Title URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(url) => setEmbed({ ...embed, url })}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Embed Color</Label>
<div className="flex gap-3">
<Input
value={embed?.color}
placeholder="Embed color"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(color) => setEmbed({ ...embed, color })}
/>
<ColorPicker
data={embed}
full
className="h-[42px] w-[44px] min-w-[44px] rounded"
value={embed?.color}
gradients={false}
onChange={(c: any, datas) => {
setEmbed({ ...embed, color: rgbaToHex(c) });
}}
/>
</div>
</div>
</div>
)}
</div>
);
};
const Images = ({
embed,
setEmbed,
}: {
embed: any;
setEmbed: (a: any) => void;
}) => {
const [open, setOpen] = useState(true);
return (
<div className="col-span-2">
<div
className="text-white text-sm font-semibold tracking-wider flex items-center justify-start gap-1 cursor-pointer hover:bg-dark-400 px-2 py-1.5 rounded"
onClick={() => setOpen(!open)}
>
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open,
})}
/>
Images
</div>
{open && (
<div className="grid grid-cols-2 gap-x-4 gap-y-3 mt-2 pl-3">
<div>
<Label className="mb-2.5 !text-xs">Image URL</Label>
<Input
value={embed?.image?.url}
placeholder="Image URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(url) => setEmbed({ ...embed, image: { url } })}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Thumbnail URL</Label>
<Input
value={embed?.thumbnail?.url}
placeholder="Thumbnail URL"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(url) => setEmbed({ ...embed, thumbnail: { url } })}
/>
</div>
</div>
)}
</div>
);
};
const Fields = ({
fields,
setFields,
}: {
fields: any;
setFields: (a: any) => void;
}) => {
const [open, setOpen] = useState(true);
return (
<div className="col-span-2">
<div
className="text-white text-sm font-semibold tracking-wider flex items-end justify-start gap-1 cursor-pointer hover:bg-dark-400 px-2 py-1.5 rounded"
onClick={() => setOpen(!open)}
>
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open,
})}
/>
Fields
<span className="opacity-50 text-xs">{fields?.length ?? 0}/25</span>
</div>
{open && (
<div className="grid grid-cols-2 gap-4 mt-2 pl-3">
{fields?.map((field: any, i: number) => (
<Field
key={i}
index={i}
field={field}
setField={(newField) => {
const newFields = fields ?? [];
newFields[i] = newField;
setFields(newFields);
}}
onDelete={() => {
const newFields = fields ?? [];
newFields.splice(i, 1);
setFields(newFields);
}}
/>
))}
<div className="w-full flex gap-3 col-span-2">
<button
className="bg-transparent flex items-center gap-1 border-2 border-dashed border-darkGreen group rounded-md text-darkGreen hover:border-solid bg-opacity-10 hover:text-white transition-all duration-200 px-2.5 py-1.5 text-[13px] font-semibold relative z-1"
onClick={() => {
setFields([
...(fields ?? []),
{
name: "Name",
value: "Value",
inline: true,
},
]);
}}
>
<PlusIcon className="w-3" />
Add Field
<div className="absolute left-0 h-full top-0 bg-darkGreen z-[-1] group-hover:w-full w-0 transition-all duration-200" />
</button>
<button
className="bg-transparent flex items-center gap-1 border-2 border-dashed border-danger group rounded-md text-danger hover:border-solid bg-opacity-10 hover:text-white transition-all duration-200 px-2.5 py-1.5 text-[13px] font-semibold relative z-1"
onClick={() => setFields([])}
>
<TrashIcon className="w-3" />
Clear Fields
<div className="absolute left-0 h-full top-0 bg-danger z-[-1] group-hover:w-full w-0 transition-all duration-200" />
</button>
</div>
</div>
)}
</div>
);
};
const Field = ({
field,
index,
setField,
onDelete,
}: {
field: any;
index: number;
setField: (e: any) => void;
onDelete: () => void;
}) => {
const [open, setOpen] = useState(true);
return (
<div className="border-2 border-dashed border-dark-200 rounded-lg col-span-2 grid grid-cols-2 gap-4 p-3">
<div
className="col-span-2 flex items-center justify-between gap-1 flex-1 text-sm text-white font-semibold cursor-pointer w-full"
onClick={() => setOpen(!open)}
>
<div className="flex items-center justify-start gap-1">
<ChevronRightIcon
className={classNames("w-4", {
"rotate-90": open,
})}
/>
<p>Field #{index + 1}</p>
</div>
<div
className="flex items-center justify-end gap-2"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
>
<TrashIcon className="w-4 hover:text-danger" onClick={onDelete} />
</div>
</div>
{open && (
<>
<div className="col-span-2 flex items-center justify-start gap-4">
<div className="w-full">
<Label className="mb-2.5 !text-xs">
Title
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{field?.name?.length ?? 0}/256
</span>
</Label>
<Input
value={field?.name}
placeholder="Field Name"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(name) => setField({ ...field, name })}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Inline</Label>
<Switch
value={field?.inline}
onChange={() => setField({ ...field, inline: !field?.inline })}
/>
</div>
</div>
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">
Field value{" "}
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{field?.value?.length ?? 0}/1024
</span>
</Label>
<Input
type="textarea"
value={field.value}
placeholder="Content"
className="bg-dark-600 bg-opacity-80 rounded-md p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(value) => setField({ ...field, value })}
/>
</div>
</>
)}
</div>
);
};
const Footer = ({
embed,
setEmbed,
}: {
embed: any;
setEmbed: (a: any) => void;
}) => {
const [open, setOpen] = useState(true);
return (
<div className="col-span-2">
<div
className="text-white text-sm font-semibold tracking-wider flex items-center justify-start gap-1 cursor-pointer hover:bg-dark-400 px-2 py-1.5 rounded"
onClick={() => setOpen(!open)}
>
<ChevronRightIcon
className={classNames("w-5", {
"rotate-90": open,
})}
/>
Body
</div>
{open && (
<div className="grid grid-cols-2 gap-x-4 gap-y-3 mt-2 pl-3">
<div className="col-span-2">
<Label className="mb-2.5 !text-xs">
Footer Text
<span className="font-sans font-regular opacity-50 text-xs ml-1">
{embed?.footer?.name ?? 0}/256
</span>
</Label>
<Input
value={embed?.footer?.text}
placeholder="Footer Text"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(text) =>
setEmbed({ ...embed, footer: { ...embed?.footer, text } })
}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Footer Icon Url</Label>
<Input
value={embed?.footer?.icon_url}
placeholder="Footer Icon URL"
className="bg-dark-600 bg-opacity-80 rounded-md p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(icon_url) =>
setEmbed({ ...embed, footer: { ...embed?.footer, icon_url } })
}
/>
</div>
<div>
<Label className="mb-2.5 !text-xs">Timestamp</Label>
<Input
value={embed?.timestamp}
placeholder="Timestamp"
className="bg-dark-600 bg-opacity-80 rounded p-3 text-sm text-white placeholder-dark-200 focus:ring-[3px] ring-white ring-opacity-50"
onChange={(timestamp) =>
setEmbed({ ...embed, footer: { ...embed?.footer, timestamp } })
}
/>
</div>
</div>
)}
</div>
);
};