clayui-multi-select 3.165.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.
package/README.md ADDED
@@ -0,0 +1,19 @@
1
+ # `@clayui/multi-select`
2
+
3
+ Multi select is the field type that allows writing text to create "tags" that are represented in the shape of labels.
4
+
5
+ - [Documentation](https://clayui.com/docs/components/multi-select.html)
6
+ - [Changelog](./CHANGELOG.md)
7
+ - [Breaking change schedule](./BREAKING.md)
8
+
9
+ ## Install
10
+
11
+ Run `yarn`
12
+
13
+ ```shell
14
+ yarn add @clayui/multi-select
15
+ ```
16
+
17
+ ## Contribute
18
+
19
+ We'd love to get contributions from you! Please, check our [Contributing Guidelines](https://github.com/liferay/clay/blob/master/CONTRIBUTING.md) to see how you can help us improve.
@@ -0,0 +1,349 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var Labels_exports = {};
30
+ __export(Labels_exports, {
31
+ Labels: () => Labels
32
+ });
33
+ module.exports = __toCommonJS(Labels_exports);
34
+ var import_form = require("@clayui/form");
35
+ var import_icon = __toESM(require("@clayui/icon"));
36
+ var import_label = __toESM(require("@clayui/label"));
37
+ var import_shared = require("@clayui/shared");
38
+ var import_react = __toESM(require("react"));
39
+ const DELIMITER_KEYS = ["Enter", ","];
40
+ const KeysNavigation = [import_shared.Keys.Left, import_shared.Keys.Right, import_shared.Keys.Up, import_shared.Keys.Down];
41
+ const KeysSides = [import_shared.Keys.Left, import_shared.Keys.Right];
42
+ let counterUid = 0;
43
+ const Labels = import_react.default.forwardRef(
44
+ function Labels2({
45
+ allowDuplicateValues = true,
46
+ allowsCustomLabel,
47
+ "aria-activedescendant": activeDescendant,
48
+ ariaDescriptionId,
49
+ closeButtonAriaLabel,
50
+ disabled,
51
+ inputName,
52
+ "insetAfter": _,
53
+ labels,
54
+ lastChangesRef,
55
+ locator,
56
+ onChange,
57
+ onFocusChange,
58
+ onLabelsChange,
59
+ placeholder,
60
+ spritemap,
61
+ suggestionList,
62
+ value,
63
+ ...otherProps
64
+ }, ref) {
65
+ const inputRef = (0, import_react.useRef)(null);
66
+ const labelsRef = (0, import_react.useRef)(null);
67
+ const lastItemRef = (0, import_react.useRef)(null);
68
+ const [isLabelFocused, setIsLabelFocused] = (0, import_react.useState)(
69
+ null
70
+ );
71
+ const [lastFocusedItem, setLastFocusedItem] = (0, import_react.useState)(
72
+ null
73
+ );
74
+ const inputElementRef = ref || inputRef;
75
+ const labelId = (0, import_shared.useId)();
76
+ const getSourceItemByLabel = (label) => {
77
+ return suggestionList.find(
78
+ (item) => (0, import_shared.getLocatorValue)({
79
+ item,
80
+ locator: locator.label
81
+ }) === label
82
+ );
83
+ };
84
+ const getNewItem = (value2) => {
85
+ counterUid++;
86
+ const labelKey = typeof locator.label === "function" ? "label" : locator.label;
87
+ const valueKey = typeof locator.value === "function" ? "value" : locator.value;
88
+ return getSourceItemByLabel(value2) || {
89
+ key: `key_${counterUid}`,
90
+ [labelKey]: value2,
91
+ [valueKey]: value2
92
+ };
93
+ };
94
+ const onRemove = (0, import_react.useCallback)(
95
+ (label, index) => {
96
+ if (labelsRef.current) {
97
+ const focusableElements = Array.from(
98
+ labelsRef.current.querySelectorAll("button")
99
+ );
100
+ const activeElement = document.activeElement.tagName === "SPAN" ? document.activeElement.querySelector("button") : document.activeElement;
101
+ const position = focusableElements.indexOf(
102
+ activeElement
103
+ );
104
+ const closeElement = focusableElements[focusableElements.length - 1 > position ? position + 1 : position - 1];
105
+ if (closeElement) {
106
+ closeElement.focus();
107
+ setLastFocusedItem(closeElement.getAttribute("id"));
108
+ } else {
109
+ inputElementRef.current?.focus();
110
+ setLastFocusedItem(null);
111
+ }
112
+ }
113
+ lastChangesRef.current = {
114
+ action: "removed",
115
+ label
116
+ };
117
+ onLabelsChange(
118
+ labels.filter((_2, itemIndex) => itemIndex !== index)
119
+ );
120
+ },
121
+ [labels]
122
+ );
123
+ (0, import_react.useEffect)(() => {
124
+ if (labelsRef.current) {
125
+ const focusableElements = Array.from(
126
+ labelsRef.current.querySelectorAll(
127
+ ".label [aria-describedby]"
128
+ )
129
+ );
130
+ const addedLabel = focusableElements[focusableElements.length - 1];
131
+ if (addedLabel) {
132
+ setLastFocusedItem(addedLabel.getAttribute("id"));
133
+ }
134
+ }
135
+ }, [labels]);
136
+ return /* @__PURE__ */ import_react.default.createElement(import_form.ClayInput.GroupItem, null, /* @__PURE__ */ import_react.default.createElement(import_form.ClayInput.Group, null, /* @__PURE__ */ import_react.default.createElement(
137
+ import_form.ClayInput.GroupItem,
138
+ {
139
+ "aria-labelledby": otherProps["aria-labelledby"],
140
+ className: "d-contents",
141
+ onFocus: (event) => setLastFocusedItem(event.target.getAttribute("id")),
142
+ onKeyDown: (event) => {
143
+ if (KeysNavigation.includes(event.key)) {
144
+ event.preventDefault();
145
+ const focusableElements = Array.from(
146
+ event.currentTarget.querySelectorAll(
147
+ KeysSides.includes(event.key) ? "[role=gridcell][tabindex], button" : lastFocusedItem?.includes(
148
+ "span"
149
+ ) ? "[role=gridcell][tabindex]" : "button"
150
+ )
151
+ );
152
+ const position = focusableElements.indexOf(
153
+ document.activeElement
154
+ );
155
+ const key = KeysSides.includes(event.key) ? import_shared.Keys.Left : import_shared.Keys.Up;
156
+ const label = focusableElements[event.key === key ? position - 1 : position + 1];
157
+ if (label) {
158
+ setLastFocusedItem(
159
+ label.getAttribute("id")
160
+ );
161
+ label.focus();
162
+ }
163
+ }
164
+ if (event.key === import_shared.Keys.Home || event.key === import_shared.Keys.End) {
165
+ event.preventDefault();
166
+ const isLabel = lastFocusedItem.includes("span");
167
+ if (isLabel && event.key === import_shared.Keys.Home || !isLabel && event.key === import_shared.Keys.End) {
168
+ return;
169
+ }
170
+ const label = event.currentTarget.querySelector(
171
+ `[id=${lastFocusedItem?.replace(
172
+ isLabel ? "span" : "close",
173
+ event.key === import_shared.Keys.Home ? "span" : "close"
174
+ )}]`
175
+ );
176
+ if (label) {
177
+ setLastFocusedItem(
178
+ label.getAttribute("id")
179
+ );
180
+ label.focus();
181
+ }
182
+ }
183
+ },
184
+ prepend: true,
185
+ ref: (ref2) => {
186
+ labelsRef.current = ref2;
187
+ },
188
+ role: "grid",
189
+ shrink: true
190
+ },
191
+ labels.map((item, i) => {
192
+ const value2 = (0, import_shared.getLocatorValue)({
193
+ item,
194
+ locator: locator.value
195
+ });
196
+ const uid = (0, import_shared.getLocatorValue)({
197
+ item,
198
+ locator: locator.id
199
+ }) ?? value2;
200
+ const id = `${labelId}-label-${uid}-span`;
201
+ const closeId = `${labelId}-label-${uid}-close`;
202
+ const label = (0, import_shared.getLocatorValue)({
203
+ item,
204
+ locator: locator.label
205
+ });
206
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, { key: id }, /* @__PURE__ */ import_react.default.createElement(
207
+ import_label.default,
208
+ {
209
+ className: isLabelFocused === id ? "focus" : void 0,
210
+ onKeyDown: ({ key }) => {
211
+ if (key === import_shared.Keys.Backspace) {
212
+ onRemove(label || "", i);
213
+ }
214
+ },
215
+ role: "row",
216
+ spritemap,
217
+ tabIndex: -1,
218
+ withClose: false
219
+ },
220
+ /* @__PURE__ */ import_react.default.createElement(
221
+ import_label.default.ItemExpand,
222
+ {
223
+ "aria-describedby": ariaDescriptionId,
224
+ id,
225
+ onBlur: () => setIsLabelFocused(null),
226
+ onFocus: () => setIsLabelFocused(id),
227
+ role: "gridcell",
228
+ style: { outline: "none" },
229
+ tabIndex: lastFocusedItem === null && i === 0 || lastFocusedItem === id ? 0 : -1
230
+ },
231
+ label
232
+ ),
233
+ /* @__PURE__ */ import_react.default.createElement(import_label.default.ItemAfter, { role: "gridcell" }, /* @__PURE__ */ import_react.default.createElement(
234
+ "button",
235
+ {
236
+ "aria-label": (0, import_shared.sub)(
237
+ closeButtonAriaLabel,
238
+ [label || ""]
239
+ ),
240
+ className: "close",
241
+ disabled,
242
+ id: closeId,
243
+ onClick: () => onRemove(label || "", i),
244
+ ref: (ref2) => {
245
+ if (i === labels.length - 1) {
246
+ lastItemRef.current = ref2;
247
+ }
248
+ },
249
+ tabIndex: lastFocusedItem === closeId ? 0 : -1,
250
+ type: "button"
251
+ },
252
+ /* @__PURE__ */ import_react.default.createElement(
253
+ import_icon.default,
254
+ {
255
+ spritemap,
256
+ symbol: "times-small"
257
+ }
258
+ )
259
+ ))
260
+ ), inputName && /* @__PURE__ */ import_react.default.createElement(
261
+ "input",
262
+ {
263
+ name: inputName,
264
+ type: "hidden",
265
+ value: value2
266
+ }
267
+ ));
268
+ })
269
+ ), /* @__PURE__ */ import_react.default.createElement(import_form.ClayInput.GroupItem, { prepend: true }, /* @__PURE__ */ import_react.default.createElement(
270
+ "input",
271
+ {
272
+ ...otherProps,
273
+ "aria-activedescendant": activeDescendant,
274
+ className: "form-control-inset",
275
+ disabled,
276
+ onBlur: (event) => {
277
+ if (otherProps.onBlur) {
278
+ otherProps.onBlur(event);
279
+ }
280
+ onFocusChange(false);
281
+ },
282
+ onChange: (event) => {
283
+ const { value: value2 } = event.target;
284
+ event.target.value = allowsCustomLabel ? value2.replace(",", "") : value2;
285
+ onChange(event);
286
+ },
287
+ onFocus: (event) => {
288
+ if (otherProps.onFocus) {
289
+ otherProps.onFocus(event);
290
+ }
291
+ onFocusChange(true);
292
+ },
293
+ onKeyDown: (event) => {
294
+ if (otherProps.onKeyDown) {
295
+ otherProps.onKeyDown(event);
296
+ }
297
+ const { key } = event;
298
+ if (key === import_shared.Keys.Backspace && !value) {
299
+ event.preventDefault();
300
+ }
301
+ if (key === import_shared.Keys.Enter && (activeDescendant || event.defaultPrevented)) {
302
+ return;
303
+ }
304
+ if (allowsCustomLabel && value.trim() && DELIMITER_KEYS.includes(key)) {
305
+ if (!allowDuplicateValues && value && labels.find(
306
+ (label) => label.label?.toLowerCase() === `${value}`.toLowerCase()
307
+ )) {
308
+ onChange({ target: { value: "" } });
309
+ return;
310
+ }
311
+ event.preventDefault();
312
+ lastChangesRef.current = {
313
+ action: "added",
314
+ label: value
315
+ };
316
+ onLabelsChange([
317
+ ...labels,
318
+ getNewItem(value)
319
+ ]);
320
+ onChange({ target: { value: "" } });
321
+ } else if (!value && key === import_shared.Keys.Backspace && inputElementRef.current && lastItemRef.current) {
322
+ inputElementRef.current.blur();
323
+ lastItemRef.current.focus();
324
+ }
325
+ },
326
+ onPaste: (event) => {
327
+ if (otherProps.onPaste) {
328
+ otherProps.onPaste(event);
329
+ }
330
+ if (event.defaultPrevented) {
331
+ return;
332
+ }
333
+ const pastedText = event.clipboardData.getData("Text");
334
+ const pastedItems = pastedText.split(",").map(
335
+ (itemLabel) => getNewItem(itemLabel.trim())
336
+ ).filter(Boolean);
337
+ if (allowsCustomLabel && !!pastedItems.length) {
338
+ event.preventDefault();
339
+ onLabelsChange([...labels, ...pastedItems]);
340
+ }
341
+ },
342
+ placeholder: labels.length ? void 0 : placeholder,
343
+ ref: inputElementRef,
344
+ type: "text",
345
+ value
346
+ }
347
+ ))));
348
+ }
349
+ );
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var MultiSelect_exports = {};
30
+ __export(MultiSelect_exports, {
31
+ MultiSelect: () => MultiSelect,
32
+ itemLabelFilter: () => itemLabelFilter
33
+ });
34
+ module.exports = __toCommonJS(MultiSelect_exports);
35
+ var import_autocomplete = __toESM(require("@clayui/autocomplete"));
36
+ var import_button = require("@clayui/button");
37
+ var import_core = require("@clayui/core");
38
+ var import_form = require("@clayui/form");
39
+ var import_shared = require("@clayui/shared");
40
+ var import_classnames = __toESM(require("classnames"));
41
+ var import_react = __toESM(require("react"));
42
+ var import_Labels = require("./Labels");
43
+ const MultiSelect = import_react.default.forwardRef(function MultiSelectInner({
44
+ active: externalActive,
45
+ allowsCustomLabel = true,
46
+ allowDuplicateValues = true,
47
+ alignmentByViewport,
48
+ children,
49
+ clearAllTitle = "Clear All",
50
+ closeButtonAriaLabel = "Remove {0}",
51
+ defaultActive = false,
52
+ defaultItems = [],
53
+ defaultValue = "",
54
+ disabled,
55
+ disabledClearAll,
56
+ displayKeyboardArrowsIndicator = false,
57
+ hotkeysDescription,
58
+ inputName,
59
+ inputValue,
60
+ isLoading: _i,
61
+ isValid = true,
62
+ items: externalItems,
63
+ liveRegion,
64
+ locator = {
65
+ id: "key",
66
+ label: "label",
67
+ value: "value"
68
+ },
69
+ loadingState,
70
+ menuRenderer: MenuRenderer,
71
+ messages = {
72
+ hotkeys: "Press backspace to delete the current row.",
73
+ labelAdded: "Label {0} added to the list",
74
+ labelRemoved: "Label {0} removed to the list",
75
+ listCount: "{0} option available.",
76
+ listCountPlural: "{0} options available.",
77
+ loading: "Loading...",
78
+ notFound: "No results found"
79
+ },
80
+ onActiveChange,
81
+ onChange,
82
+ onClearAllButtonClick,
83
+ onItemsChange,
84
+ onLoadMore,
85
+ placeholder,
86
+ size,
87
+ sourceItems = null,
88
+ spritemap,
89
+ icon,
90
+ value: externalValue,
91
+ ...otherProps
92
+ }, ref) {
93
+ const containerRef = (0, import_react.useRef)(null);
94
+ const inputRef = (0, import_react.useRef)(null);
95
+ const lastChangesRef = (0, import_react.useRef)(null);
96
+ const [isFocused, setIsFocused] = (0, import_react.useState)(false);
97
+ const [items, setItems] = (0, import_shared.useControlledState)({
98
+ defaultName: "defaultItems",
99
+ defaultValue: defaultItems,
100
+ handleName: "onItemsChange",
101
+ name: "items",
102
+ onChange: onItemsChange,
103
+ value: externalItems
104
+ });
105
+ const [value, setValue] = (0, import_shared.useControlledState)({
106
+ defaultName: "defaultValue",
107
+ defaultValue,
108
+ handleName: "onChange",
109
+ name: "value",
110
+ onChange,
111
+ value: externalValue ?? inputValue
112
+ });
113
+ const [active, setActive] = (0, import_shared.useControlledState)({
114
+ defaultName: "defaultActive",
115
+ defaultValue: defaultActive,
116
+ handleName: "onActiveChange",
117
+ name: "active",
118
+ onChange: onActiveChange,
119
+ value: externalActive
120
+ });
121
+ const selectedKeys = (0, import_react.useMemo)(() => {
122
+ return items.map(
123
+ (item) => String(
124
+ (0, import_shared.getLocatorValue)({
125
+ item,
126
+ locator: locator.value
127
+ })
128
+ )
129
+ );
130
+ }, [items, locator.value]);
131
+ const inputElementRef = ref || inputRef;
132
+ const ariaDescriptionId = (0, import_shared.useId)();
133
+ const hasAsyncItems = !!onLoadMore || typeof loadingState === "number";
134
+ const Container = MenuRenderer ? import_shared.FocusScope : import_react.default.Fragment;
135
+ const containerProps = MenuRenderer ? { arrowKeysUpDown: false } : {};
136
+ (0, import_react.useEffect)(() => {
137
+ if (MenuRenderer) {
138
+ console.warn(
139
+ `<ClayMultiSelect />: You are using 'menuRenderer' which is deprecated and missing the new features and improvements that have been implemented in the component try to migrate to the new composition based API to custom list items.`
140
+ );
141
+ }
142
+ if (allowsCustomLabel && (typeof locator.label === "function" || typeof locator.value === "function")) {
143
+ console.warn(
144
+ `<ClayMultiSelect />: Custom labels cannot be created because the expected structure of the label is unknown. Please disable allowsCustomLabel or update the locators to be strings rather than functions.`
145
+ );
146
+ }
147
+ }, []);
148
+ (0, import_react.useEffect)(() => {
149
+ if (MenuRenderer && sourceItems) {
150
+ setActive(!!value && sourceItems.length !== 0);
151
+ }
152
+ }, [value, sourceItems]);
153
+ const memoizedChildren = (0, import_react.useCallback)(
154
+ (item) => {
155
+ const handleItemClick = (event) => {
156
+ event.preventDefault();
157
+ setActive(false);
158
+ if (!allowDuplicateValues && items.find((dropdownItem) => {
159
+ return (0, import_shared.getLocatorValue)({
160
+ item: dropdownItem,
161
+ locator: locator.value
162
+ }) === (0, import_shared.getLocatorValue)({
163
+ item,
164
+ locator: locator.value
165
+ });
166
+ })) {
167
+ return;
168
+ }
169
+ setItems([...items, item]);
170
+ setValue("");
171
+ };
172
+ if (children && typeof children === "function") {
173
+ const child = children(item);
174
+ return import_react.default.cloneElement(child, {
175
+ onClick: (event) => {
176
+ if (child.props.onClick) {
177
+ child.props.onClick(event);
178
+ }
179
+ if (event.defaultPrevented) {
180
+ return;
181
+ }
182
+ handleItemClick(event);
183
+ }
184
+ });
185
+ }
186
+ return /* @__PURE__ */ import_react.default.createElement(
187
+ import_autocomplete.Item,
188
+ {
189
+ key: (0, import_shared.getLocatorValue)({
190
+ item,
191
+ locator: locator.value
192
+ }),
193
+ onClick: handleItemClick
194
+ },
195
+ (0, import_shared.getLocatorValue)({
196
+ item,
197
+ locator: locator.label
198
+ })
199
+ );
200
+ },
201
+ [children, locator, items, setItems, allowDuplicateValues]
202
+ );
203
+ return /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(Container, { ...containerProps }, /* @__PURE__ */ import_react.default.createElement(
204
+ "div",
205
+ {
206
+ className: (0, import_classnames.default)(
207
+ "form-control form-control-tag-group input-group",
208
+ {
209
+ focus: isFocused && isValid,
210
+ [`form-control-tag-group-${size}`]: size
211
+ }
212
+ ),
213
+ ref: containerRef
214
+ },
215
+ /* @__PURE__ */ import_react.default.createElement(
216
+ import_autocomplete.Autocomplete,
217
+ {
218
+ ...otherProps,
219
+ UNSAFE_loadingShrink: true,
220
+ active: MenuRenderer ? false : active,
221
+ allowsCustomLabel: typeof locator.label === "function" || typeof locator.value === "function" ? false : allowsCustomLabel,
222
+ allowsCustomValue: true,
223
+ ariaDescriptionId,
224
+ as: import_Labels.Labels,
225
+ closeButtonAriaLabel,
226
+ containerElementRef: containerRef,
227
+ defaultItems: !hasAsyncItems ? sourceItems : void 0,
228
+ disabled,
229
+ filterKey: locator.label,
230
+ inputName,
231
+ items: hasAsyncItems ? sourceItems : void 0,
232
+ labels: items,
233
+ lastChangesRef,
234
+ loadingState,
235
+ locator,
236
+ menuTrigger: "focus",
237
+ messages,
238
+ onActiveChange: MenuRenderer ? () => {
239
+ } : setActive,
240
+ onChange: setValue,
241
+ onFocus: MenuRenderer && sourceItems ? (event) => {
242
+ if (otherProps.onFocus) {
243
+ otherProps.onFocus(event);
244
+ }
245
+ setActive(
246
+ !!value && sourceItems.length !== 0
247
+ );
248
+ } : otherProps.onFocus,
249
+ onFocusChange: setIsFocused,
250
+ onItemsChange: hasAsyncItems ? () => {
251
+ } : void 0,
252
+ onLabelsChange: setItems,
253
+ onLoadMore,
254
+ placeholder,
255
+ ref: inputElementRef,
256
+ selectedKeys,
257
+ spritemap,
258
+ suggestionList: sourceItems ?? [],
259
+ value
260
+ },
261
+ memoizedChildren
262
+ ),
263
+ sourceItems && MenuRenderer && !!sourceItems.length && /* @__PURE__ */ import_react.default.createElement(
264
+ import_autocomplete.default.DropDown,
265
+ {
266
+ active,
267
+ alignElementRef: containerRef,
268
+ alignmentByViewport,
269
+ onActiveChange: setActive
270
+ },
271
+ /* @__PURE__ */ import_react.default.createElement(
272
+ MenuRenderer,
273
+ {
274
+ inputValue: value,
275
+ locator,
276
+ onItemClick: (item) => {
277
+ setItems([...items, item]);
278
+ setValue("");
279
+ if (inputElementRef.current) {
280
+ inputElementRef.current.focus();
281
+ }
282
+ },
283
+ sourceItems,
284
+ value
285
+ }
286
+ )
287
+ ),
288
+ !disabled && !disabledClearAll && (value || !!items.length) ? /* @__PURE__ */ import_react.default.createElement(import_form.ClayInput.GroupItem, { shrink: true }, /* @__PURE__ */ import_react.default.createElement(
289
+ import_button.ClayButtonWithIcon,
290
+ {
291
+ "aria-label": clearAllTitle,
292
+ borderless: true,
293
+ className: "component-action",
294
+ displayType: "secondary",
295
+ onClick: () => {
296
+ if (onClearAllButtonClick) {
297
+ onClearAllButtonClick();
298
+ } else {
299
+ setItems([]);
300
+ setValue("");
301
+ }
302
+ if (inputElementRef.current) {
303
+ inputElementRef.current.focus();
304
+ }
305
+ },
306
+ outline: true,
307
+ spritemap,
308
+ symbol: "times-circle",
309
+ title: clearAllTitle
310
+ }
311
+ )) : icon,
312
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "sr-only" }, /* @__PURE__ */ import_react.default.createElement("span", { id: ariaDescriptionId }, hotkeysDescription ?? messages.hotkeys), /* @__PURE__ */ import_react.default.createElement("span", { "aria-live": "polite", "aria-relevant": "text" }, lastChangesRef.current ? (0, import_shared.sub)(
313
+ liveRegion ? liveRegion[lastChangesRef.current.action] : lastChangesRef.current.action === "added" ? messages.labelAdded : messages.labelRemoved,
314
+ [lastChangesRef.current.label]
315
+ ) : null))
316
+ )), active && displayKeyboardArrowsIndicator && /* @__PURE__ */ import_react.default.createElement(import_shared.ClayPortal, null, /* @__PURE__ */ import_react.default.createElement(
317
+ import_core.KeyboardArrowsIndicator,
318
+ {
319
+ anchorRef: containerRef,
320
+ direction: "vertical"
321
+ }
322
+ )));
323
+ });
324
+ function itemLabelFilter(items, _value, _locator = "label") {
325
+ return items;
326
+ }