playbook_ui 14.24.0.pre.alpha.PLAY23139411 → 14.24.0.pre.alpha.pinnedrowstyling9518
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +4 -1
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +34 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_vertical_border.html.erb +43 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_vertical_border.jsx +64 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.rb +1 -1
- data/app/pb_kits/playbook/pb_date/_date.tsx +5 -3
- data/app/pb_kits/playbook/pb_date/date.html.erb +6 -6
- data/app/pb_kits/playbook/pb_date/date.rb +2 -0
- data/app/pb_kits/playbook/pb_date/docs/_date_with_show_current_year.html.erb +4 -0
- data/app/pb_kits/playbook/pb_date/docs/_date_with_show_current_year.jsx +17 -0
- data/app/pb_kits/playbook/pb_date/docs/_date_with_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_date/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_date/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_pagination/_pagination.test.jsx +212 -0
- data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +8 -1
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_external_control.jsx +112 -0
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_external_control_react.md +3 -0
- data/app/pb_kits/playbook/pb_pagination/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_pagination/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_table/styles/_vertical_border.scss +49 -1
- data/dist/chunks/{_weekday_stacked-B89kArHY.js → _weekday_stacked-BMK9Dgq_.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +11 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7481afedb2c92cfae1bdef5524d1a81c96124a47eada550b364c73f5daab1a0
|
4
|
+
data.tar.gz: 1588d96984a5b11a93919c7b6997bd061745d3bce2c9db6eb415cbd86a1c1640
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8dda5243d42cbab7f6fdb74497ca883fc07b45bcd50d6530c88178d6f17aa4243986e500773d7f33165bf8348fb4a0e1b552c2aa16490b467042c6677c357b6e
|
7
|
+
data.tar.gz: f614f7c282b1ac7096f90eb8d0fb593431bf60b91571b1f9db322f2ddbff942a7b4e10a67e605c2032001cd3ad66919e3067b442e8a619c2cde464cfb2512a1b
|
@@ -134,13 +134,15 @@ export const RegularTableView = ({
|
|
134
134
|
const columnDefinitions = table.options.meta?.columnDefinitions || [];
|
135
135
|
// Row pinning
|
136
136
|
function PinnedRow({ row }: { row: Row<any> }) {
|
137
|
+
const customRowStyle = rowStyling?.length > 0 && rowStyling?.find((s: GenericObject) => s?.rowId === row.id);
|
137
138
|
return (
|
138
139
|
<tr
|
139
140
|
className={classnames(
|
140
141
|
`pinned-row`,
|
141
142
|
)}
|
142
143
|
style={{
|
143
|
-
backgroundColor: 'white',
|
144
|
+
backgroundColor: customRowStyle?.backgroundColor ? customRowStyle?.backgroundColor : 'white',
|
145
|
+
color: customRowStyle?.fontColor,
|
144
146
|
position: 'sticky',
|
145
147
|
top:
|
146
148
|
row.getIsPinned() === 'top'
|
@@ -153,6 +155,7 @@ export const RegularTableView = ({
|
|
153
155
|
collapsibleTrail={collapsibleTrail}
|
154
156
|
columnDefinitions={columnDefinitions}
|
155
157
|
columnPinning={columnPinning}
|
158
|
+
customRowStyle={customRowStyle}
|
156
159
|
loading={loading}
|
157
160
|
row={row}
|
158
161
|
stickyLeftColumn={stickyLeftColumn}
|
@@ -971,6 +971,40 @@
|
|
971
971
|
}
|
972
972
|
}
|
973
973
|
}
|
974
|
+
|
975
|
+
// Firefox-specific fix for last-header-cell and last-cell vertical borders
|
976
|
+
@-moz-document url-prefix() {
|
977
|
+
.pb_advanced_table_header {
|
978
|
+
.last-header-cell {
|
979
|
+
border-right: none !important;
|
980
|
+
box-shadow: 1px 0 0 0 $border_light !important;
|
981
|
+
}
|
982
|
+
}
|
983
|
+
|
984
|
+
.pb_advanced_table_body {
|
985
|
+
.last-cell {
|
986
|
+
border-right: none !important;
|
987
|
+
box-shadow: 1px 0 0 0 $border_light !important;
|
988
|
+
}
|
989
|
+
}
|
990
|
+
|
991
|
+
// Dark mode Firefox fixes
|
992
|
+
&.dark {
|
993
|
+
.pb_advanced_table_header {
|
994
|
+
.last-header-cell {
|
995
|
+
border-right: none !important;
|
996
|
+
box-shadow: 1px 0 0 0 $border_dark !important;
|
997
|
+
}
|
998
|
+
}
|
999
|
+
|
1000
|
+
.pb_advanced_table_body {
|
1001
|
+
.last-cell {
|
1002
|
+
border-right: none !important;
|
1003
|
+
box-shadow: 1px 0 0 0 $border_dark !important;
|
1004
|
+
}
|
1005
|
+
}
|
1006
|
+
}
|
1007
|
+
}
|
974
1008
|
}
|
975
1009
|
|
976
1010
|
// Outside of the pb_advanced_table class for popover
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<% column_definitions = [
|
2
|
+
{
|
3
|
+
accessor: "year",
|
4
|
+
label: "Year",
|
5
|
+
cellAccessors: ["quarter", "month", "day"],
|
6
|
+
},
|
7
|
+
{
|
8
|
+
label: "Enrollment Data",
|
9
|
+
columns: [
|
10
|
+
{
|
11
|
+
accessor: "newEnrollments",
|
12
|
+
label: "New Enrollments",
|
13
|
+
},
|
14
|
+
{
|
15
|
+
accessor: "scheduledMeetings",
|
16
|
+
label: "Scheduled Meetings",
|
17
|
+
},
|
18
|
+
],
|
19
|
+
},
|
20
|
+
{
|
21
|
+
label: "Performance Data",
|
22
|
+
columns: [
|
23
|
+
{
|
24
|
+
accessor: "attendanceRate",
|
25
|
+
label: "Attendance Rate",
|
26
|
+
},
|
27
|
+
{
|
28
|
+
accessor: "completedClasses",
|
29
|
+
label: "Completed Classes",
|
30
|
+
},
|
31
|
+
{
|
32
|
+
accessor: "classCompletionRate",
|
33
|
+
label: "Class Completion Rate",
|
34
|
+
},
|
35
|
+
{
|
36
|
+
accessor: "graduatedStudents",
|
37
|
+
label: "Graduated Students",
|
38
|
+
},
|
39
|
+
],
|
40
|
+
},
|
41
|
+
] %>
|
42
|
+
|
43
|
+
<%= pb_rails("advanced_table", props: { id: "table_multi_headers_vertical_borders", table_data: @table_data, column_definitions: column_definitions, table_props: { vertical_border: true } }) %>
|
data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_vertical_border.jsx
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
import React from "react"
|
2
|
+
import AdvancedTable from '../../pb_advanced_table/_advanced_table'
|
3
|
+
import MOCK_DATA from "./advanced_table_mock_data.json"
|
4
|
+
|
5
|
+
const AdvancedTableColumnHeadersVerticalBorder = (props) => {
|
6
|
+
const columnDefinitions = [
|
7
|
+
{
|
8
|
+
accessor: "year",
|
9
|
+
label: "Year",
|
10
|
+
cellAccessors: ["quarter", "month", "day"],
|
11
|
+
},
|
12
|
+
{
|
13
|
+
label: "Enrollment Data",
|
14
|
+
columns: [
|
15
|
+
{
|
16
|
+
accessor: "newEnrollments",
|
17
|
+
label: "New Enrollments",
|
18
|
+
},
|
19
|
+
{
|
20
|
+
accessor: "scheduledMeetings",
|
21
|
+
label: "Scheduled Meetings",
|
22
|
+
},
|
23
|
+
],
|
24
|
+
},
|
25
|
+
{
|
26
|
+
label: "Performance Data",
|
27
|
+
columns: [
|
28
|
+
{
|
29
|
+
accessor: "attendanceRate",
|
30
|
+
label: "Attendance Rate",
|
31
|
+
},
|
32
|
+
{
|
33
|
+
accessor: "completedClasses",
|
34
|
+
label: "Completed Classes",
|
35
|
+
},
|
36
|
+
{
|
37
|
+
accessor: "classCompletionRate",
|
38
|
+
label: "Class Completion Rate",
|
39
|
+
},
|
40
|
+
{
|
41
|
+
accessor: "graduatedStudents",
|
42
|
+
label: "Graduated Students",
|
43
|
+
},
|
44
|
+
],
|
45
|
+
},
|
46
|
+
];
|
47
|
+
|
48
|
+
const tableProps = {
|
49
|
+
verticalBorder: true
|
50
|
+
}
|
51
|
+
|
52
|
+
return (
|
53
|
+
<>
|
54
|
+
<AdvancedTable
|
55
|
+
columnDefinitions={columnDefinitions}
|
56
|
+
tableData={MOCK_DATA}
|
57
|
+
tableProps={tableProps}
|
58
|
+
{...props}
|
59
|
+
/>
|
60
|
+
</>
|
61
|
+
)
|
62
|
+
}
|
63
|
+
|
64
|
+
export default AdvancedTableColumnHeadersVerticalBorder
|
@@ -13,6 +13,7 @@ examples:
|
|
13
13
|
- advanced_table_with_custom_header_rails: Custom Header Cell
|
14
14
|
- advanced_table_column_headers: Multi-Header Columns
|
15
15
|
- advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
|
16
|
+
- advanced_table_column_headers_vertical_border: Multi-Header Columns with Vertical Borders
|
16
17
|
- advanced_table_no_subrows: Table with No Subrows or Expansion
|
17
18
|
- advanced_table_selectable_rows_rails: Selectable Rows
|
18
19
|
- advanced_table_selectable_rows_no_subrows_rails: Selectable Rows (No Subrows)
|
@@ -53,6 +54,7 @@ examples:
|
|
53
54
|
- advanced_table_column_headers: Multi-Header Columns
|
54
55
|
- advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
|
55
56
|
- advanced_table_column_headers_custom_cell: Multi-Header Columns with Custom Cells
|
57
|
+
- advanced_table_column_headers_vertical_border: Multi-Header Columns with Vertical Borders
|
56
58
|
- advanced_table_no_subrows: Table with No Subrows or Expansion
|
57
59
|
- advanced_table_pinned_rows: Pinned Rows
|
58
60
|
- advanced_table_selectable_rows: Selectable Rows
|
@@ -21,6 +21,7 @@ export { default as AdvancedTableSelectableRowsHeader } from './_advanced_table_
|
|
21
21
|
export { default as AdvancedTableSelectableRowsActions } from './_advanced_table_selectable_rows_actions.jsx'
|
22
22
|
export { default as AdvancedTableTablePropsStickyHeader } from './_advanced_table_table_props_sticky_header.jsx'
|
23
23
|
export { default as AdvancedTableColumnHeadersCustomCell } from './_advanced_table_column_headers_custom_cell.jsx'
|
24
|
+
export { default as AdvancedTableColumnHeadersVerticalBorder } from './_advanced_table_column_headers_vertical_border.jsx'
|
24
25
|
export { default as AdvancedTableInlineEditing } from './_advanced_table_inline_editing.jsx'
|
25
26
|
export { default as AdvancedTableFullscreen } from './_advanced_table_fullscreen.jsx'
|
26
27
|
export { default as AdvancedTableStickyColumns } from './_advanced_table_sticky_columns.jsx'
|
@@ -43,7 +43,7 @@ module Playbook
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def td_classname(column, index)
|
46
|
-
classes = %w[id-cell
|
46
|
+
classes = %w[id-cell]
|
47
47
|
classes << "last-cell" if column[:is_last_in_group]
|
48
48
|
classes << "pinned-left" if index.zero? && is_pinned_left && responsive == "scroll"
|
49
49
|
classes.join(" ")
|
@@ -19,6 +19,7 @@ type PbDateProps = {
|
|
19
19
|
htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
|
20
20
|
id?: string;
|
21
21
|
showDayOfWeek?: boolean;
|
22
|
+
showCurrentYear?: boolean;
|
22
23
|
showIcon?: boolean;
|
23
24
|
size?: "sm" | "md" | "lg";
|
24
25
|
unstyled?: boolean;
|
@@ -35,6 +36,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
35
36
|
htmlOptions = {},
|
36
37
|
id,
|
37
38
|
showDayOfWeek = false,
|
39
|
+
showCurrentYear = false,
|
38
40
|
showIcon = false,
|
39
41
|
size = "md",
|
40
42
|
unstyled = false,
|
@@ -90,7 +92,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
90
92
|
{month} {day}
|
91
93
|
</span>
|
92
94
|
|
93
|
-
{currentYear
|
95
|
+
{(currentYear !== year || showCurrentYear) && <span>{`, ${year}`}</span>}
|
94
96
|
</span>
|
95
97
|
</>
|
96
98
|
: size == "md" || size == "lg"
|
@@ -124,7 +126,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
124
126
|
<span>
|
125
127
|
{month} {day}
|
126
128
|
</span>
|
127
|
-
{currentYear
|
129
|
+
{(currentYear !== year || showCurrentYear) && <span>{`, ${year}`}</span>}
|
128
130
|
</Title>
|
129
131
|
)
|
130
132
|
: (
|
@@ -158,7 +160,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
|
|
158
160
|
<Caption dark={dark}
|
159
161
|
tag="span">
|
160
162
|
{month} {day}
|
161
|
-
{currentYear
|
163
|
+
{(currentYear !== year || showCurrentYear) && <>{`, ${year}`}</>}
|
162
164
|
</Caption>
|
163
165
|
</>
|
164
166
|
)}
|
@@ -13,8 +13,8 @@
|
|
13
13
|
<% end %>
|
14
14
|
|
15
15
|
<!-- month day, year -->
|
16
|
-
<%# if not current year %>
|
17
|
-
<% if object.year.to_s == DateTime.now.year.to_s %>
|
16
|
+
<%# if not current year or show_current_year is false %>
|
17
|
+
<% if object.year.to_s == DateTime.now.year.to_s && !object.show_current_year %>
|
18
18
|
<span><%= "#{object.month} #{object.day}" %></span>
|
19
19
|
<%# if is current year %>
|
20
20
|
<% else %>
|
@@ -44,8 +44,8 @@
|
|
44
44
|
|
45
45
|
<!-- month day, year -->
|
46
46
|
|
47
|
-
<%# if not current year %>
|
48
|
-
<% if object.year.to_s == DateTime.now.year.to_s %>
|
47
|
+
<%# if not current year or show_current_year is false %>
|
48
|
+
<% if object.year.to_s == DateTime.now.year.to_s && !object.show_current_year %>
|
49
49
|
<%= pb_rails("title", props: { tag: "div", text: "#{object.month} #{object.day}", size: 4 }) %>
|
50
50
|
<%# if is current year %>
|
51
51
|
<% else %>
|
@@ -74,8 +74,8 @@
|
|
74
74
|
|
75
75
|
<!-- month day, year -->
|
76
76
|
|
77
|
-
<%# if not current year %>
|
78
|
-
<% if object.year.to_s == DateTime.now.year.to_s %>
|
77
|
+
<%# if not current year or show_current_year is false %>
|
78
|
+
<% if object.year.to_s == DateTime.now.year.to_s && !object.show_current_year %>
|
79
79
|
<%= pb_rails("caption", props: { tag: "span", text: "#{object.month} #{object.day}" }) %>
|
80
80
|
<%# if is current year %>
|
81
81
|
<% else %>
|
@@ -11,6 +11,8 @@ module Playbook
|
|
11
11
|
default: false
|
12
12
|
prop :show_day_of_week, type: Playbook::Props::Boolean,
|
13
13
|
default: false
|
14
|
+
prop :show_current_year, type: Playbook::Props::Boolean,
|
15
|
+
default: false
|
14
16
|
prop :size, type: Playbook::Props::Enum,
|
15
17
|
values: %w[lg md sm xs],
|
16
18
|
default: "md"
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
import FormattedDate from '../../pb_date/_date'
|
4
|
+
|
5
|
+
const DateWithShowCurrentYear = (props) => {
|
6
|
+
return (
|
7
|
+
<>
|
8
|
+
<FormattedDate
|
9
|
+
showCurrentYear
|
10
|
+
value={new Date()}
|
11
|
+
{...props}
|
12
|
+
/>
|
13
|
+
</>
|
14
|
+
)
|
15
|
+
}
|
16
|
+
|
17
|
+
export default DateWithShowCurrentYear
|
@@ -0,0 +1 @@
|
|
1
|
+
By default, the Date kit does NOT display the year if it is the current year. If you want to display the current year you can do so by setting `showCurrentYear`/`show_current_year` to true as shown here.
|
@@ -5,12 +5,14 @@ examples:
|
|
5
5
|
- date_variants: Variants
|
6
6
|
- date_alignment: Alignment
|
7
7
|
- date_timezone: Timezones
|
8
|
+
- date_with_show_current_year: Show Current Year
|
8
9
|
- date_unstyled: Unstyled
|
9
10
|
|
10
11
|
react:
|
11
12
|
- date_default: Default
|
12
13
|
- date_variants: Variants
|
13
14
|
- date_alignment: Alignment
|
15
|
+
- date_with_show_current_year: Show Current Year
|
14
16
|
- date_unstyled: Unstyled
|
15
17
|
|
16
18
|
swift:
|
@@ -2,3 +2,4 @@ export { default as DateDefault } from './_date_default.jsx'
|
|
2
2
|
export { default as DateVariants } from './_date_variants.jsx'
|
3
3
|
export { default as DateAlignment } from './_date_alignment.jsx'
|
4
4
|
export { default as DateUnstyled } from './_date_unstyled.jsx'
|
5
|
+
export { default as DateWithShowCurrentYear } from './_date_with_show_current_year.jsx'
|
@@ -0,0 +1,212 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { ensureAccessible, renderKit, render, fireEvent, screen } from '../utilities/test-utils'
|
3
|
+
import Pagination from './_pagination'
|
4
|
+
|
5
|
+
const defaultProps = {
|
6
|
+
data: { testid: 'pagination-test' },
|
7
|
+
total: 10,
|
8
|
+
current: 1,
|
9
|
+
range: 5,
|
10
|
+
}
|
11
|
+
|
12
|
+
describe('Pagination Component', () => {
|
13
|
+
test('returns namespaced class name', () => {
|
14
|
+
const kit = renderKit(Pagination, defaultProps)
|
15
|
+
expect(kit).toBeInTheDocument()
|
16
|
+
expect(kit).toHaveClass('pb_paginate')
|
17
|
+
})
|
18
|
+
|
19
|
+
it("should be accessible", async () => {
|
20
|
+
ensureAccessible(Pagination, defaultProps)
|
21
|
+
})
|
22
|
+
|
23
|
+
test('renders with default props', () => {
|
24
|
+
render(<Pagination {...defaultProps} />)
|
25
|
+
|
26
|
+
const pagination = screen.getByTestId('pagination-test')
|
27
|
+
expect(pagination).toBeInTheDocument()
|
28
|
+
expect(pagination).toHaveClass('pb_paginate')
|
29
|
+
})
|
30
|
+
|
31
|
+
test('renders pagination buttons correctly', () => {
|
32
|
+
render(<Pagination {...defaultProps} />)
|
33
|
+
|
34
|
+
expect(screen.getByText('1')).toBeInTheDocument()
|
35
|
+
expect(screen.getByText('2')).toBeInTheDocument()
|
36
|
+
expect(screen.getByText('3')).toBeInTheDocument()
|
37
|
+
expect(screen.getByText('4')).toBeInTheDocument()
|
38
|
+
expect(screen.getByText('5')).toBeInTheDocument()
|
39
|
+
|
40
|
+
// Check for navigation arrows by looking for the li elements with specific classes
|
41
|
+
const leftArrow = document.querySelector('.pagination-left')
|
42
|
+
const rightArrow = document.querySelector('.pagination-right')
|
43
|
+
expect(leftArrow).toBeInTheDocument()
|
44
|
+
expect(rightArrow).toBeInTheDocument()
|
45
|
+
})
|
46
|
+
|
47
|
+
test('highlights current page as active', () => {
|
48
|
+
render(<Pagination {...defaultProps}
|
49
|
+
current={3}
|
50
|
+
/>)
|
51
|
+
|
52
|
+
const activePage = screen.getByText('3')
|
53
|
+
expect(activePage).toHaveClass('active')
|
54
|
+
})
|
55
|
+
|
56
|
+
test('calls onChange when page is clicked', () => {
|
57
|
+
const mockOnChange = jest.fn()
|
58
|
+
render(<Pagination {...defaultProps}
|
59
|
+
onChange={mockOnChange}
|
60
|
+
/>)
|
61
|
+
|
62
|
+
const pageButton = screen.getByText('3')
|
63
|
+
fireEvent.click(pageButton)
|
64
|
+
|
65
|
+
expect(mockOnChange).toHaveBeenCalledWith(3)
|
66
|
+
})
|
67
|
+
|
68
|
+
test('disables left arrow on first page', () => {
|
69
|
+
render(<Pagination {...defaultProps}
|
70
|
+
current={1}
|
71
|
+
/>)
|
72
|
+
|
73
|
+
const leftArrow = document.querySelector('.pagination-left')
|
74
|
+
expect(leftArrow).toHaveClass('disabled')
|
75
|
+
})
|
76
|
+
|
77
|
+
test('disables right arrow on last page', () => {
|
78
|
+
render(<Pagination {...defaultProps}
|
79
|
+
current={10}
|
80
|
+
/>)
|
81
|
+
|
82
|
+
const rightArrow = document.querySelector('.pagination-right')
|
83
|
+
expect(rightArrow).toHaveClass('disabled')
|
84
|
+
})
|
85
|
+
|
86
|
+
test('does not render when total is 1 or less', () => {
|
87
|
+
const { container } = render(<Pagination {...defaultProps}
|
88
|
+
total={1}
|
89
|
+
/>)
|
90
|
+
|
91
|
+
expect(container.firstChild).toBeNull()
|
92
|
+
})
|
93
|
+
|
94
|
+
test('renders with custom className', () => {
|
95
|
+
render(<Pagination {...defaultProps}
|
96
|
+
className="custom-class"
|
97
|
+
/>)
|
98
|
+
|
99
|
+
const pagination = screen.getByTestId('pagination-test')
|
100
|
+
expect(pagination).toHaveClass('custom-class')
|
101
|
+
})
|
102
|
+
|
103
|
+
test('renders with custom id', () => {
|
104
|
+
render(<Pagination {...defaultProps}
|
105
|
+
id="custom-id"
|
106
|
+
/>)
|
107
|
+
|
108
|
+
const pagination = screen.getByTestId('pagination-test')
|
109
|
+
expect(pagination).toHaveAttribute('id', 'custom-id')
|
110
|
+
})
|
111
|
+
|
112
|
+
test('renders with custom range', () => {
|
113
|
+
render(<Pagination {...defaultProps}
|
114
|
+
range={3}
|
115
|
+
/>)
|
116
|
+
|
117
|
+
expect(screen.getByText('1')).toBeInTheDocument()
|
118
|
+
expect(screen.getByText('2')).toBeInTheDocument()
|
119
|
+
expect(screen.getByText('3')).toBeInTheDocument()
|
120
|
+
expect(screen.getByText('9')).toBeInTheDocument()
|
121
|
+
expect(screen.getByText('10')).toBeInTheDocument()
|
122
|
+
})
|
123
|
+
|
124
|
+
test('handles large number of pages correctly', () => {
|
125
|
+
render(<Pagination {...defaultProps}
|
126
|
+
current={50}
|
127
|
+
range={5}
|
128
|
+
total={100}
|
129
|
+
/>)
|
130
|
+
|
131
|
+
const pagination = screen.getByTestId('pagination-test')
|
132
|
+
expect(pagination).toBeInTheDocument()
|
133
|
+
expect(pagination).toHaveClass('pb_paginate')
|
134
|
+
|
135
|
+
|
136
|
+
expect(screen.getByText('48')).toBeInTheDocument()
|
137
|
+
expect(screen.getByText('49')).toBeInTheDocument()
|
138
|
+
expect(screen.getByText('50')).toBeInTheDocument()
|
139
|
+
expect(screen.getByText('51')).toBeInTheDocument()
|
140
|
+
expect(screen.getByText('52')).toBeInTheDocument()
|
141
|
+
})
|
142
|
+
|
143
|
+
test('syncs with external current prop changes', () => {
|
144
|
+
const { rerender } = render(<Pagination {...defaultProps}
|
145
|
+
current={1}
|
146
|
+
/>)
|
147
|
+
|
148
|
+
expect(screen.getByText('1')).toHaveClass('active')
|
149
|
+
|
150
|
+
rerender(<Pagination {...defaultProps}
|
151
|
+
current={3}
|
152
|
+
/>)
|
153
|
+
|
154
|
+
expect(screen.getByText('3')).toHaveClass('active')
|
155
|
+
expect(screen.getByText('1')).not.toHaveClass('active')
|
156
|
+
})
|
157
|
+
|
158
|
+
test('validates current prop is within valid range', () => {
|
159
|
+
const { rerender } = render(<Pagination {...defaultProps}
|
160
|
+
current={1}
|
161
|
+
/>)
|
162
|
+
|
163
|
+
rerender(<Pagination {...defaultProps}
|
164
|
+
current={0}
|
165
|
+
/>)
|
166
|
+
|
167
|
+
expect(screen.getByText('1')).toHaveClass('active')
|
168
|
+
|
169
|
+
rerender(<Pagination {...defaultProps}
|
170
|
+
current={15}
|
171
|
+
/>)
|
172
|
+
|
173
|
+
expect(screen.getByText('1')).toHaveClass('active')
|
174
|
+
})
|
175
|
+
|
176
|
+
test('handles htmlOptions props', () => {
|
177
|
+
const htmlOptions = { 'data-test': 'test-value' }
|
178
|
+
render(<Pagination {...defaultProps}
|
179
|
+
htmlOptions={htmlOptions}
|
180
|
+
/>)
|
181
|
+
|
182
|
+
const pagination = screen.getByTestId('pagination-test')
|
183
|
+
expect(pagination).toHaveAttribute('data-test', 'test-value')
|
184
|
+
})
|
185
|
+
|
186
|
+
test('renders first and last page buttons when range is small', () => {
|
187
|
+
render(<Pagination {...defaultProps}
|
188
|
+
current={10}
|
189
|
+
range={3}
|
190
|
+
total={20}
|
191
|
+
/>)
|
192
|
+
|
193
|
+
expect(screen.getByText('1')).toBeInTheDocument()
|
194
|
+
expect(screen.getByText('20')).toBeInTheDocument()
|
195
|
+
|
196
|
+
expect(screen.getByText('9')).toBeInTheDocument()
|
197
|
+
expect(screen.getByText('10')).toBeInTheDocument()
|
198
|
+
expect(screen.getByText('11')).toBeInTheDocument()
|
199
|
+
})
|
200
|
+
|
201
|
+
test('renders second and second-to-last page buttons when needed', () => {
|
202
|
+
render(<Pagination {...defaultProps}
|
203
|
+
current={10}
|
204
|
+
range={3}
|
205
|
+
total={20}
|
206
|
+
/>)
|
207
|
+
|
208
|
+
expect(screen.getByText('2')).toBeInTheDocument()
|
209
|
+
|
210
|
+
expect(screen.getByText('19')).toBeInTheDocument()
|
211
|
+
})
|
212
|
+
})
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useState } from "react";
|
1
|
+
import React, { useState, useEffect } from "react";
|
2
2
|
import classnames from 'classnames'
|
3
3
|
import { GlobalProps, globalProps } from '../utilities/globalProps'
|
4
4
|
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
|
@@ -123,6 +123,13 @@ const Pagination = ( props: PaginationProps) => {
|
|
123
123
|
|
124
124
|
return buttons;
|
125
125
|
};
|
126
|
+
|
127
|
+
// Sync internal state with external current prop
|
128
|
+
useEffect(() => {
|
129
|
+
if (current >= 1 && current <= total) {
|
130
|
+
setCurrentPage(current);
|
131
|
+
}
|
132
|
+
}, [current, total]);
|
126
133
|
|
127
134
|
|
128
135
|
const ariaProps = buildAriaProps(aria)
|