playbook_ui 14.13.0.pre.rc.10 → 14.14.0.pre.alpha.PBNTR866finalizecssendlessscroll6462

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 (213) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +0 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +127 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +55 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/TablePagination.tsx +33 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +275 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +143 -3
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +66 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +195 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +45 -99
  11. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +73 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +52 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +80 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +190 -6
  15. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +155 -297
  16. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +8 -1
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_custom_cell.jsx +75 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.jsx +50 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props.html.erb +1 -1
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props.jsx +1 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_rails.md +3 -1
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_react.md +3 -1
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +33 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.jsx +55 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_rails.md +3 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header_react.md +3 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_infinite_scroll.json +152002 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +5 -1
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +4 -1
  30. data/app/pb_kits/playbook/pb_bar_graph/BarGraphStyles.scss +58 -0
  31. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_pb_styles.jsx +64 -0
  32. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_pb_styles.md +1 -0
  33. data/app/pb_kits/playbook/pb_bar_graph/docs/example.yml +1 -0
  34. data/app/pb_kits/playbook/pb_bar_graph/docs/index.js +1 -0
  35. data/app/pb_kits/playbook/pb_checkbox/_checkbox.tsx +17 -8
  36. data/app/pb_kits/playbook/pb_checkbox/checkbox.test.js +16 -0
  37. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_react_hook.jsx +69 -0
  38. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_react_hook.md +1 -0
  39. data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +2 -1
  40. data/app/pb_kits/playbook/pb_checkbox/docs/index.js +1 -0
  41. data/app/pb_kits/playbook/pb_currency/_currency.tsx +46 -31
  42. data/app/pb_kits/playbook/pb_currency/currency.html.erb +15 -8
  43. data/app/pb_kits/playbook/pb_currency/currency.rb +17 -2
  44. data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display.html.erb +22 -0
  45. data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display.jsx +34 -0
  46. data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display_rails.md +1 -0
  47. data/app/pb_kits/playbook/pb_currency/docs/_currency_null_display_react.md +1 -0
  48. data/app/pb_kits/playbook/pb_currency/docs/example.yml +2 -0
  49. data/app/pb_kits/playbook/pb_currency/docs/index.js +2 -1
  50. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +3 -1
  51. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_rails.html.erb +99 -0
  52. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_multiple_containers_rails.md +1 -0
  53. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_table.html.erb +61 -0
  54. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_table.md +4 -0
  55. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_table_react.jsx +90 -0
  56. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_with_table_react.md +5 -0
  57. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +4 -5
  58. data/app/pb_kits/playbook/pb_draggable/docs/index.js +2 -1
  59. data/app/pb_kits/playbook/pb_draggable/draggable_container.html.erb +2 -2
  60. data/app/pb_kits/playbook/pb_draggable/draggable_container.rb +5 -0
  61. data/app/pb_kits/playbook/pb_draggable/draggable_item.html.erb +1 -1
  62. data/app/pb_kits/playbook/pb_draggable/draggable_item.rb +4 -0
  63. data/app/pb_kits/playbook/pb_draggable/index.js +151 -15
  64. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableContainer.tsx +7 -4
  65. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +6 -3
  66. data/app/pb_kits/playbook/pb_drawer/_drawer.scss +32 -8
  67. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_behavior.html.erb +8 -0
  68. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_borders.html.erb +33 -0
  69. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_breakpoints.html.erb +0 -0
  70. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_default.html.erb +20 -1
  71. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_menu.html.erb +24 -0
  72. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.html.erb +21 -0
  73. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_overlay.md +1 -0
  74. data/app/pb_kits/playbook/pb_drawer/docs/_drawer_sizes.html.erb +49 -0
  75. data/app/pb_kits/playbook/pb_drawer/docs/example.yml +5 -0
  76. data/app/pb_kits/playbook/pb_drawer/drawer.html.erb +20 -12
  77. data/app/pb_kits/playbook/pb_drawer/drawer.rb +49 -1
  78. data/app/pb_kits/playbook/pb_drawer/index.js +257 -0
  79. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
  80. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +2 -1
  81. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +11 -7
  82. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting.html.erb +11 -0
  83. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting.jsx +22 -0
  84. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting_rails.md +1 -0
  85. data/app/pb_kits/playbook/pb_home_address_street/docs/_home_address_street_formatting_react.md +1 -0
  86. data/app/pb_kits/playbook/pb_home_address_street/docs/example.yml +2 -0
  87. data/app/pb_kits/playbook/pb_home_address_street/docs/index.js +1 -0
  88. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.rb +13 -2
  89. data/app/pb_kits/playbook/pb_icon/icon.html.erb +2 -6
  90. data/app/pb_kits/playbook/pb_icon_button/_icon_button.tsx +71 -0
  91. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_default.html.erb +1 -2
  92. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_default.jsx +17 -0
  93. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_sizes.html.erb +27 -0
  94. data/app/pb_kits/playbook/pb_icon_button/docs/_icon_button_sizes.jsx +61 -0
  95. data/app/pb_kits/playbook/pb_icon_button/docs/example.yml +5 -3
  96. data/app/pb_kits/playbook/pb_icon_button/docs/index.js +2 -0
  97. data/app/pb_kits/playbook/pb_icon_button/icon_button.html.erb +1 -1
  98. data/app/pb_kits/playbook/pb_icon_button/icon_button.rb +3 -0
  99. data/app/pb_kits/playbook/pb_icon_button/icon_button.test.jsx +39 -0
  100. data/app/pb_kits/playbook/pb_layout/body.html.erb +1 -5
  101. data/app/pb_kits/playbook/pb_layout/footer.html.erb +1 -5
  102. data/app/pb_kits/playbook/pb_layout/header.html.erb +1 -5
  103. data/app/pb_kits/playbook/pb_layout/item.html.erb +1 -5
  104. data/app/pb_kits/playbook/pb_layout/layout.html.erb +1 -5
  105. data/app/pb_kits/playbook/pb_layout/sidebar.html.erb +1 -5
  106. data/app/pb_kits/playbook/pb_legend/legend.html.erb +1 -6
  107. data/app/pb_kits/playbook/pb_message/message.html.erb +1 -6
  108. data/app/pb_kits/playbook/pb_message/message_mention.html.erb +1 -6
  109. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.html.erb +1 -6
  110. data/app/pb_kits/playbook/pb_nav/item.html.erb +7 -19
  111. data/app/pb_kits/playbook/pb_nav/nav.html.erb +3 -8
  112. data/app/pb_kits/playbook/pb_online_status/online_status.html.erb +1 -6
  113. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +13 -0
  114. data/app/pb_kits/playbook/pb_overlay/_overlay.tsx +11 -1
  115. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.html.erb +11 -0
  116. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar.jsx +37 -0
  117. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_rails.md +1 -0
  118. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_hide_scroll_bar_react.md +1 -0
  119. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.html.erb +11 -0
  120. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.jsx +37 -0
  121. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.md +1 -0
  122. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional_react.md +1 -0
  123. data/app/pb_kits/playbook/pb_overlay/docs/example.yml +4 -0
  124. data/app/pb_kits/playbook/pb_overlay/docs/index.js +2 -0
  125. data/app/pb_kits/playbook/pb_overlay/index.js +61 -0
  126. data/app/pb_kits/playbook/pb_overlay/overlay.html.erb +5 -3
  127. data/app/pb_kits/playbook/pb_overlay/overlay.rb +16 -1
  128. data/app/pb_kits/playbook/pb_overlay/overlay.test.jsx +12 -0
  129. data/app/pb_kits/playbook/pb_overlay/subcomponents/_overlay_token.tsx +48 -10
  130. data/app/pb_kits/playbook/pb_popover/popover.html.erb +1 -6
  131. data/app/pb_kits/playbook/pb_progress_pills/_progress_pills.scss +6 -1
  132. data/app/pb_kits/playbook/pb_progress_pills/_progress_pills.tsx +7 -5
  133. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_default.html.erb +1 -0
  134. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_default.jsx +7 -0
  135. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_default.md +1 -0
  136. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_full_width.html.erb +1 -0
  137. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_full_width.jsx +18 -0
  138. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_full_width_rails.md +1 -0
  139. data/app/pb_kits/playbook/pb_progress_pills/docs/_progress_pills_full_width_react.md +1 -0
  140. data/app/pb_kits/playbook/pb_progress_pills/docs/example.yml +2 -0
  141. data/app/pb_kits/playbook/pb_progress_pills/docs/index.js +1 -0
  142. data/app/pb_kits/playbook/pb_progress_pills/progress_pills.html.erb +2 -7
  143. data/app/pb_kits/playbook/pb_progress_pills/progress_pills.rb +6 -0
  144. data/app/pb_kits/playbook/pb_progress_pills/progress_pills.test.js +26 -1
  145. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.html.erb +1 -5
  146. data/app/pb_kits/playbook/pb_progress_step/progress_step.html.erb +1 -5
  147. data/app/pb_kits/playbook/pb_progress_step/progress_step_item.html.erb +3 -7
  148. data/app/pb_kits/playbook/pb_radio/radio.html.erb +6 -11
  149. data/app/pb_kits/playbook/pb_select/index.js +38 -0
  150. data/app/pb_kits/playbook/pb_select/select.rb +8 -0
  151. data/app/pb_kits/playbook/pb_table/docs/_table_with_clickable_rows.html.erb +47 -0
  152. data/app/pb_kits/playbook/pb_table/docs/_table_with_clickable_rows.jsx +88 -0
  153. data/app/pb_kits/playbook/pb_table/docs/_table_with_clickable_rows.md +1 -0
  154. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible.jsx +1 -1
  155. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.html.erb +51 -0
  156. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click_rails.md +2 -0
  157. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +96 -0
  158. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.jsx +101 -0
  159. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.md +1 -0
  160. data/app/pb_kits/playbook/pb_table/docs/example.yml +5 -0
  161. data/app/pb_kits/playbook/pb_table/docs/index.js +3 -1
  162. data/app/pb_kits/playbook/pb_table/index.ts +41 -9
  163. data/app/pb_kits/playbook/pb_table/styles/_collapsible.scss +4 -0
  164. data/app/pb_kits/playbook/pb_table/subcomponents/_table_body.tsx +29 -2
  165. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +31 -3
  166. data/app/pb_kits/playbook/pb_table/table_body.html.erb +13 -7
  167. data/app/pb_kits/playbook/pb_table/table_body.rb +2 -0
  168. data/app/pb_kits/playbook/pb_table/table_row.html.erb +14 -7
  169. data/app/pb_kits/playbook/pb_table/table_row.rb +14 -1
  170. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_mask.html.erb +15 -1
  171. data/app/pb_kits/playbook/pb_text_input/index.js +60 -82
  172. data/app/pb_kits/playbook/pb_text_input/text_input.rb +5 -2
  173. data/app/pb_kits/playbook/pb_tooltip/_tooltip.scss +0 -3
  174. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.html.erb +39 -0
  175. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_delay_rails.md +3 -0
  176. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_interaction.html.erb +26 -0
  177. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +2 -0
  178. data/app/pb_kits/playbook/pb_tooltip/floating_ui.js +282 -0
  179. data/app/pb_kits/playbook/pb_tooltip/index.js +2 -2
  180. data/app/pb_kits/playbook/pb_tooltip/tooltip.rb +10 -2
  181. data/dist/chunks/_typeahead-B1p_cPQJ.js +36 -0
  182. data/dist/chunks/_weekday_stacked-DTN9JLqd.js +45 -0
  183. data/dist/chunks/{lib-DjpLC8uO.js → lib-Fr78pbpF.js} +2 -2
  184. data/dist/chunks/{pb_form_validation-S56UaHZl.js → pb_form_validation-CN51bfsD.js} +1 -1
  185. data/dist/chunks/vendor.js +1 -1
  186. data/dist/menu.yml +3 -10
  187. data/dist/playbook-doc.js +1 -1
  188. data/dist/playbook-rails-react-bindings.js +1 -1
  189. data/dist/playbook-rails.js +1 -1
  190. data/dist/playbook.css +1 -1
  191. data/lib/playbook/forms/builder/time_zone_select_field.rb +19 -0
  192. data/lib/playbook/forms/builder.rb +1 -0
  193. data/lib/playbook/version.rb +2 -2
  194. metadata +84 -23
  195. data/app/pb_kits/playbook/pb_avatar_action_button/_avatar_action_button.scss +0 -66
  196. data/app/pb_kits/playbook/pb_avatar_action_button/_avatar_action_button.tsx +0 -98
  197. data/app/pb_kits/playbook/pb_avatar_action_button/avatar_action_button.html.erb +0 -28
  198. data/app/pb_kits/playbook/pb_avatar_action_button/avatar_action_button.rb +0 -42
  199. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_actions.html.erb +0 -19
  200. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_actions.jsx +0 -26
  201. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_default.html.erb +0 -10
  202. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_default.jsx +0 -17
  203. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_on_click.jsx +0 -19
  204. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_onclick.html.erb +0 -16
  205. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_placement.html.erb +0 -35
  206. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_placement.jsx +0 -42
  207. data/app/pb_kits/playbook/pb_avatar_action_button/docs/_avatar_action_button_tooltip.html.erb +0 -13
  208. data/app/pb_kits/playbook/pb_avatar_action_button/docs/example.yml +0 -15
  209. data/app/pb_kits/playbook/pb_avatar_action_button/docs/index.js +0 -4
  210. data/app/pb_kits/playbook/pb_avatar_action_button/pb_avatar_action_button.test.js +0 -31
  211. data/dist/chunks/_typeahead-CkemExmL.js +0 -36
  212. data/dist/chunks/_weekday_stacked-CtSzPEH0.js +0 -45
  213. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_custom_click.md → _table_with_collapsible_with_custom_click_react.md} +0 -0
@@ -0,0 +1,99 @@
1
+ <% containers = [
2
+ "To Do",
3
+ "In Progress",
4
+ "Done"
5
+ ] %>
6
+
7
+ <% items_data = [
8
+ {
9
+ id: "11",
10
+ container: "To Do",
11
+ title: "Task 1",
12
+ description: "Bug fixes",
13
+ assignee_name: "Terry Miles",
14
+ assignee_img: "https://randomuser.me/api/portraits/men/44.jpg",
15
+ },
16
+ {
17
+ id: "12",
18
+ container: "To Do",
19
+ title: "Task 2",
20
+ description: "Documentation",
21
+ assignee_name: "Sophia Miles",
22
+ assignee_img: "https://randomuser.me/api/portraits/women/8.jpg",
23
+ },
24
+ {
25
+ id: "13",
26
+ container: "In Progress",
27
+ title: "Task 3",
28
+ description: "Add a variant",
29
+ assignee_name: "Alice Jones",
30
+ assignee_img: "https://randomuser.me/api/portraits/women/10.jpg",
31
+ },
32
+ {
33
+ id: "14",
34
+ container: "To Do",
35
+ title: "Task 4",
36
+ description: "Add jest tests",
37
+ assignee_name: "Mike James",
38
+ assignee_img: "https://randomuser.me/api/portraits/men/8.jpg",
39
+ },
40
+ {
41
+ id: "15",
42
+ container: "Done",
43
+ title: "Task 5",
44
+ description: "Alpha testing",
45
+ assignee_name: "James Guy",
46
+ assignee_img: "https://randomuser.me/api/portraits/men/18.jpg",
47
+ },
48
+ {
49
+ id: "16",
50
+ container: "In Progress",
51
+ title: "Task 6",
52
+ description: "Release",
53
+ assignee_name: "Sally Jones",
54
+ assignee_img: "https://randomuser.me/api/portraits/women/28.jpg",
55
+ },
56
+ ] %>
57
+
58
+ <%= pb_rails("draggable", props: { initial_items: items_data }) do %>
59
+ <%= pb_rails("flex", props: { justify_content: "center" }) do %>
60
+ <% containers.each do |container| %>
61
+ <%= pb_rails("draggable/draggable_container", props: {
62
+ container: container,
63
+ width: "xs",
64
+ padding: "sm",
65
+ data: { container: container }
66
+ }) do %>
67
+ <%= pb_rails("caption", props: { text_align: "center" }) do %><%= container %><% end %>
68
+ <%= pb_rails("flex", props: {align_items: "stretch", orientation: "column"}) do %>
69
+ <% items_data.select { |item| item[:container] == container }.each do |item| %>
70
+ <%= pb_rails("draggable/draggable_item", props: {
71
+ container: container,
72
+ drag_id: item[:id]
73
+ }) do %>
74
+ <%= pb_rails("card", props: { margin_bottom: "sm", padding: "sm"}) do %>
75
+ <%= pb_rails("flex", props: { justify: "between" }) do %>
76
+ <%= pb_rails("flex/flex_item") do %>
77
+ <%= pb_rails("flex") do %>
78
+ <%= pb_rails("avatar", props: {
79
+ image_url: item[:assignee_img],
80
+ name: item[:assignee_name],
81
+ size: "xxs"
82
+ }) %>
83
+ <%= pb_rails("title", props: {
84
+ padding_left: "xs",
85
+ size: 4,
86
+ text: item[:title]
87
+ }) %>
88
+ <% end %>
89
+ <% end %>
90
+ <% end %>
91
+ <%= pb_rails("body", props: { padding_top: "xs", text: item[:description] }) %>
92
+ <% end %>
93
+ <% end %>
94
+ <% end %>
95
+ <% end %>
96
+ <% end %>
97
+ <% end %>
98
+ <% end %>
99
+ <% end %>
@@ -0,0 +1 @@
1
+ The Draggable kit can also be used to achieve more complex, multiple container functionality as shown here. This complex usage requires the full subcomponent structure.
@@ -0,0 +1,61 @@
1
+ <% initial_items = [
2
+ {
3
+ id: "1",
4
+ title: "Task 1",
5
+ assignee_name: "Terry Miles",
6
+ assignee_img: "https://randomuser.me/api/portraits/men/44.jpg",
7
+ },
8
+ {
9
+ id: "2",
10
+ title: "Task 2",
11
+ assignee_name: "Sophia Miles",
12
+ assignee_img: "https://randomuser.me/api/portraits/women/8.jpg",
13
+ },
14
+ {
15
+ id: "3",
16
+ title: "Task 3",
17
+ assignee_name: "Alice Jones",
18
+ assignee_img: "https://randomuser.me/api/portraits/women/10.jpg",
19
+ },
20
+ {
21
+ id: "4",
22
+ title: "Task 4",
23
+ assignee_name: "Mike James",
24
+ assignee_img: "https://randomuser.me/api/portraits/men/8.jpg",
25
+ },
26
+ {
27
+ id: "5",
28
+ title: "Task 5",
29
+ assignee_name: "James Guy",
30
+ assignee_img: "https://randomuser.me/api/portraits/men/18.jpg",
31
+ }
32
+ ] %>
33
+
34
+
35
+
36
+ <%= pb_rails("draggable", props: {initial_items: initial_items}) do %>
37
+ <%= pb_rails("table", props: { size: "sm", responsive:"none" }) do %>
38
+ <%= pb_rails("table/table_head") do %>
39
+ <%= pb_rails("table/table_row") do %>
40
+ <%= pb_rails("table/table_header", props: { text: "id"}) %>
41
+ <%= pb_rails("table/table_header", props: { text: "name"}) %>
42
+ <%= pb_rails("table/table_header", props: { text: "task number"}) %>
43
+ <% end %>
44
+ <% end %>
45
+
46
+ <%= pb_rails("table/table_body", props: {draggable_container: true}) do %>
47
+ <% initial_items.each do |item| %>
48
+ <%= pb_rails("table/table_row", props:{drag_id: item[:id], draggable_item: true}) do %>
49
+ <%= pb_rails("table/table_cell", props: { text: item[:id]}) %>
50
+ <%= pb_rails("table/table_cell") do %>
51
+ <%= pb_rails("flex", props:{align:"center"}) do %>
52
+ <%= pb_rails("avatar", props: {size: "xs", image_url: item[:assignee_img]}) %>
53
+ <%= pb_rails("body", props: {text: item[:assignee_name], padding_left:"sm"}) %>
54
+ <% end %>
55
+ <% end %>
56
+ <%= pb_rails("table/table_cell", props: { text: item[:title]}) %>
57
+ <% end %>
58
+ <% end %>
59
+ <% end %>
60
+ <% end %>
61
+ <% end %>
@@ -0,0 +1,4 @@
1
+ The draggable kit can also be used in conjunction with the table kit to create draggable table rows. To do this:
2
+
3
+ - use the `draggable_container` prop on the table/table_body to designate it as the Draggable Container
4
+ - use the `draggable_item` prop on the table/table_row to designate it as the Draggable Item. Make sure to also pass id to the `drag_id` prop here.
@@ -0,0 +1,90 @@
1
+ import React, { useState } from "react";
2
+ import { Flex, Table, Body, Avatar, DraggableProvider } from "playbook-ui";
3
+
4
+ // Initial items to be dragged
5
+ const data = [
6
+ {
7
+ id: "1",
8
+ task: "Task 1",
9
+ assignee_name: "Terry Miles",
10
+ assignee_img: "https://randomuser.me/api/portraits/men/44.jpg",
11
+ },
12
+ {
13
+ id: "2",
14
+ task: "Task 2",
15
+ assignee_name: "Sophia Miles",
16
+ assignee_img: "https://randomuser.me/api/portraits/women/8.jpg",
17
+ },
18
+ {
19
+ id: "3",
20
+ task: "Task 3",
21
+ assignee_name: "Alice Jones",
22
+ assignee_img: "https://randomuser.me/api/portraits/women/10.jpg",
23
+ },
24
+ {
25
+ id: "4",
26
+ task: "Task 4",
27
+ assignee_name: "Mike James",
28
+ assignee_img: "https://randomuser.me/api/portraits/men/8.jpg",
29
+ },
30
+ {
31
+ id: "5",
32
+ task: "Task 5",
33
+ assignee_name: "James Guy",
34
+ assignee_img: "https://randomuser.me/api/portraits/men/18.jpg",
35
+ }
36
+ ];
37
+
38
+ const DraggableWithTableReact = (props) => {
39
+ const [initialState, setInitialState] = useState(data);
40
+
41
+ return (
42
+ <>
43
+ <DraggableProvider initialItems={data}
44
+ onReorder={(items) => setInitialState(items)}
45
+ >
46
+ <Table
47
+ responsive="none"
48
+ size="sm"
49
+ {...props}
50
+ >
51
+ <Table.Head>
52
+ <Table.Row>
53
+ <Table.Header>{"id"}</Table.Header>
54
+ <Table.Header>{"name"}</Table.Header>
55
+ <Table.Header>{"task number"}</Table.Header>
56
+ </Table.Row>
57
+ </Table.Head>
58
+ <Table.Body draggableContainer>
59
+ {initialState.map(({ id, task, assignee_name, assignee_img }) => (
60
+ <Table.Row
61
+ dragId={id}
62
+ draggableItem
63
+ key={id}
64
+ >
65
+ <Table.Cell>{id}</Table.Cell>
66
+ <Table.Cell>
67
+ <Flex align="center">
68
+ <Avatar
69
+ imageUrl={assignee_img}
70
+ size="xs"
71
+ />
72
+ <Body
73
+ paddingLeft="xxs"
74
+ text={assignee_name}
75
+ {...props}
76
+ />
77
+ </Flex>
78
+ </Table.Cell>
79
+ <Table.Cell>{task}</Table.Cell>
80
+ </Table.Row>
81
+ ))}
82
+ </Table.Body>
83
+ </Table>
84
+ </DraggableProvider>
85
+ </>
86
+
87
+ );
88
+ };
89
+
90
+ export default DraggableWithTableReact;
@@ -0,0 +1,5 @@
1
+ The draggable kit can also be used in conjunction with the table kit to create draggable table rows. To do this:
2
+
3
+ - Wrap the Table with the `DraggableProvider` and manage state as shown.
4
+ - use the `draggableContainer` prop on the Table.Body to designate it as the Draggable Container
5
+ - use the `draggableItem` prop on the Table.Row to designate it as the Draggable Item. Make sure to also pass id to the `dragId` prop here.
@@ -1,18 +1,17 @@
1
1
  examples:
2
-
3
-
4
2
  react:
5
3
  - draggable_default: Default
6
4
  - draggable_with_list: Draggable with List Kit
7
5
  - draggable_with_selectable_list: Draggable with SelectableList Kit
8
6
  - draggable_with_cards: Draggable with Cards
7
+ - draggable_with_table_react: Draggable with Table
9
8
  - draggable_multiple_containers: Dragging Across Multiple Containers
10
-
9
+
11
10
  rails:
12
11
  - draggable_default_rails: Default
13
12
  - draggable_with_list_rails: Draggable with List Kit
14
13
  - draggable_with_selectable_list_rails: Draggable with SelectableList Kit
15
14
  - draggable_with_cards_rails: Draggable with Cards
15
+ - draggable_with_table: Draggable with Table
16
+ - draggable_multiple_containers_rails: Dragging Across Multiple Containers
16
17
 
17
-
18
-
@@ -2,4 +2,5 @@ export { default as DraggableDefault } from './_draggable_default.jsx'
2
2
  export { default as DraggableWithCards } from './_draggable_with_cards.jsx'
3
3
  export { default as DraggableWithList } from './_draggable_with_list.jsx'
4
4
  export { default as DraggableWithSelectableList } from './_draggable_with_selectable_list.jsx'
5
- export { default as DraggableMultipleContainers } from './_draggable_multiple_containers.jsx'
5
+ export { default as DraggableMultipleContainers } from './_draggable_multiple_containers.jsx'
6
+ export { default as DraggableWithTableReact } from './_draggable_with_table_react.jsx'
@@ -1,3 +1,3 @@
1
- <%= pb_content_tag do %>
1
+ <%= pb_content_tag(object.tag) do %>
2
2
  <%= content.presence %>
3
- <% end %>
3
+ <% end %>
@@ -3,6 +3,11 @@
3
3
  module Playbook
4
4
  module PbDraggable
5
5
  class DraggableContainer < ::Playbook::KitBase
6
+ prop :tag, type: Playbook::Props::String,
7
+ default: "div"
8
+ prop :container, type: Playbook::Props::String,
9
+ default: ""
10
+
6
11
  def data
7
12
  Hash(prop(:data)).merge(pb_draggable_container: true)
8
13
  end
@@ -1,4 +1,4 @@
1
- <%= pb_content_tag(:div, {
1
+ <%= pb_content_tag(object.tag, {
2
2
  id: "item_#{object.drag_id}",
3
3
  draggable: true
4
4
  }) do %>
@@ -5,6 +5,10 @@ module Playbook
5
5
  class DraggableItem < ::Playbook::KitBase
6
6
  prop :drag_id, type: Playbook::Props::String,
7
7
  default: ""
8
+ prop :tag, type: Playbook::Props::String,
9
+ default: "div"
10
+ prop :container, type: Playbook::Props::String,
11
+ default: ""
8
12
 
9
13
  def data
10
14
  Hash(prop(:data)).merge(pb_draggable_item: true)
@@ -9,12 +9,38 @@ export default class PbDraggable extends PbEnhancedElement {
9
9
  }
10
10
 
11
11
  connect() {
12
+ this.state = {
13
+ items: [],
14
+ dragData: { id: "", initialGroup: "" },
15
+ isDragging: "",
16
+ activeContainer: ""
17
+ };
18
+
12
19
  this.draggedItem = null;
13
20
  this.draggedItemId = null;
21
+ this.hasMultipleContainers = false;
22
+
14
23
  document.addEventListener("DOMContentLoaded", () => this.bindEventListeners());
15
24
  }
16
25
 
26
+ setState(newState) {
27
+ this.state = { ...this.state, ...newState };
28
+ if (newState.items) {
29
+ const customEvent = new CustomEvent('pb-draggable-reorder', {
30
+ detail: {
31
+ reorderedItems: this.state.items,
32
+ containerId: this.element.querySelector(DRAGGABLE_CONTAINER).id
33
+ }
34
+ });
35
+ this.element.dispatchEvent(customEvent);
36
+ }
37
+ }
38
+
17
39
  bindEventListeners() {
40
+ // Check for multiple containers
41
+ const containers = this.element.querySelectorAll(DRAGGABLE_CONTAINER);
42
+ this.hasMultipleContainers = containers.length > 1;
43
+
18
44
  // Needed to prevent images within draggable items from being independently draggable
19
45
  // Needed if using Image kit in draggable items
20
46
  this.element.querySelectorAll(".pb_draggable_item img").forEach(img => {
@@ -27,11 +53,10 @@ export default class PbDraggable extends PbEnhancedElement {
27
53
  item.addEventListener("dragenter", this.handleDragEnter.bind(this));
28
54
  });
29
55
 
30
- const container = this.element.querySelector(DRAGGABLE_CONTAINER);
31
- if (container) {
56
+ containers.forEach(container => {
32
57
  container.addEventListener("dragover", this.handleDragOver.bind(this));
33
58
  container.addEventListener("drop", this.handleDrop.bind(this));
34
- }
59
+ });
35
60
  }
36
61
 
37
62
  handleDragStart(event) {
@@ -41,11 +66,17 @@ export default class PbDraggable extends PbEnhancedElement {
41
66
  event.preventDefault();
42
67
  return;
43
68
  }
44
-
69
+
70
+ const container = event.target.closest(DRAGGABLE_CONTAINER);
45
71
  this.draggedItem = event.target;
46
72
  this.draggedItemId = event.target.id;
47
- event.target.classList.add("is_dragging");
48
73
 
74
+ this.setState({
75
+ dragData: { id: this.draggedItemId, initialGroup: container.id },
76
+ isDragging: this.draggedItemId
77
+ });
78
+
79
+ event.target.classList.add("is_dragging");
49
80
  if (event.dataTransfer) {
50
81
  event.dataTransfer.effectAllowed = 'move';
51
82
  event.dataTransfer.setData('text/plain', this.draggedItemId);
@@ -59,11 +90,20 @@ export default class PbDraggable extends PbEnhancedElement {
59
90
  handleDragEnter(event) {
60
91
  if (!this.draggedItem || event.target === this.draggedItem) return;
61
92
 
93
+ if (this.hasMultipleContainers) {
94
+ this.handleMultiContainerDragEnter(event);
95
+ } else {
96
+ this.handleSingleContainerDragEnter(event);
97
+ }
98
+ }
99
+
100
+ handleSingleContainerDragEnter(event) {
62
101
  const targetItem = event.target.closest('.pb_draggable_item');
63
102
  if (!targetItem) return;
64
103
 
65
104
  const container = targetItem.parentNode;
66
105
  const items = Array.from(container.children);
106
+
67
107
  const draggedIndex = items.indexOf(this.draggedItem);
68
108
  const targetIndex = items.indexOf(targetItem);
69
109
 
@@ -74,47 +114,143 @@ export default class PbDraggable extends PbEnhancedElement {
74
114
  }
75
115
  }
76
116
 
117
+ handleMultiContainerDragEnter(event) {
118
+ const targetContainer = event.target.closest(DRAGGABLE_CONTAINER);
119
+ const targetItem = event.target.closest('.pb_draggable_item');
120
+
121
+ if (!targetContainer) return;
122
+
123
+ // If we're entering a container directly or there's no target item
124
+ if (!targetItem) {
125
+ const lastItem = targetContainer.querySelector('.pb_draggable_item:last-child');
126
+ if (lastItem) {
127
+ targetContainer.insertBefore(this.draggedItem, lastItem.nextSibling);
128
+ } else {
129
+ targetContainer.appendChild(this.draggedItem);
130
+ }
131
+ return;
132
+ }
133
+
134
+ const container = targetItem.parentNode;
135
+ const items = Array.from(container.children);
136
+
137
+ const newItems = [...items].map(item => ({
138
+ id: item.id,
139
+ container: container.id
140
+ }));
141
+
142
+ this.setState({ items: newItems });
143
+
144
+ const rect = targetItem.getBoundingClientRect();
145
+ const middleY = rect.top + rect.height / 2;
146
+
147
+ if (event.clientY < middleY) {
148
+ container.insertBefore(this.draggedItem, targetItem);
149
+ } else {
150
+ container.insertBefore(this.draggedItem, targetItem.nextSibling);
151
+ }
152
+ }
153
+
77
154
  handleDragOver(event) {
78
155
  event.preventDefault();
156
+ event.stopPropagation();
157
+
158
+ if (this.hasMultipleContainers) {
159
+ this.handleMultiContainerDragOver(event);
160
+ } else {
161
+ this.handleSingleContainerDragOver(event);
162
+ }
163
+ }
164
+
165
+ handleSingleContainerDragOver(event) {
79
166
  const container = event.target.closest(DRAGGABLE_CONTAINER);
167
+ if (container) {
168
+ container.classList.add("active_container");
169
+ }
170
+ }
171
+
172
+ handleMultiContainerDragOver(event) {
173
+ let container;
174
+ if (event.target.matches(DRAGGABLE_CONTAINER)) {
175
+ container = event.target;
176
+ } else {
177
+ container = event.target.closest(DRAGGABLE_CONTAINER);
178
+ }
80
179
 
81
180
  if (container) {
181
+ this.setState({ activeContainer: container.id });
82
182
  container.classList.add("active_container");
183
+
184
+ // If dragging over empty container or below last item
185
+ const lastItem = container.querySelector('.pb_draggable_item:last-child');
186
+ if (!lastItem || (lastItem && event.clientY > lastItem.getBoundingClientRect().bottom)) {
187
+ if (this.draggedItem && this.draggedItem.parentNode !== container) {
188
+ container.appendChild(this.draggedItem);
189
+ }
190
+ }
83
191
  }
84
192
  }
85
193
 
86
194
  handleDrop(event) {
87
195
  event.preventDefault();
88
- const container = event.target.closest(DRAGGABLE_CONTAINER);
196
+ event.stopPropagation();
197
+
198
+ let container;
199
+ if (event.target.matches(DRAGGABLE_CONTAINER)) {
200
+ container = event.target;
201
+ } else {
202
+ container = event.target.closest(DRAGGABLE_CONTAINER);
203
+ }
204
+
89
205
  if (!container || !this.draggedItem) return;
90
-
206
+
91
207
  container.classList.remove("active_container");
92
208
  this.draggedItem.style.opacity = '1';
93
-
209
+
210
+ // Handle empty containers
211
+ if (this.hasMultipleContainers && !container.querySelector('.pb_draggable_item')) {
212
+ container.appendChild(this.draggedItem);
213
+ }
214
+
94
215
  // Updated order of items as an array of item IDs
95
- const reorderedItems = Array.from(container.children)
96
- .filter(item => item.classList.contains("pb_draggable_item"))
97
- .map(item => item.id.replace("item_", ""));
98
-
216
+ const reorderedItems = Array.from(
217
+ this.element.querySelectorAll('.pb_draggable_item')
218
+ ).map(item => ({
219
+ id: item.id,
220
+ container: item.closest(DRAGGABLE_CONTAINER).id
221
+ }));
222
+
99
223
  // Store reordered items in a data attribute on the container
100
224
  container.setAttribute("data-reordered-items", JSON.stringify(reorderedItems));
101
-
225
+
102
226
  const customEvent = new CustomEvent('pb-draggable-reorder', {
103
227
  detail: {
104
228
  reorderedItems,
105
229
  containerId: container.id,
106
230
  }
107
231
  });
232
+
108
233
  this.element.dispatchEvent(customEvent);
109
-
234
+
235
+ this.setState({
236
+ items: reorderedItems,
237
+ isDragging: "",
238
+ activeContainer: ""
239
+ });
240
+
110
241
  this.draggedItem = null;
111
242
  this.draggedItemId = null;
112
243
  }
113
-
114
244
 
115
245
  handleDragEnd(event) {
116
246
  event.target.classList.remove("is_dragging");
117
247
  event.target.style.opacity = '1';
248
+
249
+ this.setState({
250
+ isDragging: "",
251
+ activeContainer: ""
252
+ });
253
+
118
254
  this.draggedItem = null;
119
255
  this.draggedItemId = null;
120
256
 
@@ -17,10 +17,11 @@ type DraggableContainerProps = {
17
17
  data?: { [key: string]: string };
18
18
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
19
19
  id?: string;
20
+ tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div' | 'tr' | 'th' | 'td' | 'thead' | 'col' | 'tbody',
20
21
  };
21
22
 
22
23
  const DraggableContainer = (props: DraggableContainerProps) => {
23
- const { aria = {}, children, className, container, data = {}, htmlOptions = {}, id } = props;
24
+ const { aria = {}, children, className, container, data = {}, htmlOptions = {}, id, tag="div" } = props;
24
25
 
25
26
  const { handleDragOver, handleDrop, activeContainer } = DraggableContext();
26
27
 
@@ -28,6 +29,8 @@ const DraggableContainer = (props: DraggableContainerProps) => {
28
29
  const dataProps = buildDataProps(data);
29
30
  const htmlProps = buildHtmlProps(htmlOptions);
30
31
 
32
+ const Tag: React.ReactElement | any = `${tag}`;
33
+
31
34
  const classes = classnames(
32
35
  buildCss("pb_draggable_container"),
33
36
  `${activeContainer === container ? "active" : ""}`,
@@ -36,18 +39,18 @@ const DraggableContainer = (props: DraggableContainerProps) => {
36
39
  );
37
40
 
38
41
  return (
39
- <div
42
+ <Tag
40
43
  {...ariaProps}
41
44
  {...dataProps}
42
45
  {...htmlProps}
43
46
  className={classes}
44
47
  id={id}
45
48
  key={container}
46
- onDragOver={(e) => handleDragOver(e, container)}
49
+ onDragOver={(e: Event) => handleDragOver(e, container)}
47
50
  onDrop={() => handleDrop(container)}
48
51
  >
49
52
  {children}
50
- </div>
53
+ </Tag>
51
54
  );
52
55
  };
53
56
 
@@ -18,10 +18,11 @@ type DraggableItemProps = {
18
18
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
19
19
  id?: string;
20
20
  dragId?: string;
21
+ tag?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div' | 'tr' | 'th' | 'td' | 'thead' | 'col' | 'tbody',
21
22
  };
22
23
 
23
24
  const DraggableItem = (props: DraggableItemProps) => {
24
- const { aria = {}, children, className, container, data = {}, htmlOptions = {}, id, dragId } = props;
25
+ const { aria = {}, children, className, container, data = {}, htmlOptions = {}, id, dragId, tag="div" } = props;
25
26
 
26
27
  const { isDragging, handleDragStart, handleDragEnter, handleDragEnd } =
27
28
  DraggableContext();
@@ -30,6 +31,8 @@ const DraggableItem = (props: DraggableItemProps) => {
30
31
  const dataProps = buildDataProps(data);
31
32
  const htmlProps = buildHtmlProps(htmlOptions);
32
33
 
34
+ const Tag: React.ReactElement | any = `${tag}`;
35
+
33
36
  const classes = classnames(
34
37
  buildCss("pb_draggable_item"),
35
38
  `${isDragging === dragId ? "is_dragging" : ""}`,
@@ -38,7 +41,7 @@ const DraggableItem = (props: DraggableItemProps) => {
38
41
  );
39
42
 
40
43
  return (
41
- <div
44
+ <Tag
42
45
  {...ariaProps}
43
46
  {...dataProps}
44
47
  {...htmlProps}
@@ -51,7 +54,7 @@ const DraggableItem = (props: DraggableItemProps) => {
51
54
  onDragStart={() => handleDragStart(dragId, container)}
52
55
  >
53
56
  {children}
54
- </div>
57
+ </Tag>
55
58
  );
56
59
  };
57
60