Fix formatting issues and add missing semicolons
This commit is contained in:
parent
41b3c29332
commit
44b0ca9a15
12 changed files with 116 additions and 146 deletions
|
|
@ -135,7 +135,9 @@ export default function GenericNode({
|
|||
position={{ x: xPos, y: yPos }}
|
||||
data={data}
|
||||
deleteNode={deleteNode}
|
||||
setShowNode={(showNode: boolean) => {data.showNode = showNode}}
|
||||
setShowNode={(showNode: boolean) => {
|
||||
data.showNode = showNode;
|
||||
}}
|
||||
numberOfHandles={handles}
|
||||
showNode={showNode}
|
||||
></NodeToolbarComponent>
|
||||
|
|
@ -513,7 +515,7 @@ export default function GenericNode({
|
|||
dataType: data.type,
|
||||
})}
|
||||
data={data}
|
||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||
color={nodeColors[types[data.type]] ?? nodeColors.unknown}
|
||||
title={
|
||||
data.node?.output_types && data.node.output_types.length > 0
|
||||
? data.node.output_types.join("|")
|
||||
|
|
|
|||
|
|
@ -418,7 +418,10 @@ export function FlowsProvider({ children }: { children: ReactNode }) {
|
|||
|
||||
const insidePosition = position.paneX
|
||||
? { x: position.paneX + position.x, y: position.paneY! + position.y }
|
||||
: reactFlowInstance!.screenToFlowPosition({ x: position.x, y: position.y });
|
||||
: reactFlowInstance!.screenToFlowPosition({
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
});
|
||||
|
||||
selectionInstance.nodes.forEach((node: NodeType) => {
|
||||
// Generate a unique node ID
|
||||
|
|
|
|||
|
|
@ -357,10 +357,10 @@ export async function postCustomComponent(
|
|||
code: string,
|
||||
apiClass: APIClassType
|
||||
): Promise<AxiosResponse<APIClassType>> {
|
||||
let template = apiClass.template
|
||||
let template = apiClass.template;
|
||||
return await api.post(`${BASE_URL_API}custom_component`, {
|
||||
code,
|
||||
template
|
||||
template,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { InfinityIcon, Terminal, Code } from "lucide-react";
|
||||
import { Code } from "lucide-react";
|
||||
import { forwardRef } from "react";
|
||||
import ForwardedIconComponent from "../../components/genericIconComponent";
|
||||
|
||||
|
|
@ -21,7 +21,6 @@ export const GradientInfinity = forwardRef<
|
|||
);
|
||||
});
|
||||
|
||||
|
||||
export const GradientSave = forwardRef<
|
||||
SVGSVGElement,
|
||||
React.PropsWithChildren<{}>
|
||||
|
|
@ -38,7 +37,7 @@ export const GradientSave = forwardRef<
|
|||
</svg>
|
||||
<ForwardedIconComponent
|
||||
name="Save"
|
||||
stroke="url(#grad2)"
|
||||
stroke="url(#grad2)"
|
||||
ref={ref}
|
||||
{...props}
|
||||
/>
|
||||
|
|
@ -57,11 +56,7 @@ export const GradientGroup = (props) => {
|
|||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
<ForwardedIconComponent
|
||||
name="Combine"
|
||||
stroke="url(#grad3)"
|
||||
{...props}
|
||||
/>
|
||||
<ForwardedIconComponent name="Combine" stroke="url(#grad3)" {...props} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ export default function DeleteConfirmationModal({
|
|||
</span>
|
||||
<DialogFooter>
|
||||
<DialogClose>
|
||||
<Button className="mr-3" variant="outline">Cancel</Button>
|
||||
<Button className="mr-3" variant="outline">
|
||||
Cancel
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="submit"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { cloneDeep } from "lodash";
|
||||
import { forwardRef, useContext, useEffect, useRef, useState } from "react";
|
||||
import { forwardRef, useContext, useEffect, useState } from "react";
|
||||
import { useUpdateNodeInternals } from "reactflow";
|
||||
import ShadTooltip from "../../components/ShadTooltipComponent";
|
||||
import CodeAreaComponent from "../../components/codeAreaComponent";
|
||||
|
|
@ -85,7 +85,6 @@ const EditNodeModal = forwardRef(
|
|||
updateNodeInternals(data.id);
|
||||
};
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
setMyData(data); // reset data to what it is on node when opening modal
|
||||
|
|
@ -156,64 +155,52 @@ const EditNodeModal = forwardRef(
|
|||
<TableCell className="truncate p-0 text-center text-sm text-foreground sm:px-3">
|
||||
<ShadTooltip
|
||||
content={
|
||||
myData.node?.template[templateParam]
|
||||
.proxy
|
||||
? myData.node?.template[
|
||||
templateParam
|
||||
].proxy?.id
|
||||
myData.node?.template[templateParam].proxy
|
||||
? myData.node?.template[templateParam].proxy
|
||||
?.id
|
||||
: null
|
||||
}
|
||||
>
|
||||
<span>
|
||||
{myData.node?.template[templateParam]
|
||||
.display_name
|
||||
? myData.node.template[
|
||||
templateParam
|
||||
].display_name
|
||||
: myData.node?.template[
|
||||
templateParam
|
||||
].name}
|
||||
? myData.node.template[templateParam]
|
||||
.display_name
|
||||
: myData.node?.template[templateParam].name}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
</TableCell>
|
||||
<TableCell className="w-[300px] p-0 text-center text-xs text-foreground ">
|
||||
{myData.node?.template[templateParam]
|
||||
.type === "str" &&
|
||||
!myData.node.template[templateParam]
|
||||
.options ? (
|
||||
{myData.node?.template[templateParam].type ===
|
||||
"str" &&
|
||||
!myData.node.template[templateParam].options ? (
|
||||
<div className="mx-auto">
|
||||
{myData.node.template[templateParam]
|
||||
.list ? (
|
||||
{myData.node.template[templateParam].list ? (
|
||||
<InputListComponent
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
!myData.node.template[
|
||||
templateParam
|
||||
].value ||
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value === ""
|
||||
!myData.node.template[templateParam]
|
||||
.value ||
|
||||
myData.node.template[templateParam]
|
||||
.value === ""
|
||||
? [""]
|
||||
: myData.node.template[
|
||||
templateParam
|
||||
].value
|
||||
: myData.node.template[templateParam]
|
||||
.value
|
||||
}
|
||||
onChange={(value: string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
/>
|
||||
) : myData.node.template[
|
||||
templateParam
|
||||
].multiline ? (
|
||||
) : myData.node.template[templateParam]
|
||||
.multiline ? (
|
||||
<TextAreaComponent
|
||||
id={"textarea-edit-" + index}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
|
|
@ -225,14 +212,12 @@ const EditNodeModal = forwardRef(
|
|||
editNode={true}
|
||||
disabled={disabled}
|
||||
password={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].password ?? false
|
||||
myData.node.template[templateParam]
|
||||
.password ?? false
|
||||
}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
|
|
@ -240,8 +225,8 @@ const EditNodeModal = forwardRef(
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "NestedDict" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"NestedDict" ? (
|
||||
<div className=" w-full">
|
||||
<DictComponent
|
||||
disabled={disabled}
|
||||
|
|
@ -253,9 +238,8 @@ const EditNodeModal = forwardRef(
|
|||
? {
|
||||
yourkey: "value",
|
||||
}
|
||||
: myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
: myData.node!.template[templateParam]
|
||||
.value
|
||||
}
|
||||
onChange={(newValue) => {
|
||||
myData.node!.template[
|
||||
|
|
@ -266,13 +250,13 @@ const EditNodeModal = forwardRef(
|
|||
id="editnode-div-dict-input"
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "dict" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"dict" ? (
|
||||
<div
|
||||
className={classNames(
|
||||
"max-h-48 w-full overflow-auto custom-scroll",
|
||||
myData.node!.template[templateParam]
|
||||
.value?.length > 1
|
||||
myData.node!.template[templateParam].value
|
||||
?.length > 1
|
||||
? "my-3"
|
||||
: ""
|
||||
)}
|
||||
|
|
@ -281,17 +265,14 @@ const EditNodeModal = forwardRef(
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value?.length === 0 ||
|
||||
!myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
myData.node!.template[templateParam].value
|
||||
?.length === 0 ||
|
||||
!myData.node!.template[templateParam]
|
||||
.value
|
||||
? [{ "": "" }]
|
||||
: convertObjToArray(
|
||||
myData.node!.template[
|
||||
templateParam
|
||||
].value
|
||||
myData.node!.template[templateParam]
|
||||
.value
|
||||
)
|
||||
}
|
||||
duplicateKey={errorDuplicateKey}
|
||||
|
|
@ -311,17 +292,15 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "bool" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"bool" ? (
|
||||
<div className="ml-auto">
|
||||
{" "}
|
||||
<ToggleShadComponent
|
||||
id={"toggle-edit-" + index}
|
||||
disabled={disabled}
|
||||
enabled={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value
|
||||
myData.node.template[templateParam].value
|
||||
}
|
||||
setEnabled={(isEnabled) => {
|
||||
handleOnNewValue(
|
||||
|
|
@ -332,86 +311,78 @@ const EditNodeModal = forwardRef(
|
|||
size="small"
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "float" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"float" ? (
|
||||
<div className="mx-auto">
|
||||
<FloatComponent
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "str" &&
|
||||
myData.node.template[templateParam]
|
||||
.options ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"str" &&
|
||||
myData.node.template[templateParam].options ? (
|
||||
<div className="mx-auto">
|
||||
<Dropdown
|
||||
numberOfOptions={nodeLength}
|
||||
editNode={true}
|
||||
options={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].options
|
||||
myData.node.template[templateParam]
|
||||
.options
|
||||
}
|
||||
onSelect={(value) =>
|
||||
handleOnNewValue(value, templateParam)
|
||||
}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? "Choose an option"
|
||||
myData.node.template[templateParam]
|
||||
.value ?? "Choose an option"
|
||||
}
|
||||
id={"dropdown-edit-" + index}
|
||||
></Dropdown>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "int" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"int" ? (
|
||||
<div className="mx-auto">
|
||||
<IntComponent
|
||||
id={"int-input-" + index}
|
||||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "file" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"file" ? (
|
||||
<div className="mx-auto">
|
||||
<InputFileComponent
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
}}
|
||||
fileTypes={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].fileTypes
|
||||
myData.node.template[templateParam]
|
||||
.fileTypes
|
||||
}
|
||||
suffixes={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].suffixes
|
||||
myData.node.template[templateParam]
|
||||
.suffixes
|
||||
}
|
||||
onFileChange={(filePath: string) => {
|
||||
data.node!.template[
|
||||
|
|
@ -420,13 +391,11 @@ const EditNodeModal = forwardRef(
|
|||
}}
|
||||
></InputFileComponent>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "prompt" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"prompt" ? (
|
||||
<div className="mx-auto">
|
||||
<PromptAreaComponent
|
||||
readonly={
|
||||
myData.node?.flow ? true : false
|
||||
}
|
||||
readonly={myData.node?.flow ? true : false}
|
||||
field_name={templateParam}
|
||||
editNode={true}
|
||||
disabled={disabled}
|
||||
|
|
@ -435,9 +404,8 @@ const EditNodeModal = forwardRef(
|
|||
myData.node = nodeClass;
|
||||
}}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
|
|
@ -445,15 +413,14 @@ const EditNodeModal = forwardRef(
|
|||
id={"prompt-area-edit" + index}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "code" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"code" ? (
|
||||
<div className="mx-auto">
|
||||
<CodeAreaComponent
|
||||
readonly={
|
||||
myData.node?.flow &&
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].dynamic
|
||||
myData.node.template[templateParam]
|
||||
.dynamic
|
||||
? true
|
||||
: false
|
||||
}
|
||||
|
|
@ -468,9 +435,8 @@ const EditNodeModal = forwardRef(
|
|||
disabled={disabled}
|
||||
editNode={true}
|
||||
value={
|
||||
myData.node.template[
|
||||
templateParam
|
||||
].value ?? ""
|
||||
myData.node.template[templateParam]
|
||||
.value ?? ""
|
||||
}
|
||||
onChange={(value: string | string[]) => {
|
||||
handleOnNewValue(value, templateParam);
|
||||
|
|
@ -478,8 +444,8 @@ const EditNodeModal = forwardRef(
|
|||
id={"code-area-edit" + index}
|
||||
/>
|
||||
</div>
|
||||
) : myData.node?.template[templateParam]
|
||||
.type === "Any" ? (
|
||||
) : myData.node?.template[templateParam].type ===
|
||||
"Any" ? (
|
||||
"-"
|
||||
) : (
|
||||
<div className="hidden"></div>
|
||||
|
|
@ -490,13 +456,11 @@ const EditNodeModal = forwardRef(
|
|||
<ToggleShadComponent
|
||||
id={
|
||||
"show" +
|
||||
myData.node?.template[templateParam]
|
||||
.name
|
||||
myData.node?.template[templateParam].name
|
||||
}
|
||||
enabled={
|
||||
!myData.node?.template[
|
||||
templateParam
|
||||
].advanced
|
||||
!myData.node?.template[templateParam]
|
||||
.advanced
|
||||
}
|
||||
setEnabled={(e) => {
|
||||
changeAdvanced(templateParam);
|
||||
|
|
@ -521,7 +485,7 @@ const EditNodeModal = forwardRef(
|
|||
id={"saveChangesBtn"}
|
||||
className="mt-3"
|
||||
onClick={() => {
|
||||
data.node = myData.node
|
||||
data.node = myData.node;
|
||||
//@ts-ignore
|
||||
setTabsState((prev: FlowsState) => {
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -150,9 +150,7 @@ function BaseModal({
|
|||
<div className="truncate-doubleline word-break-break-word">
|
||||
{headerChild}
|
||||
</div>
|
||||
<div className={`flex flex-col ${height!} w-full `}>
|
||||
{ContentChild}
|
||||
</div>
|
||||
<div className={`flex flex-col ${height!} w-full `}>{ContentChild}</div>
|
||||
{ContentFooter && (
|
||||
<div className="flex flex-row-reverse">{ContentFooter}</div>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { NodeToolbar } from "reactflow";
|
||||
import IconComponent from "../../../../components/genericIconComponent";
|
||||
import { GradientGroup } from "../../../../icons/GradientSparkles";
|
||||
export default function SelectionMenu({ onClick, nodes, isVisible }) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
|
@ -38,7 +37,7 @@ export default function SelectionMenu({ onClick, nodes, isVisible }) {
|
|||
<div className="h-10 w-28 overflow-hidden">
|
||||
<div
|
||||
className={
|
||||
"h-10 w-24 rounded-md border border-indigo-300 bg-white px-2.5 text-gray-700 shadow-inner transition-all duration-400 ease-in-out dark:bg-gray-800 dark:text-gray-300" +
|
||||
"duration-400 h-10 w-24 rounded-md border border-indigo-300 bg-white px-2.5 text-gray-700 shadow-inner transition-all ease-in-out dark:bg-gray-800 dark:text-gray-300" +
|
||||
(isTransitioning ? " opacity-100" : " opacity-0 ")
|
||||
}
|
||||
>
|
||||
|
|
@ -46,7 +45,11 @@ export default function SelectionMenu({ onClick, nodes, isVisible }) {
|
|||
className="flex h-full w-full items-center justify-between text-sm hover:text-indigo-500"
|
||||
onClick={onClick}
|
||||
>
|
||||
<GradientGroup strokeWidth={1.5} size={22} className="text-primary" />
|
||||
<GradientGroup
|
||||
strokeWidth={1.5}
|
||||
size={22}
|
||||
className="text-primary"
|
||||
/>
|
||||
Group
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -344,10 +344,10 @@ export default function ExtraSidebar(): JSX.Element {
|
|||
} else if (b.toLowerCase() === "saved_components") {
|
||||
return 1;
|
||||
} else if (a.toLowerCase() === "custom_components") {
|
||||
return -2
|
||||
return -2;
|
||||
} else if (b.toLowerCase() === "custom_components") {
|
||||
return 2
|
||||
}else {
|
||||
return 2;
|
||||
} else {
|
||||
return a.localeCompare(b);
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
} from "../../../../components/ui/select-custom";
|
||||
import { FlowsContext } from "../../../../contexts/flowsContext";
|
||||
import { StoreContext } from "../../../../contexts/storeContext";
|
||||
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
||||
import ConfirmationModal from "../../../../modals/ConfirmationModal";
|
||||
import EditNodeModal from "../../../../modals/EditNodeModal";
|
||||
import ShareModal from "../../../../modals/shareModal";
|
||||
|
|
@ -23,7 +24,6 @@ import {
|
|||
updateFlowPosition,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { classNames } from "../../../../utils/utils";
|
||||
import { undoRedoContext } from "../../../../contexts/undoRedoContext";
|
||||
|
||||
export default function NodeToolbarComponent({
|
||||
data,
|
||||
|
|
@ -295,7 +295,8 @@ export default function NodeToolbarComponent({
|
|||
>
|
||||
<ConfirmationModal.Content>
|
||||
<span>
|
||||
It seems {data.node?.display_name} already exists. Do you want to replace it with the current or create a new one?
|
||||
It seems {data.node?.display_name} already exists. Do you want
|
||||
to replace it with the current or create a new one?
|
||||
</span>
|
||||
</ConfirmationModal.Content>
|
||||
<ConfirmationModal.Trigger>
|
||||
|
|
|
|||
|
|
@ -96,7 +96,9 @@ export default function ComponentsComponent({
|
|||
<div className="flex h-full w-full flex-col justify-between">
|
||||
<div className="flex w-full flex-col gap-4">
|
||||
{!isLoading && data.length === 0 ? (
|
||||
<div className="w-full text-center">You haven't created any {name}s yet.</div>
|
||||
<div className="w-full text-center">
|
||||
You haven't created any {name}s yet.
|
||||
</div>
|
||||
) : (
|
||||
<div className="grid w-full gap-4 md:grid-cols-2 lg:grid-cols-2">
|
||||
{!isLoading || data?.length > 0 ? (
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import {
|
|||
Circle,
|
||||
Clipboard,
|
||||
Code2,
|
||||
Combine,
|
||||
Compass,
|
||||
Copy,
|
||||
Cpu,
|
||||
|
|
@ -80,6 +81,7 @@ import {
|
|||
Square,
|
||||
Store,
|
||||
SunIcon,
|
||||
TerminalIcon,
|
||||
TerminalSquare,
|
||||
ToyBrick,
|
||||
Trash2,
|
||||
|
|
@ -99,8 +101,6 @@ import {
|
|||
X,
|
||||
XCircle,
|
||||
Zap,
|
||||
Combine,
|
||||
TerminalIcon
|
||||
} from "lucide-react";
|
||||
import { FaApple, FaGithub } from "react-icons/fa";
|
||||
import { AWSIcon } from "../icons/AWS";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue