playbook_ui 14.1.0 → 14.3.0.pre.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +3 -3
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +1 -1
- data/app/pb_kits/playbook/pb_badge/_badge.scss +9 -0
- data/app/pb_kits/playbook/pb_badge/_badge.tsx +8 -3
- data/app/pb_kits/playbook/pb_badge/badge.rb +1 -1
- data/app/pb_kits/playbook/pb_badge/badge.test.js +17 -11
- data/app/pb_kits/playbook/pb_badge/docs/_badge_notification.html.erb +13 -0
- data/app/pb_kits/playbook/pb_badge/docs/_badge_notification.jsx +31 -12
- data/app/pb_kits/playbook/pb_button/_button.tsx +4 -1
- data/app/pb_kits/playbook/pb_button/button.html.erb +1 -1
- data/app/pb_kits/playbook/pb_button/button.rb +4 -0
- data/app/pb_kits/playbook/pb_date_time/dateTime.test.js +2 -2
- data/app/pb_kits/playbook/pb_dialog/_close_icon.tsx +5 -1
- data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +3 -1
- data/app/pb_kits/playbook/pb_dialog/dialog.test.jsx +20 -1
- data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +1 -1
- data/app/pb_kits/playbook/pb_dialog/dialog_header.rb +4 -0
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_default.jsx +1 -5
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.jsx +46 -0
- data/app/pb_kits/playbook/pb_dialog/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_dialog/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_filter/filter.rb +1 -1
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +43 -25
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +6 -2
- data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +2 -2
- data/app/pb_kits/playbook/pb_form_pill/form_pill.html.erb +4 -4
- data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +4 -0
- data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.scss +3 -0
- data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.tsx +72 -0
- data/app/pb_kits/playbook/pb_gantt_chart/docs/_gantt_chart_default.jsx +53 -0
- data/app/pb_kits/playbook/pb_gantt_chart/docs/example.yml +7 -0
- data/app/pb_kits/playbook/pb_gantt_chart/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_gantt_chart/gantt_chart.test.jsx +19 -0
- data/app/pb_kits/playbook/pb_icon/_icon.tsx +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +0 -2
- data/app/pb_kits/playbook/pb_pagination/_pagination.scss +49 -13
- data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +164 -0
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default.jsx +19 -0
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default_react.md +1 -0
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change.jsx +62 -0
- data/app/pb_kits/playbook/pb_pagination/docs/_pagination_page_change_react.md +1 -0
- data/app/pb_kits/playbook/pb_pagination/docs/data.js +23 -0
- data/app/pb_kits/playbook/pb_pagination/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_pagination/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +0 -7
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +10 -5
- data/app/pb_kits/playbook/pb_rich_text_editor/_previewer_mixin.scss +132 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +50 -76
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_preview.jsx +73 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_star_rating/index.js +78 -41
- data/app/pb_kits/playbook/pb_star_rating/star_rating.html.erb +4 -2
- data/app/pb_kits/playbook/pb_star_rating/star_rating.rb +17 -0
- data/app/pb_kits/playbook/pb_star_rating/subcomponents/_star_rating_display.tsx +0 -2
- data/app/pb_kits/playbook/pb_star_rating/subcomponents/_star_rating_interactive.tsx +0 -1
- data/app/pb_kits/playbook/pb_time/_time.tsx +12 -8
- data/app/pb_kits/playbook/pb_time/time.html.erb +3 -3
- data/app/pb_kits/playbook/pb_time/time.rb +4 -0
- data/app/pb_kits/playbook/tokens/_container.scss +21 -0
- data/app/pb_kits/playbook/utilities/_min_width.scss +45 -0
- data/app/pb_kits/playbook/utilities/globalPropNames.mjs +1 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +20 -3
- data/app/pb_kits/playbook/utilities/icons/allicons.tsx +59 -0
- data/app/pb_kits/playbook/utilities/icons/clock.svg +9 -0
- data/app/pb_kits/playbook/utilities/icons/spinner.svg +3 -0
- data/app/pb_kits/playbook/utilities/icons/times.svg +3 -0
- data/dist/chunks/_typeahead-Cq7RLPBA.js +22 -0
- data/dist/chunks/_weekday_stacked-Cykj5kLZ.js +45 -0
- data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
- data/dist/chunks/{lib-BE0Z3F7x.js → lib-DErGXNy3.js} +2 -2
- data/dist/chunks/{pb_form_validation-TzZQ0Flx.js → pb_form_validation-BC6kh7Hu.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +4 -0
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/classnames.rb +1 -0
- data/lib/playbook/spacing.rb +31 -2
- data/lib/playbook/version.rb +2 -2
- metadata +35 -13
- data/dist/chunks/_typeahead-D6PRvP-1.js +0 -22
- data/dist/chunks/_weekday_stacked-DbdEuIzh.js +0 -45
- data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
- /data/app/pb_kits/playbook/pb_pagination/docs/{_pagination_default.md → _pagination_default_rails.md} +0 -0
@@ -46,6 +46,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
|
|
46
46
|
} = props
|
47
47
|
|
48
48
|
const iconClass = icon ? "_icon" : ""
|
49
|
+
const closeIconSize = size === "small" ? "xs" : "sm"
|
49
50
|
const css = classnames(
|
50
51
|
`pb_form_pill_kit_${color}${iconClass}`,
|
51
52
|
globalProps(props),
|
@@ -69,7 +70,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
|
|
69
70
|
<Avatar
|
70
71
|
imageUrl={avatarUrl}
|
71
72
|
name={name}
|
72
|
-
size="
|
73
|
+
size="xxs"
|
73
74
|
status={null}
|
74
75
|
/>
|
75
76
|
<Title
|
@@ -84,7 +85,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
|
|
84
85
|
<Avatar
|
85
86
|
imageUrl={avatarUrl}
|
86
87
|
name={name}
|
87
|
-
size="
|
88
|
+
size="xxs"
|
88
89
|
status={null}
|
89
90
|
/>
|
90
91
|
<Title
|
@@ -94,6 +95,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
|
|
94
95
|
/>
|
95
96
|
<Icon
|
96
97
|
className="pb_form_pill_icon"
|
98
|
+
color={color}
|
97
99
|
icon={icon}
|
98
100
|
/>
|
99
101
|
</>
|
@@ -102,6 +104,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
|
|
102
104
|
<>
|
103
105
|
<Icon
|
104
106
|
className="pb_form_pill_icon"
|
107
|
+
color={color}
|
105
108
|
icon={icon}
|
106
109
|
/>
|
107
110
|
<Title
|
@@ -126,6 +129,7 @@ const FormPill = (props: FormPillProps): React.ReactElement => {
|
|
126
129
|
<Icon
|
127
130
|
fixedWidth
|
128
131
|
icon="times"
|
132
|
+
size={closeIconSize}
|
129
133
|
/>
|
130
134
|
</div>
|
131
135
|
</div>
|
@@ -5,11 +5,11 @@ examples:
|
|
5
5
|
- form_pill_size: Form Pill Size
|
6
6
|
- form_pill_tag: Form Pill Tag
|
7
7
|
- form_pill_example: Example
|
8
|
-
|
8
|
+
- form_pill_icon: Form Pill Icon
|
9
9
|
|
10
10
|
react:
|
11
11
|
- form_pill_user: Form Pill User
|
12
12
|
- form_pill_size: Form Pill Size
|
13
13
|
- form_pill_tag: Form Pill Tag
|
14
14
|
- form_pill_example: Example
|
15
|
-
|
15
|
+
- form_pill_icon: Form Pill Icon
|
@@ -1,19 +1,19 @@
|
|
1
1
|
<%= content_tag(:div, id: object.id, data: object.data, class: object.classname + object.size_class, tabindex: object.tabindex, **combined_html_options) do %>
|
2
2
|
<% if object.name.present? %>
|
3
|
-
<%= pb_rails("avatar", props: { name: object.name, image_url: object.avatar_url, size: "
|
3
|
+
<%= pb_rails("avatar", props: { name: object.name, image_url: object.avatar_url, size: "xxs" }) %>
|
4
4
|
<%= pb_rails("title", props: { text: object.name, size: 4, classname: "pb_form_pill_text" }) %>
|
5
5
|
<% if object.icon.present? %>
|
6
|
-
<%= pb_rails("icon", props: { classname: "pb_form_pill_icon", icon: object.icon }) %>
|
6
|
+
<%= pb_rails("icon", props: { classname: "pb_form_pill_icon", color: object.color, icon: object.icon }) %>
|
7
7
|
<% end %>
|
8
8
|
<% elsif object.text.present? %>
|
9
9
|
<% if object.icon.present? %>
|
10
|
-
<%= pb_rails("icon", props: { classname: "pb_form_pill_icon", icon: object.icon }) %>
|
10
|
+
<%= pb_rails("icon", props: { classname: "pb_form_pill_icon", color: object.color, icon: object.icon }) %>
|
11
11
|
<% end %>
|
12
12
|
<% if object.text.present? %>
|
13
13
|
<%= pb_rails("title", props: { text: object.text, size: 4, classname: "pb_form_pill_tag" }) %>
|
14
14
|
<% end %>
|
15
15
|
<% end %>
|
16
16
|
<%= pb_rails("body", props: { classname: "pb_form_pill_close" }) do %>
|
17
|
-
<%= pb_rails("icon", props: { icon: 'times'
|
17
|
+
<%= pb_rails("icon", props: { icon: 'times', fixed_width: true, size: object.close_icon_size }) %>
|
18
18
|
<% end %>
|
19
19
|
<% end %>
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
2
|
+
import classnames from "classnames";
|
3
|
+
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
|
4
|
+
import { globalProps } from "../utilities/globalProps";
|
5
|
+
import HighchartsReact from "highcharts-react-official";
|
6
|
+
import Highcharts from "highcharts/highcharts-gantt";
|
7
|
+
|
8
|
+
import { highchartsTheme } from "../pb_dashboard/pbChartsLightTheme";
|
9
|
+
import { highchartsDarkTheme } from "../pb_dashboard/pbChartsDarkTheme";
|
10
|
+
|
11
|
+
type GanttChartProps = {
|
12
|
+
aria?: { [key: string]: string };
|
13
|
+
className?: string;
|
14
|
+
customOptions: Partial<Highcharts.Options>;
|
15
|
+
dark?: boolean;
|
16
|
+
data?: { [key: string]: string };
|
17
|
+
htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
|
18
|
+
id?: string;
|
19
|
+
};
|
20
|
+
|
21
|
+
const GanttChart = (props: GanttChartProps) => {
|
22
|
+
const {
|
23
|
+
aria = {},
|
24
|
+
className,
|
25
|
+
customOptions = {},
|
26
|
+
dark = false,
|
27
|
+
data = {},
|
28
|
+
htmlOptions = {},
|
29
|
+
id,
|
30
|
+
} = props;
|
31
|
+
|
32
|
+
const ariaProps = buildAriaProps(aria);
|
33
|
+
const dataProps = buildDataProps(data);
|
34
|
+
const htmlProps = buildHtmlProps(htmlOptions);
|
35
|
+
const classes = classnames(
|
36
|
+
buildCss("pb_gantt_chart"),
|
37
|
+
globalProps(props),
|
38
|
+
className
|
39
|
+
);
|
40
|
+
|
41
|
+
const [options, setOptions] = useState<Highcharts.Options | undefined>(customOptions);
|
42
|
+
|
43
|
+
useEffect(() => {
|
44
|
+
setOptions(customOptions);
|
45
|
+
}, [customOptions]);
|
46
|
+
|
47
|
+
const setupTheme = () => {
|
48
|
+
dark
|
49
|
+
? Highcharts.setOptions(highchartsDarkTheme)
|
50
|
+
: Highcharts.setOptions(highchartsTheme);
|
51
|
+
};
|
52
|
+
setupTheme();
|
53
|
+
|
54
|
+
return (
|
55
|
+
<div>
|
56
|
+
<HighchartsReact
|
57
|
+
constructorType={"ganttChart"}
|
58
|
+
containerProps={{
|
59
|
+
className: classnames(globalProps(props), classes),
|
60
|
+
id: id,
|
61
|
+
...ariaProps,
|
62
|
+
...dataProps,
|
63
|
+
...htmlProps,
|
64
|
+
}}
|
65
|
+
highcharts={Highcharts}
|
66
|
+
options={options}
|
67
|
+
/>
|
68
|
+
</div>
|
69
|
+
);
|
70
|
+
};
|
71
|
+
|
72
|
+
export default GanttChart;
|
@@ -0,0 +1,53 @@
|
|
1
|
+
import React from "react";
|
2
|
+
import { GanttChart } from "playbook-ui";
|
3
|
+
|
4
|
+
const mockOptions = {
|
5
|
+
title: {
|
6
|
+
text: "Simple Gantt Chart",
|
7
|
+
},
|
8
|
+
|
9
|
+
xAxis: [
|
10
|
+
{
|
11
|
+
min: Date.UTC(2014, 10, 17),
|
12
|
+
max: Date.UTC(2014, 10, 30),
|
13
|
+
},
|
14
|
+
],
|
15
|
+
|
16
|
+
series: [
|
17
|
+
{
|
18
|
+
name: "Project 1",
|
19
|
+
data: [
|
20
|
+
{
|
21
|
+
name: "Start prototype",
|
22
|
+
start: Date.UTC(2014, 10, 18),
|
23
|
+
end: Date.UTC(2014, 10, 25),
|
24
|
+
},
|
25
|
+
{
|
26
|
+
name: "Develop",
|
27
|
+
start: Date.UTC(2014, 10, 20),
|
28
|
+
end: Date.UTC(2014, 10, 25),
|
29
|
+
},
|
30
|
+
{
|
31
|
+
name: "Run acceptance tests",
|
32
|
+
start: Date.UTC(2014, 10, 23),
|
33
|
+
end: Date.UTC(2014, 10, 26),
|
34
|
+
},
|
35
|
+
{
|
36
|
+
name: "Test prototype",
|
37
|
+
start: Date.UTC(2014, 10, 27),
|
38
|
+
end: Date.UTC(2014, 10, 29),
|
39
|
+
},
|
40
|
+
],
|
41
|
+
},
|
42
|
+
],
|
43
|
+
};
|
44
|
+
|
45
|
+
const GanttChartDefault = (props) => (
|
46
|
+
<div>
|
47
|
+
<GanttChart customOptions={mockOptions}
|
48
|
+
{...props}
|
49
|
+
/>
|
50
|
+
</div>
|
51
|
+
);
|
52
|
+
|
53
|
+
export default GanttChartDefault;
|
@@ -0,0 +1 @@
|
|
1
|
+
export { default as GanttChartDefault } from './_gantt_chart_default.jsx'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
// import { renderKit } from '../utilities/test-utils'
|
2
|
+
|
3
|
+
// import GanttChart from './_gantt_chart'
|
4
|
+
|
5
|
+
/* See these resources for more testing info:
|
6
|
+
- https://github.com/testing-library/jest-dom#usage for useage and examples
|
7
|
+
- https://jestjs.io/docs/en/using-matchers
|
8
|
+
*/
|
9
|
+
|
10
|
+
test('generated scaffold test - update me', () => {
|
11
|
+
// const props = {
|
12
|
+
// data: { testid: 'default' }
|
13
|
+
// }
|
14
|
+
|
15
|
+
|
16
|
+
// const kit = renderKit(GanttChart , props)
|
17
|
+
// expect(kit).toBeInTheDocument()
|
18
|
+
})
|
19
|
+
|
@@ -28,7 +28,7 @@ type IconProps = {
|
|
28
28
|
data?: {[key: string]: string},
|
29
29
|
fixedWidth?: boolean,
|
30
30
|
flip?: "horizontal" | "vertical" | "both" | "none",
|
31
|
-
icon
|
31
|
+
icon?: string | ReactSVGElement,
|
32
32
|
htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
|
33
33
|
id?: string,
|
34
34
|
inverse?: boolean,
|
@@ -469,7 +469,6 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
469
469
|
<FormPill
|
470
470
|
key={index}
|
471
471
|
onClick={(event: any) => handlePillClose(event, item)}
|
472
|
-
size="small"
|
473
472
|
text={item.label}
|
474
473
|
/>
|
475
474
|
))
|
@@ -482,7 +481,6 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
482
481
|
<FormPill
|
483
482
|
key={index}
|
484
483
|
onClick={(event: any) => handlePillClose(event, item)}
|
485
|
-
size="small"
|
486
484
|
text={item.label}
|
487
485
|
/>
|
488
486
|
))
|
@@ -3,36 +3,45 @@
|
|
3
3
|
@import "../tokens/border_radius";
|
4
4
|
@import "../tokens/shadows";
|
5
5
|
|
6
|
+
|
6
7
|
$pagination_padding: 7px 13px 6px 13px;
|
7
8
|
$top_bottom_radius: 0px;
|
8
9
|
|
10
|
+
@mixin hover-state {
|
11
|
+
background-color: $active_light !important;
|
12
|
+
color: $primary;
|
13
|
+
border-radius: $border_rad_light;
|
14
|
+
}
|
15
|
+
|
9
16
|
.pb_pagination {
|
10
17
|
display: inline-block;
|
11
18
|
border-radius: $border_rad_light;
|
12
19
|
border: $border_rad_lightest solid $border_light;
|
13
20
|
background-color: $white;
|
14
|
-
padding: $
|
15
|
-
li {
|
21
|
+
padding: $space_xs 0px !important;
|
22
|
+
li, .pagination-number {
|
16
23
|
display: inline;
|
17
|
-
> a, li > span {
|
24
|
+
> a, li > span, .pagination-number {
|
18
25
|
padding: $pagination_padding;
|
19
26
|
text-decoration: none;
|
20
27
|
}}
|
21
|
-
li:first-child > a, li:first-child > span
|
28
|
+
li:first-child > a, li:first-child > span, .pagination-number, .pagination-left {
|
29
|
+
background-color: $white;
|
22
30
|
padding: $pagination_padding;
|
23
31
|
border-right: $border_rad_lightest solid $border_light;
|
24
32
|
z-index: 2;
|
25
33
|
border-top-right-radius: $top_bottom_radius;
|
26
34
|
border-bottom-right-radius: $top_bottom_radius;
|
35
|
+
cursor: pointer;
|
27
36
|
}
|
28
|
-
li:last-child > a, li:last-child > span {
|
37
|
+
li:last-child > a, li:last-child > span, .pagination-number, .pagination-right {
|
29
38
|
padding: $pagination_padding;
|
30
39
|
border-left: $border_rad_lightest solid $border_light;
|
31
40
|
z-index: 2;
|
32
41
|
border-top-left-radius: $top_bottom_radius;
|
33
42
|
border-bottom-left-radius: $top_bottom_radius;
|
34
43
|
}
|
35
|
-
a {
|
44
|
+
a, .pagination-number {
|
36
45
|
color: $text_lt_default;
|
37
46
|
font-size: $text_small;
|
38
47
|
font-weight: $regular;
|
@@ -40,9 +49,7 @@ $top_bottom_radius: 0px;
|
|
40
49
|
transition: all $transition_default ease-out;
|
41
50
|
|
42
51
|
&:hover {
|
43
|
-
|
44
|
-
color: $primary;
|
45
|
-
border-radius: $border_rad_light;
|
52
|
+
@include hover-state;
|
46
53
|
}
|
47
54
|
|
48
55
|
&:focus-visible {
|
@@ -52,8 +59,8 @@ $top_bottom_radius: 0px;
|
|
52
59
|
transition: none;
|
53
60
|
}
|
54
61
|
}
|
55
|
-
.active > span {
|
56
|
-
background-color: $primary;
|
62
|
+
.active > span, .pagination-number.active {
|
63
|
+
background-color: $primary !important;
|
57
64
|
border-radius: $border_rad_light;
|
58
65
|
color: #fff;
|
59
66
|
padding: $pagination_padding;
|
@@ -62,8 +69,37 @@ $top_bottom_radius: 0px;
|
|
62
69
|
font-weight: $bold;
|
63
70
|
font-size: $text_small;
|
64
71
|
}
|
65
|
-
.disabled
|
66
|
-
|
72
|
+
.disabled {
|
73
|
+
pointer-events: none;
|
74
|
+
opacity: 0.5;
|
75
|
+
color: grey;
|
76
|
+
|
77
|
+
& > span {
|
78
|
+
padding: $pagination_padding;
|
79
|
+
font-size: $text_small;
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
.pagination-right,
|
84
|
+
.pagination-left {
|
85
|
+
background-color: $white;
|
86
|
+
border-top: none;
|
87
|
+
border-bottom: none;
|
88
|
+
cursor: pointer;
|
89
|
+
padding: 7px 11px 6px;
|
67
90
|
font-size: $text_small;
|
91
|
+
|
92
|
+
&:hover {
|
93
|
+
@include hover-state;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
.pagination-left {
|
97
|
+
border-left: none;
|
98
|
+
margin-right: $space_xxs;
|
99
|
+
}
|
100
|
+
|
101
|
+
.pagination-right {
|
102
|
+
border-right: none;
|
103
|
+
margin-left: $space_xxs;
|
68
104
|
}
|
69
105
|
}
|
@@ -0,0 +1,164 @@
|
|
1
|
+
import React, { useState } from "react";
|
2
|
+
import classnames from 'classnames'
|
3
|
+
import { globalProps } from '../utilities/globalProps'
|
4
|
+
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from '../utilities/props'
|
5
|
+
import Icon from '../pb_icon/_icon';
|
6
|
+
|
7
|
+
type PaginationProps = {
|
8
|
+
aria?: { [key: string]: string },
|
9
|
+
className?: string,
|
10
|
+
data?: { [key: string]: string },
|
11
|
+
htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
|
12
|
+
id?: string,
|
13
|
+
current?: number;
|
14
|
+
onChange?: (pageNumber: number) => void;
|
15
|
+
range?: number;
|
16
|
+
total?: number;
|
17
|
+
};
|
18
|
+
|
19
|
+
const Pagination = ( props: PaginationProps) => {
|
20
|
+
const {
|
21
|
+
aria = {},
|
22
|
+
className,
|
23
|
+
data = {},
|
24
|
+
htmlOptions = {},
|
25
|
+
id,
|
26
|
+
current = 1,
|
27
|
+
onChange,
|
28
|
+
range = 5,
|
29
|
+
total = 1,
|
30
|
+
} = props
|
31
|
+
const [currentPage, setCurrentPage] = useState(current);
|
32
|
+
|
33
|
+
const handlePageChange = (pageNumber: number) => {
|
34
|
+
if (pageNumber >= 1 && pageNumber <= total) {
|
35
|
+
setCurrentPage(pageNumber);
|
36
|
+
if (onChange) {
|
37
|
+
onChange(pageNumber);
|
38
|
+
}
|
39
|
+
}
|
40
|
+
};
|
41
|
+
|
42
|
+
const renderPageButtons = (): JSX.Element[] => {
|
43
|
+
const buttons: JSX.Element[] = [];
|
44
|
+
|
45
|
+
// Calculate pagination range with let
|
46
|
+
let rangeStart = Math.max(1, currentPage - Math.floor(range / 2));
|
47
|
+
let rangeEnd = Math.min(total, rangeStart + range - 1);
|
48
|
+
|
49
|
+
// Adjust range if it's too short to fit the range
|
50
|
+
if (rangeEnd - rangeStart + 1 < range) {
|
51
|
+
if (rangeStart > 1) {
|
52
|
+
rangeStart = Math.max(1, rangeEnd - range + 1);
|
53
|
+
} else {
|
54
|
+
rangeEnd = Math.min(total, rangeStart + range - 1);
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
// Always display the first page button
|
59
|
+
if (rangeStart > 1) {
|
60
|
+
buttons.push(
|
61
|
+
<li
|
62
|
+
className="pagination-number"
|
63
|
+
key={1}
|
64
|
+
onClick={() => handlePageChange(1)}
|
65
|
+
>
|
66
|
+
1
|
67
|
+
</li>
|
68
|
+
);
|
69
|
+
}
|
70
|
+
|
71
|
+
// Always display the second page button
|
72
|
+
if (rangeStart > 2) {
|
73
|
+
buttons.push(
|
74
|
+
<li
|
75
|
+
className="pagination-number"
|
76
|
+
key={2}
|
77
|
+
onClick={() => handlePageChange(2)}
|
78
|
+
>
|
79
|
+
2
|
80
|
+
</li>
|
81
|
+
);
|
82
|
+
}
|
83
|
+
|
84
|
+
// Display page buttons within the calculated range
|
85
|
+
for (let i = rangeStart; i <= rangeEnd; i++) {
|
86
|
+
buttons.push(
|
87
|
+
<li
|
88
|
+
className={`pagination-number ${i === currentPage ? "active" : ""}`}
|
89
|
+
key={i}
|
90
|
+
onClick={() => handlePageChange(i)}
|
91
|
+
>
|
92
|
+
{i}
|
93
|
+
</li>
|
94
|
+
);
|
95
|
+
}
|
96
|
+
|
97
|
+
// Always display the second-to-last page button
|
98
|
+
if (rangeEnd < total - 1) {
|
99
|
+
buttons.push(
|
100
|
+
<li
|
101
|
+
className={`pagination-number ${total - 1 === currentPage ? "active" : ""}`}
|
102
|
+
key={total - 1}
|
103
|
+
onClick={() => handlePageChange(total - 1)}
|
104
|
+
>
|
105
|
+
{total - 1}
|
106
|
+
</li>
|
107
|
+
);
|
108
|
+
}
|
109
|
+
|
110
|
+
// Always display the last page button
|
111
|
+
if (rangeEnd < total) {
|
112
|
+
buttons.push(
|
113
|
+
<li
|
114
|
+
className={`pagination-number ${total === currentPage ? "active" : ""}`}
|
115
|
+
key={total}
|
116
|
+
onClick={() => handlePageChange(total)}
|
117
|
+
>
|
118
|
+
{total}
|
119
|
+
</li>
|
120
|
+
);
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
return buttons;
|
125
|
+
};
|
126
|
+
|
127
|
+
|
128
|
+
const ariaProps = buildAriaProps(aria)
|
129
|
+
const dataProps = buildDataProps(data)
|
130
|
+
const htmlProps = buildHtmlProps(htmlOptions)
|
131
|
+
const classes = classnames(
|
132
|
+
buildCss('pb_paginate'),
|
133
|
+
globalProps(props),
|
134
|
+
className
|
135
|
+
)
|
136
|
+
|
137
|
+
return (
|
138
|
+
<div
|
139
|
+
{...ariaProps}
|
140
|
+
{...dataProps}
|
141
|
+
{...htmlProps}
|
142
|
+
className={classes}
|
143
|
+
id={id}
|
144
|
+
>
|
145
|
+
<div className="pb_pagination">
|
146
|
+
<li
|
147
|
+
className={`pagination-left ${currentPage === 1 ? 'disabled' : ''}`}
|
148
|
+
onClick={() => handlePageChange(currentPage - 1)}
|
149
|
+
>
|
150
|
+
<Icon icon="chevron-left" />
|
151
|
+
</li>
|
152
|
+
{renderPageButtons()}
|
153
|
+
<li
|
154
|
+
className={`pagination-right ${currentPage === total ? 'disabled' : ''}`}
|
155
|
+
onClick={() => handlePageChange(currentPage + 1)}
|
156
|
+
>
|
157
|
+
<Icon icon="chevron-right" />
|
158
|
+
</li>
|
159
|
+
</div>
|
160
|
+
</div>
|
161
|
+
);
|
162
|
+
};
|
163
|
+
|
164
|
+
export default Pagination;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
import Pagination from '../_pagination'
|
4
|
+
|
5
|
+
const PaginationDefault = (props) => {
|
6
|
+
|
7
|
+
return (
|
8
|
+
<>
|
9
|
+
<Pagination
|
10
|
+
current={1}
|
11
|
+
range={5}
|
12
|
+
total={10}
|
13
|
+
{...props}
|
14
|
+
/>
|
15
|
+
</>
|
16
|
+
)
|
17
|
+
}
|
18
|
+
|
19
|
+
export default PaginationDefault
|
@@ -0,0 +1 @@
|
|
1
|
+
The `range` prop determines how many pages to display in the Pagination component. Regardless of this value, the first two and last two pages are always visible to facilitate navigation to the beginning and end of the pagination. If these always-visible pages fall within the specified range, they are included in the display. If they fall outside the range, the pagination will show additional pages up to the number defined by the `range` prop.
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import React, { useState } from "react";
|
2
|
+
import { Table, Pagination } from 'playbook-ui'
|
3
|
+
|
4
|
+
|
5
|
+
import { data } from "./data";
|
6
|
+
|
7
|
+
const PaginationPageChange = (props) => {
|
8
|
+
|
9
|
+
const [activePage, setActivePage] = useState(1);
|
10
|
+
const rowsPerPage = 3;
|
11
|
+
const totalPages = Math.ceil(data.length / rowsPerPage);
|
12
|
+
|
13
|
+
const onPageChange = (pageNumber) => {
|
14
|
+
setActivePage(pageNumber);
|
15
|
+
};
|
16
|
+
|
17
|
+
const currentData = data.slice(
|
18
|
+
(activePage - 1) * rowsPerPage,
|
19
|
+
activePage * rowsPerPage
|
20
|
+
);
|
21
|
+
|
22
|
+
|
23
|
+
return (
|
24
|
+
<div className="App">
|
25
|
+
<Table
|
26
|
+
marginBottom="xs"
|
27
|
+
responsive="none"
|
28
|
+
size="sm"
|
29
|
+
{...props}
|
30
|
+
>
|
31
|
+
<Table.Head>
|
32
|
+
<Table.Row>
|
33
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
34
|
+
<Table.Header>{"Column 2"}</Table.Header>
|
35
|
+
<Table.Header>{"Column 3"}</Table.Header>
|
36
|
+
<Table.Header>{"Column 4"}</Table.Header>
|
37
|
+
<Table.Header>{"Column 5"}</Table.Header>
|
38
|
+
</Table.Row>
|
39
|
+
</Table.Head>
|
40
|
+
<Table.Body>
|
41
|
+
{currentData.map((row, index) => (
|
42
|
+
<Table.Row key={index}>
|
43
|
+
{row.map((cell, cellIndex) => (
|
44
|
+
<Table.Cell key={cellIndex}>{cell}</Table.Cell>
|
45
|
+
))}
|
46
|
+
</Table.Row>
|
47
|
+
))}
|
48
|
+
</Table.Body>
|
49
|
+
</Table>
|
50
|
+
|
51
|
+
<Pagination
|
52
|
+
current={1}
|
53
|
+
onChange={onPageChange}
|
54
|
+
range={5}
|
55
|
+
total={totalPages}
|
56
|
+
{...props}
|
57
|
+
/>
|
58
|
+
</div>
|
59
|
+
)
|
60
|
+
}
|
61
|
+
|
62
|
+
export default PaginationPageChange
|
@@ -0,0 +1 @@
|
|
1
|
+
You can use the `onChange` prop to control the data of your table. This prop is callback function that will allow you control the state.
|
@@ -0,0 +1,23 @@
|
|
1
|
+
export const data = [
|
2
|
+
["Value 1", "Value 2", "Value 3", "Value 4", "Value 5"],
|
3
|
+
["Value 6", "Value 7", "Value 8", "Value 9", "Value 10"],
|
4
|
+
["Value 11", "Value 12", "Value 13", "Value 14", "Value 15"],
|
5
|
+
["Value 16", "Value 17", "Value 18", "Value 19", "Value 20"],
|
6
|
+
["Value 21", "Value 22", "Value 23", "Value 24", "Value 25"],
|
7
|
+
["Value 26", "Value 27", "Value 28", "Value 29", "Value 30"],
|
8
|
+
["Value 31", "Value 32", "Value 33", "Value 34", "Value 35"],
|
9
|
+
["Value 36", "Value 37", "Value 38", "Value 39", "Value 40"],
|
10
|
+
["Value 41", "Value 42", "Value 43", "Value 44", "Value 45"],
|
11
|
+
["Value 46", "Value 47", "Value 48", "Value 49", "Value 50"],
|
12
|
+
["Value 51", "Value 52", "Value 53", "Value 54", "Value 55"],
|
13
|
+
["Value 56", "Value 57", "Value 58", "Value 59", "Value 60"],
|
14
|
+
["Value 61", "Value 62", "Value 63", "Value 64", "Value 65"],
|
15
|
+
["Value 66", "Value 67", "Value 68", "Value 69", "Value 70"],
|
16
|
+
["Value 71", "Value 72", "Value 73", "Value 74", "Value 75"],
|
17
|
+
["Value 76", "Value 77", "Value 78", "Value 79", "Value 80"],
|
18
|
+
["Value 81", "Value 82", "Value 83", "Value 84", "Value 85"],
|
19
|
+
["Value 86", "Value 87", "Value 88", "Value 89", "Value 90"],
|
20
|
+
["Value 91", "Value 92", "Value 93", "Value 94", "Value 95"],
|
21
|
+
["Value 96", "Value 97", "Value 98", "Value 99", "Value 100"],
|
22
|
+
];
|
23
|
+
|