@loja-integrada/admin-components 0.14.0 → 0.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Components/TableList/TableList.d.ts +38 -0
- package/dist/Components/TableList/TableList.spec.d.ts +1 -0
- package/dist/Components/TableList/TableList.stories.d.ts +7 -0
- package/dist/Components/TableList/TableListItem.d.ts +3 -0
- package/dist/Components/TableList/TableListItem.interface.d.ts +56 -0
- package/dist/Components/TableList/TableListItem.spec.d.ts +1 -0
- package/dist/Components/TableList/TableListItem.stories.d.ts +4 -0
- package/dist/Components/TableList/TableListItemLoading.d.ts +3 -0
- package/dist/Components/TableList/TableListItemLoading.spec.d.ts +1 -0
- package/dist/Components/TableList/TableListItemLoading.stories.d.ts +4 -0
- package/dist/Components/TableList/TableListItemWrapper.d.ts +12 -0
- package/dist/Components/TableList/TableListItemWrapper.spec.d.ts +1 -0
- package/dist/Components/TableList/TableListItemWrapper.stories.d.ts +4 -0
- package/dist/Components/TableList/index.d.ts +1 -0
- package/dist/Components/index.d.ts +1 -0
- package/dist/Indicators/Alert/Alert.d.ts +5 -1
- package/dist/Navigation/Breadcrumb/index.d.ts +7 -4
- package/dist/admin-components.cjs.development.js +193 -5
- package/dist/admin-components.cjs.development.js.map +1 -1
- package/dist/admin-components.cjs.production.min.js +1 -1
- package/dist/admin-components.cjs.production.min.js.map +1 -1
- package/dist/admin-components.esm.js +193 -6
- package/dist/admin-components.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/Components/TableList/TableList.spec.tsx +85 -0
- package/src/Components/TableList/TableList.stories.tsx +168 -0
- package/src/Components/TableList/TableList.tsx +168 -0
- package/src/Components/TableList/TableListItem.interface.ts +57 -0
- package/src/Components/TableList/TableListItem.spec.tsx +64 -0
- package/src/Components/TableList/TableListItem.stories.tsx +43 -0
- package/src/Components/TableList/TableListItem.tsx +63 -0
- package/src/Components/TableList/TableListItemLoading.spec.tsx +18 -0
- package/src/Components/TableList/TableListItemLoading.stories.tsx +22 -0
- package/src/Components/TableList/TableListItemLoading.tsx +40 -0
- package/src/Components/TableList/TableListItemWrapper.spec.tsx +32 -0
- package/src/Components/TableList/TableListItemWrapper.stories.tsx +38 -0
- package/src/Components/TableList/TableListItemWrapper.tsx +40 -0
- package/src/Components/TableList/index.tsx +1 -0
- package/src/Components/Timeline/TimelineItem.tsx +1 -1
- package/src/Components/index.ts +1 -0
- package/src/Indicators/Alert/Alert.tsx +9 -1
- package/src/Navigation/Breadcrumb/Breadcrumb.spec.tsx +12 -0
- package/src/Navigation/Breadcrumb/index.tsx +20 -6
package/package.json
CHANGED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { composeStories } from "@storybook/testing-react"
|
|
3
|
+
import { mount } from "@cypress/react"
|
|
4
|
+
import * as stories from "./TableList.stories"
|
|
5
|
+
|
|
6
|
+
const { Default, WithLoading, WithEmpty, WithLink } = composeStories(stories)
|
|
7
|
+
|
|
8
|
+
describe('TableListItem tests', () => {
|
|
9
|
+
|
|
10
|
+
it('Default', () => {
|
|
11
|
+
mount(<Default />)
|
|
12
|
+
cy.get('.table-list')
|
|
13
|
+
.should('exist')
|
|
14
|
+
.find('.table-list-group')
|
|
15
|
+
.should('have.length', 6)
|
|
16
|
+
|
|
17
|
+
cy.get('.table-list .table-list-group')
|
|
18
|
+
.first()
|
|
19
|
+
.find('.table-list-title')
|
|
20
|
+
.should('have.class', 'relative lg:hidden')
|
|
21
|
+
.contains('11 de abril')
|
|
22
|
+
|
|
23
|
+
cy.get('.table-list .table-list-group')
|
|
24
|
+
.first()
|
|
25
|
+
.find('.group-items .table-item')
|
|
26
|
+
.should('have.length', 6)
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it('WithLoading', () => {
|
|
30
|
+
mount(<WithLoading />)
|
|
31
|
+
cy.get('.table-list .table-list-loading')
|
|
32
|
+
.should('exist')
|
|
33
|
+
.find('.table-item-loading')
|
|
34
|
+
.should('have.length', 4)
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
it('WithEmpty', () => {
|
|
38
|
+
mount(<WithEmpty />)
|
|
39
|
+
cy.get('.table-list .table-list-empty')
|
|
40
|
+
.should('exist')
|
|
41
|
+
.find('.table-list-empty-illustration')
|
|
42
|
+
.should('exist')
|
|
43
|
+
.find('svg')
|
|
44
|
+
.should('exist')
|
|
45
|
+
cy.get('.table-list .table-list-empty')
|
|
46
|
+
.find('.table-list-empty-title')
|
|
47
|
+
.should('exist')
|
|
48
|
+
.contains('Você ainda não fez nenhuma venda conosco')
|
|
49
|
+
cy.get('.table-list .table-list-empty')
|
|
50
|
+
.find('.table-list-empty-subtitle')
|
|
51
|
+
.should('exist')
|
|
52
|
+
.contains('Continua firme, você consegue')
|
|
53
|
+
cy.get('.table-list .table-list-empty')
|
|
54
|
+
.find('.table-list-empty-action')
|
|
55
|
+
.should('exist')
|
|
56
|
+
.contains('Voltar')
|
|
57
|
+
|
|
58
|
+
mount(<WithEmpty empty={undefined} />)
|
|
59
|
+
cy.get('.table-list .table-list-empty')
|
|
60
|
+
.should('exist')
|
|
61
|
+
.find('.table-list-empty-illustration')
|
|
62
|
+
.should('not.exist')
|
|
63
|
+
cy.get('.table-list .table-list-empty')
|
|
64
|
+
.find('.table-list-empty-title')
|
|
65
|
+
.should('exist')
|
|
66
|
+
.contains('Nenhum registro encontrado')
|
|
67
|
+
cy.get('.table-list .table-list-empty')
|
|
68
|
+
.find('.table-list-empty-subtitle')
|
|
69
|
+
.should('not.exist')
|
|
70
|
+
cy.get('.table-list .table-list-empty')
|
|
71
|
+
.find('.table-list-empty-action')
|
|
72
|
+
.should('not.exist')
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
it('WithLink', () => {
|
|
76
|
+
mount(<WithLink />)
|
|
77
|
+
cy.get('.table-list .table-item')
|
|
78
|
+
.first()
|
|
79
|
+
.find('a.table-item-wrapper')
|
|
80
|
+
.should('exist')
|
|
81
|
+
.should('have.attr', 'href', '#link')
|
|
82
|
+
.should('have.class', 'hover:bg-base-2 before:hover:block')
|
|
83
|
+
.should('have.class', 'after:hover:block')
|
|
84
|
+
})
|
|
85
|
+
})
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Story, Meta } from '@storybook/react'
|
|
3
|
+
import { withDesign } from 'storybook-addon-designs'
|
|
4
|
+
|
|
5
|
+
import { Icon } from '../../Icons'
|
|
6
|
+
import { Button } from '../Button'
|
|
7
|
+
import { TableList, TableListProps } from './TableList'
|
|
8
|
+
|
|
9
|
+
const exampleItems = [
|
|
10
|
+
{
|
|
11
|
+
title: 'R$ 3.599,99 cancelada',
|
|
12
|
+
description: '#JZW55MBEIX - QA Loja Integrada via pix',
|
|
13
|
+
timestampTime: '11:18',
|
|
14
|
+
timestampDate: '11 de abril',
|
|
15
|
+
itemWrapperProps: { href: '#link' },
|
|
16
|
+
withIcon: { class: 'bg-danger-light text-danger-dark', icon: 'close' }
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
title: 'R$ 3.599,99 cancelada',
|
|
20
|
+
description: '#P0UYL7PWBF - QA Loja Integrada via pix',
|
|
21
|
+
timestampTime: '05:38',
|
|
22
|
+
timestampDate: '11 de abril',
|
|
23
|
+
itemWrapperProps: { href: '#link' },
|
|
24
|
+
withIcon: { class: 'bg-danger-light text-danger-dark', icon: 'close' }
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
title: 'R$ 12,00 incompleta',
|
|
28
|
+
description: '#67JYUCMTR1',
|
|
29
|
+
timestampTime: '05:37',
|
|
30
|
+
timestampDate: '11 de abril',
|
|
31
|
+
itemWrapperProps: { href: '#link' },
|
|
32
|
+
withIcon: { class: 'bg-primary-light text-inverted-2', icon: 'clock' }
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: 'R$ 0,50 cancelada',
|
|
36
|
+
description: '#JTRM6NBP41 - QA Store 1 via pix',
|
|
37
|
+
timestampTime: '05:36',
|
|
38
|
+
timestampDate: '11 de abril',
|
|
39
|
+
itemWrapperProps: { href: '#link' },
|
|
40
|
+
withIcon: { class: 'bg-danger-light text-danger-dark', icon: 'close' }
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: 'R$ 0,01 incompleta',
|
|
44
|
+
description: '#39YDAHYA1F',
|
|
45
|
+
timestampTime: '05:35',
|
|
46
|
+
timestampDate: '11 de abril',
|
|
47
|
+
itemWrapperProps: { href: '#link' },
|
|
48
|
+
withIcon: { class: 'bg-primary-light text-inverted-2', icon: 'clock' }
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
title: 'R$ 12,00 incompleta',
|
|
52
|
+
description: '#ZPN7P3BZI3',
|
|
53
|
+
timestampTime: '05:33',
|
|
54
|
+
timestampDate: '11 de abril',
|
|
55
|
+
itemWrapperProps: { href: '#link' },
|
|
56
|
+
withIcon: { class: 'bg-primary-light text-inverted-2', icon: 'clock' }
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
title: 'R$ 229,05 aprovada',
|
|
60
|
+
description: '#0XGQZQ164P - QA Loja Integrada via boleto',
|
|
61
|
+
timestampTime: '15:40',
|
|
62
|
+
timestampDate: '07 de abril',
|
|
63
|
+
itemWrapperProps: { href: '#link' },
|
|
64
|
+
withIcon: { class: 'bg-success-light text-success-dark', icon: 'check' }
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
title: 'R$ 232,56 devolvida',
|
|
68
|
+
description: '#V1KZRJS49J - QA Loja Integrada via credit_card',
|
|
69
|
+
timestampTime: '05:46',
|
|
70
|
+
timestampDate: '05 de abril',
|
|
71
|
+
itemWrapperProps: { href: '#link' },
|
|
72
|
+
withIcon: { class: 'bg-[#E7DDF3] text-inverted-1', icon: 'back' }
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
title: 'R$ 2.666,79 devolvida parcialmente',
|
|
76
|
+
description: '#RB3JJLLKV9 - QA Loja Integrada via credit_card',
|
|
77
|
+
timestampTime: '13:46',
|
|
78
|
+
timestampDate: '04 de abril',
|
|
79
|
+
itemWrapperProps: { href: '#link' },
|
|
80
|
+
withIcon: { class: 'bg-[#E7DDF3] text-inverted-1', icon: 'halfBack' }
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
title: 'R$ 144,00 criada',
|
|
84
|
+
description: '#FLGXE26Q62 - Joazinho do Teste via credit_card',
|
|
85
|
+
timestampTime: '14:59',
|
|
86
|
+
timestampDate: '29 de março',
|
|
87
|
+
itemWrapperProps: { href: '#link' },
|
|
88
|
+
withIcon: { class: 'bg-primary-light text-inverted-2', icon: 'clock' }
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
title: 'R$ 311,64 criada',
|
|
92
|
+
description: '#1RS5OPTW34 - Joazinho do Teste via credit_card',
|
|
93
|
+
timestampTime: '14:23',
|
|
94
|
+
timestampDate: '29 de março',
|
|
95
|
+
itemWrapperProps: { href: '#link' },
|
|
96
|
+
withIcon: { class: 'bg-primary-light text-inverted-2', icon: 'clock' }
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
title: 'R$ 360,00 cancelada',
|
|
100
|
+
description: '#D4RHATKP9E',
|
|
101
|
+
timestampTime: '16:10',
|
|
102
|
+
timestampDate: '24 de março',
|
|
103
|
+
itemWrapperProps: { href: '#link' },
|
|
104
|
+
withIcon: { class: 'bg-danger-light text-danger-dark', icon: 'close' }
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
title: 'R$ 350,56 cancelada',
|
|
108
|
+
description: '#4UZDIZJCNS',
|
|
109
|
+
timestampTime: '16:05',
|
|
110
|
+
timestampDate: '24 de março',
|
|
111
|
+
itemWrapperProps: { href: '#link' },
|
|
112
|
+
withIcon: { class: 'bg-danger-light text-danger-dark', icon: 'close' }
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
title: 'R$ 23,30 cancelada',
|
|
116
|
+
description: '#WNLVZQDREA',
|
|
117
|
+
timestampTime: '16:04',
|
|
118
|
+
timestampDate: '24 de março',
|
|
119
|
+
itemWrapperProps: { href: '#link' },
|
|
120
|
+
withIcon: { class: 'bg-danger-light text-danger-dark', icon: 'close' }
|
|
121
|
+
},
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
export default {
|
|
125
|
+
title: 'Components/TableList',
|
|
126
|
+
component: TableList,
|
|
127
|
+
decorators: [withDesign],
|
|
128
|
+
parameters: {
|
|
129
|
+
layout: 'padded',
|
|
130
|
+
},
|
|
131
|
+
args: {
|
|
132
|
+
items: exampleItems,
|
|
133
|
+
},
|
|
134
|
+
} as Meta
|
|
135
|
+
|
|
136
|
+
const Template: Story<TableListProps> = (args) => <TableList {...args} />
|
|
137
|
+
|
|
138
|
+
export const Default = Template.bind({})
|
|
139
|
+
|
|
140
|
+
export const WithLoading = Template.bind({})
|
|
141
|
+
WithLoading.args = {
|
|
142
|
+
isLoading: true,
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const WithEmpty = Template.bind({})
|
|
146
|
+
WithEmpty.args = {
|
|
147
|
+
items: [],
|
|
148
|
+
empty: {
|
|
149
|
+
title: 'Poxa, que pena! Você ainda não fez nenhuma venda conosco.',
|
|
150
|
+
illustration: <Icon icon="ban" size={9} className="text-primary" />,
|
|
151
|
+
subTitle: 'Mas fica tranquilo que quando você começar a vender, suas transações aparecerão aqui. Continua firme, você consegue!',
|
|
152
|
+
action: <Button variant="secondary">Voltar</Button>
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const CellLink = (props: any) => {
|
|
157
|
+
const { href = '/', children, ...restProps } = props
|
|
158
|
+
return (
|
|
159
|
+
<a href={href} {...restProps}>{children}</a>
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export const WithLink = Template.bind({})
|
|
164
|
+
WithLink.args = {
|
|
165
|
+
withHover: true,
|
|
166
|
+
isInsideContainer: true,
|
|
167
|
+
itemWrapper: CellLink,
|
|
168
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { TableListItemProps } from './TableListItem.interface'
|
|
4
|
+
import { TableListItem } from './TableListItem'
|
|
5
|
+
import { TableListItemLoading } from './TableListItemLoading'
|
|
6
|
+
|
|
7
|
+
const groupTitleMobileClass = `before:block before:absolute before:h-0 before:w-5 before:-top-px before:-left-5 before:border-t before:border-primary-bold before:border-opacity-10 after:block after:absolute after:h-0 after:w-5 after:-top-px after:-right-5 after:border-t after:border-primary-bold after:border-opacity-10`
|
|
8
|
+
|
|
9
|
+
const TableListComponent = ({
|
|
10
|
+
className = '',
|
|
11
|
+
itemWrapper,
|
|
12
|
+
items = [],
|
|
13
|
+
isLoading = false,
|
|
14
|
+
empty = {
|
|
15
|
+
title: 'Nenhum registro encontrado',
|
|
16
|
+
},
|
|
17
|
+
withHover = false,
|
|
18
|
+
isInsideContainer = false,
|
|
19
|
+
}: TableListProps) => {
|
|
20
|
+
const itemsMemoized = React.useMemo(() => {
|
|
21
|
+
const groups = items.reduce(
|
|
22
|
+
(
|
|
23
|
+
groups: {
|
|
24
|
+
[key: string]: TableListItemProps[]
|
|
25
|
+
},
|
|
26
|
+
item
|
|
27
|
+
) => {
|
|
28
|
+
const groupTitle =
|
|
29
|
+
item.timestampDate || item.timestampTime || 'no_title'
|
|
30
|
+
if (!groups[groupTitle]) {
|
|
31
|
+
groups[groupTitle] = []
|
|
32
|
+
}
|
|
33
|
+
groups[groupTitle].push(item)
|
|
34
|
+
return groups
|
|
35
|
+
},
|
|
36
|
+
{}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
return Object.keys(groups).map((groupTitle) => {
|
|
40
|
+
return {
|
|
41
|
+
title: groupTitle,
|
|
42
|
+
items: groups[groupTitle],
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}, [items])
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className={`table-list tracking-tight ${className}`}>
|
|
49
|
+
{isLoading ? (
|
|
50
|
+
<div className="table-list-loading">
|
|
51
|
+
<TableListItemLoading />
|
|
52
|
+
<TableListItemLoading />
|
|
53
|
+
<TableListItemLoading />
|
|
54
|
+
<TableListItemLoading />
|
|
55
|
+
</div>
|
|
56
|
+
) : !itemsMemoized || !itemsMemoized.length ? (
|
|
57
|
+
<div className="table-list-empty flex flex-col items-center justify-center gap-5 min-h-[80vh] lg:min-h-[60vh] max-w-sm mx-auto px-4">
|
|
58
|
+
{empty.illustration && (
|
|
59
|
+
<div className="table-list-empty-illustration text-center">
|
|
60
|
+
{empty.illustration}
|
|
61
|
+
</div>
|
|
62
|
+
)}
|
|
63
|
+
<div className="table-list-empty-title text-center text-f4 font-semibold text-primary-bold leading-7">
|
|
64
|
+
{empty.title}
|
|
65
|
+
</div>
|
|
66
|
+
{empty.subTitle && (
|
|
67
|
+
<div className="table-list-empty-subtitle text-center text-f6 text-on-base-2 leading-6 -mt-1">
|
|
68
|
+
{empty.subTitle}
|
|
69
|
+
</div>
|
|
70
|
+
)}
|
|
71
|
+
{empty.action && (
|
|
72
|
+
<div className="table-list-empty-action text-center">
|
|
73
|
+
{empty.action}
|
|
74
|
+
</div>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
) : (
|
|
78
|
+
itemsMemoized.map((group, indexGroup) => {
|
|
79
|
+
return (
|
|
80
|
+
<div key={`group-items-${indexGroup}`} className="table-list-group">
|
|
81
|
+
{group.title && group.title !== 'no_title' && (
|
|
82
|
+
<div
|
|
83
|
+
className={`table-list-title relative lg:hidden border-primary-bold border-opacity-10 ${
|
|
84
|
+
indexGroup !== 0
|
|
85
|
+
? `border-t ${
|
|
86
|
+
isInsideContainer ? groupTitleMobileClass : ''
|
|
87
|
+
}`
|
|
88
|
+
: ''
|
|
89
|
+
}`}
|
|
90
|
+
>
|
|
91
|
+
<span
|
|
92
|
+
className={`text-f5 text-on-base-2 leading-4 break-words inline-block pt-6 pb-2`}
|
|
93
|
+
>
|
|
94
|
+
{group.title}
|
|
95
|
+
</span>
|
|
96
|
+
</div>
|
|
97
|
+
)}
|
|
98
|
+
<div className="group-items">
|
|
99
|
+
{group.items.map((item, indexItem) => {
|
|
100
|
+
return (
|
|
101
|
+
<TableListItem
|
|
102
|
+
key={`group-item-${indexItem}`}
|
|
103
|
+
forceBorderDesktop={indexItem === 0 && indexGroup !== 0}
|
|
104
|
+
title={item.title}
|
|
105
|
+
description={item.description}
|
|
106
|
+
timestampTime={item.timestampTime}
|
|
107
|
+
timestampDate={item.timestampDate}
|
|
108
|
+
itemWrapper={itemWrapper}
|
|
109
|
+
itemWrapperProps={item.itemWrapperProps}
|
|
110
|
+
withIcon={item.withIcon}
|
|
111
|
+
withHover={withHover}
|
|
112
|
+
isInsideContainer={isInsideContainer}
|
|
113
|
+
/>
|
|
114
|
+
)
|
|
115
|
+
})}
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
)
|
|
119
|
+
})
|
|
120
|
+
)}
|
|
121
|
+
</div>
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const TableList = React.memo(TableListComponent)
|
|
126
|
+
|
|
127
|
+
export interface TableListProps
|
|
128
|
+
extends Pick<
|
|
129
|
+
TableListItemProps,
|
|
130
|
+
'withHover' | 'isInsideContainer' | 'itemWrapper'
|
|
131
|
+
> {
|
|
132
|
+
/**
|
|
133
|
+
* Custom class name
|
|
134
|
+
* */
|
|
135
|
+
className?: string
|
|
136
|
+
/**
|
|
137
|
+
* Items of the TableList
|
|
138
|
+
*/
|
|
139
|
+
items?: Omit<
|
|
140
|
+
TableListItemProps,
|
|
141
|
+
'forceBorderDesktop' | 'itemWrapper' | 'withHover'
|
|
142
|
+
>[]
|
|
143
|
+
/** TableList is loading
|
|
144
|
+
* @default false
|
|
145
|
+
*/
|
|
146
|
+
isLoading?: boolean
|
|
147
|
+
/**
|
|
148
|
+
* Content to show when TableList is empty
|
|
149
|
+
*/
|
|
150
|
+
empty?: {
|
|
151
|
+
/** Title when is empty
|
|
152
|
+
* @default 'Nenhum registro encontrado'
|
|
153
|
+
*/
|
|
154
|
+
title?: string | React.ReactNode
|
|
155
|
+
/**
|
|
156
|
+
* Subtitle when is empty
|
|
157
|
+
*/
|
|
158
|
+
subTitle?: string | React.ReactNode
|
|
159
|
+
/**
|
|
160
|
+
* Illustration or icon for when is empty
|
|
161
|
+
*/
|
|
162
|
+
illustration?: React.ReactNode
|
|
163
|
+
/**
|
|
164
|
+
* Action (button) for when is empty
|
|
165
|
+
*/
|
|
166
|
+
action?: React.ReactNode
|
|
167
|
+
}
|
|
168
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { IconProps } from '../../Icons'
|
|
2
|
+
|
|
3
|
+
export type TableListItemWrapperProp =
|
|
4
|
+
| React.ComponentClass<any>
|
|
5
|
+
| React.FunctionComponent<any>
|
|
6
|
+
|
|
7
|
+
export interface TableListItemProps {
|
|
8
|
+
/**
|
|
9
|
+
* Title of the item
|
|
10
|
+
*/
|
|
11
|
+
title: string | React.ReactNode
|
|
12
|
+
/**
|
|
13
|
+
* Description that appears above the title
|
|
14
|
+
*/
|
|
15
|
+
description?: string | React.ReactNode
|
|
16
|
+
/**
|
|
17
|
+
* Timestamp of the item, usually in HH:mm
|
|
18
|
+
*/
|
|
19
|
+
timestampTime?: string
|
|
20
|
+
/**
|
|
21
|
+
* Timestamp of the item, usually in dd/mm/yyyy
|
|
22
|
+
*/
|
|
23
|
+
timestampDate?: string
|
|
24
|
+
/**
|
|
25
|
+
* Icon to show at item
|
|
26
|
+
*/
|
|
27
|
+
withIcon?: {
|
|
28
|
+
/**
|
|
29
|
+
* Classes with text-color and background of icon
|
|
30
|
+
*/
|
|
31
|
+
class?: string
|
|
32
|
+
/**
|
|
33
|
+
* Icon to use
|
|
34
|
+
*/
|
|
35
|
+
icon?: IconProps['icon']
|
|
36
|
+
}
|
|
37
|
+
/** Force border top at desktop even if is first item
|
|
38
|
+
* @default false
|
|
39
|
+
*/
|
|
40
|
+
forceBorderDesktop?: boolean
|
|
41
|
+
/** Show hover effect
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
withHover?: boolean
|
|
45
|
+
/** Adds hover effect and mobile border with negative margin to fulfill container padding
|
|
46
|
+
* @default false
|
|
47
|
+
*/
|
|
48
|
+
isInsideContainer?: boolean
|
|
49
|
+
/**
|
|
50
|
+
* Props of the `item.itemWrapper`
|
|
51
|
+
*/
|
|
52
|
+
itemWrapperProps?: { [key: string]: unknown }
|
|
53
|
+
/**
|
|
54
|
+
* Component to wrap item. Usually an <a> or related. Props of each item are placed at `items.itemWrapperProps`
|
|
55
|
+
*/
|
|
56
|
+
itemWrapper?: TableListItemWrapperProp
|
|
57
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { composeStories } from "@storybook/testing-react"
|
|
3
|
+
import { mount } from "@cypress/react"
|
|
4
|
+
import * as stories from "./TableListItem.stories"
|
|
5
|
+
|
|
6
|
+
const { Item } = composeStories(stories)
|
|
7
|
+
|
|
8
|
+
describe('TableListItem tests', () => {
|
|
9
|
+
|
|
10
|
+
it('Default', () => {
|
|
11
|
+
mount(<Item />)
|
|
12
|
+
cy.get('.table-item')
|
|
13
|
+
.should('exist')
|
|
14
|
+
.should('not.have.class', 'lg:first:border-t')
|
|
15
|
+
.find('.table-item-wrapper')
|
|
16
|
+
.should('exist')
|
|
17
|
+
cy.get('.table-item .table-item-icon')
|
|
18
|
+
.should('exist')
|
|
19
|
+
.find('.table-item-icon-background')
|
|
20
|
+
.should('have.class', 'w-8')
|
|
21
|
+
.should('have.class', 'bg-warning-light')
|
|
22
|
+
.find('svg')
|
|
23
|
+
.should('exist')
|
|
24
|
+
cy.get('.table-item .table-item-content')
|
|
25
|
+
.find('.table-item-title')
|
|
26
|
+
.should('exist')
|
|
27
|
+
.contains('devolvida')
|
|
28
|
+
cy.get('.table-item .table-item-content')
|
|
29
|
+
.find('.table-item-description')
|
|
30
|
+
.should('exist')
|
|
31
|
+
.contains('Cartão')
|
|
32
|
+
cy.get('.table-item .table-item-timestamp .table-item-timestamp-time')
|
|
33
|
+
.should('exist')
|
|
34
|
+
.contains('19:45')
|
|
35
|
+
cy.get('.table-item .table-item-timestamp .table-item-timestamp-date')
|
|
36
|
+
.should('exist')
|
|
37
|
+
.contains('dezembro')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('Force Border Desktop', () => {
|
|
41
|
+
mount(<Item forceBorderDesktop={true} />)
|
|
42
|
+
cy.get('.table-item')
|
|
43
|
+
.should('have.class', 'lg:first:border-t')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
it('Without', () => {
|
|
47
|
+
mount(<Item withIcon={undefined} />)
|
|
48
|
+
cy.get('.table-item .table-item-icon')
|
|
49
|
+
.should('not.exist')
|
|
50
|
+
|
|
51
|
+
mount(<Item description={undefined} />)
|
|
52
|
+
cy.get('.table-item .table-item-description')
|
|
53
|
+
.should('not.exist')
|
|
54
|
+
|
|
55
|
+
mount(<Item timestampDate={undefined} />)
|
|
56
|
+
cy.get('.table-item .table-item-timestamp-date')
|
|
57
|
+
.should('not.exist')
|
|
58
|
+
|
|
59
|
+
mount(<Item timestampTime={undefined} />)
|
|
60
|
+
cy.get('.table-item .table-item-timestamp-time')
|
|
61
|
+
.should('not.exist')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
})
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Story, Meta } from '@storybook/react'
|
|
3
|
+
import { withDesign } from 'storybook-addon-designs'
|
|
4
|
+
|
|
5
|
+
import { TableListItemProps } from './TableListItem.interface'
|
|
6
|
+
import { TableListItem } from './TableListItem'
|
|
7
|
+
|
|
8
|
+
const CellLink = (props: any) => {
|
|
9
|
+
const { href = '/', children, ...restProps } = props
|
|
10
|
+
return (
|
|
11
|
+
<a href={href} {...restProps}>{children}</a>
|
|
12
|
+
)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
title: 'Components/TableList',
|
|
17
|
+
component: TableListItem,
|
|
18
|
+
decorators: [withDesign],
|
|
19
|
+
parameters: {
|
|
20
|
+
layout: 'padded',
|
|
21
|
+
},
|
|
22
|
+
args: {
|
|
23
|
+
title: 'R$ 49,90 devolvida parcialmente',
|
|
24
|
+
description: '#29102 - Daniela Cabral via Cartão de crédito',
|
|
25
|
+
timestampTime: '19:45',
|
|
26
|
+
timestampDate: '10 de dezembro',
|
|
27
|
+
itemWrapperProps: {
|
|
28
|
+
href: '#a'
|
|
29
|
+
},
|
|
30
|
+
withIcon: {
|
|
31
|
+
class: 'bg-warning-light text-warning-dark',
|
|
32
|
+
icon: 'clock',
|
|
33
|
+
},
|
|
34
|
+
forceBorderDesktop: false,
|
|
35
|
+
withHover: true,
|
|
36
|
+
isInsideContainer: true,
|
|
37
|
+
itemWrapper: CellLink,
|
|
38
|
+
},
|
|
39
|
+
} as Meta
|
|
40
|
+
|
|
41
|
+
const Template: Story<TableListItemProps> = (args) => <TableListItem {...args} />
|
|
42
|
+
|
|
43
|
+
export const Item = Template.bind({})
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { Icon } from '../../Icons'
|
|
4
|
+
import { TableListItemProps } from './TableListItem.interface'
|
|
5
|
+
import { TableListItemWrapper } from './TableListItemWrapper'
|
|
6
|
+
|
|
7
|
+
export const TableListItem: React.FunctionComponent<TableListItemProps> = ({
|
|
8
|
+
forceBorderDesktop = false,
|
|
9
|
+
title,
|
|
10
|
+
description,
|
|
11
|
+
timestampTime,
|
|
12
|
+
timestampDate,
|
|
13
|
+
itemWrapper,
|
|
14
|
+
itemWrapperProps,
|
|
15
|
+
withHover = false,
|
|
16
|
+
isInsideContainer = false,
|
|
17
|
+
withIcon,
|
|
18
|
+
}) => {
|
|
19
|
+
return (
|
|
20
|
+
<div
|
|
21
|
+
className={`table-item border-primary-bold border-opacity-10 border-t first:border-t-0 ${
|
|
22
|
+
forceBorderDesktop ? 'lg:first:border-t' : ''
|
|
23
|
+
}`}
|
|
24
|
+
>
|
|
25
|
+
<TableListItemWrapper
|
|
26
|
+
Wrapper={itemWrapper}
|
|
27
|
+
props={itemWrapperProps}
|
|
28
|
+
withHover={withHover}
|
|
29
|
+
isInsideContainer={isInsideContainer}
|
|
30
|
+
>
|
|
31
|
+
{withIcon && (
|
|
32
|
+
<div className="table-item-icon flex items-center justify-center flex-none mr-4">
|
|
33
|
+
<div
|
|
34
|
+
className={`table-item-icon-background h-8 w-8 flex items-center justify-center rounded ${
|
|
35
|
+
withIcon.class || ''
|
|
36
|
+
}`}
|
|
37
|
+
>
|
|
38
|
+
<Icon icon={withIcon.icon || 'minus'} block size={5} />
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
42
|
+
<div className="table-item-content flex flex-col justify-center flex-auto gap-1.5 min-w-0 w-full">
|
|
43
|
+
<div className="table-item-title text-f6 font-semibold">{title}</div>
|
|
44
|
+
{description && (
|
|
45
|
+
<div className="table-item-description">{description}</div>
|
|
46
|
+
)}
|
|
47
|
+
</div>
|
|
48
|
+
{timestampTime && (
|
|
49
|
+
<div className="table-item-timestamp flex flex-col justify-center items-end shrink-0 gap-1.5 ml-4 min-w-0 max-w-[50%] text-right">
|
|
50
|
+
<div className="table-item-timestamp-time w-full">
|
|
51
|
+
{timestampTime}
|
|
52
|
+
</div>
|
|
53
|
+
{timestampDate && (
|
|
54
|
+
<div className="table-item-timestamp-date w-full hidden lg:block">
|
|
55
|
+
{timestampDate}
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
)}
|
|
60
|
+
</TableListItemWrapper>
|
|
61
|
+
</div>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { composeStories } from "@storybook/testing-react"
|
|
3
|
+
import { mount } from "@cypress/react"
|
|
4
|
+
import * as stories from "./TableListItemLoading.stories"
|
|
5
|
+
|
|
6
|
+
const { ItemLoading } = composeStories(stories)
|
|
7
|
+
|
|
8
|
+
describe('TableListItemLoading tests', () => {
|
|
9
|
+
|
|
10
|
+
it('Default', () => {
|
|
11
|
+
mount(<ItemLoading />)
|
|
12
|
+
cy.get('.table-item.table-item-loading')
|
|
13
|
+
.should('exist')
|
|
14
|
+
.find('.table-item-content .table-item-title .animate-pulse')
|
|
15
|
+
.should('exist')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
})
|