playbook_ui 15.6.0 → 15.7.0.pre.rc.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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_card/docs/_card_header.md +1 -1
- data/app/pb_kits/playbook/pb_card/docs/_card_highlight.md +1 -1
- data/app/pb_kits/playbook/pb_collapsible/__snapshots__/collapsible.test.js.snap +2 -2
- data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleIcon.tsx +10 -8
- data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_icons.jsx +0 -1
- data/app/pb_kits/playbook/pb_collapsible/docs/_collapsible_state.jsx +0 -3
- data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +24 -0
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +181 -3
- data/app/pb_kits/playbook/pb_distribution_bar/docs/_distribution_bar_custom_colors.md +1 -1
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +316 -15
- data/app/pb_kits/playbook/pb_draggable/context/types.ts +1 -1
- data/app/pb_kits/playbook/pb_filter/Filter/FilterBackground.tsx +3 -3
- data/app/pb_kits/playbook/pb_radio/docs/_radio_error.md +1 -1
- data/app/pb_kits/playbook/pb_select/_select.tsx +8 -3
- data/app/pb_kits/playbook/pb_select/docs/_select_error.md +1 -1
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.html.erb +16 -0
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.jsx +30 -0
- data/app/pb_kits/playbook/pb_select/docs/_select_input_options.md +1 -0
- data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_select/select.html.erb +2 -2
- data/app/pb_kits/playbook/pb_select/select.rb +3 -1
- data/app/pb_kits/playbook/pb_select/select.test.js +23 -0
- data/app/pb_kits/playbook/pb_table/_table.tsx +187 -33
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.jsx +134 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.md +34 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.html.erb +101 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.md +33 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.jsx +180 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.md +3 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.html.erb +122 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.md +3 -0
- data/app/pb_kits/playbook/pb_table/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_table/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_table/table.html.erb +68 -12
- data/app/pb_kits/playbook/pb_table/table.rb +22 -3
- data/app/pb_kits/playbook/pb_table/table.test.js +143 -0
- data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.md +1 -1
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.md +1 -1
- data/app/pb_kits/playbook/pb_timeline/_item.tsx +3 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.html.erb +60 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.jsx +118 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.md +1 -0
- data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_date.md +1 -1
- data/app/pb_kits/playbook/pb_timeline/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_timeline/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_timeline/item.html.erb +1 -1
- data/app/pb_kits/playbook/pb_timeline/item.rb +2 -0
- data/app/pb_kits/playbook/pb_timeline/label.html.erb +2 -1
- data/app/pb_kits/playbook/pb_timeline/label.rb +2 -0
- data/app/pb_kits/playbook/pb_timeline/subcomponents/Label.tsx +3 -0
- data/app/pb_kits/playbook/pb_timeline/timeline.test.js +51 -0
- data/app/pb_kits/playbook/tokens/_colors.scss +2 -1
- data/app/pb_kits/playbook/utilities/deprecated.ts +73 -0
- data/dist/chunks/_typeahead-CHwm9MTE.js +6 -0
- data/dist/chunks/lib-Cugvy62C.js +29 -0
- data/dist/chunks/vendor.js +2 -2
- 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/forms/builder/collection_select_field.rb +9 -1
- data/lib/playbook/forms/builder/select_field.rb +9 -1
- data/lib/playbook/forms/builder/time_zone_select_field.rb +9 -1
- data/lib/playbook/pb_kit_helper.rb +35 -0
- data/lib/playbook/version.rb +2 -2
- metadata +19 -4
- data/dist/chunks/_typeahead-DecTL7bt.js +0 -6
- data/dist/chunks/lib-Dk4GKPut.js +0 -29
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import React, { useState } from "react"
|
|
2
|
+
import { Button, Date as DateKit, DatePicker, Dropdown, Pagination, Select, Table, TextInput, Typeahead, Flex } from "playbook-ui"
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
// Mock Data for Table
|
|
6
|
+
const users = [
|
|
7
|
+
{ id: 1, name: "Jennifer", title: "Associate Scrum Master", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-01" },
|
|
8
|
+
{ id: 2, name: "Nick", title: "UX Engineer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-02" },
|
|
9
|
+
{ id: 3, name: "Nida", title: "Senior UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-03" },
|
|
10
|
+
{ id: 4, name: "Justin", title: "Director of User Experience Engineering", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-04" },
|
|
11
|
+
{ id: 5, name: "Edward", title: "UX Designer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-05" },
|
|
12
|
+
{ id: 6, name: "Elisa", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-06" },
|
|
13
|
+
{ id: 7, name: "Gary", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-07" },
|
|
14
|
+
{ id: 8, name: "Barkley", title: "Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-08" },
|
|
15
|
+
{ id: 9, name: "Aaron", title: "Associate Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-09" },
|
|
16
|
+
{ id: 10, name: "Sarah", title: "Senior Product Manager", department: "Business Technology", branch: "New York", startDate: "2025-01-10" },
|
|
17
|
+
{ id: 11, name: "Michael", title: "Software Engineer III", department: "Business Technology", branch: "Austin", startDate: "2025-01-11" },
|
|
18
|
+
{ id: 12, name: "Emma", title: "Data Analyst II", department: "Customer Development", branch: "Philadelphia", startDate: "2025-01-12" },
|
|
19
|
+
{ id: 13, name: "David", title: "QA Engineer", department: "Business Technology", branch: "New York", startDate: "2025-01-13" },
|
|
20
|
+
{ id: 14, name: "Lisa", title: "UX Researcher", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-14" },
|
|
21
|
+
{ id: 15, name: "James", title: "DevOps Engineer", department: "Business Technology", branch: "Austin", startDate: "2025-01-15" },
|
|
22
|
+
{ id: 16, name: "Anna", title: "Product Designer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-16" },
|
|
23
|
+
{ id: 17, name: "Robert", title: "Backend Engineer", department: "Business Technology", branch: "New York", startDate: "2025-01-17" },
|
|
24
|
+
{ id: 18, name: "Maria", title: "Frontend Developer", department: "Business Technology", branch: "Austin", startDate: "2025-01-18" },
|
|
25
|
+
{ id: 19, name: "William", title: "Tech Lead", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-19" },
|
|
26
|
+
{ id: 20, name: "Jessica", title: "Scrum Master", department: "Business Technology", branch: "New York", startDate: "2025-01-20" },
|
|
27
|
+
{ id: 21, name: "Daniel", title: "Software Architect", department: "Business Technology", branch: "Austin", startDate: "2025-01-21" },
|
|
28
|
+
{ id: 22, name: "Laura", title: "Business Analyst", department: "Customer Development", branch: "Philadelphia", startDate: "2025-01-22" },
|
|
29
|
+
{ id: 23, name: "Chris", title: "Security Engineer", department: "Business Technology", branch: "New York", startDate: "2025-01-23" },
|
|
30
|
+
{ id: 24, name: "Ashley", title: "UX Engineer III", department: "Business Technology", branch: "Austin", startDate: "2025-01-24" },
|
|
31
|
+
{ id: 25, name: "Kevin", title: "Platform Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-25" },
|
|
32
|
+
{ id: 26, name: "Michelle", title: "Content Designer", department: "Business Technology", branch: "New York", startDate: "2025-01-26" },
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const TableWithFilterVariantWithPagination = () => {
|
|
37
|
+
const [territory, setTerritory] = useState("")
|
|
38
|
+
// ------Pagination-----
|
|
39
|
+
const [activePage, setActivePage] = useState(1)
|
|
40
|
+
// Calculate pagination
|
|
41
|
+
const itemsPerPage = 20
|
|
42
|
+
const totalPages = Math.ceil(users.length / itemsPerPage)
|
|
43
|
+
const startIndex = (activePage - 1) * itemsPerPage
|
|
44
|
+
const endIndex = startIndex + itemsPerPage
|
|
45
|
+
const currentData = users.slice(startIndex, endIndex)
|
|
46
|
+
|
|
47
|
+
const onPageChange = (page) => {
|
|
48
|
+
setActivePage(page)
|
|
49
|
+
}
|
|
50
|
+
// ------End Pagination-----
|
|
51
|
+
|
|
52
|
+
// -------Filter content example ------
|
|
53
|
+
const filterContent = ({ closePopover }) => (
|
|
54
|
+
<>
|
|
55
|
+
<TextInput
|
|
56
|
+
label="Territory ID"
|
|
57
|
+
onChange={event => setTerritory(event.target.value)}
|
|
58
|
+
value={territory}
|
|
59
|
+
/>
|
|
60
|
+
<Typeahead
|
|
61
|
+
label="Title"
|
|
62
|
+
options={[
|
|
63
|
+
{ key: "senior-ux-engineer", label: "Senior UX Engineer", value: "senior-ux-engineer" },
|
|
64
|
+
{ key: "ux-engineer", label: "UX Engineer", value: "ux-engineer" },
|
|
65
|
+
{ key: "ux-designer", label: "UX Designer", value: "ux-designer" }
|
|
66
|
+
]}
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<Select
|
|
70
|
+
blankSelection="All Departments"
|
|
71
|
+
label="Department"
|
|
72
|
+
options={[
|
|
73
|
+
{ value: "Business Technology", label: "Business Technology", key: "business-technology" },
|
|
74
|
+
{ value: "Customer Development", label: "Customer Development", key: "customer-development" },
|
|
75
|
+
{ value: "Talent Acquisition", label: "Talent Acquisition", key: "talent-acquisition" }
|
|
76
|
+
]}
|
|
77
|
+
/>
|
|
78
|
+
|
|
79
|
+
<Dropdown
|
|
80
|
+
label="Branch"
|
|
81
|
+
options={[
|
|
82
|
+
{ key: "Philadelphia", label: "Philadelphia", value: "philadelphia" },
|
|
83
|
+
{ key: "New York", label: "New York", value: "new-york" },
|
|
84
|
+
{ key: "Austin", label: "Austin", value: "austin" }
|
|
85
|
+
]}
|
|
86
|
+
/>
|
|
87
|
+
|
|
88
|
+
<DatePicker
|
|
89
|
+
label="Start Date"
|
|
90
|
+
paddingY="sm"
|
|
91
|
+
pickerId="startedOn"
|
|
92
|
+
/>
|
|
93
|
+
<Flex spacing="between">
|
|
94
|
+
<Button
|
|
95
|
+
onClick={() => {
|
|
96
|
+
alert("No filtering functionality - just a pattern demo!")
|
|
97
|
+
closePopover()
|
|
98
|
+
}}
|
|
99
|
+
text="Filter"
|
|
100
|
+
/>
|
|
101
|
+
<Button
|
|
102
|
+
text="Defaults"
|
|
103
|
+
variant="secondary"
|
|
104
|
+
/>
|
|
105
|
+
</Flex>
|
|
106
|
+
</>
|
|
107
|
+
)
|
|
108
|
+
// -------End Filter content example ------
|
|
109
|
+
|
|
110
|
+
// -------Pagination element example ------
|
|
111
|
+
const paginationElement = (
|
|
112
|
+
<Pagination
|
|
113
|
+
current={activePage}
|
|
114
|
+
key={`pagination-${activePage}`}
|
|
115
|
+
marginLeft="lg"
|
|
116
|
+
onChange={onPageChange}
|
|
117
|
+
paddingY="xs"
|
|
118
|
+
range={5}
|
|
119
|
+
total={totalPages}
|
|
120
|
+
/>
|
|
121
|
+
)
|
|
122
|
+
// -------End Pagination element example ------
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<Table
|
|
126
|
+
filterContent={filterContent}
|
|
127
|
+
filterProps={{
|
|
128
|
+
results: 50,
|
|
129
|
+
sortOptions: {
|
|
130
|
+
territory_id: "Territory ID",
|
|
131
|
+
first_name: "Name",
|
|
132
|
+
started_on: "Start Date",
|
|
133
|
+
department_name: "Department",
|
|
134
|
+
title_name: "Title",
|
|
135
|
+
branch_branch_name: "Branch",
|
|
136
|
+
},
|
|
137
|
+
sortValue: [{ name: 'started_on', dir: 'asc' }],
|
|
138
|
+
}}
|
|
139
|
+
pagination={paginationElement}
|
|
140
|
+
title="Table Title Here"
|
|
141
|
+
variant="withFilter"
|
|
142
|
+
>
|
|
143
|
+
<Table.Head>
|
|
144
|
+
<Table.Row>
|
|
145
|
+
<Table.Header>{'Territory ID'}</Table.Header>
|
|
146
|
+
<Table.Header>{'Name'}</Table.Header>
|
|
147
|
+
<Table.Header>{'Title'}</Table.Header>
|
|
148
|
+
<Table.Header>{'Department'}</Table.Header>
|
|
149
|
+
<Table.Header>{'Branch'}</Table.Header>
|
|
150
|
+
<Table.Header textAlign="right">{'Start Date'}</Table.Header>
|
|
151
|
+
</Table.Row>
|
|
152
|
+
</Table.Head>
|
|
153
|
+
<Table.Body>
|
|
154
|
+
{currentData.map((user) => (
|
|
155
|
+
<Table.Row key={user.id}>
|
|
156
|
+
<Table.Cell
|
|
157
|
+
marginX={{ xs: "sm" }}
|
|
158
|
+
numberSpacing="tabular"
|
|
159
|
+
>
|
|
160
|
+
{user.id}
|
|
161
|
+
</Table.Cell>
|
|
162
|
+
<Table.Cell marginX={{ xs: "sm" }}>{user.name}</Table.Cell>
|
|
163
|
+
<Table.Cell marginX={{ xs: "sm" }}>{user.title}</Table.Cell>
|
|
164
|
+
<Table.Cell marginX={{ xs: "sm" }}>{user.department}</Table.Cell>
|
|
165
|
+
<Table.Cell marginX={{ xs: "sm" }}>{user.branch}</Table.Cell>
|
|
166
|
+
<Table.Cell marginX={{ xs: "sm" }}>
|
|
167
|
+
<DateKit
|
|
168
|
+
alignment="right"
|
|
169
|
+
showCurrentYear
|
|
170
|
+
value={user.startDate}
|
|
171
|
+
/>
|
|
172
|
+
</Table.Cell>
|
|
173
|
+
</Table.Row>
|
|
174
|
+
))}
|
|
175
|
+
</Table.Body>
|
|
176
|
+
</Table>
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
export default TableWithFilterVariantWithPagination
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
The `withFilter` variant can also be used with the Pagination kit as shown here. Simply set up your Pagination as normal, and pass the Pagination kit to the prop `pagination` as shown.
|
|
2
|
+
|
|
3
|
+
For more information on the Pagination Kit and how to use it, see the documentation [here](https://playbook.powerapp.cloud/kits/pagination/react)
|
data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.html.erb
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<% users = [
|
|
2
|
+
{ id: 1, name: "Jennifer", title: "Associate Scrum Master", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 1) },
|
|
3
|
+
{ id: 2, name: "Nick", title: "UX Engineer II", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 2) },
|
|
4
|
+
{ id: 3, name: "Nida", title: "Senior UX Engineer", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 3) },
|
|
5
|
+
{ id: 4, name: "Justin", title: "Director of User Experience Engineering", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 4) },
|
|
6
|
+
{ id: 5, name: "Edward", title: "UX Designer II", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 5) },
|
|
7
|
+
{ id: 6, name: "Elisa", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 6) },
|
|
8
|
+
{ id: 7, name: "Gary", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 7) },
|
|
9
|
+
{ id: 8, name: "Barkley", title: "Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 8) },
|
|
10
|
+
{ id: 9, name: "Aaron", title: "Associate Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 9) },
|
|
11
|
+
{ id: 10, name: "Sarah", title: "Senior Product Manager", department: "Business Technology", branch: "New York", start_date: Date.new(2025, 1, 10) },
|
|
12
|
+
{ id: 11, name: "Michael", title: "Software Engineer III", department: "Business Technology", branch: "Austin", start_date: Date.new(2025, 1, 11) },
|
|
13
|
+
{ id: 12, name: "Emma", title: "Data Analyst II", department: "Customer Development", branch: "Philadelphia", start_date: Date.new(2025, 1, 12) },
|
|
14
|
+
{ id: 13, name: "David", title: "QA Engineer", department: "Business Technology", branch: "New York", start_date: Date.new(2025, 1, 13) },
|
|
15
|
+
{ id: 14, name: "Lisa", title: "UX Researcher", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 14) },
|
|
16
|
+
{ id: 15, name: "James", title: "DevOps Engineer", department: "Business Technology", branch: "Austin", start_date: Date.new(2025, 1, 15) },
|
|
17
|
+
{ id: 16, name: "Anna", title: "Product Designer", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 16) },
|
|
18
|
+
{ id: 17, name: "Robert", title: "Backend Engineer", department: "Business Technology", branch: "New York", start_date: Date.new(2025, 1, 17) },
|
|
19
|
+
{ id: 18, name: "Maria", title: "Frontend Developer", department: "Business Technology", branch: "Austin", start_date: Date.new(2025, 1, 18) },
|
|
20
|
+
{ id: 19, name: "William", title: "Tech Lead", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 19) },
|
|
21
|
+
{ id: 20, name: "Jessica", title: "Scrum Master", department: "Business Technology", branch: "New York", start_date: Date.new(2025, 1, 20) },
|
|
22
|
+
{ id: 21, name: "Daniel", title: "Software Architect", department: "Business Technology", branch: "Austin", start_date: Date.new(2025, 1, 21) },
|
|
23
|
+
{ id: 22, name: "Laura", title: "Business Analyst", department: "Customer Development", branch: "Philadelphia", start_date: Date.new(2025, 1, 22) },
|
|
24
|
+
{ id: 23, name: "Chris", title: "Security Engineer", department: "Business Technology", branch: "New York", start_date: Date.new(2025, 1, 23) },
|
|
25
|
+
{ id: 24, name: "Ashley", title: "UX Engineer III", department: "Business Technology", branch: "Austin", start_date: Date.new(2025, 1, 24) },
|
|
26
|
+
{ id: 25, name: "Kevin", title: "Platform Engineer", department: "Business Technology", branch: "Philadelphia", start_date: Date.new(2025, 1, 25) },
|
|
27
|
+
{ id: 26, name: "Michelle", title: "Content Designer", department: "Business Technology", branch: "New York", start_date: Date.new(2025, 1, 26) },
|
|
28
|
+
] %>
|
|
29
|
+
|
|
30
|
+
<% filter_content =
|
|
31
|
+
pb_rails("text_input", props: {
|
|
32
|
+
label: "Territory ID",
|
|
33
|
+
placeholder: "Enter Territory ID"
|
|
34
|
+
}) +
|
|
35
|
+
pb_rails("typeahead", props: {
|
|
36
|
+
label: "Title",
|
|
37
|
+
options: [
|
|
38
|
+
{ label: "Senior UX Engineer", value: "senior-ux-engineer" },
|
|
39
|
+
{ label: "UX Engineer", value: "ux-engineer" },
|
|
40
|
+
{ label: "UX Designer", value: "ux-designer" }
|
|
41
|
+
]
|
|
42
|
+
}) +
|
|
43
|
+
pb_rails("select", props: {
|
|
44
|
+
blank_selection: "All Departments",
|
|
45
|
+
label: "Department",
|
|
46
|
+
options: [
|
|
47
|
+
{ value: "Business Technology", text: "Business Technology" },
|
|
48
|
+
{ value: "Customer Development", text: "Customer Development" },
|
|
49
|
+
{ value: "Talent Acquisition", text: "Talent Acquisition" }
|
|
50
|
+
]
|
|
51
|
+
}) +
|
|
52
|
+
pb_rails("dropdown", props: {
|
|
53
|
+
label: "Branch",
|
|
54
|
+
options: [
|
|
55
|
+
{ label: "Philadelphia", value: "philadelphia" },
|
|
56
|
+
{ label: "New York", value: "new-york" },
|
|
57
|
+
{ label: "Austin", value: "austin" }
|
|
58
|
+
]
|
|
59
|
+
}) +
|
|
60
|
+
pb_rails("date_picker", props: {
|
|
61
|
+
label: "Start Date",
|
|
62
|
+
padding_y: "sm",
|
|
63
|
+
picker_id: "startedOn"
|
|
64
|
+
}) +
|
|
65
|
+
pb_rails("flex", props: { spacing: "between" }) do
|
|
66
|
+
pb_rails("button", props: {
|
|
67
|
+
text: "Filter",
|
|
68
|
+
}) +
|
|
69
|
+
pb_rails("button", props: {
|
|
70
|
+
text: "Defaults",
|
|
71
|
+
variant: "secondary"
|
|
72
|
+
})
|
|
73
|
+
end
|
|
74
|
+
%>
|
|
75
|
+
|
|
76
|
+
<%# Replace "model" in pagination here with your specific data source %>
|
|
77
|
+
<% pagination_element = pb_rails("pagination", props: { model: @users, view: self, padding_y:"xs", margin_left:"lg" }) %>
|
|
78
|
+
|
|
79
|
+
<%= pb_rails("table", props: {
|
|
80
|
+
variant: "with_filter",
|
|
81
|
+
title: "Table Title Here",
|
|
82
|
+
filter_content: filter_content,
|
|
83
|
+
pagination: pagination_element,
|
|
84
|
+
filter_props: {
|
|
85
|
+
id: "user-table-filters-2",
|
|
86
|
+
results: users.length,
|
|
87
|
+
sort_menu: [
|
|
88
|
+
{ item: "Start Date", link: "?q[sorts]=started_on+asc", active: true, direction: "asc" },
|
|
89
|
+
{ item: "First Name", link: "?q[sorts]=name+asc", active: false },
|
|
90
|
+
{ item: "Title", link: "?q[sorts]=title+asc", active: false },
|
|
91
|
+
{ item: "Department", link: "?q[sorts]=department+asc", active: false },
|
|
92
|
+
{ item: "Branch", link: "?q[sorts]=branch+asc", active: false },
|
|
93
|
+
{ item: "Territory ID", link: "?q[sorts]=territory_id+asc", active: false },
|
|
94
|
+
],
|
|
95
|
+
}
|
|
96
|
+
}) do %>
|
|
97
|
+
<%= pb_rails("table/table_head") do %>
|
|
98
|
+
<%= pb_rails("table/table_row") do %>
|
|
99
|
+
<%= pb_rails("table/table_header", props: { text: "Territory ID" }) %>
|
|
100
|
+
<%= pb_rails("table/table_header", props: { text: "Name" }) %>
|
|
101
|
+
<%= pb_rails("table/table_header", props: { text: "Title" }) %>
|
|
102
|
+
<%= pb_rails("table/table_header", props: { text: "Department" }) %>
|
|
103
|
+
<%= pb_rails("table/table_header", props: { text: "Branch" }) %>
|
|
104
|
+
<%= pb_rails("table/table_header", props: { text: "Start Date", text_align: "right" }) %>
|
|
105
|
+
<% end %>
|
|
106
|
+
<% end %>
|
|
107
|
+
|
|
108
|
+
<%= pb_rails("table/table_body") do %>
|
|
109
|
+
<% users.each do |user| %>
|
|
110
|
+
<%= pb_rails("table/table_row") do %>
|
|
111
|
+
<%= pb_rails("table/table_cell", props: { margin_x: { xs: "sm" }, number_spacing: "tabular" }) { user[:id].to_s } %>
|
|
112
|
+
<%= pb_rails("table/table_cell", props: { margin_x: { xs: "sm" } }) { user[:name] } %>
|
|
113
|
+
<%= pb_rails("table/table_cell", props: { margin_x: { xs: "sm" } }) { user[:title] } %>
|
|
114
|
+
<%= pb_rails("table/table_cell", props: { margin_x: { xs: "sm" } }) { user[:department] } %>
|
|
115
|
+
<%= pb_rails("table/table_cell", props: { margin_x: { xs: "sm" } }) { user[:branch] } %>
|
|
116
|
+
<%= pb_rails("table/table_cell", props: { margin_x: { xs: "sm" } }) do %>
|
|
117
|
+
<%= pb_rails("date", props: {alignment: "right", date: user[:start_date].to_s, show_current_year: true } ) %>
|
|
118
|
+
<% end %>
|
|
119
|
+
<% end %>
|
|
120
|
+
<% end %>
|
|
121
|
+
<% end %>
|
|
122
|
+
<% end %>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
The `with_filter` variant can also be used with the Pagination kit as shown here. Simply set up your Pagination as normal, and pass the Pagination kit to the prop `pagination` as shown.
|
|
2
|
+
|
|
3
|
+
**IMPORTANT NOTE**: This is NOT a working example of pagination, please set up your use case with the relevant data in your controller. For more information on the Pagination Kit and how to use it, see the documentation [here](https://playbook.powerapp.cloud/kits/pagination/rails)
|
|
@@ -40,6 +40,8 @@ examples:
|
|
|
40
40
|
- table_with_selectable_rows: Table with Selectable Rows
|
|
41
41
|
- table_with_header_style_borderless: Header Style Borderless
|
|
42
42
|
- table_with_header_style_floating: Header Style Floating
|
|
43
|
+
- table_with_filter_variant_rails: Variant with Filter
|
|
44
|
+
- table_with_filter_variant_with_pagination_rails: Variant with Filter and Pagination
|
|
43
45
|
|
|
44
46
|
react:
|
|
45
47
|
- table_sm: Small
|
|
@@ -81,3 +83,5 @@ examples:
|
|
|
81
83
|
- table_with_selectable_rows: Table with Selectable Rows
|
|
82
84
|
- table_with_header_style_borderless: Header Style Borderless
|
|
83
85
|
- table_with_header_style_floating: Header Style Floating
|
|
86
|
+
- table_with_filter_variant: Variant with Filter
|
|
87
|
+
- table_with_filter_variant_with_pagination: Variant with Filter and Pagination
|
|
@@ -38,3 +38,5 @@ export { default as TableWithSelectableRows } from './_table_with_selectable_row
|
|
|
38
38
|
export { default as TableWithClickableRows } from './_table_with_clickable_rows.jsx'
|
|
39
39
|
export { default as TableWithHeaderStyleBorderless } from './_table_with_header_style_borderless.jsx'
|
|
40
40
|
export { default as TableWithHeaderStyleFloating } from './_table_with_header_style_floating.jsx'
|
|
41
|
+
export { default as TableWithFilterVariant } from './_table_with_filter_variant.jsx'
|
|
42
|
+
export { default as TableWithFilterVariantWithPagination } from './_table_with_filter_variant_with_pagination.jsx'
|
|
@@ -1,17 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
1
|
+
<%# ------------ variant = 'withFilter' rendering ------------ %>
|
|
2
|
+
<% if object.with_filter_variant? %>
|
|
3
|
+
<%= pb_rails("title", props: {
|
|
4
|
+
padding_left: { xs: "sm", sm: "sm", md: "xl", lg: "xl", xl: "xl", default: "xl" },
|
|
5
|
+
padding_y: "md",
|
|
6
|
+
size: 3,
|
|
7
|
+
text: object.title
|
|
8
|
+
}) if object.title.present? %>
|
|
9
|
+
<%= pb_rails("card", props: {
|
|
10
|
+
margin_x: { xs: "sm", sm: "sm", md: "xl", lg: "xl", xl: "xl", default: "xl" },
|
|
11
|
+
padding: "none"
|
|
12
|
+
}) do %>
|
|
13
|
+
<%= pb_rails("flex", props: {
|
|
14
|
+
align: "stretch",
|
|
15
|
+
flex_direction: "column",
|
|
16
|
+
gap: "none"
|
|
17
|
+
}) do %>
|
|
18
|
+
<% if object.filter_content.present? %>
|
|
19
|
+
<%
|
|
20
|
+
default_filter_props = {
|
|
21
|
+
background: false,
|
|
22
|
+
max_height: "50vh",
|
|
23
|
+
min_width: "xs",
|
|
24
|
+
popover_props: { width: "350px" },
|
|
25
|
+
template: 'single'
|
|
26
|
+
}
|
|
27
|
+
merged_filter_props = default_filter_props.merge(object.filter_props)
|
|
28
|
+
%>
|
|
29
|
+
<%= pb_rails("filter", props: merged_filter_props) do %>
|
|
30
|
+
<%= object.filter_content %>
|
|
31
|
+
<% end %>
|
|
32
|
+
<% end %>
|
|
33
|
+
<%= pb_rails("section_separator") if object.filter_content.present? %>
|
|
34
|
+
<% if object.pagination.present? %>
|
|
35
|
+
<%= object.pagination %>
|
|
36
|
+
<%= pb_rails("section_separator") %>
|
|
37
|
+
<% end %>
|
|
38
|
+
<% if object.tag == "table" %>
|
|
39
|
+
<%= pb_content_tag(:table) do %>
|
|
40
|
+
<%= content.presence %>
|
|
41
|
+
<% end %>
|
|
42
|
+
<% else %>
|
|
43
|
+
<%= pb_content_tag do %>
|
|
44
|
+
<%= content.presence %>
|
|
45
|
+
<% end %>
|
|
46
|
+
<% end %>
|
|
47
|
+
<% if object.pagination.present? %>
|
|
48
|
+
<%= object.pagination %>
|
|
49
|
+
<% end %>
|
|
11
50
|
<% end %>
|
|
51
|
+
<% end %>
|
|
52
|
+
<%# ------------ End variant = 'withFilter' rendering ------------ %>
|
|
53
|
+
<% else %>
|
|
54
|
+
<%# ------------ Default Table (non-filter variant rendering) ------------ %>
|
|
55
|
+
<% if object.responsive_classname %>
|
|
56
|
+
<% responsive_class = object.responsive_classname %>
|
|
12
57
|
<% else %>
|
|
13
|
-
|
|
14
|
-
|
|
58
|
+
<% responsive_class = nil %>
|
|
59
|
+
<% end %>
|
|
60
|
+
|
|
61
|
+
<%= content_tag(:div, class: responsive_class, 'data-pb-table-wrapper' => true) do %>
|
|
62
|
+
<% if object.tag == "table" %>
|
|
63
|
+
<%= pb_content_tag(:table) do %>
|
|
64
|
+
<%= content.presence %>
|
|
65
|
+
<% end %>
|
|
66
|
+
<% else %>
|
|
67
|
+
<%= pb_content_tag do %>
|
|
68
|
+
<%= content.presence %>
|
|
69
|
+
<% end %>
|
|
15
70
|
<% end %>
|
|
16
71
|
<% end %>
|
|
72
|
+
<%# ------------ End Default Table (non-filter variant rendering) ------------ %>
|
|
17
73
|
<% end %>
|
|
@@ -40,10 +40,23 @@ module Playbook
|
|
|
40
40
|
prop :header_style, type: Playbook::Props::Enum,
|
|
41
41
|
values: %w[default borderless floating],
|
|
42
42
|
default: "default"
|
|
43
|
+
prop :variant, type: Playbook::Props::Enum,
|
|
44
|
+
values: %w[default with_filter],
|
|
45
|
+
default: "default"
|
|
46
|
+
prop :filter_props, type: Playbook::Props::HashProp,
|
|
47
|
+
default: {}
|
|
48
|
+
prop :filter_content
|
|
49
|
+
prop :pagination
|
|
50
|
+
prop :title, type: Playbook::Props::String,
|
|
51
|
+
default: nil
|
|
52
|
+
|
|
53
|
+
def size_class
|
|
54
|
+
variant === "with_filter" && size == "md" ? "sm" : size
|
|
55
|
+
end
|
|
43
56
|
|
|
44
57
|
def classname
|
|
45
58
|
generate_classname(
|
|
46
|
-
"pb_table", "table-#{
|
|
59
|
+
"pb_table", "table-#{size_class}", single_line_class, dark_class,
|
|
47
60
|
disable_hover_class, container_class, data_table_class, sticky_class, sticky_left_column_class,
|
|
48
61
|
sticky_right_column_class, collapse_class, vertical_border_class, striped_class, outer_padding_class,
|
|
49
62
|
"table-responsive-#{responsive}", header_style_class, separator: " "
|
|
@@ -54,6 +67,10 @@ module Playbook
|
|
|
54
67
|
responsive ? "table-responsive-#{responsive}" : nil
|
|
55
68
|
end
|
|
56
69
|
|
|
70
|
+
def with_filter_variant?
|
|
71
|
+
variant == "with_filter"
|
|
72
|
+
end
|
|
73
|
+
|
|
57
74
|
private
|
|
58
75
|
|
|
59
76
|
def dark_class
|
|
@@ -73,11 +90,13 @@ module Playbook
|
|
|
73
90
|
end
|
|
74
91
|
|
|
75
92
|
def container_class
|
|
76
|
-
|
|
93
|
+
effective_container = variant == "with_filter" ? false : container
|
|
94
|
+
effective_container ? "table-card" : nil
|
|
77
95
|
end
|
|
78
96
|
|
|
79
97
|
def collapse_class
|
|
80
|
-
|
|
98
|
+
effective_collapse = variant == "with_filter" && collapse == "sm" ? "md" : collapse
|
|
99
|
+
responsive != "none" ? "table-collapse-#{effective_collapse}" : ""
|
|
81
100
|
end
|
|
82
101
|
|
|
83
102
|
def sticky_class
|
|
@@ -184,3 +184,146 @@ test("when headerStyle is floating", () => {
|
|
|
184
184
|
const kit = renderKit(Table, props, { headerStyle: "floating" })
|
|
185
185
|
expect(kit).toHaveClass("pb_table table-sm table-responsive-collapse table-card header-floating table-collapse-sm")
|
|
186
186
|
})
|
|
187
|
+
|
|
188
|
+
test("renders withFilter variant with Card wrapper", () => {
|
|
189
|
+
const { container } = render(
|
|
190
|
+
<Table
|
|
191
|
+
data={{testid: "table-with-filter"}}
|
|
192
|
+
filterContent={<div>{"Mock Filter"}</div>}
|
|
193
|
+
title="Test Table"
|
|
194
|
+
variant="withFilter"
|
|
195
|
+
>
|
|
196
|
+
<Table.Head>
|
|
197
|
+
<Table.Row>
|
|
198
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
|
199
|
+
</Table.Row>
|
|
200
|
+
</Table.Head>
|
|
201
|
+
<Table.Body>
|
|
202
|
+
<Table.Row>
|
|
203
|
+
<Table.Cell>{"Value 1"}</Table.Cell>
|
|
204
|
+
</Table.Row>
|
|
205
|
+
</Table.Body>
|
|
206
|
+
</Table>
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
const card = container.querySelector('.pb_card_kit')
|
|
210
|
+
expect(card).toBeInTheDocument()
|
|
211
|
+
const filter = container.querySelector('.pb_filter_kit')
|
|
212
|
+
expect(filter).toBeInTheDocument()
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
test("renders title when provided with withFilter variant", () => {
|
|
216
|
+
render(
|
|
217
|
+
<Table
|
|
218
|
+
filterContent={<div>{"Mock Filter"}</div>}
|
|
219
|
+
title="Test Title"
|
|
220
|
+
variant="withFilter"
|
|
221
|
+
>
|
|
222
|
+
<Table.Head>
|
|
223
|
+
<Table.Row>
|
|
224
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
|
225
|
+
</Table.Row>
|
|
226
|
+
</Table.Head>
|
|
227
|
+
<Table.Body>
|
|
228
|
+
<Table.Row>
|
|
229
|
+
<Table.Cell>{"Value 1"}</Table.Cell>
|
|
230
|
+
</Table.Row>
|
|
231
|
+
</Table.Body>
|
|
232
|
+
</Table>
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
expect(screen.getByText("Test Title")).toBeInTheDocument()
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
test("renders filter component in withFilter variant", () => {
|
|
239
|
+
const { container } = render(
|
|
240
|
+
<Table
|
|
241
|
+
filterContent={<div data-testid="test-filter">{"Filter inputs"}</div>}
|
|
242
|
+
variant="withFilter"
|
|
243
|
+
>
|
|
244
|
+
<Table.Head>
|
|
245
|
+
<Table.Row>
|
|
246
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
|
247
|
+
</Table.Row>
|
|
248
|
+
</Table.Head>
|
|
249
|
+
<Table.Body>
|
|
250
|
+
<Table.Row>
|
|
251
|
+
<Table.Cell>{"Value 1"}</Table.Cell>
|
|
252
|
+
</Table.Row>
|
|
253
|
+
</Table.Body>
|
|
254
|
+
</Table>
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
const filter = container.querySelector('.pb_filter_kit')
|
|
258
|
+
expect(filter).toBeInTheDocument()
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test("renders SectionSeparator between filter and table in withFilter variant", () => {
|
|
262
|
+
const { container } = render(
|
|
263
|
+
<Table
|
|
264
|
+
filterContent={<div>{"Filter content"}</div>}
|
|
265
|
+
variant="withFilter"
|
|
266
|
+
>
|
|
267
|
+
<Table.Head>
|
|
268
|
+
<Table.Row>
|
|
269
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
|
270
|
+
</Table.Row>
|
|
271
|
+
</Table.Head>
|
|
272
|
+
<Table.Body>
|
|
273
|
+
<Table.Row>
|
|
274
|
+
<Table.Cell>{"Value 1"}</Table.Cell>
|
|
275
|
+
</Table.Row>
|
|
276
|
+
</Table.Body>
|
|
277
|
+
</Table>
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
const separator = container.querySelector('.pb_section_separator_kit')
|
|
281
|
+
expect(separator).toBeInTheDocument()
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
test("does not render title when not provided with withFilter variant", () => {
|
|
285
|
+
const { container } = render(
|
|
286
|
+
<Table
|
|
287
|
+
filterContent={<div>{"Filter content"}</div>}
|
|
288
|
+
variant="withFilter"
|
|
289
|
+
>
|
|
290
|
+
<Table.Head>
|
|
291
|
+
<Table.Row>
|
|
292
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
|
293
|
+
</Table.Row>
|
|
294
|
+
</Table.Head>
|
|
295
|
+
<Table.Body>
|
|
296
|
+
<Table.Row>
|
|
297
|
+
<Table.Cell>{"Value 1"}</Table.Cell>
|
|
298
|
+
</Table.Row>
|
|
299
|
+
</Table.Body>
|
|
300
|
+
</Table>
|
|
301
|
+
)
|
|
302
|
+
|
|
303
|
+
const title = container.querySelector('.pb_title_kit')
|
|
304
|
+
expect(title).not.toBeInTheDocument()
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
test("renders default variant without Card wrapper", () => {
|
|
308
|
+
render(
|
|
309
|
+
<Table
|
|
310
|
+
data={{testid: "default-table"}}
|
|
311
|
+
variant="default"
|
|
312
|
+
>
|
|
313
|
+
<Table.Head>
|
|
314
|
+
<Table.Row>
|
|
315
|
+
<Table.Header>{"Column 1"}</Table.Header>
|
|
316
|
+
</Table.Row>
|
|
317
|
+
</Table.Head>
|
|
318
|
+
<Table.Body>
|
|
319
|
+
<Table.Row>
|
|
320
|
+
<Table.Cell>{"Value 1"}</Table.Cell>
|
|
321
|
+
</Table.Row>
|
|
322
|
+
</Table.Body>
|
|
323
|
+
</Table>
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
const table = screen.getByTestId("default-table")
|
|
327
|
+
expect(table).toBeInTheDocument()
|
|
328
|
+
expect(table.closest('.pb_card_kit')).not.toBeInTheDocument()
|
|
329
|
+
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Text Input w/ Error shows that the
|
|
1
|
+
Text Input w/ Error shows that the input must be filled out (i.e. when used in a form it signals a user to fix an error).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Textarea w/ Error shows that the
|
|
1
|
+
Textarea w/ Error shows that the input must be filled out (i.e. when used in a form it signals a user to fix an error).
|
|
@@ -18,6 +18,7 @@ type ItemProps = {
|
|
|
18
18
|
icon?: string,
|
|
19
19
|
iconColor?: 'default' | 'royal' | 'blue' | 'purple' | 'teal' | 'red' | 'yellow' | 'green',
|
|
20
20
|
lineStyle?: 'solid' | 'dotted',
|
|
21
|
+
showCurrentYear?: boolean,
|
|
21
22
|
} & GlobalProps
|
|
22
23
|
|
|
23
24
|
function isElementOfType<P>(
|
|
@@ -35,6 +36,7 @@ const TimelineItem = ({
|
|
|
35
36
|
icon = 'user',
|
|
36
37
|
iconColor = 'default',
|
|
37
38
|
lineStyle = 'solid',
|
|
39
|
+
showCurrentYear = false,
|
|
38
40
|
...props
|
|
39
41
|
}: ItemProps): React.ReactElement => {
|
|
40
42
|
const timelineItemCss = buildCss('pb_timeline_item_kit', lineStyle)
|
|
@@ -73,6 +75,7 @@ const TimelineItem = ({
|
|
|
73
75
|
<DateStacked
|
|
74
76
|
align="center"
|
|
75
77
|
date={date}
|
|
78
|
+
showCurrentYear={showCurrentYear}
|
|
76
79
|
size="sm"
|
|
77
80
|
/>
|
|
78
81
|
)}
|