Compare commits

..

344 Commits

Author SHA1 Message Date
lijianan
d85e0e0163 Merge branch 'master' into chore/scripts 2025-10-19 11:08:45 +08:00
thinkasany
2818ba6b87 chore: turn on react-hooks/immutability (#55357)
* chore: turn on react-hooks/immutability

* Update .dumi/theme/common/Color/Palette.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-19 09:48:23 +08:00
lijianan
17cdff8c4c site: Graph should be destroy when page unmount (#55361)
* site: update missing dependency

* update

* update

* Update .dumi/theme/layouts/DocLayout/index.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* update

* site: TreeGraph should be destroy when unmount

* update

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-19 09:38:03 +08:00
renovate[bot]
9b953b0fcc chore(deps): update mcr.microsoft.com/devcontainers/typescript-node docker tag to v4 (#55360)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-19 09:20:26 +08:00
lijianan
9823f348fc site: update missing dependency (#55358)
* site: update missing dependency

* update

* update

* Update .dumi/theme/layouts/DocLayout/index.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* update

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-19 09:07:49 +08:00
lijianan
bd00e59fc1 fix: update missing dependency (#55322) 2025-10-19 00:31:59 +08:00
thinkasany
dc179c8985 chore: rm useless rules (#55356)
* chore: rm useless rules

* fix
2025-10-18 17:37:47 +08:00
lijianan
fee3e97a26 fix(splitter): update missing dependency (#55355) 2025-10-18 17:20:56 +08:00
lijianan
7d079c2560 fix(drawer): rewrite memo to render function (#55349)
* fix(drawer): update missing dependency

* update
2025-10-18 16:36:56 +08:00
lijianan
809b8820f9 fix(steps): update missing dependency (#55353) 2025-10-18 16:15:18 +08:00
lijianan
6abbee7273 fix(form): update missing dependency (#55350) 2025-10-18 16:04:40 +08:00
lijianan
2327d5bca9 fix(modal): update missing dependency (#55352) 2025-10-18 16:04:14 +08:00
thinkasany
2ad2ef7bfd chore: lock jsdom@27.0.0 (#55347) 2025-10-18 15:20:25 +08:00
thinkasany
c4b6a30e8f chore: turn on react-hooks/static-components (#55340)
* chore: turn on react-hooks/static-components

* fix

* fix
2025-10-18 11:36:41 +08:00
lijianan
669e948638 site: refactor useIssueCount with SWR (#55343)
* refactor(site): refactor useIssueCount with SWR

* Update .dumi/hooks/useIssueCount.ts

Co-authored-by: codefactor-io[bot] <47775046+codefactor-io[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* update

* update

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: codefactor-io[bot] <47775046+codefactor-io[bot]@users.noreply.github.com>
2025-10-18 10:35:27 +08:00
lijianan
54afae7767 refactor(table): refactor spinProps with useMemo (#55344)
* refactor(table): refactor spinProps with useMemo

* Update components/table/InternalTable.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* update test case

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-18 10:33:45 +08:00
afc163
da79662278 fix(Table): table pagination.align should be working (#55316) 2025-10-17 22:49:13 +08:00
afc163
aa13ad28e4 site: add issue count hook and integrate into component meta (#55337)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-10-17 22:37:12 +08:00
Copilot
e9622c2d26 chore: Set up GitHub Copilot instructions for repository (#55320)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-10-17 22:36:56 +08:00
afc163
9c129ac7b1 refactor: simplify spinProps logic in InternalTable (#55336)
* refactor: simplify spinProps logic in InternalTable

* Update components/table/InternalTable.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: afc163 <afc163@gmail.com>

* Refactor loading check to eliminate redundancy

Removed redundant return statement in loading check.

Signed-off-by: afc163 <afc163@gmail.com>

* Apply suggestion from @afc163

Signed-off-by: afc163 <afc163@gmail.com>

---------

Signed-off-by: afc163 <afc163@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-17 19:31:38 +08:00
thinkasany
f47947d857 chore: turn on react-hooks/purity (#55331) 2025-10-16 23:11:44 +08:00
thinkasany
bb21a2dfa6 chore(deps): bump @antfu/eslint-config from 5.4.1 to 6.0.0 (#55321)
* chore(deps): bump @antfu/eslint-config from 5.4.1 to 6.0.0

* rm
2025-10-15 22:05:07 +08:00
二货爱吃白萝卜
620d1bf431 docs: faq about zoom (#55312)
* docs: faq about zoom

* Update docs/react/faq.en-US.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* Update docs/react/faq.zh-CN.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* docs: faq about zoom

---------

Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-10-15 21:18:06 +08:00
𝑾𝒖𝒙𝒉
2abbbda693 chore: update AGENTS.md (#55314) 2025-10-15 21:16:53 +08:00
lijianan
e714dde0dc type: resolve gemini-code-assist review comment (#55313)
* type: resolve gemini-code-assist review comment

* type: resolve gemini-code-assist review comment

* type: resolve gemini-code-assist review comment

* update
2025-10-15 17:29:20 +08:00
smallbun
95bca1cf70 type: getTargetContainer getPopupContainer support ShadowRoot type (#55278)
Co-authored-by: topiam <support@topiam.cn>
2025-10-15 11:20:35 +08:00
Arif Çakıroğlu
76392a2fc0 docs: Add AntUIKit resources to documentation (#55293)
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-15 11:20:13 +08:00
Peach
dde07ee096 docs: improve changelog for 5.27.5 (#55308)
Signed-off-by: Peach <scdzwyxst@gmail.com>
2025-10-15 09:53:33 +08:00
ug
129b4d6e6f docs: Modify the usage of Select.Option in the Input demo (#55298)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-10-14 19:57:00 +08:00
𝑾𝒖𝒙𝒉
ac515bc0a6 docs(dumi-plugin):Improved changelog detail processing logic (#55302) 2025-10-14 19:53:00 +08:00
Peach
017fea5bb4 docs: changelog for 5.27.5 (#55292)
* docs: changelog for 5.27.5

* chore: bump version to 5.27.5

* docs: remove blank line

* Apply suggestions from code review

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: Peach <scdzwyxst@gmail.com>

---------

Signed-off-by: Peach <scdzwyxst@gmail.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-10-14 19:11:54 +08:00
Peach
117673d618 revert: "fix: handle maxCount negative value validation (#55129)" (#55303)
This reverts commit b59a1102f1.
2025-10-14 17:10:03 +08:00
lijianan
72f26b3898 fix(wave): update missing dependency (#55296) 2025-10-14 16:12:49 +08:00
lijianan
6047298565 fix(hook): update missing dependency (#55294) 2025-10-14 08:09:47 +08:00
lijianan
63e2dfd682 fix(tour): update missing dependency (#55295) 2025-10-14 08:07:18 +08:00
Allllore
7a520404aa docs: update button spec (#55290) 2025-10-13 11:10:22 +08:00
lijianan
a07161fa05 site: update error UI (#55280)
* site: update error UI

* Update .dumi/pages/index/components/BannerRecommends.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* Update .dumi/theme/builtins/ResourceArticles/index.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* site: update error UI

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-13 09:24:57 +08:00
lijianan
be85401160 fix(button): update miss autoFocus dependency (#55283)
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-13 09:24:31 +08:00
lijianan
dc362e2e1c fix(site): update miss useCssVar dependency (#55284)
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-13 09:19:36 +08:00
lijianan
eca2da28c9 fix(calendar): update miss today, prefixCls, calendarPrefixCls dependency (#55282) 2025-10-13 08:18:06 +08:00
lijianan
a4bb8aef9a chore: update eslint-plugin-react-hooks to 7.0.0 (#55286)
Co-authored-by: thinkasany <480968828@qq.com>
2025-10-13 08:14:55 +08:00
lijianan
1b6d5527c6 perf: keep LoadingIcon in memo (#55285) 2025-10-13 08:10:19 +08:00
thinkasany
450c2b2cbb chore: turn on react-dom/no-missing-button-type (#55277) 2025-10-12 11:54:01 +08:00
renovate[bot]
91a4451c5b chore(deps): update softprops/action-gh-release action to v2.4.1 (#55275)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-12 08:24:14 +08:00
lijianan
3dad1bd09e fix: add miss dependency for useMemo (#55273)
* fix: add miss dep for useMemo

* Update dependency array for useMemo in useColumnIcons

Signed-off-by: lijianan <574980606@qq.com>

---------

Signed-off-by: lijianan <574980606@qq.com>
2025-10-12 08:12:38 +08:00
thinkasany
44cfd0cdeb chore(deps): unlock antd-img-crop (#55271)
* chore(deps): unlock antd-img-crop

* skip demo
2025-10-11 22:59:07 +08:00
Trần Quang Khánh
b8cb35ca2d fix(modal): add missing accessibility for confirm modal (#55266)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-11 13:50:39 +08:00
lijianan
a1a6f1bfff chore: fix CI fail (#55259)
Signed-off-by: lijianan <574980606@qq.com>
2025-10-10 18:58:05 +08:00
thinkasany
ef45e96227 chore: bump eslint-plugin-react-hooks from 6.0.1 to 7.0.0 (#55247) 2025-10-09 20:04:50 +08:00
lijianan
6d703575ff site: use renderReactToHTMLString (#55219)
* site: use renderReactToHTMLString

* update

* Apply suggestion from @gemini-code-assist[bot]

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* Apply suggestion from @gemini-code-assist[bot]

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* update

* type: update type

* update lint

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-09 17:10:56 +08:00
lijianan
378fcad5e1 chore: merge two variables into one (#55241) 2025-10-08 15:49:44 +08:00
ug
70a9d43393 fix(DatePicker):Incorrect use of icon color token (#55065)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-08 14:15:56 +08:00
deathemperor
1370c11cf7 type: missing float button and group disabled type (#55156) 2025-10-08 10:42:44 +08:00
lijianan
9ac07bea68 type: mark children definition more strict and standards (#55233) 2025-10-06 20:49:36 +08:00
renovate[bot]
a2c571ff00 chore(deps): update softprops/action-gh-release action to v2.3.4 (#55232)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-05 10:32:22 +08:00
lijianan
af89759d8d fix(site): change button to div for fix hydration error (#55224)
* fix(site): change button => div for fix hydration issue

* update

* update

---------

Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-04 16:29:54 +08:00
lijianan
fce28d79af fix(site): fix import path issue (#55223)
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-04 16:28:06 +08:00
dependabot[bot]
3fcd6c8573 chore: bump peter-evans/commit-comment from 3 to 4 (#55226)
Bumps [peter-evans/commit-comment](https://github.com/peter-evans/commit-comment) from 3 to 4.
- [Release notes](https://github.com/peter-evans/commit-comment/releases)
- [Commits](https://github.com/peter-evans/commit-comment/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/commit-comment
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-03 21:11:26 +08:00
thinkasany
004eab7736 chore(deps): bump eslint-plugin-react-hooks from 5.2.0 to 6.1.0 (#55221) 2025-10-02 15:49:20 +08:00
thinkasany
7833e84c8d chore(deps): bump react from 19.1.0 to 19.2.0 (#55220) 2025-10-02 10:12:56 +08:00
lijianan
6b8d833cad site: compatible error & isLoading for site data (#55217)
Co-authored-by: thinkasany <480968828@qq.com>
2025-10-02 09:15:40 +08:00
dependabot[bot]
ec57a0eb02 chore: bump @testing-library/jest-dom from 6.8.0 to 6.9.1 in the dev-dependencies group (#55218)
* chore: bump @testing-library/jest-dom in the dev-dependencies group

Bumps the dev-dependencies group with 1 update: [@testing-library/jest-dom](https://github.com/testing-library/jest-dom).


Updates `@testing-library/jest-dom` from 6.8.0 to 6.9.1
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v6.8.0...v6.9.1)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-version: 6.9.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update @testing-library/jest-dom version constraint

Signed-off-by: lijianan <574980606@qq.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: lijianan <574980606@qq.com>
2025-10-02 05:53:49 +08:00
thinkasany
3635c80085 chore(eslint): move tests rules (#55214)
Co-authored-by: 遇见同学 <1875694521@qq.com>
2025-10-01 21:09:38 +08:00
Trần Quang Khánh
85812ed060 fix(list): adjust bordered list overflow styling (#55075)
* fix(list): adjust bordered list overflow styling

* fix(list): apply border radius for list header and footer

* fix: lint-style error

* fix: resolve comment

---------

Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-10-01 18:40:18 +08:00
lijianan
b5d72b5a77 site: use SWR, make query always fast and reactive (#55205)
* site: use SWR, make query always fast and reactive

* update

* update

---------

Co-authored-by: thinkasany <480968828@qq.com>
2025-10-01 11:43:57 +08:00
dependabot[bot]
c060c55fc4 chore: bump @testing-library/jest-dom from 6.6.4 to 6.9.0 in the dev-dependencies group (#55206)
* chore: bump @testing-library/jest-dom in the dev-dependencies group

Bumps the dev-dependencies group with 1 update: [@testing-library/jest-dom](https://github.com/testing-library/jest-dom).


Updates `@testing-library/jest-dom` from 6.6.4 to 6.9.0
- [Release notes](https://github.com/testing-library/jest-dom/releases)
- [Changelog](https://github.com/testing-library/jest-dom/blob/main/CHANGELOG.md)
- [Commits](https://github.com/testing-library/jest-dom/compare/v6.6.4...v6.9.0)

---
updated-dependencies:
- dependency-name: "@testing-library/jest-dom"
  dependency-version: 6.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update package.json

Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-10-01 09:23:35 +08:00
thinkasany
7c5ae3b168 chore: lock @testing-library/jest-dom@~6.6.3 (#55201)
* test

* lock
2025-09-30 23:22:26 +08:00
dependabot[bot]
9f90f35513 chore: bump @types/jsdom in the dev-dependencies group (#55194)
Bumps the dev-dependencies group with 1 update: [@types/jsdom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsdom).


Updates `@types/jsdom` from 21.1.7 to 27.0.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsdom)

---
updated-dependencies:
- dependency-name: "@types/jsdom"
  dependency-version: 27.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-30 08:12:22 +08:00
thinkasany
3e88285d77 chore: bump eslint-plugin-react-refresh from 0.4.14 to 0.4.22 (#55180) 2025-09-28 16:16:02 +08:00
thinkasany
87601689fa chore: turn on unicorn/prefer-includes (#55169) 2025-09-28 11:55:43 +08:00
thinkasany
5db1e6f449 chore: turn on perfectionist/sort-exports (#55172) 2025-09-28 11:46:21 +08:00
thinkasany
90b4a4373d chore: turn on test/prefer-hooks-in-order (#55171) 2025-09-28 11:38:42 +08:00
thinkasany
8a7e15460c chore: turn on ts/method-signature-style (#55167) 2025-09-28 10:15:00 +08:00
thinkasany
2589e693cf chore: turn on unicorn/prefer-number-properties (#55168) 2025-09-28 09:40:04 +08:00
thinkasany
94d5b800a7 chore: turn on ts/consistent-type-imports (#55166) 2025-09-28 09:10:30 +08:00
thinkasany
dfc34f6ae3 chore: bump @eslint-react/eslint-plugin (#55165) 2025-09-28 02:10:01 +08:00
lijianan
0b5ef77e5d chore: update Security Policy from 4.x to 5.x (#55160) 2025-09-27 13:18:38 +08:00
ug
4d15a1715d docs(Input): use Chinese for table headers as required​ (#55153)
* update

* Update components/input/index.zh-CN.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 遇见同学 <1875694521@qq.com>

---------

Signed-off-by: 遇见同学 <1875694521@qq.com>
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-09-26 15:44:22 +08:00
lijianan
1d433d59d5 site: block Copilot bot、renovate bot、dependa bot (#55150)
* site: block Copilot bot

* update

* update

* update

* update
2025-09-26 08:13:57 +08:00
Laffery
bd1aa0114e docs(AutoComplete): add underlined variant demo (#55055)
* docs(AutoComplete): add underlined variant demo

* Apply suggestion from @gemini-code-assist[bot]

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Laffery <49607541+Laffery@users.noreply.github.com>

* update demo snapshot

* update snapshot

* update snapshot

---------

Signed-off-by: Laffery <49607541+Laffery@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-09-25 18:03:33 +08:00
lijianan
647eba0302 demo: fix Collapse demo (#55145) 2025-09-25 16:08:08 +08:00
afc163
6ca1cbed80 docs: Update README (#55128)
* docs: Update README

Signed-off-by: afc163 <afc163@gmail.com>

* Update badges and links in README-zh_CN.md

Signed-off-by: afc163 <afc163@gmail.com>

* Update README-zh_CN.md

Signed-off-by: afc163 <afc163@gmail.com>

* Clean up badge links in README.md

Removed outdated badge links from README.

Signed-off-by: afc163 <afc163@gmail.com>

* Apply suggestion from @afc163

Signed-off-by: afc163 <afc163@gmail.com>

* Apply suggestion from @afc163

Signed-off-by: afc163 <afc163@gmail.com>

* Update README.md

Signed-off-by: afc163 <afc163@gmail.com>

* Update README-zh_CN.md

Signed-off-by: afc163 <afc163@gmail.com>

* Update README.md

Signed-off-by: afc163 <afc163@gmail.com>

---------

Signed-off-by: afc163 <afc163@gmail.com>
2025-09-24 20:07:43 +08:00
LeiZhang
b59a1102f1 fix: handle maxCount negative value validation (#55129)
Co-authored-by: 路振凯 <l>
2025-09-24 03:02:44 +08:00
afc163
00b24f5be7 fix: Tour positioning when the target is a Table with fixed headers (#55124)
* bump rc-table

* refactor: replace table measure row td with th and update styles

* style: add important flag to table measure cell styles

* style: simplify table measure cell styles
2025-09-23 09:59:45 +08:00
thinkasany
625e034a32 chore: Enhanced hints for unused variables (#55113)
* chore: Enhanced hints for unused variables

* rm unused rules

* fix
2025-09-21 19:13:18 +08:00
thinkasany
b138cadf40 chore: turn on correctness.useHookAtTopLevel (#55110) 2025-09-21 13:26:25 +08:00
lijianan
cb0dd956ba chore: add namespace for Number api (#55107)
* chore: add namespace for Number api

* fix

* fix

* Update biome.json

Co-authored-by: thinkasany <480968828@qq.com>
Signed-off-by: lijianan <574980606@qq.com>

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-21 12:27:02 +08:00
thinkasany
594ee4d989 refactor: Use indexOf instead of findIndex for index lookup (#55106) 2025-09-21 11:57:32 +08:00
thinkasany
f1036be04f chore(biome): rm some rules that do not need to be changed (#55105) 2025-09-21 11:18:51 +08:00
thinkasany
030783f41b chore(biome): turn on style.useImportType (#55104) 2025-09-21 10:33:31 +08:00
17hz
9d07df9667 docs: showTime.defaultValue has deprecated (#54896)
* docs: showTime.defaultValue has deprecated

* docs: add deprecated showTime.defaultValue with proper format

Add deprecated showTime.defaultValue entries with strikethrough formatting
and migration notes to match auto-complete documentation format.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

* docs: update deprecation version to 5.27.3

Change showTime.defaultValue deprecation version from 4.24.0 to 5.27.3

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>

---------

Co-authored-by: Claude <noreply@anthropic.com>
2025-09-20 17:19:29 +08:00
thinkasany
b189e0ec97 fix(lint): react-web-api/no-leaked-interval (#55100)
* fix(lint): react-web-api/no-leaked-interval

* update snap

* fix
2025-09-20 15:30:18 +08:00
FatahChan
6562c20134 demo: add List drag sorting examples (#55077)
* docs: List drag sorting examples

* refactor: standardize React imports and use consistent import patterns

* fix: add null checks and remove optional chaining in drag sorting handlers

* Update components/list/demo/grid-drag-sorting.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>

* Update components/list/demo/grid-drag-sorting-handler.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>

* chore: add React import to list demo components

* fix: tests

* refactor: improve drag sorting accessibility by wrapping list items in semantic containers

* Update components/list/demo/drag-sorting-handler.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>

* Update components/list/demo/grid-drag-sorting.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>

* Update components/list/demo/drag-sorting.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>

* Update components/list/demo/grid-drag-sorting-handler.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>

* fix: remove itemkey prop from list items in drag-sorting demos

* test: skip drag sorting demos in list component tests

* fix: update drag-sorting aria-describedby IDs to be more semantic and consistent

* test: update DndLiveRegion IDs in list component snapshots

* test: skip drag sorting demos in list component tests

dnd ids produce difference ids in react 17 vs react 19, and fails the demo-extend as the snap is different

* refactor: update list drag sorting to use object items with unique keys

* update code style

* update code style

---------

Signed-off-by: FatahChan <ahmadfathallah89@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: lijianan <574980606@qq.com>
2025-09-19 05:55:38 +08:00
github-actions[bot]
74c26d895d chore: upgrade deps (#55080)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2025-09-19 02:15:52 +08:00
Jonathan Reimer
18e596b1f3 docs: add Linux Foundatuon Health Score badge to README (#55071)
Congrats! We have onboarded Ant Design to LFX Insights, the Linux Foundation's platform for monitoring the world's most critical open-source projects.

Signed-off-by: Jonathan Reimer <41432658+jonathimer@users.noreply.github.com>
2025-09-18 23:29:56 +08:00
github-actions[bot]
e3e7db9fd1 chore: upgrade deps (#55057)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2025-09-18 02:29:54 +08:00
dependabot[bot]
4d86c53505 chore: bump ora from 8.2.0 to 9.0.0 in the dev-dependencies group (#55040)
Bumps the dev-dependencies group with 1 update: [ora](https://github.com/sindresorhus/ora).


Updates `ora` from 8.2.0 to 9.0.0
- [Release notes](https://github.com/sindresorhus/ora/releases)
- [Commits](https://github.com/sindresorhus/ora/compare/v8.2.0...v9.0.0)

---
updated-dependencies:
- dependency-name: ora
  dependency-version: 9.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-17 20:46:43 +08:00
QdabuliuQ
fb7bbbea50 fix(Card): fix clearfix interference with flex/grid card layouts (#54974)
* style: fix clearfix interference with flex/grid card layouts

* style: modify css selector

* style: remove ant-card-body clearFix function
2025-09-17 18:39:25 +08:00
qixian
531ea91296 fix: add error handling for notifier in pre-publish script 2025-09-17 15:24:50 +08:00
qixian
e716aec310 chore: fix formatting in changelog for version 5.27.4 2025-09-17 14:26:41 +08:00
陈帅
55a628edf8 docs: add 5.27.4 changelog (#55023)
* docs: 更新 5.27.4 版本日志,添加多个修复说明

* docs: 更新 5.27.4 版本日志,添加修复按钮内边距受主题影响的问题

* chore: 更新版本号至 5.27.4

* Update CHANGELOG.en-US.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 陈帅 <qixian.cs@outlook.com>

* Update CHANGELOG.en-US.md

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: 陈帅 <qixian.cs@outlook.com>

* Update CHANGELOG.zh-CN.md

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: 陈帅 <qixian.cs@outlook.com>

* Update CHANGELOG.en-US.md

Signed-off-by: lijianan <574980606@qq.com>

* 更新 5.27.4 的发布日期为 2025-09-17,并修复 Table 相关问题

* 修复按钮在主题影响下的图标填充问题

---------

Signed-off-by: 陈帅 <qixian.cs@outlook.com>
Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: lijianan <574980606@qq.com>
2025-09-17 14:25:15 +08:00
Wanpan
90cacd5e45 chore: fix lint error for script dir (#55022)
* chore: fix lint error for script dir

* chore: update
2025-09-16 13:29:21 +08:00
Guo Yunhe
c172411eb4 fix(Button): icon-only button padding affected by theme (#54970) 2025-09-15 10:58:55 +08:00
叶枫
2e8f162ff7 site: stackblitz support zh registry (#54973) 2025-09-15 10:57:32 +08:00
Wanpan
209f4e88d0 chore: Add deprecated tips for DropDownProps (#55020)
* fix: Add deprecated tips for DropDownProps

* fix: update
2025-09-14 22:46:16 +08:00
lijianan
4bf3f72e09 demo: type definition improvement (#55017)
* demo: type definition improvement

* rm any type

---------

Co-authored-by: thinkasany <480968828@qq.com>
2025-09-14 18:12:02 +08:00
lijianan
6e72e7bfbe test: add removeAllListeners for imageTest (#55015)
* test: add try/catch for visual diff

* Update tests/shared/imageTest.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: lijianan <574980606@qq.com>

* update

* update

* update

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-09-14 18:08:55 +08:00
lijianan
21e88f1f05 refactor: use Node.ELEMENT_NODE replace number (#52163)
* refactor: use Node.ELEMENT_NODE replace number

* fix: fix

* fix: fix

* fix: fix

* Update setup.ts

Signed-off-by: lijianan <574980606@qq.com>

* update

---------

Signed-off-by: lijianan <574980606@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-09-14 18:02:44 +08:00
chimobi-justice
9daba47ce9 fix(typo): correct typo from 'palyType' to 'playType' (#55016) 2025-09-14 16:52:19 +08:00
lijianan
5e684e8e47 refactor optimization imageTest (#55014)
* test

* refactor imageTest

* update
2025-09-14 16:22:35 +08:00
renovate[bot]
569ef8025c chore(deps): update softprops/action-gh-release action to v2.3.3 (#55010)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-14 09:45:02 +08:00
renovate[bot]
2a2bd3c0a3 chore(deps): update dependency @blazediff/core to v1 (#55011)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-14 09:43:30 +08:00
thinkasany
181e327976 chore(dep): bump jsdom from 26 to 27 (#54998) 2025-09-14 01:20:49 +08:00
lijianan
1c4138d170 refactor(splliter): simplify the for loop (#54997) 2025-09-13 14:27:09 +08:00
thinkasany
9ba69f0010 chore(biome): turn off complexity.useOptionalChain (#54993) 2025-09-13 14:18:08 +08:00
Teimur Gasanov
1a2574aaeb test: use blazediff instead of pixelmatch (#54941) 2025-09-12 11:38:50 +08:00
lijianan
8af8de294b chore: add break (#54953) 2025-09-12 11:37:41 +08:00
二货爱吃白萝卜
c88004aca9 fix: Splitter min & max not working for init limit (#54939)
* chore: add debug demo

* fix: size logic

* chore: adjust empty check logic

* chore: tmp of init

* chore: clean up

* chore: add quick avg

* chore: adjust logic

* fix: isFinite logic

* Update components/splitter/SplitBar.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* Update components/splitter/SplitBar.tsx

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* test: coverage

* test: fix test

* chore: fix ts

---------

Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>
Co-authored-by: lijianan <574980606@qq.com>
2025-09-12 11:25:31 +08:00
github-actions[bot]
31fdae68d2 chore: upgrade deps (#54954)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2025-09-12 09:25:34 +08:00
Trần Quang Khánh
dbbdaf394c fix(wave): make wave effect work with tailwind disabled variant (#54933)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-09-09 23:24:21 +08:00
afc163
2e9842cae6 chore: Organize cursor content into agents md (#54930)
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2025-09-09 13:54:09 +08:00
lijianan
4bf930c5a5 docs: update dingding QR-code (#54924)
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-08 18:20:12 +08:00
lijianan
eec3e36eb9 type: improve type safety, rm any type (#54922) 2025-09-08 17:24:52 +08:00
lijianan
a703957ce3 site: img should not be draggable (#54911) 2025-09-08 11:46:43 +08:00
lijianan
69f3664cfe refactor: make isThenable more strict (#54916) 2025-09-07 23:27:29 +08:00
lijianan
1b76227780 demo: rm Chinese characters of demo (#54913)
* demo: rm Chinese characters of demo

* test: update snap
2025-09-07 17:08:20 +08:00
Stepan Svechnikov
637fc8069e docs(en-US ): icon FAQ (#54912)
There was a character 和 here, which was replaced by the word "and"

Signed-off-by: Stepan Svechnikov <36372315+Aemulatio@users.noreply.github.com>
2025-09-07 15:45:07 +08:00
afc163
7c68d79224 fix(Table): fix duplicated filter dropdowns and tooltips is shown when Table is sticky (#54910) 2025-09-07 10:53:03 +08:00
renovate[bot]
7599bbe319 chore(deps): update mcr.microsoft.com/devcontainers/typescript-node docker tag to v3 (#54909)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-07 01:07:03 +08:00
renovate[bot]
fffc12122d chore(deps): update dependency nwsapi to v2.2.22 (#54908)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-09-07 00:56:04 +08:00
afc163
8065093543 docs: improve react 19 compatibility info (#54898)
* docs: improve react 19 compatibility info

Signed-off-by: afc163 <afc163@gmail.com>

* Update v5-for-19.en-US.md

Signed-off-by: afc163 <afc163@gmail.com>

---------

Signed-off-by: afc163 <afc163@gmail.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-06 14:12:48 +08:00
afc163
c1a6a87285 fix: Table column align issue when scroll.x is true (#54899)
* fix: Table column align issue when scroll.x is true

* test: update snapshot

* test: update snapshot
2025-09-06 13:52:01 +08:00
Trần Quang Khánh
9628555adc fix(Input.Search): prevent hover color change for border and icon in disabled search button (#54892)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-09-05 23:32:08 +08:00
dependabot[bot]
750934d3e0 chore: bump actions/github-script from 7 to 8 (#54895)
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 8.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v7...v8)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-05 19:31:41 +08:00
afc163
6119e626c8 docs: add 5.27.3 changelog (#54886)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-09-05 14:13:53 +08:00
Tarun P
47f596cf1c fix(typography): correct margin when editable (#54848) (#54871)
Co-authored-by: afc163 <afc163@gmail.com>
2025-09-05 12:18:32 +08:00
EmilyyyLiu
d40799ad4b fix: Resolve style issues in RTL mode of Carousel components (#54868)
* fix: Resolve style issues in RTL mode of Carousel components

* feat: ArrowButton aria-label

* test: add test

* feat: delete prevCount, not need

* Update components/carousel/index.tsx

Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: 刘欢 <lh01217311@antgroup.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-09-05 12:17:25 +08:00
ug
b2ad4f59a7 fix: The "customize theme" page "motionBase" description is empty. (#54874)
* fix:The "customize theme" page "motionBase" description is empty.

* Update components/theme/interface/seeds.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: ug <62086147+765477020@users.noreply.github.com>

---------

Signed-off-by: ug <62086147+765477020@users.noreply.github.com>
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-09-04 22:49:23 +08:00
二货爱吃白萝卜
b76826f426 fix: Dropdown onOpenChange closure issue (#54880)
* test: test driven

* test: test driven
2025-09-04 22:32:31 +08:00
ug
77d02d19d6 docs: add preset colors token (#54878)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-09-04 21:01:52 +08:00
ug
4d295e20db fix(Input.OTP): Continuous deletion is not allowed. (#54850)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-09-04 09:43:54 +08:00
dependabot[bot]
71b53a0db3 chore: bump @npmcli/run-script in the dev-dependencies group (#54865)
Bumps the dev-dependencies group with 1 update: [@npmcli/run-script](https://github.com/npm/run-script).


Updates `@npmcli/run-script` from 9.1.0 to 10.0.0
- [Release notes](https://github.com/npm/run-script/releases)
- [Changelog](https://github.com/npm/run-script/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/run-script/compare/v9.1.0...v10.0.0)

---
updated-dependencies:
- dependency-name: "@npmcli/run-script"
  dependency-version: 10.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: dev-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-04 08:06:15 +08:00
𝑾𝒖𝒙𝒉
78e015b313 fix: Table issues by upgrade rc-table to 7.52.5 (#54824)
Co-authored-by: afc163 <afc163@gmail.com>
2025-09-03 20:37:38 +08:00
Guo Yunhe
23a2b5ec96 fix(Button): round padding (#54845) 2025-09-02 17:55:40 +08:00
二货爱吃白萝卜
1563f59f1b chore: adjust site config (#54844) 2025-09-02 17:54:04 +08:00
Nicolò Zandarin
a1836c4ec6 fix(locale): added missing Italian translations for QRCode & ColorPicker components (#54842)
* fix(locale): added missing Italian translations for QRCode & ColorPicker components

* Update components/locale/it_IT.ts

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: Nicolò Zandarin <71180446+nikzanda@users.noreply.github.com>

---------

Signed-off-by: Nicolò Zandarin <71180446+nikzanda@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-09-02 16:35:31 +08:00
MrWangJustToDo
d6f26ee09f fix(Pagination): component style with simple and small size props (#54837)
Co-authored-by: afc163 <afc163@gmail.com>
2025-09-02 15:51:20 +08:00
ug
4d4621a03f update (#54838)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-09-02 12:29:14 +08:00
xrkffgg
38095a7641 docs: add changelog 5.27.2 (#54836)
* docs: add changelog 5.27.2

* Update CHANGELOG.en-US.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

* Update CHANGELOG.zh-CN.md

Co-authored-by: thinkasany <480968828@qq.com>
Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

* Update CHANGELOG.en-US.md

Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

* Update CHANGELOG.en-US.md

Co-authored-by: 遇见同学 <1875694521@qq.com>
Signed-off-by: thinkasany <480968828@qq.com>

* Update CHANGELOG.zh-CN.md

Co-authored-by: 遇见同学 <1875694521@qq.com>
Signed-off-by: thinkasany <480968828@qq.com>

* Update CHANGELOG.zh-CN.md

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

* Update CHANGELOG.en-US.md

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

---------

Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>
Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: 遇见同学 <1875694521@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-09-02 11:55:47 +08:00
thinkasany
7dc77c9087 chore(biome): skip *.tmp (#54825) 2025-09-01 12:15:04 +08:00
𝑾𝒖𝒙𝒉
507985619f docs: Prevent Chrome from translating demo content (#54811) 2025-09-01 10:13:04 +08:00
lijianan
88e46f6993 docs: refactor inline style with cssinjs (#54817) 2025-09-01 10:10:38 +08:00
𝑾𝒖𝒙𝒉
2b1e677ae7 fix(Table): resolve loading/empty state overlap (#54606)
* test: update unit test

* fix(Table): resolve loading/empty state overlap

* fixup! test: update unit test

* chore: update snap

* chore: update

* chore: update comment

* chore: use memo instead

---------

Co-authored-by: 二货机器人 <smith3816@gmail.com>
2025-08-29 15:12:04 +08:00
afc163
47307bec98 fix: Button token.paddingInline not working when shape="round" (#54787) 2025-08-28 23:04:10 +08:00
ug
05a35a6919 site: Modal Demo Page error (#54795)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-08-28 21:42:39 +08:00
Trần Quang Khánh
2ba4e87fca fix(Tabs): tabs remove icon not align centered vertically (#54794)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-08-28 20:28:53 +08:00
afc163
754d8bb058 Revert "fix(Button): paddingInline token not working (#54775)" (#54778)
This reverts commit 95730ba90f.

Co-authored-by: thinkasany <480968828@qq.com>
2025-08-28 14:22:41 +08:00
afc163
79c79e9109 test: update snapshot (#54780) 2025-08-28 13:49:22 +08:00
Guo Yunhe
95730ba90f fix(Button): paddingInline token not working (#54775) 2025-08-28 12:32:38 +08:00
Guo Yunhe
23b6737ad7 fix(Typography): linkHoverDecoration (#54763)
Co-authored-by: lijianan <574980606@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-08-27 17:07:57 +08:00
ug
465567f66d fix: Modal Demo Page error (#54767)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-08-27 17:01:33 +08:00
lijianan
8e54fbd4fe fix: add miss dep for useMemo (#54766) 2025-08-27 16:07:53 +08:00
thinkasany
5b6cc4c987 chore: bump jest to 30.1.0 (#54759)
* chore: bump jest to 30.1.0

* update
2025-08-27 15:39:48 +08:00
David Hsing
c20fae6695 fix: badge support text props as number 0 (#54747)
Co-authored-by: thinkasany <480968828@qq.com>
2025-08-27 11:53:02 +08:00
lijianan
95ade639c9 docs: adjust docs order (#54754) 2025-08-26 17:12:50 +08:00
遇见同学
2a66972cf9 fix: revert copybtn getPopupContainer (#54752) 2025-08-26 10:52:10 +08:00
Alexis Hope
2b7a87b14e docs(slider): improve en minor gramma (#54209)
* docs: en slider review

* docs(slider): en accessibility

* Update components/slider/index.en-US.md

Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-08-25 22:39:33 +08:00
lijianan
1ab5e38e70 Merge branch 'master' into chore/scripts 2025-08-24 15:31:56 +08:00
Trần Quang Khánh
104394c740 fix(locale): add missing vietnamese translation for color picker, text and qrcode (#54748)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-08-24 11:15:25 +08:00
ug
ddd525c789 fix(Radio) : Radio.Group display shows jagged edges and left border of the first element in the new row overflows. (#54661)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-08-22 17:35:49 +08:00
doandevhere
c453b01a4b fix(button): button href disabled accessibility not correct (#54738) 2025-08-22 16:36:08 +08:00
遇见同学
33d17cd831 fix: DirectoryTree hover color style (#54725) 2025-08-22 16:31:51 +08:00
Eduardo Javis
63a1dc3e77 docs(Table): update Table component doc (#54731)
* docs(Table): 更新Table组件文档

* docs(Table): 更新expandedRowOffset属性的废弃说明

---------

Co-authored-by: 尹帮林 <ybl02343999@antgroup.com>
2025-08-21 17:00:41 +08:00
Wanpan
07de78d3cf docs: update Collapse SemanticPreview (#54724) 2025-08-20 16:04:43 +08:00
Sébastien Béal
8c9bf94dd8 chore(qrcode): use direct icon import to enable tree shaking (#54719) 2025-08-20 10:04:31 +08:00
강주혁(Juhyeok Kang)
08f2fc31ad docs: fix typo in paste code snippet version attribute (#54718) 2025-08-19 23:46:41 +08:00
二货爱吃白萝卜
178d7c721a docs: changelog of 5.27.1 (#54717)
* docs: changelog of 5.27.1

* Update CHANGELOG.en-US.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* Update CHANGELOG.en-US.md

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* docs: update desc

---------

Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-08-19 17:58:42 +08:00
二货爱吃白萝卜
7b930a2fe8 fix: Nest form with noStyle context passing (#54715)
* fix: Nest form with noStyle context passing

* Update components/form/__tests__/index.test.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

* Update components/form/__tests__/index.test.tsx

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>

---------

Signed-off-by: 二货爱吃白萝卜 <smith3816@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-08-19 17:14:49 +08:00
QdabuliuQ
90df266491 style: add will-change to fixed table cell shadow (#54713) 2025-08-19 15:53:57 +08:00
Copilot
a267f79f08 fix(Collapse): Add pointer cursor to expand icon in header collapsible mode (#54706)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-08-18 14:08:08 +08:00
ug
0653add28f docs(theme): Add "size" series variables description (#54703)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
2025-08-16 23:21:09 +08:00
遇见同学
40a0f30b6f chore: bump biome@2.2.0 (#54692) 2025-08-15 16:54:11 +08:00
Guo Yunhe
ce2b4fd50c fix(Pagination): simple mode button and input size (#54652)
Co-authored-by: afc163 <afc163@gmail.com>
2025-08-15 14:36:18 +08:00
thinkasany
0aa7561b00 chore(biome): turn off suspicious. noTsIgnore (#54688) 2025-08-15 14:00:12 +08:00
EmilyyyLiu
57d7571b29 fix: theme editor inherit style (#54687)
Co-authored-by: 刘欢 <lh01217311@antgroup.com>
2025-08-15 13:58:51 +08:00
thinkasany
5e7f63fb30 chore: fix biome error (#54682)
* chore: fix biome error

* fix

* fix again

* revert
2025-08-14 22:52:15 +08:00
codingories
ba42d6842d docs(popover): remove redundant desc (#54671)
* docs: remove redundant align description in Tooltip API

* Update components/tooltip/shared/sharedProps.zh-CN.md

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Signed-off-by: codingories <34835258+codingories@users.noreply.github.com>

* docs: remove redundant align description in Tooltip API

* fix: recover format problem

* fix: change back wrong change

---------

Signed-off-by: codingories <34835258+codingories@users.noreply.github.com>
Co-authored-by: codingories <junjie.zhu@r2.ai>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-08-13 18:01:41 +08:00
遇见同学
7db17b3eaa test: add isPrimitive test (#54666)
* test: add isPrimitive test

* feat: update test

* update test
2025-08-13 09:44:21 +08:00
遇见同学
33691cc525 perf: code optimization and add test (#54665)
* perf: code optimization and add test

* Update components/_util/wave/util.ts

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: 遇见同学 <1875694521@qq.com>

* feat: update test

---------

Signed-off-by: 遇见同学 <1875694521@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-08-13 09:43:45 +08:00
dependabot[bot]
c6b1ad0851 chore: bump actions/checkout from 4 to 5 (#54668)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-13 09:01:57 +08:00
Ali Mahallati
eecf04371a fix(direction): typo in iran cities (#54667)
Signed-off-by: Ali Mahallati <mahallati81@gmail.com>
2025-08-12 21:28:12 +08:00
Wanpan
9be96b92a7 docs: Optimize the description of the color attribute (#54658)
* docs: Optimize the description of the color attribute

* docs: update

* Update components/tooltip/index.zh-CN.md

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-08-12 15:41:03 +08:00
doandevhere
5c61993356 fix(date-picker): missing vietnam translation (#54644) 2025-08-12 14:41:40 +08:00
inottn
b7c76d0a46 fix: correct the JSDoc description of WaveConfig (#54647) 2025-08-11 17:24:55 +08:00
MadCcc
52a701b497 chore: add inquirer to skip CI 2025-08-11 17:04:37 +08:00
MadCcc
ca4882e0f2 docs: changelog 5.27.0 (#54643)
* docs: changelog 5.27.0

* chore: fix typo

* Update CHANGELOG.zh-CN.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: thinkasany <480968828@qq.com>

* docs: update

* chore: update

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-08-11 15:40:40 +08:00
二货爱吃白萝卜
ed0a250805 docs: update Table doc (#54642)
* docs: update Table doc

* docs: update Table doc
2025-08-11 14:50:10 +08:00
github-actions[bot]
570efda7eb chore: auto merge branches (#54641)
chore: sync feature into master
2025-08-11 02:56:21 +00:00
Guo Yunhe
1f229dc7b8 feat(FloatButton): support backTopIcon global config (#54493) 2025-08-11 10:34:50 +08:00
Trần Quang Khánh
89bbc56213 fix(locale): add missing transfer component interalization text of vi-VN.ts (#54638)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-08-10 15:56:20 +08:00
Trần Quang Khánh
c0b427e47f fix: Tabs ref prop should work (#54636)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
2025-08-10 00:34:30 +08:00
Jiyur
ed6d440437 style(DatePicker): avoid important syntax in week panel cell inner style (#54634)
Co-authored-by: Khanh Tran <quangkhanhdeveloper@gmail.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-08-09 22:49:41 +08:00
Guo Yunhe
c2ec447866 feat(Button): add iconGap design token (#54629) 2025-08-09 22:17:46 +08:00
Guo Yunhe
2cc9103149 feat(Empty): support image global config (#54502) 2025-08-08 11:01:11 +08:00
github-actions[bot]
70f79ec0ad chore: auto merge branches (#54625)
chore: sync master into feature
2025-08-08 02:14:00 +00:00
afc163
613aad6a5d refactor: remove unnecessary object spread syntax for genFocusOutline calls (#54622)
Co-authored-by: lijianan <574980606@qq.com>
2025-08-08 08:34:25 +08:00
renovate[bot]
c95a08e612 chore(deps): update dependency nwsapi to v2.2.21 (#54488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-08-07 23:12:02 +08:00
afc163
7cea3bb0b4 chore: remove console.log (#54623) 2025-08-07 23:07:37 +08:00
ug
3fbcd6d080 feat(theme): Add new CSS variables for the "size" series (#54621) 2025-08-07 22:50:06 +08:00
legend80s
6de357d8f9 docs: improve icon search expierence (#54617) 2025-08-07 21:41:30 +08:00
叶枫
feaed51f09 fix: form layout style (#54611) 2025-08-07 21:36:46 +08:00
Łukasz Komoszyński
0b5a36f330 fix: hover/active text color of filled button with href (#54614) 2025-08-07 21:34:48 +08:00
诸岳
e59c2a77f7 fix: Modal and Drawer panelRef prop should work (#54619) 2025-08-07 17:44:07 +08:00
EmilyyyLiu
3e3897e09e feat: Table check header props (#54600)
* feat: add getHeaderCheckboxProps into rowSelection

* feat: Adjust the order of hearderProps

* test: update snap

* feat: add tests and modify getHeaderCheckboxProps ts

* docs: add describe

* feat: deconstruct customCheckboxProps

* test: restore snap

* test: restore snap

* test: test error

* feat: getHeaderCheckboxProps -> getTitleCheckboxProps

* feat: GetTitleCheckboxProps does not pass parameters

* docs: getTitleCheckboxProps

* test: delete one

* test: change tests

---------

Co-authored-by: 刘欢 <lh01217311@antgroup.com>
2025-08-07 16:57:20 +08:00
叶枫
9d46bd7e45 fix: formatter demo (#54615)
* fix: formatter demo

* fix: formatter demo
2025-08-07 11:42:04 +08:00
叶枫
2a30698f14 site: add stackblitz node (#54604) 2025-08-06 22:28:25 +08:00
dependabot[bot]
2597ab6b97 chore: bump actions/download-artifact from 4 to 5 (#54612)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-06 21:06:55 +08:00
ug
81a86966d2 fix(Space.Compact):Border cropping issue (#54596)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-08-05 16:00:23 +08:00
𝑾𝒖𝒙𝒉
5f75711a80 fix(InputNumber): fix suffix shift on hover in readonly state (#54585) 2025-08-05 11:06:32 +08:00
ug
f5f8967148 fix<Input.OTP>: wrong caret color (#54588)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-08-05 10:24:04 +08:00
github-actions[bot]
9a5d620dc5 chore: auto merge branches (#54591)
chore: merge master to feature
2025-08-04 16:42:03 +00:00
afc163
46c9c93773 test: upgrade jest to v30 (#54576) 2025-08-05 00:13:52 +08:00
github-actions[bot]
3f94d76ba9 chore: auto merge branches (#54590)
chore: master merge feature
2025-08-04 13:30:54 +00:00
达峰的夏天
8d36927449 Merge pull request #54589 from hustcc/patch-2
docs: update weavefox link
2025-08-04 20:34:15 +08:00
hustcc
c2e4c0dc47 docs: update weavefox link
Signed-off-by: hustcc <i@hust.cc>
2025-08-04 20:31:08 +08:00
二货爱吃白萝卜
7c9a8fabee test: fix dist test shard (#54584) 2025-08-04 16:49:51 +08:00
二货爱吃白萝卜
618fac974b chore: fix convert ts 2 js logic (#54574) 2025-08-04 14:20:39 +08:00
afc163
e82a7fae8c chore: fix Split eslint error (#54578)
* style: 添加 eslint 忽略注释避免 no-leaked-event-listener 警告

* docs: 补充中文文档句号并同步英文格式
2025-08-04 14:17:54 +08:00
Fane
bb8187416b docs: select Q&A (#54560) 2025-08-04 10:50:11 +08:00
EmilyyyLiu
260016c2cc feat: Adapt text color based on Tooltip color (#54552)
* feat: Adapt text color based on Tooltip.color

* feat: add default textcolor

* feat: Adjust the range of using white

* feat: Adjust color algorithm

* test: update snap

---------

Co-authored-by: 刘欢 <lh01217311@antgroup.com>
2025-08-04 10:40:53 +08:00
Goat
4eab7c7140 chore: code optimization (#54569) 2025-08-03 21:11:37 +08:00
Yingtao Mo
06306cd37f fix: Adjusted the Carousel dot background to prevent white gaps during animation (#54529) 2025-08-01 23:26:39 +08:00
github-actions[bot]
86385a2f4d chore: auto merge branches (#54556)
chore: sync master into feature
2025-08-01 10:02:59 +00:00
thinkasany
416c76997f chore: sync master into feature 2025-08-01 17:43:33 +08:00
EmilyyyLiu
953a8c0278 feat: add ContextIsolator component to Select (#54544)
* fix: add ContextIsolator component to Select

* feat: add ContextIsolator to mergedPopupRender

* feat: useMemo

* test: add tests

* fix: Delete the 'ContextIsolator' at the top level of the component

* feat: add usePopupRender

* test: change tests

---------

Co-authored-by: 刘欢 <lh01217311@antgroup.com>
2025-08-01 17:27:43 +08:00
dependabot[bot]
ff5218840f chore: bump the dev-dependencies group across 1 directory with 2 updates (#54551)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-08-01 09:58:17 +08:00
遇见同学
be8b735b46 fix: typography-demo-ellipsis-controlled shows error when drag slider faster (#54449) 2025-07-31 22:15:04 +08:00
遇见同学
3403561694 perf: use strict conditions (#54549) 2025-07-31 21:05:39 +08:00
GeoDaoyu
d9f8a84062 docs: table pagination position (#54541) 2025-07-31 18:44:21 +08:00
gregor-mueller
48eb543646 fix(Menu): Set correct value type for MenuItem data attributes (#54539)
* fix(Menu): Set correct value type for MenuItem data attributes

* Update components/menu/interface.ts

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: thinkasany <480968828@qq.com>

* change the type to `unknown` to support anything

* Update components/menu/interface.ts

Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-07-31 16:17:42 +08:00
lijianan
d56b3ec554 type: adding missed generics with ShowUploadListInterface (#54540) 2025-07-31 00:36:36 +08:00
EmilyyyLiu
44369acc72 docs: Modify the description of labelInValue (#54536)
Co-authored-by: 刘欢 <lh01217311@antgroup.com>
2025-07-30 19:18:39 +08:00
遇见同学
b0a3a5b485 fix: use rc useLayoutEffect to support server no warning (#54517)
* fix: add useIsomorphicLayoutEffect to support server no warning

* fix: add useIsomorphicLayoutEffect to support server no warning

* feat: use rc useLayoutEffect

* feat: SplitBar use rc useLayoutEffect

* chore: update import order
2025-07-30 11:14:08 +08:00
lijianan
4d1a6aff98 docs: add Localization log (#54522) 2025-07-30 10:07:08 +08:00
github-actions[bot]
36c93d567b chore: upgrade deps (#54525)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2025-07-30 02:16:25 +08:00
github-actions[bot]
bb61567776 chore: auto merge branches (#54523)
chore: merge master into feature
2025-07-29 17:29:48 +00:00
lijianan
3d6eaabc26 chore: fix ci biome lint error (#54521) 2025-07-30 00:19:02 +08:00
Deniz Satır
7f47601b88 feat(locale): add missing collapse of tr_TR (#54515)
Signed-off-by: Deniz Satır <45640934+deniznehlyadyuk@users.noreply.github.com>
2025-07-29 20:54:21 +08:00
lijianan
36b706bdc8 docs: update changelog info (#54510) 2025-07-29 16:22:45 +08:00
github-actions[bot]
a15aa44c4a chore: auto merge branches (#54508)
chore: merge master into feature
2025-07-29 08:15:54 +00:00
lijianan
b06330f8c8 site: code optimization (#54509) 2025-07-29 16:09:24 +08:00
lijianan
4138850801 Merge branch master into master-merge-feature 2025-07-29 15:53:15 +08:00
二货爱吃白萝卜
70b9f45404 test: rm useless test (#54513) 2025-07-29 15:50:52 +08:00
lijianan
f71752f0a7 chore: merge master into feature 2025-07-29 02:36:45 +08:00
github-actions[bot]
31c37208d5 chore: upgrade deps (#54507)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2025-07-29 02:34:09 +08:00
陈帅
a614e8b45e docs: add 5.26.7 changelog (#54486)
* docs: add 5.26.7 changelog

* chore: bump version to 5.26.7 in package.json

* Update CHANGELOG.en-US.md

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: 陈帅 <qixian.cs@outlook.com>

* Update CHANGELOG.zh-CN.md

Co-authored-by: lijianan <574980606@qq.com>
Signed-off-by: 陈帅 <qixian.cs@outlook.com>

* Update CHANGELOG.en-US.md

Signed-off-by: 陈帅 <qixian.cs@outlook.com>

* Update CHANGELOG.zh-CN.md

Signed-off-by: 陈帅 <qixian.cs@outlook.com>

---------

Signed-off-by: 陈帅 <qixian.cs@outlook.com>
Co-authored-by: lijianan <574980606@qq.com>
2025-07-28 22:26:01 +08:00
lijianan
288fe13425 site: fix palette name value (#54503) 2025-07-28 16:38:50 +08:00
qinware
1cf55b567b docs: Add AtomUI library (#54319)
Co-authored-by: chinboy <chinware@163.com>
2025-07-28 16:26:12 +08:00
lijianan
4022993143 site: translate chinese desc to english desc (#54494) 2025-07-28 16:17:34 +08:00
Guo Yunhe
b883612670 docs: support hide layout param (#54398) 2025-07-28 15:40:21 +08:00
smallbun
e20ca2c169 type: update TabPaneProps type (#54482)
* Update TabPane.ts

Signed-off-by: smallbun <30397655+leshalv@users.noreply.github.com>

* Update TabPane.ts

* Update index.tsx

---------

Signed-off-by: smallbun <30397655+leshalv@users.noreply.github.com>
Co-authored-by: lijianan <574980606@qq.com>
2025-07-27 19:33:32 +08:00
renovate[bot]
0109f3f186 chore(deps): update dependency @antfu/eslint-config to v5 (#54489)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-27 12:42:31 +08:00
renovate[bot]
2d0f484700 chore(deps): update dependency cross-env to v10 (#54490)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-27 12:42:07 +08:00
Guo Yunhe
4d3ff76a54 feat(Upload): support customRequest global config (#54474)
* feat(Upload): support customRequest global config

* Update components/config-provider/context.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: thinkasany <480968828@qq.com>

---------

Signed-off-by: thinkasany <480968828@qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-07-25 22:02:36 +08:00
lijianan
ca06fb41c5 demo: update the css logical properties (#54475) 2025-07-25 18:19:37 +08:00
Hwansoo Kim
bc66f1d18c fix(Card): update the type of tabBarExtraContent in Card component (#54470) 2025-07-25 18:14:39 +08:00
Guo Yunhe
b3ae5670e7 feat(Button): support shape global config (#54463) 2025-07-25 16:44:37 +08:00
𝑾𝒖𝒙𝒉
8379c40bc1 feat(tabs):Support for the middle mouse button in editable mode (#54462) 2025-07-25 11:02:45 +08:00
github-actions[bot]
c02424d21b chore: auto merge branches (#54461)
chore: merge master into feature
2025-07-25 02:38:20 +00:00
afc163
74b3270f6d docs: fix icon align issue in right header (#54460) 2025-07-25 09:52:26 +08:00
afc163
30fd3fd209 docs: remove auto follow system theme for site (#54450)
* fix: remove auto follow system theme for site (stop using prefers-color-scheme)\n\n> Submitted by Cursor

* feat: add dark/light/auto theme mode with localStorage persistence\n\n- Add auto mode that follows system theme\n- Implement theme priority: URL Query > Local Storage > Site (Memory)\n- Add localStorage persistence for theme preference\n- Update theme switch UI with auto option\n- Add internationalization support for auto mode\n\n> Submitted by Cursor

* chore: remove unused app.theme.switch.default text\n\n> Submitted by Cursor

* fix: only allow ?theme=light|dark in url, auto only from localStorage\n\n- Ignore ?theme=auto in url\n- Only persist light/dark to url, auto only in localStorage\n\n> Submitted by Cursor

* chore: use SyncOutlined for auto theme switch icon\n\n- Replace MonitorOutlined with SyncOutlined for better UX\n- Remove debug console.log\n\n> Submitted by Cursor

* refactor: simplify theme resolution and URL param handling

* fix: remove dead code for auto color theme handling

* style: format conditional blocks for consistency
2025-07-25 03:37:11 +08:00
ug
596ebb01d0 perf<Result>: Reduce the size of the status icons (#54455)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-07-24 23:36:36 +08:00
lijianan
ff2c15e410 site: fix color2Rgba result (#54451) 2025-07-24 18:55:15 +08:00
遇见同学
a23b2c082f perf: delete unnecessary calculations (#54443) 2025-07-22 22:29:55 +08:00
ug
3abd63c432 docs: Add change-log link in component page (#54433)
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-07-22 10:43:32 +08:00
afc163
eee7784a63 docs: correct changelog contributor username from salihyavuz to msyavuz (#54437) 2025-07-22 10:07:48 +08:00
github-actions[bot]
2f0e80ccb8 chore: upgrade deps (#54435)
Co-authored-by: afc163 <507615+afc163@users.noreply.github.com>
2025-07-22 02:40:22 +08:00
hustcc
ec40a40dc0 chore: add product weavefox's link (#54432)
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: 逍为 <xiaowei.wzw@antgroup.com>
2025-07-21 17:14:39 +08:00
lijianan
13555bfa4f site: fix site style issue (#54247)
Co-authored-by: afc163 <afc163@gmail.com>
2025-07-21 13:31:37 +08:00
lijianan
2c38b8430a chore: Code style optimization (#54425) 2025-07-21 10:49:46 +08:00
github-actions[bot]
61ebc35d53 chore: auto merge branches (#54423)
chore: sync master into feature
2025-07-20 10:02:12 +00:00
afc163
b744b9cbda chore: bump version to 5.26.6 (#54422) 2025-07-20 16:40:01 +08:00
QdabuliuQ
e9f6ec41db fix[Mentions]: fix overlap of clear and feedback icons in Mentions (#54390)
close #54389
2025-07-20 16:10:45 +08:00
Fane
00ff5a1783 docs: add tips of icons and static methods of message, Modal and notification (#54392)
Co-authored-by: afc163 <afc163@gmail.com>
2025-07-20 15:36:05 +08:00
doandevhere
cc92210f63 fix(Avatar): do not apply font size token (#54187) 2025-07-18 17:17:40 +08:00
一步
7083e3db7c docs: date-picker components demo error (#54404)
* docs: date-picker components demo error

Signed-off-by: 一步 <tiandaochouqinyn@163.com>

* Apply suggestion from @thinkasany

Co-authored-by: thinkasany <480968828@qq.com>
Signed-off-by: afc163 <afc163@gmail.com>

* Apply suggestion from @thinkasany

Co-authored-by: thinkasany <480968828@qq.com>
Signed-off-by: afc163 <afc163@gmail.com>

* test: update snap

---------

Signed-off-by: 一步 <tiandaochouqinyn@163.com>
Signed-off-by: afc163 <afc163@gmail.com>
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-07-18 07:47:04 +08:00
遇见同学
9fa56115c0 fix: Input variant=underlined use activeBorderColor (#54409) 2025-07-17 23:37:51 +08:00
ug
a2b6a14d8d docs<Anchor>:add the :target cannot trigger the FAQ. (#54397)
Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: liuqiang <qiang.liu@xinjifamily.com>
2025-07-17 22:53:14 +08:00
Guo Yunhe
e9e5011104 fix(InputNumber): fontSizeSM and fontSizeLG not working (#54396) 2025-07-17 22:51:14 +08:00
Copilot
05af953876 Fix DatePicker month picker disabledDate bug in documentation demo (#54403)
* Initial plan

* Fix DatePicker month picker disabledDate bug by separating day and month logic

Co-authored-by: zombieJ <5378891+zombieJ@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: zombieJ <5378891+zombieJ@users.noreply.github.com>
2025-07-17 13:47:22 +08:00
github-actions[bot]
402a9a36cd chore: auto merge branches (#54400)
chore: sync master into feature
2025-07-17 03:40:50 +00:00
𝑾𝒖𝒙𝒉
ef8816a59b fix: Flex children is now optional instead of required. (#54399) 2025-07-17 10:51:13 +08:00
Mehmet Salih Yavuz
7e45da92b8 fix(Menu): Allow data attributes for menu items (#54393)
* fix(Menu): Allow data attributes for menu items

* fix: add number type
2025-07-16 19:10:52 +08:00
leo
9e7414c042 test: update Affix test case (#54395) 2025-07-16 11:48:34 +08:00
xrkffgg
c0368b252d docs: add changelog 5.26.5 (#54387)
* docs: add changelog 5.26.5

* docs: update

* Update CHANGELOG.zh-CN.md

Co-authored-by: thinkasany <480968828@qq.com>
Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

* Update CHANGELOG.en-US.md

Co-authored-by: thinkasany <480968828@qq.com>
Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>

---------

Signed-off-by: xrkffgg <xrkffgg@vip.qq.com>
Co-authored-by: thinkasany <480968828@qq.com>
2025-07-15 11:31:58 +08:00
遇见同学
ddc17f68dd chore: update authors list (#54388) 2025-07-14 22:33:08 +08:00
broBinChen
1888b500a8 chore: resolve non-null assertion logic error in useLocale hook (#54384)
Co-authored-by: xiaobin <xiaobin_chen@fzzixun.com>
2025-07-14 13:24:32 +08:00
broBinChen
78814b0f4d fix: correct SiteState type property name in GlobalLayout (#54381)
Co-authored-by: xiaobin <xiaobin_chen@fzzixun.com>
2025-07-14 11:29:40 +08:00
github-actions[bot]
06ef05d7da chore: auto merge branches (#54374)
chore: merge master into feature
2025-07-13 04:46:28 +00:00
kiner-tang(星河)
14af06c614 docs: opt demo (#54373) 2025-07-13 12:02:40 +08:00
renovate[bot]
103a6dbaf5 chore(deps): update mcr.microsoft.com/devcontainers/typescript-node docker tag to v2 (#54372)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-07-13 11:13:00 +08:00
遇见同学
00033edc96 fix(useClosable): closeIcon props not correctly passed through (#54370) 2025-07-12 22:16:10 +08:00
遇见同学
9928de92dd chore: openMotion use useMemo (#54369)
* chore: openMotion use useMemo

* chore: change openMotion type
2025-07-12 11:39:08 +08:00
QdabuliuQ
bf37b20527 feat[input.password]: Input.Password support suffix property (#54342) 2025-07-12 10:36:46 +08:00
WwwHhhYran
a89e4d52ad fix(float-button): remove bottom border for float btn when placement is horizontal (#54261)
Co-authored-by: yiran <douchen.dc@alibaba-inc.com>
2025-07-11 23:16:27 +08:00
lijianan
3ad8019dc9 perf: reduce a little it bundle size (#54352) 2025-07-11 23:13:31 +08:00
broBinChen
a727f80a04 fix: fix toggle theme switch unable to turn off in docs (#54356)
Co-authored-by: xiaobin <xiaobin_chen@fzzixun.com>
2025-07-11 14:24:40 +08:00
github-actions[bot]
6e9e879a68 chore: auto merge branches (#54351)
chore: merge master into feature
2025-07-10 18:24:58 +00:00
lijianan
8455ebbc1f Merge branch master into master-merge-feature 2025-07-11 01:56:32 +08:00
二货爱吃白萝卜
4abd721eaf fix: Modal responsive width (#54349) 2025-07-10 17:52:27 +08:00
诸岳
84b28b6822 fix(notification): style should be correct when description is null (#54344) 2025-07-10 11:35:47 +08:00
QdabuliuQ
ef4fac1306 fix: Fixed the issue that splitter-mask was not hidden correctly in some scenes
* fix[Splitter]:  ant-splitter-mask should be removed when drag end

* refactor: modify useEffect and remove redundant duplicate test cases

* fix: update

---------

Co-authored-by: zhengjihao <zhengjihao@kkgroup.cn>
Co-authored-by: Wanpan <wanpan96@163.com>
2025-07-09 17:52:24 +08:00
lijianan
aecff4355a site: update site locales (#54340) 2025-07-09 17:29:35 +08:00
thinkasany
aba620223b chore: Update verify-files-modify.yml (#54339) 2025-07-09 15:48:04 +08:00
𝑾𝒖𝒙𝒉
0fba5f81a8 docs(tag): Improve document description (#54330)
* docs: update icon property documentation for CheckableTag to reflect version support

* Update components/tag/demo/icon.md

Co-authored-by: afc163 <afc163@gmail.com>
Signed-off-by: 𝑾𝒖𝒙𝒉 <wxh16144@qq.com>

* chore: update

---------

Signed-off-by: 𝑾𝒖𝒙𝒉 <wxh16144@qq.com>
Co-authored-by: afc163 <afc163@gmail.com>
2025-07-09 10:24:21 +08:00
afc163
107b4bed34 chore: Update verify-files-modify.yml (#54332) 2025-07-08 17:44:01 +08:00
afc163
69bda58475 chore: Update verify-files-modify.yml (#54327)
Signed-off-by: afc163 <afc163@gmail.com>
2025-07-08 13:34:06 +08:00
Wanpan
9a558f841e chore: MenuProps add activeKey in Dropdown (#54314) 2025-07-07 19:03:40 +08:00
Peach
c8069eac4e docs: changelog for 5.26.4 (#54307)
* docs: changelog for 5.26.4

* chore: bump version to 5.26.4

* docs: update changelog
2025-07-07 14:14:17 +08:00
QdabuliuQ
a6b5c0f28c feat[Tag.CheckableTag]: Tag.CheckableTag supports icon property (#54298)
* feat[Tag.CheckableTag]: CheckableTag support icon

* chore: commit snapshot files and update version number

* chore: modify test and md files

* chore: modify test and md files

---------

Co-authored-by: thinkasany <480968828@qq.com>
2025-07-07 11:34:59 +08:00
aojunhao123
0c901c7f0c fix: prefer using the name passed in the FormItemContext (#54206)
* fix: prefer using the name passed in the FormContext

* update snapshot

* update

* update

* update

* udpate test case

* convert formitem name to html attr

* update
2025-07-07 11:28:47 +08:00
github-actions[bot]
893507f87e chore: auto merge branches (#54304)
chore: merge master into feature
2025-07-06 14:53:40 +00:00
遇见同学
ad0df59020 docs: emoji compatible (#54303) 2025-07-06 22:14:58 +08:00
afc163
07a891388a chore: remove unused fonts style (#54293) 2025-07-04 16:20:25 +08:00
zhouxinyong
d72f4f5863 fix: 优化flattenData 函数以避免不必要的数组复制 (#54288) 2025-07-04 11:21:42 +08:00
aojunhao123
00a6074e25 site: prevent unnecessary theme switch when current theme is already selected (#54285) 2025-07-03 23:57:40 +08:00
afc163
64d938e278 docs: use AlibabaSans as website font family (#54275) 2025-07-03 15:28:47 +08:00
github-actions[bot]
fb5be0e723 chore: auto merge branches (#54272)
chore: sync master into feature
2025-07-03 02:53:37 +00:00
遇见同学
0363e412e9 docs: support docs dark in iframe color (#54252) 2025-07-02 11:20:30 +08:00
lijianan
1bbbe499c2 fix: set fontWeight unitless (#54251) 2025-07-02 11:06:43 +08:00
lijianan
84ce358d10 site: add BehaviorPattern for en page (#54254)
* site: add BehaviorPattern for en page

* site: add BehaviorPattern for en page

* fix: fix
2025-07-02 10:52:54 +08:00
Goat
05926aae76 type: Replace any with RcFile in transformFile (#54257) 2025-07-01 23:34:04 +08:00
Peach
0816ad369c docs: workaround for avoid searchbar styles async (#54241) 2025-07-01 10:59:58 +08:00
afc163
458f2cac5c fix(select): prevent flickering on Safari with GPU compositing (#54237) 2025-06-30 17:05:06 +08:00
thinkasany
8159afddb4 chore: add for biome (#54236) 2025-06-30 15:20:48 +08:00
github-actions[bot]
6026f9df65 chore: auto merge branches (#54223)
chore: sync master into feature
2025-06-29 04:51:22 +00:00
github-actions[bot]
d5f5e9663c chore: auto merge branches (#54192)
chore: sync master into feature
2025-06-25 03:45:24 +00:00
x1ngYu
b2be2f38b4 feat: add showCollapsibleIcon API to splitter component (#53540) (#54154) 2025-06-23 14:12:49 +08:00
github-actions[bot]
ff32ecbf65 chore: auto merge branches (#54165)
chore: merge master into feature
2025-06-21 05:46:07 +00:00
github-actions[bot]
1dfdcc2f4e chore: auto merge branches (#54140)
chore: sync feature to master
2025-06-19 07:18:21 +00:00
github-actions[bot]
c34e0b94be chore: auto merge branches (#54130)
chore: sync master into feature
2025-06-19 01:00:25 +00:00
github-actions[bot]
665369ea72 chore: auto merge branches (#54094)
chore: sync master into feature
2025-06-15 13:57:53 +00:00
github-actions[bot]
03f6fb0366 chore: auto merge branches (#54065)
chore: sync master into feature
2025-06-12 04:30:19 +00:00
github-actions[bot]
d3458848b4 chore: auto merge branches (#54038)
chore: merge master into feature
2025-06-10 14:52:01 +00:00
792 changed files with 19898 additions and 8997 deletions

View File

@@ -1,80 +0,0 @@
---
description:
globs: components/*/demo/**
alwaysApply: false
---
# Demo 规范
- demo 代码尽可能简洁
- 避免冗余代码,方便用户复制到项目直接使用
- 每个 demo 聚焦展示一个功能点
- 提供中英文两个版本的说明
- demo 文件扩展名:
- 基础 demo.tsx
- markdown 说明:.md
- 遵循展示优先原则,确保视觉效果良好
- 展示组件的主要使用场景
- 按照由简到繁的顺序排列 demo
- 确保 demo 在各种尺寸下都能正常展示
- 对于复杂交互提供必要的操作说明
## 文件组织
- 每个组件演示包含 `.md`(说明文档)和 `.tsx`(实际代码)两个文件
- 位置:组件目录下的 `demo` 子目录,如 `components/button/demo/`
- 命名:短横线连接的小写英文单词,如 `basic.tsx`、`custom-filter.tsx`
- 文件名应简洁地描述示例内容
## MD 文档规范
- 必须包含 `## zh-CN` 和 `## en-US` 两种语言说明
- 内容简洁明了,突出组件特性和用法
- 避免冗长段落,必要时使用列表或粗体
- 标注注意事项和实验性功能
## TSX 代码规范
- 导入顺序React → 依赖库 → 组件库 → 自定义组件 → 类型 → 样式
- 类型:为复杂数据定义清晰接口,避免 `any`
- 结构:
- 使用函数式组件和 Hooks
- 复杂逻辑提取为独立函数
- 状态管理用 `useState`/`useEffect`
- 风格:
- 2空格缩进箭头函数驼峰命名
- 常量大写+下划线布尔props用`is`/`has`前缀
## 示例类型
1. **基础用法**:展示最简用法,置于首位,代码精简
2. **变体展示**:不同大小、类型、状态,合理分组
3. **交互演示**:展示状态变化和用户交互
4. **数据交互**:展示加载、过滤、排序等
5. **边界情况**:空数据、错误状态处理
## 代码质量
- 实用且专注于单一功能
- 关键处添加简洁注释
- 使用有意义的数据和变量
- 优先使用 antd 内置组件,减少外部依赖
- 性能优化:适当使用 `useMemo`/`useCallback`,清理副作用
## 命名规则
- 基础文件:`basic.tsx`、`controlled.tsx` 等
- 调试类:使用 `debug-` 前缀
- 实验性:使用 `experimental-` 前缀
## 特殊示例
- **调试示例**:用于开发测试,通常不在文档显示
- **无障碍**:展示标签关联和键盘导航
- **响应式**:展示不同视口下的行为
- **多语言**:展示国际化配置方法
## 质量要求
- 确保代码运行正常,无控制台错误
- 适配常见浏览器
- 避免过时 API及时更新到新推荐用法

View File

@@ -1,60 +0,0 @@
---
description: 规范项目文档和 Changelog
globs: ["**/CHANGELOG*.md", "components/**/index.*.md"]
alwaysApply: false
---
# 文档和 Changelog 规范
## 基本要求
- 提供中英文两个版本
- 新的属性需要声明可用的版本号
- 属性命名符合 antd 的 API 命名规则https://github.com/ant-design/ant-design/wiki/API-Naming-rules
## Changelog 规范
- 在 CHANGELOG.en-US.md 和 CHANGELOG.zh-CN.md 书写每个版本的变更
- 对用户使用上无感知的改动建议(文档修补、微小的样式优化、代码风格重构等等)不要提及,保持 CHANGELOG 的内容有效性
- 非 antd 组件的改动(如工程化、构建工具、开发流程等)在 changelog 区块中写 "-"
- 用面向开发者的角度和叙述方式撰写 CHANGELOG不描述修复细节描述问题和对开发者的影响描述用户的原始问题而非你的解决方式
### 示例
- 不好的例子:修复组件 Typography 的 dom 结构问题
- 好的例子:修复了 List.Item 中内容空格丢失的问题
### 其他要求
- 新增属性时,建议用易于理解的语言补充描述用户可以感知的变化
- 尽量给出原始的 PR 链接,社区提交的 PR 改动加上提交者的链接
- 底层模块升级中间版本要去 rc-component 里找到改动,给出变动说明
- 建议参考之前版本的日志写法
- 将同组件的改动放在一起,内容子级缩进
### Changelog Emoji 规范
- 🐞 Bug 修复
- 💄 样式更新或 token 更新
- 🆕 新增特性,新增属性
- 🔥 极其值得关注的新增特性
- 🇺🇸🇨🇳🇬🇧 国际化改动
- 📖 📝 文档或网站改进
- ✅ 新增或更新测试用例
- 🛎 更新警告/提示信息
- ⌨️ ♿ 可访问性增强
- 🗑 废弃或移除
- 🛠 重构或工具链优化
- ⚡️ 性能提升
# 文档规范
- 提供中英文两个版本
- 新属性需声明可用的版本号
- 属性命名符合 API 命名规则
- 组件文档包含使用场景、基础用法、API 说明
- 文档示例应简洁明了
- 属性的描述应清晰易懂
- 对复杂功能提供详细说明
- 加入 TypeScript 定义
- 提供常见问题解答
- 更新文档时同步更新中英文版本

View File

@@ -1,128 +0,0 @@
---
description:
globs:
alwaysApply: true
---
# Git 规范
## 分支管理
- 禁止直接提交到以下保护分支:
- `master`:主分支,用于发布
- `feature`:特性分支,用于开发新版本
- `next`:下一个版本分支
## 开发流程
1. 从保护分支(通常是 `master`)创建新的功能分支
2. 在新分支上进行开发
3. 提交 Pull Request 到目标分支
4. 等待 Code Review 和 CI 通过
5. 合并到目标分支
## 分支命名规范
- 功能开发:`feat/description-of-feature`
- 例如:`feat/add-dark-mode`
- 例如:`feat/improve-table-performance`
- 问题修复:`fix/issue-number-or-description`
- 例如:`fix/button-style-issue`
- 例如:`fix/issue-1234`
- 文档更新:`docs/what-is-changed`
- 例如:`docs/update-api-reference`
- 例如:`docs/fix-typos`
- 代码重构:`refactor/what-is-changed`
- 例如:`refactor/button-component`
- 例如:`refactor/remove-deprecated-api`
- 样式修改:`style/what-is-changed`
- 例如:`style/update-button-tokens`
- 例如:`style/improve-mobile-layout`
- 测试相关:`test/what-is-changed`
- 例如:`test/add-button-test`
- 例如:`test/improve-coverage`
- 构建相关:`build/what-is-changed`
- 例如:`build/upgrade-webpack`
- 例如:`build/fix-ts-config`
- 持续集成:`ci/what-is-changed`
- 例如:`ci/add-e2e-test`
- 例如:`ci/fix-deploy-script`
- 性能优化:`perf/what-is-changed`
- 例如:`perf/optimize-render`
- 例如:`perf/reduce-bundle-size`
- 依赖升级:`deps/package-name-version`
- 例如:`deps/upgrade-react-18`
- 例如:`deps/update-dependencies`
## 分支命名注意事项
1. 使用小写字母
2. 使用连字符(-)分隔单词
3. 简短但具有描述性
4. 避免使用下划线或其他特殊字符
5. 如果与 Issue 关联,可以包含 Issue 编号
## Pull Request 规范
### PR 标题
- PR 标题始终使用英文
- 遵循格式:`类型: 简短描述`
- 例如:`fix: fix button style issues in Safari browser`
- 例如:`feat: add dark mode support`
### PR 内容
- PR 内容默认使用英文
- 尽量简洁清晰地描述改动内容和目的
- 可以视需要在英文描述后附上中文说明
### PR 模板
提交 PR 时请使用项目中提供的模板:
- 英文模板(推荐):[PULL_REQUEST_TEMPLATE.md](mdc:.github/PULL_REQUEST_TEMPLATE.md)
- 中文模板:[PULL_REQUEST_TEMPLATE_CN.md](mdc:.github/PULL_REQUEST_TEMPLATE_CN.md)
### PR 提交注意事项
1. **合并策略**
- 新特性请提交至 `feature` 分支
- 其余可提交至 `master` 分支
2. **审核流程**
- PR 需要由至少一名维护者审核通过后才能合并
- 确保所有 CI 检查都通过
- 解决所有 Code Review 中提出的问题
3. **PR 质量要求**
- 确保代码符合项目代码风格
- 添加必要的测试用例
- 更新相关文档
- 大型改动需要更详细的说明和更多的审核者参与
4. **工具标注**
- 如果是用 Cursor 提交的代码,请在 PR body 末尾进行标注:`> Submitted by Cursor`
## 新增内容
- Pull Request 标题格式:[组件名]: 描述
- 从 master 分支创建新分支
- 分支命名规范:
- feature/xxx新特性
- fix/xxxBug 修复
- docs/xxx文档更新
- PR 说明中选择改动类型:
- 🆕 新特性提交
- 🐞 Bug 修复
- 📝 文档改进
- 📽️ 演示代码改进
- 💄 样式/交互改进
- 🤖 TypeScript 更新
- 📦 包体积优化
- ⚡️ 性能优化
- 🌐 国际化改进
- 提供改动背景和解决方案
- 更新日志同时提供英文和中文版本

View File

@@ -1,94 +0,0 @@
---
description: 本地化规范文档
globs: ["components/locale/*_*.ts", "components/locale/index.tsx"]
alwaysApply: false
---
# 本地化规范
antd 中所有的本地化配置都应该在 `components/locale` 目录中完成定义,主要分为两步:类型定义和本地化配置
## 类型定义
antd 的本地化配置的类型定义的入口文件是 `components/locale/index.tsx`, 当需要添加新的本地化配置时,需要检查对应组件或全局配置的类型是否存在,如果不存在,则需要增加相应的类型描述。
如果新增或修改的本地化配置时组件配置,那么具体的本地化类型应该在相应的组件目录定义,定义好后在 `components/locale/index.tsx` 引入对应组件的类型定义。
## 本地化配置
### 纯字符串配置
antd 中的本地化配置文件命名规则是:`*_*.ts`,如:`zh_CN.ts`,文件默认导出一个 `Locale` 类型对象。
通常在为 antd 添加后修改某一项本地化配置时,如无特殊说明,需要同时修改所有语言的本地化配置。
本地化配置文件列表如下(包括但不限于):
```json
["components/locale/ar_EG.ts","components/locale/az_AZ.ts","components/locale/bg_BG.ts","components/locale/bn_BD.ts","components/locale/by_BY.ts","components/locale/ca_ES.ts","components/locale/cs_CZ.ts","components/locale/da_DK.ts","components/locale/de_DE.ts","components/locale/el_GR.ts","components/locale/en_GB.ts","components/locale/en_US.ts","components/locale/es_ES.ts","components/locale/et_EE.ts","components/locale/eu_ES.ts","components/locale/fa_IR.ts","components/locale/fi_FI.ts","components/locale/fr_BE.ts","components/locale/fr_CA.ts","components/locale/fr_FR.ts","components/locale/ga_IE.ts","components/locale/gl_ES.ts","components/locale/he_IL.ts","components/locale/hi_IN.ts","components/locale/hr_HR.ts","components/locale/hu_HU.ts","components/locale/hy_AM.ts","components/locale/id_ID.ts","components/locale/is_IS.ts","components/locale/it_IT.ts","components/locale/ja_JP.ts","components/locale/ka_GE.ts","components/locale/kk_KZ.ts","components/locale/km_KH.ts","components/locale/kmr_IQ.ts","components/locale/kn_IN.ts","components/locale/ko_KR.ts","components/locale/ku_IQ.ts","components/locale/lt_LT.ts","components/locale/lv_LV.ts","components/locale/mk_MK.ts","components/locale/ml_IN.ts","components/locale/mn_MN.ts","components/locale/ms_MY.ts","components/locale/my_MM.ts","components/locale/nb_NO.ts","components/locale/ne_NP.ts","components/locale/nl_BE.ts","components/locale/nl_NL.ts","components/locale/pl_PL.ts","components/locale/pt_BR.ts","components/locale/pt_PT.ts","components/locale/ro_RO.ts","components/locale/ru_RU.ts","components/locale/si_LK.ts","components/locale/sk_SK.ts","components/locale/sl_SI.ts","components/locale/sr_RS.ts","components/locale/sv_SE.ts","components/locale/ta_IN.ts","components/locale/th_TH.ts","components/locale/tk_TK.ts","components/locale/tr_TR.ts","components/locale/uk_UA.ts","components/locale/ur_PK.ts","components/locale/uz_UZ.ts","components/locale/vi_VN.ts","components/locale/zh_CN.ts","components/locale/zh_HK.ts","components/locale/zh_TW.ts"]
```
本地化配置的内容通常是纯字符串,如:
```typescript
{
// ...
Modal: {
okText: '确定',
cancelText: '取消',
justOkText: '知道了',
}
// ...
}
```
### 字符串模版配置
当然,也有一些需要配置需要再运行时实时替换变量的模版配置,带有 `${}` 的变量将在实际使用的地方被实时替换成对应的变量内容:
```typescript
{
// ...
date: {
format: '${label}日期格式无效',
parse: '${label}不能转换为日期',
invalid: '${label}是一个无效日期',
}
// ...
}
```
### 全局配置
如果某个本地化配置不独属于某个组件,而是数据全局的本地化配置,此时应该在 `global` 中添加相关属性,如:
```typescript
{
// ...
// locales for all components
global: {
placeholder: '请选择',
},
// ...
}
```
# 使用本地化
antd 中具体使用本地化配置时,可以使用 `components/locale/index.tsx` 文件中导出的 `useLocale` 获取全局上下文中配置的本地化,并跟组件属性中传入的本地化配置合并后得到最完整的本地化配置,如:
```tsx
import { useLocale } from "../locale";
import enUS from '../locale/en_US';
export function TestComp(props) {
const { locale: propLocale } = props;
const [contextLocale] = useLocale("TestComp", enUs);
const locale = {...contextLocale, ...propLocale};
return (
<div title={locale?.title}>
{locale?.text}
</div>
);
}
```

View File

@@ -1,108 +0,0 @@
---
description:
globs:
alwaysApply: true
---
Basically, antd naming requires **FULL NAME** instead of Abbreviation.
## Props
* Initialize prop: `default` + `PropName`
* Force render: `forceRender`
* Force render sub component: `force` + `Sub Component Name` + `Render`
* Sub Component Render: `Sub Component Name` + `Render`. e.g.
> panelRender(originNode, info: { SubComponent1, SubComponent2, [somePassedProps]: someValue })
* Sub Item Render: `Sub Item Name` + `Render`. e.g.
> cellRender(date, info: { [somePassedProps]: someValue })
* Data Source: `dataSource`
* Panel open: popup & dropdown `open`, additional popup `popupName` + `Open` like `tooltipOpen`
* Do not use `visible` to make sure all the visible api align
* `children`:
* Mainly display content. To avoid additional prop name.
* Option list like `Select.Option` or `Tree.TreeNode`.
* Customize wrapped component can consider use `component` prop if `children` may have other usage in future.
* Display related naming: `show` + `PropName`
* Functional: `PropName` + `able`
* Disable: `disabled`
* sub component: `disabled` + `Sub Component Name`
* Extra: `extra`
* sub component: `Sub Component Name` + `extra`. e.g. `titleExtra`
* mainly icon: `icon`
* Merge with function first: `functionName: { icon }`. e.g. `expandable: { icon: <Smile /> }`
* Multiple icons: `FunctionName` + `Icon`
* Trigger: `trigger`
* Sub function trigger: `Sub Function` + `Trigger`
* Trigger on the time point: `xxx` + `On` + `EventName` (e.g. `destroyOnHidden`)
* Component use other component config. Naming as component.(e.g. `<Table pagination={{...}} />`)
* ClassName: `className`
* Additional classes should be merged into `classes` (e.g. `<Button classes={{ inner: 'custom-inner' }} />`)
* Format
* Not modify value when blur: `preserveInvalidOnBlur`
## Event
* Trigger event: `on` + `EventName`
* Trigger sub component event: `on` + `SubComponentName` + `EventName` (e.g.`onSearchChange`)
* Trigger prop event: `on` + `PropName` + `EventName` (e.g.`onDragStart`)
* Before trigger event: `before` + `EventName`
* After trigger event: `after` + `EventName`
* After continuous action, such as drag Slider: `on` + `EventName` + `Complete`
## Reference
Component should have `ref` prop. Which should provide the structure:
```tsx
ComponentRef {
nativeElement: HTMLElement;
// Other function
focus: VoidFunction;
}
```
## Component Token
`variant (optional)` + `semantic part` + `semantic part variant (optional)` + `css property` + `size/disabled (optional)`
All component tokens should follow the structure above, and should not conflict with Global Token.
* `variant` means this token only works in certain variant, like `horizontal` `borderless`.
* `semantic part` means the typical element of component, like `item` `header`. If there's.
* `semantic part status` means the variant of the semantic part before it, like `hover` `selected`.
* `css property` means the exact property where the token is used, like `fontSize` `width`.
For example:
| v4 | v5 | Note |
| --- | --- | --- |
| `@menu-item-color` | `itemColor` | Remove the component prefix |
| `@select-item-selected-bg` | `itemSelectedBg` | `selected` is variant of item |
| `@select-single-item-height-lg` | `itemHeightLG` | `single` is variant of Select (by default), `LG` is size of Select |
> Note: If there's no semantic part for one component token, for example, the root borderRadius of Button, it is not suitable to add it. Because we could modify it easily with `className` and `style`.
## Current listing api & Chinese version
ref: [#16048](mdc:https:/github.com/ant-design/ant-design/issues/16048)
## API standard in the document
### Examples
| Property | Description | Type | Default |
| --------- | ---------------------- | ------------------------------ | ------ |
| htmlType | xxx | string | `button ` |
| type | xxx | `horizontal ` \| `vertical ` | `horizontal` |
| disabled | xxx | boolean | false |
| minLength | xxx | number | 0 |
| style | xxx | CSSProperties | - |
| character | xxx | (props) => ReactNode | - |
| offset | xxx| \[number, number] | \[0, 0] |
| value | xxx | string \| number | `small` |
### Promise
- When string type, the **Default** use ` `` `.
- Can also list string optional values in **Type**.
- When boolean type, the **Default** value is true or false.
- When number type, the **Default** value use numbers directly.
- When function type, use an arrow function expression in **Type**.
- No default value use - .
- Capitalize the first letter in **Description** apart from `someProp`.
- No period at the end of the **Description**.
- API order is arranged in alphabetical order, and can be put together under special circumstances (such as: xs sm md).
ref: [#25066](mdc:https:/github.com/ant-design/ant-design/issues/25066)

View File

@@ -1,27 +0,0 @@
---
description:
globs:
alwaysApply: true
---
# 项目背景
这是 ant-design/ant-designantd的源代码仓库是一个 React 组件库,发布为 npm 包 antd。
- 使用 TypeScript 和 React 开发
- 兼容 React 16 ~ 19 版本
- 组件库设计精美,功能完善,广泛应用于企业级中后台产品
- 遵循 Ant Design 设计规范
- 支持国际化
# 编码规范
- 使用 TypeScript 和 React 书写
- 使用函数式组件和 hooks避免类组件
- 使用提前返回early returns提高代码可读性
- 避免引入新依赖,严控打包体积
- 兼容 Chrome 80+ 浏览器
- 支持服务端渲染
- 保持向下兼容,避免 breaking change
- 组件名使用大驼峰PascalCase
- 属性名使用小驼峰camelCase
- 合理使用 React.memo、useMemo 和 useCallback 优化性能

View File

@@ -1,79 +0,0 @@
---
description:
globs: components/*/style/**
alwaysApply: false
---
# 样式规范
## 样式方案
- 使用 `@ant-design/cssinjs` 作为样式解决方案
- 每个组件的样式应该放在 `style/` 目录下
- 样式文件应该与组件结构保持一致
- 使用 CSS-in-JS 时应当注意性能影响,避免不必要的样式重计算
- 样式生成函数应遵循 `gen[ComponentName]Style` 的命名规范
- 样式覆盖应使用类选择器而非标签选择器,提高样式特异性
## Token 系统
- 使用 Ant Design 的设计 Token 系统
- 避免硬编码颜色、尺寸、间距等值
- 组件样式应基于全局 Token 和组件级 Token
- 自定义样式应尽可能使用现有的 Token保持一致性
- 组件级 Token 命名规范:`Component` + 属性名,如 `buttonPrimaryColor`
- 对 Token 的修改应当向下传递,确保设计系统的一致性
## 响应式设计
- 组件应支持在不同屏幕尺寸下良好展示
- 使用相对单位(如 em、rem而非固定像素值
- 关键断点应与设计系统保持一致
- 在小屏幕上提供良好的降级方案
- 使用 CSS Grid 和 Flexbox 布局实现响应式布局
- 考虑移动设备上的触摸交互体验
## 暗色模式
- 所有组件必须支持暗色模式
- 暗色模式应通过 Token 系统实现,不应硬编码
- 测试暗色模式下的颜色对比度,确保可访问性
- 在设计暗色模式时考虑降低亮度和饱和度
- 确保文本在暗色背景上有足够的对比度
- 图片和图标应提供适合暗色模式的版本
## RTL 支持
- 组件应支持从右到左RTL的阅读方向
- 使用 CSS 逻辑属性(如 margin-inline-start替代方向性属性如 margin-left
- 图标和方向性元素应随 RTL 模式翻转
- 测试组件在 RTL 模式下的布局和交互
- 确保文本对齐和方向符合 RTL 规范
- 处理好数字和日期等特殊内容在 RTL 模式下的显示
## 动画效果
- 使用 CSS 过渡实现简单动画
- 复杂动画使用 rc-motion 实现
- 尊重用户的减少动画设置prefers-reduced-motion
- 动画时长和缓动函数应保持一致性
- 动画不应干扰用户的操作和阅读体验
- 为关键操作提供合适的反馈动画
- 避免使用会导致性能问题的 CSS 属性(如 box-shadow进行动画
## 主题定制
- 支持通过 ConfigProvider 进行主题定制
- 提供完整的组件级 Token 配置
- 保持向后兼容性,不轻易改变 Token 含义
- 避免在组件内使用不可覆盖的样式
- 提供主题切换的平滑过渡效果
- 测试自定义主题在各种组件组合下的效果
## 可访问性样式
- 遵循 WCAG 2.1 AA 级别标准
- 确保焦点状态有明显的视觉提示
- 提供足够的色彩对比度
- 不依赖颜色来传达信息
- 支持用户放大页面至 200% 时的正常布局
- 避免使用会导致闪烁的动画

View File

@@ -1,11 +0,0 @@
---
description:
globs: **/__tests__/**,**/*.test.tsx,**/*.test.ts
alwaysApply: false
---
# 测试规范
- 使用 Jest 和 React Testing Library 编写单元测试
- 对 UI 组件使用快照测试 (Snapshot Testing)
- 测试覆盖率要求 100%
- 测试文件放在 __tests__ 目录命名格式为index.test.tsx 或 xxx.test.tsx

View File

@@ -1,81 +0,0 @@
# TypeScript 规范
## 基本原则
- 所有组件和函数必须提供准确的类型定义
- 避免使用 `any` 类型,尽可能精确地定义类型
- 使用接口而非类型别名定义对象结构
- 导出所有公共接口类型,方便用户使用
- 严格遵循 TypeScript 类型设计原则,确保类型安全
- 确保编译无任何类型错误或警告
## 组件类型定义
- 组件 props 应使用 interface 定义,便于扩展
- 组件 props 接口命名应为 `ComponentNameProps`
- 为组件状态定义专门的接口,如 `ComponentNameState`
- 复杂的数据结构应拆分为多个接口定义
- 组件的 ref 类型应该明确定义,使用 `React.ForwardRefRenderFunction`
- 所有回调函数类型应明确定义参数和返回值
## 泛型使用
- 适当使用泛型增强类型灵活性
- 为泛型参数提供合理的默认类型和约束
- 避免过度使用泛型导致类型复杂化
- 在泛型参数上应用限制条件constraints确保类型安全
- 为复杂泛型提供类型别名以提高可读性
## 类型合并与扩展
- 使用交叉类型(&)合并多个类型
- 使用 Partial<T>、Pick<T, K>、Omit<T, K> 等工具类型修改现有类型
- 扩展原生 DOM 元素属性时,继承相应的内置类型
- 使用 type 定义联合类型和交叉类型
- 优先使用自带的工具类型,避免重复定义
## 枚举和常量
- 使用字面量联合类型定义有限的选项集合
- 为复杂的枚举值提供类型守卫函数
- 避免使用 `enum`,优先使用联合类型和 `as const`
- 对于关键常量,使用 `as const` 断言确保类型严格
- 为联合类型中的每个值提供适当的注释
## 类型推断与断言
- 尽可能依赖 TypeScript 的类型推断
- 只在必要时使用类型断言as
- 使用类型守卫函数进行运行时类型检查
- 避免使用非空断言操作符(!
- 使用 `instanceof` 和 `typeof` 进行类型守卫
- 为自定义类型创建类型谓词type predicates函数
## JSDoc 注释
- 为复杂的类型、函数、组件添加 JSDoc 注释
- 使用 `@deprecated` 标记已废弃的 API
- 在注释中提供使用示例
- 说明参数和返回值的含义与约束
- 在 interface 和重要类型定义上添加文档注释
- 使用 `@template` 标记泛型参数
## 类型兼容性
- 确保类型定义兼容不同版本的 React
- 避免使用实验性或不稳定的 TypeScript 特性
- 为第三方库未提供的类型编写声明文件
- 使用条件类型处理复杂的类型逻辑
- 验证类型在不同 TypeScript 版本下的兼容性
## 严格使用 TypeScript 类型
- 导出组件类型和接口
- 使用 React.FC<Props> 或明确的返回类型
- 避免使用 any优先使用 unknown
- 组件 Props 使用 interface 定义
- 工具类型使用 type 定义
- 使用明确的命名约定
- 合理使用泛型提高复用性
- 导出类型时使用 export type
- 组件属性使用 JSDoc 注释说明用途

View File

@@ -2,7 +2,7 @@
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "ant-design",
"image": "mcr.microsoft.com/devcontainers/typescript-node:1-22-bookworm",
"image": "mcr.microsoft.com/devcontainers/typescript-node:4-22-bookworm",
"postCreateCommand": "pnpm install",
"customizations": {
"vscode": {

View File

@@ -1,3 +1,6 @@
// FIXME: workaround for avoid searchbar styles be extracted to async chunk
@import 'dumi/theme-default/slots/SearchBar/index.less';
.demo-logo {
width: 120px;
min-width: 120px;

View File

@@ -1,21 +0,0 @@
export default class FetchCache {
private cache: Map<string, PromiseLike<any>> = new Map();
get(key: string) {
return this.cache.get(key);
}
set(key: string, value: PromiseLike<any>) {
this.cache.set(key, value);
}
promise<T>(key: string, promiseFn: () => PromiseLike<T>): PromiseLike<T> {
const cached = this.get(key);
if (cached) {
return cached;
}
const promise = promiseFn();
this.set(key, promise);
return promise;
}
}

View File

@@ -1,21 +0,0 @@
import React from 'react';
import fetch from 'cross-fetch';
import FetchCache from './cache';
const cache = new FetchCache();
const useFetch = <T>(options: string | { request: () => PromiseLike<T>; 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<T>(cache.promise<T>(key, request));
};
export default useFetch;

View File

@@ -0,0 +1,65 @@
import { useMemo } from 'react';
import useSWR from 'swr';
import type { SWRConfiguration } from 'swr';
const isNumber = (value: any): value is number => {
return typeof value === 'number' && !Number.isNaN(value);
};
const fetcher = async (url: string): Promise<number> => {
// eslint-disable-next-line compat/compat
const res = await fetch(url, { headers: { Accept: 'application/vnd.github+json' } });
const data = await res.json();
const totalCount = isNumber(data?.total_count) ? data.total_count : 0;
return totalCount;
};
const swrConfig: SWRConfiguration<number, Error> = {
revalidateOnReconnect: true, // 网络重新连接时重新请求
dedupingInterval: 1000 * 60, // 1 分钟内重复 key 不会重新请求
shouldRetryOnError: true, // 错误重试
errorRetryCount: 3, // 最多重试 3 次
};
export interface UseIssueCountOptions {
repo: string; // e.g. ant-design/ant-design
proxyEndpoint?: string; // backend proxy endpoint to avoid GitHub rate limit
titleKeywords?: string[]; // keywords to match in issue title
}
export const useIssueCount = (options: UseIssueCountOptions) => {
const { repo, proxyEndpoint, titleKeywords } = options;
// Note: current query only filters by title keywords. Filtering by component name can be added later if needed.
const searchUrl = useMemo(() => {
const tokens = (titleKeywords || []).filter(Boolean).map((k) => encodeURIComponent(String(k)));
const orExpr = tokens.length > 0 ? tokens.join('%20OR%20') : '';
const titlePart = orExpr ? `in:title+(${orExpr})` : 'in:title';
const q = `repo:${repo}+is:issue+is:open+${titlePart}`;
return `https://api.github.com/search/issues?q=${q}`;
}, [repo, titleKeywords]);
const endpoint = proxyEndpoint || searchUrl;
const { data, error, isLoading } = useSWR<number, Error>(endpoint || null, fetcher, swrConfig);
const issueNewUrl = `https://github.com/${repo}/issues/new/choose`;
const issueSearchUrl = useMemo(() => {
const keywords = (titleKeywords || []).filter(Boolean).map((k) => String(k));
const groupExpr =
keywords.length > 0 ? `(${keywords.map((k) => `is:issue in:title ${k}`).join(' OR ')})` : '';
const qRaw = `is:open ${groupExpr}`.trim();
return `https://github.com/${repo}/issues?q=${encodeURIComponent(qRaw)}`;
}, [repo, titleKeywords]);
return {
issueCount: data,
issueCountError: error,
issueCountLoading: isLoading,
issueNewUrl,
issueSearchUrl,
};
};
export default useIssueCount;

View File

@@ -16,7 +16,7 @@ const useLocale = <
): [Record<K, V>, 'cn' | 'en'] => {
const { id } = useDumiLocale();
const localeType = id === 'zh-CN' ? 'cn' : 'en';
return [localeMap?.[localeType]!, localeType] as const;
return [localeMap?.[localeType] ?? ({} as Record<K, V>), localeType] as const;
};
export default useLocale;

View File

@@ -221,7 +221,7 @@ const useMenu = (options: UseMenuOptions = {}): readonly [MenuProps['items'], st
return result;
}, []) ?? []
);
}, [sidebarData, fullData, pathname, search, options]);
}, [sidebarData, pathname, fullData, search, before, after]);
return [menuItems, pathname] as const;
};

View File

@@ -38,7 +38,7 @@ const NotFoundPage: React.FC<NotFoundProps> = ({ router }) => {
code: 11,
msg: `Page not found: ${location.href}; Source: ${document.referrer}`,
});
}, []);
}, [isZhCN, pathname, router]);
return (
<Result

View File

@@ -1,12 +1,12 @@
import React from 'react';
import { Badge, Carousel, Flex, Skeleton, Typography } from 'antd';
import { Alert, Badge, Carousel, Flex, Skeleton, Typography } from 'antd';
import { createStyles } from 'antd-style';
import classNames from 'classnames';
import useLocale from '../../../hooks/useLocale';
import SiteContext from '../../../theme/slots/SiteContext';
import type { Extra, Icon } from './util';
import { getCarouselStyle, useSiteData } from './util';
import { getCarouselStyle, useAntdSiteConfig } from './util';
const useStyle = createStyles(({ token, css, cx }) => {
const { carousel } = getCarouselStyle();
@@ -67,17 +67,20 @@ const useStyle = createStyles(({ token, css, cx }) => {
interface RecommendItemProps {
extra: Extra;
index: number;
icons: Icon[];
icons?: Icon[];
className?: string;
}
const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, className }) => {
const RecommendItem: React.FC<RecommendItemProps> = (props) => {
const { extra, index, icons, className } = props;
const { styles } = useStyle();
if (!extra) {
return <Skeleton key={index} />;
}
const icon = icons.find((i) => i.name === extra.source);
const icon = icons?.find((i) => i.name === extra.source);
const card = (
<a
@@ -93,7 +96,9 @@ const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, clas
</Typography.Paragraph>
<Flex justify="space-between" align="center">
<Typography.Text>{extra.date}</Typography.Text>
{icon && <img src={icon.href} draggable={false} className={styles.bannerBg} alt="banner" />}
{icon?.href && (
<img src={icon.href} draggable={false} className={styles.bannerBg} alt="banner" />
)}
</Flex>
</a>
);
@@ -111,6 +116,7 @@ const RecommendItem: React.FC<RecommendItemProps> = ({ extra, index, icons, clas
export const BannerRecommendsFallback: React.FC = () => {
const { isMobile } = React.use(SiteContext);
const { styles } = useStyle();
const list = Array.from({ length: 3 });
@@ -118,7 +124,7 @@ export const BannerRecommendsFallback: React.FC = () => {
return isMobile ? (
<Carousel className={styles.carousel}>
{list.map((_, index) => (
<div key={index} className={styles.itemBase}>
<div key={`mobile-${index}`} className={styles.itemBase}>
<Skeleton active style={{ padding: '0 24px' }} />
</div>
))}
@@ -126,7 +132,7 @@ export const BannerRecommendsFallback: React.FC = () => {
) : (
<div className={styles.container}>
{list.map((_, index) => (
<div key={index} className={styles.itemBase}>
<div key={`desktop-${index}`} className={styles.itemBase}>
<Skeleton active />
</div>
))}
@@ -138,25 +144,37 @@ const BannerRecommends: React.FC = () => {
const { styles } = useStyle();
const [, lang] = useLocale();
const { isMobile } = React.use(SiteContext);
const data = useSiteData();
const extras = data?.extras?.[lang];
const icons = data?.icons || [];
const first3 =
!extras || extras.length === 0 ? Array.from<any>({ length: 3 }) : extras.slice(0, 3);
const { data, error, isLoading } = useAntdSiteConfig();
if (!data) {
if (isLoading) {
return <BannerRecommendsFallback />;
}
if (error) {
return (
<Alert
showIcon
type="error"
message={error.message}
description={process.env.NODE_ENV !== 'production' ? error.stack : undefined}
/>
);
}
const extras = data?.extras?.[lang];
const mergedExtras =
!extras || !extras.length ? Array.from<Extra>({ length: 3 }) : extras.slice(0, 3);
if (isMobile) {
return (
<Carousel className={styles.carousel}>
{first3.map((extra, index) => (
<div key={index}>
{mergedExtras.map((extra, index) => (
<div key={`mobile-${index}`}>
<RecommendItem
extra={extra}
index={index}
icons={icons}
icons={data?.icons}
className={styles.sliderItem}
/>
</div>
@@ -167,13 +185,13 @@ const BannerRecommends: React.FC = () => {
return (
<div className={styles.container}>
{first3.map((extra, index) => (
{mergedExtras.map((extra, index) => (
<RecommendItem
key={`desktop-${index}`}
extra={extra}
index={index}
icons={icons}
icons={data?.icons}
className={styles.cardItem}
key={index}
/>
))}
</div>

View File

@@ -258,7 +258,18 @@ const ComponentsList: React.FC = () => {
),
},
],
[isMobile],
[
isMobile,
locale.inProgress,
locale.lastMonth,
locale.lastWeek,
locale.lastYear,
locale.sampleContent,
locale.success,
locale.taskFailed,
locale.tour,
locale.yesterday,
],
);
return isMobile ? (

View File

@@ -11,6 +11,14 @@ const useStyle = createStyles(({ css, token }) => ({
position: relative;
transition: all ${token.motionDurationSlow};
`,
container: css`
position: absolute;
inset: 0;
overflow: hidden;
`,
typographyWrapper: css`
text-align: center;
`,
marginStyle: css`
max-width: 1208px;
margin-inline: auto;
@@ -40,41 +48,36 @@ const Group: React.FC<React.PropsWithChildren<GroupProps>> = (props) => {
const token = useTheme();
const { styles } = useStyle();
const { isMobile } = React.use(SiteContext);
const childNode = (
<>
<div style={{ textAlign: 'center' }}>
<Typography.Title
id={id}
level={1}
style={{
fontWeight: 900,
color: titleColor,
// Special for the title
fontFamily: `AliPuHui, ${token.fontFamily}`,
fontSize: isMobile ? token.fontSizeHeading2 : token.fontSizeHeading1,
}}
>
{title}
</Typography.Title>
<Typography.Paragraph
style={{
color: titleColor,
marginBottom: isMobile ? token.marginXXL : token.marginFarXS,
}}
>
{description}
</Typography.Paragraph>
</div>
<div className={classNames({ [styles.marginStyle]: !collapse })}>
{children ? <div>{children}</div> : <div className={styles.withoutChildren} />}
</div>
</>
);
return (
<div style={{ backgroundColor: background }} className={styles.box}>
<div style={{ position: 'absolute', inset: 0 }}>{decoration}</div>
<GroupMaskLayer style={{ paddingBlock: token.marginFarSM }}>{childNode}</GroupMaskLayer>
<div className={styles.container}>{decoration}</div>
<GroupMaskLayer style={{ paddingBlock: token.marginFarSM }}>
<div className={styles.typographyWrapper}>
<Typography.Title
id={id}
level={1}
style={{
fontWeight: 900,
color: titleColor,
// Special for the title
fontSize: isMobile ? token.fontSizeHeading2 : token.fontSizeHeading1,
}}
>
{title}
</Typography.Title>
<Typography.Paragraph
style={{
color: titleColor,
marginBottom: isMobile ? token.marginXXL : token.marginFarXS,
}}
>
{description}
</Typography.Paragraph>
</div>
<div className={classNames({ [styles.marginStyle]: !collapse })}>
{children ? <div>{children}</div> : <div className={styles.withoutChildren} />}
</div>
</GroupMaskLayer>
</div>
);
};

View File

@@ -83,7 +83,6 @@ const useStyle = createStyles(({ token, css, cx }, siteConfig: SiteContextProps)
padding-inline: ${token.paddingXL}px;
text-shadow: ${Array.from({ length: 5 }, () => textShadow).join(', ')};
h1 {
font-family: AliPuHui, ${token.fontFamily} !important;
font-weight: 900 !important;
font-size: ${token.fontSizeHeading2 * 2}px !important;
line-height: ${token.lineHeightHeading2} !important;

View File

@@ -73,13 +73,12 @@ const ThemeColorPicker: React.FC<ThemeColorPickerProps> = ({ value, onChange, id
const matchColors = React.useMemo(() => {
const valueStr = generateColor(value || '').toRgbString();
let existActive = false;
const colors = PRESET_COLORS.map((color) => {
const colorStr = generateColor(color).toRgbString();
const active = colorStr === valueStr;
existActive = existActive || active;
return { color, active, picker: false };
return { color, active, picker: false } as const;
});
const existActive = colors.some((c) => c.active);
return [
...colors,

View File

@@ -94,8 +94,6 @@ const MobileCarousel: React.FC<MobileCarouselProps> = (props) => {
style={{
fontWeight: 900,
color: mobileImageConfigList[currentSlider].titleColor,
// Special for the title
fontFamily: `AliPuHui, ${token.fontFamily}`,
fontSize: token.fontSizeHeading2,
}}
>

View File

@@ -93,7 +93,7 @@ const ThemePicker: React.FC<ThemePickerProps> = (props) => {
})}
>
<input type="radio" name="theme" id={index === 0 ? id : undefined} />
<img src={THEMES[theme]} alt={theme} />
<img draggable={false} src={THEMES[theme]} alt={theme} />
</label>
<span>{locale[theme]}</span>
</Flex>

View File

@@ -471,6 +471,7 @@ const Theme: React.FC = () => {
<div className={styles.logo}>
<div className={styles.logoImg}>
<img
draggable={false}
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
style={{
filter:
@@ -500,7 +501,7 @@ const Theme: React.FC = () => {
className={classNames(styles.transBg)}
selectedKeys={['Themes']}
openKeys={['Design']}
style={{ height: '100%', borderRight: 0 }}
style={{ height: '100%', borderInlineEnd: 0 }}
items={sideMenuItems}
expandIcon={false}
/>
@@ -588,15 +589,17 @@ const Theme: React.FC = () => {
>
{/* Image Left Top */}
<img
draggable={false}
className={classNames(styles.pos, styles.leftTopImage)}
src="https://gw.alipayobjects.com/zos/bmw-prod/bd71b0c6-f93a-4e52-9c8a-f01a9b8fe22b.svg"
alt=""
alt="image-left-top"
/>
{/* Image Right Bottom */}
<img
draggable={false}
className={classNames(styles.pos, styles.rightBottomImage)}
src="https://gw.alipayobjects.com/zos/bmw-prod/84ad805a-74cb-4916-b7ba-9cdc2bdec23a.svg"
alt=""
alt="image-right-bottom"
/>
</div>
{/* >>>>>> Dark <<<<<< */}
@@ -608,15 +611,17 @@ const Theme: React.FC = () => {
>
{/* Image Left Top */}
<img
draggable={false}
className={classNames(styles.pos, styles.leftTopImagePos)}
src="https://gw.alipayobjects.com/zos/bmw-prod/a213184a-f212-4afb-beec-1e8b36bb4b8a.svg"
alt=""
alt="image-left-top"
/>
{/* Image Right Bottom */}
<img
draggable={false}
className={classNames(styles.pos, styles.rightBottomPos)}
src="https://gw.alipayobjects.com/zos/bmw-prod/bb74a2fb-bff1-4d0d-8c2d-2ade0cd9bb0d.svg"
alt=""
alt="image-right-bottom"
/>
</div>
{/* >>>>>> Background Image <<<<<< */}

View File

@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
/* eslint-disable compat/compat */
import { css } from 'antd-style';
import fetch from 'cross-fetch';
import useSWR from 'swr';
export interface Author {
avatar: string;
@@ -82,19 +82,13 @@ export function preLoad(list: string[]) {
}
}
export function useSiteData(): Partial<SiteData> | undefined {
const [data, setData] = useState<SiteData | undefined>(undefined);
useEffect(() => {
fetch('https://render.alipay.com/p/h5data/antd4-config_website-h5data.json').then(
async (res) => {
setData(await res.json());
},
);
}, []);
return data;
}
export const useAntdSiteConfig = () => {
const { data, error, isLoading } = useSWR<Partial<SiteData>, Error>(
`https://render.alipay.com/p/h5data/antd4-config_website-h5data.json`,
(url: string) => fetch(url).then((res) => res.json()),
);
return { data, error, isLoading };
};
export const getCarouselStyle = () => ({
carousel: css`

View File

@@ -51,11 +51,7 @@ const Homepage: React.FC = () => {
<div>
{/* 定制主题 */}
<ConfigProvider
theme={{
algorithm: theme.defaultAlgorithm,
}}
>
<ConfigProvider theme={{ algorithm: theme.defaultAlgorithm }}>
<Suspense fallback={null}>
<Theme />
</Suspense>

View File

@@ -1,5 +1,5 @@
import React, { Suspense, useEffect } from 'react';
import { App, Button, Skeleton } from 'antd';
import { App, Button, ConfigProvider, Skeleton } from 'antd';
import { enUS, zhCN } from 'antd-token-previewer';
import type { ThemeConfig } from 'antd/es/config-provider/context';
import { Helmet } from 'dumi';
@@ -61,21 +61,23 @@ const CustomTheme: React.FC = () => {
<meta property="og:title" content={`${locale.title} - Ant Design`} />
</Helmet>
<Suspense fallback={<Skeleton style={{ margin: 24 }} />}>
<ThemeEditor
advanced
hideAdvancedSwitcher
theme={{ name: 'Custom Theme', key: 'test', config: theme }}
style={{ height: 'calc(100vh - 64px)' }}
onThemeChange={(newTheme) => {
setTheme(newTheme.config);
}}
locale={lang === 'cn' ? zhCN : enUS}
actions={
<Button type="primary" onClick={handleSave}>
{locale.save}
</Button>
}
/>
<ConfigProvider theme={{ inherit: false }}>
<ThemeEditor
advanced
hideAdvancedSwitcher
theme={{ name: 'Custom Theme', key: 'test', config: theme }}
style={{ height: 'calc(100vh - 64px)' }}
onThemeChange={(newTheme) => {
setTheme(newTheme.config);
}}
locale={lang === 'cn' ? zhCN : enUS}
actions={
<Button type="primary" onClick={handleSave}>
{locale.save}
</Button>
}
/>
</ConfigProvider>
</Suspense>
</div>
);

View File

@@ -1,6 +1,7 @@
import type { UnifiedTransformer } from 'dumi';
import { unistUtilVisit } from 'dumi';
import set from 'lodash/set';
import semver from 'semver';
let hastToString: typeof import('hast-util-to-string').toString;
@@ -9,6 +10,24 @@ let hastToString: typeof import('hast-util-to-string').toString;
({ toString: hastToString } = await import('hast-util-to-string'));
})();
function isValidStrictVer(ver: string): boolean {
if (!semver.valid(ver)) {
return false;
}
const parts = ver.split('.');
if (parts.length !== 3) {
return false;
}
return parts.every((part) => /^\d+$/.test(part));
}
function isValidDate(dateStr: string): boolean {
// (YYYY-MM-DD)
return /^\d{4}-\d{2}-\d{2}$/.test(dateStr);
}
const COMPONENT_NAME = 'RefinedChangelog';
function rehypeChangelog(): UnifiedTransformer<any> {
@@ -23,32 +42,73 @@ function rehypeChangelog(): UnifiedTransformer<any> {
const nodesToWrap: { parent: any; startIdx: number }[] = [];
const WRAPPER_FLAG = 'data-changelog-wrapped'; // 包裹容器唯一标识
function checkLogSegment(node: any, strict = true) {
if (node && node.type === 'element' && node.tagName === 'h2') {
if (strict) {
const ver = hastToString(node);
return isValidStrictVer(ver) && semver.major(ver) >= 5;
}
return true;
}
return false;
}
unistUtilVisit.visit(tree, 'element', (node, idx, parent) => {
if (node.properties?.[WRAPPER_FLAG]) {
return unistUtilVisit.SKIP;
}
if (
idx !== undefined &&
parent &&
idx! + 2 < parent.children.length &&
node.tagName === 'h2' &&
parent.children[idx! + 1].tagName === 'p' &&
parent.children[idx! + 2].tagName === 'ul'
) {
if (idx !== undefined && parent && checkLogSegment(node)) {
nodesToWrap.push({ parent, startIdx: idx! });
}
});
nodesToWrap.reverse().forEach(({ parent, startIdx }) => {
const [heading, date, list] = parent.children.splice(startIdx, 3);
const totalNodesToWrap = nodesToWrap.length;
for (let i = totalNodesToWrap - 1; i >= 0; i--) {
const { parent, startIdx } = nodesToWrap[i];
let endIdx = -1;
const isEndOfWrap = i === totalNodesToWrap - 1;
for (let j = startIdx + 1; j < parent.children.length; j++) {
const nextNode = parent.children[j];
if (
(isEndOfWrap && checkLogSegment(nextNode, false)) || // 日志页通常还存在历史 major 版本
nextNode.properties?.[WRAPPER_FLAG] || // 已经被处理
checkLogSegment(nextNode) // 下一段日志
) {
endIdx = j;
break;
}
}
if (endIdx === -1) {
continue;
}
// Version
const heading = parent.children[startIdx];
// Find Date
let dateIdx = -1;
for (let j = startIdx + 1; j < endIdx; j++) {
const node = parent.children[j];
if (node.type === 'element' && isValidDate(hastToString(node))) {
dateIdx = j;
break;
}
}
if (dateIdx === -1) {
continue;
}
// Collect list nodes between dateIdx and endIdx
const version = hastToString(heading);
const date = parent.children[dateIdx];
const dateStr = hastToString(date);
const details = parent.children.slice(dateIdx + 1, endIdx);
const headingWrap = {
type: 'element',
tagName: `${COMPONENT_NAME}.Version`,
// 为标签添加语义化 className (下面同理)
children: [set(heading, 'properties.className', 'changelog-version')],
};
@@ -58,10 +118,13 @@ function rehypeChangelog(): UnifiedTransformer<any> {
children: [set(date, 'properties.className', 'changelog-date')],
};
const listWrap = {
const detailWrap = {
type: 'element',
tagName: `${COMPONENT_NAME}.Details`,
children: [set(list, 'properties.className', 'changelog-details')],
properties: {
className: 'changelog-details',
},
children: details,
};
const wrapper = {
@@ -82,11 +145,11 @@ function rehypeChangelog(): UnifiedTransformer<any> {
value: JSON.stringify(dateStr),
},
],
children: [headingWrap, dateWrap, listWrap],
children: [headingWrap, dateWrap, detailWrap],
};
parent.children.splice(startIdx, 0, wrapper);
});
parent.children.splice(startIdx, endIdx - startIdx, wrapper);
}
};
}

View File

@@ -41,7 +41,7 @@ const remarkAnchor = (opt: Options = {}): UnifiedTransformer<any> => {
const ids = new Set();
unistUtilVisit.visit(tree, 'heading', (node) => {
if (toArr(realOpt.level).indexOf(node.depth) === -1) {
if (!toArr(realOpt.level).includes(node.depth)) {
return unistUtilVisit.CONTINUE;
}

View File

@@ -3,6 +3,7 @@ import { theme as antdTheme, ConfigProvider } from 'antd';
import type { ThemeConfig } from 'antd';
import type { ThemeProviderProps } from 'antd-style';
import { ThemeProvider } from 'antd-style';
import { updateCSS } from 'rc-util/lib/Dom/dynamicCSS';
import SiteContext from './slots/SiteContext';
@@ -41,6 +42,24 @@ const SiteThemeProvider: React.FC<ThemeProviderProps<any>> = ({ children, theme,
ConfigProvider.config({ theme: theme as ThemeConfig });
}, [theme]);
React.useEffect(() => {
// iframe demo 生效
if (window.parent !== window) {
updateCSS(
`
[data-prefers-color='dark'] {
color-scheme: dark !important;
}
[data-prefers-color='light'] {
color-scheme: light !important;
}
`,
'color-scheme',
);
}
}, [theme]);
return (
<ThemeProvider<NewToken>
{...rest}
@@ -51,7 +70,7 @@ const SiteThemeProvider: React.FC<ThemeProviderProps<any>> = ({ children, theme,
menuItemBorder: 2,
mobileMaxWidth: 767.99,
siteMarkdownCodeBg: token.colorFillTertiary,
siteMarkdownCodeBgDark: "#000",
siteMarkdownCodeBgDark: '#000',
antCls: `.${rootPrefixCls}`,
iconCls: `.${iconPrefixCls}`,
/** 56 */

View File

@@ -5,11 +5,10 @@ interface AntdProps {
component: keyof typeof all;
}
function Antd(props: AntdProps) {
const Antd: React.FC<AntdProps> = (props) => {
const { component, ...restProps } = props;
const Component = (all[component] ?? React.Fragment) as React.ComponentType;
const Component = (all[component] ?? React.Fragment) as React.ComponentType<any>;
return <Component {...restProps} />;
}
};
export default Antd;

View File

@@ -1,5 +1,6 @@
import * as React from 'react';
import { Tag, TagProps } from 'antd';
import { Tag } from 'antd';
import type { TagProps } from 'antd';
// https://github.com/umijs/dumi/blob/master/src/client/theme-default/builtins/Badge/index.tsx
interface BadgeProps extends TagProps {

View File

@@ -1,46 +1,66 @@
import React from 'react';
import { EditOutlined, GithubOutlined, HistoryOutlined, CompassOutlined } from '@ant-design/icons';
import {
BugOutlined,
CompassOutlined,
EditOutlined,
GithubOutlined,
HistoryOutlined,
IssuesCloseOutlined,
LoadingOutlined,
} from '@ant-design/icons';
import type { GetProp } from 'antd';
import { Descriptions, Flex, theme, Tooltip, Typography } from 'antd';
import { createStyles, css } from 'antd-style';
import kebabCase from 'lodash/kebabCase';
import CopyToClipboard from 'react-copy-to-clipboard';
import Link from '../../common/Link';
import useIssueCount from '../../../hooks/useIssueCount';
import useLocale from '../../../hooks/useLocale';
import ComponentChangelog from '../../common/ComponentChangelog';
import Link from '../../common/Link';
const locales = {
cn: {
import: '使用',
copy: '复制',
copied: '已复制',
source: '源码',
source: '反馈',
docs: '文档',
edit: '编辑此页',
changelog: '更新日志',
design: '设计指南',
version: '版本',
issueNew: '提交问题',
issueOpen: '待解决',
},
en: {
import: 'Import',
copy: 'Copy',
copied: 'Copied',
source: 'Source',
source: 'GitHub',
docs: 'Docs',
edit: 'Edit this page',
changelog: 'Changelog',
design: 'Design',
version: 'Version',
issueNew: 'Issue',
issueOpen: 'Open issues',
},
};
const branchUrl = 'https://github.com/ant-design/ant-design/edit/master/';
const branchUrl = (repo: string) => `https://github.com/${repo}/edit/master/`;
function isVersionNumber(value?: string) {
return value && /^\d+\.\d+\.\d+$/.test(value);
}
const transformComponentName = (componentName: string) => {
if (componentName === 'Notification' || componentName === 'Message') {
return componentName.toLowerCase();
}
return componentName;
};
const useStyle = createStyles(({ token }) => ({
code: css`
cursor: pointer;
@@ -61,7 +81,7 @@ const useStyle = createStyles(({ token }) => ({
}
`,
icon: css`
margin-inline-end: 3px;
margin-inline-end: 4px;
`,
}));
@@ -71,15 +91,23 @@ export interface ComponentMetaProps {
filename?: string;
version?: string;
designUrl?: string;
searchTitleKeywords?: string[];
repo: string;
}
const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
const { component, source, filename, version, designUrl } = props;
const { component, source, filename, version, designUrl, searchTitleKeywords, repo } = props;
const { token } = theme.useToken();
const [locale, lang] = useLocale(locales);
const isZhCN = lang === 'cn';
const { styles } = useStyle();
// ======================= Issues Count =======================
const { issueCount, issueCountLoading, issueNewUrl, issueSearchUrl } = useIssueCount({
repo,
titleKeywords: searchTitleKeywords,
});
// ========================= Copy =========================
const [copied, setCopied] = React.useState(false);
@@ -98,7 +126,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
if (String(source) === 'true') {
const kebabComponent = kebabCase(component);
return [
`https://github.com/ant-design/ant-design/blob/master/components/${kebabComponent}`,
`https://github.com/${repo}/blob/master/components/${kebabComponent}`,
`components/${kebabComponent}`,
];
}
@@ -108,14 +136,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
}
return [source, source];
}, [component, source]);
const transformComponentName = (componentName: string) => {
if (componentName === 'Notification' || componentName === 'Message') {
return componentName.toLowerCase();
}
return componentName;
};
}, [component, repo, source]);
// ======================== Render ========================
const importList = `import { ${transformComponentName(component)} } from "antd";`;
@@ -126,9 +147,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
colon={false}
column={1}
style={{ marginTop: token.margin }}
styles={{
label: { paddingInlineEnd: token.padding, width: 56 },
}}
styles={{ label: { paddingInlineEnd: token.padding, width: 56 } }}
items={
[
{
@@ -150,10 +169,22 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
filledSource && {
label: locale.source,
children: (
<Typography.Link className={styles.code} href={filledSource} target="_blank">
<GithubOutlined className={styles.icon} />
<span>{abbrSource}</span>
</Typography.Link>
<Flex justify="flex-start" align="center" gap="small">
<Typography.Link className={styles.code} href={filledSource} target="_blank">
<GithubOutlined className={styles.icon} />
<span>{abbrSource}</span>
</Typography.Link>
<Typography.Link className={styles.code} href={issueNewUrl} target="_blank">
<BugOutlined className={styles.icon} />
<span>{locale.issueNew}</span>
</Typography.Link>
<Typography.Link className={styles.code} href={issueSearchUrl} target="_blank">
<IssuesCloseOutlined className={styles.icon} />
<span>
{locale.issueOpen} {issueCountLoading ? <LoadingOutlined /> : issueCount}
</span>
</Typography.Link>
</Flex>
),
},
filename && {
@@ -162,7 +193,7 @@ const ComponentMeta: React.FC<ComponentMetaProps> = (props) => {
<Flex justify="flex-start" align="center" gap="small">
<Typography.Link
className={styles.code}
href={`${branchUrl}${filename}`}
href={`${branchUrl(repo)}${filename}`}
target="_blank"
>
<EditOutlined className={styles.icon} />

View File

@@ -223,6 +223,7 @@ const Overview: React.FC = () => {
>
<div className={styles.componentsOverviewImg}>
<img
draggable={false}
src={
theme.includes('dark') && component.coverDark
? component.coverDark

View File

@@ -62,7 +62,7 @@ const DemoWrapper: typeof DumiDemoGrid = ({ items }) => {
},
});
}, []),
[expandAll, showDebug],
[expandAll, items, showDebug],
);
return (

View File

@@ -0,0 +1,62 @@
import React from 'react';
import { Flex } from 'antd';
import type { FlexProps } from 'antd';
import { createStyles } from 'antd-style';
import classNames from 'classnames';
import ImagePreview from '../ImagePreview';
import type { ImagePreviewProps } from '../ImagePreview';
const isNotEmpty = (val: any) => {
return typeof val !== 'undefined' && val !== null && val !== '';
};
const useStyle = createStyles(({ css, token }) => {
return {
wrapper: css`
color: ${token.colorText};
font-size: ${token.fontSize}px;
line-height: 2;
`,
title: css`
margin: 1em 0;
`,
description: css`
margin: 1em 0;
padding-inline-start: 0.8em;
color: ${token.colorTextSecondary};
font-size: 90%;
border-inline-start: 4px solid ${token.colorSplit};
p {
margin: 0;
}
`,
};
});
interface FlexWithImagePreviewProps {
imagePreviewProps?: ImagePreviewProps;
title?: string;
description?: string;
}
const FlexWithImagePreview: React.FC<
FlexWithImagePreviewProps & React.PropsWithChildren<FlexProps>
> = (props) => {
const { imagePreviewProps, title, description, className, style, children, ...rest } = props;
const { styles } = useStyle();
if (!title && !description) {
return <ImagePreview {...imagePreviewProps}>{children}</ImagePreview>;
}
return (
<Flex className={classNames(styles.wrapper, className)} style={style} {...rest}>
<Flex align="flex-start" justify="flex-start" vertical>
{isNotEmpty(title) && <div className={styles.title}>{title}</div>}
{isNotEmpty(description) && <div className={styles.description}>{description}</div>}
</Flex>
<ImagePreview {...imagePreviewProps}>{children}</ImagePreview>
</Flex>
);
};
export default FlexWithImagePreview;

View File

@@ -30,7 +30,7 @@ interface CategoryProps {
title: CategoriesKeys;
icons: string[];
theme: ThemeType;
newIcons: string[];
newIcons: ReadonlyArray<string> | string[];
}
const Category: React.FC<CategoryProps> = (props) => {
@@ -40,17 +40,20 @@ const Category: React.FC<CategoryProps> = (props) => {
const intl = useIntl();
const [justCopied, setJustCopied] = React.useState<string | null>(null);
const copyId = React.useRef<ReturnType<typeof setTimeout> | null>(null);
const onCopied = React.useCallback((type: string, text: string) => {
message.success(
<span>
<code className={styles.copiedCode}>{text}</code> copied 🎉
</span>,
);
setJustCopied(type);
copyId.current = setTimeout(() => {
setJustCopied(null);
}, 2000);
}, []);
const onCopied = React.useCallback(
(type: string, text: string) => {
message.success(
<span>
<code className={styles.copiedCode}>{text}</code> copied 🎉
</span>,
);
setJustCopied(type);
copyId.current = setTimeout(() => {
setJustCopied(null);
}, 2000);
},
[message, styles.copiedCode],
);
React.useEffect(
() => () => {
if (copyId.current) {

View File

@@ -9,7 +9,9 @@ import debounce from 'lodash/debounce';
import Category from './Category';
import type { CategoriesKeys } from './fields';
import { categories } from './fields';
import { all, categories } from './fields';
import metaInfo from './meta';
import type { IconName, IconsMeta } from './meta';
import { FilledIcon, OutlinedIcon, TwoToneIcon } from './themeIcons';
export enum ThemeType {
@@ -33,6 +35,8 @@ interface IconSearchState {
searchKey: string;
}
const NEW_ICON_NAMES: ReadonlyArray<string> = [];
const IconSearch: React.FC = () => {
const intl = useIntl();
const { styles } = useStyle();
@@ -42,8 +46,6 @@ const IconSearch: React.FC = () => {
});
const token = useTheme();
const newIconNames: string[] = [];
const handleSearchIcon = debounce((e: React.ChangeEvent<HTMLInputElement>) => {
setDisplayState((prevState) => ({ ...prevState, searchKey: e.target.value }));
}, 300);
@@ -54,16 +56,23 @@ const IconSearch: React.FC = () => {
const renderCategories = useMemo<React.ReactNode | React.ReactNode[]>(() => {
const { searchKey = '', theme } = displayState;
// loop over metaInfo to find all the icons which has searchKey in their tags
let normalizedSearchKey = searchKey?.trim();
const categoriesResult = Object.keys(categories)
.map((key) => {
if (normalizedSearchKey) {
normalizedSearchKey = normalizedSearchKey
.replace(/^<([a-z]*)\s\/>$/gi, (_, name) => name)
.replace(/(Filled|Outlined|TwoTone)$/, '')
.toLowerCase();
}
const tagMatchedCategoryObj = matchCategoriesFromTag(normalizedSearchKey, metaInfo);
const namedMatchedCategoryObj = Object.keys(categories).reduce<Record<string, MatchedCategory>>(
(acc, key) => {
let iconList = categories[key as CategoriesKeys];
if (searchKey) {
const matchKey = searchKey
.replace(/^<([a-z]*)\s\/>$/gi, (_, name) => name)
.replace(/(Filled|Outlined|TwoTone)$/, '')
.toLowerCase();
if (normalizedSearchKey) {
const matchKey = normalizedSearchKey;
iconList = iconList.filter((iconName) => iconName.toLowerCase().includes(matchKey));
}
@@ -73,27 +82,42 @@ const IconSearch: React.FC = () => {
];
iconList = iconList.filter((icon) => !ignore.includes(icon));
return {
acc[key] = {
category: key,
icons: iconList
.map((iconName) => iconName + theme)
.filter((iconName) => allIcons[iconName]),
icons: iconList,
};
return acc;
},
{},
);
// merge matched categories from tag search
const merged = mergeCategory(namedMatchedCategoryObj, tagMatchedCategoryObj);
const matchedCategories = Object.values(merged)
.map((item) => {
item.icons = item.icons
.map((iconName) => iconName + theme)
.filter((iconName) => allIcons[iconName]);
return item;
})
.filter(({ icons }) => !!icons.length)
.map(({ category, icons }) => (
<Category
key={category}
title={category as CategoriesKeys}
theme={theme}
icons={icons}
newIcons={newIconNames}
/>
));
.filter(({ icons }) => !!icons.length);
const categoriesResult = matchedCategories.map(({ category, icons }) => (
<Category
key={category}
title={category as CategoriesKeys}
theme={theme}
icons={icons}
newIcons={NEW_ICON_NAMES}
/>
));
return categoriesResult.length ? categoriesResult : <Empty style={{ margin: '2em 0' }} />;
}, [displayState.searchKey, displayState.theme]);
}, [displayState]);
const [searchBarAffixed, setSearchBarAffixed] = useState<boolean | undefined>(false);
const { borderRadius, colorBgContainer, anchorTop } = token;
const affixedStyle: CSSProperties = {
@@ -136,7 +160,10 @@ const IconSearch: React.FC = () => {
onChange={handleChangeTheme}
/>
<Input.Search
placeholder={intl.formatMessage({ id: 'app.docs.components.icon.search.placeholder' })}
placeholder={intl.formatMessage(
{ id: 'app.docs.components.icon.search.placeholder' },
{ total: all.length },
)}
style={{ flex: 1, marginInlineStart: 16 }}
allowClear
autoFocus
@@ -151,3 +178,49 @@ const IconSearch: React.FC = () => {
};
export default IconSearch;
type MatchedCategory = {
category: string;
icons: string[];
};
function matchCategoriesFromTag(searchKey: string, metaInfo: IconsMeta) {
if (!searchKey) {
return {};
}
return Object.keys(metaInfo).reduce<Record<string, MatchedCategory>>((acc, key) => {
const icon = metaInfo[key as IconName];
const category = icon.category;
if (icon.tags.some((tag) => tag.toLowerCase().includes(searchKey))) {
if (acc[category]) {
// if category exists, push icon to icons array
acc[category].icons.push(key);
} else {
// if category does not exist, create a new entry
acc[category] = { category, icons: [key] };
}
}
return acc;
}, {});
}
function mergeCategory(
categoryA: Record<string, MatchedCategory>,
categoryB: Record<string, MatchedCategory>,
) {
const merged: Record<string, MatchedCategory> = { ...categoryA };
Object.keys(categoryB).forEach((key) => {
if (merged[key]) {
// merge icons array and remove duplicates
merged[key].icons = Array.from(new Set([...merged[key].icons, ...categoryB[key].icons]));
} else {
merged[key] = categoryB[key];
}
});
return merged;
}

View File

@@ -1,6 +1,6 @@
import * as AntdIcons from '@ant-design/icons/lib/icons';
const all = Object.keys(AntdIcons)
export const all = Object.keys(AntdIcons)
.map((n) => n.replace(/(Outlined|Filled|TwoTone)$/, ''))
.filter((n, i, arr) => arr.indexOf(n) === i);

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...financial, 'ledger'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...financial],
category: 'logo',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: financial,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { check } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: check,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { check } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: check,
category: 'suggestion',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,7 @@
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: ['time', 'watch', 'alarm'],
category: 'suggestion',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { ellipsis } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...ellipsis, 'feedback', 'discussion', 'reply', 'opinion', 'note'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,7 @@
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: ['复制', 'clone', 'duplicate'],
category: 'editor',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...financial],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { ellipsis } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...ellipsis],
category: 'editor',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: financial,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { ellipsis } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...ellipsis],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: financial,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { ellipsis } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...ellipsis],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { check } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...check],
category: 'suggestion',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { ellipsis } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...ellipsis, 'vertical'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: financial,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: financial,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...financial, 'safety', 'protection', 'security', 'shield'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: financial,
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,7 @@
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: ['ai'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { check } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...check, 'protection', 'security', 'shield', 'safety', 'privacy'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { check } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...check, 'time', 'clock', 'calendar'],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,8 @@
import { financial } from './tags';
import type { IconMetaSchema } from './tags';
export default {
contributors: ['ant-design'],
tags: [...financial],
category: 'other',
} as const satisfies IconMetaSchema;

View File

@@ -0,0 +1,62 @@
import AccountBook from './AccountBook';
import Alipay from './Alipay';
import Bank from './Bank';
import CarryOut from './CarryOut';
import Check from './Check';
import ClockSquare from './ClockSquare';
import Comment from './Comment';
import Copy from './Copy';
import CreditCard from './CreditCard';
import Dash from './Dash';
import Dollar from './Dollar';
import Ellipsis from './Ellipsis';
import Euro from './Euro';
import Holder from './Holder';
import IssuesClose from './IssuesClose';
import More from './More';
import PayCircle from './PayCircle';
import PoundCircle from './PoundCircle';
import PropertySafety from './PropertySafety';
import RedEnvelope from './RedEnvelope';
import Robot from './Robot';
import Safety from './Safety';
import Schedule from './Schedule';
import Transaction from './Transaction';
const all = {
AccountBook,
Alipay,
AlipayCircle: Alipay,
Bank,
CarryOut,
Check,
CheckCircle: Check,
CheckSquare: Check,
ClockSquare,
Comment,
Copy,
CreditCard,
Dash,
SmallDash: Dash,
Dollar,
Ellipsis,
Euro,
EuroCircle: Euro,
Holder,
IssuesClose,
More,
PayCircle,
PoundCircle,
Pound: PoundCircle,
PropertySafety,
RedEnvelope,
Robot,
Safety,
Schedule,
Transaction,
};
export type IconsMeta = typeof all;
export type IconName = keyof IconsMeta;
export default all;

View File

@@ -0,0 +1,87 @@
import type { CategoriesKeys } from '../fields';
export type IconMetaSchema = Readonly<{
contributors: string[];
tags: readonly string[];
category: CategoriesKeys;
}>;
export const check = [
'check',
'done',
'todo',
'tick',
'complete',
'finish',
'task',
'ok',
'success',
'confirm',
'approve',
'agree',
'validation',
'√',
'✔',
'✓',
'勾',
'对',
'正确',
'right',
] as const;
export const financial = [
'monetization',
'marketing',
'currency',
'money',
'payment',
'finance',
'cash',
'bank',
'transaction',
'balance',
'expense',
'income',
'budget',
'investment',
'savings',
'profit',
'cost',
'wealth',
'economy',
'wallet',
'exchange',
] as const;
export const ellipsis = [
'...',
'。。。',
'…',
'more',
'更多',
'dots',
'ellipsis',
'expand',
'collapse',
'menu',
'dropdown',
'options',
'settings',
'et cetera',
'etc',
'loader',
'loading',
'progress',
'pending',
'throbber',
'spinner',
'operator',
'code',
'spread',
'rest',
'further',
'extra',
'overflow',
] as const;

View File

@@ -3,7 +3,7 @@ import { Image } from 'antd';
import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
interface ImagePreviewProps {
export interface ImagePreviewProps {
className?: string;
/** Do not show padding & background */
pure?: boolean;
@@ -65,7 +65,7 @@ const ImagePreview: React.FC<React.PropsWithChildren<ImagePreviewProps>> = (prop
return (
<div key={index}>
<div className="image-modal-container">
<img {...metaCopy} src={meta.src} alt={meta.alt} />
<img {...metaCopy} draggable={false} src={meta.src} alt={meta.alt} />
</div>
</div>
);

View File

@@ -39,7 +39,7 @@ const LocaleLink: React.FC<React.PropsWithChildren<LocaleLinkProps>> = ({
}
return to;
}, [to]);
}, [localeType, to]);
const linkProps: LocaleLinkProps = {
...props,

View File

@@ -1,20 +1,21 @@
import React, { useRef, Suspense } from 'react';
import React, { Suspense, useRef } from 'react';
import { LinkOutlined, ThunderboltOutlined } from '@ant-design/icons';
import stackblitzSdk from '@stackblitz/sdk';
import type { Project } from '@stackblitz/sdk';
import { Flex, Tooltip } from 'antd';
import { FormattedMessage, useSiteData } from 'dumi';
import LZString from 'lz-string';
import stackblitzSdk from '@stackblitz/sdk';
import type { Project } from '@stackblitz/sdk';
import DemoContext from '../../slots/DemoContext';
import packageJson from '../../../../package.json';
import useLocale from '../../../hooks/useLocale';
import ClientOnly from '../../common/ClientOnly';
import CodePenIcon from '../../icons/CodePenIcon';
import CodeSandboxIcon from '../../icons/CodeSandboxIcon';
import ExternalLinkIcon from '../../icons/ExternalLinkIcon';
import ExpandIcon from '../../icons/ExpandIcon';
import ClientOnly from '../../common/ClientOnly';
import ExternalLinkIcon from '../../icons/ExternalLinkIcon';
import DemoContext from '../../slots/DemoContext';
import CodeBlockButton from './CodeBlockButton';
import getStackblitzConfig from './stackblitzConfig';
const track = ({ type, demo }: { type: string; demo: string }) => {
window.gtag?.('event', 'demo', { event_category: type, event_label: demo });
@@ -54,6 +55,8 @@ const Actions: React.FC<ActionsProps> = ({
entryCode,
styleCode,
}) => {
const [, lang] = useLocale();
const isZhCN = lang === 'cn';
const { pkg } = useSiteData();
const { codeType } = React.use(DemoContext);
const codeSandboxIconRef = useRef<HTMLFormElement>(null);
@@ -78,18 +81,6 @@ const Actions: React.FC<ActionsProps> = ({
</html>
`;
const tsconfig = {
compilerOptions: {
target: 'esnext',
module: 'esnext',
esModuleInterop: true,
moduleResolution: 'node',
jsx: 'react',
jsxFactory: 'React.createElement',
jsxFragmentFactory: 'React.Fragment',
},
};
const suffix = codeType === 'tsx' ? 'tsx' : 'js';
const dependencies = (jsx as string).split('\n').reduce<Record<PropertyKey, string>>(
@@ -161,7 +152,7 @@ const Actions: React.FC<ActionsProps> = ({
}
const demoJsContent = `
${importReactContent}
import './index.css';
${styleCode ? `import './index.css';` : ''}
${parsedSourceCode}
`.trim();
const indexCssContent = (styleCode || '')
@@ -213,9 +204,8 @@ createRoot(document.getElementById('container')).render(<Demo />);
},
};
const stackblitzPrefillConfig: Project = {
const stackblitzPrefillConfig: Project = getStackblitzConfig({
title: `${title} - antd@${dependencies.antd}`,
template: 'create-react-app',
dependencies: {
...dependencies,
react: '^19.0.0',
@@ -224,18 +214,11 @@ createRoot(document.getElementById('container')).render(<Demo />);
'@types/react-dom': '^19.0.0',
'@ant-design/v5-patch-for-react-19': '^1.0.3',
},
description: '',
files: {
'index.css': indexCssContent,
[`index.${suffix}`]: `import '@ant-design/v5-patch-for-react-19';\n${indexJsContent}`,
[`demo.${suffix}`]: demoJsContent,
'index.html': html,
},
};
if (suffix === 'tsx') {
stackblitzPrefillConfig.files['tsconfig.json'] = JSON.stringify(tsconfig, null, 2);
}
demoJsContent,
indexCssContent,
suffix,
isZhCN,
});
return (
<Flex wrap gap="middle" className="code-box-actions">
@@ -287,7 +270,7 @@ createRoot(document.getElementById('container')).render(<Demo />);
onClick={() => {
track({ type: 'stackblitz', demo: assetId });
stackblitzSdk.openProject(stackblitzPrefillConfig, {
openFile: [`demo.${suffix}`],
openFile: [`src/demo.${suffix === 'tsx' ? 'tsx' : 'jsx'}`],
});
}}
>

View File

@@ -1,4 +1,4 @@
import React, { Suspense, useState } from 'react';
import React, { Suspense, useMemo, useState } from 'react';
import { LoadingOutlined } from '@ant-design/icons';
import { App, Tooltip } from 'antd';
import { FormattedMessage } from 'dumi';
@@ -27,17 +27,19 @@ const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies =
const [locale] = useLocale(locales);
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(<ComponentDemo />);\n`,
css: '',
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
};
const codeBlockPrefillConfig = useMemo(() => {
return {
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(<ComponentDemo />);\n`,
css: '',
json: JSON.stringify({ name: 'antd-demo', dependencies }, null, 2),
};
}, [dependencies, jsx, title]);
const openHituCodeBlockFn = React.useCallback(() => {
setLoading(false);
@@ -52,8 +54,7 @@ const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies =
const handleClick = () => {
const scriptId = 'hitu-code-block-js';
const existScript = document.getElementById(scriptId) as HTMLScriptElement | null;
// @ts-ignore
const existScript = document.getElementById(scriptId) as HTMLScriptElement;
if (existScript?.dataset.loaded) {
openHituCodeBlockFn();
return;
@@ -86,7 +87,7 @@ const CodeBlockButton: React.FC<CodeBlockButtonProps> = ({ title, dependencies =
);
};
const SuspenseCodeBlockButton: React.FC<React.ComponentProps<typeof CodeBlockButton>> = (props) => (
const SuspenseCodeBlockButton: React.FC<CodeBlockButtonProps> = (props) => (
<Suspense fallback={null}>
<CodeBlockButton {...props} />
</Suspense>

View File

@@ -98,7 +98,7 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
if (asset.id === hash.slice(1)) {
anchorRef.current?.click();
}
}, []);
}, [asset.id, hash]);
useEffect(() => {
setCodeExpand(expand);
@@ -142,7 +142,12 @@ const CodePreviewer: React.FC<AntdPreviewerProps> = (props) => {
const codeBox: React.ReactNode = (
<section className={codeBoxClass} id={asset.id}>
<section className="code-box-demo" style={codeBoxDemoStyle} ref={demoContainer}>
<section
className="code-box-demo notranslate"
translate="no"
style={codeBoxDemoStyle}
ref={demoContainer}
>
{liveDemoNode || <React.StrictMode>{previewDemo.current}</React.StrictMode>}
</section>
{!simplify && (

View File

@@ -0,0 +1,209 @@
import type { Project, ProjectFiles } from '@stackblitz/sdk';
const getStackblitzConfig = ({
title = '',
dependencies,
indexCssContent = '',
demoJsContent = '',
suffix = '',
isZhCN = false,
}: {
title?: string;
dependencies: Record<string, string>;
indexCssContent?: string;
demoJsContent?: string;
suffix?: string;
isZhCN?: boolean;
}) => {
const _suffix = suffix === 'tsx' ? suffix : 'jsx';
const packageJSON = {
name: 'vite-react-typescript-starter',
private: true,
version: '0.0.0',
type: 'module',
scripts: {
dev: 'vite',
build: 'tsc -b && vite build',
lint: 'eslint .',
preview: 'vite preview',
},
dependencies,
devDependencies: {
'@eslint/js': '^9.32.0',
'@types/react': '^19.1.9',
'@types/react-dom': '^19.1.7',
'@vitejs/plugin-react': '^4.7.0',
eslint: '^9.32.0',
'eslint-plugin-react-hooks': '^7.0.0',
'eslint-plugin-react-refresh': '^0.4.20',
globals: '^16.3.0',
typescript: '~5.8.3',
'typescript-eslint': '^8.39.0',
vite: '^7.0.6',
},
};
const tsconfigAppJSON = {
compilerOptions: {
tsBuildInfoFile: './node_modules/.tmp/tsconfig.app.tsbuildinfo',
target: 'ES2022',
useDefineForClassFields: true,
lib: ['ES2022', 'DOM', 'DOM.Iterable'],
module: 'ESNext',
skipLibCheck: true,
/* Bundler mode */
moduleResolution: 'bundler',
allowImportingTsExtensions: true,
verbatimModuleSyntax: true,
moduleDetection: 'force',
noEmit: true,
jsx: 'react-jsx',
/* Linting */
strict: true,
noUnusedLocals: true,
noUnusedParameters: true,
erasableSyntaxOnly: true,
noFallthroughCasesInSwitch: true,
noUncheckedSideEffectImports: true,
},
include: ['src'],
};
const tsconfigNodeJSON = {
compilerOptions: {
tsBuildInfoFile: './node_modules/.tmp/tsconfig.node.tsbuildinfo',
target: 'ES2023',
lib: ['ES2023'],
module: 'ESNext',
skipLibCheck: true,
/* Bundler mode */
moduleResolution: 'bundler',
allowImportingTsExtensions: true,
verbatimModuleSyntax: true,
moduleDetection: 'force',
noEmit: true,
/* Linting */
strict: true,
noUnusedLocals: true,
noUnusedParameters: true,
erasableSyntaxOnly: true,
noFallthroughCasesInSwitch: true,
noUncheckedSideEffectImports: true,
},
include: ['vite.config.ts'],
};
const tsconfigJSON = {
files: [],
references: [{ path: './tsconfig.app.json' }, { path: './tsconfig.node.json' }],
};
let files: ProjectFiles = {
// demo.tsx
[`src/demo.${_suffix}`]: demoJsContent,
// package.json
'package.json': JSON.stringify(packageJSON, null, 4),
// index.html
'index.html': `<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#000000">
</head>
<body>
<div id="container" style="padding: 24px" />
<script type="module" src="/src/main.${_suffix}"></script>
</body>
</html>`,
// main.tsx
[`src/main.${_suffix}`]: `import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import '@ant-design/v5-patch-for-react-19';
import Demo from './demo';
createRoot(document.getElementById('container')${suffix === 'tsx' ? '!' : ''}).render(
<StrictMode>
<Demo />
</StrictMode>
);`,
// vite.config.ts
'vite.config.ts': `import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})`,
// .stackblitzrc
'.stackblitzrc': `{
"installDependencies": false,
"startCommand": "pnpm i & pnpm dev",
"env": {
"NODE_ENV": "development"
}
}`,
// .gitignore
'.gitignore': `# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local`,
// eslint.config.js
'eslint.config.js': `import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { globalIgnores } from 'eslint/config'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx,js,jsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
`,
};
if (suffix === 'tsx') {
files = {
...files,
'tsconfig.json': JSON.stringify(tsconfigJSON, null, 4),
'tsconfig.app.json': JSON.stringify(tsconfigAppJSON, null, 4),
'tsconfig.node.json': JSON.stringify(tsconfigNodeJSON, null, 4),
};
}
if (indexCssContent) {
files = { ...files, 'src/index.css': indexCssContent };
}
if (isZhCN) {
files = { ...files, '.npmrc': `registry=https://registry.npmmirror.com/` };
}
const project: Project = { title, description: '', template: 'node', files };
return project;
};
export default getStackblitzConfig;

View File

@@ -2,7 +2,8 @@ import * as React from 'react';
import { BugOutlined } from '@ant-design/icons';
import { Button, Flex, Popover, theme } from 'antd';
import { createStyles } from 'antd-style';
import dayjs, { Dayjs } from 'dayjs';
import dayjs from 'dayjs';
import type { Dayjs } from 'dayjs';
import useLocale from '../../../hooks/useLocale';
import { matchDeprecated } from '../../utils';
@@ -118,7 +119,10 @@ const Version: React.FC<React.PropsWithChildren> = ({ children }) => {
const DateComp: React.FC<React.PropsWithChildren> = (props) => props.children;
const DetailsComp: React.FC<React.PropsWithChildren> = (props) => props.children;
const DetailsComp: React.FC<React.PropsWithChildren<HTMLDivElement>> = (props) => {
const { children, className } = props;
return <div className={className}>{children}</div>;
};
export default Object.assign(RefinedChangelog, {
Version,

View File

@@ -1,12 +1,12 @@
import * as React from 'react';
import { Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
import { Alert, Avatar, Divider, Empty, Skeleton, Tabs } from 'antd';
import { createStyles } from 'antd-style';
import dayjs from 'dayjs';
import { FormattedMessage } from 'dumi';
import useLocale from '../../../hooks/useLocale';
import type { Article, Authors, SiteData } from '../../../pages/index/components/util';
import { useSiteData } from '../../../pages/index/components/util';
import { useAntdSiteConfig } from '../../../pages/index/components/util';
const useStyle = createStyles(({ token, css }) => {
const { antCls } = token;
@@ -92,7 +92,7 @@ const ArticleList: React.FC<ArticleListProps> = ({ name, data = [], authors = []
);
};
const Articles: React.FC<{ data: Partial<SiteData> }> = ({ data }) => {
const Articles: React.FC<{ data?: Partial<SiteData> }> = ({ data = {} }) => {
const [, lang] = useLocale();
const isZhCN = lang === 'cn';
@@ -107,7 +107,7 @@ const Articles: React.FC<{ data: Partial<SiteData> }> = ({ data }) => {
yearData[year][article.type] = [...(yearData[year][article.type] || []), article];
});
return yearData;
}, [articles]);
}, [articles, lang]);
const yearList = Object.keys(mergedData).sort((a, b) => Number(b) - Number(a));
@@ -145,15 +145,27 @@ const Articles: React.FC<{ data: Partial<SiteData> }> = ({ data }) => {
);
};
export default () => {
const ResourceArticles: React.FC = () => {
const { styles } = useStyle();
const data = useSiteData();
const articles = data ? <Articles data={data} /> : <Skeleton active />;
const { data, error, isLoading } = useAntdSiteConfig();
if (isLoading) {
return <Skeleton active />;
}
if (error) {
return (
<Alert
showIcon
type="error"
message={error.message}
description={process.env.NODE_ENV !== 'production' ? error.stack : undefined}
/>
);
}
return (
<div id="articles" className={styles.articles}>
{articles}
<Articles data={data} />
</div>
);
};
export default ResourceArticles;

View File

@@ -83,7 +83,11 @@ const ResourceCard: React.FC<ResourceCardProps> = ({ resource }) => {
return (
<Col xs={24} sm={12} md={8} lg={6}>
<a className={styles.card} target="_blank" href={src} rel="noreferrer">
<Card hoverable className={styles.card} cover={<img src={cover} alt={title} />}>
<Card
hoverable
className={styles.card}
cover={<img draggable={false} src={cover} alt={title} />}
>
<Card.Meta
title={title}
description={

View File

@@ -31,7 +31,7 @@ const useStyle = createStyles(({ token, css }) => {
align-items: center;
justify-content: center;
color: rgba(0, 0, 0, 0.88);
border-right: 1px solid rgba(0, 0, 0, 0.1);
border-inline-end: 1px solid rgba(0, 0, 0, 0.1);
`,
colDark: css`
@@ -55,7 +55,7 @@ const useStyle = createStyles(({ token, css }) => {
});
function color2Rgba(color: string) {
return `#${new FastColor(color).toHexString().toUpperCase()}`;
return new FastColor(color).toHexString().toUpperCase();
}
interface ColorCircleProps {
@@ -88,16 +88,15 @@ const TokenCompare: React.FC<TokenCompareProps> = (props) => {
const darkTokens = theme.getDesignToken({ algorithm: theme.darkAlgorithm });
return list.map((tokenName) => {
const meta = tokenMeta.global[tokenName];
const meta = (tokenMeta.global as any)[tokenName];
const name = lang === 'cn' ? meta.name : meta.nameEn;
return {
name: name.replace('颜色', '').replace('色', '').replace('Color', '').trim(),
light: color2Rgba(lightTokens[tokenName]),
dark: color2Rgba(darkTokens[tokenName]),
light: color2Rgba((lightTokens as any)[tokenName]),
dark: color2Rgba((darkTokens as any)[tokenName]),
};
});
}, [tokenNames]);
}, [lang, tokenNames]);
return (
<div className={styles.container}>

View File

@@ -1,14 +1,26 @@
import React, { useEffect, useRef } from 'react';
import { RightCircleOutlined } from '@ant-design/icons';
import type { TreeGraph } from '@antv/g6';
import { Flex } from 'antd';
import { createStyles, css } from 'antd-style';
import { useRouteMeta } from 'dumi';
import useLocale from '../../../hooks/useLocale';
import { renderReactToHTMLString } from '../../../theme/utils/renderReactToHTML';
const dataTransform = (data: BehaviorMapItem) => {
const changeData = (d: any, level = 0) => {
const clonedData: any = {
...d,
};
interface BehaviorMapItem {
id: string;
label: string;
targetType?: 'mvp' | 'extension';
children?: BehaviorMapItem[];
link?: string;
collapsed?: boolean;
type?: 'behavior-start-node' | 'behavior-sub-node';
}
const dataTransform = (rootData: BehaviorMapItem) => {
const changeData = (data: BehaviorMapItem, level = 0) => {
const clonedData: BehaviorMapItem = { ...data };
switch (level) {
case 0:
clonedData.type = 'behavior-start-node';
@@ -21,21 +33,12 @@ const dataTransform = (data: BehaviorMapItem) => {
clonedData.type = 'behavior-sub-node';
break;
}
if (d.children) {
clonedData.children = d.children.map((child: any) => changeData(child, level + 1));
if (Array.isArray(data.children)) {
clonedData.children = data.children.map((child) => changeData(child, level + 1));
}
return clonedData;
};
return changeData(data);
};
type BehaviorMapItem = {
id: string;
label: string;
targetType?: 'mvp' | 'extension';
children?: BehaviorMapItem[];
link?: string;
return changeData(rootData);
};
const useStyle = createStyles(({ token }) => ({
@@ -102,16 +105,19 @@ const locales = {
},
};
export type BehaviorMapProps = {
export interface BehaviorMapProps {
data: BehaviorMapItem;
};
}
const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
const ref = useRef<HTMLDivElement>(null);
const { styles } = useStyle();
const [locale] = useLocale(locales);
const meta = useRouteMeta();
const graphRef = useRef<TreeGraph>(null);
useEffect(() => {
import('@antv/g6').then((G6) => {
G6.registerNode('behavior-start-node', {
@@ -230,25 +236,11 @@ const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
y: -8,
cursor: 'pointer',
// DOM's html
html: `
<div style="width: 16px; height: 16px;">
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="DatePicker" transform="translate(-890.000000, -441.000000)" fill-rule="nonzero">
<g id="编组-30" transform="translate(288.000000, 354.000000)">
<g id="编组-7备份-7" transform="translate(522.000000, 79.000000)">
<g id="right-circle-outlinedd" transform="translate(80.000000, 8.000000)">
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
<path d="M10.4171875,7.8984375 L6.5734375,5.1171875 C6.490625,5.0578125 6.375,5.115625 6.375,5.21875 L6.375,5.9515625 C6.375,6.1109375 6.4515625,6.2625 6.58125,6.35625 L8.853125,8 L6.58125,9.64375 C6.4515625,9.7375 6.375,9.8875 6.375,10.0484375 L6.375,10.78125 C6.375,10.8828125 6.490625,10.9421875 6.5734375,10.8828125 L10.4171875,8.1015625 C10.4859375,8.0515625 10.4859375,7.9484375 10.4171875,7.8984375 Z" id="路径" fill="#BFBFBF"></path>
<path d="M8,1 C4.134375,1 1,4.134375 1,8 C1,11.865625 4.134375,15 8,15 C11.865625,15 15,11.865625 15,8 C15,4.134375 11.865625,1 8,1 Z M8,13.8125 C4.790625,13.8125 2.1875,11.209375 2.1875,8 C2.1875,4.790625 4.790625,2.1875 8,2.1875 C11.209375,2.1875 13.8125,4.790625 13.8125,8 C13.8125,11.209375 11.209375,13.8125 8,13.8125 Z" id="形状" fill="#BFBFBF"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
</div>
`,
html: renderReactToHTMLString(
<Flex align="center" justify="center">
<RightCircleOutlined style={{ color: '#BFBFBF' }} />
</Flex>,
),
},
// 在 G6 3.3 及之后的版本中,必须指定 name可以是任意字符串但需要在同一个自定义元素类型中保持唯一性
name: 'sub-node-link',
@@ -267,25 +259,11 @@ const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
hover: {
stroke: '#1677ff',
'sub-node-link': {
html: `
<div style="width: 16px; height: 16px;">
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="DatePicker" transform="translate(-890.000000, -441.000000)" fill-rule="nonzero">
<g id="编组-30" transform="translate(288.000000, 354.000000)">
<g id="编组-7备份-7" transform="translate(522.000000, 79.000000)">
<g id="right-circle-outlinedd" transform="translate(80.000000, 8.000000)">
<rect id="矩形" fill="#000000" opacity="0" x="0" y="0" width="16" height="16"></rect>
<path d="M10.4171875,7.8984375 L6.5734375,5.1171875 C6.490625,5.0578125 6.375,5.115625 6.375,5.21875 L6.375,5.9515625 C6.375,6.1109375 6.4515625,6.2625 6.58125,6.35625 L8.853125,8 L6.58125,9.64375 C6.4515625,9.7375 6.375,9.8875 6.375,10.0484375 L6.375,10.78125 C6.375,10.8828125 6.490625,10.9421875 6.5734375,10.8828125 L10.4171875,8.1015625 C10.4859375,8.0515625 10.4859375,7.9484375 10.4171875,7.8984375 Z" id="路径" fill="#1677ff"></path>
<path d="M8,1 C4.134375,1 1,4.134375 1,8 C1,11.865625 4.134375,15 8,15 C11.865625,15 15,11.865625 15,8 C15,4.134375 11.865625,1 8,1 Z M8,13.8125 C4.790625,13.8125 2.1875,11.209375 2.1875,8 C2.1875,4.790625 4.790625,2.1875 8,2.1875 C11.209375,2.1875 13.8125,4.790625 13.8125,8 C13.8125,11.209375 11.209375,13.8125 8,13.8125 Z" id="形状" fill="#1677ff"></path>
</g>
</g>
</g>
</g>
</g>
</svg>
</div>
`,
html: renderReactToHTMLString(
<Flex align="center" justify="center">
<RightCircleOutlined style={{ color: '#1677ff' }} />
</Flex>,
),
},
},
},
@@ -293,7 +271,7 @@ const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
},
'rect',
);
const graph = new G6.TreeGraph({
graphRef.current = new G6.TreeGraph({
container: ref.current!,
width: ref.current!.scrollWidth,
height: ref.current!.scrollHeight,
@@ -303,10 +281,7 @@ const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
},
defaultEdge: {
type: 'cubic-horizontal',
style: {
lineWidth: 1,
stroke: '#BFBFBF',
},
style: { lineWidth: 1, stroke: '#BFBFBF' },
},
layout: {
type: 'mindmap',
@@ -319,24 +294,26 @@ const BehaviorMap: React.FC<BehaviorMapProps> = ({ data }) => {
},
});
graph.on('node:mouseenter', (e) => {
graph.setItemState(e.item!, 'hover', true);
graphRef.current?.on('node:mouseenter', (e) => {
graphRef.current?.setItemState(e.item!, 'hover', true);
});
graph.on('node:mouseleave', (e) => {
graph.setItemState(e.item!, 'hover', false);
graphRef.current?.on('node:mouseleave', (e) => {
graphRef.current?.setItemState(e.item!, 'hover', false);
});
graph.on('node:click', (e) => {
graphRef.current?.on('node:click', (e) => {
const { link } = e.item!.getModel();
if (link) {
window.location.hash = link as string;
}
});
graph.data(dataTransform(data));
graph.render();
graph.fitCenter();
graphRef.current?.data(dataTransform(data));
graphRef.current?.render();
graphRef.current?.fitCenter();
});
}, []);
return () => {
graphRef.current?.destroy();
};
}, [data]);
return (
<div ref={ref} className={styles.container}>

View File

@@ -27,7 +27,12 @@ const BezierVisualizer = (props: BezierVisualizerProps) => {
const controls = useMemo(() => {
const m = RE.exec(value.toLowerCase().trim());
if (m) {
return m[1].split(',').map((v) => parseFloat(v.trim())) as [number, number, number, number];
return m[1].split(',').map((v) => Number.parseFloat(v.trim())) as [
number,
number,
number,
number,
];
}
return null;
}, [value]);

View File

@@ -36,6 +36,15 @@ const useStyle = createStyles(({ token, css }) => ({
& > * {
display: block;
}
[data-prefers-color='dark'] & {
border-top: 2em solid rgba(80, 80, 80, 0.7);
box-shadow: 0 0.1em 0.5em 0 rgba(0, 0, 0, 0.6);
background-color: #000; /* 可选 */
&::after {
background-color: #333;
}
}
`,
}));

View File

@@ -1,6 +1,6 @@
import type { ComponentProps } from 'react';
import React, { useEffect, useMemo } from 'react';
import { Button, Tabs, Typography } from 'antd';
import { Tabs, Typography } from 'antd';
import { createStyles } from 'antd-style';
import toReactElement from 'jsonml-to-react-element';
import JsonML from 'jsonml.js/lib/utils';
@@ -109,12 +109,16 @@ const CodePreview: React.FC<CodePreviewProps> = ({
}
const [highlightedCodes, setHighlightedCodes] = React.useState(initialCodes);
const { codeType, setCodeType } = React.use(DemoContext);
const sourceCodes = {
// omit trailing line break
tsx: sourceCode?.trim(),
jsx: jsxCode?.trim(),
style: styleCode?.trim(),
} as Record<'tsx' | 'jsx' | 'style', string>;
const sourceCodes = useMemo<Record<'tsx' | 'jsx' | 'style', string>>(() => {
return {
// omit trailing line break
tsx: sourceCode?.trim(),
jsx: jsxCode?.trim(),
style: styleCode?.trim(),
};
}, [sourceCode, jsxCode, styleCode]);
useEffect(() => {
const codes = {
tsx: Prism.highlight(sourceCode, Prism.languages.javascript, 'jsx'),
@@ -153,13 +157,24 @@ const CodePreview: React.FC<CodePreviewProps> = ({
) : (
toReactComponent(['pre', { lang, highlighted: highlightedCodes[lang] }])
)}
<Button type="text" className={styles.copyButton}>
{/* button 嵌套 button 会导致水合失败,这里需要用 div 标签,不能用 button */}
<div className={styles.copyButton}>
<Typography.Text className={styles.copyIcon} copyable={{ text: sourceCodes[lang] }} />
</Button>
</div>
</div>
),
})),
[JSON.stringify(highlightedCodes), styles.code, styles.copyButton, styles.copyIcon],
// eslint-disable-next-line react-hooks/exhaustive-deps
[
entryName,
error,
highlightedCodes,
langList,
sourceCodes,
styles.code,
styles.copyButton,
styles.copyIcon,
],
);
if (!langList.length) {

View File

@@ -45,7 +45,7 @@ const ColorPaletteTool: React.FC = () => {
}
}
return <span className="color-palette-picker-validation">{text.trim()}</span>;
}, [primaryColorInstance, primaryMinSaturation, primaryMinBrightness]);
}, [primaryColorInstance, locale]);
return (
<div className="color-palette-horizontal">
<div className="color-palette-pick">

View File

@@ -54,7 +54,7 @@ const ColorPaletteTool: React.FC = () => {
{text.trim()}
</span>
);
}, [primaryColorInstance]);
}, [locale, primaryColorInstance]);
return (
<div className="color-palette-horizontal color-palette-horizontal-dark">

View File

@@ -1,89 +1,115 @@
import React from 'react';
import React, { useMemo } from 'react';
import classNames from 'classnames';
import useLocale from '../../../hooks/useLocale';
import Palette from './Palette';
const colors = [
{
name: 'red',
english: 'Dust Red',
chinese: '薄暮',
description: '斗志、奔放',
const COLOR_KEYS = [
'red',
'volcano',
'orange',
'lime',
'gold',
'yellow',
'green',
'cyan',
'blue',
'geekblue',
'purple',
'magenta',
] as const;
const locales = {
cn: {
redTitle: '薄暮',
redDescription: '斗志、奔放',
volcanoTitle: '火山',
volcanoDescription: '醒目、澎湃',
orangeTitle: '日暮',
orangeDescription: '温暖、欢快',
limeTitle: '青柠',
limeDescription: '自然、生机',
goldTitle: '金盏花',
goldDescription: '活力、积极',
yellowTitle: '日出',
yellowDescription: '出生、阳光',
greenTitle: '极光绿',
greenDescription: '健康、创新',
cyanTitle: '明青',
cyanDescription: '希望、坚强',
blueTitle: '拂晓蓝',
blueDescription: '包容、科技、普惠',
geekblueTitle: '极客蓝',
geekblueDescription: '探索、钻研',
purpleTitle: '酱紫',
purpleDescription: '优雅、浪漫',
magentaTitle: '法式洋红',
magentaDescription: '明快、感性',
},
{
name: 'volcano',
english: 'Volcano',
chinese: '火山',
description: '醒目、澎湃',
en: {
redTitle: 'Dust Red',
redDescription: 'Fighting Spirit, Unrestrained',
volcanoTitle: 'Volcano',
volcanoDescription: 'Eye-catching, Surging',
orangeTitle: 'Sunset Orange',
orangeDescription: 'Warm, Cheerful',
limeTitle: 'Lime',
limeDescription: 'Natural, Vitality',
goldTitle: 'Calendula Gold',
goldDescription: 'Energetic, Positive',
yellowTitle: 'Sunrise Yellow',
yellowDescription: 'Birth, Sunshine',
greenTitle: 'Polar Green',
greenDescription: 'Healthy, Innovative',
cyanTitle: 'Cyan',
cyanDescription: 'Hope, Strong',
blueTitle: 'Daybreak Blue',
blueDescription: 'Inclusive, Technology, Universal',
geekblueTitle: 'Geek Blue',
geekblueDescription: 'Exploration, Research',
purpleTitle: 'Golden Purple',
purpleDescription: 'Elegant, Romantic',
magentaTitle: 'French Magenta',
magentaDescription: 'Bright, Emotional',
},
{
name: 'orange',
english: 'Sunset Orange',
chinese: '日暮',
description: '温暖、欢快',
},
{
name: 'gold',
english: 'Calendula Gold',
chinese: '金盏花',
description: '活力、积极',
},
{
name: 'yellow',
english: 'Sunrise Yellow',
chinese: '日出',
description: '出生、阳光',
},
{
name: 'lime',
english: 'Lime',
chinese: '青柠',
description: '自然、生机',
},
{
name: 'green',
english: 'Polar Green',
chinese: '极光绿',
description: '健康、创新',
},
{
name: 'cyan',
english: 'Cyan',
chinese: '明青',
description: '希望、坚强',
},
{
name: 'blue',
english: 'Daybreak Blue',
chinese: '拂晓蓝',
description: '包容、科技、普惠',
},
{
name: 'geekblue',
english: 'Geek Blue',
chinese: '极客蓝',
description: '探索、钻研',
},
{
name: 'purple',
english: 'Golden Purple',
chinese: '酱紫',
description: '优雅、浪漫',
},
{
name: 'magenta',
english: 'Magenta',
chinese: '法式洋红',
description: '明快、感性',
},
];
};
const ColorPalettes: React.FC<{ dark?: boolean }> = (props) => {
const { dark } = props;
const [locale] = useLocale(locales);
const memoizedColors = useMemo(() => {
return COLOR_KEYS.map((key) => ({
name: key,
title: locale[`${key}Title`],
description: locale[`${key}Description`],
}));
}, [locale]);
return (
<div className={classNames('color-palettes', { 'color-palettes-dark': dark })}>
{colors.map((color) => (
<Palette key={color.name} color={color} dark={dark} showTitle />
{memoizedColors.map((color) => (
<Palette key={`item-${color.name}`} color={color} dark={dark} showTitle />
))}
</div>
);

View File

@@ -10,7 +10,7 @@ interface ColorPatternsProps {
backgroundColor?: string;
}
const ColorPatterns: React.FC<ColorPatternsProps> = ({ color, dark, backgroundColor }) => {
const ColorPatterns: React.FC<ColorPatternsProps> = ({ color = '', dark, backgroundColor }) => {
const colors = generate(color, dark ? { theme: 'dark', backgroundColor } : {});
return (
<>

View File

@@ -8,9 +8,9 @@ const rgbToHex = (rgbString: string): string => {
if (!rgb) {
return '';
}
let r = parseInt(rgb[0], 10).toString(16);
let g = parseInt(rgb[1], 10).toString(16);
let b = parseInt(rgb[2], 10).toString(16);
let r = Number.parseInt(rgb[0], 10).toString(16);
let g = Number.parseInt(rgb[1], 10).toString(16);
let b = Number.parseInt(rgb[2], 10).toString(16);
r = r.length === 1 ? `0${r}` : r;
g = g.length === 1 ? `0${g}` : g;
b = b.length === 1 ? `0${b}` : b;
@@ -21,22 +21,19 @@ interface PaletteProps {
showTitle?: boolean;
direction?: 'horizontal' | 'vertical';
dark?: boolean;
count?: number;
color?: {
name: string;
count?: number;
name?: string;
title?: string;
description?: string;
english?: string;
chinese?: string;
};
}
const Palette: React.FC<PaletteProps> = (props) => {
const {
showTitle,
direction,
dark,
color: { name, count = 10, description, english, chinese } = { name: 'gray', count: 13 },
} = props;
const { showTitle, direction, dark, count = 10, color = {} } = props;
const { name = 'gray', title, description } = color;
const [hexColors, setHexColors] = React.useState<Record<PropertyKey, string>>({});
const colorNodesRef = React.useRef<Record<PropertyKey, HTMLDivElement>>({});
const { message } = App.useApp();
@@ -44,28 +41,28 @@ const Palette: React.FC<PaletteProps> = (props) => {
useEffect(() => {
const colors: Record<string, string> = {};
Object.keys(colorNodesRef.current || {}).forEach((key) => {
const computedColor = getComputedStyle(colorNodesRef.current[key])['background-color'];
if (computedColor.includes('rgba')) {
colors[key] = computedColor;
const { backgroundColor } = getComputedStyle(colorNodesRef.current[key]);
if (backgroundColor.includes('rgba')) {
colors[key] = backgroundColor;
} else {
colors[key] = rgbToHex(computedColor);
colors[key] = rgbToHex(backgroundColor);
}
});
setHexColors(colors);
}, []);
const className = direction === 'horizontal' ? 'color-palette-horizontal' : 'color-palette';
const colors: React.ReactNode[] = [];
const colorName = `${english} / ${chinese}`;
const colorPaletteMap = {
dark: ['#fff', 'unset'],
default: ['rgba(0, 0, 0, 0.85)', '#fff'],
};
const [lastColor, firstColor] = dark ? colorPaletteMap.dark : colorPaletteMap.default;
for (let i = 1; i <= count; i += 1) {
const colorText = `${name}-${i}`;
const defaultBgStyle = dark ? presetDarkPalettes[name][i - 1] : '';
colors.push(
const colors: React.ReactNode[] = Array.from({ length: count }, (_, i) => {
const colorText = `${name}-${i + 1}`;
const defaultBgStyle = dark && name ? presetDarkPalettes[name][i] : '';
return (
<CopyToClipboard
text={hexColors[colorText]}
onCopy={() => message.success(`@${colorText} copied: ${hexColors[colorText]}`)}
@@ -89,15 +86,16 @@ const Palette: React.FC<PaletteProps> = (props) => {
<span className="main-color-text">{colorText}</span>
<span className="main-color-value">{hexColors[colorText]}</span>
</div>
</CopyToClipboard>,
</CopyToClipboard>
);
}
});
return (
<div className={className}>
{showTitle && (
<div className="color-title">
{colorName}
<span className="color-description">{description}</span>
{title}
{description && <span className="color-description">{description}</span>}
</div>
)}
<div className="main-color">{colors}</div>

View File

@@ -3,8 +3,8 @@ import { BugOutlined } from '@ant-design/icons';
import { Button, Drawer, Flex, Grid, Popover, Tag, Timeline, Typography } from 'antd';
import type { TimelineItemProps } from 'antd';
import { createStyles } from 'antd-style';
import useSWR from 'swr';
import useFetch from '../../../hooks/useFetch';
import useLocale from '../../../hooks/useLocale';
import useLocation from '../../../hooks/useLocation';
import { matchDeprecated } from '../../utils';
@@ -189,6 +189,7 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
<RefLinks refs={refs} contributors={contributors} />
<br />
<img
draggable={false}
src={imgElement?.getAttribute('src') || ''}
alt={imgElement?.getAttribute('alt') || ''}
width={imgElement?.getAttribute('width') || ''}
@@ -211,17 +212,23 @@ const RenderChangelogList: React.FC<{ changelogList: ChangelogInfo[] }> = ({ cha
const useChangelog = (componentPath: string, lang: 'cn' | 'en'): ChangelogInfo[] => {
const logFileName = `components-changelog-${lang}.json`;
const data = useFetch({
key: `component-changelog-${lang}`,
request: () => import(`../../../preset/${logFileName}`),
});
return React.useMemo(() => {
const component = componentPath.replace(/-/g, '');
const componentName = Object.keys(data).find(
(name) => name.toLowerCase() === component.toLowerCase(),
);
return data[componentName as keyof typeof data] as ChangelogInfo[];
}, [data, componentPath]);
const { data, error, isLoading } = useSWR(
`component-changelog-${lang}`,
() => import(`../../../preset/${logFileName}`),
);
if (error || isLoading) {
return [];
}
const component = componentPath.replace(/-/g, '');
const componentName = Object.keys(data).find(
(name) => name.toLowerCase() === component.toLowerCase(),
);
if (!componentName) {
return [];
}
return data?.[componentName] || [];
};
const ComponentChangelog: React.FC<Readonly<React.PropsWithChildren>> = (props) => {
@@ -294,7 +301,17 @@ const ComponentChangelog: React.FC<Readonly<React.PropsWithChildren>> = (props)
),
};
});
}, [list]);
}, [
lang,
list,
locale.bugList,
styles.bug,
styles.bugReasonList,
styles.bugReasonTitle,
styles.versionTag,
styles.versionTitle,
styles.versionWrap,
]);
const screens = Grid.useBreakpoint();
const width = screens.md ? '48vw' : '90vw';

View File

@@ -10,9 +10,7 @@ const Editor: React.FC<JSONEditorPropsOptional> = (props) => {
if (container.current) {
editorRef.current = createJSONEditor({
target: container.current,
props: {
mode: Mode.text,
},
props: { mode: Mode.text },
});
}
return () => {
@@ -22,7 +20,7 @@ const Editor: React.FC<JSONEditorPropsOptional> = (props) => {
useEffect(() => {
editorRef.current?.updateProps(props);
}, [props.content]);
}, [props]);
return <div ref={container} className="vanilla-jsoneditor-react" />;
};

View File

@@ -1,6 +1,6 @@
import type { MouseEvent, MouseEventHandler } from 'react';
import React, { useMemo, forwardRef } from 'react';
import { Link as DumiLink, useLocation, useAppData, useNavigate } from 'dumi';
import React, { forwardRef, useMemo } from 'react';
import { Link as DumiLink, useAppData, useLocation, useNavigate } from 'dumi';
export interface LinkProps {
to: string | { pathname?: string; search?: string; hash?: string };
@@ -21,7 +21,7 @@ const Link = forwardRef<HTMLAnchorElement, React.PropsWithChildren<LinkProps>>(
return `${to.pathname || pathname}${to.search || ''}${to.hash || ''}`;
}
return to;
}, [to]);
}, [pathname, to]);
const onClick = (e: MouseEvent<HTMLAnchorElement>) => {
rest.onClick?.(e);
if (!href?.startsWith('http')) {

View File

@@ -16,6 +16,7 @@ const Loading: React.FC = () => {
width={40}
height={40}
alt="loading"
draggable={false}
style={{ marginBottom: 24, filter: 'grayscale(1)', opacity: 0.33 }}
/>
<Skeleton active paragraph={{ rows: 3 }} />

View File

@@ -55,7 +55,7 @@ const Markers: React.FC<MarkersProps> = (props) => {
},
);
});
}, [targetClassName]);
}, [containerRef, targetClassName]);
// ======================== Render =========================
return (

View File

@@ -33,9 +33,7 @@ const Block: React.FC<BlockProps> = ({ component: Component, options, defaultVal
defaultValue={defaultValue}
getPopupContainer={() => divRef.current}
options={options}
styles={{
popup: { zIndex: 1 },
}}
styles={{ popup: { zIndex: 1 } }}
/>
</div>
);

View File

@@ -18,7 +18,7 @@ const useStyle = createStyles(({ token }) => ({
position: relative;
`,
colWrap: css`
border-right: 1px solid ${token.colorBorderSecondary};
border-inline-end: 1px solid ${token.colorBorderSecondary};
display: flex;
justify-content: center;
align-items: center;
@@ -101,7 +101,7 @@ function HighlightExample(props: {
}
return Prism.highlight(code, Prism.languages.javascript, 'jsx');
}, [componentName, semanticName]);
}, [componentName, itemsAPI, semanticName]);
return (
// biome-ignore lint: lint/security/noDangerouslySetInnerHtml

View File

@@ -1,5 +1,11 @@
import React, { use, useRef } from 'react';
import { BgColorsOutlined, LinkOutlined, SmileOutlined, SunOutlined } from '@ant-design/icons';
import {
BgColorsOutlined,
LinkOutlined,
SmileOutlined,
SunOutlined,
SyncOutlined,
} from '@ant-design/icons';
import { Badge, Button, Dropdown } from 'antd';
import type { MenuProps } from 'antd';
import { CompactTheme, DarkTheme } from 'antd-token-previewer/es/icons';
@@ -8,11 +14,14 @@ import { FormattedMessage, useLocation } from 'dumi';
import useThemeAnimation from '../../../hooks/useThemeAnimation';
import type { SiteContextProps } from '../../slots/SiteContext';
import SiteContext from '../../slots/SiteContext';
import { getLocalizedPathname, isZhCN } from '../../utils';
import { getLocalizedPathname, isZhCN, isLocalStorageNameSupported } from '../../utils';
import Link from '../Link';
import ThemeIcon from './ThemeIcon';
export type ThemeName = 'light' | 'dark' | 'compact' | 'motion-off' | 'happy-work';
export type ThemeName = 'light' | 'dark' | 'auto' | 'compact' | 'motion-off' | 'happy-work';
// 主题持久化存储键名
const ANT_DESIGN_SITE_THEME = 'ant-design-site-theme';
export interface ThemeSwitchProps {
value?: ThemeName[];
@@ -29,10 +38,16 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
// 主题选项配置
const themeOptions = [
{
id: 'app.theme.switch.default',
id: 'app.theme.switch.auto',
icon: <SyncOutlined />,
key: 'auto',
showBadge: () => theme.includes('auto'),
},
{
id: 'app.theme.switch.light',
icon: <SunOutlined />,
key: 'light',
showBadge: () => theme.includes('light') || theme.length === 0,
showBadge: () => theme.includes('light'),
},
{
id: 'app.theme.switch.dark',
@@ -100,20 +115,32 @@ const ThemeSwitch: React.FC<ThemeSwitchProps> = () => {
return;
}
// 亮色/暗色模式切换时应用动画效果
if (key === 'dark' || key === 'light') {
lastThemeKey.current = key;
toggleAnimationTheme(domEvent, theme.includes('dark'));
}
const themeKey = key as ThemeName;
// 亮色/暗色模式是互斥的
if (['light', 'dark'].includes(key)) {
const filteredTheme = theme.filter((t) => !['light', 'dark'].includes(t));
// 亮色/暗色/自动模式是互斥的
if (['light', 'dark', 'auto'].includes(key)) {
// 校验当前主题是否包含要切换的主题(避免 timeout in DOM update
if (theme.includes(themeKey)) {
return;
}
// 亮色/暗色模式切换时应用动画效果
if (['light', 'dark'].includes(key)) {
lastThemeKey.current = key;
toggleAnimationTheme(domEvent, theme.includes('dark'));
}
const filteredTheme = theme.filter((t) => !['light', 'dark', 'auto'].includes(t));
const newTheme = [...filteredTheme, themeKey];
updateSiteConfig({
theme: [...filteredTheme, themeKey],
theme: newTheme,
});
// 持久化到 localStorage
if (isLocalStorageNameSupported()) {
localStorage.setItem(ANT_DESIGN_SITE_THEME, themeKey);
}
} else {
// 其他主题选项是开关式的
const hasTheme = theme.includes(themeKey);

View File

@@ -18,7 +18,7 @@ const GlobalStyle: React.FC = () => {
font-size: ${token.fontSize}px;
line-height: 2;
}
.highlight {
line-height: 1.5;
}
@@ -208,13 +208,13 @@ const GlobalStyle: React.FC = () => {
padding-inline-start: 0.8em;
color: ${token.colorTextSecondary};
font-size: 90%;
border-left: 4px solid ${token.colorSplit};
border-inline-start: 4px solid ${token.colorSplit};
.rtl & {
padding-inline-end: 0.8em;
padding-inline-start: 0;
border-right: 4px solid ${token.colorSplit};
border-left: none;
border-inline-end: 4px solid ${token.colorSplit};
border-inline-start: none;
}
}
@@ -298,11 +298,11 @@ const GlobalStyle: React.FC = () => {
border: 1px solid ${token.colorSplit};
&:first-child {
border-left: 1px solid ${token.colorSplit};
border-inline-start: 1px solid ${token.colorSplit};
}
&:last-child {
border-right: 1px solid ${token.colorSplit};
border-inline-end: 1px solid ${token.colorSplit};
}
img {
@@ -381,23 +381,23 @@ const GlobalStyle: React.FC = () => {
}
}
/*
/*
Api 表中某些属性用 del 标记,表示已废弃(但仍期望给开发者一个过渡期)用 css 标记出来。仅此而已。
有更多看法?移步讨论区: https://github.com/ant-design/ant-design/discussions/51298
*/
tr:has(td:first-child > del) {
color: ${token.colorWarning} !important;
background-color: ${token.colorWarningBg} !important;
display: var(--antd-site-api-deprecated-display, none);
tr:has(td:first-child > del) {
color: ${token.colorWarning} !important;
background-color: ${token.colorWarningBg} !important;
display: var(--antd-site-api-deprecated-display, none);
del {
color: ${token.colorWarning};
}
&:hover del {
text-decoration: none;
}
del {
color: ${token.colorWarning};
}
&:hover del {
text-decoration: none;
}
}
}
.grid-demo,

View File

@@ -20,7 +20,7 @@ export default () => {
.spinner-icon {
border-top-color: ${token.colorPrimary};
border-left-color: ${token.colorPrimary};
border-inline-start-color: ${token.colorPrimary};
}
}
`}

View File

@@ -9,59 +9,55 @@ export default () => {
<Global
styles={css`
@font-face {
font-weight: normal;
font-family: AlibabaPuHuiTi;
src:
url('//at.alicdn.com/t/webfont_6e11e43nfj.woff2') format('woff2'),
url('//at.alicdn.com/t/webfont_6e11e43nfj.woff') format('woff'),
/* chrome、firefox */ url('//at.alicdn.com/t/webfont_6e11e43nfj.ttf') format('truetype'); /* chrome、firefox、opera、Safari, Android, iOS 4.2+ */
font-family: 'AlibabaSans';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url('//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*1GSgSYDD_aIAAAAAQsAAAAgAegCCAQ/AlibabaSans-Light.woff2')
format('woff2');
}
@font-face {
font-weight: bold;
font-family: AlibabaPuHuiTi;
src:
url('//at.alicdn.com/t/webfont_exesdog9toj.woff2') format('woff2'),
url('//at.alicdn.com/t/webfont_exesdog9toj.woff') format('woff'),
/* chrome、firefox */ url('//at.alicdn.com/t/webfont_exesdog9toj.ttf')
format('truetype'); /* chrome、firefox、opera、Safari, Android, iOS 4.2+ */
font-family: 'AlibabaSans';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url('//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*2zEUQqnPNesAAAAAQtAAAAgAegCCAQ/AlibabaSans-Regular.woff2')
format('woff2');
}
// 组件丰富选用自如定制主题随心所欲设计语言与研发框架1234567890 QWERTYUIOPLKJHGFDSAZXCVBNM,.mnbvcxzasdfghjklpoiuytrewq
/* CDN 服务仅供平台体验和调试使用,平台不承诺服务的稳定性,企业客户需下载字体包自行发布使用并做好备份。 */
@font-face {
font-weight: 900;
font-family: 'AliPuHui';
src:
url('//at.alicdn.com/wf/webfont/exMpJIukiCms/Gsw2PSKrftc1yNWMNlXgw.woff2')
format('woff2'),
url('//at.alicdn.com/wf/webfont/exMpJIukiCms/vtu73by4O2gEBcvBuLgeu.woff') format('woff');
font-family: 'AlibabaSans';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url('//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Medium.woff2')
format('woff2');
}
@font-face {
font-family: 'AlibabaSans';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url('//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Bold.woff2')
format('woff2');
}
@font-face {
font-family: 'AlibabaSans';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url('//mdn.alipayobjects.com/huamei_iwk9zp/afts/file/A*E_cxRbMlZqUAAAAAQuAAAAgAegCCAQ/AlibabaSans-Heavy.woff2')
format('woff2');
}
html {
direction: initial;
@supports (overflow-x: clip) {
overflow-x: clip;
}
&.rtl {
direction: rtl;
}
}
body {
@supports (overflow-x: clip) {
overflow-x: clip;
}
@supports not (overflow-x: clip) {
overflow-x: hidden;
}
overflow-x: hidden;
color: ${token.colorText};
font-size: ${token.fontSize}px;
font-family: ${token.fontFamily};

View File

@@ -66,7 +66,7 @@ export default () => {
float: none;
width: auto;
padding-bottom: 30px;
border-right: 0;
border-inline-end: 0;
}
.ant-row-rtl {

View File

@@ -1,10 +1,10 @@
export { default as HeadingAnchor } from './HeadingAnchor';
export { default as Reset } from './Reset';
export { default as Common } from './Common';
export { default as Markdown } from './Markdown';
export { default as Highlight } from './Highlight';
export { default as Demo } from './Demo';
export { default as Responsive } from './Responsive';
export { default as HeadingAnchor } from './HeadingAnchor';
export { default as Highlight } from './Highlight';
export { default as Markdown } from './Markdown';
export { default as NProgress } from './NProgress';
export { default as PreviewImage } from './PreviewImage';
export { default as Reset } from './Reset';
export { default as Responsive } from './Responsive';
export { default as SearchBar } from './SearchBar';

View File

@@ -4,16 +4,15 @@ import dayjs from 'dayjs';
import 'dayjs/locale/zh-cn';
import React, { useEffect, useLayoutEffect, useRef } from 'react';
import ConfigProvider from 'antd/es/config-provider';
import { ConfigProvider, theme } from 'antd';
import zhCN from 'antd/es/locale/zh_CN';
import { Helmet, useOutlet, useSiteData } from 'dumi';
import { Helmet, useOutlet, useSearchParams, useSiteData } from 'dumi';
import useLocale from '../../../hooks/useLocale';
import useLocation from '../../../hooks/useLocation';
import GlobalStyles from '../../common/GlobalStyles';
import Header from '../../slots/Header';
import SiteContext from '../../slots/SiteContext';
import IndexLayout from '../IndexLayout';
import ResourceLayout from '../ResourceLayout';
import SidebarLayout from '../SidebarLayout';
@@ -38,6 +37,9 @@ const DocLayout: React.FC = () => {
const timerRef = useRef<ReturnType<typeof setTimeout>>(null!);
const { direction } = React.use(SiteContext);
const { loading } = useSiteData();
const { token } = theme.useToken();
const [searchParams] = useSearchParams();
const hideLayout = searchParams.get('layout') === 'false';
useLayoutEffect(() => {
if (lang === 'cn') {
@@ -45,7 +47,7 @@ const DocLayout: React.FC = () => {
} else {
dayjs.locale('en');
}
}, []);
}, [lang]);
useEffect(() => {
const nprogressHiddenStyle = document.getElementById('nprogress-style');
@@ -67,13 +69,10 @@ const DocLayout: React.FC = () => {
if (typeof (window as any).ga !== 'undefined') {
(window as any).ga('send', 'pageview', pathname + search);
}
}, [location]);
}, [pathname, search]);
const content = React.useMemo<React.ReactNode>(() => {
if (
['', '/'].some((path) => path === pathname) ||
['/index'].some((path) => pathname.startsWith(path))
) {
if (['', '/'].includes(pathname) || ['/index'].some((path) => pathname.startsWith(path))) {
return (
<IndexLayout title={locale.title} desc={locale.description}>
{outlet}
@@ -87,7 +86,7 @@ const DocLayout: React.FC = () => {
return outlet;
}
return <SidebarLayout>{outlet}</SidebarLayout>;
}, [pathname, outlet]);
}, [pathname, outlet, locale.title, locale.description]);
return (
<>
@@ -108,9 +107,13 @@ const DocLayout: React.FC = () => {
content="https://gw.alipayobjects.com/zos/rmsportal/rlpTLlbMzTNYuZGGCVYM.png"
/>
</Helmet>
<ConfigProvider direction={direction} locale={lang === 'cn' ? zhCN : undefined}>
<ConfigProvider
direction={direction}
locale={lang === 'cn' ? zhCN : undefined}
theme={{ token: { fontFamily: `AlibabaSans, ${token.fontFamily}` } }}
>
<GlobalStyles />
<Header />
{!hideLayout && <Header />}
{content}
</ConfigProvider>
</>

View File

@@ -1,6 +1,3 @@
// prettier-ignore
import { scan } from 'react-scan'; // import this BEFORE react
import React, { useCallback, useEffect } from 'react';
import {
createCache,
@@ -23,21 +20,18 @@ import type { ThemeName } from '../common/ThemeSwitch';
import SiteThemeProvider from '../SiteThemeProvider';
import type { SiteContextProps } from '../slots/SiteContext';
import SiteContext from '../slots/SiteContext';
import { isLocalStorageNameSupported } from '../utils';
import '@ant-design/v5-patch-for-react-19';
type Entries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][];
type SiteState = Partial<Omit<SiteContextProps, 'updateSiteContext'>>;
type SiteState = Partial<Omit<SiteContextProps, 'updateSiteConfig'>>;
const RESPONSIVE_MOBILE = 768;
export const ANT_DESIGN_NOT_SHOW_BANNER = 'ANT_DESIGN_NOT_SHOW_BANNER';
const getSystemTheme = (): 'dark' | 'light' => {
if (typeof window === 'undefined') {
return 'light';
}
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
};
// 主题持久化存储键名
const ANT_DESIGN_SITE_THEME = 'ant-design-site-theme';
// Compatible with old anchors
if (typeof window !== 'undefined') {
@@ -47,13 +41,6 @@ if (typeof window !== 'undefined') {
location.hash = `#${hashId.replace(/^components-/, '')}`;
}
}
if (process.env.NODE_ENV !== 'production') {
scan({
enabled: false,
showToolbar: true,
});
}
}
const getAlgorithm = (themes: ThemeName[] = []) =>
@@ -69,6 +56,23 @@ const getAlgorithm = (themes: ThemeName[] = []) =>
})
.filter(Boolean);
// 获取最终主题优先级URL Query > Local Storage > Site (Memory)
const getFinalTheme = (urlTheme: ThemeName[]): ThemeName[] => {
// 只认 light/dark
const baseTheme = urlTheme.filter((t) => !['light', 'dark', 'auto'].includes(t));
const urlColor = urlTheme.find((t) => t === 'light' || t === 'dark');
if (urlColor) return [...baseTheme, urlColor];
if (isLocalStorageNameSupported()) {
const stored = localStorage.getItem(ANT_DESIGN_SITE_THEME) as ThemeName;
if (stored && ['light', 'dark', 'auto'].includes(stored)) {
return [...baseTheme, stored];
}
}
// 默认 auto
return [...baseTheme, 'auto'];
};
const GlobalLayout: React.FC = () => {
const outlet = useOutlet();
const [searchParams, setSearchParams] = useSearchParams();
@@ -80,8 +84,6 @@ const GlobalLayout: React.FC = () => {
bannerVisible: false,
});
const [systemTheme, setSystemTheme] = React.useState<'dark' | 'light'>(() => getSystemTheme());
// TODO: This can be remove in v6
const useCssVar = searchParams.get('cssVar') !== 'false';
@@ -89,10 +91,9 @@ const GlobalLayout: React.FC = () => {
(props: SiteState) => {
setSiteState((prev) => ({ ...prev, ...props }));
// updating `searchParams` will clear the hash
const oldSearchStr = searchParams.toString();
let nextSearchParams: URLSearchParams = searchParams;
(Object.entries(props) as Entries<SiteContextProps>).forEach(([key, value]) => {
if (key === 'direction') {
if (value === 'rtl') {
@@ -102,14 +103,18 @@ const GlobalLayout: React.FC = () => {
}
}
if (key === 'theme') {
nextSearchParams = createSearchParams({
...nextSearchParams,
theme: value.filter((t) => t !== 'light'),
});
document
.querySelector('html')
?.setAttribute('data-prefers-color', value.includes('dark') ? 'dark' : 'light');
const arr = Array.isArray(value) ? value : [value];
const base = arr.filter((t) => !['light', 'dark', 'auto'].includes(t));
const color = arr.find((t) => t === 'light' || t === 'dark');
if (color) {
nextSearchParams = createSearchParams({ ...nextSearchParams, theme: [...base, color] });
} else {
nextSearchParams.delete('theme');
}
// 设置 data-prefers-color
if (color) {
document.querySelector('html')?.setAttribute('data-prefers-color', color);
}
}
});
@@ -117,13 +122,15 @@ const GlobalLayout: React.FC = () => {
setSearchParams(nextSearchParams);
}
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[searchParams, setSearchParams],
);
const updateMobileMode = () => {
const updateMobileMode = useCallback(() => {
updateSiteConfig({ isMobile: window.innerWidth < RESPONSIVE_MOBILE });
};
}, [updateSiteConfig]);
// 监听系统主题变化
useEffect(() => {
if (typeof window === 'undefined') {
return;
@@ -131,48 +138,32 @@ const GlobalLayout: React.FC = () => {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
const handleSystemThemeChange = (e: MediaQueryListEvent) => {
const newSystemTheme = e.matches ? 'dark' : 'light';
setSystemTheme(newSystemTheme);
const urlTheme = searchParams.getAll('theme') as ThemeName[];
const hasUserColorTheme = urlTheme.includes('dark') || urlTheme.includes('light');
if (!hasUserColorTheme) {
setSiteState((prev) => ({
...prev,
theme: [...urlTheme.filter((t) => t !== 'dark' && t !== 'light'), newSystemTheme],
}));
document.documentElement.setAttribute(
'data-prefers-color',
newSystemTheme === 'dark' ? 'dark' : 'light',
);
}
};
const handleSystemThemeChange = () => {};
mediaQuery.addEventListener('change', handleSystemThemeChange);
return () => {
mediaQuery.removeEventListener('change', handleSystemThemeChange);
};
}, [searchParams, setSiteState]);
}, []);
// 主题初始化
useEffect(() => {
const _theme = searchParams.getAll('theme') as ThemeName[];
const hasUserColorTheme = _theme.includes('dark') || _theme.includes('light');
const finalTheme = hasUserColorTheme
? _theme
: [..._theme.filter((t) => t !== 'dark' && t !== 'light'), systemTheme];
const urlTheme = searchParams.getAll('theme') as ThemeName[];
const finalTheme = getFinalTheme(urlTheme);
const _direction = searchParams.get('direction') as DirectionType;
setSiteState({
theme: finalTheme,
direction: _direction === 'rtl' ? 'rtl' : 'ltr',
});
document.documentElement.setAttribute(
'data-prefers-color',
finalTheme.includes('dark') ? 'dark' : 'light',
);
// 设置 data-prefers-color 属性
const colorTheme = finalTheme.find((t) => ['light', 'dark'].includes(t));
if (colorTheme) {
document.documentElement.setAttribute('data-prefers-color', colorTheme);
}
// Handle isMobile
updateMobileMode();
@@ -186,7 +177,8 @@ const GlobalLayout: React.FC = () => {
return () => {
window.removeEventListener('resize', updateMobileMode);
};
}, [systemTheme]);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchParams, updateMobileMode]);
const siteContextValue = React.useMemo<SiteContextProps>(
() => ({
@@ -199,17 +191,18 @@ const GlobalLayout: React.FC = () => {
[isMobile, direction, updateSiteConfig, theme, bannerVisible],
);
const themeConfig = React.useMemo<ThemeConfig>(
() => ({
algorithm: getAlgorithm(theme),
const themeConfig = React.useMemo<ThemeConfig>(() => {
// 算法优先级auto 时用系统主题算法
const themeForAlgorithm = theme;
return {
algorithm: getAlgorithm(themeForAlgorithm),
token: { motion: !theme.includes('motion-off') },
cssVar: useCssVar,
hashed: !useCssVar,
}),
[theme],
);
};
}, [theme, useCssVar]);
const [styleCache] = React.useState(() => createCache());
const styleCache = React.useMemo(() => createCache(), []);
useServerInsertedHTML(() => {
const styleText = extractStyle(styleCache, {

Some files were not shown because too many files have changed in this diff Show More