playbook_ui 14.20.0.pre.alpha.PLAY2140upgraderailsdependency8086 → 14.20.0.pre.alpha.PLAY2170checkboxrailsindeterminatelogicinkitPOC7980

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +1 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +49 -116
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +1 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +2 -58
  6. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +4 -16
  8. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +3 -7
  9. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +0 -40
  10. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +3 -13
  11. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +1 -7
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +0 -61
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +1 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -6
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -3
  16. data/app/pb_kits/playbook/pb_advanced_table/index.js +0 -2
  17. data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -1
  18. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +0 -7
  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/index.js +0 -24
  24. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +10 -14
  25. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +15 -26
  26. data/app/pb_kits/playbook/pb_popover/index.ts +4 -9
  27. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +51 -3
  28. data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +1 -1
  29. data/dist/chunks/{_typeahead-CoOpeYom.js → _typeahead-CRW6dJbW.js} +1 -1
  30. data/dist/chunks/_weekday_stacked-C4d17aYW.js +45 -0
  31. data/dist/chunks/{lib-D7Va7yqa.js → lib-D5R1BjUn.js} +1 -1
  32. data/dist/chunks/{pb_form_validation-DSkdRDMf.js → pb_form_validation-BZ2AVAi_.js} +1 -1
  33. data/dist/chunks/vendor.js +1 -1
  34. data/dist/playbook-doc.js +1 -1
  35. data/dist/playbook-rails-react-bindings.js +1 -1
  36. data/dist/playbook-rails.js +1 -1
  37. data/dist/playbook.css +1 -1
  38. data/lib/playbook/version.rb +1 -1
  39. metadata +6 -14
  40. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.html.erb +0 -33
  41. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +0 -57
  42. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +0 -5
  43. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.html.erb +0 -33
  44. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.jsx +0 -53
  45. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_date_display.html.erb +0 -13
  46. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +0 -42
  47. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +0 -1
  48. data/dist/chunks/_weekday_stacked-B_jpa2Rz.js +0 -45
@@ -3,12 +3,6 @@ import { render, screen, waitFor } from "../utilities/test-utils"
3
3
 
4
4
  import { AdvancedTable, Pill } from "playbook-ui"
5
5
 
6
- global.ResizeObserver = class {
7
- observe() {}
8
- unobserve() {}
9
- disconnect() {}
10
- };
11
-
12
6
  const MOCK_DATA = [
13
7
  {
14
8
  year: "2021",
@@ -78,36 +72,6 @@ const MOCK_DATA_LOADING = [
78
72
  },
79
73
  ]
80
74
 
81
- const MOCK_DATA_WITH_ID = [
82
- {
83
- id: "1",
84
- year: "2021",
85
- quarter: null,
86
- month: null,
87
- day: null,
88
- newEnrollments: "20",
89
- scheduledMeetings: "10",
90
- },
91
- {
92
- id: "2",
93
- year: "2022",
94
- quarter: null,
95
- month: null,
96
- day: null,
97
- newEnrollments: "25",
98
- scheduledMeetings: "15",
99
- },
100
- {
101
- id: "3",
102
- year: "2023",
103
- quarter: null,
104
- month: null,
105
- day: null,
106
- newEnrollments: "30",
107
- scheduledMeetings: "20",
108
- },
109
- ]
110
-
111
75
  const columnDefinitions = [
112
76
  {
113
77
  accessor: "year",
@@ -548,28 +512,3 @@ test("allowFullScreen prop adds fullscreen class", () => {
548
512
  const tableContainer = screen.getByRole("table").closest("div")
549
513
  expect(tableContainer).toHaveClass("advanced-table-allow-fullscreen")
550
514
  })
551
-
552
- test("pinnedRows prop renders pinned rows at top", () => {
553
- const pinnedRowsControl = {
554
- value: { top: ["1", "3"] },
555
- onChange: jest.fn()
556
- }
557
-
558
- render(
559
- <AdvancedTable
560
- columnDefinitions={columnDefinitions}
561
- data={{ testid: testId }}
562
- pinnedRows={pinnedRowsControl}
563
- tableData={MOCK_DATA_WITH_ID}
564
- />
565
- )
566
-
567
- const kit = screen.getByTestId(testId)
568
- const pinnedRows = kit.querySelectorAll(".pinned-row")
569
-
570
- expect(pinnedRows).toHaveLength(2)
571
-
572
- const firstPinnedRow = pinnedRows[0]
573
- expect(firstPinnedRow).toHaveStyle("position: sticky")
574
- expect(firstPinnedRow).toHaveStyle("background-color: white")
575
- })
@@ -39,6 +39,7 @@ const AdvancedTableNoSubrows = (props) => {
39
39
  <div>
40
40
  <AdvancedTable
41
41
  columnDefinitions={columnDefinitions}
42
+ enableToggleExpansion="all"
42
43
  tableData={MOCK_DATA}
43
44
  {...props}
44
45
  />
@@ -13,12 +13,10 @@ examples:
13
13
  - advanced_table_column_headers: Multi-Header Columns
14
14
  - advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
15
15
  - advanced_table_column_border_color_rails: Column Group Border Color
16
- - advanced_table_no_subrows: Table with No Subrows or Expansion
17
16
  - advanced_table_selectable_rows_rails: Selectable Rows
18
17
  - advanced_table_selectable_rows_no_subrows_rails: Selectable Rows (No Subrows)
19
18
  - advanced_table_selectable_rows_actions_rails: Selectable Rows (With Actions)
20
19
  - advanced_table_selectable_rows_header_rails: Selectable Rows (No Actions Bar)
21
- - advanced_table_scrollbar_none: Advanced Table Scrollbar None
22
20
 
23
21
  react:
24
22
  - advanced_table_default: Default (Required Props)
@@ -44,7 +42,7 @@ examples:
44
42
  - advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
45
43
  - advanced_table_column_headers_custom_cell: Multi-Header Columns with Custom Cells
46
44
  - advanced_table_column_border_color: Column Group Border Color
47
- - advanced_table_no_subrows: Table with No Subrows or Expansion
45
+ # - advanced_table_no_subrows: Table with No Subrows
48
46
  - advanced_table_selectable_rows: Selectable Rows
49
47
  - advanced_table_selectable_rows_no_subrows_react: Selectable Rows (No Subrows)
50
48
  - advanced_table_selectable_rows_actions: Selectable Rows (With Actions)
@@ -54,6 +52,4 @@ examples:
54
52
  - advanced_table_column_visibility: Column Visibility Control
55
53
  - advanced_table_column_visibility_with_state: Column Visibility Control With State
56
54
  - advanced_table_column_visibility_custom: Column Visibility Control with Custom Dropdown
57
- - advanced_table_column_visibility_multi: Column Visibility Control with Multi-Header Columns
58
- - advanced_table_pinned_rows: Pinned Rows
59
- - advanced_table_scrollbar_none: Advanced Table Scrollbar None
55
+ - advanced_table_column_visibility_multi: Column Visibility Control with Multi-Header Columns
@@ -31,6 +31,4 @@ export { default as AdvancedTableColumnBorderColor} from './_advanced_table_colu
31
31
  export { default as AdvancedTableColumnVisibility } from './_advanced_table_column_visibility.jsx'
32
32
  export { default as AdvancedTableColumnVisibilityCustom } from './_advanced_table_column_visibility_custom.jsx'
33
33
  export { default as AdvancedTableColumnVisibilityMulti } from './_advanced_table_column_visibility_multi.jsx'
34
- export { default as AdvancedTableColumnVisibilityWithState } from './_advanced_table_column_visibility_with_state.jsx'
35
- export { default as AdvancedTablePinnedRows } from './_advanced_table_pinned_rows.jsx'
36
- export { default as AdvancedTableScrollbarNone} from './_advanced_table_scrollbar_none.jsx'
34
+ export { default as AdvancedTableColumnVisibilityWithState } from './_advanced_table_column_visibility_with_state.jsx'
@@ -569,8 +569,6 @@ class PbAdvancedTableActionBar {
569
569
  actionBar.style.height = 'auto';
570
570
  actionBar.style.overflow = 'visible';
571
571
  actionBar.style.opacity = '1';
572
- actionBar.style.transitionProperty = 'all';
573
- actionBar.style.transitionTimingFunction = 'ease-in-out';
574
572
  actionBar.classList.remove("p_none");
575
573
  actionBar.classList.add("p_xs", "is-visible", "show-action-card");
576
574
 
@@ -1,4 +1,7 @@
1
- <%= pb_content_tag(:label) do %>
1
+ <%= pb_content_tag(:label, data: {
2
+ pb_checkbox_indeterminate_main: object.indeterminate_main,
3
+ pb_checkbox_indeterminate_parent: object.indeterminate_parent,
4
+ }) do %>
2
5
  <%= content.presence || object.input %>
3
6
  <span data-pb-checkbox-icon-span="true" class="pb_checkbox_checkmark">
4
7
  <%= pb_rails("icon", props: { icon: "check", classname: "check_icon", fixed_width: true}) %>
@@ -31,13 +31,6 @@ module Playbook
31
31
  error ? "negative" : nil
32
32
  end
33
33
 
34
- def data
35
- Hash(prop(:data)).merge(
36
- pb_checkbox_indeterminate_main: indeterminate_main,
37
- pb_checkbox_indeterminate_parent: indeterminate_parent
38
- )
39
- end
40
-
41
34
  private
42
35
 
43
36
  def error_class
@@ -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'
@@ -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
  );
@@ -44,7 +44,6 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
44
44
 
45
45
  const {
46
46
  autocomplete,
47
- closeOnSelection,
48
47
  filterItem,
49
48
  handleBackspace,
50
49
  handleChange,
@@ -55,7 +54,6 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
55
54
  isInputFocused,
56
55
  multiSelect,
57
56
  selected,
58
- setIsDropDownClosed,
59
57
  setIsInputFocused,
60
58
  toggleDropdown,
61
59
  } = useContext(DropdownContext);
@@ -105,26 +103,11 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
105
103
  ? placeholder
106
104
  : "Select...";
107
105
 
108
- // Click handler that respects closeOnSelection
109
- const handleInputClick = (e: React.MouseEvent) => {
110
- e.stopPropagation(); // keep the wrapper's handler from firing
111
- if (isDropDownClosed) {
112
- // Always open if closed
113
- setIsDropDownClosed(false);
114
- } else if (!closeOnSelection) {
115
- // Keep open if closeOnSelection is false
116
- return;
117
- } else {
118
- // Default behavior - toggle
119
- toggleDropdown();
120
- }
121
- };
122
-
123
106
  return (
124
- <div {...ariaProps}
125
- {...dataProps}
107
+ <div {...ariaProps}
108
+ {...dataProps}
126
109
  {...htmlProps}
127
- className={classes}
110
+ className={classes}
128
111
  id={id}
129
112
  >
130
113
  {
@@ -162,7 +145,7 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
162
145
  {customDisplay ? (
163
146
  <Flex align="center">
164
147
  {customDisplay}
165
- <Body dark={dark}
148
+ <Body dark={dark}
166
149
  paddingLeft={`${joinedLabels ? "xs" : "none"}`}
167
150
  >
168
151
  {customDisplayPlaceholder}
@@ -181,7 +164,10 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
181
164
  <input
182
165
  className="dropdown_input"
183
166
  onChange={handleChange}
184
- onClick={handleInputClick}
167
+ onClick={(e) => {
168
+ e.stopPropagation();// keep the wrapper’s handler from firing
169
+ toggleDropdown();
170
+ }}
185
171
  onFocus={() => setIsInputFocused(true)}
186
172
  onKeyDown={(e) => {
187
173
  handleKeyDown(e);
@@ -200,8 +186,8 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
200
186
  )}
201
187
  </>
202
188
  ) : (
203
- <Body dark={dark}
204
- text={defaultDisplayPlaceholder}
189
+ <Body dark={dark}
190
+ text={defaultDisplayPlaceholder}
205
191
  />
206
192
  )
207
193
  )}
@@ -209,7 +195,10 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
209
195
  <input
210
196
  className="dropdown_input"
211
197
  onChange={handleChange}
212
- onClick={handleInputClick}
198
+ onClick={(e) => {
199
+ e.stopPropagation();// keep the wrapper’s handler from firing
200
+ toggleDropdown();
201
+ }}
213
202
  onFocus={() => setIsInputFocused(true)}
214
203
  onKeyDown={handleKeyDown}
215
204
  placeholder={
@@ -234,7 +223,7 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
234
223
  onClick: (e: Event) => {e.stopPropagation();handleWrapperClick()}
235
224
  }}
236
225
  key={`${isDropDownClosed ? "chevron-down" : "chevron-up"}`}
237
- >
226
+ >
238
227
  {
239
228
  selectedArray.length > 0 && (
240
229
  <div onClick={(e)=>{e.stopPropagation();handleBackspace()}}>
@@ -13,24 +13,19 @@ export default class PbPopover extends PbEnhancedElement {
13
13
  }
14
14
 
15
15
  moveTooltip() {
16
- let container: HTMLElement | null = document.querySelector('body');
16
+ let container: HTMLElement | null;
17
17
 
18
18
  if (this.appendTo === "parent") {
19
- container = this.element.parentElement && this.element.parentElement
19
+ container = this.element.parentElement;
20
20
  } else if (this.appendTo) {
21
- container = document.querySelector(this.appendTo)
21
+ container = document.querySelector(this.appendTo);
22
22
  }
23
23
 
24
- container.appendChild(this.tooltip);
24
+ (container || document.body).appendChild(this.tooltip);
25
25
  }
26
26
 
27
27
  connect() {
28
- if (!this.triggerElement || !this.tooltip) {
29
- console.warn('Popover requires both trigger and tooltip elements to be defined.')
30
- return
31
- }
32
28
  this.moveTooltip()
33
-
34
29
  this.popper = createPopper (this.triggerElement, this.tooltip, {
35
30
  placement: this.position as Placement,
36
31
  strategy: 'fixed',