@aloudata/aloudata-design 3.0.27 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Button/index.js +10 -4
- package/dist/Button/index.js.map +1 -1
- package/dist/Checkbox/index.js +8 -2
- package/dist/Checkbox/index.js.map +1 -1
- package/dist/Collapse/index.js +68 -22
- package/dist/Collapse/index.js.map +1 -1
- package/dist/Dropdown/index.js +54 -87
- package/dist/Dropdown/index.js.map +1 -1
- package/dist/Input/components/Input/index.js +11 -5
- package/dist/Input/components/Input/index.js.map +1 -1
- package/dist/Input/components/TextArea/index.js +8 -1
- package/dist/Input/components/TextArea/index.js.map +1 -1
- package/dist/InputNumber/index.js +9 -2
- package/dist/InputNumber/index.js.map +1 -1
- package/dist/Pagination/PageSizeChanger.d.ts +1 -0
- package/dist/Pagination/PageSizeChanger.js +3 -2
- package/dist/Pagination/PageSizeChanger.js.map +1 -1
- package/dist/Pagination/index.js +33 -19
- package/dist/Pagination/index.js.map +1 -1
- package/dist/Pagination/types.d.ts +3 -0
- package/dist/Radio/components/Radio/index.js +1 -1
- package/dist/Radio/components/Radio/index.js.map +1 -1
- package/dist/Select/BaseSelect.js +12 -12
- package/dist/Select/BaseSelect.js.map +1 -1
- package/dist/Select/Selector/FixedOverflow.d.ts +1 -0
- package/dist/Select/Selector/FixedOverflow.js +3 -3
- package/dist/Select/Selector/FixedOverflow.js.map +1 -1
- package/dist/Select/Selector/MultipleSelector.js +1 -0
- package/dist/Select/Selector/MultipleSelector.js.map +1 -1
- package/dist/Steps/index.js +66 -14
- package/dist/Steps/index.js.map +1 -1
- package/dist/Switch/index.js +8 -1
- package/dist/Switch/index.js.map +1 -1
- package/dist/Table/components/Cell.js +8 -3
- package/dist/Table/components/Cell.js.map +1 -1
- package/dist/Table/components/ExpandCell.js +6 -2
- package/dist/Table/components/ExpandCell.js.map +1 -1
- package/dist/Table/components/Footer/index.js +2 -1
- package/dist/Table/components/Footer/index.js.map +1 -1
- package/dist/Table/components/Header.js +26 -18
- package/dist/Table/components/Header.js.map +1 -1
- package/dist/Table/hooks/useRowSelection.js +14 -7
- package/dist/Table/hooks/useRowSelection.js.map +1 -1
- package/dist/Table/index.js +8 -2
- package/dist/Table/index.js.map +1 -1
- package/dist/Tabs/index.d.ts +1 -1
- package/dist/Tabs/index.js +91 -11
- package/dist/Tabs/index.js.map +1 -1
- package/dist/aloudata-design.css +1 -1
- package/dist/locale/default.d.ts +6 -0
- package/dist/locale/en_US.d.ts +6 -0
- package/dist/locale/en_US.js +6 -0
- package/dist/locale/en_US.js.map +1 -1
- package/dist/locale/zh_CN.d.ts +6 -0
- package/dist/locale/zh_CN.js +6 -0
- package/dist/locale/zh_CN.js.map +1 -1
- package/dist/theme/contract/controlStateColorArtifact.d.ts +73 -0
- package/dist/theme/contract/controlStateColorArtifact.js +2 -0
- package/dist/theme/contract/focusRingArtifact.d.ts +51 -0
- package/dist/theme/contract/focusRingArtifact.js +2 -0
- package/dist/theme/contract/tokenOutputContract.d.ts +1 -1
- package/dist/theme/contract/tokenOutputContract.js +4 -0
- package/dist/theme/contract/tokenOutputContract.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +3 -0
- package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +3 -0
- package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
- package/dist/theme/runtime/themeToCssVars.js +3 -0
- package/dist/theme/runtime/themeToCssVars.js.map +1 -1
- package/package.json +1 -1
|
@@ -4,7 +4,7 @@ import { useContext } from "react";
|
|
|
4
4
|
import { jsx } from "react/jsx-runtime";
|
|
5
5
|
//#region src/Pagination/PageSizeChanger.tsx
|
|
6
6
|
var PAGE_SIZE_CHANGER_POPUP_WIDTH = 128;
|
|
7
|
-
var PageSizeChanger = ({ pageSize, pageSizeOptions, onChange, className, disabled = false }) => {
|
|
7
|
+
var PageSizeChanger = ({ pageSize, pageSizeOptions, onChange, className, disabled = false, ariaLabel }) => {
|
|
8
8
|
const { locale } = useContext(LocaleContext);
|
|
9
9
|
const t = getTranslator(locale);
|
|
10
10
|
const optionSet = new Set([...pageSizeOptions, pageSize]);
|
|
@@ -24,7 +24,8 @@ var PageSizeChanger = ({ pageSize, pageSizeOptions, onChange, className, disable
|
|
|
24
24
|
disabled,
|
|
25
25
|
className: `ald-pagination-page-size-changer ${className || ""}`.trim(),
|
|
26
26
|
placeholder: t.Pagination.selectPageSize,
|
|
27
|
-
popupMatchSelectWidth: PAGE_SIZE_CHANGER_POPUP_WIDTH
|
|
27
|
+
popupMatchSelectWidth: PAGE_SIZE_CHANGER_POPUP_WIDTH,
|
|
28
|
+
"aria-label": ariaLabel
|
|
28
29
|
});
|
|
29
30
|
};
|
|
30
31
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageSizeChanger.js","names":[],"sources":["../../src/Pagination/PageSizeChanger.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport Select from '../Select';\nimport { ISelectProps } from '../Select/interface';\nimport { LocaleContext, getTranslator } from '../locale/default';\n\nconst PAGE_SIZE_CHANGER_POPUP_WIDTH = 128;\n\ninterface IPageSizeChangerProps {\n // 当前 pageSize\n pageSize: number;\n // pageSize 选项\n pageSizeOptions: (string | number)[];\n // pageSize 变化的回调\n onChange: (size: number) => void;\n // 自定义样式类名\n className?: string;\n // 是否禁用\n disabled?: boolean;\n}\n\nconst PageSizeChanger: React.FC<IPageSizeChangerProps> = ({\n pageSize,\n pageSizeOptions,\n onChange,\n className,\n disabled = false,\n}) => {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n // 将 pageSizeOptions 转换为 Select 可用的选项格式\n // 确保当前 pageSize 值在选项中存在\n const optionSet = new Set([...pageSizeOptions, pageSize]);\n const allOptions = Array.from(optionSet).sort(\n (a, b) => Number(a) - Number(b),\n );\n const selectOptions = allOptions.map((option) => ({\n label: `${option} ${t.Pagination.itemsPerPage}`,\n value: String(option),\n }));\n\n const handleChange = (value: string) => {\n const newSize = parseInt(value, 10);\n if (!isNaN(newSize) && newSize !== pageSize) {\n onChange(newSize);\n }\n };\n\n const selectProps: ISelectProps = {\n value: String(pageSize),\n onChange: handleChange,\n options: selectOptions,\n width: 112,\n disabled,\n className: `ald-pagination-page-size-changer ${className || ''}`.trim(),\n placeholder: t.Pagination.selectPageSize,\n popupMatchSelectWidth: PAGE_SIZE_CHANGER_POPUP_WIDTH,\n };\n\n return <Select {...selectProps} />;\n};\n\nexport default PageSizeChanger;\n"],"mappings":";;;;;AAKA,IAAM,gCAAgC;
|
|
1
|
+
{"version":3,"file":"PageSizeChanger.js","names":[],"sources":["../../src/Pagination/PageSizeChanger.tsx"],"sourcesContent":["import React, { useContext } from 'react';\nimport Select from '../Select';\nimport { ISelectProps } from '../Select/interface';\nimport { LocaleContext, getTranslator } from '../locale/default';\n\nconst PAGE_SIZE_CHANGER_POPUP_WIDTH = 128;\n\ninterface IPageSizeChangerProps {\n // 当前 pageSize\n pageSize: number;\n // pageSize 选项\n pageSizeOptions: (string | number)[];\n // pageSize 变化的回调\n onChange: (size: number) => void;\n // 自定义样式类名\n className?: string;\n // 是否禁用\n disabled?: boolean;\n // 页大小选择器的可访问名称\n ariaLabel?: string;\n}\n\nconst PageSizeChanger: React.FC<IPageSizeChangerProps> = ({\n pageSize,\n pageSizeOptions,\n onChange,\n className,\n disabled = false,\n ariaLabel,\n}) => {\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n\n // 将 pageSizeOptions 转换为 Select 可用的选项格式\n // 确保当前 pageSize 值在选项中存在\n const optionSet = new Set([...pageSizeOptions, pageSize]);\n const allOptions = Array.from(optionSet).sort(\n (a, b) => Number(a) - Number(b),\n );\n const selectOptions = allOptions.map((option) => ({\n label: `${option} ${t.Pagination.itemsPerPage}`,\n value: String(option),\n }));\n\n const handleChange = (value: string) => {\n const newSize = parseInt(value, 10);\n if (!isNaN(newSize) && newSize !== pageSize) {\n onChange(newSize);\n }\n };\n\n const selectProps: ISelectProps = {\n value: String(pageSize),\n onChange: handleChange,\n options: selectOptions,\n width: 112,\n disabled,\n className: `ald-pagination-page-size-changer ${className || ''}`.trim(),\n placeholder: t.Pagination.selectPageSize,\n popupMatchSelectWidth: PAGE_SIZE_CHANGER_POPUP_WIDTH,\n 'aria-label': ariaLabel,\n };\n\n return <Select {...selectProps} />;\n};\n\nexport default PageSizeChanger;\n"],"mappings":";;;;;AAKA,IAAM,gCAAgC;AAiBtC,IAAM,mBAAoD,EACxD,UACA,iBACA,UACA,WACA,WAAW,OACX,gBACI;CACJ,MAAM,EAAE,WAAW,WAAW,cAAc;CAC5C,MAAM,IAAI,cAAc,OAAO;CAI/B,MAAM,YAAY,IAAI,IAAI,CAAC,GAAG,iBAAiB,SAAS,CAAC;CAIzD,MAAM,gBAHa,MAAM,KAAK,UAAU,CAAC,MACtC,GAAG,MAAM,OAAO,EAAE,GAAG,OAAO,EAAE,CAChC,CACgC,KAAK,YAAY;EAChD,OAAO,GAAG,OAAO,GAAG,EAAE,WAAW;EACjC,OAAO,OAAO,OAAO;EACtB,EAAE;CAEH,MAAM,gBAAgB,UAAkB;EACtC,MAAM,UAAU,SAAS,OAAO,GAAG;AACnC,MAAI,CAAC,MAAM,QAAQ,IAAI,YAAY,SACjC,UAAS,QAAQ;;AAgBrB,QAAO,oBAAC,gBAAD;EAXL,OAAO,OAAO,SAAS;EACvB,UAAU;EACV,SAAS;EACT,OAAO;EACP;EACA,WAAW,oCAAoC,aAAa,KAAK,MAAM;EACvE,aAAa,EAAE,WAAW;EAC1B,uBAAuB;EACvB,cAAc;EAGkB,CAAA"}
|
package/dist/Pagination/index.js
CHANGED
|
@@ -6,46 +6,52 @@ import Button_default from "../Button/index.js";
|
|
|
6
6
|
import { LocaleContext, getTranslator } from "../locale/default.js";
|
|
7
7
|
import PageSizeChanger from "./PageSizeChanger.js";
|
|
8
8
|
/* empty css */
|
|
9
|
-
import { useCallback, useContext,
|
|
9
|
+
import { useCallback, useContext, useState } from "react";
|
|
10
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
11
|
import _ from "lodash";
|
|
12
12
|
//#region src/Pagination/index.tsx
|
|
13
13
|
function Pagination(props) {
|
|
14
|
-
const { current:
|
|
14
|
+
const { current: controlledCurrent, defaultCurrent = 1, pageSize, total, onChange, hideOnSinglePage, showSizeChanger = false, pageSizeOptions = [
|
|
15
15
|
10,
|
|
16
16
|
20,
|
|
17
17
|
30,
|
|
18
18
|
50
|
|
19
|
-
], onShowSizeChange, showTotal = false } = props;
|
|
19
|
+
], onShowSizeChange, showTotal = false, disabled = false, "aria-label": ariaLabel } = props;
|
|
20
20
|
const { locale } = useContext(LocaleContext);
|
|
21
21
|
const t = getTranslator(locale);
|
|
22
|
+
const a11y = t.Pagination;
|
|
23
|
+
const [uncontrolledCurrent, setUncontrolledCurrent] = useState(defaultCurrent);
|
|
24
|
+
if (pageSize <= 0) throw new Error("pageSize must be greater than 0");
|
|
22
25
|
const totalPage = getTotalPage(total, pageSize);
|
|
23
|
-
const
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
setCurrent(getSafeCurrent(totalPage, currPage));
|
|
26
|
-
}, [currPage, totalPage]);
|
|
27
|
-
if (pageSize === 0) throw new Error("pageSize must be greater than 0");
|
|
26
|
+
const current = getSafeCurrent(totalPage, controlledCurrent ?? uncontrolledCurrent);
|
|
28
27
|
const onChangePage = useCallback((page) => {
|
|
29
28
|
return () => {
|
|
30
|
-
if (page === current) return;
|
|
31
|
-
|
|
29
|
+
if (disabled || page === current || page < 1 || page > totalPage) return;
|
|
30
|
+
if (controlledCurrent === void 0) setUncontrolledCurrent(page);
|
|
32
31
|
onChange(page, pageSize);
|
|
33
32
|
};
|
|
34
33
|
}, [
|
|
34
|
+
controlledCurrent,
|
|
35
|
+
disabled,
|
|
35
36
|
onChange,
|
|
36
37
|
current,
|
|
37
|
-
pageSize
|
|
38
|
+
pageSize,
|
|
39
|
+
totalPage
|
|
38
40
|
]);
|
|
39
41
|
const handlePageSizeChange = useCallback((newPageSize) => {
|
|
42
|
+
if (disabled || newPageSize <= 0 || newPageSize === pageSize) return;
|
|
40
43
|
const safeCurrent = getSafeCurrent(getTotalPage(total, newPageSize), current);
|
|
41
|
-
|
|
44
|
+
if (controlledCurrent === void 0) setUncontrolledCurrent(safeCurrent);
|
|
42
45
|
if (onShowSizeChange) onShowSizeChange(safeCurrent, newPageSize);
|
|
43
46
|
onChange(safeCurrent, newPageSize);
|
|
44
47
|
}, [
|
|
45
|
-
|
|
48
|
+
controlledCurrent,
|
|
46
49
|
current,
|
|
50
|
+
disabled,
|
|
51
|
+
onChange,
|
|
47
52
|
onShowSizeChange,
|
|
48
|
-
|
|
53
|
+
pageSize,
|
|
54
|
+
total
|
|
49
55
|
]);
|
|
50
56
|
const pageRange = getPaginationRange(totalPage, current);
|
|
51
57
|
if (hideOnSinglePage) {
|
|
@@ -58,8 +64,9 @@ function Pagination(props) {
|
|
|
58
64
|
if (showTotal === true) return t.Pagination.totalItems(total, range);
|
|
59
65
|
return null;
|
|
60
66
|
};
|
|
61
|
-
return /* @__PURE__ */ jsxs("
|
|
67
|
+
return /* @__PURE__ */ jsxs("nav", {
|
|
62
68
|
className: containerClassName,
|
|
69
|
+
"aria-label": ariaLabel ?? a11y.navigationLabel,
|
|
63
70
|
children: [
|
|
64
71
|
showTotal && /* @__PURE__ */ jsx("div", {
|
|
65
72
|
className: prefixCls("total"),
|
|
@@ -71,7 +78,8 @@ function Pagination(props) {
|
|
|
71
78
|
/* @__PURE__ */ jsx(Button_default, {
|
|
72
79
|
icon: /* @__PURE__ */ jsx(Memo, { size: 16 }),
|
|
73
80
|
onClick: onChangePage(current - 1),
|
|
74
|
-
disabled: current === 1
|
|
81
|
+
disabled: disabled || current === 1,
|
|
82
|
+
"aria-label": a11y.previousPage
|
|
75
83
|
}),
|
|
76
84
|
_.map(pageRange, (page, index) => {
|
|
77
85
|
if (page === "...") return /* @__PURE__ */ jsx("span", {
|
|
@@ -81,20 +89,26 @@ function Pagination(props) {
|
|
|
81
89
|
return /* @__PURE__ */ jsx(Button_default, {
|
|
82
90
|
icon: /* @__PURE__ */ jsx("span", { children: page }),
|
|
83
91
|
className: cn(prefixCls("button"), { [prefixCls("active")]: page === current }),
|
|
84
|
-
onClick: onChangePage(page)
|
|
92
|
+
onClick: onChangePage(page),
|
|
93
|
+
disabled,
|
|
94
|
+
"aria-label": page === current ? a11y.currentPage(page) : a11y.page(page),
|
|
95
|
+
...page === current ? { "aria-current": "page" } : {}
|
|
85
96
|
}, index);
|
|
86
97
|
}),
|
|
87
98
|
/* @__PURE__ */ jsx(Button_default, {
|
|
88
99
|
icon: /* @__PURE__ */ jsx(Memo$1, { size: 16 }),
|
|
89
100
|
onClick: onChangePage(current + 1),
|
|
90
|
-
disabled: current >= totalPage
|
|
101
|
+
disabled: disabled || current >= totalPage,
|
|
102
|
+
"aria-label": a11y.nextPage
|
|
91
103
|
})
|
|
92
104
|
]
|
|
93
105
|
}),
|
|
94
106
|
showSizeChanger && /* @__PURE__ */ jsx(PageSizeChanger, {
|
|
95
107
|
pageSize,
|
|
96
108
|
pageSizeOptions,
|
|
97
|
-
onChange: handlePageSizeChange
|
|
109
|
+
onChange: handlePageSizeChange,
|
|
110
|
+
disabled,
|
|
111
|
+
ariaLabel: a11y.pageSize
|
|
98
112
|
})
|
|
99
113
|
]
|
|
100
114
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/Pagination/index.tsx"],"sourcesContent":["import { cn } from '../lib/utils';\nimport _ from 'lodash';\nimport React, { useCallback, useContext, useEffect, useState } from 'react';\nimport Button from '../Button';\nimport { ChevronLeftLine, ChevronRightLine, Ellipsis } from '../Icon';\nimport { LocaleContext, getTranslator } from '../locale/default';\nimport { IPaginationProps } from './types';\nimport PageSizeChanger from './PageSizeChanger';\nimport './pagination.css';\n\nfunction Pagination(props: IPaginationProps) {\n const {\n current: currPage = 1,\n pageSize,\n total,\n onChange,\n hideOnSinglePage,\n showSizeChanger = false,\n pageSizeOptions = [10, 20, 30, 50],\n onShowSizeChange,\n showTotal = false,\n } = props;\n\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n const totalPage = getTotalPage(total, pageSize);\n\n const [current, setCurrent] = useState(getSafeCurrent(totalPage, currPage));\n\n useEffect(() => {\n const safeCurrent = getSafeCurrent(totalPage, currPage);\n setCurrent(safeCurrent);\n }, [currPage, totalPage]);\n\n if (pageSize === 0) {\n throw new Error('pageSize must be greater than 0');\n }\n\n const onChangePage = useCallback(\n (page: number) => {\n return () => {\n if (page === current) {\n return;\n }\n setCurrent(page);\n onChange(page, pageSize);\n };\n },\n [onChange, current, pageSize],\n );\n\n const handlePageSizeChange = useCallback(\n (newPageSize: number) => {\n const newTotalPage = getTotalPage(total, newPageSize);\n // 确保当前页在有效范围内\n const safeCurrent = getSafeCurrent(newTotalPage, current);\n\n setCurrent(safeCurrent);\n\n // 调用回调函数\n if (onShowSizeChange) {\n onShowSizeChange(safeCurrent, newPageSize);\n }\n\n // 也调用 onChange 以保持一致性\n onChange(safeCurrent, newPageSize);\n },\n [total, current, onShowSizeChange, onChange],\n );\n\n const pageRange = getPaginationRange(totalPage, current);\n\n if (hideOnSinglePage) {\n if (totalPage <= 1 && !showSizeChanger && !showTotal) {\n return null;\n }\n }\n\n // 计算当前显示的数据范围\n const startIndex = (current - 1) * pageSize + 1;\n const endIndex = Math.min(current * pageSize, total);\n const range: [number, number] = [startIndex, endIndex];\n\n const containerClassName = prefixCls('container');\n\n // 获取显示总数的函数\n const getShowTotalContent = () => {\n if (typeof showTotal === 'function') {\n return showTotal(total, range);\n }\n if (showTotal === true) {\n return t.Pagination.totalItems(total, range);\n }\n return null;\n };\n\n return (\n <div className={containerClassName}>\n {/* 显示总数和当前范围 */}\n {showTotal && (\n <div className={prefixCls('total')}>{getShowTotalContent()}</div>\n )}\n\n {/* 主要的分页控件 */}\n <div className={prefixCls('main')}>\n <Button\n icon={<ChevronLeftLine size={16} />}\n onClick={onChangePage(current - 1)}\n disabled={current === 1}\n />\n {_.map(pageRange, (page, index: number) => {\n if (page === ELLIPSIS) {\n return (\n <span key={index} className={prefixCls('ellipsis')}>\n <Ellipsis size={20} />\n </span>\n );\n }\n return (\n <Button\n key={index}\n icon={<span>{page}</span>}\n className={cn(prefixCls('button'), {\n [prefixCls('active')]: page === current,\n })}\n onClick={onChangePage(page)}\n />\n );\n })}\n <Button\n icon={<ChevronRightLine size={16} />}\n onClick={onChangePage(current + 1)}\n disabled={current >= totalPage}\n />\n </div>\n\n {/* 页面大小选择器 */}\n {showSizeChanger && (\n <PageSizeChanger\n pageSize={pageSize}\n pageSizeOptions={pageSizeOptions}\n onChange={handlePageSizeChange}\n />\n )}\n </div>\n );\n}\n\nexport default Pagination;\n\n/**\n * 获取在安全范围内的当前页数\n */\nexport function getSafeCurrent(totalPage: number, current?: number) {\n if (current === undefined) {\n return 1;\n }\n return Math.max(1, Math.min(current, totalPage));\n}\n\nfunction getTotalPage(total: number, pageSize: number) {\n return Math.max(1, Math.ceil(total / pageSize));\n}\n\nexport const ELLIPSIS = '...';\n\nexport type PaginationItemType = number | typeof ELLIPSIS;\n\n/**\n * 获取分页组件需要显示的页码范围。\n *\n * @param totalPage 最大页码。\n * @param currentPage 当前所在的页码。\n *\n * 如果总页数不超过5页,直接返回所有页码。\n * 否则,在生成页码时,除了第一页和最后一页,还会显示以当前页为中心的连续页码,数量为 `surroundCount`*2 个,\n * 当当前页码距离边界过近时,会在页码前后添加省略号。\n * 当前页码 `currentPage` 的值必须介于 1 和总页数之间,如果超出这个范围,会自动修正。\n *\n * @returns 一个包含了所有要显示的页码和省略号的数组。\n */\nexport function getPaginationRange(\n totalPage: number,\n currentPage: number,\n): PaginationItemType[] {\n // 如果总页数不超过5页,直接返回所有页码\n if (totalPage <= 5) {\n return Array.from({ length: totalPage }, (_, i) => i + 1);\n }\n\n const surroundCount = 2;\n\n const current = Math.max(1, Math.min(currentPage, totalPage));\n\n let start = Math.max(2, current - surroundCount);\n let end = Math.min(totalPage - 1, current + surroundCount);\n\n // Adjust start and end based on current page\n if (current - start < surroundCount) {\n end = Math.min(end + (surroundCount - (current - start)), totalPage - 1);\n }\n if (end - current < surroundCount) {\n start = Math.max(start - (surroundCount - (end - current)), 2);\n }\n\n // Check if current page is out of range\n if (current < start || current > end) {\n start = Math.max(2, current - surroundCount);\n end = Math.min(totalPage - 1, current + surroundCount);\n }\n\n const range: PaginationItemType[] = [];\n for (let i = start; i <= end; i++) {\n range.push(i);\n }\n\n range.unshift(1);\n if (start > 2 && range[1] !== ELLIPSIS) {\n range.splice(1, 0, ELLIPSIS);\n }\n\n if (totalPage !== range[range.length - 1]) {\n if (end < totalPage - 1 && range[range.length - 1] !== ELLIPSIS) {\n range.splice(range.length, 0, ELLIPSIS);\n }\n range.push(totalPage);\n }\n\n return range;\n}\n\nfunction prefixCls(name: string) {\n return `ald-pagination-${name}`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/Pagination/index.tsx"],"sourcesContent":["import { cn } from '../lib/utils';\nimport _ from 'lodash';\nimport React, { useCallback, useContext, useState } from 'react';\nimport Button from '../Button';\nimport { ChevronLeftLine, ChevronRightLine, Ellipsis } from '../Icon';\nimport { LocaleContext, getTranslator } from '../locale/default';\nimport { IPaginationProps } from './types';\nimport PageSizeChanger from './PageSizeChanger';\nimport './pagination.css';\n\nfunction Pagination(props: IPaginationProps) {\n const {\n current: controlledCurrent,\n defaultCurrent = 1,\n pageSize,\n total,\n onChange,\n hideOnSinglePage,\n showSizeChanger = false,\n pageSizeOptions = [10, 20, 30, 50],\n onShowSizeChange,\n showTotal = false,\n disabled = false,\n 'aria-label': ariaLabel,\n } = props;\n\n const { locale } = useContext(LocaleContext);\n const t = getTranslator(locale);\n const a11y = t.Pagination;\n const [uncontrolledCurrent, setUncontrolledCurrent] =\n useState(defaultCurrent);\n\n if (pageSize <= 0) {\n throw new Error('pageSize must be greater than 0');\n }\n\n const totalPage = getTotalPage(total, pageSize);\n const current = getSafeCurrent(\n totalPage,\n controlledCurrent ?? uncontrolledCurrent,\n );\n\n const onChangePage = useCallback(\n (page: number) => {\n return () => {\n if (disabled || page === current || page < 1 || page > totalPage) {\n return;\n }\n if (controlledCurrent === undefined) {\n setUncontrolledCurrent(page);\n }\n onChange(page, pageSize);\n };\n },\n [controlledCurrent, disabled, onChange, current, pageSize, totalPage],\n );\n\n const handlePageSizeChange = useCallback(\n (newPageSize: number) => {\n if (disabled || newPageSize <= 0 || newPageSize === pageSize) {\n return;\n }\n const newTotalPage = getTotalPage(total, newPageSize);\n const safeCurrent = getSafeCurrent(newTotalPage, current);\n\n if (controlledCurrent === undefined) {\n setUncontrolledCurrent(safeCurrent);\n }\n if (onShowSizeChange) {\n onShowSizeChange(safeCurrent, newPageSize);\n }\n\n onChange(safeCurrent, newPageSize);\n },\n [\n controlledCurrent,\n current,\n disabled,\n onChange,\n onShowSizeChange,\n pageSize,\n total,\n ],\n );\n\n const pageRange = getPaginationRange(totalPage, current);\n\n if (hideOnSinglePage) {\n if (totalPage <= 1 && !showSizeChanger && !showTotal) {\n return null;\n }\n }\n\n // 计算当前显示的数据范围\n const startIndex = (current - 1) * pageSize + 1;\n const endIndex = Math.min(current * pageSize, total);\n const range: [number, number] = [startIndex, endIndex];\n\n const containerClassName = prefixCls('container');\n\n // 获取显示总数的函数\n const getShowTotalContent = () => {\n if (typeof showTotal === 'function') {\n return showTotal(total, range);\n }\n if (showTotal === true) {\n return t.Pagination.totalItems(total, range);\n }\n return null;\n };\n\n return (\n <nav\n className={containerClassName}\n aria-label={ariaLabel ?? a11y.navigationLabel}\n >\n {/* 显示总数和当前范围 */}\n {showTotal && (\n <div className={prefixCls('total')}>{getShowTotalContent()}</div>\n )}\n\n {/* 主要的分页控件 */}\n <div className={prefixCls('main')}>\n <Button\n icon={<ChevronLeftLine size={16} />}\n onClick={onChangePage(current - 1)}\n disabled={disabled || current === 1}\n aria-label={a11y.previousPage}\n />\n {_.map(pageRange, (page, index: number) => {\n if (page === ELLIPSIS) {\n return (\n <span key={index} className={prefixCls('ellipsis')}>\n <Ellipsis size={20} />\n </span>\n );\n }\n return (\n <Button\n key={index}\n icon={<span>{page}</span>}\n className={cn(prefixCls('button'), {\n [prefixCls('active')]: page === current,\n })}\n onClick={onChangePage(page)}\n disabled={disabled}\n aria-label={\n page === current ? a11y.currentPage(page) : a11y.page(page)\n }\n {...(page === current\n ? ({ 'aria-current': 'page' } as React.AriaAttributes)\n : {})}\n />\n );\n })}\n <Button\n icon={<ChevronRightLine size={16} />}\n onClick={onChangePage(current + 1)}\n disabled={disabled || current >= totalPage}\n aria-label={a11y.nextPage}\n />\n </div>\n\n {/* 页面大小选择器 */}\n {showSizeChanger && (\n <PageSizeChanger\n pageSize={pageSize}\n pageSizeOptions={pageSizeOptions}\n onChange={handlePageSizeChange}\n disabled={disabled}\n ariaLabel={a11y.pageSize}\n />\n )}\n </nav>\n );\n}\n\nexport default Pagination;\n\n/**\n * 获取在安全范围内的当前页数\n */\nexport function getSafeCurrent(totalPage: number, current?: number) {\n if (current === undefined) {\n return 1;\n }\n return Math.max(1, Math.min(current, totalPage));\n}\n\nfunction getTotalPage(total: number, pageSize: number) {\n return Math.max(1, Math.ceil(total / pageSize));\n}\n\nexport const ELLIPSIS = '...';\n\nexport type PaginationItemType = number | typeof ELLIPSIS;\n\n/**\n * 获取分页组件需要显示的页码范围。\n *\n * @param totalPage 最大页码。\n * @param currentPage 当前所在的页码。\n *\n * 如果总页数不超过5页,直接返回所有页码。\n * 否则,在生成页码时,除了第一页和最后一页,还会显示以当前页为中心的连续页码,数量为 `surroundCount`*2 个,\n * 当当前页码距离边界过近时,会在页码前后添加省略号。\n * 当前页码 `currentPage` 的值必须介于 1 和总页数之间,如果超出这个范围,会自动修正。\n *\n * @returns 一个包含了所有要显示的页码和省略号的数组。\n */\nexport function getPaginationRange(\n totalPage: number,\n currentPage: number,\n): PaginationItemType[] {\n // 如果总页数不超过5页,直接返回所有页码\n if (totalPage <= 5) {\n return Array.from({ length: totalPage }, (_, i) => i + 1);\n }\n\n const surroundCount = 2;\n\n const current = Math.max(1, Math.min(currentPage, totalPage));\n\n let start = Math.max(2, current - surroundCount);\n let end = Math.min(totalPage - 1, current + surroundCount);\n\n // Adjust start and end based on current page\n if (current - start < surroundCount) {\n end = Math.min(end + (surroundCount - (current - start)), totalPage - 1);\n }\n if (end - current < surroundCount) {\n start = Math.max(start - (surroundCount - (end - current)), 2);\n }\n\n // Check if current page is out of range\n if (current < start || current > end) {\n start = Math.max(2, current - surroundCount);\n end = Math.min(totalPage - 1, current + surroundCount);\n }\n\n const range: PaginationItemType[] = [];\n for (let i = start; i <= end; i++) {\n range.push(i);\n }\n\n range.unshift(1);\n if (start > 2 && range[1] !== ELLIPSIS) {\n range.splice(1, 0, ELLIPSIS);\n }\n\n if (totalPage !== range[range.length - 1]) {\n if (end < totalPage - 1 && range[range.length - 1] !== ELLIPSIS) {\n range.splice(range.length, 0, ELLIPSIS);\n }\n range.push(totalPage);\n }\n\n return range;\n}\n\nfunction prefixCls(name: string) {\n return `ald-pagination-${name}`;\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
export interface IPaginationProps {
|
|
3
3
|
current?: number;
|
|
4
|
+
defaultCurrent?: number;
|
|
4
5
|
pageSize: number;
|
|
5
6
|
total: number;
|
|
6
7
|
onChange: (current: number, pageSize?: number) => void;
|
|
@@ -9,4 +10,6 @@ export interface IPaginationProps {
|
|
|
9
10
|
pageSizeOptions?: (string | number)[];
|
|
10
11
|
onShowSizeChange?: (current: number, size: number) => void;
|
|
11
12
|
showTotal?: boolean | ((total: number, range: [number, number]) => React.ReactNode);
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
'aria-label'?: string;
|
|
12
15
|
}
|
|
@@ -68,7 +68,7 @@ function Radio(props) {
|
|
|
68
68
|
}
|
|
69
69
|
}), /* @__PURE__ */ jsx("span", { className: "ald-radio-inner" })]
|
|
70
70
|
}), props.children && /* @__PURE__ */ jsx("span", {
|
|
71
|
-
className: "ald-radio-desc",
|
|
71
|
+
className: "ald-radio-desc tw-text-typography-label",
|
|
72
72
|
children: props.children
|
|
73
73
|
})]
|
|
74
74
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Radio/components/Radio/index.tsx"],"sourcesContent":["import { cn } from '../../../lib/utils';\nimport _ from 'lodash';\nimport React, { useContext, useRef, useState } from 'react';\n\nimport { getUUID } from '../../../_utils/hooks/useId';\nimport { IRadioProps } from '../../interface/radio';\nimport { RadioGroupContext } from '../Group';\n\nexport default function Radio(props: IRadioProps) {\n const groupContext = useContext(RadioGroupContext);\n const labelRef = useRef<HTMLLabelElement>(null);\n const [id] = useState(() => getUUID().toString());\n\n const radioProps = { ...props };\n const inGroup = !_.isEmpty(groupContext);\n const isControlled = 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(\n props.defaultChecked ?? false,\n );\n\n if (inGroup) {\n radioProps.disabled = groupContext.disabled || props.disabled;\n }\n\n // checked 直接从 groupContext 或 props 派生,不使用 useState + useEffect,\n // 避免双重渲染导致切换时视觉抖动。\n const checked = inGroup\n ? groupContext.value === props.value\n : !isControlled\n ? innerChecked\n : radioProps.checked;\n\n // 设置input外层盒子的class\n const aldRadioClass = cn('ald-radio', {\n 'ald-radio-checked': checked,\n 'ald-radio-disabled': radioProps.disabled,\n });\n\n // 根据属性设置最外层的class\n const getWrapperClass = () => {\n let otherClass = '';\n if (groupContext.type === 'button') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-button-wrapper-border-primary';\n }\n } else if (groupContext.type === 'iconButton') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-icon-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-icon-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-icon-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-icon-button-wrapper-border-primary';\n }\n } else {\n // 当type未设置或者是radio时\n otherClass = 'ald-radio-wrapper';\n if (props.indeterminate) {\n otherClass = otherClass + ' ald-radio-wrapper-indeterminate';\n }\n }\n return cn('ald-radio-label', otherClass, props.className, {\n 'ald-radio-wrapper-checked': checked,\n 'ald-radio-wrapper-disabled': radioProps.disabled,\n });\n };\n\n // button / iconButton 模式下,radio 圆圈需要完全隐藏\n const isButtonMode =\n groupContext.type === 'button' || groupContext.type === 'iconButton';\n const radioHideStyle: React.CSSProperties | undefined = isButtonMode\n ? { width: 0, height: 0, overflow: 'hidden' }\n : undefined;\n\n return (\n <label className={getWrapperClass()} htmlFor={id} ref={labelRef}>\n <span className={aldRadioClass} style={radioHideStyle}>\n <input\n id={id}\n type=\"radio\"\n className=\"ald-radio-input\"\n // 同步派生的 checked 到原生 input,对齐 v2/antd 行为(仅有 class 不更新 input.checked)\n checked={!!checked}\n disabled={radioProps.disabled}\n value={props.value}\n onChange={(e) => {\n if (radioProps.disabled) return;\n if (!inGroup && !isControlled) {\n setInnerChecked(e.target.checked);\n }\n props.onChange?.(e);\n }}\n onClick={(e) => {\n props.onClick?.(e);\n\n if (inGroup && groupContext?.onChange) {\n // input事件的value会被toString,所以此处进行一个覆盖\n groupContext.onChange(props.value);\n }\n }}\n />\n <span className=\"ald-radio-inner\" />\n </span>\n {props.children && (\n <span className=\"ald-radio-desc\"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../../src/Radio/components/Radio/index.tsx"],"sourcesContent":["import { cn } from '../../../lib/utils';\nimport _ from 'lodash';\nimport React, { useContext, useRef, useState } from 'react';\n\nimport { getUUID } from '../../../_utils/hooks/useId';\nimport { IRadioProps } from '../../interface/radio';\nimport { RadioGroupContext } from '../Group';\n\nexport default function Radio(props: IRadioProps) {\n const groupContext = useContext(RadioGroupContext);\n const labelRef = useRef<HTMLLabelElement>(null);\n const [id] = useState(() => getUUID().toString());\n\n const radioProps = { ...props };\n const inGroup = !_.isEmpty(groupContext);\n const isControlled = 'checked' in props;\n const [innerChecked, setInnerChecked] = useState(\n props.defaultChecked ?? false,\n );\n\n if (inGroup) {\n radioProps.disabled = groupContext.disabled || props.disabled;\n }\n\n // checked 直接从 groupContext 或 props 派生,不使用 useState + useEffect,\n // 避免双重渲染导致切换时视觉抖动。\n const checked = inGroup\n ? groupContext.value === props.value\n : !isControlled\n ? innerChecked\n : radioProps.checked;\n\n // 设置input外层盒子的class\n const aldRadioClass = cn('ald-radio', {\n 'ald-radio-checked': checked,\n 'ald-radio-disabled': radioProps.disabled,\n });\n\n // 根据属性设置最外层的class\n const getWrapperClass = () => {\n let otherClass = '';\n if (groupContext.type === 'button') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-button-wrapper-border-primary';\n }\n } else if (groupContext.type === 'iconButton') {\n if (groupContext.radioGroupStyle === 'filled') {\n otherClass = 'ald-radio-icon-button-wrapper-filled';\n } else if (groupContext.radioGroupStyle === 'border') {\n otherClass = 'ald-radio-icon-button-wrapper-border';\n } else if (groupContext.radioGroupStyle === 'filter') {\n otherClass = 'ald-radio-icon-button-wrapper-filter';\n } else {\n otherClass = 'ald-radio-icon-button-wrapper-border-primary';\n }\n } else {\n // 当type未设置或者是radio时\n otherClass = 'ald-radio-wrapper';\n if (props.indeterminate) {\n otherClass = otherClass + ' ald-radio-wrapper-indeterminate';\n }\n }\n return cn('ald-radio-label', otherClass, props.className, {\n 'ald-radio-wrapper-checked': checked,\n 'ald-radio-wrapper-disabled': radioProps.disabled,\n });\n };\n\n // button / iconButton 模式下,radio 圆圈需要完全隐藏\n const isButtonMode =\n groupContext.type === 'button' || groupContext.type === 'iconButton';\n const radioHideStyle: React.CSSProperties | undefined = isButtonMode\n ? { width: 0, height: 0, overflow: 'hidden' }\n : undefined;\n\n return (\n <label className={getWrapperClass()} htmlFor={id} ref={labelRef}>\n <span className={aldRadioClass} style={radioHideStyle}>\n <input\n id={id}\n type=\"radio\"\n className=\"ald-radio-input\"\n // 同步派生的 checked 到原生 input,对齐 v2/antd 行为(仅有 class 不更新 input.checked)\n checked={!!checked}\n disabled={radioProps.disabled}\n value={props.value}\n onChange={(e) => {\n if (radioProps.disabled) return;\n if (!inGroup && !isControlled) {\n setInnerChecked(e.target.checked);\n }\n props.onChange?.(e);\n }}\n onClick={(e) => {\n props.onClick?.(e);\n\n if (inGroup && groupContext?.onChange) {\n // input事件的value会被toString,所以此处进行一个覆盖\n groupContext.onChange(props.value);\n }\n }}\n />\n <span className=\"ald-radio-inner\" />\n </span>\n {props.children && (\n <span className=\"ald-radio-desc tw-text-typography-label\">\n {props.children}\n </span>\n )}\n </label>\n );\n}\n"],"mappings":";;;;;;;AAQA,SAAwB,MAAM,OAAoB;CAChD,MAAM,eAAe,WAAW,kBAAkB;CAClD,MAAM,WAAW,OAAyB,KAAK;CAC/C,MAAM,CAAC,MAAM,eAAe,SAAS,CAAC,UAAU,CAAC;CAEjD,MAAM,aAAa,EAAE,GAAG,OAAO;CAC/B,MAAM,UAAU,CAAC,EAAE,QAAQ,aAAa;CACxC,MAAM,eAAe,aAAa;CAClC,MAAM,CAAC,cAAc,mBAAmB,SACtC,MAAM,kBAAkB,MACzB;AAED,KAAI,QACF,YAAW,WAAW,aAAa,YAAY,MAAM;CAKvD,MAAM,UAAU,UACZ,aAAa,UAAU,MAAM,QAC7B,CAAC,eACD,eACA,WAAW;CAGf,MAAM,gBAAgB,GAAG,aAAa;EACpC,qBAAqB;EACrB,sBAAsB,WAAW;EAClC,CAAC;CAGF,MAAM,wBAAwB;EAC5B,IAAI,aAAa;AACjB,MAAI,aAAa,SAAS,SACxB,KAAI,aAAa,oBAAoB,SACnC,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;MAEb,cAAa;WAEN,aAAa,SAAS,aAC/B,KAAI,aAAa,oBAAoB,SACnC,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;WACJ,aAAa,oBAAoB,SAC1C,cAAa;MAEb,cAAa;OAEV;AAEL,gBAAa;AACb,OAAI,MAAM,cACR,cAAa,aAAa;;AAG9B,SAAO,GAAG,mBAAmB,YAAY,MAAM,WAAW;GACxD,6BAA6B;GAC7B,8BAA8B,WAAW;GAC1C,CAAC;;CAMJ,MAAM,iBADJ,aAAa,SAAS,YAAY,aAAa,SAAS,eAEtD;EAAE,OAAO;EAAG,QAAQ;EAAG,UAAU;EAAU,GAC3C;AAEJ,QACE,qBAAC,SAAD;EAAO,WAAW,iBAAiB;EAAE,SAAS;EAAI,KAAK;YAAvD,CACE,qBAAC,QAAD;GAAM,WAAW;GAAe,OAAO;aAAvC,CACE,oBAAC,SAAD;IACM;IACJ,MAAK;IACL,WAAU;IAEV,SAAS,CAAC,CAAC;IACX,UAAU,WAAW;IACrB,OAAO,MAAM;IACb,WAAW,MAAM;AACf,SAAI,WAAW,SAAU;AACzB,SAAI,CAAC,WAAW,CAAC,aACf,iBAAgB,EAAE,OAAO,QAAQ;AAEnC,WAAM,WAAW,EAAE;;IAErB,UAAU,MAAM;AACd,WAAM,UAAU,EAAE;AAElB,SAAI,WAAW,cAAc,SAE3B,cAAa,SAAS,MAAM,MAAM;;IAGtC,CAAA,EACF,oBAAC,QAAD,EAAM,WAAU,mBAAoB,CAAA,CAC/B;MACN,MAAM,YACL,oBAAC,QAAD;GAAM,WAAU;aACb,MAAM;GACF,CAAA,CAEH"}
|
|
@@ -30,6 +30,7 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
|
|
|
30
30
|
const { id, className, displayValues, onDisplayValuesChange, displayMenu, notFoundContent, onClear, width, mode, status: customStatus, onOptionSelect, onClick, size: customSize, borderLess = false, disabled, placeholder, loading = false, open, defaultOpen, onOpenChange, showSearch, innerSearchValue, setInnerSearchValue, allowClear, showArrow = true, prefix, suffixIcon, dropdownRender, overlayStyle, dropdownStyle, popupMatchSelectWidth = true, placement, popupClassName, allowOverlap, style, "data-testid": dataTestid, "aria-label": ariaLabel, ...restProps } = props;
|
|
31
31
|
const setClassNames = prefixCls("select");
|
|
32
32
|
const selectRef = useRef(null);
|
|
33
|
+
const triggerRef = useRef(null);
|
|
33
34
|
const widthStyle = getWidthStyle(width);
|
|
34
35
|
const dropdownRef = useRef(null);
|
|
35
36
|
const [matchedPopupWidth, setMatchedPopupWidth] = useState();
|
|
@@ -43,15 +44,14 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
|
|
|
43
44
|
const { status: contextStatus } = useContext(FormItemInputContext);
|
|
44
45
|
const mergedStatus = customStatus === null ? void 0 : customStatus || contextStatus;
|
|
45
46
|
React$1.useImperativeHandle(ref, () => ({
|
|
46
|
-
focus: () =>
|
|
47
|
-
blur: () =>
|
|
47
|
+
focus: () => triggerRef.current?.focus(),
|
|
48
|
+
blur: () => triggerRef.current?.blur(),
|
|
48
49
|
open: () => onToggleOpen(true),
|
|
49
50
|
close: () => {
|
|
50
51
|
console.log("ref close");
|
|
51
52
|
onToggleOpen(false);
|
|
52
53
|
}
|
|
53
54
|
}));
|
|
54
|
-
const [focus, setFocus] = useState(false);
|
|
55
55
|
const [isHover, setIsHover] = useState(false);
|
|
56
56
|
const [innerOpen, setInnerOpen] = useMergedState(false, {
|
|
57
57
|
defaultValue: defaultOpen,
|
|
@@ -67,10 +67,7 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
|
|
|
67
67
|
const onToggleOpen = React$1.useCallback((newOpen) => {
|
|
68
68
|
const nextOpen = newOpen !== void 0 ? newOpen : !mergedOpen;
|
|
69
69
|
if (nextOpen) updateMatchedPopupWidth();
|
|
70
|
-
if (!nextOpen)
|
|
71
|
-
setShowResponsiveSelectedSection(false);
|
|
72
|
-
setFocus(false);
|
|
73
|
-
}
|
|
70
|
+
if (!nextOpen) setShowResponsiveSelectedSection(false);
|
|
74
71
|
if (mergedOpen !== nextOpen && !disabled) {
|
|
75
72
|
setInnerOpen(nextOpen);
|
|
76
73
|
onOpenChange?.(nextOpen);
|
|
@@ -121,7 +118,8 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
|
|
|
121
118
|
});
|
|
122
119
|
};
|
|
123
120
|
const mergedClassName = cn(setClassNames("beta-ald-select", size, {
|
|
124
|
-
|
|
121
|
+
open: mergedOpen,
|
|
122
|
+
active: mergedOpen,
|
|
125
123
|
borderless: borderLess,
|
|
126
124
|
disabled,
|
|
127
125
|
loading,
|
|
@@ -137,10 +135,7 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
|
|
|
137
135
|
onClick: (info) => {
|
|
138
136
|
displayMenu?.onClick?.(info);
|
|
139
137
|
if (isMultipleMode) info.keepOpen = info.keepOpen ?? true;
|
|
140
|
-
else if (displayMenu)
|
|
141
|
-
onToggleOpen(false);
|
|
142
|
-
setFocus(false);
|
|
143
|
-
}
|
|
138
|
+
else if (displayMenu) onToggleOpen(false);
|
|
144
139
|
setIsHover(false);
|
|
145
140
|
onOptionSelect?.(info.key);
|
|
146
141
|
}
|
|
@@ -202,6 +197,11 @@ var BaseSelect = React$1.forwardRef((props, ref) => {
|
|
|
202
197
|
else onToggleOpen(open);
|
|
203
198
|
},
|
|
204
199
|
children: /* @__PURE__ */ jsxs("div", {
|
|
200
|
+
ref: triggerRef,
|
|
201
|
+
tabIndex: disabled ? void 0 : 0,
|
|
202
|
+
role: "combobox",
|
|
203
|
+
"aria-disabled": disabled || void 0,
|
|
204
|
+
"aria-expanded": mergedOpen,
|
|
205
205
|
className: cn(setClassNames("trigger"), "ant-select-selector"),
|
|
206
206
|
children: [
|
|
207
207
|
prefix && /* @__PURE__ */ jsx("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseSelect.js","names":[],"sources":["../../src/Select/BaseSelect.tsx"],"sourcesContent":["import './ald-select.css';\nimport * as React from 'react';\nimport useMergedState from 'rc-util/es/hooks/useMergedState';\nimport { cn } from '../lib/utils';\nimport prefixCls from '../_utils/prefixCls';\n\n/** Align config type (locally defined to avoid rc-trigger dependency) */\nexport interface AlignType {\n points?: string[];\n offset?: (number | string)[];\n targetOffset?: (number | string)[];\n overflow?: { adjustX?: boolean; adjustY?: boolean };\n _experimental?: Record<string, any>;\n}\nimport SelectTrigger, { RefTriggerProps } from './SelectTrigger';\nimport Selector from './Selector';\nimport _ from 'lodash';\nimport { useContext, useRef, useState } from 'react';\nimport { FormItemInputContext } from '../Form/FormItemContext';\nimport getWidthStyle from './utils/getWidthStyle';\nimport Suffix from './components/Suffix';\nimport { PlacementType } from '../Dropdown';\nimport {\n BaseSelectRef,\n DisplayValueType,\n ISelectProps,\n LabelInValueType,\n SelectMenuProps,\n} from './interface';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { ConfigContext } from '../ConfigProvider';\nimport { useCompactItemContext } from '../Space/CompactContext';\nimport { MenuInfo } from '../Menu';\nimport { toString } from './utils/commonUtil';\n\nexport type RenderNode = React.ReactNode | ((props: any) => React.ReactNode);\n\nexport type RenderDOMFunc = (props: any) => HTMLElement;\n\nexport type Mode =\n | 'multiple'\n | {\n type: 'multiple';\n responsive?: boolean;\n maxRows?: number;\n showSelectedSection?: boolean;\n };\n\nexport type RawValueType = string | number;\n\nexport type CustomTagProps = {\n label: React.ReactNode;\n value: any;\n disabled: boolean;\n onClose: (event?: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n closable: boolean;\n};\nexport interface BaseSelectPrivateProps {\n // >>> MISC\n omitDomProps?: string[];\n\n // >>> Value\n displayValues: LabelInValueType[];\n onDisplayValuesChange: (\n values: LabelInValueType[],\n info: {\n type: 'add' | 'remove' | 'clear';\n values: LabelInValueType[];\n },\n ) => void;\n\n // >>> Active\n /** Current dropdown list active item string value */\n activeValue?: string;\n /** Link search input with target element */\n activeDescendantId?: string;\n onActiveValueChange?: (value: string | null) => void;\n}\n\nexport type BaseSelectPropsWithoutPrivate = Omit<\n BaseSelectProps,\n keyof BaseSelectPrivateProps\n>;\n\nexport interface BaseSelectProps\n extends BaseSelectPrivateProps,\n ISelectProps,\n React.AriaAttributes {\n className?: string;\n style?: React.CSSProperties;\n notFoundContent?: React.ReactNode;\n onClear?: () => void;\n innerSearchValue?: string;\n setInnerSearchValue?: (value: string) => void;\n displayMenu?: SelectMenuProps;\n // >>> Open\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n onOptionSelect?: (val: RawValueType) => void;\n\n // >>> Icons\n allowClear?: boolean;\n showArrow?: boolean;\n suffixIcon?: React.ReactNode;\n\n // >>> Dropdown\n dropdownAlign?: AlignType;\n placement?: PlacementType;\n getPopupContainer?: () => HTMLElement;\n\n // >>> Focus\n onBlur?: React.FocusEventHandler<HTMLElement>;\n onFocus?: React.FocusEventHandler<HTMLElement>;\n\n // >>> Rest Events\n onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onMouseDown?: React.MouseEventHandler<HTMLDivElement>;\n onPopupScroll?: React.UIEventHandler<HTMLDivElement>;\n onInputKeyDown?: React.KeyboardEventHandler<\n HTMLInputElement | HTMLTextAreaElement\n >;\n onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;\n onClick?: React.MouseEventHandler<HTMLDivElement>;\n}\n\nexport function isMultiple(mode?: Mode) {\n return !!mode;\n}\nexport function isResponsive(mode?: Mode) {\n return mode === 'multiple' || (typeof mode === 'object' && mode?.responsive);\n}\nexport function isShowSelectedSection(mode?: Mode) {\n if (!mode || mode === 'multiple') {\n return false;\n }\n\n return (\n typeof mode === 'object' && mode.showSelectedSection && mode.responsive\n );\n}\nconst BaseSelect = React.forwardRef(\n (props: BaseSelectProps, ref: React.Ref<BaseSelectRef>) => {\n const {\n id,\n className,\n // Value\n displayValues,\n onDisplayValuesChange,\n displayMenu,\n notFoundContent,\n onClear,\n width,\n mode,\n status: customStatus,\n onOptionSelect,\n onClick,\n size: customSize,\n borderLess = false,\n // Status\n disabled,\n placeholder,\n loading = false,\n\n // Open\n open,\n defaultOpen,\n onOpenChange,\n showSearch,\n innerSearchValue,\n setInnerSearchValue,\n // Icons\n allowClear,\n showArrow = true,\n prefix,\n suffixIcon,\n dropdownRender,\n overlayStyle,\n dropdownStyle,\n popupMatchSelectWidth = true,\n placement,\n popupClassName,\n allowOverlap,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n ...restProps\n // Rest Props\n } = props;\n const setClassNames = prefixCls('select');\n const selectRef = useRef<HTMLDivElement>(null);\n const widthStyle = getWidthStyle(width);\n const dropdownRef = useRef<RefTriggerProps>(null);\n const [matchedPopupWidth, setMatchedPopupWidth] = useState<\n number | undefined\n >();\n const isResponsiveMode = isResponsive(mode);\n const isMultipleMode = isMultiple(mode);\n /** Used for component focused management */\n const contentSize = useContext(SizeContext);\n const { direction } = React.useContext(ConfigContext);\n // ===================== Compact Item =====================\n const { compactSize, compactItemClassnames } = useCompactItemContext(\n 'ald-select',\n direction,\n );\n const size = compactSize || customSize || contentSize || 'middle';\n const {\n status: contextStatus,\n // hasFeedback,\n // isFormItemInput,\n // feedbackIcon,\n } = useContext(FormItemInputContext);\n\n const mergedStatus =\n customStatus === null ? undefined : customStatus || contextStatus;\n\n // =========================== Imperative ===========================\n React.useImperativeHandle(ref, () => ({\n focus: () => setFocus(true),\n blur: () => setFocus(false),\n open: () => onToggleOpen(true),\n close: () => {\n console.log('ref close');\n onToggleOpen(false);\n },\n }));\n const [focus, setFocus] = useState(false);\n const [isHover, setIsHover] = useState(false);\n // ============================== Open ==============================\n const [innerOpen, setInnerOpen] = useMergedState<boolean>(false, {\n defaultValue: defaultOpen,\n value: open,\n });\n const mergedOpen = innerOpen;\n const shouldMatchPopupWidth =\n !!popupMatchSelectWidth && typeof popupMatchSelectWidth !== 'number';\n const updateMatchedPopupWidth = React.useCallback(() => {\n if (!shouldMatchPopupWidth) {\n return;\n }\n\n const nextWidth = selectRef.current?.getBoundingClientRect().width;\n if (nextWidth !== undefined) {\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n }\n }, [shouldMatchPopupWidth]);\n const onToggleOpen = React.useCallback(\n (newOpen?: boolean) => {\n const nextOpen = newOpen !== undefined ? newOpen : !mergedOpen;\n if (nextOpen) {\n updateMatchedPopupWidth();\n }\n if (!nextOpen) {\n setShowResponsiveSelectedSection(false);\n setFocus(false);\n }\n if (mergedOpen !== nextOpen && !disabled) {\n setInnerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n }\n },\n [\n mergedOpen,\n disabled,\n setInnerOpen,\n onOpenChange,\n updateMatchedPopupWidth,\n ],\n );\n React.useLayoutEffect(() => {\n if (!mergedOpen || !shouldMatchPopupWidth) {\n return;\n }\n\n const element = selectRef.current;\n if (!element) {\n return;\n }\n\n const updateMatchedWidth = () => {\n const nextWidth = element.getBoundingClientRect().width;\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n };\n\n updateMatchedWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateMatchedWidth);\n return () => {\n window.removeEventListener('resize', updateMatchedWidth);\n };\n }\n\n let resizeAnimationFrame: number | undefined;\n const scheduleMatchedWidthUpdate = () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n resizeAnimationFrame = requestAnimationFrame(updateMatchedWidth);\n };\n\n const observer = new ResizeObserver(scheduleMatchedWidthUpdate);\n observer.observe(element);\n\n return () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n observer.disconnect();\n };\n }, [mergedOpen, shouldMatchPopupWidth]);\n const [showResponsiveSelectedSection, setShowResponsiveSelectedSection] =\n useState(false);\n // 多选 responsive 进入 -1 收纳态(仅\"首 tag + +N\")时为 true,\n // width:auto 下据此给根节点加 overflow-collapsed 钳住 min-width 链,\n // 抵抗父 flex 行因 intrinsic 低估造成的假压缩(详见 ald-select.css 对应段)\n const [overflowCollapsed, setOverflowCollapsed] = useState(false);\n\n // ============================ Selector ============================\n const onSelectorRemove = (val: DisplayValueType) => {\n const newValues = displayValues.filter(\n (item) => toString(item.value) !== toString(val.value),\n );\n\n onDisplayValuesChange(newValues, {\n type: 'remove',\n values: [\n {\n label: val.label,\n value: val.value as RawValueType,\n },\n ],\n });\n };\n\n const mergedClassName = cn(\n setClassNames('beta-ald-select', size, {\n active: mergedOpen || focus,\n borderless: borderLess,\n disabled: disabled,\n loading: loading,\n [`${mergedStatus}`]: !!mergedStatus,\n 'multiple-responsive': isResponsiveMode,\n 'multiple-default': isMultipleMode && !isResponsiveMode,\n // 仅 width:auto 生效:固定宽度下 -1 收纳态的收缩省略是预期行为,\n // 钳 min-width 反而会把固定宽撑破\n 'overflow-collapsed':\n overflowCollapsed && width === 'auto' && !_.isEmpty(displayValues),\n }),\n 'tw-text-typography-body-dense',\n className,\n compactItemClassnames,\n );\n const showMenu = React.useMemo(() => {\n if (!displayMenu) {\n return undefined;\n }\n\n return {\n ...displayMenu,\n onClick: (info: MenuInfo) => {\n displayMenu?.onClick?.(info);\n if (isMultipleMode) {\n // 多选默认选中后不收起下拉:Dropdown 在 menu.onClick 之后读\n // info.keepOpen 决定是否 onChangeOpen(false),不设则每次点击都被\n // 当成关闭信号。用 ?? 保留用户在自己的 onClick 里显式设 false 的能力\n info.keepOpen = info.keepOpen ?? true;\n } else if (displayMenu) {\n onToggleOpen(false);\n setFocus(false);\n }\n setIsHover(false);\n onOptionSelect?.(info.key);\n },\n };\n }, [displayMenu, isMultipleMode, onToggleOpen, onOptionSelect]);\n const onSelectClick = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n onClick?.(e);\n },\n [disabled, onClick],\n );\n React.useEffect(() => {\n const element = selectRef.current;\n if (element) {\n const handleMouseOver = () => setIsHover(true);\n const handleMouseOut = () => setIsHover(false);\n\n element.addEventListener('mouseover', handleMouseOver);\n element.addEventListener('mouseout', handleMouseOut);\n\n return () => {\n element.removeEventListener('mouseover', handleMouseOver);\n element.removeEventListener('mouseout', handleMouseOut);\n };\n }\n }, []);\n const mergedPopupMatchSelectWidth =\n shouldMatchPopupWidth && matchedPopupWidth !== undefined\n ? matchedPopupWidth\n : popupMatchSelectWidth;\n return (\n <div\n className={mergedClassName}\n style={{\n ...widthStyle,\n // width:auto 且无选中值时锁 shrink:Chromium 对该子树给父 flex 行的\n // intrinsic 宽度贡献恒少约 14px,父行按低估值布局后回头压缩根节点,\n // placeholder 右侧会被裁;有选中值时必须保持可压缩,rc-overflow\n // 才能在父行变窄时把放不下的 tag 收纳成 \"+N\"\n ...(width === 'auto' && _.isEmpty(displayValues)\n ? { flexShrink: 0 }\n : {}),\n ...style,\n }}\n ref={selectRef}\n id={id}\n onClick={onSelectClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n >\n <SelectTrigger\n {...restProps}\n open={!!mergedOpen}\n notFoundContent={notFoundContent}\n menu={showMenu}\n ref={dropdownRef}\n showSearch={showSearch}\n searchValue={innerSearchValue}\n setInnerSearchValue={setInnerSearchValue}\n popupMatchSelectWidth={mergedPopupMatchSelectWidth}\n overlayClassName={popupClassName}\n // @ts-ignore\n dropdownRender={dropdownRender}\n overlayStyle={overlayStyle || dropdownStyle}\n placement={placement}\n allowOverlap={allowOverlap}\n onOpenChange={(open) => {\n if (isResponsiveMode) {\n if (\n !mergedOpen &&\n !showResponsiveSelectedSection &&\n displayValues.length > 0 &&\n isShowSelectedSection(mode)\n ) {\n setShowResponsiveSelectedSection(true);\n } else {\n onToggleOpen(open);\n }\n } else {\n onToggleOpen(open);\n }\n }}\n >\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div className={cn(setClassNames('trigger'), 'ant-select-selector')}>\n {prefix && <div className={setClassNames('prefix')}>{prefix}</div>}\n {_.isEmpty(displayValues) && (\n <div\n className={cn(\n setClassNames('placeholder'),\n 'ant-select-selection-placeholder',\n )}\n >\n {placeholder}\n </div>\n )}\n {!_.isEmpty(displayValues) && (\n <Selector\n {...restProps}\n suffixIcon={suffixIcon}\n size={size}\n disabled={disabled}\n mode={mode}\n dropdownRef={dropdownRef}\n displayValues={displayValues}\n onToggleOpen={onToggleOpen}\n onRemove={onSelectorRemove}\n showResponsiveSelectedSection={showResponsiveSelectedSection}\n onOverflowCollapsedChange={setOverflowCollapsed}\n ></Selector>\n )}\n </div>\n </SelectTrigger>\n <Suffix\n showArrow={showArrow}\n allowClear={allowClear}\n disabled={disabled}\n loading={loading}\n isHover={isHover}\n onClear={() => {\n onToggleOpen(false);\n\n onDisplayValuesChange([], {\n type: 'clear',\n values: displayValues,\n });\n onClear?.();\n }}\n isActive={innerOpen}\n icon={suffixIcon}\n displayValues={displayValues}\n ></Suffix>\n </div>\n );\n },\n);\n\nexport default BaseSelect;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BaseSelect.js","names":[],"sources":["../../src/Select/BaseSelect.tsx"],"sourcesContent":["import './ald-select.css';\nimport * as React from 'react';\nimport useMergedState from 'rc-util/es/hooks/useMergedState';\nimport { cn } from '../lib/utils';\nimport prefixCls from '../_utils/prefixCls';\n\n/** Align config type (locally defined to avoid rc-trigger dependency) */\nexport interface AlignType {\n points?: string[];\n offset?: (number | string)[];\n targetOffset?: (number | string)[];\n overflow?: { adjustX?: boolean; adjustY?: boolean };\n _experimental?: Record<string, any>;\n}\nimport SelectTrigger, { RefTriggerProps } from './SelectTrigger';\nimport Selector from './Selector';\nimport _ from 'lodash';\nimport { useContext, useRef, useState } from 'react';\nimport { FormItemInputContext } from '../Form/FormItemContext';\nimport getWidthStyle from './utils/getWidthStyle';\nimport Suffix from './components/Suffix';\nimport { PlacementType } from '../Dropdown';\nimport {\n BaseSelectRef,\n DisplayValueType,\n ISelectProps,\n LabelInValueType,\n SelectMenuProps,\n} from './interface';\nimport SizeContext from '../ConfigProvider/sizeContext';\nimport { ConfigContext } from '../ConfigProvider';\nimport { useCompactItemContext } from '../Space/CompactContext';\nimport { MenuInfo } from '../Menu';\nimport { toString } from './utils/commonUtil';\n\nexport type RenderNode = React.ReactNode | ((props: any) => React.ReactNode);\n\nexport type RenderDOMFunc = (props: any) => HTMLElement;\n\nexport type Mode =\n | 'multiple'\n | {\n type: 'multiple';\n responsive?: boolean;\n maxRows?: number;\n showSelectedSection?: boolean;\n };\n\nexport type RawValueType = string | number;\n\nexport type CustomTagProps = {\n label: React.ReactNode;\n value: any;\n disabled: boolean;\n onClose: (event?: React.MouseEvent<HTMLElement, MouseEvent>) => void;\n closable: boolean;\n};\nexport interface BaseSelectPrivateProps {\n // >>> MISC\n omitDomProps?: string[];\n\n // >>> Value\n displayValues: LabelInValueType[];\n onDisplayValuesChange: (\n values: LabelInValueType[],\n info: {\n type: 'add' | 'remove' | 'clear';\n values: LabelInValueType[];\n },\n ) => void;\n\n // >>> Active\n /** Current dropdown list active item string value */\n activeValue?: string;\n /** Link search input with target element */\n activeDescendantId?: string;\n onActiveValueChange?: (value: string | null) => void;\n}\n\nexport type BaseSelectPropsWithoutPrivate = Omit<\n BaseSelectProps,\n keyof BaseSelectPrivateProps\n>;\n\nexport interface BaseSelectProps\n extends BaseSelectPrivateProps,\n ISelectProps,\n React.AriaAttributes {\n className?: string;\n style?: React.CSSProperties;\n notFoundContent?: React.ReactNode;\n onClear?: () => void;\n innerSearchValue?: string;\n setInnerSearchValue?: (value: string) => void;\n displayMenu?: SelectMenuProps;\n // >>> Open\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n onOptionSelect?: (val: RawValueType) => void;\n\n // >>> Icons\n allowClear?: boolean;\n showArrow?: boolean;\n suffixIcon?: React.ReactNode;\n\n // >>> Dropdown\n dropdownAlign?: AlignType;\n placement?: PlacementType;\n getPopupContainer?: () => HTMLElement;\n\n // >>> Focus\n onBlur?: React.FocusEventHandler<HTMLElement>;\n onFocus?: React.FocusEventHandler<HTMLElement>;\n\n // >>> Rest Events\n onKeyUp?: React.KeyboardEventHandler<HTMLDivElement>;\n onKeyDown?: React.KeyboardEventHandler<HTMLDivElement>;\n onMouseDown?: React.MouseEventHandler<HTMLDivElement>;\n onPopupScroll?: React.UIEventHandler<HTMLDivElement>;\n onInputKeyDown?: React.KeyboardEventHandler<\n HTMLInputElement | HTMLTextAreaElement\n >;\n onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLDivElement>;\n onClick?: React.MouseEventHandler<HTMLDivElement>;\n}\n\nexport function isMultiple(mode?: Mode) {\n return !!mode;\n}\nexport function isResponsive(mode?: Mode) {\n return mode === 'multiple' || (typeof mode === 'object' && mode?.responsive);\n}\nexport function isShowSelectedSection(mode?: Mode) {\n if (!mode || mode === 'multiple') {\n return false;\n }\n\n return (\n typeof mode === 'object' && mode.showSelectedSection && mode.responsive\n );\n}\nconst BaseSelect = React.forwardRef(\n (props: BaseSelectProps, ref: React.Ref<BaseSelectRef>) => {\n const {\n id,\n className,\n // Value\n displayValues,\n onDisplayValuesChange,\n displayMenu,\n notFoundContent,\n onClear,\n width,\n mode,\n status: customStatus,\n onOptionSelect,\n onClick,\n size: customSize,\n borderLess = false,\n // Status\n disabled,\n placeholder,\n loading = false,\n\n // Open\n open,\n defaultOpen,\n onOpenChange,\n showSearch,\n innerSearchValue,\n setInnerSearchValue,\n // Icons\n allowClear,\n showArrow = true,\n prefix,\n suffixIcon,\n dropdownRender,\n overlayStyle,\n dropdownStyle,\n popupMatchSelectWidth = true,\n placement,\n popupClassName,\n allowOverlap,\n style,\n 'data-testid': dataTestid,\n 'aria-label': ariaLabel,\n ...restProps\n // Rest Props\n } = props;\n const setClassNames = prefixCls('select');\n const selectRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLDivElement>(null);\n const widthStyle = getWidthStyle(width);\n const dropdownRef = useRef<RefTriggerProps>(null);\n const [matchedPopupWidth, setMatchedPopupWidth] = useState<\n number | undefined\n >();\n const isResponsiveMode = isResponsive(mode);\n const isMultipleMode = isMultiple(mode);\n /** Used for component focused management */\n const contentSize = useContext(SizeContext);\n const { direction } = React.useContext(ConfigContext);\n // ===================== Compact Item =====================\n const { compactSize, compactItemClassnames } = useCompactItemContext(\n 'ald-select',\n direction,\n );\n const size = compactSize || customSize || contentSize || 'middle';\n const {\n status: contextStatus,\n // hasFeedback,\n // isFormItemInput,\n // feedbackIcon,\n } = useContext(FormItemInputContext);\n\n const mergedStatus =\n customStatus === null ? undefined : customStatus || contextStatus;\n\n // =========================== Imperative ===========================\n React.useImperativeHandle(ref, () => ({\n // The trigger is the Select focus owner. Keeping this as a real DOM\n // focus target makes keyboard focus, the Focus State Layer, and the\n // public imperative API describe the same element.\n focus: () => triggerRef.current?.focus(),\n blur: () => triggerRef.current?.blur(),\n open: () => onToggleOpen(true),\n close: () => {\n console.log('ref close');\n onToggleOpen(false);\n },\n }));\n const [isHover, setIsHover] = useState(false);\n // ============================== Open ==============================\n const [innerOpen, setInnerOpen] = useMergedState<boolean>(false, {\n defaultValue: defaultOpen,\n value: open,\n });\n const mergedOpen = innerOpen;\n const shouldMatchPopupWidth =\n !!popupMatchSelectWidth && typeof popupMatchSelectWidth !== 'number';\n const updateMatchedPopupWidth = React.useCallback(() => {\n if (!shouldMatchPopupWidth) {\n return;\n }\n\n const nextWidth = selectRef.current?.getBoundingClientRect().width;\n if (nextWidth !== undefined) {\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n }\n }, [shouldMatchPopupWidth]);\n const onToggleOpen = React.useCallback(\n (newOpen?: boolean) => {\n const nextOpen = newOpen !== undefined ? newOpen : !mergedOpen;\n if (nextOpen) {\n updateMatchedPopupWidth();\n }\n if (!nextOpen) {\n setShowResponsiveSelectedSection(false);\n }\n if (mergedOpen !== nextOpen && !disabled) {\n setInnerOpen(nextOpen);\n onOpenChange?.(nextOpen);\n }\n },\n [\n mergedOpen,\n disabled,\n setInnerOpen,\n onOpenChange,\n updateMatchedPopupWidth,\n ],\n );\n React.useLayoutEffect(() => {\n if (!mergedOpen || !shouldMatchPopupWidth) {\n return;\n }\n\n const element = selectRef.current;\n if (!element) {\n return;\n }\n\n const updateMatchedWidth = () => {\n const nextWidth = element.getBoundingClientRect().width;\n setMatchedPopupWidth((currentWidth) =>\n currentWidth === nextWidth ? currentWidth : nextWidth,\n );\n };\n\n updateMatchedWidth();\n\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateMatchedWidth);\n return () => {\n window.removeEventListener('resize', updateMatchedWidth);\n };\n }\n\n let resizeAnimationFrame: number | undefined;\n const scheduleMatchedWidthUpdate = () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n resizeAnimationFrame = requestAnimationFrame(updateMatchedWidth);\n };\n\n const observer = new ResizeObserver(scheduleMatchedWidthUpdate);\n observer.observe(element);\n\n return () => {\n if (resizeAnimationFrame !== undefined) {\n cancelAnimationFrame(resizeAnimationFrame);\n }\n observer.disconnect();\n };\n }, [mergedOpen, shouldMatchPopupWidth]);\n const [showResponsiveSelectedSection, setShowResponsiveSelectedSection] =\n useState(false);\n // 多选 responsive 进入 -1 收纳态(仅\"首 tag + +N\")时为 true,\n // width:auto 下据此给根节点加 overflow-collapsed 钳住 min-width 链,\n // 抵抗父 flex 行因 intrinsic 低估造成的假压缩(详见 ald-select.css 对应段)\n const [overflowCollapsed, setOverflowCollapsed] = useState(false);\n\n // ============================ Selector ============================\n const onSelectorRemove = (val: DisplayValueType) => {\n const newValues = displayValues.filter(\n (item) => toString(item.value) !== toString(val.value),\n );\n\n onDisplayValuesChange(newValues, {\n type: 'remove',\n values: [\n {\n label: val.label,\n value: val.value as RawValueType,\n },\n ],\n });\n };\n\n const mergedClassName = cn(\n setClassNames('beta-ald-select', size, {\n // Popup visibility is not focus. The trigger's :focus-visible state\n // owns the Focus State Layer in ald-select.css.\n open: mergedOpen,\n // Retain the legacy hook for consumers that style the open state.\n // It no longer represents trigger focus.\n active: mergedOpen,\n borderless: borderLess,\n disabled: disabled,\n loading: loading,\n [`${mergedStatus}`]: !!mergedStatus,\n 'multiple-responsive': isResponsiveMode,\n 'multiple-default': isMultipleMode && !isResponsiveMode,\n // 仅 width:auto 生效:固定宽度下 -1 收纳态的收缩省略是预期行为,\n // 钳 min-width 反而会把固定宽撑破\n 'overflow-collapsed':\n overflowCollapsed && width === 'auto' && !_.isEmpty(displayValues),\n }),\n 'tw-text-typography-body-dense',\n className,\n compactItemClassnames,\n );\n const showMenu = React.useMemo(() => {\n if (!displayMenu) {\n return undefined;\n }\n\n return {\n ...displayMenu,\n onClick: (info: MenuInfo) => {\n displayMenu?.onClick?.(info);\n if (isMultipleMode) {\n // 多选默认选中后不收起下拉:Dropdown 在 menu.onClick 之后读\n // info.keepOpen 决定是否 onChangeOpen(false),不设则每次点击都被\n // 当成关闭信号。用 ?? 保留用户在自己的 onClick 里显式设 false 的能力\n info.keepOpen = info.keepOpen ?? true;\n } else if (displayMenu) {\n onToggleOpen(false);\n }\n setIsHover(false);\n onOptionSelect?.(info.key);\n },\n };\n }, [displayMenu, isMultipleMode, onToggleOpen, onOptionSelect]);\n const onSelectClick = React.useCallback(\n (e: React.MouseEvent<HTMLDivElement>) => {\n if (disabled) {\n return;\n }\n onClick?.(e);\n },\n [disabled, onClick],\n );\n React.useEffect(() => {\n const element = selectRef.current;\n if (element) {\n const handleMouseOver = () => setIsHover(true);\n const handleMouseOut = () => setIsHover(false);\n\n element.addEventListener('mouseover', handleMouseOver);\n element.addEventListener('mouseout', handleMouseOut);\n\n return () => {\n element.removeEventListener('mouseover', handleMouseOver);\n element.removeEventListener('mouseout', handleMouseOut);\n };\n }\n }, []);\n const mergedPopupMatchSelectWidth =\n shouldMatchPopupWidth && matchedPopupWidth !== undefined\n ? matchedPopupWidth\n : popupMatchSelectWidth;\n return (\n <div\n className={mergedClassName}\n style={{\n ...widthStyle,\n // width:auto 且无选中值时锁 shrink:Chromium 对该子树给父 flex 行的\n // intrinsic 宽度贡献恒少约 14px,父行按低估值布局后回头压缩根节点,\n // placeholder 右侧会被裁;有选中值时必须保持可压缩,rc-overflow\n // 才能在父行变窄时把放不下的 tag 收纳成 \"+N\"\n ...(width === 'auto' && _.isEmpty(displayValues)\n ? { flexShrink: 0 }\n : {}),\n ...style,\n }}\n ref={selectRef}\n id={id}\n onClick={onSelectClick}\n data-testid={dataTestid}\n aria-label={ariaLabel}\n >\n <SelectTrigger\n {...restProps}\n open={!!mergedOpen}\n notFoundContent={notFoundContent}\n menu={showMenu}\n ref={dropdownRef}\n showSearch={showSearch}\n searchValue={innerSearchValue}\n setInnerSearchValue={setInnerSearchValue}\n popupMatchSelectWidth={mergedPopupMatchSelectWidth}\n overlayClassName={popupClassName}\n // @ts-ignore\n dropdownRender={dropdownRender}\n overlayStyle={overlayStyle || dropdownStyle}\n placement={placement}\n allowOverlap={allowOverlap}\n onOpenChange={(open) => {\n if (isResponsiveMode) {\n if (\n !mergedOpen &&\n !showResponsiveSelectedSection &&\n displayValues.length > 0 &&\n isShowSelectedSection(mode)\n ) {\n setShowResponsiveSelectedSection(true);\n } else {\n onToggleOpen(open);\n }\n } else {\n onToggleOpen(open);\n }\n }}\n >\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n ref={triggerRef}\n tabIndex={disabled ? undefined : 0}\n role=\"combobox\"\n aria-disabled={disabled || undefined}\n aria-expanded={mergedOpen}\n className={cn(setClassNames('trigger'), 'ant-select-selector')}\n >\n {prefix && <div className={setClassNames('prefix')}>{prefix}</div>}\n {_.isEmpty(displayValues) && (\n <div\n className={cn(\n setClassNames('placeholder'),\n 'ant-select-selection-placeholder',\n )}\n >\n {placeholder}\n </div>\n )}\n {!_.isEmpty(displayValues) && (\n <Selector\n {...restProps}\n suffixIcon={suffixIcon}\n size={size}\n disabled={disabled}\n mode={mode}\n dropdownRef={dropdownRef}\n displayValues={displayValues}\n onToggleOpen={onToggleOpen}\n onRemove={onSelectorRemove}\n showResponsiveSelectedSection={showResponsiveSelectedSection}\n onOverflowCollapsedChange={setOverflowCollapsed}\n ></Selector>\n )}\n </div>\n </SelectTrigger>\n <Suffix\n showArrow={showArrow}\n allowClear={allowClear}\n disabled={disabled}\n loading={loading}\n isHover={isHover}\n onClear={() => {\n onToggleOpen(false);\n\n onDisplayValuesChange([], {\n type: 'clear',\n values: displayValues,\n });\n onClear?.();\n }}\n isActive={innerOpen}\n icon={suffixIcon}\n displayValues={displayValues}\n ></Suffix>\n </div>\n );\n },\n);\n\nexport default BaseSelect;\n"],"mappings":"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"}
|
|
@@ -35,7 +35,7 @@ function InternalItem(props) {
|
|
|
35
35
|
var ITEM_WIDTH = 10;
|
|
36
36
|
var REST_KEY = "__OVERFLOW_REST__";
|
|
37
37
|
function OverflowInner(props, ref) {
|
|
38
|
-
const { prefixCls = "rc-overflow", data, renderItem, itemKey, renderRest, className, onVisibleChange } = props;
|
|
38
|
+
const { prefixCls = "rc-overflow", data, renderItem, itemKey, renderRest, gap = 0, className, onVisibleChange } = props;
|
|
39
39
|
const [containerWidth, setContainerWidth] = useState(null);
|
|
40
40
|
const mergedContainerWidth = containerWidth || 0;
|
|
41
41
|
const [itemWidths, setItemWidths] = useState(() => /* @__PURE__ */ new Map());
|
|
@@ -97,11 +97,11 @@ function OverflowInner(props, ref) {
|
|
|
97
97
|
return;
|
|
98
98
|
}
|
|
99
99
|
totalWidth += currentItemWidth;
|
|
100
|
-
if (lastIndex === 0 && totalWidth <= mergedContainerWidth || i === lastIndex - 1 && totalWidth + (getItemWidth(lastIndex) ?? 0) <= mergedContainerWidth) {
|
|
100
|
+
if (lastIndex === 0 && totalWidth <= mergedContainerWidth || i === lastIndex - 1 && totalWidth + (getItemWidth(lastIndex) ?? 0) + lastIndex * gap <= mergedContainerWidth) {
|
|
101
101
|
updateDisplayCount(lastIndex);
|
|
102
102
|
return;
|
|
103
103
|
}
|
|
104
|
-
if (totalWidth + mergedRestWidth > mergedContainerWidth) {
|
|
104
|
+
if (totalWidth + mergedRestWidth + (i + 1) * gap > mergedContainerWidth) {
|
|
105
105
|
updateDisplayCount(i - 1);
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FixedOverflow.js","names":[],"sources":["../../../src/Select/Selector/FixedOverflow.tsx"],"sourcesContent":["// 修复 rc-overflow 的 restReady 卡 false bug。\n//\n// 根因(rc-overflow@1.5 es/Overflow.js updateDisplayCount):\n// if (displayCount === count && ...) return; // <-- 这一行\n// setDisplayCount(count);\n// if (!notReady) { setRestReady(count < data.length - 1); onVisibleChange?.(count); }\n//\n// 触发条件:modal 首开等首屏渲染时,半测量阶段(部分 itemWidth 还没注册)\n// 会先以 notReady=true 把 displayCount 推到「最终值 N」(比如 9 个 tag 都已\n// 测过,第 10 个还没到时调用 updateDisplayCount(9, undefined, true),\n// 而最终稳定态恰好也是 displayCount=9)。后续 ready 路径 displayCount===count\n// 早返回,setRestReady 永远没被调用 → restReady 始终是 false →\n// rest 节点 opacity:0, position:absolute, height:0 不可见。\n//\n// 修复:把 setRestReady 和 onVisibleChange 移到 early-return 之前。只要本次\n// 是 ready 路径,无论 displayCount 是否变化,都把 rest 状态推到位。\n//\n// 其它逻辑 1:1 复刻 rc-overflow 的 responsive 分支(ald 只用 maxCount='responsive'\n// 一种模式,prefix/suffix/raw render 等都没用),删掉用不到的代码以降复杂度。\n// 用 React 18 自动批处理,不再重写 channelUpdate / unstable_batchedUpdates。\n\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ResizeObserver from 'rc-resize-observer';\nimport useLayoutEffect from 'rc-util/es/hooks/useLayoutEffect';\nimport cn from 'classnames';\n\ninterface ResizeInfo {\n width: number;\n height: number;\n offsetWidth: number;\n offsetHeight: number;\n}\n\ninterface InternalItemProps {\n prefixCls: string;\n display: boolean;\n order: number;\n itemKey: React.Key;\n registerSize: (key: React.Key, width: number | null) => void;\n className?: string;\n children?: React.ReactNode;\n}\n\nfunction InternalItem(props: InternalItemProps) {\n const {\n prefixCls,\n display,\n order,\n itemKey,\n registerSize,\n className,\n children,\n } = props;\n const mergedHidden = !display;\n // 卸载时把本 item 的 width 从 Map 里删掉。registerSize/itemKey 用 ref 抓最新,\n // 这样 effect 自身依赖只有 [],不需要 eslint-disable。\n const registerSizeRef = useRef(registerSize);\n const itemKeyRef = useRef(itemKey);\n registerSizeRef.current = registerSize;\n itemKeyRef.current = itemKey;\n useEffect(\n () => () => {\n registerSizeRef.current(itemKeyRef.current, null);\n },\n [],\n );\n const overflowStyle: React.CSSProperties = {\n opacity: mergedHidden ? 0 : 1,\n height: mergedHidden ? 0 : undefined,\n overflowY: mergedHidden ? 'hidden' : undefined,\n order,\n pointerEvents: mergedHidden ? 'none' : undefined,\n position: mergedHidden ? 'absolute' : undefined,\n };\n return (\n <ResizeObserver\n onResize={({ offsetWidth }: ResizeInfo) =>\n registerSize(itemKey, offsetWidth)\n }\n >\n <div\n className={cn(prefixCls, className)}\n style={overflowStyle}\n aria-hidden={mergedHidden || undefined}\n >\n {children}\n </div>\n </ResizeObserver>\n );\n}\n\nexport interface FixedOverflowProps<T> {\n prefixCls?: string;\n data: T[];\n renderItem: (item: T, info: { index: number }) => React.ReactNode;\n itemKey: (item: T) => React.Key;\n renderRest: (omittedItems: T[]) => React.ReactNode;\n className?: string;\n onVisibleChange?: (count: number) => void;\n}\n\nconst ITEM_WIDTH = 10;\n// rest 节点的固定 React key。假设调用方传入的 itemKey 不会返回此常量\n// (ald 内部 Select 的 itemKey 取 value/key 字段,不会等于这个字符串)。\nconst REST_KEY: React.Key = '__OVERFLOW_REST__';\n\nfunction OverflowInner<T>(\n props: FixedOverflowProps<T>,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n prefixCls = 'rc-overflow',\n data,\n renderItem,\n itemKey,\n renderRest,\n className,\n onVisibleChange,\n } = props;\n\n const [containerWidth, setContainerWidth] = useState<number | null>(null);\n const mergedContainerWidth = containerWidth || 0;\n const [itemWidths, setItemWidths] = useState<Map<React.Key, number>>(\n () => new Map(),\n );\n const [prevRestWidth, setPrevRestWidth] = useState(0);\n const [restWidth, setRestWidth] = useState(0);\n const [displayCount, setDisplayCount] = useState<number | null>(null);\n const [restReady, setRestReady] = useState(false);\n\n const mergedDisplayCount = displayCount || 0;\n const itemPrefixCls = `${prefixCls}-item`;\n const mergedRestWidth = Math.max(prevRestWidth, restWidth);\n\n const getKey = useCallback(\n (item: T, index: number): React.Key => {\n if (item == null) return index;\n return itemKey(item) ?? index;\n },\n [itemKey],\n );\n\n const mergedData = useMemo(() => {\n if (!data.length) return data;\n return data.slice(\n 0,\n Math.min(data.length, mergedContainerWidth / ITEM_WIDTH),\n );\n }, [data, mergedContainerWidth]);\n\n const omittedItems = useMemo(\n () => data.slice(mergedDisplayCount + 1),\n [data, mergedDisplayCount],\n );\n\n const updateDisplayCount = (count: number, notReady?: boolean) => {\n // === BUG FIX ===\n // 不论 displayCount 是否变化,只要本次是 ready 路径,立即把 restReady /\n // onVisibleChange 推到位。原版在 displayCount===count 时早返回,会跳过\n // 这两步,造成 restReady 卡死在 false。\n if (!notReady) {\n setRestReady(count < data.length - 1);\n onVisibleChange?.(count);\n }\n if (displayCount !== count) {\n setDisplayCount(count);\n }\n };\n\n const registerSize = useCallback((key: React.Key, width: number | null) => {\n setItemWidths((origin) => {\n const clone = new Map(origin);\n if (width === null) clone.delete(key);\n else clone.set(key, width);\n return clone;\n });\n }, []);\n\n const registerRestSize = useCallback(\n (_key: React.Key, width: number | null) => {\n if (width === null) return;\n setRestWidth((prev) => {\n setPrevRestWidth(prev);\n return width;\n });\n },\n [],\n );\n\n const onOverflowResize = (_: ResizeInfo, element: HTMLElement) => {\n setContainerWidth(element.clientWidth);\n };\n\n // 故意不加依赖数组:测量回路依赖每次渲染都重跑——itemWidths 变 → 重算 displayCount\n // → 触发再渲染 → 再测量。加 deps 会破坏 rc-overflow 原版的测量-更新循环。\n useLayoutEffect(() => {\n if (!mergedContainerWidth || !mergedData) return;\n const len = mergedData.length;\n const lastIndex = len - 1;\n if (!len) {\n updateDisplayCount(0);\n return;\n }\n let totalWidth = 0;\n const getItemWidth = (index: number): number | undefined =>\n itemWidths.get(getKey(mergedData[index], index));\n for (let i = 0; i < len; i += 1) {\n const currentItemWidth = getItemWidth(i);\n if (currentItemWidth === undefined) {\n // 半测量:先把 displayCount 推到 i-1,但不动 restReady(notReady=true)。\n updateDisplayCount(i - 1, true);\n return;\n }\n totalWidth += currentItemWidth;\n if (\n (lastIndex === 0 && totalWidth <= mergedContainerWidth) ||\n (i === lastIndex - 1 &&\n totalWidth + (getItemWidth(lastIndex) ?? 0) <= mergedContainerWidth)\n ) {\n // 全部塞得下\n updateDisplayCount(lastIndex);\n return;\n }\n if (totalWidth + mergedRestWidth > mergedContainerWidth) {\n // 当前这个塞不下了,需要展示 \"+N\"\n updateDisplayCount(i - 1);\n return;\n }\n }\n });\n\n const displayRest = restReady && !!omittedItems.length;\n\n return (\n <ResizeObserver onResize={onOverflowResize} disabled={!data.length}>\n <div className={cn(prefixCls, className)} ref={ref}>\n {mergedData.map((item, index) => {\n const key = getKey(item, index);\n return (\n <InternalItem\n key={key}\n prefixCls={itemPrefixCls}\n display={index <= mergedDisplayCount}\n order={index}\n itemKey={key}\n registerSize={registerSize}\n >\n {renderItem(item, { index })}\n </InternalItem>\n );\n })}\n <InternalItem\n prefixCls={itemPrefixCls}\n display={displayRest}\n order={displayRest ? mergedDisplayCount : Number.MAX_SAFE_INTEGER}\n itemKey={REST_KEY}\n registerSize={registerRestSize}\n className={`${itemPrefixCls}-rest`}\n >\n {renderRest(omittedItems)}\n </InternalItem>\n </div>\n </ResizeObserver>\n );\n}\n\nconst FixedOverflow = forwardRef(OverflowInner) as <T>(\n props: FixedOverflowProps<T> & { ref?: React.Ref<HTMLDivElement> },\n) => React.ReactElement;\n\nexport default FixedOverflow;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FixedOverflow.js","names":[],"sources":["../../../src/Select/Selector/FixedOverflow.tsx"],"sourcesContent":["// 修复 rc-overflow 的 restReady 卡 false bug。\n//\n// 根因(rc-overflow@1.5 es/Overflow.js updateDisplayCount):\n// if (displayCount === count && ...) return; // <-- 这一行\n// setDisplayCount(count);\n// if (!notReady) { setRestReady(count < data.length - 1); onVisibleChange?.(count); }\n//\n// 触发条件:modal 首开等首屏渲染时,半测量阶段(部分 itemWidth 还没注册)\n// 会先以 notReady=true 把 displayCount 推到「最终值 N」(比如 9 个 tag 都已\n// 测过,第 10 个还没到时调用 updateDisplayCount(9, undefined, true),\n// 而最终稳定态恰好也是 displayCount=9)。后续 ready 路径 displayCount===count\n// 早返回,setRestReady 永远没被调用 → restReady 始终是 false →\n// rest 节点 opacity:0, position:absolute, height:0 不可见。\n//\n// 修复:把 setRestReady 和 onVisibleChange 移到 early-return 之前。只要本次\n// 是 ready 路径,无论 displayCount 是否变化,都把 rest 状态推到位。\n//\n// 其它逻辑 1:1 复刻 rc-overflow 的 responsive 分支(ald 只用 maxCount='responsive'\n// 一种模式,prefix/suffix/raw render 等都没用),删掉用不到的代码以降复杂度。\n// 用 React 18 自动批处理,不再重写 channelUpdate / unstable_batchedUpdates。\n\nimport React, {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport ResizeObserver from 'rc-resize-observer';\nimport useLayoutEffect from 'rc-util/es/hooks/useLayoutEffect';\nimport cn from 'classnames';\n\ninterface ResizeInfo {\n width: number;\n height: number;\n offsetWidth: number;\n offsetHeight: number;\n}\n\ninterface InternalItemProps {\n prefixCls: string;\n display: boolean;\n order: number;\n itemKey: React.Key;\n registerSize: (key: React.Key, width: number | null) => void;\n className?: string;\n children?: React.ReactNode;\n}\n\nfunction InternalItem(props: InternalItemProps) {\n const {\n prefixCls,\n display,\n order,\n itemKey,\n registerSize,\n className,\n children,\n } = props;\n const mergedHidden = !display;\n // 卸载时把本 item 的 width 从 Map 里删掉。registerSize/itemKey 用 ref 抓最新,\n // 这样 effect 自身依赖只有 [],不需要 eslint-disable。\n const registerSizeRef = useRef(registerSize);\n const itemKeyRef = useRef(itemKey);\n registerSizeRef.current = registerSize;\n itemKeyRef.current = itemKey;\n useEffect(\n () => () => {\n registerSizeRef.current(itemKeyRef.current, null);\n },\n [],\n );\n const overflowStyle: React.CSSProperties = {\n opacity: mergedHidden ? 0 : 1,\n height: mergedHidden ? 0 : undefined,\n overflowY: mergedHidden ? 'hidden' : undefined,\n order,\n pointerEvents: mergedHidden ? 'none' : undefined,\n position: mergedHidden ? 'absolute' : undefined,\n };\n return (\n <ResizeObserver\n onResize={({ offsetWidth }: ResizeInfo) =>\n registerSize(itemKey, offsetWidth)\n }\n >\n <div\n className={cn(prefixCls, className)}\n style={overflowStyle}\n aria-hidden={mergedHidden || undefined}\n >\n {children}\n </div>\n </ResizeObserver>\n );\n}\n\nexport interface FixedOverflowProps<T> {\n prefixCls?: string;\n data: T[];\n renderItem: (item: T, info: { index: number }) => React.ReactNode;\n itemKey: (item: T) => React.Key;\n renderRest: (omittedItems: T[]) => React.ReactNode;\n gap?: number;\n className?: string;\n onVisibleChange?: (count: number) => void;\n}\n\nconst ITEM_WIDTH = 10;\n// rest 节点的固定 React key。假设调用方传入的 itemKey 不会返回此常量\n// (ald 内部 Select 的 itemKey 取 value/key 字段,不会等于这个字符串)。\nconst REST_KEY: React.Key = '__OVERFLOW_REST__';\n\nfunction OverflowInner<T>(\n props: FixedOverflowProps<T>,\n ref: React.ForwardedRef<HTMLDivElement>,\n) {\n const {\n prefixCls = 'rc-overflow',\n data,\n renderItem,\n itemKey,\n renderRest,\n gap = 0,\n className,\n onVisibleChange,\n } = props;\n\n const [containerWidth, setContainerWidth] = useState<number | null>(null);\n const mergedContainerWidth = containerWidth || 0;\n const [itemWidths, setItemWidths] = useState<Map<React.Key, number>>(\n () => new Map(),\n );\n const [prevRestWidth, setPrevRestWidth] = useState(0);\n const [restWidth, setRestWidth] = useState(0);\n const [displayCount, setDisplayCount] = useState<number | null>(null);\n const [restReady, setRestReady] = useState(false);\n\n const mergedDisplayCount = displayCount || 0;\n const itemPrefixCls = `${prefixCls}-item`;\n const mergedRestWidth = Math.max(prevRestWidth, restWidth);\n\n const getKey = useCallback(\n (item: T, index: number): React.Key => {\n if (item == null) return index;\n return itemKey(item) ?? index;\n },\n [itemKey],\n );\n\n const mergedData = useMemo(() => {\n if (!data.length) return data;\n return data.slice(\n 0,\n Math.min(data.length, mergedContainerWidth / ITEM_WIDTH),\n );\n }, [data, mergedContainerWidth]);\n\n const omittedItems = useMemo(\n () => data.slice(mergedDisplayCount + 1),\n [data, mergedDisplayCount],\n );\n\n const updateDisplayCount = (count: number, notReady?: boolean) => {\n // === BUG FIX ===\n // 不论 displayCount 是否变化,只要本次是 ready 路径,立即把 restReady /\n // onVisibleChange 推到位。原版在 displayCount===count 时早返回,会跳过\n // 这两步,造成 restReady 卡死在 false。\n if (!notReady) {\n setRestReady(count < data.length - 1);\n onVisibleChange?.(count);\n }\n if (displayCount !== count) {\n setDisplayCount(count);\n }\n };\n\n const registerSize = useCallback((key: React.Key, width: number | null) => {\n setItemWidths((origin) => {\n const clone = new Map(origin);\n if (width === null) clone.delete(key);\n else clone.set(key, width);\n return clone;\n });\n }, []);\n\n const registerRestSize = useCallback(\n (_key: React.Key, width: number | null) => {\n if (width === null) return;\n setRestWidth((prev) => {\n setPrevRestWidth(prev);\n return width;\n });\n },\n [],\n );\n\n const onOverflowResize = (_: ResizeInfo, element: HTMLElement) => {\n setContainerWidth(element.clientWidth);\n };\n\n // 故意不加依赖数组:测量回路依赖每次渲染都重跑——itemWidths 变 → 重算 displayCount\n // → 触发再渲染 → 再测量。加 deps 会破坏 rc-overflow 原版的测量-更新循环。\n useLayoutEffect(() => {\n if (!mergedContainerWidth || !mergedData) return;\n const len = mergedData.length;\n const lastIndex = len - 1;\n if (!len) {\n updateDisplayCount(0);\n return;\n }\n let totalWidth = 0;\n const getItemWidth = (index: number): number | undefined =>\n itemWidths.get(getKey(mergedData[index], index));\n for (let i = 0; i < len; i += 1) {\n const currentItemWidth = getItemWidth(i);\n if (currentItemWidth === undefined) {\n // 半测量:先把 displayCount 推到 i-1,但不动 restReady(notReady=true)。\n updateDisplayCount(i - 1, true);\n return;\n }\n totalWidth += currentItemWidth;\n if (\n (lastIndex === 0 && totalWidth <= mergedContainerWidth) ||\n (i === lastIndex - 1 &&\n totalWidth + (getItemWidth(lastIndex) ?? 0) + lastIndex * gap <=\n mergedContainerWidth)\n ) {\n // 全部塞得下\n updateDisplayCount(lastIndex);\n return;\n }\n if (totalWidth + mergedRestWidth + (i + 1) * gap > mergedContainerWidth) {\n // 当前这个塞不下了,需要展示 \"+N\"\n updateDisplayCount(i - 1);\n return;\n }\n }\n });\n\n const displayRest = restReady && !!omittedItems.length;\n\n return (\n <ResizeObserver onResize={onOverflowResize} disabled={!data.length}>\n <div className={cn(prefixCls, className)} ref={ref}>\n {mergedData.map((item, index) => {\n const key = getKey(item, index);\n return (\n <InternalItem\n key={key}\n prefixCls={itemPrefixCls}\n display={index <= mergedDisplayCount}\n order={index}\n itemKey={key}\n registerSize={registerSize}\n >\n {renderItem(item, { index })}\n </InternalItem>\n );\n })}\n <InternalItem\n prefixCls={itemPrefixCls}\n display={displayRest}\n order={displayRest ? mergedDisplayCount : Number.MAX_SAFE_INTEGER}\n itemKey={REST_KEY}\n registerSize={registerRestSize}\n className={`${itemPrefixCls}-rest`}\n >\n {renderRest(omittedItems)}\n </InternalItem>\n </div>\n </ResizeObserver>\n );\n}\n\nconst FixedOverflow = forwardRef(OverflowInner) as <T>(\n props: FixedOverflowProps<T> & { ref?: React.Ref<HTMLDivElement> },\n) => React.ReactElement;\n\nexport default FixedOverflow;\n"],"mappings":";;;;;;AAkDA,SAAS,aAAa,OAA0B;CAC9C,MAAM,EACJ,WACA,SACA,OACA,SACA,cACA,WACA,aACE;CACJ,MAAM,eAAe,CAAC;CAGtB,MAAM,kBAAkB,OAAO,aAAa;CAC5C,MAAM,aAAa,OAAO,QAAQ;AAClC,iBAAgB,UAAU;AAC1B,YAAW,UAAU;AACrB,uBACc;AACV,kBAAgB,QAAQ,WAAW,SAAS,KAAK;IAEnD,EAAE,CACH;CACD,MAAM,gBAAqC;EACzC,SAAS,eAAe,IAAI;EAC5B,QAAQ,eAAe,IAAI;EAC3B,WAAW,eAAe,WAAW;EACrC;EACA,eAAe,eAAe,SAAS;EACvC,UAAU,eAAe,aAAa;EACvC;AACD,QACE,oBAAC,gBAAD;EACE,WAAW,EAAE,kBACX,aAAa,SAAS,YAAY;YAGpC,oBAAC,OAAD;GACE,WAAW,GAAG,WAAW,UAAU;GACnC,OAAO;GACP,eAAa,gBAAgB;GAE5B;GACG,CAAA;EACS,CAAA;;AAerB,IAAM,aAAa;AAGnB,IAAM,WAAsB;AAE5B,SAAS,cACP,OACA,KACA;CACA,MAAM,EACJ,YAAY,eACZ,MACA,YACA,SACA,YACA,MAAM,GACN,WACA,oBACE;CAEJ,MAAM,CAAC,gBAAgB,qBAAqB,SAAwB,KAAK;CACzE,MAAM,uBAAuB,kBAAkB;CAC/C,MAAM,CAAC,YAAY,iBAAiB,+BAC5B,IAAI,KAAK,CAChB;CACD,MAAM,CAAC,eAAe,oBAAoB,SAAS,EAAE;CACrD,MAAM,CAAC,WAAW,gBAAgB,SAAS,EAAE;CAC7C,MAAM,CAAC,cAAc,mBAAmB,SAAwB,KAAK;CACrE,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CAEjD,MAAM,qBAAqB,gBAAgB;CAC3C,MAAM,gBAAgB,GAAG,UAAU;CACnC,MAAM,kBAAkB,KAAK,IAAI,eAAe,UAAU;CAE1D,MAAM,SAAS,aACZ,MAAS,UAA6B;AACrC,MAAI,QAAQ,KAAM,QAAO;AACzB,SAAO,QAAQ,KAAK,IAAI;IAE1B,CAAC,QAAQ,CACV;CAED,MAAM,aAAa,cAAc;AAC/B,MAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,SAAO,KAAK,MACV,GACA,KAAK,IAAI,KAAK,QAAQ,uBAAuB,WAAW,CACzD;IACA,CAAC,MAAM,qBAAqB,CAAC;CAEhC,MAAM,eAAe,cACb,KAAK,MAAM,qBAAqB,EAAE,EACxC,CAAC,MAAM,mBAAmB,CAC3B;CAED,MAAM,sBAAsB,OAAe,aAAuB;AAKhE,MAAI,CAAC,UAAU;AACb,gBAAa,QAAQ,KAAK,SAAS,EAAE;AACrC,qBAAkB,MAAM;;AAE1B,MAAI,iBAAiB,MACnB,iBAAgB,MAAM;;CAI1B,MAAM,eAAe,aAAa,KAAgB,UAAyB;AACzE,iBAAe,WAAW;GACxB,MAAM,QAAQ,IAAI,IAAI,OAAO;AAC7B,OAAI,UAAU,KAAM,OAAM,OAAO,IAAI;OAChC,OAAM,IAAI,KAAK,MAAM;AAC1B,UAAO;IACP;IACD,EAAE,CAAC;CAEN,MAAM,mBAAmB,aACtB,MAAiB,UAAyB;AACzC,MAAI,UAAU,KAAM;AACpB,gBAAc,SAAS;AACrB,oBAAiB,KAAK;AACtB,UAAO;IACP;IAEJ,EAAE,CACH;CAED,MAAM,oBAAoB,GAAe,YAAyB;AAChE,oBAAkB,QAAQ,YAAY;;AAKxC,yBAAsB;AACpB,MAAI,CAAC,wBAAwB,CAAC,WAAY;EAC1C,MAAM,MAAM,WAAW;EACvB,MAAM,YAAY,MAAM;AACxB,MAAI,CAAC,KAAK;AACR,sBAAmB,EAAE;AACrB;;EAEF,IAAI,aAAa;EACjB,MAAM,gBAAgB,UACpB,WAAW,IAAI,OAAO,WAAW,QAAQ,MAAM,CAAC;AAClD,OAAK,IAAI,IAAI,GAAG,IAAI,KAAK,KAAK,GAAG;GAC/B,MAAM,mBAAmB,aAAa,EAAE;AACxC,OAAI,qBAAqB,QAAW;AAElC,uBAAmB,IAAI,GAAG,KAAK;AAC/B;;AAEF,iBAAc;AACd,OACG,cAAc,KAAK,cAAc,wBACjC,MAAM,YAAY,KACjB,cAAc,aAAa,UAAU,IAAI,KAAK,YAAY,OACxD,sBACJ;AAEA,uBAAmB,UAAU;AAC7B;;AAEF,OAAI,aAAa,mBAAmB,IAAI,KAAK,MAAM,sBAAsB;AAEvE,uBAAmB,IAAI,EAAE;AACzB;;;GAGJ;CAEF,MAAM,cAAc,aAAa,CAAC,CAAC,aAAa;AAEhD,QACE,oBAAC,gBAAD;EAAgB,UAAU;EAAkB,UAAU,CAAC,KAAK;YAC1D,qBAAC,OAAD;GAAK,WAAW,GAAG,WAAW,UAAU;GAAO;aAA/C,CACG,WAAW,KAAK,MAAM,UAAU;IAC/B,MAAM,MAAM,OAAO,MAAM,MAAM;AAC/B,WACE,oBAAC,cAAD;KAEE,WAAW;KACX,SAAS,SAAS;KAClB,OAAO;KACP,SAAS;KACK;eAEb,WAAW,MAAM,EAAE,OAAO,CAAC;KACf,EARR,IAQQ;KAEjB,EACF,oBAAC,cAAD;IACE,WAAW;IACX,SAAS;IACT,OAAO,cAAc,qBAAqB,OAAO;IACjD,SAAS;IACT,cAAc;IACd,WAAW,GAAG,cAAc;cAE3B,WAAW,aAAa;IACZ,CAAA,CACX;;EACS,CAAA;;AAIrB,IAAM,gBAAgB,WAAW,cAAc"}
|
|
@@ -102,6 +102,7 @@ function MultipleSelector(props) {
|
|
|
102
102
|
className: cn({ "beta-ald-select-selector-overflow-hidden": showItemIndex === -1 && displayValues.length === 1 }),
|
|
103
103
|
renderRest,
|
|
104
104
|
itemKey,
|
|
105
|
+
gap,
|
|
105
106
|
onVisibleChange
|
|
106
107
|
}),
|
|
107
108
|
showResponsiveSelectedSection && /* @__PURE__ */ jsx(MultipleResponsiveSelectedSection, {
|