chore: import clean Agent Desk snapshot (1/7)

This commit is contained in:
2026-10-16 11:55:22 +00:00
parent 24f6423407
commit 79176541c7
323 changed files with 34882 additions and 2 deletions

View File

@@ -0,0 +1,73 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { useState, useEffect } from 'react';
import { useClientContext, CommandService } from '@flowgram.ai/free-layout-editor';
import { Button } from '@douyinfe/semi-ui';
import { IconClose, IconSmallTriangleDown, IconSmallTriangleLeft } from '@douyinfe/semi-icons';
import { toggleLoopExpanded } from '../../utils';
import { FlowCommandId } from '../../shortcuts';
import { useNodeFormPanel } from '../../plugins/panel-manager-plugin/hooks';
import { useIsSidebar, useNodeRenderContext } from '../../hooks';
import { NodeMenu } from '../../components/node-menu';
import { getIcon } from './utils';
import { TitleInput } from './title-input';
import { Header, Operators } from './styles';
export function FormHeader() {
const { node, expanded, toggleExpand, readonly } = useNodeRenderContext();
const [titleEdit, updateTitleEdit] = useState<boolean>(false);
const ctx = useClientContext();
const isSidebar = useIsSidebar();
const handleExpand = (e: React.MouseEvent) => {
toggleExpand();
e.stopPropagation(); // Disable clicking prevents the sidebar from opening
};
const { close: closePanel } = useNodeFormPanel();
const handleDelete = () => {
ctx.get<CommandService>(CommandService).executeCommand(FlowCommandId.DELETE, [node]);
};
const handleClose = () => {
closePanel();
};
useEffect(() => {
// 折叠 loop 子节点
if (node.flowNodeType === 'loop') {
toggleLoopExpanded(node, expanded);
}
}, [expanded]);
return (
<Header>
{getIcon(node)}
<TitleInput readonly={readonly} updateTitleEdit={updateTitleEdit} titleEdit={titleEdit} />
{node.renderData.expandable && !isSidebar && (
<Button
type="primary"
icon={expanded ? <IconSmallTriangleDown /> : <IconSmallTriangleLeft />}
size="small"
theme="borderless"
onClick={handleExpand}
/>
)}
{readonly ? undefined : (
<Operators>
<NodeMenu node={node} deleteNode={handleDelete} updateTitleEdit={updateTitleEdit} />
</Operators>
)}
{isSidebar && (
<Button
type="primary"
icon={<IconClose />}
size="small"
theme="borderless"
onClick={handleClose}
/>
)}
</Header>
);
}

View File

@@ -0,0 +1,41 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import styled from 'styled-components';
export const Header = styled.div`
box-sizing: border-box;
display: flex;
justify-content: flex-start;
align-items: center;
width: 100%;
column-gap: 8px;
border-radius: 8px 8px 0 0;
cursor: move;
background: linear-gradient(#f2f2ff 0%, rgb(251, 251, 251) 100%);
overflow: hidden;
padding: 8px;
`;
export const Title = styled.div`
font-size: 20px;
flex: 1;
width: 0;
`;
export const Icon = styled.img`
width: 24px;
height: 24px;
scale: 0.8;
border-radius: 4px;
`;
export const Operators = styled.div`
display: flex;
align-items: center;
column-gap: 4px;
`;

View File

@@ -0,0 +1,50 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { useRef, useEffect } from 'react';
import { Field, FieldRenderProps } from '@flowgram.ai/free-layout-editor';
import { Typography, Input } from '@douyinfe/semi-ui';
import { Title } from './styles';
import { Feedback } from '../feedback';
const { Text } = Typography;
export function TitleInput(props: {
readonly: boolean;
titleEdit: boolean;
updateTitleEdit: (setEdit: boolean) => void;
}): JSX.Element {
const { readonly, titleEdit, updateTitleEdit } = props;
const ref = useRef<any>();
const titleEditing = titleEdit && !readonly;
useEffect(() => {
if (titleEditing) {
ref.current?.focus();
}
}, [titleEditing]);
return (
<Title>
<Field name="title">
{({ field: { value, onChange }, fieldState }: FieldRenderProps<string>) => (
<div style={{ height: 24 }}>
{titleEditing ? (
<Input
value={value}
onChange={onChange}
ref={ref}
onBlur={() => updateTitleEdit(false)}
/>
) : (
<Text ellipsis={{ showTooltip: true }}>{value}</Text>
)}
<Feedback errors={fieldState?.errors} />
</div>
)}
</Field>
</Title>
);
}

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
* SPDX-License-Identifier: MIT
*/
import { type FlowNodeEntity } from '@flowgram.ai/free-layout-editor';
import { FlowNodeRegistry } from '../../typings';
import { Icon } from './styles';
export const getIcon = (node: FlowNodeEntity) => {
const icon = node.getNodeRegistry<FlowNodeRegistry>().info?.icon;
if (!icon) return null;
return <Icon src={icon} />;
};