{"componentChunkName":"component---src-templates-post-template-js","path":"/en-US/ai/aiChatInput","result":{"data":{"current":{"frontmatter":{"title":"AIChatInput","order":101,"brief":"Input box used in AI chat scenarios","icon":"doc-aiInput"},"fields":{"type":"ai"},"tableOfContents":{"items":[{"url":"#usage-scenarios","title":"Usage Scenarios"},{"url":"#demos","title":"Demos","items":[{"url":"#how-to-import","title":"How to import"},{"url":"#basic-usage","title":"Basic Usage"},{"url":"#message-sending","title":"Message Sending"},{"url":"#rich-text-input","title":"Rich Text Input"},{"url":"#reference","title":"Reference"},{"url":"#configuration-area","title":"Configuration Area"},{"url":"#action-area","title":"Action Area"},{"url":"#custom-upload-button","title":"Custom Upload Button"},{"url":"#button-shape","title":"Button Shape"},{"url":"#suggestions","title":"Suggestions"},{"url":"#skills--templates","title":"Skills & Templates"},{"url":"#custom-top-slot","title":"Custom Top Slot"},{"url":"#custom-extensions","title":"Custom Extensions"}]},{"url":"#api-reference","title":"API Reference","items":[{"url":"#aichatinput","title":"AIChatInput"},{"url":"#configureselect","title":"Configure.Select"},{"url":"#configurebutton","title":"Configure.Button"},{"url":"#configureradiobutton","title":"Configure.RadioButton"},{"url":"#configuremcp","title":"Configure.Mcp"}]},{"url":"#methods","title":"Methods"},{"url":"#design-tokens","title":"Design Tokens"}]},"body":"var _excluded = [\"components\"];\nfunction _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }\nfunction _objectWithoutProperties(e, t) { if (null == e) return {}; var o, r, i = _objectWithoutPropertiesLoose(e, t); if (Object.getOwnPropertySymbols) { var s = Object.getOwnPropertySymbols(e); for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]); } return i; }\nfunction _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (e.includes(n)) continue; t[n] = r[n]; } return t; }\n/* @jsxRuntime classic */\n/* @jsx mdx */\n\nvar _frontmatter = {\n  \"localeCode\": \"en-US\",\n  \"order\": 101,\n  \"category\": \"Ai\",\n  \"title\": \"AIChatInput\",\n  \"icon\": \"doc-aiInput\",\n  \"width\": \"60%\",\n  \"brief\": \"Input box used in AI chat scenarios\",\n  \"showNew\": true\n};\nvar makeShortcode = function makeShortcode(name) {\n  return function MDXDefaultShortcode(props) {\n    console.warn(\"Component \" + name + \" was not imported, exported, or provided by MDXProvider as global scope\");\n    return mdx(\"div\", props);\n  };\n};\nvar ApiType = makeShortcode(\"ApiType\");\nvar DesignToken = makeShortcode(\"DesignToken\");\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n    props = _objectWithoutProperties(_ref, _excluded);\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Usage Scenarios\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"In AI chat scenarios, users can use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AIChatInput\"), \" to achieve rich text input, uploading, quoting, suggestions, templates, feature configuration, and rich custom display.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AIChatInput\"), \"'s rich text input is based on \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"tiptap\"), \" (\", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://tiptap.dev/docs/editor/getting-started/overview\"\n  }, \"https://tiptap.dev/docs/editor/getting-started/overview\"), \"), a modern rich text editor development framework that supports mainstream front-end frameworks such as React and Vue, and boasts strong customizability and extensibility. Its componentization capabilities are excellent, performance is high, it has many built-in commonly used extensions, and it supports user-defined nodes, commands, plugins, and menus, enabling flexible adaptation and expansion of rich text input capabilities in complex AI scenarios. Semi's \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"AIChatInput\"), \" component encapsulates tiptap, allowing developers to use it out of the box or extend it as needed according to business requirements.\")), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Demos\"), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"How to import\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"import\",\n    \"import\": true\n  }, \"import { AIChatInput } from '@douyinfe/semi-ui';\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Basic Usage\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Supports text input and file upload. You can configure the following parameters as needed:\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"uploadProps\"), \": Configure parameters related to file upload. See \", mdx(\"a\", {\n    parentName: \"li\",\n    \"href\": \"https:/lf3-static.semi.design/obj/semi-tos/semi_main/en-US/plus/upload#API\"\n  }, \"UploadProps\")), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onUploadChange\"), \": Callback when file upload changes\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"When deleting uploaded files, \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"uploadProps.onRemove\"), \" will be triggered, and \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"uploadProps.beforeRemove\"), \" will be respected (Promise supported)\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"placeholder\"), \": Placeholder for the input box\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"defaultContent\"), \": Default content for the input box\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onContentChange\"), \": Callback when the content of the input box changes; the parameter is the current content\")), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\n\\nfunction Basic() {\\n    const onContentChange = useCallback((content) => {\\n        console.log('onContentChange', content);\\n    }, []);\\n\\n    const onUploadChange = useCallback((fileList) => {\\n        console.log('onUploadChange', fileList);\\n    }, []);\\n  \\n    return (\\n        <AIChatInput\\n            placeholder={'Enter content or upload...'} \\n            uploadProps={uploadProps}\\n            onContentChange={onContentChange}\\n            onUploadChange={onUploadChange}\\n            style={outerStyle} \\n        />\\n    );\\n};\\n\\nrender(<Basic />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Message Sending\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"When there is content in the input box (including text entry, uploaded content, \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https:/lf3-static.semi.design/obj/semi-tos/semi_main/en-US/plus/aiChatInput#Reference\"\n  }, \"reference content\"), \"), sending messages is allowed. Clicking the send message button triggers the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"onMessageSend\"), \" callback; the argument is the input content, including text, reference content, uploaded files, and configuration area content.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can manage generating status with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"generating\"), \". If \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"generating\"), \" is \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"true\"), \", AIChatInput will show a stop-generating button instead of the send button and clear the input area as well as uploaded files. References require manual handling.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Clicking the stop button triggers \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"onStopGenerate\"), \", where you can handle logic such as setting \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"generating\"), \" to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"false\"), \".\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\n\\nconst uploadProps = { \\n    action: \\\"https://api.semi.design/upload\\\",\\n    defaultFileList: [\\n        {\\n            uid: '1',\\n            name: 'dy.jpeg',\\n            status: 'success',\\n            size: '130kb',\\n            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png',\\n        },\\n        {\\n            uid: '5',\\n            name: 'resso.jpeg',\\n            percent: 50,\\n            size: '222kb',\\n            url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png',\\n        }\\n    ],\\n};\\nconst outerStyle = { margin: 12 };\\n\\nconst reference = [\\n    {\\n        id: '1',\\n        type: 'text',\\n        content: 'Test text: This is a long text repeated many times for demonstration purposes...'\\n    }\\n];\\n\\nfunction SendMessageAndStopGenerate() {\\n    const [references, setReferences] = useState(reference);\\n    const [generating, setGenerating] = useState(false);\\n    const onContentChange = useCallback((content) => {\\n        console.log('onContentChange', content);\\n    }, []);\\n\\n    const onUploadChange = useCallback((fileList) => {\\n        console.log('onUploadChange', fileList);\\n    }, []);\\n\\n    const toggleGenerate = useCallback((props) => {\\n        setGenerating(value => !value);\\n    }, []);\\n\\n    const onMessageSend = useCallback((content) => {\\n        toggleGenerate();\\n        setReferences([]);\\n    }, []);\\n\\n    const handleReferenceDelete = useCallback((item) => {\\n        setReferences((references) => {\\n            const newReference = references.filter((ref) => ref.id !== item.id);\\n            return newReference;\\n        });\\n    }, []);\\n    \\n    return (\\n        <AIChatInput\\n            defaultContent={\\\"Click Send to see changes in content, uploads, and references.\\\"}\\n            generating={generating}\\n            uploadProps={uploadProps}\\n            onContentChange={onContentChange}\\n            onUploadChange={onUploadChange}\\n            style={outerStyle}\\n            onMessageSend={onMessageSend}\\n            onStopGenerate={toggleGenerate}\\n            onReferenceDelete={handleReferenceDelete}\\n            references={references}\\n        />\\n    );\\n};\\n\\nrender(<SendMessageAndStopGenerate />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Rich Text Input\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"AIChatInput uses \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://tiptap.dev/docs/editor/getting-started/overview\"\n  }, \"tiptap\"), \" for its rich text editor. You can enter text, use built-in extensions (including \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"input-slot\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"select-slot\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"skill-slot\"), \"), or extend with your own.\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"input-slot\"), \": Supports text input and placeholder display.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"select-slot\"), \": Supports in-box option selection with string options.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"skill-slot\"), \": For skill display blocks.\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can set input content with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"setContent\"), \" ref method and focus the editor with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"focusEditor\"), \".\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React, { useRef, useCallback } from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst temp = {\\n    'input-slot': 'I am an <input-slot placeholder=\\\"[Occupation]\\\">engineer</input-slot>',\\n    'select-slot': 'I am a <select-slot value=\\\"Front-end Developer\\\" options=\\\\'[\\\"Designer\\\",\\\"Front-end Developer\\\",\\\"Back-end Developer\\\"]\\\\'></select-slot>, please help me complete...',\\n    'skill-slot': '<skill-slot data-value=\\\"AI Coding\\\"></skill-slot> Please help me complete...'\\n};\\n\\nfunction RichTextExample() {\\n    const [activeIndex, setActiveIndex] = useState(0);\\n    const ref = useRef();\\n\\n    const setTemplate = useCallback((event) => {\\n        const index = Number(event.target.dataset.index);\\n        setActiveIndex(index);\\n        const content = Object.values(temp)[index];\\n        if (ref.current) {\\n            ref.current.setContent(content);\\n            ref.current.focusEditor();\\n        }\\n    }, [ref]);\\n\\n    return (<>\\n        <div className=\\\"aiChatInput-radio\\\">\\n            {Object.keys(temp).map((item, index) => (\\n                <div \\n                    className={`aiChatInput-radio-item ${index === activeIndex ? 'aiChatInput-radio-item-selected' : ''}`}\\n                    key={index} \\n                    data-index={index} \\n                    onClick={setTemplate}\\n                >{item}</div>\\n            ))}\\n        </div>\\n        <AIChatInput\\n            ref={ref}\\n            defaultContent={temp['input-slot']}\\n            placeholder={'Enter content or upload'} \\n            uploadProps={uploadProps}\\n            style={outerStyle} \\n        />\\n    </>);\\n};\\n\\nrender(<RichTextExample />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Reference\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can pass in references via the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"references\"), \", which will display at the top of the input box.\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"renderReference\"), \": Custom renderer for an individual reference.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onReferenceDelete\"), \": Callback for deleting a reference.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"onReferenceClick\"), \": Callback for clicking a reference.\")), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst referenceTemp = [\\n    { id: '1', type: 'text', content: 'Sample text, repeated to demonstrate a long text.' },\\n    { id: '2', name: 'FeishuDoc.docx' },\\n    { id: '3', name: 'FeishuDoc.pdf' },\\n    { id: '4', name: 'Music.mp4' },\\n    { id: '5', name: 'Image.jpeg', url: 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/Resso.png' },\\n    { id: '6', name: 'code.json' }\\n];\\n\\nfunction Reference() {\\n    const [references, setReferences] = useState(referenceTemp);\\n    const handleReferenceDelete = useCallback((item) => {\\n        const newReference = references.filter((ref) => ref.id !== item.id);\\n        setReferences(newReference);\\n    }, [references]);\\n\\n    const handleReferenceClick = useCallback((item) => {\\n        console.log('Clicked reference', item);\\n    }, []);\\n    \\n    return (\\n        <AIChatInput\\n            placeholder={'Demo for viewing reference content'} \\n            onReferenceDelete={handleReferenceDelete}\\n            onReferenceClick={handleReferenceClick}\\n            references={references} \\n            uploadProps={uploadProps}\\n            style={outerStyle}\\n        />\\n    );\\n};\\n\\nrender(<Reference />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Configuration Area\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can configure options such as model parameters, web search, and critical thinking through the configuration area, or display/view MCP tools.\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"renderConfigureArea\"), \": Custom renderer for config area buttons.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Use \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Configure\"), \" components such as \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Select\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Button\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Mcp\"), \", \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"RadioButton\"), \", etc.\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"The \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Configure\"), \" component manages the state and provides a callback via \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"onConfigureChange\"), \" (make sure to set the unique \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"field\"), \"). For initial values, use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"initValue\"), \".\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can also use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getConfigureItem\"), \" to adapt your custom components.\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\nimport { IconFixedStroked, IconBookOpenStroked, IconFeishuLogo, IconGit, IconFigma } from '@douyinfe/semi-icons';\\n\\nconst { Configure } = AIChatInput;\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst modelOptions = [\\n    { value: 'GPT-5', label: 'GPT-5' },\\n    { value: 'GPT-4o', label: 'GPT-4o' },\\n    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },\\n];\\n\\nconst mcpOptions = [\\n    { icon: <IconFeishuLogo />, label: \\\"FeishuDoc\\\", value: \\\"feishu\\\" },\\n    { icon: <IconGit />, label: \\\"Github Mcp\\\", value: \\\"github\\\" },\\n    { icon: <IconFigma />, label: \\\"IconFigma Mcp\\\", value: \\\"IconFigma\\\" }\\n];\\n\\nconst radioButtonProps = [\\n    { label: 'Fast', value: 'fast' },\\n    { label: 'Think', value: 'think' },\\n    { label: 'Super', value: 'super' }\\n];\\n\\nfunction ConfigureButton() {\\n    const onConfigureButtonClick = useCallback(() => {\\n        console.log('onConfigureButtonClick');\\n    }, []);\\n\\n    const renderLeftMenu = useCallback(() => (<>\\n        <Configure.Select optionList={modelOptions} field=\\\"model\\\" initValue=\\\"GPT-4o\\\" />\\n        <Configure.Button icon={<IconBookOpenStroked />} field=\\\"onlineSearch\\\">Web search</Configure.Button>\\n        <Configure.Mcp options={mcpOptions} onConfigureButtonClick={onConfigureButtonClick}/>\\n        <Configure.RadioButton options={radioButtonProps} field=\\\"thinkType\\\" initValue=\\\"fast\\\"/>\\n    </>), []);\\n\\n    const onConfigureChange = useCallback((value, changedValue) => {\\n        console.log('onConfigureChange', value, changedValue);\\n    }, []);\\n    \\n    return (\\n        <AIChatInput\\n            placeholder={'Demo for configuration area on the lower left'} \\n            renderConfigureArea={renderLeftMenu} \\n            onConfigureChange={onConfigureChange}\\n            uploadProps={uploadProps}\\n            style={outerStyle}\\n        />\\n    );\\n};\\n\\nrender(<ConfigureButton />);\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can extend any custom component for configuration using \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"getConfigureItem\"), \".\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"function getConfigureItem(\\n    component: React.ReactElement,\\n    opts: {\\n        valueKey?: string; \\n        onKeyChangeFnName?: string;\\n        valuePath?: string;\\n        className?: string;\\n        defaultProps?: Record<string, any>\\n    }\\n)\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Demo:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React, { useCallback } from 'react';\\nimport { Cascader, AIChatInput, getConfigureItem } from '@douyinfe/semi-ui';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst cascaderModalOptions = [\\n    { label: 'GPT', value: 'GPT', children: [{ label: 'GPT-4o', value: 'GPT-4o' }, { value: 'GPT-5', label: 'GPT-5' }] },\\n    { label: 'Claude', value: 'Claude', children: [{ label: 'Claude 3.5 Sonnet', value: 'Claude 3.5 Sonnet' }] }\\n];\\n\\nconst myCascader = (props) => <Cascader {...props} />;\\nconst CustomCascader = getConfigureItem(myCascader, { \\n    className: 'aiChatInput-cascader-configure'\\n});\\n\\nclass CustomConfigure extends React.Component {\\n    constructor(props) {\\n        super(props);\\n        this.renderLeftMenu = this.renderLeftMenu.bind(this);\\n        this.onConfigureChange = this.onConfigureChange.bind(this);\\n    }\\n    renderLeftMenu() {\\n        return <CustomCascader field=\\\"model\\\" treeData={cascaderModalOptions} initValue={['GPT', 'GPT-4o']} />;\\n    }\\n    onConfigureChange(value, changedValue) {\\n        console.log('onConfigureChange', value, changedValue);\\n    }\\n    render() {\\n        return (<AIChatInput\\n            placeholder={'Demo for configuration on the lower left'} \\n            renderConfigureArea={this.renderLeftMenu} \\n            onConfigureChange={this.onConfigureChange}\\n            uploadProps={uploadProps}\\n            style={outerStyle}\\n        />);\\n    };\\n}\\n\\nrender(<CustomConfigure />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Action Area\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"The lower right corner is the action area. Use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"renderActionArea\"), \" to customize buttons (e.g. for deleting or other operations).\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput, Divider, Button } from '@douyinfe/semi-ui';\\nimport { IconDeleteStroked } from '@douyinfe/semi-icons';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\n\\nfunction ActionArea() {\\n    const renderActionArea = useCallback((props) => (\\n        <div className={props.className}>\\n            <div style={{ display: 'flex', alignItems: 'center' }} key=\\\"delete\\\">\\n                <Button type=\\\"tertiary\\\" style={{ borderRadius: '50%' }} icon={<IconDeleteStroked />}/>\\n                <Divider layout=\\\"vertical\\\" style={{ marginLeft: 8 }}/>\\n            </div>\\n            {props.menuItem}\\n        </div>\\n    ), []);\\n  \\n    return (\\n        <AIChatInput\\n            renderActionArea={renderActionArea}\\n            placeholder={'Enter content or upload...'} \\n            uploadProps={uploadProps}\\n            style={outerStyle} \\n        />\\n    );\\n};\\n\\nrender(<ActionArea />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Custom Upload Button\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"By default, an upload button is rendered on the left side of the footer action area. Use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"renderUploadButton\"), \" for \", mdx(\"strong\", {\n    parentName: \"p\"\n  }, \"UI-only\"), \" customization (e.g. icon-only button, tooltip, etc.).\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Note: This does not affect upload / paste-upload behavior (\", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"Upload\"), \" is still managed internally). \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"openFileDialog\"), \" triggers the internal Upload file chooser.\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\nimport { IconUpload } from '@douyinfe/semi-icons';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\n\\nfunction CustomUploadButton() {\\n    return (\\n        <AIChatInput\\n            placeholder={'Custom upload button UI (paste-upload still works)'}\\n            uploadProps={uploadProps}\\n            renderUploadButton={({ openFileDialog, disabled }) => (\\n                <button\\n                    type=\\\"button\\\"\\n                    disabled={disabled}\\n                    className=\\\"semi-button semi-button-borderless\\\"\\n                    onClick={(e) => {\\n                        e.stopPropagation();\\n                        openFileDialog();\\n                    }}\\n                >\\n                    <IconUpload />\\n                </button>\\n            )}\\n            style={outerStyle}\\n        />\\n    );\\n}\\n\\nrender(<CustomUploadButton />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Button Shape\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"You can use the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"round\"), \" API to configure the button shape at the bottom. The default is \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"true\"), \" (rounded). Set it to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"false\"), \" for square buttons.\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput, RadioGroup, Radio } from '@douyinfe/semi-ui';\\nimport { IconFixedStroked, IconBookOpenStroked, IconFeishuLogo, IconGit, IconFigma } from '@douyinfe/semi-icons';\\n\\nconst { Configure } = AIChatInput;\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst modelOptions = [\\n    { value: 'GPT-5', label: 'GPT-5' },\\n    { value: 'GPT-4o', label: 'GPT-4o' },\\n    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },\\n];\\n\\nconst mcpOptions = [\\n    { icon: <IconFeishuLogo />, label: \\\"FeishuDoc\\\", value: \\\"feishu\\\" },\\n    { icon: <IconGit />, label: \\\"Github Mcp\\\", value: \\\"github\\\" },\\n    { icon: <IconFigma />, label: \\\"IconFigma Mcp\\\", value: \\\"IconFigma\\\" }\\n];\\n\\nconst radioButtonProps = [\\n    { label: 'Fast', value: 'fast' },\\n    { label: 'Think', value: 'think' },\\n    { label: 'Super', value: 'super' }\\n];\\n\\nfunction Shape() {\\n    const [round, setRound] = useState(false);\\n    const renderLeftMenu = useCallback(() => <>\\n        <Configure.Select optionList={modelOptions} field=\\\"model\\\" initValue=\\\"GPT-4o\\\" />\\n        <Configure.Button icon={<IconBookOpenStroked />} field=\\\"onlineSearch\\\">Web search</Configure.Button>\\n        <Configure.Mcp options={mcpOptions} />\\n        <Configure.RadioButton options={radioButtonProps} initValue=\\\"fast\\\"/>\\n    </>);\\n    const onChange = useCallback((e) => {\\n        setRound(e.target.value);\\n    }, []);\\n    \\n    return (<>\\n        <RadioGroup onChange={onChange} value={round} aria-label=\\\"Radio group demo\\\" name=\\\"demo-radio-group\\\">\\n            <Radio value={true}>Rounded</Radio>\\n            <Radio value={false}>Square</Radio>\\n        </RadioGroup>\\n        <AIChatInput\\n            placeholder={'Square button demo'} \\n            round={round}\\n            renderConfigureArea={renderLeftMenu} \\n            uploadProps={uploadProps}\\n            style={outerStyle}\\n        />\\n    </>);\\n};\\n\\nrender(<Shape />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Suggestions\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Configure suggestions with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"suggestion\"), \" API. This works similarly to the AutoComplete component. Users can dynamically show suggestions based on input.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Use up/down keys to navigate suggestions. Pressing \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"ESC\"), \" or clicking outside the suggestion/input area will close the suggestions. You can customize rendering using \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"renderSuggestionItem\"), \".\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst suggestionTemplate = [ 'Weather', 'Air Quality', 'Work Progress', 'Schedule' ];\\n\\nfunction Suggestion() {\\n    const [suggestion, setSuggestion] = useState([]);\\n    const onChange = useCallback((content) => {\\n        let value;\\n        if (content.length && content[0].text) {\\n            value = content[0].text;\\n        }\\n        if (value === undefined) {\\n            if (suggestion === undefined || suggestion.length === 0) {\\n                return;\\n            } else {\\n                return setSuggestion([]);\\n            }\\n        }\\n        if (value.length === 0) {\\n            setSuggestion([]);\\n        } else if (value.length > 0 && value.length < 4) {\\n            const su = new Array(suggestionTemplate.length).fill(0).map((item, index) =>\\n                `${value}, ${suggestionTemplate[index]}`\\n            );\\n            setSuggestion(su);\\n        } else if (value.length >= 4) {\\n            setSuggestion([]);\\n        }\\n    }, [suggestion]);\\n  \\n    return (\\n        <AIChatInput\\n            suggestions={suggestion} \\n            onContentChange={onChange}\\n            uploadProps={uploadProps}\\n            style={outerStyle}\\n            placeholder={'When the length is less than 4, see suggestions. Use up/down to select.'} \\n        />\\n    );\\n}\\n\\nrender(<Suggestion />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Skills & Templates\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Configure a skill list with \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"skills\"), \", and use \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"skillHotKey\"), \" to set the shortcut for skill panel.\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"skills\"), \" sample format:\")), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"interface Skill {\\n    label?: string;\\n    value?: string;\\n    icon?: React.ReactNode;\\n    // If this skill has a template, set hasTemplate to true, affects the display of template display buttons\\n    hasTemplate?: boolean;\\n}\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Because templates can be displayed in a variety of ways, we don't provide a default display method. Users can customize the template display through the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"renderTemplate\"), \" API. The template panel can be displayed and closed by clicking the template button.\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\nimport { IconTemplateStroked, IconSearch } from '@douyinfe/semi-icons';\\n\\nconst { Configure } = AIChatInput;\\nconst modelOptions = [\\n    { value: 'GPT-5', label: 'GPT-5' },\\n    { value: 'GPT-4o', label: 'GPT-4o' },\\n    { value: 'Claude 3.5 Sonnet', label: 'Claude 3.5 Sonnet' },\\n];\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\nconst skills = [\\n    {\\n        icon: <IconTemplateStroked />,\\n        value: 'writing',\\n        label: 'Writing',\\n        hasTemplate: true,\\n    },\\n    {\\n        icon: <IconSearch />,\\n        value: 'AI coding',\\n        label: 'AI coding'\\n    },\\n];\\n\\nconst template = [\\n    {\\n        groupKey: 'value',\\n        group: 'Work',\\n        children: [\\n            {\\n                bg: 'var(--semi-color-primary)',\\n                icon: <IconTemplateStroked />,\\n                title: 'Summary report',\\n                desc: 'Condensate your work results',\\n                content: `My occupation is <input-slot placeholder=\\\"[Please enter your occupation]\\\"></input-slot>. Please help me write a summary report on <input-slot placeholder=\\\"[Purpose: Project Progress Summary, Team Work Results, or Other]</input-slot>`\\n            },\\n            {\\n                bg: 'var(--semi-color-warning)',\\n                icon: <IconTemplateStroked />,\\n                title: 'Speech skills',\\n                desc: 'Meet the expression needs of different scenarios',\\n                content: `I am a <select-slot value=\\\"Worker\\\" options='[\\\"Worker\\\",\\\"Student\\\"]'></select-slot>, please help me write a paragraph for <input-slot placeholder=\\\"[input object]\\\">unfamiliar colleagues</input-slot>`\\n            }\\n        ]\\n    },\\n    {\\n        groupKey: 'marketing',\\n        group: 'Marketing',\\n        children: [\\n            {\\n                bg: 'var(--semi-color-primary)',\\n                icon: <IconTemplateStroked />,\\n                title: 'Promotional copy',\\n                desc: 'Write promotional copy for each platform',\\n                content: 'Please help me write a promotional copy for <input-slot placeholder=\\\"[Enter target group]\\\"></input-slot> professionals about <input-slot placeholder=\\\"[Enter product]\\\"></input-slot>. It needs to directly hit the pain points and attract users to click.'\\n            },\\n            {\\n                bg: 'var(--semi-color-warning)',\\n                icon: <IconTemplateStroked />,\\n                title: 'Program planning',\\n                desc: 'Tailor-made solutions',\\n                content: 'I am a <input-slot placeholder=\\\"[Enter occupation]\\\"></input-slot> professional planner. Please help me write a <input-slot placeholder=\\\"[Plan type: such as offline book club activity plan, etc.]\\\"></input-slot> offline book club activity plan, which should include but not be limited to planning goals, detailed plans, required resources and budget, effect evaluation, risk response, etc.'\\n            }\\n        ]\\n    }\\n];\\n\\nconst TemplateContent = (props) => {\\n    const { onTemplateClick: onTemplateClickProps } = props;\\n    const [groupIndex, setGroupIndex] = useState(0);\\n\\n    const onItemClick = useCallback((e) => {\\n        const index = e.target.dataset.index;\\n        setGroupIndex(Number(index));\\n    }, []);\\n\\n    const onTemplateClick = useCallback((item) => {\\n        const { content } = item;\\n        onTemplateClickProps(content);\\n    }, [onTemplateClickProps]);\\n\\n    return (<div className={'aiChatInput-template'} >\\n        {/* tabs */}\\n        <div className={'template-header'} >\\n            {(template ? template : []).map((item, index) => {\\n                return (<div\\n                    key={index}\\n                    data-index={index}\\n                    className={`template-header-item ${groupIndex === index ? 'template-header-item-active' : ''}`}\\n                    onClick={onItemClick}\\n                >\\n                    {item.group}\\n                </div>);\\n            })}\\n        </div>\\n        {/* content */}\\n        <div className='template-content'>\\n            {(((template ? template : [])[groupIndex] ? (template ? template : [])[groupIndex] : {}).children ? (template ? template : [])[groupIndex].children : []).map((item, index) => (<div\\n                key={index}\\n                className='template-content-item'\\n                onClick={() => onTemplateClick(item)}\\n            >\\n                <div className='template-content-item-icon' style={{ background: item.bg }}>{item.icon}</div>\\n                <div className='template-content-item-title'>{item.title}</div>\\n                <div className='template-content-item-desc'>{item.desc}</div>\\n            </div>))}\\n        </div>\\n    </div>);\\n};\\n\\nfunction Template() {\\n    const ref = useRef();\\n\\n    const setTemplate = useCallback((content) => {\\n        const element = ref.current;\\n        if (!element) {\\n            return;\\n        }\\n        element.setContentWhileSaveTool(content);\\n        element.focusEditor();\\n    }, [ref]);\\n\\n    const renderTemplate = useCallback((skill = {}, e) => {\\n        if (skill.value === 'writing') {\\n            return <TemplateContent onTemplateClick={setTemplate}/>;\\n        }\\n    }, [setTemplate]);\\n\\n    const renderLeftMenu = useCallback(() => <>\\n        <Configure.Select optionList={modelOptions} field=\\\"model\\\" initValue=\\\"GPT-4o\\\" />\\n    </>);\\n\\n    return (\\n        <AIChatInput \\n            placeholder='Input / invoke skills'\\n            renderConfigureArea={renderLeftMenu} \\n            ref={ref}\\n            uploadProps={uploadProps}\\n            skills={skills}\\n            skillHotKey='/'\\n            renderTemplate={renderTemplate}\\n            style={outerStyle}\\n        />\\n    );\\n};\\n\\nrender(<Template />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Custom Top Slot\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Users can customize the top rendering area using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"renderTopSlot\"), \" API, rendering references, uploaded content, and configuration items. This can be combined with the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"showReference\"), \" and \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"showUploadFile\"), \" APIs to control whether references and uploaded files are displayed. Additionally, the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"topSlotPosition\"), \" API allows you to configure the relative position of customized rendered content relative to the reference and upload display areas.\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-ts\"\n  }, \"interface TopSlotProps {\\n    references: Reference[];\\n    attachments: Attachment[];\\n    // User input into the input box\\n    content: Content[];\\n    handleUploadFileDelete: (attachment: Attachment) => void;\\n    handleReferenceDelete: (reference: Reference) => void\\n}\\n\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Usage examples are as follows:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\nimport { IconClose, IconUpload, IconFile, IconFolder, IconBranch, IconTerminal, IconGlobeStroke, IconConnectionPoint2, IconTemplateStroked, IconSearch, IconGit, IconCode } from '@douyinfe/semi-icons';\\n\\nconst { Configure } = AIChatInput;\\nconst radioButtonProps = [\\n    { label: <IconTemplateStroked />, value: 'fast' },\\n    { label: <IconSearch />, value: 'think' }\\n];\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\n\\nconst customReferences = [\\n    {\\n        type: 'file',\\n        key: '1',\\n        name: 'horizontalScroller.tsx',\\n        path: 'packages/semi-ui/AIChatInput/horizontalScroller.tsx',\\n    },\\n    {\\n        type: 'folder',\\n        key: '2',\\n        name: 'AIChatInput',\\n        path: 'packages/semi-ui/AIChatInput',\\n    },\\n    {\\n        type: 'web',\\n        key: '3',\\n        name: 'web'\\n    },\\n    {\\n        type: 'change',\\n        key: '4',\\n        name: 'recentChange'\\n    },\\n    {\\n        type: 'branch',\\n        key: '5',\\n        name: 'Branch',\\n        detail: 'Diff with Main Branch',\\n        branch: 'feat/aichatinput',\\n        targetBranch: 'feat/targetBranch',\\n    },\\n    {\\n        type: 'terminal',\\n        key: '6',\\n        name: 'From 1-2',\\n        from: 1,\\n        to: 2,\\n    }\\n];\\n\\nfunction getAttachmentType(item = {}) {\\n    const { type, name = '', fileInstance = {} } = item;\\n    if (type) {\\n        return type;\\n    }\\n    const suffix = name.split('.').pop();\\n    if (suffix) {\\n        return suffix;\\n    } else if (fileInstance.type && fileInstance.type) {\\n        const temp = fileInstance.type.split('/').pop();\\n        if (temp) {\\n            return temp;\\n        }\\n    }\\n    return 'UNKNOWN';\\n}\\n\\nfunction isImageType(item = {}) {\\n    const PIC_PREFIX = 'image/';\\n    const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];\\n    const { name = '', fileInstance = {} } = item;\\n    const suffix = name.split('.').pop();\\n    let result = false;\\n    const { type = '' } = fileInstance;\\n    if (type.startsWith(PIC_PREFIX)) {\\n        result = true;\\n    } else if (PIC_SUFFIX_ARRAY.includes(suffix)) {\\n        result = true;\\n    }\\n    return result;\\n}\\n\\nconst refTypeToIconMap = new Map([\\n    ['file', <IconFile key={'file'} size=\\\"small\\\" />],\\n    ['folder', <IconFolder key={'folder'} size=\\\"small\\\" />],\\n    ['branch', <IconBranch key={'branch'} size=\\\"small\\\" />],\\n    ['terminal', <IconTerminal key={'terminal'} size=\\\"small\\\" /> ],\\n    ['web', <IconGlobeStroke key={'globalStroke'} size=\\\"small\\\" />],\\n    ['change', <IconConnectionPoint2 key={'connectionPoint2'} size=\\\"small\\\" />],\\n    ['git', <IconGit key=\\\"git\\\" size=\\\"small\\\" />],\\n    ['code', <IconCode key=\\\"code\\\" size=\\\"small\\\" />],\\n]);\\n\\nfunction RenderTopSlot() {\\n    const ref = useRef();\\n    const [reference, setReference] = useState(customReferences);\\n\\n    const renderLeftMenu = useCallback(() => <>\\n        <Configure.RadioButton options={radioButtonProps} initValue=\\\"fast\\\" field=\\\"mode\\\"/>\\n    </>);\\n\\n    const renderTopSlot = useCallback((props) => {\\n        const { attachments = [], references = [] } = props;\\n        return <div className=\\\"ai-chat-input-topSlot\\\">\\n            {references.map((item, index) => {\\n                const { type, name, detail, key, ...rest } = item;\\n                return (<div className=\\\"item\\\" key={key}>\\n                    <span className='item-icon'>\\n                        {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}\\n                        <IconClose size=\\\"small\\\" className='item-icon-delete' onClick={() => {\\n                            const newReferences = [...references];\\n                            newReferences.splice(index, 1);\\n                            setReference(newReferences);\\n                        }}/>\\n                    </span>\\n                    <span className='item-content'>\\n                        {name}\\n                        {type === 'branch' && <span className='detail'>{detail}</span>}\\n                    </span>\\n                </div>);\\n            })}\\n            {attachments.map((item, index) => {\\n                const isImage = isImageType(item);\\n                const { uid, name, url, size, percent, status } = item;\\n                return (<div className=\\\"item\\\" key={uid}>\\n                    <span className='item-icon'>\\n                        {isImage ? <img className='item-image item-left' src={item.url} alt={item.name} /> : <IconUpload size=\\\"small\\\" className='item-left item-icon' />}\\n                        <IconClose size=\\\"small\\\" className='item-icon-delete' onClick={() => {\\n                            ref.current && ref.current.deleteUploadFile(item);\\n                        }}/>\\n                    </span>\\n                    <span className='item-content'>{name}</span>\\n                </div>\\n                );\\n            })}\\n        </div>;\\n    }, []);\\n    \\n    return (\\n        <AIChatInput\\n            className='aiChatInput-customTopSlot'\\n            renderTopSlot={renderTopSlot}\\n            references={reference}\\n            showUploadFile={false}\\n            showReference={false}\\n            renderConfigureArea={renderLeftMenu} \\n            ref={ref}\\n            uploadProps={uploadProps}\\n            style={outerStyle}\\n            placeholder=\\\"Customize the rendering of top content\\\"\\n        />\\n    );\\n}\\n\\nrender(<RenderTopSlot />);\\n\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Custom Extensions\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Rich text areas support custom extensions. For implementation details, see \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://tiptap.dev/docs/editor/extensions/custom-extensions/create-new\"\n  }, \"Tiptap Custom Extensions\"), \". Custom extensions can be added to the AIChatInput component using the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"extensions\"), \" API. If you add a custom extension, you must configure the corresponding transformation rules in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"transformer\"), \" to ensure that the data returned in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"onContentChange\"), \" matches your expectations.\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"When adding a custom extension, please note the following:\"), mdx(\"ul\", {\n    parentName: \"section\"\n  }, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Please add the \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"isCustomSlot\"), \" property to your custom extension. This property is related to the cursor height before and after the custom extension.\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Since \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"AIChatInput\"), \" uses \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Enter\"), \" as the send hotkey, if your custom extension uses \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"Enter\"), \" as a shortcut, you need to manually configure \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"AIChatInput.allowHotKeySend\"), \" in \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"editor.storage\"), \" to indicate whether the hotkey should be used by AIChatInput for sending, in order to avoid hotkey conflicts.\")), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"An example of a custom extension definition and related notes is as follows:\"), mdx(\"pre\", {\n    parentName: \"section\"\n  }, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-jsx\",\n    \"metastring\": \"live=true dir=\\\"column\\\" noInline=true\",\n    \"live\": \"true\",\n    \"dir\": \"\\\"column\\\"\",\n    \"noInline\": \"true\"\n  }, \"import React from 'react';\\nimport { Node, mergeAttributes } from '@tiptap/core';\\nimport { ReactNodeViewRenderer, NodeViewWrapper, posToDOMRect, ReactRenderer } from '@tiptap/react';\\nimport { computePosition, flip, shift } from '@floating-ui/dom';\\nimport { IconFile, IconFolder, IconBranch, IconCode, IconGit, IconGlobeStroke, IconChevronRight, IconClose, IconUpload, IconTerminal, IconConnectionPoint2 } from '@douyinfe/semi-icons';\\nimport { AIChatInput } from '@douyinfe/semi-ui';\\nimport Mention from '@tiptap/extension-mention';\\n\\nconst uploadProps = { action: \\\"https://api.semi.design/upload\\\" };\\nconst outerStyle = { margin: 12 };\\n\\n// Panel options\\nconst TestAction = {\\n    'Files & Folders': [\\n        {\\n            icon: <IconFile />,\\n            key: '1-1',\\n            type: 'file',\\n            name: 'TagInput.scss',\\n            path: 'package/semi-founctaion/TagInput.scss',\\n        },\\n        {\\n            icon: <IconFolder />,\\n            key: '1-2',\\n            type: 'folder',\\n            name: 'package',\\n            path: '/package',\\n        },\\n        {\\n            icon: <IconFolder />,\\n            key: '1-3',\\n            type: 'folder',\\n            name: 'semi-ui',\\n            path: '/package/semi-ui',\\n        },\\n    ],\\n    Git: [\\n        {\\n            icon: <IconBranch />,\\n            key: '2-1',\\n            type: 'branch',\\n            name: 'fix/tag',\\n        },\\n        {\\n            icon: <IconCode />,\\n            key: '2-2',\\n            type: 'code',\\n            name: 'v2.86.0',\\n            path: '/package',\\n        },\\n        {\\n            icon: <IconGit />,\\n            key: '2-3',\\n            type: 'git',\\n            name: 'chore: publish',\\n        },\\n    ],\\n};\\n\\n// First level content\\nconst FirstLevel = Object.keys(TestAction);\\n\\n// referSlot rendering component\\nfunction ReferSlotComponent(props) {\\n    const { node, deleteNode } = props;\\n    const value = node.attrs.value ? node.attrs.value : '';\\n    const onRemove = (e) => {\\n        e.preventDefault();\\n        e.stopPropagation();\\n        deleteNode && deleteNode();\\n    };\\n    return (\\n        <NodeViewWrapper className=\\\"ai-chat-input-refer-slot-wrapper\\\">\\n            <span className='ai-chat-input-refer-slot'>\\n                {value}\\n            </span>\\n        </NodeViewWrapper>\\n    );\\n}\\n\\n// Creating a ReferSlot Extension\\nconst ReferSlot = Node.create({\\n    name: 'referSlot',\\n    inline: true,\\n    group: 'inline',\\n    atom: true,\\n    selectable: false,\\n    addAttributes() {\\n        return {\\n            value: {\\n                default: 'Enter content',\\n                parseHTML: (element) =>\\n                    element.getAttribute('data-value'),\\n                renderHTML: (attributes) => ({\\n                    'data-value': attributes.value,\\n                }),\\n            },\\n            info: {\\n                default: '',\\n                parseHTML: (element) =>\\n                    element.getAttribute('data-info'),\\n                renderHTML: (attributes) => ({\\n                    'data-info': attributes.info,\\n                }),\\n            },\\n            type: {\\n                default: 'text',\\n                parseHTML: (element) =>\\n                    element.getAttribute('data-type'),\\n                renderHTML: (attributes) => ({\\n                    'data-type': attributes.type,\\n                }),\\n            },\\n            uniqueKey: {\\n                default: '',\\n                parseHTML: (element) =>\\n                    element.getAttribute('data-unique-key'),\\n                renderHTML: (attributes) => ({\\n                    'data-unique-key': attributes.uniqueKey,\\n                }),\\n            },\\n            // !!! Very important, affects the cursor size before and after custom nodes\\n            // Please be sure to add this logic to custom nodes\\n            isCustomSlot: AIChatInput.getCustomSlotAttribute(),\\n        };\\n    },\\n    parseHTML() {\\n        return [{\\n            tag: 'refer-slot',\\n        }];\\n    },\\n    renderHTML({ HTMLAttributes }) {\\n        // Output custom tags when serializing and keep the value in data-value\\n        return ['refer-slot', mergeAttributes(HTMLAttributes)];\\n    },\\n    addNodeView() {\\n        return ReactNodeViewRenderer(ReferSlotComponent);\\n    },\\n});\\n\\n// Update position function\\nconst updatePosition = (editor, element) => {\\n    const virtualElement = {\\n        getBoundingClientRect: () => posToDOMRect(\\n            editor.view,\\n            editor.state.selection.from,\\n            editor.state.selection.to,\\n        ),\\n    };\\n    computePosition(virtualElement, element, {\\n        placement: 'bottom-start',\\n        strategy: 'absolute',\\n        middleware: [shift()],\\n    }).then(({ x, y, strategy }) => {\\n        element.style.width = 'max-content';\\n        element.style.position = strategy;\\n        element.style.left = `${x}px`;\\n        element.style.top = `${y}px`;\\n    });\\n};\\n\\nconst suggestion = {\\n    items: () => FirstLevel,\\n    command: ({ editor, range, props }) => {\\n        const { item, allowHotKeySend } = props;\\n        if (typeof allowHotKeySend === 'boolean') {\\n            editor.storage.SemiAIChatInput.allowHotKeySend = allowHotKeySend;\\n        }\\n        item && editor.chain().focus().insertContentAt(range, {\\n            type: 'referSlot',\\n            attrs: {\\n                type: item.type,\\n                value: item.name || '',\\n                info: JSON.stringify({ path: item.path }),\\n                uniqueKey: item.key,\\n            },\\n        }).run();\\n    },\\n    render: () => {\\n        let component;\\n        return {\\n            onStart: (props) => {\\n                component = new ReactRenderer(MentionList, {\\n                    props,\\n                    editor: props.editor,\\n                });\\n                if (!props.clientRect) return;\\n                component.element.style.position = 'absolute';\\n                document.body.appendChild(component.element);\\n                updatePosition(props.editor, component.element);\\n            },\\n            onUpdate(props) {\\n                component.updateProps(props);\\n                if (!props.clientRect) return;\\n                updatePosition(props.editor, component.element);\\n            },\\n            onKeyDown(props) {\\n                function onExit() {\\n                    component.destroy();\\n                }\\n                return component.ref.onKeyDown({ ...props, exitCb: onExit });\\n            },\\n            onExit() {\\n                component.element.remove();\\n                component.destroy();\\n            },\\n            focusEditor(props) {\\n                props.editor.commands.focus();\\n            },\\n        };\\n    },\\n};\\n\\nconst customReferences = [\\n    {\\n        type: 'file',\\n        key: '1',\\n        name: 'horizontalScroller.tsx',\\n        path: 'packages/semi-ui/AIChatInput/horizontalScroller.tsx',\\n    },\\n    {\\n        type: 'folder',\\n        key: '2',\\n        name: 'AIChatInput',\\n        path: 'packages/semi-ui/AIChatInput',\\n    },\\n    {\\n        type: 'web',\\n        key: '3',\\n        name: 'web'\\n    },\\n    {\\n        type: 'change',\\n        key: '4',\\n        name: 'recentChange'\\n    },\\n    {\\n        type: 'branch',\\n        key: '5',\\n        name: 'Branch',\\n        detail: 'Diff with Main Branch',\\n        branch: 'feat/aichatinput',\\n        targetBranch: 'feat/targetBranch',\\n    },\\n    {\\n        type: 'terminal',\\n        key: '6',\\n        name: 'From 1-2',\\n        from: 1,\\n        to: 2,\\n    }\\n];\\n\\n// Rendering Panel for mention list\\nclass MentionList extends React.Component {\\n    constructor(props) {\\n        super(props);\\n        this.state = {\\n            selectedIndex: 0,\\n            level: 1,\\n            options: FirstLevel,\\n            filterOptions: FirstLevel,\\n        };\\n        this.upHandler = this.upHandler.bind(this);\\n        this.downHandler = this.downHandler.bind(this);\\n        this.enterHandler = this.enterHandler.bind(this);\\n        this.selectItem = this.selectItem.bind(this);\\n        this.onKeyDown = this.onKeyDown.bind(this);\\n        this.renderItem = this.renderItem.bind(this);\\n        // When the options panel is rendered, the Enter shortcut should be used in the options panel, not for sending with AIChatInput.\\n        props.command({ allowHotKeySend: false });\\n    }\\n    componentWillUnmount() {\\n        // If the options panel is unmounted, the Enter shortcut should be used to send AIChatInput.\\n        this.props.command({ allowHotKeySend: true });\\n    }\\n    upHandler() {\\n        const { selectedIndex, filterOptions } = this.state;\\n        this.setState({\\n            selectedIndex: (selectedIndex + filterOptions.length - 1) % filterOptions.length,\\n        });\\n    };\\n    downHandler() {\\n        const { selectedIndex, filterOptions } = this.state;\\n        this.setState({\\n            selectedIndex: (selectedIndex + 1) % filterOptions.length,\\n        });\\n    };\\n    enterHandler () {\\n        const { selectedIndex, level } = this.state;\\n        if (level === 1) {\\n            this.setState({\\n                level: 2,\\n                options: TestAction[FirstLevel[selectedIndex]],\\n                selectedIndex: 0,\\n            });\\n        } else {\\n            this.selectItem(selectedIndex);\\n        }\\n    };\\n    selectItem(id) {\\n        const { options } = this.state;\\n        const item = options[id];\\n        if (item) {\\n            this.props.command({ item });\\n        }\\n    };\\n    componentDidUpdate(prevProps, prevState) {\\n        if (prevProps.items !== this.props.items) {\\n            this.setState({ selectedIndex: 0 });\\n        }\\n        if ( prevState.options !== this.state.options ||\\n        prevProps.query !== this.props.query\\n        ) {\\n            // Manual filter\\n            let filter = [];\\n            if (this.props.query && this.props.query.length) {\\n                filter = (this.state.options ? this.state.options : []).filter((item) => {\\n                    let name;\\n                    if (typeof item === 'string') {\\n                        name = item;\\n                    } else {\\n                        name = item.name;\\n                    }\\n                    return name.toLowerCase().includes(this.props.query.toLowerCase());\\n                });\\n            } else {\\n                filter = this.state.options ? this.state.options : [];\\n            }\\n            this.setState({ \\n                filterOptions: filter,\\n                selectedIndex: 0\\n            });\\n        }\\n    }\\n    componentDidMount() {\\n        if (this.props.innerRef) {\\n            this.props.innerRef.current = {\\n                onKeyDown: this.onKeyDown,\\n            };\\n        }\\n    }\\n    onKeyDown({ event, exitCb }) {\\n        if (event.key === 'ArrowUp') {\\n            this.upHandler();\\n            return true;\\n        }\\n        if (event.key === 'ArrowDown') {\\n            this.downHandler();\\n            return true;\\n        }\\n        if (event.key === 'Enter') {\\n            this.enterHandler();\\n            return true;\\n        }\\n        if (event.key === 'Escape') {\\n            if (this.state.level === 1) {\\n                exitCb && exitCb();\\n                return true;\\n            } else if (this.state.level === 2) {\\n                this.setState({ level: 1, options: FirstLevel });\\n                return true;\\n            }\\n        }\\n        return false;\\n    };\\n\\n    renderItem(item) {\\n        return (\\n            <div className=\\\"level2Item\\\">\\n                {item.icon}\\n                <span className=\\\"name\\\">{item.name}</span>\\n                <span className=\\\"path\\\">{item.path}</span>\\n            </div>\\n        );\\n    };\\n    render() {\\n        const { level, filterOptions, selectedIndex } = this.state;\\n        return (\\n            <div className=\\\"ai-chat-input-custom-extension-dropdown-menu\\\" style={{ width: level === 1 ? 200 : 300 }}>\\n                {filterOptions.length ? (filterOptions.map(\\n                    (item, index ) => (\\n                        // eslint-disable-next-line jsx-a11y/click-events-have-key-events\\n                        <div\\n                            key={index}\\n                            className={ index === selectedIndex ? 'is-selected optionItem' : 'optionItem '}\\n                            onClick={() => {\\n                                if (level === 1) {\\n                                    if (typeof item === 'string') {\\n                                        this.setState({ level: 2, options: TestAction[item] });\\n                                        this.props.editor.commands.focus();\\n                                    }\\n                                } else {\\n                                    if (typeof item !== 'string') {\\n                                        this.selectItem(index);\\n                                    }\\n                                }\\n                            }}\\n                            onMouseEnter={() => {\\n                                this.setState({ selectedIndex: index });\\n                            }}\\n                        >\\n                            {typeof item === 'string' ? <span>{item}</span> : this.renderItem(item)}\\n                            {level === 1 && <IconChevronRight className='option-item-arrow'/>}\\n                        </div>\\n                    ),\\n                )) : <div className=\\\"item\\\">No result</div>}\\n            </div>\\n        );\\n    }\\n}\\n\\nfunction getAttachmentType(item = {}) {\\n    const { type, name = '', fileInstance = {} } = item;\\n    if (type) {\\n        return type;\\n    }\\n    const suffix = name.split('.').pop();\\n    if (suffix) {\\n        return suffix;\\n    } else if (fileInstance.type && fileInstance.type) {\\n        const temp = fileInstance.type.split('/').pop();\\n        if (temp) {\\n            return temp;\\n        }\\n    }\\n    return 'UNKNOWN';\\n}\\n\\nfunction isImageType(item = {}) {\\n    const PIC_PREFIX = 'image/';\\n    const PIC_SUFFIX_ARRAY = ['png', 'jpg', 'jpeg', 'gif', 'bmp', 'webp'];\\n    const { name = '', fileInstance = {} } = item;\\n    const suffix = name.split('.').pop();\\n    let result = false;\\n    const { type = '' } = fileInstance;\\n    if (type.startsWith(PIC_PREFIX)) {\\n        result = true;\\n    } else if (PIC_SUFFIX_ARRAY.includes(suffix)) {\\n        result = true;\\n    }\\n    return result;\\n}\\n\\nconst refTypeToIconMap = new Map([\\n    ['file', <IconFile key={'file'} size=\\\"small\\\" />],\\n    ['folder', <IconFolder key={'folder'} size=\\\"small\\\" />],\\n    ['branch', <IconBranch key={'branch'} size=\\\"small\\\" />],\\n    ['terminal', <IconTerminal key={'terminal'} size=\\\"small\\\" /> ],\\n    ['web', <IconGlobeStroke key={'globalStroke'} size=\\\"small\\\" />],\\n    ['change', <IconConnectionPoint2 key={'connectionPoint2'} size=\\\"small\\\" />],\\n    ['git', <IconGit key=\\\"git\\\" size=\\\"small\\\" />],\\n    ['code', <IconCode key=\\\"code\\\" size=\\\"small\\\" />],\\n]);\\n\\nfunction CustomRichTextExtension() {\\n    const ref = useRef();\\n    const [reference, setReference] = useState(customReferences);\\n    const extensions = useMemo(() => {\\n        // Use @ to trigger\\n        return [\\n            ReferSlot,\\n            Mention.configure({\\n                HTMLAttributes: {\\n                    class: 'mention',\\n                },\\n                suggestion,\\n            }),\\n        ];\\n    }, []);\\n    const renderTopSlot = useCallback((props) => {\\n        const { attachments = [], references = [], content = [] } = props;\\n        const showContent = content.filter((item) => item.type !== 'text');\\n        return <div className=\\\"ai-chat-input-topSlot\\\">\\n            {/* Order: reference, rich text area content, attachments */}\\n            {showContent.map((item, index) => {\\n                const { type, value, name, key, detail, ...rest } = item;\\n                return (\\n                    <div className=\\\"item\\\" key={key ? key : index}>\\n                        <span className='item-icon'>\\n                            {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}\\n                            <IconClose size=\\\"small\\\" className='item-icon-delete' onClick={() => {\\n                                if (ref.current && ref.current.deleteContent) {\\n                                    ref.current.deleteContent(item);\\n                                }\\n                            }}/>\\n                        </span>\\n                        <span className='item-content'>\\n                            {name ? name : value}\\n                            {type === 'branch' && <span className='detail'>{detail}</span>}\\n                        </span>\\n                    </div>\\n                );\\n            })}\\n            {references.map((item, index) => {\\n                const { type, name, detail, key, ...rest } = item;\\n                return (\\n                    <div className=\\\"item\\\" key={key}>\\n                        <span className='item-icon'>\\n                            {React.cloneElement(refTypeToIconMap.get(type), { className: 'item-left item-icon' })}\\n                            <IconClose size=\\\"small\\\" className='item-icon-delete' onClick={() => {\\n                                const newReferences = [...references];\\n                                newReferences.splice(index, 1);\\n                                setReference(newReferences);\\n                            }}/>\\n                        </span>\\n                        <span className='item-content'>\\n                            {name}\\n                            {type === 'branch' && <span className='detail'>{detail}</span>}\\n                        </span>\\n                    </div>\\n                );\\n            })}\\n            {attachments.map((item, index) => {\\n                const isImage = isImageType(item);\\n                const realType = getAttachmentType(item);\\n                const { uid, name, url, size, percent, status } = item;\\n                return (\\n                    <div className=\\\"item\\\" key={uid}>\\n                        <span className='item-icon'>\\n                            {isImage ? <img className='item-image item-left' src={item.url} alt={item.name} /> : <IconUpload size=\\\"small\\\" className='item-left item-icon' />}\\n                            <IconClose size=\\\"small\\\" className='item-icon-delete' onClick={() => {\\n                                if (ref.current && ref.current.deleteUploadFile) {\\n                                    ref.current.deleteUploadFile(item);\\n                                }\\n                            }}/>\\n                        </span>\\n                        <span className='item-content'>{name}</span>\\n                    </div>\\n                );\\n            })}\\n        </div>;\\n    }, []);\\n    const onContentChange = useCallback((content) => {\\n        console.log('onContentChange', content);\\n    }, []);\\n    const transformer = useMemo(() => {\\n        return new Map([\\n            ['referSlot', (obj) => {\\n                const { attrs = {} } = obj;\\n                const { value, info, type = 'text', uniqueKey } = attrs;\\n                return {\\n                    type: type, \\n                    value: value,\\n                    uniqueKey: uniqueKey,\\n                    ...JSON.parse(info),\\n                };\\n            }],\\n        ]);\\n    }, []);\\n    return (\\n        <>\\n            <AIChatInput\\n                className='aiChatInput-customTopSlot'\\n                renderTopSlot={renderTopSlot}\\n                extensions={extensions}\\n                references={reference}\\n                showUploadFile={false}\\n                showReference={false}\\n                onContentChange={onContentChange}\\n                ref={ref}\\n                transformer={transformer}\\n                uploadProps={uploadProps}\\n                style={outerStyle}\\n                placeholder=\\\"Use @ to trigger\\\"\\n            />\\n        </>\\n    );\\n};\\n\\nrender(<CustomRichTextExtension />);\\n\"))), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"API Reference\"), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"AIChatInput\"), mdx(\"table\", {\n    parentName: \"section\"\n  }, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Prop\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Description\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Type\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Default\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"canSend\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Whether sending is allowed. If not set, sending depends on input, uploads, and references\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"className\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom class name\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"string\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"clearContentOnGenerating\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Whether to clear input content and attachments when generating changes from false to true. Set to false to retain input content (for infinite canvas and other non-chat scenarios) \", mdx(\"strong\", {\n    parentName: \"td\"\n  }, \">=2.94.0\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"defaultContent\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Default input content, supports html string or Tiptap content\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"TiptapContent\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"dropdownMatchTriggerWidth\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Should dropdown width match input?\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"extensions\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom editor extensions\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Extension[]\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"immediatelyRender\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"As a parameter of tiptap's userEditor, if it's an SSR scenario, this parameter needs to be set to false. See \", mdx(\"a\", {\n    parentName: \"td\",\n    \"href\": \"https://tiptap.dev/docs/editor/getting-started/install/react#use-ssr-with-react-and-tiptap\"\n  }, \"use-ssr-with-react-and-tiptap\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"generating\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Is it generating?\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"false\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onContentChange\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback when input content changes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(content: \", mdx(ApiType, {\n    detail: \"{ type: string; [key: string]: any }\",\n    mdxType: \"ApiType\"\n  }, \"OnContentChangeProps\"), \") => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onMessageSend\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for sending message\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(content: \", mdx(ApiType, {\n    detail: \"{references?: Reference[]; attachments?: Attachment[]; inputContents?: Content[]; setup?: Setup}\",\n    mdxType: \"ApiType\"\n  }, \"OnMessageSendProps\"), \") => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onReferenceClick\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for clicking a reference\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(reference: Reference) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onReferenceDelete\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for deleting a reference\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(reference: Reference) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onSkillChange\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for switching skills\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(skill: Skill) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onStopGenerate\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for stop generate\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"() => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onSuggestClick\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for clicking a suggestion\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(suggestion: Suggestion) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onTemplateVisibleChange\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for template's visibility change\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(visible: boolean) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onUploadChange\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for file upload\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(props: OnChangeProps) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderUploadButton\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Customize upload button UI in the footer action area (Upload is still managed internally; built-in upload/paste-upload logic is preserved)\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(props: \", mdx(ApiType, {\n    detail: \"{ defaultNode: React.ReactNode; openFileDialog: () => void; disabled: boolean; attachments: Attachment[] }\",\n    mdxType: \"ApiType\"\n  }, \"RenderUploadButtonProps\"), \") => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"popoverProps\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Popup configuration\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"PopoverProps\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"placeholder\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Input placeholder\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"string \", \"|\", \" (props: \", mdx(ApiType, {\n    detail: \"{ editor: Editor; node: Node; pos: number; hasAnchor: boolean }\",\n    mdxType: \"ApiType\"\n  }, \"PlaceholderProps\"), \") => string\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"showPlaceholderWhenSkillOnly\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Whether to show placeholder when only skill is selected (no other content). When enabled, the placeholder will appear after the skill\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"false\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"references\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Reference list\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Reference[]\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderActionArea\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom bottom-right operation area\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"() => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderConfigureArea\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom configuration area\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"() => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderReference\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom render reference\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(reference: Reference) => ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderSkillItem\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom skill list item renderer\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(props: \", mdx(ApiType, {\n    detail: \"{skill: Skill; onClick: () => void; className: string, onMouseEnter: () => void}\",\n    mdxType: \"ApiType\"\n  }, \"RenderSkillItemProps\"), \") => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderSuggestionItem\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom suggestion item renderer\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(props: \", mdx(ApiType, {\n    detail: \"{ suggestion: Suggestion; onClick: () => void; className: string, onMouseEnter: () => void}\",\n    mdxType: \"ApiType\"\n  }, \"RenderSkillItemProps\"), \") => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderTemplate\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom template renderer\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(skill: Skill, onTemplateClick: (content: string) => void) => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"renderTopSlot\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom top slot renderer\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"() => React.ReactNode\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"round\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Whether config/action areas have rounded style\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onBlur\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback when input blurs\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(event: React.FocusEvent) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onConfigureChange\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback for configuration area changes\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(value: LeftMenuChangeProps, changedValue: LeftMenuChangeProps) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onFocus\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback when input focused\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(event: React.FocusEvent) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onPaste\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback when paste occurs on the editor. Does not prevent default paste behavior unless you call preventDefault().\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"(event: React.ClipboardEvent<HTMLDivElement>) => void\")), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"sendHotKey\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Keyboard shortcut for sending content, supports \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"enter\"), \" \", \"|\", \" \", mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"shift+enter\"), \". The former will send the message in the input box when you press enter alone. When the shift and enter keys are pressed at the same time, it will only wrap the line and not send it. The latter is the opposite\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"string\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, mdx(\"inlineCode\", {\n    parentName: \"td\"\n  }, \"enter\"))), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"showReference\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Show reference area\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"showTemplateButton\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Show template button\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"false\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"showUploadButton\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Show upload button\\uFF0Csupported since version 2.90.0\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"showUploadFile\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Show upload file area\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"skillHotKey\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Skill panel trigger shortcut\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"string\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"skills\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Skill list\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Skill[]\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"style\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Custom style\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"React.CSSProperties\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"suggestions\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Suggestions list\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Suggestion[]\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"templatesCls\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"The template's style class name\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"string\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"templatesStyle\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Template style\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"React.CSSProperties\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"topSlotPosition\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Top slot position: relative to reference and uploads\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"'top' \", \"|\", \" 'bottom' \", \"|\", \" 'middle'\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"transformer\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Customizing the conversion rules for extensions\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Map<string, (obj: any) => any>\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  })), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"uploadProps\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Upload configuration\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"UploadProps\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"uploadTipProps\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Upload tip configuration\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"UploadTipProps\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")))), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Configure.Select\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Same as \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https:/lf3-static.semi.design/obj/semi-tos/semi_main/en-US/input/select\"\n  }, \"SelectProps\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Configure.Button\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Same as \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https:/lf3-static.semi.design/obj/semi-tos/semi_main/en-US/basic/button#Button\"\n  }, \"ButtonProps\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Configure.RadioButton\"), mdx(\"p\", {\n    parentName: \"section\"\n  }, \"Same as \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https:/lf3-static.semi.design/obj/semi-tos/semi_main/zh-CN/input/radio#RadioGroup\"\n  }, \"RadioGroupProps\")), mdx(\"h3\", {\n    parentName: \"section\"\n  }, \"Configure.Mcp\"), mdx(\"table\", {\n    parentName: \"section\"\n  }, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Method\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Description\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Type\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Default\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"options\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Mcp options\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"McpOption\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"showConfigure\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Displaying the configuration button (added in v2.89.0)\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"boolean\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"true\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"onConfigureButtonClick\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Callback when the configuration button is clicked\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"() => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\"))))), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Methods\"), mdx(\"table\", {\n    parentName: \"section\"\n  }, mdx(\"thead\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"thead\"\n  }, mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Method\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Description\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Type\"), mdx(\"th\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Default\"))), mdx(\"tbody\", {\n    parentName: \"table\"\n  }, mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"changeTemplateVisible\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Toggle visibility of the template popup\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(visible: boolean) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"deleteContent\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Delete an item in the rich text. The deletion logic depends on the uniqueKey in the content.\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(content: Content) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"deleteUploadFile\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Delete an item in the uploaded file\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(item: Attachment) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"focusEditor\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Focus the input box. By default, the focus is on the end of the input box.\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(pos?: string) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"getEditor\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Get the current tiptap editor instance\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"() => Editor\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"setContent\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Set input box content\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(content: TiptapContent) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\")), mdx(\"tr\", {\n    parentName: \"tbody\"\n  }, mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"setContentWhileSaveTool\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"Set the input box content while retaining the skill item\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"(content: string) => void\"), mdx(\"td\", {\n    parentName: \"tr\",\n    \"align\": null\n  }, \"-\"))))), mdx(\"section\", null, mdx(\"h2\", {\n    parentName: \"section\"\n  }, \"Design Tokens\"), mdx(DesignToken, {\n    mdxType: \"DesignToken\"\n  })));\n}\n;\nMDXContent.isMDXComponent = true;"}},"pageContext":{"slug":"en-US/ai/aiChatInput","next":{"fields":{"slug":"zh-CN/ai/aiChatInput"},"id":"d3909896-f9a9-52fd-9694-8318d3db2400","frontmatter":{"title":"AIChatInput 聊天输入框","localeCode":"zh-CN","icon":"doc-aiInput","showNew":true}},"previous":{"fields":{"slug":"zh-CN/ai/aiComponent"},"id":"8e7cb4ef-153a-506c-9a80-9404d68ee9de","frontmatter":{"title":"AIComponent 能力介绍","localeCode":"zh-CN","icon":"doc-aiComponent","showNew":true}}}},"staticQueryHashes":["1348983216229725","1477422646229725","3245198693229725","417590761229725","63159454229725"]}