Skip to content

Commit

Permalink
feat(pro: tree): add pro tree component
Browse files Browse the repository at this point in the history
  • Loading branch information
liuzaijiang committed May 9, 2022
1 parent 84e8e17 commit 840982e
Show file tree
Hide file tree
Showing 35 changed files with 814 additions and 18 deletions.
4 changes: 3 additions & 1 deletion packages/components/tree-select/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,11 @@ order: 0
| `@tree-select-option-selected-background-color` | `tint(@color-primary, 90%)` | - | - |
| `@tree-select-option-selected-font-weight` | `@font-weight-xl` | - | - |
| `@tree-select-option-container-zindex` | `@zindex-l4-3` | - | - |
| `@tree-select-option-container-padding` | `@spacing-sm` | `8px 12px` | - |
| `@tree-select-option-container-padding` | `@spacing-sm` | `8px 0` | - |
| `@tree-select-option-container-background-color` | `@background-color-component` | - | - |
| `@tree-select-option-container-border-radius` | `@border-radius-sm` | - | - |
| `@tree-select-option-container-box-shadow` | `@shadow-bottom-md` | - | - |
| `@tree-select-option-container-search-wrapper-padding` | `0 @spacing-md @spacing-md @spacing-md` | - | - |
| `@tree-select-option-container-tree-node-padding` | `0 0 0 @spacing-xs` | - | - |
| `@tree-select-border-radius` | - | `@border-radius-sm` | - |
<!--- insert less variable end --->
19 changes: 19 additions & 0 deletions packages/components/tree/__tests__/tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,25 @@ describe('Tree', () => {
expect(allNodes[1].classes()).toContain('ix-tree-node-expanded')
})

test('expandAll and collapseAll work', async () => {
const onUpdateExpandedKeys = vi.fn()
const wrapper = TreeMount({
props: {
dataSource: simpleDataSource,
expandedKeys: ['0'],
'onUpdate:expandedKeys': onUpdateExpandedKeys,
},
})

await wrapper.vm.collapseAll()

expect(onUpdateExpandedKeys).toBeCalledWith([])

await wrapper.vm.expandAll()

expect(onUpdateExpandedKeys).toBeCalledWith(['0'])
})

test('v-model:selectedKeys work', async () => {
const onUpdateSelectedKeys = vi.fn()
const wrapper = TreeMount({
Expand Down
8 changes: 5 additions & 3 deletions packages/components/tree/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ export type TreeDropType = 'before' | 'inside' | 'after'
| 名称 | 说明 | 参数类型 | 备注 |
| --- | --- | --- | --- |
| `blur` | 失去焦点 | - | - |
| `collapseAll` | 收起所有节点 | - | - |
| `expandAll` | 展开所有节点 | - | - |
| `focus` | 获取焦点 | - | - |
| `scrollTo` | 滚动到指定位置 | `(option?: number \| VirtualScrollToOptions) => void` | 仅 `virtual` 模式下可用 |
Expand All @@ -126,12 +128,12 @@ export type TreeDropType = 'before' | 'inside' | 'after'
| `@tree-node-hover-background-color` | `@color-graphite-l50` | - | - |
| `@tree-node-selected-color` | `@color-graphite-d40` | `@color-primary` | - |
| `@tree-node-selected-background-color` | `@color-graphite-l40` | `@color-white` | - |
| `@tree-node-line-width` | `1px` | - | - |
| `@tree-node-line-border` | `1px dashed @color-graphite` | - | - |
| `@tree-node-line-size` | `1px` | - | - |
| `@tree-node-line-color` | `@color-graphite` | - | - |
| `@tree-node-padding-vertical` | `(@spacing-sm / 2)` | `0` | - |
| `@tree-node-checkbox-margin` | `0 @spacing-xs 0 @spacing-xs` | - | - |
| `@tree-node-content-height` | `@height-sm` | `@height-md` | - |
| `@tree-node-content-label-padding` | `0 @spacing-xs` | - | - |
| `@tree-node-content-label-highlight-color` | `@color-primary` | - | - |
| `@tree-node-checkbox-margin` | `0 @spacing-xs 0 (@tree-node-content-height / 2 - @tree-icon-font-size / 2)` | - | - |
| `@tree-expand-icon-color` | `@color-graphite` | - | - |
<!--- insert less variable end --->
1 change: 1 addition & 0 deletions packages/components/tree/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type {
TreeComponent,
TreePublicProps as TreeProps,
TreeNode,
TreeNodeDisabled,
TreeCustomAdditional,
TreeDroppable,
TreeDroppableOptions,
Expand Down
8 changes: 7 additions & 1 deletion packages/components/tree/src/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,13 @@ export default defineComponent({
virtualScrollRef?.value?.scrollTo(option)
}

expose({ focus, blur, scrollTo })
expose({
focus,
blur,
expandAll: expandableContext.expandAll,
collapseAll: expandableContext.collapseAll,
scrollTo,
})

const handleScrolledChange = (startIndex: number, endIndex: number, visibleNodes: MergedNode[]) => {
callEmit(
Expand Down
22 changes: 21 additions & 1 deletion packages/components/tree/src/composables/useExpandable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import { convertMergeNodes, convertMergedNodeMap } from './useDataSource'
export interface ExpandableContext {
expandIcon: ComputedRef<string | string[]>
expandedKeys: WritableComputedRef<VKey[]>
expandAll: () => void
collapseAll: () => void
handleExpand: (key: VKey, rawNode: TreeNode) => void
loadingKeys: Ref<VKey[]>
}
Expand Down Expand Up @@ -110,9 +112,27 @@ export function useExpandable(
callChange(mergedNodeMap, newKeys, onExpandedChange)
}

const expandAll = () => {
const expandAllKeys: VKey[] = []
const expendedAllNodes: TreeNode[] = []
mergedNodeMap.value.forEach(node => {
if (!node.isLeaf) {
expandAllKeys.push(node.key)
expendedAllNodes.push(node.rawNode)
}
})
callEmit(props.onExpandedChange, expandAllKeys, expendedAllNodes)
setExpandedKeys(expandAllKeys)
}

const collapseAll = () => {
callEmit(props.onExpandedChange, [], [])
setExpandedKeys([])
}

if (searchedKeys.value.length) {
setExpandWithSearch(searchedKeys.value)
}

return { expandIcon, expandedKeys, handleExpand, loadingKeys }
return { expandIcon, expandedKeys, expandAll, collapseAll, handleExpand, loadingKeys }
}
3 changes: 2 additions & 1 deletion packages/components/tree/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ export type TreePublicProps = Omit<ExtractPublicPropTypes<typeof treeProps>, 'no
export interface TreeBindings {
focus: (options?: FocusOptions) => void
blur: () => void
collapseAll: () => void
expandAll: () => void
scrollTo: VirtualScrollToFn
setExpandAll: (isAll: boolean) => void
}
export type TreeComponent = DefineComponent<Omit<HTMLAttributes, keyof TreePublicProps> & TreePublicProps, TreeBindings>
export type TreeInstance = InstanceType<DefineComponent<TreeProps, TreeBindings>>
Expand Down
5 changes: 2 additions & 3 deletions packages/components/tree/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@
&-top-line {
position: absolute;
height: (@tree-node-content-height / 2 - 4);
top: -6px;
/* stylelint-disable function-no-unknown */
top: -(@tree-node-content-height / 4 - 4);
right: 50%;
.vertical-line();
}
Expand All @@ -65,7 +66,6 @@
position: absolute;
top: 50%;
width: (@tree-node-content-height / 4);
margin-left: 4px;
.horizontal-line();

content: ' ';
Expand Down Expand Up @@ -137,7 +137,6 @@
line-height: @tree-node-content-height;
text-align: center;
cursor: pointer;
margin-right: 4px;

&-noop {
cursor: default;
Expand Down
3 changes: 2 additions & 1 deletion packages/components/tree/style/themes/default.variable.less
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
@tree-node-line-color: @color-graphite;
@tree-node-padding-vertical: (@spacing-sm / 2);

@tree-node-checkbox-margin: 0 @spacing-xs 0 0;
@tree-node-content-height: @height-sm;
@tree-node-content-label-padding: 0 @spacing-xs;
@tree-node-content-label-highlight-color: @color-primary;

@tree-node-checkbox-margin: 0 @spacing-xs 0 (@tree-node-content-height / 2 - @tree-icon-font-size / 2);

@tree-expand-icon-color: @color-graphite;
8 changes: 7 additions & 1 deletion packages/pro/config/src/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { CommonConfig, GlobalConfig } from './types'
import type { CommonConfig, GlobalConfig, ProTree } from './types'

const common: CommonConfig = { prefixCls: 'ix-pro' }

const proTree: ProTree = {
clearIcon: 'close-circle',
expandIcon: ['minus-square', 'plus-square'],
}

export const defaultConfig: GlobalConfig = {
common,
proTree,
}
6 changes: 6 additions & 0 deletions packages/pro/config/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ export interface CommonConfig {
prefixCls: string
}

export interface ProTree {
clearIcon: string
expandIcon: string | string[]
}

export interface GlobalConfig {
// Common
common: CommonConfig
proTree: ProTree
}

export type GlobalConfigKey = keyof GlobalConfig
3 changes: 2 additions & 1 deletion packages/pro/default.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

@import './layout/style/themes/default.less';

@import './transfer/style/themes/default.less';
@import './transfer/style/themes/default.less';
@import './tree/style/themes/default.less';
4 changes: 3 additions & 1 deletion packages/pro/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import type { App, Directive } from 'vue'

import { IxProLayout, IxProLayoutSiderTrigger } from '@idux/pro/layout'
import { IxProTransfer } from '@idux/pro/transfer'
import { IxProTree } from '@idux/pro/tree'
import { version } from '@idux/pro/version'

const directives: Record<string, Directive> = {}

const components = [IxProLayout, IxProLayoutSiderTrigger, IxProTransfer]
const components = [IxProLayout, IxProLayoutSiderTrigger, IxProTransfer, IxProTree]

const install = (app: App): void => {
components.forEach(component => {
Expand All @@ -32,4 +33,5 @@ export { install, version }

export * from '@idux/pro/layout'
export * from '@idux/pro/transfer'
export * from '@idux/pro/tree'
export * from '@idux/pro/version'
3 changes: 2 additions & 1 deletion packages/pro/seer.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

@import './layout/style/themes/seer.less';

@import './transfer/style/themes/seer.less';
@import './transfer/style/themes/seer.less';
@import './tree/style/themes/seer.less';
3 changes: 2 additions & 1 deletion packages/pro/style/variable/prefix.less
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
@pro-layout-prefix: ~'@{idux-pro-prefix}-layout';

// Transfer
@pro-transfer-prefix: ~'@{idux-pro-prefix}-transfer';
@pro-transfer-prefix: ~'@{idux-pro-prefix}-transfer';
@pro-tree-prefix: ~'@{idux-pro-prefix}-tree';
19 changes: 19 additions & 0 deletions packages/pro/tree/__tests__/__snapshots__/proTree.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Vitest Snapshot v1

exports[`ProTree > render work 1`] = `
"<div class=\\"ix-pro-tree\\">
<div class=\\"ix-pro-tree-header-wrapper\\">
<!---->
<!---->
</div>
<div class=\\"ix-pro-tree-search-wrapper\\"><button class=\\"ix-button ix-button-icon-only ix-button-xs\\" type=\\"button\\" title=\\"收起全部\\"><i class=\\"ix-icon ix-icon-tree-unexpand\\" role=\\"img\\" aria-label=\\"tree-unexpand\\"></i></button><span class=\\"ix-input ix-input-sm ix-input-clearable ix-input-with-suffix\\"><!----><input class=\\"ix-input-inner\\"><span class=\\"ix-input-suffix\\"><i class=\\"ix-icon ix-icon-search\\" role=\\"img\\" aria-label=\\"search\\"></i></span><span class=\\"ix-input-clear\\"><i class=\\"ix-icon ix-icon-close-circle\\" role=\\"img\\" aria-label=\\"close-circle\\"></i></span></span></div>
<div class=\\"ix-tree ix-tree-blocked ix-tree-show-line\\" role=\\"tree\\">
<!----><input style=\\"width: 0px; height: 0px; display: flex; overflow: hidden; opacity: 0; border: 0px; padding: 0px; margin: 0px;\\" tabindex=\\"0\\" aria-label=\\"for screen reader\\">
<div class=\\"ix-empty\\">
<div class=\\"ix-empty-image\\"><i class=\\"ix-icon ix-icon-empty\\" role=\\"img\\" aria-label=\\"empty\\"></i></div>
<div class=\\"ix-empty-description\\">暂无数据</div>
<!---->
</div>
</div>
</div>"
`;
25 changes: 25 additions & 0 deletions packages/pro/tree/__tests__/proTree.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { MountingOptions, mount } from '@vue/test-utils'

import { renderWork } from '@tests'

import ProTree from '../src/ProTree'
import { ProTreeProps } from '../src/types'

describe.skip('ProTree', () => {
const ProTreeMount = (options?: MountingOptions<Partial<ProTreeProps>>) =>
mount(ProTree, { ...(options as MountingOptions<ProTreeProps>) })

renderWork<ProTreeProps>(ProTree, {
props: {},
})

test('xxx work', async () => {
const wrapper = ProTreeMount({ props: { xxx: 'Xxx' } })

expect(wrapper.classes()).toContain('ix-Xxx')

await wrapper.setProps({ xxx: 'Yyy' })

expect(wrapper.classes()).toContain('ix-Yyy')
})
})
14 changes: 14 additions & 0 deletions packages/pro/tree/demo/Basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
order: 0
title:
zh: 基本使用
en: Basic usage
---

## zh

最简单的用法。

## en

The simplest usage.
Loading

0 comments on commit 840982e

Please sign in to comment.