Skip to content
Merged
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,9 @@ pnpm-lock.*.yaml
# vitest
/html

# local v4 upgrade workflow (personal, not for commit)
.cursor/skills/nutui-component-v4-upgrade/
.claude/commands/nutui-v4-upgrade.md

# Harmony CSS files
src/packages/**/*.harmony.css
27 changes: 20 additions & 7 deletions src/packages/configprovider/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -772,13 +772,26 @@ export type NutCSSVariables =
| 'nutuiSegmentedActiveBackground'
| 'nutuiSegmentedIconMarginRight'
| 'nutuiEmptyPadding'
| 'nutuiEmptyImageSize'
| 'nutuiEmptyImageSmallSize'
| 'nutuiEmptyTitleMarginTop'
| 'nutuiEmptyBackgroundColor'
| 'nutuiEmptyTitleMarginBottom'
| 'nutuiEmptyTitleLineHeight'
| 'nutuiEmptyDescriptionLineHeight'
| 'nutuiEmptyTitleColor'
| 'nutuiEmptyDescriptionColor'
| 'nutuiEmptyFullPaddingTop'
| 'nutuiEmptyFullImageSize'
| 'nutuiEmptyFullTitleFontSize'
| 'nutuiEmptyFullTitleLineHeight'
| 'nutuiEmptyFullDescriptionFontSize'
| 'nutuiEmptyFullDescriptionLineHeight'
| 'nutuiEmptyFullActionsMarginTop'
| 'nutuiEmptyHalfImageSize'
| 'nutuiEmptyHalfTitleFontSize'
| 'nutuiEmptyHalfTitleLineHeight'
| 'nutuiEmptyHalfDescriptionFontSize'
| 'nutuiEmptyHalfDescriptionLineHeight'
| 'nutuiEmptyHalfActionsMarginTop'
| 'nutuiEmptyPartialPadding'
| 'nutuiEmptyPartialImageSize'
| 'nutuiEmptyPartialContentGap'
| 'nutuiEmptyPartialDescriptionFontSize'
| 'nutuiEmptyPartialDescriptionLineHeight'
| 'nutuiCascaderFontSize'
| 'nutuiCascaderPaneHeight'
| 'nutuiCascaderPanePaddingTop'
Expand Down
6 changes: 3 additions & 3 deletions src/packages/empty/__test__/__snapshots__/empty.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
exports[`should render description correctly 1`] = `
<div>
<div
class="nut-empty"
class="nut-empty nut-empty--half"
>
<div
class="nut-empty-base"
class="nut-empty-image"
>
<img
alt="empty"
src="https://storage.360buyimg.com/imgtools/30186cfda0-0d3eee40-c0ac-11ee-9382-9125782aa3b8.png"
src="https://img10.360buyimg.com/imagetools/jfs/t1/449411/36/15729/19102/6a30e810F36720c83/03e61e01e08ab731.png"
style="width: 100%; height: 100%;"
/>
</div>
Expand Down
84 changes: 70 additions & 14 deletions src/packages/empty/__test__/empty.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,86 @@
import * as React from 'react'
import { render } from '@testing-library/react'
import { render, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'

import { EMPTY_STATUS_IMAGES } from '@/types'
import { Empty } from '../empty'

test('should render description correctly', () => {
const { container, getByText } = render(<Empty description="暂无数据" />)
expect(getByText('暂无数据')).toBeTruthy()
expect(container).toMatchSnapshot()
})
test('should render imageSize correctly', () => {

test('should render title correctly', () => {
const { getByText } = render(
<Empty title="网络连接已断开" description="请检查网络设置" />
)
expect(getByText('网络连接已断开')).toHaveClass('nut-empty-title')
})

test('should use default half size and network status image', () => {
const { container } = render(<Empty description="暂无数据" />)
expect(container.querySelector('.nut-empty')).toHaveClass('nut-empty--half')
expect(container.querySelector('.nut-empty-image img')).toHaveAttribute(
'src',
EMPTY_STATUS_IMAGES.network
)
})

test('should render imageSize correctly', async () => {
const { container } = render(<Empty description="暂无数据" imageSize={100} />)
// expect(container.querySelector('.nut-empty-image')).toHaveStyle({
// width: '100px',
// })
await waitFor(() => {
expect(container.querySelector('.nut-empty-image')).toHaveStyle({
width: '100px',
height: '100px',
})
})
})
test('should render image props correctly', () => {
const { container } = render(<Empty status="empty" />)
// expect(container.querySelector('.img')).toHaveAttribute(
// 'src',
// 'https://storage.360buyimg.com/imgtools/30186cfda0-0d3eee40-c0ac-11ee-9382-9125782aa3b8.png'
// )

test('should render status image correctly', () => {
const { container } = render(<Empty status="search" />)
expect(container.querySelector('.nut-empty-image img')).toHaveAttribute(
'src',
EMPTY_STATUS_IMAGES.search
)
})

test('should render full size modifier class', () => {
const { container } = render(
<Empty size="full" title="标题" description="描述" />
)
expect(container.querySelector('.nut-empty')).toHaveClass('nut-empty--full')
expect(
container.querySelector('.nut-empty-partial-body')
).not.toBeInTheDocument()
})

test('should render partial layout structure', () => {
const { container } = render(
<Empty size="partial" status="search" description="没有更多商品咯" />
)
expect(container.querySelector('.nut-empty')).toHaveClass(
'nut-empty--partial'
)
expect(container.querySelector('.nut-empty-partial-body')).toBeInTheDocument()
expect(container.querySelector('.nut-empty-content')).toBeInTheDocument()
})

test('should render actions correctly', () => {
const { container, getByTestId } = render(
const { container } = render(
<Empty
data-testid="testEmpty"
title="标题"
description="暂无数据"
actions={[{ text: '操作1' }, { text: '操作2' }]}
/>
)
expect(container.querySelector('.nut-empty-actions-base')).toBeTruthy()
expect(container.querySelector('.nut-empty-actions')).toBeTruthy()
expect(
container.querySelectorAll('.nut-empty-actions-base .nut-button').length
container.querySelectorAll('.nut-empty-actions .nut-button').length
).toEqual(2)
})

test('should render custom image correctly', () => {
const { getByTestId } = render(
<Empty
Expand All @@ -54,3 +99,14 @@ test('should render custom image correctly', () => {
'https://static-ftcms.jd.com/p/files/61a9e3313985005b3958672e.png'
)
})

test('should render children correctly', () => {
const { getByTestId } = render(
<Empty description="暂无数据">
<button type="button" data-testid="custom-child">
自定义按钮
</button>
</Empty>
)
expect(getByTestId('custom-child')).toBeInTheDocument()
})
38 changes: 22 additions & 16 deletions src/packages/empty/demo.taro.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,36 @@ import Demo3 from './demos/taro/demo3'
import Demo4 from './demos/taro/demo4'
import Demo5 from './demos/taro/demo5'
import Demo6 from './demos/taro/demo6'
import Demo7 from './demos/taro/demo7'

const EmptyDemo = () => {
const [translated] = useTranslate({
'zh-CN': {
ce5c5446: '基础用法',
c38a08ee: 'Size 为 small 时,可用于半屏',
c38a08ef: '自定义内容大小',
b840c88f: '图片类型,内置3个',
ce5c5446: '全屏 full',
c38a08ee: '半屏 half',
c38a08ed: '局部 partial',
c38a08ef: '自定义图片大小',
b840c88f: '图片类型,内置8个',
a74a1fd4: '自定义图片',
'8dab2f66': '底部内容',
'8dab2f66': '自定义底部按钮',
},
'zh-TW': {
ce5c5446: '基礎用法',
c38a08ee: 'Size 为 small 时,可用于半屏',
c38a08ef: '自定義內容大小',
b840c88f: '圖片類型,內置3個',
ce5c5446: '全屏 full',
c38a08ee: '半屏 half',
c38a08ed: '局部 partial',
c38a08ef: '自定義圖片大小',
b840c88f: '圖片類型,內置8個',
a74a1fd4: '自定義圖片',
'8dab2f66': '底部內容',
'8dab2f66': '自定義底部按鈕',
},
'en-US': {
ce5c5446: 'Basic usage',
c38a08ee: 'Size is small',
c38a08ef: 'Custom content size',
b840c88f: 'Picture type, built-in 3',
ce5c5446: 'Full',
c38a08ee: 'Half',
c38a08ed: 'Partial',
c38a08ef: 'Custom image size',
b840c88f: 'Picture type, built-in 8',
a74a1fd4: 'Custom image',
'8dab2f66': 'Bottom content',
'8dab2f66': 'Custom bottom buttons',
},
})

Expand All @@ -46,10 +50,12 @@ const EmptyDemo = () => {
<Demo1 />
<View className="h2">{translated.c38a08ee}</View>
<Demo2 />
<View className="h2">{translated.c38a08ef}</View>
<View className="h2">{translated.c38a08ed}</View>
<Demo3 />
<View className="h2">{translated.b840c88f}</View>
<Demo4 />
<View className="h2">{translated.c38a08ef}</View>
<Demo7 />
<View className="h2">{translated.a74a1fd4}</View>
<Demo5 />
<View className="h2">{translated['8dab2f66']}</View>
Expand Down
38 changes: 22 additions & 16 deletions src/packages/empty/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,36 @@ import Demo3 from './demos/h5/demo3'
import Demo4 from './demos/h5/demo4'
import Demo5 from './demos/h5/demo5'
import Demo6 from './demos/h5/demo6'
import Demo7 from './demos/h5/demo7'

const EmptyDemo = () => {
const [translated] = useTranslate({
'zh-CN': {
ce5c5446: '基础用法',
c38a08ee: 'Size 为 small 时,可用于半屏',
c38a08ef: '自定义内容大小',
b840c88f: '图片类型,内置3个',
ce5c5446: '全屏 full',
c38a08ee: '半屏 half',
c38a08ed: '局部 partial',
c38a08ef: '自定义图片大小',
b840c88f: '图片类型,内置8个',
a74a1fd4: '自定义图片',
'8dab2f66': '底部内容',
'8dab2f66': '自定义底部按钮',
},
'zh-TW': {
ce5c5446: '基礎用法',
c38a08ee: 'Size 为 small 时,可用于半屏',
c38a08ef: '自定義內容大小',
b840c88f: '圖片類型,內置3個',
ce5c5446: '全屏 full',
c38a08ee: '半屏 half',
c38a08ed: '局部 partial',
c38a08ef: '自定義圖片大小',
b840c88f: '圖片類型,內置8個',
a74a1fd4: '自定義圖片',
'8dab2f66': '底部內容',
'8dab2f66': '自定義底部按鈕',
},
'en-US': {
ce5c5446: 'Basic usage',
c38a08ee: 'Size is small',
c38a08ef: 'Custom content size',
b840c88f: 'Picture type, built-in 3',
ce5c5446: 'Full',
c38a08ee: 'Half',
c38a08ed: 'Partial',
c38a08ef: 'Custom image size',
b840c88f: 'Picture type, built-in 8',
a74a1fd4: 'Custom image',
'8dab2f66': 'Bottom content',
'8dab2f66': 'Custom bottom buttons',
},
})

Expand All @@ -41,10 +45,12 @@ const EmptyDemo = () => {
<Demo1 />
<h2>{translated.c38a08ee}</h2>
<Demo2 />
<h2>{translated.c38a08ef}</h2>
<h2>{translated.c38a08ed}</h2>
<Demo3 />
<h2>{translated.b840c88f}</h2>
<Demo4 />
<h2>{translated.c38a08ef}</h2>
<Demo7 />
<h2>{translated.a74a1fd4}</h2>
<Demo5 />
<h2>{translated['8dab2f66']}</h2>
Expand Down
29 changes: 14 additions & 15 deletions src/packages/empty/demos/h5/demo1.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import React from 'react'
import { Empty } from '@nutui/nutui-react'
import { Cell, Empty, Toast } from '@nutui/nutui-react'

const Demo1 = () => {
return (
<>
<Cell>
<Empty
title="全屏缺省标题"
description="内容描述内容描述内容描述"
actions={[{ text: '次要操作' }, { text: '主要操作', type: 'primary' }]}
size="full"
status="network"
title="网络连接已断开"
description="请检查网络设置或刷新页面"
actions={[
{
text: '刷新',
type: 'primary',
onClick: () => Toast.show('正在刷新...'),
},
]}
/>
<Empty
description="内容描述内容描述内容描述"
actions={[{ text: '操作按钮' }]}
style={{ marginTop: '10px' }}
/>
<Empty
description="内容描述内容描述内容描述"
style={{ marginTop: '10px' }}
/>
</>
</Cell>
)
}
export default Demo1
26 changes: 20 additions & 6 deletions src/packages/empty/demos/h5/demo2.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,27 @@
import React from 'react'
import { Empty } from '@nutui/nutui-react'
import { Cell, Empty, Toast } from '@nutui/nutui-react'

const Demo2 = () => {
return (
<Empty
title="半屏缺省标题"
description="内容描述内容描述内容描述"
size="small"
/>
<Cell>
<Empty
size="half"
status="cart"
title="小购物车大容量"
description="把喜欢的商品都加进来吧"
actions={[
{
text: '逛逛秒杀',
onClick: () => Toast.show('逛逛秒杀'),
},
{
text: '看看关注',
type: 'primary',
onClick: () => Toast.show('看看关注'),
},
]}
/>
</Cell>
)
}
export default Demo2
8 changes: 6 additions & 2 deletions src/packages/empty/demos/h5/demo3.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import React from 'react'
import { Empty } from '@nutui/nutui-react'
import { Cell, Empty } from '@nutui/nutui-react'

const Demo3 = () => {
return <Empty description="内容描述内容描述" imageSize={80} />
return (
<Cell>
<Empty size="partial" status="search" description="没有更多商品咯" />
</Cell>
)
}
export default Demo3
Loading
Loading