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

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 (250) 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 +92 -5
  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/Context/AdvancedTableContext.tsx +58 -2
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +34 -15
  9. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +7 -3
  10. data/app/pb_kits/playbook/pb_advanced_table/Utilities/VisibilityTree.ts +47 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +11 -10
  12. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +13 -4
  13. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
  14. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +9 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +61 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +5 -7
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.jsx +57 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.md +4 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.jsx +62 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.md +1 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.jsx +82 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.md +1 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +66 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +1 -1
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +57 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
  30. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
  31. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
  32. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +5 -1
  33. 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
  34. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +3 -2
  35. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +10 -3
  36. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +7 -2
  37. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +106 -0
  38. data/app/pb_kits/playbook/pb_advanced_table/index.js +370 -10
  39. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +1 -0
  40. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
  41. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
  42. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +9 -1
  43. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -3
  44. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +1 -2
  45. data/app/pb_kits/playbook/pb_avatar/_avatar.scss +4 -0
  46. data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +3 -0
  47. data/app/pb_kits/playbook/pb_avatar/avatar.html.erb +3 -3
  48. data/app/pb_kits/playbook/pb_avatar/avatar.rb +2 -0
  49. data/app/pb_kits/playbook/pb_avatar/avatar.test.js +18 -0
  50. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_grayscale.html.erb +5 -0
  51. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_grayscale.jsx +16 -0
  52. data/app/pb_kits/playbook/pb_avatar/docs/example.yml +2 -0
  53. data/app/pb_kits/playbook/pb_avatar/docs/index.js +1 -0
  54. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -1
  55. data/app/pb_kits/playbook/pb_card/card.rb +12 -0
  56. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_error.html.erb +2 -2
  57. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones.html.erb +22 -1
  58. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line.html.erb +55 -0
  59. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_line_rails.md +5 -0
  60. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_drop_zones_rails.md +5 -0
  61. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners.jsx +59 -0
  62. data/app/pb_kits/playbook/pb_draggable/docs/_draggable_event_listeners_react.md +1 -0
  63. data/app/pb_kits/playbook/pb_draggable/docs/example.yml +2 -0
  64. data/app/pb_kits/playbook/pb_draggable/docs/index.js +2 -1
  65. data/app/pb_kits/playbook/pb_draggable/draggable_container.rb +11 -1
  66. data/app/pb_kits/playbook/pb_draggable/draggable_item.rb +11 -1
  67. data/app/pb_kits/playbook/pb_draggable/index.js +4 -2
  68. data/app/pb_kits/playbook/pb_draggable/subcomponents/DraggableItem.tsx +33 -5
  69. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +6 -1
  70. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +82 -35
  71. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +31 -0
  72. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +5 -0
  73. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +5 -2
  74. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +56 -0
  75. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +3 -0
  76. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +58 -0
  77. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +3 -0
  78. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +20 -0
  79. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +1 -0
  80. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +19 -0
  81. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +3 -0
  82. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +20 -0
  83. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +57 -0
  84. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +1 -0
  85. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +50 -0
  86. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +105 -0
  87. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +22 -0
  88. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +67 -0
  89. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.html.erb +28 -0
  90. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +17 -64
  91. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.html.erb +58 -0
  92. data/app/pb_kits/playbook/pb_dropdown/docs/{_dropdown_with_autocomplete_and_custom_display.jsx → _dropdown_with_autocomplete_with_subcomponents.jsx} +11 -25
  93. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.md +1 -0
  94. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +11 -0
  95. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.md +1 -1
  96. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +33 -2
  97. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.md +3 -1
  98. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_external_control.md +1 -0
  99. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.jsx +61 -0
  100. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.md +2 -0
  101. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.html.erb +52 -0
  102. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.md +2 -0
  103. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +18 -5
  104. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +7 -2
  105. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
  106. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +20 -2
  107. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +153 -3
  108. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.html.erb +10 -0
  109. data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +3 -0
  110. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +37 -6
  111. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +5 -1
  112. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +0 -6
  113. data/app/pb_kits/playbook/pb_dropdown/index.js +380 -17
  114. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +64 -11
  115. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +3 -4
  116. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +16 -12
  117. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +83 -17
  118. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
  119. data/app/pb_kits/playbook/pb_empty_state/_empty_state.scss +8 -1
  120. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_alignment.html.erb +27 -0
  121. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_default.html.erb +7 -0
  122. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_orientation.html.erb +12 -0
  123. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_size.html.erb +23 -0
  124. data/app/pb_kits/playbook/pb_empty_state/docs/example.yml +5 -1
  125. data/app/pb_kits/playbook/pb_empty_state/empty_state.html.erb +19 -0
  126. data/app/pb_kits/playbook/pb_empty_state/empty_state.rb +123 -0
  127. data/app/pb_kits/playbook/pb_file_upload/_file_upload.scss +13 -0
  128. data/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx +11 -1
  129. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.html.erb +1 -0
  130. data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.jsx +41 -0
  131. data/app/pb_kits/playbook/pb_file_upload/docs/example.yml +2 -0
  132. data/app/pb_kits/playbook/pb_file_upload/docs/index.js +1 -0
  133. data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -0
  134. data/app/pb_kits/playbook/pb_file_upload/file_upload.rb +7 -1
  135. data/app/pb_kits/playbook/pb_file_upload/fileupload.test.js +18 -0
  136. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
  137. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
  138. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +2 -2
  139. data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +19 -12
  140. data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +13 -7
  141. data/app/pb_kits/playbook/pb_message/_message.tsx +3 -0
  142. data/app/pb_kits/playbook/pb_message/docs/_message_grayscale.html.erb +9 -0
  143. data/app/pb_kits/playbook/pb_message/docs/_message_grayscale.jsx +21 -0
  144. data/app/pb_kits/playbook/pb_message/docs/example.yml +2 -0
  145. data/app/pb_kits/playbook/pb_message/docs/index.js +1 -0
  146. data/app/pb_kits/playbook/pb_message/message.html.erb +2 -1
  147. data/app/pb_kits/playbook/pb_message/message.rb +1 -0
  148. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -2
  149. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.html.erb +11 -11
  150. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.jsx +11 -11
  151. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.html.erb +11 -11
  152. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +11 -11
  153. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +11 -11
  154. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +11 -11
  155. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.html.erb +11 -11
  156. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.jsx +11 -11
  157. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.html.erb +11 -11
  158. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.jsx +11 -11
  159. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.html.erb +11 -11
  160. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.jsx +11 -11
  161. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.html.erb +11 -11
  162. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.jsx +11 -11
  163. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.html.erb +11 -11
  164. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.jsx +11 -11
  165. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +11 -11
  166. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +11 -11
  167. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_react_hook.jsx +11 -11
  168. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.html.erb +11 -11
  169. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +11 -11
  170. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.jsx +11 -11
  171. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.html.erb +11 -11
  172. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.md +2 -0
  173. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.jsx +11 -11
  174. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.md +3 -1
  175. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.html.erb +22 -22
  176. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.jsx +22 -22
  177. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.html.erb +22 -22
  178. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.jsx +22 -22
  179. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +11 -11
  180. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +11 -11
  181. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_form.html.erb +11 -11
  182. data/app/pb_kits/playbook/pb_overlay/_overlay.scss +2 -1
  183. data/app/pb_kits/playbook/pb_overlay/docs/_overlay_vertical_dynamic_multi_directional.jsx +1 -1
  184. data/app/pb_kits/playbook/pb_overlay/subcomponents/_overlay_token.tsx +5 -4
  185. data/app/pb_kits/playbook/pb_person/_person.tsx +12 -2
  186. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +9 -9
  187. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
  188. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
  189. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
  190. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
  191. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
  192. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
  193. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  194. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  195. data/app/pb_kits/playbook/pb_section_separator/_section_separator.tsx +2 -2
  196. data/app/pb_kits/playbook/pb_select/_select.scss +10 -0
  197. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +12 -0
  198. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +31 -0
  199. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +1 -0
  200. data/app/pb_kits/playbook/pb_select/docs/_select_error.html.erb +1 -1
  201. data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
  202. data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
  203. data/app/pb_kits/playbook/pb_table/docs/_table_with_collapsible_with_custom_click.jsx +7 -7
  204. data/app/pb_kits/playbook/pb_table/subcomponents/_table_row.tsx +5 -5
  205. data/app/pb_kits/playbook/pb_text_input/_text_input.scss +4 -2
  206. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.html.erb +1 -1
  207. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.html.erb +5 -1
  208. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +73 -3
  209. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +8 -1
  210. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.jsx +23 -0
  211. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.md +1 -0
  212. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
  213. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  214. data/app/pb_kits/playbook/pb_user/_user.tsx +3 -0
  215. data/app/pb_kits/playbook/pb_user/docs/_user_grayscale.html.erb +6 -0
  216. data/app/pb_kits/playbook/pb_user/docs/_user_grayscale.jsx +16 -0
  217. data/app/pb_kits/playbook/pb_user/docs/example.yml +2 -0
  218. data/app/pb_kits/playbook/pb_user/docs/index.js +1 -0
  219. data/app/pb_kits/playbook/pb_user/user.html.erb +2 -1
  220. data/app/pb_kits/playbook/pb_user/user.rb +1 -0
  221. data/dist/chunks/_typeahead-CRW6dJbW.js +22 -0
  222. data/dist/chunks/_weekday_stacked-yWpUc_c0.js +45 -0
  223. data/dist/chunks/lib-D5R1BjUn.js +29 -0
  224. data/dist/chunks/{pb_form_validation-BWjy4bFn.js → pb_form_validation-BZ2AVAi_.js} +1 -1
  225. data/dist/chunks/vendor.js +1 -1
  226. data/dist/menu.yml +6 -14
  227. data/dist/playbook-doc.js +2 -2
  228. data/dist/playbook-rails-react-bindings.js +1 -1
  229. data/dist/playbook-rails.js +1 -1
  230. data/dist/playbook.css +1 -1
  231. data/lib/playbook/kit_base.rb +3 -3
  232. data/lib/playbook/version.rb +2 -2
  233. metadata +84 -22
  234. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
  235. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.md +0 -1
  236. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_hook.jsx +0 -79
  237. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.scss +0 -3
  238. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.tsx +0 -72
  239. data/app/pb_kits/playbook/pb_gantt_chart/docs/_gantt_chart_default.jsx +0 -53
  240. data/app/pb_kits/playbook/pb_gantt_chart/docs/example.yml +0 -7
  241. data/app/pb_kits/playbook/pb_gantt_chart/docs/index.js +0 -1
  242. data/app/pb_kits/playbook/pb_gantt_chart/gantt_chart.test.jsx +0 -19
  243. data/dist/chunks/_typeahead-D8CsVBZO.js +0 -22
  244. data/dist/chunks/_weekday_stacked-D3oLTSkH.js +0 -45
  245. data/dist/chunks/lib-BmTAc7Nc.js +0 -29
  246. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_react.md → _advanced_table_selectable_rows.md} +0 -0
  247. /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
  248. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.html.erb → _advanced_table_selectable_rows_rails.html.erb} +0 -0
  249. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_drop_zones_line.md → _draggable_drop_zones_line_react.md} +0 -0
  250. /data/app/pb_kits/playbook/pb_draggable/docs/{_draggable_event_listeners.md → _draggable_event_listeners_rails.md} +0 -0
@@ -11,6 +11,9 @@ const CUSTOM_DISPLAY_SELECTOR = "[data-dropdown-custom-trigger]";
11
11
  const DROPDOWN_TRIGGER_DISPLAY = "#dropdown_trigger_display";
12
12
  const DROPDOWN_PLACEHOLDER = "[data-dropdown-placeholder]";
13
13
  const DROPDOWN_INPUT = "#dropdown-selected-option";
14
+ const SEARCH_INPUT_SELECTOR = "[data-dropdown-autocomplete]";
15
+ const SEARCH_BAR_SELECTOR = "[data-dropdown-search]";
16
+ const CLEAR_ICON_SELECTOR = "#dropdown_clear_icon";
14
17
 
15
18
  export default class PbDropdown extends PbEnhancedElement {
16
19
  static get selector() {
@@ -18,16 +21,45 @@ export default class PbDropdown extends PbEnhancedElement {
18
21
  }
19
22
 
20
23
  get target() {
21
- return this.element.parentNode.querySelector(CONTAINER_SELECTOR);
24
+ return this.element.querySelector(CONTAINER_SELECTOR);
22
25
  }
23
26
 
27
+ selectedOptions = new Set();
28
+ clearBtn = null;
29
+
24
30
  connect() {
25
31
  this.keyboardHandler = new PbDropdownKeyboard(this);
32
+ this.isMultiSelect = this.element.dataset.pbDropdownMultiSelect === "true";
33
+ this.formPillProps = this.element.dataset.formPillProps
34
+ ? JSON.parse(this.element.dataset.formPillProps)
35
+ : {};
26
36
  this.setDefaultValue();
27
37
  this.bindEventListeners();
38
+ this.bindSearchInput();
28
39
  this.updateArrowDisplay(false);
29
40
  this.handleFormValidation();
30
41
  this.handleFormReset();
42
+ this.bindSearchBar();
43
+ this.updatePills();
44
+
45
+ this.clearBtn = this.element.querySelector(CLEAR_ICON_SELECTOR);
46
+ if (this.clearBtn) {
47
+ this.clearBtn.style.display = "none";
48
+ this.clearBtn.addEventListener("click", (e) => {
49
+ e.stopPropagation();
50
+ this.clearSelection();
51
+ });
52
+ }
53
+ this.updateClearButton();
54
+ }
55
+
56
+ updateClearButton() {
57
+ if (!this.clearBtn) return;
58
+ const hasSelection = this.isMultiSelect
59
+ ? this.selectedOptions.size > 0
60
+ : Boolean(this.element.querySelector(DROPDOWN_INPUT).value);
61
+
62
+ this.clearBtn.style.display = hasSelection ? "" : "none";
31
63
  }
32
64
 
33
65
  bindEventListeners() {
@@ -45,20 +77,93 @@ export default class PbDropdown extends PbEnhancedElement {
45
77
  );
46
78
  }
47
79
 
80
+ bindSearchBar() {
81
+ this.searchBar = this.element.querySelector(SEARCH_BAR_SELECTOR);
82
+ if (!this.searchBar) return;
83
+
84
+ this.searchBar.addEventListener("input", (e) =>
85
+ this.handleSearch(e.target.value)
86
+ );
87
+ }
88
+
89
+ bindSearchInput() {
90
+ this.searchInput = this.element.querySelector(SEARCH_INPUT_SELECTOR);
91
+ if (!this.searchInput) return;
92
+
93
+ // Focus the input when anyone clicks the wrapper
94
+ this.element
95
+ .querySelector(TRIGGER_SELECTOR)
96
+ ?.addEventListener("click", () => this.searchInput.focus());
97
+
98
+ // Live filter
99
+ this.searchInput.addEventListener("input", (e) =>
100
+ this.handleSearch(e.target.value)
101
+ );
102
+ }
103
+
104
+ adjustDropdownHeight() {
105
+ if (this.target.classList.contains("open")) {
106
+ const el = this.target;
107
+ el.style.height = "auto";
108
+ requestAnimationFrame(() => {
109
+ const newHeight = el.scrollHeight + "px";
110
+ el.offsetHeight; // force reflow
111
+ el.style.height = newHeight;
112
+ });
113
+ }
114
+ }
115
+
116
+ handleSearch(term = "") {
117
+ const lcTerm = term.toLowerCase();
118
+ this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
119
+ //make it so that if the option is selected, it will not show up in the search results
120
+ if (this.isMultiSelect && this.selectedOptions.has(opt.dataset.dropdownOptionLabel)) {
121
+ opt.style.display = "none";
122
+ return;
123
+ }
124
+ const label = JSON.parse(opt.dataset.dropdownOptionLabel)
125
+ .label.toString()
126
+ .toLowerCase();
127
+
128
+ // hide or show option
129
+ const match = label.includes(lcTerm);
130
+ opt.style.display = match ? "" : "none";
131
+ });
132
+
133
+ this.adjustDropdownHeight();
134
+ }
135
+
48
136
  handleOptionClick(event) {
49
137
  const option = event.target.closest(OPTION_SELECTOR);
50
138
  const hiddenInput = this.element.querySelector(DROPDOWN_INPUT);
51
139
 
52
140
  if (option) {
53
141
  const value = option.dataset.dropdownOptionLabel;
54
- hiddenInput.value = JSON.parse(value).id;
55
- this.clearFormValidation(hiddenInput);
142
+ if (this.isMultiSelect) {
143
+ const alreadySelected = this.selectedOptions.has(value);
144
+ if (alreadySelected) {
145
+ this.selectedOptions.delete(value);
146
+ } else {
147
+ this.selectedOptions.add(value);
148
+ }
149
+ this.updatePills();
150
+ this.syncHiddenInputs();
151
+ if (this.searchInput && this.isMultiSelect) {
152
+ this.searchInput.value = "";
153
+ this.handleBackspaceClear();
154
+ }
155
+ } else {
156
+ hiddenInput.value = JSON.parse(value).id;
157
+ }
56
158
 
159
+ this.clearFormValidation(hiddenInput);
57
160
  this.onOptionSelected(value, option);
161
+ this.updateClearButton();
58
162
  }
59
163
  }
60
164
 
61
165
  handleDocumentClick(event) {
166
+ if (event.target.closest(SEARCH_BAR_SELECTOR)) return;
62
167
  if (this.isClickOutside(event) && this.target.classList.contains("open")) {
63
168
  this.hideElement(this.target);
64
169
  this.updateArrowDisplay(false);
@@ -85,20 +190,56 @@ export default class PbDropdown extends PbEnhancedElement {
85
190
  }
86
191
  }
87
192
 
193
+ emitSelectionChange() {
194
+ let detail;
195
+
196
+ if (this.isMultiSelect) {
197
+ detail = Array.from(this.selectedOptions).map(JSON.parse);
198
+ } else {
199
+ const hiddenInput = this.element.querySelector(DROPDOWN_INPUT);
200
+ detail = hiddenInput.value
201
+ ? JSON.parse(
202
+ this.element.querySelector(
203
+ OPTION_SELECTOR +
204
+ `[data-dropdown-option-label*='"id":"${hiddenInput.value}"']`
205
+ ).dataset.dropdownOptionLabel
206
+ )
207
+ : null;
208
+ }
209
+ this.element.setAttribute("data-option-selected", JSON.stringify(detail));
210
+ this.element.dispatchEvent(
211
+ new CustomEvent("pb:dropdown:selected", {
212
+ detail,
213
+ bubbles: true,
214
+ })
215
+ );
216
+ }
217
+
88
218
  onOptionSelected(value, selectedOption) {
89
219
  const triggerElement = this.element.querySelector(DROPDOWN_TRIGGER_DISPLAY);
90
220
  const customDisplayElement = this.element.querySelector(
91
221
  "#dropdown_trigger_custom_display"
92
222
  );
223
+
93
224
  if (triggerElement) {
94
- const selectedLabel = JSON.parse(value).label;
95
- triggerElement.textContent = selectedLabel;
225
+ if (!this.isMultiSelect) {
226
+ const selectedLabel = JSON.parse(value).label;
227
+ triggerElement.textContent = selectedLabel;
228
+ this.emitSelectionChange();
229
+ }
96
230
  if (customDisplayElement) {
231
+ triggerElement.textContent = "";
97
232
  customDisplayElement.style.display = "block";
98
233
  customDisplayElement.style.paddingRight = "8px";
99
234
  }
100
235
  }
101
236
 
237
+ const autocompleteInput = this.element.querySelector(SEARCH_INPUT_SELECTOR);
238
+ if (autocompleteInput && !this.isMultiSelect) {
239
+ autocompleteInput.value = JSON.parse(value).label;
240
+ this.emitSelectionChange();
241
+ }
242
+
102
243
  const customTrigger = this.element.querySelector(CUSTOM_DISPLAY_SELECTOR);
103
244
  if (customTrigger) {
104
245
  if (this.target.classList.contains("open")) {
@@ -108,10 +249,24 @@ export default class PbDropdown extends PbEnhancedElement {
108
249
  }
109
250
 
110
251
  const options = this.element.querySelectorAll(OPTION_SELECTOR);
111
- options.forEach((option) => {
112
- option.classList.remove("pb_dropdown_option_selected");
113
- });
114
- selectedOption.classList.add("pb_dropdown_option_selected");
252
+ if (this.isMultiSelect) {
253
+ this.emitSelectionChange();
254
+ Array.from(this.selectedOptions).map((option) => {
255
+ if (
256
+ JSON.parse(option).id ===
257
+ JSON.parse(selectedOption.dataset.dropdownOptionLabel).id
258
+ ) {
259
+ selectedOption.style.display = "none";
260
+ this.adjustDropdownHeight();
261
+ }
262
+ });
263
+ } else {
264
+ options.forEach((option) => {
265
+ option.classList.remove("pb_dropdown_option_selected");
266
+ });
267
+ selectedOption.classList.add("pb_dropdown_option_selected");
268
+ }
269
+ this.updateClearButton();
115
270
  }
116
271
 
117
272
  showElement(elem) {
@@ -185,21 +340,66 @@ export default class PbDropdown extends PbEnhancedElement {
185
340
  errorLabelElement.remove();
186
341
  }
187
342
  }
343
+ if (this.isMultiSelect) {
344
+ if (this.selectedOptions.size > 0) {
345
+ const dropdownWrapperElement = input.closest(".dropdown_wrapper");
346
+ dropdownWrapperElement.classList.remove("error");
347
+ const errorLabelElement = dropdownWrapperElement.querySelector(
348
+ ".pb_body_kit_negative"
349
+ );
350
+ if (errorLabelElement) {
351
+ errorLabelElement.remove();
352
+ }
353
+ }
354
+ }
188
355
  }
189
356
 
190
357
  setDefaultValue() {
191
358
  const hiddenInput = this.element.querySelector(DROPDOWN_INPUT);
192
- const options = this.element.querySelectorAll(OPTION_SELECTOR);
193
-
359
+ const optionEls = Array.from(
360
+ this.element.querySelectorAll(OPTION_SELECTOR)
361
+ );
194
362
  const defaultValue = hiddenInput.dataset.defaultValue || "";
195
- hiddenInput.value = defaultValue;
363
+ if (!defaultValue) return;
364
+
365
+ if (this.isMultiSelect) {
366
+ const ids = defaultValue.split(",");
367
+ ids.forEach((id) => {
368
+ const selectedOption = optionEls.find((opt) => {
369
+ try {
370
+ return JSON.parse(opt.dataset.dropdownOptionLabel).id === id;
371
+ } catch {
372
+ return false;
373
+ }
374
+ });
375
+ if (!selectedOption) {
376
+ console.warn(`Dropdown default ID ${id} not found`);
377
+ return;
378
+ }
196
379
 
197
- if (defaultValue) {
198
- const selectedOption = Array.from(options).find((option) => {
199
- return (
200
- JSON.parse(option.dataset.dropdownOptionLabel).id === defaultValue
201
- );
380
+ const raw = selectedOption.dataset.dropdownOptionLabel;
381
+ this.selectedOptions.add(raw);
382
+
383
+ selectedOption.style.display = "none";
384
+ });
385
+
386
+ this.updatePills();
387
+ this.updateClearButton();
388
+ this.adjustDropdownHeight();
389
+ this.syncHiddenInputs();
390
+ } else {
391
+ hiddenInput.value = defaultValue;
392
+ const selectedOption = optionEls.find((opt) => {
393
+ try {
394
+ return (
395
+ JSON.parse(opt.dataset.dropdownOptionLabel).id === defaultValue
396
+ );
397
+ } catch {
398
+ return false;
399
+ }
202
400
  });
401
+ if (!selectedOption) return;
402
+
203
403
  selectedOption.classList.add("pb_dropdown_option_selected");
204
404
  this.setTriggerElementText(
205
405
  JSON.parse(selectedOption.dataset.dropdownOptionLabel).label
@@ -222,12 +422,32 @@ export default class PbDropdown extends PbEnhancedElement {
222
422
  const options = this.element.querySelectorAll(OPTION_SELECTOR);
223
423
  options.forEach((option) => {
224
424
  option.classList.remove("pb_dropdown_option_selected");
425
+ option.style.display = "";
225
426
  });
226
427
 
227
428
  hiddenInput.value = "";
228
429
 
229
430
  const defaultPlaceholder = this.element.querySelector(DROPDOWN_PLACEHOLDER);
230
431
  this.setTriggerElementText(defaultPlaceholder.dataset.dropdownPlaceholder);
432
+
433
+ if (this.searchInput) {
434
+ this.searchInput.value = "";
435
+ if (this.target.classList.contains("open")) {
436
+ const el = this.target;
437
+ el.style.height = "auto";
438
+ requestAnimationFrame(() => {
439
+ const newHeight = el.scrollHeight + "px";
440
+ el.offsetHeight; // force reflow
441
+ el.style.height = newHeight;
442
+ });
443
+ }
444
+ }
445
+ if (this.isMultiSelect) {
446
+ this.selectedOptions.clear();
447
+ this.updatePills();
448
+ this.updateClearButton();
449
+ this.syncHiddenInputs();
450
+ }
231
451
  }
232
452
 
233
453
  setTriggerElementText(text) {
@@ -236,4 +456,147 @@ export default class PbDropdown extends PbEnhancedElement {
236
456
  triggerElement.textContent = text;
237
457
  }
238
458
  }
459
+
460
+ updatePills() {
461
+ if (!this.isMultiSelect) return;
462
+
463
+ const wrapper = this.element.querySelector("#dropdown_pills_wrapper");
464
+ const placeholder = this.element.querySelector(
465
+ "#dropdown_trigger_display_multi_select"
466
+ );
467
+ if (!wrapper) return;
468
+
469
+ wrapper.innerHTML = "";
470
+ // Show or hide the placeholder based on selected options
471
+ if (placeholder) {
472
+ if (this.selectedOptions.size > 0) {
473
+ placeholder.style.display = "none";
474
+ } else {
475
+ placeholder.style.display = "";
476
+ }
477
+ }
478
+
479
+ Array.from(this.selectedOptions).map((option) => {
480
+ // Create a form pill for each selected option
481
+ const pill = document.createElement("div");
482
+ const color = this.formPillProps.color || "primary";
483
+ pill.classList.add(`pb_form_pill_kit_${color}`, "mr_xs");
484
+ if (this.formPillProps.size === "small") {
485
+ pill.classList.add("small");
486
+ }
487
+ pill.tabIndex = 0;
488
+ pill.dataset.pillId = JSON.parse(option).id;
489
+ const innerDiv = document.createElement("h3");
490
+ innerDiv.className = "pb_title_kit_size_4 pb_form_pill_text";
491
+ innerDiv.textContent = JSON.parse(option).label;
492
+ pill.appendChild(innerDiv);
493
+
494
+ const closeIcon = document.createElement("div");
495
+ closeIcon.className = "pb_form_pill_close";
496
+ closeIcon.innerHTML = `<svg class="pb_custom_icon svg-inline--fa svg_${
497
+ this.formPillProps.size === "small" ? "xs" : "sm"
498
+ } svg_fw" xmlns="http://www.w3.org/2000/svg" width="auto" height="auto" viewBox="0 0 31 25"><path fill="currentColor" d="M23.0762 6.77734L17.4512 12.4023L23.0293 17.9805C23.498 18.4023 23.498 19.1055 23.0293 19.5273C22.6074 19.9961 21.9043 19.9961 21.4824 19.5273L15.8574 13.9492L10.2793 19.5273C9.85742 19.9961 9.1543 19.9961 8.73242 19.5273C8.26367 19.1055 8.26367 18.4023 8.73242 17.9336L14.3105 12.3555L8.73242 6.77734C8.26367 6.35547 8.26367 5.65234 8.73242 5.18359C9.1543 4.76172 9.85742 4.76172 10.3262 5.18359L15.9043 10.8086L21.4824 5.23047C21.9043 4.76172 22.6074 4.76172 23.0762 5.23047C23.498 5.65234 23.498 6.35547 23.0762 6.77734Z"/></svg>`;
499
+ pill.appendChild(closeIcon);
500
+
501
+ closeIcon.addEventListener("click", (e) => {
502
+ e.stopPropagation();
503
+ const id = pill.dataset.pillId;
504
+ this.selectedOptions.delete(option);
505
+
506
+ const optEl = this.element.querySelector(
507
+ `${OPTION_SELECTOR}[data-dropdown-option-label*='"id":${JSON.stringify(
508
+ id
509
+ )}']`
510
+ );
511
+ if (optEl) {
512
+ optEl.style.display = "";
513
+ if (this.target.classList.contains("open")) {
514
+ this.showElement(this.target);
515
+ }
516
+ }
517
+
518
+ this.updatePills();
519
+ this.updateClearButton();
520
+ this.emitSelectionChange();
521
+ this.syncHiddenInputs();
522
+ });
523
+ wrapper.appendChild(pill);
524
+ });
525
+ }
526
+
527
+ clearSelection() {
528
+ if (this.isMultiSelect) {
529
+ this.selectedOptions.clear();
530
+ this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
531
+ opt.style.display = "";
532
+ });
533
+ if (this.target.classList.contains("open")) {
534
+ this.showElement(this.target);
535
+ }
536
+ }
537
+ const customDisplay = this.element.querySelector(
538
+ "#dropdown_trigger_custom_display"
539
+ );
540
+ if (customDisplay) {
541
+ customDisplay.style.display = "none";
542
+ }
543
+ this.resetDropdownValue();
544
+ this.updatePills();
545
+ this.updateClearButton();
546
+ this.syncHiddenInputs();
547
+ this.emitSelectionChange();
548
+ }
549
+
550
+ syncHiddenInputs() {
551
+ if (!this.isMultiSelect) return;
552
+ this.element
553
+ .querySelectorAll('input[data-generated="true"]')
554
+ .forEach((n) => n.remove());
555
+
556
+ const baseInput = this.element.querySelector(DROPDOWN_INPUT);
557
+ if (!baseInput) return;
558
+ // for multi_select, for each selectedOption, create a hidden input
559
+ const name = baseInput.getAttribute("name");
560
+ this.selectedOptions.forEach((raw) => {
561
+ const id = JSON.parse(raw).id;
562
+ const inp = document.createElement("input");
563
+ inp.type = "hidden";
564
+ inp.name = name;
565
+ inp.value = id;
566
+ inp.dataset.generated = "true";
567
+ baseInput.insertAdjacentElement("afterend", inp);
568
+ });
569
+ baseInput.value = "";
570
+ }
571
+
572
+ handleBackspaceClear() {
573
+ if (!this.isMultiSelect) {
574
+ this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
575
+ opt.classList.remove("pb_dropdown_option_selected");
576
+ opt.style.display = "";
577
+ this.adjustDropdownHeight();
578
+ });
579
+
580
+ const hiddenInput = this.element.querySelector(DROPDOWN_INPUT);
581
+ if (hiddenInput) hiddenInput.value = "";
582
+
583
+ const placeholder = this.element.querySelector(DROPDOWN_PLACEHOLDER);
584
+ if (placeholder)
585
+ this.setTriggerElementText(placeholder.dataset.dropdownPlaceholder);
586
+ }
587
+ if (this.isMultiSelect) {
588
+ this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
589
+ const optValue = opt.dataset.dropdownOptionLabel;
590
+ if (
591
+ this.selectedOptions.size > 0 &&
592
+ this.selectedOptions.has(optValue)
593
+ ) {
594
+ opt.style.display = "none";
595
+ } else {
596
+ opt.style.display = "";
597
+ }
598
+ this.adjustDropdownHeight();
599
+ });
600
+ }
601
+ }
239
602
  }
@@ -1,4 +1,6 @@
1
1
  const OPTION_SELECTOR = "[data-dropdown-option-label]";
2
+ const SEARCH_INPUT_SELECTOR = "[data-dropdown-autocomplete]";
3
+
2
4
  export class PbDropdownKeyboard {
3
5
  constructor(dropdown) {
4
6
  this.dropdown = dropdown;
@@ -7,6 +9,9 @@ export class PbDropdownKeyboard {
7
9
  this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
8
10
  );
9
11
  this.focusedOptionIndex = -1;
12
+ this.searchInput = this.dropdownElement.querySelector(
13
+ SEARCH_INPUT_SELECTOR
14
+ );
10
15
  this.init();
11
16
  }
12
17
 
@@ -15,6 +20,25 @@ export class PbDropdownKeyboard {
15
20
  "keydown",
16
21
  this.handleKeyDown.bind(this)
17
22
  );
23
+ if (this.searchInput) {
24
+ this.searchInput.addEventListener("input", () =>
25
+ this.openDropdownIfClosed()
26
+ );
27
+ }
28
+ }
29
+
30
+ getVisibleOptions() {
31
+ // We only want to return the options that are visible
32
+ return Array.from(
33
+ this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
34
+ ).filter((opt) => opt.style.display !== "none");
35
+ }
36
+
37
+ openDropdownIfClosed() {
38
+ if (!this.dropdown.target.classList.contains("open")) {
39
+ this.dropdown.showElement(this.dropdown.target);
40
+ this.dropdown.updateArrowDisplay(true);
41
+ }
18
42
  }
19
43
 
20
44
  handleKeyDown(event) {
@@ -50,28 +74,57 @@ export class PbDropdownKeyboard {
50
74
  this.dropdown.updateArrowDisplay(false);
51
75
  this.resetFocus();
52
76
  break;
77
+ case "Backspace":
78
+ if (this.searchInput) {
79
+ setTimeout(() => {
80
+ if (this.searchInput.value.trim() === "") {
81
+ this.dropdown.handleBackspaceClear();
82
+ }
83
+ }, 0);
84
+ }
85
+ break;
53
86
  default:
54
87
  break;
55
88
  }
56
89
  }
57
90
 
58
- moveFocus(direction) {
91
+ moveFocus(direction) {
92
+ const allOptions = Array.from(
93
+ this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
94
+ );
95
+ const visible = this.getVisibleOptions();
96
+ if (!visible.length) return;
97
+
59
98
  if (this.focusedOptionIndex !== -1) {
60
- this.options[this.focusedOptionIndex].classList.remove(
99
+ allOptions[this.focusedOptionIndex].classList.remove(
61
100
  "pb_dropdown_option_focused"
62
101
  );
63
102
  }
64
- this.focusedOptionIndex =
65
- (this.focusedOptionIndex + direction + this.options.length) %
66
- this.options.length;
67
- this.options[this.focusedOptionIndex].classList.add(
68
- "pb_dropdown_option_focused"
69
- );
103
+
104
+ const prevVisibleIndex =
105
+ this.focusedOptionIndex === -1
106
+ ? -1
107
+ : visible.indexOf(allOptions[this.focusedOptionIndex]);
108
+
109
+ const nextVisibleIndex =
110
+ (prevVisibleIndex + direction + visible.length) % visible.length;
111
+
112
+ const nextEl = visible[nextVisibleIndex];
113
+ nextEl.classList.add("pb_dropdown_option_focused");
114
+
115
+ this.focusedOptionIndex = allOptions.indexOf(nextEl);
70
116
  }
71
117
 
118
+
72
119
  selectOption() {
73
- const option = this.options[this.focusedOptionIndex];
74
- this.dropdown.onOptionSelected(option.dataset.dropdownOptionLabel, option);
75
- this.dropdown.hideElement(this.dropdown.target);
120
+ const allOptions = Array.from(
121
+ this.dropdownElement.querySelectorAll(OPTION_SELECTOR)
122
+ );
123
+ if (this.focusedOptionIndex < 0) return;
124
+
125
+ const optionEl = allOptions[this.focusedOptionIndex];
126
+ this.dropdown.handleOptionClick({ target: optionEl });
127
+ this.dropdown.toggleElement(this.dropdown.target);
128
+ this.dropdown.updateClearButton();
76
129
  }
77
130
  }
@@ -6,7 +6,7 @@ import {
6
6
  buildDataProps,
7
7
  buildHtmlProps
8
8
  } from "../../utilities/props";
9
- import { globalProps } from "../../utilities/globalProps";
9
+ import { globalProps, GlobalProps } from "../../utilities/globalProps";
10
10
 
11
11
  import DropdownContext from "../context";
12
12
 
@@ -24,7 +24,7 @@ type DropdownContainerProps = {
24
24
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
25
25
  id?: string;
26
26
  searchbar?: boolean;
27
- };
27
+ } & GlobalProps;
28
28
 
29
29
  const DropdownContainer = (props: DropdownContainerProps) => {
30
30
  const {
@@ -46,7 +46,6 @@ const DropdownContainer = (props: DropdownContainerProps) => {
46
46
  inputRef,
47
47
  isDropDownClosed,
48
48
  setFocusedOptionIndex,
49
- triggerRef
50
49
  } = useContext(DropdownContext);
51
50
 
52
51
  const ariaProps = buildAriaProps(aria);
@@ -67,7 +66,7 @@ const DropdownContainer = (props: DropdownContainerProps) => {
67
66
  id={id}
68
67
  onMouseEnter={() => setFocusedOptionIndex(-1)}
69
68
  ref={dropdownContainerRef}
70
- style={triggerRef ? {} : { position: "absolute"}}
69
+ style={{ position: "absolute"}}
71
70
  >
72
71
  {searchbar && (
73
72
  <TextInput dark={dark}
@@ -45,27 +45,31 @@ 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
+
63
+ if (!isItemMatchingFilter(option) || (multiSelect && isSelected)) {
57
64
  return null;
58
65
  }
59
66
  const isFocused =
60
67
  focusedOptionIndex >= 0 &&
61
- filteredOptions[focusedOptionIndex].label === option.label;
68
+ filteredOptions[focusedOptionIndex].label === option?.label;
62
69
  const focusedClass = isFocused && "focused";
63
70
 
64
- const selectedClass = `${
65
- selected?.label === option.label
66
- ? "selected"
67
- : "list"
68
- }`;
71
+ const selectedClass = isSelected ? "selected" : "list";
72
+
69
73
  const ariaProps = buildAriaProps(aria);
70
74
  const dataProps = buildDataProps(data);
71
75
  const htmlProps = buildHtmlProps(htmlOptions);
@@ -92,14 +96,14 @@ const DropdownOption = (props: DropdownOptionProps) => {
92
96
  <ListItem
93
97
  cursor="pointer"
94
98
  dark={dark}
95
- data-name={option.value}
96
- key={option.label}
99
+ data-name={option?.value}
100
+ key={option?.label}
97
101
  padding="none"
98
102
  >
99
103
  {children ?
100
104
  <div className="dropdown_option_wrapper">{children}</div> :
101
105
  <Body dark={dark}
102
- text={option.label}
106
+ text={option?.label}
103
107
  />
104
108
  }
105
109
  </ListItem>