Skip to content

Commit

Permalink
feat(Tree): support set Indeterminate (#1993)
Browse files Browse the repository at this point in the history
* feat(Tree): support set indeterminate

* feat(Tree): support set indeterminate

* chore: revert change

* chore: revert change
  • Loading branch information
uyarn authored Dec 19, 2024
1 parent b0815e9 commit 53786c5
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 18 deletions.
2 changes: 1 addition & 1 deletion js/date-picker/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ export function flagActive(data: any[], { ...args }: FlagActiveOptions) {
const _item = item;

if (multiple) {
_item.active = (value as DateValue[]).some((val) => isSame(dayjs(val).toDate(), _item.value, type) && !_item.additional);
_item.active = (value as DateValue[])?.some?.((val) => isSame(dayjs(val).toDate(), _item.value, type) && !_item.additional);
} else {
_item.active = start && isSame(item.value, start, type) && !_item.additional;
}
Expand Down
75 changes: 64 additions & 11 deletions js/tree-v1/tree-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@ import {
TypeTreeNodeModel,
TypeTreeNodeData,
} from './types';
import {
createNodeModel,
updateNodeModel,
} from './tree-node-model';
import { createNodeModel, updateNodeModel } from './tree-node-model';
import log from '../log';

const { hasOwnProperty } = Object.prototype;
Expand All @@ -35,7 +32,12 @@ export const setableStatus: Record<string, boolean | null> = {

export const setableProps = Object.keys(setableStatus);

export const syncableProps = [...setableProps, 'actived', 'expanded', 'checked'];
export const syncableProps = [
...setableProps,
'actived',
'expanded',
'checked',
];

export const privateKey = '__tdesign_id__';

Expand Down Expand Up @@ -109,6 +111,8 @@ export class TreeNode {
// 节点在视图上实际的选中态
public checked: boolean;

public isIndeterminateManual: boolean;

// 节点实际是否为半选状态
public indeterminate: boolean;

Expand All @@ -130,7 +134,7 @@ export class TreeNode {
public constructor(
tree: TreeStore,
data?: TypeTreeNodeData,
parent?: TreeNode,
parent?: TreeNode
) {
this.data = data;
this.tree = tree;
Expand Down Expand Up @@ -552,7 +556,11 @@ export class TreeNode {
const { tree } = this;
const keys = Object.keys(item);
keys.forEach((key) => {
if (hasOwnProperty.call(setableStatus, key) || key === 'label' || key === 'disabled') {
if (
hasOwnProperty.call(setableStatus, key)
|| key === 'label'
|| key === 'disabled'
) {
this[key] = item[key];
}
});
Expand Down Expand Up @@ -737,7 +745,12 @@ export class TreeNode {
const { tree } = this;
const { hasFilter, config } = tree;
const { disabled, allowFoldNodeOnFilter } = config;
if (hasFilter && !allowFoldNodeOnFilter && this.vmIsLocked && !this.vmIsRest) {
if (
hasFilter
&& !allowFoldNodeOnFilter
&& this.vmIsLocked
&& !this.vmIsRest
) {
return true;
}
let state = disabled;
Expand Down Expand Up @@ -1124,6 +1137,7 @@ export class TreeNode {
...opts,
};
let map = tree.checkedMap;

if (!options.directly) {
map = new Map(tree.checkedMap);
}
Expand Down Expand Up @@ -1168,6 +1182,41 @@ export class TreeNode {
});
}
}
this.isIndeterminateManual = false;

return tree.getChecked(map);
}

public setIndeterminate(indeterminate: boolean, opts?: TypeSettingOptions) {
const { tree } = this;
const config = tree.config || {};
const options: TypeSettingOptions = {
// 为 true, 为 UI 操作,状态扩散受 disabled 影响
// 为 false, 为值操作, 状态扩散不受 disabled 影响
isAction: true,
// 为 true, 直接操作节点状态
// 为 false, 返回预期状态
directly: false,
...opts,
};
let map = tree.checkedMap;
if (!options.directly) {
map = new Map(tree.checkedMap);
}
if (!this.isCheckable()) {
// 当前节点非可选节点,则不可设置选中态
return tree.getChecked(map);
}
if (options.isAction && this.isDisabled()) {
// 对于 UI 动作,禁用时不可切换选中态
return tree.getChecked(map);
}
if (indeterminate === this.isIndeterminate()) {
// 值没有变更,则选中态无变化
return tree.getChecked(map);
}
this.indeterminate = indeterminate;
this.isIndeterminateManual = true;

return tree.getChecked(map);
}
Expand All @@ -1183,7 +1232,6 @@ export class TreeNode {
directly: false,
...opts,
};

// 碰到不可选节点,中断扩散
if (!this.isCheckable()) return;

Expand Down Expand Up @@ -1252,8 +1300,12 @@ export class TreeNode {
* 更新节点选中态
* @return void
*/
public updateChecked(): void {
const { tree, value } = this;
public updateChecked(from?: string): void {
const { tree, value, isIndeterminateManual } = this;
if (isIndeterminateManual && ['refresh'].includes(from)) {
return;
}

const { checkedMap } = tree;
this.checked = this.isChecked();
this.indeterminate = this.isIndeterminate();
Expand Down Expand Up @@ -1303,6 +1355,7 @@ export class TreeNode {
const relatedNodes = tree.getRelatedNodes([this.value]);
relatedNodes.forEach((node) => {
node.update();
if (node.isIndeterminateManual && node.indeterminate) return;
node.updateChecked();
});
}
Expand Down
31 changes: 25 additions & 6 deletions js/tree-v1/tree-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ export class TreeStore {
// 选中节点集合
public checkedMap: TypeIdMap;

// 设置半选集合
public indeterminateMap: TypeIdMap;

// 展开节点的集合
public expandedMap: TypeIdMap;

Expand Down Expand Up @@ -138,6 +141,7 @@ export class TreeStore {
this.expandedMap = new Map();
this.checkedMap = new Map();
this.updatedMap = new Map();
this.indeterminateMap = new Map();
this.filterMap = new Map();
this.prevFilter = null;
// 这个计时器确保频繁的 update 事件被归纳为1次完整数据更新后的触发
Expand Down Expand Up @@ -272,7 +276,7 @@ export class TreeStore {
*/
public getNodes(
item?: TypeTargetNode,
options?: TypeTreeFilterOptions,
options?: TypeTreeFilterOptions
): TreeNode[] {
let nodes: TreeNode[] = [];
let val: TreeNodeValue = '';
Expand Down Expand Up @@ -355,7 +359,7 @@ export class TreeStore {
*/
private parseNodeData(
para: TreeNodeValue | TreeNode | TypeTreeNodeData,
item: TypeTreeNodeData | TreeNode,
item: TypeTreeNodeData | TreeNode
) {
let value: TreeNodeValue = '';
let node = null;
Expand Down Expand Up @@ -398,7 +402,7 @@ export class TreeStore {
*/
public appendNodes(
para: TypeTargetNode | TypeTreeNodeData,
item?: TypeTreeNodeData | TreeNode,
item?: TypeTreeNodeData | TreeNode
): void {
const spec = this.parseNodeData(para, item);
if (spec.data) {
Expand Down Expand Up @@ -476,7 +480,7 @@ export class TreeStore {
// 所以遍历 nodeMap 确保初始化阶段 refreshState 方法也可以触发全部节点的更新
nodeMap.forEach((node) => {
node.update();
node.updateChecked();
node.updateChecked('refresh');
});
}

Expand Down Expand Up @@ -577,6 +581,21 @@ export class TreeStore {
this.setActived(list);
}

public replaceIndeterminate(list: TreeNodeValue[]): void {
this.setIndeterminate(list);
}

public setIndeterminate(indeterminate: TreeNodeValue[]): void {
indeterminate.forEach((val) => {
this.indeterminateMap.set(val, true);
const node = this.getNode(val);
if (node) {
node.setIndeterminate(true);
node.update();
}
});
}

/**
* 设置激活态
* @param {string[]} list 目标节点值数组
Expand Down Expand Up @@ -796,7 +815,7 @@ export class TreeStore {
public updateAll(): void {
this.nodeMap.forEach((node) => {
node.update();
node.updateChecked();
node.updateChecked('refresh');
});
}

Expand Down Expand Up @@ -834,7 +853,7 @@ export class TreeStore {
*/
public getRelatedNodes(
list: TreeNodeValue[],
options?: TypeRelatedNodesOptions,
options?: TypeRelatedNodesOptions
): TreeNode[] {
const conf = {
// 默认倒序排列,从底层节点开始遍历
Expand Down

0 comments on commit 53786c5

Please sign in to comment.