diff --git a/packages/common b/packages/common index 30800118e4..defc1d2242 160000 --- a/packages/common +++ b/packages/common @@ -1 +1 @@ -Subproject commit 30800118e41c7e37fcb710febd3ff3ae58e06a1b +Subproject commit defc1d2242c6895d8ca56268bd4dbbb851b9ee72 diff --git a/packages/components/tree/Tree.tsx b/packages/components/tree/Tree.tsx index 70a90b055c..14758df6da 100644 --- a/packages/components/tree/Tree.tsx +++ b/packages/components/tree/Tree.tsx @@ -1,40 +1,40 @@ import React, { forwardRef, - useState, + MouseEvent, + RefObject, + useCallback, useImperativeHandle, useMemo, - RefObject, - MouseEvent, useRef, - useCallback, + useState, } from 'react'; import { CSSTransition, TransitionGroup } from 'react-transition-group'; import classNames from 'classnames'; import { get } from 'lodash-es'; -import TreeNode from '@tdesign/common-js/tree-v1/tree-node'; import log from '@tdesign/common-js/log/index'; +import TreeNode from '@tdesign/common-js/tree-v1/tree-node'; import type { TreeNodeState, TreeNodeValue, TypeTreeNodeData, TypeTreeNodeModel, } from '@tdesign/common-js/tree-v1/types'; -import { TreeOptionData, StyledProps, ComponentScrollToElementParams } from '../common'; -import { TreeItemProps } from './interface'; -import TreeItem from './TreeItem'; +import parseTNode from '../_util/parseTNode'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { usePersistFn } from '../hooks/usePersistFn'; +import { treeDefaultProps } from './defaultProps'; +import { TreeDraggableContext } from './hooks/TreeDraggableContext'; import useControllable from './hooks/useControllable'; import { useStore } from './hooks/useStore'; import { useTreeConfig } from './hooks/useTreeConfig'; -import { TreeDraggableContext } from './hooks/TreeDraggableContext'; -import parseTNode from '../_util/parseTNode'; -import { usePersistFn } from '../hooks/usePersistFn'; import useTreeVirtualScroll from './hooks/useTreeVirtualScroll'; +import TreeItem from './TreeItem'; -import type { TreeInstanceFunctions, TdTreeProps } from './type'; -import { treeDefaultProps } from './defaultProps'; -import useDefaultProps from '../hooks/useDefaultProps'; +import type { ComponentScrollToElementParams, StyledProps, TreeOptionData } from '../common'; +import type { TreeItemProps } from './interface'; +import type { TdTreeProps, TreeInstanceFunctions } from './type'; export type TreeProps = TdTreeProps & StyledProps; @@ -179,11 +179,12 @@ const Tree = forwardRef, TreeProps>((origi }; const handleChange: TreeItemProps['onChange'] = (node, ctx) => { - if (!node || disabled || node.disabled) { - return; - } - setChecked(node, !node.isChecked(), { ...ctx, trigger: 'node-click' }); + if (!node || disabled || node.disabled) return; + const checked = node.toggleChecked(); + const treeNodeModel = node?.getModel(); + onChange?.(checked, { node: treeNodeModel, ...ctx, trigger: 'node-click' }); }; + const handleScrollToElement = useCallback( (params: ComponentScrollToElementParams) => { let { index } = params; diff --git a/packages/components/tree/TreeItem.tsx b/packages/components/tree/TreeItem.tsx index 92e39c62cd..8b28e0f97c 100644 --- a/packages/components/tree/TreeItem.tsx +++ b/packages/components/tree/TreeItem.tsx @@ -50,7 +50,6 @@ const TreeItem = forwardRef( expandOnClickNode, activable, checkProps, - disableCheck, operations, onClick, onChange, @@ -242,32 +241,20 @@ const TreeItem = forwardRef( }); if (node.isCheckable()) { - let checkboxDisabled: boolean; - if (typeof disableCheck === 'function') { - checkboxDisabled = disableCheck(node.getModel()); - } else { - checkboxDisabled = !!disableCheck; - } - - if (node.isDisabled()) { - checkboxDisabled = true; - } - let checkboxProps: CheckboxProps; if (typeof checkProps === 'function') { checkboxProps = checkProps(node.getModel()); } else { checkboxProps = checkProps; } - return ( onChange(node, ctx)} + onChange={(_, ctx) => onChange(node, ctx)} className={labelClasses} stopLabelTrigger={expandOnClickNode && !!node.children} {...checkboxProps} diff --git a/packages/components/tree/_example/lazy.tsx b/packages/components/tree/_example/lazy.tsx index f45bfea118..66d5ce8997 100644 --- a/packages/components/tree/_example/lazy.tsx +++ b/packages/components/tree/_example/lazy.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { Tree } from 'tdesign-react'; +import React, { useState } from 'react'; +import { Space, Switch, Tree } from 'tdesign-react'; import type { TreeProps } from 'tdesign-react'; const items = [ @@ -14,6 +14,9 @@ const items = [ ]; export default () => { + const [checkable, setCheckable] = useState(true); + const [strictly, setStrictly] = useState(false); + const load: TreeProps['load'] = (node) => new Promise((resolve) => { setTimeout(() => { @@ -38,5 +41,23 @@ export default () => { console.log('on load:', state); }; - return ; + return ( + + + 可选: setCheckable(value)} /> + + + 严格模式: setStrictly(value)} /> + + + + ); }; diff --git a/packages/components/tree/_example/operations.tsx b/packages/components/tree/_example/operations.tsx index afe313c5d8..84f6ce1332 100644 --- a/packages/components/tree/_example/operations.tsx +++ b/packages/components/tree/_example/operations.tsx @@ -8,6 +8,7 @@ const items = [ }, { value: 'node2', + disabled: true, }, ]; @@ -21,6 +22,7 @@ export default () => { const [expandParent, setExpandParent] = useState(false); const [filterText, setFilterText] = useState(''); const [activeIds, setActiveIds] = useState([]); + const [checkStrictly, setCheckStrictly] = useState(false); const getLabelContent = (node: TreeNodeModel) => { const pathNodes = node.getPath(); @@ -114,6 +116,22 @@ export default () => { } }; + const canToggleDisable = (node: TreeNodeModel) => { + const parent = node.getParent?.(); + const isCheckStrictly = false; // 默认关闭 + if (!isCheckStrictly && parent?.disabled) { + return false; // 父节点被禁用时,子节点状态不支持手动改变 + } + return true; + }; + + const toggleDisable = (node: TreeNodeModel) => { + treeRef.current.setItem(node.value, { + disabled: !node.disabled, + }); + console.log(treeRef.current.getItems(node.value)); + }; + const remove = (node: TreeNodeModel) => { treeRef.current.remove(node.value); }; @@ -129,6 +147,16 @@ export default () => { + @@ -291,6 +319,10 @@ export default () => { + + 严格模式 + value={checkStrictly} onChange={setCheckStrictly} /> + 允许多个节点同时高亮 value={activeMultiple} onChange={setActiveMultiple} /> @@ -316,7 +348,7 @@ export default () => { expandAll activable checkable - checkStrictly + checkStrictly={checkStrictly} line allowFoldNodeOnFilter data={items} diff --git a/packages/components/tree/hooks/useStore.ts b/packages/components/tree/hooks/useStore.ts index ec93d224b4..79128f66cd 100644 --- a/packages/components/tree/hooks/useStore.ts +++ b/packages/components/tree/hooks/useStore.ts @@ -29,6 +29,7 @@ export function useStore( activeMultiple, actived, disabled, + disableCheck, draggable, checkable, value, @@ -109,6 +110,7 @@ export function useStore( expandMutex, expandParent, disabled, + disableCheck, draggable, load, lazy, @@ -185,6 +187,7 @@ export function useStore( activable, activeMultiple, disabled, + disableCheck, checkable, draggable, checkStrictly, @@ -201,6 +204,7 @@ export function useStore( draggable, checkable, disabled, + disableCheck, expandAll, expandLevel, expandMutex, diff --git a/packages/tdesign-react/CHANGELOG.md b/packages/tdesign-react/CHANGELOG.md index 38818a2eb5..a6a0bea70a 100644 --- a/packages/tdesign-react/CHANGELOG.md +++ b/packages/tdesign-react/CHANGELOG.md @@ -92,9 +92,11 @@ spline: explain ### 🐞 Bug Fixes - `Tree`: @RylanBot ([#3756](https://github.com/Tencent/tdesign-react/pull/3756)) - 修正节点属性 `date-target` 单词拼写为 `data-target`,之前有使用该属性的业务请注意此变更 ⚠️ - - 修复拖拽后展开收起图标展示异常的问题 + - 修复拖拽后展开收起图标展示异常的问题 - `MessagePlugin`: 修复 `content` 为 `''` / `undefined` / `null` 时产生的报错 @RylanBot ([#3778](https://github.com/Tencent/tdesign-react/pull/3778)) -- `Table`: 修复未开启 `` 时,`Loading` 挂载导致的页面闪烁问题 @RylanBot ([#3775](https://github.com/Tencent/tdesign-react/pull/3775)) +- `Table`: + - 修复未开启 `` 时,`Loading` 挂载导致的页面闪烁问题 @RylanBot ([#3775](https://github.com/Tencent/tdesign-react/pull/3775)) + - 修复 `size='small'` 的 `firstFullRow` 尺寸比 `size='medium'` 大的异常 ([#common2253](https://github.com/Tencent/tdesign-common/pull/2253)) - `Upload`: 修复拖拽模式下 `status` 更新错误 @RSS1102 ([#3801](https://github.com/Tencent/tdesign-react/pull/3801)) - `Input`: 修复在开启 `readonly` 或者禁用 `allowInput` 情况下没有触发 `onFocus` 和 `onBlur` 的问题 @RylanBot ([#3800](https://github.com/Tencent/tdesign-react/pull/3800)) - `Cascader`: diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index dbcc0cce2e..698fb60d77 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -144161,9 +144161,78 @@ exports[`csr snapshot test > csr test packages/components/tree/_example/label.ts exports[`csr snapshot test > csr test packages/components/tree/_example/lazy.tsx 1`] = `
- 暂无数据 +
+
+
+ 可选: +
+
+ +
+
+
+
+
+
+ 严格模式: +
+
+ +
+
+
+
+
+ 暂无数据 +
+
`; @@ -144307,6 +144376,38 @@ exports[`csr snapshot test > csr test packages/components/tree/_example/operatio class="t-space t-space-vertical" style="gap: 16px;" > +
+
+
+ + 严格模式 + +
+
+ +
+
+
@@ -150705,13 +150806,13 @@ exports[`ssr snapshot test > ssr test packages/components/tree/_example/icon.tsx exports[`ssr snapshot test > ssr test packages/components/tree/_example/label.tsx 1`] = `"
暂无数据
"`; -exports[`ssr snapshot test > ssr test packages/components/tree/_example/lazy.tsx 1`] = `"
暂无数据
"`; +exports[`ssr snapshot test > ssr test packages/components/tree/_example/lazy.tsx 1`] = `"
可选:
严格模式:
暂无数据
"`; exports[`ssr snapshot test > ssr test packages/components/tree/_example/line.tsx 1`] = `"
暂无数据

render

暂无数据
"`; exports[`ssr snapshot test > ssr test packages/components/tree/_example/load.tsx 1`] = `"
暂无数据
"`; -exports[`ssr snapshot test > ssr test packages/components/tree/_example/operations.tsx 1`] = `"
允许多个节点同时高亮
插入节点使用高亮节点
子节点展开触发父节点展开
filter:
暂无数据
* 相关信息通过控制台输出
"`; +exports[`ssr snapshot test > ssr test packages/components/tree/_example/operations.tsx 1`] = `"
严格模式
允许多个节点同时高亮
插入节点使用高亮节点
子节点展开触发父节点展开
filter:
暂无数据
* 相关信息通过控制台输出
"`; exports[`ssr snapshot test > ssr test packages/components/tree/_example/state.tsx 1`] = `"

state:

暂无数据

api:

"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index 7c57345cd1..235fce39de 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -1212,13 +1212,13 @@ exports[`ssr snapshot test > ssr test packages/components/tree/_example/icon.tsx exports[`ssr snapshot test > ssr test packages/components/tree/_example/label.tsx 1`] = `"
暂无数据
"`; -exports[`ssr snapshot test > ssr test packages/components/tree/_example/lazy.tsx 1`] = `"
暂无数据
"`; +exports[`ssr snapshot test > ssr test packages/components/tree/_example/lazy.tsx 1`] = `"
可选:
严格模式:
暂无数据
"`; exports[`ssr snapshot test > ssr test packages/components/tree/_example/line.tsx 1`] = `"
暂无数据

render

暂无数据
"`; exports[`ssr snapshot test > ssr test packages/components/tree/_example/load.tsx 1`] = `"
暂无数据
"`; -exports[`ssr snapshot test > ssr test packages/components/tree/_example/operations.tsx 1`] = `"
允许多个节点同时高亮
插入节点使用高亮节点
子节点展开触发父节点展开
filter:
暂无数据
* 相关信息通过控制台输出
"`; +exports[`ssr snapshot test > ssr test packages/components/tree/_example/operations.tsx 1`] = `"
严格模式
允许多个节点同时高亮
插入节点使用高亮节点
子节点展开触发父节点展开
filter:
暂无数据
* 相关信息通过控制台输出
"`; exports[`ssr snapshot test > ssr test packages/components/tree/_example/state.tsx 1`] = `"

state:

暂无数据

api:

"`;