playbook_ui 13.24.0 β†’ 13.25.0.pre.alpha.barchartfix2766

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 (190) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +2 -0
  3. data/app/pb_kits/playbook/index.js +1 -0
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +10 -14
  5. data/app/pb_kits/playbook/pb_advanced_table/table_body.html.erb +5 -9
  6. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +2 -6
  7. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +2 -6
  8. data/app/pb_kits/playbook/pb_avatar/avatar.html.erb +1 -6
  9. data/app/pb_kits/playbook/pb_avatar_action_button/avatar_action_button.html.erb +1 -6
  10. data/app/pb_kits/playbook/pb_background/_background.tsx +7 -5
  11. data/app/pb_kits/playbook/pb_background/background.html.erb +2 -11
  12. data/app/pb_kits/playbook/pb_badge/badge.html.erb +1 -6
  13. data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +41 -6
  14. data/app/pb_kits/playbook/pb_bar_graph/bar_graph.rb +4 -0
  15. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_negative_numbers.html.erb +23 -0
  16. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_negative_numbers.jsx +35 -0
  17. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_secondary_y_axis.html.erb +26 -0
  18. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_secondary_y_axis.jsx +36 -0
  19. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_secondary_y_axis.md +3 -0
  20. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_stacked.html.erb +22 -0
  21. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_stacked.jsx +34 -0
  22. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_stacked.md +1 -0
  23. data/app/pb_kits/playbook/pb_bar_graph/docs/example.yml +6 -0
  24. data/app/pb_kits/playbook/pb_bar_graph/docs/index.js +3 -0
  25. data/app/pb_kits/playbook/pb_body/_body.scss +3 -3
  26. data/app/pb_kits/playbook/pb_body/_body.tsx +1 -1
  27. data/app/pb_kits/playbook/pb_body/body.html.erb +1 -6
  28. data/app/pb_kits/playbook/pb_bread_crumbs/bread_crumb_item.html.erb +1 -6
  29. data/app/pb_kits/playbook/pb_bread_crumbs/bread_crumbs.html.erb +2 -7
  30. data/app/pb_kits/playbook/pb_button/_button.scss +1 -1
  31. data/app/pb_kits/playbook/pb_button/button.html.erb +2 -3
  32. data/app/pb_kits/playbook/pb_button_toolbar/button_toolbar.html.erb +2 -7
  33. data/app/pb_kits/playbook/pb_caption/caption.html.erb +1 -6
  34. data/app/pb_kits/playbook/pb_card/card.html.erb +1 -7
  35. data/app/pb_kits/playbook/pb_card/card_body.html.erb +1 -6
  36. data/app/pb_kits/playbook/pb_card/card_header.html.erb +1 -6
  37. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +1 -6
  38. data/app/pb_kits/playbook/pb_circle_icon_button/circle_icon_button.html.erb +1 -6
  39. data/app/pb_kits/playbook/pb_collapsible/collapsible.html.erb +1 -6
  40. data/app/pb_kits/playbook/pb_collapsible/collapsible_content.html.erb +1 -6
  41. data/app/pb_kits/playbook/pb_collapsible/collapsible_main.html.erb +1 -7
  42. data/app/pb_kits/playbook/pb_contact/contact.html.erb +1 -6
  43. data/app/pb_kits/playbook/pb_currency/currency.html.erb +1 -6
  44. data/app/pb_kits/playbook/pb_currency/docs/_currency_alignment_swift.md +43 -0
  45. data/app/pb_kits/playbook/pb_currency/docs/_currency_props_swift.md +12 -0
  46. data/app/pb_kits/playbook/pb_currency/docs/_currency_size_swift.md +31 -0
  47. data/app/pb_kits/playbook/pb_currency/docs/example.yml +5 -0
  48. data/app/pb_kits/playbook/pb_dashboard_value/dashboard_value.html.erb +1 -6
  49. data/app/pb_kits/playbook/pb_date/date.html.erb +1 -6
  50. data/app/pb_kits/playbook/pb_date_picker/date_picker.html.erb +2 -6
  51. data/app/pb_kits/playbook/pb_date_range_inline/date_range_inline.html.erb +1 -5
  52. data/app/pb_kits/playbook/pb_date_range_stacked/date_range_stacked.html.erb +1 -5
  53. data/app/pb_kits/playbook/pb_date_range_stacked/docs/_date_range_stacked_default_swift.md +14 -0
  54. data/app/pb_kits/playbook/pb_date_range_stacked/docs/_date_range_stacked_props_swift.md +9 -0
  55. data/app/pb_kits/playbook/pb_date_range_stacked/docs/example.yml +4 -0
  56. data/app/pb_kits/playbook/pb_date_stacked/date_stacked.html.erb +1 -5
  57. data/app/pb_kits/playbook/pb_date_time/date_time.html.erb +1 -6
  58. data/app/pb_kits/playbook/pb_date_time_stacked/date_time_stacked.html.erb +1 -7
  59. data/app/pb_kits/playbook/pb_date_year_stacked/date_year_stacked.html.erb +1 -5
  60. data/app/pb_kits/playbook/pb_detail/detail.html.erb +1 -6
  61. data/app/pb_kits/playbook/pb_dialog/_dialog.scss +4 -2
  62. data/app/pb_kits/playbook/pb_dialog/dialog.html.erb +1 -6
  63. data/app/pb_kits/playbook/pb_dialog/dialog_body.html.erb +2 -7
  64. data/app/pb_kits/playbook/pb_dialog/dialog_footer.html.erb +1 -5
  65. data/app/pb_kits/playbook/pb_dialog/dialog_header.html.erb +2 -6
  66. data/app/pb_kits/playbook/pb_dialog/docs/example.yml +1 -1
  67. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +103 -0
  68. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +214 -0
  69. data/app/pb_kits/playbook/pb_dropdown/context/index.tsx +5 -0
  70. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.jsx +50 -0
  71. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.md +0 -0
  72. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +87 -0
  73. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.md +1 -0
  74. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.jsx +102 -0
  75. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_and_custom_display.md +1 -0
  76. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +104 -0
  77. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.md +3 -0
  78. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_options.jsx +66 -0
  79. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_options.md +1 -0
  80. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_padding.jsx +51 -0
  81. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_padding.md +1 -0
  82. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_trigger.jsx +77 -0
  83. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_trigger.md +1 -0
  84. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +12 -0
  85. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +7 -0
  86. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +17 -0
  87. data/app/pb_kits/playbook/pb_dropdown/hooks/useDropdown.tsx +17 -0
  88. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +61 -0
  89. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +100 -0
  90. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +108 -0
  91. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +172 -0
  92. data/app/pb_kits/playbook/pb_dropdown/utilities/subComponentHelper.tsx +59 -0
  93. data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -6
  94. data/app/pb_kits/playbook/pb_filter/filter.html.erb +1 -5
  95. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.html.erb +1 -6
  96. data/app/pb_kits/playbook/pb_flex/flex.html.erb +1 -5
  97. data/app/pb_kits/playbook/pb_flex/flex_item.html.erb +2 -6
  98. data/app/pb_kits/playbook/pb_form_group/form_group.html.erb +1 -6
  99. data/app/pb_kits/playbook/pb_form_pill/form_pill.html.erb +1 -1
  100. data/app/pb_kits/playbook/pb_hashtag/hashtag.html.erb +1 -6
  101. data/app/pb_kits/playbook/pb_highlight/highlight.html.erb +1 -5
  102. data/app/pb_kits/playbook/pb_home_address_street/home_address_street.html.erb +1 -5
  103. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.scss +1 -1
  104. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +1 -1
  105. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.html.erb +2 -7
  106. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.rb +1 -1
  107. data/app/pb_kits/playbook/pb_icon_circle/icon_circle.test.js +3 -3
  108. data/app/pb_kits/playbook/pb_icon_stat_value/icon_stat_value.html.erb +1 -6
  109. data/app/pb_kits/playbook/pb_icon_value/icon_value.html.erb +1 -6
  110. data/app/pb_kits/playbook/pb_label_pill/label_pill.html.erb +1 -6
  111. data/app/pb_kits/playbook/pb_label_value/label_value.html.erb +1 -6
  112. data/app/pb_kits/playbook/pb_layout/body.html.erb +1 -5
  113. data/app/pb_kits/playbook/pb_layout/footer.html.erb +1 -5
  114. data/app/pb_kits/playbook/pb_layout/header.html.erb +1 -5
  115. data/app/pb_kits/playbook/pb_layout/item.html.erb +1 -5
  116. data/app/pb_kits/playbook/pb_layout/layout.html.erb +1 -5
  117. data/app/pb_kits/playbook/pb_layout/sidebar.html.erb +1 -5
  118. data/app/pb_kits/playbook/pb_list/_list_item.tsx +2 -2
  119. data/app/pb_kits/playbook/pb_list/item.html.erb +2 -8
  120. data/app/pb_kits/playbook/pb_list/list.html.erb +2 -8
  121. data/app/pb_kits/playbook/pb_loading_inline/loading_inline.html.erb +1 -6
  122. data/app/pb_kits/playbook/pb_message/message.html.erb +1 -6
  123. data/app/pb_kits/playbook/pb_message/message_mention.html.erb +1 -6
  124. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.html.erb +1 -6
  125. data/app/pb_kits/playbook/pb_multiple_users/multiple_users.html.erb +1 -6
  126. data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.html.erb +1 -6
  127. data/app/pb_kits/playbook/pb_nav/item.html.erb +3 -14
  128. data/app/pb_kits/playbook/pb_nav/nav.html.erb +1 -6
  129. data/app/pb_kits/playbook/pb_online_status/online_status.html.erb +2 -6
  130. data/app/pb_kits/playbook/pb_pagination/pagination.html.erb +1 -6
  131. data/app/pb_kits/playbook/pb_passphrase/passphrase.html.erb +1 -1
  132. data/app/pb_kits/playbook/pb_person/person.html.erb +7 -12
  133. data/app/pb_kits/playbook/pb_person_contact/person_contact.html.erb +1 -6
  134. data/app/pb_kits/playbook/pb_pill/pill.html.erb +1 -6
  135. data/app/pb_kits/playbook/pb_popover/popover.html.erb +1 -6
  136. data/app/pb_kits/playbook/pb_progress_pills/progress_pills.html.erb +2 -6
  137. data/app/pb_kits/playbook/pb_progress_simple/progress_simple.html.erb +3 -6
  138. data/app/pb_kits/playbook/pb_progress_step/progress_step.html.erb +1 -5
  139. data/app/pb_kits/playbook/pb_progress_step/progress_step_item.html.erb +1 -5
  140. data/app/pb_kits/playbook/pb_radio/radio.html.erb +2 -8
  141. data/app/pb_kits/playbook/pb_section_separator/_section_separator.scss +6 -2
  142. data/app/pb_kits/playbook/pb_section_separator/_section_separator_mixin.scss +11 -1
  143. data/app/pb_kits/playbook/pb_section_separator/section_separator.html.erb +1 -6
  144. data/app/pb_kits/playbook/pb_select/select.html.erb +1 -5
  145. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +1 -5
  146. data/app/pb_kits/playbook/pb_selectable_card_icon/selectable_card_icon.html.erb +1 -4
  147. data/app/pb_kits/playbook/pb_selectable_icon/selectable_icon.html.erb +1 -5
  148. data/app/pb_kits/playbook/pb_selectable_list/selectable_list.html.erb +1 -6
  149. data/app/pb_kits/playbook/pb_selectable_list/selectable_list_item.html.erb +1 -6
  150. data/app/pb_kits/playbook/pb_source/source.html.erb +1 -5
  151. data/app/pb_kits/playbook/pb_source/source.test.js +2 -2
  152. data/app/pb_kits/playbook/pb_star_rating/star_rating.html.erb +1 -5
  153. data/app/pb_kits/playbook/pb_stat_change/stat_change.html.erb +1 -5
  154. data/app/pb_kits/playbook/pb_stat_value/stat_value.html.erb +1 -5
  155. data/app/pb_kits/playbook/pb_table/table.html.erb +2 -12
  156. data/app/pb_kits/playbook/pb_table/table_body.html.erb +6 -16
  157. data/app/pb_kits/playbook/pb_table/table_cell.html.erb +6 -16
  158. data/app/pb_kits/playbook/pb_table/table_head.html.erb +6 -16
  159. data/app/pb_kits/playbook/pb_table/table_header.html.erb +4 -13
  160. data/app/pb_kits/playbook/pb_table/table_row.html.erb +6 -16
  161. data/app/pb_kits/playbook/pb_textarea/textarea.html.erb +1 -5
  162. data/app/pb_kits/playbook/pb_time/time.html.erb +1 -5
  163. data/app/pb_kits/playbook/pb_time_range_inline/time_range_inline.html.erb +1 -5
  164. data/app/pb_kits/playbook/pb_time_stacked/time_stacked.html.erb +1 -5
  165. data/app/pb_kits/playbook/pb_timeline/item.html.erb +3 -7
  166. data/app/pb_kits/playbook/pb_timeline/timeline.html.erb +1 -5
  167. data/app/pb_kits/playbook/pb_timestamp/timestamp.html.erb +1 -6
  168. data/app/pb_kits/playbook/pb_title/title.html.erb +1 -6
  169. data/app/pb_kits/playbook/pb_title_count/title_count.html.erb +1 -6
  170. data/app/pb_kits/playbook/pb_title_detail/title_detail.html.erb +1 -5
  171. data/app/pb_kits/playbook/pb_toggle/toggle.html.erb +1 -6
  172. data/app/pb_kits/playbook/pb_tooltip/tooltip.html.erb +1 -5
  173. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +27 -19
  174. data/app/pb_kits/playbook/pb_typeahead/components/MenuList.tsx +4 -2
  175. data/app/pb_kits/playbook/pb_typeahead/components/index.tsx +19 -0
  176. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_custom_menu_list.jsx +51 -0
  177. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.jsx +1 -1
  178. data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
  179. data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
  180. data/app/pb_kits/playbook/pb_user/user.html.erb +1 -6
  181. data/app/pb_kits/playbook/pb_user_badge/user_badge.html.erb +1 -6
  182. data/app/pb_kits/playbook/pb_weekday_stacked/weekday_stacked.html.erb +1 -6
  183. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  184. data/app/pb_kits/playbook/tokens/_colors.scss +1 -1
  185. data/dist/menu.yml +5 -1
  186. data/dist/playbook-rails.js +6 -6
  187. data/lib/playbook/kit_base.rb +21 -1
  188. data/lib/playbook/version.rb +2 -2
  189. metadata +47 -6
  190. /data/app/pb_kits/playbook/pb_dialog/docs/{_dialog_props_table.md β†’ _dialog_props_swift.md} +0 -0
@@ -0,0 +1,214 @@
1
+ import React, { useState, useRef, useEffect, ReactElement } from "react";
2
+ import classnames from "classnames";
3
+ import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props";
4
+ import { globalProps } from "../utilities/globalProps";
5
+
6
+ import Body from "../pb_body/_body";
7
+
8
+ import DropdownContainer from "./subcomponents/DropdownContainer";
9
+ import DropdownOption from "./subcomponents/DropdownOption";
10
+ import DropdownTrigger from "./subcomponents/DropdownTrigger";
11
+ import DropdownContext from "./context";
12
+ import useDropdown from "./hooks/useDropdown";
13
+
14
+ import {
15
+ separateChildComponents,
16
+ prepareSubcomponents,
17
+ } from "./utilities/subComponentHelper";
18
+ import { GenericObject } from "../types";
19
+
20
+ type DropdownProps = {
21
+ aria?: { [key: string]: string };
22
+ autocomplete?: boolean;
23
+ className?: string;
24
+ data?: { [key: string]: string };
25
+ htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
26
+ id?: string;
27
+ children?: React.ReactChild[] | React.ReactChild | ReactElement[];
28
+ options: GenericObject;
29
+ onSelect?: (arg: GenericObject) => null;
30
+ };
31
+
32
+ const Dropdown = (props: DropdownProps) => {
33
+ const {
34
+ aria = {},
35
+ autocomplete = false,
36
+ children,
37
+ className,
38
+ data = {},
39
+ htmlOptions = {},
40
+ id,
41
+ options,
42
+ onSelect,
43
+ } = props;
44
+
45
+ const ariaProps = buildAriaProps(aria);
46
+ const dataProps = buildDataProps(data);
47
+ const htmlProps = buildHtmlProps(htmlOptions);
48
+ const classes = classnames(
49
+ buildCss("pb_dropdown"),
50
+ globalProps(props),
51
+ className
52
+ );
53
+
54
+ const [isDropDownClosed, setIsDropDownClosed, toggleDropdown] = useDropdown();
55
+
56
+ const [filterItem, setFilterItem] = useState("");
57
+ const [selected, setSelected] = useState<GenericObject>({});
58
+ const [isInputFocused, setIsInputFocused] = useState(false);
59
+ const [hasTriggerSubcomponent, setHasTriggerSubcomponent] = useState(true);
60
+ const [hasContainerSubcomponent, setHasContainerSubcomponent] =
61
+ useState(true);
62
+
63
+ //state for keyboard events
64
+ const [focusedOptionIndex, setFocusedOptionIndex] = useState(-1);
65
+
66
+ const dropdownRef = useRef(null);
67
+ const inputRef = useRef(null);
68
+
69
+ const { trigger, container, otherChildren } =
70
+ separateChildComponents(children);
71
+
72
+ // useEffect to handle clicks outside the dropdown
73
+ useEffect(() => {
74
+ const handleClickOutside = (e: MouseEvent) => {
75
+ if (dropdownRef.current && !dropdownRef.current.contains(e.target)) {
76
+ setIsDropDownClosed(true);
77
+ setFocusedOptionIndex(-1)
78
+ setIsInputFocused(false);
79
+ }
80
+ };
81
+ window.addEventListener("click", handleClickOutside);
82
+ return () => {
83
+ window.removeEventListener("click", handleClickOutside);
84
+ };
85
+ }, []);
86
+
87
+ useEffect(() => {
88
+ setHasTriggerSubcomponent(!!trigger);
89
+ setHasContainerSubcomponent(!!container);
90
+ }, []);
91
+
92
+
93
+ const filteredOptions = options?.filter((option: GenericObject) =>
94
+ option.label.toLowerCase().includes(filterItem.toLowerCase())
95
+ );
96
+
97
+ useEffect(() => {
98
+ if (!isDropDownClosed) {
99
+ let newIndex = 0;
100
+ if (selected && selected?.label) {
101
+ const selectedIndex = filteredOptions.findIndex((option: GenericObject) => option.label === selected.label);
102
+ if (selectedIndex >= 0) {
103
+ newIndex = selectedIndex;
104
+ }
105
+ }
106
+ setFocusedOptionIndex(newIndex);
107
+ }
108
+ }, [isDropDownClosed]);
109
+
110
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
111
+ setFilterItem(e.target.value);
112
+ setIsDropDownClosed(false);
113
+ };
114
+
115
+ const handleOptionClick = (selectedItem: GenericObject) => {
116
+ setSelected(selectedItem);
117
+ setFilterItem("");
118
+ setIsDropDownClosed(true);
119
+ onSelect(selectedItem);
120
+ };
121
+
122
+ const handleWrapperClick = () => {
123
+ autocomplete && inputRef.current.focus();
124
+ toggleDropdown();
125
+ };
126
+
127
+ const handleBackspace = () => {
128
+ setSelected({});
129
+ onSelect(null);
130
+ setFocusedOptionIndex(-1);
131
+ };
132
+
133
+ const componentsToRender = prepareSubcomponents({
134
+ children,
135
+ hasTriggerSubcomponent,
136
+ hasContainerSubcomponent,
137
+ trigger,
138
+ container,
139
+ otherChildren,
140
+ });
141
+
142
+ return (
143
+ <div {...ariaProps}
144
+ {...dataProps}
145
+ {...htmlProps}
146
+ className={classes}
147
+ id={id}
148
+ >
149
+ <DropdownContext.Provider
150
+ value={{
151
+ autocomplete,
152
+ filteredOptions,
153
+ filterItem,
154
+ focusedOptionIndex,
155
+ handleBackspace,
156
+ handleChange,
157
+ handleOptionClick,
158
+ handleWrapperClick,
159
+ inputRef,
160
+ isDropDownClosed,
161
+ isInputFocused,
162
+ options,
163
+ selected,
164
+ setFocusedOptionIndex,
165
+ setIsDropDownClosed,
166
+ setIsInputFocused,
167
+ setSelected,
168
+ toggleDropdown,
169
+ }}
170
+ >
171
+ <div className="dropdown_wrapper"
172
+ onBlur={() => {
173
+ // Debounce to delay the execution to prevent jumpiness in Focus state
174
+ setTimeout(() => {
175
+ if (!dropdownRef.current.contains(document.activeElement)) {
176
+ setIsInputFocused(false);
177
+ }
178
+ }, 0);
179
+ }}
180
+ onFocus={() => setIsInputFocused(true)}
181
+ ref={dropdownRef}
182
+ >
183
+ {children ? (
184
+ <>
185
+ {componentsToRender.map((component, index) => (
186
+ <React.Fragment key={index}>{component}</React.Fragment>
187
+ ))}
188
+ </>
189
+ ) : (
190
+ <>
191
+ <DropdownTrigger />
192
+ <DropdownContainer>
193
+ {options &&
194
+ options?.map((option: GenericObject) => (
195
+ <Dropdown.Option key={option.id}
196
+ option={option}
197
+ >
198
+ <Body text={option.label} />
199
+ </Dropdown.Option>
200
+ ))}
201
+ </DropdownContainer>
202
+ </>
203
+ )}
204
+ </div>
205
+ </DropdownContext.Provider>
206
+ </div>
207
+ );
208
+ };
209
+
210
+ Dropdown.Option = DropdownOption;
211
+ Dropdown.Trigger = DropdownTrigger;
212
+ Dropdown.Container = DropdownContainer;
213
+
214
+ export default Dropdown;
@@ -0,0 +1,5 @@
1
+ import { createContext } from "react";
2
+
3
+ const DropdownContext = createContext<any>({});
4
+
5
+ export default DropdownContext;
@@ -0,0 +1,50 @@
1
+ import React, { useState } from 'react'
2
+ import { Dropdown } from '../../'
3
+
4
+ const DropdownDefault = (props) => {
5
+ // eslint-disable-next-line no-unused-vars
6
+ const [selectedOption, setSelectedOption] = useState();
7
+
8
+ const options = [
9
+ {
10
+ label: "United States",
11
+ value: "United States",
12
+ areaCode: "+1",
13
+ icon: "πŸ‡ΊπŸ‡Έ",
14
+ id: "United-states"
15
+ },
16
+ {
17
+ label: "Canada",
18
+ value: "Canada",
19
+ areaCode: "+1",
20
+ icon: "πŸ‡¨πŸ‡¦",
21
+ id: "canada"
22
+ },
23
+ {
24
+ label: "Pakistan",
25
+ value: "Pakistan",
26
+ areaCode: "+92",
27
+ icon: "πŸ‡΅πŸ‡°",
28
+ id: "pakistan"
29
+ }
30
+ ];
31
+
32
+
33
+ return (
34
+ <div>
35
+ <Dropdown
36
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
37
+ options={options}
38
+ {...props}
39
+ >
40
+ {options.map((option) => (
41
+ <Dropdown.Option key={option.id}
42
+ option={option}
43
+ />
44
+ ))}
45
+ </Dropdown>
46
+ </div>
47
+ )
48
+ }
49
+
50
+ export default DropdownDefault
@@ -0,0 +1,87 @@
1
+ import React, { useState } from 'react'
2
+ import { Dropdown, User, Badge, FlexItem } from '../..'
3
+
4
+ const DropdownWithAutocomplete = (props) => {
5
+ // eslint-disable-next-line no-unused-vars
6
+ const [selectedOption, setSelectedOption] = useState();
7
+
8
+ const options = [
9
+ {
10
+ label: "Jasper Furniss",
11
+ value: "Jasper Furniss",
12
+ territory: "PHL",
13
+ title: "Senior UX Engineer",
14
+ id: "jasper-furniss",
15
+ status: "Offline"
16
+ },
17
+ {
18
+ label: "Ramon Ruiz",
19
+ value: "Ramon Ruiz",
20
+ territory: "PHL",
21
+ title: "Senior UX Desinger",
22
+ id: "ramon-ruiz",
23
+ status: "Away"
24
+ },
25
+ {
26
+ label: "Jason Cypret",
27
+ value: "Jason Cypret",
28
+ territory: "PHL",
29
+ title: "VP of User Experience",
30
+ id: "jason-cypret",
31
+ status: "Online"
32
+ },
33
+ {
34
+ label: "Courtney Long",
35
+ value: "Courtney Long",
36
+ territory: "PHL",
37
+ title: "UX Design Mentor",
38
+ id: "courtney-long",
39
+ status: "Online"
40
+ }
41
+ ];
42
+
43
+
44
+ return (
45
+ <div>
46
+ <Dropdown autocomplete
47
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
48
+ options={options}
49
+ {...props}
50
+ >
51
+ {options.map((option) => (
52
+ <Dropdown.Option key={option.id}
53
+ option={option}
54
+ >
55
+ <>
56
+ <FlexItem>
57
+ <User
58
+ align="left"
59
+ avatar
60
+ name={option.label}
61
+ orientation="horizontal"
62
+ territory={option.territory}
63
+ title={option.title}
64
+ />
65
+ </FlexItem>
66
+ <FlexItem>
67
+ <Badge
68
+ rounded
69
+ text={option.status}
70
+ variant={`${
71
+ option.status === "Offline"
72
+ ? "neutral"
73
+ : option.status === "Online"
74
+ ? "success"
75
+ : "warning"
76
+ }`}
77
+ />
78
+ </FlexItem>
79
+ </>
80
+ </Dropdown.Option>
81
+ ))}
82
+ </Dropdown>
83
+ </div>
84
+ )
85
+ }
86
+
87
+ export default DropdownWithAutocomplete
@@ -0,0 +1 @@
1
+ The `autocomplete` prop can be used to add autocomplete or typeahead functionality to the Dropdown's default Trigger. This prop is set to 'false' by default.
@@ -0,0 +1,102 @@
1
+ import React, { useState } from 'react'
2
+ import { Dropdown, User, Badge, FlexItem, Avatar } from '../..'
3
+
4
+ const DropdownWithAutocompleteAndCustomDisplay = (props) => {
5
+ // eslint-disable-next-line no-unused-vars
6
+ const [selectedOption, setSelectedOption] = useState();
7
+
8
+ const options = [
9
+ {
10
+ label: "Jasper Furniss",
11
+ value: "Jasper Furniss",
12
+ territory: "PHL",
13
+ title: "Senior UX Engineer",
14
+ id: "jasper-furniss",
15
+ status: "Offline"
16
+ },
17
+ {
18
+ label: "Ramon Ruiz",
19
+ value: "Ramon Ruiz",
20
+ territory: "PHL",
21
+ title: "Senior UX Desinger",
22
+ id: "ramon-ruiz",
23
+ status: "Away"
24
+ },
25
+ {
26
+ label: "Jason Cypret",
27
+ value: "Jason Cypret",
28
+ territory: "PHL",
29
+ title: "VP of User Experience",
30
+ id: "jason-cypret",
31
+ status: "Online"
32
+ },
33
+ {
34
+ label: "Courtney Long",
35
+ value: "Courtney Long",
36
+ territory: "PHL",
37
+ title: "UX Design Mentor",
38
+ id: "courtney-long",
39
+ status: "Online"
40
+ }
41
+ ];
42
+
43
+ const CustomDisplay = () => {
44
+ return (
45
+ <>
46
+ {
47
+ selectedOption && (
48
+ <Avatar
49
+ name={selectedOption.label}
50
+ size="xs"
51
+ />
52
+ )
53
+ }
54
+ </>
55
+ )
56
+ };
57
+
58
+ return (
59
+ <div>
60
+ <Dropdown autocomplete
61
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
62
+ options={options}
63
+ {...props}
64
+ >
65
+ <Dropdown.Trigger customDisplay={<CustomDisplay/>} />
66
+ {options.map((option) => (
67
+ <Dropdown.Option key={option.id}
68
+ option={option}
69
+ >
70
+ <>
71
+ <FlexItem>
72
+ <User
73
+ align="left"
74
+ avatar
75
+ name={option.label}
76
+ orientation="horizontal"
77
+ territory={option.territory}
78
+ title={option.title}
79
+ />
80
+ </FlexItem>
81
+ <FlexItem>
82
+ <Badge
83
+ rounded
84
+ text={option.status}
85
+ variant={`${
86
+ option.status === "Offline"
87
+ ? "neutral"
88
+ : option.status === "Online"
89
+ ? "success"
90
+ : "warning"
91
+ }`}
92
+ />
93
+ </FlexItem>
94
+ </>
95
+ </Dropdown.Option>
96
+ ))}
97
+ </Dropdown>
98
+ </div>
99
+ )
100
+ }
101
+
102
+ export default DropdownWithAutocompleteAndCustomDisplay
@@ -0,0 +1 @@
1
+ `autocomplete` prop can also be used in conjunction with the `customDisplay` prop.
@@ -0,0 +1,104 @@
1
+ import React, { useState } from 'react'
2
+ import { Dropdown, User, FlexItem, Badge, Avatar } from '../../'
3
+
4
+ const DropdownWithCustomDisplay = (props) => {
5
+ const [selectedOption, setSelectedOption] = useState();
6
+
7
+ const options = [
8
+ {
9
+ label: "Jasper Furniss",
10
+ value: "Jasper Furniss",
11
+ territory: "PHL",
12
+ title: "Senior UX Engineer",
13
+ id: "jasper-furniss",
14
+ status: "Offline"
15
+ },
16
+ {
17
+ label: "Ramon Ruiz",
18
+ value: "Ramon Ruiz",
19
+ territory: "PHL",
20
+ title: "Senior UX Desinger",
21
+ id: "ramon-ruiz",
22
+ status: "Away"
23
+ },
24
+ {
25
+ label: "Jason Cypret",
26
+ value: "Jason Cypret",
27
+ territory: "PHL",
28
+ title: "VP of User Experience",
29
+ id: "jason-cypret",
30
+ status: "Online"
31
+ },
32
+ {
33
+ label: "Courtney Long",
34
+ value: "Courtney Long",
35
+ territory: "PHL",
36
+ title: "UX Design Mentor",
37
+ id: "courtney-long",
38
+ status: "Online"
39
+ }
40
+ ];
41
+
42
+ const CustomDisplay = () => {
43
+ return (
44
+ <>
45
+ {
46
+ selectedOption && (
47
+ <Avatar
48
+ name={selectedOption.label}
49
+ size="xs"
50
+ />
51
+ )
52
+ }
53
+ </>
54
+ )
55
+ };
56
+
57
+
58
+ return (
59
+ <div>
60
+ <Dropdown
61
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
62
+ options={options}
63
+ {...props}
64
+ >
65
+ <Dropdown.Trigger customDisplay={<CustomDisplay/>}
66
+ placeholder="Select a User"
67
+ />
68
+ {options.map((option) => (
69
+ <Dropdown.Option key={option.id}
70
+ option={option}
71
+ >
72
+ <>
73
+ <FlexItem>
74
+ <User
75
+ align="left"
76
+ avatar
77
+ name={option.label}
78
+ orientation="horizontal"
79
+ territory={option.territory}
80
+ title={option.title}
81
+ />
82
+ </FlexItem>
83
+ <FlexItem>
84
+ <Badge
85
+ rounded
86
+ text={option.status}
87
+ variant={`${
88
+ option.status === "Offline"
89
+ ? "neutral"
90
+ : option.status === "Online"
91
+ ? "success"
92
+ : "warning"
93
+ }`}
94
+ />
95
+ </FlexItem>
96
+ </>
97
+ </Dropdown.Option>
98
+ ))}
99
+ </Dropdown>
100
+ </div>
101
+ )
102
+ }
103
+
104
+ export default DropdownWithCustomDisplay
@@ -0,0 +1,3 @@
1
+ The `customDisplay` prop can be used to customize the display of the selected item by allowing devs to pass in a component that will be rendered to the left of the default text-based display. In this example the Avatar kit is being used.
2
+
3
+ The `placeholder` prop can also be used to customize the placeholder text for the default Trigger.
@@ -0,0 +1,66 @@
1
+ import React, { useState } from 'react'
2
+ import { Dropdown, Icon, Body, FlexItem, Flex } from '../..'
3
+
4
+ const DropdownWithCustomOptions = (props) => {
5
+ // eslint-disable-next-line no-unused-vars
6
+ const [selectedOption, setSelectedOption] = useState();
7
+
8
+ const options = [
9
+ {
10
+ label: "United States",
11
+ value: "United States",
12
+ areaCode: "+1",
13
+ icon: "πŸ‡ΊπŸ‡Έ",
14
+ id: "United-states"
15
+ },
16
+ {
17
+ label: "Canada",
18
+ value: "Canada",
19
+ areaCode: "+1",
20
+ icon: "πŸ‡¨πŸ‡¦",
21
+ id: "canada"
22
+ },
23
+ {
24
+ label: "Pakistan",
25
+ value: "Pakistan",
26
+ areaCode: "+92",
27
+ icon: "πŸ‡΅πŸ‡°",
28
+ id: "pakistan"
29
+ }
30
+ ];
31
+
32
+
33
+ return (
34
+ <div>
35
+ <Dropdown
36
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
37
+ options={options}
38
+ {...props}
39
+ >
40
+ {options.map((option) => (
41
+ <Dropdown.Option key={option.id}
42
+ option={option}
43
+ >
44
+ <>
45
+ <FlexItem>
46
+ <Flex>
47
+ <Icon icon={option.icon}
48
+ paddingRight="xs"
49
+ />
50
+ <Body text={option.label} />
51
+ </Flex>
52
+ </FlexItem>
53
+ <FlexItem>
54
+ <Body color="light"
55
+ text={option.areaCode}
56
+ />
57
+ </FlexItem>
58
+ </>
59
+ </Dropdown.Option>
60
+ ))}
61
+ </Dropdown>
62
+ </div>
63
+ )
64
+ }
65
+
66
+ export default DropdownWithCustomOptions
@@ -0,0 +1 @@
1
+ The Dropdown also allows for custom options that can be passed in as children to the `Dropdown.Option` subcomponent. If no children are passed in the `Dropdown.Option`, the kit will render each option as text by default.
@@ -0,0 +1,51 @@
1
+ import React, { useState } from 'react'
2
+ import { Dropdown } from '../..'
3
+
4
+ const DropdownWithCustomPadding = (props) => {
5
+ // eslint-disable-next-line no-unused-vars
6
+ const [selectedOption, setSelectedOption] = useState();
7
+
8
+ const options = [
9
+ {
10
+ label: "United States",
11
+ value: "United States",
12
+ areaCode: "+1",
13
+ icon: "πŸ‡ΊπŸ‡Έ",
14
+ id: "United-states"
15
+ },
16
+ {
17
+ label: "Canada",
18
+ value: "Canada",
19
+ areaCode: "+1",
20
+ icon: "πŸ‡¨πŸ‡¦",
21
+ id: "canada"
22
+ },
23
+ {
24
+ label: "Pakistan",
25
+ value: "Pakistan",
26
+ areaCode: "+92",
27
+ icon: "πŸ‡΅πŸ‡°",
28
+ id: "pakistan"
29
+ }
30
+ ];
31
+
32
+
33
+ return (
34
+ <div>
35
+ <Dropdown
36
+ onSelect={(selectedItem) => setSelectedOption(selectedItem)}
37
+ options={options}
38
+ {...props}
39
+ >
40
+ {options.map((option) => (
41
+ <Dropdown.Option key={option.id}
42
+ option={option}
43
+ padding="sm"
44
+ />
45
+ ))}
46
+ </Dropdown>
47
+ </div>
48
+ )
49
+ }
50
+
51
+ export default DropdownWithCustomPadding
@@ -0,0 +1 @@
1
+ By default, the padding on each option in the dropdown is set to `xs`. The `padding` Global Props however can be used to override this default. In this example, we are setting padding to `sm`.