@loadsmart/loadsmart-ui 5.2.1 → 5.3.0
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/Icon/Icon.d.ts +1 -0
- package/dist/components/TablePagination/RowsPerPage.d.ts +4 -0
- package/dist/components/TablePagination/TablePagination.d.ts +4 -0
- package/dist/components/TablePagination/TablePagination.stories.d.ts +5 -0
- package/dist/components/TablePagination/TablePagination.styles.d.ts +5 -0
- package/dist/components/TablePagination/TablePagination.test.d.ts +1 -0
- package/dist/components/TablePagination/TablePagination.types.d.ts +50 -0
- package/dist/components/TablePagination/TablePaginationActions.d.ts +11 -0
- package/dist/components/TablePagination/index.d.ts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +444 -436
- package/dist/index.js.map +1 -1
- package/dist/utils/toolset/keyboard.d.ts +4 -0
- package/package.json +1 -1
- package/src/components/Icon/Icon.tsx +2 -0
- package/src/components/Icon/assets/caret-right-last.svg +4 -0
- package/src/components/TablePagination/RowsPerPage.tsx +76 -0
- package/src/components/TablePagination/TablePagination.stories.tsx +37 -0
- package/src/components/TablePagination/TablePagination.styles.ts +13 -0
- package/src/components/TablePagination/TablePagination.test.tsx +112 -0
- package/src/components/TablePagination/TablePagination.tsx +51 -0
- package/src/components/TablePagination/TablePagination.types.ts +59 -0
- package/src/components/TablePagination/TablePaginationActions.tsx +144 -0
- package/src/components/TablePagination/index.ts +2 -0
- package/src/index.ts +3 -0
- package/src/utils/toolset/keyboard.ts +4 -0
|
@@ -11,6 +11,10 @@ declare const SUPPORTED_KEYS: {
|
|
|
11
11
|
SHIFT: string;
|
|
12
12
|
SPACE: string;
|
|
13
13
|
TAB: string;
|
|
14
|
+
E_LOWERCASE: string;
|
|
15
|
+
DOT: string;
|
|
16
|
+
PLUS: string;
|
|
17
|
+
MINUS: string;
|
|
14
18
|
};
|
|
15
19
|
export declare type SupportedKey = keyof typeof SUPPORTED_KEYS;
|
|
16
20
|
export declare function getKeyboardKey(e: KeyboardEvent): KeyboardEvent['key'];
|
package/package.json
CHANGED
|
@@ -20,6 +20,7 @@ import SortIcon from './assets/sort.svg'
|
|
|
20
20
|
import UploadIcon from './assets/upload.svg'
|
|
21
21
|
import WarningIcon from './assets/warning.svg'
|
|
22
22
|
import DotsHorizontalIcon from './assets/dots-horizontal.svg'
|
|
23
|
+
import CaretRightLastIcon from './assets/caret-right-last.svg'
|
|
23
24
|
|
|
24
25
|
import type { IconProps as GenericIconProps } from '../IconFactory'
|
|
25
26
|
|
|
@@ -44,6 +45,7 @@ const icons = {
|
|
|
44
45
|
upload: UploadIcon as JSX.Element,
|
|
45
46
|
warning: WarningIcon as JSX.Element,
|
|
46
47
|
'dots-horizontal': DotsHorizontalIcon as JSX.Element,
|
|
48
|
+
'caret-right-last': CaretRightLastIcon as JSX.Element,
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
const Icon = IconFactory(icons)
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg viewBox="0 0 48 48" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.2501 6.38126L14.1842 10.4471L27.7371 24L14.1842 37.5529L18.2501 41.6187L31.803 28.0659L35.8688 24L31.803 19.9341L18.2501 6.38126Z"/>
|
|
3
|
+
<path fill-rule="evenodd" clip-rule="evenodd" d="M40.2922 38.375L44.1256 38.375L44.1256 9.625L40.2922 9.625L40.2922 38.375Z"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Text } from 'components/Text'
|
|
3
|
+
import { Dropdown, DropdownContext } from 'components/Dropdown'
|
|
4
|
+
import { Layout } from 'components/Layout'
|
|
5
|
+
import { Icon } from 'components/Icon'
|
|
6
|
+
import { RowsPerPageProps } from './TablePagination.types'
|
|
7
|
+
import { ButtonProps } from 'components/Button'
|
|
8
|
+
import { NoPaddingButton } from './TablePagination.styles'
|
|
9
|
+
|
|
10
|
+
const TriggerButton = (props: Omit<ButtonProps, 'scale' | 'variant'>) => {
|
|
11
|
+
const { toggle } = React.useContext(DropdownContext)
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<NoPaddingButton data-testid="rows-per-page-button" onClick={toggle} {...props}>
|
|
15
|
+
<Icon name="caret-down" size={16} color="neutral-darker" />
|
|
16
|
+
</NoPaddingButton>
|
|
17
|
+
)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function RowsPerPage({
|
|
21
|
+
page,
|
|
22
|
+
rowsPerPage,
|
|
23
|
+
onRowsPerPageChange,
|
|
24
|
+
labelRowsPerPage,
|
|
25
|
+
count,
|
|
26
|
+
rowsPerPageOptions,
|
|
27
|
+
disabled = false,
|
|
28
|
+
}: RowsPerPageProps): JSX.Element {
|
|
29
|
+
const getItemsRange = () => {
|
|
30
|
+
if (!count) {
|
|
31
|
+
return 0
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const from = page * rowsPerPage + 1
|
|
35
|
+
let to = (page + 1) * rowsPerPage
|
|
36
|
+
|
|
37
|
+
if (to > count) {
|
|
38
|
+
to = count
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return `${from}-${to}`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<Layout.Group space="s" align="center">
|
|
46
|
+
<Text variant="caption" color={disabled ? 'color-neutral' : 'color-neutral-dark'}>
|
|
47
|
+
{labelRowsPerPage}
|
|
48
|
+
</Text>
|
|
49
|
+
<Text variant="body" color={disabled ? 'color-neutral' : 'color-neutral-dark'}>
|
|
50
|
+
<Text variant="body-bold" color={disabled ? 'color-neutral' : 'color-neutral-dark'}>
|
|
51
|
+
{getItemsRange()}
|
|
52
|
+
</Text>{' '}
|
|
53
|
+
of{' '}
|
|
54
|
+
<Text variant="body-bold" color={disabled ? 'color-neutral' : 'color-neutral-dark'}>
|
|
55
|
+
{count}
|
|
56
|
+
</Text>
|
|
57
|
+
</Text>
|
|
58
|
+
<Dropdown>
|
|
59
|
+
<TriggerButton disabled={disabled} />
|
|
60
|
+
<Dropdown.Menu>
|
|
61
|
+
{rowsPerPageOptions.map((option) => (
|
|
62
|
+
<Dropdown.Item
|
|
63
|
+
key={option}
|
|
64
|
+
onClick={() => onRowsPerPageChange(option)}
|
|
65
|
+
trailing={option === rowsPerPage && <Icon name="check" size={20} color="accent" />}
|
|
66
|
+
>
|
|
67
|
+
{option} per page
|
|
68
|
+
</Dropdown.Item>
|
|
69
|
+
))}
|
|
70
|
+
</Dropdown.Menu>
|
|
71
|
+
</Dropdown>
|
|
72
|
+
</Layout.Group>
|
|
73
|
+
)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export default RowsPerPage
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { useState } from 'react'
|
|
2
|
+
import TablePagination from './TablePagination'
|
|
3
|
+
import { Meta, Story } from '@storybook/react/types-6-0'
|
|
4
|
+
|
|
5
|
+
import type { TablePaginationProps } from './TablePagination.types'
|
|
6
|
+
import { Layout } from 'components/Layout'
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Components/TablePagination',
|
|
10
|
+
component: TablePagination,
|
|
11
|
+
argTypes: {},
|
|
12
|
+
} as Meta
|
|
13
|
+
|
|
14
|
+
export const Playground: Story<TablePaginationProps> = (args: TablePaginationProps) => {
|
|
15
|
+
const [page, setPage] = useState(args.page)
|
|
16
|
+
const [rowsPerPage, setRowsPerPage] = useState(args.rowsPerPage)
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Layout.Group>
|
|
20
|
+
<TablePagination
|
|
21
|
+
{...args}
|
|
22
|
+
onPageChange={(page) => setPage(page)}
|
|
23
|
+
page={page}
|
|
24
|
+
rowsPerPage={rowsPerPage}
|
|
25
|
+
onRowsPerPageChange={setRowsPerPage}
|
|
26
|
+
/>
|
|
27
|
+
</Layout.Group>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
Playground.args = {
|
|
32
|
+
page: 0,
|
|
33
|
+
count: 1004,
|
|
34
|
+
rowsPerPage: 100,
|
|
35
|
+
disabled: false,
|
|
36
|
+
variant: 'default',
|
|
37
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import userEvent from '@testing-library/user-event'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
|
|
4
|
+
import renderer, { screen } from '../../../tests/renderer'
|
|
5
|
+
|
|
6
|
+
import TablePagination from './TablePagination'
|
|
7
|
+
import { TablePaginationProps } from './TablePagination.types'
|
|
8
|
+
|
|
9
|
+
describe('TablePagination', () => {
|
|
10
|
+
const setup = ({ ...overrides }: Partial<TablePaginationProps> = {}) => {
|
|
11
|
+
const defaultProps: TablePaginationProps = {
|
|
12
|
+
variant: 'default',
|
|
13
|
+
count: 1000,
|
|
14
|
+
onPageChange: jest.fn(),
|
|
15
|
+
onRowsPerPageChange: jest.fn(),
|
|
16
|
+
rowsPerPage: 100,
|
|
17
|
+
page: 0,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
renderer(<TablePagination {...defaultProps} {...overrides} />).render()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
it('disables preview page buttons if page = 0', () => {
|
|
24
|
+
setup()
|
|
25
|
+
|
|
26
|
+
expect(screen.getByTitle(/previous page/i)).toBeDisabled()
|
|
27
|
+
expect(screen.getByTitle(/first page/i)).toBeDisabled()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('disables next and last page buttons if the page is the last one', () => {
|
|
31
|
+
setup({
|
|
32
|
+
page: 9,
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
expect(screen.getByTitle(/next page/i)).toBeDisabled()
|
|
36
|
+
expect(screen.getByTitle(/last page/i)).toBeDisabled()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('calls the onChangePage action after the pagination actions are clicked', () => {
|
|
40
|
+
const onPageChange = jest.fn()
|
|
41
|
+
setup({
|
|
42
|
+
page: 2,
|
|
43
|
+
onPageChange,
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
userEvent.click(screen.getByTitle(/previous page/i))
|
|
47
|
+
expect(onPageChange).toHaveBeenLastCalledWith(1)
|
|
48
|
+
userEvent.click(screen.getByTitle(/first page/i))
|
|
49
|
+
expect(onPageChange).toHaveBeenLastCalledWith(0)
|
|
50
|
+
userEvent.click(screen.getByTitle(/next page/i))
|
|
51
|
+
expect(onPageChange).toHaveBeenLastCalledWith(3)
|
|
52
|
+
userEvent.click(screen.getByTitle(/last page/i))
|
|
53
|
+
expect(onPageChange).toHaveBeenLastCalledWith(9)
|
|
54
|
+
|
|
55
|
+
userEvent.clear(screen.getByTitle('Page'))
|
|
56
|
+
userEvent.type(screen.getByTitle('Page'), '5')
|
|
57
|
+
userEvent.tab()
|
|
58
|
+
expect(onPageChange).toHaveBeenLastCalledWith(4)
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('calls the onRowsPerPageChange with the selected option', () => {
|
|
62
|
+
const onPageChange = jest.fn()
|
|
63
|
+
const onRowsPerPageChange = jest.fn()
|
|
64
|
+
setup({
|
|
65
|
+
page: 2,
|
|
66
|
+
onPageChange,
|
|
67
|
+
onRowsPerPageChange,
|
|
68
|
+
})
|
|
69
|
+
userEvent.click(screen.getByTestId('rows-per-page-button'))
|
|
70
|
+
userEvent.click(screen.getByText(/50 per page/i))
|
|
71
|
+
|
|
72
|
+
expect(onRowsPerPageChange).toHaveBeenLastCalledWith(50)
|
|
73
|
+
expect(onPageChange).toHaveBeenLastCalledWith(0)
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('hides some actions for the compact variant', () => {
|
|
77
|
+
setup({
|
|
78
|
+
variant: 'compact',
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
expect(screen.queryByTitle(/first page/i)).not.toBeInTheDocument()
|
|
82
|
+
expect(screen.queryByTitle(/last page/i)).not.toBeInTheDocument()
|
|
83
|
+
expect(screen.queryByTitle('Page')).not.toBeInTheDocument()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('disables all the buttons when the component is disabled', () => {
|
|
87
|
+
setup({
|
|
88
|
+
disabled: true,
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
expect(screen.getByTitle('Page')).toBeDisabled()
|
|
92
|
+
expect(screen.getByTitle(/previous page/i)).toBeDisabled()
|
|
93
|
+
expect(screen.getByTitle(/first page/i)).toBeDisabled()
|
|
94
|
+
expect(screen.getByTitle(/next page/i)).toBeDisabled()
|
|
95
|
+
expect(screen.getByTitle(/last page/i)).toBeDisabled()
|
|
96
|
+
expect(screen.getByTestId('rows-per-page-button')).toBeDisabled()
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('displays no pages state when no items available', () => {
|
|
100
|
+
setup({
|
|
101
|
+
count: 0,
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
expect(screen.getByTitle('Page')).toHaveValue(0)
|
|
105
|
+
expect(screen.getByTitle('Page')).toBeDisabled()
|
|
106
|
+
expect(screen.getByTitle(/previous page/i)).toBeDisabled()
|
|
107
|
+
expect(screen.getByTitle(/first page/i)).toBeDisabled()
|
|
108
|
+
expect(screen.getByTitle(/next page/i)).toBeDisabled()
|
|
109
|
+
expect(screen.getByTitle(/last page/i)).toBeDisabled()
|
|
110
|
+
expect(screen.getByTestId('rows-per-page-button')).toBeDisabled()
|
|
111
|
+
})
|
|
112
|
+
})
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { Layout } from 'components/Layout'
|
|
4
|
+
|
|
5
|
+
import type { TablePaginationProps } from './TablePagination.types'
|
|
6
|
+
import TablePaginationActions from 'components/TablePagination/TablePaginationActions'
|
|
7
|
+
import RowsPerPage from 'components/TablePagination/RowsPerPage'
|
|
8
|
+
|
|
9
|
+
function TablePagination(props: TablePaginationProps): JSX.Element {
|
|
10
|
+
const {
|
|
11
|
+
variant = 'default',
|
|
12
|
+
count,
|
|
13
|
+
labelRowsPerPage = 'Rows per page:',
|
|
14
|
+
onPageChange,
|
|
15
|
+
onRowsPerPageChange,
|
|
16
|
+
page,
|
|
17
|
+
rowsPerPage = 50,
|
|
18
|
+
rowsPerPageOptions = [10, 25, 50, 100],
|
|
19
|
+
disabled = false,
|
|
20
|
+
...rest
|
|
21
|
+
} = props
|
|
22
|
+
|
|
23
|
+
const handleRowsPerPageChange = (selectedOption: number) => {
|
|
24
|
+
onRowsPerPageChange(selectedOption)
|
|
25
|
+
onPageChange(0)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<Layout.Group space="xl" align="center" justify="space-between" {...rest}>
|
|
30
|
+
<RowsPerPage
|
|
31
|
+
page={page}
|
|
32
|
+
count={count}
|
|
33
|
+
onRowsPerPageChange={handleRowsPerPageChange}
|
|
34
|
+
rowsPerPage={rowsPerPage}
|
|
35
|
+
rowsPerPageOptions={rowsPerPageOptions}
|
|
36
|
+
labelRowsPerPage={labelRowsPerPage}
|
|
37
|
+
disabled={disabled || !count}
|
|
38
|
+
/>
|
|
39
|
+
<TablePaginationActions
|
|
40
|
+
variant={variant}
|
|
41
|
+
page={page}
|
|
42
|
+
onPageChange={onPageChange}
|
|
43
|
+
rowsPerPage={rowsPerPage}
|
|
44
|
+
count={count}
|
|
45
|
+
disabled={disabled || !count}
|
|
46
|
+
/>
|
|
47
|
+
</Layout.Group>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default TablePagination
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { GroupProps } from 'components/Layout/Group'
|
|
2
|
+
|
|
3
|
+
export interface TablePaginationProps extends GroupProps {
|
|
4
|
+
/**
|
|
5
|
+
* The pagination variant
|
|
6
|
+
* @default 'default'
|
|
7
|
+
*/
|
|
8
|
+
variant?: 'compact' | 'default'
|
|
9
|
+
/**
|
|
10
|
+
* The total number of paginated items
|
|
11
|
+
*/
|
|
12
|
+
count: number
|
|
13
|
+
/**
|
|
14
|
+
* Customize the rows per page label.
|
|
15
|
+
* @default 'Rows per page:'
|
|
16
|
+
*/
|
|
17
|
+
labelRowsPerPage?: string
|
|
18
|
+
/**
|
|
19
|
+
* Callback fired when the page is changed.
|
|
20
|
+
*/
|
|
21
|
+
onPageChange: (page: number) => void
|
|
22
|
+
/**
|
|
23
|
+
* Callback fired when the number of rows per page is changed.
|
|
24
|
+
*/
|
|
25
|
+
onRowsPerPageChange: (rowsPerPage: number) => void
|
|
26
|
+
/**
|
|
27
|
+
* The number of rows per page.
|
|
28
|
+
* @default 50
|
|
29
|
+
*/
|
|
30
|
+
rowsPerPage?: number
|
|
31
|
+
/**
|
|
32
|
+
* The zero-based index of the current page.
|
|
33
|
+
*/
|
|
34
|
+
page: number
|
|
35
|
+
/**
|
|
36
|
+
* Customizes the options of the rows per page select field.
|
|
37
|
+
* @default [10, 25, 50, 100]
|
|
38
|
+
*/
|
|
39
|
+
rowsPerPageOptions?: number[]
|
|
40
|
+
/**
|
|
41
|
+
* Disable all the pagination actions
|
|
42
|
+
*/
|
|
43
|
+
disabled?: boolean
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type TablePaginationActionsProps = Omit<
|
|
47
|
+
TablePaginationProps,
|
|
48
|
+
'labelRowsPerPage' | 'onRowsPerPageChange' | 'rowsPerPageOptions' | 'rowsPerPage'
|
|
49
|
+
> & {
|
|
50
|
+
rowsPerPage: number
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export type RowsPerPageProps = Omit<
|
|
54
|
+
TablePaginationProps,
|
|
55
|
+
'rowsPerPageOptions' | 'onPageChange' | 'rowsPerPage'
|
|
56
|
+
> & {
|
|
57
|
+
rowsPerPageOptions: number[]
|
|
58
|
+
rowsPerPage: number
|
|
59
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import React, { ChangeEvent, KeyboardEvent, useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import { Layout } from 'components/Layout'
|
|
4
|
+
import { Text } from 'components/Text'
|
|
5
|
+
import { TextField } from 'components/TextField'
|
|
6
|
+
import { TablePaginationActionsProps } from 'components/TablePagination/TablePagination.types'
|
|
7
|
+
import styled from 'styled-components'
|
|
8
|
+
import { Icon, IconProps } from 'components/Icon'
|
|
9
|
+
import Keyboard from 'utils/toolset/keyboard'
|
|
10
|
+
import { NoPaddingButton } from './TablePagination.styles'
|
|
11
|
+
import { prop } from 'tools/index'
|
|
12
|
+
|
|
13
|
+
export const ActionIcon = styled(Icon).attrs({
|
|
14
|
+
color: 'neutral-darker',
|
|
15
|
+
size: '16',
|
|
16
|
+
})<IconProps & { rotate?: number }>`
|
|
17
|
+
transform: rotate(${prop('rotate', 0)}deg);
|
|
18
|
+
`
|
|
19
|
+
|
|
20
|
+
function TablePaginationActions({
|
|
21
|
+
variant = 'default',
|
|
22
|
+
disabled = false,
|
|
23
|
+
onPageChange,
|
|
24
|
+
page,
|
|
25
|
+
count,
|
|
26
|
+
rowsPerPage,
|
|
27
|
+
}: TablePaginationActionsProps): JSX.Element {
|
|
28
|
+
const totalPages = Math.ceil(count / rowsPerPage)
|
|
29
|
+
const [pageValue, setPageValue] = useState<number | ''>(page + 1)
|
|
30
|
+
const isCompact = variant === 'compact'
|
|
31
|
+
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
setPageValue(page + 1)
|
|
34
|
+
}, [page])
|
|
35
|
+
|
|
36
|
+
const handleFirstPageClick = () => {
|
|
37
|
+
onPageChange(0)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const handlePreviousPageClick = () => {
|
|
41
|
+
onPageChange(page - 1)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const handleNextPageClick = () => {
|
|
45
|
+
onPageChange(page + 1)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const handleLastPageClick = () => {
|
|
49
|
+
onPageChange(totalPages - 1)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const publishPageChange = () => {
|
|
53
|
+
if (pageValue && pageValue - 1 !== page) {
|
|
54
|
+
onPageChange(pageValue - 1)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const handleKeyUp = (e: KeyboardEvent) => {
|
|
59
|
+
if (Keyboard(e).is('ENTER')) {
|
|
60
|
+
publishPageChange()
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const handleKeyDown = (e: KeyboardEvent) => {
|
|
65
|
+
if (Keyboard(e).is(['E_LOWERCASE', 'DOT', 'MINUS', 'PLUS'])) {
|
|
66
|
+
e.preventDefault()
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const handlePageChange = (e: ChangeEvent<HTMLInputElement>) => {
|
|
71
|
+
if (e.target.value === '') {
|
|
72
|
+
setPageValue('')
|
|
73
|
+
return
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const numberValue = Number(e.target.value)
|
|
77
|
+
|
|
78
|
+
if (!numberValue || numberValue < 1 || numberValue > totalPages) return
|
|
79
|
+
|
|
80
|
+
setPageValue(numberValue)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<Layout.Group space="s" align="center">
|
|
85
|
+
{!isCompact && (
|
|
86
|
+
<NoPaddingButton
|
|
87
|
+
onClick={handleFirstPageClick}
|
|
88
|
+
disabled={page === 0 || disabled}
|
|
89
|
+
title="First page"
|
|
90
|
+
>
|
|
91
|
+
<ActionIcon name="caret-right-last" rotate={180} />
|
|
92
|
+
</NoPaddingButton>
|
|
93
|
+
)}
|
|
94
|
+
<NoPaddingButton
|
|
95
|
+
onClick={handlePreviousPageClick}
|
|
96
|
+
disabled={page === 0 || disabled}
|
|
97
|
+
title="Previous page"
|
|
98
|
+
>
|
|
99
|
+
<ActionIcon name="caret-left" />
|
|
100
|
+
</NoPaddingButton>
|
|
101
|
+
{!isCompact && (
|
|
102
|
+
<>
|
|
103
|
+
<TextField
|
|
104
|
+
type="number"
|
|
105
|
+
min={1}
|
|
106
|
+
max={totalPages}
|
|
107
|
+
disabled={disabled || totalPages === 1}
|
|
108
|
+
onChange={handlePageChange}
|
|
109
|
+
onBlur={publishPageChange}
|
|
110
|
+
onKeyUp={handleKeyUp}
|
|
111
|
+
onKeyDown={handleKeyDown}
|
|
112
|
+
scale="small"
|
|
113
|
+
value={count ? pageValue : 0}
|
|
114
|
+
title="Page"
|
|
115
|
+
/>
|
|
116
|
+
<Text variant="body" color={disabled ? 'color-neutral' : 'color-neutral-dark'}>
|
|
117
|
+
of{' '}
|
|
118
|
+
<Text variant="body-bold" color={disabled ? 'color-neutral' : 'color-neutral-dark'}>
|
|
119
|
+
{totalPages}
|
|
120
|
+
</Text>
|
|
121
|
+
</Text>
|
|
122
|
+
</>
|
|
123
|
+
)}
|
|
124
|
+
<NoPaddingButton
|
|
125
|
+
onClick={handleNextPageClick}
|
|
126
|
+
disabled={page >= totalPages - 1 || disabled}
|
|
127
|
+
title="Next page"
|
|
128
|
+
>
|
|
129
|
+
<ActionIcon name="caret-right" />
|
|
130
|
+
</NoPaddingButton>
|
|
131
|
+
{!isCompact && (
|
|
132
|
+
<NoPaddingButton
|
|
133
|
+
onClick={handleLastPageClick}
|
|
134
|
+
disabled={page >= totalPages - 1 || disabled}
|
|
135
|
+
title="Last page"
|
|
136
|
+
>
|
|
137
|
+
<ActionIcon name="caret-right-last" />
|
|
138
|
+
</NoPaddingButton>
|
|
139
|
+
)}
|
|
140
|
+
</Layout.Group>
|
|
141
|
+
)
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default TablePaginationActions
|
package/src/index.ts
CHANGED
|
@@ -173,3 +173,6 @@ export type {
|
|
|
173
173
|
DragDropFileProviderProps,
|
|
174
174
|
DragDropFileContextValue,
|
|
175
175
|
} from './components/DragDropFile/types'
|
|
176
|
+
|
|
177
|
+
export { TablePagination } from './components/TablePagination'
|
|
178
|
+
export type { TablePaginationProps } from './components/TablePagination'
|