playbook_ui 14.20.0.pre.rc.2 → 14.20.0
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/TableActionBar.tsx +61 -35
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +36 -22
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +6 -19
- 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_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/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_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 +334 -41
- data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +39 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +16 -12
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +78 -12
- 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_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-MUu4QW0I.js +22 -0
- data/dist/chunks/_weekday_stacked-CZJor-EY.js +45 -0
- data/dist/chunks/lazysizes-DHz07jlL.js +1 -0
- data/dist/chunks/lib-DFF1N868.js +29 -0
- data/dist/chunks/{pb_form_validation-WWvUXPKD.js → pb_form_validation-D1Bwm-op.js} +1 -1
- data/dist/chunks/vendor.js +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 +1 -1
- metadata +27 -8
- 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/lazysizes-B7xYodB-.js +0 -1
- 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";
|
@@ -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,9 +72,19 @@ 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 ? (
|
@@ -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;
|
@@ -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 } %>
|
@@ -29,6 +29,7 @@ import { GenericObject, Noop } from '../types'
|
|
29
29
|
* @prop {boolean} async - whether Typeahead should fetch data from
|
30
30
|
* a remote location to populate the options
|
31
31
|
* @prop {string} label - the text for the optional typeahead input label
|
32
|
+
* @prop {boolean} preserveSearchInput - whether to preserve the input value when the field loses focus
|
32
33
|
*/
|
33
34
|
|
34
35
|
type TypeaheadProps = {
|
@@ -54,6 +55,7 @@ type TypeaheadProps = {
|
|
54
55
|
optionsByContext?: Record<string, Array<{ label: string; value?: string }>>
|
55
56
|
searchContextSelector?: string,
|
56
57
|
clearOnContextChange?: boolean,
|
58
|
+
preserveSearchInput?: boolean,
|
57
59
|
} & GlobalProps
|
58
60
|
|
59
61
|
export type SelectValueType = {
|
@@ -93,8 +95,44 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
93
95
|
optionsByContext = {},
|
94
96
|
searchContextSelector,
|
95
97
|
clearOnContextChange = false,
|
98
|
+
preserveSearchInput = false, // Default to false to maintain backward compatibility
|
96
99
|
...props
|
97
100
|
}: TypeaheadProps) => {
|
101
|
+
// State to manage the input value when preserveSearchInput is true
|
102
|
+
const [inputValue, setInputValue] = useState("")
|
103
|
+
|
104
|
+
// If preserveSearchInput is true, we need to control the input value
|
105
|
+
const handleInputChange = preserveSearchInput
|
106
|
+
? (newValue: string, actionMeta: {action: string}) => {
|
107
|
+
// Only update the input value for certain actions
|
108
|
+
if (actionMeta.action === 'input-change') {
|
109
|
+
setInputValue(newValue)
|
110
|
+
} else if (actionMeta.action === 'menu-close' && !props.value) {
|
111
|
+
// Don't clear the input when the menu closes without a selection
|
112
|
+
// unless the component is controlled and has a value
|
113
|
+
} else if (actionMeta.action === 'set-value') {
|
114
|
+
// When an option is selected, clear the input
|
115
|
+
setInputValue('')
|
116
|
+
}
|
117
|
+
|
118
|
+
// If the original onInputChange was provided, call it too
|
119
|
+
if (props.onInputChange) {
|
120
|
+
return props.onInputChange(newValue, actionMeta)
|
121
|
+
}
|
122
|
+
return newValue
|
123
|
+
}
|
124
|
+
: props.onInputChange
|
125
|
+
|
126
|
+
// Handle blur events if we're preserving input
|
127
|
+
const handleBlur = preserveSearchInput
|
128
|
+
? (event: React.FocusEvent<HTMLInputElement>) => {
|
129
|
+
// Do not clear input on blur - the value is preserved in our state
|
130
|
+
if (props.onBlur) {
|
131
|
+
props.onBlur(event)
|
132
|
+
}
|
133
|
+
}
|
134
|
+
: props.onBlur
|
135
|
+
|
98
136
|
const selectProps = {
|
99
137
|
cacheOptions: true,
|
100
138
|
components: {
|
@@ -124,11 +162,29 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
124
162
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
125
163
|
onMultiValueClick: (_option: SelectValueType): any => undefined,
|
126
164
|
pillColor: pillColor,
|
165
|
+
...(preserveSearchInput ? { inputValue } : {}),
|
166
|
+
onInputChange: handleInputChange,
|
167
|
+
onBlur: handleBlur,
|
127
168
|
...props,
|
128
169
|
}
|
129
170
|
|
130
171
|
const [contextValue, setContextValue] = useState("")
|
131
172
|
|
173
|
+
// Add listener for clearing
|
174
|
+
useEffect(() => {
|
175
|
+
const handleClear = () => {
|
176
|
+
if (preserveSearchInput) {
|
177
|
+
setInputValue('')
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
document.addEventListener(`pb-typeahead-kit-${selectProps.id}:clear`, handleClear)
|
182
|
+
|
183
|
+
return () => {
|
184
|
+
document.removeEventListener(`pb-typeahead-kit-${selectProps.id}:clear`, handleClear)
|
185
|
+
}
|
186
|
+
}, [selectProps.id, preserveSearchInput])
|
187
|
+
|
132
188
|
useEffect(() => {
|
133
189
|
if (searchContextSelector) {
|
134
190
|
const searchContextElement = document.getElementById(searchContextSelector)
|
@@ -137,7 +193,12 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
137
193
|
const handleContextChange = (e: Event) => {
|
138
194
|
const target = e.target as HTMLInputElement;
|
139
195
|
setContextValue(target.value);
|
140
|
-
if (clearOnContextChange)
|
196
|
+
if (clearOnContextChange) {
|
197
|
+
document.dispatchEvent(new CustomEvent(`pb-typeahead-kit-${selectProps.id}:clear`))
|
198
|
+
if (preserveSearchInput) {
|
199
|
+
setInputValue('')
|
200
|
+
}
|
201
|
+
}
|
141
202
|
}
|
142
203
|
|
143
204
|
if (searchContextElement) searchContextElement.addEventListener('change', handleContextChange)
|
@@ -146,7 +207,7 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
146
207
|
if (searchContextElement) searchContextElement.removeEventListener('change', handleContextChange)
|
147
208
|
}
|
148
209
|
}
|
149
|
-
}, [searchContextSelector])
|
210
|
+
}, [searchContextSelector, clearOnContextChange, selectProps.id, preserveSearchInput])
|
150
211
|
|
151
212
|
const contextArray = optionsByContext[contextValue]
|
152
213
|
if (Array.isArray(contextArray) && contextArray.length > 0) {
|
@@ -168,7 +229,12 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
168
229
|
onChange(_data)
|
169
230
|
}
|
170
231
|
}
|
171
|
-
|
232
|
+
|
233
|
+
// If a value is selected and we're preserving input on blur, clear the input
|
234
|
+
if (action === 'select-option' && preserveSearchInput) {
|
235
|
+
setInputValue('')
|
236
|
+
}
|
237
|
+
|
172
238
|
if (action === 'select-option') {
|
173
239
|
if (selectProps.onMultiValueClick) selectProps.onMultiValueClick(option)
|
174
240
|
const multiValueClearEvent = new CustomEvent(`pb-typeahead-kit-${selectProps.id}-result-option-select`, { detail: option ? option : _data })
|
@@ -181,6 +247,10 @@ const Typeahead = forwardRef<HTMLInputElement, TypeaheadProps>(({
|
|
181
247
|
if (action === 'clear') {
|
182
248
|
const multiValueClearEvent = new CustomEvent(`pb-typeahead-kit-${selectProps.id}-result-clear`)
|
183
249
|
document.dispatchEvent(multiValueClearEvent)
|
250
|
+
// If preserving input on blur, also clear input on explicit clear
|
251
|
+
if (preserveSearchInput) {
|
252
|
+
setInputValue('')
|
253
|
+
}
|
184
254
|
}
|
185
255
|
}
|
186
256
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
import Typeahead from '../_typeahead'
|
4
|
+
|
5
|
+
const options = [
|
6
|
+
{ label: 'Orange', value: '#FFA500' },
|
7
|
+
{ label: 'Red', value: '#FF0000' },
|
8
|
+
{ label: 'Green', value: '#00FF00' },
|
9
|
+
{ label: 'Blue', value: '#0000FF' },
|
10
|
+
]
|
11
|
+
|
12
|
+
const TypeaheadPreserveInput = (props) => {
|
13
|
+
return (
|
14
|
+
<Typeahead
|
15
|
+
label="Colors"
|
16
|
+
options={options}
|
17
|
+
preserveSearchInput
|
18
|
+
{...props}
|
19
|
+
/>
|
20
|
+
)
|
21
|
+
}
|
22
|
+
|
23
|
+
export default TypeaheadPreserveInput
|
@@ -0,0 +1 @@
|
|
1
|
+
By default, text is not preserved in the typeahead kit when you click off of the input field. You can utilize the `preserveSearchInput` prop in order to prevent text from being cleared when the field loses focus
|
@@ -15,3 +15,4 @@ export { default as TypeaheadWithPillsColor } from './_typeahead_with_pills_colo
|
|
15
15
|
export { default as TypeaheadTruncatedText } from './_typeahead_truncated_text.jsx'
|
16
16
|
export { default as TypeaheadReactHook } from './_typeahead_react_hook.jsx'
|
17
17
|
export { default as TypeaheadDisabled } from './_typeahead_disabled.jsx'
|
18
|
+
export { default as TypeaheadPreserveInput } from './_typeahead_preserve_input.jsx'
|