From d0ba4ff4568ae2944c60fd421242435593a9b825 Mon Sep 17 00:00:00 2001 From: 07akioni <07akioni2@gmail.com> Date: Sun, 19 Sep 2021 16:41:34 +0800 Subject: [PATCH] feat(tree, tree-select): indeterminate-keys & on-update:indeterminate-keys prop --- CHANGELOG.en-US.md | 4 ++++ CHANGELOG.zh-CN.md | 4 ++++ .../demos/enUS/index.demo-entry.md | 4 +++- .../demos/zhCN/index.demo-entry.md | 4 +++- src/tree-select/src/TreeSelect.tsx | 24 +++++++++++++++++++ src/tree/demos/enUS/index.demo-entry.md | 6 +++-- src/tree/demos/zhCN/index.demo-entry.md | 4 +++- src/tree/src/Tree.tsx | 21 +++++++++++++++- 8 files changed, 65 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.en-US.md b/CHANGELOG.en-US.md index cbeb138f6..8e414a64e 100644 --- a/CHANGELOG.en-US.md +++ b/CHANGELOG.en-US.md @@ -14,6 +14,10 @@ - `n-spin` add `description` prop and slot. - `n-anchor` add `variant` prop. - `n-upload` add `abstract` prop, add `n-upload-trigger` 和 `n-upload-file-list` component, closes [#1102](https://github.com/TuSimple/naive-ui/issues/1102). +- `n-tree` add `indeterminate-keys` prop. +- `n-tree-select` add `indeterminate-keys` prop. +- `n-tree` add `on-update:indeterminate-keys` prop. +- `n-tree-select` add `on-update:indeterminate-keys` prop. ### Fixes diff --git a/CHANGELOG.zh-CN.md b/CHANGELOG.zh-CN.md index 240d67da5..08c9e5c3b 100644 --- a/CHANGELOG.zh-CN.md +++ b/CHANGELOG.zh-CN.md @@ -14,6 +14,10 @@ - `n-spin` 新增 `description` prop 和 slot - `n-anchor` 新增 `variant` 属性 - `n-upload` 新增 `abstract` 属性,新增 `n-upload-trigger` 和 `n-upload-file-list` 组件,关闭 [#1102](https://github.com/TuSimple/naive-ui/issues/1102) +- `n-tree` 新增 `indeterminate-keys` 属性 +- `n-tree-select` 新增 `indeterminate-keys` 属性 +- `n-tree` 新增 `on-update:indeterminate-keys` 属性 +- `n-tree-select` 新增 `on-update:indeterminate-keys` 属性 ### Fixes diff --git a/src/tree-select/demos/enUS/index.demo-entry.md b/src/tree-select/demos/enUS/index.demo-entry.md index 558e06856..362bfe2ed 100644 --- a/src/tree-select/demos/enUS/index.demo-entry.md +++ b/src/tree-select/demos/enUS/index.demo-entry.md @@ -31,6 +31,7 @@ debug | default-expanded-keys | `Array` | `[]` | Expanded keys by default. | | disabled | `boolean` | `false` | Whether to disable the tree select. | | expanded-keys | `Array` | `undefined` | Expanded keys. | +| indeterminate-keys | `Array` | `undefined` | Indeterminate keys of the tree. | | filterable | `boolean` | `false` | Whether the tree select is disabled. | | filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | Filter function. | | key-field | `string` | `'key'` | The key field in `TreeSelectOption`. | @@ -45,8 +46,9 @@ debug | value | `string \| number \| Array \| null>` | `undefined` | Selected key (or keys when multiple). | | virtual-scroll | `boolean` | `true` | Whether to enable virtual scroll. | | on-blur | `(e: FocusEvent) => void` | `undefined` | Callback on blur. | -| on-update:expanded-keys | `(value: Array) => void` | `undefined` | Callback on expanded keys updated. | | on-focus | `(e: FocusEvent) => void` | `undefined` | Callback on focus. | +| on-update:expanded-keys | `(value: Array) => void` | `undefined` | Callback on expanded keys updated. | +| on-update:indeterminate-keys | `(keys: Array) => void` | `undefined` | Callback function when node indeterminate options change. | | on-update:value | `(value: string \| number \| Array \| null, option: TreeSelectOption \| null \| Array) => void` | `undefined` | Callback on value updated. | ### TreeSelectOption Properties diff --git a/src/tree-select/demos/zhCN/index.demo-entry.md b/src/tree-select/demos/zhCN/index.demo-entry.md index a7b7bf0f6..09e271c69 100644 --- a/src/tree-select/demos/zhCN/index.demo-entry.md +++ b/src/tree-select/demos/zhCN/index.demo-entry.md @@ -31,6 +31,7 @@ debug | default-expanded-keys | `Array` | `[]` | 默认展开节点的 key | | disabled | `boolean` | `false` | 是否禁用 | | expanded-keys | `Array` | `undefined` | 展开节点的 key | +| indeterminate-keys | `string \| number` | `undefined` | 部分选中选项的 key | | filterable | `boolean` | `false` | 是否可过滤 | | filter | `(pattern: string, option: TreeSelectOption) => boolean` | - | 过滤器函数 | | key-field | `string` | `'key'` | 替代 `TreeSelectOption` 中的 key 字段名 | @@ -46,8 +47,9 @@ debug | value | `string \| number \| Array \| null>` | `undefined` | 选中的 key | | virtual-scroll | `boolean` | `true` | 是否开启虚拟滚动 | | on-blur | `(e: FocusEvent) => void` | `undefined` | Blur 时的回调 | -| on-update:expanded-keys | `(value: Array) => void` | `undefined` | 展开节点更新的回调 | | on-focus | `(e: FocusEvent) => void` | `undefined` | Focus 时的回调 | +| on-update:expanded-keys | `(value: Array) => void` | `undefined` | 展开节点更新的回调 | +| on-update:indeterminate-keys | `(keys: Array) => void` | `undefined` | 节点部分勾选项发生变化时的回调函数 | | on-update:value | `(value: string \| number \| Array \| null, option: TreeSelectOption \| null \| Array) => void` | `undefined` | 更新值的回调 | ### TreeSelectOption Properties diff --git a/src/tree-select/src/TreeSelect.tsx b/src/tree-select/src/TreeSelect.tsx index d56a4dee5..9e082cf72 100644 --- a/src/tree-select/src/TreeSelect.tsx +++ b/src/tree-select/src/TreeSelect.tsx @@ -362,6 +362,21 @@ export default defineComponent({ nTriggerFormInput() nTriggerFormChange() } + function doUpdateIndeterminateKeys ( + value: string | number | Array | null, + option: TreeSelectOption | null | Array + ): void { + const { + onUpdateIndeterminateKeys, + 'onUpdate:indeterminateKeys': _onUpdateIndeterminateKeys + } = props + if (onUpdateIndeterminateKeys) { + call(onUpdateIndeterminateKeys as OnUpdateValueImpl, value, option) + } + if (_onUpdateIndeterminateKeys) { + call(_onUpdateIndeterminateKeys as OnUpdateValueImpl, value, option) + } + } function doUpdateExpandedKeys (keys: Key[]): void { const { onUpdateExpandedKeys, @@ -455,6 +470,11 @@ export default defineComponent({ } } } + function handleUpdateIndeterminateKeys (keys: Key[]): void { + if (props.checkable && props.multiple) { + doUpdateIndeterminateKeys(keys, getOptionsByKeys(keys)) + } + } function handleTriggerFocus (e: FocusEvent): void { if (menuElRef.value?.contains(e.relatedTarget as Element)) return focusedRef.value = true @@ -635,6 +655,7 @@ export default defineComponent({ handleMenuClickoutside, handleUpdateSelectedKeys, handleUpdateCheckedKeys, + handleUpdateIndeterminateKeys, handleTriggerFocus, handleTriggerBlur, handleMenuFocusin, @@ -782,6 +803,9 @@ export default defineComponent({ onUpdateCheckedKeys={ this.handleUpdateCheckedKeys } + onUpdateIndeterminateKeys={ + this.handleUpdateIndeterminateKeys + } onUpdateExpandedKeys={ this.doUpdateExpandedKeys } diff --git a/src/tree/demos/enUS/index.demo-entry.md b/src/tree/demos/enUS/index.demo-entry.md index 96bf22a53..b6e1ccaf4 100644 --- a/src/tree/demos/enUS/index.demo-entry.md +++ b/src/tree/demos/enUS/index.demo-entry.md @@ -34,7 +34,7 @@ batch-render | check-strategy | `string` | `'all'` | The strategy of setting checked callback's keys argument. `all` means setting all checked node. `parent` means setting all checked parent node of whom all child node are checked. `child` means setting all child node. | | checkable | `boolean` | `false` | Whether to display the selection box, you need to set `cascade` to `true`. | | children-field | `string` | `'children'` | The children field in `TreeOption`. | -| checked-keys | `Array` | `undefined` | If set, checked status will work in controlled manner. | +| checked-keys | `Array` | `undefined` | Checked keys of the tree. | | data | `Array` | `[]` | The node data of the tree. Reset `data` will cause clearing of some uncontrolled status. If you need to modify data, you'd better make tree work in a controlled manner. | | default-checked-keys | `Array` | `[]` | Multiple options selected by default. | | default-expand-all | `boolean` | `false` | Expand all options. | @@ -44,6 +44,7 @@ batch-render | expand-on-dragenter | `boolean` | `true` | Whether to expand nodes after dragenter. | | expanded-keys | `Array` | `undefined` | If set, expanded status will work in controlled manner. | | filter | `(node: TreeOption) => boolean` | `undefined` | A simple string based filter. | +| indeterminate-keys | `Array` | `undefined` | Indeterminate keys of the tree. | | key-field | `string` | `'key'` | The key field in `TreeOption`. | | label-field | `string` | `'label'` | The label field in `TreeOption`. | | leaf-only | `boolean` | `false` | Whether to open or not, only the bottom tree node is optional. | @@ -62,7 +63,8 @@ batch-render | on-dragleave | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | Drag a node, the callback function after the node leaves other nodes. | | on-dragstart | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | Callback function to start dragging a certain node. | | on-drop | `(data: { node: TreeOption, dragNode: TreeOption, dropPosition: 'before' \| 'inside' \| 'after', event: DragEvent }) => void` | `undefined` | The callback function after the node completes the dragging action. | -| on-update:checked-keys | `(keys: Array) => void` | `undefined` | Callback function when node multiple options change. | +| on-update:checked-keys | `(keys: Array) => void` | `undefined` | Callback function when node checked options change. | +| on-update:indeterminate-keys | `(keys: Array) => void` | `undefined` | Callback function when node indeterminate options change. | | on-update:expanded-keys | `(keys: Array) => void` | `undefined` | The callback function when the node expansion item changes. | | on-update:selected-keys | `(keys: Array) => void` | `undefined` | The callback function when the selected item of the node changes. | diff --git a/src/tree/demos/zhCN/index.demo-entry.md b/src/tree/demos/zhCN/index.demo-entry.md index 853bd5a0e..b470f2bba 100644 --- a/src/tree/demos/zhCN/index.demo-entry.md +++ b/src/tree/demos/zhCN/index.demo-entry.md @@ -44,6 +44,7 @@ batch-render | expand-on-dragenter | `boolean` | `true` | 是否在拖入后展开节点 | | expanded-keys | `Array` | `undefined` | 如果设定则展开受控 | | filter | `(node: TreeOption) => boolean` | `undefined` | 一个简单的字符串过滤算法 | +| indeterminate-keys | `string \| number` | `undefined` | 部分选中选项的 key | | key-field | `string` | `'key'` | 替代 `TreeOption` 中的 key 字段名 | | label-field | `string` | `'label'` | 替代 `TreeOption` 中的 label 字段名 | | leaf-only | `boolean` | `false` | 是否开启仅末层树节点可选 | @@ -62,7 +63,8 @@ batch-render | on-dragleave | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | 拖拽一个节点,该节点离开其它节点后的回调函数 | | on-dragstart | `(data: { node: TreeOption, event: DragEvent }) => void` | `undefined` | 开始拖拽某一个节点的回调函数 | | on-drop | `(data: { node: TreeOption, dragNode: TreeOption, dropPosition: 'before' \| 'inside' \| 'after', event: DragEvent }) => void` | `undefined` | 节点完成拖拽动作后的回调函数 | -| on-update:checked-keys | `(keys: Array) => void` | `undefined` | 节点多选项发生变化时的回调函数 | +| on-update:checked-keys | `(keys: Array) => void` | `undefined` | 节点勾选项发生变化时的回调函数 | +| on-update:indeterminate-keys | `(keys: Array) => void` | `undefined` | 节点部分勾选项发生变化时的回调函数 | | on-update:expanded-keys | `(keys: Array) => void` | `undefined` | 节点展开项发生变化时的回调函数 | | on-update:selected-keys | `(keys: Array) => void` | `undefined` | 节点选中项发生变化时的回调函数 | diff --git a/src/tree/src/Tree.tsx b/src/tree/src/Tree.tsx index 225bc3511..114a9e855 100644 --- a/src/tree/src/Tree.tsx +++ b/src/tree/src/Tree.tsx @@ -99,6 +99,13 @@ export const treeSharedProps = { type: Array as PropType, default: () => [] }, + indeterminateKeys: Array as PropType, + onUpdateIndeterminateKeys: [Function, Array] as PropType< + MaybeArray<(value: Key[]) => void> + >, + 'onUpdate:indeterminateKeys': [Function, Array] as PropType< + MaybeArray<(value: Key[]) => void> + >, onUpdateExpandedKeys: [Function, Array] as PropType< MaybeArray<(value: Key[]) => void> >, @@ -275,6 +282,8 @@ export default defineComponent({ return checkedStatusRef.value.checkedKeys }) const displayedIndeterminateKeysRef = computed(() => { + const { indeterminateKeys } = props + if (indeterminateKeys !== undefined) return indeterminateKeys return checkedStatusRef.value.indeterminateKeys }) const uncontrolledSelectedKeysRef = ref( @@ -511,6 +520,15 @@ export default defineComponent({ if (onUpdateCheckedKeys) call(onUpdateCheckedKeys, value) if (_onUpdateCheckedKeys) call(_onUpdateCheckedKeys, value) } + function doUpdateIndeterminateKeys (value: Key[]): void { + const { + 'onUpdate:indeterminateKeys': _onUpdateIndeterminateKeys, + onUpdateIndeterminateKeys + } = props + uncontrolledCheckedKeysRef.value = value + if (_onUpdateIndeterminateKeys) call(_onUpdateIndeterminateKeys, value) + if (onUpdateIndeterminateKeys) call(onUpdateIndeterminateKeys, value) + } function doUpdateSelectedKeys (value: Key[]): void { const { 'onUpdate:selectedKeys': _onUpdateSelectedKeys, @@ -571,7 +589,7 @@ export default defineComponent({ if (props.disabled || node.disabled) { return } - const { checkedKeys } = dataTreeMateRef.value![ + const { checkedKeys, indeterminateKeys } = dataTreeMateRef.value![ checked ? 'check' : 'uncheck' ](node.key, displayedCheckedKeysRef.value, { cascade: props.cascade, @@ -579,6 +597,7 @@ export default defineComponent({ checkStrategy: mergedCheckStrategyRef.value }) doUpdateCheckedKeys(checkedKeys) + doUpdateIndeterminateKeys(indeterminateKeys) } function toggleExpand (key: Key): void { if (props.disabled) return