diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/ActionSpaceTree/index.tsx b/apps/builder/src/page/App/Module/DataWorkspace/components/ActionSpaceTree/index.tsx index a4d47800bd..d28087cb3e 100644 --- a/apps/builder/src/page/App/Module/DataWorkspace/components/ActionSpaceTree/index.tsx +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/ActionSpaceTree/index.tsx @@ -8,6 +8,7 @@ import { getActionList } from "@/redux/currentApp/action/actionSelector" import { getActionExecutionResultWithOutIgnoreKey } from "@/redux/currentApp/executionTree/executionSelector" import { FocusManager } from "@/utils/focusManager" import { BaseDataItem } from "../BaseDataItem" +import { BaseDataItemContextProvider } from "../BaseDataItem/context" export const ActionSpaceTree: FC = () => { const { t } = useTranslation() @@ -35,18 +36,22 @@ export const ActionSpaceTree: FC = () => { }} destroyChildrenWhenClose > - {Object.keys(actionExecution).map((actionDisplayName) => ( - } - haveMoreAction - selectedDisplayNames={[selectedAction?.displayName ?? ""]} - onClick={handleActionSelect} - dataType="action" - /> - ))} + + {Object.keys(actionExecution).map((actionDisplayName) => ( + + } + haveMoreAction + selectedDisplayNames={[selectedAction?.displayName ?? ""]} + onClick={handleActionSelect} + dataType="action" + /> + ))} + ) } diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/context/index.tsx b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/context/index.tsx new file mode 100644 index 0000000000..877ee4e6b6 --- /dev/null +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/context/index.tsx @@ -0,0 +1,30 @@ +import { FC, createContext, useState } from "react" +import { Injected, Props } from "./interface" + +export const BaseDataItemContext = createContext({} as Injected) + +export const BaseDataItemContextProvider: FC = (props) => { + const { children } = props + + const [expandedStatus, setExpandedStatus] = useState(new Map()) + + const handleUpdateExpandedWidget = ( + displayName: string, + currentStatus: boolean, + ) => { + setExpandedStatus((prev) => { + prev.set(displayName, !currentStatus) + return new Map(prev) + }) + } + + return ( + + {children} + + ) +} + +BaseDataItemContextProvider.displayName = "SelectedProvider" diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/context/interface.ts b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/context/interface.ts new file mode 100644 index 0000000000..b66a288b2d --- /dev/null +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/context/interface.ts @@ -0,0 +1,13 @@ +import { ReactNode } from "react" + +export interface Injected { + handleUpdateExpandedWidget: ( + displayName: string, + currentExpanded: boolean, + ) => void + expandedStatus: Map +} + +export interface Props { + children: ReactNode +} diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/index.tsx b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/index.tsx index 872402b4ec..2b1e6f5491 100644 --- a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/index.tsx +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/index.tsx @@ -1,19 +1,22 @@ import { getIconFromWidgetType } from "@illa-public/icon" -import { FC, useState } from "react" -import useMeasure from "react-use-measure" +import { AnimatePresence, motion } from "framer-motion" +import { FC, useContext, useState } from "react" import { CaretRightIcon, getColor } from "@illa-design/react" import { ReactComponent as LocateIcon } from "@/assets/dataWorkspace/locate.svg" import { ReactComponent as StateIcon } from "@/assets/dataWorkspace/state.svg" import IconHotSpot from "@/components/IconHotSpot" import { MovableModal } from "@/components/Modal/movableModal" +import { panelBarItemContainerAnimationVariants } from "@/components/PanelBar/style" import { MoreAction } from "../MoreAction" import { WorkSpaceTreeNode } from "../WorkSpaceTreeItem/WorkSpaceTreeNode" +import { BaseDataItemContext } from "./context" import { BaseDataItemProps } from "./interface" import { applyExpandIconStyle, expendContainerStyle, iconContainerStyle, itemContainerStyle, + itemContentStyle, modalBodyContainerStyle, outerContainerStyle, rectangleStyle, @@ -31,11 +34,15 @@ export const BaseDataItem: FC = (props) => { haveMoreAction, value, onClick, + onFocus, dataType, selectedDisplayNames, } = props const [isOpenCodeModal, setIsOpenCodeModal] = useState(false) - const [measureRef, rect] = useMeasure() + const { handleUpdateExpandedWidget, expandedStatus } = + useContext(BaseDataItemContext) + const isExpanded = + (canExpand ?? false) && (expandedStatus.get(title) ?? false) const isSelected = selectedDisplayNames?.includes(title) ?? false @@ -43,16 +50,28 @@ export const BaseDataItem: FC = (props) => { onClick?.(title, type ?? "") } + const handleOnFocus = () => { + onFocus?.(title) + } + + const handleClickOnExpandIcon = (e: React.MouseEvent) => { + e.stopPropagation() + handleUpdateExpandedWidget(title, isExpanded) + } + return ( <>
- + {!!type && level >= 1 &&
} @@ -63,7 +82,10 @@ export const BaseDataItem: FC = (props) => {
{canFocused && ( - + )} @@ -76,23 +98,36 @@ export const BaseDataItem: FC = (props) => {
- {dataType === "widget" && - Array.isArray(value.$childrenNode) && - value.$childrenNode.map((item) => ( - 0} - haveMoreAction={item.$widgetType.endsWith("_WIDGET")} - canFocused={item.$widgetType.endsWith("_WIDGET")} - selectedDisplayNames={selectedDisplayNames} - onClick={onClick} - /> - ))} + + {dataType === "widget" && Array.isArray(value.$childrenNode) && ( + + {isExpanded && ( + + {value.$childrenNode.map((item) => ( + 0} + haveMoreAction={item.$widgetType.endsWith("_WIDGET")} + canFocused={item.$widgetType.endsWith("_WIDGET")} + selectedDisplayNames={selectedDisplayNames} + onClick={onClick} + /> + ))} + + )} + + )} {isOpenCodeModal && ( = (props) => { }} docLink={`${value.type}` ?? ""} defaultPosition={{ - x: rect.right, - y: rect.top, + x: + document + .querySelector(`#${title}-baseDataItemContainer`) + ?.getBoundingClientRect().right ?? 0, + y: + document + .querySelector(`#${title}-baseDataItemContainer`) + ?.getBoundingClientRect().top ?? 0, width: 320, height: 214, }} diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/interface.ts b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/interface.ts index 02ad8d566f..ac9f037cc6 100644 --- a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/interface.ts +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/interface.ts @@ -9,4 +9,5 @@ export interface BaseDataItemProps { selectedDisplayNames?: string[] onClick?: (displayName: string, type: string) => void dataType: "globalData" | "action" | "widget" + onFocus?: (displayName: string) => void } diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/style.ts b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/style.ts index 5e871beef0..3c735c3c4e 100644 --- a/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/style.ts +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/BaseDataItem/style.ts @@ -84,3 +84,8 @@ export const modalBodyContainerStyle = css` flex-direction: column; gap: 4px; ` + +export const itemContentStyle = css` + font-family: "Fira Code", monospace; + height: 0; +` diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/ComponentSpaceTree/index.tsx b/apps/builder/src/page/App/Module/DataWorkspace/components/ComponentSpaceTree/index.tsx index d17535ada0..6f8a916ae0 100644 --- a/apps/builder/src/page/App/Module/DataWorkspace/components/ComponentSpaceTree/index.tsx +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/ComponentSpaceTree/index.tsx @@ -17,6 +17,7 @@ import { import { executionActions } from "@/redux/currentApp/executionTree/executionSlice" import { FocusManager } from "@/utils/focusManager" import { BaseDataItem } from "../BaseDataItem" +import { BaseDataItemContextProvider } from "../BaseDataItem/context" import { dividerStyle } from "./style" export const ComponentSpaceTree: FC = () => { @@ -47,6 +48,13 @@ export const ComponentSpaceTree: FC = () => { [dispatch], ) + const handleOnFocus = useCallback((displayName: string) => { + const dom = document.querySelector(`#${displayName}`) + if (dom) { + dom.scrollIntoView({ behavior: "smooth" }) + } + }, []) + return ( { }} destroyChildrenWhenClose > - {modalSectionTree.length > 0 && ( - - {modalSectionTree.map((tree) => ( - - ))} - - )} - {headerSectionTree.length > 0 && ( - <> - - - {headerSectionTree.map((tree) => ( + + {modalSectionTree.length > 0 && ( + + {modalSectionTree.map((tree) => ( { level={0} dataType="widget" type={tree.$widgetType as string} - canExpand={tree.$childrenNode.length > 0} + canExpand + haveMoreAction canFocused onClick={handleOnClick} selectedDisplayNames={selectedComponent} + onFocus={handleOnFocus} /> ))} - - )} + )} + {headerSectionTree.length > 0 && ( + <> + + + {headerSectionTree.map((tree) => ( + 0} + canFocused + onClick={handleOnClick} + selectedDisplayNames={selectedComponent} + onFocus={handleOnFocus} + /> + ))} + + + )} - - - {bodySectionTree.map((tree) => ( - 0} - haveMoreAction - canFocused - onClick={handleOnClick} - selectedDisplayNames={selectedComponent} - /> - ))} - + + + {bodySectionTree.map((tree) => ( + 0} + haveMoreAction + canFocused + onClick={handleOnClick} + selectedDisplayNames={selectedComponent} + onFocus={handleOnFocus} + /> + ))} + - {leftSectionTree.length > 0 && ( - <> - - - {leftSectionTree.map((tree) => ( - 0} - haveMoreAction - canFocused - onClick={handleOnClick} - selectedDisplayNames={selectedComponent} - /> - ))} - - - )} + {leftSectionTree.length > 0 && ( + <> + + + {leftSectionTree.map((tree) => ( + 0} + haveMoreAction + canFocused + onClick={handleOnClick} + selectedDisplayNames={selectedComponent} + onFocus={handleOnFocus} + /> + ))} + + + )} - {rightSectionTree.length > 0 && ( - <> - - - {rightSectionTree.map((tree) => ( - 0} - haveMoreAction - canFocused - onClick={handleOnClick} - selectedDisplayNames={selectedComponent} - /> - ))} - - - )} + {rightSectionTree.length > 0 && ( + <> + + + {rightSectionTree.map((tree) => ( + 0} + haveMoreAction + canFocused + onClick={handleOnClick} + selectedDisplayNames={selectedComponent} + onFocus={handleOnFocus} + /> + ))} + + + )} - {footerSectionTree.length > 0 && ( - <> - + {footerSectionTree.length > 0 && ( + <> + - - {footerSectionTree.map((tree) => ( - 0} - haveMoreAction - canFocused - onClick={handleOnClick} - selectedDisplayNames={selectedComponent} - /> - ))} - - - )} + + {footerSectionTree.map((tree) => ( + 0} + haveMoreAction + canFocused + onClick={handleOnClick} + selectedDisplayNames={selectedComponent} + onFocus={handleOnFocus} + /> + ))} + + + )} + ) } diff --git a/apps/builder/src/page/App/Module/DataWorkspace/components/GlobalsSpaceTree/index.tsx b/apps/builder/src/page/App/Module/DataWorkspace/components/GlobalsSpaceTree/index.tsx index 4c26d41bda..b36bb6ceae 100644 --- a/apps/builder/src/page/App/Module/DataWorkspace/components/GlobalsSpaceTree/index.tsx +++ b/apps/builder/src/page/App/Module/DataWorkspace/components/GlobalsSpaceTree/index.tsx @@ -5,6 +5,7 @@ import { PanelBar } from "@/components/PanelBar" import { getGlobalInfoExecutionResult } from "@/redux/currentApp/executionTree/executionSelector" import { FocusManager } from "@/utils/focusManager" import { BaseDataItem } from "../BaseDataItem" +import { BaseDataItemContextProvider } from "../BaseDataItem/context" export const GlobalsSpaceTree: FC = () => { const { t } = useTranslation() @@ -22,15 +23,17 @@ export const GlobalsSpaceTree: FC = () => { }} destroyChildrenWhenClose > - {Object.keys(globalInfoList).map((key) => ( - } - dataType="globalData" - /> - ))} + + {Object.keys(globalInfoList).map((key) => ( + } + dataType="globalData" + /> + ))} + ) } diff --git a/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx b/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx index 250e1ab042..878e54d69a 100644 --- a/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx +++ b/apps/builder/src/widgetLibrary/PublicSector/TransformWidgetWrapper/index.tsx @@ -385,6 +385,7 @@ export const TransformWidgetWrapper: FC = memo( shadow, widgetType, )} + id={displayName} >