Skip to content

Commit

Permalink
feat(comp: cascader): add cascader component (#857)
Browse files Browse the repository at this point in the history
fix #797
  • Loading branch information
danranVm committed Apr 25, 2022
1 parent 1204300 commit 50fb584
Show file tree
Hide file tree
Showing 67 changed files with 2,705 additions and 93 deletions.
2 changes: 2 additions & 0 deletions azure-pipelines.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

trigger:
- main
- next
- hotfix

pool:
vmImage: 'ubuntu-latest'
Expand Down
2 changes: 1 addition & 1 deletion packages/cdk/scroll/src/virtual/composables/useGetKey.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,6 @@ export function useGetKey(props: VirtualScrollProps): ComputedRef<GetKey> {
return key
}
}
return getKey
return getKey!
})
}
2 changes: 1 addition & 1 deletion packages/components/_private/selector/src/Selector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export default defineComponent({
disabled: _disabled,
prefixCls: itemPrefixCls,
removable,
value,
value: value ?? key,
label,
onRemove: props.onItemRemove,
}
Expand Down
3 changes: 1 addition & 2 deletions packages/components/_private/selector/style/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@
.ellipsis();

&-label {
display: inline-flex;
align-items: center;
.ellipsis();
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Vitest Snapshot v1

exports[`Cascader > multiple work > render work 1`] = `
"<div class=\\"ix-cascader ix-selector ix-selector-multiple ix-selector-opened ix-selector-md\\">
<!---->
<div class=\\"ix-selector-content\\">
<div class=\\"ix-overflow ix-selector-overflow\\">
<div class=\\"ix-overflow-item\\">
<div class=\\"ix-selector-item\\"><span class=\\"ix-selector-item-label\\">Components/General/Button</span><span class=\\"ix-selector-item-remove\\"><i class=\\"ix-icon ix-icon-close\\" role=\\"img\\" aria-label=\\"close\\"></i></span></div>
</div>
<div class=\\"ix-overflow-item\\">
<div class=\\"ix-selector-item\\"><span class=\\"ix-selector-item-label\\">Pro/Table</span><span class=\\"ix-selector-item-remove\\"><i class=\\"ix-icon ix-icon-close\\" role=\\"img\\" aria-label=\\"close\\"></i></span></div>
</div>
<!---->
<div class=\\"ix-overflow-item ix-overflow-suffix\\">
<div class=\\"ix-selector-input\\"><input class=\\"ix-selector-input-inner\\" style=\\"opacity: 0; width: 0px;\\" autocomplete=\\"off\\"><span class=\\"ix-selector-input-mirror\\" aria-hidden=\\"true\\"></span></div>
</div>
</div>
<div class=\\"ix-selector-suffix\\"><i class=\\"ix-icon ix-icon-down\\" style=\\"transform: rotate(180deg);\\" role=\\"img\\" aria-label=\\"down\\"></i></div>
</div>
</div>
<!--teleport start-->
<!--teleport end-->"
`;
exports[`Cascader > single work > render work 1`] = `
"<div class=\\"ix-cascader ix-selector ix-selector-opened ix-selector-single ix-selector-md\\">
<!---->
<div class=\\"ix-selector-content\\">
<div class=\\"ix-selector-item\\"><span class=\\"ix-selector-item-label\\">Components/General/Button</span>
<!---->
</div>
<div class=\\"ix-selector-input\\"><input class=\\"ix-selector-input-inner\\" style=\\"opacity: 0;\\" autocomplete=\\"off\\">
<!---->
</div>
<div class=\\"ix-selector-suffix\\"><i class=\\"ix-icon ix-icon-down\\" style=\\"transform: rotate(180deg);\\" role=\\"img\\" aria-label=\\"down\\"></i></div>
</div>
</div>
<!--teleport start-->
<!--teleport end-->"
`;
241 changes: 241 additions & 0 deletions packages/components/cascader/__tests__/cascader.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
import { MountingOptions, mount } from '@vue/test-utils'

import { renderWork } from '@tests'

import Cascader from '../src/Cascader'
import OverlayContent from '../src/contents/OverlayContent'
import { CascaderData, CascaderProps } from '../src/types'

const defaultDataSource: CascaderData[] = [
{
key: 'components',
label: 'Components',
children: [
{
key: 'general',
label: 'General',
children: [
{
key: 'button',
label: 'Button',
},
{
key: 'header',
label: 'Header',
},
{
key: 'icon',
label: 'Icon',
},
],
},
{
key: 'layout',
label: 'Layout',
children: [
{
key: 'divider',
label: 'Divider',
},
{
key: 'grid',
label: 'Grid',
},
{
key: 'space',
label: 'Space',
},
],
},
{
key: 'navigation',
label: 'Navigation',
children: [
{
key: 'breadcrumb',
label: 'Breadcrumb',
},
{
key: 'dropdown',
label: 'Dropdown',
},
{
key: 'menu',
label: 'Menu',
},
{
key: 'pagination',
label: 'Pagination',
},
],
},
],
},
{
key: 'pro',
label: 'Pro',
children: [
{
key: 'pro-layout',
label: 'Layout',
},
{
key: 'pro-table',
label: 'Table',
disabled: true,
},
{
key: 'pro-transfer',
label: 'Transfer',
},
],
},
{
key: 'cdk',
label: 'CDK',
disabled: true,
children: [
{
key: 'a11y',
label: 'Accessibility',
},
{
key: 'breakpoint',
label: 'Breakpoint',
},
{
key: 'click-outside',
label: 'ClickOutside',
},
{
key: 'clipboard',
label: 'Clipboard',
},
{
key: 'forms',
label: 'Forms',
},
],
},
]
const defaultSingleValue = ['components', 'general', 'button']
const defaultMultipleValue = [
['components', 'general', 'button'],
['pro', 'pro-table'],
]
const defaultExpandedKeys = ['components', 'general']

describe.only('Cascader', () => {
describe('single work', () => {
const CascaderMount = (options?: MountingOptions<Partial<CascaderProps>>) => {
const { props, ...rest } = options || {}
return mount(Cascader, {
...rest,
props: {
dataSource: defaultDataSource,
value: defaultSingleValue,
expandedKeys: defaultExpandedKeys,
...props,
},
attachTo: 'body',
})
}

renderWork<CascaderProps>(Cascader, {
props: {
open: true,
dataSource: defaultDataSource,
value: defaultSingleValue,
expandedKeys: defaultExpandedKeys,
},
attachTo: 'body',
})

test('v-model:value work', async () => {
const onUpdateValue = vi.fn()
const onChange = vi.fn()
const wrapper = CascaderMount({
props: {
open: true,
'onUpdate:value': onUpdateValue,
onChange,
},
})

expect(wrapper.find('.ix-selector-item').text()).toBe('Components/General/Button')

await wrapper.setProps({ value: undefined })

expect(wrapper.find('.ix-selector-item').exists()).toBe(false)

const allGroups = wrapper.findComponent(OverlayContent).findAll('.ix-cascader-option-group')

await allGroups[2].find('.ix-cascader-option').trigger('click')

// expect(onUpdateValue).toBeCalledWith(['components', 'general', 'button'])
// expect(onChange).toBeCalledWith(['components', 'general', 'button'], undefined)

await wrapper.setProps({ value: ['components', 'general', 'button'] })
await allGroups[2].find('.ix-cascader-option').trigger('click')

// expect(onUpdateValue).toBeCalledWith(['pro', 'pro-layout'])
// expect(onChange).toBeCalledWith(['pro', 'pro-layout'], ['components', 'general', 'button'])
})
})

describe('multiple work', () => {
const CascaderMount = (options?: MountingOptions<Partial<CascaderProps>>) => {
const { props, ...rest } = options || {}
return mount(Cascader, {
...rest,
props: {
multiple: true,
dataSource: defaultDataSource,
value: defaultMultipleValue,
expandedKeys: defaultExpandedKeys,
...props,
},
attachTo: 'body',
})
}

renderWork<CascaderProps>(Cascader, {
props: { multiple: true, open: true, dataSource: defaultDataSource, value: defaultMultipleValue },
attachTo: 'body',
})

test('v-model:value work', async () => {
const onUpdateValue = vi.fn()
const onChange = vi.fn()
const wrapper = CascaderMount({
props: {
open: true,
'onUpdate:value': onUpdateValue,
onChange,
},
})

expect(wrapper.findAll('.ix-selector-item').length).toBe(2)

await wrapper.setProps({ value: [['components', 'general', 'button']] })

expect(wrapper.findAll('.ix-selector-item').length).toBe(1)

const allGroups = wrapper.findComponent(OverlayContent).findAll('.ix-cascader-option-group')

await allGroups[2].find('.ix-cascader-option').trigger('click')

// expect(onUpdateValue).toBeCalledWith([
// ['components', 'general', 'button'],
// ['pro', 'pro-layout'],
// ])
// expect(onChange).toBeCalledWith(
// [
// ['components', 'general', 'button'],
// ['pro', 'pro-layout'],
// ],
// [['components', 'general', 'button']],
// )
})
})
})
14 changes: 14 additions & 0 deletions packages/components/cascader/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

最简单的用法, 请注意 `fullPath` 时值类型的差异。

## en

The simplest usage. Note the difference in value types in `fullPath`.
Loading

0 comments on commit 50fb584

Please sign in to comment.