Skip to content

Commit

Permalink
refactor(comp:list): rebuild with tsx (IDuxFE#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
qingshan-dev authored and 大鱼 committed Apr 23, 2022
1 parent 24f173e commit b8aedc5
Show file tree
Hide file tree
Showing 13 changed files with 216 additions and 258 deletions.
29 changes: 11 additions & 18 deletions packages/components/list/__tests__/__snapshots__/list.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -1,43 +1,36 @@
// Vitest Snapshot v1

exports[`List > render work 1`] = `
"<div class=\\"ix-list ix-list-md ix-list-border\\">
<!--v-if-->
"<div class=\\"ix-list ix-list-split ix-list-md ix-list-border\\">
<!---->
<div class=\\"ix-spin\\">
<!---->
<div class=\\"ix-spin-container\\">
<div>
<div class=\\"ix-list-item\\">
<div class=\\"ix-list-item-title\\"></div>
<!---->
<div class=\\"ix-list-item-content\\">default</div>
<div class=\\"ix-list-item-extra\\"></div>
<!---->
</div>
<div class=\\"ix-list-item\\">
<div class=\\"ix-list-item-title\\"></div>
<!---->
<div class=\\"ix-list-item-content\\">default</div>
<div class=\\"ix-list-item-extra\\"></div>
<!---->
</div>
<div class=\\"ix-list-item\\">
<div class=\\"ix-list-item-title\\"></div>
<!---->
<div class=\\"ix-list-item-content\\">default</div>
<div class=\\"ix-list-item-extra\\"></div>
<!---->
</div>
<div class=\\"ix-list-item\\">
<div class=\\"ix-list-item-title\\"></div>
<!---->
<div class=\\"ix-list-item-content\\">default</div>
<div class=\\"ix-list-item-extra\\"></div>
</div>
</div>
<div class=\\"ix-list-empty\\" style=\\"display: none;\\">
<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>
<!--v-if-->
<!---->
</div>
</div>
<!--v-if-->
<!---->
</div>"
`;
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

exports[`ListItem > render work 1`] = `
"<div class=\\"ix-list-item\\">
<div class=\\"ix-list-item-title\\"></div>
<div class=\\"ix-list-item-content\\"></div>
<div class=\\"ix-list-item-extra\\"></div>
<!---->
<div class=\\"ix-list-item-content\\">
<!---->
</div>
<!---->
</div>"
`;
36 changes: 20 additions & 16 deletions packages/components/list/__tests__/list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,39 @@ import { flushPromises, mount } from '@vue/test-utils'
import { renderWork } from '@tests'
import { DoneCallback } from 'vitest'

import List from '../src/List.vue'
import ListItem from '../src/ListItem.vue'
import ListItem from '../src/Item'
import List from '../src/List'

const TestComponent = {
components: { List, ListItem },
template: `
<List
:size="size"
:header="header"
:footer="footer"
:loadMore="loadMore"
:split="split"
<List
:size="size"
:header="header"
:footer="footer"
:loadMore="loadMore"
:loading="loading"
:grid="grid"
:borderless="borderless"
@loadMore="handleLoadMore">
<ListItem>default</ListItem>
<ListItem>default</ListItem>
<ListItem>default</ListItem>
<ListItem>default</ListItem>
<ListItem v-for='item in items'>{{item}}</ListItem>
</List>
`,
props: {
size: String,
header: String,
footer: String,
loadMore: String,
split: Boolean,
loading: Boolean,
grid: Object,
borderless: Boolean,
handleLoadMore: Function,
},
data() {
return {
items: Array.from(new Array(4)).map(() => 'default'),
}
},
}

async function sleep(time: number) {
Expand Down Expand Up @@ -101,9 +101,6 @@ describe('List', () => {
})
test('split', async () => {
const wrapper = mount(TestComponent)

expect(wrapper.classes()).not.toContain('ix-list-split')
await wrapper.setProps({ split: true })
expect(wrapper.classes()).toContain('ix-list-split')
})
test('borderless', async () => {
Expand All @@ -116,6 +113,13 @@ describe('List', () => {
expect(wrapper.classes()).not.toContain('ix-list-borderless')
})

test('empty', async () => {
const wrapper = mount(TestComponent)
expect(wrapper.find('.ix-empty').exists()).toBeFalsy()
await wrapper.setData({ items: [] })
expect(wrapper.find('.ix-empty').exists()).toBeTruthy()
})

test('grid', async () => {
const wrapper = mount(TestComponent)

Expand Down
2 changes: 1 addition & 1 deletion packages/components/list/__tests__/listItem.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { MountingOptions, mount } from '@vue/test-utils'

import { renderWork } from '@tests'

import IxListItem from '../src/ListItem.vue'
import IxListItem from '../src/Item'
import { ListItemProps } from '../src/types'

describe('ListItem', () => {
Expand Down
1 change: 0 additions & 1 deletion packages/components/list/docs/Index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ order: 0
| `loadMore` | 加载更多 | `string \| slot` | 加载更多 | - | - |
| `empty` | 空状态 | `string \| slot` | - | - | - |
| `borderless` | 是否无边框 | `boolean` | true || - |
| `split` | 是否显示分割线 | `boolean` | true | - | - |
| `loading` | 加载状态 | `boolean \| SpinProps` | false | - | SpinProps请参照 spin 组件 |
| `size` | 大小 | `'lg' \| 'md' \| 'sm'` | `'md'` || - |
| `grid` | grid 布局 | `ListGridProps` | - | - | 结合了IxRow, IxCol 的部分配置 |
Expand Down
7 changes: 3 additions & 4 deletions packages/components/list/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

import type { ListComponent, ListItemComponent } from './src/types'

import List from './src/List.vue'
import ListItem from './src/ListItem.vue'
import ListItem from './src/Item'
import List from './src/List'

const IxList = List as unknown as ListComponent
const IxListItem = ListItem as unknown as ListItemComponent
const IxList = List as unknown as ListComponent

export { IxList, IxListItem }

Expand All @@ -23,6 +23,5 @@ export type {
ListItemComponent,
ListItemPublicProps as ListItemProps,
ListSize,
ListLayout,
ListGridProps,
} from './src/types'
63 changes: 63 additions & 0 deletions packages/components/list/src/Item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { ListGridProps } from './types'

import { defineComponent, inject } from 'vue'

import { IxCol } from '@idux/components/grid'

import { listToken } from './token'
import { listItemProps } from './types'

export default defineComponent({
name: 'IxListItem',
props: listItemProps,
setup(props, { slots }) {
const listGrid = inject(listToken, null)

const getGrid = <T, K extends keyof T>(grid: T, dim: K) => {
const v = grid[dim]
if (typeof v === 'number') {
return Math.floor(24 / v)
}

return undefined
}

const useGrid = (grid: ListGridProps) => {
const defaultSpan = getGrid(grid, 'column')
const xsSpan = getGrid(grid, 'xs')
const smSpan = getGrid(grid, 'sm')
const mdSpan = getGrid(grid, 'md')
const lgSpan = getGrid(grid, 'lg')
const xlSpan = getGrid(grid, 'xl')
return {
xs: xsSpan || defaultSpan,
sm: smSpan || defaultSpan,
md: mdSpan || defaultSpan,
ld: lgSpan || defaultSpan,
xl: xlSpan || defaultSpan,
}
}

return () => {
const grid = listGrid?.value && useGrid(listGrid?.value)
const title = props.title ?? slots.title?.()
const content = props.content ?? slots.default?.()
const extra = slots.extra?.()
const renderContent = (
<>
{title && <div class="ix-list-item-title">{title}</div>}
<div class="ix-list-item-content">{content}</div>
{extra && <div class="ix-list-item-extra">{extra}</div>}
</>
)
return grid ? <IxCol {...grid}>{renderContent}</IxCol> : <div class="ix-list-item">{renderContent}</div>
}
},
})
109 changes: 109 additions & 0 deletions packages/components/list/src/List.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import { computed, defineComponent, provide, ref } from 'vue'

import { getFirstValidNode } from '@idux/cdk/utils'
import { IxButton } from '@idux/components/button'
import { ListConfig, useGlobalConfig } from '@idux/components/config'
import { IxEmpty } from '@idux/components/empty'
import { IxRow } from '@idux/components/grid'
import { IxSpin } from '@idux/components/spin'

import { listToken } from './token'
import { ListProps, listProps } from './types'

export default defineComponent({
name: 'IxList',
components: {
IxSpin,
IxButton,
IxEmpty,
},
props: listProps,
emits: ['loadMore'],
setup(props: ListProps, { slots, emit }) {
provide(
listToken,
computed(() => props.grid),
)

const listConfig = useGlobalConfig('list')

const loadingProp = computed(() => {
if (typeof props.loading === 'boolean') {
return {
spinning: props.loading,
}
}
return props.loading
})
const loadMoreLoading = ref(false)
const loadMoreHandleClick = () => {
loadMoreLoading.value = true
const done = () => {
loadMoreLoading.value = false
}
emit('loadMore', done)
}

const useClasses = (props: ListProps, listConfig: ListConfig) => {
return computed(() => {
const borderless = props.borderless ?? listConfig.borderless
const size = props.size ?? listConfig.size
return [
'ix-list',
'ix-list-split',
`ix-list-${size}`,
{
'ix-list-border': !borderless,
},
]
})
}

return () => {
const classesProps = useClasses(props, listConfig)
const header = props.header ?? slots.header?.()
const footer = props.footer ?? slots.footer?.()
const content = getFirstValidNode(slots.default?.())
? slots.default?.()
: slots.empty?.() ?? <IxEmpty description={props.empty} />
const loadMore = props.loadMore ?? slots.loadMore?.()

const renderContent = () => {
if (props.grid) {
return <IxRow gutter={props.grid.gutter}>{content}</IxRow>
}
return <div>{content}</div>
}

const renderLoadMore = () => {
return (
loadMore && (
<div class="ix-list-loadMore">
<IxButton loading={loadMoreLoading.value} onClick={loadMoreHandleClick}>
{loadMore}
</IxButton>
</div>
)
)
}

return (
<div class={classesProps.value}>
{header && <div class="ix-list-header">{header}</div>}
<IxSpin {...loadingProp.value}>
{renderContent()}
{renderLoadMore()}
</IxSpin>
{footer && <div class="ix-list-footer">{footer}</div>}
</div>
)
}
},
})
Loading

0 comments on commit b8aedc5

Please sign in to comment.