diff --git a/app/designer/sidebar-left/panels/tree.tsx b/app/designer/sidebar-left/panels/tree.tsx index 6468db4035..ddcd0ef059 100644 --- a/app/designer/sidebar-left/panels/tree.tsx +++ b/app/designer/sidebar-left/panels/tree.tsx @@ -1,124 +1,11 @@ -import { useState, useMemo } from "react"; import { type Instance } from "@webstudio-is/sdk"; import { ListNestedIcon } from "~/shared/icons"; -import { - Flex, - Text, - Collapsible, - Button, - keyframes, - styled, -} from "~/shared/design-system"; -import { TriangleRightIcon, TriangleDownIcon } from "~/shared/icons"; -import { primitives, type SelectedInstanceData } from "~/shared/component"; +import { Flex } from "~/shared/design-system"; +import { type SelectedInstanceData } from "~/shared/component"; import { type Publish } from "~/designer/canvas-iframe"; import { useSelectedInstancePath } from "~/designer/instance/use-selected-instance-path"; import { useRootInstance } from "~/designer/nano-values"; - -const openKeyframes = keyframes({ - from: { height: 0 }, - to: { height: "var(--radix-collapsible-content-height)" }, -}); - -const closeKeyframes = keyframes({ - from: { height: "var(--radix-collapsible-content-height)" }, - to: { height: 0 }, -}); - -const CollapsibleContent = styled(Collapsible.Content, { - overflow: "hidden", - '&[data-state="open"]': { - animation: `${openKeyframes} 150ms ease-in-out`, - }, - '&[data-state="closed"]': { - animation: `${closeKeyframes} 150ms ease-in-out`, - }, -}); - -type TreeProps = { - instance: Instance; - selectedInstanceId?: Instance["id"]; - selectedInstancePath: Array; - level?: number; - onSelect: (instance: Instance) => void; -}; - -const Tree = ({ - instance, - selectedInstanceId, - level = 0, - onSelect, - selectedInstancePath, -}: TreeProps) => { - const [isOpen, setIsOpen] = useState(selectedInstancePath.includes(instance)); - - // Text nodes have only one child which is a string. - const showChildren = - instance.children.length > 1 || typeof instance.children[0] === "object"; - - const children = useMemo(() => { - if (isOpen === false || showChildren === false) { - return null; - } - const children = []; - for (const child of instance.children) { - if (typeof child === "string") continue; - children.push( - - ); - } - return children; - }, [ - instance, - level, - isOpen, - selectedInstanceId, - selectedInstancePath, - onSelect, - showChildren, - ]); - - const { Icon, label } = primitives[instance.component]; - - return ( - - - {showChildren && ( - - {isOpen ? : } - - )} - - - {children} - - ); -}; +import { Tree } from "~/designer/tree"; type TabContentProps = { publish: Publish; diff --git a/app/designer/tree/Tree.tsx b/app/designer/tree/Tree.tsx new file mode 100644 index 0000000000..ea8d83447f --- /dev/null +++ b/app/designer/tree/Tree.tsx @@ -0,0 +1,117 @@ +import { useState, useMemo } from "react"; +import { type Instance } from "@webstudio-is/sdk"; +import { + Flex, + Text, + Collapsible, + Button, + keyframes, + styled, +} from "~/shared/design-system"; +import { TriangleRightIcon, TriangleDownIcon } from "~/shared/icons"; +import { primitives } from "~/shared/component"; + +const openKeyframes = keyframes({ + from: { height: 0 }, + to: { height: "var(--radix-collapsible-content-height)" }, +}); + +const closeKeyframes = keyframes({ + from: { height: "var(--radix-collapsible-content-height)" }, + to: { height: 0 }, +}); + +const CollapsibleContent = styled(Collapsible.Content, { + overflow: "hidden", + '&[data-state="open"]': { + animation: `${openKeyframes} 150ms ease-in-out`, + }, + '&[data-state="closed"]': { + animation: `${closeKeyframes} 150ms ease-in-out`, + }, +}); + +type TreeProps = { + instance: Instance; + selectedInstanceId?: Instance["id"]; + selectedInstancePath: Array; + level?: number; + onSelect: (instance: Instance) => void; +}; + +export const Tree = ({ + instance, + selectedInstanceId, + level = 0, + onSelect, + selectedInstancePath, +}: TreeProps) => { + const [isOpen, setIsOpen] = useState(selectedInstancePath.includes(instance)); + + // Text nodes have only one child which is a string. + const showChildren = + instance.children.length > 1 || typeof instance.children[0] === "object"; + + const children = useMemo(() => { + if (isOpen === false || showChildren === false) { + return null; + } + const children = []; + for (const child of instance.children) { + if (typeof child === "string") continue; + children.push( + + ); + } + return children; + }, [ + instance, + level, + isOpen, + selectedInstanceId, + selectedInstancePath, + onSelect, + showChildren, + ]); + + const { Icon, label } = primitives[instance.component]; + + return ( + + + {showChildren && ( + + {isOpen ? : } + + )} + + + {children} + + ); +}; diff --git a/app/designer/tree/index.ts b/app/designer/tree/index.ts new file mode 100644 index 0000000000..264fbe15a2 --- /dev/null +++ b/app/designer/tree/index.ts @@ -0,0 +1 @@ +export * from "./Tree";