playbook_ui 14.20.0.pre.rc.2 → 14.21.0.pre.alpha.PLAY2140upgraderailsdependency8110
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/CustomCell.tsx +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +116 -49
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +61 -35
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +37 -23
- data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +58 -2
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +16 -4
- data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +7 -3
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +48 -19
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +13 -3
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +16 -1
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +61 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +6 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_default.md +1 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.html.erb +33 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_no_subrows.jsx +0 -1
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.html.erb +33 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_scrollbar_none.jsx +53 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +8 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/index.js +157 -12
- data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
- data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
- data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -0
- data/app/pb_kits/playbook/pb_checkbox/checkbox.html.erb +4 -11
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +10 -6
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +2 -48
- data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +1 -0
- data/app/pb_kits/playbook/pb_checkbox/index.js +56 -0
- data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_date_display.html.erb +13 -0
- data/app/pb_kits/playbook/pb_draggable/context/index.tsx +17 -58
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -1
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +86 -19
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.jsx +42 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_close_on_select.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +31 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +5 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +56 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +58 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +20 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +19 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +3 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +20 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +57 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +50 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +105 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +22 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +67 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +13 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +6 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +16 -2
- data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +108 -2
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +34 -13
- data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +3 -1
- data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +0 -6
- data/app/pb_kits/playbook/pb_dropdown/index.js +357 -40
- data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +39 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +26 -18
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +96 -19
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +1 -0
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +4 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.html.erb +4 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx +15 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.md +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_only_countries.jsx +1 -1
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +4 -3
- 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_popover/index.ts +9 -4
- data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.html.erb +12 -0
- data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.jsx +31 -0
- data/app/pb_kits/playbook/pb_select/docs/_select_custom_select_subheaders.md +1 -0
- data/app/pb_kits/playbook/pb_select/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_select/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +3 -51
- data/app/pb_kits/playbook/pb_table/styles/_mobile_collapse.scss +1 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +73 -3
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.jsx +23 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_preserve_input.md +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/example.yml +1 -0
- data/app/pb_kits/playbook/pb_typeahead/docs/index.js +1 -0
- data/dist/chunks/_typeahead-CoOpeYom.js +22 -0
- data/dist/chunks/_weekday_stacked-B_jpa2Rz.js +45 -0
- data/dist/chunks/lib-D7Va7yqa.js +29 -0
- data/dist/chunks/{pb_form_validation-WWvUXPKD.js → pb_form_validation-DSkdRDMf.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/menu.yml +1 -1
- data/dist/playbook-doc.js +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/kit_base.rb +3 -3
- data/lib/playbook/version.rb +2 -2
- metadata +48 -7
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
- data/dist/chunks/_typeahead-B9-s4j4U.js +0 -22
- data/dist/chunks/_weekday_stacked-CvzpmXD5.js +0 -45
- data/dist/chunks/lib-B20MXZcW.js +0 -29
@@ -10,6 +10,7 @@ import { globalProps } from "../../utilities/globalProps";
|
|
10
10
|
import { useHandleOnKeyDown } from "../hooks/useHandleOnKeydown";
|
11
11
|
|
12
12
|
import DropdownContext from "../context";
|
13
|
+
import MultiSelectTriggerDisplay from "./MultiSelectTriggerDisplay";
|
13
14
|
|
14
15
|
import Body from "../../pb_body/_body";
|
15
16
|
import Icon from "../../pb_icon/_icon";
|
@@ -43,14 +44,18 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
43
44
|
|
44
45
|
const {
|
45
46
|
autocomplete,
|
47
|
+
closeOnSelection,
|
46
48
|
filterItem,
|
49
|
+
handleBackspace,
|
47
50
|
handleChange,
|
48
51
|
handleWrapperClick,
|
49
52
|
inputRef,
|
50
53
|
inputWrapperRef,
|
51
54
|
isDropDownClosed,
|
52
55
|
isInputFocused,
|
56
|
+
multiSelect,
|
53
57
|
selected,
|
58
|
+
setIsDropDownClosed,
|
54
59
|
setIsInputFocused,
|
55
60
|
toggleDropdown,
|
56
61
|
} = useContext(DropdownContext);
|
@@ -69,9 +74,19 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
69
74
|
const triggerWrapperClasses = buildCss(
|
70
75
|
"dropdown_trigger_wrapper",
|
71
76
|
isInputFocused && "focus",
|
72
|
-
!autocomplete && "select_only"
|
77
|
+
!autocomplete && !multiSelect && "select_only"
|
73
78
|
);
|
74
79
|
|
80
|
+
const selectedArray = Array.isArray(selected)
|
81
|
+
? selected
|
82
|
+
: selected && Object.keys(selected).length
|
83
|
+
? [selected]
|
84
|
+
: [];
|
85
|
+
|
86
|
+
const joinedLabels = multiSelect
|
87
|
+
? ""
|
88
|
+
: selectedArray.map((option) => option.label).join(", ");
|
89
|
+
|
75
90
|
const customDisplayPlaceholder = selected?.label ? (
|
76
91
|
""
|
77
92
|
) : autocomplete ? (
|
@@ -82,19 +97,34 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
82
97
|
"Select..."
|
83
98
|
);
|
84
99
|
|
85
|
-
const defaultDisplayPlaceholder =
|
86
|
-
?
|
100
|
+
const defaultDisplayPlaceholder = joinedLabels
|
101
|
+
? joinedLabels
|
87
102
|
: autocomplete
|
88
103
|
? ""
|
89
104
|
: placeholder
|
90
105
|
? placeholder
|
91
106
|
: "Select...";
|
92
107
|
|
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
|
+
|
93
123
|
return (
|
94
|
-
<div {...ariaProps}
|
95
|
-
{...dataProps}
|
124
|
+
<div {...ariaProps}
|
125
|
+
{...dataProps}
|
96
126
|
{...htmlProps}
|
97
|
-
className={classes}
|
127
|
+
className={classes}
|
98
128
|
id={id}
|
99
129
|
>
|
100
130
|
{
|
@@ -125,34 +155,65 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
125
155
|
paddingX="sm"
|
126
156
|
paddingY="xs"
|
127
157
|
>
|
128
|
-
<FlexItem>
|
129
|
-
<Flex align="center"
|
158
|
+
<FlexItem fixedSize={multiSelect ? "85%" : ""}>
|
159
|
+
<Flex align="center"
|
160
|
+
wrap
|
161
|
+
>
|
130
162
|
{customDisplay ? (
|
131
163
|
<Flex align="center">
|
132
164
|
{customDisplay}
|
133
|
-
<Body dark={dark}
|
134
|
-
paddingLeft={`${
|
165
|
+
<Body dark={dark}
|
166
|
+
paddingLeft={`${joinedLabels ? "xs" : "none"}`}
|
135
167
|
>
|
136
168
|
{customDisplayPlaceholder}
|
137
169
|
</Body>
|
138
170
|
</Flex>
|
139
171
|
) : (
|
140
|
-
|
141
|
-
|
142
|
-
|
172
|
+
multiSelect ? (
|
173
|
+
<>
|
174
|
+
<MultiSelectTriggerDisplay
|
175
|
+
autocomplete={autocomplete}
|
176
|
+
dark={dark}
|
177
|
+
placeholder={placeholder}
|
178
|
+
selected={selectedArray}
|
179
|
+
/>
|
180
|
+
{autocomplete && (
|
181
|
+
<input
|
182
|
+
className="dropdown_input"
|
183
|
+
onChange={handleChange}
|
184
|
+
onClick={handleInputClick}
|
185
|
+
onFocus={() => setIsInputFocused(true)}
|
186
|
+
onKeyDown={(e) => {
|
187
|
+
handleKeyDown(e);
|
188
|
+
e.stopPropagation(); //Fixes issue with keyboard accessibility
|
189
|
+
}}
|
190
|
+
placeholder={
|
191
|
+
joinedLabels
|
192
|
+
? ""
|
193
|
+
: placeholder
|
194
|
+
? placeholder
|
195
|
+
: "Select..."
|
196
|
+
}
|
197
|
+
ref={inputRef}
|
198
|
+
value={filterItem}
|
199
|
+
/>
|
200
|
+
)}
|
201
|
+
</>
|
202
|
+
) : (
|
203
|
+
<Body dark={dark}
|
204
|
+
text={defaultDisplayPlaceholder}
|
205
|
+
/>
|
206
|
+
)
|
143
207
|
)}
|
144
|
-
{autocomplete && (
|
208
|
+
{autocomplete && !multiSelect && (
|
145
209
|
<input
|
146
210
|
className="dropdown_input"
|
147
211
|
onChange={handleChange}
|
148
|
-
onClick={
|
149
|
-
e.stopPropagation();// keep the wrapper’s handler from firing
|
150
|
-
toggleDropdown();
|
151
|
-
}}
|
212
|
+
onClick={handleInputClick}
|
152
213
|
onFocus={() => setIsInputFocused(true)}
|
153
214
|
onKeyDown={handleKeyDown}
|
154
215
|
placeholder={
|
155
|
-
|
216
|
+
joinedLabels
|
156
217
|
? ""
|
157
218
|
: placeholder
|
158
219
|
? placeholder
|
@@ -164,7 +225,9 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
164
225
|
)}
|
165
226
|
</Flex>
|
166
227
|
</FlexItem>
|
228
|
+
<FlexItem>
|
167
229
|
<Body
|
230
|
+
alignItems="center"
|
168
231
|
dark={dark}
|
169
232
|
display="flex"
|
170
233
|
htmlOptions={{
|
@@ -172,6 +235,19 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
172
235
|
}}
|
173
236
|
key={`${isDropDownClosed ? "chevron-down" : "chevron-up"}`}
|
174
237
|
>
|
238
|
+
{
|
239
|
+
selectedArray.length > 0 && (
|
240
|
+
<div onClick={(e)=>{e.stopPropagation();handleBackspace()}}>
|
241
|
+
<Icon
|
242
|
+
cursor="pointer"
|
243
|
+
dark={dark}
|
244
|
+
icon="times"
|
245
|
+
paddingRight="xs"
|
246
|
+
size="sm"
|
247
|
+
/>
|
248
|
+
</div>
|
249
|
+
)
|
250
|
+
}
|
175
251
|
<Icon
|
176
252
|
cursor="pointer"
|
177
253
|
dark={dark}
|
@@ -179,6 +255,7 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
179
255
|
size="sm"
|
180
256
|
/>
|
181
257
|
</Body>
|
258
|
+
</FlexItem>
|
182
259
|
</Flex>
|
183
260
|
</>
|
184
261
|
)
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import React, { useContext } from "react";
|
2
|
+
import FormPill from "../../pb_form_pill/_form_pill";
|
3
|
+
import Flex from "../../pb_flex/_flex";
|
4
|
+
import Body from "../../pb_body/_body";
|
5
|
+
import { GenericObject } from "../../types";
|
6
|
+
import DropdownContext
|
7
|
+
from "../context";
|
8
|
+
type MultiSelectTriggerDisplayProps = {
|
9
|
+
autocomplete?: boolean;
|
10
|
+
selected: GenericObject[];
|
11
|
+
placeholder?: string;
|
12
|
+
dark?: boolean;
|
13
|
+
};
|
14
|
+
|
15
|
+
const MultiSelectTriggerDisplay = ({
|
16
|
+
autocomplete,
|
17
|
+
selected,
|
18
|
+
placeholder,
|
19
|
+
dark = false,
|
20
|
+
}: MultiSelectTriggerDisplayProps) => {
|
21
|
+
|
22
|
+
const { setSelected, onSelect, formPillProps } = useContext(DropdownContext);
|
23
|
+
|
24
|
+
if (selected.length === 0) {
|
25
|
+
if (autocomplete) return null;
|
26
|
+
return (
|
27
|
+
<Body dark={dark}
|
28
|
+
text={placeholder ? placeholder : "Select..."}
|
29
|
+
/>
|
30
|
+
)
|
31
|
+
}
|
32
|
+
|
33
|
+
const handleRemoveIconClick = (option: GenericObject) => {
|
34
|
+
setSelected((prev: GenericObject[]) => {
|
35
|
+
const next = prev.filter((item) => item.label !== option.label);
|
36
|
+
onSelect && onSelect(next);
|
37
|
+
return next;
|
38
|
+
});
|
39
|
+
}
|
40
|
+
|
41
|
+
return (
|
42
|
+
<Flex wrap>
|
43
|
+
{selected.map((option, i) => (
|
44
|
+
<FormPill
|
45
|
+
dark={dark}
|
46
|
+
key={i}
|
47
|
+
marginRight="xs"
|
48
|
+
onClick={(e)=>{e.stopPropagation();handleRemoveIconClick(option)}}
|
49
|
+
tabIndex={0}
|
50
|
+
text={option.label}
|
51
|
+
{...formPillProps}
|
52
|
+
/>
|
53
|
+
))}
|
54
|
+
</Flex>
|
55
|
+
);
|
56
|
+
};
|
57
|
+
|
58
|
+
export default MultiSelectTriggerDisplay;
|
@@ -99,6 +99,7 @@
|
|
99
99
|
<%= form.url_field :example_url_field, props: { label: true } %>
|
100
100
|
<%= form.text_area :example_text_area, props: { label: true } %>
|
101
101
|
<%= form.dropdown_field :example_dropdown, props: { label: true, options: example_dropdown_options } %>
|
102
|
+
<%= form.dropdown_field :example_dropdown_multi, props: { label: true, options: example_dropdown_options, multi_select: true } %>
|
102
103
|
<%= form.select :example_select, [ ["Yes", 1], ["No", 2] ], props: { label: true } %>
|
103
104
|
<%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true } %>
|
104
105
|
<%= form.check_box :example_checkbox,
|
@@ -98,6 +98,7 @@
|
|
98
98
|
<%= form.url_field :example_url_field_validation, props: { label: true, required: true } %>
|
99
99
|
<%= form.text_area :example_text_area_validation, props: { label: true, required: true } %>
|
100
100
|
<%= form.dropdown_field :example_dropdown_validation, props: { label: true, options: example_dropdown_options, required: true } %>
|
101
|
+
<%= form.dropdown_field :example_dropdown_validation_multi, props: { label: true, options: example_dropdown_options, multi_select: true, required: true } %>
|
101
102
|
<%= form.select :example_select_validation, [ ["Yes", 1], ["No", 2] ], props: { label: true, blank_selection: "Select One...", required: true, validation_message: "Please, select an option." } %>
|
102
103
|
<%= form.collection_select :example_collection_select_validation, example_collection, :value, :name, props: { label: true, blank_selection: "Select One...", required: true } %>
|
103
104
|
<%= form.check_box :example_checkbox, props: { text: "Example Checkbox", label: true, required: true } %>
|
@@ -33,6 +33,7 @@ type PhoneNumberInputProps = {
|
|
33
33
|
onChange?: (e: React.FormEvent<HTMLInputElement>) => void,
|
34
34
|
onValidate?: Callback<boolean, void>,
|
35
35
|
onlyCountries: string[],
|
36
|
+
excludeCountries: string[],
|
36
37
|
preferredCountries?: string[],
|
37
38
|
required?: boolean,
|
38
39
|
value?: string,
|
@@ -88,6 +89,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
88
89
|
},
|
89
90
|
onValidate = () => null,
|
90
91
|
onlyCountries = [],
|
92
|
+
excludeCountries = [],
|
91
93
|
required = false,
|
92
94
|
preferredCountries = [],
|
93
95
|
value = "",
|
@@ -234,6 +236,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
234
236
|
const fallbackCountry =
|
235
237
|
preferredCountries.length > 0 ? preferredCountries[0] :
|
236
238
|
onlyCountries.length > 0 ? onlyCountries.sort()[0] :
|
239
|
+
excludeCountries.length > 0 ? excludeCountries.sort()[0] :
|
237
240
|
"af";
|
238
241
|
|
239
242
|
useEffect(() => {
|
@@ -244,6 +247,7 @@ const PhoneNumberInput = (props: PhoneNumberInputProps, ref?: React.MutableRefOb
|
|
244
247
|
autoInsertDialCode: false,
|
245
248
|
initialCountry: initialCountry || fallbackCountry,
|
246
249
|
onlyCountries,
|
250
|
+
excludeCountries,
|
247
251
|
countrySearch: countrySearch,
|
248
252
|
fixDropdownWidth: false,
|
249
253
|
formatAsYouType: formatAsYouType,
|
data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_exclude_countries.jsx
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import PhoneNumberInput from '../../pb_phone_number_input/_phone_number_input'
|
3
|
+
|
4
|
+
const PhoneNumberInputExcludeCountries = (props) => (
|
5
|
+
<>
|
6
|
+
<PhoneNumberInput
|
7
|
+
excludeCountries={['us', 'br']}
|
8
|
+
id='exclude'
|
9
|
+
initialCountry='gb'
|
10
|
+
{...props}
|
11
|
+
/>
|
12
|
+
</>
|
13
|
+
)
|
14
|
+
|
15
|
+
export default PhoneNumberInputExcludeCountries
|
@@ -0,0 +1 @@
|
|
1
|
+
Excluding countries removes the selected countries from the dropdown.
|
@@ -4,7 +4,8 @@ examples:
|
|
4
4
|
- phone_number_input_default: Default
|
5
5
|
- phone_number_input_preferred_countries: Preferred Countries
|
6
6
|
- phone_number_input_initial_country: Initial Country
|
7
|
-
- phone_number_input_only_countries:
|
7
|
+
- phone_number_input_only_countries: Only Countries
|
8
|
+
- phone_number_input_exclude_countries: Exclude Countries
|
8
9
|
- phone_number_input_validation: Form Validation
|
9
10
|
- phone_number_input_clear_field: Clearing the Input Field
|
10
11
|
- phone_number_input_access_input_element: Accessing the Input Element
|
@@ -15,9 +16,9 @@ examples:
|
|
15
16
|
- phone_number_input_default: Default
|
16
17
|
- phone_number_input_preferred_countries: Preferred Countries
|
17
18
|
- phone_number_input_initial_country: Initial Country
|
18
|
-
- phone_number_input_only_countries:
|
19
|
+
- phone_number_input_only_countries: Only Countries
|
20
|
+
- phone_number_input_exclude_countries: Exclude Countries
|
19
21
|
- phone_number_input_validation: Form Validation
|
20
22
|
- phone_number_input_format: Format as You Type
|
21
23
|
- phone_number_input_hidden_inputs: Hidden Inputs
|
22
24
|
- phone_number_input_country_search: Country Search
|
23
|
-
|
@@ -2,6 +2,7 @@ export { default as PhoneNumberInputDefault } from './_phone_number_input_defaul
|
|
2
2
|
export { default as PhoneNumberInputPreferredCountries } from './_phone_number_input_preferred_countries'
|
3
3
|
export { default as PhoneNumberInputInitialCountry } from './_phone_number_input_initial_country'
|
4
4
|
export { default as PhoneNumberInputOnlyCountries } from './_phone_number_input_only_countries'
|
5
|
+
export { default as PhoneNumberInputExcludeCountries } from './_phone_number_input_exclude_countries'
|
5
6
|
export { default as PhoneNumberInputValidation } from './_phone_number_input_validation'
|
6
7
|
export { default as PhoneNumberInputClearField } from './_phone_number_input_clear_field'
|
7
8
|
export { default as PhoneNumberInputAccessInputElement } from './_phone_number_input_access_input_element'
|
@@ -15,6 +15,8 @@ module Playbook
|
|
15
15
|
default: ""
|
16
16
|
prop :only_countries, type: Playbook::Props::Array,
|
17
17
|
default: []
|
18
|
+
prop :exclude_countries, type: Playbook::Props::Array,
|
19
|
+
default: []
|
18
20
|
prop :preferred_countries, type: Playbook::Props::Array,
|
19
21
|
default: []
|
20
22
|
prop :error, type: Playbook::Props::String,
|
@@ -44,6 +46,7 @@ module Playbook
|
|
44
46
|
label: label,
|
45
47
|
name: name,
|
46
48
|
onlyCountries: only_countries,
|
49
|
+
excludeCountries: exclude_countries,
|
47
50
|
preferredCountries: preferred_countries,
|
48
51
|
required: required,
|
49
52
|
value: value,
|
@@ -13,19 +13,24 @@ export default class PbPopover extends PbEnhancedElement {
|
|
13
13
|
}
|
14
14
|
|
15
15
|
moveTooltip() {
|
16
|
-
let container: HTMLElement | null;
|
16
|
+
let container: HTMLElement | null = document.querySelector('body');
|
17
17
|
|
18
18
|
if (this.appendTo === "parent") {
|
19
|
-
container = this.element.parentElement
|
19
|
+
container = this.element.parentElement && 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
|
-
|
24
|
+
container.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
|
+
}
|
28
32
|
this.moveTooltip()
|
33
|
+
|
29
34
|
this.popper = createPopper (this.triggerElement, this.tooltip, {
|
30
35
|
placement: this.position as Placement,
|
31
36
|
strategy: 'fixed',
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<%= pb_rails("select", props: { label: "Favorite Animal" }) do %>
|
2
|
+
<select name="animal" id="animal">
|
3
|
+
<optgroup label="Mammal">
|
4
|
+
<option value="1">Cat</option>
|
5
|
+
<option value="2">Dog</option>
|
6
|
+
</optgroup>
|
7
|
+
<optgroup label="Amphibian">
|
8
|
+
<option value="3">Frog</option>
|
9
|
+
<option value="4">Salamander</option>
|
10
|
+
</optgroup>
|
11
|
+
</select>
|
12
|
+
<% end %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
import Select from '../_select'
|
4
|
+
|
5
|
+
const SelectCustomSelectSubheaders = (props) => {
|
6
|
+
return (
|
7
|
+
<div>
|
8
|
+
<Select
|
9
|
+
label="Favorite Animal"
|
10
|
+
{...props}
|
11
|
+
>
|
12
|
+
<select
|
13
|
+
id="animal"
|
14
|
+
name="animal"
|
15
|
+
{...props}
|
16
|
+
>
|
17
|
+
<optgroup label="Mammal">
|
18
|
+
<option value="1">{'Cat'}</option>
|
19
|
+
<option value="2">{'Dog'}</option>
|
20
|
+
</optgroup>
|
21
|
+
<optgroup label="Amphibian">
|
22
|
+
<option value="3">{'Frog'}</option>
|
23
|
+
<option value="4">{'Salamander'}</option>
|
24
|
+
</optgroup>
|
25
|
+
</select>
|
26
|
+
</Select>
|
27
|
+
</div>
|
28
|
+
)
|
29
|
+
}
|
30
|
+
|
31
|
+
export default SelectCustomSelectSubheaders
|
@@ -0,0 +1 @@
|
|
1
|
+
To create a select with non-selectable subheaders, use a Custom Select component to render a native `<select>` containing `<optgroup>` elements. The [optgroup HTML element](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/optgroup) groups related options under a non-selectable label in the dropdown.
|
@@ -8,6 +8,7 @@ examples:
|
|
8
8
|
- select_required: Required Select Field
|
9
9
|
- select_value_text_same: Equal option value and value text
|
10
10
|
- select_custom_select: Custom Select
|
11
|
+
- select_custom_select_subheaders: Custom Select Subheaders
|
11
12
|
- select_error: Select w/ Error
|
12
13
|
- select_inline: Select Inline
|
13
14
|
- select_inline_show_arrow: Select Inline (Always Show Arrow)
|
@@ -25,6 +26,7 @@ examples:
|
|
25
26
|
- select_required: Required Select Field
|
26
27
|
- select_value_text_same: Equal option value and value text
|
27
28
|
- select_custom_select: Custom Select
|
29
|
+
- select_custom_select_subheaders: Custom Select Subheaders
|
28
30
|
- select_error: Select w/ Error
|
29
31
|
- select_inline: Select Inline
|
30
32
|
- select_inline_show_arrow: Select Inline (Always Show Arrow)
|
@@ -11,3 +11,4 @@ export { default as SelectInlineShowArrow } from './_select_inline_show_arrow.js
|
|
11
11
|
export { default as SelectInlineCompact } from './_select_inline_compact.jsx'
|
12
12
|
export { default as SelectMultiple } from './_select_multiple.jsx'
|
13
13
|
export { default as SelectReactHook } from './_select_react_hook.jsx'
|
14
|
+
export { default as SelectCustomSelectSubheaders } from './_select_custom_select_subheaders.jsx'
|
@@ -18,7 +18,7 @@
|
|
18
18
|
checked: true,
|
19
19
|
value: "checkbox-value",
|
20
20
|
name: "main-checkbox-selectable",
|
21
|
-
|
21
|
+
indeterminate_main: true,
|
22
22
|
id: "checkbox-selectable"
|
23
23
|
}) %>
|
24
24
|
<% end %>
|
@@ -33,7 +33,7 @@
|
|
33
33
|
<% checkboxes.each_with_index do |checkbox, index| %>
|
34
34
|
<%= pb_rails("table/table_row") do %>
|
35
35
|
<%= pb_rails("table/table_cell") do %>
|
36
|
-
<%= pb_rails("checkbox", props: { checked: checkbox[:checked], id: "#{checkbox[:id]}-selectable-checkbox", name: "#{checkbox[:id]}-selectable-checkbox", on_change: "updateCheckboxes(#{index})", value: "check-box value" }) %>
|
36
|
+
<%= pb_rails("checkbox", props: { checked: checkbox[:checked], id: "#{checkbox[:id]}-selectable-checkbox", name: "#{checkbox[:id]}-selectable-checkbox", on_change: "updateCheckboxes(#{index})", value: "check-box value", indeterminate_parent: "checkbox-selectable" }) %>
|
37
37
|
<% end %>
|
38
38
|
<%= pb_rails("table/table_cell") do %>
|
39
39
|
<%= pb_rails("image", props: { alt: "picture of a misty forest", size: "xs", url: "https://unsplash.it/500/400/?image=634" }) %>
|
@@ -45,52 +45,4 @@
|
|
45
45
|
<% end %>
|
46
46
|
<% end %>
|
47
47
|
<% end %>
|
48
|
-
<% end %>
|
49
|
-
|
50
|
-
<script>
|
51
|
-
document.addEventListener('DOMContentLoaded', function() {
|
52
|
-
const mainCheckboxWrapper = document.getElementById('checkbox-selectable');
|
53
|
-
const mainCheckbox = document.getElementsByName("main-checkbox-selectable")[0];
|
54
|
-
const childCheckboxes = document.querySelectorAll('input[type="checkbox"][id$="selectable-checkbox"]');
|
55
|
-
const deleteButton = document.getElementById('delete-button');
|
56
|
-
|
57
|
-
const updateDeleteButton = () => {
|
58
|
-
const anyChecked = Array.from(childCheckboxes).some(checkbox => checkbox.checked);
|
59
|
-
deleteButton.style.display = anyChecked ? 'block' : 'none';
|
60
|
-
};
|
61
|
-
|
62
|
-
const updateMainCheckbox = () => {
|
63
|
-
// Count the number of checked child checkboxes
|
64
|
-
const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
|
65
|
-
// Determine if the main checkbox should be in an indeterminate state
|
66
|
-
const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
|
67
|
-
|
68
|
-
// Set the main checkbox states
|
69
|
-
mainCheckbox.indeterminate = indeterminate;
|
70
|
-
mainCheckbox.checked = checkedCount > 0;
|
71
|
-
|
72
|
-
// Determine the icon class to add and remove based on the number of checked checkboxes
|
73
|
-
const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
|
74
|
-
const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
|
75
|
-
|
76
|
-
// Add and remove the icon class to the main checkbox wrapper
|
77
|
-
mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
|
78
|
-
mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
|
79
|
-
|
80
|
-
// Toggle the visibility of the checkbox icon based on the indeterminate state
|
81
|
-
mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
|
82
|
-
mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
|
83
|
-
|
84
|
-
updateDeleteButton();
|
85
|
-
};
|
86
|
-
|
87
|
-
mainCheckbox.addEventListener('change', function() {
|
88
|
-
childCheckboxes.forEach(cb => cb.checked = this.checked);
|
89
|
-
updateMainCheckbox();
|
90
|
-
});
|
91
|
-
|
92
|
-
childCheckboxes.forEach(cb => {
|
93
|
-
cb.addEventListener('change', updateMainCheckbox);
|
94
|
-
});
|
95
|
-
});
|
96
|
-
</script>
|
48
|
+
<% end %>
|
@@ -3,7 +3,7 @@
|
|
3
3
|
@import "../../pb_caption/caption_mixin";
|
4
4
|
|
5
5
|
@media only screen and (max-width: $screen-xs-max) {
|
6
|
-
[class^=pb_table] {
|
6
|
+
[class^=pb_table]:not(.table-responsive-scroll) {
|
7
7
|
&.table-sm.table-collapse-sm,
|
8
8
|
&.table-md.table-collapse-sm,
|
9
9
|
&.table-lg.table-collapse-sm {
|