@aloudata/aloudata-design 3.0.26 → 3.0.27

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.
Files changed (65) hide show
  1. package/dist/Button/index.js +4 -10
  2. package/dist/Button/index.js.map +1 -1
  3. package/dist/Checkbox/index.js +2 -8
  4. package/dist/Checkbox/index.js.map +1 -1
  5. package/dist/Collapse/index.js +22 -68
  6. package/dist/Collapse/index.js.map +1 -1
  7. package/dist/Input/components/Input/index.js +5 -11
  8. package/dist/Input/components/Input/index.js.map +1 -1
  9. package/dist/Input/components/TextArea/index.js +1 -7
  10. package/dist/Input/components/TextArea/index.js.map +1 -1
  11. package/dist/InputNumber/index.js +2 -8
  12. package/dist/InputNumber/index.js.map +1 -1
  13. package/dist/Pagination/PageSizeChanger.d.ts +0 -1
  14. package/dist/Pagination/PageSizeChanger.js +2 -3
  15. package/dist/Pagination/PageSizeChanger.js.map +1 -1
  16. package/dist/Pagination/index.js +19 -33
  17. package/dist/Pagination/index.js.map +1 -1
  18. package/dist/Pagination/types.d.ts +0 -3
  19. package/dist/Radio/components/Radio/index.js +1 -1
  20. package/dist/Radio/components/Radio/index.js.map +1 -1
  21. package/dist/Select/BaseSelect.js +12 -12
  22. package/dist/Select/BaseSelect.js.map +1 -1
  23. package/dist/Steps/index.js +14 -66
  24. package/dist/Steps/index.js.map +1 -1
  25. package/dist/Switch/index.js +1 -8
  26. package/dist/Switch/index.js.map +1 -1
  27. package/dist/Table/components/Cell.js +3 -8
  28. package/dist/Table/components/Cell.js.map +1 -1
  29. package/dist/Table/components/ExpandCell.js +2 -6
  30. package/dist/Table/components/ExpandCell.js.map +1 -1
  31. package/dist/Table/components/Footer/index.js +1 -2
  32. package/dist/Table/components/Footer/index.js.map +1 -1
  33. package/dist/Table/components/Header.js +18 -26
  34. package/dist/Table/components/Header.js.map +1 -1
  35. package/dist/Table/hooks/useRowSelection.js +7 -14
  36. package/dist/Table/hooks/useRowSelection.js.map +1 -1
  37. package/dist/Table/index.js +2 -8
  38. package/dist/Table/index.js.map +1 -1
  39. package/dist/Tabs/index.d.ts +1 -1
  40. package/dist/Tabs/index.js +11 -91
  41. package/dist/Tabs/index.js.map +1 -1
  42. package/dist/aloudata-design.css +1 -1
  43. package/dist/locale/default.d.ts +0 -6
  44. package/dist/locale/en_US.d.ts +0 -6
  45. package/dist/locale/en_US.js +0 -6
  46. package/dist/locale/en_US.js.map +1 -1
  47. package/dist/locale/zh_CN.d.ts +0 -6
  48. package/dist/locale/zh_CN.js +0 -6
  49. package/dist/locale/zh_CN.js.map +1 -1
  50. package/dist/theme/contract/tokenOutputContract.d.ts +1 -1
  51. package/dist/theme/contract/tokenOutputContract.js +0 -4
  52. package/dist/theme/contract/tokenOutputContract.js.map +1 -1
  53. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.d.ts +1 -1
  54. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js +0 -3
  55. package/dist/theme/runtime/colorValueMode/generated/darkBaselineDeclarations.js.map +1 -1
  56. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.d.ts +1 -1
  57. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js +0 -3
  58. package/dist/theme/runtime/colorValueMode/generated/v3BaselineDeclarations.js.map +1 -1
  59. package/dist/theme/runtime/themeToCssVars.js +0 -3
  60. package/dist/theme/runtime/themeToCssVars.js.map +1 -1
  61. package/package.json +1 -1
  62. package/dist/theme/contract/controlStateColorArtifact.d.ts +0 -73
  63. package/dist/theme/contract/controlStateColorArtifact.js +0 -2
  64. package/dist/theme/contract/focusRingArtifact.d.ts +0 -51
  65. package/dist/theme/contract/focusRingArtifact.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"useRowSelection.js","names":[],"sources":["../../../src/Table/hooks/useRowSelection.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from 'react';\nimport Checkbox from '../../Checkbox';\nimport { getRowKey, hasFixedLeftColumn, prefixCls } from '../helper';\nimport { IRowSelection, ITableColumn, ITableProps } from '../types';\n\nexport default function useRowSelection<TDataItem extends object>(\n props: ITableProps<TDataItem> & {\n isExpandable?: boolean;\n flattenData?: TDataItem[];\n },\n): IRowSelectionInfo<TDataItem> {\n const { columns, rowSelection, rowKey, data, isExpandable, flattenData } =\n props;\n\n const [selectedRowKeysState, setSelectedRowKeysState] = useState(\n rowSelection?.selectedRowKeys || rowSelection?.defaultSelectedRowKeys || [],\n );\n\n const selectedRowKeys = rowSelection?.selectedRowKeys || selectedRowKeysState;\n\n const getSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return data.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [data, rowKey],\n );\n\n // 获取用于全选状态计算和数据获取的完整数据\n const allDataForSelection = useMemo(() => {\n // 如果开启了 expandable,使用扁平化后的数据\n if (isExpandable && flattenData) {\n return flattenData;\n }\n // 否则使用原始数据\n return data;\n }, [isExpandable, flattenData, data]);\n\n // 从完整数据中获取选中的行\n const getAllSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return allDataForSelection.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [allDataForSelection, rowKey],\n );\n\n const changeSelectedRowKeys = useCallback(\n (newSelectedRowKeys: string[]) => {\n setSelectedRowKeysState(newSelectedRowKeys);\n\n // 获取所有选中的行数据(包括被折叠的子项)\n const allSelectedRows = getAllSelectedRows(newSelectedRowKeys);\n rowSelection?.onChange?.(newSelectedRowKeys, allSelectedRows);\n },\n [getAllSelectedRows, rowSelection],\n );\n\n const checkboxAllStatus = getCheckboxAllStatus(\n allDataForSelection,\n selectedRowKeys,\n rowKey,\n rowSelection?.getCheckboxProps,\n );\n\n const selectAll = useCallback(() => {\n const newKeys = getDataWithoutDisabled(\n allDataForSelection,\n rowSelection?.getCheckboxProps,\n ).map((record) => getRowKey(record, rowKey));\n\n changeSelectedRowKeys(newKeys);\n }, [\n allDataForSelection,\n rowKey,\n rowSelection?.getCheckboxProps,\n changeSelectedRowKeys,\n ]);\n\n const unSelectAll = useCallback(() => {\n changeSelectedRowKeys([]);\n }, [changeSelectedRowKeys]);\n\n const onChangeAllCheckbox = useCallback(() => {\n if (checkboxAllStatus === 'all') {\n unSelectAll();\n } else {\n selectAll();\n }\n }, [checkboxAllStatus, unSelectAll, selectAll]);\n\n // 获取节点的所有子孙节点keys\n const getDescendantKeys = useCallback(\n (parentKey: string): string[] => {\n return getNodeDescendants(parentKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的所有祖先节点keys\n const getAncestorKeys = useCallback(\n (targetKey: string): string[] => {\n return getNodeAncestors(targetKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的选择状态(考虑子节点状态)\n const getNodeCheckStatus = useCallback(\n (nodeKey: string): { checked: boolean; indeterminate: boolean } => {\n return calculateNodeCheckStatus(\n nodeKey,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n );\n },\n [\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n ],\n );\n\n const onChangeCheckbox = useCallback(\n (key: string, isChecked: boolean) => () => {\n const newKeys = calculateCascadeSelection(\n key,\n isChecked,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n );\n\n changeSelectedRowKeys(newKeys);\n },\n [\n selectedRowKeys,\n changeSelectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n ],\n );\n\n // 全选按钮\n const getCheckboxAllNode = (children?: React.ReactNode) => (\n <div className={prefixCls('row-selection-all')}>\n <Checkbox\n onChange={onChangeAllCheckbox}\n checked={checkboxAllStatus === 'all'}\n indeterminate={checkboxAllStatus === 'indeterminate'}\n >\n {children || <span className=\"tw-sr-only\">Select all rows</span>}\n </Checkbox>\n </div>\n );\n\n if (!rowSelection) {\n return {\n columns,\n isRowSelectionEnabled: false,\n getCheckboxAllNode,\n selectedRowKeys: [],\n selectedRowKeysInCurrPage: [],\n unSelectAll,\n isShowRowSelectionInFooter: false,\n items: [],\n onChange: () => {},\n };\n }\n\n if (!rowKey) {\n throw new Error('rowKey is required when rowSelection is enabled');\n }\n\n const fixed = !!rowSelection.fixed || hasFixedLeftColumn(columns);\n\n const rowSelectionColumn: ITableColumn<TDataItem> = {\n dataIndex: '',\n title: (\n <div className={prefixCls('row-selection-all-header-wrap')}>\n {getCheckboxAllNode()}\n </div>\n ),\n width: 48,\n render: (text: unknown, record: TDataItem) => {\n const key = getRowKey(record, rowKey);\n const nodeStatus = getNodeCheckStatus(key);\n const checkboxProps = rowSelection.getCheckboxProps?.(record) || {};\n\n return (\n <div className={prefixCls('row-selection-item')}>\n <Checkbox\n onChange={onChangeCheckbox(\n key,\n nodeStatus.checked || nodeStatus.indeterminate,\n )}\n checked={nodeStatus.checked}\n indeterminate={nodeStatus.indeterminate}\n {...checkboxProps}\n >\n <span className=\"tw-sr-only\">Select row {key}</span>\n </Checkbox>\n </div>\n );\n },\n fixed: fixed ? 'left' : undefined,\n };\n\n const selectedRowKeysInCurrPage = getDataWithoutDisabled(\n data,\n rowSelection.getCheckboxProps,\n )\n .map((record) => getRowKey(record, rowKey))\n .filter((key) => selectedRowKeys.includes(key));\n\n const isShowRowSelectionInFooter = selectedRowKeysInCurrPage.length > 0;\n\n const items =\n rowSelection.items?.map((operationItem) => ({\n ...operationItem,\n onClick: (e: React.MouseEvent) => {\n operationItem.onClick(\n selectedRowKeysInCurrPage,\n getSelectedRows(selectedRowKeysInCurrPage),\n e,\n );\n },\n })) || [];\n\n return {\n columns: [rowSelectionColumn, ...columns],\n isRowSelectionEnabled: true,\n getCheckboxAllNode,\n selectedRowKeys: selectedRowKeys, // 返回完整的选中项列表\n selectedRowKeysInCurrPage, // 当前页面可见的选中项\n unSelectAll,\n isShowRowSelectionInFooter,\n items,\n onChange: changeSelectedRowKeys,\n };\n}\n\nfunction getCheckboxAllStatus<TDataItem extends object>(\n data: TDataItem[],\n selectedRowKeys: string[],\n rowKey: ITableProps<TDataItem>['rowKey'],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n): 'all' | 'none' | 'indeterminate' {\n const enabledData = getDataWithoutDisabled(data, getCheckboxProps);\n\n if (enabledData.length === 0) {\n return 'none';\n }\n\n const selectedEnabledCount = enabledData.filter((record) =>\n selectedRowKeys.includes(getRowKey(record, rowKey)),\n ).length;\n\n if (selectedEnabledCount === 0) {\n return 'none';\n }\n if (selectedEnabledCount === enabledData.length) {\n return 'all';\n }\n return 'indeterminate';\n}\n\nfunction getDataWithoutDisabled<TDataItem extends object>(\n data: TDataItem[],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n) {\n return data.filter((record) => {\n const checkboxProps = getCheckboxProps?.(record) || {};\n const { disabled } = checkboxProps;\n return !disabled;\n });\n}\n\nexport interface IRowSelectionInfo<TDataItem extends object> {\n columns: ITableProps<TDataItem>['columns'];\n isRowSelectionEnabled: boolean;\n getCheckboxAllNode: ((children?: React.ReactNode) => React.ReactNode) | null;\n selectedRowKeys: string[]; // 完整的选中项列表\n selectedRowKeysInCurrPage: string[]; // 当前页面可见的选中项\n unSelectAll: () => void;\n isShowRowSelectionInFooter: boolean;\n items: {\n key: string;\n label: React.ReactNode;\n onClick: (e: React.MouseEvent) => void;\n }[];\n onChange: (selectedRowKeys: string[]) => void;\n}\n\n/**\n * 获取节点的所有子孙节点keys\n * @param parentKey 父节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据(包含所有节点,包括子节点)\n * @param rowKey 行key获取函数\n * @returns 子孙节点keys数组\n */\nexport function getNodeDescendants<TDataItem extends object>(\n parentKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const descendants: string[] = [];\n\n // 找到父节点在flattenData中的记录\n const parentNode = flattenData.find(\n (item) => getRowKey(item, rowKey) === parentKey,\n );\n if (!parentNode) return [];\n\n // 从原始节点的children中收集所有子孙节点\n const collectDescendants = (node: any) => {\n const children = node.children || [];\n children.forEach((child: any) => {\n const childKey = getRowKey(child, rowKey);\n descendants.push(childKey);\n collectDescendants(child);\n });\n };\n\n collectDescendants(parentNode);\n return descendants;\n}\n\n/**\n * 获取节点的所有祖先节点keys\n * @param targetKey 目标节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据\n * @param rowKey 行key获取函数\n * @returns 祖先节点keys数组(从直接父节点到根节点)\n */\nexport function getNodeAncestors<TDataItem extends object>(\n targetKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const ancestors: string[] = [];\n\n // 找到目标节点的直接父节点\n const findDirectParent = (childKey: string): TDataItem | null => {\n for (const item of flattenData) {\n const children = (item as any).children || [];\n if (\n children.some((child: any) => getRowKey(child, rowKey) === childKey)\n ) {\n return item;\n }\n }\n return null;\n };\n\n let currentKey = targetKey;\n\n for (;;) {\n const parent = findDirectParent(currentKey);\n if (!parent) break;\n\n const parentKey = getRowKey(parent, rowKey);\n ancestors.push(parentKey);\n currentKey = parentKey;\n }\n\n return ancestors;\n}\n\n/**\n * 计算级联选择后的keys(包含向上级联)\n * @param targetKey 被操作的节点key\n * @param isChecked 当前是否选中\n * @param currentSelectedKeys 当前已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @param getAncestorKeys 获取祖先节点keys的函数\n * @returns 新的选中keys\n */\nexport function calculateCascadeSelection(\n targetKey: string,\n isChecked: boolean,\n currentSelectedKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n getAncestorKeys?: (nodeKey: string) => string[],\n): string[] {\n if (\n checkStrictly ||\n !isExpandable ||\n !getDescendantKeys ||\n !getAncestorKeys\n ) {\n // 严格模式,不进行级联\n return isChecked\n ? currentSelectedKeys.filter((key) => key !== targetKey)\n : [...currentSelectedKeys, targetKey];\n }\n\n let newKeys = [...currentSelectedKeys];\n\n if (isChecked) {\n // 取消选择:移除目标节点和所有子孙节点\n newKeys = newKeys.filter((key) => key !== targetKey);\n const descendants = getDescendantKeys(targetKey);\n newKeys = newKeys.filter((key) => !descendants.includes(key));\n\n // 向上级联:检查父节点是否需要取消选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果子孙节点没有全部选中,则父节点也应该取消选择\n if (selectedDescendantsCount < ancestorDescendants.length) {\n newKeys = newKeys.filter((key) => key !== ancestorKey);\n }\n });\n } else {\n // 选择:添加目标节点和所有子孙节点\n if (!newKeys.includes(targetKey)) {\n newKeys.push(targetKey);\n }\n const descendants = getDescendantKeys(targetKey);\n descendants.forEach((descendantKey) => {\n if (!newKeys.includes(descendantKey)) {\n newKeys.push(descendantKey);\n }\n });\n\n // 向上级联:检查父节点是否需要选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果所有子孙节点都被选中,则父节点也应该被选中\n if (\n selectedDescendantsCount === ancestorDescendants.length &&\n !newKeys.includes(ancestorKey)\n ) {\n newKeys.push(ancestorKey);\n }\n });\n }\n\n return newKeys;\n}\n\n/**\n * 计算节点的选择状态(考虑子节点状态)\n * @param nodeKey 节点key\n * @param selectedRowKeys 已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @returns 节点的选择状态\n */\nexport function calculateNodeCheckStatus(\n nodeKey: string,\n selectedRowKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n): { checked: boolean; indeterminate: boolean } {\n if (checkStrictly || !isExpandable || !getDescendantKeys) {\n // 严格模式下或非展开模式,直接返回节点本身的选择状态\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const descendants = getDescendantKeys(nodeKey);\n\n // 如果没有子节点,直接返回本身状态\n if (descendants.length === 0) {\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const selectedDescendants = descendants.filter((key) =>\n selectedRowKeys.includes(key),\n );\n const isNodeSelected = selectedRowKeys.includes(nodeKey);\n\n if (isNodeSelected && selectedDescendants.length === descendants.length) {\n // 节点本身选中且所有子节点都选中\n return { checked: true, indeterminate: false };\n } else if (!isNodeSelected && selectedDescendants.length === 0) {\n // 节点本身未选中且所有子节点都未选中\n return { checked: false, indeterminate: false };\n } else {\n // 部分选中的情况:节点选中但子节点未全选,或节点未选中但部分子节点选中\n return { checked: false, indeterminate: true };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useRowSelection.js","names":[],"sources":["../../../src/Table/hooks/useRowSelection.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from 'react';\nimport Checkbox from '../../Checkbox';\nimport { getRowKey, hasFixedLeftColumn, prefixCls } from '../helper';\nimport { IRowSelection, ITableColumn, ITableProps } from '../types';\n\nexport default function useRowSelection<TDataItem extends object>(\n props: ITableProps<TDataItem> & {\n isExpandable?: boolean;\n flattenData?: TDataItem[];\n },\n): IRowSelectionInfo<TDataItem> {\n const { columns, rowSelection, rowKey, data, isExpandable, flattenData } =\n props;\n\n const [selectedRowKeysState, setSelectedRowKeysState] = useState(\n rowSelection?.selectedRowKeys || rowSelection?.defaultSelectedRowKeys || [],\n );\n\n const selectedRowKeys = rowSelection?.selectedRowKeys || selectedRowKeysState;\n\n const getSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return data.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [data, rowKey],\n );\n\n // 获取用于全选状态计算和数据获取的完整数据\n const allDataForSelection = useMemo(() => {\n // 如果开启了 expandable,使用扁平化后的数据\n if (isExpandable && flattenData) {\n return flattenData;\n }\n // 否则使用原始数据\n return data;\n }, [isExpandable, flattenData, data]);\n\n // 从完整数据中获取选中的行\n const getAllSelectedRows = useCallback(\n (rowKeys: string[]) => {\n return allDataForSelection.filter((record) =>\n rowKeys.includes(getRowKey(record, rowKey)),\n );\n },\n [allDataForSelection, rowKey],\n );\n\n const changeSelectedRowKeys = useCallback(\n (newSelectedRowKeys: string[]) => {\n setSelectedRowKeysState(newSelectedRowKeys);\n\n // 获取所有选中的行数据(包括被折叠的子项)\n const allSelectedRows = getAllSelectedRows(newSelectedRowKeys);\n rowSelection?.onChange?.(newSelectedRowKeys, allSelectedRows);\n },\n [getAllSelectedRows, rowSelection],\n );\n\n const checkboxAllStatus = getCheckboxAllStatus(\n allDataForSelection,\n selectedRowKeys,\n rowKey,\n rowSelection?.getCheckboxProps,\n );\n\n const selectAll = useCallback(() => {\n const newKeys = getDataWithoutDisabled(\n allDataForSelection,\n rowSelection?.getCheckboxProps,\n ).map((record) => getRowKey(record, rowKey));\n\n changeSelectedRowKeys(newKeys);\n }, [\n allDataForSelection,\n rowKey,\n rowSelection?.getCheckboxProps,\n changeSelectedRowKeys,\n ]);\n\n const unSelectAll = useCallback(() => {\n changeSelectedRowKeys([]);\n }, [changeSelectedRowKeys]);\n\n const onClickAllCheckbox = useCallback<(e?: React.MouseEvent) => void>(() => {\n if (checkboxAllStatus === 'all') {\n unSelectAll();\n } else {\n selectAll();\n }\n }, [checkboxAllStatus, unSelectAll, selectAll]);\n\n // 获取节点的所有子孙节点keys\n const getDescendantKeys = useCallback(\n (parentKey: string): string[] => {\n return getNodeDescendants(parentKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的所有祖先节点keys\n const getAncestorKeys = useCallback(\n (targetKey: string): string[] => {\n return getNodeAncestors(targetKey, isExpandable, flattenData, rowKey);\n },\n [isExpandable, flattenData, rowKey],\n );\n\n // 获取节点的选择状态(考虑子节点状态)\n const getNodeCheckStatus = useCallback(\n (nodeKey: string): { checked: boolean; indeterminate: boolean } => {\n return calculateNodeCheckStatus(\n nodeKey,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n );\n },\n [\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n ],\n );\n\n const onClickCheckbox = useCallback(\n (key: string, isChecked: boolean) => () => {\n const newKeys = calculateCascadeSelection(\n key,\n isChecked,\n selectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n );\n\n changeSelectedRowKeys(newKeys);\n },\n [\n selectedRowKeys,\n changeSelectedRowKeys,\n rowSelection?.checkStrictly,\n isExpandable,\n getDescendantKeys,\n getAncestorKeys,\n ],\n );\n\n // 全选按钮\n const getCheckboxAllNode = (children?: React.ReactNode) => (\n <div className={prefixCls('row-selection-all')}>\n <Checkbox\n onClick={onClickAllCheckbox}\n checked={checkboxAllStatus === 'all'}\n indeterminate={checkboxAllStatus === 'indeterminate'}\n >\n {children}\n </Checkbox>\n </div>\n );\n\n if (!rowSelection) {\n return {\n columns,\n isRowSelectionEnabled: false,\n getCheckboxAllNode,\n selectedRowKeys: [],\n selectedRowKeysInCurrPage: [],\n unSelectAll,\n isShowRowSelectionInFooter: false,\n items: [],\n onChange: () => {},\n };\n }\n\n if (!rowKey) {\n throw new Error('rowKey is required when rowSelection is enabled');\n }\n\n const fixed = !!rowSelection.fixed || hasFixedLeftColumn(columns);\n\n const rowSelectionColumn: ITableColumn<TDataItem> = {\n dataIndex: '',\n title: (\n <div className={prefixCls('row-selection-all-header-wrap')}>\n {getCheckboxAllNode()}\n </div>\n ),\n width: 48,\n render: (text: unknown, record: TDataItem) => {\n const key = getRowKey(record, rowKey);\n const nodeStatus = getNodeCheckStatus(key);\n const checkboxProps = rowSelection.getCheckboxProps?.(record) || {};\n\n return (\n <div className={prefixCls('row-selection-item')}>\n <Checkbox\n onClick={onClickCheckbox(\n key,\n nodeStatus.checked || nodeStatus.indeterminate,\n )}\n checked={nodeStatus.checked}\n indeterminate={nodeStatus.indeterminate}\n {...checkboxProps}\n />\n </div>\n );\n },\n fixed: fixed ? 'left' : undefined,\n };\n\n const selectedRowKeysInCurrPage = getDataWithoutDisabled(\n data,\n rowSelection.getCheckboxProps,\n )\n .map((record) => getRowKey(record, rowKey))\n .filter((key) => selectedRowKeys.includes(key));\n\n const isShowRowSelectionInFooter = selectedRowKeysInCurrPage.length > 0;\n\n const items =\n rowSelection.items?.map((operationItem) => ({\n ...operationItem,\n onClick: (e: React.MouseEvent) => {\n operationItem.onClick(\n selectedRowKeysInCurrPage,\n getSelectedRows(selectedRowKeysInCurrPage),\n e,\n );\n },\n })) || [];\n\n return {\n columns: [rowSelectionColumn, ...columns],\n isRowSelectionEnabled: true,\n getCheckboxAllNode,\n selectedRowKeys: selectedRowKeys, // 返回完整的选中项列表\n selectedRowKeysInCurrPage, // 当前页面可见的选中项\n unSelectAll,\n isShowRowSelectionInFooter,\n items,\n onChange: changeSelectedRowKeys,\n };\n}\n\nfunction getCheckboxAllStatus<TDataItem extends object>(\n data: TDataItem[],\n selectedRowKeys: string[],\n rowKey: ITableProps<TDataItem>['rowKey'],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n): 'all' | 'none' | 'indeterminate' {\n const enabledData = getDataWithoutDisabled(data, getCheckboxProps);\n\n if (enabledData.length === 0) {\n return 'none';\n }\n\n const selectedEnabledCount = enabledData.filter((record) =>\n selectedRowKeys.includes(getRowKey(record, rowKey)),\n ).length;\n\n if (selectedEnabledCount === 0) {\n return 'none';\n }\n if (selectedEnabledCount === enabledData.length) {\n return 'all';\n }\n return 'indeterminate';\n}\n\nfunction getDataWithoutDisabled<TDataItem extends object>(\n data: TDataItem[],\n getCheckboxProps?: IRowSelection<TDataItem>['getCheckboxProps'],\n) {\n return data.filter((record) => {\n const checkboxProps = getCheckboxProps?.(record) || {};\n const { disabled } = checkboxProps;\n return !disabled;\n });\n}\n\nexport interface IRowSelectionInfo<TDataItem extends object> {\n columns: ITableProps<TDataItem>['columns'];\n isRowSelectionEnabled: boolean;\n getCheckboxAllNode: ((children?: React.ReactNode) => React.ReactNode) | null;\n selectedRowKeys: string[]; // 完整的选中项列表\n selectedRowKeysInCurrPage: string[]; // 当前页面可见的选中项\n unSelectAll: () => void;\n isShowRowSelectionInFooter: boolean;\n items: {\n key: string;\n label: React.ReactNode;\n onClick: (e: React.MouseEvent) => void;\n }[];\n onChange: (selectedRowKeys: string[]) => void;\n}\n\n/**\n * 获取节点的所有子孙节点keys\n * @param parentKey 父节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据(包含所有节点,包括子节点)\n * @param rowKey 行key获取函数\n * @returns 子孙节点keys数组\n */\nexport function getNodeDescendants<TDataItem extends object>(\n parentKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const descendants: string[] = [];\n\n // 找到父节点在flattenData中的记录\n const parentNode = flattenData.find(\n (item) => getRowKey(item, rowKey) === parentKey,\n );\n if (!parentNode) return [];\n\n // 从原始节点的children中收集所有子孙节点\n const collectDescendants = (node: any) => {\n const children = node.children || [];\n children.forEach((child: any) => {\n const childKey = getRowKey(child, rowKey);\n descendants.push(childKey);\n collectDescendants(child);\n });\n };\n\n collectDescendants(parentNode);\n return descendants;\n}\n\n/**\n * 获取节点的所有祖先节点keys\n * @param targetKey 目标节点key\n * @param isExpandable 是否启用展开功能\n * @param flattenData 扁平化后的数据\n * @param rowKey 行key获取函数\n * @returns 祖先节点keys数组(从直接父节点到根节点)\n */\nexport function getNodeAncestors<TDataItem extends object>(\n targetKey: string,\n isExpandable?: boolean,\n flattenData?: TDataItem[],\n rowKey?: ITableProps<TDataItem>['rowKey'],\n): string[] {\n if (!isExpandable || !flattenData || !rowKey) return [];\n\n const ancestors: string[] = [];\n\n // 找到目标节点的直接父节点\n const findDirectParent = (childKey: string): TDataItem | null => {\n for (const item of flattenData) {\n const children = (item as any).children || [];\n if (\n children.some((child: any) => getRowKey(child, rowKey) === childKey)\n ) {\n return item;\n }\n }\n return null;\n };\n\n let currentKey = targetKey;\n\n for (;;) {\n const parent = findDirectParent(currentKey);\n if (!parent) break;\n\n const parentKey = getRowKey(parent, rowKey);\n ancestors.push(parentKey);\n currentKey = parentKey;\n }\n\n return ancestors;\n}\n\n/**\n * 计算级联选择后的keys(包含向上级联)\n * @param targetKey 被操作的节点key\n * @param isChecked 当前是否选中\n * @param currentSelectedKeys 当前已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @param getAncestorKeys 获取祖先节点keys的函数\n * @returns 新的选中keys\n */\nexport function calculateCascadeSelection(\n targetKey: string,\n isChecked: boolean,\n currentSelectedKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n getAncestorKeys?: (nodeKey: string) => string[],\n): string[] {\n if (\n checkStrictly ||\n !isExpandable ||\n !getDescendantKeys ||\n !getAncestorKeys\n ) {\n // 严格模式,不进行级联\n return isChecked\n ? currentSelectedKeys.filter((key) => key !== targetKey)\n : [...currentSelectedKeys, targetKey];\n }\n\n let newKeys = [...currentSelectedKeys];\n\n if (isChecked) {\n // 取消选择:移除目标节点和所有子孙节点\n newKeys = newKeys.filter((key) => key !== targetKey);\n const descendants = getDescendantKeys(targetKey);\n newKeys = newKeys.filter((key) => !descendants.includes(key));\n\n // 向上级联:检查父节点是否需要取消选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果子孙节点没有全部选中,则父节点也应该取消选择\n if (selectedDescendantsCount < ancestorDescendants.length) {\n newKeys = newKeys.filter((key) => key !== ancestorKey);\n }\n });\n } else {\n // 选择:添加目标节点和所有子孙节点\n if (!newKeys.includes(targetKey)) {\n newKeys.push(targetKey);\n }\n const descendants = getDescendantKeys(targetKey);\n descendants.forEach((descendantKey) => {\n if (!newKeys.includes(descendantKey)) {\n newKeys.push(descendantKey);\n }\n });\n\n // 向上级联:检查父节点是否需要选择\n const ancestors = getAncestorKeys(targetKey);\n ancestors.forEach((ancestorKey) => {\n const ancestorDescendants = getDescendantKeys(ancestorKey);\n const selectedDescendantsCount = ancestorDescendants.filter((key) =>\n newKeys.includes(key),\n ).length;\n\n // 如果所有子孙节点都被选中,则父节点也应该被选中\n if (\n selectedDescendantsCount === ancestorDescendants.length &&\n !newKeys.includes(ancestorKey)\n ) {\n newKeys.push(ancestorKey);\n }\n });\n }\n\n return newKeys;\n}\n\n/**\n * 计算节点的选择状态(考虑子节点状态)\n * @param nodeKey 节点key\n * @param selectedRowKeys 已选中的keys\n * @param checkStrictly 是否严格模式\n * @param isExpandable 是否启用展开功能\n * @param getDescendantKeys 获取子孙节点keys的函数\n * @returns 节点的选择状态\n */\nexport function calculateNodeCheckStatus(\n nodeKey: string,\n selectedRowKeys: string[],\n checkStrictly?: boolean,\n isExpandable?: boolean,\n getDescendantKeys?: (nodeKey: string) => string[],\n): { checked: boolean; indeterminate: boolean } {\n if (checkStrictly || !isExpandable || !getDescendantKeys) {\n // 严格模式下或非展开模式,直接返回节点本身的选择状态\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const descendants = getDescendantKeys(nodeKey);\n\n // 如果没有子节点,直接返回本身状态\n if (descendants.length === 0) {\n return {\n checked: selectedRowKeys.includes(nodeKey),\n indeterminate: false,\n };\n }\n\n const selectedDescendants = descendants.filter((key) =>\n selectedRowKeys.includes(key),\n );\n const isNodeSelected = selectedRowKeys.includes(nodeKey);\n\n if (isNodeSelected && selectedDescendants.length === descendants.length) {\n // 节点本身选中且所有子节点都选中\n return { checked: true, indeterminate: false };\n } else if (!isNodeSelected && selectedDescendants.length === 0) {\n // 节点本身未选中且所有子节点都未选中\n return { checked: false, indeterminate: false };\n } else {\n // 部分选中的情况:节点选中但子节点未全选,或节点未选中但部分子节点选中\n return { checked: false, indeterminate: true };\n }\n}\n"],"mappings":"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"}
@@ -46,7 +46,7 @@ function TableResizeWrapper({ children, onResize }) {
46
46
  });
47
47
  }
48
48
  function Table(props, ref) {
49
- const { data, bordered, rowKey, columnSizing, sticky, loading, pagination, scroll = {}, empty: emptyComponent, virtual = false, rowClassName = () => "", onRowClick, onError, onSort, expandable, rowDnd, rowSelection } = props;
49
+ const { data, bordered, rowKey, columnSizing, sticky, loading, pagination, scroll = {}, empty: emptyComponent, virtual = false, rowClassName = () => "", onRowClick, onError, onSort, expandable, rowDnd } = props;
50
50
  const [totalSize, setTotalSize] = useState(null);
51
51
  const [hoverRowId, setHoverRowId] = useState(null);
52
52
  const { y } = scroll;
@@ -336,15 +336,11 @@ function Table(props, ref) {
336
336
  ] });
337
337
  } else content = allRowCells.map((cell, index) => renderBodyCell(row, cell, index));
338
338
  const rowId = row.id;
339
- const isRowSelected = rowSelectionInfo.isRowSelectionEnabled && rowSelectionInfo.selectedRowKeys.includes(rowId);
340
- const isRowSelectionDisabled = rowSelectionInfo.isRowSelectionEnabled && !!rowSelection?.getCheckboxProps?.(row.original).disabled;
341
339
  const rowNode = /* @__PURE__ */ jsx("div", {
342
340
  "data-index": virtual ? rowData.index : rowIndex,
343
341
  className: cn(prefixCls("tr"), {
344
342
  [prefixCls("row-hover")]: rowDndInfo.draggingRowId ? void 0 : hoverRowId === rowId,
345
343
  [prefixCls("row-dragging")]: rowDndInfo.draggingRowId === rowId,
346
- [prefixCls("row-selected")]: isRowSelected,
347
- [prefixCls("row-selection-disabled")]: isRowSelectionDisabled,
348
344
  [prefixCls("no-border-tr")]: isShowPagination && rowIndex === rows.length - 1
349
345
  }, rowClassName(row.original, rowIndex)),
350
346
  ref: (node) => {
@@ -355,9 +351,7 @@ function Table(props, ref) {
355
351
  }
356
352
  },
357
353
  onClick: onClickRow(row.original, rowIndex),
358
- onMouseEnter: () => {
359
- if (!isRowSelectionDisabled) setHoverRowId(rowId);
360
- },
354
+ onMouseEnter: () => setHoverRowId(rowId),
361
355
  onMouseLeave: () => setHoverRowId(null),
362
356
  style: virtual ? {
363
357
  position: "absolute",
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Table/index.tsx"],"sourcesContent":["import {\n Cell,\n Header,\n Row,\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from '@tanstack/react-table';\nimport { VirtualItem, useVirtualizer } from '@tanstack/react-virtual';\nimport { cn } from '../lib/utils';\nimport './table.css';\nimport _ from 'lodash';\nimport React, {\n CSSProperties,\n ForwardedRef,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Empty, Spin } from '..';\nimport ExpandCell from './components/ExpandCell';\nimport Footer from './components/Footer';\nimport DndWrapper from './components/DndWrapper';\nimport { getRowKey, getTableColumns, prefixCls } from './helper';\nimport useExpandable, { getExpandableConfig } from './hooks/useExpandable';\nimport useFixed from './hooks/useFixed';\nimport useRowSelection from './hooks/useRowSelection';\nimport useScroll from './hooks/useScroll';\nimport { ITableProps, ITableRef } from './types';\nimport useRowDnd from './hooks/useRowDnd';\n\nconst HEADER_HEIGHT = 41;\nconst FOOTER_HEIGHT = 52;\n\nfunction TableResizeWrapper({\n children,\n onResize,\n}: {\n children: React.ReactNode;\n onResize: (width: number, height: number) => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n let prevW = 0;\n let prevH = 0;\n const ro = new window.ResizeObserver(() => {\n const w = el.offsetWidth;\n const h = el.offsetHeight;\n if (w === prevW && h === prevH) return;\n prevW = w;\n prevH = h;\n onResizeRef.current(w, h);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n return (\n <div ref={ref} style={{ height: '100%' }}>\n {children}\n </div>\n );\n}\n\nfunction Table<TDataItem extends object>(\n props: ITableProps<TDataItem>,\n ref: ForwardedRef<ITableRef>,\n) {\n const {\n data,\n bordered,\n rowKey,\n columnSizing,\n sticky,\n loading,\n pagination,\n scroll = {},\n empty: emptyComponent,\n virtual = false,\n rowClassName = () => '',\n onRowClick,\n onError,\n onSort,\n expandable,\n rowDnd,\n rowSelection,\n } = props;\n const [totalSize, setTotalSize] = useState<{\n width: number;\n height: number;\n } | null>(null);\n\n const [hoverRowId, setHoverRowId] = useState<string | null>(null);\n\n const { y } = scroll;\n const {\n containerWidth,\n onBodyScroll,\n headerRef,\n bodyRef,\n isPingLeft,\n isPingRight,\n scrollbarWidth,\n changeIsPing,\n } = useScroll({\n totalSize,\n scroll,\n });\n\n const scrollToFirstRow = useCallback(() => {\n if (!bodyRef.current) {\n return;\n }\n bodyRef.current.scrollTop = 0;\n }, [bodyRef]);\n\n useImperativeHandle(ref, () => ({\n scrollToFirstRow,\n }));\n\n const expandableInfo = useExpandable({\n expandable,\n data,\n rowKey,\n });\n const expandableConfig = getExpandableConfig(expandable);\n\n const rowSelectionInfo = useRowSelection({\n ...props,\n data: expandableInfo.data,\n isExpandable: expandableInfo.isExpandable,\n flattenData: expandableInfo.flattenData,\n });\n\n const rowDndInfo = useRowDnd({\n ...props,\n columns: rowSelectionInfo.columns,\n data: expandableInfo.data,\n });\n\n const tableColumns = useMemo(() => {\n return getTableColumns<TDataItem>({\n columns: rowDndInfo.columns,\n containerWidth: containerWidth || 0,\n onError,\n onSort,\n });\n }, [containerWidth, onError, onSort, rowDndInfo.columns]);\n\n const tableInstance = useReactTable<TDataItem>({\n columns: tableColumns,\n // 排除掉被折叠的行\n data: rowDndInfo.tableData,\n getCoreRowModel: getCoreRowModel(),\n getRowId: (row, index) => {\n return getRowKey(row, rowKey, index);\n },\n columnResizeMode: 'onChange',\n });\n\n const headerGroups = tableInstance.getHeaderGroups();\n\n const columnWidths = headerGroups[0].headers.map((header) =>\n header.getSize(),\n );\n const getColumnFixedInfo = useFixed<TDataItem>({\n columnWidths,\n tableColumns,\n y,\n scrollbarWidth,\n });\n\n // 渲染 header\n const { rows } = tableInstance.getRowModel();\n\n const isStickyWork = !!sticky && y === undefined;\n const headerStyle: CSSProperties = {};\n if (isStickyWork && _.get(sticky, 'offsetHeader')) {\n headerStyle.top = _.get(sticky, 'offsetHeader', 0);\n }\n\n const totalColumnsWidth = _.sum(columnWidths);\n\n useEffect(() => {\n // 总列宽改变时,重新计算是否需要显示固定列的阴影\n changeIsPing(totalColumnsWidth);\n }, [changeIsPing, totalColumnsWidth]);\n\n const renderHeaderCell = useCallback(\n (header: Header<TDataItem, unknown>, index: number) => {\n // 选择行的列不能拖动宽度\n const showResizer =\n columnSizing &&\n !(!!rowSelectionInfo.isRowSelectionEnabled && index === 0);\n const { className: fixedClassName, style: fixedStyle } =\n getColumnFixedInfo(index, true);\n return (\n <div\n className={cn(prefixCls('th'), fixedClassName)}\n style={{ width: header.getSize(), ...fixedStyle }}\n key={header.id}\n >\n {flexRender(header.column.columnDef.header, header.getContext())}\n {showResizer && (\n <div\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n className={cn(prefixCls('resizer'), {\n [prefixCls('self-resizing')]: header.column.getIsResizing(),\n })}\n />\n )}\n </div>\n );\n },\n [columnSizing, rowSelectionInfo, getColumnFixedInfo],\n );\n\n const visibleColumns = tableInstance.getVisibleLeafColumns();\n\n const columnVirtualizer = useVirtualizer({\n count: tableColumns.length,\n estimateSize: (index: number) => visibleColumns[index].getSize(),\n getScrollElement: () => bodyRef.current,\n horizontal: true,\n overscan: 5,\n });\n\n const virtualColumns = columnVirtualizer.getVirtualItems();\n\n //different virtualization strategy for columns - instead of absolute and translateY, we add empty columns to the left and right\n let virtualPaddingLeft: number | undefined;\n let virtualPaddingRight: number | undefined;\n\n if (columnVirtualizer && virtualColumns?.length) {\n virtualPaddingLeft = virtualColumns[0]?.start ?? 0;\n virtualPaddingRight =\n columnVirtualizer.getTotalSize() -\n (virtualColumns[virtualColumns.length - 1]?.end ?? 0);\n }\n\n const headerContent = (\n <div\n className={cn(prefixCls('header'), {\n [prefixCls('overflow-x')]: true,\n [prefixCls('sticky')]: isStickyWork,\n [prefixCls('resizing')]:\n tableInstance.getState().columnSizingInfo.isResizingColumn,\n })}\n ref={headerRef}\n style={headerStyle}\n >\n {_.map(headerGroups, (headerGroup) => {\n const allHeaderCells = headerGroup.headers;\n const virtualColumns = columnVirtualizer.getVirtualItems();\n\n const middleVirtualColumns: VirtualItem[] = [];\n // 将固定列单独拎出来,固定列不受列虚拟化影响,必须要渲染\n const leftFixedColumns: {\n header: Header<TDataItem, unknown>;\n index: number;\n }[] = [];\n const rightFixedColumns: {\n header: Header<TDataItem, unknown>;\n index: number;\n }[] = [];\n let content: React.ReactNode | null = null;\n if (virtual) {\n _.forEach(allHeaderCells, (header, index) => {\n const fixedInfo = getColumnFixedInfo(index);\n if (fixedInfo.fixed === 'left') {\n leftFixedColumns.push({ header, index });\n }\n if (fixedInfo.fixed === 'right') {\n rightFixedColumns.push({ header, index });\n }\n });\n\n _.forEach(virtualColumns, (virtualColumn) => {\n const colIndex = virtualColumn.index;\n const fixedInfo = getColumnFixedInfo(colIndex);\n if (fixedInfo.fixed !== 'left' && fixedInfo.fixed !== 'right') {\n middleVirtualColumns.push(virtualColumn);\n }\n });\n content = (\n <>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-left')}\n style={{ width: virtualPaddingLeft }}\n />\n ) : null}\n {leftFixedColumns.map(({ header, index }) => {\n return renderHeaderCell(header, index);\n })}\n {_.map(middleVirtualColumns, (virtualColumn) => {\n const header = allHeaderCells[virtualColumn.index];\n return renderHeaderCell(header, virtualColumn.index);\n })}\n {rightFixedColumns.map(({ header, index }) => {\n return renderHeaderCell(header, index);\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-right')}\n style={{ width: virtualPaddingRight }}\n />\n ) : null}\n </>\n );\n } else {\n content = _.map(allHeaderCells, (header, index) =>\n renderHeaderCell(header, index),\n );\n }\n\n return (\n <div\n className={prefixCls('tr')}\n key={headerGroup.id}\n style={{ width: totalColumnsWidth }}\n >\n {content}\n {y !== undefined && (\n <div\n className={prefixCls('header-scroll-placeholder')}\n style={{ flexBasis: scrollbarWidth }}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n\n const onClickRow = useCallback(\n (rowData: TDataItem, rowIndex: number) => () => {\n if (typeof onRowClick !== 'function') {\n return;\n }\n if (window.getSelection()?.toString().length !== 0) {\n // 防止选择文本时触发 onRowClick\n return;\n }\n onRowClick(rowData, rowIndex);\n },\n [onRowClick],\n );\n\n const isShowPagination = !!(\n pagination &&\n (pagination.total > pagination.pageSize || pagination.showSizeChanger)\n );\n const isShowRowSelection = rowSelectionInfo.isShowRowSelectionInFooter;\n\n const isShowFooter = isShowPagination || isShowRowSelection;\n\n // 空态切换 size 的阈值\n const EMPTY_SMALL_SIZE_HEIGHT = 436;\n const isSmallEmpty = totalSize && totalSize.height < EMPTY_SMALL_SIZE_HEIGHT;\n\n const isEmpty = rows.length === 0 && !loading;\n\n const rowVirtualizer = useVirtualizer({\n count: rows.length,\n estimateSize: () => 48, // estimate row height for accurate scrollbar dragging\n // 没有测量出 bodyRef.current 的高度时,返回 null,避免虚拟化器从 DOM 获取异常高度\n getScrollElement: () => (totalSize ? bodyRef.current : null),\n // measure dynamic row height, except in firefox because it measures table border height incorrectly\n measureElement:\n typeof window !== 'undefined' &&\n navigator.userAgent.indexOf('Firefox') === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n });\n\n const tableRows = virtual ? rowVirtualizer.getVirtualItems() : rows;\n\n const renderBodyCell = useCallback(\n (row: Row<TDataItem>, cell: Cell<TDataItem, unknown>, colIndex: number) => {\n const { className: fixedClassName, style: fixedStyle } =\n getColumnFixedInfo(colIndex);\n const tdContent = flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n );\n return (\n <div\n className={cn(prefixCls('td'), fixedClassName)}\n key={cell.id}\n style={{ width: cell.column.getSize(), ...fixedStyle }}\n >\n {expandableInfo.isExpandable &&\n colIndex === (rowSelectionInfo.isRowSelectionEnabled ? 1 : 0) ? (\n <ExpandCell\n expandableInfo={expandableInfo}\n expandable={expandable}\n data={row.original}\n rowKey={rowKey}\n >\n {tdContent}\n </ExpandCell>\n ) : (\n tdContent\n )}\n </div>\n );\n },\n [\n expandableInfo,\n expandable,\n rowKey,\n getColumnFixedInfo,\n rowSelectionInfo.isRowSelectionEnabled,\n ],\n );\n\n // 渲染 body\n const bodyContent = (\n <div\n className={prefixCls('body')}\n style={{\n width: totalColumnsWidth,\n height: virtual\n ? totalSize\n ? rowVirtualizer.getTotalSize()\n : 0\n : 'auto',\n }}\n >\n {isEmpty ? (\n <div style={{ width: totalSize?.width }}>\n <div style={{ visibility: 'hidden' }}>\n {emptyComponent || (\n <div\n className={cn(prefixCls('empty'), {\n [prefixCls('empty-small')]: isSmallEmpty,\n })}\n >\n <Empty\n image={isSmallEmpty ? null : Empty.PRESENTED_IMAGE_SEARCH}\n size={isSmallEmpty ? 'small' : undefined}\n />\n </div>\n )}\n </div>\n <div\n aria-invalid=\"true\"\n style={{\n position: 'absolute',\n top: 40,\n left: 0,\n right: 0,\n bottom: 0,\n }}\n >\n {emptyComponent || (\n <div\n className={cn(prefixCls('empty'), {\n [prefixCls('empty-small')]: isSmallEmpty,\n })}\n >\n <Empty\n image={isSmallEmpty ? null : Empty.PRESENTED_IMAGE_SEARCH}\n size={isSmallEmpty ? 'small' : undefined}\n />\n </div>\n )}\n </div>\n </div>\n ) : (\n _.reduce<Row<TDataItem> | VirtualItem, React.ReactNode[]>(\n tableRows,\n (rowList, rowData, rowIndex) => {\n const row = virtual\n ? rows[rowData.index]\n : (rowData as Row<TDataItem>);\n const allRowCells = row.getVisibleCells();\n\n let content: React.ReactNode | null = null;\n // 将固定列单独拎出来,固定列不受列虚拟化影响,必须要渲染\n const leftFixedColumns: {\n cell: Cell<TDataItem, unknown>;\n index: number;\n }[] = [];\n const rightFixedColumns: {\n cell: Cell<TDataItem, unknown>;\n index: number;\n }[] = [];\n\n if (virtual) {\n const virtualColumns = columnVirtualizer.getVirtualItems();\n\n const middleVirtualColumns: VirtualItem[] = [];\n\n _.forEach(allRowCells, (cell, index) => {\n const fixedInfo = getColumnFixedInfo(index);\n if (fixedInfo.fixed === 'left') {\n leftFixedColumns.push({ cell, index });\n }\n if (fixedInfo.fixed === 'right') {\n rightFixedColumns.push({ cell, index });\n }\n });\n\n _.forEach(virtualColumns, (virtualColumn) => {\n const colIndex = virtualColumn.index;\n const fixedInfo = getColumnFixedInfo(colIndex);\n if (fixedInfo.fixed !== 'left' && fixedInfo.fixed !== 'right') {\n middleVirtualColumns.push(virtualColumn);\n }\n });\n content = (\n <>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-left')}\n style={{ width: virtualPaddingLeft }}\n />\n ) : null}\n {leftFixedColumns.map(({ cell, index }) => {\n return renderBodyCell(row, cell, index);\n })}\n {middleVirtualColumns.map((virtualColumn) => {\n const colIndex = virtualColumn.index;\n const cell = allRowCells[colIndex];\n return renderBodyCell(row, cell, colIndex);\n })}\n {rightFixedColumns.map(({ cell, index }) => {\n return renderBodyCell(row, cell, index);\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-right')}\n style={{ width: virtualPaddingRight }}\n />\n ) : null}\n </>\n );\n } else {\n content = allRowCells.map((cell, index) =>\n renderBodyCell(row, cell, index),\n );\n }\n const rowId = row.id;\n const isRowSelected =\n rowSelectionInfo.isRowSelectionEnabled &&\n rowSelectionInfo.selectedRowKeys.includes(rowId);\n const isRowSelectionDisabled =\n rowSelectionInfo.isRowSelectionEnabled &&\n !!rowSelection?.getCheckboxProps?.(row.original).disabled;\n\n const rowNode = (\n <div\n key={rowId}\n data-index={virtual ? (rowData as VirtualItem).index : rowIndex}\n className={cn(\n prefixCls('tr'),\n {\n // 需要用 state 的原因是,存在固定列的情况,左右侧的固定列在 dom 结构上不在同一个 tr 上,所以不能用 css 的 :hover 来实现\n // 当拖拽行时,不显示 hover 状态\n [prefixCls('row-hover')]: rowDndInfo.draggingRowId\n ? undefined\n : hoverRowId === rowId,\n [prefixCls('row-dragging')]:\n rowDndInfo.draggingRowId === rowId,\n [prefixCls('row-selected')]: isRowSelected,\n [prefixCls('row-selection-disabled')]:\n isRowSelectionDisabled,\n [prefixCls('no-border-tr')]:\n isShowPagination && rowIndex === rows.length - 1,\n },\n rowClassName(row.original, rowIndex),\n )}\n ref={(node) => {\n // 只在虚拟滚动模式下才测量行高度,避免非虚拟模式下的不必要重渲染\n if (virtual) {\n rowVirtualizer.measureElement(node);\n }\n\n // 如果启用了行拖拽,则设置行引用\n if (rowDnd && node) {\n const rowRef = rowDndInfo.getRowRef(row.original, rowIndex);\n if (rowRef) {\n rowRef.current = node;\n }\n }\n }}\n onClick={onClickRow(row.original, rowIndex)}\n onMouseEnter={() => {\n if (!isRowSelectionDisabled) {\n setHoverRowId(rowId);\n }\n }}\n onMouseLeave={() => setHoverRowId(null)}\n style={\n virtual\n ? {\n position: 'absolute',\n transform: `translateY(${\n (rowData as VirtualItem).start\n }px)`,\n }\n : {}\n }\n >\n {content}\n </div>\n );\n rowList.push(rowNode);\n\n // 渲染额外展开的行\n const expandItem = expandableInfo.expandItemMap[rowId];\n const customExpandRowKey =\n expandableInfo.isExpandable && expandItem?.customExpandRowKey;\n const hasCustomExpandRowKey = !!customExpandRowKey;\n if (hasCustomExpandRowKey) {\n // 在该行的下面追加自定义展开行\n const expandedRowRender = expandableConfig.expandedRowRender;\n if (typeof expandedRowRender !== 'function') {\n console.error('expandedRowRender must be a function');\n return rowList;\n }\n if (expandItem?.isExpanded !== true) {\n return rowList;\n }\n const customRow = (\n <div\n key={customExpandRowKey}\n className={cn(prefixCls('tr'))}\n onClick={onClickRow(row.original, rowIndex)}\n >\n {expandedRowRender(row.original, expandItem.level + 1)}\n </div>\n );\n rowList.push(customRow);\n }\n return rowList;\n },\n [],\n )\n )}\n </div>\n );\n\n const tableContentHeight = useMemo(() => {\n return y && totalSize\n ? totalSize.height - HEADER_HEIGHT - (isShowFooter ? FOOTER_HEIGHT : 0)\n : 'auto';\n }, [y, totalSize, isShowFooter]);\n\n const tableContent = (\n <Spin spinning={!!loading}>\n <div className={prefixCls('content')}>\n {headerContent}\n <div\n style={{\n height: tableContentHeight,\n position: virtual ? 'relative' : undefined,\n }}\n className={cn(prefixCls('body-scroll'), {\n [prefixCls('scroll-y')]: y !== undefined,\n [prefixCls('scroll-hidden')]: isEmpty,\n })}\n ref={bodyRef}\n onScroll={onBodyScroll}\n >\n {bodyContent}\n </div>\n {isShowFooter && (\n <Footer\n rowSelectionInfo={rowSelectionInfo}\n isShowPagination={isShowPagination}\n pagination={pagination}\n scroll={scroll}\n scrollToFirstRow={scrollToFirstRow}\n />\n )}\n </div>\n </Spin>\n );\n\n const tableStyle: CSSProperties = {};\n if (y) {\n tableStyle.height = y;\n }\n\n return (\n <div\n className={cn(prefixCls('container'), {\n [prefixCls('bordered')]: bordered,\n })}\n style={tableStyle}\n >\n <TableResizeWrapper\n onResize={(w, h) =>\n setTotalSize((prev) => {\n if (prev && prev.width === w && prev.height === h) return prev;\n return { width: w, height: h };\n })\n }\n >\n <div\n className={cn(prefixCls('main'), {\n [prefixCls('overflow-hidden')]: !!y,\n [prefixCls('ping-left')]: isPingLeft,\n [prefixCls('ping-right')]: isPingRight,\n })}\n >\n {rowDnd ? <DndWrapper>{tableContent}</DndWrapper> : tableContent}\n </div>\n </TableResizeWrapper>\n </div>\n );\n}\n\nexport default forwardRef(Table) as <TDataItem extends object>(\n props: ITableProps<TDataItem> & {\n ref?: React.ForwardedRef<ITableRef>;\n },\n) => ReturnType<typeof Table>;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Table/index.tsx"],"sourcesContent":["import {\n Cell,\n Header,\n Row,\n flexRender,\n getCoreRowModel,\n useReactTable,\n} from '@tanstack/react-table';\nimport { VirtualItem, useVirtualizer } from '@tanstack/react-virtual';\nimport { cn } from '../lib/utils';\nimport './table.css';\nimport _ from 'lodash';\nimport React, {\n CSSProperties,\n ForwardedRef,\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { Empty, Spin } from '..';\nimport ExpandCell from './components/ExpandCell';\nimport Footer from './components/Footer';\nimport DndWrapper from './components/DndWrapper';\nimport { getRowKey, getTableColumns, prefixCls } from './helper';\nimport useExpandable, { getExpandableConfig } from './hooks/useExpandable';\nimport useFixed from './hooks/useFixed';\nimport useRowSelection from './hooks/useRowSelection';\nimport useScroll from './hooks/useScroll';\nimport { ITableProps, ITableRef } from './types';\nimport useRowDnd from './hooks/useRowDnd';\n\nconst HEADER_HEIGHT = 41;\nconst FOOTER_HEIGHT = 52;\n\nfunction TableResizeWrapper({\n children,\n onResize,\n}: {\n children: React.ReactNode;\n onResize: (width: number, height: number) => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const onResizeRef = useRef(onResize);\n onResizeRef.current = onResize;\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n let prevW = 0;\n let prevH = 0;\n const ro = new window.ResizeObserver(() => {\n const w = el.offsetWidth;\n const h = el.offsetHeight;\n if (w === prevW && h === prevH) return;\n prevW = w;\n prevH = h;\n onResizeRef.current(w, h);\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n return (\n <div ref={ref} style={{ height: '100%' }}>\n {children}\n </div>\n );\n}\n\nfunction Table<TDataItem extends object>(\n props: ITableProps<TDataItem>,\n ref: ForwardedRef<ITableRef>,\n) {\n const {\n data,\n bordered,\n rowKey,\n columnSizing,\n sticky,\n loading,\n pagination,\n scroll = {},\n empty: emptyComponent,\n virtual = false,\n rowClassName = () => '',\n onRowClick,\n onError,\n onSort,\n expandable,\n rowDnd,\n } = props;\n const [totalSize, setTotalSize] = useState<{\n width: number;\n height: number;\n } | null>(null);\n\n const [hoverRowId, setHoverRowId] = useState<string | null>(null);\n\n const { y } = scroll;\n const {\n containerWidth,\n onBodyScroll,\n headerRef,\n bodyRef,\n isPingLeft,\n isPingRight,\n scrollbarWidth,\n changeIsPing,\n } = useScroll({\n totalSize,\n scroll,\n });\n\n const scrollToFirstRow = useCallback(() => {\n if (!bodyRef.current) {\n return;\n }\n bodyRef.current.scrollTop = 0;\n }, [bodyRef]);\n\n useImperativeHandle(ref, () => ({\n scrollToFirstRow,\n }));\n\n const expandableInfo = useExpandable({\n expandable,\n data,\n rowKey,\n });\n const expandableConfig = getExpandableConfig(expandable);\n\n const rowSelectionInfo = useRowSelection({\n ...props,\n data: expandableInfo.data,\n isExpandable: expandableInfo.isExpandable,\n flattenData: expandableInfo.flattenData,\n });\n\n const rowDndInfo = useRowDnd({\n ...props,\n columns: rowSelectionInfo.columns,\n data: expandableInfo.data,\n });\n\n const tableColumns = useMemo(() => {\n return getTableColumns<TDataItem>({\n columns: rowDndInfo.columns,\n containerWidth: containerWidth || 0,\n onError,\n onSort,\n });\n }, [containerWidth, onError, onSort, rowDndInfo.columns]);\n\n const tableInstance = useReactTable<TDataItem>({\n columns: tableColumns,\n // 排除掉被折叠的行\n data: rowDndInfo.tableData,\n getCoreRowModel: getCoreRowModel(),\n getRowId: (row, index) => {\n return getRowKey(row, rowKey, index);\n },\n columnResizeMode: 'onChange',\n });\n\n const headerGroups = tableInstance.getHeaderGroups();\n\n const columnWidths = headerGroups[0].headers.map((header) =>\n header.getSize(),\n );\n const getColumnFixedInfo = useFixed<TDataItem>({\n columnWidths,\n tableColumns,\n y,\n scrollbarWidth,\n });\n\n // 渲染 header\n const { rows } = tableInstance.getRowModel();\n\n const isStickyWork = !!sticky && y === undefined;\n const headerStyle: CSSProperties = {};\n if (isStickyWork && _.get(sticky, 'offsetHeader')) {\n headerStyle.top = _.get(sticky, 'offsetHeader', 0);\n }\n\n const totalColumnsWidth = _.sum(columnWidths);\n\n useEffect(() => {\n // 总列宽改变时,重新计算是否需要显示固定列的阴影\n changeIsPing(totalColumnsWidth);\n }, [changeIsPing, totalColumnsWidth]);\n\n const renderHeaderCell = useCallback(\n (header: Header<TDataItem, unknown>, index: number) => {\n // 选择行的列不能拖动宽度\n const showResizer =\n columnSizing &&\n !(!!rowSelectionInfo.isRowSelectionEnabled && index === 0);\n const { className: fixedClassName, style: fixedStyle } =\n getColumnFixedInfo(index, true);\n return (\n <div\n className={cn(prefixCls('th'), fixedClassName)}\n style={{ width: header.getSize(), ...fixedStyle }}\n key={header.id}\n >\n {flexRender(header.column.columnDef.header, header.getContext())}\n {showResizer && (\n <div\n onMouseDown={header.getResizeHandler()}\n onTouchStart={header.getResizeHandler()}\n className={cn(prefixCls('resizer'), {\n [prefixCls('self-resizing')]: header.column.getIsResizing(),\n })}\n />\n )}\n </div>\n );\n },\n [columnSizing, rowSelectionInfo, getColumnFixedInfo],\n );\n\n const visibleColumns = tableInstance.getVisibleLeafColumns();\n\n const columnVirtualizer = useVirtualizer({\n count: tableColumns.length,\n estimateSize: (index: number) => visibleColumns[index].getSize(),\n getScrollElement: () => bodyRef.current,\n horizontal: true,\n overscan: 5,\n });\n\n const virtualColumns = columnVirtualizer.getVirtualItems();\n\n //different virtualization strategy for columns - instead of absolute and translateY, we add empty columns to the left and right\n let virtualPaddingLeft: number | undefined;\n let virtualPaddingRight: number | undefined;\n\n if (columnVirtualizer && virtualColumns?.length) {\n virtualPaddingLeft = virtualColumns[0]?.start ?? 0;\n virtualPaddingRight =\n columnVirtualizer.getTotalSize() -\n (virtualColumns[virtualColumns.length - 1]?.end ?? 0);\n }\n\n const headerContent = (\n <div\n className={cn(prefixCls('header'), {\n [prefixCls('overflow-x')]: true,\n [prefixCls('sticky')]: isStickyWork,\n [prefixCls('resizing')]:\n tableInstance.getState().columnSizingInfo.isResizingColumn,\n })}\n ref={headerRef}\n style={headerStyle}\n >\n {_.map(headerGroups, (headerGroup) => {\n const allHeaderCells = headerGroup.headers;\n const virtualColumns = columnVirtualizer.getVirtualItems();\n\n const middleVirtualColumns: VirtualItem[] = [];\n // 将固定列单独拎出来,固定列不受列虚拟化影响,必须要渲染\n const leftFixedColumns: {\n header: Header<TDataItem, unknown>;\n index: number;\n }[] = [];\n const rightFixedColumns: {\n header: Header<TDataItem, unknown>;\n index: number;\n }[] = [];\n let content: React.ReactNode | null = null;\n if (virtual) {\n _.forEach(allHeaderCells, (header, index) => {\n const fixedInfo = getColumnFixedInfo(index);\n if (fixedInfo.fixed === 'left') {\n leftFixedColumns.push({ header, index });\n }\n if (fixedInfo.fixed === 'right') {\n rightFixedColumns.push({ header, index });\n }\n });\n\n _.forEach(virtualColumns, (virtualColumn) => {\n const colIndex = virtualColumn.index;\n const fixedInfo = getColumnFixedInfo(colIndex);\n if (fixedInfo.fixed !== 'left' && fixedInfo.fixed !== 'right') {\n middleVirtualColumns.push(virtualColumn);\n }\n });\n content = (\n <>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-left')}\n style={{ width: virtualPaddingLeft }}\n />\n ) : null}\n {leftFixedColumns.map(({ header, index }) => {\n return renderHeaderCell(header, index);\n })}\n {_.map(middleVirtualColumns, (virtualColumn) => {\n const header = allHeaderCells[virtualColumn.index];\n return renderHeaderCell(header, virtualColumn.index);\n })}\n {rightFixedColumns.map(({ header, index }) => {\n return renderHeaderCell(header, index);\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-right')}\n style={{ width: virtualPaddingRight }}\n />\n ) : null}\n </>\n );\n } else {\n content = _.map(allHeaderCells, (header, index) =>\n renderHeaderCell(header, index),\n );\n }\n\n return (\n <div\n className={prefixCls('tr')}\n key={headerGroup.id}\n style={{ width: totalColumnsWidth }}\n >\n {content}\n {y !== undefined && (\n <div\n className={prefixCls('header-scroll-placeholder')}\n style={{ flexBasis: scrollbarWidth }}\n />\n )}\n </div>\n );\n })}\n </div>\n );\n\n const onClickRow = useCallback(\n (rowData: TDataItem, rowIndex: number) => () => {\n if (typeof onRowClick !== 'function') {\n return;\n }\n if (window.getSelection()?.toString().length !== 0) {\n // 防止选择文本时触发 onRowClick\n return;\n }\n onRowClick(rowData, rowIndex);\n },\n [onRowClick],\n );\n\n const isShowPagination = !!(\n pagination &&\n (pagination.total > pagination.pageSize || pagination.showSizeChanger)\n );\n const isShowRowSelection = rowSelectionInfo.isShowRowSelectionInFooter;\n\n const isShowFooter = isShowPagination || isShowRowSelection;\n\n // 空态切换 size 的阈值\n const EMPTY_SMALL_SIZE_HEIGHT = 436;\n const isSmallEmpty = totalSize && totalSize.height < EMPTY_SMALL_SIZE_HEIGHT;\n\n const isEmpty = rows.length === 0 && !loading;\n\n const rowVirtualizer = useVirtualizer({\n count: rows.length,\n estimateSize: () => 48, // estimate row height for accurate scrollbar dragging\n // 没有测量出 bodyRef.current 的高度时,返回 null,避免虚拟化器从 DOM 获取异常高度\n getScrollElement: () => (totalSize ? bodyRef.current : null),\n // measure dynamic row height, except in firefox because it measures table border height incorrectly\n measureElement:\n typeof window !== 'undefined' &&\n navigator.userAgent.indexOf('Firefox') === -1\n ? (element) => element?.getBoundingClientRect().height\n : undefined,\n overscan: 5,\n });\n\n const tableRows = virtual ? rowVirtualizer.getVirtualItems() : rows;\n\n const renderBodyCell = useCallback(\n (row: Row<TDataItem>, cell: Cell<TDataItem, unknown>, colIndex: number) => {\n const { className: fixedClassName, style: fixedStyle } =\n getColumnFixedInfo(colIndex);\n const tdContent = flexRender(\n cell.column.columnDef.cell,\n cell.getContext(),\n );\n return (\n <div\n className={cn(prefixCls('td'), fixedClassName)}\n key={cell.id}\n style={{ width: cell.column.getSize(), ...fixedStyle }}\n >\n {expandableInfo.isExpandable &&\n colIndex === (rowSelectionInfo.isRowSelectionEnabled ? 1 : 0) ? (\n <ExpandCell\n expandableInfo={expandableInfo}\n expandable={expandable}\n data={row.original}\n rowKey={rowKey}\n >\n {tdContent}\n </ExpandCell>\n ) : (\n tdContent\n )}\n </div>\n );\n },\n [\n expandableInfo,\n expandable,\n rowKey,\n getColumnFixedInfo,\n rowSelectionInfo.isRowSelectionEnabled,\n ],\n );\n\n // 渲染 body\n const bodyContent = (\n <div\n className={prefixCls('body')}\n style={{\n width: totalColumnsWidth,\n height: virtual\n ? totalSize\n ? rowVirtualizer.getTotalSize()\n : 0\n : 'auto',\n }}\n >\n {isEmpty ? (\n <div style={{ width: totalSize?.width }}>\n <div style={{ visibility: 'hidden' }}>\n {emptyComponent || (\n <div\n className={cn(prefixCls('empty'), {\n [prefixCls('empty-small')]: isSmallEmpty,\n })}\n >\n <Empty\n image={isSmallEmpty ? null : Empty.PRESENTED_IMAGE_SEARCH}\n size={isSmallEmpty ? 'small' : undefined}\n />\n </div>\n )}\n </div>\n <div\n aria-invalid=\"true\"\n style={{\n position: 'absolute',\n top: 40,\n left: 0,\n right: 0,\n bottom: 0,\n }}\n >\n {emptyComponent || (\n <div\n className={cn(prefixCls('empty'), {\n [prefixCls('empty-small')]: isSmallEmpty,\n })}\n >\n <Empty\n image={isSmallEmpty ? null : Empty.PRESENTED_IMAGE_SEARCH}\n size={isSmallEmpty ? 'small' : undefined}\n />\n </div>\n )}\n </div>\n </div>\n ) : (\n _.reduce<Row<TDataItem> | VirtualItem, React.ReactNode[]>(\n tableRows,\n (rowList, rowData, rowIndex) => {\n const row = virtual\n ? rows[rowData.index]\n : (rowData as Row<TDataItem>);\n const allRowCells = row.getVisibleCells();\n\n let content: React.ReactNode | null = null;\n // 将固定列单独拎出来,固定列不受列虚拟化影响,必须要渲染\n const leftFixedColumns: {\n cell: Cell<TDataItem, unknown>;\n index: number;\n }[] = [];\n const rightFixedColumns: {\n cell: Cell<TDataItem, unknown>;\n index: number;\n }[] = [];\n\n if (virtual) {\n const virtualColumns = columnVirtualizer.getVirtualItems();\n\n const middleVirtualColumns: VirtualItem[] = [];\n\n _.forEach(allRowCells, (cell, index) => {\n const fixedInfo = getColumnFixedInfo(index);\n if (fixedInfo.fixed === 'left') {\n leftFixedColumns.push({ cell, index });\n }\n if (fixedInfo.fixed === 'right') {\n rightFixedColumns.push({ cell, index });\n }\n });\n\n _.forEach(virtualColumns, (virtualColumn) => {\n const colIndex = virtualColumn.index;\n const fixedInfo = getColumnFixedInfo(colIndex);\n if (fixedInfo.fixed !== 'left' && fixedInfo.fixed !== 'right') {\n middleVirtualColumns.push(virtualColumn);\n }\n });\n content = (\n <>\n {virtualPaddingLeft ? (\n //fake empty column to the left for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-left')}\n style={{ width: virtualPaddingLeft }}\n />\n ) : null}\n {leftFixedColumns.map(({ cell, index }) => {\n return renderBodyCell(row, cell, index);\n })}\n {middleVirtualColumns.map((virtualColumn) => {\n const colIndex = virtualColumn.index;\n const cell = allRowCells[colIndex];\n return renderBodyCell(row, cell, colIndex);\n })}\n {rightFixedColumns.map(({ cell, index }) => {\n return renderBodyCell(row, cell, index);\n })}\n {virtualPaddingRight ? (\n //fake empty column to the right for virtualization scroll padding\n <div\n className={prefixCls('virtual-padding-right')}\n style={{ width: virtualPaddingRight }}\n />\n ) : null}\n </>\n );\n } else {\n content = allRowCells.map((cell, index) =>\n renderBodyCell(row, cell, index),\n );\n }\n const rowId = row.id;\n\n const rowNode = (\n <div\n key={rowId}\n data-index={virtual ? (rowData as VirtualItem).index : rowIndex}\n className={cn(\n prefixCls('tr'),\n {\n // 需要用 state 的原因是,存在固定列的情况,左右侧的固定列在 dom 结构上不在同一个 tr 上,所以不能用 css 的 :hover 来实现\n // 当拖拽行时,不显示 hover 状态\n [prefixCls('row-hover')]: rowDndInfo.draggingRowId\n ? undefined\n : hoverRowId === rowId,\n [prefixCls('row-dragging')]:\n rowDndInfo.draggingRowId === rowId,\n [prefixCls('no-border-tr')]:\n isShowPagination && rowIndex === rows.length - 1,\n },\n rowClassName(row.original, rowIndex),\n )}\n ref={(node) => {\n // 只在虚拟滚动模式下才测量行高度,避免非虚拟模式下的不必要重渲染\n if (virtual) {\n rowVirtualizer.measureElement(node);\n }\n\n // 如果启用了行拖拽,则设置行引用\n if (rowDnd && node) {\n const rowRef = rowDndInfo.getRowRef(row.original, rowIndex);\n if (rowRef) {\n rowRef.current = node;\n }\n }\n }}\n onClick={onClickRow(row.original, rowIndex)}\n onMouseEnter={() => setHoverRowId(rowId)}\n onMouseLeave={() => setHoverRowId(null)}\n style={\n virtual\n ? {\n position: 'absolute',\n transform: `translateY(${\n (rowData as VirtualItem).start\n }px)`,\n }\n : {}\n }\n >\n {content}\n </div>\n );\n rowList.push(rowNode);\n\n // 渲染额外展开的行\n const expandItem = expandableInfo.expandItemMap[rowId];\n const customExpandRowKey =\n expandableInfo.isExpandable && expandItem?.customExpandRowKey;\n const hasCustomExpandRowKey = !!customExpandRowKey;\n if (hasCustomExpandRowKey) {\n // 在该行的下面追加自定义展开行\n const expandedRowRender = expandableConfig.expandedRowRender;\n if (typeof expandedRowRender !== 'function') {\n console.error('expandedRowRender must be a function');\n return rowList;\n }\n if (expandItem?.isExpanded !== true) {\n return rowList;\n }\n const customRow = (\n <div\n key={customExpandRowKey}\n className={cn(prefixCls('tr'))}\n onClick={onClickRow(row.original, rowIndex)}\n >\n {expandedRowRender(row.original, expandItem.level + 1)}\n </div>\n );\n rowList.push(customRow);\n }\n return rowList;\n },\n [],\n )\n )}\n </div>\n );\n\n const tableContentHeight = useMemo(() => {\n return y && totalSize\n ? totalSize.height - HEADER_HEIGHT - (isShowFooter ? FOOTER_HEIGHT : 0)\n : 'auto';\n }, [y, totalSize, isShowFooter]);\n\n const tableContent = (\n <Spin spinning={!!loading}>\n <div className={prefixCls('content')}>\n {headerContent}\n <div\n style={{\n height: tableContentHeight,\n position: virtual ? 'relative' : undefined,\n }}\n className={cn(prefixCls('body-scroll'), {\n [prefixCls('scroll-y')]: y !== undefined,\n [prefixCls('scroll-hidden')]: isEmpty,\n })}\n ref={bodyRef}\n onScroll={onBodyScroll}\n >\n {bodyContent}\n </div>\n {isShowFooter && (\n <Footer\n rowSelectionInfo={rowSelectionInfo}\n isShowPagination={isShowPagination}\n pagination={pagination}\n scroll={scroll}\n scrollToFirstRow={scrollToFirstRow}\n />\n )}\n </div>\n </Spin>\n );\n\n const tableStyle: CSSProperties = {};\n if (y) {\n tableStyle.height = y;\n }\n\n return (\n <div\n className={cn(prefixCls('container'), {\n [prefixCls('bordered')]: bordered,\n })}\n style={tableStyle}\n >\n <TableResizeWrapper\n onResize={(w, h) =>\n setTotalSize((prev) => {\n if (prev && prev.width === w && prev.height === h) return prev;\n return { width: w, height: h };\n })\n }\n >\n <div\n className={cn(prefixCls('main'), {\n [prefixCls('overflow-hidden')]: !!y,\n [prefixCls('ping-left')]: isPingLeft,\n [prefixCls('ping-right')]: isPingRight,\n })}\n >\n {rowDnd ? <DndWrapper>{tableContent}</DndWrapper> : tableContent}\n </div>\n </TableResizeWrapper>\n </div>\n );\n}\n\nexport default forwardRef(Table) as <TDataItem extends object>(\n props: ITableProps<TDataItem> & {\n ref?: React.ForwardedRef<ITableRef>;\n },\n) => ReturnType<typeof Table>;\n"],"mappings":"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"}
@@ -42,7 +42,7 @@ export interface ITabsProps {
42
42
  moreIcon?: React.ReactNode;
43
43
  /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */
44
44
  'data-testid'?: string;
45
- /** 透传到 tablist aria-label,用于可访问性与自动化测试定位 */
45
+ /** 透传到 Tabs 根容器的 aria-label,用于可访问性与自动化测试定位 */
46
46
  'aria-label'?: string;
47
47
  }
48
48
  declare function Tabs(props: ITabsProps): import("react/jsx-runtime").JSX.Element;
@@ -25,67 +25,15 @@ function Tabs(props) {
25
25
  const [innerActiveKey, setInnerActiveKey] = useState(defaultActiveKey || firstKey);
26
26
  const mergedActiveKey = controlledActiveKey !== void 0 ? controlledActiveKey : innerActiveKey;
27
27
  const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey) ? mergedActiveKey : firstKey;
28
- const tabsId = React.useId();
29
- const tabRefs = useRef({});
30
- const pendingFocusKeyRef = useRef(null);
31
- const getPreferredFocusKey = useCallback((items = resolvedItems) => items.find((item) => item.key === activeKey && !item.disabled)?.key || items.find((item) => !item.disabled)?.key || "", [activeKey, resolvedItems]);
32
- const [focusedKey, setFocusedKey] = useState(() => getPreferredFocusKey());
33
- const getTabId = (key) => `${tabsId}-tab-${key}`;
34
- const getPanelId = (key) => `${tabsId}-panel-${key}`;
35
- const focusTab = useCallback((key) => {
36
- setFocusedKey(key);
37
- tabRefs.current[key]?.focus();
38
- }, []);
39
- useEffect(() => {
40
- const pendingFocusKey = pendingFocusKeyRef.current;
41
- if (pendingFocusKey && resolvedItems.some((item) => item.key === pendingFocusKey && !item.disabled)) {
42
- pendingFocusKeyRef.current = null;
43
- focusTab(pendingFocusKey);
44
- return;
45
- }
46
- setFocusedKey((currentFocusedKey) => {
47
- const focusedItem = resolvedItems.find((item) => item.key === currentFocusedKey);
48
- return focusedItem && !focusedItem.disabled ? currentFocusedKey : getPreferredFocusKey();
49
- });
50
- }, [
51
- focusTab,
52
- getPreferredFocusKey,
53
- resolvedItems
54
- ]);
55
- const activateTab = useCallback((key) => {
28
+ const handleTabClick = (key, e) => {
56
29
  if (controlledActiveKey === void 0) setInnerActiveKey(key);
57
30
  onChange?.(key);
58
- }, [controlledActiveKey, onChange]);
59
- const handleTabClick = (key, e) => {
60
- setFocusedKey(key);
61
- activateTab(key);
62
31
  onTabClick?.(key, e);
63
32
  };
64
33
  const handleRemove = (key, e) => {
65
34
  e.stopPropagation();
66
- const itemIndex = resolvedItems.findIndex((item) => item.key === key);
67
- pendingFocusKeyRef.current = [...resolvedItems.slice(itemIndex + 1), ...resolvedItems.slice(0, itemIndex).reverse()].find((item) => !item.disabled)?.key || null;
68
35
  onEdit?.(key, "remove");
69
36
  };
70
- const handleTabKeyDown = (item, e) => {
71
- const enabledItems = resolvedItems.filter((candidate) => !candidate.disabled);
72
- const currentIndex = enabledItems.findIndex((candidate) => candidate.key === item.key);
73
- if (currentIndex === -1) return;
74
- let nextIndex;
75
- if (!isVertical && e.key === "ArrowRight" || isVertical && e.key === "ArrowDown") nextIndex = (currentIndex + 1) % enabledItems.length;
76
- else if (!isVertical && e.key === "ArrowLeft" || isVertical && e.key === "ArrowUp") nextIndex = (currentIndex - 1 + enabledItems.length) % enabledItems.length;
77
- else if (e.key === "Home") nextIndex = 0;
78
- else if (e.key === "End") nextIndex = enabledItems.length - 1;
79
- if (nextIndex !== void 0) {
80
- e.preventDefault();
81
- focusTab(enabledItems[nextIndex].key);
82
- return;
83
- }
84
- if (e.key === "Enter" || e.key === " ") {
85
- e.preventDefault();
86
- activateTab(item.key);
87
- }
88
- };
89
37
  const handleAdd = (e) => {
90
38
  onEdit?.(e, "add");
91
39
  };
@@ -143,6 +91,7 @@ function Tabs(props) {
143
91
  const showScrollButtons = canScrollLeft || canScrollRight;
144
92
  return /* @__PURE__ */ jsxs("div", {
145
93
  "data-testid": dataTestId,
94
+ "aria-label": ariaLabel,
146
95
  className: cn("ald-tabs ant-tabs tw-flex", rootDirectionClass, adaptHeight && "ald-adapt-height tw-h-full", size !== "small" && "ald-tabs-default", monospace && "ald-tabs-monospace", compact && "ald-tabs-compact", !hasDividing && "ald-tabs-no-dividing", className),
147
96
  style: {
148
97
  ...style,
@@ -169,12 +118,6 @@ function Tabs(props) {
169
118
  style: paddingVal ? { margin: `0 ${paddingVal}px` } : void 0,
170
119
  children: /* @__PURE__ */ jsx("div", {
171
120
  ref: navListRef,
172
- role: "tablist",
173
- "aria-label": ariaLabel,
174
- "aria-orientation": isVertical ? "vertical" : "horizontal",
175
- onBlur: (e) => {
176
- if (!e.currentTarget.contains(e.relatedTarget)) setFocusedKey(getPreferredFocusKey());
177
- },
178
121
  className: cn("ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden", isVertical && "tw-w-full tw-shrink-0 tw-flex-col tw-self-stretch", centered && !isVertical && "tw-justify-center", monospace && "[&>*]:tw-flex-1", isCard ? "tw-gap-1" : !isVertical && !monospace && "tw-gap-8"),
179
122
  style: !isVertical ? {
180
123
  scrollbarWidth: "none",
@@ -183,40 +126,19 @@ function Tabs(props) {
183
126
  children: resolvedItems.map((item) => {
184
127
  const isActive = activeKey === item.key;
185
128
  const showClose = isEditable && item.closable !== false;
186
- const closeLabel = typeof item.label === "string" || typeof item.label === "number" ? `Remove ${item.label}` : "Remove tab";
187
129
  return /* @__PURE__ */ jsxs("div", {
188
- className: cn("ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors", isVertical && "tw-w-full tw-self-stretch", isCard ? cn("tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5", "tw-gap-sp-75", isActive ? "tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--content-brand-primary)]" : "tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-text-[var(--content-secondary)] hover:tw-text-inherit") : cn(size === "small" ? "tw-py-2 tw-text-xs tw-leading-4" : "tw-py-2.5 tw-text-sm tw-leading-5", monospace && "tw-justify-center", isActive ? "tw-font-medium tw-text-[var(--content-brand-primary)]" : "tw-font-medium tw-text-[var(--content-secondary)] hover:tw-text-inherit"), item.disabled && "tw-pointer-events-none tw-cursor-default tw-opacity-50", !item.disabled && [
189
- "has-[.ald-tabs-tab-trigger:focus-visible]:tw-shadow-[0_0_0_2px_var(--focus-ring)]",
190
- "forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline",
191
- "forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline-2",
192
- "forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline-offset-2",
193
- "forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline-[Highlight]"
194
- ]),
130
+ className: cn("ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors", isVertical && "tw-w-full tw-self-stretch", isCard ? cn("tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5", "tw-gap-sp-75", isActive ? "tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--content-brand-primary)]" : "tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-text-[var(--content-secondary)] hover:tw-text-inherit") : cn(size === "small" ? "tw-py-2 tw-text-xs tw-leading-4" : "tw-py-2.5 tw-text-sm tw-leading-5", monospace && "tw-justify-center", isActive ? "tw-font-medium tw-text-[var(--content-brand-primary)]" : "tw-font-medium tw-text-[var(--content-secondary)] hover:tw-text-inherit"), item.disabled && "tw-pointer-events-none tw-cursor-default tw-opacity-50"),
131
+ onClick: item.disabled ? void 0 : (e) => handleTabClick(item.key, e),
195
132
  children: [
196
- /* @__PURE__ */ jsxs("div", {
197
- ref: (node) => {
198
- tabRefs.current[item.key] = node;
199
- },
200
- id: getTabId(item.key),
201
- role: "tab",
202
- "aria-selected": isActive,
203
- "aria-controls": getPanelId(item.key),
204
- "aria-disabled": item.disabled || void 0,
205
- tabIndex: !item.disabled && focusedKey === item.key ? 0 : -1,
206
- className: cn("ald-tabs-tab-trigger tw-flex tw-min-w-0 tw-flex-1 tw-cursor-pointer tw-items-center tw-whitespace-nowrap", isCard ? "tw-gap-sp-75" : "tw-gap-2", monospace && "tw-justify-center"),
207
- onClick: item.disabled ? void 0 : (e) => handleTabClick(item.key, e),
208
- onFocus: () => setFocusedKey(item.key),
209
- onKeyDown: (e) => handleTabKeyDown(item, e),
210
- children: [item.icon, /* @__PURE__ */ jsx("span", {
211
- className: "ant-tabs-tab-btn",
212
- children: item.label
213
- })]
133
+ item.icon,
134
+ /* @__PURE__ */ jsx("span", {
135
+ className: "ant-tabs-tab-btn",
136
+ children: item.label
214
137
  }),
215
- showClose && /* @__PURE__ */ jsx("button", {
216
- type: "button",
217
- className: "ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-border-0 tw-bg-transparent tw-p-0 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]",
138
+ showClose && /* @__PURE__ */ jsx("span", {
139
+ className: "ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-p-0 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]",
218
140
  onClick: (e) => handleRemove(item.key, e),
219
- "aria-label": closeLabel,
141
+ "aria-label": `Remove ${item.label}`,
220
142
  children: /* @__PURE__ */ jsx(Memo$2, { size: 12 })
221
143
  }),
222
144
  !isCard && isActive && isTop && /* @__PURE__ */ jsx("div", { className: "ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]" }),
@@ -274,8 +196,6 @@ function Tabs(props) {
274
196
  return /* @__PURE__ */ jsx("div", {
275
197
  className: cn("ald-tabs-tabpane ant-tabs-tabpane", adaptHeight && "tw-h-full tw-overflow-y-auto", isActive ? "ant-tabs-tabpane-active tw-block" : "tw-hidden"),
276
198
  role: "tabpanel",
277
- id: getPanelId(item.key),
278
- "aria-labelledby": getTabId(item.key),
279
199
  children: item.children
280
200
  }, item.key);
281
201
  })
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/Tabs/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\nimport { ChevronLeftLine, ChevronRightLine, CloseLightLine } from '../Icon';\nimport TabPane from './TabPane';\n\nexport type TabsSize = 'default' | 'small';\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n disabled?: boolean;\n closable?: boolean;\n icon?: React.ReactNode;\n forceRender?: boolean;\n className?: string;\n}\n\nexport interface ITabsProps {\n size?: TabsSize;\n activeKey?: string;\n defaultActiveKey?: string;\n onChange?: (activeKey: string) => void;\n onTabClick?: (activeKey: string, e: React.MouseEvent) => void;\n destroyInactiveTabPane?: boolean;\n centered?: boolean;\n adaptHeight?: boolean;\n tabPosition?: 'left' | 'right' | 'top' | 'bottom';\n className?: string;\n children?: React.ReactNode;\n headerBackgroundColor?: string;\n monospace?: boolean;\n padding?: boolean | number;\n compact?: boolean;\n hasDividing?: boolean;\n items?: TabItem[];\n type?: 'line' | 'card' | 'editable-card';\n tabBarExtraContent?:\n | React.ReactNode\n | { left?: React.ReactNode; right?: React.ReactNode };\n onEdit?: (\n targetKey: string | React.MouseEvent | React.KeyboardEvent,\n action: 'add' | 'remove',\n ) => void;\n hideAdd?: boolean;\n style?: React.CSSProperties;\n tabBarStyle?: React.CSSProperties;\n popupClassName?: string;\n tabBarGutter?: number;\n moreIcon?: React.ReactNode;\n /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到 tablist 的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport default function Tabs(props: ITabsProps) {\n const {\n size,\n className,\n adaptHeight,\n style = {},\n monospace: propsMonospace,\n tabPosition = 'top',\n padding: propsPadding = false,\n compact,\n hasDividing = true,\n items,\n activeKey: controlledActiveKey,\n defaultActiveKey,\n onChange,\n onTabClick,\n destroyInactiveTabPane,\n centered,\n tabBarExtraContent,\n headerBackgroundColor,\n children,\n type,\n onEdit,\n hideAdd,\n tabBarStyle,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n\n const isEditable = type === 'editable-card';\n const isCard = type === 'card' || type === 'editable-card';\n\n // Derive items from children if not provided\n const resolvedItems: TabItem[] = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children)\n .filter(React.isValidElement)\n .map((child: any) => ({\n key: child.key || child.props.key || '',\n label: child.props.tab,\n children: child.props.children,\n disabled: child.props.disabled,\n closable: child.props.closable,\n forceRender: child.props.forceRender,\n }));\n }, [items, children]);\n\n const firstKey = resolvedItems[0]?.key || '';\n const [innerActiveKey, setInnerActiveKey] = useState(\n defaultActiveKey || firstKey,\n );\n const mergedActiveKey =\n controlledActiveKey !== undefined ? controlledActiveKey : innerActiveKey;\n const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey)\n ? mergedActiveKey\n : firstKey;\n\n const tabsId = React.useId();\n const tabRefs = useRef<Record<string, HTMLDivElement | null>>({});\n const pendingFocusKeyRef = useRef<string | null>(null);\n const getPreferredFocusKey = useCallback(\n (items: TabItem[] = resolvedItems) =>\n items.find((item) => item.key === activeKey && !item.disabled)?.key ||\n items.find((item) => !item.disabled)?.key ||\n '',\n [activeKey, resolvedItems],\n );\n const [focusedKey, setFocusedKey] = useState(() => getPreferredFocusKey());\n\n const getTabId = (key: string) => `${tabsId}-tab-${key}`;\n const getPanelId = (key: string) => `${tabsId}-panel-${key}`;\n\n const focusTab = useCallback((key: string) => {\n setFocusedKey(key);\n tabRefs.current[key]?.focus();\n }, []);\n\n useEffect(() => {\n const pendingFocusKey = pendingFocusKeyRef.current;\n if (\n pendingFocusKey &&\n resolvedItems.some(\n (item) => item.key === pendingFocusKey && !item.disabled,\n )\n ) {\n pendingFocusKeyRef.current = null;\n focusTab(pendingFocusKey);\n return;\n }\n\n setFocusedKey((currentFocusedKey) => {\n const focusedItem = resolvedItems.find(\n (item) => item.key === currentFocusedKey,\n );\n return focusedItem && !focusedItem.disabled\n ? currentFocusedKey\n : getPreferredFocusKey();\n });\n }, [focusTab, getPreferredFocusKey, resolvedItems]);\n\n const activateTab = useCallback(\n (key: string) => {\n if (controlledActiveKey === undefined) {\n setInnerActiveKey(key);\n }\n onChange?.(key);\n },\n [controlledActiveKey, onChange],\n );\n\n const handleTabClick = (key: string, e: React.MouseEvent) => {\n setFocusedKey(key);\n activateTab(key);\n onTabClick?.(key, e);\n };\n\n const handleRemove = (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n const itemIndex = resolvedItems.findIndex((item) => item.key === key);\n const nextFocusableItem = [\n ...resolvedItems.slice(itemIndex + 1),\n ...resolvedItems.slice(0, itemIndex).reverse(),\n ].find((item) => !item.disabled);\n pendingFocusKeyRef.current = nextFocusableItem?.key || null;\n onEdit?.(key, 'remove');\n };\n\n const handleTabKeyDown = (\n item: TabItem,\n e: React.KeyboardEvent<HTMLDivElement>,\n ) => {\n const enabledItems = resolvedItems.filter(\n (candidate) => !candidate.disabled,\n );\n const currentIndex = enabledItems.findIndex(\n (candidate) => candidate.key === item.key,\n );\n if (currentIndex === -1) return;\n\n let nextIndex: number | undefined;\n if (\n (!isVertical && e.key === 'ArrowRight') ||\n (isVertical && e.key === 'ArrowDown')\n ) {\n nextIndex = (currentIndex + 1) % enabledItems.length;\n } else if (\n (!isVertical && e.key === 'ArrowLeft') ||\n (isVertical && e.key === 'ArrowUp')\n ) {\n nextIndex =\n (currentIndex - 1 + enabledItems.length) % enabledItems.length;\n } else if (e.key === 'Home') {\n nextIndex = 0;\n } else if (e.key === 'End') {\n nextIndex = enabledItems.length - 1;\n }\n\n if (nextIndex !== undefined) {\n e.preventDefault();\n focusTab(enabledItems[nextIndex].key);\n return;\n }\n\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n activateTab(item.key);\n }\n };\n\n const handleAdd = (e: React.MouseEvent) => {\n onEdit?.(e, 'add');\n };\n\n const monospace = tabPosition !== 'top' ? false : propsMonospace;\n const paddingVal = useMemo(() => {\n if (tabPosition !== 'top') return 0;\n if (typeof propsPadding === 'number') return propsPadding;\n if (typeof propsPadding === 'boolean' && propsPadding) return 20;\n return 0;\n }, [propsPadding, tabPosition]);\n\n const isTop = tabPosition === 'top';\n const isBottom = tabPosition === 'bottom';\n const isLeft = tabPosition === 'left';\n const isRight = tabPosition === 'right';\n const isVertical = tabPosition === 'left' || tabPosition === 'right';\n const rootDirectionClass = isRight\n ? 'tw-flex-row-reverse'\n : isLeft\n ? 'tw-flex-row'\n : isBottom\n ? 'tw-flex-col-reverse'\n : 'tw-flex-col';\n\n const extraLeft =\n tabBarExtraContent &&\n typeof tabBarExtraContent === 'object' &&\n 'left' in tabBarExtraContent\n ? tabBarExtraContent.left\n : null;\n const extraRight = tabBarExtraContent\n ? typeof tabBarExtraContent === 'object' && 'right' in tabBarExtraContent\n ? tabBarExtraContent.right\n : React.isValidElement(tabBarExtraContent)\n ? tabBarExtraContent\n : null\n : null;\n\n // Scroll state for overflow\n const navListRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const checkScroll = useCallback(() => {\n const el = navListRef.current;\n if (!el || isVertical) {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const { scrollLeft, scrollWidth, clientWidth } = el;\n setCanScrollLeft(scrollLeft > 1);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n }, [isVertical]);\n\n useEffect(() => {\n checkScroll();\n const el = navListRef.current;\n if (!el) return;\n // Use ResizeObserver to detect size changes\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => checkScroll());\n ro.observe(el);\n }\n el.addEventListener('scroll', checkScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', checkScroll);\n ro?.disconnect();\n };\n }, [checkScroll, resolvedItems.length]);\n\n const scrollBy = (delta: number) => {\n const el = navListRef.current;\n if (el) {\n el.scrollBy({ left: delta, behavior: 'smooth' });\n }\n };\n\n const showScrollButtons = canScrollLeft || canScrollRight;\n\n return (\n <div\n data-testid={dataTestId}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs ant-tabs tw-flex',\n rootDirectionClass,\n adaptHeight && 'ald-adapt-height tw-h-full',\n size !== 'small' && 'ald-tabs-default',\n monospace && 'ald-tabs-monospace',\n compact && 'ald-tabs-compact',\n !hasDividing && 'ald-tabs-no-dividing',\n className,\n )}\n style={\n {\n ...style,\n '--header-bg-color': headerBackgroundColor,\n '--tabs-padding': `${paddingVal}px`,\n } as React.CSSProperties\n }\n >\n {/* Tab nav */}\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav ant-tabs-nav tw-flex',\n isVertical ? 'tw-shrink-0 tw-items-stretch' : 'tw-items-center',\n isTop && 'tw-mb-5',\n isBottom && 'tw-mt-5',\n isTop &&\n hasDividing &&\n 'tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--border-default)]',\n isBottom &&\n hasDividing &&\n 'tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--border-default)]',\n isTop && compact && '!tw-mb-0',\n isBottom && compact && '!tw-mt-0',\n isLeft &&\n 'tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--border-default)]',\n isRight &&\n 'tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--border-default)]',\n )}\n style={\n headerBackgroundColor || tabBarStyle\n ? {\n ...tabBarStyle,\n ...(headerBackgroundColor\n ? { backgroundColor: headerBackgroundColor }\n : {}),\n }\n : undefined\n }\n >\n {extraLeft}\n\n {/* Scroll left button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-[var(--action-ghost-normal)] tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollLeft && 'tw-invisible',\n )}\n onClick={() => scrollBy(-200)}\n aria-label=\"Scroll tabs left\"\n >\n <ChevronLeftLine size={16} />\n </button>\n )}\n\n <div\n className={cn(\n 'ald-tabs-nav-wrap ant-tabs-nav-wrap',\n isVertical\n ? 'tw-w-full tw-shrink-0 tw-self-stretch'\n : 'tw-min-w-0 tw-flex-1',\n )}\n style={paddingVal ? { margin: `0 ${paddingVal}px` } : undefined}\n >\n <div\n ref={navListRef}\n role=\"tablist\"\n aria-label={ariaLabel}\n aria-orientation={isVertical ? 'vertical' : 'horizontal'}\n onBlur={(e) => {\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) {\n setFocusedKey(getPreferredFocusKey());\n }\n }}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden',\n isVertical && 'tw-w-full tw-shrink-0 tw-flex-col tw-self-stretch',\n centered && !isVertical && 'tw-justify-center',\n monospace && '[&>*]:tw-flex-1',\n isCard ? 'tw-gap-1' : !isVertical && !monospace && 'tw-gap-8',\n )}\n style={\n !isVertical\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = activeKey === item.key;\n // For editable-card, closable defaults to true unless explicitly set to false\n const showClose = isEditable && item.closable !== false;\n const closeLabel =\n typeof item.label === 'string' || typeof item.label === 'number'\n ? `Remove ${item.label}`\n : 'Remove tab';\n\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors',\n isVertical && 'tw-w-full tw-self-stretch',\n // Card / editable-card styling\n isCard\n ? cn(\n 'tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5',\n 'tw-gap-sp-75',\n isActive\n ? 'tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--content-brand-primary)]'\n : 'tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-text-[var(--content-secondary)] hover:tw-text-inherit',\n )\n : cn(\n size === 'small'\n ? 'tw-py-2 tw-text-xs tw-leading-4'\n : 'tw-py-2.5 tw-text-sm tw-leading-5',\n monospace && 'tw-justify-center',\n isActive\n ? 'tw-font-medium tw-text-[var(--content-brand-primary)]'\n : 'tw-font-medium tw-text-[var(--content-secondary)] hover:tw-text-inherit',\n ),\n item.disabled &&\n 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n // Focus belongs to the roving tab trigger, not to the\n // selected/active state. Render it on the tab envelope so\n // card and line tab geometry remain unchanged.\n !item.disabled && [\n 'has-[.ald-tabs-tab-trigger:focus-visible]:tw-shadow-[0_0_0_2px_var(--focus-ring)]',\n 'forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline',\n 'forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline-2',\n 'forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline-offset-2',\n 'forced-colors:has-[.ald-tabs-tab-trigger:focus-visible]:tw-outline-[Highlight]',\n ],\n )}\n >\n <div\n ref={(node) => {\n tabRefs.current[item.key] = node;\n }}\n id={getTabId(item.key)}\n role=\"tab\"\n aria-selected={isActive}\n aria-controls={getPanelId(item.key)}\n aria-disabled={item.disabled || undefined}\n tabIndex={\n !item.disabled && focusedKey === item.key ? 0 : -1\n }\n className={cn(\n 'ald-tabs-tab-trigger tw-flex tw-min-w-0 tw-flex-1 tw-cursor-pointer tw-items-center tw-whitespace-nowrap',\n isCard ? 'tw-gap-sp-75' : 'tw-gap-2',\n monospace && 'tw-justify-center',\n )}\n onClick={\n item.disabled\n ? undefined\n : (e) => handleTabClick(item.key, e)\n }\n onFocus={() => setFocusedKey(item.key)}\n onKeyDown={(e) => handleTabKeyDown(item, e)}\n >\n {item.icon}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ant-tabs-tab-btn\">{item.label}</span>\n </div>\n {/* Close button for editable-card */}\n {showClose && (\n <button\n type=\"button\"\n className=\"ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-border-0 tw-bg-transparent tw-p-0 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={(e) => handleRemove(item.key, e)}\n aria-label={closeLabel}\n >\n <CloseLightLine size={12} />\n </button>\n )}\n {/* Active indicator for non-card line tabs */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {!isCard && isActive && isTop && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n {!isCard && isActive && isBottom && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--top-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n {!isCard && isActive && isLeft && (\n <div className=\"tw-absolute tw-inset-y-0 tw--right-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n {!isCard && isActive && isRight && (\n <div className=\"tw-absolute tw-inset-y-0 tw--left-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Scroll right button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-[var(--action-ghost-normal)] tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollRight && 'tw-invisible',\n )}\n onClick={() => scrollBy(200)}\n aria-label=\"Scroll tabs right\"\n >\n <ChevronRightLine size={16} />\n </button>\n )}\n\n {/* Add button for editable-card */}\n {isEditable && !hideAdd && (\n <button\n type=\"button\"\n className=\"ald-tabs-nav-add tw-ml-1 tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-px-2 tw-py-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={handleAdd}\n aria-label=\"Add tab\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n\n {extraRight}\n </div>\n\n {/* Tab content */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n className={cn(\n 'ald-tabs-content ant-tabs-content ant-tabs-content-holder tw-min-h-0 tw-flex-1',\n adaptHeight && 'tw-h-full',\n )}\n style={\n paddingVal\n ? { padding: `0 ${paddingVal}px ${paddingVal}px` }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = item.key === activeKey;\n if (!isActive && destroyInactiveTabPane && !item.forceRender) {\n return null;\n }\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tabpane ant-tabs-tabpane',\n // v2 行为:adaptHeight 时 tabpane 撑满内容区,子元素的百分比高度才能解析\n adaptHeight && 'tw-h-full tw-overflow-y-auto',\n isActive ? 'ant-tabs-tabpane-active tw-block' : 'tw-hidden',\n )}\n role=\"tabpanel\"\n id={getPanelId(item.key)}\n aria-labelledby={getTabId(item.key)}\n >\n {item.children}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nTabs.TabPane = TabPane;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/Tabs/index.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { cn } from '../lib/utils';\nimport { ChevronLeftLine, ChevronRightLine, CloseLightLine } from '../Icon';\nimport TabPane from './TabPane';\n\nexport type TabsSize = 'default' | 'small';\n\ninterface TabItem {\n key: string;\n label: React.ReactNode;\n children?: React.ReactNode;\n disabled?: boolean;\n closable?: boolean;\n icon?: React.ReactNode;\n forceRender?: boolean;\n className?: string;\n}\n\nexport interface ITabsProps {\n size?: TabsSize;\n activeKey?: string;\n defaultActiveKey?: string;\n onChange?: (activeKey: string) => void;\n onTabClick?: (activeKey: string, e: React.MouseEvent) => void;\n destroyInactiveTabPane?: boolean;\n centered?: boolean;\n adaptHeight?: boolean;\n tabPosition?: 'left' | 'right' | 'top' | 'bottom';\n className?: string;\n children?: React.ReactNode;\n headerBackgroundColor?: string;\n monospace?: boolean;\n padding?: boolean | number;\n compact?: boolean;\n hasDividing?: boolean;\n items?: TabItem[];\n type?: 'line' | 'card' | 'editable-card';\n tabBarExtraContent?:\n | React.ReactNode\n | { left?: React.ReactNode; right?: React.ReactNode };\n onEdit?: (\n targetKey: string | React.MouseEvent | React.KeyboardEvent,\n action: 'add' | 'remove',\n ) => void;\n hideAdd?: boolean;\n style?: React.CSSProperties;\n tabBarStyle?: React.CSSProperties;\n popupClassName?: string;\n tabBarGutter?: number;\n moreIcon?: React.ReactNode;\n /** 透传到 Tabs 根容器的 data-testid,用于自动化测试定位 */\n 'data-testid'?: string;\n /** 透传到 Tabs 根容器的 aria-label,用于可访问性与自动化测试定位 */\n 'aria-label'?: string;\n}\n\nexport default function Tabs(props: ITabsProps) {\n const {\n size,\n className,\n adaptHeight,\n style = {},\n monospace: propsMonospace,\n tabPosition = 'top',\n padding: propsPadding = false,\n compact,\n hasDividing = true,\n items,\n activeKey: controlledActiveKey,\n defaultActiveKey,\n onChange,\n onTabClick,\n destroyInactiveTabPane,\n centered,\n tabBarExtraContent,\n headerBackgroundColor,\n children,\n type,\n onEdit,\n hideAdd,\n tabBarStyle,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n } = props;\n\n const isEditable = type === 'editable-card';\n const isCard = type === 'card' || type === 'editable-card';\n\n // Derive items from children if not provided\n const resolvedItems: TabItem[] = useMemo(() => {\n if (items) return items;\n return React.Children.toArray(children)\n .filter(React.isValidElement)\n .map((child: any) => ({\n key: child.key || child.props.key || '',\n label: child.props.tab,\n children: child.props.children,\n disabled: child.props.disabled,\n closable: child.props.closable,\n forceRender: child.props.forceRender,\n }));\n }, [items, children]);\n\n const firstKey = resolvedItems[0]?.key || '';\n const [innerActiveKey, setInnerActiveKey] = useState(\n defaultActiveKey || firstKey,\n );\n const mergedActiveKey =\n controlledActiveKey !== undefined ? controlledActiveKey : innerActiveKey;\n const activeKey = resolvedItems.some((item) => item.key === mergedActiveKey)\n ? mergedActiveKey\n : firstKey;\n\n const handleTabClick = (key: string, e: React.MouseEvent) => {\n if (controlledActiveKey === undefined) {\n setInnerActiveKey(key);\n }\n onChange?.(key);\n onTabClick?.(key, e);\n };\n\n const handleRemove = (key: string, e: React.MouseEvent) => {\n e.stopPropagation();\n onEdit?.(key, 'remove');\n };\n\n const handleAdd = (e: React.MouseEvent) => {\n onEdit?.(e, 'add');\n };\n\n const monospace = tabPosition !== 'top' ? false : propsMonospace;\n const paddingVal = useMemo(() => {\n if (tabPosition !== 'top') return 0;\n if (typeof propsPadding === 'number') return propsPadding;\n if (typeof propsPadding === 'boolean' && propsPadding) return 20;\n return 0;\n }, [propsPadding, tabPosition]);\n\n const isTop = tabPosition === 'top';\n const isBottom = tabPosition === 'bottom';\n const isLeft = tabPosition === 'left';\n const isRight = tabPosition === 'right';\n const isVertical = tabPosition === 'left' || tabPosition === 'right';\n const rootDirectionClass = isRight\n ? 'tw-flex-row-reverse'\n : isLeft\n ? 'tw-flex-row'\n : isBottom\n ? 'tw-flex-col-reverse'\n : 'tw-flex-col';\n\n const extraLeft =\n tabBarExtraContent &&\n typeof tabBarExtraContent === 'object' &&\n 'left' in tabBarExtraContent\n ? tabBarExtraContent.left\n : null;\n const extraRight = tabBarExtraContent\n ? typeof tabBarExtraContent === 'object' && 'right' in tabBarExtraContent\n ? tabBarExtraContent.right\n : React.isValidElement(tabBarExtraContent)\n ? tabBarExtraContent\n : null\n : null;\n\n // Scroll state for overflow\n const navListRef = useRef<HTMLDivElement>(null);\n const [canScrollLeft, setCanScrollLeft] = useState(false);\n const [canScrollRight, setCanScrollRight] = useState(false);\n\n const checkScroll = useCallback(() => {\n const el = navListRef.current;\n if (!el || isVertical) {\n setCanScrollLeft(false);\n setCanScrollRight(false);\n return;\n }\n const { scrollLeft, scrollWidth, clientWidth } = el;\n setCanScrollLeft(scrollLeft > 1);\n setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 1);\n }, [isVertical]);\n\n useEffect(() => {\n checkScroll();\n const el = navListRef.current;\n if (!el) return;\n // Use ResizeObserver to detect size changes\n let ro: ResizeObserver | undefined;\n if (typeof ResizeObserver !== 'undefined') {\n ro = new ResizeObserver(() => checkScroll());\n ro.observe(el);\n }\n el.addEventListener('scroll', checkScroll, { passive: true });\n return () => {\n el.removeEventListener('scroll', checkScroll);\n ro?.disconnect();\n };\n }, [checkScroll, resolvedItems.length]);\n\n const scrollBy = (delta: number) => {\n const el = navListRef.current;\n if (el) {\n el.scrollBy({ left: delta, behavior: 'smooth' });\n }\n };\n\n const showScrollButtons = canScrollLeft || canScrollRight;\n\n return (\n <div\n data-testid={dataTestId}\n aria-label={ariaLabel}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs ant-tabs tw-flex',\n rootDirectionClass,\n adaptHeight && 'ald-adapt-height tw-h-full',\n size !== 'small' && 'ald-tabs-default',\n monospace && 'ald-tabs-monospace',\n compact && 'ald-tabs-compact',\n !hasDividing && 'ald-tabs-no-dividing',\n className,\n )}\n style={\n {\n ...style,\n '--header-bg-color': headerBackgroundColor,\n '--tabs-padding': `${paddingVal}px`,\n } as React.CSSProperties\n }\n >\n {/* Tab nav */}\n <div\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav ant-tabs-nav tw-flex',\n isVertical ? 'tw-shrink-0 tw-items-stretch' : 'tw-items-center',\n isTop && 'tw-mb-5',\n isBottom && 'tw-mt-5',\n isTop &&\n hasDividing &&\n 'tw-border-0 tw-border-b tw-border-solid tw-border-b-[var(--border-default)]',\n isBottom &&\n hasDividing &&\n 'tw-border-0 tw-border-t tw-border-solid tw-border-t-[var(--border-default)]',\n isTop && compact && '!tw-mb-0',\n isBottom && compact && '!tw-mt-0',\n isLeft &&\n 'tw-flex-col tw-border-0 tw-border-r tw-border-solid tw-border-r-[var(--border-default)]',\n isRight &&\n 'tw-flex-col tw-border-0 tw-border-l tw-border-solid tw-border-l-[var(--border-default)]',\n )}\n style={\n headerBackgroundColor || tabBarStyle\n ? {\n ...tabBarStyle,\n ...(headerBackgroundColor\n ? { backgroundColor: headerBackgroundColor }\n : {}),\n }\n : undefined\n }\n >\n {extraLeft}\n\n {/* Scroll left button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-[var(--action-ghost-normal)] tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollLeft && 'tw-invisible',\n )}\n onClick={() => scrollBy(-200)}\n aria-label=\"Scroll tabs left\"\n >\n <ChevronLeftLine size={16} />\n </button>\n )}\n\n <div\n className={cn(\n 'ald-tabs-nav-wrap ant-tabs-nav-wrap',\n isVertical\n ? 'tw-w-full tw-shrink-0 tw-self-stretch'\n : 'tw-min-w-0 tw-flex-1',\n )}\n style={paddingVal ? { margin: `0 ${paddingVal}px` } : undefined}\n >\n <div\n ref={navListRef}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-nav-list ant-tabs-nav-list tw-flex tw-overflow-hidden',\n isVertical && 'tw-w-full tw-shrink-0 tw-flex-col tw-self-stretch',\n centered && !isVertical && 'tw-justify-center',\n monospace && '[&>*]:tw-flex-1',\n isCard ? 'tw-gap-1' : !isVertical && !monospace && 'tw-gap-8',\n )}\n style={\n !isVertical\n ? { scrollbarWidth: 'none', msOverflowStyle: 'none' }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = activeKey === item.key;\n // For editable-card, closable defaults to true unless explicitly set to false\n const showClose = isEditable && item.closable !== false;\n\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tab ant-tabs-tab tw-relative tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-gap-2 tw-whitespace-nowrap tw-transition-colors',\n isVertical && 'tw-w-full tw-self-stretch',\n // Card / editable-card styling\n isCard\n ? cn(\n 'tw-h-10 tw-rounded-t-[6px] tw-border tw-border-b-0 tw-border-solid tw-px-4 tw-text-sm tw-leading-5',\n 'tw-gap-sp-75',\n isActive\n ? 'tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-font-medium tw-text-[var(--content-brand-primary)]'\n : 'tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-text-[var(--content-secondary)] hover:tw-text-inherit',\n )\n : cn(\n size === 'small'\n ? 'tw-py-2 tw-text-xs tw-leading-4'\n : 'tw-py-2.5 tw-text-sm tw-leading-5',\n monospace && 'tw-justify-center',\n isActive\n ? 'tw-font-medium tw-text-[var(--content-brand-primary)]'\n : 'tw-font-medium tw-text-[var(--content-secondary)] hover:tw-text-inherit',\n ),\n item.disabled &&\n 'tw-pointer-events-none tw-cursor-default tw-opacity-50',\n )}\n onClick={\n item.disabled\n ? undefined\n : (e) => handleTabClick(item.key, e)\n }\n >\n {item.icon}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <span className=\"ant-tabs-tab-btn\">{item.label}</span>\n {/* Close button for editable-card */}\n {showClose && (\n <span\n className=\"ald-tabs-tab-remove tw-m-0 tw-grid tw-size-4 tw-cursor-pointer tw-place-items-center tw-p-0 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={(e) => handleRemove(item.key, e)}\n aria-label={`Remove ${item.label}`}\n >\n <CloseLightLine size={12} />\n </span>\n )}\n {/* Active indicator for non-card line tabs */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n {!isCard && isActive && isTop && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--bottom-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n {!isCard && isActive && isBottom && (\n <div className=\"ant-tabs-ink-bar tw-absolute tw-inset-x-0 tw--top-px tw-h-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n {!isCard && isActive && isLeft && (\n <div className=\"tw-absolute tw-inset-y-0 tw--right-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n {!isCard && isActive && isRight && (\n <div className=\"tw-absolute tw-inset-y-0 tw--left-px tw-w-[2px] tw-rounded-[2px] tw-bg-[var(--border-brand-strong)]\" />\n )}\n </div>\n );\n })}\n </div>\n </div>\n\n {/* Scroll right button */}\n {showScrollButtons && !isVertical && (\n <button\n type=\"button\"\n className={cn(\n 'ald-tabs-scroll-btn tw-flex tw-shrink-0 tw-items-center tw-justify-center tw-border-none tw-bg-[var(--action-ghost-normal)] tw-p-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]',\n !canScrollRight && 'tw-invisible',\n )}\n onClick={() => scrollBy(200)}\n aria-label=\"Scroll tabs right\"\n >\n <ChevronRightLine size={16} />\n </button>\n )}\n\n {/* Add button for editable-card */}\n {isEditable && !hideAdd && (\n <button\n type=\"button\"\n className=\"ald-tabs-nav-add tw-ml-1 tw-flex tw-shrink-0 tw-cursor-pointer tw-items-center tw-justify-center tw-rounded tw-border tw-border-solid tw-border-[var(--border-default)] tw-bg-[var(--background-default)] tw-px-2 tw-py-1 tw-text-[var(--content-secondary)] tw-transition-colors hover:tw-text-[var(--content-primary)]\"\n onClick={handleAdd}\n aria-label=\"Add tab\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\" />\n <line x1=\"5\" y1=\"12\" x2=\"19\" y2=\"12\" />\n </svg>\n </button>\n )}\n\n {extraRight}\n </div>\n\n {/* Tab content */}\n {/* antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器 */}\n <div\n className={cn(\n 'ald-tabs-content ant-tabs-content ant-tabs-content-holder tw-min-h-0 tw-flex-1',\n adaptHeight && 'tw-h-full',\n )}\n style={\n paddingVal\n ? { padding: `0 ${paddingVal}px ${paddingVal}px` }\n : undefined\n }\n >\n {resolvedItems.map((item) => {\n const isActive = item.key === activeKey;\n if (!isActive && destroyInactiveTabPane && !item.forceRender) {\n return null;\n }\n return (\n <div\n key={item.key}\n className={cn(\n // antd 兼容:保留 ant-* class,消费方 CSS 可能依赖该选择器\n 'ald-tabs-tabpane ant-tabs-tabpane',\n // v2 行为:adaptHeight 时 tabpane 撑满内容区,子元素的百分比高度才能解析\n adaptHeight && 'tw-h-full tw-overflow-y-auto',\n isActive ? 'ant-tabs-tabpane-active tw-block' : 'tw-hidden',\n )}\n role=\"tabpanel\"\n >\n {item.children}\n </div>\n );\n })}\n </div>\n </div>\n );\n}\n\nTabs.TabPane = TabPane;\n"],"mappings":";;;;;;;;AA8DA,SAAwB,KAAK,OAAmB;CAC9C,MAAM,EACJ,MACA,WACA,aACA,QAAQ,EAAE,EACV,WAAW,gBACX,cAAc,OACd,SAAS,eAAe,OACxB,SACA,cAAc,MACd,OACA,WAAW,qBACX,kBACA,UACA,YACA,wBACA,UACA,oBACA,uBACA,UACA,MACA,QACA,SACA,aACA,eAAe,YACf,cAAc,cACZ;CAEJ,MAAM,aAAa,SAAS;CAC5B,MAAM,SAAS,SAAS,UAAU,SAAS;CAG3C,MAAM,gBAA2B,cAAc;AAC7C,MAAI,MAAO,QAAO;AAClB,SAAO,MAAM,SAAS,QAAQ,SAAS,CACpC,OAAO,MAAM,eAAe,CAC5B,KAAK,WAAgB;GACpB,KAAK,MAAM,OAAO,MAAM,MAAM,OAAO;GACrC,OAAO,MAAM,MAAM;GACnB,UAAU,MAAM,MAAM;GACtB,UAAU,MAAM,MAAM;GACtB,UAAU,MAAM,MAAM;GACtB,aAAa,MAAM,MAAM;GAC1B,EAAE;IACJ,CAAC,OAAO,SAAS,CAAC;CAErB,MAAM,WAAW,cAAc,IAAI,OAAO;CAC1C,MAAM,CAAC,gBAAgB,qBAAqB,SAC1C,oBAAoB,SACrB;CACD,MAAM,kBACJ,wBAAwB,SAAY,sBAAsB;CAC5D,MAAM,YAAY,cAAc,MAAM,SAAS,KAAK,QAAQ,gBAAgB,GACxE,kBACA;CAEJ,MAAM,kBAAkB,KAAa,MAAwB;AAC3D,MAAI,wBAAwB,OAC1B,mBAAkB,IAAI;AAExB,aAAW,IAAI;AACf,eAAa,KAAK,EAAE;;CAGtB,MAAM,gBAAgB,KAAa,MAAwB;AACzD,IAAE,iBAAiB;AACnB,WAAS,KAAK,SAAS;;CAGzB,MAAM,aAAa,MAAwB;AACzC,WAAS,GAAG,MAAM;;CAGpB,MAAM,YAAY,gBAAgB,QAAQ,QAAQ;CAClD,MAAM,aAAa,cAAc;AAC/B,MAAI,gBAAgB,MAAO,QAAO;AAClC,MAAI,OAAO,iBAAiB,SAAU,QAAO;AAC7C,MAAI,OAAO,iBAAiB,aAAa,aAAc,QAAO;AAC9D,SAAO;IACN,CAAC,cAAc,YAAY,CAAC;CAE/B,MAAM,QAAQ,gBAAgB;CAC9B,MAAM,WAAW,gBAAgB;CACjC,MAAM,SAAS,gBAAgB;CAC/B,MAAM,UAAU,gBAAgB;CAChC,MAAM,aAAa,gBAAgB,UAAU,gBAAgB;CAC7D,MAAM,qBAAqB,UACvB,wBACA,SACA,gBACA,WACA,wBACA;CAEJ,MAAM,YACJ,sBACA,OAAO,uBAAuB,YAC9B,UAAU,qBACN,mBAAmB,OACnB;CACN,MAAM,aAAa,qBACf,OAAO,uBAAuB,YAAY,WAAW,qBACnD,mBAAmB,QACnB,MAAM,eAAe,mBAAmB,GACxC,qBACA,OACF;CAGJ,MAAM,aAAa,OAAuB,KAAK;CAC/C,MAAM,CAAC,eAAe,oBAAoB,SAAS,MAAM;CACzD,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,MAAM;CAE3D,MAAM,cAAc,kBAAkB;EACpC,MAAM,KAAK,WAAW;AACtB,MAAI,CAAC,MAAM,YAAY;AACrB,oBAAiB,MAAM;AACvB,qBAAkB,MAAM;AACxB;;EAEF,MAAM,EAAE,YAAY,aAAa,gBAAgB;AACjD,mBAAiB,aAAa,EAAE;AAChC,oBAAkB,aAAa,cAAc,cAAc,EAAE;IAC5D,CAAC,WAAW,CAAC;AAEhB,iBAAgB;AACd,eAAa;EACb,MAAM,KAAK,WAAW;AACtB,MAAI,CAAC,GAAI;EAET,IAAI;AACJ,MAAI,OAAO,mBAAmB,aAAa;AACzC,QAAK,IAAI,qBAAqB,aAAa,CAAC;AAC5C,MAAG,QAAQ,GAAG;;AAEhB,KAAG,iBAAiB,UAAU,aAAa,EAAE,SAAS,MAAM,CAAC;AAC7D,eAAa;AACX,MAAG,oBAAoB,UAAU,YAAY;AAC7C,OAAI,YAAY;;IAEjB,CAAC,aAAa,cAAc,OAAO,CAAC;CAEvC,MAAM,YAAY,UAAkB;EAClC,MAAM,KAAK,WAAW;AACtB,MAAI,GACF,IAAG,SAAS;GAAE,MAAM;GAAO,UAAU;GAAU,CAAC;;CAIpD,MAAM,oBAAoB,iBAAiB;AAE3C,QACE,qBAAC,OAAD;EACE,eAAa;EACb,cAAY;EACZ,WAAW,GAET,6BACA,oBACA,eAAe,8BACf,SAAS,WAAW,oBACpB,aAAa,sBACb,WAAW,oBACX,CAAC,eAAe,wBAChB,UACD;EACD,OACE;GACE,GAAG;GACH,qBAAqB;GACrB,kBAAkB,GAAG,WAAW;GACjC;YAnBL,CAuBE,qBAAC,OAAD;GACE,WAAW,GAET,qCACA,aAAa,iCAAiC,mBAC9C,SAAS,WACT,YAAY,WACZ,SACE,eACA,+EACF,YACE,eACA,+EACF,SAAS,WAAW,YACpB,YAAY,WAAW,YACvB,UACE,2FACF,WACE,0FACH;GACD,OACE,yBAAyB,cACrB;IACE,GAAG;IACH,GAAI,wBACA,EAAE,iBAAiB,uBAAuB,GAC1C,EAAE;IACP,GACD;aA5BR;IA+BG;IAGA,qBAAqB,CAAC,cACrB,oBAAC,UAAD;KACE,MAAK;KACL,WAAW,GACT,qOACA,CAAC,iBAAiB,eACnB;KACD,eAAe,SAAS,KAAK;KAC7B,cAAW;eAEX,oBAAC,MAAD,EAAiB,MAAM,IAAM,CAAA;KACtB,CAAA;IAGX,oBAAC,OAAD;KACE,WAAW,GACT,uCACA,aACI,0CACA,uBACL;KACD,OAAO,aAAa,EAAE,QAAQ,KAAK,WAAW,KAAK,GAAG;eAEtD,oBAAC,OAAD;MACE,KAAK;MACL,WAAW,GAET,kEACA,cAAc,qDACd,YAAY,CAAC,cAAc,qBAC3B,aAAa,mBACb,SAAS,aAAa,CAAC,cAAc,CAAC,aAAa,WACpD;MACD,OACE,CAAC,aACG;OAAE,gBAAgB;OAAQ,iBAAiB;OAAQ,GACnD;gBAGL,cAAc,KAAK,SAAS;OAC3B,MAAM,WAAW,cAAc,KAAK;OAEpC,MAAM,YAAY,cAAc,KAAK,aAAa;AAElD,cACE,qBAAC,OAAD;QAEE,WAAW,GAET,kJACA,cAAc,6BAEd,SACI,GACE,sGACA,gBACA,WACI,8HACA,+HACL,GACD,GACE,SAAS,UACL,oCACA,qCACJ,aAAa,qBACb,WACI,0DACA,0EACL,EACL,KAAK,YACH,yDACH;QACD,SACE,KAAK,WACD,UACC,MAAM,eAAe,KAAK,KAAK,EAAE;kBA9B1C;SAiCG,KAAK;SAEN,oBAAC,QAAD;UAAM,WAAU;oBAAoB,KAAK;UAAa,CAAA;SAErD,aACC,oBAAC,QAAD;UACE,WAAU;UACV,UAAU,MAAM,aAAa,KAAK,KAAK,EAAE;UACzC,cAAY,UAAU,KAAK;oBAE3B,oBAAC,QAAD,EAAgB,MAAM,IAAM,CAAA;UACvB,CAAA;SAIR,CAAC,UAAU,YAAY,SACtB,oBAAC,OAAD,EAAK,WAAU,0HAA2H,CAAA;SAE3I,CAAC,UAAU,YAAY,YACtB,oBAAC,OAAD,EAAK,WAAU,uHAAwH,CAAA;SAExI,CAAC,UAAU,YAAY,UACtB,oBAAC,OAAD,EAAK,WAAU,wGAAyG,CAAA;SAEzH,CAAC,UAAU,YAAY,WACtB,oBAAC,OAAD,EAAK,WAAU,uGAAwG,CAAA;SAErH;UA3DC,KAAK,IA2DN;QAER;MACE,CAAA;KACF,CAAA;IAGL,qBAAqB,CAAC,cACrB,oBAAC,UAAD;KACE,MAAK;KACL,WAAW,GACT,qOACA,CAAC,kBAAkB,eACpB;KACD,eAAe,SAAS,IAAI;KAC5B,cAAW;eAEX,oBAAC,QAAD,EAAkB,MAAM,IAAM,CAAA;KACvB,CAAA;IAIV,cAAc,CAAC,WACd,oBAAC,UAAD;KACE,MAAK;KACL,WAAU;KACV,SAAS;KACT,cAAW;eAEX,qBAAC,OAAD;MACE,OAAM;MACN,OAAM;MACN,QAAO;MACP,SAAQ;MACR,MAAK;MACL,QAAO;MACP,aAAY;MACZ,eAAc;MACd,gBAAe;gBATjB,CAWE,oBAAC,QAAD;OAAM,IAAG;OAAK,IAAG;OAAI,IAAG;OAAK,IAAG;OAAO,CAAA,EACvC,oBAAC,QAAD;OAAM,IAAG;OAAI,IAAG;OAAK,IAAG;OAAK,IAAG;OAAO,CAAA,CACnC;;KACC,CAAA;IAGV;IACG;MAIN,oBAAC,OAAD;GACE,WAAW,GACT,kFACA,eAAe,YAChB;GACD,OACE,aACI,EAAE,SAAS,KAAK,WAAW,KAAK,WAAW,KAAK,GAChD;aAGL,cAAc,KAAK,SAAS;IAC3B,MAAM,WAAW,KAAK,QAAQ;AAC9B,QAAI,CAAC,YAAY,0BAA0B,CAAC,KAAK,YAC/C,QAAO;AAET,WACE,oBAAC,OAAD;KAEE,WAAW,GAET,qCAEA,eAAe,gCACf,WAAW,qCAAqC,YACjD;KACD,MAAK;eAEJ,KAAK;KACF,EAXC,KAAK,IAWN;KAER;GACE,CAAA,CACF;;;AAIV,KAAK,UAAU"}