playbook_ui 14.19.0.pre.rc.2 → 14.20.0.pre.alpha.PLAY2127dropdowncloseonselectionpropreact8006

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 (252) 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 +11 -1
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +175 -16
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +56 -25
  6. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +23 -13
  7. data/app/pb_kits/playbook/pb_advanced_table/Utilities/VisibilityTree.ts +47 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +14 -10
  9. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +7 -2
  10. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
  11. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +9 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +5 -7
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.jsx +57 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.md +4 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.jsx +62 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.md +1 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.jsx +82 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.md +1 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +66 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +1 -1
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +5 -1
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows.jsx → _advanced_table_selectable_rows_no_subrows_react.jsx} +2 -2
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +3 -2
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +9 -3
  30. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +6 -2
  31. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +106 -0
  32. data/app/pb_kits/playbook/pb_advanced_table/index.js +370 -10
  33. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +1 -0
  34. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
  35. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
  36. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +9 -1
  37. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -3
  38. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +1 -2
  39. data/app/pb_kits/playbook/pb_avatar/_avatar.scss +4 -0
  40. data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +3 -0
  41. data/app/pb_kits/playbook/pb_avatar/avatar.html.erb +3 -3
  42. data/app/pb_kits/playbook/pb_avatar/avatar.rb +2 -0
  43. data/app/pb_kits/playbook/pb_avatar/avatar.test.js +18 -0
  44. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_grayscale.html.erb +5 -0
  45. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_grayscale.jsx +16 -0
  46. data/app/pb_kits/playbook/pb_avatar/docs/example.yml +2 -0
  47. data/app/pb_kits/playbook/pb_avatar/docs/index.js +1 -0
  48. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
  49. data/app/pb_kits/playbook/pb_card/card.rb +12 -0
  50. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -11
  51. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +10 -6
  52. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +2 -48
  53. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +1 -0
  54. data/app/pb_kits/playbook/pb_checkbox/index.js +56 -0
  55. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_error.html.erb +2 -2
  56. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.html.erb +22 -1
  57. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.html.erb +55 -0
  58. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line_rails.md +5 -0
  59. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_rails.md +5 -0
  60. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners.jsx +59 -0
  61. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners_react.md +1 -0
  62. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +2 -0
  63. data/app/pb_kits/playbook/pb_draggable/docs/index.js +2 -1
  64. data/app/pb_kits/playbook/pb_draggable/draggable_container.rb +11 -1
  65. data/app/pb_kits/playbook/pb_draggable/draggable_item.rb +11 -1
  66. data/app/pb_kits/playbook/pb_draggable/index.js +4 -2
  67. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +33 -5
  68. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +6 -1
  69. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +91 -35
  70. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +42 -0
  71. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +1 -0
  72. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +31 -0
  73. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +5 -0
  74. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +5 -2
  75. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +56 -0
  76. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +3 -0
  77. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +58 -0
  78. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +3 -0
  79. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +20 -0
  80. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +1 -0
  81. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +19 -0
  82. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +3 -0
  83. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +20 -0
  84. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +57 -0
  85. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +1 -0
  86. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +50 -0
  87. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +105 -0
  88. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +22 -0
  89. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +67 -0
  90. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.html.erb +28 -0
  91. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +17 -64
  92. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.html.erb +58 -0
  93. data/app/pb_kits/playbook/pb_dropdown/docs/{_dropdown_with_autocomplete_and_custom_display.jsx → _dropdown_with_autocomplete_with_subcomponents.jsx} +11 -25
  94. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.md +1 -0
  95. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +11 -0
  96. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.md +1 -1
  97. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +33 -2
  98. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.md +3 -1
  99. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_external_control.md +1 -0
  100. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.jsx +61 -0
  101. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.md +2 -0
  102. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.html.erb +52 -0
  103. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.md +2 -0
  104. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +20 -5
  105. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +8 -2
  106. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
  107. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +20 -2
  108. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +153 -3
  109. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +10 -0
  110. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +3 -0
  111. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +37 -6
  112. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +5 -1
  113. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +0 -6
  114. data/app/pb_kits/playbook/pb_dropdown/index.js +404 -17
  115. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +64 -11
  116. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +3 -4
  117. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +26 -18
  118. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +97 -20
  119. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
  120. data/app/pb_kits/playbook/pb_empty_state/_empty_state.scss +8 -1
  121. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_alignment.html.erb +27 -0
  122. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_default.html.erb +7 -0
  123. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_orientation.html.erb +12 -0
  124. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_size.html.erb +23 -0
  125. data/app/pb_kits/playbook/pb_empty_state/docs/example.yml +5 -1
  126. data/app/pb_kits/playbook/pb_empty_state/empty_state.html.erb +19 -0
  127. data/app/pb_kits/playbook/pb_empty_state/empty_state.rb +123 -0
  128. data/app/pb_kits/playbook/pb_file_upload/_file_upload.scss +13 -0
  129. data/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx +11 -1
  130. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.html.erb +1 -0
  131. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.jsx +41 -0
  132. data/app/pb_kits/playbook/pb_file_upload/docs/example.yml +2 -0
  133. data/app/pb_kits/playbook/pb_file_upload/docs/index.js +1 -0
  134. data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -0
  135. data/app/pb_kits/playbook/pb_file_upload/file_upload.rb +7 -1
  136. data/app/pb_kits/playbook/pb_file_upload/fileupload.test.js +18 -0
  137. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
  138. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
  139. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +2 -2
  140. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +19 -12
  141. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +13 -7
  142. data/app/pb_kits/playbook/pb_message/_message.tsx +3 -0
  143. data/app/pb_kits/playbook/pb_message/docs/_message_grayscale.html.erb +9 -0
  144. data/app/pb_kits/playbook/pb_message/docs/_message_grayscale.jsx +21 -0
  145. data/app/pb_kits/playbook/pb_message/docs/example.yml +2 -0
  146. data/app/pb_kits/playbook/pb_message/docs/index.js +1 -0
  147. data/app/pb_kits/playbook/pb_message/message.html.erb +2 -1
  148. data/app/pb_kits/playbook/pb_message/message.rb +1 -0
  149. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -2
  150. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.html.erb +11 -11
  151. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.jsx +11 -11
  152. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.html.erb +11 -11
  153. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +11 -11
  154. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +11 -11
  155. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +11 -11
  156. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.html.erb +11 -11
  157. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.jsx +11 -11
  158. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.html.erb +11 -11
  159. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.jsx +11 -11
  160. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.html.erb +11 -11
  161. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.jsx +11 -11
  162. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.html.erb +11 -11
  163. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.jsx +11 -11
  164. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.html.erb +11 -11
  165. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.jsx +11 -11
  166. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +11 -11
  167. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +11 -11
  168. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_react_hook.jsx +11 -11
  169. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.html.erb +11 -11
  170. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +11 -11
  171. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.jsx +11 -11
  172. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.html.erb +11 -11
  173. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.md +2 -0
  174. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.jsx +11 -11
  175. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.md +3 -1
  176. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.html.erb +22 -22
  177. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.jsx +22 -22
  178. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.html.erb +22 -22
  179. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.jsx +22 -22
  180. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +11 -11
  181. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +11 -11
  182. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_form.html.erb +11 -11
  183. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +2 -1
  184. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.jsx +1 -1
  185. data/app/pb_kits/playbook/pb_overlay/subcomponents/_overlay_token.tsx +5 -4
  186. data/app/pb_kits/playbook/pb_person/_person.tsx +12 -2
  187. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +9 -9
  188. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
  189. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
  190. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
  191. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
  192. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
  193. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
  194. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  195. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  196. data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +2 -2
  197. data/app/pb_kits/playbook/pb_select/_select.scss +10 -0
  198. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +12 -0
  199. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +31 -0
  200. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +1 -0
  201. data/app/pb_kits/playbook/pb_select/docs/_select_error.html.erb +1 -1
  202. data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
  203. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  204. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.jsx +7 -7
  205. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +3 -51
  206. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +5 -5
  207. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +4 -2
  208. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.html.erb +1 -1
  209. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.html.erb +5 -1
  210. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +73 -3
  211. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +8 -1
  212. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.jsx +23 -0
  213. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.md +1 -0
  214. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
  215. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  216. data/app/pb_kits/playbook/pb_user/_user.tsx +3 -0
  217. data/app/pb_kits/playbook/pb_user/docs/_user_grayscale.html.erb +6 -0
  218. data/app/pb_kits/playbook/pb_user/docs/_user_grayscale.jsx +16 -0
  219. data/app/pb_kits/playbook/pb_user/docs/example.yml +2 -0
  220. data/app/pb_kits/playbook/pb_user/docs/index.js +1 -0
  221. data/app/pb_kits/playbook/pb_user/user.html.erb +2 -1
  222. data/app/pb_kits/playbook/pb_user/user.rb +1 -0
  223. data/dist/chunks/_typeahead-CRW6dJbW.js +22 -0
  224. data/dist/chunks/_weekday_stacked-fRmhq4xQ.js +45 -0
  225. data/dist/chunks/lib-D5R1BjUn.js +29 -0
  226. data/dist/chunks/{pb_form_validation-BWjy4bFn.js → pb_form_validation-BZ2AVAi_.js} +1 -1
  227. data/dist/chunks/vendor.js +1 -1
  228. data/dist/menu.yml +7 -15
  229. data/dist/playbook-doc.js +2 -2
  230. data/dist/playbook-rails-react-bindings.js +1 -1
  231. data/dist/playbook-rails.js +1 -1
  232. data/dist/playbook.css +1 -1
  233. data/lib/playbook/kit_base.rb +3 -3
  234. data/lib/playbook/version.rb +2 -2
  235. metadata +86 -22
  236. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
  237. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.md +0 -1
  238. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_hook.jsx +0 -79
  239. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.scss +0 -3
  240. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.tsx +0 -72
  241. data/app/pb_kits/playbook/pb_gantt_chart/docs/_gantt_chart_default.jsx +0 -53
  242. data/app/pb_kits/playbook/pb_gantt_chart/docs/example.yml +0 -7
  243. data/app/pb_kits/playbook/pb_gantt_chart/docs/index.js +0 -1
  244. data/app/pb_kits/playbook/pb_gantt_chart/gantt_chart.test.jsx +0 -19
  245. data/dist/chunks/_typeahead-D8CsVBZO.js +0 -22
  246. data/dist/chunks/_weekday_stacked-D3oLTSkH.js +0 -45
  247. data/dist/chunks/lib-BmTAc7Nc.js +0 -29
  248. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_react.md → _advanced_table_selectable_rows.md} +0 -0
  249. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows.html.erb → _advanced_table_selectable_rows_no_subrows_rails.html.erb} +0 -0
  250. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.html.erb → _advanced_table_selectable_rows_rails.html.erb} +0 -0
  251. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_line.md → _draggable_drop_zones_line_react.md} +0 -0
  252. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_event_listeners.md → _draggable_event_listeners_rails.md} +0 -0
@@ -25,7 +25,7 @@ type DropdownOptionProps = {
25
25
  key?: string | number;
26
26
  option?: GenericObject;
27
27
  padding?: string;
28
- } & GlobalProps;
28
+ } & GlobalProps;
29
29
 
30
30
  const DropdownOption = (props: DropdownOptionProps) => {
31
31
  const {
@@ -45,27 +45,32 @@ const DropdownOption = (props: DropdownOptionProps) => {
45
45
  filterItem,
46
46
  focusedOptionIndex,
47
47
  handleOptionClick,
48
+ multiSelect,
48
49
  selected,
49
50
  } = useContext(DropdownContext);
50
51
 
51
- const isItemMatchingFilter = (option: GenericObject) => {
52
- const label = typeof option.label === 'string' ? option.label.toLowerCase() : option.label;
52
+ const isItemMatchingFilter = (option: GenericObject | undefined) => {
53
+ const label = typeof option?.label === 'string' ? option.label.toLowerCase() : option?.label;
53
54
  return String(label).toLowerCase().includes(filterItem.toLowerCase());
54
55
  }
55
56
 
56
- if (!isItemMatchingFilter(option)) {
57
+ // When multiSelect, then if an option is selected, remove from dropdown
58
+ const isSelected = Array.isArray(selected)
59
+ ? selected.some((item) => item.label === option?.label)
60
+ : (selected as GenericObject)?.label === option?.label;
61
+
62
+ if (!isItemMatchingFilter(option) || (multiSelect && isSelected)) {
57
63
  return null;
58
64
  }
65
+
59
66
  const isFocused =
60
67
  focusedOptionIndex >= 0 &&
61
- filteredOptions[focusedOptionIndex].label === option.label;
68
+ filteredOptions[focusedOptionIndex].label === option?.label;
69
+
62
70
  const focusedClass = isFocused && "focused";
63
71
 
64
- const selectedClass = `${
65
- selected?.label === option.label
66
- ? "selected"
67
- : "list"
68
- }`;
72
+ const selectedClass = isSelected ? "selected" : "list";
73
+
69
74
  const ariaProps = buildAriaProps(aria);
70
75
  const dataProps = buildDataProps(data);
71
76
  const htmlProps = buildHtmlProps(htmlOptions);
@@ -87,21 +92,24 @@ const DropdownOption = (props: DropdownOptionProps) => {
87
92
  className={classes}
88
93
  id={id}
89
94
  key={key}
90
- onClick= {() => handleOptionClick(option)}
95
+ onClick={(e) => {
96
+ e.stopPropagation();
97
+ handleOptionClick(option);
98
+ }}
91
99
  >
92
100
  <ListItem
93
101
  cursor="pointer"
94
102
  dark={dark}
95
- data-name={option.value}
96
- key={option.label}
103
+ data-name={option?.value}
104
+ key={option?.label}
97
105
  padding="none"
98
106
  >
99
- {children ?
107
+ {children ?
100
108
  <div className="dropdown_option_wrapper">{children}</div> :
101
- <Body dark={dark}
102
- text={option.label}
103
- />
104
- }
109
+ <Body dark={dark}
110
+ text={option?.label}
111
+ />
112
+ }
105
113
  </ListItem>
106
114
  </div>
107
115
  );
@@ -10,6 +10,7 @@ import { globalProps } from "../../utilities/globalProps";
10
10
  import { useHandleOnKeyDown } from "../hooks/useHandleOnKeydown";
11
11
 
12
12
  import DropdownContext from "../context";
13
+ import MultiSelectTriggerDisplay from "./MultiSelectTriggerDisplay";
13
14
 
14
15
  import Body from "../../pb_body/_body";
15
16
  import Icon from "../../pb_icon/_icon";
@@ -43,17 +44,20 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
43
44
 
44
45
  const {
45
46
  autocomplete,
47
+ closeOnSelection,
46
48
  filterItem,
49
+ handleBackspace,
47
50
  handleChange,
48
51
  handleWrapperClick,
49
52
  inputRef,
50
53
  inputWrapperRef,
51
54
  isDropDownClosed,
52
55
  isInputFocused,
56
+ multiSelect,
53
57
  selected,
58
+ setIsDropDownClosed,
54
59
  setIsInputFocused,
55
60
  toggleDropdown,
56
- triggerRef,
57
61
  } = useContext(DropdownContext);
58
62
 
59
63
  const handleKeyDown = useHandleOnKeyDown();
@@ -70,11 +74,21 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
70
74
  const triggerWrapperClasses = buildCss(
71
75
  "dropdown_trigger_wrapper",
72
76
  isInputFocused && "focus",
73
- !autocomplete && "select_only"
77
+ !autocomplete && !multiSelect && "select_only"
74
78
  );
75
79
 
80
+ const selectedArray = Array.isArray(selected)
81
+ ? selected
82
+ : selected && Object.keys(selected).length
83
+ ? [selected]
84
+ : [];
85
+
86
+ const joinedLabels = multiSelect
87
+ ? ""
88
+ : selectedArray.map((option) => option.label).join(", ");
89
+
76
90
  const customDisplayPlaceholder = selected?.label ? (
77
- <b>{selected.label}</b>
91
+ ""
78
92
  ) : autocomplete ? (
79
93
  ""
80
94
  ) : placeholder ? (
@@ -83,23 +97,37 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
83
97
  "Select..."
84
98
  );
85
99
 
86
- const defaultDisplayPlaceholder = selected?.label
87
- ? selected.label
100
+ const defaultDisplayPlaceholder = joinedLabels
101
+ ? joinedLabels
88
102
  : autocomplete
89
103
  ? ""
90
104
  : placeholder
91
105
  ? placeholder
92
106
  : "Select...";
93
107
 
108
+ // Click handler that respects closeOnSelection
109
+ const handleInputClick = (e: React.MouseEvent) => {
110
+ e.stopPropagation(); // keep the wrapper's handler from firing
111
+ if (isDropDownClosed) {
112
+ // Always open if closed
113
+ setIsDropDownClosed(false);
114
+ } else if (!closeOnSelection) {
115
+ // Keep open if closeOnSelection is false
116
+ return;
117
+ } else {
118
+ // Default behavior - toggle
119
+ toggleDropdown();
120
+ }
121
+ };
122
+
94
123
  return (
95
- <div {...ariaProps}
96
- {...dataProps}
124
+ <div {...ariaProps}
125
+ {...dataProps}
97
126
  {...htmlProps}
98
- className={classes}
127
+ className={classes}
99
128
  id={id}
100
129
  >
101
130
  {
102
- !triggerRef && (
103
131
  children ? (
104
132
  <div
105
133
  onClick={() => toggleDropdown()}
@@ -127,31 +155,65 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
127
155
  paddingX="sm"
128
156
  paddingY="xs"
129
157
  >
130
- <FlexItem>
131
- <Flex align="center">
158
+ <FlexItem fixedSize={multiSelect ? "85%" : ""}>
159
+ <Flex align="center"
160
+ wrap
161
+ >
132
162
  {customDisplay ? (
133
163
  <Flex align="center">
134
164
  {customDisplay}
135
- <Body dark={dark}
136
- paddingLeft={`${selected.label ? "xs" : "none"}`}
165
+ <Body dark={dark}
166
+ paddingLeft={`${joinedLabels ? "xs" : "none"}`}
137
167
  >
138
168
  {customDisplayPlaceholder}
139
169
  </Body>
140
170
  </Flex>
141
171
  ) : (
142
- <Body dark={dark}
143
- text={defaultDisplayPlaceholder}
144
- />
172
+ multiSelect ? (
173
+ <>
174
+ <MultiSelectTriggerDisplay
175
+ autocomplete={autocomplete}
176
+ dark={dark}
177
+ placeholder={placeholder}
178
+ selected={selectedArray}
179
+ />
180
+ {autocomplete && (
181
+ <input
182
+ className="dropdown_input"
183
+ onChange={handleChange}
184
+ onClick={handleInputClick}
185
+ onFocus={() => setIsInputFocused(true)}
186
+ onKeyDown={(e) => {
187
+ handleKeyDown(e);
188
+ e.stopPropagation(); //Fixes issue with keyboard accessibility
189
+ }}
190
+ placeholder={
191
+ joinedLabels
192
+ ? ""
193
+ : placeholder
194
+ ? placeholder
195
+ : "Select..."
196
+ }
197
+ ref={inputRef}
198
+ value={filterItem}
199
+ />
200
+ )}
201
+ </>
202
+ ) : (
203
+ <Body dark={dark}
204
+ text={defaultDisplayPlaceholder}
205
+ />
206
+ )
145
207
  )}
146
- {autocomplete && (
208
+ {autocomplete && !multiSelect && (
147
209
  <input
148
210
  className="dropdown_input"
149
211
  onChange={handleChange}
150
- onClick={() => toggleDropdown()}
212
+ onClick={handleInputClick}
151
213
  onFocus={() => setIsInputFocused(true)}
152
214
  onKeyDown={handleKeyDown}
153
215
  placeholder={
154
- selected.label
216
+ joinedLabels
155
217
  ? ""
156
218
  : placeholder
157
219
  ? placeholder
@@ -163,7 +225,9 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
163
225
  )}
164
226
  </Flex>
165
227
  </FlexItem>
228
+ <FlexItem>
166
229
  <Body
230
+ alignItems="center"
167
231
  dark={dark}
168
232
  display="flex"
169
233
  htmlOptions={{
@@ -171,6 +235,19 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
171
235
  }}
172
236
  key={`${isDropDownClosed ? "chevron-down" : "chevron-up"}`}
173
237
  >
238
+ {
239
+ selectedArray.length > 0 && (
240
+ <div onClick={(e)=>{e.stopPropagation();handleBackspace()}}>
241
+ <Icon
242
+ cursor="pointer"
243
+ dark={dark}
244
+ icon="times"
245
+ paddingRight="xs"
246
+ size="sm"
247
+ />
248
+ </div>
249
+ )
250
+ }
174
251
  <Icon
175
252
  cursor="pointer"
176
253
  dark={dark}
@@ -178,10 +255,10 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
178
255
  size="sm"
179
256
  />
180
257
  </Body>
258
+ </FlexItem>
181
259
  </Flex>
182
260
  </>
183
261
  )
184
- )
185
262
  }
186
263
  </div>
187
264
  );
@@ -0,0 +1,58 @@
1
+ import React, { useContext } from "react";
2
+ import FormPill from "../../pb_form_pill/_form_pill";
3
+ import Flex from "../../pb_flex/_flex";
4
+ import Body from "../../pb_body/_body";
5
+ import { GenericObject } from "../../types";
6
+ import DropdownContext
7
+ from "../context";
8
+ type MultiSelectTriggerDisplayProps = {
9
+ autocomplete?: boolean;
10
+ selected: GenericObject[];
11
+ placeholder?: string;
12
+ dark?: boolean;
13
+ };
14
+
15
+ const MultiSelectTriggerDisplay = ({
16
+ autocomplete,
17
+ selected,
18
+ placeholder,
19
+ dark = false,
20
+ }: MultiSelectTriggerDisplayProps) => {
21
+
22
+ const { setSelected, onSelect, formPillProps } = useContext(DropdownContext);
23
+
24
+ if (selected.length === 0) {
25
+ if (autocomplete) return null;
26
+ return (
27
+ <Body dark={dark}
28
+ text={placeholder ? placeholder : "Select..."}
29
+ />
30
+ )
31
+ }
32
+
33
+ const handleRemoveIconClick = (option: GenericObject) => {
34
+ setSelected((prev: GenericObject[]) => {
35
+ const next = prev.filter((item) => item.label !== option.label);
36
+ onSelect && onSelect(next);
37
+ return next;
38
+ });
39
+ }
40
+
41
+ return (
42
+ <Flex wrap>
43
+ {selected.map((option, i) => (
44
+ <FormPill
45
+ dark={dark}
46
+ key={i}
47
+ marginRight="xs"
48
+ onClick={(e)=>{e.stopPropagation();handleRemoveIconClick(option)}}
49
+ tabIndex={0}
50
+ text={option.label}
51
+ {...formPillProps}
52
+ />
53
+ ))}
54
+ </Flex>
55
+ );
56
+ };
57
+
58
+ export default MultiSelectTriggerDisplay;
@@ -1,4 +1,5 @@
1
1
  .pb_empty_state_kit {
2
+ max-width: 100%;
2
3
 
3
4
  .sm-state-vertical {
4
5
  width: 150px;
@@ -35,4 +36,10 @@
35
36
  }
36
37
  }
37
38
 
38
- }
39
+ &.dark {
40
+ [class*="pb_title_kit"],
41
+ [class*="pb_body_kit"],
42
+ [class*="pb_detail_kit"],
43
+ [class*="pb_button_kit_link"]:hover { color: $white; }
44
+ }
45
+ }
@@ -0,0 +1,27 @@
1
+ <%= pb_rails("flex", props: {align: "center", spacing: "evenly", wrap: true}) do %>
2
+ <%= pb_rails("empty_state", props: {
3
+ description: "Body text goes into detail with possible steps for user to take",
4
+ header: "Title Explains",
5
+ image: "default",
6
+ primary_button: "Next Action",
7
+ primary_button_url: "#primary_button_url",
8
+ alignment: "left",
9
+ }) %>
10
+
11
+ <%= pb_rails("empty_state", props: {
12
+ description: "Body text goes into detail with possible steps for user to take",
13
+ header: "Title Explains",
14
+ image: "default",
15
+ primary_button: "Next Action",
16
+ primary_button_url: "#primary_button_url",
17
+ }) %>
18
+
19
+ <%= pb_rails("empty_state", props: {
20
+ description: "Body text goes into detail with possible steps for user to take",
21
+ header: "Title Explains",
22
+ image: "default",
23
+ primary_button: "Next Action",
24
+ primary_button_url: "#primary_button_url",
25
+ alignment: "right",
26
+ }) %>
27
+ <% end %>
@@ -0,0 +1,7 @@
1
+ <%= pb_rails("flex", props: {align: "center", justify: "center"}) do %>
2
+ <%= pb_rails("empty_state", props: {
3
+ description: "Body text goes into detail with possible steps for user to take",
4
+ header: "Title Explains",
5
+ image: "default",
6
+ }) %>
7
+ <% end %>
@@ -0,0 +1,12 @@
1
+ <%= pb_rails("flex", props: {align: "center", justify: "center", wrap: true}) do %>
2
+ <%= pb_rails("empty_state", props: {
3
+ description: "Body text goes into detail with possible steps for user to take",
4
+ header: "Title Explains",
5
+ image: "default",
6
+ orientation:"horizontal",
7
+ alignment: "left",
8
+ size: "lg",
9
+ primary_button: "Next Action",
10
+ primary_button_url: "#primary_button_url",
11
+ }) %>
12
+ <% end %>
@@ -0,0 +1,23 @@
1
+ <%= pb_rails("flex", props: {align: "center", spacing: "evenly", wrap: true}) do %>
2
+ <%= pb_rails("empty_state", props: {
3
+ description: "Body text goes into detail with possible steps for user to take",
4
+ header: "Title Explains",
5
+ image: "default",
6
+ primary_button: "Next Action",
7
+ primary_button_url: "#primary_button_url",
8
+ link_button: "Alt Action",
9
+ link_button_url: "#link_button_url",
10
+ size: "sm",
11
+ }) %>
12
+
13
+ <%= pb_rails("empty_state", props: {
14
+ description: "Body text goes into detail with possible steps for user to take",
15
+ header: "Title Explains",
16
+ image: "default",
17
+ primary_button: "Next Action",
18
+ primary_button_url: "#primary_button_url",
19
+ link_button: "Alt Action",
20
+ link_button_url: "#link_button_url",
21
+ size: "lg",
22
+ }) %>
23
+ <% end %>
@@ -1,5 +1,9 @@
1
1
  examples:
2
-
2
+ rails:
3
+ - empty_state_default: Default
4
+ - empty_state_size: Size
5
+ - empty_state_orientation: Orientation
6
+ - empty_state_alignment: Alignment
3
7
 
4
8
  react:
5
9
  - empty_state_default: Default
@@ -0,0 +1,19 @@
1
+ <%= pb_content_tag do %>
2
+ <%= pb_rails("flex", props: { align: flex_align, orientation: config[:flex_direction], padding_left: padding_size, padding_right: padding_size, vertical: "center", classname: config[:scss_class], max_width: "100%" }) do %>
3
+ <%= pb_rails("image", props: { url: image == "default" ? default_image_data_uri : image, alt: "Empty State Image", html_options: { width: config[:image_width], height: "auto", alignment: "start" } }) %>
4
+ <%= pb_rails("flex/flex_item") do %>
5
+ <%= pb_rails("title", props: { text: object.header, size: config[:title_size], padding_bottom: config[:title_padding], text_align: alignment }) %>
6
+ <% if size == "sm" %>
7
+ <%= pb_rails("detail", props: { text: object.description, padding_bottom: config[:description_pad], text_align: alignment }) %>
8
+ <% else %>
9
+ <%= pb_rails("body", props: { text: object.description, padding_bottom: config[:description_pad], text_align: alignment }) %>
10
+ <% end %>
11
+ <% if primary_button.present? %>
12
+ <%= pb_rails("button", props: { text: primary_button, variant: "primary", width: "100%", size: config[:button_size], link: primary_button_url, margin_bottom: config[:button_margin] }) %>
13
+ <% end %>
14
+ <% if link_button.present? %>
15
+ <%= pb_rails("button", props: { text: link_button, variant: "link", size: config[:button_size], link: link_button_url, width: "100%" }) %>
16
+ <% end %>
17
+ <% end %>
18
+ <% end %>
19
+ <% end %>
@@ -0,0 +1,123 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbEmptyState
5
+ class EmptyState < Playbook::KitBase
6
+ prop :alignment, type: Playbook::Props::Enum,
7
+ values: %w[center left right],
8
+ default: "center"
9
+ prop :description
10
+ prop :header
11
+ prop :image
12
+ prop :link_button
13
+ prop :link_button_url
14
+ prop :orientation, type: Playbook::Props::Enum,
15
+ values: %w[horizontal vertical],
16
+ default: "vertical"
17
+ prop :primary_button
18
+ prop :primary_button_url
19
+ prop :size, type: Playbook::Props::Enum,
20
+ values: %w[sm md lg],
21
+ default: "md"
22
+
23
+ SIZE_CONFIGS = {
24
+ sm: {
25
+ vertical: {
26
+ image_width: "100px",
27
+ title_size: 4,
28
+ title_padding: "xxs",
29
+ description_pad: "sm",
30
+ button_size: "sm",
31
+ button_margin: "xs",
32
+ scss_class: "sm-state-vertical",
33
+ flex_direction: "column",
34
+ },
35
+ horizontal: {
36
+ image_width: "100px",
37
+ title_size: 4,
38
+ title_padding: "xxs",
39
+ description_pad: "sm",
40
+ button_size: "sm",
41
+ button_margin: "xs",
42
+ scss_class: "sm-state-horizontal",
43
+ flex_direction: "row",
44
+ },
45
+ },
46
+ md: {
47
+ vertical: {
48
+ image_width: "140px",
49
+ title_size: 3,
50
+ title_padding: "xs",
51
+ description_pad: "md",
52
+ button_size: "md",
53
+ button_margin: "sm",
54
+ scss_class: "md-state-vertical",
55
+ flex_direction: "column",
56
+ },
57
+ horizontal: {
58
+ image_width: "140px",
59
+ title_size: 3,
60
+ title_padding: "xs",
61
+ description_pad: "md",
62
+ button_size: "md",
63
+ button_margin: "sm",
64
+ scss_class: "md-state-horizontal",
65
+ flex_direction: "row",
66
+ },
67
+ },
68
+ lg: {
69
+ vertical: {
70
+ image_width: "100%",
71
+ title_size: 1,
72
+ title_padding: "sm",
73
+ description_pad: "lg",
74
+ button_size: "md",
75
+ button_margin: "md",
76
+ scss_class: "lg-state-vertical",
77
+ flex_direction: "column",
78
+ },
79
+ horizontal: {
80
+ image_width: "100%",
81
+ title_size: 2,
82
+ title_padding: "sm",
83
+ description_pad: "lg",
84
+ button_size: "md",
85
+ button_margin: "md",
86
+ scss_class: "lg-state-horizontal",
87
+ flex_direction: "row",
88
+ },
89
+ },
90
+ }.freeze
91
+
92
+ def classname
93
+ generate_classname("pb_empty_state_kit")
94
+ end
95
+
96
+ def config
97
+ SIZE_CONFIGS[size.to_sym][orientation.to_sym]
98
+ end
99
+
100
+ def default_image_data_uri
101
+ svg_path = __dir__.then { |d| File.join(d, "docs", "default_image", "computer_fly_no_branding.svg") }
102
+ svg = File.read(svg_path)
103
+ encoded = ERB::Util.url_encode(svg)
104
+ "data:image/svg+xml,#{encoded}"
105
+ end
106
+
107
+ def padding_size
108
+ size == "sm" ? "xs" : "xl"
109
+ end
110
+
111
+ def flex_align
112
+ case alignment
113
+ when "left"
114
+ "start"
115
+ when "right"
116
+ "end"
117
+ else
118
+ "center"
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -9,10 +9,23 @@
9
9
  border: none;
10
10
  width: 0;
11
11
  }
12
+ &.error {
13
+ [class^='pb_card_kit'] {
14
+ border-color: $error;
15
+ }
16
+ [class^='pb_body_kit'][status="negative"] {
17
+ margin-top: $space_xs;
18
+ }
19
+ }
12
20
  }
13
21
 
14
22
  .dark [class*='pb_file_upload_kit'] {
15
23
  [class*='pb_card_kit'] {
16
24
  border: 1px $text_dk_lighter dashed;
17
25
  }
26
+ &.error {
27
+ [class^='pb_card_kit'] {
28
+ border-color: $error_dark;
29
+ }
30
+ }
18
31
  }
@@ -22,6 +22,7 @@ type FileUploadProps = {
22
22
  maxSize?: number,
23
23
  onFilesAccepted: Callback<File, File>,
24
24
  onFilesRejected: (error: string, files: readonly FileRejection[]) => void,
25
+ error?: string,
25
26
  }
26
27
 
27
28
  const getFormattedFileSize = (fileSize: number): string => {
@@ -36,6 +37,7 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => {
36
37
  customMessage,
37
38
  dark = false,
38
39
  data = {},
40
+ error,
39
41
  htmlOptions = {},
40
42
  maxSize,
41
43
  onFilesAccepted = noop,
@@ -100,7 +102,7 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => {
100
102
 
101
103
  return (
102
104
  <div
103
- className={classnames(buildCss('pb_file_upload_kit'), globalProps(props), className)}
105
+ className={classnames(buildCss('pb_file_upload_kit'), { 'error': error }, globalProps(props), className)}
104
106
  {...dataProps}
105
107
  {...htmlProps}
106
108
  {...getRootProps()}
@@ -118,6 +120,14 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => {
118
120
  }
119
121
  </Body>
120
122
  </Card>
123
+ {error && (
124
+ <Body
125
+ dark={dark}
126
+ marginTop="xxs"
127
+ status="negative"
128
+ text={error}
129
+ />
130
+ )}
121
131
  </div>
122
132
  )
123
133
  }
@@ -0,0 +1 @@
1
+ <%= pb_rails("file_upload", props: {id: "error", error: raw(pb_rails("icon", props: { icon: "warning" }) + " Please upload a valid file")}) %>