playbook_ui 16.7.0 → 16.8.0.pre.alpha.PLAY2935formbuilderrequiredindicatorbug16780
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 +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +2 -0
- data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +5 -1
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +24 -0
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/ColumnLayoutHelper.ts +138 -0
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +144 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.jsx +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.md +6 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_width.jsx +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_width.md +66 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.html.erb +62 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_enable_toggle_expansion_rails.md +7 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.jsx +12 -4
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.html.erb +16 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_header_rails.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.jsx +68 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sticky_scroll_limitation.md +7 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +16 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +12 -5
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +5 -3
- data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +180 -5839
- data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.overrides.json +5 -30
- data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_column_definitions_styling.json +4 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_card/_card.tsx +1 -1
- data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
- data/app/pb_kits/playbook/pb_currency/_currency.tsx +9 -6
- data/app/pb_kits/playbook/pb_currency/currency.rb +5 -10
- data/app/pb_kits/playbook/pb_currency/currency.test.js +44 -1
- data/app/pb_kits/playbook/pb_date/docs/_playground.json +13 -17
- data/app/pb_kits/playbook/pb_date/docs/_playground.overrides.json +13 -16
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +3 -2
- data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +38 -23
- data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +2 -1
- data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +31 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_dialog_submission.jsx +2 -2
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.html.erb +0 -2
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_inline.jsx +0 -2
- data/app/pb_kits/playbook/pb_date_picker/docs/_playground.json +136 -42
- data/app/pb_kits/playbook/pb_date_picker/docs/_playground.overrides.json +113 -45
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_playground.json +48 -6
- data/app/pb_kits/playbook/pb_date_range_inline/docs/_playground.overrides.json +57 -0
- data/app/pb_kits/playbook/pb_date_range_stacked/docs/_playground.json +28 -5
- data/app/pb_kits/playbook/pb_date_range_stacked/docs/_playground.overrides.json +38 -0
- data/app/pb_kits/playbook/pb_date_stacked/docs/_playground.json +1 -1
- data/app/pb_kits/playbook/pb_date_stacked/docs/_playground.overrides.json +1 -1
- data/app/pb_kits/playbook/pb_date_time/docs/_playground.json +16 -3
- data/app/pb_kits/playbook/pb_date_time/docs/_playground.overrides.json +16 -3
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/_playground.json +11 -15
- data/app/pb_kits/playbook/pb_date_time_stacked/docs/_playground.overrides.json +11 -15
- data/app/pb_kits/playbook/pb_date_year_stacked/docs/_playground.json +4 -4
- data/app/pb_kits/playbook/pb_date_year_stacked/docs/_playground.overrides.json +4 -4
- data/app/pb_kits/playbook/pb_detail/docs/_playground.json +12 -18
- data/app/pb_kits/playbook/pb_detail/docs/_playground.overrides.json +13 -12
- data/app/pb_kits/playbook/pb_dialog/docs/_playground.json +108 -42
- data/app/pb_kits/playbook/pb_dialog/docs/_playground.overrides.json +88 -40
- data/app/pb_kits/playbook/pb_distribution_bar/docs/_playground.json +65 -7
- data/app/pb_kits/playbook/pb_distribution_bar/docs/_playground.overrides.json +45 -0
- data/app/pb_kits/playbook/pb_draggable/_draggable.scss +19 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_rails.md +2 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_cards_react.md +1 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_rails.md +2 -0
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_list_react.md +3 -1
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_rails.md +3 -1
- data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_selectable_list_react.md +3 -1
- data/app/pb_kits/playbook/pb_draggable/draggable.test.jsx +16 -0
- data/app/pb_kits/playbook/pb_draggable/draggable_container.html.erb +3 -1
- data/app/pb_kits/playbook/pb_draggable/draggable_item.html.erb +1 -0
- data/app/pb_kits/playbook/pb_draggable/index.js +149 -7
- data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableContainer.tsx +1 -0
- data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +67 -1
- data/app/pb_kits/playbook/pb_draggable/touchDrag.test.js +38 -0
- data/app/pb_kits/playbook/pb_draggable/utilities/touchDrag.ts +173 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_playground.json +318 -21
- data/app/pb_kits/playbook/pb_dropdown/docs/_playground.overrides.json +192 -19
- data/app/pb_kits/playbook/pb_empty_state/docs/_playground.json +77 -12
- data/app/pb_kits/playbook/pb_empty_state/docs/_playground.overrides.json +79 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/_playground.json +98 -13
- data/app/pb_kits/playbook/pb_file_upload/docs/_playground.overrides.json +99 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.html.erb +20 -19
- data/app/pb_kits/playbook/pb_icon/_icon.scss +2 -1
- data/app/pb_kits/playbook/pb_icon/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_icon/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_link/docs/_playground.json +81 -40
- data/app/pb_kits/playbook/pb_link/docs/_playground.overrides.json +88 -30
- data/app/pb_kits/playbook/pb_list/_list_item.tsx +4 -1
- data/app/pb_kits/playbook/pb_list/item.html.erb +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_centered_data.html.erb +90 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_centered_data.jsx +100 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_centered_data.md +1 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/_pb_circle_chart_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_pb_circle_chart/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_playground.json +4 -2
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +1 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_styles.scss +262 -43
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.html.erb +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.md +12 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_simple.html.erb +9 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_simple.md +8 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/kit.schema.json +18 -9
- data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +162 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +71 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_rails.js +202 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky.html.erb +85 -83
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky.jsx +88 -86
- data/app/pb_kits/playbook/pb_table/docs/_table_sticky.md +3 -1
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_external_filter_rails.md +1 -1
- data/app/pb_kits/playbook/pb_text_input/_text_input.scss +37 -0
- data/app/pb_kits/playbook/pb_title/docs/_playground.json +72 -23
- data/app/pb_kits/playbook/pb_title/docs/_playground.overrides.json +80 -16
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +133 -102
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +54 -41
- data/app/pb_kits/playbook/pb_tooltip/tooltip.test.jsx +60 -2
- data/dist/chunks/{_pb_line_graph-CIWJe3Gr.js → _pb_line_graph-BgsTI0CL.js} +1 -1
- data/dist/chunks/_typeahead-DA__Kgp5.js +5 -0
- data/dist/chunks/{globalProps-CqO4Tko1.js → globalProps-DOB47YGB.js} +1 -1
- data/dist/chunks/{lib-czQnE40X.js → lib-BzglXly2.js} +2 -2
- data/dist/chunks/vendor.js +4 -4
- data/dist/menu.yml +71 -132
- 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/form_field_builder.rb +2 -0
- data/lib/playbook/version.rb +2 -2
- metadata +31 -10
- data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.html.erb +0 -1
- data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.jsx +0 -21
- data/app/pb_kits/playbook/pb_icon/docs/_icon_fa_kit.md +0 -7
- data/dist/chunks/_typeahead-B_Ac4z84.js +0 -1
|
@@ -1,95 +1,143 @@
|
|
|
1
1
|
{
|
|
2
|
+
"structureModes": {
|
|
3
|
+
"default": "simple",
|
|
4
|
+
"modes": {
|
|
5
|
+
"simple": {
|
|
6
|
+
"label": "Simple",
|
|
7
|
+
"template": "<Dialog opened={dialogOpen} onCancel={closeDialog} onClose={closeDialog} onConfirm={closeDialog}{{props}} />",
|
|
8
|
+
"children": "",
|
|
9
|
+
"props": {
|
|
10
|
+
"size": "md",
|
|
11
|
+
"title": "Header Title is the Title Prop",
|
|
12
|
+
"text": "Hello Body Text, Nice to meet ya.",
|
|
13
|
+
"cancelButton": "Cancel Button",
|
|
14
|
+
"confirmButton": "Okay"
|
|
15
|
+
},
|
|
16
|
+
"imports": ["Button"],
|
|
17
|
+
"wrapper": "const DialogPlaygroundExample = () => {\n const [dialogOpen, setDialogOpen] = useState(false)\n const openDialog = () => setDialogOpen(true)\n const closeDialog = () => setDialogOpen(false)\n\n return (\n <>\n <Button marginBottom=\"sm\" onClick={openDialog}>\n Open Dialog\n </Button>\n {{component}}\n </>\n )\n}\n\n<DialogPlaygroundExample />"
|
|
18
|
+
},
|
|
19
|
+
"subcomponents": {
|
|
20
|
+
"label": "Compound Components",
|
|
21
|
+
"template": "<Dialog opened={dialogOpen} onClose={closeDialog}{{props}}>\n <Dialog.Header>Header Title inside Dialog.Header</Dialog.Header>\n <Dialog.Body>{{children}}</Dialog.Body>\n <Dialog.Footer>\n <Button onClick={closeDialog}>Okay</Button>\n <Button onClick={closeDialog} variant=\"link\">Cancel Button</Button>\n </Dialog.Footer>\n</Dialog>",
|
|
22
|
+
"children": "Hello Body Text, Nice to meet ya.",
|
|
23
|
+
"imports": ["Button"],
|
|
24
|
+
"wrapper": "const DialogPlaygroundExample = () => {\n const [dialogOpen, setDialogOpen] = useState(false)\n const openDialog = () => setDialogOpen(true)\n const closeDialog = () => setDialogOpen(false)\n\n return (\n <>\n <Button marginBottom=\"sm\" onClick={openDialog}>\n Open Dialog\n </Button>\n {{component}}\n </>\n )\n}\n\n<DialogPlaygroundExample />"
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
},
|
|
2
28
|
"children": {
|
|
3
29
|
"default": "Custom dialog content goes here when you are not using the title and text props."
|
|
4
30
|
},
|
|
31
|
+
"hiddenProps": [
|
|
32
|
+
"trigger",
|
|
33
|
+
"portalClassName"
|
|
34
|
+
],
|
|
35
|
+
"defaults": {
|
|
36
|
+
"closeable": true,
|
|
37
|
+
"placement": "center",
|
|
38
|
+
"shouldCloseOnOverlayClick": true,
|
|
39
|
+
"size": "md",
|
|
40
|
+
"title": "Header Title is the Title Prop",
|
|
41
|
+
"text": "Hello Body Text, Nice to meet ya."
|
|
42
|
+
},
|
|
5
43
|
"groups": [
|
|
6
44
|
{
|
|
7
45
|
"name": "Content",
|
|
8
|
-
"props": ["title", "text", "cancelButton", "confirmButton"]
|
|
46
|
+
"props": ["title", "text", "cancelButton", "confirmButton", "onCancel", "onClose", "onConfirm", "opened", "onChange"]
|
|
9
47
|
},
|
|
10
48
|
{
|
|
11
49
|
"name": "Behavior",
|
|
12
50
|
"props": [
|
|
13
|
-
"opened",
|
|
14
51
|
"placement",
|
|
15
52
|
"shouldCloseOnOverlayClick",
|
|
16
53
|
"closeable",
|
|
17
|
-
"loading"
|
|
18
|
-
"trigger",
|
|
19
|
-
"onClose",
|
|
20
|
-
"onCancel",
|
|
21
|
-
"onConfirm",
|
|
22
|
-
"onChange"
|
|
54
|
+
"loading"
|
|
23
55
|
]
|
|
24
56
|
},
|
|
25
57
|
{
|
|
26
58
|
"name": "Appearance",
|
|
27
|
-
"props": ["size", "status", "fullHeight"
|
|
59
|
+
"props": ["size", "status", "fullHeight"]
|
|
28
60
|
}
|
|
29
61
|
],
|
|
30
62
|
"presets": [
|
|
31
63
|
{
|
|
32
|
-
"name": "
|
|
64
|
+
"name": "Default",
|
|
33
65
|
"props": {
|
|
34
|
-
"size": "
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
66
|
+
"size": "md",
|
|
67
|
+
"title": "Header Title is the Title Prop",
|
|
68
|
+
"text": "Hello Body Text, Nice to meet ya.",
|
|
69
|
+
"cancelButton": "Cancel Button",
|
|
70
|
+
"confirmButton": "Okay"
|
|
38
71
|
}
|
|
39
72
|
},
|
|
40
73
|
{
|
|
41
|
-
"name": "
|
|
74
|
+
"name": "Small",
|
|
42
75
|
"props": {
|
|
43
|
-
"size": "
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"text": "Default size for most forms and standard content."
|
|
76
|
+
"size": "sm",
|
|
77
|
+
"title": "Small dialog",
|
|
78
|
+
"text": "Narrow width for short confirmations and alerts."
|
|
47
79
|
}
|
|
48
80
|
},
|
|
49
81
|
{
|
|
50
82
|
"name": "Large",
|
|
51
83
|
"props": {
|
|
52
84
|
"size": "lg",
|
|
53
|
-
"opened": true,
|
|
54
85
|
"title": "Large dialog",
|
|
55
86
|
"text": "Wider layout for dense content or two-column layouts."
|
|
56
87
|
}
|
|
57
88
|
},
|
|
58
|
-
|
|
59
|
-
"name": "
|
|
89
|
+
{
|
|
90
|
+
"name": "Status Alert",
|
|
60
91
|
"props": {
|
|
61
|
-
"size": "
|
|
62
|
-
"
|
|
63
|
-
"title": "
|
|
64
|
-
"text": "
|
|
92
|
+
"size": "status_size",
|
|
93
|
+
"status": "success",
|
|
94
|
+
"title": "Success",
|
|
95
|
+
"text": "Compact status layout for confirmations and feedback."
|
|
65
96
|
}
|
|
66
97
|
},
|
|
67
98
|
{
|
|
68
|
-
"name": "
|
|
99
|
+
"name": "Compound components",
|
|
100
|
+
"structureMode": "subcomponents",
|
|
69
101
|
"props": {
|
|
70
|
-
"size": "
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"text": "Width follows the content instead of fixed breakpoints."
|
|
74
|
-
}
|
|
102
|
+
"size": "sm"
|
|
103
|
+
},
|
|
104
|
+
"children": "Hello Body Text, Nice to meet ya."
|
|
75
105
|
},
|
|
76
106
|
{
|
|
77
|
-
"name": "
|
|
107
|
+
"name": "Full height compound",
|
|
108
|
+
"structureMode": "subcomponents",
|
|
78
109
|
"props": {
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
"text": "Compact status layout for confirmations and feedback."
|
|
84
|
-
}
|
|
110
|
+
"fullHeight": true,
|
|
111
|
+
"size": "lg"
|
|
112
|
+
},
|
|
113
|
+
"children": "Custom dialog content goes here when you need more vertical space."
|
|
85
114
|
}
|
|
86
115
|
],
|
|
87
|
-
"conditionals": {
|
|
116
|
+
"conditionals": {
|
|
117
|
+
"title": { "structureMode": "simple" },
|
|
118
|
+
"text": { "structureMode": "simple" },
|
|
119
|
+
"cancelButton": { "structureMode": "simple" },
|
|
120
|
+
"confirmButton": { "structureMode": "simple" },
|
|
121
|
+
"onCancel": { "structureMode": "simple" },
|
|
122
|
+
"onClose": { "structureMode": "simple" },
|
|
123
|
+
"onConfirm": { "structureMode": "simple" },
|
|
124
|
+
"opened": { "structureMode": "simple" }
|
|
125
|
+
},
|
|
88
126
|
"hints": {
|
|
89
127
|
"status_dialog": {
|
|
90
128
|
"when": { "status": "success" },
|
|
91
129
|
"message": "Status dialogs show an icon, title, and body copy in a centered layout.",
|
|
92
130
|
"type": "info"
|
|
131
|
+
},
|
|
132
|
+
"compound_components_info": {
|
|
133
|
+
"presetName": "Compound components",
|
|
134
|
+
"message": "Use Compound Components when you need custom header, body, or footer content instead of the simple title/text/button props API.",
|
|
135
|
+
"type": "info"
|
|
136
|
+
},
|
|
137
|
+
"full_height_info": {
|
|
138
|
+
"presetName": "Full height compound",
|
|
139
|
+
"message": "fullHeight is most useful with the compound structure when the dialog contains richer or scrollable content.",
|
|
140
|
+
"type": "info"
|
|
93
141
|
}
|
|
94
142
|
}
|
|
95
143
|
}
|
|
@@ -2,24 +2,82 @@
|
|
|
2
2
|
"template": "<DistributionBar{{props}} />",
|
|
3
3
|
"propTargets": {},
|
|
4
4
|
"defaults": {
|
|
5
|
-
"size": "lg"
|
|
5
|
+
"size": "lg",
|
|
6
|
+
"colors": [
|
|
7
|
+
"data_7",
|
|
8
|
+
"data_1",
|
|
9
|
+
"neutral"
|
|
10
|
+
]
|
|
6
11
|
},
|
|
7
12
|
"groups": [
|
|
8
13
|
{
|
|
9
|
-
"name": "
|
|
14
|
+
"name": "Data",
|
|
10
15
|
"props": [
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
|
|
16
|
+
"widths",
|
|
17
|
+
"colors"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "Appearance",
|
|
22
|
+
"props": [
|
|
23
|
+
"size"
|
|
14
24
|
]
|
|
15
25
|
}
|
|
16
26
|
],
|
|
17
27
|
"presets": [
|
|
18
28
|
{
|
|
19
29
|
"name": "Default",
|
|
20
|
-
"props": {
|
|
30
|
+
"props": {
|
|
31
|
+
"widths": [
|
|
32
|
+
1,
|
|
33
|
+
2,
|
|
34
|
+
3,
|
|
35
|
+
4,
|
|
36
|
+
5,
|
|
37
|
+
3,
|
|
38
|
+
3,
|
|
39
|
+
7
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"name": "Small",
|
|
45
|
+
"props": {
|
|
46
|
+
"widths": [
|
|
47
|
+
1,
|
|
48
|
+
2,
|
|
49
|
+
3,
|
|
50
|
+
4,
|
|
51
|
+
5,
|
|
52
|
+
3,
|
|
53
|
+
3,
|
|
54
|
+
7
|
|
55
|
+
],
|
|
56
|
+
"size": "sm"
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"name": "Custom colors",
|
|
61
|
+
"props": {
|
|
62
|
+
"colors": [
|
|
63
|
+
"data_7",
|
|
64
|
+
"data_1",
|
|
65
|
+
"neutral"
|
|
66
|
+
],
|
|
67
|
+
"widths": [
|
|
68
|
+
4,
|
|
69
|
+
5,
|
|
70
|
+
3
|
|
71
|
+
]
|
|
72
|
+
}
|
|
21
73
|
}
|
|
22
74
|
],
|
|
23
75
|
"conditionals": {},
|
|
24
|
-
"hints": {
|
|
76
|
+
"hints": {
|
|
77
|
+
"custom_colors": {
|
|
78
|
+
"presetName": "Custom colors",
|
|
79
|
+
"message": "Use the colors prop to change the colors of the distribution bar. Currently only the data and status colors will work for DistributionBar.",
|
|
80
|
+
"type": "info"
|
|
81
|
+
}
|
|
82
|
+
}
|
|
25
83
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"defaults": {
|
|
3
|
+
"colors": ["data_7", "data_1", "neutral"]
|
|
4
|
+
},
|
|
5
|
+
"groups": [
|
|
6
|
+
{
|
|
7
|
+
"name": "Data",
|
|
8
|
+
"props": ["widths", "colors"]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"name": "Appearance",
|
|
12
|
+
"props": ["size"]
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"presets": [
|
|
16
|
+
{
|
|
17
|
+
"name": "Default",
|
|
18
|
+
"props": {
|
|
19
|
+
"widths": [1, 2, 3, 4, 5, 3, 3, 7]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "Small",
|
|
24
|
+
"props": {
|
|
25
|
+
"widths": [1, 2, 3, 4, 5, 3, 3, 7],
|
|
26
|
+
"size": "sm"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "Custom colors",
|
|
31
|
+
"props": {
|
|
32
|
+
"colors": ["data_7", "data_1", "neutral"],
|
|
33
|
+
"widths": [4, 5, 3]
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"conditionals": {},
|
|
38
|
+
"hints": {
|
|
39
|
+
"custom_colors": {
|
|
40
|
+
"presetName": "Custom colors",
|
|
41
|
+
"message": "Use the colors prop to change the colors of the distribution bar. Currently only the data and status colors will work for DistributionBar.",
|
|
42
|
+
"type": "info"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -8,6 +8,25 @@
|
|
|
8
8
|
cursor: grab;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
+
&.is_touch_active {
|
|
12
|
+
.pb_draggable_handle,
|
|
13
|
+
.card_draggable_handle {
|
|
14
|
+
color: $text_lt_default;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.pb_draggable_handle,
|
|
19
|
+
.card_draggable_handle {
|
|
20
|
+
touch-action: none;
|
|
21
|
+
-webkit-touch-callout: none;
|
|
22
|
+
user-select: none;
|
|
23
|
+
cursor: grab;
|
|
24
|
+
|
|
25
|
+
&:active {
|
|
26
|
+
color: $text_lt_default;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
11
30
|
&.is_dragging {
|
|
12
31
|
position: relative;
|
|
13
32
|
|
|
@@ -5,3 +5,5 @@ Use the `draggable` kit and manage state as shown.
|
|
|
5
5
|
`draggable/draggable_container` kit creates the container within which the cards can be dragged and dropped.
|
|
6
6
|
|
|
7
7
|
The Card kit is optimized to work with the draggable kit. To enable drag, use the `draggable_item` and `drag_id` props on the Card kit as shown. An additional optional boolean prop (set to true by default) of `drag_handle` is also available to show the drag handle icon.
|
|
8
|
+
|
|
9
|
+
On touch devices, drag from the grip handle (no long press). Swiping the card body scrolls as usual. Keep `drag_handle` enabled on mobile. Desktop mouse drag is unchanged.
|
|
@@ -6,4 +6,5 @@ Use `DraggableProvider` and manage state as shown.
|
|
|
6
6
|
|
|
7
7
|
The Card kit is optimized to work with the draggable kit. To enable drag, use the `draggableItem` and `dragId` props on the Card kit as shown. An additional optional boolean prop (set to true by default) of `dragHandle` is also available to show the drag handle icon.
|
|
8
8
|
|
|
9
|
+
On touch devices, drag from the grip handle (no long press). Swiping the card body scrolls as usual. Keep `dragHandle` enabled on mobile. Desktop mouse drag is unchanged.
|
|
9
10
|
|
|
@@ -3,3 +3,5 @@ For a simplified version of the Draggable API for the List kit, you can do the f
|
|
|
3
3
|
The List kit is optimized to work with the draggable kit. To enable drag, use the `enable_drag` prop on List kit with an array of the included items AND `drag_id` prop on ListItems. You will also need to include the `items` prop containing your array of listed items for the Draggable API.
|
|
4
4
|
|
|
5
5
|
An additional optional boolean prop (set to true by default) of `drag_handle` is also available on ListItem kit to show the drag handle icon.
|
|
6
|
+
|
|
7
|
+
On touch devices, drag from the grip handle (no long press). Swiping the rest of the row scrolls as usual. Keep `drag_handle` enabled on mobile. Desktop mouse drag is unchanged.
|
|
@@ -2,4 +2,6 @@ For a simplified version of the Draggable API for the List kit, you can do the f
|
|
|
2
2
|
|
|
3
3
|
Use `DraggableProvider` and manage state as shown.
|
|
4
4
|
|
|
5
|
-
The List kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on List kit AND `dragId` prop on ListItem. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on
|
|
5
|
+
The List kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on List kit AND `dragId` prop on ListItem. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on ListItem to show the drag handle icon.
|
|
6
|
+
|
|
7
|
+
On touch devices, drag from the grip handle (no long press). Swiping the rest of the row scrolls as usual. Keep `dragHandle` enabled on mobile. Desktop mouse drag is unchanged.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
For a simplified version of the Draggable API for the SelectableList kit, you can do the following:
|
|
2
2
|
|
|
3
|
-
The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the `enable_drag` prop on SelectableList kit AND `drag_id` prop within the SelectableList kit prop. An additional optional boolean prop (set to true by default) of `drag_handle` is also available on SelectableList kit to show the drag handle icon.
|
|
3
|
+
The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the `enable_drag` prop on SelectableList kit AND `drag_id` prop within the SelectableList kit prop. An additional optional boolean prop (set to true by default) of `drag_handle` is also available on SelectableList kit to show the drag handle icon.
|
|
4
|
+
|
|
5
|
+
On touch devices, drag from the grip handle (no long press). Swiping the rest of the row scrolls as usual. Keep `drag_handle` enabled on mobile. Desktop mouse drag is unchanged.
|
|
@@ -2,4 +2,6 @@ For a simplified version of the Draggable API for the SelectableList kit, you ca
|
|
|
2
2
|
|
|
3
3
|
Use `DraggableProvider` and manage state as shown.
|
|
4
4
|
|
|
5
|
-
The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on SelectableList kit AND `dragId` prop on SelectableList.Item. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on SelectableList kit to show the drag handle icon.
|
|
5
|
+
The SelectableList kit is optimized to work with the draggable kit. To enable drag, use the `enableDrag` prop on SelectableList kit AND `dragId` prop on SelectableList.Item. An additional optional boolean prop (set to true by default) of `dragHandle` is also available on SelectableList kit to show the drag handle icon.
|
|
6
|
+
|
|
7
|
+
On touch devices, drag from the grip handle (no long press). Swiping the rest of the row scrolls as usual. Keep `dragHandle` enabled on mobile. Desktop mouse drag is unchanged.
|
|
@@ -211,6 +211,14 @@ test("Attached draggable HTML attributes", () => {
|
|
|
211
211
|
expect(item).toHaveAttribute("draggable");
|
|
212
212
|
});
|
|
213
213
|
|
|
214
|
+
test("draggable items expose data-pb-drag-id for touch reordering", () => {
|
|
215
|
+
render(<DefaultDraggableKit />);
|
|
216
|
+
const kit = screen.getByTestId(testId);
|
|
217
|
+
|
|
218
|
+
const item = kit.querySelector(".pb_draggable_item");
|
|
219
|
+
expect(item).toHaveAttribute("data-pb-drag-id", "1");
|
|
220
|
+
});
|
|
221
|
+
|
|
214
222
|
test("generated dragHandle with List", () => {
|
|
215
223
|
render(<DraggableKitWithList />);
|
|
216
224
|
const kit = screen.getByTestId(testId);
|
|
@@ -302,6 +310,14 @@ const DraggableMultipleContainers = () => {
|
|
|
302
310
|
);
|
|
303
311
|
};
|
|
304
312
|
|
|
313
|
+
test("draggable containers expose data-pb-drag-container when provided", () => {
|
|
314
|
+
render(<DraggableMultipleContainers />);
|
|
315
|
+
const kit = screen.getByTestId(testId);
|
|
316
|
+
|
|
317
|
+
const container = kit.querySelector('[data-testid="container-To Do"]');
|
|
318
|
+
expect(container).toHaveAttribute("data-pb-drag-container", "To Do");
|
|
319
|
+
});
|
|
320
|
+
|
|
305
321
|
test("renders multiple containers with correct items", () => {
|
|
306
322
|
render(<DraggableMultipleContainers />);
|
|
307
323
|
|
|
@@ -2,7 +2,32 @@ import PbEnhancedElement from "../pb_enhanced_element";
|
|
|
2
2
|
|
|
3
3
|
const DRAGGABLE_SELECTOR = "[data-pb-draggable]";
|
|
4
4
|
const DRAGGABLE_CONTAINER = ".pb_draggable_container";
|
|
5
|
+
const DRAG_HANDLE_SELECTOR = ".pb_draggable_handle, .card_draggable_handle";
|
|
5
6
|
const NEEDS_CLONE = ["shadow", "outline", "line"]; // clone only for these types
|
|
7
|
+
const DRAG_THRESHOLD_PX = 5;
|
|
8
|
+
|
|
9
|
+
const isTouchDragDevice = () => {
|
|
10
|
+
const hasTouch = "ontouchstart" in window;
|
|
11
|
+
const hasCoarsePointer =
|
|
12
|
+
typeof window.matchMedia === "function" &&
|
|
13
|
+
window.matchMedia("(hover: none) and (pointer: coarse)").matches;
|
|
14
|
+
|
|
15
|
+
return hasTouch || hasCoarsePointer;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const getDragIdFromElement = (element) => {
|
|
19
|
+
const item = element?.closest(".pb_draggable_item");
|
|
20
|
+
if (!item) return null;
|
|
21
|
+
|
|
22
|
+
return item.getAttribute("data-pb-drag-id") || item.id;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const getContainerFromElement = (element) => {
|
|
26
|
+
const container = element?.closest(DRAGGABLE_CONTAINER);
|
|
27
|
+
if (!container) return null;
|
|
28
|
+
|
|
29
|
+
return container.getAttribute("data-pb-drag-container") || container.id;
|
|
30
|
+
};
|
|
6
31
|
|
|
7
32
|
export default class PbDraggable extends PbEnhancedElement {
|
|
8
33
|
static get selector() { return DRAGGABLE_SELECTOR; }
|
|
@@ -21,6 +46,8 @@ export default class PbDraggable extends PbEnhancedElement {
|
|
|
21
46
|
this.hasMultipleContainers = false;
|
|
22
47
|
this.dragZoneType = "";
|
|
23
48
|
this.dragZoneColor = "";
|
|
49
|
+
this.useTouchDrag = isTouchDragDevice();
|
|
50
|
+
this.touchCleanups = [];
|
|
24
51
|
|
|
25
52
|
// If DOM is already loaded, bind immediately; otherwise wait for DOMContentLoaded
|
|
26
53
|
if (document.readyState === "loading") {
|
|
@@ -54,9 +81,14 @@ export default class PbDraggable extends PbEnhancedElement {
|
|
|
54
81
|
|
|
55
82
|
this.element.querySelectorAll(".pb_draggable_item")
|
|
56
83
|
.forEach(item => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
84
|
+
if (this.useTouchDrag) {
|
|
85
|
+
item.setAttribute("draggable", "false");
|
|
86
|
+
this.touchCleanups.push(this.bindTouchDragForItem(item));
|
|
87
|
+
} else {
|
|
88
|
+
item.addEventListener("dragstart", this.handleDragStart.bind(this));
|
|
89
|
+
item.addEventListener("dragend", this.handleDragEnd.bind(this));
|
|
90
|
+
item.addEventListener("dragenter", this.handleDragEnter.bind(this));
|
|
91
|
+
}
|
|
60
92
|
});
|
|
61
93
|
|
|
62
94
|
containers.forEach(c => {
|
|
@@ -65,8 +97,118 @@ export default class PbDraggable extends PbEnhancedElement {
|
|
|
65
97
|
});
|
|
66
98
|
}
|
|
67
99
|
|
|
100
|
+
bindTouchDragForItem(item) {
|
|
101
|
+
const handle = item.querySelector(DRAG_HANDLE_SELECTOR);
|
|
102
|
+
const dragTarget = handle || item;
|
|
103
|
+
const state = {
|
|
104
|
+
active: false,
|
|
105
|
+
dragging: false,
|
|
106
|
+
startX: 0,
|
|
107
|
+
startY: 0,
|
|
108
|
+
lastTargetDragId: null,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
const resetState = () => {
|
|
112
|
+
state.active = false;
|
|
113
|
+
state.dragging = false;
|
|
114
|
+
state.lastTargetDragId = null;
|
|
115
|
+
item.classList.remove("is_touch_active");
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const pointerEventFromTouch = (touch, target) => ({
|
|
119
|
+
target,
|
|
120
|
+
clientX: touch.clientX,
|
|
121
|
+
clientY: touch.clientY,
|
|
122
|
+
preventDefault: () => undefined,
|
|
123
|
+
stopPropagation: () => undefined,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
const onTouchStart = (event) => {
|
|
127
|
+
if (handle && !handle.contains(event.target)) return;
|
|
128
|
+
|
|
129
|
+
const touch = event.touches[0];
|
|
130
|
+
if (!touch) return;
|
|
131
|
+
|
|
132
|
+
state.active = true;
|
|
133
|
+
state.startX = touch.clientX;
|
|
134
|
+
state.startY = touch.clientY;
|
|
135
|
+
item.classList.add("is_touch_active");
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const onTouchMove = (event) => {
|
|
139
|
+
if (!state.active) return;
|
|
140
|
+
|
|
141
|
+
const touch = event.touches[0];
|
|
142
|
+
if (!touch) return;
|
|
143
|
+
|
|
144
|
+
if (!state.dragging) {
|
|
145
|
+
const deltaX = touch.clientX - state.startX;
|
|
146
|
+
const deltaY = touch.clientY - state.startY;
|
|
147
|
+
|
|
148
|
+
if (Math.hypot(deltaX, deltaY) < DRAG_THRESHOLD_PX) return;
|
|
149
|
+
|
|
150
|
+
state.dragging = true;
|
|
151
|
+
this.handleDragStart(pointerEventFromTouch(touch, item));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
event.preventDefault();
|
|
155
|
+
|
|
156
|
+
const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY);
|
|
157
|
+
const targetItem = elementBelow?.closest(".pb_draggable_item");
|
|
158
|
+
const targetDragId = getDragIdFromElement(elementBelow);
|
|
159
|
+
|
|
160
|
+
if (targetItem && targetItem !== item && targetDragId !== state.lastTargetDragId) {
|
|
161
|
+
state.lastTargetDragId = targetDragId;
|
|
162
|
+
this.handleDragEnter(pointerEventFromTouch(touch, targetItem));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const targetContainer = getContainerFromElement(elementBelow);
|
|
166
|
+
if (targetContainer) {
|
|
167
|
+
const containerElement = elementBelow.closest(DRAGGABLE_CONTAINER);
|
|
168
|
+
if (containerElement) {
|
|
169
|
+
this.handleDragOver(pointerEventFromTouch(touch, containerElement));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
const finishTouchDrag = (touch) => {
|
|
175
|
+
if (!state.active) return;
|
|
176
|
+
|
|
177
|
+
if (state.dragging && touch) {
|
|
178
|
+
const elementBelow = document.elementFromPoint(touch.clientX, touch.clientY);
|
|
179
|
+
const containerElement = elementBelow?.closest(DRAGGABLE_CONTAINER);
|
|
180
|
+
|
|
181
|
+
if (containerElement) {
|
|
182
|
+
this.handleDrop(pointerEventFromTouch(touch, containerElement));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.handleDragEnd({ target: item });
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
resetState();
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const onTouchEnd = (event) => finishTouchDrag(event.changedTouches[0]);
|
|
192
|
+
const onTouchCancel = (event) => finishTouchDrag(event.changedTouches[0]);
|
|
193
|
+
|
|
194
|
+
dragTarget.addEventListener("touchstart", onTouchStart, { passive: true });
|
|
195
|
+
dragTarget.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
196
|
+
dragTarget.addEventListener("touchend", onTouchEnd, { passive: true });
|
|
197
|
+
dragTarget.addEventListener("touchcancel", onTouchCancel, { passive: true });
|
|
198
|
+
|
|
199
|
+
return () => {
|
|
200
|
+
dragTarget.removeEventListener("touchstart", onTouchStart);
|
|
201
|
+
dragTarget.removeEventListener("touchmove", onTouchMove);
|
|
202
|
+
dragTarget.removeEventListener("touchend", onTouchEnd);
|
|
203
|
+
dragTarget.removeEventListener("touchcancel", onTouchCancel);
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
68
207
|
/* ---------------- DRAG START ---------------- */
|
|
69
208
|
handleDragStart(event) {
|
|
209
|
+
const item = event.target.closest(".pb_draggable_item");
|
|
210
|
+
if (!item) return;
|
|
211
|
+
|
|
70
212
|
// Needed to prevent images within draggable items from being independently draggable
|
|
71
213
|
// Needed if using Image kit in draggable items
|
|
72
214
|
if (event.target.tagName.toLowerCase() === "img") {
|
|
@@ -74,9 +216,9 @@ export default class PbDraggable extends PbEnhancedElement {
|
|
|
74
216
|
return;
|
|
75
217
|
}
|
|
76
218
|
|
|
77
|
-
const container =
|
|
78
|
-
this.draggedItem =
|
|
79
|
-
this.draggedItemId =
|
|
219
|
+
const container = item.closest(DRAGGABLE_CONTAINER);
|
|
220
|
+
this.draggedItem = item;
|
|
221
|
+
this.draggedItemId = getDragIdFromElement(item);
|
|
80
222
|
this.dragZoneType = this.element.dataset.dropZoneType || "";
|
|
81
223
|
this.dragZoneColor = this.element.dataset.dropZoneColor || "";
|
|
82
224
|
|
|
@@ -122,7 +264,7 @@ export default class PbDraggable extends PbEnhancedElement {
|
|
|
122
264
|
}
|
|
123
265
|
|
|
124
266
|
if (this.dragZoneType !== "line") {
|
|
125
|
-
requestAnimationFrame(() => (
|
|
267
|
+
requestAnimationFrame(() => (item.style.opacity = "0.5"));
|
|
126
268
|
}
|
|
127
269
|
}
|
|
128
270
|
|