playbook_ui 16.1.0.pre.alpha.play264213817 → 16.1.0.pre.alpha.play273614090
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +12 -2
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +33 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background_custom.jsx +71 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_background_custom.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_card/docs/_card_light.html.erb +3 -35
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.scss +1 -1
- data/app/pb_kits/playbook/pb_checkbox/_checkbox.tsx +17 -0
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +10 -1
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +2 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.html.erb +6 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.jsx +17 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_checkbox/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +14 -5
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_default.md +1 -0
- data/app/pb_kits/playbook/pb_dialog/_dialog.scss +8 -6
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +6 -0
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +83 -13
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_blank_selection_rails.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_blank_selection_react.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_clearable.html.erb +52 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_clearable.jsx +72 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_clearable.md +5 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_constrain_height.jsx +33 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_constrain_height_rails.html.erb +20 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_constrain_height_rails.md +8 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_constrain_height_react.md +8 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +1 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.html.erb +6 -3
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.jsx +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.md +3 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_placeholder.html.erb +9 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_placeholder.jsx +33 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_placeholder.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +6 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +4 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +12 -6
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +15 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +94 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown_container.rb +5 -1
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +15 -10
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +4 -0
- data/app/pb_kits/playbook/pb_dropdown/index.js +191 -83
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +3 -0
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +18 -1
- data/app/pb_kits/playbook/pb_dropdown/utilities/clickOutsideHelper.tsx +6 -0
- data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.tsx +1 -1
- data/app/pb_kits/playbook/pb_filter/docs/_filter_default.html.erb +2 -2
- data/app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx +16 -9
- data/app/pb_kits/playbook/pb_filter/filter.rb +2 -2
- data/app/pb_kits/playbook/pb_form/docs/_form_with_required_indicator.html.erb +6 -2
- data/app/pb_kits/playbook/pb_form/pb_form_validation.js +9 -2
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.html.erb +5 -5
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.jsx +4 -4
- data/app/pb_kits/playbook/pb_form_pill/form_pill.rb +4 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +7 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +638 -549
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +3 -3
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +4 -7
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.md +3 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +4 -4
- data/app/pb_kits/playbook/pb_passphrase/_passphrase.tsx +40 -7
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_meter_settings.jsx +1 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_required_indicator.html.erb +7 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_required_indicator.jsx +24 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/_passphrase_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_passphrase/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_passphrase/passphrase.rb +2 -0
- data/app/pb_kits/playbook/pb_passphrase/passphrase.test.jsx +30 -1
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +3 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_required_indicator.html.erb +5 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_required_indicator.jsx +14 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +34 -3
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +51 -16
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_label.jsx +44 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_label.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_required_indicator.jsx +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_label.jsx +28 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_label.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_required_indicator.jsx +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +2 -0
- data/app/pb_kits/playbook/pb_table/index.ts +29 -27
- data/app/pb_kits/playbook/pb_text_input/text_input.html.erb +10 -10
- data/app/pb_kits/playbook/pb_textarea/_textarea.tsx +10 -0
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_default.html.erb +3 -3
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_default.jsx +3 -0
- data/app/pb_kits/playbook/pb_textarea/docs/_textarea_default.md +1 -0
- data/app/pb_kits/playbook/pb_textarea/textarea.html.erb +25 -9
- data/app/pb_kits/playbook/pb_textarea/textarea.rb +7 -1
- data/app/pb_kits/playbook/pb_time_picker/_time_picker.tsx +97 -11
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_on_handler.jsx +5 -2
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.html.erb +6 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.jsx +16 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/_time_picker_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_time_picker/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.rb +3 -0
- data/app/pb_kits/playbook/pb_time_picker/time_picker.test.jsx +47 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +24 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +412 -324
- data/app/pb_kits/playbook/pb_typeahead/components/Control.tsx +2 -0
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +4 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.html.erb +16 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.jsx +23 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_required_indicator.md +3 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.html.erb +1 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_truncated_text.jsx +1 -1
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +22 -21
- data/app/pb_kits/playbook/pb_typeahead/typeahead.html.erb +3 -2
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +7 -1
- data/dist/chunks/{_pb_line_graph-BgKF_zz1.js → _pb_line_graph-DuJNCf7N.js} +1 -1
- data/dist/chunks/_typeahead-BKSzddAX.js +1 -0
- data/dist/chunks/{globalProps-BhVYCqRf.js → globalProps-Bc-FVsRt.js} +1 -1
- data/dist/chunks/lib-BwX82vim.js +29 -0
- data/dist/chunks/vendor.js +3 -3
- data/dist/menu.yml +2 -2
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/forms/builder/form_field_builder.rb +1 -1
- data/lib/playbook/forms/builder/phone_number_field.rb +9 -0
- data/lib/playbook/forms/builder/typeahead_field.rb +15 -1
- data/lib/playbook/forms/builder.rb +2 -2
- data/lib/playbook/truncate.rb +1 -1
- data/lib/playbook/version.rb +1 -1
- metadata +42 -6
- data/dist/chunks/_typeahead-B9a6ZsEP.js +0 -1
- data/dist/chunks/lib-DD34ZrWL.js +0 -29
|
@@ -4,16 +4,18 @@ import { PbDropdownKeyboard } from "./keyboard_accessibility";
|
|
|
4
4
|
const DROPDOWN_SELECTOR = "[data-pb-dropdown]";
|
|
5
5
|
const TRIGGER_SELECTOR = "[data-dropdown-trigger]";
|
|
6
6
|
const CONTAINER_SELECTOR = "[data-dropdown-container]";
|
|
7
|
-
const DOWN_ARROW_SELECTOR = "
|
|
8
|
-
const UP_ARROW_SELECTOR = "
|
|
7
|
+
const DOWN_ARROW_SELECTOR = "[data-dropdown-open-icon]";
|
|
8
|
+
const UP_ARROW_SELECTOR = "[data-dropdown-close-icon]";
|
|
9
9
|
const OPTION_SELECTOR = "[data-dropdown-option-label]";
|
|
10
10
|
const CUSTOM_DISPLAY_SELECTOR = "[data-dropdown-custom-trigger]";
|
|
11
|
-
const DROPDOWN_TRIGGER_DISPLAY = "
|
|
11
|
+
const DROPDOWN_TRIGGER_DISPLAY = "[data-dropdown-trigger-display]";
|
|
12
12
|
const DROPDOWN_PLACEHOLDER = "[data-dropdown-placeholder]";
|
|
13
|
-
const DROPDOWN_INPUT = "
|
|
13
|
+
const DROPDOWN_INPUT = "[data-dropdown-selected-option]";
|
|
14
14
|
const SEARCH_INPUT_SELECTOR = "[data-dropdown-autocomplete]";
|
|
15
15
|
const SEARCH_BAR_SELECTOR = "[data-dropdown-search]";
|
|
16
|
-
const CLEAR_ICON_SELECTOR = "
|
|
16
|
+
const CLEAR_ICON_SELECTOR = "[data-dropdown-clear-icon]";
|
|
17
|
+
const LABEL_SELECTOR = '[data-dropdown="pb-dropdown-label"]';
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
export default class PbDropdown extends PbEnhancedElement {
|
|
19
21
|
static get selector() {
|
|
@@ -30,14 +32,15 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
30
32
|
connect() {
|
|
31
33
|
// Store instance on element for DatePicker sync
|
|
32
34
|
this.element._pbDropdownInstance = this;
|
|
33
|
-
|
|
35
|
+
|
|
34
36
|
this.keyboardHandler = new PbDropdownKeyboard(this);
|
|
35
37
|
this.isMultiSelect = this.element.dataset.pbDropdownMultiSelect === "true";
|
|
36
38
|
this.formPillProps = this.element.dataset.formPillProps
|
|
37
39
|
? JSON.parse(this.element.dataset.formPillProps)
|
|
38
40
|
: {};
|
|
39
41
|
const baseInput = this.element.querySelector(DROPDOWN_INPUT);
|
|
40
|
-
this.wasOriginallyRequired =
|
|
42
|
+
this.wasOriginallyRequired =
|
|
43
|
+
baseInput && baseInput.hasAttribute("required");
|
|
41
44
|
this.setDefaultValue();
|
|
42
45
|
this.bindEventListeners();
|
|
43
46
|
this.bindSearchInput();
|
|
@@ -48,6 +51,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
48
51
|
this.updatePills();
|
|
49
52
|
|
|
50
53
|
this.clearBtn = this.element.querySelector(CLEAR_ICON_SELECTOR);
|
|
54
|
+
this.isClearable = this.element.dataset.pbDropdownClearable !== "false";
|
|
51
55
|
if (this.clearBtn) {
|
|
52
56
|
this.clearBtn.style.display = "none";
|
|
53
57
|
this.clearBtn.addEventListener("click", (e) => {
|
|
@@ -60,6 +64,10 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
60
64
|
|
|
61
65
|
updateClearButton() {
|
|
62
66
|
if (!this.clearBtn) return;
|
|
67
|
+
if (!this.isClearable) {
|
|
68
|
+
this.clearBtn.style.display = "none";
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
63
71
|
const hasSelection = this.isMultiSelect
|
|
64
72
|
? this.selectedOptions.size > 0
|
|
65
73
|
: Boolean(this.element.querySelector(DROPDOWN_INPUT).value);
|
|
@@ -70,15 +78,24 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
70
78
|
bindEventListeners() {
|
|
71
79
|
const customTrigger =
|
|
72
80
|
this.element.querySelector(CUSTOM_DISPLAY_SELECTOR) || this.element;
|
|
73
|
-
customTrigger.addEventListener("click", () =>
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
customTrigger.addEventListener("click", (e) => {
|
|
82
|
+
const label = e.target.closest(LABEL_SELECTOR);
|
|
83
|
+
if (label && label.htmlFor) {
|
|
84
|
+
const trigger = this.element.querySelector(
|
|
85
|
+
`#${CSS.escape(label.htmlFor)}`,
|
|
86
|
+
);
|
|
87
|
+
if (trigger) {
|
|
88
|
+
trigger.focus();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
this.toggleElement(this.target);
|
|
92
|
+
});
|
|
76
93
|
|
|
77
94
|
this.target.addEventListener("click", this.handleOptionClick.bind(this));
|
|
78
95
|
document.addEventListener(
|
|
79
96
|
"click",
|
|
80
97
|
this.handleDocumentClick.bind(this),
|
|
81
|
-
true
|
|
98
|
+
true,
|
|
82
99
|
);
|
|
83
100
|
}
|
|
84
101
|
|
|
@@ -87,7 +104,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
87
104
|
if (!this.searchBar) return;
|
|
88
105
|
|
|
89
106
|
this.searchBar.addEventListener("input", (e) =>
|
|
90
|
-
this.handleSearch(e.target.value)
|
|
107
|
+
this.handleSearch(e.target.value),
|
|
91
108
|
);
|
|
92
109
|
}
|
|
93
110
|
|
|
@@ -102,46 +119,85 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
102
119
|
|
|
103
120
|
// Live filter
|
|
104
121
|
this.searchInput.addEventListener("input", (e) =>
|
|
105
|
-
this.handleSearch(e.target.value)
|
|
122
|
+
this.handleSearch(e.target.value),
|
|
106
123
|
);
|
|
107
124
|
}
|
|
108
125
|
|
|
109
126
|
adjustDropdownHeight() {
|
|
110
127
|
if (this.target.classList.contains("open")) {
|
|
111
128
|
const el = this.target;
|
|
129
|
+
const shouldConstrain = el.classList.contains("constrain_height");
|
|
112
130
|
el.style.height = "auto";
|
|
113
131
|
requestAnimationFrame(() => {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
132
|
+
if (shouldConstrain) {
|
|
133
|
+
// Calculate 18em in pixels (matches SCSS max-height: 18em)
|
|
134
|
+
const fontSize = parseFloat(getComputedStyle(el).fontSize) || 16;
|
|
135
|
+
const maxHeight = fontSize * 18;
|
|
136
|
+
const scrollHeight = el.scrollHeight;
|
|
137
|
+
const newHeight = Math.min(scrollHeight, maxHeight);
|
|
138
|
+
el.offsetHeight; // force reflow
|
|
139
|
+
el.style.height = newHeight + "px";
|
|
140
|
+
} else {
|
|
141
|
+
el.offsetHeight; // force reflow
|
|
142
|
+
el.style.height = el.scrollHeight + "px";
|
|
143
|
+
}
|
|
117
144
|
});
|
|
118
145
|
}
|
|
119
146
|
}
|
|
120
147
|
|
|
148
|
+
adjustDropdownPosition(container) {
|
|
149
|
+
if (!container) return;
|
|
150
|
+
|
|
151
|
+
const wrapper = this.element.querySelector(".dropdown_wrapper");
|
|
152
|
+
if (!wrapper) return;
|
|
153
|
+
|
|
154
|
+
const wrapperRect = wrapper.getBoundingClientRect();
|
|
155
|
+
const h = container.getBoundingClientRect().height || container.scrollHeight;
|
|
156
|
+
const spaceBelow = window.innerHeight - wrapperRect.bottom;
|
|
157
|
+
const spaceAbove = wrapperRect.top;
|
|
158
|
+
|
|
159
|
+
// If not enough space below but enough space above, position above
|
|
160
|
+
if (spaceBelow < h + 10 && spaceAbove >= h + 10) {
|
|
161
|
+
container.style.top = "auto";
|
|
162
|
+
container.style.bottom = "calc(100% + 5px)";
|
|
163
|
+
container.style.marginTop = "0";
|
|
164
|
+
container.style.marginBottom = "0";
|
|
165
|
+
} else {
|
|
166
|
+
// Default: position below
|
|
167
|
+
container.style.top = "";
|
|
168
|
+
container.style.bottom = "";
|
|
169
|
+
container.style.marginTop = "";
|
|
170
|
+
container.style.marginBottom = "";
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
121
174
|
handleSearch(term = "") {
|
|
122
175
|
const lcTerm = term.toLowerCase();
|
|
123
|
-
let hasMatch = false
|
|
176
|
+
let hasMatch = false;
|
|
124
177
|
this.element.querySelectorAll(OPTION_SELECTOR).forEach((opt) => {
|
|
125
178
|
//make it so that if the option is selected, it will not show up in the search results
|
|
126
|
-
if (
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
179
|
+
if (
|
|
180
|
+
this.isMultiSelect &&
|
|
181
|
+
this.selectedOptions.has(opt.dataset.dropdownOptionLabel)
|
|
182
|
+
) {
|
|
183
|
+
opt.style.display = "none";
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
130
186
|
const label = JSON.parse(opt.dataset.dropdownOptionLabel)
|
|
131
187
|
.label.toString()
|
|
132
188
|
.toLowerCase();
|
|
133
189
|
|
|
134
|
-
|
|
190
|
+
// hide or show option
|
|
135
191
|
const match = label.includes(lcTerm);
|
|
136
192
|
opt.style.display = match ? "" : "none";
|
|
137
|
-
if (match) hasMatch = true
|
|
193
|
+
if (match) hasMatch = true;
|
|
138
194
|
});
|
|
139
195
|
|
|
140
196
|
this.adjustDropdownHeight();
|
|
141
197
|
|
|
142
|
-
this.removeNoOptionsMessage()
|
|
198
|
+
this.removeNoOptionsMessage();
|
|
143
199
|
if (!hasMatch) {
|
|
144
|
-
this.showNoOptionsMessage()
|
|
200
|
+
this.showNoOptionsMessage();
|
|
145
201
|
}
|
|
146
202
|
}
|
|
147
203
|
|
|
@@ -149,7 +205,8 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
149
205
|
if (this.element.querySelector(".dropdown_no_options")) return;
|
|
150
206
|
|
|
151
207
|
const noOptionElement = document.createElement("div");
|
|
152
|
-
noOptionElement.className =
|
|
208
|
+
noOptionElement.className =
|
|
209
|
+
"pb_body_kit_light dropdown_no_options pb_item_kit p_xs display_flex justify_content_center";
|
|
153
210
|
noOptionElement.textContent = "no option";
|
|
154
211
|
|
|
155
212
|
this.target.appendChild(noOptionElement);
|
|
@@ -200,6 +257,8 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
200
257
|
}
|
|
201
258
|
|
|
202
259
|
isClickOutside(event) {
|
|
260
|
+
const label = event.target.closest(LABEL_SELECTOR);
|
|
261
|
+
if (label && this.element.contains(label)) return false;
|
|
203
262
|
const customTrigger = this.element.querySelector(CUSTOM_DISPLAY_SELECTOR);
|
|
204
263
|
if (customTrigger) {
|
|
205
264
|
return !customTrigger.contains(event.target);
|
|
@@ -230,8 +289,8 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
230
289
|
? JSON.parse(
|
|
231
290
|
this.element.querySelector(
|
|
232
291
|
OPTION_SELECTOR +
|
|
233
|
-
`[data-dropdown-option-label*='"id":"${hiddenInput.value}"']
|
|
234
|
-
).dataset.dropdownOptionLabel
|
|
292
|
+
`[data-dropdown-option-label*='"id":"${hiddenInput.value}"']`,
|
|
293
|
+
).dataset.dropdownOptionLabel,
|
|
235
294
|
)
|
|
236
295
|
: null;
|
|
237
296
|
}
|
|
@@ -240,14 +299,14 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
240
299
|
new CustomEvent("pb:dropdown:selected", {
|
|
241
300
|
detail,
|
|
242
301
|
bubbles: true,
|
|
243
|
-
})
|
|
302
|
+
}),
|
|
244
303
|
);
|
|
245
304
|
}
|
|
246
305
|
|
|
247
306
|
onOptionSelected(value, selectedOption) {
|
|
248
307
|
const triggerElement = this.element.querySelector(DROPDOWN_TRIGGER_DISPLAY);
|
|
249
308
|
const customDisplayElement = this.element.querySelector(
|
|
250
|
-
|
|
309
|
+
'[data-dropdown-trigger-custom-display]',
|
|
251
310
|
);
|
|
252
311
|
|
|
253
312
|
if (triggerElement) {
|
|
@@ -255,36 +314,46 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
255
314
|
const selectedLabel = JSON.parse(value).label;
|
|
256
315
|
triggerElement.textContent = selectedLabel;
|
|
257
316
|
this.emitSelectionChange();
|
|
258
|
-
|
|
317
|
+
|
|
259
318
|
// Handle quickpick variant: populate start/end date hidden inputs
|
|
260
319
|
const optionData = JSON.parse(value);
|
|
261
320
|
const startDateId = this.element.dataset.startDateId;
|
|
262
321
|
const endDateId = this.element.dataset.endDateId;
|
|
263
322
|
const controlsStartId = this.element.dataset.controlsStartId;
|
|
264
323
|
const controlsEndId = this.element.dataset.controlsEndId;
|
|
265
|
-
|
|
324
|
+
|
|
266
325
|
if (optionData.formatted_start_date && optionData.formatted_end_date) {
|
|
267
326
|
// Populate date inputs when option has date fields
|
|
268
327
|
if (startDateId) {
|
|
269
328
|
const startDateInput = document.getElementById(startDateId);
|
|
270
|
-
if (startDateInput)
|
|
329
|
+
if (startDateInput)
|
|
330
|
+
startDateInput.value = optionData.formatted_start_date;
|
|
271
331
|
}
|
|
272
|
-
|
|
332
|
+
|
|
273
333
|
if (endDateId) {
|
|
274
334
|
const endDateInput = document.getElementById(endDateId);
|
|
275
|
-
if (endDateInput)
|
|
335
|
+
if (endDateInput)
|
|
336
|
+
endDateInput.value = optionData.formatted_end_date;
|
|
276
337
|
}
|
|
277
|
-
|
|
338
|
+
|
|
278
339
|
// Sync with DatePickers if controlsStartId/controlsEndId are present
|
|
279
340
|
if (controlsStartId) {
|
|
280
|
-
const startPicker = document.querySelector(
|
|
341
|
+
const startPicker = document.querySelector(
|
|
342
|
+
`#${controlsStartId}`,
|
|
343
|
+
)?._flatpickr;
|
|
281
344
|
if (startPicker) {
|
|
282
|
-
startPicker.setDate(
|
|
345
|
+
startPicker.setDate(
|
|
346
|
+
optionData.formatted_start_date,
|
|
347
|
+
true,
|
|
348
|
+
"m/d/Y",
|
|
349
|
+
);
|
|
283
350
|
}
|
|
284
351
|
}
|
|
285
|
-
|
|
352
|
+
|
|
286
353
|
if (controlsEndId) {
|
|
287
|
-
const endPicker = document.querySelector(
|
|
354
|
+
const endPicker = document.querySelector(
|
|
355
|
+
`#${controlsEndId}`,
|
|
356
|
+
)?._flatpickr;
|
|
288
357
|
if (endPicker) {
|
|
289
358
|
endPicker.setDate(optionData.formatted_end_date, true, "m/d/Y");
|
|
290
359
|
}
|
|
@@ -295,22 +364,26 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
295
364
|
const startDateInput = document.getElementById(startDateId);
|
|
296
365
|
if (startDateInput) startDateInput.value = "";
|
|
297
366
|
}
|
|
298
|
-
|
|
367
|
+
|
|
299
368
|
if (endDateId) {
|
|
300
369
|
const endDateInput = document.getElementById(endDateId);
|
|
301
370
|
if (endDateInput) endDateInput.value = "";
|
|
302
371
|
}
|
|
303
|
-
|
|
372
|
+
|
|
304
373
|
// Clear DatePickers as well
|
|
305
374
|
if (controlsStartId) {
|
|
306
|
-
const startPicker = document.querySelector(
|
|
375
|
+
const startPicker = document.querySelector(
|
|
376
|
+
`#${controlsStartId}`,
|
|
377
|
+
)?._flatpickr;
|
|
307
378
|
if (startPicker) {
|
|
308
379
|
startPicker.clear();
|
|
309
380
|
}
|
|
310
381
|
}
|
|
311
|
-
|
|
382
|
+
|
|
312
383
|
if (controlsEndId) {
|
|
313
|
-
const endPicker = document.querySelector(
|
|
384
|
+
const endPicker = document.querySelector(
|
|
385
|
+
`#${controlsEndId}`,
|
|
386
|
+
)?._flatpickr;
|
|
314
387
|
if (endPicker) {
|
|
315
388
|
endPicker.clear();
|
|
316
389
|
}
|
|
@@ -350,7 +423,9 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
350
423
|
this.adjustDropdownHeight();
|
|
351
424
|
}
|
|
352
425
|
});
|
|
353
|
-
this.element.querySelector(DROPDOWN_INPUT).value = Array.from(
|
|
426
|
+
this.element.querySelector(DROPDOWN_INPUT).value = Array.from(
|
|
427
|
+
this.selectedOptions,
|
|
428
|
+
)
|
|
354
429
|
.map((opt) => JSON.parse(opt).id)
|
|
355
430
|
.join(",");
|
|
356
431
|
} else {
|
|
@@ -365,7 +440,21 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
365
440
|
showElement(elem) {
|
|
366
441
|
elem.classList.remove("close");
|
|
367
442
|
elem.classList.add("open");
|
|
368
|
-
|
|
443
|
+
|
|
444
|
+
const shouldConstrain = elem.classList.contains("constrain_height");
|
|
445
|
+
if (shouldConstrain) {
|
|
446
|
+
// Calculate height respecting max-height constraint (18em)
|
|
447
|
+
const fontSize = parseFloat(getComputedStyle(elem).fontSize) || 16;
|
|
448
|
+
const maxHeight = fontSize * 18; // matches SCSS max-height: 18em
|
|
449
|
+
const scrollHeight = elem.scrollHeight;
|
|
450
|
+
const height = Math.min(scrollHeight, maxHeight);
|
|
451
|
+
elem.style.height = height + "px";
|
|
452
|
+
} else {
|
|
453
|
+
elem.style.height = elem.scrollHeight + "px";
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Auto-position dropdown above if not enough space below
|
|
457
|
+
this.adjustDropdownPosition(elem);
|
|
369
458
|
}
|
|
370
459
|
|
|
371
460
|
hideElement(elem) {
|
|
@@ -382,7 +471,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
382
471
|
this.keyboardHandler.focusedOptionIndex = -1;
|
|
383
472
|
const options = this.element.querySelectorAll(OPTION_SELECTOR);
|
|
384
473
|
options.forEach((option) =>
|
|
385
|
-
option.classList.remove("pb_dropdown_option_focused")
|
|
474
|
+
option.classList.remove("pb_dropdown_option_focused"),
|
|
386
475
|
);
|
|
387
476
|
}
|
|
388
477
|
}
|
|
@@ -417,7 +506,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
417
506
|
hiddenInput.closest(".dropdown_wrapper").classList.add("error");
|
|
418
507
|
}
|
|
419
508
|
},
|
|
420
|
-
true
|
|
509
|
+
true,
|
|
421
510
|
);
|
|
422
511
|
}
|
|
423
512
|
|
|
@@ -427,7 +516,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
427
516
|
const dropdownWrapperElement = input.closest(".dropdown_wrapper");
|
|
428
517
|
dropdownWrapperElement.classList.remove("error");
|
|
429
518
|
const errorLabelElement = dropdownWrapperElement.querySelector(
|
|
430
|
-
".pb_body_kit_negative"
|
|
519
|
+
".pb_body_kit_negative",
|
|
431
520
|
);
|
|
432
521
|
if (errorLabelElement) {
|
|
433
522
|
errorLabelElement.remove();
|
|
@@ -435,13 +524,13 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
435
524
|
return;
|
|
436
525
|
}
|
|
437
526
|
}
|
|
438
|
-
|
|
527
|
+
|
|
439
528
|
if (input.checkValidity()) {
|
|
440
529
|
const dropdownWrapperElement = input.closest(".dropdown_wrapper");
|
|
441
530
|
dropdownWrapperElement.classList.remove("error");
|
|
442
531
|
|
|
443
532
|
const errorLabelElement = dropdownWrapperElement.querySelector(
|
|
444
|
-
".pb_body_kit_negative"
|
|
533
|
+
".pb_body_kit_negative",
|
|
445
534
|
);
|
|
446
535
|
if (errorLabelElement) {
|
|
447
536
|
errorLabelElement.remove();
|
|
@@ -452,7 +541,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
452
541
|
setDefaultValue() {
|
|
453
542
|
const hiddenInput = this.element.querySelector(DROPDOWN_INPUT);
|
|
454
543
|
const optionEls = Array.from(
|
|
455
|
-
this.element.querySelectorAll(OPTION_SELECTOR)
|
|
544
|
+
this.element.querySelectorAll(OPTION_SELECTOR),
|
|
456
545
|
);
|
|
457
546
|
const defaultValue = hiddenInput.dataset.defaultValue || "";
|
|
458
547
|
if (!defaultValue) return;
|
|
@@ -498,44 +587,53 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
498
587
|
selectedOption.classList.add("pb_dropdown_option_selected");
|
|
499
588
|
const optionData = JSON.parse(selectedOption.dataset.dropdownOptionLabel);
|
|
500
589
|
this.setTriggerElementText(optionData.label);
|
|
501
|
-
|
|
590
|
+
|
|
502
591
|
// Handle quickpick variant: populate start/end date hidden inputs and sync DatePickers
|
|
503
592
|
if (optionData.formatted_start_date && optionData.formatted_end_date) {
|
|
504
593
|
const startDateId = this.element.dataset.startDateId;
|
|
505
594
|
const endDateId = this.element.dataset.endDateId;
|
|
506
595
|
const controlsStartId = this.element.dataset.controlsStartId;
|
|
507
596
|
const controlsEndId = this.element.dataset.controlsEndId;
|
|
508
|
-
|
|
597
|
+
|
|
509
598
|
if (startDateId) {
|
|
510
599
|
const startDateInput = document.getElementById(startDateId);
|
|
511
|
-
if (startDateInput)
|
|
600
|
+
if (startDateInput)
|
|
601
|
+
startDateInput.value = optionData.formatted_start_date;
|
|
512
602
|
}
|
|
513
|
-
|
|
603
|
+
|
|
514
604
|
if (endDateId) {
|
|
515
605
|
const endDateInput = document.getElementById(endDateId);
|
|
516
606
|
if (endDateInput) endDateInput.value = optionData.formatted_end_date;
|
|
517
607
|
}
|
|
518
|
-
|
|
608
|
+
|
|
519
609
|
// Sync with DatePickers - retry with delays to ensure DatePickers are initialized
|
|
520
610
|
const syncDatePickers = () => {
|
|
521
611
|
if (controlsStartId) {
|
|
522
|
-
const startPicker = document.querySelector(
|
|
612
|
+
const startPicker = document.querySelector(
|
|
613
|
+
`#${controlsStartId}`,
|
|
614
|
+
)?._flatpickr;
|
|
523
615
|
if (startPicker) {
|
|
524
|
-
startPicker.setDate(
|
|
616
|
+
startPicker.setDate(
|
|
617
|
+
optionData.formatted_start_date,
|
|
618
|
+
true,
|
|
619
|
+
"m/d/Y",
|
|
620
|
+
);
|
|
525
621
|
}
|
|
526
622
|
}
|
|
527
|
-
|
|
623
|
+
|
|
528
624
|
if (controlsEndId) {
|
|
529
|
-
const endPicker = document.querySelector(
|
|
625
|
+
const endPicker = document.querySelector(
|
|
626
|
+
`#${controlsEndId}`,
|
|
627
|
+
)?._flatpickr;
|
|
530
628
|
if (endPicker) {
|
|
531
629
|
endPicker.setDate(optionData.formatted_end_date, true, "m/d/Y");
|
|
532
630
|
}
|
|
533
631
|
}
|
|
534
632
|
};
|
|
535
|
-
|
|
633
|
+
|
|
536
634
|
// Try immediately
|
|
537
635
|
syncDatePickers();
|
|
538
|
-
|
|
636
|
+
|
|
539
637
|
// Retry after short delay in case DatePickers aren't ready yet
|
|
540
638
|
setTimeout(syncDatePickers, 100);
|
|
541
639
|
setTimeout(syncDatePickers, 300);
|
|
@@ -596,9 +694,9 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
596
694
|
updatePills() {
|
|
597
695
|
if (!this.isMultiSelect) return;
|
|
598
696
|
|
|
599
|
-
const wrapper = this.element.querySelector(
|
|
697
|
+
const wrapper = this.element.querySelector('[data-dropdown-pills-wrapper]');
|
|
600
698
|
const placeholder = this.element.querySelector(
|
|
601
|
-
|
|
699
|
+
'[data-dropdown-trigger-display-multi-select]',
|
|
602
700
|
);
|
|
603
701
|
if (!wrapper) return;
|
|
604
702
|
|
|
@@ -616,7 +714,12 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
616
714
|
// Create a form pill for each selected option
|
|
617
715
|
const pill = document.createElement("div");
|
|
618
716
|
const color = this.formPillProps.color || "primary";
|
|
619
|
-
pill.classList.add(
|
|
717
|
+
pill.classList.add(
|
|
718
|
+
"pb_form_pill_kit",
|
|
719
|
+
`pb_form_pill_${color}`,
|
|
720
|
+
"pb_form_pill_none",
|
|
721
|
+
"mr_xs",
|
|
722
|
+
);
|
|
620
723
|
if (this.formPillProps.size === "small") {
|
|
621
724
|
pill.classList.add("pb_form_pill_small");
|
|
622
725
|
}
|
|
@@ -641,8 +744,8 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
641
744
|
|
|
642
745
|
const optEl = this.element.querySelector(
|
|
643
746
|
`${OPTION_SELECTOR}[data-dropdown-option-label*='"id":${JSON.stringify(
|
|
644
|
-
id
|
|
645
|
-
)}']
|
|
747
|
+
id,
|
|
748
|
+
)}']`,
|
|
646
749
|
);
|
|
647
750
|
if (optEl) {
|
|
648
751
|
optEl.style.display = "";
|
|
@@ -671,18 +774,18 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
671
774
|
}
|
|
672
775
|
}
|
|
673
776
|
const customDisplay = this.element.querySelector(
|
|
674
|
-
|
|
777
|
+
'[data-dropdown-trigger-custom-display]',
|
|
675
778
|
);
|
|
676
779
|
if (customDisplay) {
|
|
677
780
|
customDisplay.style.display = "none";
|
|
678
781
|
}
|
|
679
|
-
|
|
782
|
+
|
|
680
783
|
// Clear quickpick hidden inputs
|
|
681
784
|
const startDateId = this.element.dataset.startDateId;
|
|
682
785
|
const endDateId = this.element.dataset.endDateId;
|
|
683
786
|
const controlsStartId = this.element.dataset.controlsStartId;
|
|
684
787
|
const controlsEndId = this.element.dataset.controlsEndId;
|
|
685
|
-
|
|
788
|
+
|
|
686
789
|
if (startDateId) {
|
|
687
790
|
const startDateInput = document.getElementById(startDateId);
|
|
688
791
|
if (startDateInput) startDateInput.value = "";
|
|
@@ -691,22 +794,24 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
691
794
|
const endDateInput = document.getElementById(endDateId);
|
|
692
795
|
if (endDateInput) endDateInput.value = "";
|
|
693
796
|
}
|
|
694
|
-
|
|
797
|
+
|
|
695
798
|
// Clear linked DatePickers if controlsStartId/controlsEndId are present
|
|
696
799
|
if (controlsStartId) {
|
|
697
|
-
const startPicker = document.querySelector(
|
|
800
|
+
const startPicker = document.querySelector(
|
|
801
|
+
`#${controlsStartId}`,
|
|
802
|
+
)?._flatpickr;
|
|
698
803
|
if (startPicker) {
|
|
699
804
|
startPicker.clear();
|
|
700
805
|
}
|
|
701
806
|
}
|
|
702
|
-
|
|
807
|
+
|
|
703
808
|
if (controlsEndId) {
|
|
704
809
|
const endPicker = document.querySelector(`#${controlsEndId}`)?._flatpickr;
|
|
705
810
|
if (endPicker) {
|
|
706
811
|
endPicker.clear();
|
|
707
812
|
}
|
|
708
813
|
}
|
|
709
|
-
|
|
814
|
+
|
|
710
815
|
this.resetDropdownValue();
|
|
711
816
|
this.updatePills();
|
|
712
817
|
this.updateClearButton();
|
|
@@ -717,21 +822,24 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
717
822
|
// Method for DatePicker sync - only clears the dropdown, not the DatePickers
|
|
718
823
|
clearSelected() {
|
|
719
824
|
// Only clear if this is a single-select quickpick variant
|
|
720
|
-
if (
|
|
825
|
+
if (
|
|
826
|
+
this.element.dataset.pbDropdownVariant !== "quickpick" ||
|
|
827
|
+
this.isMultiSelect
|
|
828
|
+
) {
|
|
721
829
|
return;
|
|
722
830
|
}
|
|
723
|
-
|
|
831
|
+
|
|
724
832
|
const customDisplay = this.element.querySelector(
|
|
725
|
-
|
|
833
|
+
'[data-dropdown-trigger-custom-display]',
|
|
726
834
|
);
|
|
727
835
|
if (customDisplay) {
|
|
728
836
|
customDisplay.style.display = "none";
|
|
729
837
|
}
|
|
730
|
-
|
|
838
|
+
|
|
731
839
|
// Clear quickpick hidden inputs only (not the DatePickers)
|
|
732
840
|
const startDateId = this.element.dataset.startDateId;
|
|
733
841
|
const endDateId = this.element.dataset.endDateId;
|
|
734
|
-
|
|
842
|
+
|
|
735
843
|
if (startDateId) {
|
|
736
844
|
const startDateInput = document.getElementById(startDateId);
|
|
737
845
|
if (startDateInput) startDateInput.value = "";
|
|
@@ -740,7 +848,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
740
848
|
const endDateInput = document.getElementById(endDateId);
|
|
741
849
|
if (endDateInput) endDateInput.value = "";
|
|
742
850
|
}
|
|
743
|
-
|
|
851
|
+
|
|
744
852
|
this.resetDropdownValue();
|
|
745
853
|
this.updateClearButton();
|
|
746
854
|
this.emitSelectionChange();
|
|
@@ -767,7 +875,7 @@ export default class PbDropdown extends PbEnhancedElement {
|
|
|
767
875
|
inp.dataset.generated = "true";
|
|
768
876
|
baseInput.insertAdjacentElement("afterend", inp);
|
|
769
877
|
});
|
|
770
|
-
|
|
878
|
+
|
|
771
879
|
// For multi-select, remove required from base input when there are selections
|
|
772
880
|
// The generated inputs handle the form submission with actual values
|
|
773
881
|
// Restore required attribute when there are no selections (if it was originally required)
|
|
@@ -19,6 +19,7 @@ type DropdownContainerProps = {
|
|
|
19
19
|
aria?: { [key: string]: string };
|
|
20
20
|
children?: React.ReactChild[] | React.ReactChild;
|
|
21
21
|
className?: string;
|
|
22
|
+
constrainHeight?: boolean;
|
|
22
23
|
dark?: boolean;
|
|
23
24
|
data?: { [key: string]: string };
|
|
24
25
|
htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
|
|
@@ -31,6 +32,7 @@ const DropdownContainer = (props: DropdownContainerProps) => {
|
|
|
31
32
|
aria = {},
|
|
32
33
|
children,
|
|
33
34
|
className,
|
|
35
|
+
constrainHeight = false,
|
|
34
36
|
dark = false,
|
|
35
37
|
data = {},
|
|
36
38
|
htmlOptions = {},
|
|
@@ -54,6 +56,7 @@ const DropdownContainer = (props: DropdownContainerProps) => {
|
|
|
54
56
|
const classes = classnames(
|
|
55
57
|
buildCss("pb_dropdown_container"),
|
|
56
58
|
`${isDropDownClosed ? "close" : "open"}`,
|
|
59
|
+
constrainHeight && "constrain_height",
|
|
57
60
|
globalProps(props),
|
|
58
61
|
className
|
|
59
62
|
);
|