playbook_ui 14.20.0.pre.alpha.PLAY2214checkboxhiddeninput8052 → 14.20.0.pre.alpha.PLAY21817891

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +49 -116
  3. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +2 -58
  4. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +4 -16
  6. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +3 -7
  7. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +0 -13
  8. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +3 -10
  9. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +0 -61
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -2
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -2
  12. data/app/pb_kits/playbook/pb_advanced_table/index.js +0 -2
  13. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +11 -4
  14. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +7 -28
  15. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_custom.html.erb +0 -1
  16. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +48 -2
  17. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_options.html.erb +0 -1
  18. data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +0 -1
  19. data/app/pb_kits/playbook/pb_draggable/context/index.tsx +58 -17
  20. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +3 -12
  21. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +0 -2
  22. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +1 -2
  23. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +2 -108
  24. data/app/pb_kits/playbook/pb_dropdown/index.js +0 -24
  25. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +10 -14
  26. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +15 -26
  27. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -1
  28. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +0 -4
  29. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
  30. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +3 -4
  31. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +0 -1
  32. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +0 -3
  33. data/app/pb_kits/playbook/pb_popover/index.ts +4 -9
  34. data/app/pb_kits/playbook/pb_select/docs/example.yml +0 -2
  35. data/app/pb_kits/playbook/pb_select/docs/index.js +0 -1
  36. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +51 -3
  37. data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +1 -1
  38. data/dist/chunks/{_typeahead-CoOpeYom.js → _typeahead-BmOWdDtp.js} +2 -2
  39. data/dist/chunks/_weekday_stacked-CvcuQyr9.js +45 -0
  40. data/dist/chunks/{lib-D7Va7yqa.js → lib-D5R1BjUn.js} +1 -1
  41. data/dist/chunks/{pb_form_validation-DSkdRDMf.js → pb_form_validation-BZ2AVAi_.js} +1 -1
  42. data/dist/chunks/vendor.js +1 -1
  43. data/dist/menu.yml +1 -1
  44. data/dist/playbook-doc.js +2 -2
  45. data/dist/playbook-rails-react-bindings.js +1 -1
  46. data/dist/playbook-rails.js +1 -1
  47. data/dist/playbook.css +1 -1
  48. data/lib/playbook/version.rb +1 -1
  49. metadata +6 -21
  50. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +0 -57
  51. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +0 -5
  52. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_custom_rails.md +0 -1
  53. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_form.html.erb +0 -22
  54. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_form.md +0 -5
  55. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +0 -1
  56. data/app/pb_kits/playbook/pb_checkbox/index.js +0 -56
  57. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +0 -42
  58. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +0 -1
  59. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +0 -4
  60. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +0 -15
  61. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +0 -1
  62. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +0 -12
  63. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +0 -31
  64. data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +0 -1
  65. data/dist/chunks/_weekday_stacked-BppvLxTS.js +0 -45
@@ -5,8 +5,7 @@ module Playbook
5
5
  class Checkbox < Playbook::KitBase
6
6
  prop :error, type: Playbook::Props::Boolean, default: false
7
7
  prop :checked, type: Playbook::Props::Boolean, default: false
8
- prop :indeterminate_main, type: Playbook::Props::Boolean, default: false
9
- prop :indeterminate_parent
8
+ prop :indeterminate, type: Playbook::Props::Boolean, default: false
10
9
  prop :text
11
10
  prop :value
12
11
  prop :name
@@ -18,43 +17,19 @@ module Playbook
18
17
  default: false
19
18
  prop :form_spacing, type: Playbook::Props::Boolean,
20
19
  default: false
21
- prop :hidden_input, type: Playbook::Props::Boolean,
22
- default: false
23
- prop :hidden_value
24
20
 
25
21
  def classname
26
- generate_classname("pb_checkbox_kit", checked_class) + error_class
22
+ generate_classname("pb_checkbox_kit", checked_class) + indeterminate_class + error_class
27
23
  end
28
24
 
29
25
  def input
30
- inputs = []
31
- effective_name = name || input_options[:name]
32
- effective_value = value || input_options[:value] || "1"
33
- is_checked = checked || input_options[:checked]
34
-
35
- inputs << hidden_field_tag(effective_name, hidden_value || "0") if hidden_input && effective_name.present?
36
-
37
- inputs << check_box_tag(
38
- effective_name,
39
- effective_value,
40
- is_checked,
41
- input_options.merge(disabled: disabled)
42
- )
43
-
44
- safe_join(inputs)
26
+ check_box_tag(name, value, checked, input_options.merge(disabled: disabled))
45
27
  end
46
28
 
47
29
  def checkbox_label_status
48
30
  error ? "negative" : nil
49
31
  end
50
32
 
51
- def data
52
- Hash(prop(:data)).merge(
53
- pb_checkbox_indeterminate_main: indeterminate_main,
54
- pb_checkbox_indeterminate_parent: indeterminate_parent
55
- )
56
- end
57
-
58
33
  private
59
34
 
60
35
  def error_class
@@ -64,6 +39,10 @@ module Playbook
64
39
  def checked_class
65
40
  checked ? "on" : "off"
66
41
  end
42
+
43
+ def indeterminate_class
44
+ indeterminate ? " indeterminate" : ""
45
+ end
67
46
  end
68
47
  end
69
48
  end
@@ -1,4 +1,3 @@
1
1
  <%= pb_rails("checkbox", props: {text: "Custom Checkbox"}) do%>
2
- <input type="hidden" name="custom-name" value="0" />
3
2
  <input type="checkbox" name="custom-name" value="custom-value"/>
4
3
  <% end %>
@@ -9,10 +9,11 @@
9
9
  <tr>
10
10
  <th>
11
11
  <%= pb_rails("checkbox", props: {
12
+ checked: true,
12
13
  text: "Uncheck All",
13
14
  value: "checkbox-value",
14
15
  name: "main-checkbox",
15
- indeterminate_main: true,
16
+ indeterminate: true,
16
17
  id: "indeterminate-checkbox"
17
18
  }) %>
18
19
  </th>
@@ -29,10 +30,55 @@
29
30
  value: checkbox[:id],
30
31
  name: "#{checkbox[:id]}-indeterminate-checkbox",
31
32
  id: "#{checkbox[:id]}-indeterminate-checkbox",
32
- indeterminate_parent: "indeterminate-checkbox",
33
33
  }) %>
34
34
  </td>
35
35
  </tr>
36
36
  <% end %>
37
37
  </tbody>
38
38
  <% end %>
39
+
40
+ <script>
41
+ document.addEventListener('DOMContentLoaded', function() {
42
+ const mainCheckboxWrapper = document.getElementById('indeterminate-checkbox');
43
+ const mainCheckbox = document.getElementsByName("main-checkbox")[0];
44
+ const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="indeterminate-checkbox"]');
45
+
46
+ const updateMainCheckbox = () => {
47
+ // Count the number of checked child checkboxes
48
+ const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
49
+ // Determine if the main checkbox should be in an indeterminate state
50
+ const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
51
+
52
+ // Set the main checkbox states
53
+ mainCheckbox.indeterminate = indeterminate;
54
+ mainCheckbox.checked = checkedCount > 0;
55
+
56
+ // Determine the main checkbox label based on the number of checked checkboxes
57
+ const text = checkedCount === 0 ? 'Check All' : 'Uncheck All';
58
+
59
+ // Determine the icon class to add and remove based on the number of checked checkboxes
60
+ const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
61
+ const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
62
+
63
+ // Update main checkbox label
64
+ mainCheckboxWrapper.getElementsByClassName('pb_body_kit')[0].textContent = text;
65
+
66
+ // Add and remove the icon class to the main checkbox wrapper
67
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
68
+ mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
69
+
70
+ // Toggle the visibility of the checkbox icon based on the indeterminate state
71
+ mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
72
+ mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
73
+ };
74
+
75
+ mainCheckbox.addEventListener('change', function() {
76
+ childCheckboxes.forEach(cb => cb.checked = this.checked);
77
+ updateMainCheckbox();
78
+ });
79
+
80
+ childCheckboxes.forEach(cb => {
81
+ cb.addEventListener('change', updateMainCheckbox);
82
+ });
83
+ });
84
+ </script>
@@ -1,6 +1,5 @@
1
1
  <%= pb_rails("checkbox" , props: {
2
2
  text: "Checkbox with Options",
3
- hidden_input: true,
4
3
  input_options: {
5
4
  id: "checkbox-id",
6
5
  name: "checkbox-name",
@@ -7,7 +7,6 @@ examples:
7
7
  - checkbox_options: Checkbox w/ Options
8
8
  - checkbox_indeterminate: Indeterminate Checkbox
9
9
  - checkbox_disabled: Disabled Checkbox
10
- - checkbox_form: Form and Hidden Input
11
10
 
12
11
  react:
13
12
  - checkbox_default: Default
@@ -1,11 +1,11 @@
1
- import React, { createContext, useReducer, useContext, useEffect, useMemo } from "react";
1
+ import React, { createContext, useReducer, useContext, useEffect, useMemo, useRef, useState } from "react";
2
2
  import { InitialStateType, ActionType, DraggableProviderType } from "./types";
3
3
 
4
4
  const initialState: InitialStateType = {
5
5
  items: [],
6
6
  dragData: { id: "", initialGroup: "" },
7
7
  isDragging: "",
8
- activeContainer: ""
8
+ activeContainer: "",
9
9
  };
10
10
 
11
11
  const reducer = (state: InitialStateType, action: ActionType) => {
@@ -31,9 +31,23 @@ const reducer = (state: InitialStateType, action: ActionType) => {
31
31
  const { dragId, targetId } = action.payload;
32
32
  const newItems = [...state.items];
33
33
  const draggedItem = newItems.find(item => item.id === dragId);
34
- const draggedIndex = newItems.indexOf(draggedItem);
34
+ const targetItem = newItems.find(item => item.id === targetId);
35
+
36
+ if (!draggedItem || !targetItem || draggedItem.container !== targetItem.container) {
37
+ return state;
38
+ }
39
+
40
+ if (dragId === targetId) {
41
+ return state;
42
+ }
43
+
44
+ const draggedIndex = newItems.findIndex(item => item.id === dragId);
35
45
  const targetIndex = newItems.findIndex(item => item.id === targetId);
36
46
 
47
+ if (draggedIndex === -1 || targetIndex === -1) {
48
+ return state;
49
+ }
50
+
37
51
  newItems.splice(draggedIndex, 1);
38
52
  newItems.splice(targetIndex, 0, draggedItem);
39
53
 
@@ -48,7 +62,11 @@ const reducer = (state: InitialStateType, action: ActionType) => {
48
62
  const DragContext = createContext<any>({});
49
63
 
50
64
  export const DraggableContext = () => {
51
- return useContext(DragContext);
65
+ const context = useContext(DragContext);
66
+ if (context === undefined) {
67
+ throw new Error('DraggableContext must be used within a DraggableProvider');
68
+ }
69
+ return context;
52
70
  };
53
71
 
54
72
  export const DraggableProvider = ({
@@ -63,7 +81,11 @@ export const DraggableProvider = ({
63
81
  dropZone = { type: 'ghost', color: 'neutral', direction: 'vertical' }
64
82
  }: DraggableProviderType) => {
65
83
  const [state, dispatch] = useReducer(reducer, initialState);
66
-
84
+
85
+ // Store initial items in a ref to use if needed (for consistency when needed in future updates)
86
+ const initialItemsRef = useRef(initialItems);
87
+ const [isDragging, setIsDragging] = useState(false);
88
+
67
89
  // Parse dropZone prop - handle both string format (backward compatibility) and object format
68
90
  let dropZoneType = 'ghost';
69
91
  let dropZoneColor = 'neutral';
@@ -86,45 +108,64 @@ export const DraggableProvider = ({
86
108
 
87
109
  useEffect(() => {
88
110
  dispatch({ type: 'SET_ITEMS', payload: initialItems });
111
+ initialItemsRef.current = initialItems;
89
112
  }, [initialItems]);
90
113
 
91
114
  useEffect(() => {
92
- onReorder(state.items);
93
- }, [state.items]);
115
+ if (onReorder) {
116
+ onReorder(state.items);
117
+ }
118
+ }, [state.items, onReorder]);
94
119
 
95
120
  const handleDragStart = (id: string, container: string) => {
96
- dispatch({ type: 'SET_DRAG_DATA', payload: { id: id, initialGroup: container } });
121
+ setIsDragging(true);
122
+ dispatch({ type: 'SET_DRAG_DATA', payload: { id, initialGroup: container } });
97
123
  dispatch({ type: 'SET_IS_DRAGGING', payload: id });
124
+ dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
98
125
  if (onDragStart) onDragStart(id, container);
99
126
  };
100
127
 
101
128
  const handleDragEnter = (id: string, container: string) => {
102
- if (state.dragData.id !== id) {
103
- dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
104
- dispatch({ type: 'SET_DRAG_DATA', payload: { id: state.dragData.id, initialGroup: container } });
129
+ if (!isDragging || container !== state.activeContainer) return;
130
+
131
+ if (state.dragData.id === id) return;
132
+
133
+ const draggedItem = state.items.find(item => item.id === state.dragData.id);
134
+ const targetItem = state.items.find(item => item.id === id);
135
+
136
+ if (!draggedItem || !targetItem || draggedItem.container !== targetItem.container) {
137
+ return;
105
138
  }
139
+
140
+ dispatch({ type: 'REORDER_ITEMS', payload: { dragId: state.dragData.id, targetId: id } });
141
+
106
142
  if (onDragEnter) onDragEnter(id, container);
107
143
  };
108
144
 
109
145
  const handleDragEnd = () => {
146
+ setIsDragging(false);
110
147
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
111
148
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
112
149
  if (onDragEnd) onDragEnd();
113
150
  };
114
151
 
115
- const changeCategory = (itemId: string, container: string) => {
116
- dispatch({ type: 'CHANGE_CATEGORY', payload: { itemId, container } });
117
- };
118
-
119
152
  const handleDrop = (container: string) => {
153
+ const draggedItem = state.items.find(item => item.id === state.dragData.id);
154
+
155
+ if (draggedItem && draggedItem.container !== container) {
156
+ dispatch({ type: 'CHANGE_CATEGORY', payload: { itemId: state.dragData.id, container } });
157
+ }
158
+
120
159
  dispatch({ type: 'SET_IS_DRAGGING', payload: "" });
121
160
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: "" });
122
- changeCategory(state.dragData.id, container);
161
+
162
+ setIsDragging(false);
123
163
  if (onDrop) onDrop(container);
124
164
  };
125
165
 
126
166
  const handleDragOver = (e: Event, container: string) => {
127
167
  e.preventDefault();
168
+ e.stopPropagation();
128
169
  dispatch({ type: 'SET_ACTIVE_CONTAINER', payload: container });
129
170
  if (onDragOver) onDragOver(e, container);
130
171
  };
@@ -144,7 +185,7 @@ export const DraggableProvider = ({
144
185
  handleDragEnd,
145
186
  handleDrop,
146
187
  handleDragOver
147
- }), [state, dropZoneType, dropZoneColor, dropZoneDirection]);
188
+ }), [state, dropZoneType, dropZoneColor, dropZoneDirection, handleDragStart, handleDragEnter, handleDragEnd, handleDrop, handleDragOver]);
148
189
 
149
190
  return (
150
191
  <DragContext.Provider value={contextValue}>{children}</DragContext.Provider>
@@ -25,7 +25,6 @@ type DropdownProps = {
25
25
  blankSelection?: string;
26
26
  children?: React.ReactChild[] | React.ReactChild | React.ReactElement[];
27
27
  className?: string;
28
- closeOnSelection?: boolean;
29
28
  formPillProps?: GenericObject;
30
29
  dark?: boolean;
31
30
  data?: { [key: string]: string };
@@ -56,7 +55,6 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
56
55
  blankSelection = '',
57
56
  children,
58
57
  className,
59
- closeOnSelection = true,
60
58
  dark = false,
61
59
  data = {},
62
60
  defaultValue = {},
@@ -154,7 +152,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
154
152
  if (!multiSelect) return optionsWithBlankSelection;
155
153
  return optionsWithBlankSelection.filter((option: GenericObject) => !selectedArray.some((sel) => sel.label === option.label));
156
154
  }, [optionsWithBlankSelection, selectedArray, multiSelect]);
157
-
155
+
158
156
  const filteredOptions = useMemo(() => {
159
157
  return availableOptions.filter((opt: GenericObject) =>
160
158
  String(opt.label).toLowerCase().includes(filterItem.toLowerCase())
@@ -194,18 +192,12 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
194
192
  return next;
195
193
  });
196
194
  setFilterItem("");
197
- // Only close dropdown if closeOnSelection is true
198
- if (closeOnSelection) {
199
- setIsDropDownClosed(true);
200
- }
195
+ setIsDropDownClosed(true);
201
196
  } else {
202
197
  setSelected(clickedItem);
203
198
  setFilterItem("");
199
+ setIsDropDownClosed(true);
204
200
  onSelect && onSelect(clickedItem);
205
- // Only close dropdown if closeOnSelection is true
206
- if (closeOnSelection) {
207
- setIsDropDownClosed(true);
208
- }
209
201
  }
210
202
  };
211
203
 
@@ -260,7 +252,6 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
260
252
  <DropdownContext.Provider
261
253
  value={{
262
254
  autocomplete,
263
- closeOnSelection,
264
255
  dropdownContainerRef,
265
256
  filteredOptions,
266
257
  filterItem,
@@ -44,6 +44,4 @@ examples:
44
44
  - dropdown_clear_selection: Clear Selection
45
45
  - dropdown_separators_hidden: Separators Hidden
46
46
  - dropdown_with_external_control: useDropdown Hook
47
- - dropdown_close_on_select: Close On Selection
48
-
49
47
 
@@ -19,5 +19,4 @@ export { default as DropdownMultiSelect } from './_dropdown_multi_select.jsx'
19
19
  export { default as DropdownMultiSelectDisplay } from './_dropdown_multi_select_display.jsx'
20
20
  export { default as DropdownMultiSelectWithAutocomplete } from './_dropdown_multi_select_with_autocomplete.jsx'
21
21
  export { default as DropdownMultiSelectWithDefault } from './_dropdown_multi_select_with_default.jsx'
22
- export { default as DropdownMultiSelectWithCustomOptions } from './_dropdown_multi_select_with_custom_options.jsx'
23
- export { default as DropdownCloseOnSelect } from './_dropdown_close_on_select.jsx'
22
+ export { default as DropdownMultiSelectWithCustomOptions } from './_dropdown_multi_select_with_custom_options.jsx'
@@ -1,5 +1,5 @@
1
1
  import React from "react"
2
- import { render, screen, fireEvent } from "../utilities/test-utils"
2
+ import { render, screen } from "../utilities/test-utils"
3
3
 
4
4
  import { Dropdown, Icon, IconCircle } from 'playbook-ui'
5
5
 
@@ -263,110 +263,4 @@ test("searchbar prop to render TextInput in container", () => {
263
263
  const kit = screen.getByTestId(testId)
264
264
  const searchbar = kit.querySelector('.pb_text_input_kit')
265
265
  expect(searchbar).toBeInTheDocument()
266
- })
267
-
268
- test("MultiSelect prop to allow multiple selections + add correct Form Pills", () => {
269
- render(
270
- <Dropdown
271
- data={{ testid: testId }}
272
- multiSelect
273
- options={options}
274
- />
275
- );
276
-
277
- const kit = screen.getByTestId(testId);
278
- const option = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
279
- fireEvent.click(option[0]); // Select first option
280
- fireEvent.click(option[1]); // Select second option
281
- const formPills = kit.querySelectorAll(".pb_form_pill_kit_primary");
282
- expect(formPills.length).toBe(2);
283
- expect(formPills[0]).toHaveTextContent("United States");
284
- expect(formPills[1]).toHaveTextContent("Canada");
285
- });
286
-
287
- test("hides each selected option from the dropdown", () => {
288
-
289
- render(
290
- <Dropdown
291
- data={{ testid: testId }}
292
- multiSelect
293
- options={options}
294
- />
295
- );
296
-
297
- const kit = screen.getByTestId(testId);
298
- const option = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
299
- const firstOpt = options[0].label
300
- fireEvent.click(option[0]);
301
- const option2 = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
302
- expect(option2[0]).not.toHaveTextContent(firstOpt)
303
- })
304
-
305
- test("renders form pills inside trigger", () => {
306
- render(
307
- <Dropdown
308
- data={{ testid: testId }}
309
- multiSelect
310
- options={options}
311
- />
312
- );
313
-
314
- const kit = screen.getByTestId(testId)
315
- const option = kit.querySelector('.pb_dropdown_option_list')
316
- fireEvent.click(option)
317
- const formPill = kit.querySelector(".pb_form_pill_kit_primary")
318
- expect(formPill).toBeInTheDocument()
319
- })
320
-
321
- test("multiSelect and autocomplete to work together", () => {
322
- render (
323
- <Dropdown
324
- autocomplete
325
- data={{ testid: testId }}
326
- multiSelect
327
- options={options}
328
- />
329
- )
330
-
331
- const kit = screen.getByTestId(testId)
332
- const input = kit.querySelector('.dropdown_input')
333
- expect(input).toBeInTheDocument()
334
- const option = kit.querySelector('.pb_dropdown_option_list')
335
- fireEvent.click(option)
336
- const formPill = kit.querySelector(".pb_form_pill_kit_primary")
337
- expect(formPill).toBeInTheDocument()
338
- })
339
-
340
- test("renders form pills with size and color", () => {
341
- render(
342
- <Dropdown
343
- data={{ testid: testId }}
344
- formPillProps={{ size: "small", color: "neutral" }}
345
- multiSelect
346
- options={options}
347
- />
348
- );
349
-
350
- const kit = screen.getByTestId(testId)
351
- const option = kit.querySelector('.pb_dropdown_option_list')
352
- fireEvent.click(option)
353
- const formPill = kit.querySelector(".pb_form_pill_kit_neutral")
354
- expect(formPill).toBeInTheDocument()
355
- expect(formPill).toHaveClass("small")
356
- })
357
-
358
- test("defaultValue works with multiSelect", () => {
359
- render(
360
- <Dropdown
361
- data={{ testid: testId }}
362
- defaultValue={[options[0], options[2]]}
363
- multiSelect
364
- options={options}
365
- />
366
- )
367
- const kit = screen.getByTestId(testId)
368
- expect(kit.querySelectorAll(".pb_form_pill_kit_primary")).toHaveLength(2)
369
- const option2 = Array.from(kit.querySelectorAll(".pb_dropdown_option_list"));
370
- const firstOpt = options[0].label
371
- expect(option2[0]).not.toHaveTextContent(firstOpt)
372
- })
266
+ })
@@ -115,7 +115,6 @@ export default class PbDropdown extends PbEnhancedElement {
115
115
 
116
116
  handleSearch(term = "") {
117
117
  const lcTerm = term.toLowerCase();
118
- let hasMatch = false
119
118
  this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
120
119
  //make it so that if the option is selected, it will not show up in the search results
121
120
  if (this.isMultiSelect && this.selectedOptions.has(opt.dataset.dropdownOptionLabel)) {
@@ -129,32 +128,9 @@ export default class PbDropdown extends PbEnhancedElement {
129
128
  // hide or show option
130
129
  const match = label.includes(lcTerm);
131
130
  opt.style.display = match ? "" : "none";
132
- if (match) hasMatch = true
133
131
  });
134
132
 
135
133
  this.adjustDropdownHeight();
136
-
137
- this.removeNoOptionsMessage()
138
- if (!hasMatch) {
139
- this.showNoOptionsMessage()
140
- }
141
- }
142
-
143
- showNoOptionsMessage() {
144
- if (this.element.querySelector(".dropdown_no_options")) return;
145
-
146
- const noOptionElement = document.createElement("div");
147
- noOptionElement.className = "pb_body_kit_light dropdown_no_options pb_item_kit p_xs display_flex justify_content_center";
148
- noOptionElement.textContent = "no option";
149
-
150
- this.target.appendChild(noOptionElement);
151
- }
152
-
153
- removeNoOptionsMessage() {
154
- const existing = this.element.querySelector(".dropdown_no_options");
155
- if (existing) {
156
- existing.remove();
157
- }
158
134
  }
159
135
 
160
136
  handleOptionClick(event) {
@@ -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 {
@@ -56,17 +56,16 @@ const DropdownOption = (props: DropdownOptionProps) => {
56
56
 
57
57
  // When multiSelect, then if an option is selected, remove from dropdown
58
58
  const isSelected = Array.isArray(selected)
59
- ? selected.some((item) => item.label === option?.label)
60
- : (selected as GenericObject)?.label === option?.label;
59
+ ? selected.some((item) => item.label === option?.label)
60
+ : (selected as GenericObject)?.label === option?.label;
61
61
 
62
+
62
63
  if (!isItemMatchingFilter(option) || (multiSelect && isSelected)) {
63
64
  return null;
64
65
  }
65
-
66
66
  const isFocused =
67
67
  focusedOptionIndex >= 0 &&
68
68
  filteredOptions[focusedOptionIndex].label === option?.label;
69
-
70
69
  const focusedClass = isFocused && "focused";
71
70
 
72
71
  const selectedClass = isSelected ? "selected" : "list";
@@ -92,10 +91,7 @@ const DropdownOption = (props: DropdownOptionProps) => {
92
91
  className={classes}
93
92
  id={id}
94
93
  key={key}
95
- onClick={(e) => {
96
- e.stopPropagation();
97
- handleOptionClick(option);
98
- }}
94
+ onClick= {() => handleOptionClick(option)}
99
95
  >
100
96
  <ListItem
101
97
  cursor="pointer"
@@ -104,12 +100,12 @@ const DropdownOption = (props: DropdownOptionProps) => {
104
100
  key={option?.label}
105
101
  padding="none"
106
102
  >
107
- {children ?
103
+ {children ?
108
104
  <div className="dropdown_option_wrapper">{children}</div> :
109
- <Body dark={dark}
110
- text={option?.label}
111
- />
112
- }
105
+ <Body dark={dark}
106
+ text={option?.label}
107
+ />
108
+ }
113
109
  </ListItem>
114
110
  </div>
115
111
  );