playbook_ui 14.19.0 → 14.20.0.pre.alpha.revert4453PBNTR933reactdraggablebugdragbtwnexamples7854
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +11 -1
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +175 -16
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +56 -25
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +23 -13
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/VisibilityTree.ts +47 -0
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +6 -10
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +7 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.jsx +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.jsx +62 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.jsx +82 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +66 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +5 -1
- data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +1 -0
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +17 -58
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -1
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +77 -19
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +31 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +5 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +56 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +58 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +20 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +19 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +20 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +57 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +50 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +105 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +22 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +67 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +11 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.md +1 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +33 -2
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.md +3 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +11 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +5 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +16 -2
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +34 -13
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +3 -1
- data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +0 -6
- data/app/pb_kits/playbook/pb_dropdown/index.js +336 -30
- data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +39 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +2 -2
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +16 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +79 -13
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
- data/app/pb_kits/playbook/pb_file_upload/_file_upload.scss +13 -0
- data/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx +11 -1
- data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.html.erb +1 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.jsx +41 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -0
- data/app/pb_kits/playbook/pb_file_upload/file_upload.rb +7 -1
- data/app/pb_kits/playbook/pb_file_upload/fileupload.test.js +18 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
- data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +2 -2
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +19 -12
- data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +13 -7
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -2
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_react_hook.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.md +2 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.md +3 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.html.erb +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.jsx +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.html.erb +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.jsx +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_form.html.erb +11 -11
- data/app/pb_kits/playbook/pb_person/_person.tsx +12 -2
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +9 -9
- data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +2 -2
- data/app/pb_kits/playbook/pb_text_input/_text_input.scss +4 -2
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +73 -3
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.jsx +23 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.md +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
- data/dist/chunks/_typeahead-C-CI5Vgw.js +22 -0
- data/dist/chunks/_weekday_stacked-BCiM3zWM.js +45 -0
- data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
- data/dist/chunks/lib-D5R1BjUn.js +29 -0
- data/dist/chunks/{pb_form_validation-BioH7DWv.js → pb_form_validation-BZ2AVAi_.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.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/kit_base.rb +3 -3
- data/lib/playbook/version.rb +2 -2
- metadata +38 -8
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
- data/dist/chunks/_typeahead-D62OcwsT.js +0 -22
- data/dist/chunks/_weekday_stacked-Ceh9N0ow.js +0 -45
- data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
- data/dist/chunks/lib-CeKZrPmu.js +0 -29
@@ -0,0 +1,62 @@
|
|
1
|
+
import React from "react"
|
2
|
+
import AdvancedTable from '../../pb_advanced_table/_advanced_table'
|
3
|
+
import MOCK_DATA from "./advanced_table_mock_data.json"
|
4
|
+
|
5
|
+
const AdvancedTableColumnVisibilityCustom = (props) => {
|
6
|
+
const columnDefinitions = [
|
7
|
+
{
|
8
|
+
accessor: "year",
|
9
|
+
label: "Year",
|
10
|
+
cellAccessors: ["quarter", "month", "day"],
|
11
|
+
id: "year"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
accessor: "newEnrollments",
|
15
|
+
label: "New Enrollments",
|
16
|
+
id: "newEnrollments"
|
17
|
+
},
|
18
|
+
{
|
19
|
+
accessor: "scheduledMeetings",
|
20
|
+
label: "Scheduled Meetings",
|
21
|
+
id: "scheduledMeetings"
|
22
|
+
},
|
23
|
+
{
|
24
|
+
accessor: "attendanceRate",
|
25
|
+
label: "Attendance Rate",
|
26
|
+
id: "attendanceRate"
|
27
|
+
},
|
28
|
+
{
|
29
|
+
accessor: "completedClasses",
|
30
|
+
label: "Completed Classes",
|
31
|
+
id: "completedClasses"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
accessor: "classCompletionRate",
|
35
|
+
label: "Class Completion Rate",
|
36
|
+
id: "classCompletionRate"
|
37
|
+
},
|
38
|
+
{
|
39
|
+
accessor: "graduatedStudents",
|
40
|
+
label: "Graduated Students",
|
41
|
+
id: "graduatedStudents"
|
42
|
+
},
|
43
|
+
]
|
44
|
+
|
45
|
+
const columnVisibilityControl = {
|
46
|
+
// This is the list of column ids that will be included in the column visibility control
|
47
|
+
includeIds:["newEnrollments", "scheduledMeetings", "attendanceRate", "completedClasses"],
|
48
|
+
}
|
49
|
+
|
50
|
+
return (
|
51
|
+
<div>
|
52
|
+
<AdvancedTable
|
53
|
+
columnDefinitions={columnDefinitions}
|
54
|
+
columnVisibilityControl={columnVisibilityControl}
|
55
|
+
tableData={MOCK_DATA}
|
56
|
+
{...props}
|
57
|
+
/>
|
58
|
+
</div>
|
59
|
+
)
|
60
|
+
}
|
61
|
+
|
62
|
+
export default AdvancedTableColumnVisibilityCustom
|
@@ -0,0 +1 @@
|
|
1
|
+
By using the `includeIds` key/value pair as shown within the `columnVisibilityControl` prop, you can control which columns show up as options in the columnVisibility dropdown.
|
@@ -0,0 +1,82 @@
|
|
1
|
+
import React from "react"
|
2
|
+
import AdvancedTable from '../../pb_advanced_table/_advanced_table'
|
3
|
+
import MOCK_DATA from "./advanced_table_mock_data.json"
|
4
|
+
|
5
|
+
const AdvancedTableColumnVisibilityMulti = (props) => {
|
6
|
+
const columnDefinitions = [
|
7
|
+
{
|
8
|
+
accessor: "year",
|
9
|
+
label: "Year",
|
10
|
+
id: "year",
|
11
|
+
cellAccessors: ["quarter", "month", "day"],
|
12
|
+
},
|
13
|
+
{
|
14
|
+
label: "Enrollment Data",
|
15
|
+
id: "enrollmentData",
|
16
|
+
columns: [
|
17
|
+
{
|
18
|
+
label: "Enrollment Stats",
|
19
|
+
id: "enrollmentStats",
|
20
|
+
columns: [
|
21
|
+
{
|
22
|
+
accessor: "newEnrollments",
|
23
|
+
label: "New Enrollments",
|
24
|
+
id: "newEnrollments",
|
25
|
+
},
|
26
|
+
{
|
27
|
+
accessor: "scheduledMeetings",
|
28
|
+
label: "Scheduled Meetings",
|
29
|
+
id: "scheduledMeetings",
|
30
|
+
},
|
31
|
+
],
|
32
|
+
},
|
33
|
+
],
|
34
|
+
},
|
35
|
+
{
|
36
|
+
label: "Performance Data",
|
37
|
+
id: "performanceData",
|
38
|
+
columns: [
|
39
|
+
{
|
40
|
+
label: "Completion Metrics",
|
41
|
+
id: "completionMetrics",
|
42
|
+
columns: [
|
43
|
+
{
|
44
|
+
accessor: "completedClasses",
|
45
|
+
label: "Completed Classes",
|
46
|
+
id: "completedClasses",
|
47
|
+
},
|
48
|
+
{
|
49
|
+
accessor: "classCompletionRate",
|
50
|
+
label: "Class Completion Rate",
|
51
|
+
id: "classCompletionRate",
|
52
|
+
},
|
53
|
+
],
|
54
|
+
},
|
55
|
+
{
|
56
|
+
label: "Attendance",
|
57
|
+
id: "attendance",
|
58
|
+
columns: [
|
59
|
+
{
|
60
|
+
accessor: "attendanceRate",
|
61
|
+
label: "Attendance Rate",
|
62
|
+
id: "attendanceRate",
|
63
|
+
},
|
64
|
+
],
|
65
|
+
},
|
66
|
+
],
|
67
|
+
},
|
68
|
+
];
|
69
|
+
|
70
|
+
return (
|
71
|
+
<div>
|
72
|
+
<AdvancedTable
|
73
|
+
columnDefinitions={columnDefinitions}
|
74
|
+
columnVisibilityControl={{default: true}}
|
75
|
+
tableData={MOCK_DATA}
|
76
|
+
{...props}
|
77
|
+
/>
|
78
|
+
</div>
|
79
|
+
)
|
80
|
+
}
|
81
|
+
|
82
|
+
export default AdvancedTableColumnVisibilityMulti
|
@@ -0,0 +1 @@
|
|
1
|
+
The `columnVisibilityControl` prop can also be used with multi-header columns as shown.
|
data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
import React, { useState } from "react"
|
2
|
+
import AdvancedTable from '../../pb_advanced_table/_advanced_table'
|
3
|
+
import MOCK_DATA from "./advanced_table_mock_data.json"
|
4
|
+
|
5
|
+
const AdvancedTableColumnVisibilityWithState = (props) => {
|
6
|
+
const columnDefinitions = [
|
7
|
+
{
|
8
|
+
accessor: "year",
|
9
|
+
label: "Year",
|
10
|
+
cellAccessors: ["quarter", "month", "day"],
|
11
|
+
id: "year"
|
12
|
+
},
|
13
|
+
{
|
14
|
+
accessor: "newEnrollments",
|
15
|
+
label: "New Enrollments",
|
16
|
+
id: "newEnrollments"
|
17
|
+
},
|
18
|
+
{
|
19
|
+
accessor: "scheduledMeetings",
|
20
|
+
label: "Scheduled Meetings",
|
21
|
+
id: "scheduledMeetings"
|
22
|
+
},
|
23
|
+
{
|
24
|
+
accessor: "attendanceRate",
|
25
|
+
label: "Attendance Rate",
|
26
|
+
id: "attendanceRate"
|
27
|
+
},
|
28
|
+
{
|
29
|
+
accessor: "completedClasses",
|
30
|
+
label: "Completed Classes",
|
31
|
+
id: "completedClasses"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
accessor: "classCompletionRate",
|
35
|
+
label: "Class Completion Rate",
|
36
|
+
id: "classCompletionRate"
|
37
|
+
},
|
38
|
+
{
|
39
|
+
accessor: "graduatedStudents",
|
40
|
+
label: "Graduated Students",
|
41
|
+
id: "graduatedStudents"
|
42
|
+
},
|
43
|
+
]
|
44
|
+
|
45
|
+
const [columnVisibility, setColumnVisibility] = useState({
|
46
|
+
newEnrollments: false
|
47
|
+
})
|
48
|
+
|
49
|
+
const columnVisibilityControl = {
|
50
|
+
value: columnVisibility,
|
51
|
+
onChange: setColumnVisibility,
|
52
|
+
onColumnVisibilityChange: (currentState) => console.log(currentState),
|
53
|
+
}
|
54
|
+
return (
|
55
|
+
<div>
|
56
|
+
<AdvancedTable
|
57
|
+
columnDefinitions={columnDefinitions}
|
58
|
+
columnVisibilityControl={columnVisibilityControl}
|
59
|
+
tableData={MOCK_DATA}
|
60
|
+
{...props}
|
61
|
+
/>
|
62
|
+
</div>
|
63
|
+
)
|
64
|
+
}
|
65
|
+
|
66
|
+
export default AdvancedTableColumnVisibilityWithState
|
data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md
ADDED
@@ -0,0 +1,3 @@
|
|
1
|
+
The `columnVisibilityControl` prop also allows for greater control over the columnVisibility state. Devs can manage state themselves by passing in `value` and `onChange` as shown.
|
2
|
+
|
3
|
+
The additional `onColumnVisibilityChange` provides a callback with the current state as the argument if needed.
|
@@ -47,3 +47,7 @@ examples:
|
|
47
47
|
- advanced_table_selectable_rows_header: Selectable Rows (No Actions Bar)
|
48
48
|
- advanced_table_inline_editing: Inline Cell Editing
|
49
49
|
- advanced_table_fullscreen: Fullscreen
|
50
|
+
- advanced_table_column_visibility: Column Visibility Control
|
51
|
+
- advanced_table_column_visibility_with_state: Column Visibility Control With State
|
52
|
+
- advanced_table_column_visibility_custom: Column Visibility Control with Custom Dropdown
|
53
|
+
- advanced_table_column_visibility_multi: Column Visibility Control with Multi-Header Columns
|
@@ -27,4 +27,8 @@ export { default as AdvancedTableStickyColumns } from './_advanced_table_sticky_
|
|
27
27
|
export { default as AdvancedTableStickyHeader } from './_advanced_table_sticky_header.jsx'
|
28
28
|
export { default as AdvancedTableStickyColumnsAndHeader } from './_advanced_table_sticky_columns_and_header.jsx'
|
29
29
|
export { default as AdvancedTableExpandByDepth } from './_advanced_table_expand_by_depth.jsx'
|
30
|
-
export { default as AdvancedTableColumnBorderColor} from './_advanced_table_column_border_color.jsx'
|
30
|
+
export { default as AdvancedTableColumnBorderColor} from './_advanced_table_column_border_color.jsx'
|
31
|
+
export { default as AdvancedTableColumnVisibility } from './_advanced_table_column_visibility.jsx'
|
32
|
+
export { default as AdvancedTableColumnVisibilityCustom } from './_advanced_table_column_visibility_custom.jsx'
|
33
|
+
export { default as AdvancedTableColumnVisibilityMulti } from './_advanced_table_column_visibility_multi.jsx'
|
34
|
+
export { default as AdvancedTableColumnVisibilityWithState } from './_advanced_table_column_visibility_with_state.jsx'
|
@@ -1,11 +1,11 @@
|
|
1
|
-
import React, { createContext, useReducer, useContext, useEffect, useMemo
|
1
|
+
import React, { createContext, useReducer, useContext, useEffect, useMemo } from "react";
|
2
2
|
import { InitialStateType, ActionType, DraggableProviderType } from "./types";
|
3
3
|
|
4
4
|
const initialState: InitialStateType = {
|
5
5
|
items: [],
|
6
6
|
dragData: { id: "", initialGroup: "" },
|
7
7
|
isDragging: "",
|
8
|
-
activeContainer: ""
|
8
|
+
activeContainer: ""
|
9
9
|
};
|
10
10
|
|
11
11
|
const reducer = (state: InitialStateType, action: ActionType) => {
|
@@ -31,23 +31,9 @@ const reducer = (state: InitialStateType, action: ActionType) => {
|
|
31
31
|
const { dragId, targetId } = action.payload;
|
32
32
|
const newItems = [...state.items];
|
33
33
|
const draggedItem = newItems.find(item => item.id === dragId);
|
34
|
-
const
|
35
|
-
|
36
|
-
if (!draggedItem || !targetItem || draggedItem.container !== targetItem.container) {
|
37
|
-
return state;
|
38
|
-
}
|
39
|
-
|
40
|
-
if (dragId === targetId) {
|
41
|
-
return state;
|
42
|
-
}
|
43
|
-
|
44
|
-
const draggedIndex = newItems.findIndex(item => item.id === dragId);
|
34
|
+
const draggedIndex = newItems.indexOf(draggedItem);
|
45
35
|
const targetIndex = newItems.findIndex(item => item.id === targetId);
|
46
36
|
|
47
|
-
if (draggedIndex === -1 || targetIndex === -1) {
|
48
|
-
return state;
|
49
|
-
}
|
50
|
-
|
51
37
|
newItems.splice(draggedIndex, 1);
|
52
38
|
newItems.splice(targetIndex, 0, draggedItem);
|
53
39
|
|
@@ -62,11 +48,7 @@ const reducer = (state: InitialStateType, action: ActionType) => {
|
|
62
48
|
const DragContext = createContext<any>({});
|
63
49
|
|
64
50
|
export const DraggableContext = () => {
|
65
|
-
|
66
|
-
if (context === undefined) {
|
67
|
-
throw new Error('DraggableContext must be used within a DraggableProvider');
|
68
|
-
}
|
69
|
-
return context;
|
51
|
+
return useContext(DragContext);
|
70
52
|
};
|
71
53
|
|
72
54
|
export const DraggableProvider = ({
|
@@ -81,11 +63,7 @@ export const DraggableProvider = ({
|
|
81
63
|
dropZone = { type: 'ghost', color: 'neutral', direction: 'vertical' }
|
82
64
|
}: DraggableProviderType) => {
|
83
65
|
const [state, dispatch] = useReducer(reducer, initialState);
|
84
|
-
|
85
|
-
// Store initial items in a ref to use if needed (for consistency when needed in future updates)
|
86
|
-
const initialItemsRef = useRef(initialItems);
|
87
|
-
const [isDragging, setIsDragging] = useState(false);
|
88
|
-
|
66
|
+
|
89
67
|
// Parse dropZone prop - handle both string format (backward compatibility) and object format
|
90
68
|
let dropZoneType = 'ghost';
|
91
69
|
let dropZoneColor = 'neutral';
|
@@ -108,64 +86,45 @@ export const DraggableProvider = ({
|
|
108
86
|
|
109
87
|
useEffect(() => {
|
110
88
|
dispatch({ type: 'SET_ITEMS', payload: initialItems });
|
111
|
-
initialItemsRef.current = initialItems;
|
112
89
|
}, [initialItems]);
|
113
90
|
|
114
91
|
useEffect(() => {
|
115
|
-
|
116
|
-
|
117
|
-
}
|
118
|
-
}, [state.items, onReorder]);
|
92
|
+
onReorder(state.items);
|
93
|
+
}, [state.items]);
|
119
94
|
|
120
95
|
const handleDragStart = (id: string, container: string) => {
|
121
|
-
|
122
|
-
dispatch({ type: 'SET_DRAG_DATA', payload: { id, initialGroup: container } });
|
96
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container } });
|
123
97
|
dispatch({ type: 'SET_IS_DRAGGING', payload: id });
|
124
|
-
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
|
125
98
|
if (onDragStart) onDragStart(id, container);
|
126
99
|
};
|
127
100
|
|
128
101
|
const handleDragEnter = (id: string, container: string) => {
|
129
|
-
if (
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
const draggedItem = state.items.find(item => item.id === state.dragData.id);
|
134
|
-
const targetItem = state.items.find(item => item.id === id);
|
135
|
-
|
136
|
-
if (!draggedItem || !targetItem || draggedItem.container !== targetItem.container) {
|
137
|
-
return;
|
102
|
+
if (state.dragData.id !== id) {
|
103
|
+
dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
|
104
|
+
dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container } });
|
138
105
|
}
|
139
|
-
|
140
|
-
dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
|
141
|
-
|
142
106
|
if (onDragEnter) onDragEnter(id, container);
|
143
107
|
};
|
144
108
|
|
145
109
|
const handleDragEnd = () => {
|
146
|
-
setIsDragging(false);
|
147
110
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
148
111
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
149
112
|
if (onDragEnd) onDragEnd();
|
150
113
|
};
|
151
114
|
|
152
|
-
const
|
153
|
-
|
154
|
-
|
155
|
-
if (draggedItem && draggedItem.container !== container) {
|
156
|
-
dispatch({ type: 'CHANGE_CATEGORY', payload: { itemId: state.dragData.id, container } });
|
157
|
-
}
|
115
|
+
const changeCategory = (itemId: string, container: string) => {
|
116
|
+
dispatch({ type: 'CHANGE_CATEGORY', payload: { itemId, container } });
|
117
|
+
};
|
158
118
|
|
119
|
+
const handleDrop = (container: string) => {
|
159
120
|
dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
|
160
121
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
|
161
|
-
|
162
|
-
setIsDragging(false);
|
122
|
+
changeCategory(state.dragData.id, container);
|
163
123
|
if (onDrop) onDrop(container);
|
164
124
|
};
|
165
125
|
|
166
126
|
const handleDragOver = (e: Event, container: string) => {
|
167
127
|
e.preventDefault();
|
168
|
-
e.stopPropagation();
|
169
128
|
dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
|
170
129
|
if (onDragOver) onDragOver(e, container);
|
171
130
|
};
|
@@ -185,7 +144,7 @@ export const DraggableProvider = ({
|
|
185
144
|
handleDragEnd,
|
186
145
|
handleDrop,
|
187
146
|
handleDragOver
|
188
|
-
}), [state, dropZoneType, dropZoneColor, dropZoneDirection
|
147
|
+
}), [state, dropZoneType, dropZoneColor, dropZoneDirection]);
|
189
148
|
|
190
149
|
return (
|
191
150
|
<DragContext.Provider value={contextValue}>{children}</DragContext.Provider>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle } from "react";
|
1
|
+
import React, { useState, useRef, useEffect, forwardRef, useImperativeHandle, useMemo } from "react";
|
2
2
|
import classnames from "classnames";
|
3
3
|
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
|
4
4
|
import { globalProps } from "../utilities/globalProps";
|
@@ -25,6 +25,7 @@ type DropdownProps = {
|
|
25
25
|
blankSelection?: string;
|
26
26
|
children?: React.ReactChild[] | React.ReactChild | React.ReactElement[];
|
27
27
|
className?: string;
|
28
|
+
formPillProps?: GenericObject;
|
28
29
|
dark?: boolean;
|
29
30
|
data?: { [key: string]: string };
|
30
31
|
defaultValue?: GenericObject;
|
@@ -33,6 +34,7 @@ type DropdownProps = {
|
|
33
34
|
id?: string;
|
34
35
|
isClosed?: boolean;
|
35
36
|
label?: string;
|
37
|
+
multiSelect?: boolean;
|
36
38
|
onSelect?: (arg: GenericObject) => null;
|
37
39
|
options: GenericObject;
|
38
40
|
separators?: boolean;
|
@@ -61,6 +63,8 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
61
63
|
id,
|
62
64
|
isClosed = true,
|
63
65
|
label,
|
66
|
+
multiSelect = false,
|
67
|
+
formPillProps,
|
64
68
|
onSelect,
|
65
69
|
options,
|
66
70
|
separators = true,
|
@@ -80,7 +84,20 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
80
84
|
const [isDropDownClosed, setIsDropDownClosed, toggleDropdown] = useDropdown(isClosed);
|
81
85
|
|
82
86
|
const [filterItem, setFilterItem] = useState("");
|
83
|
-
const
|
87
|
+
const initialSelected = useMemo(() => {
|
88
|
+
if (multiSelect) {
|
89
|
+
if (Array.isArray(defaultValue)) return defaultValue;
|
90
|
+
return defaultValue && Object.keys(defaultValue).length
|
91
|
+
? [defaultValue]
|
92
|
+
: [];
|
93
|
+
}
|
94
|
+
return defaultValue || {};
|
95
|
+
}, [multiSelect, defaultValue]);
|
96
|
+
|
97
|
+
const [selected, setSelected] = useState<GenericObject | GenericObject[]>(
|
98
|
+
initialSelected
|
99
|
+
);
|
100
|
+
|
84
101
|
const [isInputFocused, setIsInputFocused] = useState(false);
|
85
102
|
const [hasTriggerSubcomponent, setHasTriggerSubcomponent] = useState(true);
|
86
103
|
const [hasContainerSubcomponent, setHasContainerSubcomponent] =
|
@@ -93,6 +110,12 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
93
110
|
const inputWrapperRef = useRef(null);
|
94
111
|
const dropdownContainerRef = useRef(null);
|
95
112
|
|
113
|
+
const selectedArray = Array.isArray(selected)
|
114
|
+
? selected
|
115
|
+
: selected && Object.keys(selected).length
|
116
|
+
? [selected]
|
117
|
+
: [];
|
118
|
+
|
96
119
|
const { trigger, container, otherChildren } =
|
97
120
|
separateChildComponents(children);
|
98
121
|
|
@@ -124,16 +147,23 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
124
147
|
|
125
148
|
const blankSelectionOption: GenericObject = blankSelection ? [{ label: blankSelection, value: "" }] : [];
|
126
149
|
const optionsWithBlankSelection = blankSelectionOption.concat(options);
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
150
|
+
|
151
|
+
const availableOptions = useMemo(()=> {
|
152
|
+
if (!multiSelect) return optionsWithBlankSelection;
|
153
|
+
return optionsWithBlankSelection.filter((option: GenericObject) => !selectedArray.some((sel) => sel.label === option.label));
|
154
|
+
}, [optionsWithBlankSelection, selectedArray, multiSelect]);
|
155
|
+
|
156
|
+
const filteredOptions = useMemo(() => {
|
157
|
+
return availableOptions.filter((opt: GenericObject) =>
|
158
|
+
String(opt.label).toLowerCase().includes(filterItem.toLowerCase())
|
159
|
+
);
|
160
|
+
}, [availableOptions, filterItem]);
|
131
161
|
|
132
162
|
// For keyboard accessibility: Set focus within dropdown to selected item if it exists
|
133
163
|
useEffect(() => {
|
134
164
|
if (!isDropDownClosed) {
|
135
165
|
let newIndex = 0;
|
136
|
-
if (selected && selected
|
166
|
+
if (selected && !Array.isArray(selected) && selected.label) {
|
137
167
|
const selectedIndex = filteredOptions.findIndex((option: GenericObject) => option.label === selected.label);
|
138
168
|
if (selectedIndex >= 0) {
|
139
169
|
newIndex = selectedIndex;
|
@@ -149,12 +179,27 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
149
179
|
setIsDropDownClosed(false);
|
150
180
|
};
|
151
181
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
182
|
+
|
183
|
+
const handleOptionClick = (clickedItem: GenericObject) => {
|
184
|
+
if (multiSelect) {
|
185
|
+
setSelected((prev) => {
|
186
|
+
const list = prev as GenericObject[];
|
187
|
+
const exists = list.find((option) => option.value === clickedItem.value);
|
188
|
+
const next = exists
|
189
|
+
? list.filter((option) => option.value !== clickedItem.value)
|
190
|
+
: [...list, clickedItem];
|
191
|
+
onSelect && onSelect(next);
|
192
|
+
return next;
|
193
|
+
});
|
194
|
+
setFilterItem("");
|
195
|
+
setIsDropDownClosed(true);
|
196
|
+
} else {
|
197
|
+
setSelected(clickedItem);
|
198
|
+
setFilterItem("");
|
199
|
+
setIsDropDownClosed(true);
|
200
|
+
onSelect && onSelect(clickedItem);
|
201
|
+
}
|
202
|
+
};
|
158
203
|
|
159
204
|
const handleWrapperClick = () => {
|
160
205
|
autocomplete && inputRef?.current?.focus();
|
@@ -162,9 +207,14 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
162
207
|
};
|
163
208
|
|
164
209
|
const handleBackspace = () => {
|
210
|
+
if (multiSelect) {
|
211
|
+
setSelected([]);
|
212
|
+
onSelect && onSelect([]);
|
213
|
+
} else {
|
165
214
|
setSelected({});
|
166
215
|
onSelect && onSelect(null);
|
167
216
|
setFocusedOptionIndex(-1);
|
217
|
+
}
|
168
218
|
};
|
169
219
|
|
170
220
|
const componentsToRender = prepareSubcomponents({
|
@@ -178,12 +228,17 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
178
228
|
});
|
179
229
|
|
180
230
|
useImperativeHandle(ref, () => ({
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
231
|
+
clearSelected: () => {
|
232
|
+
if (multiSelect) {
|
233
|
+
setSelected([]);
|
234
|
+
onSelect && onSelect([]);
|
235
|
+
} else {
|
236
|
+
setSelected({});
|
237
|
+
onSelect && onSelect(null);
|
238
|
+
}
|
239
|
+
setFilterItem("");
|
240
|
+
setIsDropDownClosed(true);
|
241
|
+
},
|
187
242
|
}));
|
188
243
|
|
189
244
|
return (
|
@@ -201,6 +256,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
201
256
|
filteredOptions,
|
202
257
|
filterItem,
|
203
258
|
focusedOptionIndex,
|
259
|
+
formPillProps,
|
204
260
|
handleBackspace,
|
205
261
|
handleChange,
|
206
262
|
handleOptionClick,
|
@@ -209,6 +265,8 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
|
|
209
265
|
inputWrapperRef,
|
210
266
|
isDropDownClosed,
|
211
267
|
isInputFocused,
|
268
|
+
multiSelect,
|
269
|
+
onSelect,
|
212
270
|
optionsWithBlankSelection,
|
213
271
|
selected,
|
214
272
|
setFocusedOptionIndex,
|
@@ -0,0 +1,31 @@
|
|
1
|
+
<%
|
2
|
+
options = [
|
3
|
+
{ label: 'United States', value: 'United States', id: 'us' },
|
4
|
+
{ label: 'Canada', value: 'Canada', id: 'ca' },
|
5
|
+
{ label: 'Pakistan', value: 'Pakistan', id: 'pk' },
|
6
|
+
]
|
7
|
+
|
8
|
+
%>
|
9
|
+
|
10
|
+
<%
|
11
|
+
options2 = [
|
12
|
+
{ label: 'India', value: 'India', id: 'in' },
|
13
|
+
{ label: 'Mexico', value: 'Mexico', id: 'mx' },
|
14
|
+
{ label: 'Brazil', value: 'Brazil', id: 'br' },
|
15
|
+
{ label: 'Argentina', value: 'Argentina', id: 'ar' },
|
16
|
+
{ label: 'Colombia', value: 'Colombia', id: 'co' },
|
17
|
+
{ label: 'Chile', value: 'Chile', id: 'cl' },
|
18
|
+
{ label: 'Peru', value: 'Peru', id: 'pe' },
|
19
|
+
]
|
20
|
+
|
21
|
+
%>
|
22
|
+
|
23
|
+
<%= pb_rails("dropdown", props: {options: options}) %>
|
24
|
+
|
25
|
+
<script>
|
26
|
+
document.addEventListener("pb:dropdown:selected", (e) => {
|
27
|
+
const option = e.detail;
|
28
|
+
const dropdown = e.target;
|
29
|
+
console.log("Selected option:", option);
|
30
|
+
})
|
31
|
+
</script>
|
@@ -0,0 +1,5 @@
|
|
1
|
+
This kit's `options` prop requires an array of objects, each of which will be used as the selectable options within the dropdown. Each option object can support any number of key-value pairs, but each MUST contain `label`, `value` and `id`.
|
2
|
+
|
3
|
+
The kit also comes with a custom event called "pb:dropdown:selected" which updates dynamically with the selection as it changes. See code snippet to see this in action.
|
4
|
+
|
5
|
+
In addition, a data attribute called `data-option-selected` with the selection is also rendered on the parent dropdown div.
|