Repository: ant-design/x Branch: main Commit: 1b85e6f34cab Files: 1219 Total size: 5.5 MB Directory structure: gitextract_onxxzun6/ ├── .codefuse/ │ └── skills/ │ └── components/ │ └── SKILL.md ├── .editorconfig ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.yml │ │ └── feature_request.yml │ ├── PULL_REQUEST_TEMPLATE.md │ ├── PULL_REQUEST_TEMPLATE_CN.md │ ├── dependabot.yml │ └── workflows/ │ ├── main.yml │ ├── markdown-benchmark.yml │ ├── pr-auto-merge.yml │ ├── pr-contributor-welcome.yml │ ├── preview-build.yml │ ├── preview-deploy.yml │ ├── preview-start.yml │ ├── release-dingtalk.yml │ ├── release-x.yml │ ├── site-deploy.yml │ └── size-limit.yml ├── .gitignore ├── .husky/ │ ├── commit-msg │ └── pre-commit ├── .lintstagedrc.json ├── .npmrc ├── .prettierrc ├── CHANGELOG.en-US.md ├── CHANGELOG.zh-CN.md ├── CNAME ├── README-zh_CN.md ├── README.md ├── biome.json ├── package.json ├── packages/ │ ├── x/ │ │ ├── .dumi/ │ │ │ ├── components/ │ │ │ │ └── SemanticPreview.tsx │ │ │ ├── global.css │ │ │ ├── hooks/ │ │ │ │ ├── use.ts │ │ │ │ ├── useDark.tsx │ │ │ │ ├── useFetch/ │ │ │ │ │ ├── cache.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── useLayoutState.ts │ │ │ │ ├── useLocale.ts │ │ │ │ ├── useLocation.ts │ │ │ │ ├── useLottie.ts │ │ │ │ ├── useMenu.tsx │ │ │ │ ├── useScrollY.ts │ │ │ │ └── useThemeAnimation.ts │ │ │ ├── loading.js │ │ │ ├── pages/ │ │ │ │ ├── 404/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── index/ │ │ │ │ │ ├── common/ │ │ │ │ │ │ ├── Container.tsx │ │ │ │ │ │ ├── CustomizationProvider.tsx │ │ │ │ │ │ ├── CustomizationSender.tsx │ │ │ │ │ │ └── Introduction.tsx │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── CompIntroduction/ │ │ │ │ │ │ │ ├── Customization.tsx │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ ├── DesignBanner.tsx │ │ │ │ │ │ ├── DesignFramework.tsx │ │ │ │ │ │ ├── DesignGuide.tsx │ │ │ │ │ │ ├── Lottie.tsx │ │ │ │ │ │ ├── MainBanner.tsx │ │ │ │ │ │ ├── SceneIntroduction/ │ │ │ │ │ │ │ ├── Assistant.tsx │ │ │ │ │ │ │ ├── Independent.tsx │ │ │ │ │ │ │ ├── Nest.tsx │ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ │ └── SiteContext.ts │ │ │ │ │ └── index.tsx │ │ │ │ └── index-cn/ │ │ │ │ └── index.ts │ │ │ ├── preset/ │ │ │ │ └── .gitkeep │ │ │ ├── rehypeAntd.ts │ │ │ ├── remarkAnchor.ts │ │ │ ├── remarkAntd.ts │ │ │ ├── theme/ │ │ │ │ ├── SiteThemeProvider.tsx │ │ │ │ ├── builtins/ │ │ │ │ │ ├── APITable/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Antd.tsx │ │ │ │ │ ├── Audio/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Badge/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ColorChunk/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ColorPaletteTool/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── ColorPaletteToolDark/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── ColorPalettes/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── ComponentMeta/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ComponentOverview/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ComponentTokenTable/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Container/ │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── style.ts │ │ │ │ │ ├── DemoWrapper/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── IconSearch/ │ │ │ │ │ │ ├── Category.tsx │ │ │ │ │ │ ├── CopyableIcon.tsx │ │ │ │ │ │ ├── IconSearch.tsx │ │ │ │ │ │ ├── fields.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── themeIcons.tsx │ │ │ │ │ ├── ImagePreview/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── InlinePopover/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── InstallDependencies/ │ │ │ │ │ │ ├── bun.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ ├── npm.tsx │ │ │ │ │ │ ├── pnpm.tsx │ │ │ │ │ │ ├── utoo.tsx │ │ │ │ │ │ └── yarn.tsx │ │ │ │ │ ├── LocaleLink/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── MarkdownPluginsOverView.tsx │ │ │ │ │ ├── Palette/ │ │ │ │ │ │ └── index.ts │ │ │ │ │ ├── Previewer/ │ │ │ │ │ │ ├── CodeBlockButton.tsx │ │ │ │ │ │ ├── CodePreviewer.tsx │ │ │ │ │ │ ├── DemoFallback.tsx │ │ │ │ │ │ ├── DesignPreviewer.tsx │ │ │ │ │ │ ├── Previewer.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── PromptTemplate.tsx │ │ │ │ │ ├── ResourceCards/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Sandpack/ │ │ │ │ │ │ ├── Sandpack.ts │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── SkillsOverView.tsx │ │ │ │ │ ├── TokenCompare/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── TokenTable/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── VideoPlayer/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── common/ │ │ │ │ │ ├── BehaviorMap/ │ │ │ │ │ │ ├── BehaviorMap.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── BezierVisualizer/ │ │ │ │ │ │ ├── Visualizer.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── BrowserFrame.tsx │ │ │ │ │ ├── ClientOnly.tsx │ │ │ │ │ ├── CodePreview.tsx │ │ │ │ │ ├── Color/ │ │ │ │ │ │ ├── ColorBlock.tsx │ │ │ │ │ │ ├── ColorPaletteTool.tsx │ │ │ │ │ │ ├── ColorPaletteToolDark.tsx │ │ │ │ │ │ ├── ColorPalettes.tsx │ │ │ │ │ │ ├── ColorPatterns.tsx │ │ │ │ │ │ ├── ColorStyle.tsx │ │ │ │ │ │ └── Palette.tsx │ │ │ │ │ ├── CommonHelmet.tsx │ │ │ │ │ ├── ComponentChangelog/ │ │ │ │ │ │ ├── ComponentChangelog.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── EditButton.tsx │ │ │ │ │ ├── GlobalStyles.tsx │ │ │ │ │ ├── Helmet.tsx │ │ │ │ │ ├── JSONEditor/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Link.tsx │ │ │ │ │ ├── LinkButton.tsx │ │ │ │ │ ├── LiveCode.tsx │ │ │ │ │ ├── Loading.tsx │ │ │ │ │ ├── PrevAndNext.tsx │ │ │ │ │ ├── ThemeSwitch/ │ │ │ │ │ │ ├── ThemeIcon.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── styles/ │ │ │ │ │ ├── Common.tsx │ │ │ │ │ ├── Demo.tsx │ │ │ │ │ ├── HeadingAnchor.tsx │ │ │ │ │ ├── Highlight.tsx │ │ │ │ │ ├── InlineCard.tsx │ │ │ │ │ ├── Markdown.tsx │ │ │ │ │ ├── NProgress.tsx │ │ │ │ │ ├── PreviewImage.tsx │ │ │ │ │ ├── Reset.tsx │ │ │ │ │ ├── Responsive.tsx │ │ │ │ │ ├── SearchBar.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── icons/ │ │ │ │ │ ├── CodePenIcon.tsx │ │ │ │ │ ├── CodeSandboxIcon.tsx │ │ │ │ │ ├── DirectionIcon.tsx │ │ │ │ │ └── ExternalLinkIcon.tsx │ │ │ │ ├── layouts/ │ │ │ │ │ ├── DocLayout/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── GlobalLayout.tsx │ │ │ │ │ ├── IndexLayout/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── SidebarLayout/ │ │ │ │ │ └── index.tsx │ │ │ │ ├── locales/ │ │ │ │ │ ├── en-US.json │ │ │ │ │ └── zh-CN.json │ │ │ │ ├── plugin.ts │ │ │ │ ├── slots/ │ │ │ │ │ ├── Alert/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Content/ │ │ │ │ │ │ ├── ColumnCard.tsx │ │ │ │ │ │ ├── ContributorAvatar.tsx │ │ │ │ │ │ ├── Contributors.tsx │ │ │ │ │ │ ├── DocAnchor.tsx │ │ │ │ │ │ ├── DocMeta.tsx │ │ │ │ │ │ ├── InViewSuspense.tsx │ │ │ │ │ │ ├── JuejinLogo.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── ContentTabs/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── DemoContext.ts │ │ │ │ │ ├── Footer/ │ │ │ │ │ │ ├── AdditionalInfo.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Header/ │ │ │ │ │ │ ├── Actions.tsx │ │ │ │ │ │ ├── Logo.tsx │ │ │ │ │ │ ├── Navigation.tsx │ │ │ │ │ │ ├── SwitchBtn.tsx │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── interface.ts │ │ │ │ │ ├── LiveError/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── Sidebar/ │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── SiteContext.ts │ │ │ │ ├── static/ │ │ │ │ │ └── style.ts │ │ │ │ ├── themeConfig.ts │ │ │ │ ├── utils/ │ │ │ │ │ ├── __tests__/ │ │ │ │ │ │ ├── runTests.ts │ │ │ │ │ │ └── tsToJs.test.ts │ │ │ │ │ ├── tsToJs.test.ts │ │ │ │ │ └── tsToJs.ts │ │ │ │ └── utils.ts │ │ │ └── tsconfig.json │ │ ├── .dumirc.ts │ │ ├── .fatherrc.ts │ │ ├── .jest.js │ │ ├── .lintstagedrc.json │ │ ├── .surgeignore │ │ ├── BUG_VERSIONS.json │ │ ├── CNAME │ │ ├── LICENSE │ │ ├── README-zh_CN.md │ │ ├── README.md │ │ ├── alias/ │ │ │ └── cssinjs.js │ │ ├── bunfig.toml │ │ ├── components/ │ │ │ ├── _util/ │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── hooks.test.tsx │ │ │ │ │ └── warning.test.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-collapsible.ts │ │ │ │ │ ├── use-proxy-imperative-handle.ts │ │ │ │ │ ├── use-shortcut-keys.ts │ │ │ │ │ └── use-x-component-config.ts │ │ │ │ ├── motion.ts │ │ │ │ ├── type.ts │ │ │ │ └── warning.ts │ │ │ ├── actions/ │ │ │ │ ├── ActionsAudio.tsx │ │ │ │ ├── ActionsCopy.tsx │ │ │ │ ├── ActionsFeedback.tsx │ │ │ │ ├── ActionsItem.tsx │ │ │ │ ├── ActionsMenu.tsx │ │ │ │ ├── Item.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── action-item.test.tsx │ │ │ │ │ ├── audio.test.tsx │ │ │ │ │ ├── copy.test.tsx │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── feedback.test.tsx │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic-audio.tsx │ │ │ │ │ ├── _semantic-copy.tsx │ │ │ │ │ ├── _semantic-feedback.tsx │ │ │ │ │ ├── _semantic-item.tsx │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── fadeIn.md │ │ │ │ │ ├── fadeIn.tsx │ │ │ │ │ ├── preset.md │ │ │ │ │ ├── preset.tsx │ │ │ │ │ ├── sub.md │ │ │ │ │ ├── sub.tsx │ │ │ │ │ ├── variant.md │ │ │ │ │ └── variant.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── audio.tsx │ │ │ │ ├── copy.ts │ │ │ │ ├── feedback.ts │ │ │ │ └── index.ts │ │ │ ├── attachments/ │ │ │ │ ├── DropArea.tsx │ │ │ │ ├── FileList/ │ │ │ │ │ ├── Progress.tsx │ │ │ │ │ └── index.tsx │ │ │ │ ├── PlaceholderUploader.tsx │ │ │ │ ├── SilentUploader.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.tsx.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.tsx │ │ │ │ │ ├── drag.test.tsx │ │ │ │ │ ├── image.test.ts │ │ │ │ │ ├── index.test.tsx │ │ │ │ │ └── util.test.ts │ │ │ │ ├── context.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── overflow.md │ │ │ │ │ ├── overflow.tsx │ │ │ │ │ ├── placeholder.md │ │ │ │ │ ├── placeholder.tsx │ │ │ │ │ ├── select-files.md │ │ │ │ │ ├── select-files.tsx │ │ │ │ │ ├── with-sender.md │ │ │ │ │ └── with-sender.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── style/ │ │ │ │ │ └── index.ts │ │ │ │ └── util.ts │ │ │ ├── bubble/ │ │ │ │ ├── Bubble.tsx │ │ │ │ ├── BubbleList.tsx │ │ │ │ ├── Divider.tsx │ │ │ │ ├── EditableContent.tsx │ │ │ │ ├── System.tsx │ │ │ │ ├── TypingContent.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── divider.test.tsx │ │ │ │ │ ├── enhanced.test.tsx │ │ │ │ │ ├── image.test.ts │ │ │ │ │ ├── index.test.tsx │ │ │ │ │ ├── list-scroll.test.tsx │ │ │ │ │ ├── list.test.tsx │ │ │ │ │ └── system.test.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic-divider.tsx │ │ │ │ │ ├── _semantic-list.tsx │ │ │ │ │ ├── _semantic-system.tsx │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── animation.md │ │ │ │ │ ├── animation.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── custom-content.md │ │ │ │ │ ├── custom-content.tsx │ │ │ │ │ ├── divider.md │ │ │ │ │ ├── divider.tsx │ │ │ │ │ ├── editable.md │ │ │ │ │ ├── editable.tsx │ │ │ │ │ ├── footer.md │ │ │ │ │ ├── footer.tsx │ │ │ │ │ ├── gpt-vis.md │ │ │ │ │ ├── gpt-vis.tsx │ │ │ │ │ ├── header.md │ │ │ │ │ ├── header.tsx │ │ │ │ │ ├── list-extra.md │ │ │ │ │ ├── list-extra.tsx │ │ │ │ │ ├── list-scroll.md │ │ │ │ │ ├── list-scroll.tsx │ │ │ │ │ ├── list.md │ │ │ │ │ ├── list.tsx │ │ │ │ │ ├── loading.md │ │ │ │ │ ├── loading.tsx │ │ │ │ │ ├── markdown.md │ │ │ │ │ ├── markdown.tsx │ │ │ │ │ ├── semantic-list-custom.md │ │ │ │ │ ├── semantic-list-custom.tsx │ │ │ │ │ ├── sider-and-placement.md │ │ │ │ │ ├── sider-and-placement.tsx │ │ │ │ │ ├── stream.md │ │ │ │ │ ├── stream.tsx │ │ │ │ │ ├── system.md │ │ │ │ │ ├── system.tsx │ │ │ │ │ ├── variant-and-shape.md │ │ │ │ │ └── variant-and-shape.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── useCompatibleScroll.ts │ │ │ │ │ └── useTyping.ts │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── interface.ts │ │ │ │ ├── loading.tsx │ │ │ │ └── style/ │ │ │ │ ├── bubble.ts │ │ │ │ ├── content.ts │ │ │ │ ├── divider.ts │ │ │ │ ├── index.ts │ │ │ │ ├── list.ts │ │ │ │ ├── slot.ts │ │ │ │ └── system.ts │ │ │ ├── code-highlighter/ │ │ │ │ ├── CodeHighlighter.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── custom-header.tsx │ │ │ │ │ └── with-xmarkdown.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── conversations/ │ │ │ │ ├── Creation.tsx │ │ │ │ ├── GroupTitle.tsx │ │ │ │ ├── Item.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── controlled-collapsible.md │ │ │ │ │ ├── controlled-collapsible.tsx │ │ │ │ │ ├── controlled-mode.md │ │ │ │ │ ├── controlled-mode.tsx │ │ │ │ │ ├── custom-new-chat.md │ │ │ │ │ ├── custom-new-chat.tsx │ │ │ │ │ ├── group-collapsible.md │ │ │ │ │ ├── group-collapsible.tsx │ │ │ │ │ ├── group.md │ │ │ │ │ ├── group.tsx │ │ │ │ │ ├── infinite-load.md │ │ │ │ │ ├── infinite-load.tsx │ │ │ │ │ ├── menu-trigger.md │ │ │ │ │ ├── menu-trigger.tsx │ │ │ │ │ ├── new-chat.md │ │ │ │ │ ├── new-chat.tsx │ │ │ │ │ ├── shortcutKeys.md │ │ │ │ │ ├── shortcutKeys.tsx │ │ │ │ │ ├── with-menu.md │ │ │ │ │ └── with-menu.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── useCreation.tsx │ │ │ │ │ └── useGroupable.ts │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── file-card/ │ │ │ │ ├── FileCard.tsx │ │ │ │ ├── List.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ └── demo.test.ts.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── components/ │ │ │ │ │ ├── File.tsx │ │ │ │ │ ├── ImageIcon.tsx │ │ │ │ │ ├── ImageLoading.tsx │ │ │ │ │ └── usePercent.ts │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic-list.tsx │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── audio.md │ │ │ │ │ ├── audio.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── custom-description.md │ │ │ │ │ ├── custom-description.tsx │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── icon.tsx │ │ │ │ │ ├── image-loading.md │ │ │ │ │ ├── image-loading.tsx │ │ │ │ │ ├── image.md │ │ │ │ │ ├── image.tsx │ │ │ │ │ ├── list.md │ │ │ │ │ ├── list.tsx │ │ │ │ │ ├── mask.md │ │ │ │ │ ├── mask.tsx │ │ │ │ │ ├── overflow.md │ │ │ │ │ ├── overflow.tsx │ │ │ │ │ ├── size.md │ │ │ │ │ └── size.tsx │ │ │ │ ├── icons/ │ │ │ │ │ ├── audio.tsx │ │ │ │ │ └── video.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── style/ │ │ │ │ │ └── index.ts │ │ │ │ └── utils.ts │ │ │ ├── folder/ │ │ │ │ ├── DirectoryTree.tsx │ │ │ │ ├── FilePreview.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── custom-icons.md │ │ │ │ │ ├── custom-icons.tsx │ │ │ │ │ ├── custom-service.md │ │ │ │ │ ├── custom-service.tsx │ │ │ │ │ ├── file-controlled.md │ │ │ │ │ ├── file-controlled.tsx │ │ │ │ │ ├── fully-controlled.md │ │ │ │ │ ├── fully-controlled.tsx │ │ │ │ │ ├── preview-render.md │ │ │ │ │ ├── preview-render.tsx │ │ │ │ │ ├── searchable.md │ │ │ │ │ └── searchable.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── style/ │ │ │ │ └── index.tsx │ │ │ ├── index.ts │ │ │ ├── introduce/ │ │ │ │ ├── index.en-US.md │ │ │ │ └── index.zh-CN.md │ │ │ ├── locale/ │ │ │ │ ├── __tests__/ │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── en_US.ts │ │ │ │ ├── index.tsx │ │ │ │ ├── useLocale.ts │ │ │ │ └── zh_CN.ts │ │ │ ├── mermaid/ │ │ │ │ ├── Mermaid.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── custom-header.tsx │ │ │ │ │ ├── header-actions.tsx │ │ │ │ │ └── with-xmarkdown.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── notification/ │ │ │ │ ├── __tests__/ │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── close_tag.md │ │ │ │ │ ├── close_tag.tsx │ │ │ │ │ ├── duration.md │ │ │ │ │ ├── duration.tsx │ │ │ │ │ ├── hooks.md │ │ │ │ │ ├── hooks.tsx │ │ │ │ │ ├── static-method.md │ │ │ │ │ └── static-method.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── interface.ts │ │ │ ├── overview/ │ │ │ │ ├── index.en-US.md │ │ │ │ └── index.zh-CN.md │ │ │ ├── prompts/ │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── disabled.md │ │ │ │ │ ├── disabled.tsx │ │ │ │ │ ├── fadeIn.md │ │ │ │ │ ├── fadeIn.tsx │ │ │ │ │ ├── flex-vertical.md │ │ │ │ │ ├── flex-vertical.tsx │ │ │ │ │ ├── flex-wrap-fixed.md │ │ │ │ │ ├── flex-wrap-fixed.tsx │ │ │ │ │ ├── flex-wrap.md │ │ │ │ │ ├── flex-wrap.tsx │ │ │ │ │ ├── nest.md │ │ │ │ │ └── nest.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── sender/ │ │ │ │ ├── Sender.tsx │ │ │ │ ├── SenderHeader.tsx │ │ │ │ ├── SenderSwitch.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ ├── header.test.tsx.snap │ │ │ │ │ │ ├── index.test.tsx.snap │ │ │ │ │ │ └── switch.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── header.test.tsx │ │ │ │ │ ├── image.test.ts │ │ │ │ │ ├── index.test.tsx │ │ │ │ │ ├── skill.test.tsx │ │ │ │ │ ├── slot.test.tsx │ │ │ │ │ ├── switch.test.tsx │ │ │ │ │ ├── use-cursor.test.tsx │ │ │ │ │ └── use-speech.test.tsx │ │ │ │ ├── components/ │ │ │ │ │ ├── ActionButton.tsx │ │ │ │ │ ├── ClearButton.tsx │ │ │ │ │ ├── LoadingButton/ │ │ │ │ │ │ ├── StopLoading.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── SendButton.tsx │ │ │ │ │ ├── Skill.tsx │ │ │ │ │ ├── SlotTextArea.tsx │ │ │ │ │ ├── SpeechButton/ │ │ │ │ │ │ ├── RecordingIcon.tsx │ │ │ │ │ │ └── index.tsx │ │ │ │ │ └── TextArea.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic-switch.tsx │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── agent.md │ │ │ │ │ ├── agent.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── disable-ctrl-slot.md │ │ │ │ │ ├── disable-ctrl-slot.tsx │ │ │ │ │ ├── disable-ctrl.md │ │ │ │ │ ├── disable-ctrl.tsx │ │ │ │ │ ├── footer.md │ │ │ │ │ ├── footer.tsx │ │ │ │ │ ├── header-fixed.md │ │ │ │ │ ├── header-fixed.tsx │ │ │ │ │ ├── header.md │ │ │ │ │ ├── header.tsx │ │ │ │ │ ├── paste-image.md │ │ │ │ │ ├── paste-image.tsx │ │ │ │ │ ├── ref-action.md │ │ │ │ │ ├── ref-action.tsx │ │ │ │ │ ├── send-style.md │ │ │ │ │ ├── send-style.tsx │ │ │ │ │ ├── slot-filling.md │ │ │ │ │ ├── slot-filling.tsx │ │ │ │ │ ├── slot-with-suggestion.md │ │ │ │ │ ├── slot-with-suggestion.tsx │ │ │ │ │ ├── speech-custom.md │ │ │ │ │ ├── speech-custom.tsx │ │ │ │ │ ├── speech.md │ │ │ │ │ ├── speech.tsx │ │ │ │ │ ├── submitType.md │ │ │ │ │ ├── submitType.tsx │ │ │ │ │ ├── suffix.md │ │ │ │ │ ├── suffix.tsx │ │ │ │ │ ├── switch.md │ │ │ │ │ └── switch.tsx │ │ │ │ ├── hooks/ │ │ │ │ │ ├── use-cursor.ts │ │ │ │ │ ├── use-input-height.ts │ │ │ │ │ ├── use-slot-builder.ts │ │ │ │ │ ├── use-slot-config-state.ts │ │ │ │ │ └── use-speech.ts │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── header.ts │ │ │ │ ├── index.ts │ │ │ │ ├── slot-textarea.ts │ │ │ │ └── switch.ts │ │ │ ├── sources/ │ │ │ │ ├── Sources.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── components/ │ │ │ │ │ └── CarouselCard.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── expand.md │ │ │ │ │ ├── expand.tsx │ │ │ │ │ ├── icon.md │ │ │ │ │ ├── icon.tsx │ │ │ │ │ ├── inline.md │ │ │ │ │ └── inline.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── style/ │ │ │ │ ├── index.ts │ │ │ │ └── motion/ │ │ │ │ ├── blink.ts │ │ │ │ ├── collapse.ts │ │ │ │ ├── fade.ts │ │ │ │ └── init.ts │ │ │ ├── suggestion/ │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ ├── index.test.tsx │ │ │ │ │ └── useActive.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── block.md │ │ │ │ │ ├── block.tsx │ │ │ │ │ ├── trigger.md │ │ │ │ │ └── trigger.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── style/ │ │ │ │ │ └── index.ts │ │ │ │ └── useActive.ts │ │ │ ├── theme/ │ │ │ │ ├── __tests__/ │ │ │ │ │ └── theme.test.tsx │ │ │ │ ├── context.ts │ │ │ │ ├── genStyleUtils.ts │ │ │ │ ├── interface/ │ │ │ │ │ ├── alias.ts │ │ │ │ │ ├── components.ts │ │ │ │ │ ├── cssinjs-utils.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── maps/ │ │ │ │ │ │ ├── colors.ts │ │ │ │ │ │ ├── font.ts │ │ │ │ │ │ ├── index.ts │ │ │ │ │ │ ├── size.ts │ │ │ │ │ │ └── style.ts │ │ │ │ │ ├── presetColors.ts │ │ │ │ │ └── seeds.ts │ │ │ │ ├── themes/ │ │ │ │ │ └── seed.ts │ │ │ │ ├── useToken.ts │ │ │ │ └── util/ │ │ │ │ ├── alias.ts │ │ │ │ └── getAlphaColor.ts │ │ │ ├── think/ │ │ │ │ ├── Think.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── expand.md │ │ │ │ │ ├── expand.tsx │ │ │ │ │ ├── status.md │ │ │ │ │ └── status.tsx │ │ │ │ ├── icons/ │ │ │ │ │ └── think.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ ├── thought-chain/ │ │ │ │ ├── Item.tsx │ │ │ │ ├── Node.tsx │ │ │ │ ├── Status.tsx │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ ├── index.test.tsx.snap │ │ │ │ │ │ └── item.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ ├── index.test.tsx │ │ │ │ │ └── item.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic-item.tsx │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── collapsible.md │ │ │ │ │ ├── collapsible.tsx │ │ │ │ │ ├── controlled-collapsible.md │ │ │ │ │ ├── controlled-collapsible.tsx │ │ │ │ │ ├── customization.md │ │ │ │ │ ├── customization.tsx │ │ │ │ │ ├── nested.md │ │ │ │ │ ├── nested.tsx │ │ │ │ │ ├── simple.md │ │ │ │ │ ├── simple.tsx │ │ │ │ │ ├── single-row.md │ │ │ │ │ ├── single-row.tsx │ │ │ │ │ ├── status.md │ │ │ │ │ └── status.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── interface.ts │ │ │ │ └── style/ │ │ │ │ ├── index.ts │ │ │ │ └── item.ts │ │ │ ├── version/ │ │ │ │ └── index.ts │ │ │ ├── welcome/ │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── demo-extend.test.ts.snap │ │ │ │ │ │ ├── demo.test.ts.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── demo-extend.test.ts │ │ │ │ │ ├── demo.test.ts │ │ │ │ │ ├── image.test.ts │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── demo/ │ │ │ │ │ ├── _semantic.tsx │ │ │ │ │ ├── background.md │ │ │ │ │ ├── background.tsx │ │ │ │ │ ├── basic.md │ │ │ │ │ ├── basic.tsx │ │ │ │ │ ├── variant.md │ │ │ │ │ └── variant.tsx │ │ │ │ ├── index.en-US.md │ │ │ │ ├── index.tsx │ │ │ │ ├── index.zh-CN.md │ │ │ │ └── style/ │ │ │ │ └── index.ts │ │ │ └── x-provider/ │ │ │ ├── __tests__/ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ ├── cssVar.test.tsx │ │ │ │ ├── image.test.ts │ │ │ │ └── index.test.tsx │ │ │ ├── context.ts │ │ │ ├── demo/ │ │ │ │ ├── direction.md │ │ │ │ ├── direction.tsx │ │ │ │ ├── locale.md │ │ │ │ ├── locale.tsx │ │ │ │ ├── shortcutKeys.md │ │ │ │ ├── shortcutKeys.tsx │ │ │ │ ├── theme.md │ │ │ │ └── theme.tsx │ │ │ ├── hooks/ │ │ │ │ └── use-x-provider-context.ts │ │ │ ├── index.en-US.md │ │ │ ├── index.tsx │ │ │ └── index.zh-CN.md │ │ ├── docs/ │ │ │ ├── playground/ │ │ │ │ ├── _utils/ │ │ │ │ │ └── local.ts │ │ │ │ ├── agent-tbox.en-US.md │ │ │ │ ├── agent-tbox.tsx │ │ │ │ ├── agent-tbox.zh-CN.md │ │ │ │ ├── copilot.en-US.md │ │ │ │ ├── copilot.tsx │ │ │ │ ├── copilot.zh-CN.md │ │ │ │ ├── independent.en-US.md │ │ │ │ ├── independent.tsx │ │ │ │ ├── independent.zh-CN.md │ │ │ │ ├── ultramodern.en-US.md │ │ │ │ ├── ultramodern.tsx │ │ │ │ └── ultramodern.zh-CN.md │ │ │ ├── react/ │ │ │ │ ├── agent-use-tbox.en-US.md │ │ │ │ ├── agent-use-tbox.zh-CN.md │ │ │ │ ├── common-props.en-US.md │ │ │ │ ├── common-props.zh-CN.md │ │ │ │ ├── compatible-style.en-US.md │ │ │ │ ├── compatible-style.zh-CN.md │ │ │ │ ├── contributing.en-US.md │ │ │ │ ├── contributing.zh-CN.md │ │ │ │ ├── demo/ │ │ │ │ │ ├── qwen-sdk.tsx │ │ │ │ │ ├── qwen.tsx │ │ │ │ │ └── tbox.tsx │ │ │ │ ├── faq.en-US.md │ │ │ │ ├── faq.zh-CN.md │ │ │ │ ├── introduce.en-US.md │ │ │ │ ├── introduce.zh-CN.md │ │ │ │ ├── migration-v2.en-US.md │ │ │ │ ├── migration-v2.zh-CN.md │ │ │ │ ├── model-use-openai.en-US.md │ │ │ │ ├── model-use-openai.zh-CN.md │ │ │ │ ├── model-use-qwen.en-US.md │ │ │ │ ├── model-use-qwen.zh-CN.md │ │ │ │ ├── use-with-create-react-app.en-US.md │ │ │ │ ├── use-with-create-react-app.zh-CN.md │ │ │ │ ├── use-with-next.en-US.md │ │ │ │ ├── use-with-next.zh-CN.md │ │ │ │ ├── use-with-rsbuild.en-US.md │ │ │ │ ├── use-with-rsbuild.zh-CN.md │ │ │ │ ├── use-with-umi.en-US.md │ │ │ │ ├── use-with-umi.zh-CN.md │ │ │ │ ├── use-with-vite.en-US.md │ │ │ │ └── use-with-vite.zh-CN.md │ │ │ ├── spec/ │ │ │ │ ├── authentic-consistent.en-US.md │ │ │ │ ├── authentic-consistent.zh-CN.md │ │ │ │ ├── confirm-generation-process.en-US.md │ │ │ │ ├── confirm-generation-process.zh-CN.md │ │ │ │ ├── confirm.en-US.md │ │ │ │ ├── confirm.zh-CN.md │ │ │ │ ├── conversation-design.en-US.md │ │ │ │ ├── conversation-design.zh-CN.md │ │ │ │ ├── define-intention-type.en-US.md │ │ │ │ ├── define-intention-type.zh-CN.md │ │ │ │ ├── end.en-US.md │ │ │ │ ├── end.zh-CN.md │ │ │ │ ├── error.en-US.md │ │ │ │ ├── error.zh-CN.md │ │ │ │ ├── expression-user-input.en-US.md │ │ │ │ ├── expression-user-input.zh-CN.md │ │ │ │ ├── expression-user-send.en-US.md │ │ │ │ ├── expression-user-send.zh-CN.md │ │ │ │ ├── feedback-result-application.en-US.md │ │ │ │ ├── feedback-result-application.zh-CN.md │ │ │ │ ├── feedback-result-display.en-US.md │ │ │ │ ├── feedback-result-display.zh-CN.md │ │ │ │ ├── follow-up.en-US.md │ │ │ │ ├── follow-up.zh-CN.md │ │ │ │ ├── guide-intention-expression.en-US.md │ │ │ │ ├── guide-intention-expression.zh-CN.md │ │ │ │ ├── hint.en-US.md │ │ │ │ ├── hint.zh-CN.md │ │ │ │ ├── human-touch.en-US.md │ │ │ │ ├── human-touch.zh-CN.md │ │ │ │ ├── hybrid-ui-design.en-US.md │ │ │ │ ├── hybrid-ui-design.zh-CN.md │ │ │ │ ├── intention-introduce.en-US.md │ │ │ │ ├── intention-introduce.zh-CN.md │ │ │ │ ├── introduce.en-US.md │ │ │ │ ├── introduce.zh-CN.md │ │ │ │ ├── provide-intention-expectation.en-US.md │ │ │ │ ├── provide-intention-expectation.zh-CN.md │ │ │ │ ├── role-design.en-US.md │ │ │ │ ├── role-design.zh-CN.md │ │ │ │ ├── smooth-natural.en-US.md │ │ │ │ ├── smooth-natural.zh-CN.md │ │ │ │ ├── start.en-US.md │ │ │ │ ├── start.zh-CN.md │ │ │ │ ├── wake-up-ai-icon.en-US.md │ │ │ │ ├── wake-up-ai-icon.zh-CN.md │ │ │ │ ├── wake-up-welcome-message.en-US.md │ │ │ │ └── wake-up-welcome-message.zh-CN.md │ │ │ ├── x-markdown/ │ │ │ │ ├── chat-enhancement.en-US.md │ │ │ │ ├── chat-enhancement.zh-CN.md │ │ │ │ ├── components.en-US.md │ │ │ │ ├── components.zh-CN.md │ │ │ │ ├── custom-plugin.en-US.md │ │ │ │ ├── custom-plugin.zh-CN.md │ │ │ │ ├── data-display.en-US.md │ │ │ │ ├── data-display.zh-CN.md │ │ │ │ ├── demo/ │ │ │ │ │ ├── _utils/ │ │ │ │ │ │ ├── adx-markdown.ts │ │ │ │ │ │ ├── index.tsx │ │ │ │ │ │ └── theme-markdown.ts │ │ │ │ │ ├── codeDemo/ │ │ │ │ │ │ ├── basic.tsx │ │ │ │ │ │ ├── escape-raw-html.tsx │ │ │ │ │ │ ├── link.tsx │ │ │ │ │ │ ├── plugin.tsx │ │ │ │ │ │ ├── renderer.tsx │ │ │ │ │ │ ├── streaming.tsx │ │ │ │ │ │ ├── supersets.tsx │ │ │ │ │ │ ├── tokenizer.tsx │ │ │ │ │ │ ├── walkTokens.tsx │ │ │ │ │ │ └── xss.tsx │ │ │ │ │ ├── components/ │ │ │ │ │ │ ├── codeHighlighter.tsx │ │ │ │ │ │ ├── custom.tsx │ │ │ │ │ │ ├── dataChart.tsx │ │ │ │ │ │ ├── infographic.tsx │ │ │ │ │ │ ├── mermaid.tsx │ │ │ │ │ │ ├── sources.tsx │ │ │ │ │ │ └── think.tsx │ │ │ │ │ ├── streaming/ │ │ │ │ │ │ ├── animation.tsx │ │ │ │ │ │ ├── combined.tsx │ │ │ │ │ │ ├── debug.tsx │ │ │ │ │ │ └── format.tsx │ │ │ │ │ ├── supersets/ │ │ │ │ │ │ ├── CustomPlugin/ │ │ │ │ │ │ │ ├── custom.tsx │ │ │ │ │ │ │ ├── marked.tsx │ │ │ │ │ │ │ └── plugin.css │ │ │ │ │ │ └── Latex/ │ │ │ │ │ │ └── basic.tsx │ │ │ │ │ └── themes/ │ │ │ │ │ ├── custom.tsx │ │ │ │ │ ├── dark.tsx │ │ │ │ │ ├── light.tsx │ │ │ │ │ └── switch.tsx │ │ │ │ ├── examples.en-US.md │ │ │ │ ├── examples.zh-CN.md │ │ │ │ ├── introduce.en-US.md │ │ │ │ ├── introduce.zh-CN.md │ │ │ │ ├── playground.en-US.md │ │ │ │ ├── playground.tsx │ │ │ │ ├── playground.zh-CN.md │ │ │ │ ├── plugin-latex.en-US.md │ │ │ │ ├── plugin-latex.zh-CN.md │ │ │ │ ├── plugins.en-US.md │ │ │ │ ├── plugins.zh-CN.md │ │ │ │ ├── rich-text.en-US.md │ │ │ │ ├── rich-text.zh-CN.md │ │ │ │ ├── streaming.en-US.md │ │ │ │ ├── streaming.zh-CN.md │ │ │ │ ├── themes.en-US.md │ │ │ │ └── themes.zh-CN.md │ │ │ ├── x-sdk/ │ │ │ │ ├── chat-provider-custom.en-US.md │ │ │ │ ├── chat-provider-custom.zh-CN.md │ │ │ │ ├── chat-provider-deepseek.en-US.md │ │ │ │ ├── chat-provider-deepseek.zh-CN.md │ │ │ │ ├── chat-provider-open-ai.en-US.md │ │ │ │ ├── chat-provider-open-ai.zh-CN.md │ │ │ │ ├── chat-provider.en-US.md │ │ │ │ ├── chat-provider.zh-CN.md │ │ │ │ ├── demos/ │ │ │ │ │ ├── chat-providers/ │ │ │ │ │ │ ├── custom-provider-width-ui.md │ │ │ │ │ │ ├── custom-provider-width-ui.tsx │ │ │ │ │ │ ├── deep-seek-chat-provider.md │ │ │ │ │ │ ├── deep-seek-chat-provider.tsx │ │ │ │ │ │ ├── default-chat-provider-width-ui.md │ │ │ │ │ │ ├── default-chat-provider-width-ui.tsx │ │ │ │ │ │ ├── default-chat-provider.md │ │ │ │ │ │ ├── default-chat-provider.tsx │ │ │ │ │ │ ├── open-ai-chat-provider.md │ │ │ │ │ │ └── open-ai-chat-provider.tsx │ │ │ │ │ ├── x-chat/ │ │ │ │ │ │ ├── async-defaultMessages.md │ │ │ │ │ │ ├── async-defaultMessages.tsx │ │ │ │ │ │ ├── custom-request-fetch-en.tsx │ │ │ │ │ │ ├── custom-request-fetch.md │ │ │ │ │ │ ├── custom-request-fetch.tsx │ │ │ │ │ │ ├── deepSeek.md │ │ │ │ │ │ ├── deepSeek.tsx │ │ │ │ │ │ ├── defaultMessages.md │ │ │ │ │ │ ├── defaultMessages.tsx │ │ │ │ │ │ ├── developer.md │ │ │ │ │ │ ├── developer.tsx │ │ │ │ │ │ ├── openai-callback.md │ │ │ │ │ │ ├── openai-callback.tsx │ │ │ │ │ │ ├── openai.md │ │ │ │ │ │ ├── openai.tsx │ │ │ │ │ │ ├── request-openai-node.md │ │ │ │ │ │ └── request-openai-node.tsx │ │ │ │ │ ├── x-conversations/ │ │ │ │ │ │ ├── async-defaultMessages.md │ │ │ │ │ │ ├── async-defaultMessages.tsx │ │ │ │ │ │ ├── basic.md │ │ │ │ │ │ ├── basic.tsx │ │ │ │ │ │ ├── multi-instances.md │ │ │ │ │ │ ├── multi-instances.tsx │ │ │ │ │ │ ├── operations.md │ │ │ │ │ │ ├── operations.tsx │ │ │ │ │ │ ├── session-key.md │ │ │ │ │ │ ├── session-key.tsx │ │ │ │ │ │ ├── with-x-chat.md │ │ │ │ │ │ └── with-x-chat.tsx │ │ │ │ │ ├── x-request/ │ │ │ │ │ │ ├── basic.md │ │ │ │ │ │ ├── basic.tsx │ │ │ │ │ │ ├── custom-params-headers.md │ │ │ │ │ │ ├── custom-params-headers.tsx │ │ │ │ │ │ ├── custom-transformer.md │ │ │ │ │ │ ├── custom-transformer.tsx │ │ │ │ │ │ ├── manual.md │ │ │ │ │ │ ├── manual.tsx │ │ │ │ │ │ ├── stream-separator.md │ │ │ │ │ │ ├── stream-separator.tsx │ │ │ │ │ │ ├── stream-timeout.md │ │ │ │ │ │ ├── stream-timeout.tsx │ │ │ │ │ │ ├── timeout.md │ │ │ │ │ │ └── timeout.tsx │ │ │ │ │ └── x-stream/ │ │ │ │ │ ├── custom-protocol.md │ │ │ │ │ ├── custom-protocol.tsx │ │ │ │ │ ├── default-protocol.md │ │ │ │ │ └── default-protocol.tsx │ │ │ │ ├── introduce.en-US.md │ │ │ │ ├── introduce.zh-CN.md │ │ │ │ ├── use-x-chat.en-US.md │ │ │ │ ├── use-x-chat.zh-CN.md │ │ │ │ ├── use-x-conversations.en-US.md │ │ │ │ ├── use-x-conversations.zh-CN.md │ │ │ │ ├── x-request.en-US.md │ │ │ │ ├── x-request.zh-CN.md │ │ │ │ ├── x-stream.en-US.md │ │ │ │ └── x-stream.zh-CN.md │ │ │ └── x-skill/ │ │ │ ├── introduce.en-US.md │ │ │ ├── introduce.zh-CN.md │ │ │ ├── prompt.en-US.md │ │ │ ├── prompt.zh-CN.md │ │ │ ├── skills.en-US.md │ │ │ └── skills.zh-CN.md │ │ ├── index.js │ │ ├── jest-puppeteer.config.js │ │ ├── mako.config.json │ │ ├── package.json │ │ ├── scripts/ │ │ │ ├── __snapshots__/ │ │ │ │ └── check-site.ts.snap │ │ │ ├── check-cssinjs.tsx │ │ │ ├── check-site.ts │ │ │ ├── check-version-md.ts │ │ │ ├── ci-mock-project-build.sh │ │ │ ├── collect-token-statistic.ts │ │ │ ├── generate-authors.ts │ │ │ ├── generate-component-changelog.ts │ │ │ ├── generate-cssinjs.ts │ │ │ ├── generate-token-meta.ts │ │ │ ├── generate-version.ts │ │ │ ├── previewEditor/ │ │ │ │ └── template.html │ │ │ ├── print-changelog.ts │ │ │ ├── set-node-options.ts │ │ │ ├── tsconfig.json │ │ │ └── visual-regression/ │ │ │ ├── build.ts │ │ │ ├── convert.ts │ │ │ ├── report-template.html │ │ │ └── upload.js │ │ ├── tests/ │ │ │ ├── __mocks__/ │ │ │ │ ├── @rc-component/ │ │ │ │ │ ├── trigger.tsx │ │ │ │ │ └── virtual-list.ts │ │ │ │ ├── copy-to-clipboard.ts │ │ │ │ └── mermaid.js │ │ │ ├── __snapshots__/ │ │ │ │ ├── changelog.test.ts.snap │ │ │ │ └── index.test.ts.snap │ │ │ ├── changelog.test.ts │ │ │ ├── dekko/ │ │ │ │ ├── dist.test.ts │ │ │ │ ├── index.test.ts │ │ │ │ ├── lib.test.ts │ │ │ │ └── use-client.test.ts │ │ │ ├── index.html │ │ │ ├── index.test.ts │ │ │ ├── setup-streams.ts │ │ │ ├── setup.ts │ │ │ ├── setupAfterEnv.ts │ │ │ ├── shared/ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ └── demoTest.tsx.snap │ │ │ │ ├── accessibilityTest.tsx │ │ │ │ ├── demoTest.tsx │ │ │ │ ├── demoTestContext.ts │ │ │ │ ├── excludeWarning.ts │ │ │ │ ├── focusTest.tsx │ │ │ │ ├── imageTest.tsx │ │ │ │ ├── mountTest.tsx │ │ │ │ ├── rootPropsTest.tsx │ │ │ │ ├── rtlTest.tsx │ │ │ │ └── themeTest.tsx │ │ │ └── utils.tsx │ │ ├── tsconfig.json │ │ └── typings/ │ │ ├── custom-typings.d.ts │ │ ├── index.d.ts │ │ └── jest.d.ts │ ├── x-markdown/ │ │ ├── .fatherrc.ts │ │ ├── .jest.js │ │ ├── BUG_VERSIONS.json │ │ ├── LICENSE │ │ ├── README-zh_CN.md │ │ ├── README.md │ │ ├── jest-puppeteer.config.js │ │ ├── mako.config.json │ │ ├── package.json │ │ ├── scripts/ │ │ │ ├── generate-plugin-meta.ts │ │ │ └── generate-version.ts │ │ ├── src/ │ │ │ ├── XMarkdown/ │ │ │ │ ├── AnimationText.tsx │ │ │ │ ├── DebugPanel/ │ │ │ │ │ ├── DebugPanel.css │ │ │ │ │ ├── DebugPanel.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── __benchmark__/ │ │ │ │ │ ├── README.md │ │ │ │ │ ├── components/ │ │ │ │ │ │ └── MarkdownRenderer.tsx │ │ │ │ │ ├── playwright/ │ │ │ │ │ │ ├── index.html │ │ │ │ │ │ └── index.tsx │ │ │ │ │ ├── playwright-ct.config.ts │ │ │ │ │ ├── scripts/ │ │ │ │ │ │ ├── check-performance.js │ │ │ │ │ │ └── run-benchmark.js │ │ │ │ │ └── tests/ │ │ │ │ │ ├── benchmark.config.ts │ │ │ │ │ ├── performance.spec.tsx │ │ │ │ │ └── test.md │ │ │ │ ├── __tests__/ │ │ │ │ │ ├── AnimationText.test.tsx │ │ │ │ │ ├── DebugPanel.test.tsx │ │ │ │ │ ├── Parser.test.ts │ │ │ │ │ ├── Renderer.test.ts │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ ├── DebugPanel.test.tsx.snap │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ ├── hooks.test.tsx │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── core/ │ │ │ │ │ ├── Parser.ts │ │ │ │ │ ├── Renderer.ts │ │ │ │ │ ├── detectUnclosedComponentTags.ts │ │ │ │ │ └── index.ts │ │ │ │ ├── hooks/ │ │ │ │ │ ├── index.ts │ │ │ │ │ └── useStreaming.ts │ │ │ │ ├── index.css │ │ │ │ ├── index.tsx │ │ │ │ ├── interface.ts │ │ │ │ └── utils/ │ │ │ │ └── tail.ts │ │ │ ├── index.ts │ │ │ ├── plugins/ │ │ │ │ ├── Latex/ │ │ │ │ │ ├── __tests__/ │ │ │ │ │ │ ├── __snapshots__/ │ │ │ │ │ │ │ └── index.test.tsx.snap │ │ │ │ │ │ └── index.test.tsx │ │ │ │ │ └── index.ts │ │ │ │ ├── type.ts │ │ │ │ └── version/ │ │ │ │ └── index.ts │ │ │ ├── themes/ │ │ │ │ ├── dark.css │ │ │ │ └── light.css │ │ │ └── version/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── dekko/ │ │ │ │ ├── dist.test.ts │ │ │ │ ├── index.test.ts │ │ │ │ └── lib.test.ts │ │ │ ├── setup.ts │ │ │ └── setupAfterEnv.ts │ │ ├── tsconfig.json │ │ └── typings/ │ │ ├── custom-typings.d.ts │ │ ├── index.d.ts │ │ └── jest.d.ts │ ├── x-sdk/ │ │ ├── .fatherrc.ts │ │ ├── .jest.js │ │ ├── BUG_VERSIONS.json │ │ ├── LICENSE │ │ ├── README-zh_CN.md │ │ ├── README.md │ │ ├── mako.config.json │ │ ├── package.json │ │ ├── scripts/ │ │ │ └── generate-version.ts │ │ ├── src/ │ │ │ ├── _util/ │ │ │ │ └── type.ts │ │ │ ├── chat-providers/ │ │ │ │ ├── AbstractChatProvider.ts │ │ │ │ ├── DeepSeekChatProvider.ts │ │ │ │ ├── DefaultChatProvider.ts │ │ │ │ ├── OpenAIChatProvider.ts │ │ │ │ ├── __test__/ │ │ │ │ │ └── providers.test.ts │ │ │ │ ├── index.ts │ │ │ │ └── types/ │ │ │ │ └── model.ts │ │ │ ├── index.ts │ │ │ ├── version/ │ │ │ │ └── index.ts │ │ │ ├── x-chat/ │ │ │ │ ├── __test__/ │ │ │ │ │ ├── index.test.tsx │ │ │ │ │ ├── store.test.ts │ │ │ │ │ └── useSyncState.test.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── store.ts │ │ │ │ └── useSyncState.ts │ │ │ ├── x-conversations/ │ │ │ │ ├── __test__/ │ │ │ │ │ └── index.test.tsx │ │ │ │ ├── index.ts │ │ │ │ └── store.ts │ │ │ ├── x-mcp-client/ │ │ │ │ ├── __test__/ │ │ │ │ │ └── index.test.ts │ │ │ │ └── index.ts │ │ │ ├── x-request/ │ │ │ │ ├── __test__/ │ │ │ │ │ ├── abort.test.ts │ │ │ │ │ ├── index.test.ts │ │ │ │ │ └── x-fetch.test.tsx │ │ │ │ ├── index.ts │ │ │ │ └── x-fetch.ts │ │ │ └── x-stream/ │ │ │ ├── __test__/ │ │ │ │ └── index.test.ts │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── dekko/ │ │ │ │ ├── dist.test.ts │ │ │ │ ├── index.test.ts │ │ │ │ └── lib.test.ts │ │ │ ├── index.test.ts │ │ │ ├── setup-streams.ts │ │ │ ├── setup.ts │ │ │ └── utils.tsx │ │ ├── tsconfig.json │ │ └── typings/ │ │ ├── custom-typings.d.ts │ │ ├── index.d.ts │ │ └── jest.d.ts │ └── x-skill/ │ ├── .claude-plugin/ │ │ └── marketplace.json │ ├── .fatherrc.ts │ ├── .gitignore │ ├── .skill.json │ ├── LICENSE │ ├── README-zh_CN.md │ ├── README.md │ ├── package.json │ ├── scripts/ │ │ ├── config.ts │ │ ├── dekko.ts │ │ ├── generate-meta.ts │ │ ├── generate-version.ts │ │ ├── skillApi.ts │ │ └── typings/ │ │ └── custom-typings.d.ts │ ├── skills/ │ │ ├── use-x-chat/ │ │ │ ├── SKILL.md │ │ │ └── reference/ │ │ │ ├── API.md │ │ │ ├── CORE.md │ │ │ └── EXAMPLES.md │ │ ├── x-chat-provider/ │ │ │ ├── SKILL.md │ │ │ └── reference/ │ │ │ └── EXAMPLES.md │ │ ├── x-markdown/ │ │ │ ├── SKILL.md │ │ │ └── reference/ │ │ │ ├── API.md │ │ │ ├── CORE.md │ │ │ ├── EXTENSIONS.md │ │ │ └── STREAMING.md │ │ └── x-request/ │ │ ├── SKILL.md │ │ └── reference/ │ │ ├── API.md │ │ ├── CORE.md │ │ └── EXAMPLES_SERVICE_PROVIDER.md │ ├── skills-zh/ │ │ ├── use-x-chat/ │ │ │ ├── SKILL.md │ │ │ └── reference/ │ │ │ ├── API.md │ │ │ ├── CORE.md │ │ │ └── EXAMPLES.md │ │ ├── x-chat-provider/ │ │ │ ├── SKILL.md │ │ │ └── reference/ │ │ │ └── EXAMPLES.md │ │ ├── x-markdown/ │ │ │ ├── SKILL.md │ │ │ └── reference/ │ │ │ ├── API.md │ │ │ ├── CORE.md │ │ │ ├── EXTENSIONS.md │ │ │ └── STREAMING.md │ │ └── x-request/ │ │ ├── SKILL.md │ │ └── reference/ │ │ ├── API.md │ │ ├── CORE.md │ │ └── EXAMPLES_SERVICE_PROVIDER.md │ ├── src/ │ │ ├── getSkillRepo.ts │ │ ├── help.ts │ │ ├── index.ts │ │ ├── locale/ │ │ │ └── index.ts │ │ └── skill-meta.json │ └── tsconfig.json ├── scripts/ │ ├── check-repo.ts │ ├── pre-publish.ts │ └── synchronize-version.ts ├── tsconfig.base.json └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .codefuse/skills/components/SKILL.md ================================================ # Ant Design X 组件开发规范指南 基于 antd 组件库最佳实践的完整开发规范,涵盖命名、架构、样式、测试等各个方面。 ## 1. 项目架构规范 ### 1.1 目录结构 ``` components/[组件名]/ ├── index.tsx # 组件入口文件 ├── [组件名].tsx # 主组件实现 ├── [子组件].tsx # 子组件实现 ├── style/ │ ├── index.ts # 样式入口 │ ├── token.ts # Token 定义 │ └── [其他样式文件].ts ├── demo/ # 示例代码 │ ├── basic.tsx # 基础示例 │ └── [其他示例].tsx ├── __tests__/ # 测试文件 │ └── index.test.tsx # 单元测试 └── index.zh-CN.md # 中文文档 ``` ### 1.2 文件命名规范 - 组件文件:PascalCase(如 `Button.tsx`) - 样式文件:camelCase(如 `buttonStyle.ts`) - 测试文件:`index.test.tsx` 或 `[组件名].test.tsx` - 示例文件:kebab-case(如 `basic.tsx`、`custom-filter.tsx`) ## 2. 命名规范与语义化 ### 2.1 组件命名 - **完整名称**:使用完整单词,避免缩写 - **PascalCase**:组件名使用大驼峰命名 - **语义化**:名称应准确描述组件功能 ```typescript // ✅ 正确 interface ButtonProps {} interface TypographyTextProps {} // ❌ 错误 interface BtnProps {} // 缩写 interface TxtProps {} // 缩写 interface MyComponentProps {} // 语义不清 ``` ### 2.2 Props 命名规范 #### 基础属性 - **类型属性**:`type`(如 `type="primary"`) - **状态属性**:`disabled`、`loading`、`open` - **尺寸属性**:`size`(`large` | `middle` | `small`) - **默认值**:`default` + 属性名(如 `defaultValue`) #### 功能属性 - **可编辑**:`editable`(布尔或配置对象) - **可复制**:`copyable`(布尔或配置对象) - **可展开**:`expandable`(布尔或配置对象) #### 事件属性 - **触发事件**:`on` + 事件名(如 `onClick`、`onChange`) - **子组件事件**:`on` + 子组件名 + 事件名(如 `onPanelClick`) - **前置事件**:`before` + 事件名(如 `beforeUpload`) - **后置事件**:`after` + 事件名(如 `afterClose`) ### 2.3 CSS 类名规范 ```typescript // 组件前缀 const prefixCls = getPrefixCls('button', customizePrefixCls); // 状态类名 `${prefixCls}-${type}` // 类型类名 `${prefixCls}-disabled` // 禁用状态 `${prefixCls}-loading` // 加载状态 `${prefixCls}-${sizeCls}` // 尺寸类名 // 组合类名 `${prefixCls}-icon-only` // 仅图标按钮 `${prefixCls}-two-chinese-chars`; // 中文字符间距 ``` ## 3. TypeScript 类型设计 ### 3.1 Props 接口定义 ```typescript // 基础 Props 接口 export interface ButtonProps extends React.ButtonHTMLAttributes { // 类型定义 type?: 'primary' | 'default' | 'dashed' | 'text' | 'link'; size?: 'large' | 'middle' | 'small'; // 状态控制 loading?: boolean | { delay?: number }; disabled?: boolean; // 内容相关 icon?: React.ReactNode; children?: React.ReactNode; // 样式相关 className?: string; style?: React.CSSProperties; // 事件处理 onClick?: (event: React.MouseEvent) => void; } // 配置对象类型 export interface CopyConfig { text?: string | (() => string | Promise); onCopy?: (event?: React.MouseEvent) => void; icon?: React.ReactNode; tooltips?: React.ReactNode; format?: 'text/plain' | 'text/html'; } ``` ### 3.2 泛型组件设计 ```typescript // 泛型组件支持不同元素类型 export interface BlockProps< C extends keyof JSX.IntrinsicElements = keyof JSX.IntrinsicElements, > extends TypographyProps { component?: C; // 其他属性... } // 使用示例 const Base = React.forwardRef((props, ref) => { const { component = 'div' as C, ...rest } = props; return React.createElement(component, rest); }); ``` ### 3.3 类型安全实践 ```typescript // 使用联合类型而非 enum type ButtonType = 'primary' | 'default' | 'dashed' | 'text' | 'link'; // 使用 as const 定义常量 const BUTTON_TYPES = ['primary', 'default', 'dashed', 'text', 'link'] as const; // 精确的类型定义 interface EllipsisConfig { rows?: number; expandable?: boolean | 'collapsible'; suffix?: string; symbol?: React.ReactNode | ((expanded: boolean) => React.ReactNode); } ``` ## 4. 组件架构模式 ### 4.1 复合组件模式 ```typescript // 主组件 const Button = React.forwardRef((props, ref) => { // 实现... }); // 子组件 Button.Group = ButtonGroup; Button.__ANT_BUTTON = true; // 使用 ``` ### 4.2 配置合并模式 ```typescript // 使用 useMergedConfig 合并布尔值和配置对象 const [enableEdit, editConfig] = useMergedConfig(editable); // 实现 useMergedConfig function useMergedConfig(config: boolean | T): [boolean, T] { const enable = Boolean(config); const mergedConfig = React.useMemo(() => { if (config === true) return {} as T; if (config === false) return {} as T; return config || ({} as T); }, [config]); return [enable, mergedConfig]; } ``` ### 4.3 受控与非受控模式 ```typescript // 使用 useControlledState 处理受控/非受控状态 const [editing, setEditing] = useControlledState(false, editConfig.editing); // useControlledState 实现 function useControlledState(defaultValue: T, controlledValue?: T): [T, (value: T) => void] { const [internalValue, setInternalValue] = React.useState(defaultValue); const isControlled = controlledValue !== undefined; const value = isControlled ? controlledValue : internalValue; const setValue = React.useCallback( (newValue: T) => { if (!isControlled) { setInternalValue(newValue); } }, [isControlled], ); return [value, setValue]; } ``` ## 5. 样式系统规范 ### 5.1 CSS-in-JS 架构 ```typescript // Token 定义 export interface ComponentToken { // 颜色相关 colorPrimary?: string; colorBgContainer?: string; // 尺寸相关 controlHeight?: number; controlHeightSM?: number; controlHeightLG?: number; // 间距相关 padding?: number; paddingSM?: number; paddingLG?: number; } // 样式生成函数 const genButtonStyle = (token: ButtonToken): CSSInterpolation => { return [ // 基础样式 genSharedButtonStyle(token), // 尺寸样式 genSizeBaseButtonStyle(token), genSizeSmallButtonStyle(token), genSizeLargeButtonStyle(token), // 变体样式 genVariantStyle(token), ]; }; // 样式导出 export default genStyleHooks('Button', genButtonStyle, prepareComponentToken, { unitless: { fontWeight: true }, }); ``` ### 5.2 响应式设计 ```typescript // 使用 CSS 逻辑属性支持 RTL const styles = { marginInlineStart: token.marginXS, // 替代 marginLeft marginInlineEnd: token.marginXS, // 替代 marginRight paddingBlock: token.paddingSM, // 替代 paddingTop/paddingBottom paddingInline: token.paddingSM, // 替代 paddingLeft/paddingRight }; // 响应式断点 const responsiveStyles = { [token.screenXS]: { fontSize: token.fontSizeSM, }, [token.screenMD]: { fontSize: token.fontSize, }, [token.screenLG]: { fontSize: token.fontSizeLG, }, }; ``` ### 5.3 主题定制支持 ```typescript // 支持 ConfigProvider 主题定制 const { getPrefixCls, direction } = React.useContext(ConfigContext); const prefixCls = getPrefixCls('button', customizePrefixCls); // 支持语义化 className 和 style export interface ButtonSemanticClassNames { root?: string; icon?: string; content?: string; } export interface ButtonSemanticStyles { root?: React.CSSProperties; icon?: React.CSSProperties; content?: React.CSSProperties; } ``` ## 6. 可访问性规范 ### 6.1 ARIA 属性 ```typescript // 正确的 ARIA 属性使用 // 键盘导航支持 const handleKeyDown = (event: React.KeyboardEvent) => { switch (event.key) { case 'Enter': case ' ': event.preventDefault(); handleClick(); break; case 'Escape': handleCancel(); break; } }; ``` ### 6.2 焦点管理 ```typescript // 焦点状态样式 const focusStyles = { '&:focus-visible': { outline: `${token.lineWidthFocus}px solid ${token.colorPrimaryBorder}`, outlineOffset: 1, }, }; // 程序化焦点管理 const buttonRef = React.useRef(null); React.useEffect(() => { if (autoFocus && buttonRef.current) { buttonRef.current.focus(); } }, [autoFocus]); ``` ## 7. 性能优化规范 ### 7.1 React 优化 ```typescript // 使用 React.memo 避免不必要的重渲染 const Button = React.memo( React.forwardRef((props, ref) => { // 组件实现 }), ); // 使用 useMemo 缓存计算结果 const classes = React.useMemo(() => { return clsx(prefixCls, `${prefixCls}-${type}`, `${prefixCls}-${size}`, className); }, [prefixCls, type, size, className]); // 使用 useCallback 缓存函数 const handleClick = React.useCallback( (event: React.MouseEvent) => { if (!disabled && !loading) { onClick?.(event); } }, [disabled, loading, onClick], ); ``` ### 7.2 样式优化 ```typescript // 避免不必要的样式重计算 const useStyle = genStyleHooks( 'Button', (token) => { // 样式计算逻辑 }, prepareComponentToken, ); // 使用 CSS containment const containerStyles = { contain: 'layout style paint', contentVisibility: 'auto', }; ``` ## 8. 测试规范 ### 8.1 测试文件结构 ```typescript // __tests__/index.test.tsx import React from 'react'; import { render, screen, fireEvent } from '@testing-library/react'; import Button from '../index'; describe('Button', () => { it('should render correctly', () => { const { container } = render(); expect(container.firstChild).toMatchSnapshot(); }); it('should handle click events', () => { const handleClick = jest.fn(); render(); fireEvent.click(screen.getByText('Click me')); expect(handleClick).toHaveBeenCalledTimes(1); }); it('should be disabled when disabled prop is true', () => { render(); expect(screen.getByText('Disabled')).toBeDisabled(); }); }); ``` ### 8.2 测试覆盖率要求 - 单元测试覆盖率:100% - 集成测试:主要使用场景 - 可访问性测试:键盘导航、屏幕阅读器 - 视觉回归测试:UI 变化检测 ## 9. 文档规范 ### 9.1 API 文档格式 ```markdown | 参数 | 说明 | 类型 | 默认值 | | -------- | ---------------- | ------------------------------------------------------ | --------- | | type | 设置按钮类型 | `primary` \| `default` \| `dashed` \| `text` \| `link` | `default` | | size | 设置按钮大小 | `large` \| `middle` \| `small` | `middle` | | disabled | 按钮失效状态 | boolean | false | | loading | 设置按钮载入状态 | boolean \| { delay: number } | false | | onClick | 点击按钮时的回调 | (event) => void | - | ``` ### 9.2 示例代码规范 ```typescript // demo/basic.tsx import React from 'react'; import { Button } from 'antd'; const App: React.FC = () => ( <> ); export default App; ``` ## 10. 国际化规范 ### 10.1 本地化配置 ```typescript // locale/zh_CN.ts export default { Text: { edit: '编辑', copy: '复制', copied: '复制成功', expand: '展开', collapse: '收起', }, }; // 使用 useLocale 获取本地化 const [textLocale] = useLocale('Text', enUS.Text); ``` ### 10.2 动态文本处理 ```typescript // 支持模板变量的本地化 const messages = { selected: '已选择 ${count} 项', }; // 使用 const message = messages.selected.replace('${count}', count.toString()); ``` ## 11. 版本兼容规范 ### 11.1 向下兼容 - 避免破坏性变更 - 提供迁移指南 - 保持 API 稳定性 - 使用废弃警告 ```typescript // 废弃警告 if (process.env.NODE_ENV !== 'production') { const warning = devUseWarning('Button'); warning.deprecated(!iconPosition, 'iconPosition', 'iconPlacement'); } ``` ### 11.2 浏览器兼容 - 支持 Chrome 80+ - 支持服务端渲染 - 支持 TypeScript 4.0+ - 支持 React 18 ~ 19 ## 12. 发布规范 ### 12.1 版本管理 - 遵循语义化版本(SemVer) - 主版本:破坏性变更 - 次版本:新功能 - 修订版本:Bug 修复 ### 12.2 变更日志 ```markdown ## 5.0.0 ### 重大变更 - 移除废弃的 `icon` 字符串用法 - 重构样式系统,使用 CSS-in-JS ### 新功能 - 新增 `variant` 属性支持多种按钮变体 - 新增语义化 className 和 style 支持 ### Bug 修复 - 修复按钮在 disabled 状态下仍可点击的问题 ``` --- 这套规范基于 antd 组件库的最佳实践,涵盖了从项目结构到发布流程的完整开发规范。遵循这些规范可以确保组件的一致性、可维护性和高质量。 ================================================ FILE: .editorconfig ================================================ # top-most EditorConfig file root = true # Unix-style newlines with a newline ending every file [*.{js,css}] end_of_line = lf insert_final_newline = true indent_style = space indent_size = 2 ================================================ FILE: .github/FUNDING.yml ================================================ # These are supported funding model platforms github: ant-design # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] patreon: # Replace with a single Patreon username open_collective: ant-design # Replace with a single Open Collective username ko_fi: # Replace with a single Ko-fi username tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry polar: # Replace with a single Polar username buy_me_a_coffee: # Replace with a single Buy Me a Coffee username thanks_dev: # Replace with a single thanks.dev username custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.yml ================================================ name: 错误报告 🐛 description: 提交一个 @ant-design/x 的 bug labels: ['bug'] body: - type: markdown attributes: value: 感谢您的贡献!❤️ 请在上方写一个易于搜索的标题 ⬆️。 validations: required: true - type: textarea attributes: label: 重现步骤 description: | **⚠️ 我们无法重现的问题是无法修复的。** 请提供一个在线示例的链接和一组明确的步骤来重现这个错误。请参阅我们的[文档](https://github.com/ant-design/ant-design/wiki/%E4%BB%80%E4%B9%88%E6%98%AF%E6%9C%80%E5%B0%8F%E5%8C%96%E9%87%8D%E7%8E%B0%EF%BC%8C%E4%B8%BA%E4%BB%80%E4%B9%88%E8%BF%99%E6%98%AF%E5%BF%85%E9%9C%80%E7%9A%84%EF%BC%9F)了解如何构建重现案例。 value: | 在线示例链接:(必填) 步骤: 1. 2. 3. - type: textarea attributes: label: 当前行为 description: 描述实际发生的情况,而不是预期行为。 - type: textarea attributes: label: 预期行为 description: 描述应该发生的情况。 - type: textarea attributes: label: 上下文 description: 您想要完成什么?提供背景有助于我们提出在现实世界中更有用的解决方案。 - type: input id: version attributes: label: 版本 description: 使用的 @ant-design/x 版本是多少? validations: required: true - type: dropdown id: browsers attributes: label: 您在哪些浏览器上遇到了这个问题? multiple: true options: - Firefox - Chrome - Safari - Microsoft Edge - 其他 ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.yml ================================================ name: 功能请求 💄 description: 我想给 @ant-design/x 加个新功能 labels: ['feature request'] body: - type: markdown attributes: value: 感谢您的贡献!❤️ 请在上方写一个易于搜索的标题 ⬆️。 - type: textarea attributes: label: 需求动机 description: 要解决什么问题?提供背景有助于我们提出在现实世界中更有用的解决方案。 - type: textarea attributes: label: 提议的 API 是什么样的? description: 描述您希望用什么样的 API 来解决这个问题,可以写一个具体的 markdown 代码块示例。 ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ [中文版模板 / Chinese template](https://github.com/ant-design/x/blob/master/.github/PULL_REQUEST_TEMPLATE_CN.md?plain=1) ### 🤔 This is a ... - [ ] 🆕 New feature - [ ] 🐞 Bug fix - [ ] 📝 Site / documentation improvement - [ ] 📽️ Demo improvement - [ ] 💄 Component style improvement - [ ] 🤖 TypeScript definition improvement - [ ] 📦 Bundle size optimization - [ ] ⚡️ Performance optimization - [ ] ⭐️ Feature enhancement - [ ] 🌐 Internationalization - [ ] 🛠 Refactoring - [ ] 🎨 Code style optimization - [ ] ✅ Test Case - [ ] 🔀 Branch merge - [ ] ⏩ Workflow - [ ] ⌨️ Accessibility improvement - [ ] ❓ Other (about what?) ### 🔗 Related Issues > - Describe the source of related requirements, such as links to relevant issue discussions. > - For example: close #xxxx, fix #xxxx ### 💡 Background and Solution > - The specific problem to be addressed. > - List the final API implementation and usage if needed. > - If there are UI/interaction changes, consider providing screenshots or GIFs. ### 📝 Change Log > - Read [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) like a cat tracks a laser pointer. > - Describe the impact of the changes on developers, not the solution approach. > - Reference: https://x.ant.design/changelog | Language | Changelog | | ---------- | --------- | | 🇺🇸 English | | | 🇨🇳 Chinese | | ================================================ FILE: .github/PULL_REQUEST_TEMPLATE_CN.md ================================================ [English Template / 英文模板](https://github.com/ant-design/x/blob/master/.github/PULL_REQUEST_TEMPLATE.md?plain=1) ### 🤔 这个变动的性质是? - [ ] 🆕 新特性提交 - [ ] 🐞 Bug 修复 - [ ] 📝 站点、文档改进 - [ ] 📽️ 演示代码改进 - [ ] 💄 组件样式/交互改进 - [ ] 🤖 TypeScript 定义更新 - [ ] 📦 包体积优化 - [ ] ⚡️ 性能优化 - [ ] ⭐️ 功能增强 - [ ] 🌐 国际化改进 - [ ] 🛠 重构 - [ ] 🎨 代码风格优化 - [ ] ✅ 测试用例 - [ ] 🔀 分支合并 - [ ] ⏩ 工作流程 - [ ] ⌨️ 无障碍改进 - [ ] ❓ 其他改动(是关于什么的改动?) ### 🔗 相关 Issue > 1. 描述相关需求的来源,如相关的 issue 讨论链接。 > 2. 例如 close #xxxx、 fix #xxxx ### 💡 需求背景和解决方案 > 1. 要解决的具体问题。 > 2. 列出最终的 API 实现和用法。 > 3. 涉及UI/交互变动建议提供截图或 GIF。 ### 📝 更新日志 > - 郑重地阅读 [如何维护更新日志](https://keepachangelog.com/zh-CN/1.1.0/) > - 描述改动对开发者有哪些影响,而非解决方式 > - 可参考:https://x.ant.design/changelog-cn | 语言 | 更新描述 | | ------- | -------- | | 🇺🇸 英文 | | | 🇨🇳 中文 | | ================================================ FILE: .github/dependabot.yml ================================================ # To get started with Dependabot version updates, you'll need to specify which # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates version: 2 updates: - package-ecosystem: npm directory: / schedule: interval: weekly day: monday time: '10:00' timezone: Asia/Shanghai ignore: - dependency-name: '@ant-design/cssinjs' - dependency-name: dayjs versions: [1.x] - package-ecosystem: github-actions directory: / schedule: interval: monthly labels: - github-actions - dependencies - skip-verify-files ================================================ FILE: .github/workflows/main.yml ================================================ name: ✅ test on: [push, pull_request] permissions: contents: read jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: utooland/setup-utoo@v1 - run: ut install --ignore-scripts - run: ut prestart - run: ut lint - run: ut tsc - run: ut compile - run: ut coverage - run: ut test:dekko - uses: codecov/codecov-action@v5 with: directories: packages/x,packages/x-markdown,packages/x-sdk token: ${{ secrets.CODECOV_TOKEN }} ================================================ FILE: .github/workflows/markdown-benchmark.yml ================================================ name: Markdown Performance on: pull_request: paths: - 'packages/x-markdown/**' push: paths: - 'packages/x-markdown/**' workflow_dispatch: permissions: contents: read pull-requests: write checks: write jobs: benchmark: name: Performance BenchMark runs-on: ubuntu-latest timeout-minutes: 30 steps: - name: Checkout code uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: '18' - name: Install dependencies run: npm install - name: Setup Playwright run: | cd packages/x-markdown npx playwright install --with-deps chromium - name: Run x-markdown benchmark id: benchmark run: | cd packages/x-markdown npm run benchmark - name: Check performance against thresholds id: check run: | cd packages/x-markdown node src/XMarkdown/__benchmark__/scripts/check-performance.js \ test-results/benchmark-results.json \ benchmark-check-report.txt - name: Comment PR with results if: | github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository uses: actions/github-script@v8 with: script: | const fs = require('fs'); const path = 'packages/x-markdown/src/XMarkdown/__benchmark__/benchmark-check-report.txt'; let report = '⚠️ Performance benchmark report not found.'; if (fs.existsSync(path)) { report = fs.readFileSync(path, 'utf8'); } const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, }); const botComment = comments.find(comment => comment.user.type === 'Bot' && comment.body.includes('📊 x-markdown Performance Report') ); const commentBody = report + '\n\n---\n*This comment is automatically generated by the x-markdown performance CI.*'; if (botComment) { await github.rest.issues.updateComment({ owner: context.repo.owner, repo: context.repo.repo, comment_id: botComment.id, body: commentBody }); } else { await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: commentBody }); } ================================================ FILE: .github/workflows/pr-auto-merge.yml ================================================ # Used to merge master/feature branches with each other name: PR Auto Merge Bot on: schedule: - cron: '*/5 * * * *' permissions: contents: read jobs: pr-check-ci: if: github.repository == 'ant-design/x' permissions: checks: read # for actions-cool/check-pr-ci to get check reference contents: write # for actions-cool/check-pr-ci to merge PRs issues: write # for actions-cool/check-pr-ci to update issues pull-requests: write # for actions-cool/check-pr-ci to update PRs runs-on: ubuntu-latest steps: - uses: actions-cool/check-pr-ci@v1 with: filter-label: BranchAutoMerge filter-creator-authority: write filter-head-ref: 'main, feature, next, main-merge-feature, feature-merge-main, next-merge-main, next-merge-feature' filter-support-fork: false skip-run-names: 'deploy preview, pr-check-ci, upstream workflow summary, suggest-related-links, download visual-regression report' conflict-review-body: 😅 This branch has conflicts that must be resolved! success-review: true success-merge: true merge-method: merge merge-title: 'chore: auto merge branches (#${number})' ================================================ FILE: .github/workflows/pr-contributor-welcome.yml ================================================ # 当 PR 被合并时,留言欢迎加入共建群 name: PullRequest Contributor Welcome on: pull_request_target: types: - closed paths: - 'packages/**' permissions: contents: read jobs: comment: permissions: issues: write # for actions-cool/maintain-one-comment to modify or create issue comments pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments if: github.event.pull_request.merged == true && github.repository == 'ant-design/x' runs-on: ubuntu-latest steps: - name: get commit count id: get_commit_count run: | PR_AUTHOR=$(echo "${{ github.event.pull_request.user.login }}") RESULT_DATA=$(curl -s "https://api.github.com/repos/${{ github.repository }}/commits?author=${PR_AUTHOR}&per_page=5") DATA_LENGTH=$(echo $RESULT_DATA | jq 'if type == "array" then length else 0 end') echo "COUNT=$DATA_LENGTH" >> $GITHUB_OUTPUT - name: Comment on PR if: steps.get_commit_count.outputs.COUNT < 3 uses: actions-cool/maintain-one-comment@v3 with: token: ${{ secrets.GITHUB_TOKEN }} body: | 🎉 Thank you for your contribution! If you have not yet joined our DingTalk community group, please feel free to join us (when joining, please provide the link to this PR). 🎉 感谢您的贡献!如果您还没有加入钉钉社区群,请扫描下方二维码加入我们(加群时请提供此 PR 链接)。 Thank you for your contribution! body-include: ================================================ FILE: .github/workflows/preview-build.yml ================================================ # Each PR will build preview site that help to check code is work as expect. name: Preview Build on: pull_request: types: [opened, synchronize, reopened] # Cancel prev CI if new commit come concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read jobs: build-site: name: build preview runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: utooland/setup-utoo@v1 - run: ut - run: ut prestart --workspaces - name: ut site id: site run: ut site --workspace packages/x env: NODE_OPTIONS: '--max_old_space_size=4096' - name: upload site artifact uses: actions/upload-artifact@v7 with: name: site path: packages/x/_site/ retention-days: 5 # Upload PR id for next workflow use - name: Save PR number if: ${{ always() }} run: echo ${{ github.event.number }} > ./pr-id.txt - name: Upload PR number if: ${{ always() }} uses: actions/upload-artifact@v7 with: name: pr path: ./pr-id.txt ================================================ FILE: .github/workflows/preview-deploy.yml ================================================ # Each PR will build preview site that help to check code is work as expect. name: Preview Deploy on: workflow_run: workflows: ['Preview Build'] types: - completed permissions: contents: read actions: read jobs: upstream-workflow-summary: name: upstream workflow summary runs-on: ubuntu-latest if: github.event.workflow_run.event == 'pull_request' outputs: jobs: ${{ steps.prep-summary.outputs.result }} build-success: ${{ steps.prep-summary.outputs.build-success }} build-failure: ${{ steps.prep-summary.outputs.build-failure }} steps: - name: summary jobs status uses: actions/github-script@v8 id: prep-summary with: script: | const response = await github.rest.actions.listJobsForWorkflowRun({ owner: context.repo.owner, repo: context.repo.repo, run_id: ${{ github.event.workflow_run.id }}, }); // { [name]: [conclusion] }, e.g. { 'build preview': 'success' } const jobs = (response.data?.jobs ?? []).reduce((acc, job) => { if(job?.status === 'completed' && 'name' in job && 'conclusion' in job) { acc[job.name] = job.conclusion; } return acc; }, {}); const total = Object.keys(jobs).length; if(total === 0) core.setFailed('no jobs found'); // the name here must be the same as `jobs.xxx.{name}` in preview-build.yml // set output core.setOutput('build-success', jobs['build preview'] === 'success'); core.setOutput('build-failure', jobs['build preview'] === 'failure'); return jobs; deploy-preview: name: deploy preview permissions: actions: read # for dawidd6/action-download-artifact to query and download artifacts issues: write # for actions-cool/maintain-one-comment to modify or create issue comments pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments runs-on: ubuntu-latest needs: upstream-workflow-summary if: github.event.workflow_run.event == 'pull_request' steps: # We need get PR id first - name: download pr artifact uses: dawidd6/action-download-artifact@v16 with: workflow: ${{ github.event.workflow_run.workflow_id }} run_id: ${{ github.event.workflow_run.id }} name: pr # Save PR id to output - name: save PR id id: pr run: | pr_id=$(> $GITHUB_OUTPUT # Download site artifact - name: download site artifact if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-success) }} uses: dawidd6/action-download-artifact@v16 with: workflow: ${{ github.event.workflow_run.workflow_id }} run_id: ${{ github.event.workflow_run.id }} name: site - name: upload surge service id: deploy continue-on-error: true env: PR_ID: ${{ steps.pr.outputs.id }} run: | export DEPLOY_DOMAIN=https://preview-${PR_ID}-antd-x.surge.sh npx surge --project ./ --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }} - name: success comment uses: actions-cool/maintain-one-comment@v3 if: ${{ steps.deploy.outcome == 'success' }} with: token: ${{ secrets.GITHUB_TOKEN }} body: | [Preview is ready](https://preview-${{ steps.pr.outputs.id }}-antd-x.surge.sh) body-include: '' number: ${{ steps.pr.outputs.id }} - name: failed comment if: ${{ fromJSON(needs.upstream-workflow-summary.outputs.build-failure) || steps.deploy.outcome == 'failure' || failure() }} uses: actions-cool/maintain-one-comment@v3 with: token: ${{ secrets.GITHUB_TOKEN }} body: | [Preview failed](https://preview-${{ steps.pr.outputs.id }}-antd-x.surge.sh) body-include: '' number: ${{ steps.pr.outputs.id }} ================================================ FILE: .github/workflows/preview-start.yml ================================================ # When `preview-build` start. Leave a message on the PR # # 🚨🚨🚨 Important 🚨🚨🚨 # Never do any `checkout` or `npm install` action! # `pull_request_target` will enable PR to access the secrets! name: Preview Start on: pull_request_target: types: [opened, synchronize, reopened] permissions: contents: read jobs: preview-start: permissions: issues: write # for actions-cool/maintain-one-comment to modify or create issue comments pull-requests: write # for actions-cool/maintain-one-comment to modify or create PR comments name: start preview info runs-on: ubuntu-latest steps: - name: update status comment uses: actions-cool/maintain-one-comment@v3 with: token: ${{ secrets.GITHUB_TOKEN }} body: | [Prepare preview](https://preview-${{ github.event.number }}-ant-design.surge.sh) body-include: '' ================================================ FILE: .github/workflows/release-dingtalk.yml ================================================ name: DingTalk Release Notification on: create permissions: contents: read jobs: release-helper: permissions: contents: write # for actions-cool/release-helper to create releases if: github.event.ref_type == 'tag' runs-on: ubuntu-latest steps: - name: Send to Ant Design X DingGroup uses: actions-cool/release-helper@v2 with: trigger: tag changelogs: 'CHANGELOG.en-US.md, CHANGELOG.zh-CN.md' branch: 'main' tag: '2*' latest: '2*' dingding-token: ${{ secrets.DINGDING_BOT_TOKEN }} ${{ secrets.DINGDING_BOT_INTERNAL_TOKEN }} ${{ secrets.DINGDING_BOT_XMARKDOWN_TOKEN }} dingding-msg: CHANGELOG.zh-CN.md msg-title: '# Ant Design X {{v}} 发布日志' msg-poster: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*kjHUSYIdsnUAAAAAAAAAAAAADgCCAQ/original' msg-footer: '💬 前往 [**Ant Design X Releases**]({{url}}) 查看更新日志' prettier: true prerelease-filter: '-, a, b, A, B' ================================================ FILE: .github/workflows/release-x.yml ================================================ name: 🆇 Release to X on: create jobs: tweet: runs-on: ubuntu-latest if: ${{ github.event.ref_type == 'tag' && !contains(github.event.ref, 'alpha') }} steps: - name: Tweet uses: nearform-actions/github-action-notify-twitter@master with: message: | 𝕏 Ant Design X just released @ant-design/x@${{ github.event.ref }} ✨🎊✨ Check out the full release note: https://github.com/ant-design/x/releases/tag/${{ github.event.ref }} twitter-app-key: ${{ secrets.TWITTER_API_KEY }} twitter-app-secret: ${{ secrets.TWITTER_API_SECRET }} twitter-access-token: ${{ secrets.TWITTER_ACCESS_TOKEN }} twitter-access-token-secret: ${{ secrets.TWITTER_ACCESS_TOKEN_SECRET }} ================================================ FILE: .github/workflows/site-deploy.yml ================================================ # When pushing a tag. this workflow will trigger site deployment and fixed version address comments name: Deploy website on: push: tags: - '2.*' workflow_dispatch: permissions: contents: write jobs: build-and-deploy: runs-on: ubuntu-latest if: (startsWith(github.ref, 'refs/tags/') && (contains(github.ref_name, '-') == false)) || github.event_name == 'workflow_dispatch' steps: - name: checkout uses: actions/checkout@v6 - uses: utooland/setup-utoo@v1 - run: ut - name: build site run: ut run predeploy env: NODE_OPTIONS: --max_old_space_size=4096 - name: build dist and bundle analyzer report run: ut compile env: ANALYZER: 1 NODE_OPTIONS: --max_old_space_size=4096 - name: Get version id: publish-version run: echo "VERSION=$(echo ${{ github.ref_name }} | sed 's/\./-/g')" >> $GITHUB_OUTPUT - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v4 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./_site force_orphan: true # Since force_orphan will not trigger Sync to Gitee, we need to force run it here - name: Sync to Gitee uses: wearerequired/git-mirror-action@v1 env: SSH_PRIVATE_KEY: ${{ secrets.GITEE_SSH_PRIVATE_KEY }} with: source-repo: 'git@github.com:ant-design/x.git' destination-repo: 'git@gitee.com:ant-design/antd-x.git' - name: Deploy to Surge (with TAG) working-directory: ./packages/x run: | export DEPLOY_DOMAIN=ant-design-x-${{ steps.publish-version.outputs.VERSION }}.surge.sh npx surge --project ./_site --domain $DEPLOY_DOMAIN --token ${{ secrets.SURGE_TOKEN }} - name: Create Commit Comment uses: peter-evans/commit-comment@v4 with: body: | - Documentation site for this release: https://ant-design-x-${{ steps.publish-version.outputs.VERSION }}.surge.sh ================================================ FILE: .github/workflows/size-limit.yml ================================================ name: 📦 Size Limit on: pull_request: types: [opened, synchronize] permissions: issues: write contents: read jobs: size: permissions: contents: read pull-requests: write runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 - name: size-limit uses: ant-design/size-limit-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} package_manager: npm build_script: compile ================================================ FILE: .gitignore ================================================ *.iml .idea/ .ipr .iws *~ ~* *.diff *.patch *.bak .DS_Store Thumbs.db .project .*proj .svn/ *.swp *.swo *.log *.log.* *.json.gzip node_modules/ .buildpath .settings npm-debug.log nohup.out _site _data dist report.html lib bin es elasticsearch-* config/base.yaml /.vscode/ coverage yarn.lock package-lock.json bun.lock bun.lockb pnpm-lock.yaml bun.lockb .pnpm-debug.log packages/*/components/**/*.js packages/*/components/**/*.jsx !packages/*/components/**/__tests__/**/*.js !packages/*/components/**/__tests__/**/*.js.snap /.history *.tmp artifacts.zip oss-artifacts.zip server/ packages/*/.dumi/tmp packages/*/.dumi/tmp-test packages/*/.dumi/tmp-production packages/*/.dumi/preset/components-changelog* packages/*/.dumi/preset/misc-changelog.json # Image snapshot diff __diff_output__/ __image_snapshots__/ /jest-stare /imageSnapshots* /imageDiffSnapshots /visualRegressionReport* .devcontainer* .husky/prepare-commit-msg .eslintcache .node-version .node .env examples/ packages/x-markdown/plugins packages/x-markdown/themes packages/x/locale # Docs templates packages/x/scripts/previewEditor/index.html packages/x/components/version/version.ts packages/x/components/version/version.tsx packages/x/components/version/token.json packages/x/components/version/token-meta.json packages/x/components/theme/interface/XMarkdownComponents.ts packages/x-markdown/src/plugins/version/version.ts packages/x-markdown/src/plugins/version/plugin-meta.json packages/x-markdown/src/plugins/version/token-meta.json packages/x-markdown/src/plugins/version/token.json packages/x-markdown/src/version/version.ts packages/x-sdk/src/version/version.ts # Playwright (from benchmark) packages/x-markdown/test-results/ packages/x-markdown/src/XMarkdown/__benchmark__/playwright-report/ packages/x-markdown/src/XMarkdown/__benchmark__/blob-report/ packages/x-markdown/src/XMarkdown/__benchmark__/playwright/.cache/ packages/x-markdown/src/XMarkdown/__benchmark__/playwright/.auth/ packages/x-markdown/src/XMarkdown/__benchmark__/test-results ================================================ FILE: .husky/commit-msg ================================================ #!/usr/bin/env sh # npx commitlint --edit $1 ================================================ FILE: .husky/pre-commit ================================================ lint-staged ================================================ FILE: .lintstagedrc.json ================================================ { "*.{ts,tsx,js,jsx,json,css,sh}": ["biome check --write --no-errors-on-unmatched"], "*.{md,yml}": ["prettier --ignore-unknown --write"] } ================================================ FILE: .npmrc ================================================ legacy-peer-deps=true ================================================ FILE: .prettierrc ================================================ { "endOfLine": "lf", "semi": true, "singleQuote": true, "tabWidth": 2, "printWidth": 100, "proseWrap": "never", "trailingComma": "all", "jsxSingleQuote": false } ================================================ FILE: CHANGELOG.en-US.md ================================================ --- order: 6 title: Changelog toc: false timeline: true tag: vVERSION --- `@ant-design/x` follows [Semantic Versioning 2.0.0](http://semver.org/). #### Release Schedule - Weekly release: Patch version for routine bugfix. - Monthly release: minor version at the end for new features. - Major version release for breaking change and new features. --- ## 2.4.0 `2026-03-13` ### @ant-design/x - 🐛 Fix incorrect event handling in `useShortcutKeys`.[#1822](https://github.com/ant-design/x/pull/1822) by [cxybd](https://github.com/cxybd) - 🔥 New component Folder. [#1797](https://github.com/ant-design/x/pull/1797) by [kimteayon](https://github.com/kimteayon) - 🆕 Enhanced FileCard's `description`, `mask`, and `onClick` configuration capabilities. [#1807](https://github.com/ant-design/x/pull/1807) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🆕 XMarkdown streaming rendering adds `tail` configuration, supporting custom tail content and custom tail components while avoiding tail rendering before incomplete components. [#1296](https://github.com/ant-design/x/pull/1296) by [Div627](https://github.com/Div627) - 🐛 Fixed XMarkdown custom component streaming state detection to correctly handle void elements and isolate `streamStatus` across multiple instances with the same component name. [#1590](https://github.com/ant-design/x/pull/1590) by [Last-Order](https://github.com/Last-Order) - 🛠 Exported XMarkdown's `StreamCacheTokenType` type for external reuse of streaming-related types. [#1592](https://github.com/ant-design/x/pull/1592) by [Last-Order](https://github.com/Last-Order) - 📖 Added XMarkdown Playground and refreshed the streaming, examples, and data-display documentation, including the AntV Infographic example. [#1779](https://github.com/ant-design/x/pull/1779) by [Div627](https://github.com/Div627), [#1780](https://github.com/ant-design/x/pull/1780) by [Div627](https://github.com/Div627), [#1814](https://github.com/ant-design/x/pull/1814) by [Div627](https://github.com/Div627) ### @ant-design/x-skill - 🆕 Released x-markdown skill. [#1813](https://github.com/ant-design/x/pull/1813) by [Div627](https://github.com/Div627) ### Others - 🛠 Upgraded all components' useMergedState to useControlledState. [#1808](https://github.com/ant-design/x/pull/1808) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized official website to improve user experience. [#1814](https://github.com/ant-design/x/pull/1814) by [Div627](https://github.com/Div627), [#1793](https://github.com/ant-design/x/pull/1793) by [kimteayon](https://github.com/kimteayon), [#1792](https://github.com/ant-design/x/pull/1792) by [Div627](https://github.com/Div627), [#1780](https://github.com/ant-design/x/pull/1780) by [Div627](https://github.com/Div627), [#1779](https://github.com/ant-design/x/pull/1779) by [Div627](https://github.com/Div627) ## 2.3.0 `2026-02-26` ### @ant-design/x - 🆕 Conversation's onActiveChange callback now returns both the activated item and its key value, while updating useMergedState to useControlledState. [#1762](https://github.com/ant-design/x/pull/1762) by [kimteayon](https://github.com/kimteayon) - 🐛 Optimized the visual presentation of Sender's disabled state buttons, unified the addition of transparent border handling to ensure consistent appearance across different button variants when disabled. [#1751](https://github.com/ant-design/x/pull/1751) by [Rain120](https://github.com/Rain120) ### @ant-design/x-markdown - 🆕 XMarkdown adds escapeRawHtml property, allowing users to choose whether to escape raw HTML during rendering. [#1769](https://github.com/ant-design/x/pull/1769) by [Div627](https://github.com/Div627) - 🐛 Fixed XMarkdown rendering when encountering unclosed inline code in lists, ensuring list markers are preserved in special unclosed cases. [#1739](https://github.com/ant-design/x/pull/1739) by [Div627](https://github.com/Div627) - 🐛 Improved parsing of block-level LaTeX formulas, with more tolerant handling of trailing whitespace and indentation, enhancing compatibility with different line ending formats and reducing misjudgment and rendering issues. [#1744](https://github.com/ant-design/x/pull/1744) by [Waiter](https://github.com/Waiter) - 🐛 Optimized dark mode CodeHighlighter and Mermaid plugin styling issues. [#1766](https://github.com/ant-design/x/pull/1766) by [menghany](https://github.com/menghany) ### @ant-design/x-sdk - 🆕 useXChat adds queueRequest method, implementing initialization message sending for ConversationKey and SessionId. [#1761](https://github.com/ant-design/x/pull/1761) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-skill - 🆕 Added skill installation commands, simultaneously releasing three skills: use-x-chat, x-chat-provider, and x-request. [#1753](https://github.com/ant-design/x/pull/1753), [#1767](https://github.com/ant-design/x/pull/1767) by [kimteayon](https://github.com/kimteayon) ### Others - 🛠 Fixed build errors caused by dependency upgrades. [#1754](https://github.com/ant-design/x/pull/1754) by [kimteayon](https://github.com/kimteayon) - 🛠 Resolved domhandler's ModuleNotFoundError in CodeSandbox preview. [#1754](https://github.com/ant-design/x/pull/1754) by [Div627](https://github.com/Div627) ## 2.2.2 `2026-02-06` ### @ant-design/x - 🛠 Fixed some documentation and types to support AI Coding. [#1733](https://github.com/ant-design/x/pull/1733) by [kimteayon](https://github.com/kimteayon) - 💄 Fixed Bubble.List style and semantic issues. [#1731](https://github.com/ant-design/x/pull/1731) by [anxLiang](https://github.com/anxLiang) - 🐛 Fixed Sender insert node replacement issue when replaceCharacters is configured. [#1727](https://github.com/ant-design/x/pull/1727) by [kimteayon](https://github.com/kimteayon) ## 2.2.1 `2026-01-30` ### @ant-design/x - 💄 Fixed Bubble.List style issues. [#1713](https://github.com/ant-design/x/pull/1713) by [anxLiang](https://github.com/anxLiang), [#1704](https://github.com/ant-design/x/pull/1704) by [anxLiang](https://github.com/anxLiang) - 🐛 Fixed Node environment build errors caused by other third-party dependencies `esm` paths. [#1708](https://github.com/ant-design/x/pull/1708) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🐛 Fixed streaming rendering cache invalidation issue where cache would prematurely commit and cause rendering anomalies when list items contained inline code (like - \code\`\` ). [#1709](https://github.com/ant-design/x/pull/1709) by [Div627](https://github.com/Div627) - 🆕 Custom code rendering now accepts language information. [#1705](https://github.com/ant-design/x/pull/1705) by [Aarebecca](https://github.com/Aarebecca) ### @ant-design/x-sdk - 🆕 When XRequest is used together with Chat Provider, it will additionally obtain the assembled message. [#1714](https://github.com/ant-design/x/pull/1714) by [kimteayon](https://github.com/kimteayon) ### Others - 📖 Optimized official website to improve user experience. [#1717](https://github.com/ant-design/x/pull/1717) by [kimteayon](https://github.com/kimteayon), [#1707](https://github.com/ant-design/x/pull/1707) by [Div627](https://github.com/Div627) ## 2.2.0 `2026-01-26` ### @ant-design/x - Sender - 🐛 Fixed cursor insertion position error when cursor is at skill position. [#1633](https://github.com/ant-design/x/pull/1633) by [IsDyh01](https://github.com/IsDyh01) - 🛠 Refactored node insertion position capability and rewrote test cases. [#1612](https://github.com/ant-design/x/pull/1612) by [kimteayon](https://github.com/kimteayon) - XProvider - 🐛 Fixed `iconPrefixCls` setting not taking effect. [#1656](https://github.com/ant-design/x/pull/1656) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed `prefix` setting not taking effect. [#1642](https://github.com/ant-design/x/pull/1642) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed `layer` setting issue. [#1616](https://github.com/ant-design/x/pull/1616) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed forced `antd` dependency on `es` path causing Node environment build errors. [#1645](https://github.com/ant-design/x/pull/1645) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed ThoughtChain layout causing animation stuttering. [#1641](https://github.com/ant-design/x/pull/1641) by [IsDyh01](https://github.com/IsDyh01) - 🐛 Fixed Think layout causing animation stuttering. [#1636](https://github.com/ant-design/x/pull/1636) by [IsDyh01](https://github.com/IsDyh01) - 🐛 Fixed Sources setting position but unable to locate content issue. [#1683](https://github.com/ant-design/x/pull/1683) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Bubble.List internal height change scrollbar change error issue. [#1690](https://github.com/ant-design/x/pull/1690) by [anxLiang](https://github.com/anxLiang) - 🆕 Added Mermaid settings initialization configuration and operation bar functionality. [#1631](https://github.com/ant-design/x/pull/1631) by [Div627](https://github.com/Div627) - 🆕 Added Attachments card type setting capability. [#1610](https://github.com/ant-design/x/pull/1610) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-sdk - 🆕 XRequest added reconnection capability. [#1629](https://github.com/ant-design/x/pull/1629) by [hylin](https://github.com/hylin) - 🆕 XRequest and XStream support stream data parsing with configurable delimiters `streamSeparator`, `partSeparator`, `kvSeparator`, while adding polyfill for TextDecoderStream to improve compatibility, and fixing the issue where undefined values were added to stream results. [#1611](https://github.com/ant-design/x/pull/1611) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🆕 Enhanced XMarkdown parser to support custom components with placeholder protection. [#1668](https://github.com/ant-design/x/pull/1668) by [yanghuanrong](https://github.com/yanghuanrong) - 🆕 Added XMarkdown performance benchmarking capability for streaming Markdown rendering based on Playwright Component Testing. [#1314](https://github.com/ant-design/x/pull/1314) by [Div627](https://github.com/Div627) - 🆕 Added XMarkdown streaming syntax support for inline code caching. [#1630](https://github.com/ant-design/x/pull/1630) by [Div627](https://github.com/Div627) ### Others - 📖 Optimized official website to improve user experience. [#1675](https://github.com/ant-design/x/pull/1675) by [hongxuWei](https://github.com/hongxuWei), [#1644](https://github.com/ant-design/x/pull/1644) by [kimteayon](https://github.com/kimteayon), [#1658](https://github.com/ant-design/x/pull/1658) by [kimteayon](https://github.com/kimteayon), [#1646](https://github.com/ant-design/x/pull/1646) by [kimteayon](https://github.com/kimteayon), [#1651](https://github.com/ant-design/x/pull/1651) by [kimteayon](https://github.com/kimteayon), [#1650](https://github.com/ant-design/x/pull/1650) by [Div627](https://github.com/Div627), [#1635](https://github.com/ant-design/x/pull/1635) by [IsDyh01](https://github.com/IsDyh01), [#1627](https://github.com/ant-design/x/pull/1627) by [Alexzjt](https://github.com/Alexzjt), [#1615](https://github.com/ant-design/x/pull/1615) by [Yx0201](https://github.com/Yx0201) ## 2.1.3 `2026-01-04` ### @ant-design/x - 🐛 Fixed an undeclared dependency issue in Sender by replacing `classnames` with `clsx` and enabling dependency checks in `biome.json`. [#1608](https://github.com/ant-design/x/pull/1608) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized official website to improve user experience. [#1605](https://github.com/ant-design/x/pull/1605) by [kimteayon](https://github.com/kimteayon) ## 2.1.2 `2025-12-30` ### @ant-design/x - 💄 Fixed Actions `disliked` className error issue. [#1521](https://github.com/ant-design/x/pull/1521) by [kimteayon](https://github.com/kimteayon) - Sender - 🛠 Overall refactoring of Sender component implementation, while fixing some detailed cursor issues. [#1515](https://github.com/ant-design/x/pull/1515) [#1548](https://github.com/ant-design/x/pull/1548) by [kimteayon](https://github.com/kimteayon) - 💄 Fixed Sender component actions style conflict with antd Button causing rendering errors. [#1535](https://github.com/ant-design/x/pull/1535) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where cursor was too small when placeholder was empty in slot mode `skill`. [#1537](https://github.com/ant-design/x/pull/1537) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where undo stack was not updated when pasting text. [#1527](https://github.com/ant-design/x/pull/1527) by [Chiaki-xps](https://github.com/Chiaki-xps) - 🐛 Removed Bubble.List automatic scrolling to bottom logic for new messages, changed to manual control. [#1548](https://github.com/ant-design/x/pull/1548) by [anxLiang](https://github.com/anxLiang) - 💄 Fixed Prompts component animation demo not working issue. [#1580](https://github.com/ant-design/x/pull/1580) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Actions.Feedback tooltip display anomaly issue. [#1591](https://github.com/ant-design/x/pull/1591) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Attachments calling `ref.select()` error when no parameters passed. [#1587](https://github.com/ant-design/x/pull/1587) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed FileCard `overflow` display button not updating issue, and Image display failure when no `src` in image display. [#1587](https://github.com/ant-design/x/pull/1587) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-sdk - 🐛 Fixed XChat unable to remotely load historical messages issue. [#1593](https://github.com/ant-design/x/pull/1593) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed OpenAIChatProvider and DeepSeekChatProvider non-streaming requests rendering content twice issue. [#1593](https://github.com/ant-design/x/pull/1593) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 💄 Fixed XMarkdown animation font color error issue. [#1531](https://github.com/ant-design/x/pull/1531) by [Div627](https://github.com/Div627) ### Others - 🛠 Overall dependency refactoring and upgrade. [#1448](https://github.com/ant-design/x/pull/1448) by [yoyo837](https://github.com/yoyo837) - 📖 Optimized official website to improve user experience. [#1508](https://github.com/ant-design/x/pull/1508) by [kimteayon](https://github.com/kimteayon), [#1516](https://github.com/ant-design/x/pull/1516) by [kimteayon](https://github.com/kimteayon), [#1529](https://github.com/ant-design/x/pull/1529) by [fireairforce](https://github.com/fireairforce), [#1549](https://github.com/ant-design/x/pull/1549) by [kimteayon](https://github.com/kimteayon), [#1551](https://github.com/ant-design/x/pull/1551) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1553](https://github.com/ant-design/x/pull/1553) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1555](https://github.com/ant-design/x/pull/1555) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1543](https://github.com/ant-design/x/pull/1543) by [IsDyh01](https://github.com/IsDyh01), [#1558](https://github.com/ant-design/x/pull/1558) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1557](https://github.com/ant-design/x/pull/1557) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1562](https://github.com/ant-design/x/pull/1562) by [hustcc](https://github.com/hustcc), [#1569](https://github.com/ant-design/x/pull/1569) by [kimteayon](https://github.com/kimteayon), [#1561](https://github.com/ant-design/x/pull/1561) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1584](https://github.com/ant-design/x/pull/1584) by [kimteayon](https://github.com/kimteayon), [#1581](https://github.com/ant-design/x/pull/1581) by [teimurjan](https://github.com/teimurjan) ## 2.1.1 `2025-12-10` ### @ant-design/x - Sender - 🐛 Fixed the issue where send shortcuts enter and shift + enter were not controlled by the disabled state of the submit button, and fixed the inconsistency between `onSubmit` shortcut keys and button parameters. [#1472](https://github.com/ant-design/x/pull/1472) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the missing `skill` parameter in `onChange`, fixed the issue where placeholder was not displayed when slot mode only showed skill capabilities, and refactored `onChange` logic. [#1477](https://github.com/ant-design/x/pull/1477) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where send shortcuts enter and shift + enter were not triggered when `input` type slot was activated and focused in slot mode. [#1498](https://github.com/ant-design/x/pull/1498) by [kimteayon](https://github.com/kimteayon) - Attachment - 🐛 Fixed the issue where the last file was not uploaded after setting `maxCount`. [#1486](https://github.com/ant-design/x/pull/1486) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the antd warning issue after uploading images. [#1492](https://github.com/ant-design/x/pull/1492) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Mermaid rendering jitter issue. [#1497](https://github.com/ant-design/x/pull/1497) by [Div627](https://github.com/Div627) - 📖 Optimized official website to improve user experience. [#1464](https://github.com/ant-design/x/pull/1464) by [IsDyh01](https://github.com/IsDyh01), [#1483](https://github.com/ant-design/x/pull/1483) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1463](https://github.com/ant-design/x/pull/1463) by [J-Da-Shi](https://github.com/J-Da-Shi), [#1489](https://github.com/ant-design/x/pull/1489) by [Chiaki-xps](https://github.com/Chiaki-xps), [#1499](https://github.com/ant-design/x/pull/1499) by [kimteayon](https://github.com/kimteayon), [#1500](https://github.com/ant-design/x/pull/1500) by [kimteayon](https://github.com/kimteayon), [#1501](https://github.com/ant-design/x/pull/1501) by [Samoy](https://github.com/Samoy) - 🛠 Modified dependency configuration for `mermaid`. [#1475](https://github.com/ant-design/x/pull/1475) by [Div627](https://github.com/Div627) ### @ant-design/x-sdk - 🐛 Optimized message flow throttling and emission logic to avoid deep update errors caused by high-frequency streaming updates, improving real-time message stability and performance. [#1418](https://github.com/ant-design/x/pull/1418) by [Afee2019](https://github.com/Afee2019) ### @ant-design/x-markdown - 🛠 Optimized `sideEffects` configuration. [#1408](https://github.com/ant-design/x/pull/1408) by [hongxuWei](https://github.com/hongxuWei) ## 2.1.0 `2025-12-05` ### @ant-design/x - 🐛 Fixed Bubble css token `typingContent` configuration not taking effect. [#1435](https://github.com/ant-design/x/pull/1435) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed multiple component style loss issues caused by antd upgrade to 6.0.1. [#1441](https://github.com/ant-design/x/pull/1441) by [kimteayon](https://github.com/kimteayon), [#1446](https://github.com/ant-design/x/pull/1446) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Bubble.List scrolling compatibility issue in Safari browser. [#1392](https://github.com/ant-design/x/pull/1392) by [anxLiang](https://github.com/anxLiang) - 🔥 New components HighlightCode and Mermaid. [#1402](https://github.com/ant-design/x/pull/1402) by [Div627](https://github.com/Div627) - 🆕 Added semantic implementation for Actions. [#1443](https://github.com/ant-design/x/pull/1443) by [kimteayon](https://github.com/kimteayon) - 🆕 Added semantic implementation for Suggestion, removed duplicate Enter trigger events, fixed the issue of `onSubmit` method being executed multiple times, added complete data return of `selectedOptions` to `onSelect` method, and refactored the option implementation using `useMergedState`. [#1406](https://github.com/ant-design/x/pull/1406) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized official website to improve user experience. [#1444](https://github.com/ant-design/x/pull/1444) by [kimteayon](https://github.com/kimteayon) - 🆕 Added new slot type `content` and skill function `skill` for Sender. [#1377](https://github.com/ant-design/x/pull/1377) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-sdk - 🐛 Fixed DeepSeekChatProvider's improper handling of newline characters in `` tag format causing XMarkdown rendering anomalies. [#1445](https://github.com/ant-design/x/pull/1445) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed useXChat `setMessages` method call not triggering re-rendering. [#1450](https://github.com/ant-design/x/pull/1450) by [hylin](https://github.com/hylin) - 🐛 Fixed missing rc-util dependency declaration. [#1456](https://github.com/ant-design/x/pull/1456) by [hylin](https://github.com/hylin) ### @ant-design/x-markdown - 🐛 Replaced useStreaming regex to resolve iOS compatibility issues. [#1457](https://github.com/ant-design/x/pull/1457) by [Div627](https://github.com/Div627) - 📖 Improved documentation to enhance user experience. [#1451](https://github.com/ant-design/x/pull/1451) by [Div627](https://github.com/Div627) - 🛠 Migrated UI plugins HighlightCode and Mermaid to @ant-design/x to achieve more reasonable dependency relationships. [#1402](https://github.com/ant-design/x/pull/1402) by [Div627](https://github.com/Div627) ## 2.0.1 `2025-12-03` ### @ant-design/x - 🐛 Fixed multiple component style loss issues caused by antd upgrade to 6.0.1. [#1428](https://github.com/ant-design/x/pull/1428) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed antd error when using Attachments component. [#1395](https://github.com/ant-design/x/pull/1395) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Sender component `allowSpeech` custom disable error. [#1398](https://github.com/ant-design/x/pull/1398) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed missing semantic configuration for Sender.Switch component. [#1396](https://github.com/ant-design/x/pull/1396) by [kimteayon](https://github.com/kimteayon) - 🛠 Fixed test case failures caused by version upgrades. [#1393](https://github.com/ant-design/x/pull/1393) by [kimteayon](https://github.com/kimteayon) - 📖 Added 1.x official website links. [#1386](https://github.com/ant-design/x/pull/1386) by [kimteayon](https://github.com/kimteayon), [#1394](https://github.com/ant-design/x/pull/1394) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized official website to improve user experience. [#1384](https://github.com/ant-design/x/pull/1384) by [kimteayon](https://github.com/kimteayon), [#1416](https://github.com/ant-design/x/pull/1416) by [IsDyh01](https://github.com/IsDyh01) ### @ant-design/x-sdk - 📖 Comprehensive updates to official website directory, documentation, and examples. [#1419](https://github.com/ant-design/x/pull/1419) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed useXChat `requestFallback` adding errorInfo parameter to resolve inability to get API error data. [#1419](https://github.com/ant-design/x/pull/1419) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🐛 Fixed HighlightCode plugin copy code error. [#1414](https://github.com/ant-design/x/pull/1414) by [Jimi1126](https://github.com/Jimi1126) - 🐛 Fixed XMarkdown rendering special characters failure. [#1413](https://github.com/ant-design/x/pull/1413) by [Div627](https://github.com/Div627) - 🐛 Fixed XMarkdown cache reset logic not taking effect due to old references. [#1420](https://github.com/ant-design/x/pull/1420) by [Div627](https://github.com/Div627) ## 2.0.0 `2025-11-22` 🏆 Ant Design X 2.0.0 has been released! `@ant-design/x` - Smart UI Construction Framework A React UI library based on the Ant Design system, specifically designed for AI-driven interfaces. It includes ready-to-use intelligent chat components and seamless integration with API services, enabling rapid development of smart application interfaces. `@ant-design/x-markdown` - High-performance streaming rendering engine A Markdown rendering solution optimized for streaming content, featuring robust extensibility and exceptional performance with support for formulas, code highlighting, Mermaid diagrams, and more, ensuring a seamless content display experience. `@ant-design/x-sdk` - AI Chat Data Flow Management Provide a complete set of tool APIs, out-of-the-box AI chat application data flow management, simplify development processes, and enhance development efficiency. ##### Upgrade Required 🌟 We have prepared an upgrade guide. Please check the [details](/docs/react/migration-v2-cn). ## 2.0.0-alpha.16 `2025-11-17` ### @ant-design/x - 🛠 Removed the components property while promoting internal properties. [#1338](https://github.com/ant-design/x/pull/1338) by [kimteayon](https://github.com/kimteayon) - 🆕 FileCard adds image generation process and loading/rendering capabilities. [#1311](https://github.com/ant-design/x/pull/1311) by [kimteayon](https://github.com/kimteayon) - 🆕 Think upgrades `blink` animation styles to css token. [#1318](https://github.com/ant-design/x/pull/1318) by [kimteayon](https://github.com/kimteayon) - 🆕 ThoughtChain upgrades `blink` animation styles to css token. [#1318](https://github.com/ant-design/x/pull/1318) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1335](https://github.com/ant-design/x/pull/1335) by [kimteayon](https://github.com/kimteayon), [#1329](https://github.com/ant-design/x/pull/1329) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🛠 Optimized markdown rendering with useMemo, and updated basic demo text and animation demo text. [#1337](https://github.com/ant-design/x/pull/1337) by [Div627](https://github.com/Div627) - 🆕 XMarkdown renders HTML tags with `disabled` and `checked` attributes exposed. [#1328](https://github.com/ant-design/x/pull/1328) by [Div627](https://github.com/Div627) - 🆕 XMarkdown `hasNextChunk` adds table rendering processing capability. [#1322](https://github.com/ant-design/x/pull/1322) by [Div627](https://github.com/Div627) - 🐛 Fixed XMarkdown default table rendering styles. [#1324](https://github.com/ant-design/x/pull/1324) by [Div627](https://github.com/Div627) - 🆕 XMarkdown `incompleteMarkdownComponentMap` adds multiple type renderings. [#1325](https://github.com/ant-design/x/pull/1325) by [Div627](https://github.com/Div627) - 📖 Optimized the official site to enhance user experience. [#1326](https://github.com/ant-design/x/pull/1326) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.15 `2025-11-07` ### @ant-design/x - 🛠 Upgraded antd dependency version to `6.00-alpha.4`. [#1300](https://github.com/ant-design/x/pull/1300) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1303](https://github.com/ant-design/x/pull/1303) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🛠 Refactored markdown theme styles. [#1305](https://github.com/ant-design/x/pull/1305) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where `code` tag `streamStatus` state was incorrect. [#1307](https://github.com/ant-design/x/pull/1307) by [Div627](https://github.com/Div627) - 🛠 Transformed `index.less` to `index.css`. [#1306](https://github.com/ant-design/x/pull/1306) by [Div627](https://github.com/Div627) - 🐛 Fixed `SteamingOption` to `StreamingOption`. [#1301](https://github.com/ant-design/x/pull/1301) by [Div627](https://github.com/Div627) - 🐛 Fixed the issue where dompurifyConfig.ALLOWED_TAGS was incorrectly merged into ADD_TAGS. [#1297](https://github.com/ant-design/x/pull/1297) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.13 `2025-10-30` ### @ant-design/x - 🐛 Removed Bubble.List `suffix` property and modified typing through CSS Token. [#1285](https://github.com/ant-design/x/pull/1285) by [kimteayon](https://github.com/kimteayon) - 🆕 Added flashing animation effect to ThoughtChain.Item component. [#1278](https://github.com/ant-design/x/pull/1278) by [kimteayon](https://github.com/kimteayon) - 🆕 Added flashing animation effect to Think component. [#1278](https://github.com/ant-design/x/pull/1278) by [kimteayon](https://github.com/kimteayon) - 🆕 Added flashing animation effect to ThoughtChain component. [#1286](https://github.com/ant-design/x/pull/1286) by [kimteayon](https://github.com/kimteayon) - 🆕 Added fadeIn and fadeInLeft effects to Actions. [#1288](https://github.com/ant-design/x/pull/1288) by [kimteayon](https://github.com/kimteayon), [#1289](https://github.com/ant-design/x/pull/1289) by [kimteayon](https://github.com/kimteayon) - 🆕 Added fadeIn and fadeInLeft effects to Prompts. [#1289](https://github.com/ant-design/x/pull/1289) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1290](https://github.com/ant-design/x/pull/1290) by [Rain120](https://github.com/Rain120) ### @ant-design/x-markdown - 🐛 Fixed the issue where the renderer link passed in was overwritten. [#1276](https://github.com/ant-design/x/pull/1276) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.12 `2025-10-29` ### @ant-design/x - 🆕 Attachments Ref adds `select` method to support file selection capability, while fixing the issue where the upload button still appears after reaching the maximum quantity when a maximum limit is set. [#1266](https://github.com/ant-design/x/pull/1266) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1269](https://github.com/ant-design/x/pull/1269) by [kimteayon](https://github.com/kimteayon), [#1274](https://github.com/ant-design/x/pull/1274) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🐛 Fixed KaTeX plugin rendering failure and exception throwing issues, modified formula rendering rules to reduce rendering exceptions. [#1265](https://github.com/ant-design/x/pull/1265) by [Div627](https://github.com/Div627) - 📖 Added code examples for XMarkdown handling Chinese links. [#1270](https://github.com/ant-design/x/pull/1270) by [kimteayon](https://github.com/kimteayon) - 🆕 `code` and `pre` tags now return rendering status `streamStatus` and block-level identifier `block` during rendering. [#1272](https://github.com/ant-design/x/pull/1272) by [Div627](https://github.com/Div627) - 🐛 Fixed duplicate DOM keys when rendering markdown. [#1273](https://github.com/ant-design/x/pull/1273) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.11 `2025-10-27` ### @ant-design/x - 🆕 Sender slot configuration changed to mutable properties, in slot mode the `insert` method adds `replaceCharacters` parameter to support replacement functionality, and the `focus` method adds slot `key` configuration to support focusing on specific slots. [#1259](https://github.com/ant-design/x/pull/1259) by [kimteayon](https://github.com/kimteayon) - 🆕 Sources inline mode supports specifying the currently active panel, adds `activeKey` property, and optimizes panel switching interaction styles for better experience. [#1261](https://github.com/ant-design/x/pull/1261) by [kimteayon](https://github.com/kimteayon) - 🆕 Bubble.List optimized scrollbar layout, implementation, and semantics. [#1263](https://github.com/ant-design/x/pull/1263) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🐛 Fixed inconsistent parameter structure issue for XMarkdown custom components under different states. [#1260](https://github.com/ant-design/x/pull/1260) by [Div627](https://github.com/Div627) - 📖 Added XMarkdown code examples. [#1262](https://github.com/ant-design/x/pull/1262) by [kimteayon](https://github.com/kimteayon) ## 2.0.0-alpha.10 `2025-10-23` ### @ant-design/x - 🔥 New component Sources. [#1250](https://github.com/ant-design/x/pull/1250) by [hy993658052](https://github.com/hy993658052) - 🆕 Bubble adds two subcomponents: Bubble.System and Bubble.Divider. [#1239](https://github.com/ant-design/x/pull/1239) by [anxLiang](https://github.com/anxLiang) and [kimteayon](https://github.com/kimteayon) - Sender - 🆕 Added slot focus event functionality. [#1221](https://github.com/ant-design/x/pull/1221) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where `onPasteFile` callback data was incorrect when pasting multiple files in the input box. [#1221](https://github.com/ant-design/x/pull/1221) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed accessibility issues caused by SVG not being internationalized. [#1243](https://github.com/ant-design/x/pull/1243) by [kimteayon](https://github.com/kimteayon) - FileCard - 🆕 Added semantic implementation. [#1220](https://github.com/ant-design/x/pull/1220) by [kimteayon](https://github.com/kimteayon) - 🆕 Added support for `jfif` type. [#1248](https://github.com/ant-design/x/pull/1248) by [IsDyh01](https://github.com/IsDyh01) - 🆕 Attachments added semantic implementation. [#1220](https://github.com/ant-design/x/pull/1220) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1216](https://github.com/ant-design/x/pull/1216) by [kimteayon](https://github.com/kimteayon), [#1217](https://github.com/ant-design/x/pull/1217) by [Div627](https://github.com/Div627), [#1218](https://github.com/ant-design/x/pull/1218) by [IsDyh01](https://github.com/IsDyh01), [#1224](https://github.com/ant-design/x/pull/1224) by [kimteayon](https://github.com/kimteayon), [#1232](https://github.com/ant-design/x/pull/1232) by [IsDyh01](https://github.com/IsDyh01), [#1233](https://github.com/ant-design/x/pull/1233) by [kimteayon](https://github.com/kimteayon), [#1243](https://github.com/ant-design/x/pull/1243) by [kimteayon](https://github.com/kimteayon), [#1247](https://github.com/ant-design/x/pull/1247) by [elrrrrrrr](https://github.com/elrrrrrrr) ### @ant-design/x-markdown - 🆕 XMarkdown adds rendering component configuration `incomplete` for tags that need to be closed during the rendering process and corresponding functionality. [#1223](https://github.com/ant-design/x/pull/1223) by [Div627](https://github.com/Div627) - 🐛 Fixed the issue where XMarkdown `openLinksInNewTab` property configuration was ineffective. [#1253](https://github.com/ant-design/x/pull/1253) by [Div627](https://github.com/Div627) - 🐛 Fixed the issue of repeated rendering in XMarkdown animations. [#1255](https://github.com/ant-design/x/pull/1255) by [Div627](https://github.com/Div627) - 🆕 Enhanced XMarkdown's ability to identify formula rendering tags. [#1255](https://github.com/ant-design/x/pull/1255) by [Div627](https://github.com/Div627) ### @ant-design/x-sdk - 🐛 Fixed the issue where useXChat handling stream data server errors caused parameter problems in the `requestFallback` callback. [#1224](https://github.com/ant-design/x/pull/1224) by [kimteayon](https://github.com/kimteayon) - 🆕 Added implementation for activeConversationKey in useXConversations. [#1252](https://github.com/ant-design/x/pull/1252) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the non-multi-instance issue of useXChat `isRequesting`, and optimized the callback parameters for `requestPlaceholder` and `requestFallback`. [#1254](https://github.com/ant-design/x/pull/1254) by [kimteayon](https://github.com/kimteayon) ## 2.0.0-alpha.9 `2025-09-24` ### @ant-design/x-markdown - 🐛 Fixed code highlighting plugin style loss, resolved component matching issues with nested child elements, and removed table text-align attribute from default styles. [#1212](https://github.com/ant-design/x/pull/1212) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.8 `2025-09-22` ### @ant-design/x - Bubble - 🆕 Bubble.List adds `extra` parameter, which supports custom functions with useXChat. [#1195](https://github.com/ant-design/x/pull/1195) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where the content height was fixed in the `loading` state. [#1178](https://github.com/ant-design/x/pull/1178) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed component type export naming error. [#1182](https://github.com/ant-design/x/pull/1182) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed ThoughtChain.Item component type export naming error. [#1178](https://github.com/ant-design/x/pull/1178) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue of missing listening components in XProvider. [#1178](https://github.com/ant-design/x/pull/1178) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🛠 Refactored animation-related implementation. [#1198](https://github.com/ant-design/x/pull/1198) by [Div627](https://github.com/Div627), [#1204](https://github.com/ant-design/x/pull/1204) by [Div627](https://github.com/Div627) - 🐛 Fixed plugin export type error, and added examples and documentation. [#1187](https://github.com/ant-design/x/pull/1187) by [Div627](https://github.com/Div627) - 🐛 Fixed rendering exception when switching Mermaid plugin. [#1175](https://github.com/ant-design/x/pull/1175) by [Div627](https://github.com/Div627) - 🆕 Added semantic implementation for HighlightCode and Mermaid plugins. [#1178](https://github.com/ant-design/x/pull/1178) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed incomplete theme style override in XMarkdown. [#1182](https://github.com/ant-design/x/pull/1182) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-sdk - 🆕 useXChat `setMessage` now supports a callback function to get the original message, and `onRequest` and `onReload` add an `extra` parameter to support custom functions. [#1195](https://github.com/ant-design/x/pull/1195) by [kimteayon](https://github.com/kimteayon) ### Others - 🆕 Updated the overall site documentation. [#1194](https://github.com/ant-design/x/pull/1194) by [kimteayon](https://github.com/kimteayon) - 🆕 Updated the showcase functionality, added 'Ultramodern' showcase. [#1184](https://github.com/ant-design/x/pull/1184) by [kimteayon](https://github.com/kimteayon), [#1195](https://github.com/ant-design/x/pull/1195) by [kimteayon](https://github.com/kimteayon), [#1194](https://github.com/ant-design/x/pull/1194) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1170](https://github.com/ant-design/x/pull/1170) by [jinyang](https://github.com/jinyang), [#1186](https://github.com/ant-design/x/pull/1186) by [jinyang](https://github.com/jinyang), [#1192](https://github.com/ant-design/x/pull/1192) by [iamkun-2](https://github.com/iamkun-2), [#1193](https://github.com/ant-design/x/pull/1193) by [iamkun-2](https://github.com/iamkun-2), [#1197](https://github.com/ant-design/x/pull/1197) by [elrrrrrrr](https://github.com/elrrrrrrr), [#1199](https://github.com/ant-design/x/pull/1199) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.7 `2025-09-14` ### @ant-design/x - Bubble - 💄 Fixed the default `white-space` style issue. [#1147](https://github.com/ant-design/x/pull/1147) by [kimteayon](https://github.com/kimteayon) - 💄 Fixed missing semantics and incorrect height in `loading` state under Bubble.List. [#1162](https://github.com/ant-design/x/pull/1162) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed type export and documentation import errors. [#1160](https://github.com/ant-design/x/pull/1160) by [kimteayon](https://github.com/kimteayon) - 📖 Removed deprecated tools `useXAgent` and `useXChat`, and updated or replaced related documentation with `X SDK`. [#1148](https://github.com/ant-design/x/pull/1148) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the missing `status` display issue in the FileCard component. [#1156](https://github.com/ant-design/x/pull/1156) by [hy993658052](https://github.com/hy993658052) - 🐛 Fixed the issue where the Sender component could not paste Excel cell text when file paste was enabled. [#1167](https://github.com/ant-design/x/pull/1167) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🆕 Added Mermaid plugin operation functionality. [#1135](https://github.com/ant-design/x/pull/1135) by [Div627](https://github.com/Div627) - 🐛 Fixed the streaming effect in XMarkdown. [#1135](https://github.com/ant-design/x/pull/1135) by [Div627](https://github.com/Div627) - 🆕 Added plugin internationalization and theme customization features, along with documentation upgrades. [#1135](https://github.com/ant-design/x/pull/1135) by [kimteayon](https://github.com/kimteayon) - 🆕 Added `openLinksInNewTab` configuration for XMarkdown links and adjusted theme colors. [#1164](https://github.com/ant-design/x/pull/1164) by [Div627](https://github.com/Div627) - 🐛 Fixed style conflicts between XMarkdown and documentation markdown. [#1161](https://github.com/ant-design/x/pull/1161) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-sdk - 🛠 Refactored the `isRequesting` property in the useXChat tool, upgrading it from a method to an observable variable. [#1168](https://github.com/ant-design/x/pull/1168) by [hylin](https://github.com/hylin) - 🆕 Added message `abort` status to the useXChat tool, fixed the `message` parameter error in the `requestFallback` callback method, and removed error state message filtering. [#1171](https://github.com/ant-design/x/pull/1171) by [kimteayon](https://github.com/kimteayon) ### Others - 📖 Optimized the official site to enhance user experience. [#1169](https://github.com/ant-design/x/pull/1169) by [hylin](https://github.com/hylin) - 📖 Updated documentation for introduction, model integration, agent integration, X SDK, and template code. [#1171](https://github.com/ant-design/x/pull/1171) by [kimteayon](https://github.com/kimteayon) ## 2.0.0-alpha.6 `2025-08-28` ### @ant-design/x - 🐛 Fixed the issue where pressing `Enter` in normal mode of the Sender component would trigger `Submit` when selecting a candidate word. [#1144](https://github.com/ant-design/x/pull/1144) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue where the Sender component could not insert a new line when `submitType` was set to `shiftEnter` in slot mode. [#1143](https://github.com/ant-design/x/pull/1143) by [kimteayon](https://github.com/kimteayon) - 💄 Fixed the abnormal `margin` style when the `description` content of ThoughtChain.Item wrapped to a new line. - 🛠 Refactored the template room using `@ant-design/x-sdk`. [#1139](https://github.com/ant-design/x/pull/1139) by [hylin](https://github.com/hylin) - 🐛 Fixed the persistent display of the `prefix` in the Bubble component. [#1137](https://github.com/ant-design/x/pull/1137) by [anxLiang](https://github.com/anxLiang) - 📖 Added documentation to explain the scrolling container issue in Bubble.List. [#1133](https://github.com/ant-design/x/pull/1133) by [anxLiang](https://github.com/anxLiang) - 🐛 Fixed the issue where uploaded images in the Attachment component were not displayed. [#1140](https://github.com/ant-design/x/pull/1140) by [hy993658052](https://github.com/hy993658052) - 🐛 Fixed semantic issues and size display problems in the FileCard component. [#1130](https://github.com/ant-design/x/pull/1130) by [kimteayon](https://github.com/kimteayon) ### Others - 📦 Upgraded the father configuration. [#1125](https://github.com/ant-design/x/pull/1125) by [fireairforce](https://github.com/fireairforce) - 📖 Optimized the official site to enhance user experience. [#1142](https://github.com/ant-design/x/pull/1142) by [kimteayon](https://github.com/kimteayon) ## 2.0.0-alpha.5 `2025-08-20` ### @ant-design/x - 🆕 Added subcomponent features for Actions, including Actions.Copy, Actions.Audio, and Actions.Item. [#1121](https://github.com/ant-design/x/pull/1121) by [kimteayon](https://github.com/kimteayon) - Bubble - 🆕 Added functionality to render content with line breaks and tabs when `string content` is provided. [#1127](https://github.com/ant-design/x/pull/1127) by [anxLiang](https://github.com/anxLiang) - 🆕 Added semantic implementation. [#1116](https://github.com/ant-design/x/pull/1116) by [kimteayon](https://github.com/kimteayon) - 🐛 Optimized styles and type issues. [#1108](https://github.com/ant-design/x/pull/1108) by [anxLiang](https://github.com/anxLiang) - 🆕 Added semantic configuration for the Sender component. [#1116](https://github.com/ant-design/x/pull/1116) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-sdk - 🛠 Overall optimization of X SDK. [#1114](https://github.com/ant-design/x/pull/1114) by [hylin](https://github.com/hylin) ### Others - 📖 Refactored the template room using X SDK. [#1139](https://github.com/ant-design/x/pull/1139) by [hylin](https://github.com/hylin) - 📖 Optimized the official site to enhance user experience. [#1124](https://github.com/ant-design/x/pull/1124) by [kimteayon](https://github.com/kimteayon), [#1123](https://github.com/ant-design/x/pull/1123) by [kimteayon](https://github.com/kimteayon) - 🛠 Optimized the release process. [#1115](https://github.com/ant-design/x/pull/1115) by [kimteayon](https://github.com/kimteayon) ## 2.0.0-alpha.3 `2025-08-14` ### @ant-design/x-markdown - 🛠 Optimized version logic, configuration, and documentation. [#1112](https://github.com/ant-design/x/pull/1112) by [Div627](https://github.com/Div627) ## 2.0.0-alpha.1 `2025-08-12` ### @ant-design/x - 🛠 Refactored and upgraded the Bubble component. [#1100](https://github.com/ant-design/x/pull/1100) by [anxLiang](https://github.com/anxLiang), [#1077](https://github.com/ant-design/x/pull/1077) by [anxLiang](https://github.com/anxLiang) - 🛠 Refactored and upgraded the Bubble.List component. [#1077](https://github.com/ant-design/x/pull/1077) by [anxLiang](https://github.com/anxLiang) - 🐛 Fixed the issue where the `readOnly` and `loading` logic of the Bubble component did not take effect. [#1101](https://github.com/ant-design/x/pull/1101) by [kimteayon](https://github.com/kimteayon) ### Others - 🛠 Optimized the release process. [#1098](https://github.com/ant-design/x/pull/1098) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1087](https://github.com/ant-design/x/pull/1087) by [kimteayon](https://github.com/kimteayon) ## 2.0.0-alpha.0 `2025-08-05` ### @ant-design/x - 🔥 Added new component FileCard. [#1094](https://github.com/ant-design/x/pull/1094) by [hy993658052](https://github.com/hy993658052) - 🔥 Added new component Notification. [#973](https://github.com/ant-design/x/pull/973) by [kimteayon](https://github.com/kimteayon) - 🔥 Added new component Think. [#970](https://github.com/ant-design/x/pull/970) [#966](https://github.com/ant-design/x/pull/966) [#946](https://github.com/ant-design/x/pull/946) by [hy993658052](https://github.com/hy993658052) - 🛠 Refactored and upgraded the Attachments component. - 🛠 Refactored and upgraded the Actions component. [#994](https://github.com/ant-design/x/pull/994) by [vanndxh](https://github.com/vanndxh) - 🛠 Refactored and upgraded the Conversations component. [#955](https://github.com/ant-design/x/pull/955) [#954](https://github.com/ant-design/x/pull/954) [#937](https://github.com/ant-design/x/pull/937) by [kimteayon](https://github.com/kimteayon) - 🛠 Refactored and upgraded the Sender component. [#1073](https://github.com/ant-design/x/pull/1073), [#962](https://github.com/ant-design/x/pull/962) by [kimteayon](https://github.com/kimteayon), [Chuck-Ray](https://github.com/Chuck-Ray) - 🛠 Refactored and upgraded the ThoughtChain component. [#985](https://github.com/ant-design/x/pull/985) by [kimteayon](https://github.com/kimteayon) - 🆕 Added `Ref` functionality to all components. [#1081](https://github.com/ant-design/x/pull/1081) by [kimteayon](https://github.com/kimteayon) - 🆕 Integrated internationalization logic into the XProvider component. [#952](https://github.com/ant-design/x/pull/952) by [kimteayon](https://github.com/kimteayon) ### @ant-design/x-markdown - 🔥 Added new component XMarkdown. [#1060](https://github.com/ant-design/x/pull/1060), [#989](https://github.com/ant-design/x/pull/989) by [Div627](https://github.com/Div627) - 🔥 Added new plugin Latex. [#1060](https://github.com/ant-design/x/pull/1060), [#989](https://github.com/ant-design/x/pull/989) by [Div627](https://github.com/Div627) - 🔥 Added new plugin HighlightCode. [#1060](https://github.com/ant-design/x/pull/1060), [#989](https://github.com/ant-design/x/pull/989) by [Div627](https://github.com/Div627) - 🔥 Added new plugin Mermaid. [#1060](https://github.com/ant-design/x/pull/1060), [#989](https://github.com/ant-design/x/pull/989) by [Div627](https://github.com/Div627) ### @ant-design/x-sdk - 🔥 Added new tool useXChat. [#1098](https://github.com/ant-design/x/pull/1098) by [hylin](https://github.com/hylin) - 🔥 Added new tool useXConversations. [#1098](https://github.com/ant-design/x/pull/1098) by [hylin](https://github.com/hylin) - 🔥 Added new tool Chat Provider. [#1098](https://github.com/ant-design/x/pull/1098) by [hylin](https://github.com/hylin) - 🔥 Added new tool XRequest. [#1098](https://github.com/ant-design/x/pull/1098) by [hylin](https://github.com/hylin) - 🔥 Added new tool XStream. [#1098](https://github.com/ant-design/x/pull/1098) by [hylin](https://github.com/hylin) ### Others - 🛠 The overall framework has been upgraded to Monorepo.[#823](https://github.com/ant-design/x/pull/823) by [elrrrrrrr](https://github.com/elrrrrrrr) - 🛠 Upgraded all components to Ant Design V6. [#1012](https://github.com/ant-design/x/pull/1012) by [kimteayon](https://github.com/kimteayon) - 🛠 Upgraded and adjusted the release logic of Ant Design X. [#1098](https://github.com/ant-design/x/pull/1098), [#1009](https://github.com/ant-design/x/pull/1009) by [kimteayon](https://github.com/kimteayon) - 📖 Optimized the official site to enhance user experience. [#1083](https://github.com/ant-design/x/pull/1083) by [kimteayon](https://github.com/kimteayon), [#1001](https://github.com/ant-design/x/pull/1001) by [elrrrrrrr](https://github.com/elrrrrrrr) ## 1.6.1 `2025-09-12` - 🐛 Fixed ThoughtChain component `title` could not display the collapsed title when passing `ReactNode`. [#1172](https://github.com/ant-design/x/pull/1172) by [IsDyh01](https://github.com/IsDyh01) - 🐛 Fixed Sender component `LoadingButton` would display two icons when the `icon ` property is passed. [#1145](https://github.com/ant-design/x/pull/1145) by [IsDyh01](https://github.com/IsDyh01) - 🐛 Fixed semantic loss in Sender component `content`. [#703](https://github.com/ant-design/x/pull/703) by [HomyeeKing](https://github.com/HomyeeKing) - 🐛 Removed redundant condition checks in Bubble component typing effect prefix logic. [#1091](https://github.com/ant-design/x/pull/1091) by [AqingCyan](https://github.com/AqingCyan) - 🐛 Fixed missing `updating` status in useXChat. [#833](https://github.com/ant-design/x/pull/833) by [wzc520pyfm](https://github.com/wzc520pyfm) - 🐛 Fixed the exception in Suggestion component when items is an empty array in `useActive`. [#824](https://github.com/ant-design/x/pull/824) by [LengYXin](https://github.com/LengYXin) - 📖 Improved the official site for better user experience. [#960](https://github.com/ant-design/x/pull/960) by [wzc520pyfm](https://github.com/wzc520pyfm), [#1048](https://github.com/ant-design/x/pull/1048) by [wzc520pyfm](https://github.com/wzc520pyfm), [#1118](https://github.com/ant-design/x/pull/1118) by [afc163](https://github.com/afc163), [#1122](https://github.com/ant-design/x/pull/1122) by [fireairforce](https://github.com/fireairforce), [#1120](https://github.com/ant-design/x/pull/1120) by [IsDyh01](https://github.com/IsDyh01) ## 1.6.0 `2025-07-30` - 🆕 Attachments component `FileCard` adds icon and type configuration. [#1006](https://github.com/ant-design/x/pull/1006) by [kieranwv](https://github.com/kieranwv) - 📖 Added documentation and demo for Toolbox Agent integration. [#1063](https://github.com/ant-design/x/pull/1063) by [iamkun-2](https://github.com/iamkun-2) - 📖 Improved official site for better user experience. [#1054](https://github.com/ant-design/x/pull/1054) by [hylin](https://github.com/hylin), [#1056](https://github.com/hylin) ## 1.5.0 `2025-07-16` - 🆕 Added Bubble component support for `onScroll` event listener. [#1021](https://github.com/ant-design/x/pull/1021) by [QdabuliuQ](https://github.com/QdabuliuQ) - 🐛 Removed duplicate TypeScript type declaration in Bubble component. [#1032](https://github.com/ant-design/x/pull/1032) by [wzc520pyfm](https://github.com/wzc520pyfm) - 🐛 Fixed Conversations `onActiveChange` being triggered when a disabled `menu` item is clicked. [#1024](https://github.com/ant-design/x/pull/1024) by [QdabuliuQ](https://github.com/QdabuliuQ) - 🐛 Fixed semantic configuration for Attachments component `FileList`. [#1017](https://github.com/ant-design/x/pull/1017) by [kimteayon](https://github.com/kimteayon) - 🐛 Added html configuration for Actions component. [#995](https://github.com/ant-design/x/pull/995) by [vanndxh](https://github.com/vanndxh) - 🐛 Fixed Conversations label display issue and improved semantic configuration. [#898](https://github.com/ant-design/x/pull/898) by [yuanliu147](https://github.com/yuanliu147) - 📖 Improved official site for better user experience. [#940](https://github.com/ant-design/x/pull/940) by [coding-ice](https://github.com/coding-ice), [#969](https://github.com/ant-design/x/pull/969) by [afc163](https://github.com/afc163), [#968](https://github.com/ant-design/x/pull/968) by [afc163](https://github.com/afc163), [#1019](https://github.com/ant-design/x/pull/1019) by [hylin](https://github.com/hylin),[#1036](https://github.com/ant-design/x/pull/1036) by [kimteayon](https://github.com/kimteayon) ## 1.4.0 `2025-05-30` - 🔥 New Component Actions.[#768](https://github.com/ant-design/x/pull/768) by [vanndxh](https://github.com/vanndxh) - 🐛 Fix the issue where Bubble.List `footer` and `header` cannot retrieve keys.[#876](https://github.com/ant-design/x/pull/876) by [kimteayon](https://github.com/kimteayon) - 🐛 Fix the issue of overflow and ellipsis of Conversations list titles.[#877](https://github.com/ant-design/x/pull/877) by [kimteayon](https://github.com/kimteayon) - 📖 Enhance the official website to improve user experience.[#816](https://github.com/ant-design/x/pull/816) by [Rain120](https://github.com/Rain120)、[#880](https://github.com/ant-design/x/pull/880) by [kimteayon](https://github.com/kimteayon) ## 1.3.0 `2025-05-21` - 📖 Add Conversation type export. [#258](https://github.com/ant-design/x/pull/258) by [ONLY-yours](https://github.com/ONLY-yours) - 💄 Fixed the issue that the Prompts scroll bar is always displayed. [#785](https://github.com/ant-design/x/pull/785) by [kimteayon](https://github.com/kimteayon) - 🐛 Fix Suggestion warning for using antd deprecated API `onDropdownVisibleChange`. [#827](https://github.com/ant-design/x/pull/827) by [zombieJ](https://github.com/zombieJ) - 🆕 Extend Bubble`content` to `footer` and `header` method implementation parameters, and add Demo implementation.[#683](https://github.com/ant-design/x/pull/683) by [L-Hknu](https://github.com/L-Hknu) and [kimteayon](https://github.com/kimteayon) - 📖 Fixed the security issue of Api Key being exposed on the site.[#840](https://github.com/ant-design/x/pull/840) by [kimteayon](https://github.com/kimteayon) - 📖 Enhance the official website to improve user experience.[#783](https://github.com/ant-design/x/pull/783) by [kimteayon](https://github.com/kimteayon) ,[#229](https://github.com/ant-design/x/pull/229) by [afc163](https://github.com/afc163) ,[#835](https://github.com/ant-design/x/pull/835) by [kimteayon](https://github.com/kimteayon) ,[#814](https://github.com/ant-design/x/pull/814) by [wzc520pyfm](https://github.com/wzc520pyfm) ## 1.2.0 `2025-04-25` - 🐛 Delete Conversations ellipsis tooltip , fix 'tooltip' display error issue.[#776](https://github.com/ant-design/x/pull/776) by [afc163](https://github.com/afc163) - 🐛 Fixed Attachments `image` card style.[#751](https://github.com/ant-design/x/pull/751) by [wzc520pyfm](https://github.com/wzc520pyfm) - 🐛 Fixed ThoughtChain controlled issue.[#752](https://github.com/ant-design/x/pull/752) by [Youzi2233](https://github.com/Youzi2233) - XRequest - 🆕 XRequestCallbacks adds an 'onStream' callback that allows for stream listening and abort operations.[#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue of XRequestOptions changes not taking effect and added a demo.[#736](https://github.com/ant-design/x/pull/736) by [kimteayon](https://github.com/kimteayon) - 🆕 Add an example of model integration. [#725](https://github.com/ant-design/x/pull/725) by [kimteayon](https://github.com/kimteayon) - 📖 Inaccurate parameter naming in optimizing API methods.[#736](https://github.com/ant-design/x/pull/736) by [kimteayon](https://github.com/kimteayon) - useXAgent - 🆕 RequestFn adds an `onStream` callback that allows for stream listening and abort operations.[#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - 🆕 RequestFn has added a `transformStream` transformation function for processing stream data.[#725](https://github.com/ant-design/x/pull/725) by [kimteayon](https://github.com/kimteayon) - 🐛 Fix the issue of XAgentConfig Preset changes not taking effect and add an example.[#736](https://github.com/ant-design/x/pull/736) by [kimteayon](https://github.com/kimteayon) - 🐛 Fix the issue of incorrect callback types for RequestFn `onSuccess` and update the corresponding demo. [#725](https://github.com/ant-design/x/pull/725) by [kimteayon](https://github.com/kimteayon) - 🆕 Add model access, Custom RequestParams,and customize `XRequestOptions`demos. [#725](https://github.com/ant-design/x/pull/725) by [kimteayon](https://github.com/kimteayon) ,[#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - useXChat - 🆕 XChatConfig adds input and output generic types.[#725](https://github.com/ant-design/x/pull/725) by [kimteayon](https://github.com/kimteayon) - 🆕 XChatConfig adds `transformMessage` transformation function,which can transform `messages` when updating data and update to `messages` at the same time. [#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - 🆕 XChatConfig adds `transformStream`conversion function for processing stream data.[#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - 🆕 XChatConfig adds `resolveAbortController`callback function, which can obtain the`AbortController` controller for controlling the stream state.[#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - 🆕 Add model access examples and remove incorrect abort examples. [#711](https://github.com/ant-design/x/pull/711) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed the issue of Sender `header` `border-radius` style overflow.[#732](https://github.com/ant-design/x/pull/732) by [Bao0630](https://github.com/Bao0630) - 📖 Add a copilot style model room.[#657](https://github.com/ant-design/x/pull/657) by [vanndxh](https://github.com/vanndxh) - 📖 Refactoring the independent model room.[#753](https://github.com/ant-design/x/pull/753) by [vanndxh](https://github.com/vanndxh) - 📖 Enhance the official website to improve user experience.[#730](https://github.com/ant-design/x/pull/730) by [afc163](https://github.com/afc163) ,[#758](https://github.com/ant-design/x/pull/758) by [coding-ice](https://github.com/coding-ice) , [#761](https://github.com/ant-design/x/pull/761) by [ONLY-yours](https://github.com/ONLY-yours) ## 1.1.1 `2025-04-14` - Bubble.List - 💄 Refactor Bubble.List, reduce unnecessary refreshes during updates.[#479](https://github.com/ant-design/x/pull/479) by [YumoImer](https://github.com/YumoImer) - 🐛 Fixed scrollbar styles issues of `Bubble.List` under dark theme.[#727](https://github.com/ant-design/x/pull/727) by [kimteayon](https://github.com/kimteayon) - Conversation - 🐛 Fixed style issues of `ul` and `li` in Conversation.[#726](https://github.com/ant-design/x/pull/726) by [kimteayon](https://github.com/kimteayon) - 🆕 Extended `getPopupContainer` for `menu`.[#698](https://github.com/ant-design/x/pull/698) by [yuxuan-ctrl](https://github.com/yuxuan-ctrl) - 🐛 Fixed ThoughtChain Collapse cannot unfold issue.[#720](https://github.com/ant-design/x/pull/720) by [kimteayon](https://github.com/kimteayon) - 🐛 Fixed Attachments image display style issue.[#708](https://github.com/ant-design/x/pull/708) by [hy993658052](https://github.com/hy993658052) - 💄 Refactor Sender,Control the 'disabled' attribute of custom `Actions`.[#666](https://github.com/ant-design/x/pull/666) by [afc163](https://github.com/afc163) - 📖 Enhance the official website to improve user experience.[#680](https://github.com/ant-design/x/pull/680) by [wzc520pyfm](https://github.com/wzc520pyfm),[#699](https://github.com/ant-design/x/pull/699) by [afc163](https://github.com/afc163),[#716](https://github.com/ant-design/x/pull/716) by [afc163](https://github.com/afc163),[#686](https://github.com/ant-design/x/pull/686) by [afc163](https://github.com/afc163),[#728](https://github.com/ant-design/x/pull/728) by [kimteayon](https://github.com/kimteayon) ## 1.1.0 `2025-03-28` - Sender - 🆕 Add `footer` to support custom footer content.[#654](https://github.com/ant-design/x/pull/654) by [kimteayon](https://github.com/kimteayon) - 🆕 Extended `autoSize` to support custom content height.[#637](https://github.com/ant-design/x/pull/637) by [Zhang-Wei-666](https://github.com/Zhang-Wei-666) - 📖 Add the declarations for `onFocus` and `onBlur` types.[#625](https://github.com/ant-design/x/pull/625) by [aojunhao123](https://github.com/aojunhao123) - 🆕 Extended Conversations `menu.trigger` to support custom menu trigger.[#630](https://github.com/ant-design/x/pull/630) by [kimteayon](https://github.com/kimteayon) - Attachments - 🆕 Extended `ImageProps` to support custom image configuration.[#613](https://github.com/ant-design/x/pull/613) by [hy993658052](https://github.com/hy993658052) - 📖 Add Attachments `onRemove` API documentation[#608](https://github.com/ant-design/x/pull/608) by [kimteayon](https://github.com/kimteayon) - 📖 Extended `GPT-Vis` rendering chart example.[#603](https://github.com/ant-design/x/pull/603) by [lvisei](https://github.com/lvisei) - 📦 Improved Chat Design X `peerDependencies`.[#611](https://github.com/ant-design/x/pull/611) by [pokerface9830](https://github.com/pokerface9830) - 📖 Enhance the official website to improve user experience.[#626](https://github.com/ant-design/x/pull/626) by [aojunhao123](https://github.com/aojunhao123),[#648](https://github.com/ant-design/x/pull/648) by [kimteayon](https://github.com/kimteayon),[#659](https://github.com/ant-design/x/pull/659) by [afc163](https://github.com/afc163),[#667](https://github.com/ant-design/x/pull/667) by [jin19980928](https://github.com/jin19980928) ## 1.0.6 `2025-03-14` - 🆕 Extended `Sender` file pasting can handle multiple files.[#505](https://github.com/ant-design/x/pull/500) by [ztkuaikuai](https://github.com/ztkuaikuai) - 🆕 Extended `BubbleList` role definition function.[#485](https://github.com/ant-design/x/pull/500) by [chenluda](https://github.com/chenluda) - 🐛 Fixed `Attachments` multi file horizontal scrollbar display.[#556](https://github.com/ant-design/x/pull/556) by [onefeng123 ](https://github.com/onefeng123) - 🐛 Fixed `Attachments` onRemove non effective issue.[#555](https://github.com/ant-design/x/pull/555) by [edison-tianhe ](https://github.com/edison-tianhe) - 🐛 Fixed `Sender` the issue of actions lacking `SpeechButton`.[#549](https://github.com/ant-design/x/pull/549) by [zombieJ ](https://github.com/zombieJ) - 🐛 Fixed `Attachments`the issue of file initialization display.[#524](https://github.com/ant-design/x/pull/524) by [ztkuaikuai ](https://github.com/ztkuaikuai) - 🐛 Fixed `Conversations`scroll bar issue.[#485](https://github.com/ant-design/x/pull/485) by [LofiSu](https://github.com/LofiSu) - 📖 Improved`Bubble` `typing` reduces unnecessary rendering.[#477](https://github.com/ant-design/x/pull/477) by [kxcy001123](https://github.com/kxcy001123) - 📦 Improved Chat Design X construct [#578](https://github.com/ant-design/x/pull/578),[#584](https://github.com/ant-design/x/pull/584) by [kimteayon](https://github.com/kimteayon), [#578](https://github.com/ant-design/x/pull/578) by [kimteayon](https://github.com/kimteayon),[#587](https://github.com/ant-design/x/pull/587) by [afc163](https://github.com/afc163) - 📖 Enhance the official website to improve user experience.[#484](https://github.com/ant-design/x/pull/484) by [ztkuaikuai](https://github.com/ztkuaikuai), [#495](https://github.com/ant-design/x/pull/495) by [ztkuaikuai](https://github.com/ztkuaikuai), [#522](https://github.com/ant-design/x/pull/522) by [liangchaofei](https://github.com/liangchaofei),[#537](https://github.com/ant-design/x/pull/537) by [wzc520pyfm](https://github.com/wzc520pyfm),[#553](https://github.com/ant-design/x/pull/553) by [PeachScript](https://github.com/PeachScript), [#578](https://github.com/ant-design/x/pull/578) by [kimteayon](https://github.com/kimteayon), [#585](https://github.com/ant-design/x/pull/585) by [MaricoHan](https://github.com/MaricoHan) ## 1.0.5 `2025-01-13` - 🐛 Fix `Attachment` remove icon style. [#460](https://github.com/ant-design/x/pull/460) by [Rain120](https://github.com/Rain120) - 🛠 Refactor `BubbleProps` to support `ContentType` type argument. [#403](https://github.com/ant-design/x/pull/403) by [YumoImer](https://github.com/YumoImer) - 🛠 Dev and site support React 19. [#432](https://github.com/ant-design/x/pull/432) by [YumoImer](https://github.com/YumoImer) - 📖 Enhance the official website to improve user experience. [#456](https://github.com/ant-design/x/pull/456), [#446](https://github.com/ant-design/x/pull/446), [#448](https://github.com/ant-design/x/pull/448), [#444](https://github.com/ant-design/x/pull/444), [#414](https://github.com/ant-design/x/pull/414), [#406](https://github.com/ant-design/x/pull/406), [#404](https://github.com/ant-design/x/pull/404) by [wzc520pyfm](https://github.com/wzc520pyfm), [YumoImer](https://github.com/YumoImer), [Rain120](https://github.com/Rain120), [afc163](https://github.com/afc163) ## 1.0.4 `2024-12-25` - 🆕 Extended `XStream` support for the cancel feature. [#319](https://github.com/ant-design/x/pull/319) by [ppbl](https://github.com/ppbl) - 🆕 Extended `Bubble` support for the `typing.suffix` feature. [#316](https://github.com/ant-design/x/pull/316) by [BQXBQX](https://github.com/BQXBQX) - 🆕 Extended `Sender` component's `onChange` parameter to include the `event` object. [#362](https://github.com/ant-design/x/pull/362) by [defaultjacky](https://github.com/defaultjacky) - 🆕 Enhanced the `Sender` component's `ref` to support focus control methods like `focus` and `blur`. [#397](https://github.com/ant-design/x/pull/397) by [YumoImer](https://github.com/YumoImer) - 🐛 Fixed styling issues in `ThoughtChain` when `cssVar` is not applied. [#373](https://github.com/ant-design/x/pull/373) by [YumoImer](https://github.com/YumoImer) - 📖 Added `Petercat` assistant feature. [#375](https://github.com/ant-design/x/pull/375) by [xingwanying](https://github.com/xingwanying) - 📖 Improved the official website for a better user experience. [#389](https://github.com/ant-design/x/pull/389), [#377](https://github.com/ant-design/x/pull/377), [#364](https://github.com/ant-design/x/pull/364), [#368](https://github.com/ant-design/x/pull/368) by [afc163](https://github.com/afc163), [YumoImer](https://github.com/YumoImer) ## 1.0.3 `2024-12-16` - 💄 Refactor the styles when `placement: 'end'` is set for `Bubble`. [#314](https://github.com/ant-design/x/pull/314) by [YumoImer](https://github.com/YumoImer) - 🐛 Fix occasional failure to trigger auto-scrolling when `autoScroll` is set in `Bubble.List`. [#336](https://github.com/ant-design/x/pull/336) by [anzhou99Ru](https://github.com/anzhou99Ru) - 📖 Enhance the official website to improve user experience. [#343](https://github.com/ant-design/x/pull/343), [#334](https://github.com/ant-design/x/pull/334), [#315](https://github.com/ant-design/x/pull/315), [#331](https://github.com/ant-design/x/pull/331) by [afc163](https://github.com/afc163), [YumoImer](https://github.com/YumoImer), [Wxh16144](https://github.com/Wxh16144) - 🛠 Fix errors encountered when running `pnpm lint`. [#313](https://github.com/ant-design/x/pull/313) by [BQXBQX](https://github.com/BQXBQX) ## 1.0.2 `2024-12-04` - 🛠 Enhanced `XRequest` to support parsing custom protocols. [#293](https://github.com/ant-design/x/pull/293) by [YumoImer](https://github.com/YumoImer) - 🐛 Fixed an issue where the preview buttons for `Attachment` did not toggle visibility properly. [#295](https://github.com/ant-design/x/pull/295) by [anzhou99](https://github.com/anzhou99) - 🐛 Fixed a bug in `useXChat` where the same message triggered `onUpdate` multiple times. [#298](https://github.com/ant-design/x/pull/298) by [YumoImer](https://github.com/YumoImer) - 📖 Added documentation for using `Bubble` with `GPT-Vis`. [#288](https://github.com/ant-design/x/pull/288) by [lvisei](https://github.com/lvisei) - 📦 Updated browser target configurations to reduce bundle size. [#282](https://github.com/ant-design/x/pull/282) by [afc163](https://github.com/afc163) - 🛠 Fixed errors when running `pnpm run prestart`. [#287](https://github.com/ant-design/x/pull/287) by [long36708](https://github.com/long36708) ## 1.0.1 `2024-11-29` - 🛠 Optimized TS types for `useXAgent` and `XStream`. [#272](https://github.com/ant-design/x/pull/272) by [YumoImer](https://github.com/YumoImer) - 🛠 Made the `agent` parameter optional to support data management functionality using only `useXChat`. [#271](https://github.com/ant-design/x/pull/271) by [YumoImer](https://github.com/YumoImer) - 💄 Adjusted `Conversations` style based on RICH design specification. [#242](https://github.com/ant-design/x/pull/242) by [YumoImer](https://github.com/YumoImer) - 🛠 Fixed ghost dependency issue that prevented the project from starting when using `pnpm`. [#223](https://github.com/ant-design/x/pull/223) by [YumoImer](https://github.com/YumoImer) - 🌈 Demonstrated the attachment upload functionality in the standalone template. [#250](https://github.com/ant-design/x/pull/250), [#265](https://github.com/ant-design/x/pull/265) by [kelvinelove](https://github.com/kelvinelove) - 📖 Fixed missing contributor information. [#212](https://github.com/ant-design/x/pull/212) by [afc163](https://github.com/afc163) - 📖 Optimized official site to enhance user experience. [#277](https://github.com/ant-design/x/pull/277), [#264](https://github.com/ant-design/x/pull/264), [#263](https://github.com/ant-design/x/pull/263), [#262](https://github.com/ant-design/x/pull/262), [#261](https://github.com/ant-design/x/pull/261), [#241](https://github.com/ant-design/x/pull/241), [#246](https://github.com/ant-design/x/pull/246), [#210](https://github.com/ant-design/x/pull/210), [#211](https://github.com/ant-design/x/pull/211) by [YumoImer](https://github.com/YumoImer), [afc163](https://github.com/afc163), [Rain-1214](https://github.com/Rain-1214), [kelvinelove](https://github.com/kelvinelove) and [tabzzz1](https://github.com/tabzzz1) - 📦 Updated browser targets to reduce bundle size. [#234](https://github.com/ant-design/x/pull/234) by [afc163](https://github.com/afc163) ## 1.0.0 `2024-11-22` 🎉 We are thrilled to announce the official release of [Ant Design X](https://x.ant.design) 1.0.0! - 🌈 **Derived from Best Practices of Enterprise-Level AI Products**: Built on the RICH interaction paradigm, delivering an exceptional AI interaction experience. - 🧩 **Flexible and Diverse Atomic Components**: Covers most AI dialogue scenarios, empowering you to quickly build personalized AI interaction interfaces. - ⚡ **Out-of-the-Box Model Integration**: Easily connect with inference services compatible with OpenAI standards. - 🔄 **Efficient Management of Conversation Data Flows**: Provides powerful tools for managing data flows, enhancing development efficiency. - 📦 **Rich Template Support**: Offers multiple templates for quickly starting LUI application development. - 🛡 **Complete TypeScript Support**: Developed with TypeScript, ensuring robust type coverage to improve the development experience and reliability. - 🎨 **Advanced Theme Customization**: Supports fine-grained style adjustments to meet diverse use cases and personalization needs. ## 1.0.0-alpha.12 `2024-11-07` - 🔥 Sender support `onPasteFile` and Attachments support `ref.upload` for manual uploading, by [zombieJ](https://github.com/zombieJ) [#184](https://github.com/ant-design/x/pull/184) - 🔥 Sender `allowSpeech` support using third-part SDK, by [zombieJ](https://github.com/zombieJ) [#187](https://github.com/ant-design/x/pull/187) ## 1.0.0-alpha.11 `2024-11-06` - 🔥 New Component Welcome, by [zombieJ](https://github.com/zombieJ) [#179](https://github.com/ant-design/x/pull/179) - 🔥 Prompts support nest structure, by [zombieJ](https://github.com/zombieJ) [#181](https://github.com/ant-design/x/pull/181) - 🔥 Attachments support Attachments.FileCard component, by [zombieJ](https://github.com/zombieJ) [#182](https://github.com/ant-design/x/pull/182) ## 1.0.0-alpha.10 `2024-11-04` - 🐛 Fix Attachments drop upload could not trigger the upload request, by [YumoImer](https://github.com/YumoImer) [#178](https://github.com/ant-design/x/pull/178) ## 1.0.0-alpha.9 `2024-11-01` - 🐛 Fix the logic in the Attachments, by [YumoImer](https://github.com/YumoImer) [#174](https://github.com/ant-design/x/pull/174) - 🐛 Fix Sender.Header can not focus, by [zombieJ](https://github.com/zombieJ) [#175](https://github.com/ant-design/x/pull/175) ## 1.0.0-alpha.7 `2024-10-31` - 🐛 Fix Attachments first upload could not trigger the upload request, by [YumoImer](https://github.com/YumoImer) [#172](https://github.com/ant-design/x/pull/172) ## 1.0.0-alpha.6 `2024-10-25` - 🔥 New Component `Attachments`, by [zombieJ](https://github.com/zombieJ) [#168](https://github.com/ant-design/x/pull/168) - 🔥 New Tools `XStream`, by [YumoImer](https://github.com/YumoImer) [#138](https://github.com/ant-design/x/pull/138) - 🔥 New Tools `XRequest`, by [YumoImer](https://github.com/YumoImer) [#138](https://github.com/ant-design/x/pull/138) ## 1.0.0-alpha.5 `2024-10-23` - 🆕 Bubble support `loadingRender` to customize loading content. [#165](https://github.com/ant-design/x/pull/165) - 🐛 Fix components missing style when without XProvider. [#163](https://github.com/ant-design/x/pull/163) ## 1.0.0-alpha.4 `2024-10-17` - Sender - 🆕 Sender support `speech`, by [zombieJ](https://github.com/zombieJ) [#154](https://github.com/ant-design/x/pull/154) - 🆕 Sender support Sender.Header, by [zombieJ](https://github.com/zombieJ) [#156](https://github.com/ant-design/x/pull/156) - 🆕 Sender style adjust, by [zombieJ](https://github.com/zombieJ) [#151](https://github.com/ant-design/x/pull/151) - 📖 update group config for Components category, by [YumoImer](https://github.com/YumoImer) [#155](https://github.com/ant-design/x/pull/155) - 📖 tweak demo toggle button style , by [afc163](https://github.com/afc163) [#146](https://github.com/ant-design/x/pull/146) - 📖 Update README.md, by [afc163](https://github.com/afc163) [#142](https://github.com/ant-design/x/pull/142) ## 1.0.0-alpha.3 `2024-10-10` - Bubble - 🆕 Bubble support `variant` props, by [zombieJ](https://github.com/zombieJ) [#140](https://github.com/ant-design/x/pull/140) - 🆕 Bubble support `shape` props, by [zombieJ](https://github.com/zombieJ) [#144](https://github.com/ant-design/x/pull/144) - 🆕 Bubble support `header` and `footer` props, by [zombieJ](https://github.com/zombieJ) [#147](https://github.com/ant-design/x/pull/147) ## 1.0.0-alpha.2 `2024-09-27` - 🔥 New Component `XProvider` for global configuration, by [YumoImer](https://github.com/YumoImer) [#127](https://github.com/ant-design/x/pull/127) - 🔥 New Runtime Hook `useXChat` for data management, by [zombieJ](https://github.com/zombieJ) [#125](https://github.com/ant-design/x/pull/125) - 🔥 New Runtime Hook `useXAgent` for model scheduling, by [zombieJ](https://github.com/zombieJ) [#125](https://github.com/ant-design/x/pull/125) - 🆕 `ThoughtChain` component now support the `size` property, by [YumoImer](https://github.com/YumoImer) [#123](https://github.com/ant-design/x/pull/123) - 🛠 Updated `.lintstagedrc.json`, by [afc163](https://github.com/afc163) [#128](https://github.com/ant-design/x/pull/128) - 🛠 Updated dependency `cheerio` to `v1.0.0`, by [afc163](https://github.com/afc163) [#121](https://github.com/ant-design/x/pull/121) ## 1.0.0-alpha.1 `2024-09-10` ### 🚀 Features - 🔥 feat: Suggestion 建议组件 by [ONLY-yours](https://github.com/ONLY-yours) in [#87](https://github.com/ant-design/x/pull/87) ### 🐛 Fixes - 🐛 fix: change the Sender restProps type by [ONLY-yours](https://github.com/ONLY-yours) in [#101](https://github.com/ant-design/x/pull/101) - 🛠 fix: bun install by [afc163](https://github.com/afc163) in [#111](https://github.com/ant-design/x/pull/111) ### 🛠 Refactors - 🛠 chore: add layer support by [zombieJ](https://github.com/zombieJ) in [#118](https://github.com/ant-design/x/pull/118) - 🛠 chore: speed up workflows by [afc163](https://github.com/afc163) in [#119](https://github.com/ant-design/x/pull/119) - 🛠 chore(deps-dev): bump the dev-dependencies group with 5 updates by [dependabot](https://github.com/dependabot) in [#120](https://github.com/ant-design/x/pull/120) - 🛠 chore: clean up README.md by [afc163](https://github.com/afc163) in [#102](https://github.com/ant-design/x/pull/102) - 🛠 chore: add issue templates by [afc163](https://github.com/afc163) in [#103](https://github.com/ant-design/x/pull/103) - 🛠 chore: add bun.lockb by [afc163](https://github.com/afc163) in [#108](https://github.com/ant-design/x/pull/108) - 🛠 chore: Delete index-style-only.js by [afc163](https://github.com/afc163) in [#106](https://github.com/ant-design/x/pull/106) - 🛠 chore: Update main.yml by [afc163](https://github.com/afc163) in [#105](https://github.com/ant-design/x/pull/105) - 🛠 chore: Update package.json by [afc163](https://github.com/afc163) in [#110](https://github.com/ant-design/x/pull/110) ### 📖 Documentation - 📖 docs: Update README.md by [afc163](https://github.com/afc163) in [#104](https://github.com/ant-design/x/pull/104) - 📖 docs: Update codecov badge by [afc163](https://github.com/afc163) in [#112](https://github.com/ant-design/x/pull/112) ## 1.0.0-alpha.0 `2024-09-05` - 🔥 New Component Bubble. [#19](https://github.com/ant-design/x/pull/19) [li-jia-nan](https://github.com/li-jia-nan) - 🔥 Bubble support direction [#52](https://github.com/ant-design/x/pull/52) [li-jia-nan](https://github.com/li-jia-nan) - 🔥 New Component Bubble.List. [#57](https://github.com/ant-design/x/pull/57) [zombieJ](https://github.com/zombieJ) - 🔥 New Component Conversations. [#48](https://github.com/ant-design/x/pull/48) [YumoImer](https://github.com/YumoImer) - 🔥 New Component Prompts. [#55](https://github.com/ant-design/x/pull/55) [YumoImer](https://github.com/YumoImer) - 🔥 New Component Sender. [#46](https://github.com/ant-design/x/pull/46) [ONLY-yours](https://github.com/ONLY-yours) - 🔥 New Component ThoughtChain. [#86](https://github.com/ant-design/x/pull/86) [YumoImer](https://github.com/YumoImer) - 📦 Use `father` to build. [#84](https://github.com/ant-design/x/pull/84) [zombieJ](https://github.com/zombieJ) - 🛠 Fix ThemeContext instances being inconsistent when using `antd` es or lib package. [#88](https://github.com/ant-design/x/pull/88) [YumoImer](https://github.com/YumoImer) - 🛠 Refactor: API Naming Conventions [#73](https://github.com/ant-design/x/pull/73) [zombieJ](https://github.com/zombieJ) - 🛠 MISC: CI, Github Actions, Publish - 🛠 [#59](https://github.com/ant-design/x/pull/59) [zombieJ](https://github.com/zombieJ) - 🛠 [#62](https://github.com/ant-design/x/pull/62) [zombieJ](https://github.com/zombieJ) - 🛠 [#71](https://github.com/ant-design/x/pull/71) [ONLY-yours](https://github.com/ONLY-yours) - 🛠 [#72](https://github.com/ant-design/x/pull/72) [YumoImer](https://github.com/YumoImer) - 🛠 [#98](https://github.com/ant-design/x/pull/98) [YumoImer](https://github.com/YumoImer) - 📖 Update README.md - 📖 [#81](https://github.com/ant-design/x/pull/81) [zombieJ](https://github.com/zombieJ) - 📖 [#82](https://github.com/ant-design/x/pull/82) [zombieJ](https://github.com/zombieJ) - 📖 [#61](https://github.com/ant-design/x/pull/61) [afc163](https://github.com/afc163) ## 0.0.0-alpha.0 `2024-05-10` - MISC: Project initialization. ================================================ FILE: CHANGELOG.zh-CN.md ================================================ --- order: 6 title: 更新日志 timeline: true tag: vVERSION --- `@ant-design/x` 遵循 [Semantic Versioning 2.0.0](http://semver.org/lang/zh-CN/) 语义化版本规范。 #### 发布周期 - 修订版本号:日常 bugfix 更新。 - 次版本号:带有新特性的向下兼容的版本。 - 主版本号:含有破坏性更新和新特性。 --- ## 2.4.0 `2026-03-13` ### @ant-design/x - 🔥 新组件 Folder。[#1797](https://github.com/ant-design/x/pull/1797) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 强化 FileCard 的 `description`、`mask`、`onClick` 配置的能力。[#1807](https://github.com/ant-design/x/pull/1807) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🆕 XMarkdown 流式渲染新增 `tail` 配置,支持自定义尾缀内容与尾缀组件,并避免尾缀出现在未完成组件之前。[#1296](https://github.com/ant-design/x/pull/1296) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 自定义组件流式状态识别问题,正确处理 void elements,并隔离同名组件多实例的 `streamStatus`。[#1590](https://github.com/ant-design/x/pull/1590) 由 [Last-Order](https://github.com/Last-Order) 提交 - 🛠 导出 XMarkdown 的 `StreamCacheTokenType` 类型,便于外部复用流式渲染相关类型。[#1592](https://github.com/ant-design/x/pull/1592) 由 [Last-Order](https://github.com/Last-Order) 提交 - 📖 新增 XMarkdown Playground,并重构 streaming、examples、data-display 文档,补充 AntV Infographic 示例。[#1779](https://github.com/ant-design/x/pull/1779) 由 [Div627](https://github.com/Div627) 提交、[#1780](https://github.com/ant-design/x/pull/1780) 由 [Div627](https://github.com/Div627) 提交、[#1814](https://github.com/ant-design/x/pull/1814) 由 [Div627](https://github.com/Div627) 提交 ### @ant-design/x-skill - 🆕 发布 x-markdown skill。[#1813](https://github.com/ant-design/x/pull/1813) 由 [Div627](https://github.com/Div627) 提交 ### 其他 - 🐛 修复 useShortcutKeys 错误的事件处理。[#1822](https://github.com/ant-design/x/pull/1822) 由 [cxybd](https://github.com/cxybd) 提交 - 🛠 将所有组件 useMergedState 升级为 useControlledState。[#1808](https://github.com/ant-design/x/pull/1808) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1814](https://github.com/ant-design/x/pull/1814) 由 [Div627](https://github.com/Div627) 提交、[#1793](https://github.com/ant-design/x/pull/1793) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1792](https://github.com/ant-design/x/pull/1792) 由 [Div627](https://github.com/Div627) 提交、[#1780](https://github.com/ant-design/x/pull/1780) 由 [Div627](https://github.com/Div627) 提交、[#1779](https://github.com/ant-design/x/pull/1779) 由 [Div627](https://github.com/Div627) 提交 ## 2.3.0 `2026-02-26` ### @ant-design/x - 🆕 Conversation 的 onActiveChange 回调现在同时返回被激活的项及其键值,同时更新 useMergedState 为 useControlledState。[#1762](https://github.com/ant-design/x/pull/1762) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 优化 Sender 禁用状态按钮的视觉表现,统一添加透明边框处理,确保不同按钮变体在禁用时的外观一致。[#1751](https://github.com/ant-design/x/pull/1751) 由 [Rain120](https://github.com/Rain120) 提交 ### @ant-design/x-markdown - 🆕 XMarkdown 新增 escapeRawHtml 属性,允许用户在渲染时选择是否对原始 HTML 进行转义。[#1769](https://github.com/ant-design/x/pull/1769) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 列表中遇到未闭合行内代码时的渲染,确保列表标记在特殊未闭合情况仍被保留。[#1739](https://github.com/ant-design/x/pull/1739) 由 [Div627](https://github.com/Div627) 提交 - 🐛 改进了块级 LaTeX 公式的解析,对结尾处的空白与缩进处理更宽容,提升了对不同行尾格式的兼容性,减少误判与渲染问题。[#1744](https://github.com/ant-design/x/pull/1744) 由 [Waiter](https://github.com/Waiter) 提交 - 🐛 优化深色模式 CodeHighlighter,Mermaid 插件样式问题。[#1766](https://github.com/ant-design/x/pull/1766) 由 [menghany](https://github.com/menghany) 提交 ### @ant-design/x-sdk - 🆕 useXChat 新增 queueRequest 方法,实现 ConversationKey 和 SessionId 的初始化消息发送。[#1761](https://github.com/ant-design/x/pull/1761) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-skill - 🆕 新增 skill 安装指令,同时发布 use-x-chat、x-chat-provider、x-request 三个 skill。[#1753](https://github.com/ant-design/x/pull/1768)、[#1767](https://github.com/ant-design/x/pull/1767) 由 [kimteayon](https://github.com/kimteayon) 提交 ### 其他 - 🛠 修复了因依赖升级导致的构建错误问题。 [#1754](https://github.com/ant-design/x/pull/1754) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🛠 解决 CodeSandbox 预览中 domhandler 的 ModuleNotFoundError 错误。[#1754](https://github.com/ant-design/x/pull/1754) 由 [Div627](https://github.com/Div627) 提交 ## 2.2.2 `2026-02-06` ### @ant-design/x - 🛠 修复一些文档和类型来支持 AI Coding。[#1733](https://github.com/ant-design/x/pull/1733) 由 [kimteayon](https://github.com/kimteayon) 提交 - 💄 修复 Bubble.List 样式和语义化问题。[#1731](https://github.com/ant-design/x/pull/1731) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🐛 修复 Sender 插入节点配置了 replaceCharacters 时的替换问题。[#1727](https://github.com/ant-design/x/pull/1727) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.2.1 `2026-01-30` ### @ant-design/x - 💄 修复 Bubble.List 样式问题。[#1713](https://github.com/ant-design/x/pull/1713) 由 [anxLiang](https://github.com/anxLiang) 提交、[#1704](https://github.com/ant-design/x/pull/1704) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🐛 修复因其他三方依赖 `esm` 路径导致 Node 环境构建报错问题。[#1708](https://github.com/ant-design/x/pull/1708) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🐛 修复流式渲染缓存失效问题,当列表项包含行内代码(如 - \code\`\` )时,缓存会提前提交导致渲染异常。[#1709](https://github.com/ant-design/x/pull/1709) 由 [Div627](https://github.com/Div627) 提交 - 🆕 自定义代码渲染支持接受语言信息。[#1705](https://github.com/ant-design/x/pull/1705) 由 [Aarebecca](https://github.com/Aarebecca) 提交 ### @ant-design/x-sdk - 🆕 XRequest 与 Chat Provider 一起使用时会额外获取到组装好的 message。[#1714](https://github.com/ant-design/x/pull/1714) 由 [kimteayon](https://github.com/kimteayon) 提交 ### 其他 - 📖 优化官网站点提升用户体验。[#1717](https://github.com/ant-design/x/pull/1717) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1707](https://github.com/ant-design/x/pull/1707) 由 [Div627](https://github.com/Div627) 提交 ## 2.2.0 `2026-01-26` ### @ant-design/x - Sender - 🐛 修复光标在技能位置时插入位置错误问题。[#1633](https://github.com/ant-design/x/pull/1633) 由 [IsDyh01](https://github.com/IsDyh01) 提交 - 🛠 重构插入节点位置能力,同时重写测试用例。[#1612](https://github.com/ant-design/x/pull/1612) 由 [kimteayon](https://github.com/kimteayon) 提交 - XProvider - 🐛 修复设置 `iconPrefixCls` 不生效问题。[#1656](https://github.com/ant-design/x/pull/1656) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复设置 `prefix` 不生效问题。[#1642](https://github.com/ant-design/x/pull/1642) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 `layer` 设置问题。 [#1616](https://github.com/ant-design/x/pull/1616) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复因强制 `antd` 依赖 `es` 路径导致 Node 环境构建报错问题。[#1645](https://github.com/ant-design/x/pull/1645) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 ThoughtChain 布局导致动画卡顿问题。[#1641](https://github.com/ant-design/x/pull/1641) 由 [IsDyh01](https://github.com/IsDyh01) 提交 - 🐛 修复 Think 布局导致动画卡顿问题。[#1636](https://github.com/ant-design/x/pull/1636) 由 [IsDyh01](https://github.com/IsDyh01) 提交 - 🐛 修复 Sources 设置了位置但无法定位内容问题。 [#1683](https://github.com/ant-design/x/pull/1683) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Bubble.List 内部高度变化滚动条变化错误问题。[#1690](https://github.com/ant-design/x/pull/1690) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🆕 新增 Mermaid 设置初始化配置和操作栏功能。[#1631](https://github.com/ant-design/x/pull/1631) 由 [Div627](https://github.com/Div627) 提交 - 🆕 新增 Attachments 设置卡片类型能力。[#1610](https://github.com/ant-design/x/pull/1610) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-sdk - 🆕 XRequest 新增重连接能力。[#1629](https://github.com/ant-design/x/pull/1629) 由 [hylin](https://github.com/hylin) 提交 - 🆕 XRequest 和 XStream 支持流数据解析引入了可配置的分隔符 `streamSeparator`、`partSeparator`、`kvSeparator` 能力,同时为 TextDecoderStream 添加了 polyfill 以提高兼容性,修复了 undefined 值被添加到流结果中的问题。 [#1611](https://github.com/ant-design/x/pull/1611) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🆕 增强 XMarkdown 解析器,使其支持带占位符保护的自定义组件。[#1668](https://github.com/ant-design/x/pull/1668) 由 [yanghuanrong](https://github.com/yanghuanrong) 提交 - 🆕 新增 XMarkdown 基于 Playwright Component Testing 实现流式 Markdown 渲染的性能基准测试能力。[#1314](https://github.com/ant-design/x/pull/1314) 由 [Div627](https://github.com/Div627) 提交 - 🆕 新增 XMarkdown 流式语法对行内代码缓存的功能。[#1630](https://github.com/ant-design/x/pull/1630) 由 [Div627](https://github.com/Div627) 提交 ### 其他 - 📖 优化官网站点提升用户体验。[#1675](https://github.com/ant-design/x/pull/1675) 由 [hongxuWei](https://github.com/hongxuWei) 提交、[#1644](https://github.com/ant-design/x/pull/1644) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1658](https://github.com/ant-design/x/pull/1658) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1646](https://github.com/ant-design/x/pull/1646) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1651](https://github.com/ant-design/x/pull/1651) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1650](https://github.com/ant-design/x/pull/1650) 由 [Div627](https://github.com/Div627) 提交、[#1635](https://github.com/ant-design/x/pull/1635) 由 [IsDyh01](https://github.com/IsDyh01) 提交、[#1627](https://github.com/ant-design/x/pull/1627) 由 [Alexzjt](https://github.com/Alexzjt) 提交、[#1615](https://github.com/ant-design/x/pull/1615) 由 [Yx0201](https://github.com/Yx0201) 提交 ## 2.1.3 `2026-01-04` ### @ant-design/x - 🐛 修复了 Sender 未声明依赖问题,将 `classnames` 替换为 `clsx` 并为 `biome.json` 配置了依赖引用检查。[#1608](https://github.com/ant-design/x/pull/1608) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1605](https://github.com/ant-design/x/pull/1605) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.1.2 `2025-12-30` ### @ant-design/x - 💄 修复 Actions `disliked` 类名错误问题。[#1521](https://github.com/ant-design/x/pull/1521) 由 [kimteayon](https://github.com/kimteayon) 提交 - Sender - 🛠 整体重构 Sender 组件实现,同时修复一些细节光标问题。[#1515](https://github.com/ant-design/x/pull/1515) [#1548](https://github.com/ant-design/x/pull/1548) 由 [kimteayon](https://github.com/kimteayon) 提交 - 💄 修复 Sender 组件 actions 与 antd Button 样式冲突导致渲染错误问题。[#1535](https://github.com/ant-design/x/pull/1535) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复词槽模式 `skill` 情况下 placeholder 为空时光标太小异常的问题。[#1537](https://github.com/ant-design/x/pull/1537) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复粘贴文字时撤销栈(undo)未更新问题。[#1527](https://github.com/ant-design/x/pull/1527) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交 - 🐛 移除 Bubble.List 新消息自动滚动到最底部的逻辑,改为手动控制。[#1548](https://github.com/ant-design/x/pull/1548) 由 [anxLiang](https://github.com/anxLiang) 提交 - 💄 修复 Prompts 组件动画演示不生效问题。 [#1580](https://github.com/ant-design/x/pull/1580) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Actions.Feedback tooltip 展示异常问题。[#1591](https://github.com/ant-design/x/pull/1591) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Attachments 调用 `ref.select()` 未传参数时报错问题 [#1587](https://github.com/ant-design/x/pull/1587) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 FileCard `overflow` 展示时按钮未更新问题,以及图片展示时无 `src` 导致 Image 展示失败问题。 [#1587](https://github.com/ant-design/x/pull/1587) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-sdk - 🐛 修复 XChat 无法远程加载历史消息问题。[#1593](https://github.com/ant-design/x/pull/1593) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 OpenAIChatProvider 和 DeepSeekChatProvider 非流式请求渲染了两次内容问题。[#1593](https://github.com/ant-design/x/pull/1593) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 💄 修复 XMarkdown 动画字体颜色错误问题。[#1531](https://github.com/ant-design/x/pull/1531) 由 [Div627](https://github.com/Div627) 提交 ### 其他 - 🛠 整体的依赖重构升级。[#1448](https://github.com/ant-design/x/pull/1448) 由 [yoyo837](https://github.com/yoyo837) 提交 - 📖 优化官网站点提升用户体验。[#1508](https://github.com/ant-design/x/pull/1508) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1516](https://github.com/ant-design/x/pull/1516) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1529](https://github.com/ant-design/x/pull/1529) 由 [fireairforce](https://github.com/fireairforce) 提交、[#1549](https://github.com/ant-design/x/pull/1549) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1551](https://github.com/ant-design/x/pull/1551) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1553](https://github.com/ant-design/x/pull/1553) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1555](https://github.com/ant-design/x/pull/1555) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1543](https://github.com/ant-design/x/pull/1543) 由 [IsDyh01](https://github.com/IsDyh01) 提交、[#1558](https://github.com/ant-design/x/pull/1558) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1557](https://github.com/ant-design/x/pull/1557) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1562](https://github.com/ant-design/x/pull/1562) 由 [hustcc](https://github.com/hustcc) 提交、[#1569](https://github.com/ant-design/x/pull/1569) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1561](https://github.com/ant-design/x/pull/1561) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1584](https://github.com/ant-design/x/pull/1584) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1581](https://github.com/ant-design/x/pull/1581) 由 [teimurjan](https://github.com/teimurjan) 提交 ## 2.1.1 `2025-12-10` ### @ant-design/x - Sender - 🐛 修复发送快捷键 enter 和 shift + enter 未受 submit 按钮 disabled 状态控制的问题,修复 `onSubmit` 快捷键和按钮参数不一致问题。 [#1472](https://github.com/ant-design/x/pull/1472) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 `onChange` 缺少 `skill` 参数问题,修复词槽模式仅展示技能能力时 placeholder 未展示问题,并重构 `onChange`逻辑。[#1477](https://github.com/ant-design/x/pull/1477) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复词槽模式 `input` 类型词槽激活焦点时发送快捷键 enter 和 shift + enter 未触发问题。[#1498](https://github.com/ant-design/x/pull/1498) 由 [kimteayon](https://github.com/kimteayon) 提交 - Attachment - 🐛 修复设置 `maxCount` 后最后一个文件未上传问题。[#1486](https://github.com/ant-design/x/pull/1486) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复上传图片后 antd 报警告问题。[#1492](https://github.com/ant-design/x/pull/1492) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Mermaid 渲染抖动问题。[#1497](https://github.com/ant-design/x/pull/1497) 由 [Div627](https://github.com/Div627) 提交 - 📖 优化官网站点提升用户体验。[#1464](https://github.com/ant-design/x/pull/1464) 由 [IsDyh01](https://github.com/IsDyh01) 提交、[#1483](https://github.com/ant-design/x/pull/1483) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1463](https://github.com/ant-design/x/pull/1463) 由 [J-Da-Shi](https://github.com/J-Da-Shi) 提交、[#1489](https://github.com/ant-design/x/pull/1489) 由 [Chiaki-xps](https://github.com/Chiaki-xps) 提交、[#1499](https://github.com/ant-design/x/pull/1499) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1500](https://github.com/ant-design/x/pull/1500) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1501](https://github.com/ant-design/x/pull/1501) 由 [Samoy](https://github.com/Samoy) 提交 - 🛠 修改对 `mermaid` 的依赖配置。[#1475](https://github.com/ant-design/x/pull/1475) 由 [Div627](https://github.com/Div627) 提交 ### @ant-design/x-sdk - 🐛 优化消息流的节流与发射逻辑,避免高频流式更新导致的深度更新错误,提升实时消息稳定性与性能。[#1418](https://github.com/ant-design/x/pull/1418) 由 [Afee2019](https://github.com/Afee2019) 提交 ### @ant-design/x-markdown - 🛠 优化 `sideEffects` 配置。[#1408](https://github.com/ant-design/x/pull/1408) 由 [hongxuWei](https://github.com/hongxuWei) 提交 ## 2.1.0 `2025-12-05` ### @ant-design/x - 🐛 修复 Bubble css token `typingContent` 配置不生效问题。[#1435](https://github.com/ant-design/x/pull/1435) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复因 antd 升级到 6.0.1 导致多个组件样式丢失问题。[#1441](https://github.com/ant-design/x/pull/1441) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1446](https://github.com/ant-design/x/pull/1446) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Bubble.List 在 safari 浏览器滚动兼容性问题。[#1392](https://github.com/ant-design/x/pull/1392) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🔥 新组件 HighlightCode 和 Mermaid。[#1402](https://github.com/ant-design/x/pull/1402) 由 [Div627](https://github.com/Div627) 提交 - 🆕 Actions 新增语义化实现。[#1443](https://github.com/ant-design/x/pull/1443) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Suggestion 新增语义化实现,移除重复的 Enter 触发事件,修复 `onSubmit` 方法多次执行的问题,`onSelect` 方法新增 `selectedOptions` 完整数据返回,同时对选项的实现使用 `useMergedState` 进行了重构。[#1406](https://github.com/ant-design/x/pull/1406) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1444](https://github.com/ant-design/x/pull/1444) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Sender 新的词槽类型 `content` 和技能功能 `skill`。[#1377](https://github.com/ant-design/x/pull/1377) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-sdk - 🐛 修复 DeepSeekChatProvider 对 `` 标签格式换行处理不当导致 XMarkdown 格式渲染异常问题。[#1445](https://github.com/ant-design/x/pull/1445) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 useXChat `setMessages` 方法调用未触发渲染问题。[#1450](https://github.com/ant-design/x/pull/1450) 由 [hylin](https://github.com/hylin) 提交 - 🐛 修复 rc-util 依赖未声明问题。[#1456](https://github.com/ant-design/x/pull/1456) 由 [hylin](https://github.com/hylin) 提交 ### @ant-design/x-markdown - 🐛 替换 useStreaming 正则解决 ios 兼容性问题。[#1457](https://github.com/ant-design/x/pull/1457) 由 [Div627](https://github.com/Div627) 提交 - 📖 完善文档提升用户体验。[#1451](https://github.com/ant-design/x/pull/1451) 由 [Div627](https://github.com/Div627) 提交 - 🛠 迁移 UI 插件 HighlightCode 和 Mermaid 到 @ant-design/x 达成更合理的依赖关系。[#1402](https://github.com/ant-design/x/pull/1402) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.1 `2025-12-03` ### @ant-design/x - 🐛 修复因 antd 升级到 6.0.1 导致多个组件样式丢失问题。[#1428](https://github.com/ant-design/x/pull/1428) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Attachments 组件使用时 antd 报错问题。[#1395](https://github.com/ant-design/x/pull/1395) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Sender 组件 `allowSpeech` 自定义时 disable 错误问题。[#1398](https://github.com/ant-design/x/pull/1398) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Sender.Switch 组件语义化配置缺失问题。[#1396](https://github.com/ant-design/x/pull/1396) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🛠 修复因版本升级导致的测试用例失败。[#1393](https://github.com/ant-design/x/pull/1393) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 新增 1.x 官网链接。[#1386](https://github.com/ant-design/x/pull/1386) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1394](https://github.com/ant-design/x/pull/1394) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1384](https://github.com/ant-design/x/pull/1384) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1416](https://github.com/ant-design/x/pull/1416) 由 [IsDyh01](https://github.com/IsDyh01) 提交 ### @ant-design/x-sdk - 📖 官网目录、文档、示例全面更新。[#1419](https://github.com/ant-design/x/pull/1419) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 useXChat `requestFallback` 新增 errorInfo 参数解决无法获取接口错误数据问题。[#1419](https://github.com/ant-design/x/pull/1419) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🐛 修复插件 HighlightCode 复制代码错误问题。[#1414](https://github.com/ant-design/x/pull/1414) 由 [Jimi1126](https://github.com/Jimi1126) 提交 - 🐛 修复 XMarkdown 渲染特殊字符失败问题。[#1413](https://github.com/ant-design/x/pull/1413) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 缓存重置逻辑因旧引用未生效问题。[#1420](https://github.com/ant-design/x/pull/1420) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0 `2025-11-22` 🏆 Ant Design X 2.0.0 已发布! `@ant-design/x` - 智能界面构建框架 基于 Ant Design 设计体系的 React UI 库、专为 AI 驱动界面设计,开箱即用的智能对话组件、无缝集成 API 服务,快速搭建智能应用界面。 `@ant-design/x-markdown` - 高性能流式渲染引擎 专为流式内容优化的 Markdown 渲染解决方案、强大的扩展能力,支持公式、代码高亮、mermaid 图表等极致性能表现,确保流畅的内容展示体验。 `@ant-design/x-sdk` - AI 对话数据流管理 提供完整的工具 API 集合、开箱即用的 AI 对话应用数据流管理、简化开发流程,提升开发效率。 ##### 升级必读 🌟 我们准备了升级文档,查看[详情](/docs/react/migration-v2-cn)。 ## 2.0.0-alpha.16 `2025-11-17` ### @ant-design/x - 🛠 删除 components 属性,同时将内部属性提升。[#1338](https://github.com/ant-design/x/pull/1338) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 FileCard 新增图片生成过程以及加载、渲染能力。[#1311](https://github.com/ant-design/x/pull/1311) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Think 将 `blink` 动画样式升级为 css token。[#1318](https://github.com/ant-design/x/pull/1318) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 ThoughtChain 将 `blink` 动画样式升级为 css token。[#1318](https://github.com/ant-design/x/pull/1318) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1335](https://github.com/ant-design/x/pull/1335) 由 [kimteayon](https://github.com/kimteayon)、[#1329](https://github.com/ant-design/x/pull/1329) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🛠 使用 useMemo 优化 markdown 渲染,同时修改基本演示文本和动画演示文本。[#1337](https://github.com/ant-design/x/pull/1337) 由 [Div627](https://github.com/Div627) 提交 - 🆕 XMarkdown 渲染 HTML 标签对 `disabled` 和 `checked` 属性透出。[#1328](https://github.com/ant-design/x/pull/1328) 由 [Div627](https://github.com/Div627) 提交 - 🆕 XMarkdown `hasNextChunk` 增加对表格渲染处理的能力。[#1322](https://github.com/ant-design/x/pull/1322) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 默认的表格渲染的样式。[#1324](https://github.com/ant-design/x/pull/1324) 由 [Div627](https://github.com/Div627) 提交 - 🆕 XMarkdown `incompleteMarkdownComponentMap` 新增多个类型渲染。[#1325](https://github.com/ant-design/x/pull/1325) 由 [Div627](https://github.com/Div627) 提交 - 📖 优化官网站点提升用户体验。[#1326](https://github.com/ant-design/x/pull/1326) 由 [Div627](https://github.com/Div627)。 ## 2.0.0-alpha.15 `2025-11-07` ### @ant-design/x - 🛠 升级 antd 依赖版本到 `6.00-alpha.4`。[#1300](https://github.com/ant-design/x/pull/1300) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1303](https://github.com/ant-design/x/pull/1303) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🛠 重构 markdown 主题样式。[#1305](https://github.com/ant-design/x/pull/1305) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 `code` 标签 `streamStatus` 状态错误问题。[#1307](https://github.com/ant-design/x/pull/1307) 由 [Div627](https://github.com/Div627) 提交 - 🛠 将 `index.less` 改造为 `index.css`。[#1306](https://github.com/ant-design/x/pull/1306) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 `SteamingOption` 为 `StreamingOption`。[#1301](https://github.com/ant-design/x/pull/1301) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 dompurifyConfig.ALLOWED_TAGS 被错误合并到 ADD_TAGS 的问题。[#1297](https://github.com/ant-design/x/pull/1297) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0-alpha.13 `2025-10-30` ### @ant-design/x - 🐛 删除 Bubble.List `suffix` 属性,并通过 CSS Token 修改来 typing。[#1285](https://github.com/ant-design/x/pull/1285) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 ThoughtChain.Item 组件新增闪动效果。[#1278](https://github.com/ant-design/x/pull/1278) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Think 组件新增闪动效果。[#1278](https://github.com/ant-design/x/pull/1278) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 ThoughtChain 组件新增闪动效果。[#1286](https://github.com/ant-design/x/pull/1286) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Actions 新增 fadeIn 和 fadeInLeft 效果。[#1288](https://github.com/ant-design/x/pull/1288) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1289](https://github.com/ant-design/x/pull/1289) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Prompts 新增 fadeIn 和 fadeInLeft 效果。[#1289](https://github.com/ant-design/x/pull/1289) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1290](https://github.com/ant-design/x/pull/1290) 由 [Rain120](https://github.com/Rain120)。 ### @ant-design/x-markdown - 🐛 修复传入的 renderer link 被覆盖问题。[#1276](https://github.com/ant-design/x/pull/1276) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0-alpha.12 `2025-10-29` ### @ant-design/x - 🆕 Attachments Ref 新增 `select` 方法支持选择文件的能力,同时修复设置了最大数量,并达到了最大数量后仍显示上传按钮的问题。[#1266](https://github.com/ant-design/x/pull/1266) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1269](https://github.com/ant-design/x/pull/1269) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1274](https://github.com/ant-design/x/pull/1274) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🐛 修复 KaTeX 插件渲染失败抛出异常的问题,修改公式渲染规则减少渲染异常。[#1265](https://github.com/ant-design/x/pull/1265) 由 [Div627](https://github.com/Div627) 提交 - 📖 新增 XMarkdown 处理中文链接的代码示例。[#1270](https://github.com/ant-design/x/pull/1270) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 `code` 和 `pre` 标签渲染时返回渲染状态 `streamStatus` 以及块级标识 `block`。[#1272](https://github.com/ant-design/x/pull/1272) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复渲染 markdown 时重复的 DOM key。[#1273](https://github.com/ant-design/x/pull/1273) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0-alpha.11 `2025-10-27` ### @ant-design/x - 🆕 Sender 词槽配置改为可变属性,词槽模式下 `insert` 方法新增 `replaceCharacters` 属性入参,支持新增替换功能,同时 `focus` 方法新增词槽 `key` 的配置以支持指定词槽的 `focus` 功能。[#1259](https://github.com/ant-design/x/pull/1259) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Sources 行内模式支持指定当前激活的面板,新增 `activeKey` 属性,同时优化面板切换的交互样式,使体验更好。[#1261](https://github.com/ant-design/x/pull/1261) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 Bubble.List 对滚动条布局和实现以及语义化进行了优化。[#1263](https://github.com/ant-design/x/pull/1263) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🐛 修复 XMarkdown 自定义组件不同状态下入参结构不一致问题。[#1260](https://github.com/ant-design/x/pull/1260) 由 [Div627](https://github.com/Div627) 提交 - 📖 新增 XMarkdown 代码示例。[#1262](https://github.com/ant-design/x/pull/1262) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.0.0-alpha.10 `2025-10-23` ### @ant-design/x - 🔥 新组件 Sources。[#1250](https://github.com/ant-design/x/pull/1250) 由 [hy993658052](https://github.com/hy993658052) 提交 - 🆕 Bubble 新增 Bubble.System 和 Bubble.Divider 两个子组件。[#1239](https://github.com/ant-design/x/pull/1239) 由 [anxLiang](https://github.com/anxLiang) 和 [kimteayon](https://github.com/kimteayon) 提交 - Sender - 🆕 新增词槽焦点事件功能。[#1221](https://github.com/ant-design/x/pull/1221) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复输入框 `onPasteFile` 粘贴多文件回调数据错误问题。[#1221](https://github.com/ant-design/x/pull/1221) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 svg 未做国际化导致的无障碍问题。[#1243](https://github.com/ant-design/x/pull/1243) 由 [kimteayon](https://github.com/kimteayon) 提交 - FileCard - 🆕 新增语义化实现。[#1220](https://github.com/ant-design/x/pull/1220) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 新增 `jfif` 类型支持。[#1248](https://github.com/ant-design/x/pull/1248) 由 [IsDyh01](https://github.com/IsDyh01) 提交 - 🆕 Attachments 新增语义化实现。[#1220](https://github.com/ant-design/x/pull/1220) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1216](https://github.com/ant-design/x/pull/1216) 由 [kimteayon](https://github.com/kimteayon) 提交, [#1217](https://github.com/ant-design/x/pull/1217) 由 [Div627](https://github.com/Div627) 提交,[#1218](https://github.com/ant-design/x/pull/1218) 由 [IsDyh01](https://github.com/IsDyh01) 提交,[#1224](https://github.com/ant-design/x/pull/1224) 由 [kimteayon](https://github.com/ kimteayon) 提交,[#1232](https://github.com/ant-design/x/pull/1232) 由 [IsDyh01](https://github.com/IsDyh01) 提交,[#1233](https://github.com/ant-design/x/pull/1233) 由 [kimteayon](https://github.com/kimteayon) 提交,[#1243](https://github.com/ant-design/x/pull/1243) 由 [kimteayon](https://github.com/kimteayon) 提交,[#1247](https://github.com/ant-design/x/pull/1247) 由 [elrrrrrrr](https://github.com/elrrrrrrr) 提交 ### @ant-design/x-markdown - 🆕 XMarkdown 新增需闭合标签语法的过程中的渲染组件配置 `incomplete` 以及对应功能。[#1223](https://github.com/ant-design/x/pull/1223) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown openLinksInNewTab 属性配置失效问题。[#1253](https://github.com/ant-design/x/pull/1253) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 动画重复渲染问题。[#1255](https://github.com/ant-design/x/pull/1255) 由 [Div627](https://github.com/Div627) 提交 - 🆕 健壮 XMarkdown 对公式渲染标签识别能力。[#1255](https://github.com/ant-design/x/pull/1255) 由 [Div627](https://github.com/Div627) 提交 ### @ant-design/x-sdk - 🐛 修复 useXChat 处理流数据服务器错误导致 `requestFallback` 回调入参问题。[#1224](https://github.com/ant-design/x/pull/1224) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 useXConversations 新增 activeConversationKey 的实现。[#1252](https://github.com/ant-design/x/pull/1252) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 useXChat `isRequesting` 非多实例问题,以及优化 `requestPlaceholder` 和 `requestFallback` 回调入参。[#1254](https://github.com/ant-design/x/pull/1254) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.0.0-alpha.9 `2025-09-24` ### @ant-design/x-markdown - 🐛 修复代码高亮插件样式丢失、组件无法匹配嵌套子元素的问题,并移除默认样式中的 table text-align 属性。[#1212](https://github.com/ant-design/x/pull/1212) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0-alpha.8 `2025-09-22` ### @ant-design/x - Bubble - 🆕 Bubble.List 新增 `extra` 参数,配合 useXChat 已支持自定义功能。[#1195](https://github.com/ant-design/x/pull/1195) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 `loading` 状态下内容高度被固定问题。[#1178](https://github.com/ant-design/x/pull/1178) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复组件类型导出命名错误问题。[#1182](https://github.com/ant-design/x/pull/1182) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 ThoughtChain.Item 组件类型导出命名错误问题。[#1178](https://github.com/ant-design/x/pull/1178) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 XProvider 监听组件缺少问题。[#1178](https://github.com/ant-design/x/pull/1178) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🛠 重构动画相关实现。[#1198](https://github.com/ant-design/x/pull/1198) 由 [Div627](https://github.com/Div627) 提交、[#1204](https://github.com/ant-design/x/pull/1204) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复插件导出类型错误问题,以及新增示例和文档[#1187](https://github.com/ant-design/x/pull/1187) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 Mermaid 插件切换时渲染异常。[#1175](https://github.com/ant-design/x/pull/1175) 由 [Div627](https://github.com/Div627) 提交 - 🆕 补充 HighlightCode 插件和 Mermaid 插件语义化实现。[#1178](https://github.com/ant-design/x/pull/1178) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 XMarkdown 主题样式覆盖不全问题。 [#1182](https://github.com/ant-design/x/pull/1182) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-sdk - 🆕 useXChat `setMessage` 支持使用回调函数支持获取原始消息,同时 `onRequest` 和 `onReload` 新增 `extra` 参数以支持自定义功能。 [#1195](https://github.com/ant-design/x/pull/1195) 由 [kimteayon](https://github.com/kimteayon) 提交 ### 其他 - 🆕 更新站点整体文档。 [#1194](https://github.com/ant-design/x/pull/1194) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 更新样板间功能,新增'现代感'样板间。 [#1184](https://github.com/ant-design/x/pull/1184) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1195](https://github.com/ant-design/x/pull/1195) 由 [kimteayon](https://github.com/kimteayon) 提交、 [#1194](https://github.com/ant-design/x/pull/1194) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1170](https://github.com/ant-design/x/pull/1170) 由 [jinyang](https://github.com/jinyang) 提交、[#1186](https://github.com/ant-design/x/pull/1186) 由 [jinyang](https://github.com/jinyang) 提交、[#1192](https://github.com/ant-design/x/pull/1192) 由 [iamkun-2](https://github.com/iamkun-2) 提交、[#1193](https://github.com/ant-design/x/pull/1193) 由 [iamkun-2](https://github.com/iamkun-2) 提交、[#1197](https://github.com/ant-design/x/pull/1197) 由 [elrrrrrrr](https://github.com/elrrrrrrr) 提交、[#1199](https://github.com/ant-design/x/pull/1199) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0-alpha.7 `2025-09-14` ### @ant-design/x - Bubble - 💄 修复默认 `white-space` 样式问题。[#1147](https://github.com/ant-design/x/pull/1147) 由 [kimteayon](https://github.com/kimteayon) 提交 - 💄 修复语义化缺失以及 `loading` 状态下在 Bubble.List 下高度错误问题。[#1162](https://github.com/ant-design/x/pull/1162) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复类型导出和文档引入错误问题。[#1160](https://github.com/ant-design/x/pull/1160) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 删除下线工具 `useXAgent` 和 `useXChat`,以及对应的文档引用删除或者替换为 `X SDK`。[#1148](https://github.com/ant-design/x/pull/1148) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 FileCard 组件 `status` 展示缺失问题。[#1156](https://github.com/ant-design/x/pull/1156) 由 [hy993658052](https://github.com/hy993658052) 提交 - 🐛 修复 Sender 组件开启文件粘贴功能时无法粘贴 Excel 单元格文本数据问题。[#1167](https://github.com/ant-design/x/pull/1167) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🆕 新增 Mermaid 插件操作功能。[#1135](https://github.com/ant-design/x/pull/1135) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 流式效果。[#1135](https://github.com/ant-design/x/pull/1135) 由 [Div627](https://github.com/Div627) 提交 - 🆕 新增插件国际化和主题定制功能,以及文档升级。[#1135](https://github.com/ant-design/x/pull/1135) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 新增 XMarkdown 链接 `openLinksInNewTab` 配置、以及主题颜色调整。[#1164](https://github.com/ant-design/x/pull/1164) 由 [Div627](https://github.com/Div627) 提交 - 🐛 修复 XMarkdown 与文档 markdown 样式冲突问题。[#1161](https://github.com/ant-design/x/pull/1161) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-sdk - 🛠 重构 useXChat 工具 `isRequesting` 属性,由方法升级为可监控变量。[#1168](https://github.com/ant-design/x/pull/1168) 由 [hylin](https://github.com/hylin) 提交 - 🆕 新增 useXChat 工具消息 `abort` 状态,同时修复 `requestFallback` 回调方法 `message` 参数错误以及删掉对错误状态的消息过滤。[#1171](https://github.com/ant-design/x/pull/1171) 由 [kimteayon](https://github.com/kimteayon) 提交 ### 其他 - 📖 优化官网站点提升用户体验。[#1169](https://github.com/ant-design/x/pull/1169) 由 [hylin](https://github.com/hylin) 提交 - 📖 更新官网介绍、模型接入、百宝箱智能体接入、X SDK 等文档,以及样板间代码更新。[#1171](https://github.com/ant-design/x/pull/1171) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.0.0-alpha.6 `2025-08-28` ### @ant-design/x - 🐛 修复 Sender 普通模式点击 `Enter` 选中文候选词时触发 `Submit` 的问题。[#1144](https://github.com/ant-design/x/pull/1144) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Sender 词槽模式 `submitType` 为 `shiftEnter` 时无法换行问题。[#1143](https://github.com/ant-design/x/pull/1143) 由 [kimteayon](https://github.com/kimteayon) 提交 - 💄 修复 ThoughtChain.Item `description` 内容过多换行后 `margin` 样式异常。由 [kimteayon](https://github.com/kimteayon) 提交 - 🛠 使用 `@ant-design/x-sdk` 重构样板间。[#1139](https://github.com/ant-design/x/pull/1139) 由 [hylin](https://github.com/hylin) 提交 - 🐛 修复 Bubble `prefix` 持续展示。[#1137](https://github.com/ant-design/x/pull/1137) 由 [anxLiang](https://github.com/anxLiang) 提交 - 📖 补充 Bubble.List 文档解释滚动容器问题。[#1133](https://github.com/ant-design/x/pull/1133) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🐛 修复 Attachment 组件上传图片未展示图片问题。[#1140](https://github.com/ant-design/x/pull/1140) 由 [hy993658052](https://github.com/hy993658052) 提交 - 🐛 修复 FileCard 语义化问题以及卡片大小展示问题。[#1130](https://github.com/ant-design/x/pull/1130) 由 [kimteayon](https://github.com/kimteayon) 提交 ### 其他 - 📦 升级 father 配置。[#1125](https://github.com/ant-design/x/pull/1125) 由 [fireairforce](https://github.com/fireairforce) 提交 - 📖 优化官网站点提升用户体验。[#1142](https://github.com/ant-design/x/pull/1142) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.0.0-alpha.5 `2025-08-20` ### @ant-design/x - 🆕 新增 Actions 子组件功能,Actions.Copy、Actions.Audio、Actions.Item。[#1121](https://github.com/ant-design/x/pull/1121) 由 [kimteayon](https://github.com/kimteayon) 提交 - Bubble - 🆕 新增 `string content` 时渲染带换行符、制表符的功能。[#1127](https://github.com/ant-design/x/pull/1127) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🆕 新增语义化实现。[#1116](https://github.com/ant-design/x/pull/1116) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 优化样式和类型问题。[#1108](https://github.com/ant-design/x/pull/1108) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🆕 新增 Sender 组件语义化配置。[#1116](https://github.com/ant-design/x/pull/1116) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-sdk - 🛠 整体优化 X SDK。[#1114](https://github.com/ant-design/x/pull/1114) 由 [hylin](https://github.com/hylin) 提交 ### 其他 - 📖 使用 X SDK 重构样板间。[#1139](https://github.com/ant-design/x/pull/1139) 由 [hylin](https://github.com/hylin) 提交 - 📖 优化官网站点提升用户体验。[#1124](https://github.com/ant-design/x/pull/1124) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1123](https://github.com/ant-design/x/pull/1123) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🛠 发布链路优化。[#1115](https://github.com/ant-design/x/pull/1115) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.0.0-alpha.3 `2025-08-14` ### @ant-design/x-markdown - 🛠 优化 version 逻辑以及配置、文档。[#1112](https://github.com/ant-design/x/pull/1112) 由 [Div627](https://github.com/Div627) 提交 ## 2.0.0-alpha.1 `2025-08-12` ### @ant-design/x - 🛠 重构升级组件 Bubble。[#1100](https://github.com/ant-design/x/pull/1100) 由 [anxLiang](https://github.com/anxLiang) 提交、[#1077](https://github.com/ant-design/x/pull/1077) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🛠 重构升级组件 Bubble.List。[#1077](https://github.com/ant-design/x/pull/1077) 由 [anxLiang](https://github.com/anxLiang) 提交 - 🐛 修复 Bubble 组件 `readOnly` 和 `loading` 逻辑不生效问题。[#1101](https://github.com/ant-design/x/pull/1101) 由 [kimteayon](https://github.com/kimteayon) 提交 ### 其他 - 🛠 发布链路优化。[#1098](https://github.com/ant-design/x/pull/1098) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1009](https://github.com/ant-design/x/pull/1009) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1087](https://github.com/ant-design/x/pull/1087) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 2.0.0-alpha.0 `2025-08-05` ### @ant-design/x - 🔥 新组件 FileCard。[#1094](https://github.com/ant-design/x/pull/1094) 由 [hy993658052](https://github.com/hy993658052) 提交 - 🔥 新组件 Notification。[#973](https://github.com/ant-design/x/pull/973) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🔥 新组件 Think。[#970](https://github.com/ant-design/x/pull/970) [#966](https://github.com/ant-design/x/pull/966) [#946](https://github.com/ant-design/x/pull/946) 由 [hy993658052](https://github.com/hy993658052) 提交 - 🛠 重构升级组件 Attachments。 - 🛠 重构升级组件 Actions。[#994](https://github.com/ant-design/x/pull/994) 由 [vanndxh](https://github.com/vanndxh) 提交 - 🛠 重构升级组件 Conversations。[#937](https://github.com/ant-design/x/pull/937) [#954](https://github.com/ant-design/x/pull/954) [#955](https://github.com/ant-design/x/pull/955) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🛠 重构升级组件 Sender。[#1073](https://github.com/ant-design/x/pull/1073) 由 [kimteayon](https://github.com/kimteayon) 提交、[#962](https://github.com/ant-design/x/pull/962) 由 [Chuck-Ray](https://github.com/Chuck-Ray) 提交 - 🛠 重构升级组件 ThoughtChain。[#985](https://github.com/ant-design/x/pull/985) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 全部组件 `Ref` 功能补全。[#1081](https://github.com/ant-design/x/pull/1081) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 XProvider 组件国际化逻辑接入。[#952](https://github.com/ant-design/x/pull/952) 由 [kimteayon](https://github.com/kimteayon) 提交 ### @ant-design/x-markdown - 🔥 新组件 XMarkdown。[#1060](https://github.com/ant-design/x/pull/1060) 由 [Div627](https://github.com/Div627) 提交、[#989](https://github.com/ant-design/x/pull/989) 由 [Div627](https://github.com/Div627) 提交 - 🔥 新插件 Latex。[#1060](https://github.com/ant-design/x/pull/1060) 由 [Div627](https://github.com/Div627) 提交、[#989](https://github.com/ant-design/x/pull/989) 由 [Div627](https://github.com/Div627) 提交 - 🔥 新插件 HighlightCode。[#1060](https://github.com/ant-design/x/pull/1060) 由 [Div627](https://github.com/Div627) 提交、[#989](https://github.com/ant-design/x/pull/989) 由 [Div627](https://github.com/Div627) 提交 - 🔥 新插件 Mermaid。[#1060](https://github.com/ant-design/x/pull/1060) 由 [Div627](https://github.com/Div627) 提交、[#989](https://github.com/ant-design/x/pull/989) 由 [Div627](https://github.com/Div627) 提交 ### @ant-design/x-sdk - 🔥 新工具 useXChat。[#1098](https://github.com/ant-design/x/pull/1098) 由 [hylin](https://github.com/hylin) 提交 - 🔥 新工具 useXConversations。[#1098](https://github.com/ant-design/x/pull/1098) 由 [hylin](https://github.com/hylin) 提交 - 🔥 新工具 Chat Provider。[#1098](https://github.com/ant-design/x/pull/1098) 由 [hylin](https://github.com/hylin) 提交 - 🔥 新工具 XRequest。[#1098](https://github.com/ant-design/x/pull/1098) 由 [hylin](https://github.com/hylin) 提交 - 🔥 新工具 XStream。[#1098](https://github.com/ant-design/x/pull/1098) 由 [hylin](https://github.com/hylin) 提交 ### 其他 - 🛠 整体框架升级为 Monorepo。[#823](https://github.com/ant-design/x/pull/823) 由 [elrrrrrrr](https://github.com/elrrrrrrr) 提交 - 🛠 整体组件升级 Ant Design V6。[#1012](https://github.com/ant-design/x/pull/1012) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🛠 Ant Design X 发布逻辑升级调整。[#1098](https://github.com/ant-design/x/pull/1098) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1009](https://github.com/ant-design/x/pull/1009) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#1083](https://github.com/ant-design/x/pull/1083) 由 [kimteayon](https://github.com/kimteayon) 提交、[#1001](https://github.com/ant-design/x/pull/1001) 由 [elrrrrrrr](https://github.com/elrrrrrrr) 提交 ## 1.6.1 `2025-09-12` - 🐛 修复 ThoughtChain 组件 `title` 传入 `ReactNode` 时折叠标题无法显示问题。[#1172](https://github.com/ant-design/x/pull/1172) 由 [IsDyh01](https://github.com/IsDyh01) 提交 - 🐛 修复 Sender 组件 `LoadingButton` 传入 `icon` 属性时同时显示两个图标问题。[#1145](https://github.com/ant-design/x/pull/1145) 由 [IsDyh01](https://github.com/IsDyh01) 提交 - 🐛 修复 Sender 组件 `content` 语义化缺失问题。[#703](https://github.com/ant-design/x/pull/703) 由 [HomyeeKing](https://github.com/HomyeeKing) 提交 - 🐛 移除 Bubble 组件打字效果公共前缀逻辑中的冗余条件判断。[#1091](https://github.com/ant-design/x/pull/1091) 由 [AqingCyan](https://github.com/AqingCyan) 提交 - 🐛 修复 useXChat `updating` 状态缺失问题。[#833](https://github.com/ant-design/x/pull/833) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交 - 🐛 修复 Suggestion 组件 `useActive` 中 items 为空数组导致的异常。[#824](https://github.com/ant-design/x/pull/824) 由 [LengYXin](https://github.com/LengYXin) 提交 - 📖 优化官网站点提升用户体验。[#960](https://github.com/ant-design/x/pull/960) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交、[#1048](https://github.com/ant-design/x/pull/1048) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交、[#1118](https://github.com/ant-design/x/pull/1118) 由 [afc163](https://github.com/afc163) 提交、[#1122](https://github.com/ant-design/x/pull/1122) 由 [fireairforce](https://github.com/fireairforce) 提交、[#1120](https://github.com/ant-design/x/pull/1120) 由 [IsDyh01](https://github.com/IsDyh01) 提交 ## 1.6.0 `2025-07-30` - 🆕 Attachments 组件 `FileCard` 新增图标和类型的配置能力。[#1006](https://github.com/ant-design/x/pull/1006) 由 [kieranwv](https://github.com/kieranwv) 提交 - 📖 新增百宝箱智能体接入文档和样板间。[#1063](https://github.com/ant-design/x/pull/1063) 由 [iamkun-2](https://github.com/iamkun-2) 提交 - 📖 优化官网站点提升用户体验。[#1054](https://github.com/ant-design/x/pull/1054) 由 [hylin](https://github.com/hylin) 提交、[#1056](https://github.com/ant-design/x/pull/1056) 由 [hylin](https://github.com/hylin) 提交 ## 1.5.0 `2025-07-16` - 🆕 补充 Bubble 组件对滚动事件 `onScroll` 的监听。[#1021](https://github.com/ant-design/x/pull/1021) 由 [QdabuliuQ](https://github.com/QdabuliuQ) 提交 - 🐛 移除 Bubble 重复的 TS 类型定义。[#1032](https://github.com/ant-design/x/pull/1032) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交 - 🐛 修复 Conversations 组件点击禁用的 `menu` 导致触发 `onActiveChange` 的问题。[#1024](https://github.com/ant-design/x/pull/1024) 由 [QdabuliuQ](https://github.com/QdabuliuQ) 提交 - 🐛 修复 Attachments 组件 `FileList` 语义化配置。[#1017](https://github.com/ant-design/x/pull/1017) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 补充 Actions 组件 html 配置。[#995](https://github.com/ant-design/x/pull/995) 由 [vanndxh](https://github.com/vanndxh) 提交 - 🐛 修复 Conversations label 标签展示问题,同时补充语义化配置。[#898](https://github.com/ant-design/x/pull/898) 由 [yuanliu147](https://github.com/yuanliu147) 提交 - 📖 优化官网站点提升用户体验。[#940](https://github.com/ant-design/x/pull/940) 由 [coding-ice](https://github.com/coding-ice) 提交、[#969](https://github.com/ant-design/x/pull/969) 由 [afc163](https://github.com/afc163) 提交、[#968](https://github.com/ant-design/x/pull/968) 由 [afc163](https://github.com/afc163) 提交、[#1019](https://github.com/ant-design/x/pull/1019) 由 [hylin](https://github.com/hylin) 提交、[#1036](https://github.com/ant-design/x/pull/1036) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 1.4.0 `2025-05-30` - 🔥 新组件 操作列表 - Actions。[#768](https://github.com/ant-design/x/pull/768) 由 [vanndxh](https://github.com/vanndxh) 提交 - 🐛 修复 Bubble.List `footer` 和 `header` 无法获取 key 的问题。[#876](https://github.com/ant-design/x/pull/876) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Conversations 列表标题溢出截断失效问题。[#877](https://github.com/ant-design/x/pull/877) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#816](https://github.com/ant-design/x/pull/816) 由 [Rain120](https://github.com/Rain120) 提交、[#880](https://github.com/ant-design/x/pull/880) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 1.3.0 `2025-05-21` - 📖 新增 Conversation 类型导出。[#258](https://github.com/ant-design/x/pull/258) 由 [ONLY-yours](https://github.com/ONLY-yours) 提交 - 💄 修复 Prompts 滚动条始终显示问题。[#785](https://github.com/ant-design/x/pull/785) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Suggestion 警告使用 antd 废弃 API `onDropdownVisibleChange` 的问题。[#827](https://github.com/ant-design/x/pull/827) 由 [zombieJ](https://github.com/zombieJ) 提交 - 🆕 扩展 Bubble `content` 到 `footer` 和 `header` 的方法实现参数,同时补充 Demo 实现。[#683](https://github.com/ant-design/x/pull/683) 由 [L-Hknu](https://github.com/L-Hknu) 和 [kimteayon](https://github.com/kimteayon) 提交 - 📖 修复 Api Key 在站点露出的安全问题。[#840](https://github.com/ant-design/x/pull/840) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化官网站点提升用户体验。[#783](https://github.com/ant-design/x/pull/783) 由 [kimteayon](https://github.com/kimteayon) 提交、[#229](https://github.com/ant-design/x/pull/229) 由 [afc163](https://github.com/afc163) 提交、[#835](https://github.com/ant-design/x/pull/835) 由 [kimteayon](https://github.com/kimteayon) 、[#814](https://github.com/ant-design/x/pull/814) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交 ## 1.2.0 `2025-04-25` - 🐛 删除 Conversations 溢出省略逻辑修复 `tooltip` 展示错误的问题。[#776](https://github.com/ant-design/x/pull/776) 由 [afc163](https://github.com/afc163) 提交 - 🐛 修复 Attachments `image` 卡片样式问题。[#751](https://github.com/ant-design/x/pull/751) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交 - 🐛 修复 ThoughtChain 受控问题。[#752](https://github.com/ant-design/x/pull/752) 由 [Youzi2233](https://github.com/Youzi2233) 提交 - XRequest - 🆕 XRequestCallbacks 新增 `onStream` 回调,可对流监听和终止操作。[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 XRequestOptions 变更不生效问题,并新增示例。[#736](https://github.com/ant-design/x/pull/736) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 新增模型接入示例。[#725](https://github.com/ant-design/x/pull/725) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 优化 API 方法参数命名不准确问题。[#736](https://github.com/ant-design/x/pull/736) 由 [kimteayon](https://github.com/kimteayon) 提交 - useXAgent - 🆕 RequestFn 新增 `onStream` 回调,可对流监听和终止操作。[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 RequestFn 新增 `transformStream` 转换函数,用于处理流数据。[#725](https://github.com/ant-design/x/pull/725) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 XAgentConfigPreset 变更不生效问题,并新增示例。[#736](https://github.com/ant-design/x/pull/736) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 RequestFn `onSuccess` 回调类型错误问题,同时更新对应示例。[#725](https://github.com/ant-design/x/pull/725) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 新增模型接入、自定义入参、变更配置示例。[#725](https://github.com/ant-design/x/pull/725) 由 [kimteayon](https://github.com/kimteayon) 提交、[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - useXChat - 🆕 XChatConfig 新增 Input 和 Output 泛型类型。[#725](https://github.com/ant-design/x/pull/725) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 XChatConfig 新增 `transformMessage` 转换函数,可在更新数据时对 `messages` 做转换,同时会更新到 `messages`。[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 XChatConfig 新增 `transformStream` 转换函数,用于处理流数据。[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 XChatConfig 新增 `resolveAbortController` 回调函数,可获得 `AbortController` 控制器,用于控制流状态。[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 新增模型接入示例,删除错误的终止流示例。[#711](https://github.com/ant-design/x/pull/711) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Sender `header` 圆角样式溢出问题。[#732](https://github.com/ant-design/x/pull/732) 由 [Bao0630](https://github.com/Bao0630) 提交 - 📖 新增助手式样板间。[#657](https://github.com/ant-design/x/pull/657) 由 [vanndxh](https://github.com/vanndxh) 提交 - 📖 重构独立式样板间。[#753](https://github.com/ant-design/x/pull/753) 由 [vanndxh](https://github.com/vanndxh) 提交 - 📖 优化官网站点提升用户体验。[#730](https://github.com/ant-design/x/pull/730) 由 [afc163](https://github.com/afc163) 提交、[#758](https://github.com/ant-design/x/pull/758) 由 [coding-ice](https://github.com/coding-ice) 提交、 [#761](https://github.com/ant-design/x/pull/761) 由 [ONLY-yours](https://github.com/ONLY-yours) 提交 ## 1.1.1 `2025-04-14` - Bubble.List - 💄 优化 Bubble.List 更新时减少不必要的刷新。[#479](https://github.com/ant-design/x/pull/479) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🐛 修复 Bubble.List 暗黑主题下滚动条样式不兼容问题。[#727](https://github.com/ant-design/x/pull/727) 由 [kimteayon](https://github.com/kimteayon) 提交 - Conversation - 🐛 修复 Conversation 内 ul 和 li 的样式问题。[#726](https://github.com/ant-design/x/pull/726) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 新增 `menu` 的 `getPopupContainer` 的实现。[#698](https://github.com/ant-design/x/pull/698) 由 [yuxuan-ctrl](https://github.com/yuxuan-ctrl) 提交 - 🐛 修复 ThoughtChain 折叠面板无法展开问题。[#720](https://github.com/ant-design/x/pull/720) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🐛 修复 Attachments 图片展示样式问题。[#708](https://github.com/ant-design/x/pull/708) 由 [hy993658052](https://github.com/hy993658052) 提交 - 💄 优化 Sender,使自定义 Actions 的 `disabled` 属性受控。[#666](https://github.com/ant-design/x/pull/666) 由 [afc163](https://github.com/afc163) 提交 - 📖 优化官网站点提升用户体验。[#680](https://github.com/ant-design/x/pull/680) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交、[#699](https://github.com/ant-design/x/pull/699) 由 [afc163](https://github.com/afc163) 提交、[#716](https://github.com/ant-design/x/pull/716) 由 [afc163](https://github.com/afc163) 提交、[#686](https://github.com/ant-design/x/pull/686) 由 [afc163](https://github.com/afc163) 提交、[#728](https://github.com/ant-design/x/pull/728) 由 [kimteayon](https://github.com/kimteayon) 提交 ## 1.1.0 `2025-03-28` - Sender - 🆕 新增 `footer` 支持自定义底部内容。[#654](https://github.com/ant-design/x/pull/654) 由 [kimteayon](https://github.com/kimteayon) 提交 - 🆕 扩展 `autoSize` 支持配置内容高度。[#637](https://github.com/ant-design/x/pull/637) 由 [Zhang-Wei-666](https://github.com/Zhang-Wei-666) 提交 - 📖 补充 `onFocus` 和 `onBlur` 类型声明。[#625](https://github.com/ant-design/x/pull/625) 由 [aojunhao123](https://github.com/aojunhao123) 提交 - 🆕 扩展 Conversations 组件 `menu.trigger` 支持自定义菜单触发器。[#630](https://github.com/ant-design/x/pull/630) 由 [kimteayon](https://github.com/kimteayon) 提交 - Attachments - 🆕 扩展 `ImageProps` 支持自定义图像展示配置。[#613](https://github.com/ant-design/x/pull/613) 由 [hy993658052](https://github.com/hy993658052) 提交 - 📖 补充 Attachments 组件 `onRemove` API 文档。[#608](https://github.com/ant-design/x/pull/608) 由 [kimteayon](https://github.com/kimteayon) 提交 - 📖 补充 `GPT-Vis` 渲染图表示例。[#603](https://github.com/ant-design/x/pull/603) 由 [lvisei](https://github.com/lvisei) 提交 - 📦 优化 Chat Design X `peerDependencies`。[#611](https://github.com/ant-design/x/pull/611) 由 [pokerface9830](https://github.com/pokerface9830) 提交 - 📖 优化官网站点提升用户体验。[#626](https://github.com/ant-design/x/pull/626) 由 [aojunhao123](https://github.com/aojunhao123) 提交、[#648](https://github.com/ant-design/x/pull/648) 由 [kimteayon](https://github.com/kimteayon) 提交、[#659](https://github.com/ant-design/x/pull/659) 由 [afc163](https://github.com/afc163) 提交、[#667](https://github.com/ant-design/x/pull/667) 由 [jin19980928](https://github.com/jin19980928) 提交 ## 1.0.6 `2025-03-14` - 🆕 扩展 `Sender` 文件粘贴可处理多个文件。[#505](https://github.com/ant-design/x/pull/500) 由 [ztkuaikuai](https://github.com/ztkuaikuai) 提交 - 🆕 扩展 `BubbleList` 角色定义功能。[#500](https://github.com/ant-design/x/pull/500) 由 [chenluda](https://github.com/chenluda) 提交 - 🐛 修复 `Attachments` 组件多文件横向滚动条展示。[#556](https://github.com/ant-design/x/pull/556) 由 [onefeng123](https://github.com/onefeng123) 提交 - 🐛 修复 `Attachments` 组件 onRemove 不生效问题。[#555](https://github.com/ant-design/x/pull/555) 由 [edison-tianhe](https://github.com/edison-tianhe) 提交 - 🐛 修复 `Sender` 组件 actions 缺少 SpeechButton 组件的问题。[#549](https://github.com/ant-design/x/pull/549) 由 [zombieJ](https://github.com/zombieJ) 提交 - 🐛 修复 `Attachments` 组件文件初始化展示问题。[#524](https://github.com/ant-design/x/pull/524) 由 [ztkuaikuai](https://github.com/ztkuaikuai) 提交 - 🐛 修复 `Conversations` 组件滚动条问题。[#485](https://github.com/ant-design/x/pull/485) 由 [LofiSu](https://github.com/LofiSu) 提交 - 📖 优化 `Bubble` 组件 typing 减少不必要的渲染。[#477](https://github.com/ant-design/x/pull/477) 由 [kxcy001123](https://github.com/kxcy001123) 提交 - 📦 优化 Chat Design X 构建 [#578](https://github.com/ant-design/x/pull/578),[#584](https://github.com/ant-design/x/pull/584) 由 [kimteayon](https://github.com/kimteayon) 提交、 [#578](https://github.com/ant-design/x/pull/578) 由 [kimteayon](https://github.com/kimteayon) 提交、[#587](https://github.com/ant-design/x/pull/587) 由 [afc163](https://github.com/afc163) 提交 - 📖 优化官网站点提升用户体验。[#484](https://github.com/ant-design/x/pull/484) 由 [ztkuaikuai](https://github.com/ztkuaikuai) 提交、 [#495](https://github.com/ant-design/x/pull/495) 由 [ztkuaikuai](https://github.com/ztkuaikuai) 提交、 [#522](https://github.com/ant-design/x/pull/522) 由 [liangchaofei](https://github.com/liangchaofei) 提交、[#537](https://github.com/ant-design/x/pull/537) 由 [wzc520pyfm](https://github.com/wzc520pyfm) 提交、 [#553](https://github.com/ant-design/x/pull/553) 由 [PeachScript](https://github.com/PeachScript) 提交、 [#578](https://github.com/ant-design/x/pull/578) 由 [kimteayon](https://github.com/kimteayon) 提交 、 [#585](https://github.com/ant-design/x/pull/585) 由 [MaricoHan](https://github.com/MaricoHan) 提交 ## 1.0.5 `2025-01-13` - 🐛 修复 `Attachment` 组件移除图标的样式问题。[#460](https://github.com/ant-design/x/pull/460) 由 [Rain120](https://github.com/Rain120) 提交 - 🛠 重构 `BubbleProps`,支持 `ContentType` 类型参数。[#403](https://github.com/ant-design/x/pull/403) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🛠 开发环境和网站支持 React 19。[#432](https://github.com/ant-design/x/pull/432) 由 [YumoImer](https://github.com/YumoImer) 提交 - 📖 优化官网站点提升用户体验。[#456](https://github.com/ant-design/x/pull/456), [#446](https://github.com/ant-design/x/pull/446), [#448](https://github.com/ant-design/x/pull/448), [#444](https://github.com/ant-design/x/pull/444), [#414](https://github.com/ant-design/x/pull/414), [#406](https://github.com/ant-design/x/pull/406), [#404](https://github.com/ant-design/x/pull/404) 由 [wzc520pyfm](https://github.com/wzc520pyfm), [YumoImer](https://github.com/YumoImer), [Rain120](https://github.com/Rain120), [afc163](https://github.com/afc163) 提交 ## 1.0.4 `2024-12-25` - 🆕 扩展 `XStream` 对取消功能的支持。[#319](https://github.com/ant-design/x/pull/319) 由 [ppbl](https://github.com/ppbl) 提交 - 🆕 扩展 `Bubble` 对 `typing.suffix` 打字后缀的支持。[#316](https://github.com/ant-design/x/pull/316) 由 [BQXBQX](https://github.com/BQXBQX) 提交 - 🆕 扩展 `Sender` 组件 `onChange` 对 `event` 事件参数的支持。[#362](https://github.com/ant-design/x/pull/362) 由 [defaultjacky](https://github.com/defaultjacky) 提交 - 🆕 扩展 `Sender` 组件 `ref` 对 `focus`、`blur` 等焦点控制能力的支持。[#397](https://github.com/ant-design/x/pull/397) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🐛 修复 `ThoughtChain` 在非 cssVar 下的样式问题。[#373](https://github.com/ant-design/x/pull/373) 由 [YumoImer](https://github.com/YumoImer) 提交 - 📖 添加 `Petercat` 助理功能。[#375](https://github.com/ant-design/x/pull/375) 由 [xingwanying](https://github.com/xingwanying) 提交 - 📖 优化官网站点提升用户体验。[#389](https://github.com/ant-design/x/pull/389)、[#377](https://github.com/ant-design/x/pull/377)、[#364](https://github.com/ant-design/x/pull/364)、[#368](https://github.com/ant-design/x/pull/368) 由 [afc163](https://github.com/afc163)、[YumoImer](https://github.com/YumoImer) 提交 ## 1.0.3 `2024-12-16` - 💄 优化 `Bubble` 设置 `placement: 'end'` 后的样式。[#314](https://github.com/ant-design/x/pull/314) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🐛 修复 `Bubble.List` 设置 `autoScroll` 后偶现无法触发自动滚动的问题。[#336](https://github.com/ant-design/x/pull/336) 由 [anzhou99Ru](https://github.com/anzhou99Ru) 提交 - 📖 优化官网站点提升用户体验。[#343](https://github.com/ant-design/x/pull/343)、[#334](https://github.com/ant-design/x/pull/334)、[#315](https://github.com/ant-design/x/pull/315)、[#331](https://github.com/ant-design/x/pull/331) 由 [afc163](https://github.com/afc163)、[YumoImer](https://github.com/YumoImer)、[Wxh16144](https://github.com/Wxh16144) 提交 - 🛠 修复 `pnpm lint` 时的错误。[#313](https://github.com/ant-design/x/pull/313) 由 [BQXBQX](https://github.com/BQXBQX) 提交 ## 1.0.2 `2024-12-04` - 🛠 优化 `XRequest` 支持对自定义协议解析。[#293](https://github.com/ant-design/x/pull/293) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🐛 修复 `Attachment` 前后预览按钮无法正常显隐的问题。[#295](https://github.com/ant-design/x/pull/295) 由 [anzhou99](https://github.com/anzhou99) 提交 - 🐛 修复 `useXChat` 对同一条消息重复触发 `onUpdate` 的问题。[#298](https://github.com/ant-design/x/pull/298) 由 [YumoImer](https://github.com/YumoImer) 提交 - 📖 添加 `Bubble` 配合 `GPT-Vis` 的使用演示文档。[#288](https://github.com/ant-design/x/pull/288) 由 [lvisei](https://github.com/lvisei) 提交 - 📦 更新浏览器目标配置减少打包体积。[#282](https://github.com/ant-design/x/pull/282) 由 [afc163](https://github.com/afc163) 提交 - 🛠 修复运行 `pnpm run prestart` 的错误。[#287](https://github.com/ant-design/x/pull/287) 由 [long36708](https://github.com/long36708) 提交 ## 1.0.1 `2024-11-29` - 🛠 优化 `useXAgent` 和 `XStream` 的 TS 类型。[#272](https://github.com/ant-design/x/pull/272) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🛠 调整 `agent` 参数设为可选,以支持仅使用 `useXChat` 的数据管理功能。[#271](https://github.com/ant-design/x/pull/271) 由 [YumoImer](https://github.com/YumoImer) 提交 - 💄 调整 `Conversations` 样式基于 RICH 设计规范。[#242](https://github.com/ant-design/x/pull/242) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🛠 修复使用 `pnpm` 启动项目时幽灵依赖导致无法启动的问题。[#223](https://github.com/ant-design/x/pull/223) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🌈 独立式样板间支持附件上传功能演示。[#250](https://github.com/ant-design/x/pull/250)、[#265](https://github.com/ant-design/x/pull/265) 由 [kelvinelove](https://github.com/kelvinelove) 提交 - 📖 修复缺失的贡献者信息。[#212](https://github.com/ant-design/x/pull/212) 由 [afc163](https://github.com/afc163) 提交 - 📖 优化官网站点提升用户体验。[#277](https://github.com/ant-design/x/pull/277)、[#264](https://github.com/ant-design/x/pull/264)、[#263](https://github.com/ant-design/x/pull/263)、[#262](https://github.com/ant-design/x/pull/262)、[#261](https://github.com/ant-design/x/pull/261)、[#241](https://github.com/ant-design/x/pull/241)、[#246](https://github.com/ant-design/x/pull/246)、[#210](https://github.com/ant-design/x/pull/210)、[#211](https://github.com/ant-design/x/pull/211) 由 [YumoImer](https://github.com/YumoImer)、[afc163](https://github.com/afc163)、[Rain-1214](https://github.com/Rain-1214)、[kelvinelove](https://github.com/kelvinelove)、[tabzzz1](https://github.com/tabzzz1) 提交 - 📦 更新浏览器目标减少打包体积。[#234](https://github.com/ant-design/x/pull/234) 由 [afc163](https://github.com/afc163) 提交 ## 1.0.0 `2024-11-22` 🎉 我们非常开心的宣布 [Ant Design X](https://x.ant.design) 1.0.0 版本正式发布啦~ - 🌈 **源自企业级 AI 产品的最佳实践**:基于 RICH 交互范式,提供卓越的 AI 交互体验 - 🧩 **灵活多样的原子组件**:覆盖绝大部分 AI 对话场景,助力快速构建个性化 AI 交互页面 - ⚡ **开箱即用的模型对接能力**:轻松对接符合 OpenAI 标准的模型推理服务 - 🔄 **高效管理对话数据流**:提供好用的数据流管理功能,让开发更高效 - 📦 **丰富的样板间支持**:提供多种模板,快速启动 LUI 应用开发 - 🛡 **TypeScript 全覆盖**:采用 TypeScript 开发,提供完整类型支持,提升开发体验与可靠性 - 🎨 **深度主题定制能力**:支持细粒度的样式调整,满足各种场景的个性化需求 ![demos](https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*UAEeSbJfuM8AAAAAAAAAAAAADgCCAQ/fmt.webp) ## 1.0.0-alpha.12 `2024-11-07` - 🔥 Sender 支持 `onPasteFile` 事件与 Attachments 支持 `ref.upload` 手动上传文件。[#184](https://github.com/ant-design/x/pull/184) 由 [zombieJ](https://github.com/zombieJ) 提交 - 🔥 Sender `allowSpeech` 支持受控使用三方语音 SDK。 [#187](https://github.com/ant-design/x/pull/187) 由 [zombieJ](https://github.com/zombieJ) 提交 ## 1.0.0-alpha.11 `2024-11-06` - 🔥 新组件 欢迎 - Welcome。 [#179](https://github.com/ant-design/x/pull/179) 由 [zombieJ](https://github.com/zombieJ) 提交 - 🔥 Prompts 支持嵌套层级展示。[#181](https://github.com/ant-design/x/pull/181)由 [zombieJ](https://github.com/zombieJ) 提交 - 🔥 Attachments 支持 Attachments.FileCard 子组件。[#182](https://github.com/ant-design/x/pull/182) 由 [zombieJ](https://github.com/zombieJ) 提交 ## 1.0.0-alpha.10 `2024-11-04` - 🐛 修复 Attachments 组件使用拖动上传时无法触发上传请求的问题。[#178](https://github.com/ant-design/x/pull/178) 由 [YumoImer](https://github.com/YumoImer) 提交 ## 1.0.0-alpha.9 `2024-11-01` - 🐛 修复 Attachments 组件内的代码逻辑问题。[#174](https://github.com/ant-design/x/pull/174) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🐛 修复 Sender.Header 内不可以聚焦的问题。[#175](https://github.com/ant-design/x/pull/175) 由[zombieJ](https://github.com/zombieJ) 提交 ## 1.0.0-alpha.7 `2024-10-31` - 🐛 修复 Attachments 组件第一次上传时无法触发上传请求的问题。 [#172](https://github.com/ant-design/x/pull/172) 由 [YumoImer](https://github.com/YumoImer) 提交 ## 1.0.0-alpha.6 `2024-10-25` - 🔥 新组件 附件 - `Attachments`。[#168](https://github.com/ant-design/x/pull/168) 由 [zombieJ](https://github.com/zombieJ) [#168](https://github.com/ant-design/x/pull/168) 提交 - 🔥 新工具 流 - `XStream`。[#138](https://github.com/ant-design/x/pull/138) 由 [YumoImer](https://github.com/YumoImer) 提交 - 🔥 新工具 请求 - `XRequest`。[#138](https://github.com/ant-design/x/pull/138) 由 [YumoImer](https://github.com/YumoImer) 提交 ## 1.0.0-alpha.5 `2024-10-23` - 🆕 Bubble 支持 `loadingRender` 以自定义加载状态。[#165](https://github.com/ant-design/x/pull/165) - 🐛 修复不包裹 XProvider 时,组件样式丢失的问题。[#163](https://github.com/ant-design/x/pull/163) ## 1.0.0-alpha.4 `2024-10-17` - Sender - 🆕 Sender 支持 `speech` 语音功能。[#154](https://github.com/ant-design/x/pull/154) 由 [zombieJ](https://github.com/zombieJ) 提交 - 🆕 Sender 支持 `Sender.Header`。[#156](https://github.com/ant-design/x/pull/156) 由 [zombieJ](https://github.com/zombieJ) 提交 - 🆕 Sender 样式调整。[#151](https://github.com/ant-design/x/pull/151) 由 [zombieJ](https://github.com/zombieJ) 提交 - 📖 更新文档页面下的组配置。[#155](https://github.com/ant-design/x/pull/155) 由 [YumoImer](https://github.com/YumoImer) 提交 - 📖 调整示例切换按钮样式。[#146](https://github.com/ant-design/x/pull/146) 由 [afc163](https://github.com/afc163) 提交 - 📖 更新 README.md。[#142](https://github.com/ant-design/x/pull/142) 由 [afc163](https://github.com/afc163) 提交 ## 1.0.0-alpha.3 `2024-10-10` - Bubble - 🆕 Bubble 新增 `variant` 变体支持,由 [zombieJ](https://github.com/zombieJ) 完成 [#140](https://github.com/ant-design/x/pull/140) - 🆕 Bubble 新增 `shape` 形状支持,由 [zombieJ](https://github.com/zombieJ) 完成 [#144](https://github.com/ant-design/x/pull/144) - 🆕 Bubble 新增 `header` 和 `footer` 支持自定义头部与底部内容并添加对应语义化 `className`,由 [zombieJ](https://github.com/zombieJ) 完成 [#147](https://github.com/ant-design/x/pull/147) ## 1.0.0-alpha.2 `2024-09-27` - 🔥 新增 `XProvider` 全局化配置组件,由 [YumoImer](https://github.com/YumoImer) 完成 [#127](https://github.com/ant-design/x/pull/127) - 🔥 新增 运行时钩子 `useXChat` 数据管理,由 [zombieJ](https://github.com/zombieJ) 完成 [#125](https://github.com/ant-design/x/pull/125) - 🔥 新增 运行时钩子 `useXAgent` 模型调度,由 [zombieJ](https://github.com/zombieJ) 完成 [#125](https://github.com/ant-design/x/pull/125) - 🆕 `ThoughtChain` 思维链组件支持 `size` 属性,由 [YumoImer](https://github.com/YumoImer) 完成 [#123](https://github.com/ant-design/x/pull/123) - 🛠 更新 `.lintstagedrc.json`。 由 [afc163](https://github.com/afc163) 完成 [#128](https://github.com/ant-design/x/pull/128) - 🛠 更新依赖 `cheerio` 至 `v1.0.0`。 由 [afc163](https://github.com/afc163) 完成 [#121](https://github.com/ant-design/x/pull/121) ## 1.0.0-alpha.1 `2024-09-10` ### 🚀 新特性 - 🔥 新增:`Suggestion` 建议组件,由 [ONLY-yours](https://github.com/ONLY-yours) 完成 [#87](https://github.com/ant-design/x/pull/87) ### 🐛 修复 - 🐛 修复:更改 `Sender` 的 `restProps` 类型,由 [ONLY-yours](https://github.com/ONLY-yours) 完成 [#101](https://github.com/ant-design/x/pull/101) - 🛠 修复:`bun install` 问题,由 [afc163](https://github.com/afc163) 完成 [#111](https://github.com/ant-design/x/pull/111) ### 🛠 重构 - 🛠 重构:添加层级支持,由 [zombieJ](https://github.com/zombieJ) 完成 [#118](https://github.com/ant-design/x/pull/118) - 🛠 重构:加速工作流,由 [afc163](https://github.com/afc163) 完成 [#119](https://github.com/ant-design/x/pull/119) - 🛠 重构:升级开发依赖的 5 个更新,由 [dependabot](https://github.com/dependabot) 完成 [#120](https://github.com/ant-design/x/pull/120) - 🛠 重构:清理 `README.md`,由 [afc163](https://github.com/afc163) 完成 [#102](https://github.com/ant-design/x/pull/102) - 🛠 重构:添加 issue 模板,由 [afc163](https://github.com/afc163) 完成 [#103](https://github.com/ant-design/x/pull/103) - 🛠 重构:添加 `bun.lockb`,由 [afc163](https://github.com/afc163) 完成 [#108](https://github.com/ant-design/x/pull/108) - 🛠 删除 `index-style-only.js`,由 [afc163](https://github.com/afc163) 完成 [#106](https://github.com/ant-design/x/pull/106) - 🛠 重构:更新 `main.yml`,由 [afc163](https://github.com/afc163) 完成 [#105](https://github.com/ant-design/x/pull/105) - 🛠 重构:更新 `package.json`,由 [afc163](https://github.com/afc163) 完成 [#110](https://github.com/ant-design/x/pull/110) ### 📖 文档 - 📖 文档:更新 `README.md`,由 [afc163](https://github.com/afc163) 完成 [#104](https://github.com/ant-design/x/pull/104) - 📖 文档:更新 `codecov` 徽章,由 [afc163](https://github.com/afc163) 完成 [#112](https://github.com/ant-design/x/pull/112) ## 1.0.0-alpha.0 `2024-09-05` - 🔥 新组件 Bubble。 [#19](https://github.com/ant-design/x/pull/19) [li-jia-nan](https://github.com/li-jia-nan) - 🔥 Bubble 支持方向 [#52](https://github.com/ant-design/x/pull/52) [li-jia-nan](https://github.com/li-jia-nan) - 🔥 新组件 Bubble.List。 [#57](https://github.com/ant-design/x/pull/57) [zombieJ](https://github.com/zombieJ) - 🔥 新组件 Conversations。 [#48](https://github.com/ant-design/x/pull/48) [YumoImer](https://github.com/YumoImer) - 🔥 新组件 Prompts。 [#55](https://github.com/ant-design/x/pull/55) [YumoImer](https://github.com/YumoImer) - 🔥 新组件 Sender。 [#46](https://github.com/ant-design/x/pull/46) [ONLY-yours](https://github.com/ONLY-yours) - 🔥 新组件 ThoughtChain。 [#86](https://github.com/ant-design/x/pull/86) [YumoImer](https://github.com/YumoImer) - 📦 使用 `father` 构建。 [#84](https://github.com/ant-design/x/pull/84) [zombieJ](https://github.com/zombieJ) - 🛠 修复使用 `antd` 的 es 或 lib 包时 ThemeContext 实例不一致的问题。 [#88](https://github.com/ant-design/x/pull/88) [YumoImer](https://github.com/YumoImer) - 🛠 重构:API 命名规范 [#73](https://github.com/ant-design/x/pull/73) [zombieJ](https://github.com/zombieJ) - 🛠 杂项:CI、Github Actions、发布 - 🛠 [#59](https://github.com/ant-design/x/pull/59) [zombieJ](https://github.com/zombieJ) - 🛠 [#62](https://github.com/ant-design/x/pull/62) [zombieJ](https://github.com/zombieJ) - 🛠 [#71](https://github.com/ant-design/x/pull/71) [ONLY-yours](https://github.com/ONLY-yours) - 🛠 [#72](https://github.com/ant-design/x/pull/72) [YumoImer](https://github.com/YumoImer) - 🛠 [#98](https://github.com/ant-design/x/pull/98) [YumoImer](https://github.com/YumoImer) - 📖 更新 README.md - 📖 [#81](https://github.com/ant-design/x/pull/81) [zombieJ](https://github.com/zombieJ) - 📖 [#82](https://github.com/ant-design/x/pull/82) [zombieJ](https://github.com/zombieJ) - 📖 [#61](https://github.com/ant-design/x/pull/61) [afc163](https://github.com/afc163) ## 0.0.0-alpha.0 `2024-05-10` - MISC: 项目初始化。 ================================================ FILE: CNAME ================================================ x.ant.design ================================================ FILE: README-zh_CN.md ================================================

Ant Design X

打造卓越 AI 界面解决方案,引领智能新体验。 [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] ![GitHub contributors][github-contributors] [![Follow zhihu][zhihu-image]][zhihu-url] [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ant-design/x) | Package | Latest Version | Download stats | Bundle Size | JSDelivr | | :-- | :-- | :-- | :-- | :-- | | `@ant-design/x` | [![npm version][x-version-image]][x-version-url] | [![npm downloads][x-downloads-image]][x-downloads-url] | [![bundle size][x-bundle-size-image]][x-bundle-size-url] | [![jsdelivr][x-jsdelivr-image]][x-jsdelivr-url] | | `@ant-design/x-markdown` | [![npm version][x-markdown-version-image]][x-markdown-version-url] | [![npm downloads][x-markdown-downloads-image]][x-markdown-downloads-url] | [![bundle size][x-markdown-bundle-size-image]][x-markdown-bundle-size-url] | [![jsdelivr][x-markdown-jsdelivr-image]][x-markdown-jsdelivr-url] | | `@ant-design/x-sdk` | [![npm version][x-sdk-version-image]][x-sdk-version-url] | [![npm downloads][x-sdk-downloads-image]][x-sdk-downloads-url] | [![bundle size][x-sdk-bundle-size-image]][x-sdk-bundle-size-url] | [![jsdelivr][x-sdk-jsdelivr-image]][x-sdk-jsdelivr-url] | | `@ant-design/x-skill` | [![npm version][x-skill-version-image]][x-skill-version-url] | [![npm downloads][x-skill-downloads-image]][x-skill-downloads-url] | [![bundle size][x-skill-bundle-size-image]][x-skill-bundle-size-url] | [![jsdelivr][x-skill-jsdelivr-image]][x-skill-jsdelivr-url] | [更新日志](./CHANGELOG.zh-CN.md) · [报告一个 Bug][github-issues-bug-report] · [想新增特性?][github-issues-feature-request] · [English](./README.md) · 中文 [x-version-image]: https://img.shields.io/npm/v/@ant-design/x.svg?style=flat-square [x-version-url]: https://www.npmjs.com/package/@ant-design/x [x-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x.svg?style=flat [x-downloads-url]: https://www.npmjs.com/package/@ant-design/x [x-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x [x-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x [x-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x [x-package-size-url]: https://packagephobia.com/result?p=@ant-design/x [x-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x/badge [x-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x [x-markdown-version-image]: https://img.shields.io/npm/v/@ant-design/x-markdown.svg?style=flat [x-markdown-version-url]: https://www.npmjs.com/package/@ant-design/x-markdown [x-markdown-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x-markdown.svg?style=flat [x-markdown-downloads-url]: https://www.npmjs.com/package/@ant-design/x-markdown [x-markdown-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x-markdown [x-markdown-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x-markdown [x-markdown-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x-markdown [x-markdown-package-size-url]: https://packagephobia.com/result?p=@ant-design/x-markdown [x-markdown-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x-markdown/badge [x-markdown-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x-markdown [x-sdk-version-image]: https://img.shields.io/npm/v/@ant-design/x-sdk.svg?style=flat [x-sdk-version-url]: https://www.npmjs.com/package/@ant-design/x-sdk [x-sdk-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x-sdk.svg?style=flat [x-sdk-downloads-url]: https://www.npmjs.com/package/@ant-design/x-sdk [x-sdk-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x-sdk [x-sdk-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x-sdk [x-sdk-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x-sdk [x-sdk-package-size-url]: https://packagephobia.com/result?p=@ant-design/x-sdk [x-sdk-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x-sdk/badge [x-sdk-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x-sdk [x-skill-version-image]: https://img.shields.io/npm/v/@ant-design/x-skill.svg?style=flat-square [x-skill-version-url]: https://www.npmjs.com/package/@ant-design/x-skill [x-skill-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x-skill.svg?style=flat [x-skill-downloads-url]: https://www.npmjs.com/package/@ant-design/x-skill [x-skill-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x-skill [x-skill-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x-skill [x-skill-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x-skill [x-skill-package-size-url]: https://packagephobia.com/result?p=@ant-design/x-skill [x-skill-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x-skill/badge [x-skill-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x-skill [npm-image]: https://img.shields.io/npm/v/@ant-design/x.svg?style=flat-square [npm-url]: https://npmjs.org/package/@ant-design/x [github-action-image]: https://github.com/ant-design/x/actions/workflows/main.yml/badge.svg [github-action-url]: https://github.com/ant-design/x/actions/workflows/main.yml [codecov-image]: https://codecov.io/gh/ant-design/x/graph/badge.svg?token=wrCCsyTmdi [codecov-url]: https://codecov.io/gh/ant-design/x [download-image]: https://img.shields.io/npm/dm/@ant-design/x.svg?style=flat-square [download-url]: https://npmjs.org/package/@ant-design/x [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/@ant-design/x?style=flat-square [bundlephobia-url]: https://bundlephobia.com/package/@ant-design/x [github-issues-bug-report]: https://github.com/ant-design/x/issues/new?template=bug-report.yml [github-issues-feature-request]: https://github.com/ant-design/x/issues/new?template=bug-feature-request.yml [antd-image]: https://img.shields.io/badge/-Ant%20Design-blue?labelColor=black&logo=antdesign&style=flat-square [antd-url]: https://ant.design [zhihu-image]: https://img.shields.io/badge/-Ant%20Design-white?logo=zhihu [zhihu-url]: https://www.zhihu.com/column/c_1564262000561106944 [github-contributors]: https://img.shields.io/github/contributors-anon/ant-design/x
![demos](https://github.com/user-attachments/assets/8f6b56b9-3619-4ddc-9105-ca0eb7af070f) ## 🌈 开箱即用的大模型企业级组件 `@ant-design/x` 基于 RICH 交互范式,在不同的交互阶段提供了大量的原子组件,帮助你灵活搭建你的 AI 应用,详情点击[这里](packages/x/README-zh_CN.md)。 ## ⚡️ 对接模型智能体服务 & 高效管理数据流 `@ant-design/x-sdk` 提供了一系列的工具API,旨在提供开发者开箱即用的管理AI应用数据流,详情点击[这里](packages/x-sdk/README-zh_CN.md)。 ## ✨ Markdown 渲染器 `@ant-design/x-markdown` 旨在提供流式友好、强拓展性和高性能的 Markdown 渲染器。提供流式渲染公式、代码高亮、mermaid 等能力,详情点击[这里](packages/x-markdown/README-zh_CN.md)。 ## 🚀 Skill `@ant-design/x-skill` 是专为 Ant Design X 打造的智能技能库,提供了一系列精心设计的 Agent 技能。这些技能能够显著提升开发效率,帮助您快速构建高质量的 AI 对话应用,并有效解决开发过程中遇到的各种问题,详情点击[这里](packages/x-skill/README-zh_CN.md)。 ## 谁在使用 Ant Design X 广泛用于蚂蚁集团内由 AI 驱动的用户交互界面。如果你的公司和产品使用了 Ant Design X,欢迎到 [这里](https://github.com/ant-design/x/issues/126) 留言。 ## 本地研发 > antx 通过 [npm-workspace](https://docs.npmjs.com/cli/v11/using-npm/workspaces) 来组织代码,推荐使用 npm 或 [utoo](https://github.com/umijs/mako/tree/next) 进行本地研发。 ```bash # 安装 utoo $ npm i -g utoo # 安装项目依赖 (by utoo) $ ut [install] # 启动项目 $ ut start # 方式一: 通过主包的 script 启动 $ ut start --workspace packages/x # 方式二: 通过 workspace 参数启动 $ ut start --workspace @ant-design/x # 方式三: 通过 package.name 启动 (utoo only) $ cd packages/x && ut start # 方式四: 进入子包目录单独启动 # 添加依赖 $ ut install [pkg@version] # 为主包添加依赖 $ ut install [pkg@version] --workspace packages/x # 为子包添加依赖 $ cd packages/x && ut install [pkg@version] # 为子包添加依赖 # 依赖更新 $ ut update # utoo only ``` ## 如何贡献 在任何形式的参与前,请先阅读 [贡献者文档](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md)。如果你希望参与贡献,欢迎提交 [Pull Request](https://github.com/ant-design/ant-design/pulls),或给我们 [报告 Bug](http://new-issue.ant.design/)。 > 强烈推荐阅读 [《提问的智慧》](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way)、[《如何向开源社区提问题》](https://github.com/seajs/seajs/issues/545) 和 [《如何有效地报告 Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-cn.html)、[《如何向开源项目提交无法解答的问题》](https://zhuanlan.zhihu.com/p/25795393),更好的问题更容易获得帮助。 ## 社区互助 如果您在使用的过程中碰到问题,可以通过下面几个途径寻求帮助,同时我们也鼓励资深用户通过下面的途径给新人提供帮助。 通过 GitHub Discussions 提问时,建议使用 `Q&A` 标签。 1. [GitHub Discussions](https://github.com/ant-design/x/discussions) 2. [GitHub Issues](https://github.com/ant-design/x/issues) Contribution Leaderboard ================================================ FILE: README.md ================================================

Ant Design X

Build excellent AI interfaces and pioneer intelligent new experiences. [![CI status][github-action-image]][github-action-url] [![codecov][codecov-image]][codecov-url] ![GitHub contributors][github-contributors] [![Follow zhihu][zhihu-image]][zhihu-url] [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/ant-design/x) | Package | Latest Version | Download stats | Bundle Size | JSDelivr | | :-- | :-- | :-- | :-- | :-- | | `@ant-design/x` | [![npm version][x-version-image]][x-version-url] | [![npm downloads][x-downloads-image]][x-downloads-url] | [![bundle size][x-bundle-size-image]][x-bundle-size-url] | [![jsdelivr][x-jsdelivr-image]][x-jsdelivr-url] | | `@ant-design/x-markdown` | [![npm version][x-markdown-version-image]][x-markdown-version-url] | [![npm downloads][x-markdown-downloads-image]][x-markdown-downloads-url] | [![bundle size][x-markdown-bundle-size-image]][x-markdown-bundle-size-url] | [![jsdelivr][x-markdown-jsdelivr-image]][x-markdown-jsdelivr-url] | | `@ant-design/x-sdk` | [![npm version][x-sdk-version-image]][x-sdk-version-url] | [![npm downloads][x-sdk-downloads-image]][x-sdk-downloads-url] | [![bundle size][x-sdk-bundle-size-image]][x-sdk-bundle-size-url] | [![jsdelivr][x-sdk-jsdelivr-image]][x-sdk-jsdelivr-url] | | `@ant-design/x-skill` | [![npm version][x-skill-version-image]][x-skill-version-url] | [![npm downloads][x-skill-downloads-image]][x-skill-downloads-url] | [![bundle size][x-skill-bundle-size-image]][x-skill-bundle-size-url] | [![jsdelivr][x-skill-jsdelivr-image]][x-skill-jsdelivr-url] | [Changelog](./CHANGELOG.en-US.md) · [Report a Bug][github-issues-bug-report] · [Request a Feature][github-issues-feature-request] · English · [中文](./README-zh_CN.md) [x-version-image]: https://img.shields.io/npm/v/@ant-design/x.svg?style=flat-square [x-version-url]: https://www.npmjs.com/package/@ant-design/x [x-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x.svg?style=flat [x-downloads-url]: https://www.npmjs.com/package/@ant-design/x [x-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x [x-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x [x-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x [x-package-size-url]: https://packagephobia.com/result?p=@ant-design/x [x-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x/badge [x-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x [x-markdown-version-image]: https://img.shields.io/npm/v/@ant-design/x-markdown.svg?style=flat [x-markdown-version-url]: https://www.npmjs.com/package/@ant-design/x-markdown [x-markdown-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x-markdown.svg?style=flat [x-markdown-downloads-url]: https://www.npmjs.com/package/@ant-design/x-markdown [x-markdown-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x-markdown [x-markdown-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x-markdown [x-markdown-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x-markdown [x-markdown-package-size-url]: https://packagephobia.com/result?p=@ant-design/x-markdown [x-markdown-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x-markdown/badge [x-markdown-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x-markdown [x-sdk-version-image]: https://img.shields.io/npm/v/@ant-design/x-sdk.svg?style=flat [x-sdk-version-url]: https://www.npmjs.com/package/@ant-design/x-sdk [x-sdk-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x-sdk.svg?style=flat [x-sdk-downloads-url]: https://www.npmjs.com/package/@ant-design/x-sdk [x-sdk-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x-sdk [x-sdk-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x-sdk [x-sdk-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x-sdk [x-sdk-package-size-url]: https://packagephobia.com/result?p=@ant-design/x-sdk [x-sdk-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x-sdk/badge [x-sdk-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x-sdk [x-skill-version-image]: https://img.shields.io/npm/v/@ant-design/x-skill.svg?style=flat-square [x-skill-version-url]: https://www.npmjs.com/package/@ant-design/x-skill [x-skill-downloads-image]: https://img.shields.io/npm/dm/@ant-design/x-skill.svg?style=flat [x-skill-downloads-url]: https://www.npmjs.com/package/@ant-design/x-skill [x-skill-bundle-size-image]: https://img.shields.io/bundlephobia/minzip/@ant-design/x-skill [x-skill-bundle-size-url]: https://bundlephobia.com/result?p=@ant-design/x-skill [x-skill-package-size-image]: https://packagephobia.com/badge?p=@ant-design/x-skill [x-skill-package-size-url]: https://packagephobia.com/result?p=@ant-design/x-skill [x-skill-jsdelivr-image]: https://data.jsdelivr.com/v1/package/npm/@ant-design/x-skill/badge [x-skill-jsdelivr-url]: https://www.jsdelivr.com/package/npm/@ant-design/x-skill [npm-image]: https://img.shields.io/npm/v/@ant-design/x.svg?style=flat-square [npm-url]: https://npmjs.org/package/@ant-design/x [github-action-image]: https://github.com/ant-design/x/actions/workflows/main.yml/badge.svg [github-action-url]: https://github.com/ant-design/x/actions/workflows/main.yml [codecov-image]: https://codecov.io/gh/ant-design/x/graph/badge.svg?token=wrCCsyTmdi [codecov-url]: https://codecov.io/gh/ant-design/x [download-image]: https://img.shields.io/npm/dm/@ant-design/x.svg?style=flat-square [download-url]: https://npmjs.org/package/@ant-design/x [bundlephobia-image]: https://badgen.net/bundlephobia/minzip/@ant-design/x?style=flat-square [bundlephobia-url]: https://bundlephobia.com/package/@ant-design/x [github-issues-bug-report]: https://github.com/ant-design/x/issues/new?template=bug-report.yml [github-issues-feature-request]: https://github.com/ant-design/x/issues/new?template=bug-feature-request.yml [antd-image]: https://img.shields.io/badge/-Ant%20Design-blue?labelColor=black&logo=antdesign&style=flat-square [antd-url]: https://ant.design [zhihu-image]: https://img.shields.io/badge/-Ant%20Design-white?logo=zhihu [zhihu-url]: https://www.zhihu.com/column/c_1564262000561106944 [github-contributors]: https://img.shields.io/github/contributors-anon/ant-design/x
![demos](https://github.com/user-attachments/assets/8f6b56b9-3619-4ddc-9105-ca0eb7af070f) ## 🌈 Enterprise-level LLM Components Out of the Box `@ant-design/x` provides a rich set of atomic components for different interaction stages based on the RICH interaction paradigm, helping you flexibly build your AI applications. See details [here](packages/x/README.md). ## ⚡️ Connect to Model Agents & Efficiently Manage Data Streams `@ant-design/x-sdk` provides a set of utility APIs to help developers manage AI application data streams out of the box. See details [here](packages/x-sdk/README.md). ## ✨ Markdown Renderer `@ant-design/x-markdown` aims to provide a streaming-friendly, highly extensible, and high-performance Markdown renderer. It supports streaming rendering of formulas, code highlighting, mermaid, and more. See details [here](packages/x-markdown/README.md). ## 🚀 Skill `@ant-design/x-skill` is an intelligent skill library specially designed for Ant Design X, providing a series of carefully designed Agent skills. These skills can significantly improve development efficiency, help you quickly build high-quality AI conversation applications, and effectively solve various problems encountered during development. See details [here](packages/x-skill/README.md). ## Who's using Ant Design X is widely used in AI-driven user interfaces within Ant Group. If your company or product uses Ant Design X, feel free to leave a message [here](https://github.com/ant-design/x/issues/126). ## Local Development > antx uses [npm-workspace](https://docs.npmjs.com/cli/v11/using-npm/workspaces) to organize code. We recommend using npm or [utoo](https://github.com/umijs/mako/tree/next) for local development. ```bash # Install utoo $ npm i -g utoo # Install project dependencies (by utoo) $ ut [install] # Start project $ ut start # Method 1: Start via main package script $ ut start --workspace packages/x # Method 2: Start via workspace param $ ut start --workspace @ant-design/x # Method 3: Start via package.name (utoo only) $ cd packages/x && ut start # Method 4: Enter subpackage dir and start # Add dependency $ ut install [pkg@version] # Add to main package $ ut install [pkg@version] --workspace packages/x # Add to subpackage $ cd packages/x && ut install [pkg@version] # Add to subpackage # Update dependencies $ ut update # utoo only ``` ## How to Contribute Before participating in any form, please read the [Contributor Guide](https://github.com/ant-design/ant-design/blob/master/.github/CONTRIBUTING.md). If you wish to contribute, feel free to submit a [Pull Request](https://github.com/ant-design/ant-design/pulls) or [report a Bug](http://new-issue.ant.design/). > We highly recommend reading [How To Ask Questions The Smart Way](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way), [How to Ask Questions in Open Source Community](https://github.com/seajs/seajs/issues/545), [How to Report Bugs Effectively](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs.html), and [How to Submit Unanswerable Questions to Open Source Projects](https://zhuanlan.zhihu.com/p/25795393). Better questions are more likely to get help. ## Community Support If you encounter problems during use, you can seek help through the following channels. We also encourage experienced users to help newcomers through these channels. When asking questions on GitHub Discussions, it is recommended to use the `Q&A` tag. 1. [GitHub Discussions](https://github.com/ant-design/x/discussions) 2. [GitHub Issues](https://github.com/ant-design/x/issues) Contribution Leaderboard ================================================ FILE: biome.json ================================================ { "files": { "ignoreUnknown": true, "includes": [ "**", "!**/.dumi/tmp*", "!**/dist/**/*", "!**/es/**/*", "!**/lib/**/*", "!**/bin/**/*", "!**/_site/**/*", "!**/server/**/*", "!**/node_modules", "!**/coverage", "!**/package.json", "!**/x-markdown/plugins/**/*", "!**/x-markdown/themes/**/*", "!**/tests/index.html", "!**/scripts/visual-regression/report-template.html" ] }, "formatter": { "enabled": true, "indentStyle": "space", "lineWidth": 100, "indentWidth": 2 }, "javascript": { "jsxRuntime": "reactClassic", "formatter": { "quoteStyle": "single" } }, "linter": { "rules": { "style": { "useImportType": "off", "useNumberNamespace": "off", "useNodejsImportProtocol": "off", "noNonNullAssertion": "off", "noUnusedTemplateLiteral": "off", "useAsConstAssertion": "error", "useDefaultParameterLast": "error", "useEnumInitializers": "error", "useSelfClosingElements": "error", "useSingleVarDeclarator": "error", "noInferrableTypes": "error", "noUselessElse": "error", "noParameterAssign": "off" }, "complexity": { "noUselessTypeConstraint": "off", "noForEach": "off", "noUselessFragments": "off" }, "correctness": { "useExhaustiveDependencies": "off", "useUniqueElementIds": "off", "noVoidTypeReturn": "off", "noUndeclaredDependencies": "error" }, "suspicious": { "noGlobalIsNan": "off", "noGlobalIsFinite": "off", "noExplicitAny": "off", "noArrayIndexKey": "off", "noConfusingVoidType": "off", "noThenProperty": "off", "noTsIgnore": "off", "noImplicitAnyLet": "off", "noNonNullAssertedOptionalChain": "off" }, "performance": { "noDelete": "off", "noAccumulatingSpread": "off" }, "a11y": { "noAriaHiddenOnFocusable": "off", "useSemanticElements": "off", "useKeyWithClickEvents": "off", "noStaticElementInteractions": "off", "useValidAnchor": "off", "useAnchorContent": "off" } } }, "overrides": [ { "includes": [ "**/*.test.ts", "**/*.test.tsx", "**/tests/**/*", "**/scripts/**/*", "**/.dumi/**/*" ], "linter": { "rules": { "style": { "noParameterAssign": "off" }, "suspicious": { "noThenProperty": "off", "noImplicitAnyLet": "off" }, "complexity": { "noUselessFragments": "off" }, "a11y": { "useValidAnchor": "off", "useAnchorContent": "off", "useKeyWithClickEvents": "off" } } } }, { "includes": ["**/packages/x/components/**/*/demo/**/*", "**/packages/x-sdk/src/**/*"], "linter": { "rules": { "correctness": { "noVoidTypeReturn": "off", "noUnusedPrivateClassMembers": "off" }, "a11y": { "useValidAnchor": "off", "useAnchorContent": "off", "useKeyWithClickEvents": "off" } } } }, { "includes": ["**/packages/x-markdown/src/**/*"], "linter": { "rules": { "correctness": { "noVoidTypeReturn": "off" }, "complexity": { "noImportantStyles": "off" }, "a11y": { "useValidAnchor": "off", "useAnchorContent": "off", "useKeyWithClickEvents": "off" } } } }, { "includes": ["**/packages/x/components/notification/**/*"], "linter": { "rules": { "correctness": { "noUnusedPrivateClassMembers": "off" } } } }, { "includes": [ "**/node_modules/**", "**/dist/**", "**/es/**", "**/lib/**", "**/bin/**", "**/_site/**", "**/coverage/**", "**/scripts/**", "**/.fatherrc.ts", "**/tests/**", "**/__tests__/**", "**/demo/**", "**/.dumi/**", "packages/x/docs/**" ], "linter": { "rules": { "correctness": { "noUndeclaredDependencies": "off" } } } } ] } ================================================ FILE: package.json ================================================ { "name": "x-mono", "version": "2.4.0", "private": true, "scripts": { "presite": "npm run prestart --workspaces", "predeploy": "npm run site", "deploy": "gh-pages -d _site -b gh-pages -f", "site": "npm run site --workspace packages/x && cp -rf packages/x/_site ./_site && cp CNAME _site", "compile": "npm run compile --workspaces", "version": "npm run version --workspaces", "start": "npm run start --workspace packages/x", "prestart": "npm run prestart --workspaces", "pretest": "npm run pretest --workspaces", "publish-version": "tsx ./scripts/synchronize-version.ts", "prepublishOnly": "tsx ./scripts/pre-publish.ts", "precompile": "npm run precompile --workspaces", "prepare": "husky", "size-limit": "size-limit", "lint": "npm run lint --workspaces", "tsc": "npm run tsc --workspaces", "test": "npm run test --workspaces", "coverage": "npm run test --workspaces", "test:dekko": "npm run test:dekko --workspaces", "test:package-diff": "npm run test:package-diff --workspaces" }, "license": "MIT", "workspaces": [ "packages/*" ], "devDependencies": { "@ant-design/tools": "^19.1.0", "@biomejs/biome": "^2.0.5", "@codecov/webpack-plugin": "^1.4.0", "@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0", "@size-limit/file": "^12.0.0", "@testing-library/react": "^16.3.0", "antd": "^6.1.1", "circular-dependency-plugin": "^5.2.2", "dekko": "^0.2.1", "encoding": "^0.1.13", "father": "^4.6.10", "gh-pages": "^6.3.0", "glob": "^13.0.0", "husky": "^9.1.6", "lint-staged": "^16.3.1", "marked-emoji": "^2.0.1", "prettier": "^3.3.3", "react-markdown": "^10.1.0", "size-limit": "^12.0.0" }, "size-limit": [ { "path": "./packages/x/dist/antdx.min.js", "limit": "500 KiB" }, { "path": "./packages/x-sdk/dist/x-sdk.min.js", "limit": "350 KiB" }, { "path": "./packages/x-markdown/dist/x-markdown.min.js", "limit": "150 KiB" }, { "path": "./packages/x-markdown/dist/plugins/latex.min.js", "limit": "300 KiB" } ], "description": "Craft AI-driven interfaces effortlessly", "homepage": "https://x.ant.design", "bugs": { "url": "https://github.com/ant-design/x/issues" }, "repository": { "type": "git", "url": "https://github.com/ant-design/x" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/ant-design" }, "overrides": { "@emotion/hash": "^0.9.2", "react-is": "^18.3.1" } } ================================================ FILE: packages/x/.dumi/components/SemanticPreview.tsx ================================================ import { XProvider } from '@ant-design/x'; import set from '@rc-component/util/lib/utils/set'; import { Col, Flex, Popover, Row, Tag, Typography, theme } from 'antd'; import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; /* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */ import React from 'react'; const MARK_BORDER_SIZE = 2; const useStyle = createStyles(({ token }, markPos: [number, number, number, number]) => ({ container: css` position: relative; `, colWrap: css` border-right: 1px solid ${token.colorBorderSecondary}; display: flex; justify-content: center; align-items: center; padding: ${token.paddingMD}px; overflow: hidden; `, listWrap: css` display: flex; flex-direction: column; list-style: none; margin: 0; padding: 0; overflow: hidden; `, listItem: css` cursor: pointer; padding: ${token.paddingSM}px; transition: background-color ${token.motionDurationFast} ease; &:hover { background-color: ${token.controlItemBgHover}; } &:not(:first-of-type) { border-top: 1px solid ${token.colorBorderSecondary}; } `, marker: css` position: absolute; border: ${MARK_BORDER_SIZE}px solid ${token.colorWarning}; box-sizing: border-box; z-index: 999999; box-shadow: 0 0 0 1px #fff; pointer-events: none; inset-inline-start: ${markPos[0] - MARK_BORDER_SIZE}px; top: ${markPos[1] - MARK_BORDER_SIZE}px; width: ${markPos[2] + MARK_BORDER_SIZE * 2}px; height: ${markPos[3] + MARK_BORDER_SIZE * 2}px; `, markerActive: css` opacity: 1; `, markerNotActive: css` opacity: 0; `, markerMotion: css` transition: opacity ${token.motionDurationSlow} ease, all ${token.motionDurationSlow} ease; `, markerNotMotion: css` transition: opacity ${token.motionDurationSlow} ease; `, })); function getSemanticCells(semanticPath: string) { return semanticPath.split('.'); } const getMarkClassName = (semanticKey: string) => `semantic-mark-${semanticKey}`.replace(/\./g, '-'); export interface SemanticPreviewProps { componentName: string; semantics: { name: string; desc: string; version?: string }[]; children: React.ReactElement | ((injectProps: any) => React.ReactElement); height?: number; } const SemanticPreview: React.FC = (props) => { const { semantics = [], children, height, componentName = 'Component' } = props; const { token } = theme.useToken(); // ======================= Semantic ======================= const semanticClassNames = React.useMemo>(() => { let classNames: Record = {}; semantics.forEach((semantic) => { const pathCell = getSemanticCells(semantic.name); classNames = set(classNames, pathCell, getMarkClassName(semantic.name)); }); return classNames; }, [semantics]); const injectProps = { classNames: semanticClassNames, }; const cloneNode = typeof children === 'function' ? children(injectProps) : React.cloneElement(children, injectProps); // ======================== Hover ========================= const containerRef = React.useRef(null); const timerRef = React.useRef>(null); const [positionMotion, setPositionMotion] = React.useState(false); const [hoverSemantic, setHoverSemantic] = React.useState(null); const [markPos, setMarkPos] = React.useState<[number, number, number, number]>([0, 0, 0, 0]); const { styles } = useStyle(markPos); React.useEffect(() => { if (hoverSemantic) { const targetClassName = getMarkClassName(hoverSemantic); const targetElement = containerRef.current?.querySelector(`.${targetClassName}`); const containerRect = containerRef.current?.getBoundingClientRect(); const targetRect = targetElement?.getBoundingClientRect(); setMarkPos([ (targetRect?.left || 0) - (containerRect?.left || 0), (targetRect?.top || 0) - (containerRect?.top || 0), targetRect?.width || 0, targetRect?.height || 0, ]); timerRef.current = setTimeout(() => { setPositionMotion(true); }, 10); } else { timerRef.current = setTimeout(() => { setPositionMotion(false); }, 500); } return () => { if (timerRef.current) { clearTimeout(timerRef.current); } }; }, [hoverSemantic]); // ======================== Render ======================== return (
{cloneNode}
    {semantics.map((semantic) => (
                          
                            {`<${componentName}
      classNames={{
        ${semantic.name}: 'my-${componentName.toLowerCase()}',
      }}
      styles={{
        ${semantic.name}: { color: 'red' },
      }}
    >
      ...
    `}
                          
                        
    } >
  • setHoverSemantic(semantic.name)} onMouseLeave={() => setHoverSemantic(null)} > {semantic.name} {semantic.version && {semantic.version}} {semantic.desc}
  • ))}
); }; export default SemanticPreview; ================================================ FILE: packages/x/.dumi/global.css ================================================ .demo-logo { width: 120px; min-width: 120px; height: 32px; background: rgba(255, 255, 255, 0.2); border-radius: 6px; margin-inline-end: 24px; } .demo-logo-vertical { height: 32px; margin: 16px; background: rgba(255, 255, 255, 0.2); border-radius: 6px; } html { scrollbar-width: thin; scrollbar-color: #eaeaea transparent; } ================================================ FILE: packages/x/.dumi/hooks/use.ts ================================================ function use(promise: PromiseLike): T { const internal: PromiseLike & { status?: 'pending' | 'fulfilled' | 'rejected'; value?: T; reason?: any; } = promise; if (internal.status === 'fulfilled') { return internal.value as T; } if (internal.status === 'rejected') { throw internal.reason; } if (internal.status === 'pending') { throw internal; } internal.status = 'pending'; internal.then( (result) => { internal.status = 'fulfilled'; internal.value = result; }, (reason) => { internal.status = 'rejected'; internal.reason = reason; }, ); throw internal; } export default use; ================================================ FILE: packages/x/.dumi/hooks/useDark.tsx ================================================ import React from 'react'; export const DarkContext = React.createContext(false); ================================================ FILE: packages/x/.dumi/hooks/useFetch/cache.ts ================================================ export default class FetchCache { private cache: Map> = new Map(); get(key: string) { return this.cache.get(key); } set(key: string, value: PromiseLike) { this.cache.set(key, value); } promise(key: string, promiseFn: () => PromiseLike): PromiseLike { const cached = this.get(key); if (cached) { return cached; } const promise = promiseFn(); this.set(key, promise); return promise; } } ================================================ FILE: packages/x/.dumi/hooks/useFetch/index.ts ================================================ import fetch from 'cross-fetch'; import React from 'react'; import FetchCache from './cache'; const cache = new FetchCache(); const useFetch = (options: string | { request: () => PromiseLike; key: string }) => { let request; let key; if (typeof options === 'string') { request = () => fetch(options).then((res) => res.json()); key = options; } else { request = options.request; key = options.key; } return React.use(cache.promise(key, request)); }; export default useFetch; ================================================ FILE: packages/x/.dumi/hooks/useLayoutState.ts ================================================ import { startTransition, useState } from 'react'; const useLayoutState: typeof useState = ( ...args: Parameters> ): ReturnType> => { const [state, setState] = useState(...args); const setLayoutState: typeof setState = (...setStateArgs) => { startTransition(() => { setState(...setStateArgs); }); }; return [state, setLayoutState]; }; export default useLayoutState; ================================================ FILE: packages/x/.dumi/hooks/useLocale.ts ================================================ import { useIntl } from 'dumi'; export interface LocaleMap< K extends PropertyKey = PropertyKey, V extends string | ((...params: any[]) => string) = string, > { cn: Record; en: Record; } const useLocale = < K extends PropertyKey = PropertyKey, V extends string | ((...params: any[]) => string) = string, >( localeMap?: LocaleMap, ): [Record, 'cn' | 'en'] => { const { locale } = useIntl(); const localeType = locale === 'zh-CN' ? 'cn' : 'en'; return [localeMap?.[localeType]!, localeType] as const; }; export default useLocale; ================================================ FILE: packages/x/.dumi/hooks/useLocation.ts ================================================ import { useLocation as useDumiLocation } from 'dumi'; import * as React from 'react'; import useLocale from './useLocale'; function clearPath(path: string) { return path.replace('-cn', '').replace(/\/$/, ''); } export default function useLocation() { const location = useDumiLocation(); const { search } = location; const [, localeType] = useLocale(); const getLink = React.useCallback( (path: string, hash?: string | { cn: string; en: string }) => { let pathname = clearPath(path); if (localeType === 'cn') { pathname = `${pathname}-cn`; } if (search) { pathname = `${pathname}${search}`; } if (hash) { let hashStr: string; if (typeof hash === 'object') { hashStr = hash[localeType]; } else { hashStr = hash; } pathname = `${pathname}#${hashStr}`; } return pathname; }, [localeType, search], ); return { ...location, pathname: clearPath(location.pathname), getLink, }; } ================================================ FILE: packages/x/.dumi/hooks/useLottie.ts ================================================ import type { AnimationConfig, AnimationItem, LottiePlayer } from 'lottie-web'; import React from 'react'; interface UseLottieOptions extends Omit { renderer?: 'svg' | 'canvas' | 'html'; lazyLoad?: boolean; disabled?: boolean; rootMargin?: string; path?: string; } // 用于确保 lottie-web 只加载一次 let lottiePromise: Promise | null = null; const loadLottie = async (): Promise => { if (!lottiePromise) { lottiePromise = new Promise((resolve, reject) => { if ((window as any)?.lottie) { resolve((window as any).lottie); return; } const script = document.createElement('script'); script.src = 'https://gw.alipayobjects.com/os/lib/lottie-web/5.12.2/build/player/lottie_svg.min.js'; script.async = true; script.onload = () => resolve((window as any).lottie); script.onerror = reject; document.body.appendChild(script); }); } return lottiePromise; }; const useLottie = (options: UseLottieOptions) => { const { lazyLoad = true, rootMargin = '200px', disabled = false, ...lottieOptions } = options; const stableLottieOptions = React.useMemo(() => lottieOptions, []); const containerRef = React.useRef(null); const [isIntersected, setIsIntersected] = React.useState(!lazyLoad); const animationInstanceRef = React.useRef(null); const [error, setError] = React.useState(null); const [animationInstance, setAnimationInstance] = React.useState(); React.useEffect(() => { if (disabled) return; let mounted = true; const initAnimation = async () => { if (!animationInstanceRef.current && (!lazyLoad || isIntersected)) { if (!containerRef.current) return; try { const lottie = await loadLottie(); if (!mounted) return; const animation = lottie.loadAnimation({ container: containerRef.current, renderer: 'svg', // 默认使用 SVG 渲染,性能更好 ...stableLottieOptions, }); setAnimationInstance(animation); animationInstanceRef.current = animation; } catch (err) { if (mounted) { setError(err as Error); console.error('Failed to load Lottie animation:', err); } } } }; initAnimation(); return () => { mounted = false; if (animationInstanceRef.current) { animationInstanceRef.current.destroy(); animationInstanceRef.current = null; } }; }, [isIntersected, lazyLoad, stableLottieOptions, disabled]); React.useEffect(() => { if (disabled) return; if (lazyLoad) { const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsIntersected(true); } }, { root: null, rootMargin, threshold: 0 }, ); if (containerRef.current) { observer.observe(containerRef.current); } return () => { if (containerRef.current) { observer.unobserve(containerRef.current); } }; } }, [lazyLoad, rootMargin, disabled]); return [ containerRef, animationInstance, { isIntersected, error, }, ] as const; }; export default useLottie; ================================================ FILE: packages/x/.dumi/hooks/useMenu.tsx ================================================ import { version } from '@ant-design/x'; import type { MenuProps } from 'antd'; import { Flex, Tag } from 'antd'; import { createStyles } from 'antd-style'; import { clsx } from 'clsx'; import { useFullSidebarData, useSidebarData } from 'dumi'; import React, { useMemo } from 'react'; import Link from '../theme/common/Link'; import useLocation from './useLocation'; function isVersionNumber(value?: string) { return value && /^\d+\.\d+\.\d+$/.test(value); } const getTagColor = (val?: string) => { if (isVersionNumber(val)) { return 'success'; } if (val?.toUpperCase() === 'NEW') { return 'success'; } if (val?.toUpperCase() === 'UPDATED') { return 'processing'; } if (val?.toUpperCase() === 'DEPRECATED') { return 'red'; } return 'success'; }; const useStyle = createStyles(({ css, token }) => ({ link: css` display: flex; align-items: center; justify-content: space-between; `, tag: css` margin-inline-end: 0; `, subtitle: css` font-weight: normal; font-size: ${token.fontSizeSM}px; opacity: 0.8; `, })); interface MenuItemLabelProps { before?: React.ReactNode; after?: React.ReactNode; link: string; title: React.ReactNode; subtitle?: React.ReactNode; search?: string; tag?: string; className?: string; } const MenuItemLabelWithTag: React.FC = (props) => { const { styles } = useStyle(); const { before, after, link, title, subtitle, search, tag, className } = props; if (!before && !after) { return ( {title} {subtitle && {subtitle}} {tag && ( {tag.replace(/VERSION/i, version)} )} ); } return ( {before} {title} {subtitle && {subtitle}} {after} ); }; export interface UseMenuOptions { before?: React.ReactNode; after?: React.ReactNode; } const useMenu = (options: UseMenuOptions = {}): readonly [MenuProps['items'], string] => { const fullData = useFullSidebarData(); const { pathname, search } = useLocation(); const sidebarData = useSidebarData(); const { before, after } = options; const menuItems = useMemo(() => { const sidebarItems = [...(sidebarData ?? [])]; // // 将设计文档未分类的放在最后 // if (pathname.startsWith('/docs/spec')) { // const notGrouped = sidebarItems.splice(0, 1); // sidebarItems.push(...notGrouped); // } // 把 /changelog 拼到开发文档中 if (pathname.startsWith('/docs/react')) { const changelogData = Object.entries(fullData).find(([key]) => key.startsWith('/changelog'), )?.[1]; if (changelogData) { sidebarItems.splice(1, 0, changelogData[0]); } } if (pathname.startsWith('/changelog')) { const reactDocData = Object.entries(fullData).find(([key]) => key.startsWith('/docs/react'), )?.[1]; if (reactDocData) { sidebarItems.unshift(reactDocData[0]); sidebarItems.push(...reactDocData.slice(1)); } } return ( sidebarItems?.reduce>((result, group) => { if (group?.title) { // 设计文档特殊处理二级分组 if (pathname.startsWith('/docs/spec')) { const childrenGroup = group.children.reduce< Record[number]['children']> >((childrenResult, child) => { const type = child.frontmatter?.type ?? 'default'; if (!childrenResult[type]) { childrenResult[type] = []; } childrenResult[type].push(child); return childrenResult; }, {}); const childItems = []; childItems.push( ...(childrenGroup.default?.map((item) => ({ label: ( {before} {item?.title} {after} ), key: item.link.replace(/(-cn$)/g, ''), })) ?? []), ); Object.entries(childrenGroup).forEach(([type, children]) => { if (type !== 'default') { childItems.push({ type: 'group', label: type, key: type, children: children?.map((item) => ({ label: ( {before} {item?.title} {after} ), key: item.link.replace(/(-cn$)/g, ''), })), }); } }); result.push({ label: group?.title, key: group?.title, children: childItems, }); } else { result.push({ type: 'group', label: group?.title, key: group?.title, children: group.children?.map((item) => ({ label: ( ), key: item.link.replace(/(-cn$)/g, ''), })), }); } } else { const list = group.children || []; // 如果有 date 字段,我们就对其进行排序 if (list.every((info) => info?.frontmatter?.date)) { list.sort((a, b) => (a.frontmatter?.date > b.frontmatter?.date ? -1 : 1)); } result.push( ...list.map((item) => ({ label: ( ), key: item.link.replace(/(-cn$)/g, ''), })), ); } return result; }, []) ?? [] ); }, [sidebarData, fullData, pathname, search, options]); return [menuItems, pathname] as const; }; export default useMenu; ================================================ FILE: packages/x/.dumi/hooks/useScrollY.ts ================================================ import React from 'react'; const getSnapshot = () => window.scrollY; const getServerSnapshot = () => 0; const useScrollY = () => { const [scrollYDirection, setScrollYDirection] = React.useState<'down' | 'up'>(); const subscribe = React.useCallback((callback: () => void) => { let ticking = false; let scrollY = window.scrollY; const handleScroll = () => { if (!ticking) { requestAnimationFrame(() => { callback(); setScrollYDirection(scrollY > window.scrollY ? 'up' : 'down'); scrollY = window.scrollY; ticking = false; }); ticking = true; } }; window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, []); const scrollY = React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); return { scrollY, scrollYDirection, }; }; export default useScrollY; ================================================ FILE: packages/x/.dumi/hooks/useThemeAnimation.ts ================================================ import { removeCSS, updateCSS } from '@rc-component/util/lib/Dom/dynamicCSS'; import { useTheme } from 'antd-style'; import { useEffect, useRef } from 'react'; const viewTransitionStyle = ` ::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; } .dark::view-transition-old(root) { z-index: 1; } .dark::view-transition-new(root) { z-index: 999; } ::view-transition-old(root) { z-index: 999; } ::view-transition-new(root) { z-index: 1; } `; const useThemeAnimation = () => { const { colorBgElevated } = useTheme(); const animateRef = useRef<{ colorBgElevated: string }>({ colorBgElevated }); const startAnimationTheme = (clipPath: string[], isDark: boolean) => { updateCSS( ` * { transition: none !important; } `, 'disable-transition', ); document.documentElement .animate( { clipPath: isDark ? [...clipPath].reverse() : clipPath, }, { duration: 500, easing: 'ease-in', pseudoElement: isDark ? '::view-transition-old(root)' : '::view-transition-new(root)', }, ) .addEventListener('finish', () => { removeCSS('disable-transition'); }); }; const toggleAnimationTheme = ( event: React.MouseEvent, isDark: boolean, ) => { if (!(event && typeof document.startViewTransition === 'function')) { return; } const time = Date.now(); const x = event.clientX; const y = event.clientY; const endRadius = Math.hypot(Math.max(x, innerWidth - x), Math.max(y, innerHeight - y)); updateCSS( ` [data-prefers-color='dark'] { color-scheme: light !important; } [data-prefers-color='light'] { color-scheme: dark !important; } `, 'color-scheme', ); document .startViewTransition(async () => { // wait for theme change end while (colorBgElevated === animateRef.current.colorBgElevated) { await new Promise((resolve) => setTimeout(resolve, 1000 / 60)); } const root = document.documentElement; root.classList.remove(isDark ? 'dark' : 'light'); root.classList.add(isDark ? 'light' : 'dark'); }) .ready.then(() => { // eslint-disable-next-line no-console console.log(`Theme transition finished in ${Date.now() - time}ms`); const clipPath = [ `circle(0px at ${x}px ${y}px)`, `circle(${endRadius}px at ${x}px ${y}px)`, ]; removeCSS('color-scheme'); startAnimationTheme(clipPath, isDark); }); }; // inject transition style useEffect(() => { if (typeof document.startViewTransition === 'function') { updateCSS(viewTransitionStyle, 'view-transition-style'); } }, []); useEffect(() => { if (colorBgElevated !== animateRef.current.colorBgElevated) { animateRef.current.colorBgElevated = colorBgElevated; } }, [colorBgElevated]); return toggleAnimationTheme; }; export default useThemeAnimation; ================================================ FILE: packages/x/.dumi/loading.js ================================================ // must be .js file, can't modify to be .ts file! export { default } from './theme/common/Loading'; ================================================ FILE: packages/x/.dumi/pages/404/index.tsx ================================================ import { HomeOutlined } from '@ant-design/icons'; import { Button, Result } from 'antd'; import { useLocation } from 'dumi'; import React, { useEffect } from 'react'; import Link from '../../theme/common/Link'; import * as utils from '../../theme/utils'; export interface NotFoundProps { router: { push: (pathname: string) => void; replace: (pathname: string) => void; }; } const DIRECT_MAP: Record = { 'docs/spec/download': 'docs/resources', 'docs/spec/work-with-us': 'docs/resources', }; const NotFoundPage: React.FC = ({ router }) => { const { pathname } = useLocation(); const isZhCN = utils.isZhCN(pathname); useEffect(() => { const directLinks = Object.keys(DIRECT_MAP); for (let i = 0; i < directLinks.length; i += 1) { const matchPath = directLinks[i]; if (pathname.includes(matchPath)) { router.replace(utils.getLocalizedPathname(`/${DIRECT_MAP[matchPath]}`, isZhCN).pathname); } } // Report if necessary const { yuyanMonitor } = window as any; yuyanMonitor?.log({ code: 11, msg: `Page not found: ${location.href}; Source: ${document.referrer}`, }); }, []); return ( } /> ); }; export default NotFoundPage; ================================================ FILE: packages/x/.dumi/pages/index/common/Container.tsx ================================================ import { createStyles } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; const useStyle = createStyles(({ token, css }) => { return { container: css` width: 100%; margin: 0 auto; max-width: ${token.pcMaxWidth - token.pcContainerMargin * 2}px; font-family: AlibabaPuHuiTi, ${token.fontFamily}, sans-serif; @media only screen and (max-width: ${token.pcMaxWidth}px) { max-width: calc(100vw - ${token.pcContainerMargin * 2}px); } @media only screen and (max-width: ${token.mobileMaxWidth}px) { max-width: calc(100vw - ${token.marginLG * 2}px); } `, title: css` font-size: 48px; color: #fff; text-align: center; padding-bottom: ${token.padding}px; @media only screen and (max-width: ${token.mobileMaxWidth}px) { font-size: ${token.fontSizeHeading1}px; } `, desc: css` color: ${token.colorTextSecondary}; max-width: 880px !important; margin: 0 auto; text-align: center; padding-bottom: ${token.padding}px; `, }; }); export interface ContainerProps extends Omit, 'title'> { children?: React.ReactNode; title?: React.ReactNode; desc?: React.ReactNode; } const Container: React.FC = (props) => { const { styles } = useStyle(); return (
{props.title &&

{props.title}

} {props.desc &&

{props.desc}

} {props.children}
); }; export default Container; ================================================ FILE: packages/x/.dumi/pages/index/common/CustomizationProvider.tsx ================================================ import { XProvider } from '@ant-design/x'; import { createStyles } from 'antd-style'; import React from 'react'; export const useCustomizationBgStyle = createStyles(({ token, css }) => { return { background: css` background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%) !important; overflow: hidden; position: auto; &::after { content: ''; width: 100%; height: 100%; box-sizing: border-box; border-radius: inherit; pointer-events: none; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; inset-inline-end: 0; padding: ${token.lineWidth}px; background: linear-gradient(180deg, #ffffff26 0%, #ffffff00 100%); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; }; `, }; }); export const LOCALES = { cn: { greeting: '你好, 我是全新 AI 产品创造助手', greeting_short: '你好, 我是 Ant Design X', description: '基于 Ant Design 的 AGI 产品智能解决方案, 创造更美好的智能视界', description_short: '基于 Ant Design 的 AGI 产品智能解决方案, 创造更美好的智能视界', help_text: '我可以帮您: ', conversations_group: '最近对话', send_placeholder: '输入 / 获取建议', hot_question: '热门话题', question1: 'Ant Design X 全新升级了什么? ', question2: 'Ant Design X 推出全新 RICH 设计规范 ', question3: 'Ant Design X 组件资产有哪些? ', question4: '快来了解全新AI时代的设计范式! ', design_guide: 'Rich 设计指南', empathy: 'AI 理解用户诉求并解决', persona: 'AI 对外的人设及形象', conversation: 'AI 如何表达用户能听懂', interface: 'AI 兼顾“chat” & “do” 行为', }, en: { greeting: 'Hello, I am your AI Product Design Assistant', greeting_short: 'Hello, I am Ant Design X', description: "Powered by Ant Design's AGI solution to enhance intelligent, aesthetic visual experiences", description_short: 'Aesthetic visual experiences', help_text: 'I can assist you with:', conversations_group: 'History', send_placeholder: 'Type / to get suggestions', hot_question: 'Hot Topics', question1: 'What are the new upgrades in X?', question2: 'X has introduced the new RICH design guide.', question3: 'What are the component assets in X?', question4: 'Discover new design for the AI!', design_guide: 'Rich Design Guidelines', empathy: 'AI that understands and addresses user needs', persona: "Defining AI's persona and presentation", conversation: 'Ensuring AI communicates clearly', interface: "Balancing 'chat' & 'do' functionalities", }, }; export const DESIGN_STAGE_COLOR = { AWAKE: { START: '#6fb3e2', END: '#6c57ff', }, EXPRESS: { START: '#6dd6f5', END: '#108c44', }, CONFIRM: { START: '#ba2cb8', END: '#6c37e8', }, FEEDBACK: { START: '#f7c348', END: '#f75972', }, COMMON: { START: '#d857ff', END: '#8594ff', }, }; const useStyle = createStyles(({ token, css }) => { const borderRadius = 20; return { welcome: css` display: flex; align-items: center; gap: ${token.paddingXS}px; position: relative; box-sizing: border-box; border-radius: ${borderRadius}px; padding: 18px; .ant-welcome-title { font-size: ${token.fontSize}px; font-weight: 400; } .ant-welcome-description { font-size: ${token.fontSizeSM - 1}px; opacity: 0.65; } `, prompts: css` border-radius: ${borderRadius}px !important; position: relative; .ant-prompts-desc { font-size: ${token.fontSizeSM}px !important; opacity: 0.9; } .ant-prompts-label { font-size: ${token.fontSize}px !important; font-weight: 400; } .ant-prompts-title { font-size: ${token.fontSize}px !important; padding-bottom: ${token.paddingXS}px; } `, sender: css` border-radius: ${borderRadius * 2}px; height: 44px; display: flex; align-items: center; .ant-sender-content { padding: 0px ${token.paddingSM}px; } `, conversations: css` padding: ${token.padding}px; padding-top: 0; border-radius: ${borderRadius}px; position: relative; `, suggestion: css` border-radius: ${borderRadius}px; position: relative; `, }; }); const CustomizationProvider: React.FC<{ children: React.ReactNode }> = (props) => { const { styles } = useStyle(); return ( {props.children} ); }; export default CustomizationProvider; ================================================ FILE: packages/x/.dumi/pages/index/common/CustomizationSender.tsx ================================================ import { Sender, type SenderProps } from '@ant-design/x'; import { Button } from 'antd'; import { createStyles } from 'antd-style'; import React from 'react'; export const useStyle = createStyles(({ css, token }) => { return { sender: css` margin-inline: ${token.paddingSM * 2}px; background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%); position: relative; border: none; cursor: pointer; :hover { opacity: 0.85; } `, }; }); const CustomizationSender: React.FC = (props) => { const { styles } = useStyle(); return ( { return (
} {...props} content={props.content || locale.question1} /> ); }; export const CustomConversations: React.FC = (props) => { const [locale] = useLocale(LOCALES); return ( ); }; ================================================ FILE: packages/x/.dumi/pages/index/components/CompIntroduction/index.tsx ================================================ import { createStyles } from 'antd-style'; import React from 'react'; import useLocale from '../../../../hooks/useLocale'; import { DESIGN_STAGE_COLOR } from '../../common/CustomizationProvider'; import Introduction, { type IntroductionItem } from '../../common/Introduction'; import SiteContext from '../SiteContext'; import { CustomizationBubble, CustomizationPrompts, CustomizationWelcome } from './Customization'; const locales = { cn: { title: '组件丰富 , 选用自如', desc: 'Ant Design X 全新 AI 组件 , 大量实用组件满足你的需求 , 灵活定制与拓展', welcome_title: '欢迎组件', welcome_desc: '开箱即用、易于配置、极致体验的通用图表库', welcome_tag: '唤醒', prompts_title: '用户推荐', prompts_desc: '让首次接触AI产品的用户快速理解AI能做什么', prompts_tag: '唤醒', suggestion_title: '快捷命令', suggestion_desc: '开箱即用、易于配置、极致体验的通用图表库', suggestion_tag: '表达', bubble_title: '进度加载', bubble_desc: '开箱即用、易于配置、极致体验的通用图表库', bubble_tag: '确认', actions_title: '结果操作', actions_desc: '开箱即用、易于配置、极致体验的通用图表库', actions_tag: '反馈', conversations_title: '管理对话', conversations_desc: '开箱即用、易于配置、极致体验的通用图表库', conversations_tag: '通用', }, en: { title: 'Components Rich, Easy to Use', desc: 'Ant Design X’s new AI components offer a wide range of practical options to meet your needs, with flexible customization and expansion', welcome_title: 'Welcome', welcome_desc: 'Ready to use, easy to set up, with great user experience', welcome_tag: 'Activate', prompts_title: 'User Guide', prompts_desc: 'Helps new users quickly understand AI capabilities', prompts_tag: 'Activate', suggestion_title: 'Quick Commands', suggestion_desc: 'Ready to use, easy to set up, with great user experience', suggestion_tag: 'Execute', bubble_title: 'Loading Progress', bubble_desc: 'Ready to use, easy to set up, with great user experience', bubble_tag: 'Confirm', actions_title: 'Results', actions_desc: 'Ready to use, easy to set up, with great user experience', actions_tag: 'Feedback', conversations_title: 'Manage Chats', conversations_desc: 'Ready to use, easy to set up, with great user experience', conversations_tag: 'General', }, }; const useStyle = createStyles(({ css }) => { return { header: css` height: 280px; display: flex; align-items: center; justify-content: center; `, }; }); const CompIntroduction: React.FC = () => { const { styles } = useStyle(); const [locale, lang] = useLocale(locales); const isZhCN = lang === 'cn'; const { isMobile } = React.useContext(SiteContext); const items: IntroductionItem[] = [ { title: locale.welcome_title, desc: locale.welcome_desc, tag: locale.welcome_tag, startColor: DESIGN_STAGE_COLOR.AWAKE.START, endColor: DESIGN_STAGE_COLOR.AWAKE.END, header: (
), }, { title: locale.prompts_title, desc: locale.prompts_desc, tag: locale.prompts_tag, startColor: DESIGN_STAGE_COLOR.AWAKE.START, endColor: DESIGN_STAGE_COLOR.AWAKE.END, header: (
), }, { title: locale.suggestion_title, desc: locale.suggestion_desc, tag: locale.suggestion_tag, startColor: DESIGN_STAGE_COLOR.EXPRESS.START, endColor: DESIGN_STAGE_COLOR.EXPRESS.END, header: (
thumbnails
), }, { title: locale.bubble_title, desc: locale.bubble_desc, tag: locale.bubble_tag, startColor: DESIGN_STAGE_COLOR.CONFIRM.START, endColor: DESIGN_STAGE_COLOR.CONFIRM.END, header: (
thumbnails
), }, { title: locale.actions_title, desc: locale.actions_desc, tag: locale.actions_tag, startColor: DESIGN_STAGE_COLOR.FEEDBACK.START, endColor: DESIGN_STAGE_COLOR.FEEDBACK.END, header: (
), }, { title: locale.conversations_title, desc: locale.conversations_desc, tag: locale.conversations_tag, startColor: DESIGN_STAGE_COLOR.COMMON.START, endColor: DESIGN_STAGE_COLOR.COMMON.END, header: (
thumbnails
), }, ]; return ( ); }; export default CompIntroduction; ================================================ FILE: packages/x/.dumi/pages/index/components/DesignBanner.tsx ================================================ import { createStyles } from 'antd-style'; import { useLocation, useNavigate } from 'dumi'; import React, { lazy, Suspense, useEffect, useRef } from 'react'; import useLocale from '../../../hooks/useLocale'; import { getLocalizedPathname, isZhCN } from '../../../theme/utils'; import Container from '../common/Container'; const locales = { cn: { title: 'AI 设计范式 - RICH', desc: '我们致力于构建 AI 设计理论,并在蚂蚁内部海量 AI 产品中实践、迭代。在此过程中,RICH 设计范式应运而生:角色(Role)、意图(Intention)、会话(Conversation)和混合界面(Hybrid UI) ', }, en: { title: 'AI Design Paradigm - RICH', desc: "We focus on developing AI design theory, iterating it across Ant Group's AI products, leading to the RICH design paradigm: Role, Intention, Conversation, and Hybrid UI.", }, }; const useStyle = createStyles(({ css }) => { return { container: css` height: 500px; overflow: hidden; cursor: pointer; `, lottie: css` width: 100%; height: auto; transform: translate(0, -20%); `, }; }); const DesignBanner: React.FC = () => { const [locale] = useLocale(locales); const { pathname, search } = useLocation(); const navigate = useNavigate(); const { styles } = useStyle(); const LottieComponent = lazy(() => import('./Lottie')); const lottieRef = useRef<{ animation: any }>(null); const onScrollFn = () => { if (window?.scrollY > 600) { lottieRef?.current?.animation?.play?.(); } }; useEffect(() => { window.addEventListener('scroll', onScrollFn); return () => { window.removeEventListener('scroll', onScrollFn); }; }, []); return ( navigate(getLocalizedPathname('docs/spec/introduce', isZhCN(pathname), search)) } > ); }; export default DesignBanner; ================================================ FILE: packages/x/.dumi/pages/index/components/DesignFramework.tsx ================================================ import { createStyles } from 'antd-style'; import { useLocation } from 'dumi'; import React, { useContext } from 'react'; import useLocale from '../../../hooks/useLocale'; import SiteContext from '../../../theme/slots/SiteContext'; import * as utils from '../../../theme/utils'; import Introduction from '../common/Introduction'; const locales = { cn: { title: 'AI 设计语言与研发框架', desc: '配套生态 , 让你快速搭建网站应用', values: 'RICH 设计指南', valuesDesc: '意图、角色、会话、混合 UI', guide: '组件设计指引', guideDesc: '全局样式、设计模式', lib: '组件库', libDesc: 'Ant Design of React / Angular / Vue', // Secondary antd: 'Ant Design', antdDesc: '企业级 UI 设计语言和 React 组件库', antdMobile: 'Ant Design Mobile', antdMobileDesc: 'Ant Design移动端 UI 组件库', antv: 'AntV', antvDesc: '全新一代数据可视化解决方案', }, en: { title: 'Design & Framework', desc: 'An ecosystem for rapid web app development', values: 'RICH Design Guide', valuesDesc: 'Intention, Role, Conversation, Hybrid', guide: 'Design guide', guideDesc: 'Global style and design pattern', lib: 'Components Libraries', libDesc: 'Ant Design of React / Angular / Vue', // Secondary antd: 'Ant Design', antdDesc: 'Help designers/developers building beautiful products more flexible and working with happiness', antdMobile: 'Ant Design Mobile', antdMobileDesc: 'Mobile UI component library', antv: 'AntV', antvDesc: 'New generation of data visualization solutions', }, }; const useStyle = () => { return createStyles(({ token, css }) => ({ container: css` `, header: css` display: flex; align-items: center; justify-content: center; height: 270px; `, card: css` padding: ${token.paddingSM}px; border-radius: ${token.borderRadius * 2}px; box-shadow: 0 1px 2px rgba(0, 0, 0, 0.03), 0 1px 6px -1px rgba(0, 0, 0, 0.02), 0 2px 4px rgba(0, 0, 0, 0.02); background: #ffffff1a; border-radius: 24px; img { width: 100%; vertical-align: top; border-radius: ${token.borderRadius}px; } `, cardMini: css` background: #ffffff1a; border-radius: 24px; display: block; border-radius: ${token.borderRadius * 2}px; padding: ${token.paddingMD}px ${token.paddingLG}px; img { height: 48px; } `, }))(); }; const DesignFramework: React.FC = () => { const [locale] = useLocale(locales); const { styles } = useStyle(); const { pathname, search } = useLocation(); const isZhCN = utils.isZhCN(pathname); const { isMobile } = useContext(SiteContext); const items = [ { title: locale.values, desc: locale.valuesDesc, header: (
thumbnails
), to: utils.getLocalizedPathname('/docs/spec/introduce', isZhCN, search), }, { title: locale.guide, desc: locale.guideDesc, header: (
thumbnails
), to: utils.getLocalizedPathname('/docs/spec/hybrid-ui-design', isZhCN, search), }, { title: locale.lib, desc: locale.libDesc, header: (
thumbnails
), to: utils.getLocalizedPathname('/components/overview', isZhCN, search), }, { title: locale.antd, desc: locale.antdDesc, icon: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*dUzuRJes4pUAAAAAAAAAAAAADgCCAQ/original', to: 'https://ant.design/', }, { title: locale.antdMobile, desc: locale.antdMobileDesc, icon: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*rzh3RoWC9zAAAAAAAAAAAAAADgCCAQ/original', to: 'https://mobile.ant.design/', }, { title: locale.antv, desc: locale.antvDesc, icon: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*9MFyQ77L6E4AAAAAAAAAAAAADgCCAQ/fmt.webp', to: 'https://antv.vision/', }, ]; return ( ); }; export default DesignFramework; ================================================ FILE: packages/x/.dumi/pages/index/components/DesignGuide.tsx ================================================ import { Button } from 'antd'; import { createStyles } from 'antd-style'; import { useLocation, useNavigate } from 'dumi'; import React from 'react'; import useLocale from '../../../hooks/useLocale'; import { getLocalizedPathname, isZhCN } from '../../../theme/utils'; import Container from '../common/Container'; import { DESIGN_STAGE_COLOR } from '../common/CustomizationProvider'; const comma = '\u00A0,\u00A0\u00A0\u00A0'; const locales = { cn: { title: 'AI 界面解决方案', desc: '基于RICH,延续熟悉的 Ant Design 设计语言,全新 AGI 混合界面(Hybrid-UI)解决方案,完美融合 GUI 和自然会话交互。从唤醒到表达,从过程到反馈,合适的组件恰当的呈现在所有的人机互动过程中。', awaken: '唤醒', awaken_title: `轻松唤醒${comma}即刻吸引`, awaken_desc: '可以让首次接触的用户快速理解AI能做什么, 告知用户AI可实现的意图范围, 降低用户成本', awaken_action: '从唤醒开始', express: '表达', express_title: `简单表达${comma}随时反馈`, express_desc: '让用户知道如何快捷且正确的表达意图, 减少AI的不理解风险, 看清自己发送的内容', express_action: '从表达开始', confirm: '确认', confirm_title: `过程确认${comma}尽在掌握`, confirm_desc: '让用户知道该任务的AI执行运转情况, 缓解用户等待焦虑, 有掌控感', confirm_action: '从确认开始', feedback: '反馈', feedback_title: `结果反馈${comma}谁能不信`, feedback_desc: '让用户清晰看到并信任AI任务完成的情况, 并快速应用AI生成结果', feedback_action: '从反馈开始', }, en: { title: 'AI Interface Solution', desc: 'Building on the RICH paradigm and Ant Design language, the AGI Hybrid-UI solution blends GUI with natural conversation, presenting optimal components at each stage of human-computer interaction.', awaken: 'Awaken', awaken_title: `Effortlessly Awaken${comma}Instantly Engage`, awaken_desc: 'Helps new users quickly understand what AI can do, informs them of the AI’s capability range, and lowers entry barriers.', awaken_action: 'Start with Awaken', express: 'Express', express_title: `Simple Express${comma}Instant Feedback`, express_desc: 'Guides users on how to express intentions effectively, reducing misunderstandings with AI and clarifying their input.', express_action: 'Start with Express', confirm: 'Confirm', confirm_title: `Process Confirm${comma}Fully in Control`, confirm_desc: 'Keeps users informed of the AI’s task execution status, easing wait-time anxiety and providing a sense of control.', confirm_action: 'Start with Confirm', feedback: 'Feedback', feedback_title: `Result Feedback${comma}Built-in Trust`, feedback_desc: 'Clearly displays AI task completion, fostering trust, and enabling quick application of AI-generated results.', feedback_action: 'Start with Feedback', }, }; const useStyle = createStyles(({ token, css }) => { return { container: css` `, content: css` display: flex; justify-content: space-between; padding-top: ${token.pcContainerMargin}px; `, chain: css` display: flex; flex-direction: column; width: 100%; max-width: 540px; `, chain_item: css` display: flex; gap: ${token.paddingLG}px; color: #ffffff; `, chain_item_content: css` box-sizing: border-box; display: flex; flex-direction: column; gap: ${token.paddingLG}px; overflow: hidden; `, chain_item_line: css` height: 300px; width: 4px; margin: 0 auto; `, chain_item_label: css` font-size: ${token.fontSizeHeading4}px; font-weight: bold; line-height: 40px; `, chain_item_title: css` font-size: ${token.fontSizeHeading1 + 10}px; line-height: 56px; font-weight: bold; @media only screen and (max-width: ${token.mobileMaxWidth}px) { font-size: ${token.fontSizeHeading2}px; } `, chain_item_desc: css` font-size: ${token.fontSizeHeading5}px; line-height: 32px; opacity: 0.65; `, chain_item_action: css` background: #ffffff1a; position: relative; border-radius: 40px; width: min-content; padding: ${token.paddingLG}px; overflow: hidden; font-size: ${token.fontSizeHeading5}px; font-weight: bold; opacity: 0.9; border: none !important; &::after { content: ''; width: 100%; height: 100%; box-sizing: border-box; border-radius: inherit; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; inset-inline-end: 0; padding: ${token.lineWidth}px; background: linear-gradient(180deg, #ffffff26 0%, #ffffff00 100%); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; }; `, chain_item_icon: css` width: 40px; height: 40px; position: relative; display: flex; align-items: center; justify-content: center; img { width: auto; height: 40px; position: absolute; } `, }; }); const DesignGuide: React.FC = () => { const [locale] = useLocale(locales); const { styles } = useStyle(); const { pathname, search } = useLocation(); const navigate = useNavigate(); const items = [ { icon: 'https://mdn.alipayobjects.com/huamei_lkxviz/afts/img/f14LTKOFxRsAAAAAQbAAAAgADtFMAQFr/original', label: locale.awaken, title: locale.awaken_title, desc: locale.awaken_desc, action: locale.awaken_action, startColor: DESIGN_STAGE_COLOR.AWAKE.START, endColor: DESIGN_STAGE_COLOR.AWAKE.END, path: 'components/welcome', }, { icon: 'https://mdn.alipayobjects.com/huamei_lkxviz/afts/img/dGfqSaM9ZxoAAAAAQaAAAAgADtFMAQFr/original', label: locale.express, title: locale.express_title, desc: locale.express_desc, action: locale.express_action, startColor: DESIGN_STAGE_COLOR.EXPRESS.START, endColor: DESIGN_STAGE_COLOR.EXPRESS.END, path: 'components/attachments', }, { icon: 'https://mdn.alipayobjects.com/huamei_lkxviz/afts/img/BQaCTIUU-CkAAAAAQZAAAAgADtFMAQFr/original', label: locale.confirm, title: locale.confirm_title, desc: locale.confirm_desc, action: locale.confirm_action, startColor: DESIGN_STAGE_COLOR.CONFIRM.START, endColor: DESIGN_STAGE_COLOR.CONFIRM.END, path: 'components/think', }, { icon: 'https://mdn.alipayobjects.com/huamei_lkxviz/afts/img/r-DuSZG-9NIAAAAAQdAAAAgADtFMAQFr/original', label: locale.feedback, title: locale.feedback_title, desc: locale.feedback_desc, action: locale.feedback_action, startColor: DESIGN_STAGE_COLOR.FEEDBACK.START, endColor: DESIGN_STAGE_COLOR.FEEDBACK.END, path: 'components/actions', }, ]; return (
{items.map((item, index) => { const titleParts = item.title.split(item.label); return (
icon icon
{index + 1}. {item.label}
{titleParts[0]} {item.label} {titleParts[1]}
{item.desc}
); })}
); }; export default DesignGuide; ================================================ FILE: packages/x/.dumi/pages/index/components/Lottie.tsx ================================================ import type { AnimationItem } from 'lottie-web'; import React, { useEffect, useImperativeHandle } from 'react'; import useLottie from '../../../hooks/useLottie'; interface Props { path: string; className?: string; onLoad?: (animation: AnimationItem, lottieRef: React.RefObject) => void; config?: { autoplay: boolean; }; ref?: any; } const Lottie: React.FC = ({ path, className, config, ref, onLoad }) => { const [lottieRef, animation] = useLottie({ renderer: 'svg', loop: false, autoplay: config?.autoplay === undefined ? true : config?.autoplay, path, }); useImperativeHandle(ref, () => { return { animation, lottieRef, }; }, [animation, lottieRef.current]); useEffect(() => { if (!animation) return; onLoad?.(animation, lottieRef); return () => { animation?.destroy(); }; }, [animation]); return
; }; export default Lottie; ================================================ FILE: packages/x/.dumi/pages/index/components/MainBanner.tsx ================================================ import { Button } from 'antd'; import { createStyles } from 'antd-style'; import { clsx } from 'clsx'; import { useLocation } from 'dumi'; import type { AnimationDirection, AnimationItem } from 'lottie-web'; import React, { lazy, Suspense, useRef } from 'react'; import useLocale from '../../../hooks/useLocale'; import Link from '../../../theme/common/Link'; import { getLocalizedPathname, isZhCN } from '../../../theme/utils'; import Container from '../common/Container'; import type { SiteContextProps } from './SiteContext'; import SiteContext from './SiteContext'; const locales = { cn: { slogan: 'AI 体验新秩序', desc: 'Ant Design 团队匠心呈现 RICH 设计范式,打造卓越 AI 界面解决方案,引领智能新体验。', start: '开始使用', design: '设计语言', }, en: { slogan: 'New AI Experience', desc: 'The Ant Design team presents the RICH paradigm, crafting superior AI interface solutions and pioneering intelligent experiences.', start: 'Get Started', design: 'Get Design', }, }; const useStyle = createStyles(({ token, css }) => { const minBannerWidth = token.mobileMaxWidth - token.padding * 2; return { banner: css` width: 100vw; height: calc(100vh - 160px); min-height: 600px; display: flex; justify-content: center; align-items: center; position: relative; font-family: AlibabaPuHuiTi, ${token.fontFamily}, sans-serif; @media only screen and (max-width: ${token.mobileMaxWidth}px) { height: calc(100vh - ${token.paddingLG}px); } `, background: css` width: 100%; height: 100vh; position: absolute; filter: blur(50px); background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%); `, container: css` height: 100%; max-height: calc(100vh - ${token.headerHeight * 2}px); position: relative; `, title: css` max-width: ${minBannerWidth}px; position: absolute; top: 50%; inset-inline-start: 0; transform: translateY(-50%); z-index: 1; @media only screen and (max-width: ${token.mobileMaxWidth}px) { width: 100%; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: ${token.paddingXS}px; } `, lottie: css` position: absolute; top: 50%; inset-inline-end: 0; transform: translate(${token.pcContainerMargin}px, -40%); z-index: 0; @media only screen and (max-width: ${token.mobileMaxWidth}px) { display: none; } `, lottie_rtl: css` transform: translate(${token.pcContainerMargin * -2}px, -40%) !important; `, name: css` font-size: 80px !important; line-height: 1.3; color: ${token.colorText}; font-weight: bold; @media only screen and (max-width: ${token.mobileMaxWidth}px) { font-size: 54px !important; } `, desc: css` font-size: ${token.fontSizeHeading5}px; font-weight: 400; max-width: 500px; color: ${token.colorText}; opacity: 0.65; margin: ${token.marginLG}px 0 ${token.marginLG * 2}px 0; `, iAlphabet: css` position: relative; font-size: 60px; display: inline-block; @media only screen and (max-width: ${token.mobileMaxWidth}px) { transform: scale(0.7); top: 6px; } `, iAlphabetStar: css` position: absolute; top: 0; left: 50%; transform: translate(-50%, -50%); width: 22px; height: 22px; background: no-repeat center url('https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*RMOpRLHgA9wAAAAAAAAAAAAADgCCAQ/original'); background-size: cover; &::before { content: ''; width: 100%; height: 100%; box-sizing: border-box; border-radius: inherit; position: absolute; background: radial-gradient(circle, #fe8aff 0%, #fe8aff00 100%); filter: blur(12px); }; `, content: css` display: flex; gap: ${token.paddingLG}px; flex-wrap: wrap; `, btn: css` height: 56px; border: none; border-radius: 40px; padding: 0 40px; display: inline-block; font-size: 18px; cursor: pointer; font-weight: 600; box-shadow: ${token.boxShadow}; position: relative; @media only screen and (max-width: ${token.mobileMaxWidth}px) { padding: 0 ${token.paddingLG}px; } `, startBtn: css` background: linear-gradient(90deg, #c7deff 0%, #ffffffd9 76%); color: #14204c; position: relative; ::after { content: ''; position: absolute; border-radius: 40px; top: 0; left: 0; width: 100%; height: 100%; background: rgba(255, 255, 255, 0.5); opacity: 0; z-index: -1; transition: opacity 0.2s; } :hover::after { opacity: 1; } `, designBtn: css` background: #ffffff1a; backdrop-filter: blur(40px); border: ${token.lineWidth}px solid transparent; &::after { content: ''; width: 100%; height: 100%; box-sizing: border-box; border-radius: inherit; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; inset-inline-end: 0; padding: ${token.lineWidth}px; background: linear-gradient(180deg, #ffffff26 0%, #ffffff00 100%); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; }; `, }; }); const MainBanner: React.FC = () => { const [locale] = useLocale(locales); const { pathname, search } = useLocation(); const { direction, isMobile } = React.useContext(SiteContext); const { styles } = useStyle(); const LottieComponent = lazy(() => import('./Lottie')); const animationDirection = useRef(1); const onLoad = (animation: AnimationItem) => { animation?.addEventListener('complete', () => { animation.loop = true; animation.setSpeed(0.7); animation.playSegments([100, 150], false); }); }; const onBackgroundLoad = (animation: AnimationItem) => { animation?.addEventListener('complete', () => { animationDirection.current = animationDirection.current === -1 ? 1 : -1; animation.setDirection(animationDirection.current); animation.setSpeed(0.6); animation.play(); }); }; return (

Ant Des I gn X

{locale.slogan}

{locale.desc}
{!isMobile && ( )}
); }; export default MainBanner; ================================================ FILE: packages/x/.dumi/pages/index/components/SceneIntroduction/Assistant.tsx ================================================ import type { BubbleItemType } from '@ant-design/x'; import { Bubble, Prompts, Welcome } from '@ant-design/x'; import { DefaultChatProvider, useXChat, XRequest, XRequestOptions } from '@ant-design/x-sdk'; import { Flex, type GetProp, Skeleton } from 'antd'; import { createStyles } from 'antd-style'; import React from 'react'; import useLocale from '../../../../hooks/useLocale'; import CustomizationProvider, { LOCALES } from '../../common/CustomizationProvider'; import CustomizationSender from '../../common/CustomizationSender'; const sleep = () => new Promise((resolve) => setTimeout(resolve, 1000)); interface ChatInput { query: string; } const roles: GetProp = { ai: { placement: 'start', typing: { effect: 'typing', step: 5, interval: 20 }, style: { maxWidth: 600, }, styles: { content: { borderRadius: 16, }, }, }, local: { placement: 'end', styles: { content: { borderRadius: 16, background: '#3877FF', }, }, contentRender(content: ChatInput) { return content?.query; }, }, }; const useStyle = createStyles(({ token, css }) => { return { container: css` display: flex; padding: ${token.paddingXL}px 0px; box-sizing: border-box; flex-direction: column; gap: ${token.paddingSM}px; height: 100%; width: 350px; background: #0000001a; `, content: css` padding: ${token.paddingXL}px; flex: 1; display: flex; flex-direction: column; gap: ${token.padding}px; `, bubble_list: css` flex: 1; `, placeholder_bubble: css` .ant-welcome { padding: 0; } .ant-welcome-title { font-size: 16px !important; font-weight: 500 !important; opacity: 0.9; } .ant-welcome-description { font-size: 12px; opacity: 0.65; } .ant-welcome-icon { img { transform: scale(1.2); margin-inline-end: 10px; } } .ant-bubble-content { overflow: hidden; background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%) !important; width: 100%; border-radius: 16px; padding: 24px; } .ant-prompts { padding: 0; } .ant-prompts-item { background: rgba(255, 255, 255, 0.05); box-sizing: border-box; padding: 8px 16px; font-size: 12px; height: 36px; line-height: 36px; border: none; flex: 1; } `, }; }); const AssistantScene: React.FC = () => { const { styles } = useStyle(); const [locale] = useLocale(LOCALES); const [content, setContent] = React.useState(''); const [provider] = React.useState( new DefaultChatProvider({ request: XRequest('https://api.example.com/chat', { manual: true, fetch: async ( _: Parameters[0], options: XRequestOptions, ) => { await sleep(); const params = options?.params; return Promise.resolve( new Response(JSON.stringify([`Mock success return. You said: ${params?.query}`]), { headers: { 'Content-Type': 'application/json' }, }), ); }, }), }), ); const { onRequest, messages, isRequesting } = useXChat({ provider, requestPlaceholder: 'Waiting...', requestFallback: 'Mock failed return. Please try again later.', }); const placeholderMessage: BubbleItemType = { role: 'system', key: 'placeholder', variant: 'borderless', className: styles.placeholder_bubble, content: ( } variant="borderless" title={locale.greeting_short} description={locale.description_short} /> ), footer: ( { onRequest({ query: item.data.description as string }); }} vertical items={[ { key: '1-1', description: locale.question1, }, { key: '1-2', description: locale.question2, }, { key: '1-3', description: locale.question3, }, { key: '1-4', description: locale.question4, }, ]} /> ), }; return (
({ key: id, loading: status === 'loading', role: status === 'local' ? 'local' : 'ai', content: message, })), ]} /> { if (!nextContent) return; onRequest({ query: nextContent }); setContent(''); }} />
); }; export default AssistantScene; ================================================ FILE: packages/x/.dumi/pages/index/components/SceneIntroduction/Independent.tsx ================================================ import type { BubbleItemType } from '@ant-design/x'; import { Bubble, Prompts, Welcome } from '@ant-design/x'; import { DefaultChatProvider, useXChat, XRequest, XRequestOptions } from '@ant-design/x-sdk'; import { type GetProp, Tag } from 'antd'; import { createStyles } from 'antd-style'; import React from 'react'; import useLocale from '../../../../hooks/useLocale'; import CustomizationProvider, { LOCALES } from '../../common/CustomizationProvider'; import CustomizationSender from '../../common/CustomizationSender'; interface ChatInput { query: string; } const sleep = () => new Promise((resolve) => setTimeout(resolve, 1000)); const roles: GetProp = { ai: { placement: 'start', typing: { effect: 'typing', step: 5, interval: 20 }, styles: { content: { borderRadius: 16, }, }, }, local: { placement: 'end', styles: { content: { borderRadius: 16, background: '#3877FF', }, }, contentRender(content: ChatInput) { return content?.query; }, }, }; const useStyle = createStyles(({ token, css }) => { return { container: css` display: flex; box-sizing: border-box; flex-direction: column; align-items: center; gap: ${token.padding}px; height: 100%; justify-content: space-between; padding-block: ${token.paddingXL}px; `, bubble_list: css` flex: 1; `, placeholder_bubble: css` .ant-welcome { padding: 0; margin-bottom: ${token.marginSM}px; } .ant-welcome-title { font-size: 16px !important; font-weight: 500 !important; opacity: 0.9; } .ant-welcome-description { font-size: 12px; opacity: 0.65; } .ant-welcome-icon { img { transform: scale(1.2); margin-inline-end: 10px; } } .ant-bubble-content { overflow: hidden; background: linear-gradient(135deg, #ffffff26 14%, #ffffff0d 59%) !important; width: 100%; border-radius: 16px; padding: 24px; } .ant-prompts-content { display: flex; align-items: center; justify-content: center; height: 100%; } .ant-tag { background: linear-gradient(45deg, #ffffff33 0%, #ffffff00 100%); border: 1px solid #ffffff4d; border-radius: 4px; margin: 0; width: 18px; height: 18px; display: inline-flex; align-items: center; justify-content: center; } .ant-prompts { padding: 0; } .ant-prompts-desc { line-height: 2 !important; } .ant-prompts-item { background: rgba(255, 255, 255, 0.05); padding: 16px; border: none; flex: 1; height: 100%; } `, }; }); const IndependentScene: React.FC = () => { const { styles } = useStyle(); const [locale] = useLocale(LOCALES); const [content, setContent] = React.useState(''); const [provider] = React.useState( new DefaultChatProvider({ request: XRequest('https://api.example.com/chat', { manual: true, fetch: async ( _: Parameters[0], options: XRequestOptions, ) => { await sleep(); const params = options?.params; return Promise.resolve( new Response(JSON.stringify([`Mock success return. You said: ${params?.query}`]), { headers: { 'Content-Type': 'application/json' }, }), ); }, }), }), ); const { onRequest, messages, isRequesting } = useXChat({ provider, requestPlaceholder: 'Waiting...', requestFallback: 'Mock failed return. Please try again later.', }); const placeholderMessage: BubbleItemType = { role: 'system', key: 'placeholder', variant: 'borderless', className: styles.placeholder_bubble, content: (
} title={locale.greeting} description={locale.description} variant="borderless" /> { onRequest({ query: item.data.description as string, }); }} styles={{ subItem: { background: 'none', padding: '4px 0', }, }} items={[ { key: '1', label: locale.hot_question, children: [ { key: '1-1', icon: 1, description: locale.question1, }, { key: '1-2', icon: 2, description: locale.question2, }, { key: '1-3', icon: 3, description: locale.question3, }, { key: '1-4', icon: 4, description: locale.question4, }, ], }, { key: '2', label: locale.design_guide, children: [ { key: '2-1', icon: 1, description: locale.empathy, }, { key: '2-2', icon: 2, description: locale.persona, }, { key: '2-3', icon: 3, description: locale.conversation, }, { key: '2-4', icon: 4, description: locale.interface, }, ], }, ]} />
), }; return (
({ key: id, loading: status === 'loading', role: status === 'local' ? 'local' : 'ai', content: message, })), ]} /> { if (!nextContent) return; onRequest({ query: nextContent, }); setContent(''); }} />
); }; export default IndependentScene; ================================================ FILE: packages/x/.dumi/pages/index/components/SceneIntroduction/Nest.tsx ================================================ import { createStyles } from 'antd-style'; import React from 'react'; import useLocale from '../../../../hooks/useLocale'; import { LOCALES, useCustomizationBgStyle } from '../../common/CustomizationProvider'; import CustomizationSender from '../../common/CustomizationSender'; const useStyle = createStyles(({ token, css }) => { return { container: css` display: flex; height: 100%; width: 100%; align-items: center; justify-content: center; flex-direction: column; gap: ${token.paddingLG}px; `, title: css` font-size: 42px; color: #ffffff3f; line-height: 50px; font-weight: 500; `, }; }); const NestScene: React.FC = () => { const { styles } = useStyle(); const { styles: { background }, } = useCustomizationBgStyle(); const [locale] = useLocale(LOCALES); return (
{locale.greeting_short}
); }; export default NestScene; ================================================ FILE: packages/x/.dumi/pages/index/components/SceneIntroduction/index.tsx ================================================ import { Button, Carousel } from 'antd'; import { createStyles } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; import useLocale from '../../../../hooks/useLocale'; import Container from '../../common/Container'; import SiteContext from '../SiteContext'; import AssistantScene from './Assistant'; import Independent from './Independent'; import NestScene from './Nest'; const locales = { cn: { title: '试一试 , 多种 AI 场景体验', desc: '提供多场景解决方案 , 帮助用户提高与 AI 协作效率', independent_title: 'Web 独立式', independent_desc: '自然语言为主 , 几乎没有界面操作', assistant_title: 'Web 助手式', assistant_desc: '自然语言和界面操作均衡配合使用', nest_title: 'Web 嵌入式', nest_desc: '界面操作为主 , 偶尔唤起AI指令', app_title: 'App 端', app_desc: '疯狂研发中 , 敬请期待', }, en: { title: 'Multiple AI Scenario Experiences', desc: 'Offering multi-scenario solutions to help users enhance collaboration efficiency with AI', independent_title: 'Web - Independent', independent_desc: 'Primarily LUI', assistant_title: 'Web - Assistant', assistant_desc: 'Mix of LUI and GUI', nest_title: 'Web - Nest', nest_desc: 'Mainly UI-driven', app_title: 'Mobile - APP', app_desc: 'In development, stay tuned', }, }; const useStyle = createStyles(({ token, css }) => { return { container: css` position: relative; @media screen and (max-width: ${token.mobileMaxWidth}px) { height: 100vh; } `, content_bg: css` position: absolute; top: 0; right: 0; transform: translate(10%, -20%); `, content: css` display: flex; justify-content: space-between; gap: ${token.paddingXL}px; width: 100%; margin-top: ${token.pcContainerMargin / 2}px; `, mobile_content: css` margin: ${token.marginXXL}px 0; h3 { text-align: center; font-size: ${token.fontSizeHeading3}px; } p { text-align: center; opacity: 0.65; } img { width: 100%; background: #0c0e10cc; border-radius: 12px; margin-top: ${token.margin}px; } `, tab: css` width: 280px; display: flex; flex-direction: column; gap: ${token.margin}px; `, tab_content: css` width: 890px; height: 600px; box-sizing: border-box; background-image: url(https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*RxJMSbQRvTUAAAAAAAAAAAAADgCCAQ/fmt.avif); background-repeat: no-repeat; background-size: cover; z-index: 2; `, item: css` position: relative; border-radius: 20px; height: 86px; padding: ${token.padding}px; box-sizing: border-box; display: flex; gap: 4px; flex-direction: column; align-items: flex-start; cursor: pointer; border: none !important; `, 'item-disabled': css` h3,p { color: ${token.colorTextDisabled}; } `, 'item-active': css` background: #ffffff1a; &::after { content: ''; width: 100%; height: 100%; box-sizing: border-box; border-radius: inherit; position: absolute; top: 0; bottom: 0; inset-inline-start: 0; inset-inline-end: 0; padding: ${token.lineWidth}px; background: linear-gradient(180deg, #ffffff26 0%, #ffffff00 100%); mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); mask-composite: exclude; }; `, item_title: css` font-size: ${token.fontSizeHeading4}px; color: #ffffff; font-weight: 500; `, item_desc: css` font-size: 14px; color: #ffffff; line-height: 22px; opacity: 0.65; `, }; }); const SceneBanner: React.FC = () => { const { styles } = useStyle(); const [locale] = useLocale(locales); const { isMobile } = React.useContext(SiteContext); const tabItems = [ { key: 'independent', title: locale.independent_title, desc: locale.independent_desc, content: , img: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*YVjbTqbc7ngAAAAAAAAAAAAADgCCAQ/fmt.avif', }, { key: 'assistant', title: locale.assistant_title, desc: locale.assistant_desc, content: , img: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*kCojRo0SoAAAAAAAAAAAAAAADgCCAQ/fmt.avif', }, { key: 'nest', title: locale.nest_title, desc: locale.nest_desc, content: , img: 'https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*krfsT5zBSuUAAAAAAAAAAAAADgCCAQ/fmt.avif', }, { key: 'app', title: locale.app_title, desc: locale.app_desc, disabled: true, content: null, }, ]; const [active, setActive] = React.useState(tabItems[0].key); const genHandleActive = (key: string) => () => setActive(key); const activeContent = tabItems.find((item) => item.key === active)?.content; return ( {!isMobile && ( bg )} {isMobile ? ( {tabItems.map( (item) => item.img && (

{item.title}

{item.desc}

item.img
), )}
) : (
{tabItems.map((item) => ( ))}
{!!activeContent &&
{activeContent}
}
)}
); }; export default SceneBanner; ================================================ FILE: packages/x/.dumi/pages/index/components/SiteContext.ts ================================================ import SiteContext from '../../../theme/slots/SiteContext'; export type { SiteContextProps } from '../../../theme/slots/SiteContext'; export default SiteContext; ================================================ FILE: packages/x/.dumi/pages/index/index.tsx ================================================ import { createStyles } from 'antd-style'; import { clsx } from 'clsx'; import React, { lazy, Suspense } from 'react'; import DesignBanner from './components/DesignBanner'; import MainBanner from './components/MainBanner'; const useStyle = createStyles(({ token, css }) => { return { section: css` background: linear-gradient(180deg, #1e2226e6 0%, #1c2024 38%, #16191c 100%); border-radius: 40px 40px 0 0; backdrop-filter: blur(40px); display: flex; flex-direction: column; gap: ${token.pcContainerMargin}px; padding: ${token.pcContainerMargin}px 0; `, container: css` margin-top: -40px; `, framework: css` border-radius: 0; background-image: linear-gradient(90deg, #5a37e6 0%, #0059c9 100%); `, }; }); const Homepage: React.FC = () => { const { styles } = useStyle(); const DesignFramework = lazy(() => import('./components/DesignFramework')); const CompIntroduction = lazy(() => import('./components/CompIntroduction')); const SceneIntroduction = lazy(() => import('./components/SceneIntroduction')); const DesignGuide = lazy(() => import('./components/DesignGuide')); return (
); }; export default Homepage; ================================================ FILE: packages/x/.dumi/pages/index-cn/index.ts ================================================ import Homepage from '../index/index'; export default Homepage; ================================================ FILE: packages/x/.dumi/preset/.gitkeep ================================================ ================================================ FILE: packages/x/.dumi/rehypeAntd.ts ================================================ import assert from 'assert'; import type { HastRoot, UnifiedTransformer } from 'dumi'; import { unistUtilVisit } from 'dumi'; /** * plugin for modify hast tree when docs compiling */ function rehypeAntd(): UnifiedTransformer { return (tree, vFile) => { const { filename } = vFile.data.frontmatter as any; unistUtilVisit.visit(tree, 'element', (node, i, parent) => { if (node.tagName === 'DumiDemoGrid') { // replace DumiDemoGrid to DemoWrapper, to implement demo toolbar node.tagName = 'DemoWrapper'; } else if (node.tagName === 'ResourceCards') { const propNames = ['title', 'cover', 'description', 'src', 'official']; const contentNode = node.children[0]; assert( contentNode.type === 'text', `ResourceCards content must be plain text!\nat ${filename}`, ); // clear children node.children = []; // generate JSX props (node as any).JSXAttributes = [ { type: 'JSXAttribute', name: 'resources', value: JSON.stringify( contentNode.value .trim() .split('\n') .reduce((acc, cur) => { // match text from ` - 桌面组件 Sketch 模板包` const [, isProp, val] = cur.match(/(\s+)?-\s(.+)/)!; if (!isProp) { // create items when match title acc.push({ [propNames[0]]: val }); } else { // add props when match others const prev = acc[acc.length - 1]; prev[propNames[Object.keys(prev).length]] = val; } return acc; }, []), ), }, ]; } else if ( node.type === 'element' && node.tagName === 'Table' && /^(components|docs\/x-sdk|docs\/x-markdown)/.test(filename) ) { if (!node.properties) return; node.properties.className ??= []; (node.properties.className as string[]).push('component-api-table'); } else if (node.type === 'element' && (node.tagName === 'Link' || node.tagName === 'a')) { const { tagName } = node; node.properties!.sourceType = tagName; node.tagName = 'LocaleLink'; } else if (node.type === 'element' && node.tagName === 'video') { node.tagName = 'VideoPlayer'; } else if (node.tagName === 'SourceCode') { const { lang } = node.properties!; if (typeof lang === 'string' && lang.startsWith('sandpack')) { const code = (node.children[0] as any).value as string; const configRegx = /^const sandpackConfig = ([\s\S]*?});/; const [configString] = code.match(configRegx) || []; /* biome-ignore lint/security/noGlobalEval: used in documentation */ /* eslint-disable-next-line no-eval */ const config = configString && eval(`(${configString.replace(configRegx, '$1')})`); Object.keys(config || {}).forEach((key) => { if (typeof config[key] === 'object') { config[key] = JSON.stringify(config[key]); } }); parent!.children.splice(i!, 1, { type: 'element', tagName: 'Sandpack', properties: { ...config, }, children: [ { type: 'text', value: code.replace(configRegx, '').trim(), }, ], }); } } }); }; } export default rehypeAntd; ================================================ FILE: packages/x/.dumi/remarkAnchor.ts ================================================ import type { UnifiedTransformer } from 'dumi'; import { unistUtilVisit } from 'dumi'; let toSlug: typeof import('github-slugger').slug; // workaround to import pure esm module (async () => { ({ slug: toSlug } = await import('github-slugger')); })(); const isNil = (value: any) => value == null; const toArr = (value: T | T[]) => { if (isNil(value)) return []; return Array.isArray(value) ? value : [value]; }; const patch = (context: Record, key: string, value: any) => { if (!context[key]) { context[key] = value; } return context[key]; }; interface Options { level?: number; } const remarkAnchor = (opt: Options = {}): UnifiedTransformer => { // https://regex101.com/r/WDjkK0/1 const RE = /\s*\{#([^}]+)\}$/; const realOpt = { level: [1, 2, 3, 4, 5, 6], ...opt, }; return function transformer(tree) { const ids = new Set(); unistUtilVisit.visit(tree, 'heading', (node) => { if (toArr(realOpt.level).indexOf(node.depth) === -1) { return unistUtilVisit.CONTINUE; } const lastChild = node.children.at(-1); if (lastChild?.type === 'text') { const text = lastChild.value; const match = text.match(RE); if (match) { const id = match[1]; if (id !== toSlug(id)) { throw new Error( `Expected header ID to be a valid slug. You specified: {#${id}}. Replace it with: {#${toSlug(id)}}`, ); } node.data ??= {}; node.data.hProperties = { ...node.data.hProperties, id }; lastChild.value = text.replace(RE, ''); if (lastChild.value === '') { node.children.pop(); } if (ids.has(id)) { throw new Error(`Cannot have a duplicate header with id "${id}" on the page. Rename the section or give it an explicit unique ID. For example: #### Arguments {#setstate-arguments}`); } ids.add(id); const data = patch(node, 'data', {}); patch(data, 'id', id); patch(data, 'htmlAttributes', {}); patch(data, 'hProperties', {}); patch(data.htmlAttributes, 'id', id); patch(data.hProperties, 'id', id); } } }); }; }; export default remarkAnchor; ================================================ FILE: packages/x/.dumi/remarkAntd.ts ================================================ import type { UnifiedTransformer } from 'dumi'; import { unistUtilVisit } from 'dumi'; function remarkMeta(): UnifiedTransformer { return (tree, vFile) => { // read frontmatter unistUtilVisit.visit(tree, 'yaml', (node) => { if (!/(^|[\n\r])description:/.test(node.value)) { (vFile.data.frontmatter as any).__autoDescription = true; } }); }; } export default remarkMeta; ================================================ FILE: packages/x/.dumi/theme/SiteThemeProvider.tsx ================================================ import { theme as antdTheme, ConfigProvider } from 'antd'; import type { ThemeConfig } from 'antd/es/config-provider'; import type { ThemeProviderProps } from 'antd-style'; import { ThemeProvider } from 'antd-style'; import React, { useContext } from 'react'; interface NewToken { bannerHeight: number; headerHeight: number; alertHeight: number; menuItemBorder: number; mobileMaxWidth: number; siteMarkdownCodeBg: string; antCls: string; iconCls: string; marginFarXS: number; marginFarSM: number; marginFar: number; codeFamily: string; contentMarginTop: number; anchorTop: number; indexRadius: number; pcMaxWidth: number; pcContainerMargin: number; } // 通过给 antd-style 扩展 CustomToken 对象类型定义,可以为 useTheme 中增加相应的 token 对象 declare module 'antd-style' { export interface CustomToken extends NewToken {} } const alertHeight = 40; const headerHeight = 80; const bannerHeight = 38; const indexRadius = 24; const pcMaxWidth = 1560; const SiteThemeProvider: React.FC> = ({ children, theme, ...rest }) => { const { getPrefixCls, iconPrefixCls } = useContext(ConfigProvider.ConfigContext); const rootPrefixCls = getPrefixCls(); const { token } = antdTheme.useToken(); React.useEffect(() => { // 需要注意与 components/config-provider/demo/holderRender.tsx 配置冲突 ConfigProvider.config({ theme: theme as ThemeConfig }); }, [theme]); return ( {...rest} theme={theme} customToken={{ headerHeight, alertHeight, bannerHeight, indexRadius, pcMaxWidth, pcContainerMargin: 100, menuItemBorder: 2, mobileMaxWidth: 767.99, siteMarkdownCodeBg: token.colorFillTertiary, antCls: `.${rootPrefixCls}`, iconCls: `.${iconPrefixCls}`, /** 56 */ marginFarXS: (token.marginXXL / 6) * 7, /** 80 */ marginFarSM: (token.marginXXL / 3) * 5, /** 96 */ marginFar: token.marginXXL * 2, codeFamily: `'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, Courier, monospace`, contentMarginTop: 40, anchorTop: headerHeight + token.margin, }} > {children} ); }; export default SiteThemeProvider; ================================================ FILE: packages/x/.dumi/theme/builtins/APITable/index.tsx ================================================ import React from 'react'; const APITable: React.FC = () => ( // TODO: implement api table, depend on the new markdown data structure passed <>API Table ); export default APITable; ================================================ FILE: packages/x/.dumi/theme/builtins/Antd.tsx ================================================ import * as all from 'antd'; import * as React from 'react'; interface AntdProps { component: keyof typeof all; } function Antd(props: AntdProps) { const { component, ...restProps } = props; // biome-ignore lint/performance/noDynamicNamespaceImportAccess: it is useful const Component = (all[component] ?? React.Fragment) as React.ComponentType; return ; } export default Antd; ================================================ FILE: packages/x/.dumi/theme/builtins/Audio/index.tsx ================================================ import { SoundOutlined } from '@ant-design/icons'; import { createStyles } from 'antd-style'; import React from 'react'; const useStyle = createStyles(({ css, token }) => { const { paddingXXS, fontSizeXL, motionDurationSlow, colorLink, colorLinkHover, colorLinkActive } = token; return { playBtn: css` display: inline-flex; justify-content: center; align-items: center; column-gap: ${paddingXXS}px; margin: 0; `, icon: css` font-size: ${fontSizeXL}px; color: ${colorLink}; transition: all ${motionDurationSlow}; &:hover { color: ${colorLinkHover}; } &:active { color: ${colorLinkActive}; } `, }; }); interface AudioProps { id?: string; } const AudioControl: React.FC> = ({ id, children }) => { const { styles } = useStyle(); const onClick: React.MouseEventHandler = () => { const audio = document.querySelector(`#${id}`); audio?.play(); }; return ( {children} ); }; export default AudioControl; ================================================ FILE: packages/x/.dumi/theme/builtins/Badge/index.tsx ================================================ import { Tag, TagProps } from 'antd'; import * as React from 'react'; // https://github.com/umijs/dumi/blob/master/src/client/theme-default/builtins/Badge/index.tsx interface BadgeProps extends TagProps { type: 'info' | 'warning' | 'error' | 'success'; } const colorMap = { info: 'blue', warning: 'orange', error: 'red', success: 'green', }; export default ({ type = 'info', ...props }: BadgeProps) => ( ); ================================================ FILE: packages/x/.dumi/theme/builtins/ColorChunk/index.tsx ================================================ import type { ColorInput } from '@ant-design/fast-color'; import { FastColor } from '@ant-design/fast-color'; import { Popover } from 'antd'; import { createStyles } from 'antd-style'; import * as React from 'react'; const useStyle = createStyles(({ token, css }) => ({ codeSpan: css` padding: 0.2em 0.4em; font-size: 0.9em; background: ${token.siteMarkdownCodeBg}; border-radius: ${token.borderRadius}px; font-family: monospace; `, dot: css` display: inline-block; width: 6px; height: 6px; border-radius: 50%; margin-inline-end: ${token.marginXXS}px; border: 1px solid ${token.colorSplit}; `, })); interface ColorChunkProps { value: ColorInput; enablePopover?: boolean; } const ColorChunk: React.FC> = (props) => { const { styles, theme } = useStyle(); const { value, children, enablePopover } = props; const dotColor = React.useMemo(() => new FastColor(value).toHexString(), [value]); let dotNode = ( {children ?? dotColor} ); if (enablePopover) { dotNode = ( ); } return dotNode; }; export default ColorChunk; ================================================ FILE: packages/x/.dumi/theme/builtins/ColorPaletteTool/index.ts ================================================ import ColorPaletteTool from '../../common/Color/ColorPaletteTool'; export default ColorPaletteTool; ================================================ FILE: packages/x/.dumi/theme/builtins/ColorPaletteToolDark/index.ts ================================================ import ColorPaletteToolDark from '../../common/Color/ColorPaletteToolDark'; export default ColorPaletteToolDark; ================================================ FILE: packages/x/.dumi/theme/builtins/ColorPalettes/index.ts ================================================ import ColorPalettes from '../../common/Color/ColorPalettes'; export default ColorPalettes; ================================================ FILE: packages/x/.dumi/theme/builtins/ComponentMeta/index.tsx ================================================ import { CompassOutlined, EditOutlined, GithubOutlined, HistoryOutlined } from '@ant-design/icons'; import type { GetProp } from 'antd'; import { Descriptions, Flex, Tooltip, Typography, theme } from 'antd'; import { createStyles, css } from 'antd-style'; import kebabCase from 'lodash/kebabCase'; import React from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; import useLocale from '../../../hooks/useLocale'; import ComponentChangelog from '../../common/ComponentChangelog'; import Link from '../../common/Link'; const locales = { cn: { import: '使用', copy: '复制', copied: '已复制', source: '源码', docs: '文档', edit: '编辑此页', changelog: '更新日志', design: '设计指南', version: '版本', }, en: { import: 'Import', copy: 'Copy', copied: 'Copied', source: 'Source', docs: 'Docs', edit: 'Edit this page', changelog: 'Changelog', design: 'Design', version: 'Version', }, }; const branchUrl = 'https://github.com/ant-design/x/edit/main/packages/x/'; function isVersionNumber(value?: string) { return value && /^\d+\.\d+\.\d+$/.test(value); } const useStyle = createStyles(({ token }) => ({ code: css` cursor: pointer; position: relative; display: inline-flex; align-items: center; column-gap: ${token.paddingXXS}px; border-radius: ${token.borderRadiusSM}px; padding-inline: ${token.paddingXXS}px !important; transition: all ${token.motionDurationSlow} !important; font-family: ${token.codeFamily}; color: ${token.colorTextSecondary} !important; &:hover { background: ${token.controlItemBgHover}; } a&:hover { text-decoration: underline !important; } `, icon: css` margin-inline-end: 3px; `, })); export interface ComponentMetaProps { component: string; source: string | true; filename?: string; version?: string; packageName?: string; designUrl?: string; } const ComponentMeta: React.FC = (props) => { const { component, packageName = 'x', source, filename, version, designUrl } = props; const { token } = theme.useToken(); const [locale, lang] = useLocale(locales); const isZhCN = lang === 'cn'; const { styles } = useStyle(); // ========================= Copy ========================= const [copied, setCopied] = React.useState(false); const onCopy = () => { setCopied(true); }; const onOpenChange = (open: boolean) => { if (open) { setCopied(false); } }; const getPackageCodeUrl = (kebabComponent: string, packageName: string) => { switch (packageName) { case 'x-sdk': { const sdkComponent = kebabComponent.replace('use-', ''); return [ `https://github.com/ant-design/x/blob/main/packages/x-sdk/src/${sdkComponent}`, `x-sdk/src/${sdkComponent}`, ]; } case 'x-markdown': return [ `https://github.com/ant-design/x/blob/main/packages/x-markdown/src/${kebabComponent}`, `x-markdown/src/${kebabComponent}`, ]; case 'x-markdown/plugins': return [ `https://github.com/ant-design/x/blob/main/packages/x-markdown/src/plugins/${kebabComponent}`, `x-markdown/src/plugins/${kebabComponent}`, ]; default: return [ `https://github.com/ant-design/x/blob/main/packages/x/components/${kebabComponent}`, `x/components/${kebabComponent}`, ]; } }; // ======================== Source ======================== const [filledSource, abbrSource] = React.useMemo(() => { if (String(source) === 'true') { const kebabComponent = kebabCase(component); return getPackageCodeUrl(kebabComponent, packageName); } if (typeof source !== 'string') { return [null, null]; } return [source, source]; }, [component, source, packageName]); const transformComponentName = (componentName: string) => { if (componentName === 'Notification') { return componentName.toLowerCase(); } return componentName; }; // ======================== Render ======================== const importList = packageName !== 'x-markdown/plugins' ? `import { ${transformComponentName(component)} } from "@ant-design/${packageName}";` : `import ${transformComponentName(component)} from "@ant-design/x-markdown/plugins/${transformComponentName(component)}";`; return ( {importList} ), }, filledSource && { label: locale.source, children: ( {abbrSource} ), }, filename && { label: locale.docs, children: ( {locale.edit} {designUrl && ( {locale.design} )} {locale.changelog} ), }, isVersionNumber(version) && { label: locale.version, children: ( {isZhCN ? `自 ${version} 起支持` : `supported since ${version}`} ), }, ].filter(Boolean) as GetProp } /> ); }; export default ComponentMeta; ================================================ FILE: packages/x/.dumi/theme/builtins/ComponentOverview/index.tsx ================================================ import { SearchOutlined } from '@ant-design/icons'; import { Affix, Card, Col, Divider, Flex, Input, Row, Tag, Typography } from 'antd'; import { createStyles, useTheme } from 'antd-style'; import { useIntl, useLocation, useSidebarData } from 'dumi'; import debounce from 'lodash/debounce'; import type { CSSProperties } from 'react'; import React, { memo, useMemo, useRef, useState } from 'react'; import scrollIntoView from 'scroll-into-view-if-needed'; import Link from '../../common/Link'; import SiteContext from '../../slots/SiteContext'; import type { Component } from './ProComponentsList'; const useStyle = createStyles(({ token, css }) => ({ componentsOverviewGroupTitle: css` margin-bottom: ${token.marginLG}px !important; `, componentsOverviewTitle: css` overflow: hidden; color: ${token.colorTextHeading}; text-overflow: ellipsis; `, componentsOverviewImg: css` display: flex; align-items: center; justify-content: center; height: 152px; `, componentsOverviewCard: css` cursor: pointer; transition: all 0.5s; &:hover { box-shadow: 0 6px 16px -8px #00000014, 0 9px 28px #0000000d, 0 12px 48px 16px #00000008; } `, componentsOverviewAffix: css` display: flex; transition: all ${token.motionDurationSlow}; justify-content: space-between; `, componentsOverviewSearch: css` padding: 0; box-shadow: none !important; .anticon-search { color: ${token.colorTextDisabled}; } `, componentsOverviewContent: css` &:empty:after { display: block; padding: ${token.padding}px 0 ${token.paddingMD * 2}px; color: ${token.colorTextDisabled}; text-align: center; border-bottom: 1px solid ${token.colorSplit}; content: 'Not Found'; } `, })); const onClickCard = (pathname: string) => { if (window.gtag) { window.gtag('event', '点击', { event_category: '组件总览卡片', event_label: pathname, }); } }; const reportSearch = debounce<(value: string) => void>((value) => { if (window.gtag) { window.gtag('event', '搜索', { event_category: '组件总览卡片', event_label: value, }); } }, 2000); const { Title } = Typography; const Overview: React.FC = () => { const { styles } = useStyle(); const { theme } = React.use(SiteContext); const data = useSidebarData(); const [searchBarAffixed, setSearchBarAffixed] = useState(false); const token = useTheme(); const { borderRadius, colorBgContainer, fontSizeXL, anchorTop } = token; const affixedStyle: CSSProperties = { boxShadow: 'rgba(50, 50, 93, 0.25) 0 6px 12px -2px, rgba(0, 0, 0, 0.3) 0 3px 7px -3px', padding: 8, margin: -8, borderRadius, backgroundColor: colorBgContainer, }; const { search: urlSearch } = useLocation(); const { locale, formatMessage } = useIntl(); const [search, setSearch] = useState(() => { const params = new URLSearchParams(urlSearch); if (params.has('s')) { return params.get('s') || ''; } return ''; }); const sectionRef = useRef(null); const onKeyDown: React.KeyboardEventHandler = (event) => { if (event.keyCode === 13 && search.trim().length) { sectionRef.current?.querySelector(`.${styles.componentsOverviewCard}`)?.click(); } }; const groups = useMemo<{ title: string; children: Component[] }[]>( () => data .filter((item) => item?.title) .map<{ title: string; children: Component[] }>((item) => ({ title: item?.title || '', children: item.children.map((child) => ({ title: child.frontmatter?.title || '', subtitle: child.frontmatter?.subtitle, cover: child.frontmatter?.cover, coverDark: child.frontmatter?.coverDark, link: child.link, })), })), [data, locale], ); return (
setSearchBarAffixed(!!affixed)}>
{ setSearch(e.target.value); reportSearch(e.target.value); if (sectionRef.current && searchBarAffixed) { scrollIntoView(sectionRef.current, { scrollMode: 'if-needed', block: 'start', behavior: (actions) => actions.forEach(({ el, top }) => { el.scrollTop = top - 64; }), }); } }} onKeyDown={onKeyDown} variant="borderless" suffix={} style={{ fontSize: searchBarAffixed ? fontSizeXL - 2 : fontSizeXL }} />
{groups .filter((i) => i?.title) .map((group) => { const components = group?.children?.filter( (component) => !search.trim() || component?.title?.toLowerCase()?.includes(search.trim().toLowerCase()) || (component?.subtitle || '').toLowerCase().includes(search.trim().toLowerCase()), ); return components?.length ? (
<Flex gap="small" align="center"> <span style={{ fontSize: 24 }}>{group?.title}</span> <Tag style={{ display: 'block' }}>{components.length}</Tag> </Flex> {components.map((component) => { let url = component.link; /** 是否是外链 */ const isExternalLink = url.startsWith('http'); if (!isExternalLink) { url += urlSearch; } const cardContent = ( onClickCard(url)} styles={{ body: { backgroundRepeat: 'no-repeat', backgroundPosition: 'bottom right', backgroundImage: `url(${component.tag || ''})`, }, }} size="small" className={styles.componentsOverviewCard} title={
{component.title} {component.subtitle}
} >
{component.title}
); const linkContent = isExternalLink ? ( {cardContent} ) : ( {cardContent} ); return ( {linkContent} ); })}
) : null; })}
); }; export default memo(Overview); ================================================ FILE: packages/x/.dumi/theme/builtins/ComponentTokenTable/index.tsx ================================================ import { LinkOutlined, QuestionCircleOutlined, RightOutlined } from '@ant-design/icons'; import { XProvider } from '@ant-design/x'; import tokenData from '@ant-design/x/es/version/token.json'; import tokenMeta from '@ant-design/x/es/version/token-meta.json'; import { Flex, Popover, Table, Typography } from 'antd'; import { createStyles, css, useTheme } from 'antd-style'; import { getDesignToken } from 'antd-token-previewer'; import React, { useMemo, useState } from 'react'; import useLocale from '../../../hooks/useLocale'; import type { TokenData } from '../TokenTable'; import { useColumns } from '../TokenTable'; const compare = (token1: string, token2: string) => { const hasColor1 = token1.toLowerCase().includes('color'); const hasColor2 = token2.toLowerCase().includes('color'); if (hasColor1 && !hasColor2) { return -1; } if (!hasColor1 && hasColor2) { return 1; } return token1 < token2 ? -1 : 1; }; const defaultToken: any = getDesignToken(); const xTokenData: any = tokenData; const xTokenMeta: any = tokenMeta; const locales = { cn: { token: 'Token 名称', description: '描述', type: '类型', value: '默认值', componentToken: '组件 Token', globalToken: '全局 Token', componentComment: '这里是你的组件 token', globalComment: '这里是你的全局 token', help: '如何定制?', customizeTokenLink: '/docs/react/customize-theme-cn#修改主题变量', customizeComponentTokenLink: '/docs/react/customize-theme-cn#修改组件变量', }, en: { token: 'Token Name', description: 'Description', type: 'Type', value: 'Default Value', componentToken: 'Component Token', globalToken: 'Global Token', componentComment: 'here is your component tokens', globalComment: 'here is your global tokens', help: 'How to use?', customizeTokenLink: '/docs/react/customize-theme#customize-design-token', customizeComponentTokenLink: 'docs/react/customize-theme#customize-component-token', }, }; const useStyle = createStyles(({ token }) => ({ tableTitle: css` cursor: pointer; position: relative; display: flex; align-items: center; justify-content: flex-start; line-height: 40px; gap: ${token.marginXS}px; `, arrowIcon: css` font-size: ${token.fontSizeLG}px; & svg { transition: all ${token.motionDurationSlow}; } `, help: css` font-size: ${token.fontSizeSM}px; font-weight: normal; color: #999; a { color: #999; } `, tokenTitle: css` font-size: ${token.fontSizeLG}px; font-weight: bold; `, })); interface SubTokenTableProps { defaultOpen?: boolean; title: string; helpText: React.ReactNode; helpLink: string; tokens: string[]; component?: string; comment?: { componentComment?: string; globalComment?: string; }; } const SubTokenTable: React.FC = (props) => { const { defaultOpen, tokens, title, helpText, helpLink, component, comment } = props; const [, lang] = useLocale(locales); const token = useTheme(); const columns = useColumns(); const [open, setOpen] = useState(defaultOpen ?? process.env.NODE_ENV !== 'production'); const { styles } = useStyle(); if (!tokens.length) { return null; } const data = tokens .sort(component ? undefined : compare) .map((name) => { const meta = component ? xTokenMeta.components[component].find((item: { token: string }) => item.token === name) : xTokenMeta.global?.[name]; if (!meta) { return null as unknown as TokenData; } return { name, desc: lang === 'cn' ? meta.desc : meta.descEn, type: meta.type, value: component ? xTokenData[component].component[name] : defaultToken[name], }; }) .filter(Boolean); const code = component ? ` ... ` : ` ... `; return ( <>
setOpen(!open)}> {title}
                  {code}
                
{helpText} } > {helpText}
{open && ( size="middle" columns={columns} bordered dataSource={data} style={{ marginBottom: token.margin }} pagination={false} rowKey={(record) => record.name} /> )} ); }; export interface ComponentTokenTableProps { component: string; } const ComponentTokenTable: React.FC = ({ component }) => { const [locale] = useLocale(locales); const [mergedGlobalTokens] = useMemo(() => { const globalTokenSet = new Set(); component.split(',').forEach((comp) => { const { global: globalTokens = [] } = xTokenData?.[comp] || {}; globalTokens.forEach((token: string) => { globalTokenSet.add(token); }); }); return [Array.from(globalTokenSet)] as const; }, [component]); return ( <> {xTokenMeta?.components?.[component] && ( item.token)} component={component} comment={{ componentComment: locale.componentComment, globalComment: locale.globalComment, }} /> )} ); }; export default React.memo(ComponentTokenTable); ================================================ FILE: packages/x/.dumi/theme/builtins/Container/index.tsx ================================================ /** * copied: https://github.com/arvinxx/dumi-theme-antd-style/tree/master/src/builtins/Container */ import { Alert } from 'antd'; import * as React from 'react'; import useStyles from './style'; interface ContainerProps { type: 'info' | 'warning' | 'success' | 'error'; title?: string; } const Container: React.FC> = ({ type, title, children, }) => { const { styles, cx } = useStyles(); return (
{children}
} className={styles.alert} />
); }; export default Container; ================================================ FILE: packages/x/.dumi/theme/builtins/Container/style.ts ================================================ import { createStyles } from 'antd-style'; const useStyles = createStyles(({ token, prefixCls, css }) => ({ container: css` margin: ${token.marginXS}px 0; `, alert: css` .${prefixCls}-alert-message { font-weight: bold; } `, /* 使用 `&&` 加一点点权重 */ desc: css` && p { margin: 0; } `, })); export default useStyles; ================================================ FILE: packages/x/.dumi/theme/builtins/DemoWrapper/index.tsx ================================================ import { BugOutlined, CodeOutlined, ExperimentOutlined } from '@ant-design/icons'; import { XProvider } from '@ant-design/x'; import { css, Global } from '@emotion/react'; import { Button, Tooltip } from 'antd'; import { DumiDemo, DumiDemoGrid, FormattedMessage } from 'dumi'; import React, { Suspense } from 'react'; import useLayoutState from '../../../hooks/useLayoutState'; import useLocale from '../../../hooks/useLocale'; import DemoContext from '../../slots/DemoContext'; import DemoFallback from '../Previewer/DemoFallback'; const locales = { cn: { enableCssVar: '启用 CSS 变量', disableCssVar: '禁用 CSS 变量', }, en: { enableCssVar: 'Enable CSS Var', disableCssVar: 'Disable CSS Var', }, }; const DemoWrapper: typeof DumiDemoGrid = ({ items }) => { const { showDebug, setShowDebug } = React.use(DemoContext); const [locale] = useLocale(locales); const [expandAll, setExpandAll] = useLayoutState(false); const [enableCssVar, setEnableCssVar] = useLayoutState(true); const handleVisibleToggle = () => { setShowDebug?.(!showDebug); }; const handleExpandToggle = () => { setExpandAll(!expandAll); }; const handleCssVarToggle = () => { setEnableCssVar((v) => !v); }; const demos = React.useMemo( () => items.reduce((acc, item) => { const { previewerProps } = item; const { debug } = previewerProps; if (debug && !showDebug) { return acc; } return acc.concat({ ...item, previewerProps: { ...previewerProps, expand: expandAll, // always override debug property, because dumi will hide debug demo in production debug: false, /** * antd extra marker for the original debug * @see https://github.com/ant-design/ant-design/pull/40130#issuecomment-1380208762 */ originDebug: debug, }, }); }, []), [expandAll, showDebug], ); return (
} >
); }; export default DemoWrapper; ================================================ FILE: packages/x/.dumi/theme/builtins/IconSearch/Category.tsx ================================================ import { App } from 'antd'; import { createStyles } from 'antd-style'; import { useIntl } from 'dumi'; import * as React from 'react'; import CopyableIcon from './CopyableIcon'; import type { CategoriesKeys } from './fields'; import type { ThemeType } from './IconSearch'; const useStyle = createStyles(({ token, css }) => ({ anticonsList: css` margin: ${token.margin}px 0; overflow: hidden; direction: ltr; list-style: none; display: grid; grid-gap: ${token.margin}px; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); padding: 0; `, copiedCode: css` padding: 0 ${token.paddingXXS}px; font-size: ${token.fontSizeSM}px; background-color: ${token.colorBgLayout}; border-radius: ${token.borderRadiusXS}px; `, })); interface CategoryProps { title: CategoriesKeys; icons: string[]; theme: ThemeType; newIcons: string[]; } const Category: React.FC = (props) => { const { message } = App.useApp(); const { icons, title, newIcons, theme } = props; const { styles } = useStyle(); const intl = useIntl(); const [justCopied, setJustCopied] = React.useState(null); const copyId = React.useRef | null>(null); const onCopied = React.useCallback((type: string, text: string) => { message.success( {text} copied 🎉 , ); setJustCopied(type); copyId.current = setTimeout(() => { setJustCopied(null); }, 2000); }, []); React.useEffect( () => () => { if (copyId.current) { clearTimeout(copyId.current); } }, [], ); return (

{intl.formatMessage({ id: `app.docs.components.icon.category.${title}` })}

    {icons.map((name) => ( ))}
); }; export default Category; ================================================ FILE: packages/x/.dumi/theme/builtins/IconSearch/CopyableIcon.tsx ================================================ import * as AntdIcons from '@ant-design/icons'; import { App, Badge } from 'antd'; import { createStyles } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; import CopyToClipboard from 'react-copy-to-clipboard'; import type { ThemeType } from './IconSearch'; const allIcons: { [key: PropertyKey]: any } = AntdIcons; const useStyle = createStyles(({ token, css }) => { const { antCls, iconCls } = token; return { iconItem: css` display: inline-flex; flex-direction: column; justify-content: center; align-items: center; margin-inline-start: 0 !important; margin-inline-end: 0 !important; padding-inline-start: 0 !important; padding-inline-end: 0 !important; position: relative; width: 200px; height: 100px; overflow: hidden; color: #555; text-align: center; list-style: none; background-color: inherit; border-radius: ${token.borderRadiusSM}px; cursor: pointer; transition: all ${token.motionDurationSlow} ease-in-out; ${token.iconCls} { margin: ${token.marginXS}px 0; font-size: 36px; transition: transform ${token.motionDurationSlow} ease-in-out; will-change: transform; } &:hover { color: ${token.colorWhite}; background-color: ${token.colorPrimary}; ${iconCls} { transform: scale(1.3); } ${antCls}-badge { color: ${token.colorWhite}; } } &.TwoTone:hover { background-color: #8ecafe; } &.copied:hover { color: rgba(255, 255, 255, 0.2); } &::after { content: 'Copied!'; position: absolute; top: 0; inset-inline-start: 0; width: 100%; height: 100%; line-height: 100px; color: ${token.colorTextLightSolid}; text-align: center; background-color: ${token.colorPrimary}; opacity: 0; transition: all ${token.motionDurationSlow} cubic-bezier(0.18, 0.89, 0.32, 1.28); } &.copied::after { opacity: 1; } `, anticonCls: css` display: block; font-family: 'Lucida Console', Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; white-space: nowrap; text-align: center; transform: scale(0.8); ${antCls}-badge { transition: color ${token.motionDurationSlow} ease-in-out; } `, }; }); export interface CopyableIconProps { name: string; isNew: boolean; theme: ThemeType; justCopied: string | null; onCopied: (type: string, text: string) => void; } const CopyableIcon: React.FC = (props) => { const { message } = App.useApp(); const { name, isNew, justCopied, theme, onCopied } = props; const { styles } = useStyle(); const onCopy = (text: string, result: boolean) => { if (result) { onCopied(name, text); } else { message.error('Copy icon name failed, please try again.'); } }; return ( `} onCopy={onCopy}>
  • {React.createElement(allIcons[name])} {name}
  • ); }; export default CopyableIcon; ================================================ FILE: packages/x/.dumi/theme/builtins/IconSearch/IconSearch.tsx ================================================ import Icon, * as AntdIcons from '@ant-design/icons'; import { Affix, Empty, Input, Segmented } from 'antd'; import type { SegmentedOptions } from 'antd/es/segmented'; import { createStyles, useTheme } from 'antd-style'; import { useIntl } from 'dumi'; import debounce from 'lodash/debounce'; import type { CSSProperties } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; import Category from './Category'; import type { CategoriesKeys } from './fields'; import { categories } from './fields'; import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons'; export enum ThemeType { Filled = 'Filled', Outlined = 'Outlined', TwoTone = 'TwoTone', } const allIcons: { [key: string]: any } = AntdIcons; const useStyle = createStyles(({ token, css }) => ({ iconSearchAffix: css` display: flex; transition: all ${token.motionDurationSlow}; justify-content: space-between; `, })); interface IconSearchState { theme: ThemeType; searchKey: string; } const IconSearch: React.FC = () => { const intl = useIntl(); const { styles } = useStyle(); const [displayState, setDisplayState] = useState({ searchKey: '', theme: ThemeType.Outlined, }); const token = useTheme(); const newIconNames: string[] = []; const handleSearchIcon = debounce((e: React.ChangeEvent) => { setDisplayState((prevState) => ({ ...prevState, searchKey: e.target.value })); }, 300); const handleChangeTheme = useCallback((value: ThemeType) => { setDisplayState((prevState) => ({ ...prevState, theme: value as ThemeType })); }, []); const renderCategories = useMemo(() => { const { searchKey = '', theme } = displayState; const categoriesResult = Object.keys(categories) .map((key) => { let iconList = categories[key as CategoriesKeys]; if (searchKey) { const matchKey = searchKey .replace(/^<([a-z]*)\s\/>$/gi, (_, name) => name) .replace(/(Filled|Outlined|TwoTone)$/, '') .toLowerCase(); iconList = iconList.filter((iconName) => iconName.toLowerCase().includes(matchKey)); } const ignore = [ 'CopyrightCircle', // same as Copyright 'DollarCircle', // same as Dollar ]; iconList = iconList.filter((icon) => !ignore.includes(icon)); return { category: key, icons: iconList .map((iconName) => iconName + theme) .filter((iconName) => allIcons[iconName]), }; }) .filter(({ icons }) => !!icons.length) .map(({ category, icons }) => ( )); return categoriesResult.length ? categoriesResult : ; }, [displayState.searchKey, displayState.theme]); const [searchBarAffixed, setSearchBarAffixed] = useState(false); const { borderRadius, colorBgContainer, anchorTop } = token; const affixedStyle: CSSProperties = { boxShadow: 'rgba(50, 50, 93, 0.25) 0 6px 12px -2px, rgba(0, 0, 0, 0.3) 0 3px 7px -3px', padding: 8, margin: -8, borderRadius, backgroundColor: colorBgContainer, }; const memoizedOptions = React.useMemo>( () => [ { value: ThemeType.Outlined, icon: , label: intl.formatMessage({ id: 'app.docs.components.icon.outlined' }), }, { value: ThemeType.Filled, icon: , label: intl.formatMessage({ id: 'app.docs.components.icon.filled' }), }, { value: ThemeType.TwoTone, icon: , label: intl.formatMessage({ id: 'app.docs.components.icon.two-tone' }), }, ], [intl], ); return (
    size="large" value={displayState.theme} options={memoizedOptions} onChange={handleChangeTheme} />
    {renderCategories}
    ); }; export default IconSearch; ================================================ FILE: packages/x/.dumi/theme/builtins/IconSearch/fields.ts ================================================ import * as AntdIcons from '@ant-design/icons/lib/icons'; const all = Object.keys(AntdIcons) .map((n) => n.replace(/(Outlined|Filled|TwoTone)$/, '')) .filter((n, i, arr) => arr.indexOf(n) === i); const direction = [ 'StepBackward', 'StepForward', 'FastBackward', 'FastForward', 'Shrink', 'ArrowsAlt', 'Down', 'Up', 'Left', 'Right', 'CaretUp', 'CaretDown', 'CaretLeft', 'CaretRight', 'UpCircle', 'DownCircle', 'LeftCircle', 'RightCircle', 'DoubleRight', 'DoubleLeft', 'VerticalLeft', 'VerticalRight', 'VerticalAlignTop', 'VerticalAlignMiddle', 'VerticalAlignBottom', 'Forward', 'Backward', 'Rollback', 'Enter', 'Retweet', 'Swap', 'SwapLeft', 'SwapRight', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'PlayCircle', 'UpSquare', 'DownSquare', 'LeftSquare', 'RightSquare', 'Login', 'Logout', 'MenuFold', 'MenuUnfold', 'BorderBottom', 'BorderHorizontal', 'BorderInner', 'BorderOuter', 'BorderLeft', 'BorderRight', 'BorderTop', 'BorderVerticle', 'PicCenter', 'PicLeft', 'PicRight', 'RadiusBottomleft', 'RadiusBottomright', 'RadiusUpleft', 'RadiusUpright', 'Fullscreen', 'FullscreenExit', ]; const suggestion = [ 'Question', 'QuestionCircle', 'Plus', 'PlusCircle', 'Pause', 'PauseCircle', 'Minus', 'MinusCircle', 'PlusSquare', 'MinusSquare', 'Info', 'InfoCircle', 'Exclamation', 'ExclamationCircle', 'Close', 'CloseCircle', 'CloseSquare', 'Check', 'CheckCircle', 'CheckSquare', 'ClockCircle', 'Warning', 'IssuesClose', 'Stop', ]; const editor = [ 'Edit', 'Form', 'Copy', 'Scissor', 'Delete', 'Snippets', 'Diff', 'Highlight', 'AlignCenter', 'AlignLeft', 'AlignRight', 'BgColors', 'Bold', 'Italic', 'Underline', 'Strikethrough', 'Redo', 'Undo', 'ZoomIn', 'ZoomOut', 'FontColors', 'FontSize', 'LineHeight', 'Dash', 'SmallDash', 'SortAscending', 'SortDescending', 'Drag', 'OrderedList', 'UnorderedList', 'RadiusSetting', 'ColumnWidth', 'ColumnHeight', ]; const data = [ 'AreaChart', 'PieChart', 'BarChart', 'DotChart', 'LineChart', 'RadarChart', 'HeatMap', 'Fall', 'Rise', 'Stock', 'BoxPlot', 'Fund', 'Sliders', ]; const logo = [ 'Android', 'Apple', 'Windows', 'Ie', 'Chrome', 'Github', 'Aliwangwang', 'Dingding', 'WeiboSquare', 'WeiboCircle', 'TaobaoCircle', 'Html5', 'Weibo', 'Twitter', 'Wechat', 'WhatsApp', 'Youtube', 'AlipayCircle', 'Taobao', 'Dingtalk', 'Skype', 'Qq', 'MediumWorkmark', 'Gitlab', 'Medium', 'Linkedin', 'GooglePlus', 'Dropbox', 'Facebook', 'Codepen', 'CodeSandbox', 'CodeSandboxCircle', 'Amazon', 'Google', 'CodepenCircle', 'Alipay', 'AntDesign', 'AntCloud', 'Aliyun', 'Zhihu', 'Slack', 'SlackSquare', 'Behance', 'BehanceSquare', 'Dribbble', 'DribbbleSquare', 'Instagram', 'Yuque', 'Alibaba', 'Yahoo', 'Reddit', 'Sketch', 'WechatWork', 'OpenAI', 'Discord', 'X', 'Bilibili', 'Pinterest', 'TikTok', 'Spotify', 'Twitch', 'Linux', 'Java', 'JavaScript', 'Python', 'Ruby', 'DotNet', 'Kubernetes', 'Docker', 'Baidu', 'HarmonyOS', ]; const datum = [...direction, ...suggestion, ...editor, ...data, ...logo]; const other = all.filter((n) => !datum.includes(n)); export const categories = { direction, suggestion, editor, data, logo, other, }; export default categories; export type Categories = typeof categories; export type CategoriesKeys = keyof Categories; ================================================ FILE: packages/x/.dumi/theme/builtins/IconSearch/index.tsx ================================================ import { Skeleton } from 'antd'; import { createStyles } from 'antd-style'; import React, { Suspense } from 'react'; const IconSearch = React.lazy(() => import('./IconSearch')); const useStyle = createStyles(({ token, css }) => ({ searchWrapper: css` display: flex; gap: ${token.padding}px; > *:first-child { flex: 0 0 328px; } > *:last-child { flex: 1; } `, fallbackWrapper: css` display: flex; flex-wrap: wrap; justify-content: space-between; > * { flex: 0 0 15%; margin: ${token.marginXXS}px 0; } `, skeletonWrapper: css` text-align: center; > * { width: 100% !important; } `, })); const IconSearchFallback: React.FC = () => { const { styles } = useStyle(); return ( <>
    {Array.from({ length: 24 }).map((_, index) => (
    ))}
    ); }; export default () => ( }> ); ================================================ FILE: packages/x/.dumi/theme/builtins/IconSearch/themeIcons.tsx ================================================ import type { CustomIconComponentProps } from '@ant-design/icons/es/components/Icon'; import * as React from 'react'; type CustomIconComponent = React.ComponentType< CustomIconComponentProps | React.SVGProps >; export const FilledIcon: CustomIconComponent = (props) => { const path = 'M864 64H160C107 64 64 107 64 160v' + '704c0 53 43 96 96 96h704c53 0 96-43 96-96V16' + '0c0-53-43-96-96-96z'; return ( Filled Icon ); }; export const OutlinedIcon: CustomIconComponent = (props) => { const path = 'M864 64H160C107 64 64 107 64 160v7' + '04c0 53 43 96 96 96h704c53 0 96-43 96-96V160c' + '0-53-43-96-96-96z m-12 800H172c-6.6 0-12-5.4-' + '12-12V172c0-6.6 5.4-12 12-12h680c6.6 0 12 5.4' + ' 12 12v680c0 6.6-5.4 12-12 12z'; return ( Outlined Icon ); }; export const TwoToneIcon: CustomIconComponent = (props) => { const path = 'M16 512c0 273.932 222.066 496 496 49' + '6s496-222.068 496-496S785.932 16 512 16 16 238.' + '066 16 512z m496 368V144c203.41 0 368 164.622 3' + '68 368 0 203.41-164.622 368-368 368z'; return ( TwoTone Icon ); }; ================================================ FILE: packages/x/.dumi/theme/builtins/ImagePreview/index.tsx ================================================ import toArray from '@rc-component/util/lib/Children/toArray'; import { Image } from 'antd'; import { clsx } from 'clsx'; import React from 'react'; interface ImagePreviewProps { className?: string; /** Do not show padding & background */ pure?: boolean; } function isGood(className: string): boolean { return /\bgood\b/i.test(className); } function isBad(className: string): boolean { return /\bbad\b/i.test(className); } function isInline(className: string): boolean { return /\binline\b/i.test(className); } function isGoodBadImg(imgMeta: any): boolean { return imgMeta.isGood || imgMeta.isBad; } function isCompareImg(imgMeta: any): boolean { return isGoodBadImg(imgMeta) || imgMeta.inline; } interface MateType { className: string; alt: string; description: string; src: string; isGood: boolean; isBad: boolean; inline: boolean; } const ImagePreview: React.FC> = (props) => { const { children, className: rootClassName, pure } = props; const imgs = toArray(children).filter((ele) => ele.type === 'img'); const imgsMeta = imgs.map>((img) => { const { alt, description, src, className } = img.props; return { className, alt, description, src, isGood: isGood(className), isBad: isBad(className), inline: isInline(className), }; }); const imagesList = imgsMeta.map((meta, index) => { const metaCopy = { ...meta }; delete metaCopy.description; delete metaCopy.isGood; delete metaCopy.isBad; return (
    {meta.alt}
    ); }); const comparable = (imgs.length === 2 && imgsMeta.every(isCompareImg)) || (imgs.length >= 2 && imgsMeta.every(isGoodBadImg)); const style: React.CSSProperties = comparable ? { width: `${(100 / imgs.length).toFixed(3)}%` } : {}; const hasCarousel = imgs.length > 1 && !comparable; const previewClassName = clsx(rootClassName, 'clearfix', 'preview-image-boxes', { 'preview-image-boxes-compare': comparable, 'preview-image-boxes-with-carousel': hasCarousel, }); // ===================== Render ===================== const imgWrapperCls = 'preview-image-wrapper'; return (
    {!imgs.length && (
    {children}
    )} {imagesList.map((_, index) => { if (!comparable && index !== 0) { return null; } const coverMeta = imgsMeta[index]; const imageWrapperClassName = clsx(imgWrapperCls, { good: coverMeta.isGood, bad: coverMeta.isBad, }); return (
    {coverMeta.alt}
    {coverMeta.alt}
    ); })}
    ); }; export default ImagePreview; ================================================ FILE: packages/x/.dumi/theme/builtins/InlinePopover/index.tsx ================================================ import { PictureOutlined } from '@ant-design/icons'; import { Image, Tooltip, Typography } from 'antd'; import React from 'react'; import useLocale from '../../../hooks/useLocale'; const locales = { cn: { tip: '预览', }, en: { tip: 'Preview', }, }; export interface InlinePopoverProps { previewURL?: string; } // 鼠标悬浮弹出 Popover 组件,用于帮助用户更快看到一些属性对应的预览效果 const InlinePopover: React.FC = (props) => { const { previewURL } = props; const [locale] = useLocale(locales); const [visible, setVisible] = React.useState(false); return ( <> setVisible(true)}> { setVisible(value); }, }} /> ); }; export default InlinePopover; ================================================ FILE: packages/x/.dumi/theme/builtins/InstallDependencies/bun.tsx ================================================ import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; interface IconProps { className?: string; style?: React.CSSProperties; } const useStyle = createStyles(() => ({ iconWrap: css` display: inline-flex; align-items: center; line-height: 0; text-align: center; vertical-align: -0.125em; `, })); const BunIcon: React.FC = (props) => { const { className, style } = props; const { styles } = useStyle(); return ( Bun Logo ); }; export default BunIcon; ================================================ FILE: packages/x/.dumi/theme/builtins/InstallDependencies/index.tsx ================================================ import { XProvider } from '@ant-design/x'; import type { Tab } from '@rc-component/tabs/lib/interface'; import { Tabs } from 'antd'; import SourceCode from 'dumi/theme-default/builtins/SourceCode'; import React from 'react'; import BunLogo from './bun'; import NpmLogo from './npm'; import PnpmLogo from './pnpm'; import UtooLogo from './utoo'; import YarnLogo from './yarn'; interface InstallProps { npm?: string; yarn?: string; pnpm?: string; bun?: string; utoo?: string; } const InstallDependencies: React.FC = (props) => { const { npm, yarn, pnpm, bun, utoo } = props; const items: Tab[] = [ { key: 'npm', label: 'npm', children: npm ? {npm} : null, icon: , }, { key: 'yarn', label: 'yarn', children: yarn ? {yarn} : null, icon: , }, { key: 'pnpm', label: 'pnpm', children: pnpm ? {pnpm} : null, icon: , }, { key: 'bun', label: 'Bun', children: bun ? {bun} : null, icon: , }, { key: 'utoo', label: 'utoo', children: utoo ? {utoo} : null, icon: , }, ].filter((item) => item.children); return ( ); }; export default InstallDependencies; ================================================ FILE: packages/x/.dumi/theme/builtins/InstallDependencies/npm.tsx ================================================ import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; interface IconProps { className?: string; style?: React.CSSProperties; } const useStyle = createStyles(() => ({ iconWrap: css` display: inline-flex; align-items: center; line-height: 0; text-align: center; vertical-align: -0.125em; `, })); const NpmIcon: React.FC = (props) => { const { className, style } = props; const { styles } = useStyle(); return ( npm icon ); }; export default NpmIcon; ================================================ FILE: packages/x/.dumi/theme/builtins/InstallDependencies/pnpm.tsx ================================================ import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; interface IconProps { className?: string; style?: React.CSSProperties; } const useStyle = createStyles(() => ({ iconWrap: css` display: inline-flex; align-items: center; line-height: 0; text-align: center; vertical-align: -0.125em; `, })); const PnpmIcon: React.FC = (props) => { const { className, style } = props; const { styles } = useStyle(); return ( ); }; export default PnpmIcon; ================================================ FILE: packages/x/.dumi/theme/builtins/InstallDependencies/utoo.tsx ================================================ import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; interface IconProps { className?: string; style?: React.CSSProperties; } const useStyle = createStyles(() => ({ iconWrap: css` display: inline-flex; align-items: center; line-height: 0; text-align: center; vertical-align: -0.125em; `, })); const UtooIcon: React.FC = (props) => { const { className, style } = props; const { styles } = useStyle(); return ( Utoo Logo ); }; export default UtooIcon; ================================================ FILE: packages/x/.dumi/theme/builtins/InstallDependencies/yarn.tsx ================================================ import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; import React from 'react'; interface IconProps { className?: string; style?: React.CSSProperties; } const useStyle = createStyles(() => ({ iconWrap: css` display: inline-flex; align-items: center; line-height: 0; text-align: center; vertical-align: -0.125em; `, })); const YarnIcon: React.FC = (props) => { const { className, style } = props; const { styles } = useStyle(); return ( ); }; export default YarnIcon; ================================================ FILE: packages/x/.dumi/theme/builtins/LocaleLink/index.tsx ================================================ import * as React from 'react'; import useLocale from '../../../hooks/useLocale'; import Link from '../../../theme/common/Link'; type LinkProps = Parameters[0]; export interface LocaleLinkProps extends LinkProps { sourceType: 'a' | 'Link'; } const LocaleLink: React.FC> = ({ sourceType, to, ...props }) => { const Component = sourceType === 'a' ? 'a' : Link; const [, localeType] = useLocale(); const localeTo = React.useMemo(() => { if (!to || typeof to !== 'string') { return to; } // Auto locale switch const cells = to.match(/(\/[^#]*)(#.*)?/); if (cells) { let path = cells[1].replace(/\/$/, ''); const hash = cells[2] || ''; if (localeType === 'cn' && !path.endsWith('-cn')) { path = `${path}-cn`; } else if (localeType === 'en' && path.endsWith('-cn')) { path = path.replace(/-cn$/, ''); } return `${path}${hash}`; } return to; }, [to]); const linkProps: LocaleLinkProps = { ...props, } as LocaleLinkProps; if (to) { linkProps.to = localeTo; } return ; }; export default LocaleLink; ================================================ FILE: packages/x/.dumi/theme/builtins/MarkdownPluginsOverView.tsx ================================================ import PluginMeta from '@ant-design/x-markdown/plugins/version/plugin-meta.json'; import { List } from 'antd'; import { createStyles, css } from 'antd-style'; import { Link } from 'dumi'; import React from 'react'; import useLocale from '../../hooks/useLocale'; interface PluginItem { plugin: string; [key: string]: any; } const useStyle = createStyles(({ token }) => ({ container: css` border-radius: ${token.borderRadiusLG}px; border: 1px solid ${token.colorSplit}; `, item: css` a { width: 100%; } cursor: pointer; transition: all ${token.motionDurationMid} ${token.motionEaseInOut}; &:hover { background-color: ${token.colorFillQuaternary}; } `, itemMeta: css` padding-inline: ${token.padding}px}; `, })); const MarkdownPluginsOverView: React.FC = () => { // ======================== locale ========================= const [_, lang] = useLocale(); // ======================== style ========================= const { styles } = useStyle(); // ======================== info ========================= const getInfo = (item: any) => { const description = lang === 'cn' ? item?.desc : item?.descEn; const hrefBase = item?.plugin?.toLowerCase(); const href = lang === 'cn' ? `/x-markdowns/plugin-${hrefBase}-cn` : `/x-markdowns/plugin-${hrefBase}`; return { description, href, }; }; // ======================== Render ======================== return ( { const info = getInfo(item); return ( ); }} /> ); }; export default MarkdownPluginsOverView; ================================================ FILE: packages/x/.dumi/theme/builtins/Palette/index.ts ================================================ import Palette from '../../common/Color/Palette'; export default Palette; ================================================ FILE: packages/x/.dumi/theme/builtins/Previewer/CodeBlockButton.tsx ================================================ import { Tooltip } from 'antd'; import { FormattedMessage } from 'dumi'; import React, { Suspense } from 'react'; // import { ping } from '../../utils'; // let pingDeferrer: PromiseLike; // const codeBlockJs = // 'https://renderoffice.a' + // 'lipay' + // 'objects.com/p' + // '/yuyan/180020010001206410/parseFileData-v1.0.1.js'; // function useShowCodeBlockButton() { // const [showCodeBlockButton, setShowCodeBlockButton] = useState(false); // useEffect(() => { // pingDeferrer ??= new Promise((resolve) => { // ping((status) => { // if (status !== 'timeout' && status !== 'error') { // // Async insert `codeBlockJs` into body end // const script = document.createElement('script'); // script.src = codeBlockJs; // script.async = true; // document.body.appendChild(script); // return resolve(true); // } // return resolve(false); // }); // }); // pingDeferrer.then(setShowCodeBlockButton); // }, []); // return showCodeBlockButton; // } interface CodeBlockButtonProps { title?: string; dependencies: Record; jsx: string; } const CodeBlockButton: React.FC = ({ title, dependencies = {}, jsx }) => { const showCodeBlockButton = false; //useShowCodeBlockButton(); const codeBlockPrefillConfig = { title: `${title} - antd@${dependencies.antd}`, js: `${ /import React(\D*)from 'react';/.test(jsx) ? '' : `import React from 'react';\n` }import { createRoot } from 'react-dom/client';\n${jsx.replace( /export default/, 'const ComponentDemo =', )}\n\ncreateRoot(mountNode).render();\n`, css: '', json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2), }; return showCodeBlockButton ? ( }>
    codeblock { (window as any).openHituCodeBlock?.(JSON.stringify(codeBlockPrefillConfig)); }} />
    ) : null; }; export default (props: CodeBlockButtonProps) => ( ); ================================================ FILE: packages/x/.dumi/theme/builtins/Previewer/CodePreviewer.tsx ================================================ import { LinkOutlined, ThunderboltOutlined, UpOutlined } from '@ant-design/icons'; import type { Project } from '@stackblitz/sdk'; import stackblitzSdk from '@stackblitz/sdk'; import { Alert, Badge, Flex, Tooltip } from 'antd'; import { createStyles, css } from 'antd-style'; import { clsx } from 'clsx'; import { FormattedMessage, useLiveDemo, useSiteData } from 'dumi'; import { pickBy } from 'lodash'; import LZString from 'lz-string'; /* eslint-disable react-hooks-extra/no-direct-set-state-in-use-effect */ import React, { useEffect, useRef, useState } from 'react'; import useLocation from '../../../hooks/useLocation'; import BrowserFrame from '../../common/BrowserFrame'; import ClientOnly from '../../common/ClientOnly'; import CodePreview from '../../common/CodePreview'; import EditButton from '../../common/EditButton'; import CodePenIcon from '../../icons/CodePenIcon'; import CodeSandboxIcon from '../../icons/CodeSandboxIcon'; import ExternalLinkIcon from '../../icons/ExternalLinkIcon'; import DemoContext from '../../slots/DemoContext'; import LiveError from '../../slots/LiveError'; import SiteContext from '../../slots/SiteContext'; import CodeBlockButton from './CodeBlockButton'; import type { AntdPreviewerProps } from './Previewer'; const { ErrorBoundary } = Alert; function compress(string: string): string { return LZString.compressToBase64(string) .replace(/\+/g, '-') // Convert '+' to '-' .replace(/\//g, '_') // Convert '/' to '_' .replace(/=+$/, ''); // Remove ending '=' } const track = ({ type, demo }: { type: string; demo: string }) => { if (!window.gtag) { return; } window.gtag('event', 'demo', { event_category: type, event_label: demo }); }; const useStyle = createStyles(({ token }) => { const { borderRadius } = token; return { stickyBox: css` position: sticky; bottom: 0; z-index: 1; `, codeHideBtn: css` width: 100%; height: 40px; display: flex; justify-content: center; align-items: center; border-radius: 0 0 ${borderRadius}px ${borderRadius}px; border-top: 1px solid ${token.colorSplit}; color: ${token.colorTextSecondary}; transition: all ${token.motionDurationMid} ease-in-out; background-color: ${token.colorBgElevated}; cursor: pointer; &:hover { color: ${token.colorPrimary}; } span { margin-inline-end: ${token.marginXXS}px; } `, }; }); const CodePreviewer: React.FC = (props) => { const { asset, expand, iframe, demoUrl, children, title, description, originDebug, jsx = '', style, compact, background, filename, version, simplify, clientOnly, pkgDependencyList, pkgPeerDependencies, } = props; const { codeType } = React.use(DemoContext); const { pkg } = useSiteData(); const location = useLocation(); const { styles } = useStyle(); const entryName = 'index.tsx'; const entryCode = asset.dependencies[entryName].value; const otherCodeObject = pickBy(asset.dependencies, (_, key) => key.startsWith('.')); const previewDemo = useRef(null); const demoContainer = useRef(null); const { node: liveDemoNode, error: liveDemoError, setSource: setLiveDemoSource, } = useLiveDemo(asset.id, { iframe: Boolean(iframe), containerRef: demoContainer as React.RefObject, }); const anchorRef = useRef(null); const codeSandboxIconRef = useRef(null); const codepenIconRef = useRef(null); const [codeExpand, setCodeExpand] = useState(false); const { theme } = React.use(SiteContext); const { hash, pathname, search } = location; const docsOnlineUrl = `https://ant-design-x.antgroup.com${pathname}${search}#${asset.id}`; const [showOnlineUrl, setShowOnlineUrl] = useState(false); useEffect(() => { const regexp = /preview-(\d+)-ant-design/; // matching PR preview addresses setShowOnlineUrl( process.env.NODE_ENV === 'development' || regexp.test(window.location.hostname), ); }, []); const handleCodeExpand = (demo: string) => { setCodeExpand((prev) => !prev); track({ type: 'expand', demo }); }; useEffect(() => { if (asset.id === hash.slice(1)) { anchorRef.current?.click(); } }, []); useEffect(() => { setCodeExpand(expand); }, [expand]); const mergedChildren = !iframe && clientOnly ? {children} : children; const demoUrlWithTheme = `${demoUrl}${theme.includes('dark') ? '?theme=dark' : ''}`; if (!previewDemo.current) { previewDemo.current = iframe ? ( #### 4. Attribute-based XSS #### 5. Script Tag Injection #### 6. Event Handler XSS Test Image #### 7. JavaScript Protocol XSS Click Here #### 8. SVG Vector XSS #### 9. Form Input XSS
    #### 10. CSS Injection XSS
    Test Content
    #### 11. Data URI XSS #### 12. HTML Entity Encoding Bypass #### 13. Filter Evasion XSS ipt>alert('Filter evasion XSS - nested script tags')ipt> #### 14. Mouse Event XSS
    Hover over this text
    #### 15. Focus Event XSS #### 16. Frame Injection XSS #### 17. Object Tag XSS #### 18. Embed Tag XSS #### 19. URL Parameter XSS Malicious Search Link #### 20. MathML XSS Vector X #### 21. Stylesheet XSS #### 22. Meta Refresh XSS #### 23. Base Tag XSS #### 24. Image Map XSS #### 25. Media Tag XSS #### 26. Details Tag XSS
    Click to expand details
    #### 27. Progress Bar XSS 50% #### 28. Select List XSS #### 29. Text Area XSS #### 30. Button Tag XSS #### 31. Marquee Tag XSS (Deprecated but still functional) Scrolling text #### 32. Keygen Tag XSS (Deprecated) #### 33. Table Background XSS
    Table cell
    #### 34. Input Type XSS #### 35. Body Tag XSS Page content #### 36. Div Background XSS
    Content
    #### 37. Table Cell XSS Cell content #### 38. XML Namespace XSS XML namespace XSS #### 39. VBScript XSS (IE specific) #### 40. Expression XSS (IE specific)
    IE specific XSS
    `; const App = () => { const { theme: antdTheme } = theme.useToken(); const className = antdTheme.id === 0 ? 'x-markdown-light' : 'x-markdown-dark'; return ; }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/codeHighlighter.tsx ================================================ import { Bubble, CodeHighlighter } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import { Button, Flex } from 'antd'; import React from 'react'; const text = ` Here's a Python code block example that demonstrates how to calculate Fibonacci numbers: \`\`\` python def fibonacci(n): """ Calculate the nth Fibonacci number :param n: The position in the Fibonacci sequence (must be a positive integer) :return: The value at position n """ if n <= 0: return 0 elif n == 1: return 1 else: a, b = 0, 1 for _ in range(2, n+1): a, b = b, a + b return b # Example usage if __name__ == "__main__": num = 10 print(f"The {num}th Fibonacci number is: {fibonacci(num)}") # Print the first 15 Fibonacci numbers print("First 15 Fibonacci numbers:") for i in range(1, 16): print(fibonacci(i), end=" ") \`\`\` This code includes: 1. A function to compute Fibonacci numbers 2. Docstring documentation 3. Example usage in the main block 4. A loop to print the first 15 numbers You can modify the parameters or output format as needed. The Fibonacci sequence here starts with fib(1) = 1, fib(2) = 1. `; const Code: React.FC = (props) => { const { className, children } = props; const lang = className?.match(/language-(\w+)/)?.[1] || ''; if (typeof children !== 'string') return null; return {children}; }; const App = () => { const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/custom.tsx ================================================ import { Bubble, Think } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import React, { useCallback, useEffect, useState } from 'react'; import '@ant-design/x-markdown/themes/light.css'; import { DeleteOutlined, DollarOutlined, EyeOutlined, PlusOutlined, ShoppingCartOutlined, UserOutlined, } from '@ant-design/icons'; import { Button, Card, Flex, Form, Input, Modal, message, Select, Space, Statistic, Table, Tag, } from 'antd'; const { Option } = Select; // 模拟业务数据 interface OrderData { id: string; customer: string; product: string; amount: number; status: 'pending' | 'processing' | 'completed' | 'cancelled'; date: string; region: string; } interface SalesData { name: string; value: number; color: string; } // 自定义业务组件 - 从模型数据获取的销售仪表板 const Salesdashboard = React.memo(({ children, streamStatus }: ComponentProps) => { const [salesData, setSalesData] = useState([]); const [totalSales, setTotalSales] = useState(0); const [totalOrders, setTotalOrders] = useState(0); const [newCustomers, setNewCustomers] = useState(0); useEffect(() => { if (children) { // 从模型返回的数据中解析销售信息 try { const parsedData = typeof children === 'string' ? JSON.parse(children) : children; if (parsedData.sales) { setSalesData(parsedData.sales); } if (parsedData.totalSales) { setTotalSales(parsedData.totalSales); } if (parsedData.totalOrders) { setTotalOrders(parsedData.totalOrders); } if (parsedData.newCustomers) { setNewCustomers(parsedData.newCustomers); } } catch (_error) { // 如果解析失败,使用默认数据 const defaultData = [ { name: '电子产品', value: 45000, color: '#3b82f6' }, { name: '服装', value: 32000, color: '#8b5cf6' }, { name: '家居用品', value: 28000, color: '#10b981' }, ]; setSalesData(defaultData); setTotalSales(115000); setTotalOrders(342); setNewCustomers(67); } } else { // 默认数据 const defaultData = [ { name: '电子产品', value: 45000, color: '#3b82f6' }, { name: '服装', value: 32000, color: '#8b5cf6' }, { name: '家居用品', value: 28000, color: '#10b981' }, ]; setSalesData(defaultData); setTotalSales(115000); setTotalOrders(342); setNewCustomers(67); } }, [children]); if (streamStatus === 'loading') return; return (
    销售仪表板 (从模型数据获取) 实时数据 } precision={2} valueStyle={{ color: '#3f8600' }} /> } valueStyle={{ color: '#1890ff' }} /> } valueStyle={{ color: '#722ed1' }} />
    {salesData.map((item, index) => (
    {item.name} ¥{item.value.toLocaleString()}
    ))}

    🤖 以上数据由AI模型实时生成

    📊 数据格式: JSON格式,包含sales、totalSales、totalOrders、newCustomers字段

    💡 示例格式: sales数组包含name和value字段

    ); }); // 自定义业务组件 - 订单管理表格 const OrderManager = React.memo(() => { const [orders, setOrders] = useState([]); const [loading, setLoading] = useState(false); const [modalVisible, setModalVisible] = useState(false); const [editingOrder, setEditingOrder] = useState(null); const [form] = Form.useForm(); const fetchOrders = useCallback(async () => { setLoading(true); try { await new Promise((resolve) => setTimeout(resolve, 1000)); const mockOrders: OrderData[] = [ { id: 'ORD001', customer: '张三', product: 'iPhone 15', amount: 8999, status: 'completed', date: '2024-01-15', region: '北京', }, { id: 'ORD002', customer: '李四', product: 'MacBook Pro', amount: 15999, status: 'processing', date: '2024-01-16', region: '上海', }, { id: 'ORD003', customer: '王五', product: 'AirPods Pro', amount: 1999, status: 'pending', date: '2024-01-17', region: '广州', }, { id: 'ORD004', customer: '赵六', product: 'iPad Air', amount: 4799, status: 'completed', date: '2024-01-18', region: '深圳', }, ]; setOrders(mockOrders); } catch (_error) { message.error('获取订单失败'); } finally { setLoading(false); } }, []); useEffect(() => { fetchOrders(); }, [fetchOrders]); const handleDelete = async (id: string) => { try { await new Promise((resolve) => setTimeout(resolve, 500)); setOrders((prev) => prev.filter((order) => order.id !== id)); message.success('订单已删除'); } catch (_error) { message.error('删除失败'); } }; const handleEdit = (order: OrderData) => { setEditingOrder(order); form.setFieldsValue(order); setModalVisible(true); }; const handleSubmit = async (values: Partial) => { try { await new Promise((resolve) => setTimeout(resolve, 800)); if (editingOrder) { setOrders((prev) => prev.map((order) => (order.id === editingOrder.id ? { ...order, ...values } : order)), ); message.success('订单已更新'); } else { const newOrder: OrderData = { id: `ORD${String(Date.now()).slice(-3)}`, customer: values.customer || '', product: values.product || '', amount: values.amount || 0, status: values.status || 'pending', date: new Date().toISOString().split('T')[0], region: values.region || '', }; setOrders((prev) => [...prev, newOrder]); message.success('订单已创建'); } setModalVisible(false); form.resetFields(); setEditingOrder(null); } catch (_error) { message.error('操作失败'); } }; const columns = [ { title: '订单号', dataIndex: 'id', key: 'id' }, { title: '客户', dataIndex: 'customer', key: 'customer' }, { title: '产品', dataIndex: 'product', key: 'product' }, { title: '金额', dataIndex: 'amount', key: 'amount', render: (amount: number) => `¥${amount}` }, { title: '状态', dataIndex: 'status', key: 'status', render: (status: string) => { const colors = { pending: 'orange', processing: 'blue', completed: 'green', cancelled: 'red', }; const labels = { pending: '待处理', processing: '处理中', completed: '已完成', cancelled: '已取消', }; return ( {labels[status as keyof typeof labels]} ); }, }, { title: '日期', dataIndex: 'date', key: 'date' }, { title: '地区', dataIndex: 'region', key: 'region' }, { title: '操作', key: 'action', render: (_: any, record: OrderData) => ( { setModalVisible(false); form.resetFields(); setEditingOrder(null); }} onOk={() => form.submit()} >
    ); }); // 思考组件 const ThinkComponent = React.memo((props: ComponentProps) => { const [title, setTitle] = React.useState('正在分析业务数据...'); const [loading, setLoading] = React.useState(true); const [expand, setExpand] = React.useState(true); React.useEffect(() => { if (props.streamStatus === 'done') { setTitle('业务分析完成'); setLoading(false); setExpand(false); } }, [props.streamStatus]); if (typeof props.children !== 'string') { return null; } return (
    setExpand(!expand)}> {props?.children?.trim()}
    ); }); const text = ` 基于用户提供的业务需求,我们需要创建一个完整的销售管理系统示例,该系统需要展示如何从AI模型返回的数据中动态获取和展示信息。这个示例将展示XMarkdown如何: 1. 从模型返回的JSON数据中解析业务信息 2. 使用小写组件标签(如salesdashboard) 3. 处理动态数据渲染 4. 实现复杂的业务场景和交互需求 通过这种方式,用户可以清楚地看到XMarkdown不仅支持简单的文本渲染,还能处理动态数据驱动的复杂业务场景。 ### 📊 动态销售仪表板 {"sales":[{"name":"电子产品","value":52000,"color":"#3b82f6"},{"name":"服装","value":38000,"color":"#8b5cf6"}],"totalSales":141000,"totalOrders":487,"newCustomers":94} ### 📋 订单管理系统 `; const App = () => { const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/dataChart.tsx ================================================ import { Bubble } from '@ant-design/x'; import XMarkdown from '@ant-design/x-markdown'; import { Line } from '@antv/gpt-vis'; import { Button, Flex, Skeleton } from 'antd'; /* eslint-disable react/no-danger */ import React, { useEffect } from 'react'; const text = ` **GPT-Vis**, Components for GPTs, generative AI, and LLM projects. Not only UI Components. [more...](https://github.com/antvis/GPT-Vis) \n\n Here’s a visualization of Haidilao's food delivery revenue from 2013 to 2022. You can see a steady increase over the years, with notable *growth* particularly in recent years. [{"time":2013,"value":59.3},{"time":2014,"value":64.4},{"time":2015,"value":68.9},{"time":2016,"value":74.4},{"time":2017,"value":82.7},{"time":2018,"value":91.9},{"time":2019,"value":99.1},{"time":2020,"value":101.6},{"time":2021,"value":114.4},{"time":2022,"value":121}] `; const LineCompt = (props: Record) => { const { children, streamstatus } = props; const resolvedAxisXTitle = props['data-axis-x-title'] || ''; const resolvedAxisYTitle = props['data-axis-y-title'] || ''; const resolvedStreamStatus = streamstatus || 'done'; // Extract JSON from children - children can be array or string let jsonData: any = []; if (Array.isArray(children) && children.length > 0) { jsonData = children[0]; } else if (typeof children === 'string') { jsonData = children; } if (resolvedStreamStatus === 'loading') { return ; } try { const parsedData = typeof jsonData === 'string' ? JSON.parse(jsonData) : jsonData; return ( ); } catch (error) { console.error('Failed to parse Line data:', jsonData, error); return
    Error rendering chart
    ; } }; const App = () => { const [index, setIndex] = React.useState(0); const [hasNextChunk, setHasNextChunk] = React.useState(true); const timer = React.useRef(null); const contentRef = React.useRef(null); useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); useEffect(() => { if (index >= text.length) { setHasNextChunk(false); } else if (!hasNextChunk) { setHasNextChunk(true); } }, [index, hasNextChunk]); useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/infographic.tsx ================================================ import { Bubble } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import { Button, Flex, Spin } from 'antd'; import React from 'react'; const text = ` **[Infographic](https://github.com/antvis/Infographic)**, An Infographic Generation and Rendering Framework, bring words to life with AI! The advantages of an enterprise are generally analyzed from dimensions such as brand influence, technological R&D capabilities, rapid market growth, service satisfaction, comprehensive data assets, and strong innovation capabilities, which are reflected in the final performance. \`\`\` infographic infographic sequence-pyramid-simple data title 企业数字化转型层级 desc 从基础设施到战略创新的五层进阶路径 items - label 战略创新 desc 数据驱动决策,引领行业变革 icon ref:search:lightbulb-on - label 智能运营 desc AI赋能业务,实现自动化管理 icon ref:search:robot - label 数据整合 desc 打通数据孤岛,建立统一平台 icon ref:search:database-sync - label 流程优化 desc 数字化核心业务流程和协作 icon ref:search:workflow - label 基础设施 desc 构建云计算和网络基础架构 icon ref:search:server-network themeConfig palette antv \`\`\` `; type ReactInfographicProps = { children: React.ReactNode; }; /** * React wrapper for @antv/infographic * Dynamically imports the library to avoid SSR issues */ function ReactInfographic(props: ReactInfographicProps) { const { children } = props; const [isClient, setIsClient] = React.useState(false); const [isLoading, setIsLoading] = React.useState(true); const containerRef = React.useRef(null); const infographicInstance = React.useRef<{ render: (spec: string) => void; destroy: () => void; } | null>(null); React.useEffect(() => { setIsClient(true); }, []); React.useEffect(() => { if (!isClient || !containerRef.current) return; let isMounted = true; import('@antv/infographic') .then(({ Infographic }) => { if (!isMounted || !containerRef.current) return; infographicInstance.current = new Infographic({ container: containerRef.current, }); infographicInstance.current.render(children as string); setIsLoading(false); }) .catch((error) => { console.error('Failed to load infographic:', error); setIsLoading(false); }); return () => { isMounted = false; infographicInstance.current?.destroy(); infographicInstance.current = null; }; }, [isClient, children]); if (!isClient) { return (
    ); } return (
    {isLoading && (
    )}
    ); } /** * Custom code renderer for XMarkdown * Handles 'infographic' language code blocks */ const Code: React.FC = (props) => { const { className, children } = props; const lang = className?.match(/language-(\w+)/)?.[1] || ''; if (typeof children !== 'string') return null; if (lang === 'infographic') { return {children}; } return {children}; }; /** * Main application component * Demonstrates streaming markdown rendering with infographic support */ const App = () => { const [index, setIndex] = React.useState(0); const timerRef = React.useRef(null); const contentRef = React.useRef(null); // Streaming text animation React.useEffect(() => { if (index >= text.length) return; timerRef.current = setTimeout(() => { setIndex((prev) => Math.min(prev + 5, text.length)); }, 20); return () => { if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null; } }; }, [index]); // Auto-scroll to bottom during streaming React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); const handleRerender = () => { setIndex(0); }; return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/mermaid.tsx ================================================ import { Bubble, Mermaid } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import { Button, Flex } from 'antd'; import React from 'react'; const text = ` Here are several Mermaid diagram examples #### 1. Flowchart (Vertical) \`\`\` mermaid graph TD A[Start] --> B{Data Valid?} B -->|Yes| C[Process Data] B -->|No| D[Error Handling] C --> E[Generate Report] D --> E E --> F[End] style A fill:#2ecc71,stroke:#27ae60 style F fill:#e74c3c,stroke:#c0392b \`\`\` #### 2. Sequence Diagram \`\`\` mermaid sequenceDiagram participant Client participant Server participant Database Client->>Server: POST /api/data Server->>Database: INSERT record Database-->>Server: Success Server-->>Client: 201 Created \`\`\` #### 3. Quadrant Chart \`\`\`mermaid quadrantChart title Reach and engagement of campaigns x-axis Low Reach --> High Reach y-axis Low Engagement --> High Engagement quadrant-1 We should expand quadrant-2 Need to promote quadrant-3 Re-evaluate quadrant-4 May be improved Campaign A: [0.3, 0.6] Campaign B: [0.45, 0.23] Campaign C: [0.57, 0.69] Campaign D: [0.78, 0.34] Campaign E: [0.40, 0.34] Campaign F: [0.35, 0.78] \`\`\` `; const Code: React.FC = (props) => { const { className, children } = props; const lang = className?.match(/language-(\w+)/)?.[1] || ''; if (typeof children !== 'string') return null; if (lang === 'mermaid') { return {children}; } return {children}; }; const App = () => { const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/sources.tsx ================================================ import { Bubble, Sources } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import { Button, Flex } from 'antd'; import React from 'react'; const text = `Ant Financial has a large number of enterprise-level products.1 With complex scenarios, designers and developers often need to respond fast due to frequent changes in product demands and concurrent R & D workflow.2 Many similar contents exist in the process. Through abstraction, we could obtain some stable and highly reusable components and pages.3`; const SupComponent = React.memo((props: ComponentProps) => { const items = [ { title: '1. Data source', key: 1, url: 'https://x.ant.design/components/overview', description: 'Artificial Intelligence, often abbreviated as AI, is a broad branch of computer science concerned with building smart machines capable of performing tasks that typically require human intelligence.', }, { title: '2. Data source', key: 2, url: 'https://x.ant.design/components/overview', }, { title: '3. Data source', key: 3, url: 'https://x.ant.design/components/overview', }, ]; return ( ); }); const App = () => { const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/components/think.tsx ================================================ import { Bubble, Think } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import { Button, Flex } from 'antd'; import React from 'react'; const text = ` Deep thinking is a systematic and structured cognitive approach that requires individuals to move beyond intuition and superficial information, delving into the essence of a problem and its underlying principles through logical analysis, multi-perspective examination, and persistent inquiry. Unlike quick reactions or heuristic judgments, deep thinking emphasizes ​slow thinking, actively engaging knowledge reserves, critical thinking, and creativity to uncover deeper connections and meanings. Key characteristics of deep thinking include: ​Probing the Essence: Not settling for "what it is," but continuously asking "why" and "how it works" until reaching the fundamental logic. ​Multidimensional Connections: Placing the issue in a broader context and analyzing it through interdisciplinary knowledge or diverse perspectives. ​Skepticism & Reflection: Challenging existing conclusions, authoritative opinions, and even personal biases, validating them through logic or evidence. ​Long-term Value Focus: Prioritizing systemic consequences and sustainable impact over short-term or localized benefits. This mode of thinking helps individuals avoid cognitive biases in complex scenarios, improve decision-making, and generate groundbreaking insights in fields such as academic research, business innovation, and social problem-solving. # Hello Deep Thinking\n Deep thinking is over.\n\n You can use the think tag to package your thoughts. `; const ThinkComponent = React.memo((props: ComponentProps) => { const [title, setTitle] = React.useState('Deep thinking...'); const [loading, setLoading] = React.useState(true); const [expand, setExpand] = React.useState(true); React.useEffect(() => { if (props.streamStatus === 'done') { setTitle('Complete thinking'); setLoading(false); setExpand(false); } }, [props.streamStatus]); return ( setExpand(!expand)}> {props.children} ); }); const App = () => { const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/streaming/animation.tsx ================================================ import { SettingOutlined } from '@ant-design/icons'; import { Bubble } from '@ant-design/x'; import XMarkdown from '@ant-design/x-markdown'; import { Button, Flex, Input, Popover, Space, Switch, Typography, theme } from 'antd'; import React from 'react'; import '@ant-design/x-markdown/themes/light.css'; import '@ant-design/x-markdown/themes/dark.css'; const text = ` # Ant Design X: AI Conversation UI Framework > "Easily build AI-driven interfaces" > > — Ant Design X Team ## Features - Best practices from enterprise-level AI products - Flexible atomic components covering most AI scenarios - Stream-friendly, extensible, and high-performance Markdown renderer - Out-of-the-box model/agent integration - Efficient management of large model data streams - Rich template support - Full TypeScript coverage - Deep theme customization ## Atomic Components Based on the RICH interaction paradigm: ### Core Components - **Bubble**: Message bubble for displaying chat messages - **Bubble.List**: Virtualized message list - **Sender**: Input box for sending messages - **Conversations**: Conversation history management - **Welcome**: Welcome screen component > Ant Design X is more than just a component library—it's a complete solution for building AI-powered applications. `; const { Text } = Typography; interface ToggleItemProps { label: string; checked: boolean; onChange: (checked: boolean) => void; } const ToggleItem: React.FC = ({ label, checked, onChange }) => ( {label} ); interface InputItemProps { label: string; value: string; onChange: (value: string) => void; disabled?: boolean; } const InputItem: React.FC = ({ label, value, onChange, disabled }) => ( {label} onChange(e.target.value)} disabled={disabled} /> ); const App = () => { const [enableAnimation, setEnableAnimation] = React.useState(true); const [enableTail, setEnableTail] = React.useState(false); const [tailContent, setTailContent] = React.useState('▋'); const [enableDebug, setEnableDebug] = React.useState(false); const [hasNextChunk, setHasNextChunk] = React.useState(true); const { theme: antdTheme } = theme.useToken(); const className = antdTheme.id === 0 ? 'x-markdown-light' : 'x-markdown-dark'; const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) { setHasNextChunk(false); return; } timer.current = setTimeout(() => { setIndex(Math.min(index + 2, text.length)); }, 40); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); const configContent = ( ); return (
    {configContent}
    } > ( {content} )} />
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/streaming/combined.tsx ================================================ import { SettingOutlined } from '@ant-design/icons'; import { Bubble } from '@ant-design/x'; import XMarkdown from '@ant-design/x-markdown'; import { Button, Flex, Input, Popover, Skeleton, Switch, Typography, theme } from 'antd'; import React, { useState } from 'react'; import '@ant-design/x-markdown/themes/light.css'; import '@ant-design/x-markdown/themes/dark.css'; const { Text } = Typography; interface ToggleItemProps { label: string; checked: boolean; onChange: (checked: boolean) => void; } const ToggleItem: React.FC = ({ label, checked, onChange }) => ( {label} ); interface InputItemProps { label: string; value: string; onChange: (value: string) => void; disabled?: boolean; } const InputItem: React.FC = ({ label, value, onChange, disabled }) => ( {label} onChange(e.target.value)} disabled={disabled} /> ); // 简化的示例文本 const text = `# Ant Design X Ant Design X 是一款 AI 应用复合工具集,融合了 UI 组件库、流式 Markdown 渲染引擎和 AI SDK,为开发者提供构建下一代 AI 驱动应用的完整工具链。 ![Ant Design X](https://mdn.alipayobjects.com/huamei_yz9z7c/afts/img/0lMhRYbo0-8AAAAAQDAAAAgADlJoAQFr/original) 基于 Ant Design 设计体系的 React UI 库、专为 AI 驱动界面设计,开箱即用的智能对话组件、无缝集成 API 服务,快速搭建智能应用界面,查看详情请点击 [Ant Design X](https://github.com/ant-design/x)。 `; // 自定义加载组件 const LoadingComponents = { 'loading-link': () => ( ), 'loading-image': () => , }; const App: React.FC = () => { const [enableAnimation, setEnableAnimation] = useState(true); const [enableCache, setEnableCache] = useState(true); const [tailEnabled, setTailEnabled] = useState(false); const [tailContent, setTailContent] = useState('▋'); const [isStreaming, setIsStreaming] = useState(false); const [index, setIndex] = useState(0); const { theme: antdTheme } = theme.useToken(); const className = antdTheme.id === 0 ? 'x-markdown-light' : 'x-markdown-dark'; const timer = React.useRef(-1); React.useEffect(() => { clearTimeout(timer.current); if (index >= text.length) { setIsStreaming(false); return; } setIsStreaming(true); timer.current = setTimeout(() => { setIndex((prev) => Math.min(prev + 1, text.length)); }, 50); return () => { clearTimeout(timer.current); }; }, [index]); return (
    } > ( )} />
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/streaming/debug.tsx ================================================ import { Bubble } from '@ant-design/x'; import XMarkdown from '@ant-design/x-markdown'; import { Button, Flex, Space, theme } from 'antd'; import React from 'react'; import '@ant-design/x-markdown/themes/light.css'; import '@ant-design/x-markdown/themes/dark.css'; const text = ` # Ant Design X: The Ultimate AI Conversation UI Framework > "Easily build AI-driven interfaces" > > — Ant Design X Team ## ✨ Features - 🌈 Best practices from enterprise-level AI products: Based on RICH interaction paradigms, providing excellent AI interaction experience - 🧩 Flexible atomic components: Covering most AI scenarios, helping you quickly build personalized AI interaction pages - ✨ Stream-friendly, extensible, and high-performance Markdown renderer: Supports streaming formulas, code highlighting, mermaid diagrams, etc. - 🚀 Out-of-the-box model/agent integration: Easily connect to OpenAI-compatible model/agent services - ⚡️ Efficient management of large model data streams: Provides handy data stream management features for more efficient development - 📦 Rich template support: Multiple templates for quick LUI app development - 🛡 Full TypeScript coverage: Developed with TypeScript, providing complete type support for better experience and reliability - 🎨 Deep theme customization: Fine-grained style adjustments for personalized needs in various scenarios ## 🧩 Atomic Components Based on the RICH interaction paradigm, we provide many atomic components for different interaction stages to help you flexibly build your AI application: ### Core Components - **Bubble**: Message bubble for displaying chat messages - **Bubble.List**: Virtualized message list for handling large datasets - **Sender**: Input box for sending messages - **Conversations**: Conversation history management - **Welcome**: Welcome screen component ### Input Components - **Prompts**: Quick suggestion prompts - **Attachments**: File upload and preview ### Display Components - **ThoughtChain**: AI reasoning process display - **Sources**: Reference and citation display - **FileCard**: File preview cards ## 🔗 Ecosystem ### Related Packages - **@ant-design/x-markdown**: Advanced markdown rendering with streaming support - **@ant-design/x-sdk**: AI model integration and data stream management ### Framework Integrations - **Next.js**: Server-side rendering support - **Vite**: Fast development experience - **Create React App**: Zero configuration setup - **Umi**: Enterprise-grade framework > Ant Design X is more than just a component library—it's a complete solution for building the next generation of AI-powered applications. Start building today and create experiences that delight your users. `; const App = () => { const { theme: antdTheme } = theme.useToken(); const className = antdTheme.id === 0 ? 'x-markdown-light' : 'x-markdown-dark'; const [index, setIndex] = React.useState(0); const [hasNextChunk, setHasNextChunk] = React.useState(false); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) { setHasNextChunk(false); return; } timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); const handleReRender = () => { setIndex(0); setHasNextChunk(true); }; return (
    ( {content} )} />
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/streaming/format.tsx ================================================ import { Welcome } from '@ant-design/x'; import XMarkdown, { type ComponentProps } from '@ant-design/x-markdown'; import { Button, Card, Segmented, Skeleton, theme } from 'antd'; import React, { useState } from 'react'; const demos = [ { title: 'Mixed Syntax', content: `## Ant Design X ![Logo](https://mdn.alipayobjects.com/huamei_yz9z7c/afts/img/0lMhRYbo0-8AAAAAQDAAAAgADlJoAQFr/original) UI components, streaming Markdown, and AI SDK in one toolkit. - \`@ant-design/x\` — components - \`@ant-design/x-markdown\` — rendering - \`@ant-design/x-sdk\` — tools & chat ### Get started \`npm install @ant-design/x\`. See [components](/components/introduce/) and [Markdown](/x-markdowns/introduce) docs. | Package | Description | | --- | --- | | @ant-design/x | AI-oriented UI library | | @ant-design/x-markdown | Streaming Markdown | | @ant-design/x-sdk | Tools & APIs | `, }, { title: 'Link Syntax', content: 'Learn more: [Ant Design X](https://github.com/ant-design/x).', }, { title: 'Image Syntax', content: '![Ant Design X](https://mdn.alipayobjects.com/huamei_yz9z7c/afts/img/0lMhRYbo0-8AAAAAQDAAAAgADlJoAQFr/original)', }, { title: 'Html', content: ``, }, { title: 'Table', content: `| Package | Description | | --- | --- | | @ant-design/x | AI-oriented UI library | | @ant-design/x-markdown | Streaming Markdown | | @ant-design/x-sdk | Tools & APIs |`, }, { title: 'Emphasis', content: '**Bold**, *italic*, and ***both***.', }, { title: 'InlineCode', content: 'Run `npm install @ant-design/x-markdown`.', }, ]; const ImageSkeleton = () => ; const IncompleteLink = (props: ComponentProps) => { const text = decodeURIComponent(String(props['data-raw'] || '')); // 提取链接文本,格式为 [text](url) const linkTextMatch = text.match(/^\[([^\]]*)\]/); const displayText = linkTextMatch ? linkTextMatch[1] : text.slice(1); return ( {displayText} ); }; const TableSkeleton = () => ; const HtmlSkeleton = () => ; const IncompleteEmphasis = (props: ComponentProps) => { const text = decodeURIComponent(String(props['data-raw'] || '')); const match = text.match(/^([*_]{1,3})([^*_]*)/); if (!match || !match[2]) return null; const [, symbols, content] = match; const level = symbols.length; switch (level) { case 1: return {content}; case 2: return {content}; case 3: return ( {content} ); default: return null; } }; const IncompleteInlineCode = (props: ComponentProps) => { const rawData = String(props['data-raw'] || ''); if (!rawData) return null; const decodedText = decodeURIComponent(rawData)?.slice(1); return {decodedText}; }; const WelcomeCard = (props: Record) => ( ); const StreamDemo: React.FC<{ content: string }> = ({ content }) => { const [hasNextChunk, setHasNextChunk] = React.useState(true); const { theme: antdTheme } = theme.useToken(); const className = antdTheme.id === 0 ? 'x-markdown-light' : 'x-markdown-dark'; const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); const sourceRef = React.useRef(null); const scrollToBottom = React.useCallback( (el: HTMLDivElement | null) => { if (el && index > 0) { const { scrollHeight, clientHeight } = el; if (scrollHeight > clientHeight) { el.scrollTo({ top: scrollHeight, behavior: 'smooth' }); } } }, [index], ); React.useEffect(() => { if (index >= content.length) { setHasNextChunk(false); return; } timer.current = setTimeout(() => { setIndex(Math.min(index + 1, content.length)); }, 30); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (index > 0) { scrollToBottom(sourceRef.current); scrollToBottom(contentRef.current); } }, [index, scrollToBottom]); const isLongContent = content.length > 500; const previewMinHeight = isLongContent ? 320 : 160; const previewMaxHeight = isLongContent ? 420 : 280; return (
    {content.slice(0, index)}
    { e.preventDefault(); setIndex(0); setHasNextChunk(true); }} size="small" > Re-Render } >
    ); }; const App = () => { const [currentDemo, setCurrentDemo] = useState(0); return (
    setCurrentDemo(Number(v))} options={demos.map((demo, index) => ({ label: demo.title, value: index }))} block />
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/supersets/CustomPlugin/custom.tsx ================================================ import { type ComponentProps, type Token, XMarkdown } from '@ant-design/x-markdown'; import React from 'react'; import './plugin.css'; import { Popover, theme } from 'antd'; import { useIntl } from 'react-intl'; import '@ant-design/x-markdown/themes/light.css'; import '@ant-design/x-markdown/themes/dark.css'; const customPluginMarkdownZh = ` # 自定义脚注插件 Ant Design X 提供可扩展的 Markdown 渲染能力[^1],你可以按需添加插件并映射为业务组件[^2]。 - 解析自定义语法 - 渲染业务化 UI - 兼容流式输出 更多说明见文档[^3]。 [^1]: x-markdown 支持扩展 tokenizer 与 renderer。 [^2]: 通过 components 将标签映射为 React 组件。 [^3]: 示例链接仅用于演示脚注交互。 `; const customPluginMarkdownEn = ` # Custom Footnote Plugin Ant Design X provides extensible Markdown rendering[^1], so you can add plugins and map them to business components[^2]. - Parse custom syntax - Render business UI - Keep streaming-friendly behavior See docs for more details[^3]. [^1]: x-markdown supports custom tokenizer and renderer. [^2]: Use components to map tags to React components. [^3]: Links in this demo are for footnote interaction only. `; const referenceList = [ { url: 'https://x.ant.design', title: 'link1' }, { url: 'https://x.ant.design', title: 'link2' }, { url: 'https://x.ant.design', title: 'link3' }, { url: 'https://x.ant.design', title: 'link4' }, { url: 'https://x.ant.design', title: 'link5' }, { url: 'https://x.ant.design', title: 'link6' }, { url: 'https://x.ant.design', title: 'link7' }, { url: 'https://x.ant.design', title: 'link8' }, { url: 'https://x.ant.design', title: 'link9' }, ]; const Footnote: React.FC> = (props) => ( window.open(props.href)} className="markdown-cite"> {props.children} ); const App = () => { const { theme: antdTheme } = theme.useToken(); const className = antdTheme.id === 0 ? 'x-markdown-light' : 'x-markdown-dark'; const { locale } = useIntl(); const content = locale === 'zh-CN' ? customPluginMarkdownZh : customPluginMarkdownEn; const footNoteExtension = { name: 'footnote', level: 'inline' as const, tokenizer(src: string) { const match = src.match(/^\[\^(\d+)\]/); if (match) { const content = match[0].trim(); return { type: 'footnote', raw: content, text: content?.replace(/^\[\^(\d+)\]/g, '$1'), renderType: 'component', }; } }, renderer(token: Token) { if (!referenceList) { return ''; } const { text } = token; const order = Number(text) - 1; const currentUrl = referenceList?.[order]?.url; const currentTitle = referenceList?.[order]?.title; if (!currentUrl) { return null; } return `${text}`; }, }; return ( {content} ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/supersets/CustomPlugin/marked.tsx ================================================ import XMarkdown from '@ant-design/x-markdown'; import { markedEmoji } from 'marked-emoji'; import React from 'react'; const content = ` ### Use [marked extensions](https://marked.js.org/using_advanced#extensions) I :heart: XMarkdown! :tada:`; const options = { emojis: { heart: '❤️', tada: '🎉', }, renderer: (token: any) => token.emoji, }; const App = () => { return {content}; }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/supersets/CustomPlugin/plugin.css ================================================ .markdown-cite { background-color: rgba(154, 154, 154, 0.2); color: inherit; width: 20px; height: 20px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; text-decoration: none; font-size: 0.8em; margin-left: 8px; vertical-align: middle; transition: all 0.3s ease; cursor: pointer; &:hover { background-color: rgba(154, 154, 154, 40%); } } ================================================ FILE: packages/x/docs/x-markdown/demo/supersets/Latex/basic.tsx ================================================ import { Bubble } from '@ant-design/x'; import XMarkdown from '@ant-design/x-markdown'; import Latex from '@ant-design/x-markdown/plugins/Latex'; import { Button, Flex } from 'antd'; import React from 'react'; const text = ` ## 行内公式 在文本中嵌入数学公式,如:勾股定理 $ a^2 + b^2 = c^2 $,欧拉公式 $ e^{i\\pi} + 1 = 0 $。 圆的面积公式是\n $$ \n S = \\pi r^2 \n $$,其中 $ r $ 是半径。 二次方程 \\( ax^2 + bx + c = 0 \\) 的解为 \n \\[ \n x = \\frac{-b \\pm \\sqrt{b^2-4ac}}{2a} \n \\]。 ## 块级公式 ### 基础数学运算 $$ \\begin{aligned} a + b &= c \\\\ d - e &= f \\\\ g \\times h &= i \\\\ \\frac{j}{k} &= l \\end{aligned} $$ ### 平方根和指数 $$ \\sqrt{x} = x^{\\frac{1}{2}} $$ $$ \\sqrt[n]{x} = x^{\\frac{1}{n}} $$ $$ e^{i\\theta} = cos + sin $$ ### 分数和比例 $$ \\frac{\\partial f}{\\partial x} = \\lim_{h \\to 0} \\frac{f(x+h) - f(x)}{h} $$ $$ \\frac{a}{b} = \\frac{c}{d} \\Rightarrow ad = bc $$ ### 求和与积分 #### 求和公式 $$ \\sum_{i=1}^{n} i = \\frac{n(n+1)}{2} $$ $$ \\sum_{i=1}^{n} i^2 = \\frac{n(n+1)(2n+1)}{6} $$ #### 积分公式 $$ \\int_a^b f(x) dx = F(b) - F(a) $$ $$ \\int_{-\\infty}^{+\\infty} e^{-x^2} dx = \\sqrt{\\pi} $$ $$ \\int_0^{\\pi} \\sin x dx = 2 $$ ### 微分方程 $$ \\frac{dy}{dx} = ky \\Rightarrow y = Ce^{kx} $$ $$ \\frac{d^2y}{dx^2} + \\omega^2 y = 0 \\Rightarrow y = A\\cos(\\omega x) + B\\sin(\\omega x) $$ ### 矩阵运算 $$ \\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix} \\begin{pmatrix} x \\\\ y \\end{pmatrix} = \\begin{pmatrix} ax + by \\\\ cx + dy \\end{pmatrix} $$ 行列式: $$ \\det\\begin{pmatrix} a & b \\\\ c & d \\end{pmatrix} = ad - bc $$ ### 统计学公式 #### 正态分布 $$ f(x) = \\frac{1}{\\sigma\\sqrt{2\\pi}} e^{-\\frac{(x-\\mu)^2}{2\\sigma^2}} $$ #### 贝叶斯定理 $$ P(A|B) = \\frac{P(B|A) \\cdot P(A)}{P(B)} $$ #### 标准差 $$ \\sigma = \\sqrt{\\frac{1}{N}\\sum_{i=1}^{N}(x_i - \\mu)^2} $$ ### 三角函数 $$ \\sin^2\\theta + \\cos^2\\theta = 1 $$ $$ \\tan\\theta = \\frac{\\sin\\theta}{\\cos\\theta} $$ $$ e^{i\\theta} = \\cos\\theta + i\\sin\\theta $$ ### 级数展开 #### 泰勒级数 $$ f(x) = \\sum_{n=0}^{\\infty} \\frac{f^{(n)}(a)}{n!}(x-a)^n $$ #### 指数函数展开 $$ e^x = \\sum_{n=0}^{\\infty} \\frac{x^n}{n!} = 1 + x + \\frac{x^2}{2!} + \\frac{x^3}{3!} + \\cdots $$ #### 正弦函数展开 $$ \\sin x = \\sum_{n=0}^{\\infty} \\frac{(-1)^n x^{2n+1}}{(2n+1)!} = x - \\frac{x^3}{3!} + \\frac{x^5}{5!} - \\cdots $$ ### 复数运算 复数的一般形式: $ z = a + bi $ 复数的模: $ |z| = \\sqrt{a^2 + b^2} $ 复数的乘法: $$ (a + bi)(c + di) = (ac - bd) + (ad + bc)i $$ 德摩弗定理: $$ (\\cos\\theta + i\\sin\\theta)^n = \\cos(n\\theta) + i\\sin(n\\theta) $$ ### 极限 $$ \\lim_{x \\to 0} \\frac{\\sin x}{x} = 1 $$ $$ \\lim_{x \\to \\infty} \\left(1 + \\frac{1}{x}\\right)^x = e $$ $$ \\lim_{n \\to \\infty} \\sqrt[n]{n} = 1 $$ ### 组合数学 排列数: $ P(n,r) = \\frac{n!}{(n-r)!} $ 组合数: $ C(n,r) = \\binom{n}{r} = \\frac{n!}{r!(n-r)!} $ 二项式定理: $$ (x + y)^n = \\sum_{k=0}^{n} \\binom{n}{k} x^{n-k} y^k $$ ### 向量运算 向量的点积: $ \\vec{a} \\cdot \\vec{b} = |\\vec{a}||\\vec{b}|\\cos\\theta $ 向量的叉积: $ \\vec{a} \\times \\vec{b} = |\\vec{a}||\\vec{b}|\\sin\\theta \\vec{n} $ 三维向量的叉积: $$ \\vec{a} \\times \\vec{b} = \\begin{vmatrix} \\vec{i} & \\vec{j} & \\vec{k} \\\\ a_1 & a_2 & a_3 \\\\ b_1 & b_2 & b_3 \\end{vmatrix} $$ ### 支持的语法格式 本示例支持以下 LaTeX 语法格式: #### 行内公式 - 使用单个 $ 包围:$E=mc^2$ - 使用 ( ) 包围:(a^2+b^2=c^2) - 使用两个 $ 包围并带有 \`\n\`:$\n E=mc^2 \n$ - 使用 [ ] 包围:[ \n a^2+b^2=c^2 \n ] - 使用 $$\n\n$$ 语法:$$ E=mc^2 $$ - 使用 [ \n ] 语法:[ E=mc^2 ] #### 块级公式 - 使用双 $$ 包围: $$ int_a^b f(x)dx = F(b) - F(a) $$ - 使用 [ ] 包围: [ sum_{i=1}^n i = \frac{n(n+1)}{2} ] > **注意**:LaTeX 公式的渲染依赖于 KaTeX 库,确保已正确配置相关依赖。 `; const App = () => { const [index, setIndex] = React.useState(0); const timer = React.useRef(null); const contentRef = React.useRef(null); React.useEffect(() => { if (index >= text.length) return; timer.current = setTimeout(() => { setIndex(Math.min(index + 5, text.length)); }, 20); return () => { if (timer.current) { clearTimeout(timer.current); timer.current = null; } }; }, [index]); React.useEffect(() => { if (contentRef.current && index > 0 && index < text.length) { const { scrollHeight, clientHeight } = contentRef.current; if (scrollHeight > clientHeight) { contentRef.current.scrollTo({ top: scrollHeight, behavior: 'smooth', }); } } }, [index]); return ( ( {content} )} variant="outlined" /> ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/themes/custom.tsx ================================================ import { XMarkdown } from '@ant-design/x-markdown'; import React from 'react'; import '@ant-design/x-markdown/themes/light.css'; import { useIntl } from 'react-intl'; import { Theme_Markdown_En, Theme_Markdown_Zh } from '../_utils/theme-markdown'; const App = () => { const { locale } = useIntl(); const content = locale === 'zh-CN' ? Theme_Markdown_Zh : Theme_Markdown_En; const customVars = { '--primary-color': '#0f766e', '--primary-color-hover': '#0d9488', '--heading-color': '#0f172a', '--text-color': '#1f2937', '--light-bg': 'rgba(15, 118, 110, 0.08)', '--border-color': 'rgba(15, 23, 42, 0.12)', } as React.CSSProperties; return (
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/themes/dark.tsx ================================================ import { XMarkdown } from '@ant-design/x-markdown'; import React from 'react'; import '@ant-design/x-markdown/themes/dark.css'; import { useIntl } from 'react-intl'; import { Adx_Markdown_En, Adx_Markdown_Zh } from '../_utils/adx-markdown'; const App = () => { const { locale } = useIntl(); const content = locale === 'zh-CN' ? Adx_Markdown_Zh : Adx_Markdown_En; return (
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/themes/light.tsx ================================================ import { XMarkdown } from '@ant-design/x-markdown'; import React from 'react'; import '@ant-design/x-markdown/themes/light.css'; import { useIntl } from 'react-intl'; import { Adx_Markdown_En, Adx_Markdown_Zh } from '../_utils/adx-markdown'; const App = () => { const { locale } = useIntl(); const content = locale === 'zh-CN' ? Adx_Markdown_Zh : Adx_Markdown_En; return (
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/demo/themes/switch.tsx ================================================ import { XMarkdown } from '@ant-design/x-markdown'; import { Segmented } from 'antd'; import React from 'react'; import '@ant-design/x-markdown/themes/light.css'; import '@ant-design/x-markdown/themes/dark.css'; import { useIntl } from 'react-intl'; import { Theme_Markdown_En, Theme_Markdown_Zh } from '../_utils/theme-markdown'; const App = () => { const { locale } = useIntl(); const content = locale === 'zh-CN' ? Theme_Markdown_Zh : Theme_Markdown_En; const [mode, setMode] = React.useState<'light' | 'dark'>('light'); const className = mode === 'light' ? 'x-markdown-light' : 'x-markdown-dark'; const containerStyle = mode === 'light' ? { background: '#ffffff', border: '1px solid rgba(5, 5, 5, 0.06)' } : { background: '#141414', border: '1px solid rgba(255, 255, 255, 0.14)' }; return (
    value={mode} onChange={setMode} options={[ { label: 'Light', value: 'light' }, { label: 'Dark', value: 'dark' }, ]} style={{ marginBottom: 12 }} />
    ); }; export default App; ================================================ FILE: packages/x/docs/x-markdown/examples.en-US.md ================================================ --- title: Code Examples order: 2 tag: 2.0.0 category: Components componentName: XMarkdown packageName: x-markdown --- ## When to Use Use this page to get a minimal setup for rendering LLM Markdown output. ## Code Examples ## API | Property | Description | Type | Default | | --- | --- | --- | --- | | content | Markdown content to render | `string` | - | | children | Markdown content (use either `content` or `children`) | `string` | - | | components | Map HTML nodes to custom React components | `Record \| keyof JSX.IntrinsicElements>` | - | | streaming | Streaming behavior config | `StreamingOption` | - | | config | Marked parse config, applied last and may override built-in renderers | [`MarkedExtension`](https://marked.js.org/using_advanced#options) | `{ gfm: true }` | | rootClassName | Extra CSS class for the root element | `string` | - | | className | Extra CSS class for the root container | `string` | - | | paragraphTag | HTML tag for paragraphs (avoids validation issues when custom components contain block elements) | `keyof JSX.IntrinsicElements` | `'p'` | | style | Inline styles for the root container | `CSSProperties` | - | | prefixCls | CSS class name prefix for component nodes | `string` | - | | openLinksInNewTab | Add `target="_blank"` to all links so they open in a new tab | `boolean` | `false` | | dompurifyConfig | DOMPurify config for HTML sanitization and XSS protection | [`DOMPurify.Config`](https://github.com/cure53/DOMPurify#can-i-configure-dompurify) | - | | protectCustomTagNewlines | Whether to preserve newlines inside custom tags | `boolean` | `false` | | escapeRawHtml | Escape raw HTML in Markdown as plain text (do not parse as real HTML), to prevent XSS while keeping content visible | `boolean` | `false` | | debug | Enable debug mode (performance overlay) | `boolean` | `false` | ### StreamingOption | Field | Description | Type | Default | | --- | --- | --- | --- | | hasNextChunk | Whether more chunks are expected. Set `false` to flush cache and finish rendering | `boolean` | `false` | | enableAnimation | Whether to enable fade-in animation for block elements | `boolean` | `false` | | animationConfig | Animation options (for example fade duration and easing) | `AnimationConfig` | - | | tail | Enable tail indicator | `boolean \| TailConfig` | `false` | | incompleteMarkdownComponentMap | Map incomplete Markdown fragments to custom loading components | `Partial>` | `{ link: 'incomplete-link', image: 'incomplete-image' }` | ### TailConfig | Property | Description | Type | Default | | --- | --- | --- | --- | | content | Content to display as tail | `string` | `'▋'` | | component | Custom tail component, takes precedence over content | `React.ComponentType<{ content?: string }>` | - | ### AnimationConfig | Property | Description | Type | Default | | ------------ | ------------------- | -------- | --------------- | | fadeDuration | Duration in ms | `number` | `200` | | easing | CSS easing function | `string` | `'ease-in-out'` | ## Related Docs - [Component Extension](/x-markdowns/components) - [Streaming](/x-markdowns/streaming) ================================================ FILE: packages/x/docs/x-markdown/examples.zh-CN.md ================================================ --- title: 代码示例 order: 2 tag: 2.0.0 category: Components componentName: XMarkdown packageName: x-markdown --- ## 何时使用 用于快速接入 LLM 的 Markdown 输出渲染。 ## 代码演示 ## API | 属性 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | content | 需要渲染的 Markdown 内容 | `string` | - | | children | Markdown 内容(与 `content` 二选一) | `string` | - | | components | 将 HTML 节点映射为自定义 React 组件 | `Record \| keyof JSX.IntrinsicElements>` | - | | streaming | 流式渲染行为配置 | `StreamingOption` | - | | config | Marked 解析配置,后应用且可能覆盖内置 renderer | [`MarkedExtension`](https://marked.js.org/using_advanced#options) | `{ gfm: true }` | | rootClassName | 根元素的额外 CSS 类名 | `string` | - | | className | 根容器的额外 CSS 类名 | `string` | - | | paragraphTag | 段落使用的 HTML 标签(避免自定义组件含块级元素时的校验问题) | `keyof JSX.IntrinsicElements` | `'p'` | | style | 根容器的内联样式 | `CSSProperties` | - | | prefixCls | 组件节点 CSS 类名前缀 | `string` | - | | openLinksInNewTab | 是否为所有链接添加 `target="_blank"` 并在新标签页打开 | `boolean` | `false` | | dompurifyConfig | HTML 净化与 XSS 防护的 DOMPurify 配置 | [`DOMPurify.Config`](https://github.com/cure53/DOMPurify#can-i-configure-dompurify) | - | | protectCustomTagNewlines | 是否保留自定义标签内部的换行 | `boolean` | `false` | | escapeRawHtml | 是否将 Markdown 中的原始 HTML 转义为纯文本展示(不解析为真实 HTML),用于防 XSS 同时保留内容 | `boolean` | `false` | | debug | 是否开启调试模式(显示性能监控浮层) | `boolean` | `false` | ### StreamingOption | 字段 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | hasNextChunk | 是否还有后续内容块。为 `false` 时会刷新缓存并完成渲染 | `boolean` | `false` | | enableAnimation | 是否为块级元素启用文字淡入动画 | `boolean` | `false` | | animationConfig | 动画配置(如淡入时长、缓动函数) | `AnimationConfig` | - | | tail | 是否启用尾部指示器 | `boolean \| TailConfig` | `false` | | incompleteMarkdownComponentMap | 将未闭合 Markdown 片段映射到自定义 loading 组件 | `Partial>` | `{ link: 'incomplete-link', image: 'incomplete-image' }` | ### TailConfig | 属性 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | | content | 尾部显示的内容 | `string` | `'▋'` | | component | 自定义尾部组件,优先级高于 content | `React.ComponentType<{ content?: string }>` | - | ### AnimationConfig | 属性 | 说明 | 类型 | 默认值 | | ------------ | ---------------- | -------- | --------------- | | fadeDuration | 动画时长(毫秒) | `number` | `200` | | easing | 缓动函数 | `string` | `'ease-in-out'` | ================================================ FILE: packages/x/docs/x-markdown/introduce.en-US.md ================================================ --- order: 1 title: Introduction --- `@ant-design/x-markdown` aims to provide a streaming-friendly, highly extensible and high-performance Markdown renderer. It offers capabilities such as streaming rendering of formulas, code highlighting, mermaid etc. ## ✨ Features Built on [`marked`](https://github.com/markedjs/marked) as the base Markdown renderer, inheriting all features of marked. - 🚀 Built for speed. - 🤖 Streaming-friendly, a Markdown rendering solution for large models. - ⬇️ Low-level compiler for parsing Markdown without long-term caching or blocking. - ⚖️ Lightweight while implementing all supported Markdown styles and specifications. - 🔐 Secure by default, no dangerouslySetInnerHTML XSS attacks. - 🎨 Customizable components - replace any Markdown element with your own, e.g. `

    ` for `## hi`. - 🔧 Rich plugin ecosystem with many plugins to choose from. - 😊 Compatible - 100% CommonMark compliant, 100% GFM plugin compliant. ## Compatibility Aligned with [`marked`](https://github.com/markedjs/marked). To improve overall Markdown compatibility with systems, custom polyfills can be added. | [Edge](https://godban.github.io/browsers-support-badges/)
    Edge | [Firefox](https://godban.github.io/browsers-support-badges/)
    Firefox | [Chrome](https://godban.github.io/browsers-support-badges/)
    Chrome | [Safari](https://godban.github.io/browsers-support-badges/)
    Safari | [Opera](https://godban.github.io/browsers-support-badges/)
    Opera | | --- | --- | --- | --- | --- | | >= 92 | >= 90 | >= 92 | >= 15.4 | >= 78 | ## Supported Markdown Specifications - [Markdown 1.0.0](https://daringfireball.net/projects/markdown/) - [CommonMark](https://github.com/commonmark/commonmark-spec/wiki/Markdown-Flavors) - [GitHub Flavored Markdown (GFM)](https://github.github.com/gfm/) ## Installation ### Using npm or yarn or pnpm or bun or utoo **We recommend using [npm](https://www.npmjs.com/) or [yarn](https://github.com/yarnpkg/yarn/) or [pnpm](https://pnpm.io/) or [bun](https://bun.sh/) or [utoo](https://github.com/umijs/mako/tree/next) for development**, which allows easy debugging in development environments and safe production deployment, enjoying the benefits of the entire ecosystem and toolchain. If your network environment is poor, we recommend using [cnpm](https://github.com/cnpm/cnpm). ### Browser Usage Include files directly in the browser using `script` and `link` tags, and use the global variable `XMarkdown`. We provide `x-markdown.js`, `x-markdown.min.js` and `x-markdown.min.js.map` in the dist directory of the npm package. > **Strongly not recommended to use built files directly**, as this prevents on-demand loading and makes it difficult to get quick bug fixes for underlying dependencies. > Note: `x-markdown.js`, `x-markdown.min.js` and `x-markdown.min.js.map` depend on `react` and `react-dom`. Please ensure these are included first. ## Example ```tsx import React from 'react'; import { XMarkdown } from '@ant-design/x-markdown'; const content = `# Hello XMarkdown\n\nThis is a streaming, user-friendly Markdown renderer.`; const App = () => ; export default App; ``` ## Plugins `@ant-design/x-markdown` provides a rich set of plugins that can be used via the `plugins` property. See [Plugin Collection](/x-markdowns/plugins) for details. ## Themes `@ant-design/x-markdown` offers a variety of themes to choose from. See [Themes](/x-markdowns/themes) for details. ================================================ FILE: packages/x/docs/x-markdown/introduce.zh-CN.md ================================================ --- order: 1 title: 介绍 --- `@ant-design/x-markdown` 旨在提供流式友好、强拓展性和高性能的 Markdown 渲染器。提供流式渲染公式、代码高亮、mermaid 等能力。 ## ✨ 特性 使用 [`marked`](https://github.com/markedjs/marked) 作为基础 markdown 渲染器,具备 marked 的所有特性。 - 🚀 为速度而生。 - 🤖 流式友好,大模型 Markdown 渲染解决方案。 - ⬇️ 低级编译器,用于解析 Markdown,无需长时间缓存或阻塞。 - ⚖️ 轻量级,同时实现所有支持的风格和规范的 markdown 功能。 - 🔐 默认安全,无 dangerouslySetInnerHTML XSS 攻击。 - 🎨 可自定义组件,支持传入自定义组件替换任意 Markdown 元素,如用自定义组件替换 `## hi` 对应的 `

    `。 - 🔧 丰富的插件,有很多插件可供选择。 - 😊 兼容,100% 符合 CommonMark,100% 符合 GFM 插件。 ## 兼容环境 与 [`marked`](https://github.com/markedjs/marked) 保持一致。为了提高整体 markdown 对于系统的兼容性支持,可以自定义 polyfill,来提高兼容性。 | [Edge](https://godban.github.io/browsers-support-badges/)
    Edge | [Firefox](https://godban.github.io/browsers-support-badges/)
    Firefox | [Chrome](https://godban.github.io/browsers-support-badges/)
    Chrome | [Safari](https://godban.github.io/browsers-support-badges/)
    Safari | [Opera](https://godban.github.io/browsers-support-badges/)
    Opera | | --- | --- | --- | --- | --- | | >= 92 | >= 90 | >= 92 | >= 15.4 | >= 78 | ## 支持的 Markdown 规范 - [Markdown 1.0.0](https://daringfireball.net/projects/markdown/) - [CommonMark](https://github.com/commonmark/commonmark-spec/wiki/Markdown-Flavors) - [GitHub Flavored Markdown (GFM)](https://github.github.com/gfm/) ## 安装 ### 使用 npm 或 yarn 或 pnpm 或 bun 安装 或 utoo 安装 **我们推荐使用 [npm](https://www.npmjs.com/) 或 [yarn](https://github.com/yarnpkg/yarn/) 或 [pnpm](https://pnpm.io/zh/) 或 [bun](https://bun.sh/) 或 [utoo](https://github.com/umijs/mako/tree/next) 的方式进行开发**,不仅可在开发环境轻松调试,也可放心地在生产环境打包部署使用,享受整个生态圈和工具链带来的诸多好处。 如果你的网络环境不佳,推荐使用 [cnpm](https://github.com/cnpm/cnpm)。 ### 浏览器引入 在浏览器中使用 `script` 和 `link` 标签直接引入文件,并使用全局变量 `XMarkdown`。 我们在 npm 发布包内的 dist 目录下提供了 `x-markdown.js`、`x-markdown.min.js` 和 `x-markdown.min.js.map`。 > **强烈不推荐使用已构建文件**,这样无法按需加载,而且难以获得底层依赖模块的 bug 快速修复支持。 > 注意:`x-markdown.js` 、 `x-markdown.min.js` 和 `x-markdown.min.js.map`。依赖 `react`、`react-dom`请确保提前引入这些文件。 ## 示例 ```tsx import React from 'react'; import { XMarkdown } from '@ant-design/x-markdown'; const content = '# Hello XMarkdown\n\n这是一个流式友好的 Markdown 渲染器。'; const App = () => ; export default App; ``` ## 插件 `@ant-design/x-markdown` 提供了丰富的插件,你可以通过 `plugins` 属性来使用这些插件。插件详情查看[插件集](/x-markdowns/plugins-cn)。 ## 主题 `@ant-design/x-markdown` 提供了主题可供选择。主题详情查看[主题](/x-markdowns/themes-cn)。 ================================================ FILE: packages/x/docs/x-markdown/playground.en-US.md ================================================ --- title: Playground order: 2.1 --- ================================================ FILE: packages/x/docs/x-markdown/playground.tsx ================================================ import { SettingOutlined } from '@ant-design/icons'; import type { ComponentProps } from '@ant-design/x-markdown'; import XMarkdown from '@ant-design/x-markdown'; import { Button, Card, Flex, Input, Popover, Segmented, Select, Space, Switch, Typography, theme, } from 'antd'; import React from 'react'; import '@ant-design/x-markdown/themes/light.css'; import '@ant-design/x-markdown/themes/dark.css'; const { Text } = Typography; const { TextArea } = Input; const DEFAULT_SOURCE = `# XMarkdown Playground Type Markdown in the editor and see real-time rendering. ## Features - CommonMark and GFM - Streaming-friendly rendering - Safe HTML handling with configurable escaping \`\`\`tsx const message = 'Hello, XMarkdown'; console.log(message); \`\`\` ## Streaming Preview 1. Click "Run Stream" 2. Observe incomplete syntax handling 3. Continue typing in the editor for instant full preview | Step | Status | | --- | --- | | Parse | Done | | Render | Running | [Link example](https://x.ant.design/x-markdowns/introduce) ## HTML and Security
    Inline raw HTML block
    Try toggling \`escapeRawHtml\` to compare behavior. `; const getDataRaw = (rest: ComponentProps['rest']) => { if (!rest || typeof rest !== 'object') { return ''; } return typeof (rest as Record)['data-raw'] === 'string' ? ((rest as Record)['data-raw'] as string) : ''; }; const IncompleteLoadingComponents = { 'loading-link': ({ rest }: ComponentProps) => { const raw = getDataRaw(rest); return {raw || '...'}; }, 'loading-image': () => ( Loading image... ), 'loading-table': () => ( Loading table... ), 'loading-html': ({ rest }: ComponentProps) => { const raw = getDataRaw(rest); return {raw || ''}; }, }; interface ToggleItemProps { label: string; checked: boolean; onChange: (checked: boolean) => void; } const ToggleItem: React.FC = ({ label, checked, onChange }) => ( {label} ); interface SelectItemProps { label: string; value: string; onChange: (value: string) => void; options: { label: string; value: string }[]; } const SelectItem: React.FC = ({ label, value, onChange, options }) => ( {label}