playbook_ui 17.2.0.pre.rc.0 → 17.2.0.pre.rc.1

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +9 -18
  3. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.json +0 -2
  4. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.overrides.json +1 -2
  5. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +0 -6
  6. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +0 -2
  7. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +1 -13
  8. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +2 -205
  9. data/app/pb_kits/playbook/pb_dropdown/index.js +1 -240
  10. data/app/pb_kits/playbook/pb_dropdown/kit.schema.json +6 -40
  11. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +2 -2
  12. data/app/pb_kits/playbook/pb_table/docs/_sections.yml +1 -0
  13. data/app/pb_kits/playbook/pb_table/docs/example.yml +11 -11
  14. data/dist/chunks/vendor.js +1 -1
  15. data/dist/playbook-rails.js +1 -1
  16. data/lib/playbook/version.rb +1 -1
  17. metadata +24 -35
  18. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_dynamic_options.html.erb +0 -34
  19. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_dynamic_options.md +0 -4
  20. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_dynamic_options_with_autocomplete.html.erb +0 -35
  21. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_dynamic_options_with_autocomplete.md +0 -1
  22. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_dynamic_options_with_multi_select.html.erb +0 -35
  23. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_dynamic_options_with_multi_select.md +0 -1
  24. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_react_hook.jsx +0 -45
  25. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_react_hook.md +0 -1
  26. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_react_hook.jsx +0 -36
  27. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_react_hook.md +0 -1
  28. data/app/pb_kits/playbook/pb_dropdown/dropdown_index.test.js +0 -372
  29. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_column_rails.html.erb → _table_alignment_column.html.erb} +0 -0
  30. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_column.md → _table_alignment_column_react.md} +0 -0
  31. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_row_rails.html.erb → _table_alignment_row.html.erb} +0 -0
  32. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_row.md → _table_alignment_row_react.md} +0 -0
  33. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_shift_data_rails.html.erb → _table_alignment_shift_data.html.erb} +0 -0
  34. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_shift_data.md → _table_alignment_shift_data_react.md} +0 -0
  35. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_shift_row_rails.html.erb → _table_alignment_shift_row.html.erb} +0 -0
  36. /data/app/pb_kits/playbook/pb_table/docs/{_table_alignment_shift_row.md → _table_alignment_shift_row_react.md} +0 -0
  37. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_custom_content_rails.html.erb → _table_with_collapsible_with_custom_content.html.erb} +0 -0
  38. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_custom_content.md → _table_with_collapsible_with_custom_content_react.md} +0 -0
  39. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_nested_rows_rails.html.erb → _table_with_collapsible_with_nested_rows.html.erb} +0 -0
  40. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_nested_rows.md → _table_with_collapsible_with_nested_rows_react.md} +0 -0
  41. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_nested_table_rails.html.erb → _table_with_collapsible_with_nested_table.html.erb} +0 -0
  42. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_collapsible_with_nested_table.md → _table_with_collapsible_with_nested_table_react.md} +0 -0
  43. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_filter_variant_rails.html.erb → _table_with_filter_variant.html.erb} +0 -0
  44. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_filter_variant.md → _table_with_filter_variant_react.md} +0 -0
  45. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_filter_variant_with_pagination_rails.html.erb → _table_with_filter_variant_with_pagination.html.erb} +0 -0
  46. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_filter_variant_with_pagination.md → _table_with_filter_variant_with_pagination_react.md} +0 -0
  47. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_filter_with_card_title_props_rails.html.erb → _table_with_filter_with_card_title_props.html.erb} +0 -0
  48. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_filter_with_card_title_props.md → _table_with_filter_with_card_title_props_react.md} +0 -0
  49. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_subcomponents_rails.html.erb → _table_with_subcomponents.html.erb} +0 -0
  50. /data/app/pb_kits/playbook/pb_table/docs/{_table_with_subcomponents.md → _table_with_subcomponents_react.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02e9d48053efc7bc4dde6c77d9b396a21e3b35f8343a35eb334f816c5e7423f8
4
- data.tar.gz: a275c089998b99dfd64fb86754fd9db545214fb12bde587411e8100cedb1bf88
3
+ metadata.gz: b0cfdd29dff7aa690ffa80f529b880a467df847de2897b20978f15aee42493f9
4
+ data.tar.gz: efe2a6be9fa5b594a9ec8cf3dba4085b7bbc3b6e0ce181a60710b0e760165640
5
5
  SHA512:
6
- metadata.gz: d0dc9ada45182473c6d16c6f04b3a961ab99dfc02f8c476ed274ffec5ae0b44df9836fc598b123a44cf5f02d43d420efd63ca5253ef4fa18b20835b23eada81d
7
- data.tar.gz: e794e5364b4ac28a62091f95be02f5ed01e8c5108fbfd86ee70cd11bee5d58241688ec797a8c2576ba591f7379cbfb2ff9a8ebe7aad5834e1e5d5f2ccfd7b599
6
+ metadata.gz: d1000f4e35e8953cbeff95dba2a55f2373c594320e00fc58ac8436eded89a5eb9f5383c85600bf3d747d71148182841ab2a1c5f4124581b5b03596813ea0b353
7
+ data.tar.gz: '068ba2587e7d290077532454b72d6b6cddefa2d919834bc41329259a010b70535ab6ab0636a846973f3c436d6f6cc259a1fb455edade7989f352b15e76c3543d'
@@ -112,8 +112,6 @@ type DropdownProps = {
112
112
  isClosed?: boolean;
113
113
  label?: string;
114
114
  multiSelect?: boolean;
115
- name?: string;
116
- onChange?: (event: { target: { name?: string; value: any } }) => void;
117
115
  onSelect?: (arg: GenericObject) => null;
118
116
  options?: GenericObject;
119
117
  placeholder?: string;
@@ -158,8 +156,6 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
158
156
  label,
159
157
  multiSelect = false,
160
158
  formPillProps,
161
- name,
162
- onChange,
163
159
  onSelect,
164
160
  options,
165
161
  placeholder,
@@ -418,10 +414,6 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
418
414
  setIsDropDownClosed(false);
419
415
  };
420
416
 
421
- const handleSelectionChange = (value: any) => {
422
- onSelect && onSelect(value);
423
- onChange && onChange({ target: { name, value } });
424
- };
425
417
 
426
418
  const handleOptionClick = (clickedItem: GenericObject) => {
427
419
  if (disabled) return;
@@ -434,7 +426,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
434
426
  const next = exists
435
427
  ? list.filter((option) => option.value !== clickedItem.value)
436
428
  : [...list, clickedItem];
437
- handleSelectionChange(next);
429
+ onSelect && onSelect(next);
438
430
  return next;
439
431
  });
440
432
  setFilterItem("");
@@ -447,7 +439,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
447
439
  if (shouldCloseOnClick) {
448
440
  setIsDropDownClosed(true);
449
441
  }
450
- handleSelectionChange(clickedItem);
442
+ onSelect && onSelect(clickedItem);
451
443
 
452
444
  // Sync with DatePickers if this is a quickpick variant
453
445
  if (variant === "quickpick" && Array.isArray(clickedItem.value)) {
@@ -476,10 +468,10 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
476
468
  if (disabled) return;
477
469
  if (multiSelect) {
478
470
  setSelected([]);
479
- handleSelectionChange([]);
471
+ onSelect && onSelect([]);
480
472
  } else {
481
473
  setSelected({});
482
- handleSelectionChange(null);
474
+ onSelect && onSelect(null);
483
475
  setFocusedOptionIndex(-1);
484
476
  setFilterItem("");
485
477
 
@@ -513,10 +505,10 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
513
505
  clearSelected: () => {
514
506
  if (multiSelect) {
515
507
  setSelected([]);
516
- handleSelectionChange([]);
508
+ onSelect && onSelect([]);
517
509
  } else {
518
510
  setSelected({});
519
- handleSelectionChange(null);
511
+ onSelect && onSelect(null);
520
512
  }
521
513
  setFilterItem("");
522
514
  setIsDropDownClosed(true);
@@ -530,16 +522,16 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
530
522
  clearSelected: () => {
531
523
  if (multiSelect) {
532
524
  setSelected([]);
533
- handleSelectionChange([]);
525
+ onSelect && onSelect([]);
534
526
  } else {
535
527
  setSelected({});
536
- handleSelectionChange(null);
528
+ onSelect && onSelect(null);
537
529
  }
538
530
  setFilterItem("");
539
531
  setIsDropDownClosed(true);
540
532
  },
541
533
  };
542
- }, [multiSelect, handleSelectionChange, setSelected, setFilterItem, setIsDropDownClosed]);
534
+ }, [multiSelect, onSelect, setSelected, setFilterItem, setIsDropDownClosed]);
543
535
 
544
536
  useImperativeHandle(ref, () => imperativeRef.current);
545
537
 
@@ -602,7 +594,6 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
602
594
  handleBackspace,
603
595
  handleChange,
604
596
  handleOptionClick,
605
- handleSelectionChange,
606
597
  handleWrapperClick,
607
598
  inputRef,
608
599
  inputWrapperRef,
@@ -88,7 +88,6 @@
88
88
  "name": "Content",
89
89
  "props": [
90
90
  "label",
91
- "name",
92
91
  "placeholder",
93
92
  "options",
94
93
  "defaultValue",
@@ -131,7 +130,6 @@
131
130
  {
132
131
  "name": "Events",
133
132
  "props": [
134
- "onChange",
135
133
  "onSelect"
136
134
  ]
137
135
  }
@@ -70,7 +70,6 @@
70
70
  "name": "Content",
71
71
  "props": [
72
72
  "label",
73
- "name",
74
73
  "placeholder",
75
74
  "options",
76
75
  "defaultValue",
@@ -112,7 +111,7 @@
112
111
  },
113
112
  {
114
113
  "name": "Events",
115
- "props": ["onChange", "onSelect"]
114
+ "props": ["onSelect"]
116
115
  }
117
116
  ],
118
117
  "presets": [
@@ -39,9 +39,6 @@ examples:
39
39
  - dropdown_disabled: Disabled Input
40
40
  - dropdown_grouped_options: Grouped Options
41
41
  - dropdown_custom_event_type: Custom Event Type
42
- - dropdown_dynamic_options: Dynamic Options
43
- - dropdown_dynamic_options_with_autocomplete: Dynamic Options with Autocomplete
44
- - dropdown_dynamic_options_with_multi_select: Dynamic Options with Multi Select
45
42
 
46
43
  react:
47
44
  - dropdown_default: Default
@@ -84,6 +81,3 @@ examples:
84
81
  - dropdown_required_indicator: Required Indicator
85
82
  - dropdown_disabled: Disabled Input
86
83
  - dropdown_grouped_options: Grouped Options
87
- - dropdown_react_hook: React Hook
88
- - dropdown_multi_select_react_hook: React Hook Multi Select
89
-
@@ -1,6 +1,4 @@
1
1
  export { default as DropdownDefault } from './_dropdown_default.jsx'
2
- export { default as DropdownReactHook } from './_dropdown_react_hook.jsx'
3
- export { default as DropdownMultiSelectReactHook } from './_dropdown_multi_select_react_hook.jsx'
4
2
  export { default as DropdownWithCustomDisplay } from './_dropdown_with_custom_display.jsx'
5
3
  export { default as DropdownWithCustomOptions } from './_dropdown_with_custom_options.jsx'
6
4
  export { default as DropdownWithCustomTrigger } from './_dropdown_with_custom_trigger.jsx'
@@ -59,14 +59,6 @@ module Playbook
59
59
  default: false
60
60
  prop :custom_event_type, type: Playbook::Props::String,
61
61
  default: ""
62
- prop :options_by_context, type: Playbook::Props::HashProp,
63
- default: {}
64
- prop :context_selector, type: Playbook::Props::String,
65
- default: ""
66
- prop :clear_on_context_change, type: Playbook::Props::Boolean,
67
- default: true
68
- prop :options_event_type, type: Playbook::Props::String,
69
- default: ""
70
62
 
71
63
  def data
72
64
  Hash(prop(:data)).merge(
@@ -81,11 +73,7 @@ module Playbook
81
73
  end_date_id: variant == "quickpick" ? end_date_id : nil,
82
74
  controls_start_id: variant == "quickpick" && controls_start_id.present? ? controls_start_id : nil,
83
75
  controls_end_id: variant == "quickpick" && controls_end_id.present? ? controls_end_id : nil,
84
- custom_event_type: custom_event_type.presence,
85
- pb_dropdown_options_by_context: options_by_context.present? ? options_by_context.to_json : nil,
86
- pb_dropdown_context_selector: context_selector.presence,
87
- pb_dropdown_clear_on_context_change: clear_on_context_change,
88
- options_event_type: options_event_type.presence
76
+ custom_event_type: custom_event_type.presence
89
77
  ).compact
90
78
  end
91
79
 
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from "react"
2
- import { render, screen, fireEvent, waitFor, act } from "../utilities/test-utils"
2
+ import { render, screen, fireEvent, waitFor } from "../utilities/test-utils"
3
3
 
4
4
  import { Dropdown, Icon, IconCircle } from 'playbook-ui'
5
5
  import DateTime from "../pb_kit/dateTime.ts"
@@ -995,207 +995,4 @@ test('disabled prop disables autocomplete input', () => {
995
995
  const input = kit.querySelector('.dropdown_input')
996
996
 
997
997
  expect(input).toBeDisabled()
998
- })
999
-
1000
- test('onChange uses react-hook-form event shape', () => {
1001
- const onChange = jest.fn()
1002
-
1003
- render(
1004
- <Dropdown
1005
- data={{ testid: testId }}
1006
- name="color"
1007
- onChange={onChange}
1008
- options={options}
1009
- />
1010
- )
1011
-
1012
- const kit = screen.getByTestId(testId)
1013
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1014
-
1015
- expect(onChange).toHaveBeenCalledWith({
1016
- target: { name: 'color', value: options[0] },
1017
- })
1018
- })
1019
-
1020
- test('react-hook-form onChange receives selected options for multiSelect', () => {
1021
- const onChange = jest.fn()
1022
-
1023
- render(
1024
- <Dropdown
1025
- data={{ testid: testId }}
1026
- multiSelect
1027
- name="languages"
1028
- onChange={onChange}
1029
- options={options}
1030
- />
1031
- )
1032
-
1033
- const kit = screen.getByTestId(testId)
1034
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1035
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1036
-
1037
- expect(onChange.mock.calls[0][0]).toEqual({
1038
- target: { name: 'languages', value: [options[0]] },
1039
- })
1040
- expect(onChange.mock.calls[1][0]).toEqual({
1041
- target: { name: 'languages', value: [options[0], options[1]] },
1042
- })
1043
- })
1044
-
1045
- test('onSelect still fires when onChange is provided', () => {
1046
- const onSelect = jest.fn()
1047
- const onChange = jest.fn()
1048
-
1049
- render(
1050
- <Dropdown
1051
- data={{ testid: testId }}
1052
- name="country"
1053
- onChange={onChange}
1054
- onSelect={onSelect}
1055
- options={options}
1056
- />
1057
- )
1058
-
1059
- const kit = screen.getByTestId(testId)
1060
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1061
-
1062
- expect(onSelect).toHaveBeenCalledWith(options[0])
1063
- expect(onChange).toHaveBeenCalledWith({
1064
- target: { name: 'country', value: options[0] },
1065
- })
1066
- })
1067
-
1068
- test('onSelect-only single select still receives the option object', () => {
1069
- const onSelect = jest.fn()
1070
-
1071
- render(
1072
- <Dropdown
1073
- data={{ testid: testId }}
1074
- onSelect={onSelect}
1075
- options={options}
1076
- />
1077
- )
1078
-
1079
- const kit = screen.getByTestId(testId)
1080
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1081
-
1082
- expect(onSelect).toHaveBeenCalledTimes(1)
1083
- expect(onSelect).toHaveBeenCalledWith(options[0])
1084
- })
1085
-
1086
- test('onSelect-only multiSelect still receives the selected options array', () => {
1087
- const onSelect = jest.fn()
1088
-
1089
- render(
1090
- <Dropdown
1091
- data={{ testid: testId }}
1092
- multiSelect
1093
- onSelect={onSelect}
1094
- options={options}
1095
- />
1096
- )
1097
-
1098
- const kit = screen.getByTestId(testId)
1099
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1100
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[0])
1101
-
1102
- expect(onSelect.mock.calls[0][0]).toEqual([options[0]])
1103
- expect(onSelect.mock.calls[1][0]).toEqual([options[0], options[1]])
1104
- })
1105
-
1106
- test('onSelect-only clearSelected still receives null', () => {
1107
- const onSelect = jest.fn()
1108
- const dropdownRef = React.createRef()
1109
-
1110
- render(
1111
- <Dropdown
1112
- data={{ testid: testId }}
1113
- defaultValue={options[0]}
1114
- onSelect={onSelect}
1115
- options={options}
1116
- ref={dropdownRef}
1117
- />
1118
- )
1119
-
1120
- act(() => {
1121
- dropdownRef.current.clearSelected()
1122
- })
1123
-
1124
- expect(onSelect).toHaveBeenCalledWith(null)
1125
- })
1126
-
1127
- test('onSelect-only clear icon still receives null', () => {
1128
- const onSelect = jest.fn()
1129
-
1130
- render(
1131
- <Dropdown
1132
- data={{ testid: testId }}
1133
- defaultValue={options[0]}
1134
- onSelect={onSelect}
1135
- options={options}
1136
- />
1137
- )
1138
-
1139
- const kit = screen.getByTestId(testId)
1140
- fireEvent.click(kit.querySelector('[aria-label="times icon"]').closest('div'))
1141
-
1142
- expect(onSelect).toHaveBeenCalledWith(null)
1143
- })
1144
-
1145
- test('onSelect-only removing a multiSelect pill still receives remaining options', () => {
1146
- const onSelect = jest.fn()
1147
-
1148
- render(
1149
- <Dropdown
1150
- data={{ testid: testId }}
1151
- defaultValue={[options[0], options[1]]}
1152
- multiSelect
1153
- onSelect={onSelect}
1154
- options={options}
1155
- />
1156
- )
1157
-
1158
- const kit = screen.getByTestId(testId)
1159
- fireEvent.click(kit.querySelector('.pb_form_pill_close'))
1160
-
1161
- expect(onSelect).toHaveBeenCalledWith([options[1]])
1162
- })
1163
-
1164
- test('autocomplete typing does not fire onSelect or onChange', () => {
1165
- const onSelect = jest.fn()
1166
- const onChange = jest.fn()
1167
-
1168
- render(
1169
- <Dropdown
1170
- autocomplete
1171
- data={{ testid: testId }}
1172
- onChange={onChange}
1173
- onSelect={onSelect}
1174
- options={options}
1175
- />
1176
- )
1177
-
1178
- const kit = screen.getByTestId(testId)
1179
- fireEvent.change(kit.querySelector('.dropdown_input'), { target: { value: 'Can' } })
1180
-
1181
- expect(onSelect).not.toHaveBeenCalled()
1182
- expect(onChange).not.toHaveBeenCalled()
1183
- })
1184
-
1185
- test('autocomplete selection still fires onSelect', () => {
1186
- const onSelect = jest.fn()
1187
-
1188
- render(
1189
- <Dropdown
1190
- autocomplete
1191
- data={{ testid: testId }}
1192
- onSelect={onSelect}
1193
- options={options}
1194
- />
1195
- )
1196
-
1197
- const kit = screen.getByTestId(testId)
1198
- fireEvent.click(kit.querySelectorAll('.pb_dropdown_option_list')[1])
1199
-
1200
- expect(onSelect).toHaveBeenCalledWith(options[1])
1201
- })
998
+ })
@@ -162,8 +162,6 @@ export default class PbDropdown extends PbEnhancedElement {
162
162
  const baseInput = this.baseInput;
163
163
  this.wasOriginallyRequired =
164
164
  baseInput && baseInput.hasAttribute("required");
165
- // Apply context options before default value so SSR/default selection matches current context
166
- this.bindContextSelector();
167
165
  this.setDefaultValue();
168
166
  this.bindEventListeners();
169
167
  this.bindSearchInput();
@@ -186,13 +184,11 @@ export default class PbDropdown extends PbEnhancedElement {
186
184
  this.updateClearButton();
187
185
  this.applyDisabledState();
188
186
 
189
- // Listen for clear, select, and updateOptions events from external source
187
+ // Listen for clear and select events from external source
190
188
  this.handleClearEventBound = this.handleClearEvent.bind(this);
191
189
  document.addEventListener("pb:dropdown:clear", this.handleClearEventBound);
192
190
  this.handleSelectEventBound = this.handleSelectEvent.bind(this);
193
191
  document.addEventListener("pb:dropdown:select", this.handleSelectEventBound);
194
- this.handleUpdateOptionsEventBound = this.handleUpdateOptionsEvent.bind(this);
195
- document.addEventListener("pb:dropdown:updateOptions", this.handleUpdateOptionsEventBound);
196
192
 
197
193
  // Listen for custom_event_type to clear on custom events
198
194
  const customEventTypeString = this.element.dataset.customEventType;
@@ -206,19 +202,6 @@ export default class PbDropdown extends PbEnhancedElement {
206
202
  document.addEventListener(eventType, this.handleCustomClearBound);
207
203
  });
208
204
  }
209
-
210
- // Listen for options_event_type to replace options on custom/Turbo events
211
- const optionsEventTypeString = this.element.dataset.optionsEventType;
212
- if (optionsEventTypeString) {
213
- this.optionsEventTypes = optionsEventTypeString
214
- .split(",")
215
- .map((e) => e.trim())
216
- .filter(Boolean);
217
- this.handleOptionsEventTypeBound = this.handleOptionsEventType.bind(this);
218
- this.optionsEventTypes.forEach((eventType) => {
219
- document.addEventListener(eventType, this.handleOptionsEventTypeBound);
220
- });
221
- }
222
205
  }
223
206
 
224
207
  disconnect() {
@@ -280,22 +263,11 @@ export default class PbDropdown extends PbEnhancedElement {
280
263
  if (this.handleSelectEventBound) {
281
264
  document.removeEventListener("pb:dropdown:select", this.handleSelectEventBound)
282
265
  }
283
- if (this.handleUpdateOptionsEventBound) {
284
- document.removeEventListener("pb:dropdown:updateOptions", this.handleUpdateOptionsEventBound)
285
- }
286
266
  if (this.customClearEventTypes && this.handleCustomClearBound) {
287
267
  this.customClearEventTypes.forEach((eventType) => {
288
268
  document.removeEventListener(eventType, this.handleCustomClearBound)
289
269
  })
290
270
  }
291
- if (this.optionsEventTypes && this.handleOptionsEventTypeBound) {
292
- this.optionsEventTypes.forEach((eventType) => {
293
- document.removeEventListener(eventType, this.handleOptionsEventTypeBound)
294
- })
295
- }
296
- if (this.contextElement && this.handleContextChangeBound) {
297
- this.contextElement.removeEventListener("change", this.handleContextChangeBound)
298
- }
299
271
  }
300
272
 
301
273
  updateClearButton() {
@@ -658,217 +630,6 @@ export default class PbDropdown extends PbEnhancedElement {
658
630
  }
659
631
 
660
632
  // ----- External events handling section -----
661
-
662
- get optionsByContext() {
663
- return this.element.dataset.pbDropdownOptionsByContext
664
- ? JSON.parse(this.element.dataset.pbDropdownOptionsByContext)
665
- : null;
666
- }
667
-
668
- get contextElement() {
669
- const selector = this.element.dataset.pbDropdownContextSelector;
670
- if (!selector) return null;
671
-
672
- return (
673
- this.element.parentNode?.querySelector(`#${CSS.escape(selector)}`) ||
674
- this.element.closest(`#${CSS.escape(selector)}`) ||
675
- document.getElementById(selector)
676
- );
677
- }
678
-
679
- get clearOnContextChange() {
680
- return this.element.dataset.pbDropdownClearOnContextChange !== "false";
681
- }
682
-
683
- bindContextSelector() {
684
- const contextEl = this.contextElement;
685
- if (!contextEl || !this.optionsByContext) return;
686
-
687
- this.handleContextChangeBound = this.handleContextChange.bind(this);
688
- contextEl.addEventListener("change", this.handleContextChangeBound);
689
-
690
- // Sync to the current context value on connect (default/restored select), without clearing
691
- this.applyOptionsForCurrentContext({ clearSelection: false });
692
- }
693
-
694
- applyOptionsForCurrentContext({ clearSelection } = {}) {
695
- if (this.isDisabled || !this.optionsByContext) return;
696
-
697
- const options = this.optionsByContext[this.contextElement?.value] || [];
698
- this.replaceOptions(options, {
699
- clearSelection:
700
- clearSelection != null ? clearSelection : this.clearOnContextChange,
701
- });
702
- }
703
-
704
- handleContextChange() {
705
- this.applyOptionsForCurrentContext();
706
- }
707
-
708
- normalizeOption(option) {
709
- const normalized = { ...option };
710
- if (normalized.id == null && normalized.value != null) {
711
- normalized.id = normalized.value;
712
- }
713
- if (normalized.value == null && normalized.id != null) {
714
- normalized.value = normalized.id;
715
- }
716
- return normalized;
717
- }
718
-
719
- getOptionsParent() {
720
- const container = this.target;
721
- if (!container) return null;
722
-
723
- return container.querySelector(".pb_list_kit") || container;
724
- }
725
-
726
- buildOptionElement(option) {
727
- const normalized = this.normalizeOption(option);
728
- const disabled = normalized.disabled === true;
729
- const optionEl = document.createElement("div");
730
- optionEl.className = `pb_dropdown_option_list${disabled ? " disabled" : ""}`;
731
- if (normalized.id != null && normalized.id !== "") {
732
- optionEl.id = String(normalized.id);
733
- }
734
- optionEl.setAttribute("aria-disabled", disabled ? "true" : "false");
735
- optionEl.dataset.dropdownOptionLabel = JSON.stringify(normalized);
736
- optionEl.dataset.dropdownOptionDisabled = disabled ? "true" : "false";
737
-
738
- const listItem = document.createElement("div");
739
- listItem.className =
740
- "pb_list_item_kit display_flex justify_content_center p_none cursor_pointer";
741
-
742
- const wrapper = document.createElement("div");
743
- wrapper.className = disabled
744
- ? "dropdown_option_wrapper disabled"
745
- : "dropdown_option_wrapper";
746
-
747
- const body = document.createElement("div");
748
- body.className = "pb_body_kit_light";
749
- body.textContent =
750
- normalized.label != null ? String(normalized.label) : "";
751
-
752
- wrapper.appendChild(body);
753
- listItem.appendChild(wrapper);
754
- optionEl.appendChild(listItem);
755
-
756
- return optionEl;
757
- }
758
-
759
- replaceOptions(options, { clearSelection = true } = {}) {
760
- if (this.isDisabled || !Array.isArray(options)) return;
761
-
762
- const parent = this.getOptionsParent();
763
- if (!parent) return;
764
-
765
- // Clear option nodes and any SSR empty-state ("No option") placeholder
766
- parent.replaceChildren();
767
- this.removeNoOptionsMessage();
768
-
769
- options.forEach((option) => {
770
- parent.appendChild(this.buildOptionElement(option));
771
- });
772
-
773
- // Clear typed filters and keyboard focus so new options aren't left unfiltered /
774
- // focused against stale indexes from the previous list
775
- this.resetInteractiveOptionState();
776
-
777
- if (clearSelection) {
778
- this.clearSelection();
779
- } else {
780
- this.reconcileSelectionWithOptions();
781
- }
782
-
783
- if (this.target?.classList.contains("open")) {
784
- this.adjustDropdownHeight();
785
- }
786
- }
787
-
788
- resetInteractiveOptionState() {
789
- this.resetFocus();
790
-
791
- if (this.searchBar) {
792
- this.searchBar.value = "";
793
- }
794
-
795
- if (this.searchInput) {
796
- this.searchInput.value = "";
797
- }
798
- }
799
-
800
- reconcileSelectionWithOptions() {
801
- const optionEls = Array.from(this.queryAllOptions());
802
- const optionsById = new Map();
803
- optionEls.forEach((opt) => {
804
- try {
805
- const optionData = JSON.parse(opt.dataset.dropdownOptionLabel);
806
- if (optionData?.id != null) {
807
- optionsById.set(optionData.id, opt);
808
- }
809
- } catch {
810
- // ignore invalid option payloads
811
- }
812
- });
813
-
814
- if (this.isMultiSelect) {
815
- const keptIds = Array.from(this.selectedOptions)
816
- .map((raw) => {
817
- try {
818
- return JSON.parse(raw).id;
819
- } catch {
820
- return null;
821
- }
822
- })
823
- .filter((id) => id != null && optionsById.has(id));
824
-
825
- if (keptIds.length === 0) {
826
- this.clearSelection();
827
- return;
828
- }
829
-
830
- // Rebuild from current option payloads so labels/values stay in sync
831
- this.setSelectionByOptionIds(keptIds);
832
- return;
833
- }
834
-
835
- const currentId = this.baseInput?.value;
836
- if (!currentId || !optionsById.has(currentId)) {
837
- this.clearSelection();
838
- return;
839
- }
840
-
841
- // Re-apply selection so trigger/autocomplete use the updated option payload
842
- this.setSelectionByOptionId(currentId);
843
- }
844
-
845
- // Handles pb:dropdown:updateOptions - replace options when event.detail.dropdownId matches.
846
- // detail: { dropdownId, options: [{ id, label, value }], clearSelection?: boolean }
847
- handleUpdateOptionsEvent(event) {
848
- if (this.isDisabled) return;
849
- const targetId = event.detail?.dropdownId;
850
- if (!targetId || this.element.id !== targetId) return;
851
-
852
- const options = event.detail?.options;
853
- if (!Array.isArray(options)) return;
854
-
855
- const clearSelection = event.detail?.clearSelection !== false;
856
- this.replaceOptions(options, { clearSelection });
857
- }
858
-
859
- // Handles options_event_type events - replace options when detail.options is present.
860
- handleOptionsEventType(event) {
861
- if (this.isDisabled) return;
862
- const targetId = event.detail?.dropdownId;
863
- if (targetId != null && this.element.id !== targetId) return;
864
-
865
- const options = event.detail?.options;
866
- if (!Array.isArray(options)) return;
867
-
868
- const clearSelection = event.detail?.clearSelection !== false;
869
- this.replaceOptions(options, { clearSelection });
870
- }
871
-
872
633
  // Handles pb:dropdown:clear - clear this dropdown when event.detail.dropdownId matches.
873
634
  handleClearEvent(event) {
874
635
  if (this.isDisabled) return;