AI 组件

侧边信息栏

展示 AI 场景下的配置和详情信息

使用场景

侧边信息栏主要用于在 AI 场景下,用于信息展示,功能配置。包括 MCP 配置、参考来源、代码预览、富文本预览及编辑等功能

代码演示

如何引入

<script lang="ts">
    import { Annotation, MCPConfigure, Sidebar } from '@fibrae/semi-ai-svelte';

    const { Container, CodeContent, CodeItem, FileContent, FileItem } = Sidebar;
    const { AnnotationContent } = Annotation;
</script>

基础容器

侧边信息栏的基础容器,基础容器是MCP 配置、参考来源、以及侧边消息栏的基础容器。

  • bind:visible 控制显示和隐藏。点击关闭按钮,或在 closeOnEsc 为 true 时按下 Esc,会先更新为 false 再调用 onCancel
  • title 设置标题,可传纯文本或 snippet;需要自定义整个头部时使用 header snippet
  • motion 设置是否有展开动画
  • resizable 设置宽度是否可伸缩,为 true 时候可通过 minWidth,maxWidth 设置最小,最大宽度
是否有动画
是否可伸缩
基础容器示例
代码
<script lang="ts">
    import { Sidebar } from '@fibrae/semi-ai-svelte';
    import { Button, Switch } from '@fibrae/semi-ui-svelte';

    const { Container } = Sidebar;

    const containerStyle = 'display: flex; height: 500px; border: 1px solid var(--semi-color-border); border-radius: 8px; overflow: hidden; box-sizing: border-box';

    let visible = $state(true);
    let motion = $state(true);
    let resizable = $state(true);
</script>

<div style={containerStyle}>
    <div style="flex-grow: 1; flex-shrink: 1; padding: 20px">
        <div>
            <Button aria-pressed={visible} onclick={() => (visible = !visible)}>显示容器</Button>
            <div style="display: flex; align-items: center; margin-top: 10px">
                <span id="sidebar-container-motion">是否有动画</span>
                <Switch aria-labelledby="sidebar-container-motion" bind:checked={motion} />
            </div>
            <div style="display: flex; align-items: center; margin-top: 10px">
                <span id="sidebar-container-resizable">是否可伸缩</span>
                <Switch aria-labelledby="sidebar-container-resizable" bind:checked={resizable} />
            </div>
        </div>
    </div>
    <Container bind:visible maxWidth="60%" minWidth={250} {motion} {resizable} style={resizable ? undefined : 'width: 200px'} title="基础容器示例" />
</div>

MCP 配置

使用 MCPConfigure 进行 MCP 工具的展示、启用/关闭、配置及搜索

  • 通过 bind:options 和 bind:customOptions 绑定内置的 MCP 工具和自定义 MCP 工具,切换启用/关闭时先更新绑定值,再调用 onStatusChange
  • 通过 bind:visible 设置组件的显示和隐藏,使用 onCancel 监听用户的关闭行为
  • 使用 onStatusChange 自定义处理 MCP 工具的启用/关闭
  • 使用 onAddClick 处理自定义 MCP 页的点击添加按钮后的操作
  • 可通过 onConfigureClick 监听内置 MCP 工具的配置,通过 onEditClick 监听自定义 MCP 工具的配置
  • 工具项的图标和描述使用 icon、desc snippet,整行用 item snippet 替换;snippet 参数为 { item, index, custom }

其他 MCPConfigure 的 API 见 MCPConfigure

传入 MCP 工具项的类型如下

interface MCPConfigureOption {
    icon?: string; // 图片地址,其他内容使用 icon snippet
    label?: string;
    value: string; // 必填,标识工具项,需唯一
    desc?: string; // 纯文本,其他内容使用 desc snippet
    active?: boolean;
    disabled?: boolean;
    configure?: boolean; // 是否显示配置按钮
}

用例如下:

MCP 配置
已激活 MCP 数: 0/2
支持 Semi 的文档、源码搜索,辅助开发
Figma MCP Server 连接Figma与AI开发工具的功能。它通过标准化的模型上下文协MCP),将组件、变量等设计数据和上下文暴露给AI,从而实现从设计稿到代码的智能生成,显著提升开发效率。
代码
<script lang="ts">
    import { MCPConfigure, type MCPConfigureOption } from '@fibrae/semi-ai-svelte';
    import { IconFigma, IconSemiLogo } from '@fibrae/semi-icons-svelte';
    import { Button, Form, FormInput, FormTextArea, Modal, type FormApi } from '@fibrae/semi-ui-svelte';

    interface McpFormValues {
        name: string;
        src: string;
        desc: string;
    }

    const containerStyle = 'display: flex; height: 500px; border: 1px solid var(--semi-color-border); border-radius: 8px; overflow: hidden; box-sizing: border-box';

    // icon only takes an image URL, so the built-in options get their icons from the icon snippet
    const builtinIcons: Record<string, typeof IconFigma> = {
        'Semi mcp': IconSemiLogo,
        figma: IconFigma,
    };

    const srcRules = [
        { required: true, message: '请输入 MCP 图标 URL' },
        {
            validator: (_rule: unknown, value: string) => /^(?:https?:\/\/)?(?:www\.)?[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+(?::\d+)?(?:\/[^\s]*)?$/i.test(value),
            message: '请输入有效的 MCP 图标 URL',
        },
    ];

    let index = 1;

    let visible = $state(true);
    let options = $state.raw<MCPConfigureOption[]>([
        {
            value: 'Semi mcp',
            label: 'Semi',
            configure: true,
            desc: '支持 Semi 的文档、源码搜索,辅助开发',
        },
        {
            value: 'figma',
            label: 'Figma',
            desc: 'Figma MCP Server 连接Figma与AI开发工具的功能。它通过标准化的模型上下文协MCP),将组件、变量等设计数据和上下文暴露给AI,从而实现从设计稿到代码的智能生成,显著提升开发效率。',
        },
    ]);
    let customOptions = $state.raw<MCPConfigureOption[]>([]);
    let modalVisible = $state(false);
    let formApi: FormApi<McpFormValues> | undefined;

    const handleOk = () => {
        formApi
            ?.validate()
            .then((values) => {
                customOptions = [
                    ...customOptions,
                    {
                        label: values.name,
                        icon: values.src,
                        value: `mcp-${index++}`,
                        desc: values.desc,
                    },
                ];
                modalVisible = false;
            })
            .catch((errors) => {
                console.log('errors', errors);
            });
    };

    const onConfigureClick = (_event: MouseEvent, option: MCPConfigureOption) => {
        console.log('configure click', option);
    };

    const onEditClick = (_event: MouseEvent, option: MCPConfigureOption) => {
        console.log('edit click', option);
    };
</script>

<div style={containerStyle}>
    <div style="flex-grow: 1; flex-shrink: 1; padding: 20px">
        <Button aria-pressed={visible} onclick={() => (visible = !visible)}>MCP 配置</Button>
    </div>
    <MCPConfigure bind:customOptions bind:options bind:visible onAddClick={() => (modalVisible = true)} {onConfigureClick} {onEditClick} resizable={false} style="width: 500px">
        {#snippet icon({ item })}
            {#if item.icon}
                <img alt="" src={item.icon} style="width: 100%; height: 100%" />
            {:else}
                {@const Icon = builtinIcons[item.value]}
                <Icon />
            {/if}
        {/snippet}
    </MCPConfigure>
    <Modal bind:visible={modalVisible} closeOnEsc onOk={handleOk} title="自定义 MCP">
        <Form getFormApi={(api) => (formApi = api)} layout="vertical" onValueChange={(values) => console.log(values)}>
            <FormInput field="name" label="MCP 名称" rules={[{ required: true, message: '请输入 MCP 名称' }]} style="width: 100%" />
            <FormInput field="src" initValue="/assets/placeholder/avatar-a.svg" label="MCP 图标 URL" rules={srcRules} style="width: 100%" />
            <FormTextArea field="desc" label="MCP 介绍" rules={[{ required: true, message: '请输入 MCP 介绍' }]} style="width: 100%" />
        </Form>
    </Modal>
</div>

参考来源

使用 Annotation 组件可以管理参考来源的展示

  • bind:activeKey 管理当前展开的项
  • info 设置参考来源的具体内容
  • onClick 在点击某条参考来源时调用,参数为事件和该条目
  • 分组标题使用 infoHeader snippet,条目使用 item snippet 替换;header 是整个容器头部
代码
<script lang="ts">
    import { Annotation, type AnnotationInfo, type AnnotationItem } from '@fibrae/semi-ai-svelte';
    import { Button } from '@fibrae/semi-ui-svelte';

    const containerStyle = 'display: flex; height: 500px; border: 1px solid var(--semi-color-border); border-radius: 8px; overflow: hidden; box-sizing: border-box';

    const logo = '/assets/placeholder/avatar-a.svg';
    const img = '/assets/root-web-sites/abstract.jpg';

    const defaultInfoList: AnnotationInfo[] = [
        {
            header: 'Semi design introduction',
            key: '1',
            annotations: [
                {
                    order: 1,
                    type: 'video',
                    duration: 4432,
                    title: 'Semi Design is a design system designed',
                    url: 'https://semi.design/',
                    logo,
                    siteName: 'Semi Design',
                    detail: ' As a comprehensive, easy-to-use, and high-quality modern enterprise-level application UI solution',
                    img,
                },
                {
                    order: 2,
                    title: 'Quick start',
                    type: 'video',
                    duration: 56,
                    url: 'https://semi.design/',
                    detail: ' As a comprehensive, easy-to-use, and high-quality modern enterprise-level application UI solution',
                    logo,
                    siteName: 'Semi Design',
                    img,
                },
                {
                    order: 3,
                    title: 'Use components in a modular way',
                    url: 'https://semi.design/',
                    detail: `Semi provides esm format dist, and the css of the component is only imported by the corresponding js.
When used in Webpack, Rspack, create-react-app or Vite projects, there is no need to configure any compilation items.`,
                    logo,
                    siteName: 'Semi Design',
                    img,
                },
            ],
        },
        {
            header: 'Design resource',
            key: '2',
            annotations: [
                {
                    order: 2,
                    title: 'Semi Design resource',
                    url: 'https://semi.design/',
                    detail: 'Semi Design provides a wealth of design resources to help designers and developers collaborate efficiently. Whether you are a community user or a ByteDance internal designer, you can find UI Kit resource and Figma plug-ins that suit you here.',
                    logo,
                    siteName: 'Semi Design resource',
                    img,
                },
            ],
        },
    ];

    const defaultSize = { width: 420 };
    let visible = $state(true);
    let activeKey = $state<string | string[]>('1');

    const onChange = (key: string | string[]) => {
        console.log('change', key);
    };

    const onClick = (event: MouseEvent, item: AnnotationItem) => {
        console.log('click', event, item);
    };
</script>

<div style={containerStyle}>
    <div style="flex-grow: 1; flex-shrink: 1; padding: 20px">
        <Button aria-pressed={visible} onclick={() => (visible = !visible)}>参考来源</Button>
    </div>
    <Annotation bind:activeKey bind:visible {defaultSize} info={defaultInfoList} {onChange} {onClick} />
</div>

代码展示

可通过 Sidebar 中的 CodeItem 展示代码,CodeItem 基于 JsonViewer 以及 CodeHighlight 实现。

  • content: 内容字符串
  • isJson: 是否为 json
  • language: 编程语言名称,同 CodeHighlight 的 language,需先通过 CodeHighlight.register 注册
  • jsonViewerProps: 配置其他 JsonViewer 参数
  • codeHighlightProps: 配置其他 CodeHighlight 参数

jsonViewerProps 中 JsonViewer 的 value 默认取 content,jsonViewerProps 与 codeHighlightProps 还可以带 class、style。JsonViewer 的自定义渲染与搜索按钮通过 CodeItem 的 customRender、searchButton snippet 使用。

代码
<script lang="ts">
    import { Sidebar } from '@fibrae/semi-ai-svelte';
    import { Radio, RadioGroup, type RadioValue } from '@fibrae/semi-ui-svelte';

    const { CodeItem } = Sidebar;

    const code = `.semi-animation-react-demo-auto {
    button {
        height: 50px;
        border: 0;
        cursor: pointer !important;
        background: #777;
        color: white;
        outline: none;
        -webkit-appearance: none;
    }

    button:hover {
        background: #878787;
    }

    .auto-main {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-template-rows: auto 1fr;
        background: #575757;
    }

    .content {
        grid-column: span 3;
    }

    .item {
        background: indianred;
        width: 100%;
        overflow: hidden;
        color: white;
    }

    .item p {
        margin: 0;
        padding: 10px;
    }
}
`;

    const json = `{
    "axisX": {
        "title": {
            "visible": false,
            "position": "center"
        },
        "label": {
            "visible": true,
            "style": {
                "fontSize": 12,
                "fontWeight": 400,
                "lineHeight": 16,
                "fontFamily": [
                    "Inter"
                ],
                "fill": "rgba(0, 0, 0, 0.47843137254901963)"
            },
            "space": 12
        }
    }
}`;

    const codeProps = {
        content: code,
        language: 'css',
    };

    const jsonProps = {
        isJson: true,
        content: json,
    };

    let type = $state<RadioValue | undefined>('json');
    const itemProps = $derived(type === 'json' ? jsonProps : codeProps);
</script>

<RadioGroup bind:value={type} buttonSize="middle" style="margin-bottom: 10px" type="button">
    <Radio value="json">JSON</Radio>
    <Radio value="css">CSS</Radio>
</RadioGroup>
<div style="height: 200px; overflow: auto">
    <CodeItem {...itemProps} />
</div>

代码列表

用户可通过 Sidebar 中的 CodeContent 组件展示代码列表信息。

  • bind:activeKey 管理当前展开的面板
  • onExpand 监听面板头部的展开按钮,设置后才显示展开按钮
  • customRender、searchButton snippet 转发给每个 JSON 面板中的 JsonViewer
import React from 'react';
import { AutoComplete } from '@fibrae/semi-ui-react';
import { IconSearch } from '@fibrae/semi-icons-react';

() => {
    const [stringData, setStringData] = useState([]);
    const [value, setValue] = useState('');
    const handleStringSearch = (value) => {
        let result;
        if (value) {
            result = ['gmail.com', '163.com', 'qq.com'].map(domain => value+domain);
        } else {
            result = [];
        }
        setStringData(result);
    };

    const handleChange = (value) => {
        console.log('onChange', value);
        setValue(value);
    };
    return (
        <AutoComplete
            data={stringData}
            value={value}
            showClear
            prefix={<IconSearch />}
            placeholder="搜索... "
            onSearch={handleStringSearch}
            onChange={handleChange}
            style={{ width: 200 }}
        />
    );
};
代码
<script lang="ts">
    import { Sidebar } from '@fibrae/semi-ai-svelte';

    const { CodeContent } = Sidebar;

    const defaultCodes = [
        {
            name: 'Component.js',
            key: 'code1',
            language: 'javascript',
            content: `import React from 'react';
import { AutoComplete } from '@fibrae/semi-ui-react';
import { IconSearch } from '@fibrae/semi-icons-react';

() => {
    const [stringData, setStringData] = useState([]);
    const [value, setValue] = useState('');
    const handleStringSearch = (value) => {
        let result;
        if (value) {
            result = ['gmail.com', '163.com', 'qq.com'].map(domain => value+domain);
        } else {
            result = [];
        }
        setStringData(result);
    };

    const handleChange = (value) => {
        console.log('onChange', value);
        setValue(value);
    };
    return (
        <AutoComplete
            data={stringData}
            value={value}
            showClear
            prefix={<IconSearch />}
            placeholder="搜索... "
            onSearch={handleStringSearch}
            onChange={handleChange}
            style={{ width: 200 }}
        />
    );
};
`,
        },
        {
            name: 'Style.css',
            key: 'code2',
            language: 'css',
            content: `.semi-animation-react-demo-auto {
    button {
        height: 50px;
        border: 0;
        cursor: pointer !important;
        background: #777;
        color: white;
        outline: none;
        -webkit-appearance: none;
    }

    button:hover {
        background: #878787;
    }

    .auto-main {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-template-rows: auto 1fr;
        background: #575757;
    }

    .content {
        grid-column: span 3;
    }

    .item {
        background: indianred;
        width: 100%;
        overflow: hidden;
        color: white;
    }

    .item p {
        margin: 0;
        padding: 10px;
    }
}
`,
        },
        {
            name: 'Chart.json',
            key: 'code3',
            isJson: true,
            language: 'html',
            content: `{
    "axisX": {
        "title": {
            "visible": false,
            "position": "center"
        },
        "label": {
            "visible": true,
            "style": {
                "fontSize": 12,
                "fontWeight": 400,
                "lineHeight": 16,
                "fontFamily": [
                    "Inter"
                ],
                "fill": "rgba(0, 0, 0, 0.47843137254901963)"
            },
            "space": 12
        },
        "domainLine": {
            "visible": true,
            "style": {
                "lineWidth": 1,
                "stroke": "rgba(0, 0, 0, 0.12156862745098039)",
                "lineDash": []
            }
        },
        "tick": {
            "visible": false,
            "style": {
                "lineWidth": 1,
                "stroke": "rgba(255, 255, 255, 0)"
            }
        },
        "subTick": {
            "visible": false
        },
        "grid": {
            "visible": false
        },
        "subGrid": {
            "visible": false
        }
    }
}`,
        },
    ];

    let activeKey = $state<string | string[]>('code1');
</script>

<div class="semi-sidebar-main">
    <CodeContent bind:activeKey codes={defaultCodes} style="width: 600px" />
</div>

富文本编辑器

可通过 Sidebar 中的 FileItem 查看、编辑富文本内容, FileItem 基于 tiptap 实现。

  • content:富文本 HTML。挂载后变化会同步到编辑器,与编辑器当前内容相同时不会重置,不会打断输入也不会丢失光标,同步不调用 onContentChange
  • editable: 设置是否可编辑,挂载后变化会同步到编辑器
  • imgUploadProps: 设置图片上传路径以及图片上传后 src 的设置,通过 action 设置上传地址,通过 getUploadImageSrc(response) 函数根据上传响应返回图片上传后地址(未提供时,响应是字符串则直接作为地址,否则取 response.src),用于富文本中 img 节点的 src;Upload 的 on 开头回调(如 onSuccess)也可在这里传入。只有设置了 action 或 customRequest,工具栏才显示图片按钮
  • extensions 与 imgUploadProps 只在创建编辑器时读取,要换用新值时用 {#key} 重新挂载
  • onContentChange 在编辑后调用,参数为 HTML 字符串


代码
<script lang="ts">
    import { Sidebar, type ImageUploadNodeOptions } from '@fibrae/semi-ai-svelte';
    import { Button } from '@fibrae/semi-ui-svelte';

    const { FileItem } = Sidebar;

    const content = `<h2>
  Semi Design 介绍
</h2>
<p>
  Semi Design 是由 <strong>抖音前端团队</strong>和MED产品设计团队设计、开发并维护的<em>设计系统</em>。作为一个全面、易用、优质的现代应用UI解决方案,Semi Design从字节跳动各业务线的复杂场景中提炼而来,目前已经支撑了近千个平台产品,服务了内外部超过10万用户,详情见https://semi.design/zh-CN/start/introduction。Semi Design的特点包括:
</p>
<ul>
  <li>
    设计简洁、现代化。
  </li>
  <li>
    提供主题方案,可深度样式定制。
  </li>
</ul>
<p>
  国际化,覆盖了简/繁体中文、英语、日语、韩语、葡萄牙语等20+种语言,日期时间组件提供全球时区支持,全部组件可自动适配阿拉伯文RTL布局。
</p>
<pre><code class="language-css">body {
  display: none;
}</code></pre>
<p>
  采用 Foundation 和 Adapter 跨框架技术方案,方便扩展。
</p>
<blockquote>
  Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统
  <br />
  — Semi Design
</blockquote>`;

    const imgUploadProps: ImageUploadNodeOptions = {
        action: 'https://api.semi.design/upload',
        // response is the action's result; real code reads the uploaded image URL from it
        getUploadImageSrc: () => '/assets/placeholder/avatar-a.svg',
    };

    let editable = $state(true);
</script>

<Button aria-pressed={editable} onclick={() => (editable = !editable)}>可编辑</Button>
<br />
<br />
<FileItem {content} {editable} {imgUploadProps} name="Semi Design 介绍" style="border: 1px solid var(--semi-color-border); padding: 12px" />

富文本列表

用户可通过 Sidebar 中的 FileContent 组件展示富文本列表信息。

  • bind:activeKey 管理当前展开的面板
  • onExpand 监听面板头部的展开按钮,设置后才显示展开按钮
代码
<script lang="ts">
    import { Sidebar } from '@fibrae/semi-ai-svelte';

    const { FileContent } = Sidebar;

    const intro = `<h2>
  Semi Design 介绍
</h2>
<p>
  Semi Design 是由 <strong>抖音前端团队</strong>和MED产品设计团队设计、开发并维护的<em>设计系统</em>。作为一个全面、易用、优质的现代应用UI解决方案,Semi Design从字节跳动各业务线的复杂场景中提炼而来,目前已经支撑了近千个平台产品,服务了内外部超过10万用户,详情见https://semi.design/zh-CN/start/introduction。Semi Design的特点包括:
</p>
<ul>
  <li>
    设计简洁、现代化。
  </li>
  <li>
    提供主题方案,可深度样式定制。
  </li>
</ul>
<p>
  国际化,覆盖了简/繁体中文、英语、日语、韩语、葡萄牙语等20+种语言,日期时间组件提供全球时区支持,全部组件可自动适配阿拉伯文RTL布局。
</p>
<pre><code class="language-css">body {
  display: none;
}</code></pre>
<p>
  采用 Foundation 和 Adapter 跨框架技术方案,方便扩展。
</p>
<blockquote>
  Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统
  <br />
  — Semi Design
</blockquote>
`;

    const defaultFiles = [
        {
            key: 'file1',
            name: 'Semi Design 介绍',
            content: `\n${intro}${intro}${intro}`,
        },
        {
            key: 'file2',
            name: 'Semi Design DSM',
            content: `<h2>
  Semi Design DSM
</h2>
<p>Semi DSM is a design system management tool provided by Semi Design. It supports global and component-level style customization and keeps synchronization between Figma and front-end code. Suitable for teams of all sizes. Whether you need to simplify workflow, improve team collaboration, or increase productivity, we have features suitable for you.</p>
`,
        },
        {
            key: 'file3',
            name: 'React v19 Adaptation',
            content: `<h2>
  React v19 Adaptation
</h2>
<p>Since the release of React v19, React has introduced numerous underlying mechanism and API changes, including upgrades and adjustments to the render mechanism, ref, context, TypeScript types, and related deprecated APIs. To ensure that the Semi Design component library is smoothly compatible with both React v19 and lower versions, we provide the original component package @fibrae/semi-ui-react for React versions below v19, as well as a new package @fibrae/semi-ui-19 specifically adapted for React v19, so users can choose as needed. This guide will help you understand how to install, use, and the precautions to take.
Installation & Usage
If your project is using React v19, please use @fibrae/semi-ui-19. For React versions below v19, continue using @fibrae/semi-ui-react as before.</p>
`,
        },
    ];

    let activeKey = $state<string | string[]>('file1');
</script>

<div class="semi-sidebar-main">
    <FileContent bind:activeKey files={defaultFiles} style="width: 600px" />
</div>

侧边信息栏

侧边信息栏 Sidebar 有主视图(mode 为 main)和详情视图(mode 为 code、file 及其他)。

主视图可以通过 title 配置标题,通过 showClose 决定是否展示关闭按钮,通过 options 设置顶部的按钮组(每项为 { name, key }),bind:activeKey 绑定当前选中的项。按钮图标使用 optionIcon snippet(参数 { item, index }),需要替换整个按钮时使用 optionItem,其参数 onClick 用于选中该项。

对于主视图的内容渲染,可通过 mainContent snippet(参数 { activeKey }),根据当前选中项渲染。可使用 Annotation 中的 AnnotationContent 渲染参考来源,使用 Sidebar 中内置的 FileContent 渲染富文本, CodeContent 渲染代码。

对于详情视图,如果是富文本或者代码,分别设置 mode 为 code、file,通过 detailContent 设置显示内容,即可通过内置的代码显示组件, 富文本编辑器进行显示;detailContent 的 key 变化时会重新挂载。如果想要自定义详情视图的展示,则通过 detailBody snippet(参数 { mode })自行渲染,详情头部通过 detailHeader snippet(参数 { mode, detailContent })自定义,两者内容为空时回退到内置内容。点击详情头部的返回按钮调用 onBackWard。

工作区占位
Agent 的工作空间
import React from 'react';
import { AutoComplete } from '@fibrae/semi-ui-react';
import { IconSearch } from '@fibrae/semi-icons-react';

() => {
    const [stringData, setStringData] = useState([]);
    const [value, setValue] = useState('');
    const handleStringSearch = (value) => {
        let result;
        if (value) {
            result = ['gmail.com', '163.com', 'qq.com'].map(domain => value+domain);
        } else {
            result = [];
        }
        setStringData(result);
    };

    const handleChange = (value) => {
        console.log('onChange', value);
        setValue(value);
    };
    return (
        <AutoComplete
            data={stringData}
            value={value}
            showClear
            prefix={<IconSearch />}
            placeholder="搜索... "
            onSearch={handleStringSearch}
            onChange={handleChange}
            style={{ width: 200 }}
        />
    );
};
代码
<script lang="ts">
    import { Annotation, Sidebar, type AnnotationInfo, type ImageUploadNodeOptions, type SideBarDetailContent } from '@fibrae/semi-ai-svelte';
    import { IconBriefStroked, IconCodeStroked, IconModalStroked, IconSearch } from '@fibrae/semi-icons-svelte';

    const { FileContent, CodeContent } = Sidebar;
    const { AnnotationContent } = Annotation;

    const containerStyle = 'display: flex; height: 800px; border: 1px solid var(--semi-color-border); border-radius: 8px; overflow: hidden; box-sizing: border-box';

    const optionList = [
        {
            name: '查看搜索',
            key: 'searchResult',
        },
        {
            name: '文件预览',
            key: 'filePreview',
        },
        {
            name: '代码预览',
            key: 'codePreview',
        },
        {
            name: '浏览器',
            key: 'network',
        },
    ];

    const optionIcons: Record<string, typeof IconSearch> = {
        searchResult: IconSearch,
        filePreview: IconBriefStroked,
        codePreview: IconCodeStroked,
        network: IconModalStroked,
    };

    const defaultCodes = [
        {
            name: 'Component.js',
            key: 'code1',
            language: 'javascript',
            content: `import React from 'react';
import { AutoComplete } from '@fibrae/semi-ui-react';
import { IconSearch } from '@fibrae/semi-icons-react';

() => {
    const [stringData, setStringData] = useState([]);
    const [value, setValue] = useState('');
    const handleStringSearch = (value) => {
        let result;
        if (value) {
            result = ['gmail.com', '163.com', 'qq.com'].map(domain => value+domain);
        } else {
            result = [];
        }
        setStringData(result);
    };

    const handleChange = (value) => {
        console.log('onChange', value);
        setValue(value);
    };
    return (
        <AutoComplete
            data={stringData}
            value={value}
            showClear
            prefix={<IconSearch />}
            placeholder="搜索... "
            onSearch={handleStringSearch}
            onChange={handleChange}
            style={{ width: 200 }}
        />
    );
};
`,
        },
        {
            name: 'Style.css',
            key: 'code2',
            language: 'css',
            content: `.semi-animation-react-demo-auto {
    button {
        height: 50px;
        border: 0;
        cursor: pointer !important;
        background: #777;
        color: white;
        outline: none;
        -webkit-appearance: none;
    }

    button:hover {
        background: #878787;
    }

    .auto-main {
        display: grid;
        grid-template-columns: repeat(3, 1fr);
        grid-template-rows: auto 1fr;
        background: #575757;
    }

    .content {
        grid-column: span 3;
    }

    .item {
        background: indianred;
        width: 100%;
        overflow: hidden;
        color: white;
    }

    .item p {
        margin: 0;
        padding: 10px;
    }
}
`,
        },
        {
            name: 'Chart.json',
            key: 'code3',
            isJson: true,
            language: 'html',
            content: `{
    "axisX": {
        "title": {
            "visible": false,
            "position": "center"
        },
        "label": {
            "visible": true,
            "style": {
                "fontSize": 12,
                "fontWeight": 400,
                "lineHeight": 16,
                "fontFamily": [
                    "Inter"
                ],
                "fill": "rgba(0, 0, 0, 0.47843137254901963)"
            },
            "space": 12
        },
        "domainLine": {
            "visible": true,
            "style": {
                "lineWidth": 1,
                "stroke": "rgba(0, 0, 0, 0.12156862745098039)",
                "lineDash": []
            }
        },
        "tick": {
            "visible": false,
            "style": {
                "lineWidth": 1,
                "stroke": "rgba(255, 255, 255, 0)"
            }
        },
        "subTick": {
            "visible": false
        },
        "grid": {
            "visible": false
        },
        "subGrid": {
            "visible": false
        }
    }
}`,
        },
    ];

    const intro = `<h2>
  Semi Design 介绍
</h2>
<p>
  Semi Design 是由 <strong>抖音前端团队</strong>和MED产品设计团队设计、开发并维护的<em>设计系统</em>。作为一个全面、易用、优质的现代应用UI解决方案,Semi Design从字节跳动各业务线的复杂场景中提炼而来,目前已经支撑了近千个平台产品,服务了内外部超过10万用户,详情见https://semi.design/zh-CN/start/introduction。Semi Design的特点包括:
</p>
<ul>
  <li>
    设计简洁、现代化。
  </li>
  <li>
    提供主题方案,可深度样式定制。
  </li>
</ul>
<p>
  国际化,覆盖了简/繁体中文、英语、日语、韩语、葡萄牙语等20+种语言,日期时间组件提供全球时区支持,全部组件可自动适配阿拉伯文RTL布局。
</p>
<pre><code class="language-css">body {
  display: none;
}</code></pre>
<p>
  采用 Foundation 和 Adapter 跨框架技术方案,方便扩展。
</p>
<blockquote>
  Semi Design 是由抖音前端团队和MED产品设计团队设计、开发并维护的设计系统
  <br />
  — Semi Design
</blockquote>
`;

    const defaultFiles = [
        {
            key: 'file1',
            name: 'Semi Design 介绍',
            content: `\n${intro}${intro}${intro}`,
        },
        {
            key: 'file2',
            name: 'Semi Design DSM',
            content: `<h2>
  Semi Design DSM
</h2>
<p>Semi DSM is a design system management tool provided by Semi Design. It supports global and component-level style customization and keeps synchronization between Figma and front-end code. Suitable for teams of all sizes. Whether you need to simplify workflow, improve team collaboration, or increase productivity, we have features suitable for you.</p>
`,
        },
        {
            key: 'file3',
            name: 'React v19 Adaptation',
            content: `<h2>
  React v19 Adaptation
</h2>
<p>Since the release of React v19, React has introduced numerous underlying mechanism and API changes, including upgrades and adjustments to the render mechanism, ref, context, TypeScript types, and related deprecated APIs. To ensure that the Semi Design component library is smoothly compatible with both React v19 and lower versions, we provide the original component package @fibrae/semi-ui-react for React versions below v19, as well as a new package @fibrae/semi-ui-19 specifically adapted for React v19, so users can choose as needed. This guide will help you understand how to install, use, and the precautions to take.
Installation & Usage
If your project is using React v19, please use @fibrae/semi-ui-19. For React versions below v19, continue using @fibrae/semi-ui-react as before.</p>
`,
        },
    ];

    const logo = '/assets/placeholder/avatar-a.svg';
    const img = '/assets/root-web-sites/abstract.jpg';

    const defaultInfoList: AnnotationInfo[] = [
        {
            header: 'Semi design introduction',
            key: '1',
            annotations: [
                {
                    order: 1,
                    type: 'video',
                    duration: 4432,
                    title: 'Semi Design is a design system designed',
                    url: 'https://semi.design/',
                    logo,
                    siteName: 'Semi Design',
                    detail: ' As a comprehensive, easy-to-use, and high-quality modern enterprise-level application UI solution',
                    img,
                },
                {
                    order: 2,
                    title: 'Quick start',
                    type: 'video',
                    duration: 56,
                    url: 'https://semi.design/',
                    detail: ' As a comprehensive, easy-to-use, and high-quality modern enterprise-level application UI solution',
                    logo,
                    siteName: 'Semi Design',
                    img,
                },
                {
                    order: 3,
                    title: 'Use components in a modular way',
                    url: 'https://semi.design/',
                    detail: `Semi provides esm format dist, and the css of the component is only imported by the corresponding js.
When used in Webpack, Rspack, create-react-app or Vite projects, there is no need to configure any compilation items.`,
                    logo,
                    siteName: 'Semi Design',
                    img,
                },
            ],
        },
        {
            header: 'Design resource',
            key: '2',
            annotations: [
                {
                    order: 2,
                    title: 'Semi Design resource',
                    url: 'https://semi.design/',
                    detail: 'Semi Design provides a wealth of design resources to help designers and developers collaborate efficiently. Whether you are a community user or a ByteDance internal designer, you can find UI Kit resource and Figma plug-ins that suit you here.',
                    logo,
                    siteName: 'Semi Design resource',
                    img,
                },
            ],
        },
    ];

    const imgUploadProps: ImageUploadNodeOptions = {
        action: 'https://api.semi.design/upload',
        // response is the action's result; real code reads the uploaded image URL from it
        getUploadImageSrc: () => logo,
    };

    const defaultSize = { width: '60%' };
    let mode = $state('main');
    let activeKey = $state('codePreview');
    let activeCodeKey = $state<string | string[]>('code1');
    let activeFileKey = $state<string | string[]>('file1');
    let activeReferKey = $state<string | string[]>('1');
    let currentDetail = $state.raw<SideBarDetailContent>();

    const onExpand = (_event: MouseEvent, content: SideBarDetailContent, expandMode: string) => {
        mode = expandMode;
        currentDetail = content;
    };
</script>

<div style={containerStyle}>
    <div style="flex-grow: 1; flex-shrink: 1; padding: 20px">工作区占位</div>
    <Sidebar bind:activeKey {defaultSize} detailContent={currentDetail} {imgUploadProps} {mode} motion={false} onBackWard={(_event, backMode) => (mode = backMode)} options={optionList} showClose={false} title="Agent 的工作空间" visible>
        {#snippet optionIcon({ item })}
            {@const Icon = optionIcons[item.key]}
            <Icon />
        {/snippet}
        {#snippet mainContent({ activeKey: currentKey })}
            {#if currentKey === 'searchResult'}
                <AnnotationContent bind:activeKey={activeReferKey} info={defaultInfoList} />
            {:else if currentKey === 'filePreview'}
                <FileContent bind:activeKey={activeFileKey} files={defaultFiles} {onExpand} />
            {:else if currentKey === 'codePreview'}
                <CodeContent bind:activeKey={activeCodeKey} codes={defaultCodes} {onExpand} />
            {:else if currentKey === 'network'}
                <img alt="network" src="/assets/root-web-sites/test.jpg" style="width: 100%" />
            {/if}
        {/snippet}
    </Sidebar>
</div>

API 参考

Sidebar、Annotation、MCPConfigure 与 Container 的 class、style 和其他未声明的属性(如 aria-label)落在 .semi-sidebar-container 元素上;根元素被命名(aria-label 或 aria-labelledby)且没有指定 role 时,role 为 group。CodeContent、CodeItem、FileContent、FileItem、AnnotationContent 的未声明属性落在各自的根元素上。

Sidebar、Annotation、MCPConfigure 与 Sidebar.Container 通过 export function 暴露 getRoot(),用 bind:this 取得实例后调用,返回 HTMLDivElement | null,容器隐藏时为 null。Container 的类型为 SidebarContainerHandle(从 @fibrae/semi-ai-svelte 导出)。

写在组件标签内的 snippet 按名称成为该组件的属性,所以只有 optionIcon、mainContent 等组件声明过的名称才能写在标签内;自己的辅助 snippet 要声明在组件标签之外。

Container

Props

属性说明类型默认值
afterVisibleChange显示或隐藏动画结束后调用,参数为当前是否可见。Type(visible: boolean) => void-
children容器的内容区域。Snippet-
closeOnEsc按下 Esc 键时是否调用 onCancel,默认关闭。booleanfalse
defaultSize初始宽高,仅在 resizable 为 true 时生效。{ width?: number | string; height?: number | string }-
header替换整个头部,标题与关闭按钮也由它负责。Snippet-
maxWidth可调整的最大宽度,仅在 resizable 为 true 时生效。number | string-
minWidth可调整的最小宽度,仅在 resizable 为 true 时生效。number | string150
motion显示与隐藏时是否使用展开动画。booleantrue
onCancel点击关闭按钮,或在 closeOnEsc 为 true 时按下 Esc 调用。Type(event: MouseEvent | KeyboardEvent) => void-
onintroend原生 introend 事件监听,与组件自身的动画结束处理同时执行。TypeEventHandler<CustomEvent<null>, T> | null-
onoutroend原生 outroend 事件监听,与组件自身的动画结束处理同时执行。TypeEventHandler<CustomEvent<null>, T> | null-
resizable宽度是否可拖拽调整;为 true 时 minWidth、maxWidth 与 defaultSize 生效。booleantrue
showClose是否显示头部的关闭按钮。booleantrue
title标题,可以是纯文本,也可以是 snippet。Snippet | string-
visible是否显示容器,可用 bind:visible 绑定。关闭按钮或 Esc 触发取消时先写入 false,再调用 onCancel。boolean-

Methods

方法说明类型
getRoot返回容器根元素 .semi-sidebar-container;隐藏时为 null。Type() => HTMLDivElement | null

MCPConfigure

Props

属性说明类型默认值
afterVisibleChange显示或隐藏动画结束后调用,参数为当前是否可见。Type(visible: boolean) => void-
closeOnEsc按下 Esc 键时是否调用 onCancel。boolean-
customOptions自定义 MCP 工具列表,可用 bind:customOptions 绑定。切换启用状态时先写回绑定,再调用 onStatusChange。MCPConfigureOption[]-
defaultSize初始宽高,仅在 resizable 为 true 时生效。{ width?: number | string; height?: number | string }-
desc选项的描述,参数为 item、index 和 custom;未提供时显示 desc 字段。TypeSnippet<[MCPConfigureItemSnippetProps]>-
filter自定义搜索过滤,参数为转为小写的输入值和选项;默认按 label 与 desc 匹配。Type(inputValue: string, option: MCPConfigureOption) => boolean-
header替换整个头部,标题与关闭按钮也由它负责。Snippet-
icon选项的图标,参数为 item、index 和 custom;提供后所有选项都使用它,icon 字段只在未提供时作为图片地址。TypeSnippet<[MCPConfigureItemSnippetProps]>-
item替换整行内置选项,参数为 item、index 和 custom。TypeSnippet<[MCPConfigureItemSnippetProps]>-
maxWidth可调整的最大宽度,仅在 resizable 为 true 时生效。number | string-
minWidth可调整的最小宽度,仅在 resizable 为 true 时生效。number | string-
motion显示与隐藏时是否使用展开动画。boolean-
onAddClick点击自定义页的新增按钮时调用。Type(event: MouseEvent) => void-
onCancel点击关闭按钮,或在 closeOnEsc 为 true 时按下 Esc 调用。Type(event: MouseEvent | KeyboardEvent) => void-
onConfigureClick点击内置工具的配置按钮时调用,参数为点击事件和对应选项。Type(event: MouseEvent, option: MCPConfigureOption) => void-
onEditClick点击自定义工具的编辑按钮时调用,参数为点击事件和对应选项。Type(event: MouseEvent, option: MCPConfigureOption) => void-
onSearch搜索输入变化时调用,参数为输入值,以及当前是否为自定义列表。Type(inputValue: string, custom: boolean) => void-
onStatusChange切换启用状态后调用,参数为 active 已更新的列表,以及它是否为自定义列表。Type(options: MCPConfigureOption[], custom: boolean) => void-
options内置 MCP 工具列表,可用 bind:options 绑定;每项的 value 必填且唯一。切换启用状态时先写回绑定,再调用 onStatusChange。MCPConfigureOption[]-
placeholder搜索框的占位文字,默认使用语言包文案。string-
resizable宽度是否可拖拽调整;为 true 时 minWidth、maxWidth 与 defaultSize 生效。boolean-
showClose是否显示头部的关闭按钮。boolean-
title标题,可以是纯文本或 snippet,默认使用语言包中的 MCP 配置。Snippet | string-
visible是否显示,可用 bind:visible 绑定。boolean-

Methods

方法说明类型
getRoot返回容器根元素 .semi-sidebar-container;隐藏时为 null。Type() => any

MCPConfigureOption

属性说明类型默认值
active是否处于激活状态booleanfalse
configure是否显示配置按钮booleanfalse
desc描述文本,内置过滤会匹配它;其他内容使用 desc snippetstring-
disabled是否禁用,为 true 时用户无法更改激活状态booleanfalse
icon图标的图片地址;其他内容使用 icon snippetstring-
label标签文本string-
value对应的值,必填。在 onStatusChange 中标识选项,也作为列表项的 key,同一列表内需唯一string-

Annotation

Props

属性说明类型默认值
activeKey当前展开的分组 key,可用 bind:activeKey 绑定。string | string[]-
afterVisibleChange显示或隐藏动画结束后调用,参数为当前是否可见。Type(visible: boolean) => void-
closeOnEsc按下 Esc 键时是否调用 onCancel。boolean-
defaultSize初始宽高,仅在 resizable 为 true 时生效。{ width?: number | string; height?: number | string }-
header替换整个头部,标题与关闭按钮也由它负责。Snippet-
info参考来源分组列表,每组包含 header、key 与 annotations。AnnotationInfo[]-
infoHeader分组头部图标之后的内容,参数为 item 与 index;未提供时显示 header 字段。容器的 header 已用于替换整个头部,所以分组头部叫 infoHeader。TypeSnippet<[AnnotationHeaderSnippetProps]>-
item替换内置的参考来源条目,参数为 item 与 index(在分组内的位置)。TypeSnippet<[AnnotationItemSnippetProps]>-
maxWidth可调整的最大宽度,仅在 resizable 为 true 时生效。number | string-
minWidth可调整的最小宽度,仅在 resizable 为 true 时生效。number | string-
motion显示与隐藏时是否使用展开动画。boolean-
onCancel点击关闭按钮,或在 closeOnEsc 为 true 时按下 Esc 调用。Type(event: MouseEvent | KeyboardEvent) => void-
onChange展开或收起分组时调用,参数为当前展开的 key。Type(activeKey: string | string[]) => void-
onClick点击某条参考来源时调用,参数为点击事件和对应条目;根元素的原生 click 不单独上报。Type(event: MouseEvent, item: AnnotationItem) => void-
resizable宽度是否可拖拽调整;为 true 时 minWidth、maxWidth 与 defaultSize 生效。boolean-
showClose是否显示头部的关闭按钮。boolean-
title标题,可以是纯文本或 snippet,默认使用语言包文案。Snippet | string-
visible是否显示,可用 bind:visible 绑定。boolean-

Methods

方法说明类型
getRoot返回容器根元素 .semi-sidebar-container;隐藏时为 null。Type() => any

AnnotationContent

Props

属性说明类型默认值
activeKey当前展开的分组 key,可用 bind:activeKey 绑定。string | string[]-
header分组头部图标之后的内容,参数为 item 与 index;未提供时显示 header 字段。TypeSnippet<[AnnotationHeaderSnippetProps]>-
info参考来源分组列表,每组包含 header、key 与 annotations。AnnotationInfo[][]
item替换内置的参考来源条目,参数为 item 与 index(在分组内的位置)。TypeSnippet<[AnnotationItemSnippetProps]>-
onChange展开或收起分组时调用,参数为当前展开的 key。Type(activeKey: string | string[]) => void-
onClick点击某条参考来源时调用,参数为点击事件和对应条目;根元素的原生 click 不单独上报。Type(event: MouseEvent, item: AnnotationItem) => void-

AnnotationInfo

属性说明类型默认值
annotations该分组下的参考来源条目AnnotationItem[]-
header分组标题的纯文本,也可用 infoHeader(Annotation)或 header(AnnotationContent)snippet 自定义string-
key分组的唯一标识string-

AnnotationItem

属性说明类型默认值
detail内容详情/补充说明(如视频简介、文本备注等)string-
duration时长(通常为视频时长,单位:秒)number-
img图片地址(如视频封面图、文本配图地址)string-
logo站点/内容所属平台的 logo 图片地址string-
order引用序号(用于内容排序/标注序号展示)number-
siteName内容所属的站点/平台名称string-
title内容标题string-
type内容类型'video' | 'text'-
url资源链接,在新标签页打开;没有 url 的条目渲染为无 href 的链接,只能用指针点击string-

Props

属性说明类型默认值
activeKey主视图中当前选中的选项 key,可用 bind:activeKey 绑定。string-
afterVisibleChange显示或隐藏动画结束后调用,参数为当前是否可见。Type(visible: boolean) => void-
closeOnEsc按下 Esc 键时是否调用 onCancel。boolean-
customRender转发给内置代码详情中 JsonViewer 的 customRender snippet,用于渲染 customRenderRule 匹配的内容。TypeSnippet<[JsonViewerCustomRenderArgs]>-
defaultSize初始宽高,仅在 resizable 为 true 时生效。{ width?: number | string; height?: number | string }-
detailBody详情模式的内容,参数为 mode;内容为空时回退到内置的代码或富文本详情。因 detailContent 已是数据属性,所以叫 detailBody。TypeSnippet<[SideBarDetailBodySnippetProps]>-
detailContentcode 与 file 模式显示的条目,为 CodeItem 或 FileItem 的属性加 key;key 变化时重新挂载该条目。file 模式下其中的 editable 与 imgUploadProps 不生效,由 fileEditable 与 imgUploadProps 决定。SideBarDetailContent-
detailHeader详情模式的头部,参数为 mode 与 detailContent;内容为空时回退到内置头部。TypeSnippet<[SideBarDetailHeaderSnippetProps]>-
fileEditablefile 模式的富文本是否可编辑。booleantrue
imgUploadPropsfile 模式的图片上传配置,编辑器创建时读取,之后变化不生效。ImageUploadNodeOptions-
mainContent主视图中选项下方的内容,参数为 activeKey。TypeSnippet<[SideBarMainContentSnippetProps]>-
maxWidth可调整的最大宽度,仅在 resizable 为 true 时生效。number | string-
minWidth可调整的最小宽度,仅在 resizable 为 true 时生效。number | string-
mode展示模式:main 为主视图,code 与 file 使用内置详情,其他字符串通过 detailBody snippet 自行渲染。string"main"
motion显示与隐藏时是否使用展开动画。boolean-
onActiveOptionChange点击选项、activeKey 更新后调用,参数为点击事件和该选项的 key。Type(event: MouseEvent, activeKey: string) => void-
onBackWard点击详情头部的返回按钮时调用,参数为点击事件和 main。Type(event: MouseEvent, mode: string) => void-
onCancel点击关闭按钮,或在 closeOnEsc 为 true 时按下 Esc 调用。Type(event: MouseEvent | KeyboardEvent) => void-
onDetailContentCopy复制按钮写入剪贴板后调用,参数为点击事件、复制的内容和是否成功。Type(event: MouseEvent, content: string, success: boolean) => void-
onFileContentChangefile 模式下编辑后调用,参数为 HTML 字符串。Type(content: string) => void-
optionIcon内置选项按钮的图标,参数为 item 与 index。TypeSnippet<[SideBarOptionSnippetProps]>-
optionItem替换整个选项按钮,参数为 item、index、active 与 onClick(选中该选项)。TypeSnippet<[SideBarOptionItemSnippetProps]>-
options主视图顶部的选项按钮,每项包含 name 与 key;图标使用 optionIcon snippet。SideBarOption[]-
resizable宽度是否可拖拽调整;为 true 时 minWidth、maxWidth 与 defaultSize 生效。boolean-
searchButton转发给内置代码详情中 JsonViewer 的 searchButton snippet,替换其搜索按钮。TypeSnippet<[JsonViewerSearchButtonArgs]>-
showClose是否显示头部的关闭按钮。boolean-
title标题,可以是纯文本或 snippet。Snippet | string-
visible是否显示,可用 bind:visible 绑定。boolean-

Methods

方法说明类型
getRoot返回容器根元素 .semi-sidebar-container;隐藏时为 null。Type() => any

SideBarOption

属性说明类型默认值
key选项的唯一标识string-
name选项名称,图标使用 optionIcon snippetstring-

CodeContent

codes 的每一项为 CodeItem 的属性加用于标识面板的 key。

Props

属性说明类型默认值
activeKey当前展开的代码面板 key,可用 bind:activeKey 绑定。string | string[]-
codes代码条目列表,每项为 CodeItem 的属性加用于标识面板的 key。CodeItemData[][]
customRender转发给每个 JSON 面板中 JsonViewer 的 customRender snippet。TypeSnippet<[JsonViewerCustomRenderArgs]>-
onChange通过箭头展开或收起面板时调用,参数为当前展开的 key。Type(activeKey: string | string[]) => void-
onExpand点击面板头部旁的展开按钮时调用,参数为点击事件、对应条目和 code。未传入时不渲染展开按钮。Type(event: MouseEvent, item: T, mode: string) => void-
searchButton转发给每个 JSON 面板中 JsonViewer 的 searchButton snippet,替换其搜索按钮。TypeSnippet<[JsonViewerSearchButtonArgs]>-

CodeItem

Props

属性说明类型默认值
codeHighlightProps传给 CodeHighlight 的其他属性,以及追加的 class 与 style。TypePartial<CodeHighlightProps>-
content代码或 JSON 字符串。string-
customRenderJsonViewer 的 customRender snippet,用于渲染 jsonViewerProps.options.customRenderRule 匹配的内容。TypeSnippet<[JsonViewerCustomRenderArgs]>-
isJson为 true 时用 JsonViewer 展示,否则用 CodeHighlight。booleanfalse
jsonViewerProps传给 JsonViewer 的其他属性,以及追加的 class 与 style。value(content)、width 与 height(100%)、options(只读、自动换行)、showSearch(false)已有默认值,同名属性整体覆盖默认值。TypePartial<JsonViewerProps>-
language编程语言名称,同 CodeHighlight 的 language,需先通过 CodeHighlight.register 注册,未注册时显示纯文本。string-
name代码项名称,由 CodeContent 的面板头部和 Sidebar 的详情头部显示,CodeItem 自身不渲染。string-
searchButtonJsonViewer 的 searchButton snippet,替换其搜索按钮。TypeSnippet<[JsonViewerSearchButtonArgs]>-

FileContent

files 的每一项为 FileItem 的属性加用于标识面板的 key,以只读方式渲染,extensions 与 imgUploadProps 会传给其预览。

Props

属性说明类型默认值
activeKey当前展开的文件面板 key,可用 bind:activeKey 绑定。string | string[]-
files文件条目列表,以只读方式渲染,每项的 extensions 与 imgUploadProps 会传给其预览。FileItemData[][]
onChange通过箭头展开或收起面板时调用,参数为当前展开的 key。Type(activeKey: string | string[]) => void-
onExpand点击面板头部旁的展开按钮时调用,参数为点击事件、对应条目和 file。未传入时不渲染展开按钮。Type(event: MouseEvent, item: T, mode: string) => void-

FileItem

Props

属性说明类型默认值
content富文本 HTML。挂载后变化会同步到编辑器,与编辑器当前内容相同时不会重置,同步不调用 onContentChange。string-
editable是否可编辑,挂载后变化会同步到编辑器。booleantrue
extensions追加到内置扩展之后的 tiptap 扩展,编辑器创建时读取,之后变化不生效。Extensions[]
imgUploadProps图片上传配置,编辑器创建时读取,之后变化不生效。ImageUploadNodeOptions-
name文件名称,作为编辑区域的可访问名称,挂载后变化会同步到编辑器。string-
onContentChange编辑后调用,参数为 HTML 字符串。Type(content: string) => void-