playbook_ui 15.7.0.pre.rc.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_filter/Filter/FilterBackground.tsx +3 -3
  3. data/app/pb_kits/playbook/pb_table/_table.tsx +187 -33
  4. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.jsx +134 -0
  5. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant.md +34 -0
  6. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.html.erb +101 -0
  7. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.md +33 -0
  8. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.jsx +180 -0
  9. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination.md +3 -0
  10. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.html.erb +122 -0
  11. data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_with_pagination_rails.md +3 -0
  12. data/app/pb_kits/playbook/pb_table/docs/example.yml +4 -0
  13. data/app/pb_kits/playbook/pb_table/docs/index.js +2 -0
  14. data/app/pb_kits/playbook/pb_table/table.html.erb +68 -12
  15. data/app/pb_kits/playbook/pb_table/table.rb +22 -3
  16. data/app/pb_kits/playbook/pb_table/table.test.js +143 -0
  17. data/app/pb_kits/playbook/pb_timeline/_item.tsx +3 -0
  18. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.html.erb +60 -0
  19. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.jsx +118 -0
  20. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_show_current_year.md +1 -0
  21. data/app/pb_kits/playbook/pb_timeline/docs/_timeline_with_date.md +1 -1
  22. data/app/pb_kits/playbook/pb_timeline/docs/example.yml +2 -0
  23. data/app/pb_kits/playbook/pb_timeline/docs/index.js +1 -0
  24. data/app/pb_kits/playbook/pb_timeline/item.html.erb +1 -1
  25. data/app/pb_kits/playbook/pb_timeline/item.rb +2 -0
  26. data/app/pb_kits/playbook/pb_timeline/label.html.erb +2 -1
  27. data/app/pb_kits/playbook/pb_timeline/label.rb +2 -0
  28. data/app/pb_kits/playbook/pb_timeline/subcomponents/Label.tsx +3 -0
  29. data/app/pb_kits/playbook/pb_timeline/timeline.test.js +51 -0
  30. data/app/pb_kits/playbook/utilities/deprecated.ts +73 -0
  31. data/dist/chunks/_typeahead-CHwm9MTE.js +6 -0
  32. data/dist/chunks/{lib-DDDLiZuu.js → lib-Cugvy62C.js} +3 -3
  33. data/dist/chunks/vendor.js +2 -2
  34. data/dist/playbook-rails-react-bindings.js +1 -1
  35. data/dist/playbook-rails.js +1 -1
  36. data/lib/playbook/pb_kit_helper.rb +35 -0
  37. data/lib/playbook/version.rb +1 -1
  38. metadata +16 -4
  39. data/dist/chunks/_typeahead-CYNrKU10.js +0 -6
@@ -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)
@@ -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
- <% if object.responsive_classname %>
2
- <% responsive_class = object.responsive_classname %>
3
- <% else %>
4
- <% responsive_class = nil %>
5
- <% end %>
6
-
7
- <%= content_tag(:div, class: responsive_class, 'data-pb-table-wrapper' => true) do %>
8
- <% if object.tag == "table" %>
9
- <%= pb_content_tag(:table) do %>
10
- <%= content.presence %>
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
- <%= pb_content_tag do %>
14
- <%= content.presence %>
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-#{size}", single_line_class, dark_class,
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
- container ? "table-card" : nil
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
- responsive != "none" ? "table-collapse-#{collapse}" : ""
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
+ })
@@ -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
  )}