Refactor Accordion Component for Shared Usage (#653)

This pull request aims to refactor the Accordion Component to enable its
shared usage by both the formModal (chat) component and the Tweaks
component. By making the necessary modifications, we can eliminate code
duplication and improve maintainability across the application.
This commit is contained in:
anovazzi1 2023-07-18 16:15:31 -03:00 • committed by GitHub
commit 8d4031dec0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 199 additions and 129 deletions

View file

@ -147,9 +147,9 @@
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.22.6", "version": "7.22.9",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.6.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz",
"integrity": "sha512-29tfsWTq2Ftu7MXmimyC0C5FDZv5DYxOZkh3XD3+QW4V/BYuv/LyEsjj3c0hqedEaDt6DBfDvexMKU8YevdqFg==", "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@ -194,6 +194,14 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/core/node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.22.7", "version": "7.22.7",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.7.tgz",
@ -226,6 +234,14 @@
"@babel/core": "^7.0.0" "@babel/core": "^7.0.0"
} }
}, },
"node_modules/@babel/helper-compilation-targets/node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-environment-visitor": { "node_modules/@babel/helper-environment-visitor": {
"version": "7.22.5", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz",
@ -1175,9 +1191,9 @@
} }
}, },
"node_modules/@mui/private-theming/node_modules/@babel/runtime": { "node_modules/@mui/private-theming/node_modules/@babel/runtime": {
"version": "7.22.5", "version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz",
"integrity": "sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==", "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==",
"dependencies": { "dependencies": {
"regenerator-runtime": "^0.13.11" "regenerator-runtime": "^0.13.11"
}, },
@ -1338,14 +1354,6 @@
"resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz",
"integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w=="
}, },
"node_modules/@nicolo-ribaudo/semver-v6": {
"version": "6.3.3",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/semver-v6/-/semver-v6-6.3.3.tgz",
"integrity": "sha512-3Yc1fUTs69MG/uZbJlLSI3JISMn2UV2rg+1D/vROUqZyh3l6iYHCs7GMp+M40ZD7yOdDbYjJcU1oTJhrc+dGKg==",
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@nodelib/fs.scandir": { "node_modules/@nodelib/fs.scandir": {
"version": "2.1.5", "version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",

View file

@ -11,6 +11,7 @@ export default function AccordionComponent({
trigger, trigger,
children, children,
open = [], open = [],
keyValue,
}: AccordionComponentType) { }: AccordionComponentType) {
const [value, setValue] = useState( const [value, setValue] = useState(
open.length === 0 ? "" : getOpenAccordion() open.length === 0 ? "" : getOpenAccordion()
@ -28,13 +29,18 @@ export default function AccordionComponent({
} }
function handleClick() { function handleClick() {
value == "" ? setValue(trigger) : setValue(""); value === "" ? setValue(keyValue) : setValue("");
} }
return ( return (
<> <>
<Accordion type="single" value={value} onValueChange={setValue}> <Accordion
<AccordionItem value={trigger} className="border-none"> type="single"
className="w-full"
value={value}
onValueChange={setValue}
>
<AccordionItem value={keyValue} className="border-b">
<AccordionTrigger <AccordionTrigger
onClick={() => { onClick={() => {
handleClick(); handleClick();
@ -43,7 +49,9 @@ export default function AccordionComponent({
> >
{trigger} {trigger}
</AccordionTrigger> </AccordionTrigger>
<AccordionContent>{children}</AccordionContent> <AccordionContent className="AccordionContent">
{children}
</AccordionContent>
</AccordionItem> </AccordionItem>
</Accordion> </Accordion>
</> </>

View file

@ -46,7 +46,7 @@ const AccordionContent = React.forwardRef<
<AccordionPrimitive.Content <AccordionPrimitive.Content
ref={ref} ref={ref}
className={cn( className={cn(
"overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down", "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm",
className className
)} )}
{...props} {...props}

View file

@ -152,6 +152,34 @@ The cursor: default; property value restores the browser's default cursor style
cursor: default; cursor: default;
} }
.AccordionContent {
overflow: hidden;
}
.AccordionContent[data-state='open'] {
animation: slideDown 300ms ease-out;
}
.AccordionContent[data-state='closed'] {
animation: slideUp 300ms ease-out;
}
@keyframes slideDown {
from {
height: 0;
}
to {
height: var(--radix-accordion-content-height);
}
}
@keyframes slideUp {
from {
height: var(--radix-accordion-content-height);
}
to {
height: 0;
}
}
@layer components { @layer components {
.round-buttons-position { .round-buttons-position {

View file

@ -340,6 +340,7 @@ export default function ApiModal({ flow }: { flow: FlowType }) {
{tweaksList.current.includes(t["data"]["id"]) && ( {tweaksList.current.includes(t["data"]["id"]) && (
<AccordionComponent <AccordionComponent
trigger={t["data"]["id"]} trigger={t["data"]["id"]}
keyValue={t["data"]["id"]}
open={openAccordion} open={openAccordion}
> >
<div className="api-modal-table-arrangement"> <div className="api-modal-table-arrangement">

View file

@ -81,7 +81,7 @@ export default function ChatMessage({
remarkPlugins={[remarkGfm, remarkMath]} remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeMathjax]} rehypePlugins={[rehypeMathjax]}
className="markdown prose inline-block break-words text-primary className="markdown prose inline-block break-words text-primary
dark:prose-invert sm:max-w-[30vw] lg:max-w-[40vw] sm:w-[30vw] lg:w-[40vw]" dark:prose-invert sm:w-[30vw] sm:max-w-[30vw] lg:w-[40vw] lg:max-w-[40vw]"
components={{ components={{
code: ({ code: ({
node, node,

View file

@ -10,13 +10,8 @@ import ChatInput from "./chatInput";
import ChatMessage from "./chatMessage"; import ChatMessage from "./chatMessage";
import _ from "lodash"; import _ from "lodash";
import AccordionComponent from "../../components/AccordionComponent";
import ToggleShadComponent from "../../components/toggleShadComponent"; import ToggleShadComponent from "../../components/toggleShadComponent";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "../../components/ui/accordion";
import { Badge } from "../../components/ui/badge"; import { Badge } from "../../components/ui/badge";
import { import {
Dialog, Dialog,
@ -388,6 +383,7 @@ export default function FormModal({
setChatValue(""); setChatValue("");
} }
} }
return ( return (
<Dialog open={open} onOpenChange={setModalOpen}> <Dialog open={open} onOpenChange={setModalOpen}>
<DialogTrigger className="hidden"></DialogTrigger> <DialogTrigger className="hidden"></DialogTrigger>
@ -422,12 +418,12 @@ export default function FormModal({
</span> </span>
</div> </div>
</div> </div>
<Accordion type="multiple" className="w-full">
{Object.keys(tabsState[id.current].formKeysData.input_keys).map( {Object.keys(tabsState[id.current].formKeysData.input_keys).map(
(i, k) => ( (i, k) => (
<div className="file-component-accordion-div" key={k}> <div className="file-component-accordion-div" key={k}>
<AccordionItem className="w-full" key={k} value={i}> <AccordionComponent
<AccordionTrigger className="flex gap-2"> trigger={
<div className="file-component-badge-div"> <div className="file-component-badge-div">
<Badge variant="gray" size="md"> <Badge variant="gray" size="md">
{i} {i}
@ -451,26 +447,29 @@ export default function FormModal({
/> />
</div> </div>
</div> </div>
</AccordionTrigger> }
<AccordionContent> key={k}
keyValue={i}
>
<div className="file-component-tab-column"> <div className="file-component-tab-column">
{tabsState[ {tabsState[id.current].formKeysData.handle_keys.some(
id.current (t) => t === i
].formKeysData.handle_keys.some((t) => t === i) && ( ) && (
<div className="font-normal text-muted-foreground "> <div className="font-normal text-muted-foreground ">
Source: Component Source: Component
</div> </div>
)} )}
<Textarea <Textarea
className="custom-scroll"
value={ value={
tabsState[id.current].formKeysData.input_keys[i] tabsState[id.current].formKeysData.input_keys[i]
} }
onChange={(e) => { onChange={(e) => {
setTabsState((old) => { setTabsState((old) => {
let newTabsState = _.cloneDeep(old); let newTabsState = _.cloneDeep(old);
newTabsState[ newTabsState[id.current].formKeysData.input_keys[
id.current i
].formKeysData.input_keys[i] = e.target.value; ] = e.target.value;
return newTabsState; return newTabsState;
}); });
}} }}
@ -478,24 +477,68 @@ export default function FormModal({
placeholder="Enter text..." placeholder="Enter text..."
></Textarea> ></Textarea>
</div> </div>
</AccordionContent> </AccordionComponent>
</AccordionItem>
</div> </div>
) )
)} )}
{tabsState[id.current].formKeysData.memory_keys.map((i, k) => ( {tabsState[id.current].formKeysData.memory_keys.map((i, k) => (
<AccordionItem key={k} value={i}> <div className="file-component-accordion-div" key={k}>
<div className="tab-accordion-badge-div group"> <AccordionComponent
<div className="group-hover:underline"> trigger={
<Badge size="md" variant="gray"> <div className="file-component-badge-div">
<Badge variant="gray" size="md">
{i} {i}
</Badge> </Badge>
<div
className="-mb-1"
onClick={(event) => {
event.stopPropagation();
}}
>
<ToggleShadComponent
enabled={chatKey === i}
setEnabled={(value) =>
handleOnCheckedChange(value, i)
}
size="small"
disabled={tabsState[
id.current
].formKeysData.handle_keys.some((t) => t === i)}
/>
</div> </div>
Used as memory key
</div> </div>
</AccordionItem> }
key={k}
keyValue={i}
>
<div className="file-component-tab-column">
{tabsState[id.current].formKeysData.handle_keys.some(
(t) => t === i
) && (
<div className="font-normal text-muted-foreground ">
Source: Component
</div>
)}
<Textarea
className="custom-scroll"
value={tabsState[id.current].formKeysData.input_keys[i]}
onChange={(e) => {
setTabsState((old) => {
let newTabsState = _.cloneDeep(old);
newTabsState[id.current].formKeysData.input_keys[
i
] = e.target.value;
return newTabsState;
});
}}
disabled={chatKey === i}
placeholder="Enter text..."
></Textarea>
</div>
</AccordionComponent>
</div>
))} ))}
</Accordion>
</div> </div>
<div className="eraser-column-arrangement"> <div className="eraser-column-arrangement">
<div className="eraser-size"> <div className="eraser-size">

View file

@ -6,7 +6,11 @@ import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button"; import { Button } from "../../components/ui/button";
import { DialogTitle } from "../../components/ui/dialog"; import { DialogTitle } from "../../components/ui/dialog";
import { Textarea } from "../../components/ui/textarea"; import { Textarea } from "../../components/ui/textarea";
import { MAX_WORDS_HIGHLIGHT, PROMPT_DIALOG_SUBTITLE, TEXT_DIALOG_SUBTITLE } from "../../constants"; import {
MAX_WORDS_HIGHLIGHT,
PROMPT_DIALOG_SUBTITLE,
TEXT_DIALOG_SUBTITLE,
} from "../../constants";
import { alertContext } from "../../contexts/alertContext"; import { alertContext } from "../../contexts/alertContext";
import { darkContext } from "../../contexts/darkContext"; import { darkContext } from "../../contexts/darkContext";
import { PopUpContext } from "../../contexts/popUpContext"; import { PopUpContext } from "../../contexts/popUpContext";
@ -122,13 +126,14 @@ export default function GenericModal({
function getClassByNumberLength() { function getClassByNumberLength() {
let sumOfCaracteres: number = 0; let sumOfCaracteres: number = 0;
wordsHighlight.forEach(element => { wordsHighlight.forEach((element) => {
sumOfCaracteres = sumOfCaracteres + element.replace(/[{}]/g, "").length sumOfCaracteres = sumOfCaracteres + element.replace(/[{}]/g, "").length;
}); });
return sumOfCaracteres > MAX_WORDS_HIGHLIGHT ? "code-highlight" : "code-nohighlight" return sumOfCaracteres > MAX_WORDS_HIGHLIGHT
? "code-highlight"
: "code-nohighlight";
} }
function validatePrompt(closeModal: boolean) { function validatePrompt(closeModal: boolean) {
postValidatePrompt(field_name, inputValue, nodeClass) postValidatePrompt(field_name, inputValue, nodeClass)
.then((apiReturn) => { .then((apiReturn) => {
@ -234,7 +239,10 @@ export default function GenericModal({
<div className="mb-auto flex-1"> <div className="mb-auto flex-1">
{type === TypeModal.PROMPT && ( {type === TypeModal.PROMPT && (
<div className=" mr-2"> <div className=" mr-2">
<div ref={divRef} className="max-h-20 overflow-y-auto custom-scroll"> <div
ref={divRef}
className="max-h-20 overflow-y-auto custom-scroll"
>
<div className="flex flex-wrap items-center"> <div className="flex flex-wrap items-center">
<Variable className=" -ml-px mr-1 flex h-4 w-4 text-primary"></Variable> <Variable className=" -ml-px mr-1 flex h-4 w-4 text-primary"></Variable>
<span className="text-md font-semibold text-primary"> <span className="text-md font-semibold text-primary">

View file

@ -130,7 +130,8 @@ export type RadialProgressType = {
export type AccordionComponentType = { export type AccordionComponentType = {
children?: ReactElement; children?: ReactElement;
open?: string[]; open?: string[];
trigger?: string; trigger?: string | ReactElement;
keyValue?: string;
}; };
export type Side = "top" | "right" | "bottom" | "left"; export type Side = "top" | "right" | "bottom" | "left";

View file

@ -28,20 +28,6 @@ module.exports = {
}, },
}, },
extend: { extend: {
keyframes: {
"accordion-down": {
from: { height: 0 },
to: { height: "var(--radix-accordion-content-height)" },
},
"accordion-up": {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "accordion-down 0.2s ease-out",
"accordion-up": "accordion-up 0.2s ease-out",
},
colors: { colors: {
connection: "var(--connection)", connection: "var(--connection)",
"almost-dark-gray": "var(--almost-dark-gray)", "almost-dark-gray": "var(--almost-dark-gray)",
@ -129,20 +115,6 @@ module.exports = {
fontFamily: { fontFamily: {
sans: ["var(--font-sans)", ...fontFamily.sans], sans: ["var(--font-sans)", ...fontFamily.sans],
}, },
keyframes: {
slideDown: {
from: { height: 0 },
to: { height: 100 },
},
slideUp: {
from: { height: "var(--radix-accordion-content-height)" },
to: { height: 0 },
},
},
animation: {
"accordion-down": "slideDown 300ms ease-out",
"accordion-up": "slideUp 300ms ease-in",
},
}, },
}, },
@ -214,6 +186,7 @@ module.exports = {
"&::-webkit-scrollbar-thumb:hover": { "&::-webkit-scrollbar-thumb:hover": {
backgroundColor: "#bbb", backgroundColor: "#bbb",
}, },
"cursor": "auto"
}, },
".dark .theme-attribution .react-flow__attribution": { ".dark .theme-attribution .react-flow__attribution": {
backgroundColor: "rgba(255, 255, 255, 0.2)", backgroundColor: "rgba(255, 255, 255, 0.2)",