playbook_ui 14.19.0 → 14.20.0.pre.alpha.PLAY2170checkboxrailsindeterminatelogicinkitPOC7980
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +11 -1
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +175 -16
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +56 -25
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +23 -13
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/VisibilityTree.ts +47 -0
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +6 -10
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +7 -2
- 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 +9 -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.jsx +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.md +4 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.jsx +62 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.jsx +82 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.jsx +66 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -0
- 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_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 +6 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +5 -1
- data/app/pb_kits/playbook/pb_advanced_table/index.js +155 -12
- data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +1 -0
- 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 +8 -12
- data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +3 -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_dropdown/_dropdown.scss +1 -1
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +77 -19
- 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/_dropdown_with_custom_display.jsx +11 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.md +1 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +33 -2
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.md +3 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +11 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +5 -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 +336 -30
- data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +39 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +2 -2
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +16 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +79 -13
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +58 -0
- data/app/pb_kits/playbook/pb_file_upload/_file_upload.scss +13 -0
- data/app/pb_kits/playbook/pb_file_upload/_file_upload.tsx +11 -1
- data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.html.erb +1 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/_file_upload_error.jsx +41 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_file_upload/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_file_upload/file_upload.html.erb +1 -0
- data/app/pb_kits/playbook/pb_file_upload/file_upload.rb +7 -1
- data/app/pb_kits/playbook/pb_file_upload/fileupload.test.js +18 -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_form_group/_error_state_mixin.scss +2 -2
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.scss +19 -12
- data/app/pb_kits/playbook/pb_home_address_street/_home_address_street.tsx +13 -7
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +2 -2
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_color.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_default.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_disabled_options_parent_default.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_error.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_label.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_react_hook.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.html.erb +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids.md +2 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_selected_ids_react.md +3 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.html.erb +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single.jsx +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.html.erb +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_single_children_only.jsx +22 -22
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +11 -11
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_form.html.erb +11 -11
- data/app/pb_kits/playbook/pb_person/_person.tsx +12 -2
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +9 -9
- 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_section_separator/_section_separator.tsx +2 -2
- 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_text_input/_text_input.scss +4 -2
- 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-CRW6dJbW.js +22 -0
- data/dist/chunks/_weekday_stacked-C4d17aYW.js +45 -0
- data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
- data/dist/chunks/lib-D5R1BjUn.js +29 -0
- data/dist/chunks/{pb_form_validation-BioH7DWv.js → pb_form_validation-BZ2AVAi_.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 +52 -8
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +0 -10
- data/dist/chunks/_typeahead-D62OcwsT.js +0 -22
- data/dist/chunks/_weekday_stacked-Ceh9N0ow.js +0 -45
- data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
- data/dist/chunks/lib-CeKZrPmu.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";
|
@@ -44,12 +45,14 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
44
45
|
const {
|
45
46
|
autocomplete,
|
46
47
|
filterItem,
|
48
|
+
handleBackspace,
|
47
49
|
handleChange,
|
48
50
|
handleWrapperClick,
|
49
51
|
inputRef,
|
50
52
|
inputWrapperRef,
|
51
53
|
isDropDownClosed,
|
52
54
|
isInputFocused,
|
55
|
+
multiSelect,
|
53
56
|
selected,
|
54
57
|
setIsInputFocused,
|
55
58
|
toggleDropdown,
|
@@ -69,11 +72,21 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
69
72
|
const triggerWrapperClasses = buildCss(
|
70
73
|
"dropdown_trigger_wrapper",
|
71
74
|
isInputFocused && "focus",
|
72
|
-
!autocomplete && "select_only"
|
75
|
+
!autocomplete && !multiSelect && "select_only"
|
73
76
|
);
|
74
77
|
|
78
|
+
const selectedArray = Array.isArray(selected)
|
79
|
+
? selected
|
80
|
+
: selected && Object.keys(selected).length
|
81
|
+
? [selected]
|
82
|
+
: [];
|
83
|
+
|
84
|
+
const joinedLabels = multiSelect
|
85
|
+
? ""
|
86
|
+
: selectedArray.map((option) => option.label).join(", ");
|
87
|
+
|
75
88
|
const customDisplayPlaceholder = selected?.label ? (
|
76
|
-
|
89
|
+
""
|
77
90
|
) : autocomplete ? (
|
78
91
|
""
|
79
92
|
) : placeholder ? (
|
@@ -82,8 +95,8 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
82
95
|
"Select..."
|
83
96
|
);
|
84
97
|
|
85
|
-
const defaultDisplayPlaceholder =
|
86
|
-
?
|
98
|
+
const defaultDisplayPlaceholder = joinedLabels
|
99
|
+
? joinedLabels
|
87
100
|
: autocomplete
|
88
101
|
? ""
|
89
102
|
: placeholder
|
@@ -125,23 +138,60 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
125
138
|
paddingX="sm"
|
126
139
|
paddingY="xs"
|
127
140
|
>
|
128
|
-
<FlexItem>
|
129
|
-
<Flex align="center"
|
141
|
+
<FlexItem fixedSize={multiSelect ? "85%" : ""}>
|
142
|
+
<Flex align="center"
|
143
|
+
wrap
|
144
|
+
>
|
130
145
|
{customDisplay ? (
|
131
146
|
<Flex align="center">
|
132
147
|
{customDisplay}
|
133
148
|
<Body dark={dark}
|
134
|
-
paddingLeft={`${
|
149
|
+
paddingLeft={`${joinedLabels ? "xs" : "none"}`}
|
135
150
|
>
|
136
151
|
{customDisplayPlaceholder}
|
137
152
|
</Body>
|
138
153
|
</Flex>
|
139
154
|
) : (
|
140
|
-
|
141
|
-
|
142
|
-
|
155
|
+
multiSelect ? (
|
156
|
+
<>
|
157
|
+
<MultiSelectTriggerDisplay
|
158
|
+
autocomplete={autocomplete}
|
159
|
+
dark={dark}
|
160
|
+
placeholder={placeholder}
|
161
|
+
selected={selectedArray}
|
162
|
+
/>
|
163
|
+
{autocomplete && (
|
164
|
+
<input
|
165
|
+
className="dropdown_input"
|
166
|
+
onChange={handleChange}
|
167
|
+
onClick={(e) => {
|
168
|
+
e.stopPropagation();// keep the wrapper’s handler from firing
|
169
|
+
toggleDropdown();
|
170
|
+
}}
|
171
|
+
onFocus={() => setIsInputFocused(true)}
|
172
|
+
onKeyDown={(e) => {
|
173
|
+
handleKeyDown(e);
|
174
|
+
e.stopPropagation(); //Fixes issue with keyboard accessibility
|
175
|
+
}}
|
176
|
+
placeholder={
|
177
|
+
joinedLabels
|
178
|
+
? ""
|
179
|
+
: placeholder
|
180
|
+
? placeholder
|
181
|
+
: "Select..."
|
182
|
+
}
|
183
|
+
ref={inputRef}
|
184
|
+
value={filterItem}
|
185
|
+
/>
|
186
|
+
)}
|
187
|
+
</>
|
188
|
+
) : (
|
189
|
+
<Body dark={dark}
|
190
|
+
text={defaultDisplayPlaceholder}
|
191
|
+
/>
|
192
|
+
)
|
143
193
|
)}
|
144
|
-
{autocomplete && (
|
194
|
+
{autocomplete && !multiSelect && (
|
145
195
|
<input
|
146
196
|
className="dropdown_input"
|
147
197
|
onChange={handleChange}
|
@@ -152,7 +202,7 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
152
202
|
onFocus={() => setIsInputFocused(true)}
|
153
203
|
onKeyDown={handleKeyDown}
|
154
204
|
placeholder={
|
155
|
-
|
205
|
+
joinedLabels
|
156
206
|
? ""
|
157
207
|
: placeholder
|
158
208
|
? placeholder
|
@@ -164,14 +214,29 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
164
214
|
)}
|
165
215
|
</Flex>
|
166
216
|
</FlexItem>
|
217
|
+
<FlexItem>
|
167
218
|
<Body
|
219
|
+
alignItems="center"
|
168
220
|
dark={dark}
|
169
221
|
display="flex"
|
170
222
|
htmlOptions={{
|
171
223
|
onClick: (e: Event) => {e.stopPropagation();handleWrapperClick()}
|
172
224
|
}}
|
173
225
|
key={`${isDropDownClosed ? "chevron-down" : "chevron-up"}`}
|
174
|
-
>
|
226
|
+
>
|
227
|
+
{
|
228
|
+
selectedArray.length > 0 && (
|
229
|
+
<div onClick={(e)=>{e.stopPropagation();handleBackspace()}}>
|
230
|
+
<Icon
|
231
|
+
cursor="pointer"
|
232
|
+
dark={dark}
|
233
|
+
icon="times"
|
234
|
+
paddingRight="xs"
|
235
|
+
size="sm"
|
236
|
+
/>
|
237
|
+
</div>
|
238
|
+
)
|
239
|
+
}
|
175
240
|
<Icon
|
176
241
|
cursor="pointer"
|
177
242
|
dark={dark}
|
@@ -179,6 +244,7 @@ const DropdownTrigger = (props: DropdownTriggerProps) => {
|
|
179
244
|
size="sm"
|
180
245
|
/>
|
181
246
|
</Body>
|
247
|
+
</FlexItem>
|
182
248
|
</Flex>
|
183
249
|
</>
|
184
250
|
)
|
@@ -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;
|
@@ -9,10 +9,23 @@
|
|
9
9
|
border: none;
|
10
10
|
width: 0;
|
11
11
|
}
|
12
|
+
&.error {
|
13
|
+
[class^='pb_card_kit'] {
|
14
|
+
border-color: $error;
|
15
|
+
}
|
16
|
+
[class^='pb_body_kit'][status="negative"] {
|
17
|
+
margin-top: $space_xs;
|
18
|
+
}
|
19
|
+
}
|
12
20
|
}
|
13
21
|
|
14
22
|
.dark [class*='pb_file_upload_kit'] {
|
15
23
|
[class*='pb_card_kit'] {
|
16
24
|
border: 1px $text_dk_lighter dashed;
|
17
25
|
}
|
26
|
+
&.error {
|
27
|
+
[class^='pb_card_kit'] {
|
28
|
+
border-color: $error_dark;
|
29
|
+
}
|
30
|
+
}
|
18
31
|
}
|
@@ -22,6 +22,7 @@ type FileUploadProps = {
|
|
22
22
|
maxSize?: number,
|
23
23
|
onFilesAccepted: Callback<File, File>,
|
24
24
|
onFilesRejected: (error: string, files: readonly FileRejection[]) => void,
|
25
|
+
error?: string,
|
25
26
|
}
|
26
27
|
|
27
28
|
const getFormattedFileSize = (fileSize: number): string => {
|
@@ -36,6 +37,7 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => {
|
|
36
37
|
customMessage,
|
37
38
|
dark = false,
|
38
39
|
data = {},
|
40
|
+
error,
|
39
41
|
htmlOptions = {},
|
40
42
|
maxSize,
|
41
43
|
onFilesAccepted = noop,
|
@@ -100,7 +102,7 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => {
|
|
100
102
|
|
101
103
|
return (
|
102
104
|
<div
|
103
|
-
className={classnames(buildCss('pb_file_upload_kit'), globalProps(props), className)}
|
105
|
+
className={classnames(buildCss('pb_file_upload_kit'), { 'error': error }, globalProps(props), className)}
|
104
106
|
{...dataProps}
|
105
107
|
{...htmlProps}
|
106
108
|
{...getRootProps()}
|
@@ -118,6 +120,14 @@ const FileUpload = (props: FileUploadProps): React.ReactElement => {
|
|
118
120
|
}
|
119
121
|
</Body>
|
120
122
|
</Card>
|
123
|
+
{error && (
|
124
|
+
<Body
|
125
|
+
dark={dark}
|
126
|
+
marginTop="xxs"
|
127
|
+
status="negative"
|
128
|
+
text={error}
|
129
|
+
/>
|
130
|
+
)}
|
121
131
|
</div>
|
122
132
|
)
|
123
133
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= pb_rails("file_upload", props: {id: "error", error: raw(pb_rails("icon", props: { icon: "warning" }) + " Please upload a valid file")}) %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import FileUpload from '../_file_upload'
|
3
|
+
import List from '../../pb_list/_list'
|
4
|
+
import ListItem from '../../pb_list/_list_item'
|
5
|
+
import Icon from '../../pb_icon/_icon'
|
6
|
+
|
7
|
+
const AcceptedFilesList = ({ files }) => (
|
8
|
+
<List>
|
9
|
+
{files.map((file) => (
|
10
|
+
<ListItem key={file.name}>{file.name}</ListItem>
|
11
|
+
))}
|
12
|
+
</List>
|
13
|
+
)
|
14
|
+
|
15
|
+
const FileUploadError = (props) => {
|
16
|
+
const [filesToUpload, setFilesToUpload] = useState([])
|
17
|
+
|
18
|
+
const handleOnFilesAccepted = (files) => {
|
19
|
+
setFilesToUpload([...filesToUpload, ...files])
|
20
|
+
}
|
21
|
+
|
22
|
+
const error = (<>
|
23
|
+
<Icon icon="warning" /> Please upload a valid file
|
24
|
+
</>)
|
25
|
+
|
26
|
+
return (
|
27
|
+
<div>
|
28
|
+
<AcceptedFilesList
|
29
|
+
files={filesToUpload}
|
30
|
+
{...props}
|
31
|
+
/>
|
32
|
+
<FileUpload
|
33
|
+
error={error}
|
34
|
+
onFilesAccepted={handleOnFilesAccepted}
|
35
|
+
{...props}
|
36
|
+
/>
|
37
|
+
</div>
|
38
|
+
)
|
39
|
+
}
|
40
|
+
|
41
|
+
export default FileUploadError
|
@@ -3,6 +3,7 @@ examples:
|
|
3
3
|
rails:
|
4
4
|
- file_upload_default: File Upload
|
5
5
|
- file_upload_custom: Custom
|
6
|
+
- file_upload_error: Error
|
6
7
|
|
7
8
|
react:
|
8
9
|
- file_upload_default: Default List of files to upload
|
@@ -10,3 +11,4 @@ examples:
|
|
10
11
|
- file_upload_custom_message: Add a custom message
|
11
12
|
- file_upload_custom_description: Add your one accepted files description
|
12
13
|
- file_upload_max_size: Set a file size limit
|
14
|
+
- file_upload_error: Error
|
@@ -3,3 +3,4 @@ export { default as FileUploadAccept } from './_file_upload_accept.jsx'
|
|
3
3
|
export { default as FileUploadCustomMessage } from './_file_upload_custom_message.jsx'
|
4
4
|
export { default as FileUploadCustomDescription } from './_file_upload_custom_description.jsx'
|
5
5
|
export { default as FileUploadMaxSize } from './_file_upload_max_size.jsx'
|
6
|
+
export { default as FileUploadError } from './_file_upload_error.jsx'
|
@@ -21,14 +21,20 @@ module Playbook
|
|
21
21
|
prop :input_options, type: Playbook::Props::HashProp,
|
22
22
|
default: {}
|
23
23
|
|
24
|
+
prop :error, type: Playbook::Props::String
|
25
|
+
|
24
26
|
def classname
|
25
27
|
file_upload_class = generate_classname("pb_file_upload_kit")
|
26
|
-
file_upload_class + full_width_class
|
28
|
+
file_upload_class + error_class + full_width_class
|
27
29
|
end
|
28
30
|
|
29
31
|
def full_width_class
|
30
32
|
full_width ? " full_width" : ""
|
31
33
|
end
|
34
|
+
|
35
|
+
def error_class
|
36
|
+
error.present? ? "_error" : ""
|
37
|
+
end
|
32
38
|
end
|
33
39
|
end
|
34
40
|
end
|
@@ -50,3 +50,21 @@ test('displays custom message', () => {
|
|
50
50
|
const kit = screen.getByTestId(testid)
|
51
51
|
expect(kit).toHaveTextContent('Hello world!')
|
52
52
|
})
|
53
|
+
|
54
|
+
test('handles error state with error prop', () => {
|
55
|
+
const errorText = "Test error message"
|
56
|
+
render(
|
57
|
+
<FileUpload
|
58
|
+
data={{ testid: testid }}
|
59
|
+
error={errorText}
|
60
|
+
/>
|
61
|
+
)
|
62
|
+
|
63
|
+
const kit = screen.getByTestId(testid)
|
64
|
+
|
65
|
+
expect(kit).toHaveClass('pb_file_upload_kit')
|
66
|
+
expect(kit).toHaveClass('error')
|
67
|
+
|
68
|
+
const errorElement = screen.getByText(errorText)
|
69
|
+
expect(errorElement).toBeInTheDocument()
|
70
|
+
})
|
@@ -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 } %>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
@mixin error-state-right-side-select-kit {
|
24
24
|
&:has(.pb_text_input_kit:not(.error)):has(.pb_text_input_kit_label):has(.pb_select_kit_wrapper.error),
|
25
25
|
&:has(.pb_text_input_kit.error):has(.pb_text_input_kit_label):has(.pb_select_kit_wrapper) {
|
26
|
-
&:not(:has(.pb_phone_number_input)) {
|
26
|
+
&:not(:has(.pb_phone_number_input)):not(:has(.passphrase-text-input)) {
|
27
27
|
align-items: flex-start;
|
28
28
|
|
29
29
|
.pb_select_kit_wrapper {
|
@@ -49,7 +49,7 @@
|
|
49
49
|
|
50
50
|
@mixin error-state-left-side-select-kit {
|
51
51
|
&:has(.pb_select_kit_label):has(.pb_select_kit_wrapper):has(.pb_text_input_kit.error) {
|
52
|
-
&:not(:has(.pb_phone_number_input)) {
|
52
|
+
&:not(:has(.pb_phone_number_input)):not(:has(.passphrase-text-input)) {
|
53
53
|
align-items: flex-start;
|
54
54
|
|
55
55
|
.pb_text_input_kit.error {
|
@@ -20,9 +20,12 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
|
|
20
20
|
margin-bottom: 2px;
|
21
21
|
margin-top: 2px;
|
22
22
|
cursor: pointer;
|
23
|
-
.pb_form_pill_text, .
|
23
|
+
.pb_form_pill_text, .pb_form_pill_tag {
|
24
24
|
font-size: $font_small !important;
|
25
25
|
}
|
26
|
+
.pb_form_pill_close {
|
27
|
+
font-size: 17px;
|
28
|
+
}
|
26
29
|
|
27
30
|
&[class*=wrapped] {
|
28
31
|
height: max-content;
|
@@ -96,7 +99,9 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
|
|
96
99
|
display: flex;
|
97
100
|
align-items: center;
|
98
101
|
height: 17px;
|
99
|
-
|
102
|
+
width: 17px;
|
103
|
+
justify-content: center;
|
104
|
+
border-radius: 50%;
|
100
105
|
cursor: pointer;
|
101
106
|
@if ($color_name == "neutral") {
|
102
107
|
color: $text_lt_default;
|
@@ -146,8 +151,7 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
|
|
146
151
|
outline-offset: -1px;
|
147
152
|
}
|
148
153
|
.pb_form_pill_icon {
|
149
|
-
height:
|
150
|
-
width: 12px !important;
|
154
|
+
height: 0.875em;
|
151
155
|
padding-right: $space_xs;
|
152
156
|
+ .pb_form_pill_text, + .pb_form_pill_tag,
|
153
157
|
+ .pb_tooltip_kit .pb_form_pill_text, + .pb_tooltip_kit .pb_form_pill_tag,
|
@@ -158,7 +162,7 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
|
|
158
162
|
&.small {
|
159
163
|
height: 17px;
|
160
164
|
padding: 0 $space-xs;
|
161
|
-
.pb_form_pill_text, .
|
165
|
+
.pb_form_pill_text, .pb_form_pill_tag {
|
162
166
|
font-size: $font_smallest !important;
|
163
167
|
}
|
164
168
|
.pb_form_pill_text, .pb_form_pill_tag {
|
@@ -166,17 +170,20 @@ $form_pill_colors: map-merge($status_color_text, map-merge($data_colors, $produc
|
|
166
170
|
padding: 0 $space_xxs;
|
167
171
|
}
|
168
172
|
.pb_form_pill_close {
|
169
|
-
height:
|
170
|
-
|
173
|
+
height: 14px;
|
174
|
+
width: 14px;
|
175
|
+
font-size: 15px;
|
176
|
+
border-radius: 50%;
|
171
177
|
}
|
172
178
|
[class^=pb_avatar_kit] .avatar_wrapper {
|
173
|
-
flex-basis:
|
174
|
-
height:
|
175
|
-
margin-top:
|
176
|
-
width:
|
177
|
-
&::before { line-height:
|
179
|
+
flex-basis: 14px;
|
180
|
+
height: 14px;
|
181
|
+
margin-top: 3px;
|
182
|
+
width: 14px;
|
183
|
+
&::before { line-height: 15px; }
|
178
184
|
}
|
179
185
|
.pb_form_pill_icon {
|
186
|
+
height: 0.75em;
|
180
187
|
padding-right: $space_xxs;
|
181
188
|
+ .pb_form_pill_text, + .pb_form_pill_tag,
|
182
189
|
+ .pb_tooltip_kit .pb_form_pill_text, + .pb_tooltip_kit .pb_form_pill_tag,
|
@@ -81,6 +81,11 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
81
81
|
|
82
82
|
const formatStreetAdr = (address: string): string => preserveCase ? address : titleize(address)
|
83
83
|
|
84
|
+
const uppercaseState = state?.toUpperCase() ?? ''
|
85
|
+
|
86
|
+
const fields = [address, addressCont, city, homeId, homeUrl, houseStyle, state, territory, zipcode]
|
87
|
+
const hasAllEmptyProps = fields.every(field => field === undefined || field === null || field === '')
|
88
|
+
|
84
89
|
return (
|
85
90
|
<div
|
86
91
|
className={classes(className, dark)}
|
@@ -88,7 +93,8 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
88
93
|
{...dataProps}
|
89
94
|
{...htmlProps}
|
90
95
|
>
|
91
|
-
{
|
96
|
+
{hasAllEmptyProps && '—'}
|
97
|
+
{emphasis == 'street' && !hasAllEmptyProps &&
|
92
98
|
<div>
|
93
99
|
<Title
|
94
100
|
className="pb_home_address_street_address"
|
@@ -105,11 +111,11 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
105
111
|
{titleize(addressCont)}
|
106
112
|
</Title>
|
107
113
|
<Body color="light">
|
108
|
-
{`${titleize(city)}, ${
|
114
|
+
{`${city ? `${titleize(city)}, ` : ''}${uppercaseState}${zipcode ? ` ${zipcode}` : ''}`}
|
109
115
|
</Body>
|
110
116
|
</div>
|
111
117
|
}
|
112
|
-
{emphasis == 'city' &&
|
118
|
+
{emphasis == 'city' && !hasAllEmptyProps &&
|
113
119
|
<div>
|
114
120
|
<Body color="light">
|
115
121
|
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
@@ -122,18 +128,18 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
122
128
|
size={4}
|
123
129
|
tag="span"
|
124
130
|
>
|
125
|
-
{`${titleize(city)}, ${
|
131
|
+
{`${city ? `${titleize(city)}, ` : ''}${uppercaseState}`}
|
126
132
|
</Title>
|
127
133
|
<Body
|
128
134
|
color="light"
|
129
135
|
tag="span"
|
130
136
|
>
|
131
|
-
{` ${zipcode}`}
|
137
|
+
{` ${zipcode ?? ''}`}
|
132
138
|
</Body>
|
133
139
|
</div>
|
134
140
|
</div>
|
135
141
|
}
|
136
|
-
{emphasis == 'none' &&
|
142
|
+
{emphasis == 'none' && !hasAllEmptyProps &&
|
137
143
|
<div>
|
138
144
|
<Body dark={dark}>
|
139
145
|
{joinPresent([formatStreetAdr(address), houseStyle], ' · ')}
|
@@ -144,7 +150,7 @@ const HomeAddressStreet = (props: HomeAddressStreetProps): React.ReactElement =>
|
|
144
150
|
color="light"
|
145
151
|
dark={dark}
|
146
152
|
>
|
147
|
-
{`${titleize(city)}, ${
|
153
|
+
{`${city ? `${titleize(city)}, ` : ''}${uppercaseState}${zipcode ? ` ${zipcode}` : ''}`}
|
148
154
|
</Body>
|
149
155
|
</div>
|
150
156
|
</div>
|
@@ -195,8 +195,8 @@ const MultiLevelSelect = forwardRef<HTMLInputElement, MultiLevelSelectProps>((pr
|
|
195
195
|
if (!selectedItem.length) {
|
196
196
|
setSingleSelectedItem({ id: [], value: "", item: [] });
|
197
197
|
} else {
|
198
|
-
const { id,
|
199
|
-
setSingleSelectedItem({ id: [id], value, item: selectedItem });
|
198
|
+
const { id, label } = selectedItem[0];
|
199
|
+
setSingleSelectedItem({ id: [id], value: label, item: selectedItem });
|
200
200
|
}
|
201
201
|
}
|
202
202
|
}
|
@@ -1,62 +1,62 @@
|
|
1
1
|
<% treeData = [{
|
2
2
|
label: "Power Home Remodeling",
|
3
|
-
value: "
|
3
|
+
value: "powerHomeRemodeling",
|
4
4
|
id: "100",
|
5
5
|
expanded: true,
|
6
6
|
children: [
|
7
7
|
{
|
8
8
|
label: "People",
|
9
|
-
value: "
|
9
|
+
value: "people",
|
10
10
|
id: "101",
|
11
11
|
expanded: true,
|
12
12
|
children: [
|
13
13
|
{
|
14
14
|
label: "Talent Acquisition",
|
15
|
-
value: "
|
15
|
+
value: "talentAcquisition",
|
16
16
|
id: "102",
|
17
17
|
},
|
18
18
|
{
|
19
19
|
label: "Business Affairs",
|
20
|
-
value: "
|
20
|
+
value: "businessAffairs",
|
21
21
|
id: "103",
|
22
22
|
children: [
|
23
23
|
{
|
24
24
|
label: "Initiatives",
|
25
|
-
value: "
|
25
|
+
value: "initiatives",
|
26
26
|
id: "104",
|
27
27
|
},
|
28
28
|
{
|
29
29
|
label: "Learning & Development",
|
30
|
-
value: "
|
30
|
+
value: "learningAndDevelopment",
|
31
31
|
id: "105",
|
32
32
|
},
|
33
33
|
],
|
34
34
|
},
|
35
35
|
{
|
36
36
|
label: "People Experience",
|
37
|
-
value: "
|
37
|
+
value: "peopleExperience",
|
38
38
|
id: "106",
|
39
39
|
},
|
40
40
|
],
|
41
41
|
},
|
42
42
|
{
|
43
43
|
label: "Contact Center",
|
44
|
-
value: "
|
44
|
+
value: "contactCenter",
|
45
45
|
id: "107",
|
46
46
|
children: [
|
47
47
|
{
|
48
48
|
label: "Appointment Management",
|
49
|
-
value: "
|
49
|
+
value: "appointmentManagement",
|
50
50
|
id: "108",
|
51
51
|
},
|
52
52
|
{
|
53
53
|
label: "Customer Service",
|
54
|
-
value: "
|
54
|
+
value: "customerService",
|
55
55
|
id: "109",
|
56
56
|
},
|
57
57
|
{
|
58
58
|
label: "Energy",
|
59
|
-
value: "
|
59
|
+
value: "energy",
|
60
60
|
id: "110",
|
61
61
|
},
|
62
62
|
],
|