fix: improve notes functionality, update theme colors definition and resolve ui and ux small bugs (#4414)
* Fixed background blur overlay color on dialogs * Try to fix f5 error * Fix text color of notes * Fix bg color of nodenode to first one available if not existent * Removed unused imports * Added new node colors * Updated color of placeholder note node * Fixed notes to appear as soon as when the add button is clicked * Added transparent option to notes * Fixed editor design * Fix design of notes editor * Update text color on the note node description * Added canvas dot variable * Added size and gap definition to background dots * Updated emerald colors and badge * used correct badges on tableAutoCellRender * Used correct colors on the component global variable badge * Fix color on light mode * Fixed emerald color on the status of component * Applied static pink to active icons on navs * Make sidebar narrower * Updated size of / * Fixed Beta and Legacy badges * Fixed position of chevron * Fixed node name input * Updated clear search button * Updated color for grid dots * Updated sidebar filter color * Added chat input check * Fixed sorting of flow sidebar component * Fix canvas color * Updated sticky notes test * Fixed tests * Fixed test
This commit is contained in:
parent
e5969b2f18
commit
de7b23ea93
27 changed files with 518 additions and 406 deletions
|
|
@ -1,6 +1,7 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<base href="/" />
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ export default function NodeDescription({
|
|||
selected,
|
||||
nodeId,
|
||||
emptyPlaceholder = "Double Click to Edit Description",
|
||||
placeholderClassName,
|
||||
charLimit,
|
||||
inputClassName,
|
||||
mdClassName,
|
||||
|
|
@ -20,6 +21,7 @@ export default function NodeDescription({
|
|||
selected: boolean;
|
||||
nodeId: string;
|
||||
emptyPlaceholder?: string;
|
||||
placeholderClassName?: string;
|
||||
charLimit?: number;
|
||||
inputClassName?: string;
|
||||
mdClassName?: string;
|
||||
|
|
@ -62,7 +64,8 @@ export default function NodeDescription({
|
|||
className={cn(
|
||||
!inputDescription ? "overflow-auto" : "",
|
||||
hasScroll ? "nowheel" : "",
|
||||
charLimit ? "px-2" : "",
|
||||
charLimit ? "px-2 pb-4" : "",
|
||||
"w-full",
|
||||
)}
|
||||
>
|
||||
{inputDescription ? (
|
||||
|
|
@ -114,10 +117,11 @@ export default function NodeDescription({
|
|||
{charLimit && (
|
||||
<div
|
||||
className={cn(
|
||||
"text-left text-[13px]",
|
||||
"pt-1 text-left text-[13px]",
|
||||
(nodeDescription?.length ?? 0) >= charLimit
|
||||
? "text-error"
|
||||
: "text-primary",
|
||||
placeholderClassName,
|
||||
)}
|
||||
data-testid="note_char_limit"
|
||||
>
|
||||
|
|
@ -130,8 +134,9 @@ export default function NodeDescription({
|
|||
data-testid="generic-node-desc"
|
||||
ref={overflowRef}
|
||||
className={cn(
|
||||
"nodoubleclick generic-node-desc-text h-full cursor-text text-[13px] word-break-break-word dark:text-note-placeholder",
|
||||
"nodoubleclick generic-node-desc-text h-full cursor-text text-[13px] word-break-break-word",
|
||||
description === "" || !description ? "font-light italic" : "",
|
||||
placeholderClassName,
|
||||
)}
|
||||
onDoubleClick={(e) => {
|
||||
setInputDescription(true);
|
||||
|
|
@ -144,7 +149,7 @@ export default function NodeDescription({
|
|||
<Markdown
|
||||
linkTarget="_blank"
|
||||
className={cn(
|
||||
"markdown prose flex h-full w-full flex-col text-[13px] leading-5 text-muted-foreground word-break-break-word dark:prose-invert",
|
||||
"markdown prose flex h-full w-full flex-col text-[13px] leading-5 text-foreground word-break-break-word",
|
||||
mdClassName,
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import InputComponent from "@/components/inputComponent";
|
||||
import { BuildStatus } from "@/constants/enums";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import { VertexBuildTypeAPI } from "@/types/api";
|
||||
|
|
@ -39,7 +38,7 @@ export default function NodeName({
|
|||
|
||||
return inputName ? (
|
||||
<div className="m-[1px] w-full">
|
||||
<InputComponent
|
||||
<Input
|
||||
onBlur={() => {
|
||||
setInputName(false);
|
||||
if (nodeName?.trim() !== "") {
|
||||
|
|
@ -60,10 +59,8 @@ export default function NodeName({
|
|||
}}
|
||||
value={nodeName}
|
||||
autoFocus
|
||||
onChange={setNodeName}
|
||||
password={false}
|
||||
blurOnEnter={true}
|
||||
id={`input-title-${display_name}`}
|
||||
onChange={(e) => setNodeName(e.target.value)}
|
||||
data-testid={`input-title-${display_name}`}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
import { useDarkStore } from "@/stores/darkStore";
|
||||
import useFlowStore from "@/stores/flowStore";
|
||||
import { log } from "console";
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { Handle, Position, useViewport } from "reactflow";
|
||||
import { Handle, Position } from "reactflow";
|
||||
import ShadTooltip from "../../../../components/shadTooltipComponent";
|
||||
import {
|
||||
isValidConnection,
|
||||
scapedJSONStringfy,
|
||||
} from "../../../../utils/reactflowUtils";
|
||||
import { classNames, cn, groupByFamily } from "../../../../utils/utils";
|
||||
import { cn, groupByFamily } from "../../../../utils/utils";
|
||||
import HandleTooltipComponent from "../HandleTooltipComponent";
|
||||
|
||||
export default function HandleRenderComponent({
|
||||
|
|
@ -42,7 +41,7 @@ export default function HandleRenderComponent({
|
|||
nodeId: string;
|
||||
colorName?: string[];
|
||||
}) {
|
||||
const handleColorName = colorName?.[0];
|
||||
const handleColorName = colorName?.[0] ?? "";
|
||||
|
||||
const innerColorName = `inner-${handleColorName}`;
|
||||
const innerForegroundColorName = `${innerColorName}-foreground`;
|
||||
|
|
@ -156,7 +155,7 @@ export default function HandleRenderComponent({
|
|||
source: undefined,
|
||||
sourceHandle: undefined,
|
||||
type: tooltipTitle,
|
||||
color: colors[0],
|
||||
color: handleColorName,
|
||||
}
|
||||
: {
|
||||
sourceHandle: myId,
|
||||
|
|
@ -164,7 +163,7 @@ export default function HandleRenderComponent({
|
|||
target: undefined,
|
||||
targetHandle: undefined,
|
||||
type: tooltipTitle,
|
||||
color: colors[0],
|
||||
color: handleColorName,
|
||||
},
|
||||
[left, myId, nodeId, tooltipTitle, colors],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -5,15 +5,12 @@ import { usePostValidateComponentCode } from "@/controllers/API/queries/nodes/us
|
|||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useHotkeys } from "react-hotkeys-hook";
|
||||
import { NodeToolbar, useUpdateNodeInternals } from "reactflow";
|
||||
import IconComponent, {
|
||||
ForwardedIconComponent,
|
||||
} from "../../components/genericIconComponent";
|
||||
import { ForwardedIconComponent } from "../../components/genericIconComponent";
|
||||
import ShadTooltip from "../../components/shadTooltipComponent";
|
||||
import { Button } from "../../components/ui/button";
|
||||
import {
|
||||
TOOLTIP_HIDDEN_OUTPUTS,
|
||||
TOOLTIP_OPEN_HIDDEN_OUTPUTS,
|
||||
TOOLTIP_OUTDATED_NODE,
|
||||
} from "../../constants/constants";
|
||||
import NodeToolbarComponent from "../../pages/FlowPage/components/nodeToolbarComponent";
|
||||
import useAlertStore from "../../stores/alertStore";
|
||||
|
|
@ -379,6 +376,7 @@ export default function GenericNode({
|
|||
<div>
|
||||
<NodeDescription
|
||||
description={data.node?.description}
|
||||
mdClassName={"dark:prose-invert"}
|
||||
nodeId={data.id}
|
||||
selected={selected}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@ import useAlertStore from "@/stores/alertStore";
|
|||
import useFlowStore from "@/stores/flowStore";
|
||||
import useFlowsManagerStore from "@/stores/flowsManagerStore";
|
||||
import { useShortcutsStore } from "@/stores/shortcuts";
|
||||
import { NodeDataType, noteDataType } from "@/types/flow";
|
||||
import { noteDataType } from "@/types/flow";
|
||||
import { classNames, cn, openInNewTab } from "@/utils/utils";
|
||||
import { cloneDeep, set, take } from "lodash";
|
||||
import { useState } from "react";
|
||||
import { cloneDeep } from "lodash";
|
||||
import IconComponent from "../../../components/genericIconComponent";
|
||||
|
||||
export default function NoteToolbarComponent({
|
||||
|
|
@ -30,7 +29,6 @@ export default function NoteToolbarComponent({
|
|||
data: noteDataType;
|
||||
bgColor: string;
|
||||
}) {
|
||||
const setSuccessData = useAlertStore((state) => state.setSuccessData);
|
||||
const setNoticeData = useAlertStore((state) => state.setNoticeData);
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
const setLastCopiedSelection = useFlowStore(
|
||||
|
|
@ -95,9 +93,12 @@ export default function NoteToolbarComponent({
|
|||
>
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: COLOR_OPTIONS[bgColor],
|
||||
backgroundColor: COLOR_OPTIONS[bgColor] ?? "#00000000",
|
||||
}}
|
||||
className="h-4 w-4 rounded-full"
|
||||
className={cn(
|
||||
"h-4 w-4 rounded-full",
|
||||
COLOR_OPTIONS[bgColor] === null && "border",
|
||||
)}
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -131,9 +132,10 @@ export default function NoteToolbarComponent({
|
|||
className={cn(
|
||||
"h-4 w-4 rounded-full hover:border hover:border-ring",
|
||||
bgColor === color ? "border-2 border-blue-500" : "",
|
||||
code === null && "border",
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: code,
|
||||
backgroundColor: code ?? "#00000000",
|
||||
}}
|
||||
></div>
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@ function NoteNode({
|
|||
selected: boolean;
|
||||
}) {
|
||||
const bgColor =
|
||||
data.node?.template.backgroundColor ?? Object.keys(COLOR_OPTIONS)[0];
|
||||
Object.keys(COLOR_OPTIONS).find(
|
||||
(key) => key === data.node?.template.backgroundColor,
|
||||
) ?? Object.keys(COLOR_OPTIONS)[0];
|
||||
const nodeDiv = useRef<HTMLDivElement>(null);
|
||||
const [size, setSize] = useState({ width: 0, height: 0 });
|
||||
//tricky to start the description with the right size
|
||||
|
|
@ -61,12 +63,13 @@ function NoteNode({
|
|||
maxWidth: NOTE_NODE_MAX_WIDTH,
|
||||
minWidth: NOTE_NODE_MIN_WIDTH,
|
||||
minHeight: NOTE_NODE_MIN_HEIGHT,
|
||||
backgroundColor: COLOR_OPTIONS[bgColor],
|
||||
backgroundColor: COLOR_OPTIONS[bgColor] ?? "#00000000",
|
||||
}}
|
||||
ref={nodeDiv}
|
||||
className={cn(
|
||||
"flex h-full w-full flex-col gap-3 border border-b p-3 transition-all",
|
||||
selected ? "" : "-z-50 shadow-sm",
|
||||
"flex h-full w-full flex-col gap-3 rounded-xl p-3 transition-all",
|
||||
COLOR_OPTIONS[bgColor] !== null &&
|
||||
`border ${!selected && "-z-50 shadow-sm"}`,
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
|
@ -77,13 +80,26 @@ function NoteNode({
|
|||
}}
|
||||
>
|
||||
<NodeDescription
|
||||
inputClassName="border-0 ring-transparent resize-none rounded-none shadow-none h-full w-full"
|
||||
style={{ backgroundColor: COLOR_OPTIONS[bgColor] }}
|
||||
inputClassName={cn(
|
||||
"border-0 ring-transparent resize-none shadow-none rounded-sm h-full w-full",
|
||||
COLOR_OPTIONS[bgColor] === null
|
||||
? ""
|
||||
: "dark:!ring-background dark:text-background",
|
||||
)}
|
||||
mdClassName={
|
||||
COLOR_OPTIONS[bgColor] === null
|
||||
? "dark:prose-invert"
|
||||
: "dark:!text-background"
|
||||
}
|
||||
style={{ backgroundColor: COLOR_OPTIONS[bgColor] ?? "#00000000" }}
|
||||
charLimit={2500}
|
||||
nodeId={data.id}
|
||||
selected={selected}
|
||||
description={data.node?.description}
|
||||
emptyPlaceholder="Double-click to start typing or enter Markdown..."
|
||||
placeholderClassName={
|
||||
COLOR_OPTIONS[bgColor] === null ? "" : "dark:!text-background"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
import { cn } from "@/utils/utils";
|
||||
import { PopoverAnchor } from "@radix-ui/react-popover";
|
||||
import { X } from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
const CustomInputPopover = ({
|
||||
id,
|
||||
|
|
@ -97,11 +97,10 @@ const CustomInputPopover = ({
|
|||
))
|
||||
) : selectedOption?.length > 0 ? (
|
||||
<Badge
|
||||
variant="secondary"
|
||||
variant={nodeStyle ? "emerald" : "secondary"}
|
||||
className={cn(
|
||||
"flex items-center gap-1 truncate bg-muted",
|
||||
nodeStyle &&
|
||||
"font-jetbrains rounded-[3px] bg-emerald-100 px-1 text-emerald-700 hover:bg-emerald-200",
|
||||
"flex items-center gap-1 truncate",
|
||||
nodeStyle ? "font-jetbrains rounded-[3px] px-1" : "bg-muted",
|
||||
)}
|
||||
>
|
||||
<div className="max-w-36 truncate">{selectedOption}</div>
|
||||
|
|
|
|||
|
|
@ -40,11 +40,9 @@ export default function TableAutoCellRender({
|
|||
else if (value === "success") {
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
variant="successStatic"
|
||||
size="sq"
|
||||
className={cn(
|
||||
"h-[18px] w-full justify-center bg-success-background text-success-foreground hover:bg-success-background",
|
||||
)}
|
||||
className={cn("h-[18px] w-full justify-center")}
|
||||
>
|
||||
{value}
|
||||
</Badge>
|
||||
|
|
@ -52,11 +50,9 @@ export default function TableAutoCellRender({
|
|||
} else if (value === "failure") {
|
||||
return (
|
||||
<Badge
|
||||
variant="outline"
|
||||
variant="errorStatic"
|
||||
size="sq"
|
||||
className={cn(
|
||||
"h-[18px] w-full justify-center bg-error-background text-error-foreground hover:bg-error-background",
|
||||
)}
|
||||
className={cn("h-[18px] w-full justify-center")}
|
||||
>
|
||||
{value}
|
||||
</Badge>
|
||||
|
|
|
|||
|
|
@ -15,15 +15,20 @@ const badgeVariants = cva(
|
|||
destructive:
|
||||
"bg-destructive hover:bg-destructive/80 border-transparent text-destructive-foreground",
|
||||
outline: "text-primary/80 border-ring/60",
|
||||
secondaryStatic: "bg-input text-muted-foreground border-0",
|
||||
secondaryStatic: "bg-muted text-muted-foreground border-0",
|
||||
pinkStatic: "bg-accent-pink text-accent-pink-foreground border-0",
|
||||
emerald:
|
||||
"bg-accent-emerald text-accent-emerald-foreground hover:bg-accent-emerald-hover",
|
||||
successStatic:
|
||||
"bg-accent-emerald text-accent-emerald-foreground border-0",
|
||||
errorStatic: "bg-error-background text-error-foreground border-0",
|
||||
},
|
||||
size: {
|
||||
sm: "h-4 text-xs",
|
||||
md: "h-5 text-sm",
|
||||
lg: "h-6 text-base",
|
||||
sq: "h-6 px-1.5 text-sm font-medium rounded-md",
|
||||
xq: "h-5 px-1 text-xs font-medium rounded-md",
|
||||
xq: "h-6 px-1.5 text-xs font-medium rounded-sm",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ const DialogOverlay = React.forwardRef<
|
|||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"nopan nodelete nodrag noflow fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"nopan nodelete nodrag noflow fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ const DialogOverlay = React.forwardRef<
|
|||
<DialogPrimitive.Overlay
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"nopan nodelete nodrag noflow fixed inset-0 bottom-0 left-0 right-0 top-0 z-40 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"nopan nodelete nodrag noflow fixed inset-0 bottom-0 left-0 right-0 top-0 z-40 overflow-auto bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ const SheetOverlay = React.forwardRef<
|
|||
>(({ className, ...props }, ref) => (
|
||||
<SheetPrimitive.Overlay
|
||||
className={cn(
|
||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
"fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
|
|
|||
|
|
@ -871,7 +871,7 @@ export const LOCATIONS_TO_RETURN = ["/flow/", "/settings/"];
|
|||
export const MAX_BATCH_SIZE = 50;
|
||||
|
||||
export const MODAL_CLASSES =
|
||||
"nopan nodelete nodrag noflow fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-blur-shared backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0";
|
||||
"nopan nodelete nodrag noflow fixed inset-0 bottom-0 left-0 right-0 top-0 z-50 overflow-auto bg-black/50 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0";
|
||||
|
||||
export const ALLOWED_IMAGE_INPUT_EXTENSIONS = ["png", "jpg", "jpeg"];
|
||||
|
||||
|
|
@ -926,19 +926,12 @@ export const NOTE_NODE_MAX_HEIGHT = 800;
|
|||
export const NOTE_NODE_MAX_WIDTH = 600;
|
||||
|
||||
export const COLOR_OPTIONS = {
|
||||
default: "var(--note-default)",
|
||||
indigo: "var(--note-indigo)",
|
||||
emerald: "var(--note-emerald)",
|
||||
amber: "var(--note-amber)",
|
||||
red: "var(--note-red)",
|
||||
};
|
||||
|
||||
export const SHADOW_COLOR_OPTIONS = {
|
||||
default: "var(--note-default-opacity)",
|
||||
indigo: "var(--note-indigo-opacity)",
|
||||
emerald: "var(--note-emerald-opacity)",
|
||||
amber: "var(--note-amber-opacity)",
|
||||
red: "var(--note-red-opacity)",
|
||||
amber: "hsl(var(--note-amber))",
|
||||
neutral: "hsl(var(--note-neutral))",
|
||||
rose: "hsl(var(--note-rose))",
|
||||
blue: "hsl(var(--note-blue))",
|
||||
lime: "hsl(var(--note-lime))",
|
||||
transparent: null,
|
||||
};
|
||||
|
||||
export const maxSizeFilesInBytes = 10 * 1024 * 1024; // 10MB in bytes
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ export function SaveChangesModal({
|
|||
>
|
||||
<ConfirmationModal.Content>
|
||||
{autoSave ? (
|
||||
<div className="mb-4 flex w-full items-center gap-3 rounded-md bg-gray-100 px-4 py-2 text-gray-800 dark:bg-gray-900/40 dark:text-gray-100">
|
||||
<div className="mb-4 flex w-full items-center gap-3 rounded-md bg-muted px-4 py-2 text-muted-foreground">
|
||||
<Loading className="h-5 w-5" />
|
||||
Saving your changes...
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ export function Nav({ categories, currentTab, setCurrentTab }: NavProps) {
|
|||
name={link.icon}
|
||||
className={`h-4 w-4 stroke-2 ${
|
||||
currentTab === link.id
|
||||
? "x-gradient"
|
||||
? "text-accent-pink-foreground"
|
||||
: "text-muted-foreground"
|
||||
}`}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ import ForwardedIconComponent from "@/components/genericIconComponent";
|
|||
import LoadingComponent from "@/components/loadingComponent";
|
||||
import { SidebarTrigger, useSidebar } from "@/components/ui/sidebar";
|
||||
import {
|
||||
COLOR_OPTIONS,
|
||||
NOTE_NODE_MIN_HEIGHT,
|
||||
NOTE_NODE_MIN_WIDTH,
|
||||
SHADOW_COLOR_OPTIONS,
|
||||
} from "@/constants/constants";
|
||||
import { useGetBuildsQuery } from "@/controllers/API/queries/_builds";
|
||||
import { track } from "@/customization/utils/analytics";
|
||||
|
|
@ -196,8 +196,7 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
const zoomLevel = reactFlowInstance?.getZoom();
|
||||
const shadowBoxWidth = NOTE_NODE_MIN_WIDTH * (zoomLevel || 1);
|
||||
const shadowBoxHeight = NOTE_NODE_MIN_HEIGHT * (zoomLevel || 1);
|
||||
const shadowBoxBackgroundColor =
|
||||
SHADOW_COLOR_OPTIONS[Object.keys(SHADOW_COLOR_OPTIONS)[0]];
|
||||
const shadowBoxBackgroundColor = COLOR_OPTIONS[Object.keys(COLOR_OPTIONS)[0]];
|
||||
|
||||
function handleGroupNode() {
|
||||
takeSnapshot();
|
||||
|
|
@ -432,6 +431,11 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
const onDrop = useCallback(
|
||||
(event: React.DragEvent) => {
|
||||
event.preventDefault();
|
||||
const grabbingElement =
|
||||
document.getElementsByClassName("cursor-grabbing");
|
||||
if (grabbingElement.length > 0) {
|
||||
document.body.removeChild(grabbingElement[0]);
|
||||
}
|
||||
if (event.dataTransfer.types.some((type) => isSupportedNodeTypes(type))) {
|
||||
takeSnapshot();
|
||||
|
||||
|
|
@ -561,20 +565,6 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
[isAddingNote, setNodes, reactFlowInstance, getNodeId, setFilterEdge],
|
||||
);
|
||||
|
||||
const onPaneMouseMove = useCallback(
|
||||
(event: React.MouseEvent) => {
|
||||
if (isAddingNote) {
|
||||
const shadowBox = document.getElementById("shadow-box");
|
||||
if (shadowBox) {
|
||||
shadowBox.style.display = "block";
|
||||
shadowBox.style.left = `${event.clientX - shadowBoxWidth / 2}px`;
|
||||
shadowBox.style.top = `${event.clientY - shadowBoxHeight / 2}px`;
|
||||
}
|
||||
}
|
||||
},
|
||||
[isAddingNote],
|
||||
);
|
||||
|
||||
const handleEdgeClick = (event, edge) => {
|
||||
const color =
|
||||
nodeColorsName[edge?.data?.targetHandle?.inputTypes[0]] ||
|
||||
|
|
@ -588,6 +578,25 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
|
||||
const { open } = useSidebar();
|
||||
|
||||
useEffect(() => {
|
||||
const handleGlobalMouseMove = (event) => {
|
||||
if (isAddingNote) {
|
||||
const shadowBox = document.getElementById("shadow-box");
|
||||
if (shadowBox) {
|
||||
shadowBox.style.display = "block";
|
||||
shadowBox.style.left = `${event.clientX - shadowBoxWidth / 2}px`;
|
||||
shadowBox.style.top = `${event.clientY - shadowBoxHeight / 2}px`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("mousemove", handleGlobalMouseMove);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("mousemove", handleGlobalMouseMove);
|
||||
};
|
||||
}, [isAddingNote, shadowBoxWidth, shadowBoxHeight]);
|
||||
|
||||
return (
|
||||
<div className="h-full w-full bg-canvas" ref={reactFlowWrapper}>
|
||||
{showCanvas ? (
|
||||
|
|
@ -625,10 +634,9 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
panActivationKeyCode={""}
|
||||
proOptions={{ hideAttribution: true }}
|
||||
onPaneClick={onPaneClick}
|
||||
onPaneMouseMove={onPaneMouseMove}
|
||||
onEdgeClick={handleEdgeClick}
|
||||
>
|
||||
<Background className="" />
|
||||
<Background size={2} gap={20} className="" />
|
||||
{!view && (
|
||||
<>
|
||||
<CanvasControls>
|
||||
|
|
@ -637,6 +645,12 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
tooltipText="Add Note"
|
||||
onClick={() => {
|
||||
setIsAddingNote(true);
|
||||
const shadowBox = document.getElementById("shadow-box");
|
||||
if (shadowBox) {
|
||||
shadowBox.style.display = "block";
|
||||
shadowBox.style.left = `${position.current.x - shadowBoxWidth / 2}px`;
|
||||
shadowBox.style.top = `${position.current.y - shadowBoxHeight / 2}px`;
|
||||
}
|
||||
}}
|
||||
iconClasses="text-primary"
|
||||
testId="add_note"
|
||||
|
|
@ -678,6 +692,7 @@ export default function Page({ view }: { view?: boolean }): JSX.Element {
|
|||
width: `${shadowBoxWidth}px`,
|
||||
height: `${shadowBoxHeight}px`,
|
||||
backgroundColor: `${shadowBoxBackgroundColor}`,
|
||||
opacity: 0.7,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
></div>
|
||||
|
|
|
|||
|
|
@ -5,18 +5,25 @@ import { Button } from "@/components/ui/button";
|
|||
export function SidebarFilterComponent({
|
||||
isInput,
|
||||
type,
|
||||
color,
|
||||
resetFilters,
|
||||
}: {
|
||||
isInput: boolean;
|
||||
type: string;
|
||||
color: string;
|
||||
resetFilters: () => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="mb-0.5 flex w-full items-center justify-between rounded border bg-accent-indigo p-2 text-sm text-foreground">
|
||||
<div
|
||||
className={`mb-0.5 flex w-full items-center justify-between rounded border p-2 text-sm text-foreground`}
|
||||
style={{
|
||||
backgroundColor: `hsl(var(--inner-${color}-foreground))`,
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-1 items-center gap-1.5">
|
||||
<ForwardedIconComponent
|
||||
name="ListFilter"
|
||||
className="h-4 w-4 shrink-0 stroke-2 text-accent-indigo-foreground"
|
||||
className={`h-4 w-4 shrink-0 stroke-2`}
|
||||
/>
|
||||
<div className="flex flex-1">
|
||||
{isInput ? "Input" : "Output"}:{" "}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ export const SidebarDraggableComponent = forwardRef(
|
|||
official,
|
||||
beta,
|
||||
legacy,
|
||||
disabled,
|
||||
disabledTooltip,
|
||||
}: {
|
||||
sectionName: string;
|
||||
apiClass: APIClassType;
|
||||
|
|
@ -49,6 +51,8 @@ export const SidebarDraggableComponent = forwardRef(
|
|||
official: boolean;
|
||||
beta: boolean;
|
||||
legacy: boolean;
|
||||
disabled?: boolean;
|
||||
disabledTooltip?: string;
|
||||
},
|
||||
ref,
|
||||
) => {
|
||||
|
|
@ -103,116 +107,129 @@ export const SidebarDraggableComponent = forwardRef(
|
|||
open={open}
|
||||
key={itemName}
|
||||
>
|
||||
<div
|
||||
onPointerDown={handlePointerDown}
|
||||
onContextMenuCapture={(e) => {
|
||||
e.preventDefault();
|
||||
setOpen(true);
|
||||
}}
|
||||
key={itemName}
|
||||
data-tooltip-id={itemName}
|
||||
tabIndex={0}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="rounded-md outline-none ring-ring focus-visible:ring-2"
|
||||
<ShadTooltip
|
||||
content={disabled ? disabledTooltip : null}
|
||||
styleClasses="z-50"
|
||||
>
|
||||
<div
|
||||
data-testid={sectionName + display_name}
|
||||
id={sectionName + display_name}
|
||||
className={cn(
|
||||
"group/draggable flex cursor-grab items-center gap-2 rounded-md bg-muted p-3 hover:bg-secondary-hover/75",
|
||||
error ? "cursor-not-allowed select-none" : "",
|
||||
)}
|
||||
draggable={!error}
|
||||
style={{
|
||||
borderLeftColor: color,
|
||||
}}
|
||||
onDragStart={onDragStart}
|
||||
onDragEnd={() => {
|
||||
document.body.removeChild(
|
||||
document.getElementsByClassName("cursor-grabbing")[0],
|
||||
);
|
||||
onPointerDown={handlePointerDown}
|
||||
onContextMenuCapture={(e) => {
|
||||
e.preventDefault();
|
||||
setOpen(true);
|
||||
}}
|
||||
key={itemName}
|
||||
data-tooltip-id={itemName}
|
||||
tabIndex={0}
|
||||
onKeyDown={handleKeyDown}
|
||||
className="rounded-md outline-none ring-ring focus-visible:ring-2"
|
||||
>
|
||||
<ForwardedIconComponent name={icon} className="h-5 w-5 shrink-0" />
|
||||
<div className="flex flex-1 items-center overflow-hidden">
|
||||
<ShadTooltip content={display_name} styleClasses="z-50">
|
||||
<span className="truncate text-sm font-semibold">
|
||||
{display_name}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
{beta && (
|
||||
<Badge
|
||||
variant="pinkStatic"
|
||||
size="sq"
|
||||
className="ml-1.5 shrink-0"
|
||||
>
|
||||
BETA
|
||||
</Badge>
|
||||
<div
|
||||
data-testid={sectionName + display_name}
|
||||
id={sectionName + display_name}
|
||||
className={cn(
|
||||
"group/draggable flex cursor-grab items-center gap-2 rounded-md bg-muted p-3 hover:bg-secondary-hover/75",
|
||||
error && "cursor-not-allowed select-none",
|
||||
disabled
|
||||
? "pointer-events-none bg-accent text-placeholder-foreground"
|
||||
: "bg-muted text-foreground",
|
||||
)}
|
||||
{legacy && (
|
||||
<Badge
|
||||
variant="secondaryStatic"
|
||||
size="sq"
|
||||
className="ml-1.5 shrink-0"
|
||||
>
|
||||
LEGACY
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
tabIndex={-1}
|
||||
className="text-primary"
|
||||
onClick={() => addComponent(apiClass, itemName)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name="Plus"
|
||||
className="h-4 w-4 shrink-0 transition-all group-hover/draggable:opacity-100 group-focus/draggable:opacity-100 sm:opacity-0"
|
||||
/>
|
||||
</Button>
|
||||
<div ref={popoverRef}>
|
||||
<ForwardedIconComponent
|
||||
name="GripVertical"
|
||||
className="h-4 w-4 shrink-0 text-muted-foreground group-hover/draggable:text-primary"
|
||||
/>
|
||||
<SelectTrigger tabIndex={-1}></SelectTrigger>
|
||||
<SelectContent
|
||||
position="popper"
|
||||
side="bottom"
|
||||
sideOffset={-25}
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: cursorPos.x,
|
||||
top: cursorPos.y,
|
||||
}}
|
||||
>
|
||||
<SelectItem value={"download"}>
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name="Download"
|
||||
className="relative top-0.5 mr-2 h-4 w-4"
|
||||
/>{" "}
|
||||
Download{" "}
|
||||
</div>{" "}
|
||||
</SelectItem>
|
||||
{!official && (
|
||||
<SelectItem value={"delete"}>
|
||||
draggable={!error}
|
||||
style={{
|
||||
borderLeftColor: color,
|
||||
}}
|
||||
onDragStart={onDragStart}
|
||||
onDragEnd={() => {
|
||||
document.body.removeChild(
|
||||
document.getElementsByClassName("cursor-grabbing")[0],
|
||||
);
|
||||
}}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name={icon}
|
||||
className="h-5 w-5 shrink-0"
|
||||
/>
|
||||
<div className="flex flex-1 items-center overflow-hidden">
|
||||
<ShadTooltip content={display_name} styleClasses="z-50">
|
||||
<span className="truncate text-sm font-semibold">
|
||||
{display_name}
|
||||
</span>
|
||||
</ShadTooltip>
|
||||
{beta && (
|
||||
<Badge
|
||||
variant="pinkStatic"
|
||||
size="xq"
|
||||
className="ml-1.5 shrink-0"
|
||||
>
|
||||
BETA
|
||||
</Badge>
|
||||
)}
|
||||
{legacy && (
|
||||
<Badge
|
||||
variant="secondaryStatic"
|
||||
size="xq"
|
||||
className="ml-1.5 shrink-0"
|
||||
>
|
||||
LEGACY
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-1">
|
||||
{!disabled && (
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
tabIndex={-1}
|
||||
className="text-primary"
|
||||
onClick={() => addComponent(apiClass, itemName)}
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name="Plus"
|
||||
className="h-4 w-4 shrink-0 transition-all group-hover/draggable:opacity-100 group-focus/draggable:opacity-100 sm:opacity-0"
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
<div ref={popoverRef}>
|
||||
<ForwardedIconComponent
|
||||
name="GripVertical"
|
||||
className="h-4 w-4 shrink-0 text-muted-foreground group-hover/draggable:text-primary"
|
||||
/>
|
||||
<SelectTrigger tabIndex={-1}></SelectTrigger>
|
||||
<SelectContent
|
||||
position="popper"
|
||||
side="bottom"
|
||||
sideOffset={-25}
|
||||
style={{
|
||||
position: "absolute",
|
||||
left: cursorPos.x,
|
||||
top: cursorPos.y,
|
||||
}}
|
||||
>
|
||||
<SelectItem value={"download"}>
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name="Trash2"
|
||||
name="Download"
|
||||
className="relative top-0.5 mr-2 h-4 w-4"
|
||||
/>{" "}
|
||||
Delete{" "}
|
||||
Download{" "}
|
||||
</div>{" "}
|
||||
</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
{!official && (
|
||||
<SelectItem value={"delete"}>
|
||||
<div className="flex">
|
||||
<IconComponent
|
||||
name="Trash2"
|
||||
className="relative top-0.5 mr-2 h-4 w-4"
|
||||
/>{" "}
|
||||
Delete{" "}
|
||||
</div>{" "}
|
||||
</SelectItem>
|
||||
)}
|
||||
</SelectContent>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ShadTooltip>
|
||||
</Select>
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import { Switch } from "@/components/ui/switch";
|
|||
import { CustomLink } from "@/customization/components/custom-link";
|
||||
import { useAddComponent } from "@/hooks/useAddComponent";
|
||||
import { useStoreStore } from "@/stores/storeStore";
|
||||
import { checkChatInput } from "@/utils/reactflowUtils";
|
||||
import {
|
||||
nodeColors,
|
||||
SIDEBAR_BUNDLES,
|
||||
|
|
@ -97,6 +98,7 @@ export function FlowSidebarComponent() {
|
|||
(category) => Object.keys(category).length > 0,
|
||||
);
|
||||
}, [dataFilter]);
|
||||
const [sortedCategories, setSortedCategories] = useState<string[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
filterComponents();
|
||||
|
|
@ -128,6 +130,7 @@ export function FlowSidebarComponent() {
|
|||
// Apply search filter
|
||||
if (search && fuse) {
|
||||
const results = fuse.search(search);
|
||||
setSortedCategories(results.map((result) => result.item.category));
|
||||
filteredData = Object.fromEntries(
|
||||
Object.entries(data).map(([category, items]) => {
|
||||
const categoryResults = results.filter(
|
||||
|
|
@ -303,12 +306,21 @@ export function FlowSidebarComponent() {
|
|||
dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0,
|
||||
);
|
||||
|
||||
const hasCategoryItems = categories.some(
|
||||
(item) =>
|
||||
dataFilter[item.name] && Object.keys(dataFilter[item.name]).length > 0,
|
||||
);
|
||||
|
||||
function handleClearSearch() {
|
||||
setSearch("");
|
||||
setFilterData(data);
|
||||
setOpenCategories([]);
|
||||
}
|
||||
|
||||
const nodes = useFlowStore((state) => state.nodes);
|
||||
|
||||
const chatInputAdded = checkChatInput(nodes);
|
||||
|
||||
return (
|
||||
<Sidebar collapsible="offcanvas" data-testid="shad-sidebar">
|
||||
<SidebarHeader className="flex w-full flex-col gap-4 p-4 pb-1">
|
||||
|
|
@ -339,12 +351,11 @@ export function FlowSidebarComponent() {
|
|||
<div className="flex flex-col gap-7 border-b pb-7 pt-5">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm font-medium">
|
||||
Show{" "}
|
||||
<Badge variant="pinkStatic" size="sq">
|
||||
<span className="flex gap-2 text-sm font-medium">
|
||||
Show
|
||||
<Badge variant="pinkStatic" size="xq">
|
||||
BETA
|
||||
</Badge>{" "}
|
||||
Components
|
||||
</Badge>
|
||||
</span>
|
||||
</div>
|
||||
<Switch
|
||||
|
|
@ -355,12 +366,11 @@ export function FlowSidebarComponent() {
|
|||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="text-sm font-medium">
|
||||
Show{" "}
|
||||
<Badge variant="secondaryStatic" size="sq">
|
||||
<span className="flex gap-2 text-sm font-medium">
|
||||
Show
|
||||
<Badge variant="secondaryStatic" size="xq">
|
||||
LEGACY
|
||||
</Badge>{" "}
|
||||
Components
|
||||
</Badge>
|
||||
</span>
|
||||
</div>
|
||||
<Switch
|
||||
|
|
@ -393,8 +403,7 @@ export function FlowSidebarComponent() {
|
|||
Type{" "}
|
||||
<span>
|
||||
<ShortcutDisplay sidebar shortcut="/" />
|
||||
</span>{" "}
|
||||
to search components
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -402,6 +411,7 @@ export function FlowSidebarComponent() {
|
|||
<SidebarFilterComponent
|
||||
isInput={!!filterType.source}
|
||||
type={filterType.type}
|
||||
color={filterType.color}
|
||||
resetFilters={() => {
|
||||
setFilterEdge([]);
|
||||
setFilterData(data);
|
||||
|
|
@ -409,19 +419,186 @@ export function FlowSidebarComponent() {
|
|||
/>
|
||||
)}
|
||||
</SidebarHeader>
|
||||
<SidebarContent className="p-2">
|
||||
<SidebarContent>
|
||||
{hasResults ? (
|
||||
<>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{!data
|
||||
? Array.from({ length: 5 }).map((_, index) => (
|
||||
<SidebarMenuItem key={index}>
|
||||
<SidebarMenuSkeleton />
|
||||
</SidebarMenuItem>
|
||||
))
|
||||
: categories.map(
|
||||
{hasCategoryItems && (
|
||||
<SidebarGroup className="p-3">
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{!data
|
||||
? Array.from({ length: 5 }).map((_, index) => (
|
||||
<SidebarMenuItem key={index}>
|
||||
<SidebarMenuSkeleton />
|
||||
</SidebarMenuItem>
|
||||
))
|
||||
: categories
|
||||
.toSorted(
|
||||
(a, b) =>
|
||||
(search !== ""
|
||||
? sortedCategories
|
||||
: categories
|
||||
).findIndex((value) => value === a.name) -
|
||||
(search !== ""
|
||||
? sortedCategories
|
||||
: categories
|
||||
).findIndex((value) => value === b.name),
|
||||
)
|
||||
.map(
|
||||
(item) =>
|
||||
dataFilter[item.name] &&
|
||||
Object.keys(dataFilter[item.name]).length > 0 && (
|
||||
<Disclosure
|
||||
key={item.name}
|
||||
open={openCategories.includes(item.name)}
|
||||
onOpenChange={(isOpen) => {
|
||||
setOpenCategories((prev) =>
|
||||
isOpen
|
||||
? [...prev, item.name]
|
||||
: prev.filter(
|
||||
(cat) => cat !== item.name,
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<DisclosureTrigger className="group/collapsible">
|
||||
<SidebarMenuButton asChild>
|
||||
<div
|
||||
data-testid={`disclosure-${item.display_name.toLocaleLowerCase()}`}
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) =>
|
||||
handleKeyDown(e, item.name)
|
||||
}
|
||||
className="flex cursor-pointer items-center gap-2"
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name={item.icon}
|
||||
className="h-4 w-4 group-aria-expanded/collapsible:text-accent-pink-foreground"
|
||||
/>
|
||||
<span className="flex-1 group-aria-expanded/collapsible:font-semibold">
|
||||
{item.display_name}
|
||||
</span>
|
||||
<ForwardedIconComponent
|
||||
name="ChevronRight"
|
||||
className="-mr-1 h-4 w-4 text-muted-foreground transition-all group-aria-expanded/collapsible:rotate-90"
|
||||
/>
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</DisclosureTrigger>
|
||||
<DisclosureContent>
|
||||
<div className="flex flex-col gap-1 py-2">
|
||||
{Object.keys(dataFilter[item.name])
|
||||
.sort((a, b) =>
|
||||
sensitiveSort(
|
||||
dataFilter[item.name][a]
|
||||
.display_name,
|
||||
dataFilter[item.name][b]
|
||||
.display_name,
|
||||
),
|
||||
)
|
||||
.map((SBItemName: string, idx) => (
|
||||
<ShadTooltip
|
||||
content={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
].display_name
|
||||
}
|
||||
side="right"
|
||||
key={idx}
|
||||
>
|
||||
<SidebarDraggableComponent
|
||||
sectionName={
|
||||
item.name as string
|
||||
}
|
||||
apiClass={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
]
|
||||
}
|
||||
icon={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
].icon ??
|
||||
item.icon ??
|
||||
"Unknown"
|
||||
}
|
||||
key={idx}
|
||||
onDragStart={(event) =>
|
||||
onDragStart(event, {
|
||||
type: removeCountFromString(
|
||||
SBItemName,
|
||||
),
|
||||
node: dataFilter[item.name][
|
||||
SBItemName
|
||||
],
|
||||
})
|
||||
}
|
||||
color={nodeColors[item.name]}
|
||||
itemName={SBItemName}
|
||||
error={
|
||||
!!dataFilter[item.name][
|
||||
SBItemName
|
||||
].error
|
||||
}
|
||||
display_name={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
].display_name
|
||||
}
|
||||
official={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
].official === false
|
||||
? false
|
||||
: true
|
||||
}
|
||||
beta={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
].beta ?? false
|
||||
}
|
||||
legacy={
|
||||
dataFilter[item.name][
|
||||
SBItemName
|
||||
].legacy ?? false
|
||||
}
|
||||
disabled={
|
||||
SBItemName === "ChatInput" &&
|
||||
chatInputAdded
|
||||
}
|
||||
disabledTooltip="Chat input already added"
|
||||
/>
|
||||
</ShadTooltip>
|
||||
))}
|
||||
</div>
|
||||
</DisclosureContent>
|
||||
</SidebarMenuItem>
|
||||
</Disclosure>
|
||||
),
|
||||
)}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
)}
|
||||
{hasBundleItems && (
|
||||
<SidebarGroup className="p-3">
|
||||
<SidebarGroupLabel>Bundles</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{bundles
|
||||
.toSorted(
|
||||
(a, b) =>
|
||||
(search !== ""
|
||||
? sortedCategories
|
||||
: bundles
|
||||
).findIndex((value) => value === a.name) -
|
||||
(search !== ""
|
||||
? sortedCategories
|
||||
: bundles
|
||||
).findIndex((value) => value === b.name),
|
||||
)
|
||||
.map(
|
||||
(item) =>
|
||||
dataFilter[item.name] &&
|
||||
Object.keys(dataFilter[item.name]).length > 0 && (
|
||||
|
|
@ -440,7 +617,6 @@ export function FlowSidebarComponent() {
|
|||
<DisclosureTrigger className="group/collapsible">
|
||||
<SidebarMenuButton asChild>
|
||||
<div
|
||||
data-testid={`disclosure-${item.display_name.toLocaleLowerCase()}`}
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) =>
|
||||
handleKeyDown(e, item.name)
|
||||
|
|
@ -449,14 +625,14 @@ export function FlowSidebarComponent() {
|
|||
>
|
||||
<ForwardedIconComponent
|
||||
name={item.icon}
|
||||
className="group-aria-expanded/collapsible:x-gradient h-4 w-4"
|
||||
className="h-4 w-4 text-muted-foreground group-aria-expanded/collapsible:text-primary"
|
||||
/>
|
||||
<span className="group-aria-expanded/collapsible:font-semibold">
|
||||
<span className="flex-1 group-aria-expanded/collapsible:font-semibold">
|
||||
{item.display_name}
|
||||
</span>
|
||||
<ForwardedIconComponent
|
||||
name="ChevronRight"
|
||||
className="h-4 w-4 text-muted-foreground transition-all group-aria-expanded/collapsible:rotate-90"
|
||||
className="-mr-1 h-4 w-4 text-muted-foreground transition-all group-aria-expanded/collapsible:rotate-90"
|
||||
/>
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
|
|
@ -526,6 +702,11 @@ export function FlowSidebarComponent() {
|
|||
dataFilter[item.name][SBItemName]
|
||||
.legacy ?? false
|
||||
}
|
||||
disabled={
|
||||
SBItemName === "ChatInput" &&
|
||||
chatInputAdded
|
||||
}
|
||||
disabledTooltip="Chat input already added"
|
||||
/>
|
||||
</ShadTooltip>
|
||||
))}
|
||||
|
|
@ -535,126 +716,6 @@ export function FlowSidebarComponent() {
|
|||
</Disclosure>
|
||||
),
|
||||
)}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
{hasBundleItems && (
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Bundles</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
{bundles.map(
|
||||
(item) =>
|
||||
dataFilter[item.name] &&
|
||||
Object.keys(dataFilter[item.name]).length > 0 && (
|
||||
<Disclosure
|
||||
key={item.name}
|
||||
open={openCategories.includes(item.name)}
|
||||
onOpenChange={(isOpen) => {
|
||||
setOpenCategories((prev) =>
|
||||
isOpen
|
||||
? [...prev, item.name]
|
||||
: prev.filter((cat) => cat !== item.name),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<SidebarMenuItem>
|
||||
<DisclosureTrigger className="group/collapsible">
|
||||
<SidebarMenuButton asChild>
|
||||
<div
|
||||
tabIndex={0}
|
||||
onKeyDown={(e) =>
|
||||
handleKeyDown(e, item.name)
|
||||
}
|
||||
className="flex cursor-pointer items-center gap-2"
|
||||
>
|
||||
<ForwardedIconComponent
|
||||
name={item.icon}
|
||||
className="h-4 w-4 text-muted-foreground group-aria-expanded/collapsible:text-primary"
|
||||
/>
|
||||
<span className="group-aria-expanded/collapsible:font-semibold">
|
||||
{item.display_name}
|
||||
</span>
|
||||
<ForwardedIconComponent
|
||||
name="ChevronRight"
|
||||
className="h-4 w-4 text-muted-foreground transition-all group-aria-expanded/collapsible:rotate-90"
|
||||
/>
|
||||
</div>
|
||||
</SidebarMenuButton>
|
||||
</DisclosureTrigger>
|
||||
<DisclosureContent>
|
||||
<div className="flex flex-col gap-1 py-2">
|
||||
{Object.keys(dataFilter[item.name])
|
||||
.sort((a, b) =>
|
||||
sensitiveSort(
|
||||
dataFilter[item.name][a].display_name,
|
||||
dataFilter[item.name][b].display_name,
|
||||
),
|
||||
)
|
||||
.map((SBItemName: string, idx) => (
|
||||
<ShadTooltip
|
||||
content={
|
||||
dataFilter[item.name][SBItemName]
|
||||
.display_name
|
||||
}
|
||||
side="right"
|
||||
key={idx}
|
||||
>
|
||||
<SidebarDraggableComponent
|
||||
sectionName={item.name as string}
|
||||
apiClass={
|
||||
dataFilter[item.name][SBItemName]
|
||||
}
|
||||
icon={
|
||||
dataFilter[item.name][SBItemName]
|
||||
.icon ??
|
||||
item.icon ??
|
||||
"Unknown"
|
||||
}
|
||||
key={idx}
|
||||
onDragStart={(event) =>
|
||||
onDragStart(event, {
|
||||
type: removeCountFromString(
|
||||
SBItemName,
|
||||
),
|
||||
node: dataFilter[item.name][
|
||||
SBItemName
|
||||
],
|
||||
})
|
||||
}
|
||||
color={nodeColors[item.name]}
|
||||
itemName={SBItemName}
|
||||
error={
|
||||
!!dataFilter[item.name][SBItemName]
|
||||
.error
|
||||
}
|
||||
display_name={
|
||||
dataFilter[item.name][SBItemName]
|
||||
.display_name
|
||||
}
|
||||
official={
|
||||
dataFilter[item.name][SBItemName]
|
||||
.official === false
|
||||
? false
|
||||
: true
|
||||
}
|
||||
beta={
|
||||
dataFilter[item.name][SBItemName]
|
||||
.beta ?? false
|
||||
}
|
||||
legacy={
|
||||
dataFilter[item.name][SBItemName]
|
||||
.legacy ?? false
|
||||
}
|
||||
/>
|
||||
</ShadTooltip>
|
||||
))}
|
||||
</div>
|
||||
</DisclosureContent>
|
||||
</SidebarMenuItem>
|
||||
</Disclosure>
|
||||
),
|
||||
)}
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default function ShortcutDisplay({
|
|||
{name && <span> {name} </span>}
|
||||
<span
|
||||
className={cn(
|
||||
"flex h-5 items-center rounded-sm bg-muted px-1.5 text-lg text-muted-foreground",
|
||||
"flex h-[16px] w-[16px] items-center justify-center rounded-sm bg-muted text-muted-foreground",
|
||||
name && "ml-3",
|
||||
)}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -167,7 +167,7 @@ export default function FlowPage({ view }: { view?: boolean }): JSX.Element {
|
|||
<div className="flow-page-positioning">
|
||||
{currentFlow && (
|
||||
<div className="flex h-full overflow-hidden">
|
||||
<SidebarProvider width="19rem" defaultOpen={!isMobile}>
|
||||
<SidebarProvider width="17.5rem" defaultOpen={!isMobile}>
|
||||
{!view && <FlowSidebarComponent />}
|
||||
<main className="flex flex-1">
|
||||
<div className="h-full w-full">
|
||||
|
|
|
|||
|
|
@ -273,11 +273,21 @@ pre {
|
|||
}
|
||||
|
||||
[type="search"]:not(:placeholder-shown)::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
background-color: hsl(var(--primary));
|
||||
opacity: 1 !important;
|
||||
-webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23777'><path d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/></svg>");
|
||||
background-size: 20px 20px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
input[type="search"]::-webkit-search-cancel-button {
|
||||
-webkit-appearance: none;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-left: 0.4em;
|
||||
position: relative;
|
||||
right: -4px;
|
||||
mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='white'><path d='M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z'/></svg>");
|
||||
background-color: hsl(var(--foreground)) !important;
|
||||
background-image: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.react-flow__background pattern circle {
|
||||
fill: hsl(var(--canvas-dot)) !important;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,18 +32,17 @@
|
|||
--secondary-hover: 240 6% 90%; /* hsl(240, 6%, 90%) */
|
||||
--placeholder-foreground: 240 5% 65%; /* hsl(240, 5%, 65%) */
|
||||
--canvas: 240 5% 96%; /* hsl(240, 5%, 96%) */
|
||||
--canvas-dot: 240 5% 65%; /* hsl(240, 5%, 65%) */
|
||||
--accent-emerald: 149 80% 90%; /* hsl(149, 80%, 90%) */
|
||||
--accent-emerald-foreground: 161 41% 30%; /* hsl(161, 41%, 30%) */
|
||||
--accent-emerald-hover: 152.4 76% 80.4%; /* hsl(152.4, 76%, 80.4%) */
|
||||
--accent-indigo: 226 100% 94%; /* hsl(226, 100%, 94%) */
|
||||
--accent-indigo-foreground: 243 75% 59%; /* hsl(243, 75%, 59%) */
|
||||
--accent-pink: 326 78% 95%; /* hsl(326, 78%, 95%) */
|
||||
--accent-pink-foreground: 333 71% 51%; /* hsl(333, 71%, 51%) */
|
||||
--note-amber: 48 97% 77%; /* hsl(48, 97%, 77%) */
|
||||
--tooltip: 0 0% 0%; /* hsl(0, 0%, 0%) */
|
||||
--tooltip-foreground: 0 0% 100%; /* hsl(0, 0%, 100%) */
|
||||
|
||||
--canvas-dark: 240 6% 10%; /* hsl(240, 6%, 10%) */
|
||||
|
||||
--node-selected: 243 75% 59%;
|
||||
--round-btn-shadow: #00000063;
|
||||
--ice: #31a3cc;
|
||||
|
|
@ -89,28 +88,22 @@
|
|||
--status-blue: #2563eb;
|
||||
--status-gray: #6b7280;
|
||||
--connection: #555;
|
||||
--note-default: #f1f5f9;
|
||||
--note-indigo: #e0e7ff;
|
||||
--note-emerald: #d1fae5;
|
||||
--note-red: #fee2e2;
|
||||
|
||||
--note-amber: 48 96.6% 76.7%; /* hsl(48, 96.6%, 76.7%) */
|
||||
--note-neutral: 240 5.9% 90%; /* hsl(240, 5.9%, 90%) */
|
||||
--note-rose: 352.7 96.1% 90%; /* hsl(352.7, 96.1%, 90%) */
|
||||
--note-blue: 213.3 96.9% 87.3%; /* hsl(213.3, 96.9%, 87.3%) */
|
||||
--note-lime: 80.9 88.5% 79.6%; /* hsl(80.9, 88.5%, 79.6%) */
|
||||
|
||||
--error-red: 0, 86%, 97%; /*hsla(0, 86%, 97%)*/
|
||||
--error-red-border: 0, 96%, 89%; /*hsla(0,96%,89%)*/
|
||||
--note-default-opacity: #f1f5f980;
|
||||
--note-indigo-opacity: #312e8180;
|
||||
--note-emerald-opacity: #064e3b80;
|
||||
--note-amber-opacity: #78350f80;
|
||||
--note-red-opacity: #7f1d1d80;
|
||||
|
||||
--code-background: var(--canvas);
|
||||
--emerald-success: 160.1 84.1% 39.4%;
|
||||
--accent-emerald-foreground: 161.4 93.5% 30.4%;
|
||||
--placeholder: 240 5% 64.9%;
|
||||
--hard-zinc: 240 5.2% 33.9%;
|
||||
--smooth-red: 0 93.3% 94.1%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
--accent-pink: 327.3 73.3% 97.1%;
|
||||
--accent-pink-foreground: 333.3 71.4% 50.6%;
|
||||
|
||||
--inner-yellow: 40.6 96.1% 40.4%;
|
||||
--inner-yellow-foreground: 50.4 97.8% 63.5%;
|
||||
--inner-yellow-muted-foreground: 35.5 91.7% 32.9%;
|
||||
|
|
@ -180,30 +173,25 @@
|
|||
--secondary-hover: 240 4% 16%; /* hsl(240, 4%, 16%) */
|
||||
--placeholder-foreground: 240 4% 46%; /* hsl(240, 4%, 46%) */
|
||||
--canvas: 0 0% 0%; /* hsl(0, 0%, 0%) */
|
||||
--canvas-dot: 240 5% 34%; /* hsl(240, 5%, 34%) */
|
||||
--accent-emerald: 164 86% 16%; /* hsl(164, 86%, 16%) */
|
||||
--accent-emerald-foreground: 158 64% 52%; /* hsl(158, 64%, 52%) */
|
||||
--accent-emerald-hover: 163.1 88.1% 19.8%; /* hsl(163.1, 88.1%, 19.8%) */
|
||||
--accent-indigo: 242 25% 34%; /* hsl(242, 25%, 34%) */
|
||||
--accent-indigo-foreground: 234 89% 74%; /* hsl(234, 89%, 74%) */
|
||||
--accent-pink: 336 30% 30%; /* hsl(336, 30%, 30%) */
|
||||
--accent-pink: 336 69% 30%; /* hsl(336, 69%, 30%) */
|
||||
--accent-pink-foreground: 329 86% 70%; /* hsl(329, 86%, 70%) */
|
||||
--note-amber: 46 97% 65%; /* hsl(46, 97%, 65%) */
|
||||
--tooltip: 0 0% 100%; /* hsl(0, 0%, 100%) */
|
||||
|
||||
--tooltip-foreground: 0 0% 0%; /* hsl(0, 0%, 0%) */
|
||||
--error-red: 0, 75%, 15%; /*hsla(0, 75%, 15%)*/
|
||||
--error-red-border: 0, 70%, 35%; /*hsla(0,70%,35%)*/
|
||||
|
||||
--note-default: #0f172a;
|
||||
--note-indigo: #312e81;
|
||||
--note-emerald: #064e3b;
|
||||
--note-red: #7f1d1d;
|
||||
--note-placeholder: 216 12% 84%; /* hsl(216 12% 84%) */
|
||||
|
||||
--note-default-opacity: #0f172a80;
|
||||
--note-indigo-opacity: #312e8180;
|
||||
--note-emerald-opacity: #064e3b80;
|
||||
--note-amber-opacity: #78350f80;
|
||||
--note-red-opacity: #7f1d1d80;
|
||||
--note-amber: 45.9 96.7% 64.5%; /* hsl(45.9, 96.7%, 64.5%) */
|
||||
--note-neutral: 240 4.9% 83.9%; /* hsl(240, 4.9%, 83.9%) */
|
||||
--note-rose: 352.6 95.7% 81.8%; /* hsl(352.6, 95.7%, 81.8%) */
|
||||
--note-blue: 211.7 96.4% 78.4%; /* hsl(211.7, 96.4%, 78.4%) */
|
||||
--note-lime: 82 84.5% 67.1%; /* hsl(82, 84.5%, 67.1%) */
|
||||
|
||||
--node-selected: 234 89% 74%;
|
||||
|
||||
|
|
@ -234,8 +222,6 @@
|
|||
--component-icon: #c35f85;
|
||||
--flow-icon: #2467e4;
|
||||
|
||||
/* Colors that are shared in dark and light mode */
|
||||
--blur-shared: #151923d2;
|
||||
--build-trigger: #dc735b;
|
||||
--chat-trigger: #5c8be1;
|
||||
--chat-trigger-disabled: #2d3b54;
|
||||
|
|
@ -262,14 +248,10 @@
|
|||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
--emerald-success: 160.1 84.1% 39.4%;
|
||||
--placeholder: 240 5% 64.9%;
|
||||
--hard-zinc: 240 5.2% 33.9%;
|
||||
--smooth-red: 0 93.3% 94.1%;
|
||||
|
||||
--accent-pink: 335.9 69% 30.4%;
|
||||
--accent-pink-foreground: 330.4 81.2% 60.4%;
|
||||
|
||||
--inner-yellow: 47.9 95.8% 53.1%;
|
||||
--inner-yellow-foreground: 35.5 91.7% 32.9%;
|
||||
--inner-yellow-muted-foreground: 50.4 97.8% 63.5%;
|
||||
|
|
|
|||
|
|
@ -69,11 +69,9 @@ const config = {
|
|||
"build-trigger": "var(--build-trigger)",
|
||||
"chat-trigger": "var(--chat-trigger)",
|
||||
"chat-trigger-disabled": "var(--chat-trigger-disabled)",
|
||||
"blur-shared": "var(--blur-shared)",
|
||||
"dark-blue": "var(--dark-blue)",
|
||||
"dark-gray": "var(--dark-gray)",
|
||||
"dark-red": "var(--dark-red)",
|
||||
"note-placeholder": "var(--note-placeholder)",
|
||||
error: {
|
||||
DEFAULT: "var(--error)",
|
||||
background: "var(--error-background)",
|
||||
|
|
@ -97,7 +95,11 @@ const config = {
|
|||
"medium-high-indigo": "var(--medium-high-indigo)",
|
||||
"medium-indigo": "var(--medium-indigo)",
|
||||
"medium-low-gray": "var(--medium-low-gray)",
|
||||
"note-amber": "var(--note-amber)",
|
||||
"note-amber": "hsl(var(--note-amber))",
|
||||
"note-neutral": "hsl(var(--note-neutral))",
|
||||
"note-rose": "hsl(var(--note-rose))",
|
||||
"note-blue": "hsl(var(--note-blue))",
|
||||
"note-lime": "hsl(var(--note-lime))",
|
||||
"status-green": "var(--status-green)",
|
||||
"status-red": "var(--status-red)",
|
||||
"status-yellow": "var(--status-yellow)",
|
||||
|
|
@ -120,7 +122,7 @@ const config = {
|
|||
"code-background": "hsl(var(--code-background))",
|
||||
canvas: {
|
||||
DEFAULT: "hsl(var(--canvas))",
|
||||
dark: "hsl(var(--canvas-dark))",
|
||||
dot: "hsl(var(--canvas-dot))",
|
||||
},
|
||||
ice: "var(--ice)",
|
||||
selected: "var(--selected)",
|
||||
|
|
@ -128,13 +130,15 @@ const config = {
|
|||
border: "hsl(var(--border))",
|
||||
input: "hsl(var(--input))",
|
||||
ring: "hsl(var(--ring))",
|
||||
"error-red":"hsl(var(--error-red))",
|
||||
"error-red-border":"hsl(var(--error-red-border))",
|
||||
"error-red": "hsl(var(--error-red))",
|
||||
"error-red-border": "hsl(var(--error-red-border))",
|
||||
"node-selected": "hsl(var(--node-selected))",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
"emerald-success": "hsl(var(--emerald-success))",
|
||||
"accent-emerald-foreground": "hsl(var(--accent-emerald-foreground))",
|
||||
"accent-emerald": {
|
||||
DEFAULT: "hsl(var(--accent-emerald))",
|
||||
foreground: "hsl(var(--accent-emerald-foreground))",
|
||||
},
|
||||
"emerald-smooth": "hsl(var(--emaral-smooth))",
|
||||
"emerald-hard": "hsl(var(--emeral-hard))",
|
||||
placeholder: "hsl(var(--placeholder))",
|
||||
|
|
@ -166,6 +170,7 @@ const config = {
|
|||
"accent-emerald": {
|
||||
DEFAULT: "hsl(var(--accent-emerald))",
|
||||
foreground: "hsl(var(--accent-emerald-foreground))",
|
||||
hover: "hsl(var(--accent-emerald-hover))",
|
||||
},
|
||||
"accent-indigo": {
|
||||
DEFAULT: "hsl(var(--accent-indigo))",
|
||||
|
|
@ -377,34 +382,34 @@ const config = {
|
|||
tailwindcssTypography,
|
||||
tailwindcssDottedBackground,
|
||||
plugin(function ({ addUtilities, theme, e }) {
|
||||
const colors = theme('colors');
|
||||
const colors = theme("colors");
|
||||
|
||||
const generateUtilities = (colors, prefix = '') => {
|
||||
const generateUtilities = (colors, prefix = "") => {
|
||||
return Object.keys(colors).reduce((acc, colorName) => {
|
||||
const colorValue = colors[colorName];
|
||||
const className = prefix ? `${prefix}-${e(colorName)}` : e(colorName);
|
||||
|
||||
if (typeof colorValue === 'string') {
|
||||
if (typeof colorValue === "string") {
|
||||
acc[`.truncate-${className}`] = {
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
'&::after': {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
"&::after": {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
inset: '0 0 0 0',
|
||||
position: "absolute",
|
||||
inset: "0 0 0 0",
|
||||
background: `linear-gradient(to right, transparent, 75%, ${colorValue})`,
|
||||
},
|
||||
};
|
||||
} else if (typeof colorValue === 'object') {
|
||||
} else if (typeof colorValue === "object") {
|
||||
// Use the DEFAULT value for the base class if it exists
|
||||
if (colorValue.DEFAULT) {
|
||||
acc[`.truncate-${className}`] = {
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
'&::after': {
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
"&::after": {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
inset: '0 0 0 0',
|
||||
position: "absolute",
|
||||
inset: "0 0 0 0",
|
||||
background: `linear-gradient(to right, transparent, ${colorValue.DEFAULT})`,
|
||||
},
|
||||
};
|
||||
|
|
@ -419,7 +424,7 @@ const config = {
|
|||
|
||||
const newUtilities = generateUtilities(colors);
|
||||
|
||||
addUtilities(newUtilities, ['responsive', 'hover']);
|
||||
addUtilities(newUtilities, ["responsive", "hover"]);
|
||||
}),
|
||||
plugin(({ addVariant }) => {
|
||||
addVariant("group-increment-hover", ":merge(.group-increment):hover &");
|
||||
|
|
|
|||
|
|
@ -35,10 +35,7 @@ test.describe("group node test", () => {
|
|||
|
||||
await page.getByRole("button", { name: "Group" }).click();
|
||||
await page.getByTestId("title-Group").dblclick();
|
||||
await page
|
||||
.getByTestId("popover-anchor-input-title-Group")
|
||||
.first()
|
||||
.fill("test");
|
||||
await page.getByTestId("input-title-Group").first().fill("test");
|
||||
await page.getByTestId("icon-Ungroup").first().click();
|
||||
await page.keyboard.press("Control+g");
|
||||
await page.getByTestId("title-OpenAI").isVisible();
|
||||
|
|
|
|||
|
|
@ -105,7 +105,10 @@ The future of AI is both exciting and uncertain. As the technology continues to
|
|||
|
||||
let hasStyles = await element?.evaluate((el) => {
|
||||
const style = window.getComputedStyle(el);
|
||||
return style.backgroundColor === "rgb(241, 245, 249)";
|
||||
return (
|
||||
style.backgroundColor === "rgb(252, 211, 77)" ||
|
||||
style.backgroundColor === "rgb(253, 230, 138)"
|
||||
);
|
||||
});
|
||||
expect(hasStyles).toBe(true);
|
||||
|
||||
|
|
@ -113,7 +116,7 @@ The future of AI is both exciting and uncertain. As the technology continues to
|
|||
|
||||
await page.getByTestId("color_picker").click();
|
||||
|
||||
await page.getByTestId("color_picker_button_red").click();
|
||||
await page.getByTestId("color_picker_button_rose").click();
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.getByTestId("note_node").click();
|
||||
|
|
@ -122,7 +125,11 @@ The future of AI is both exciting and uncertain. As the technology continues to
|
|||
|
||||
hasStyles = await element?.evaluate((el) => {
|
||||
const style = window.getComputedStyle(el);
|
||||
return style.backgroundColor === "rgb(254, 226, 226)";
|
||||
|
||||
return (
|
||||
style.backgroundColor === "rgb(253, 164, 175)" ||
|
||||
style.backgroundColor === "rgb(254, 205, 211)"
|
||||
);
|
||||
});
|
||||
expect(hasStyles).toBe(true);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue