@@ -2,15 +2,12 @@ import type { ComponentPropsWithoutRef } from 'react'
2
2
import React , { forwardRef , useMemo } from 'react'
3
3
import { Stack } from '../stack'
4
4
import { Action } from '../action'
5
- import {
6
- IconCaretDown ,
7
- IconCaretLeft ,
8
- IconCaretRight ,
9
- } from '@vtex/shoreline-icons'
5
+ import { IconCaretLeft , IconCaretRight } from '@vtex/shoreline-icons'
10
6
11
7
import './pagination.css'
12
- import { Select , SelectOption , SelectPopover , SelectProvider } from '../select'
13
- import { Bleed } from '../bleed'
8
+ import { SelectOption } from '../select'
9
+ import { Skeleton } from '../skeleton'
10
+ import { PaginationSelect } from './pagination-select'
14
11
15
12
/**
16
13
* Pagination triggers allow merchants to view the size of a list and navigate between pages.
@@ -35,90 +32,76 @@ export const Pagination = forwardRef<HTMLDivElement, PaginationProps>(
35
32
total,
36
33
onSizeChange,
37
34
onPageChange,
35
+ loading = false ,
38
36
...otherProps
39
37
} = props
40
38
41
39
const hasSizes = sizeOptions . length > 0
42
40
43
- const totalPages = Math . ceil ( total / size )
41
+ const totalPages = useMemo ( ( ) => Math . ceil ( total / size ) , [ total , size ] )
44
42
45
- const pageOptions = useMemo (
46
- ( ) => [ ...Array ( totalPages ) . keys ( ) ] . slice ( 1 ) ,
47
- [ total , size ]
48
- )
43
+ const pageOptions = useMemo ( ( ) => {
44
+ const totalPages = Math . ceil ( total / size )
45
+
46
+ return [ ...Array ( totalPages ) . keys ( ) ] . slice ( 1 )
47
+ } , [ total , size ] )
49
48
50
49
return (
51
50
< div data-sl-pagination ref = { ref } { ...otherProps } >
52
51
< Stack direction = "row" space = "$space-2" >
53
52
{ hasSizes && (
54
- < SelectProvider
55
- value = { String ( size ) }
56
- setValue = { ( value ) => onSizeChange ?.( Number ( value ) ) }
53
+ < PaginationSelect
54
+ data-sl-pagination-size-select
55
+ value = { size }
56
+ options = { sizeOptions }
57
+ onValueChange = { ( value ) => onSizeChange ?.( value ) }
58
+ label = { `Show ${ size } ` }
59
+ disabled = { loading }
57
60
>
58
- < Select asChild >
59
- < Action >
60
- Show { size } < IconCaretDown width = { 16 } height = { 16 } />
61
- </ Action >
62
- </ Select >
63
- < Bleed >
64
- < SelectPopover data-sl-pagination-select-popover >
65
- { sizeOptions . map ( ( sizeOption ) => (
66
- < SelectOption value = { String ( sizeOption ) } >
67
- Show { sizeOption }
68
- </ SelectOption >
69
- ) ) }
70
- </ SelectPopover >
71
- </ Bleed >
72
- </ SelectProvider >
61
+ { sizeOptions . map ( ( option ) => (
62
+ < SelectOption value = { String ( option ) } >
63
+ Show { option }
64
+ </ SelectOption >
65
+ ) ) }
66
+ </ PaginationSelect >
73
67
) }
74
68
75
- < div data-sl-pagination-total-label > { total } items</ div >
69
+ < div data-sl-pagination-total-label data-loading = { loading } >
70
+ { loading ? < Skeleton /> : `${ total } items` }
71
+ </ div >
76
72
77
73
< div data-sl-pagination-actions >
78
74
< Action
79
75
iconOnly
80
76
onClick = { ( ) => {
81
77
onPageChange ?.( page - 1 , 'prev' )
82
78
} }
83
- disabled = { page === 1 }
79
+ disabled = { page === 1 || loading }
84
80
aria-label = "Previous page"
85
81
data-sl-pagination-action-prev
86
82
>
87
83
< IconCaretLeft />
88
84
</ Action >
89
85
90
- { totalPages === 1 ? (
91
- < div data-sl-pagination-page-label >
92
- { page } of { totalPages }
93
- </ div >
94
- ) : (
95
- < SelectProvider
96
- value = { String ( page ) }
97
- setValue = { ( value ) => onPageChange ?.( Number ( value ) , 'selection' ) }
98
- >
99
- < Select asChild >
100
- < Action >
101
- { page } of { totalPages }
102
- </ Action >
103
- </ Select >
104
- < Bleed >
105
- < SelectPopover data-sl-pagination-select-popover >
106
- { pageOptions . map ( ( pageOption ) => (
107
- < SelectOption value = { String ( pageOption ) } >
108
- { pageOption }
109
- </ SelectOption >
110
- ) ) }
111
- </ SelectPopover >
112
- </ Bleed >
113
- </ SelectProvider >
114
- ) }
86
+ < PaginationSelect
87
+ data-sl-pagination-page-select
88
+ onValueChange = { ( value ) => onPageChange ?.( value , 'selection' ) }
89
+ value = { page }
90
+ options = { pageOptions }
91
+ loading = { loading }
92
+ label = { `${ page } of ${ pageOptions . length } ` }
93
+ >
94
+ { pageOptions . map ( ( option ) => (
95
+ < SelectOption value = { String ( option ) } > { option } </ SelectOption >
96
+ ) ) }
97
+ </ PaginationSelect >
115
98
116
99
< Action
117
100
iconOnly
118
101
onClick = { ( ) => {
119
102
onPageChange ?.( page + 1 , 'next' )
120
103
} }
121
- disabled = { page === totalPages }
104
+ disabled = { page === totalPages || loading }
122
105
aria-label = "Next page"
123
106
data-sl-pagination-action-next
124
107
>
@@ -138,4 +121,5 @@ export interface PaginationProps extends ComponentPropsWithoutRef<'div'> {
138
121
size : number
139
122
page : number
140
123
total : number
124
+ loading ?: boolean
141
125
}
0 commit comments