UNPKG

@progress/kendo-react-dropdowns

Version:

React DropDowns offer an interface for users to select different items from a list and more. KendoReact Dropdowns package

717 lines (716 loc) • 33.1 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2026 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import * as g from "react"; import v from "prop-types"; import { Keys as u, classNames as S, IconWrap as B, WatermarkOverlay as J, getLicenseMessage as Q, canUseDOM as V, validatePackage as X, createPropsContext as Z, withIdHOC as ee, withPropsContext as te, withAdaptiveModeContext as se, kendoThemeMaps as ie } from "@progress/kendo-react-common"; import { plusIcon as oe } from "@progress/kendo-svg-icons"; import { FloatingLabel as ae } from "@progress/kendo-react-labels"; import ne from "../common/ListContainer.mjs"; import le from "../common/List.mjs"; import de from "../common/GroupStickyHeader.mjs"; import re from "./TagList.mjs"; import he from "../common/SearchBar.mjs"; import O from "../common/DropDownBase.mjs"; import { ActiveDescendant as w } from "../common/settings.mjs"; import { getFilteredData as x, areSame as P, removeDataItems as D, isPresent as _, getItemValue as K, preventDefaultNonInputs as pe, matchTags as z, itemIndexStartsWith as ce } from "../common/utils.mjs"; import { packageMetadata as A } from "../package-metadata.mjs"; import ue from "../common/ClearButton.mjs"; import { AdaptiveMode as fe } from "../common/AdaptiveMode.mjs"; import { ActionSheetContent as ge } from "@progress/kendo-react-layout"; import me from "../common/ListFilter.mjs"; import H from "../common/withCustomComponent.mjs"; const { sizeMap: M, roundedMap: ve } = ie, be = "Please enter a valid value!", W = (E) => E.preventDefault(), $ = (E) => E === 2, C = class C extends g.Component { constructor(n) { super(n), this.state = { activedescendant: w.PopupList, currentValue: [] }, this._element = null, this._valueItemsDuringOnChange = null, this.base = new O(this), this._tags = [], this._input = null, this._adaptiveInput = null, this._skipFocusEvent = !1, this._lastSelectedOrDeslectedItemIndex = null, this.itemHeight = 0, this.scrollToFocused = !1, this.showLicenseWatermark = !1, this.focus = () => { this._input && this._input.focus(); }, this.handleItemSelect = (e, t) => { const { dataItemKey: o, virtual: s } = this.props, a = x(this.props), i = s ? s.skip : 0, p = a[e - i], r = this.value.findIndex((h) => P(h, p, o)); this._lastSelectedOrDeslectedItemIndex = a.findIndex((h) => P(h, p, o)); let d = []; r !== -1 ? (d = this.value, d.splice(r, 1)) : d = [...this.value, p], (this.props.filter !== void 0 ? this.props.filter : this.state.text) && !this.mobileMode && (this.state.text && (t.data.text = ""), this.base.filterChanged("", t)), this._adaptiveInput && this._adaptiveInput.blur(), this.state.focusedIndex !== void 0 && (t.data.focusedIndex = void 0), this.triggerOnChange(d, t), this.base.triggerPageChangeCornerItems(p, t); }, this.onTagDelete = (e, t) => { const o = this.base.initState(); o.syntheticEvent = t, this.opened && this.base.togglePopup(o), !this.state.focused && !this.mobileMode && (o.data.focused = !0, this.focus()); const s = this.value; D(s, e, this.props.dataItemKey), this.triggerOnChange(s, o), this.applyState(o); }, this.itemFocus = (e, t) => { const { allowCustom: o, virtual: s } = this.props, a = x(this.props), i = s ? s.skip : 0, p = s ? s.pageSize : 0, r = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedIndex: d } = this.getFocusedState(), l = o && r, h = a[e - i]; if (s && !h && e >= 0 && d !== e) { const f = Math.floor(e / p) * p; if (f !== i) { this.state.focusedIndex !== e && (t.data.focusedIndex = e, t.data.activedescendant = w.PopupList), this.base.triggerOnPageChange(t, f, p); return; } } h && d !== e ? this.state.focusedIndex !== e && (t.data.focusedIndex = e, t.data.activedescendant = w.PopupList) : l && e === -1 && this.state.focusedIndex !== void 0 && (t.data.focusedIndex = void 0), this.base.triggerPageChangeCornerItems(h, t); }, this.componentRef = (e) => { this._element = e, this.base.wrapper = e; }, this.searchbarRef = (e) => { const t = this._input = e && e.input; t && this.state.focused && window.setTimeout(() => t.focus(), 0); }, this.onChangeHandler = (e) => { const t = this.base.initState(), o = e.target.value; t.syntheticEvent = e, this.props.filter === void 0 && (t.data.text = o), t.data.focusedIndex = void 0, this.opened ? this.scrollToFocused = !0 : (this.base.togglePopup(t), this.setState({ currentValue: this.value })), this.base.filterChanged(o, t), this.applyState(t), this.setState({ group: void 0 }); }, this.clearButtonClick = (e) => { const t = this.base.initState(); t.syntheticEvent = e, e.stopPropagation(), this.value.length > 0 && this.triggerOnChange([], t), this.state.focusedIndex !== void 0 && (t.data.focusedIndex = void 0), this.opened && this.base.togglePopup(t); const o = this.props.filter !== void 0 ? this.props.filter : this.state.text; _(o) && o !== "" && this.base.filterChanged("", t), this.state.text && (t.data.text = ""), this._lastSelectedOrDeslectedItemIndex = null, this.applyState(t); }, this.onInputKeyDown = (e) => { const { textField: t, groupField: o, virtual: s } = this.props, a = x(this.props), i = e.keyCode, p = this.props.filter !== void 0 ? this.props.filter : this.state.text, r = this.props.opened !== void 0 ? this.props.opened : this.state.opened, { focusedItem: d, focusedIndex: l } = this.getFocusedState(), h = this.base.initState(); if (h.syntheticEvent = e, !p && this.value.length > 0 && (i === u.left || i === u.right || i === u.home || i === u.end || i === u.delete || i === u.backspace) && !e.shiftKey) return this.onTagsNavigate(e, h); const f = () => { e.preventDefault(), this.base.togglePopup(h), this.applyState(h); }; if (this.opened) if (i === u.pageUp) e.preventDefault(), this.base.scrollPopupByPageSize(-1); else if (i === u.pageDown) e.preventDefault(), this.base.scrollPopupByPageSize(1); else if ((e.ctrlKey || e.metaKey) && e.code === "KeyA") { const b = (this.state.value && this.state.value.length) === a.length ? [] : a; this.updateStateOnKeyboardNavigation(b, h); } else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === u.end) { const c = a.slice(this.getFocusedState().focusedIndex); this.itemFocus(a.length - 1, h), this.updateStateOnKeyboardNavigation(c, h); } else if ((e.ctrlKey || e.metaKey) && e.shiftKey && e.keyCode === u.home) { const c = a.slice(0, this.getFocusedState().focusedIndex + 1); this.itemFocus(0, h), this.updateStateOnKeyboardNavigation(c, h); } else if (e.shiftKey && e.keyCode === u.up) { let c; const b = this.getLastSelectedOrDeselectedIndex(1, l); b === null ? c = l !== 0 ? a.slice(l - 1, l) : [a[l]] : b === l ? c = [a[b - 1]] : l >= 0 && (c = b > l ? a.slice(l - 1, b) : a.slice(b - 1, l)), c && c.length > 0 && (l >= 1 && this.itemFocus(l - 1, h), this.updateStateOnKeyboardNavigation(c, h)); } else if (e.shiftKey && e.keyCode === u.down) { let c; const b = this.getLastSelectedOrDeselectedIndex(0, l); b === null ? c = l !== a.length - 1 ? a.slice(l, l + 1) : [a[l]] : b === l ? c = a.slice(l, l + 2) : l >= 0 && (c = b > l ? a.slice(l + 1, b + 1) : a.slice(b, l + 2)), c && c.length >= 1 && (this.itemFocus(l + 1, h), this.updateStateOnKeyboardNavigation(c, h)); } else if (e.altKey && i === u.up) f(); else if (i === u.up || i === u.down) { const c = s ? s.skip : 0, b = l - c; if (o !== "" && t) if (!this.props.skipDisabledItems && r) this.onNavigate(h, i); else { let m = 0; if (i === u.down || i === u.right) { const y = a.slice(b + 1).find((I) => !I.disabled && I[t]); m = y && a.findIndex((I) => I[t] === y[t]), m && m !== -1 && (m = m + c); } else if (i === u.up || i === u.left) { let y; if (l === -1) y = a, m = a.findIndex((I) => !I.disabled && I[t]), m !== -1 && (m = m + c); else { y = a.slice(0, b); let I = y.pop(); for (; I && I.disabled; ) I = y.pop(); m = I && a.findIndex((T) => T[t] === I[t]), m && m !== -1 && (m = m + c); } } if (m) { const y = m - l; this.onNavigate(h, i, y); } else this.onNavigate(h, i); } else if (!this.props.skipDisabledItems && r) this.onNavigate(h, i); else { let m = null; if (i === u.down || i === u.right) m = a.slice(b + 1).find((y) => !y.disabled); else if (i === u.up || i === u.left) { const y = a.slice(0, b); for (m = y.pop(); m && m.disabled; ) m = y.pop(); } if (m) { const y = a.indexOf(m); if (y !== -1) { const I = c + y - l; this.onNavigate(h, i, I); } else this.onNavigate(h, i); } else this.onNavigate(h, i); } this.applyState(h), e.preventDefault(); } else i === u.enter ? (e.preventDefault(), this.props.allowCustom && p && d === null ? this.customItemSelect(e) : d && d.disabled ? f() : this.selectFocusedItem(e)) : i === u.esc && f(); else e.altKey && i === u.down ? f() : i === u.esc && this.clearButtonClick(e); }, this.listContainerContent = () => { const { header: e, footer: t, allowCustom: o, size: s, groupStickyHeaderItemRender: a, groupField: i, list: p } = this.props, r = x(this.props), d = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedType: l } = this.getFocusedState(), h = o && d && /* @__PURE__ */ g.createElement( "div", { className: S("k-list", { [`k-list-${M[s] || s}`]: s }), key: "customitem", onClick: this.customItemSelect, onMouseDown: W }, /* @__PURE__ */ g.createElement( "div", { className: S("k-list-item k-custom-item", { "k-focus": $(l) }), style: { fontStyle: "italic" } }, d, /* @__PURE__ */ g.createElement(B, { name: "plus", icon: oe, style: { position: "absolute", right: "0.5em" } }) ) ); let { group: f } = this.state; return f === void 0 && i !== void 0 && (f = K(r[0], i)), /* @__PURE__ */ g.createElement(g.Fragment, null, e && /* @__PURE__ */ g.createElement("div", { className: "k-list-header" }, e), h, /* @__PURE__ */ g.createElement( "div", { className: S("k-list", { [`k-list-${this.mobileMode ? "lg" : M[s] || s}`]: s, "k-virtual-list": this.base.vs.enabled }) }, !p && f && r.length !== 0 && /* @__PURE__ */ g.createElement(de, { group: f, groupMode: "modern", render: a }), this.renderList() ), this.showLicenseWatermark && /* @__PURE__ */ g.createElement(J, { message: this.licenseMessage }), t && /* @__PURE__ */ g.createElement("div", { className: "k-list-footer" }, t)); }, this.renderListContainer = () => { const e = this.base, { dir: t } = this.props, o = x(this.props), s = this.base.getPopupSettings(), a = s.width !== void 0 ? s.width : e.popupWidth, i = { dir: t !== void 0 ? t : e.dirCalculated, width: a, popupSettings: { ...s, popupClass: S(s.popupClass, "k-list-container", "k-multiselect-popup"), anchor: s.anchor || this.element, show: this.opened, onOpen: this.onPopupOpened, onClose: this.onPopupClosed }, itemsCount: [o.length, this.value.length] }; return /* @__PURE__ */ g.createElement(ne, { ...i }, this.listContainerContent()); }, this.renderAdaptiveListContainer = () => { const { adaptiveTitle: e, adaptiveSubtitle: t, filterable: o, filter: s } = this.props, { windowWidth: a = 0 } = this.state, i = s !== void 0 ? s : this.state.text, p = o ? /* @__PURE__ */ g.createElement( me, { value: i, ref: (d) => { this._adaptiveInput = d && d.element; }, onChange: this.onChangeHandler, onKeyDown: this.onInputKeyDown, size: "large", rounded: this.props.rounded, fillMode: this.props.fillMode, placeholder: this.props.placeholder } ) : null, r = { title: e || this.props.label, subTitle: t, expand: this.opened, onClose: (d) => this.closePopup(d), windowWidth: a, mobileFilter: p }; return /* @__PURE__ */ g.createElement(fe, { ...r }, /* @__PURE__ */ g.createElement(ge, null, /* @__PURE__ */ g.createElement("div", { className: "k-list-container" }, this.listContainerContent()))); }, this.closePopup = (e) => { const t = this.base.initState(); t.syntheticEvent = e, e.stopPropagation(), this.state.focusedIndex !== void 0 && (t.data.focusedIndex = void 0), this.opened && this.base.togglePopup(t), t.events.push({ type: "onClose" }); const o = this.props.filter !== void 0 ? this.props.filter : this.state.text; _(o) && o !== "" && this.base.filterChanged("", t), this.state.text && (t.data.text = ""), this.applyState(t); }, this.onCancel = (e) => { const t = this.base.initState(); t.syntheticEvent = e, e.stopPropagation(), this.state.focusedIndex !== void 0 && (t.data.focusedIndex = void 0), this.opened && this.base.togglePopup(t), t.events.push({ type: "onCancel" }); const o = this.props.filter !== void 0 ? this.props.filter : this.state.text; _(o) && o !== "" && this.base.filterChanged("", t), this.state.text && (t.data.text = ""), this.applyState(t); }, this.renderList = () => { const { textField: e, listNoDataRender: t, itemRender: o, groupHeaderItemRender: s, dataItemKey: a, virtual: i = { skip: 0, total: void 0 } } = this.props, p = x(this.props), r = this.base.vs, { focusedIndex: d } = this.getFocusedState(), l = this.base.getPopupSettings(), h = `translateY(${r.translate}px)`; return /* @__PURE__ */ g.createElement( le, { id: this.base.listBoxId, show: this.opened, data: p.slice(), focusedIndex: d - i.skip, value: this.value, textField: e, valueField: a, optionsGuid: this.base.guid, groupField: this.props.groupField, groupMode: "modern", listRef: (f) => { r.list = this.base.list = f; }, wrapperStyle: this.mobileMode ? {} : { maxHeight: l.height }, wrapperCssClass: "k-list-content", listStyle: r.enabled ? { transform: h } : void 0, key: "listKey", skip: i.skip, onClick: this.handleItemClick, itemRender: o, groupHeaderItemRender: s, noDataRender: t, onMouseDown: W, onBlur: this.handleBlur, onScroll: this.onScroll, wrapperRef: r.scrollerRef, scroller: this.base.renderScrollElement(), ariaSetSize: i.total } ); }, this.onScroll = (e) => { const { vs: t, list: o } = this.base; t.scrollHandler(e); const { groupField: s } = this.props; let a = x(this.props); if (!(!s || !a.length) && s) { const i = this.itemHeight = this.itemHeight || (t.enabled ? t.itemHeight : o ? o.children[0].offsetHeight : 0), r = e.target.scrollTop - t.skip * i; a = this.base.getGroupedDataModernMode(a, s); let d = a[0][s]; for (let l = 1; l < a.length && !(i * l > r); l++) a[l] && a[l][s] && (d = a[l][s]); d !== this.state.group && this.setState({ group: d }); } }, this.customItemSelect = (e) => { const t = this.props.filter !== void 0 ? this.props.filter : this.state.text, { textField: o } = this.props; if (!t) return; const s = this.base.initState(); s.syntheticEvent = e; const a = o ? { [o]: t } : t; this.state.text !== void 0 && (s.data.text = ""), s.data.focusedIndex = void 0, this.base.filterChanged("", s); const i = [...this.value, a]; this.triggerOnChange(i, s), this.base.togglePopup(s), this.applyState(s); }, this.handleWrapperClick = (e) => { const t = this._input; !this.opened && t && this.focusElement(t); const o = this.base.initState(); o.syntheticEvent = e, !this.state.focused && !this.mobileMode && (o.events.push({ type: "onFocus" }), o.data.focused = !0), this.mobileMode && (this.setState({ currentValue: this.tagsToRender }), this.mobileMode && window.setTimeout(() => this._adaptiveInput && this._adaptiveInput.focus(), 300)), this.base.togglePopup(o), this.applyState(o); }, this.handleItemClick = (e, t) => { const o = this.base.initState(); o.syntheticEvent = t, this.handleItemSelect(e, o), this.props.autoClose && this.base.togglePopup(o), t.stopPropagation(), this.applyState(o); }, this.handleBlur = (e) => { if (!this.state.focused || this._skipFocusEvent) return; const t = this.base.initState(), { allowCustom: o, filterable: s } = this.props; t.syntheticEvent = e, t.data.focused = !1, t.events.push({ type: "onBlur" }), this.opened && !this.mobileMode && (this.state.opened && (t.data.opened = !1), t.events.push({ type: "onClose" })), !o && !s && this.state.text && (t.data.text = ""), this.applyState(t); }, this.handleFocus = (e) => { this._skipFocusEvent || this.base.handleFocus(e); }, this.onPopupOpened = () => { this._input && this.state.focused && !this.mobileMode && this.focusElement(this._input); }, this.onPopupClosed = () => { this.state.focused && window.setTimeout(() => { this.state.focused && this.focusElement(this._input); }, 0); }, this.setValidity = () => { this._input && this._input.setCustomValidity && this._input.setCustomValidity( this.validity.valid ? "" : this.props.validationMessage || be ); }, this.validate(n), this.licenseMessage = Q(A); } get _inputId() { return this.props.id; } get document() { if (V) return this.element && this.element.ownerDocument || document; } validate(n) { if (n.filterable || n.virtual) { const e = []; n.filterable && e.push("filterable"), n.virtual && e.push("virtualization"), this.showLicenseWatermark = !X(A, { component: "MultiSelect", features: e }); } } /** @hidden */ get element() { return this._element; } /** @hidden */ get opened() { return !!(this.props.opened !== void 0 ? this.props.opened : this.state.opened); } /** @hidden */ get tagsToRender() { const { tags: n, textField: e } = this.props, t = []; return n === void 0 ? this.value.forEach((o) => { t.push({ text: K(o, e), data: [o] }); }) : t.push(...n), t; } /** * The mobile mode of the MultiSelect. */ get mobileMode() { var e; return !!(this.state.windowWidth && this.props._adaptiveMode && this.state.windowWidth <= ((e = this.props._adaptiveMode) == null ? void 0 : e.medium) && this.props.adaptive); } /** * Represents the value of the MultiSelect. */ get value() { const n = []; return this._valueItemsDuringOnChange ? n.push(...this._valueItemsDuringOnChange) : this.props.value ? n.push(...this.props.value) : this.state.value ? n.push(...this.state.value) : this.props.defaultValue && n.push(...this.props.defaultValue), n; } /** * Gets the `name` property of the MultiSelect. */ get name() { return this.props.name; } /** * Represents the validity state into which the MultiSelect is set. */ get validity() { const n = this.props.validationMessage !== void 0, e = !this.required || this.value !== null && this.value.length > 0 && this.value !== void 0, t = this.props.valid !== void 0 ? this.props.valid : e; return { customError: n, valid: t, valueMissing: this.value === null }; } /** @hidden */ get required() { return this.props.required !== void 0 ? this.props.required : C.defaultProps.required; } get validityStyles() { return this.props.validityStyles !== void 0 ? this.props.validityStyles : C.defaultProps.validityStyles; } /** @hidden */ componentDidUpdate(n, e) { var h; const { virtual: t, groupField: o = "" } = this.props, s = x(this.props), a = t ? t.skip : 0, i = n.virtual ? n.virtual.total : 0, p = n.opened !== void 0 ? n.opened : e.opened, r = !p && this.opened, d = p && !this.opened, l = this.base.getPopupSettings(); if (this.validate(this.props), this.base.didUpdate(), !l.animate && d && this.onPopupClosed(), t && t.total !== i) this.base.vs.calcScrollElementHeight(), this.base.vs.reset(); else { let { focusedItem: f, focusedIndex: c } = this.getFocusedState(); o !== "" && (c = (h = this.base.getGroupedDataModernMode(s, o)) == null ? void 0 : h.indexOf(f)), r && t ? this.base.scrollToVirtualItem(t, c - a) : r && !t ? (s && s.length !== 0 && this.base.resetGroupStickyHeader(s[0][o], this), this.base.scrollToItem(c)) : this.opened && p && f && this.scrollToFocused && this.base.scrollToItem(c - a); } this.scrollToFocused = !1, this.setValidity(); } /** @hidden */ componentDidMount() { var n; this.observerResize = V && window.ResizeObserver && new window.ResizeObserver(this.calculateMedia.bind(this)), this.base.didMount(), this.setValidity(), (n = this.document) != null && n.body && this.observerResize && this.observerResize.observe(this.document.body); } /** @hidden */ componentWillUnmount() { var n; (n = this.document) != null && n.body && this.observerResize && this.observerResize.disconnect(); } /** @hidden */ onNavigate(n, e, t) { const { allowCustom: o } = this.props, s = x(this.props), a = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedType: i, focusedIndex: p } = this.getFocusedState(), r = o && a, d = $(i), l = this.base, h = l.vs; if (this.opened && e === u.up && d) this.state.focusedIndex !== void 0 && (n.data.focusedIndex = void 0); else { const f = l.navigation.navigate({ keyCode: e, current: p, max: (h.enabled ? h.total : s.length) - 1, min: r ? -1 : 0, skipItems: t || void 0 }); f !== void 0 && (this.itemFocus(f, n), this.scrollToFocused = !0); } this.applyState(n); } /** @hidden */ render() { const { style: n, className: e, label: t, dir: o, disabled: s, textField: a, dataItemKey: i, virtual: p, size: r, rounded: d, fillMode: l, loading: h, filter: f } = this.props, { text: c, focused: b, focusedTag: m, currentValue: y } = this.state, I = this.base.vs, T = this.props.id || this._inputId; I.enabled = p !== void 0, p !== void 0 && (I.skip = p.skip, I.total = p.total, I.pageSize = p.pageSize); const k = this.mobileMode && this.opened ? y : this.tagsToRender; this.setItems(this.tagsToRender, this._tags); const R = !this.validityStyles || this.validity.valid, q = !!(f !== void 0 ? f : c) || k && k.length > 0, [G, U] = H(this.props.prefix || g.Fragment), [j, Y] = H(this.props.suffix || g.Fragment), L = /* @__PURE__ */ g.createElement(g.Fragment, null, /* @__PURE__ */ g.createElement( "div", { ref: this.componentRef, className: S("k-multiselect k-input", e, { [`k-input-${M[r] || r}`]: r, [`k-rounded-${ve[d] || d}`]: d, [`k-input-${l}`]: l, "k-focus": b && !s, "k-invalid": !R, "k-disabled": s, "k-loading": h, "k-required": this.required }), style: t ? { ...n, width: void 0 } : n, dir: o, onFocus: (F) => { this.mobileMode ? this.handleWrapperClick(F) : this.handleFocus(F); }, onBlur: this.handleBlur, onClick: this.handleWrapperClick, onMouseDown: pe }, this.props.prefix && /* @__PURE__ */ g.createElement(G, { ...U }), /* @__PURE__ */ g.createElement("div", { className: S("k-input-values") }, /* @__PURE__ */ g.createElement( "div", { className: S("k-chip-list", { [`k-chip-list-${M[r] || r}`]: r }), role: "listbox", id: "tagslist-" + this.base.guid }, k && k.length > 0 && /* @__PURE__ */ g.createElement( re, { tagRender: this.props.tagRender, onTagDelete: this.onTagDelete, data: k, guid: this.base.guid, focused: m ? k.find((F) => z(F, m, i)) : void 0, size: r } ) ), this.renderSearchBar(T)), h && /* @__PURE__ */ g.createElement(B, { className: "k-input-loading-icon", name: "loading" }), this.props.suffix && /* @__PURE__ */ g.createElement(j, { ...Y }), q && /* @__PURE__ */ g.createElement(ue, { onClick: this.clearButtonClick }), !this.mobileMode && this.renderListContainer() ), this.mobileMode && this.renderAdaptiveListContainer()); return t ? /* @__PURE__ */ g.createElement( ae, { label: t, editorId: T, editorValue: c || K(this.value[0], a), editorValid: R, editorDisabled: s, style: { width: n ? n.width : void 0 }, children: L } ) : L; } renderSearchBar(n) { const { activedescendant: e, focusedTag: t, currentValue: o } = this.state, { disabled: s, placeholder: a, ariaDescribedBy: i, ariaLabelledBy: p, ariaLabel: r, inputAttributes: d } = this.props, l = !this.mobileMode && (this.props.filter !== void 0 ? this.props.filter : this.state.text) || "", { focusedIndex: h } = this.getFocusedState(), f = this.value.length === 0 && !l ? a : void 0, c = o && o.length > 0 ? void 0 : a, b = e === w.TagsList && t !== void 0 ? `tag-${this.base.guid}-${t.text.replace(/\s+/g, "-")}` : `option-${this.base.guid}-${h}`, m = { accessKey: this.props.accessKey, tabIndex: this.props.tabIndex }; return /* @__PURE__ */ g.createElement( he, { id: n, size: Math.max((f || "").length, l.length, 1), placeholder: this.mobileMode && this.opened ? c : f, value: l, onChange: this.onChangeHandler, onKeyDown: this.onInputKeyDown, ref: this.searchbarRef, disabled: s, expanded: this.opened, owns: this.base.listBoxId, role: "combobox", activedescendant: b, ariaDescribedBy: `tagslist-${this.base.guid}${i ? " " + i : ""}`, ariaLabelledBy: p, ariaRequired: this.required, ariaLabel: r, inputAttributes: d, ...m } ); } onTagsNavigate(n, e) { const t = n.keyCode, { focusedTag: o } = this.state, s = this._tags, a = this.props.dataItemKey; let i = o ? s.findIndex((d) => z(d, o, a)) : -1, p; const r = i !== -1; if (t === u.left) r ? i = Math.max(0, i - 1) : i = s.length - 1, p = s[i]; else if (t === u.right) i === s.length - 1 ? p = void 0 : r && (i = Math.min(s.length - 1, i + 1), p = s[i]); else if (t === u.home && !n.shiftKey) p = s[0]; else if (t === u.end && !n.shiftKey) p = s[s.length - 1]; else if (t === u.delete) { if (r) { const d = this.value; D(d, s[i].data, a), this.triggerOnChange(d, e); } } else if (t === u.backspace) { const d = this.value; if (r) D(d, s[i].data, a), this.triggerOnChange(d, e); else if (!r && s.length) { const l = s.pop(); D(d, l.data, a), this.triggerOnChange(d, e); } } p !== o && (e.data.focusedTag = p, e.data.activedescendant = w.TagsList), this.applyState(e); } triggerOnChange(n, e) { this.props.value === void 0 && (e.data.value = [...n]), this._valueItemsDuringOnChange = [], this.setItems(n, this._valueItemsDuringOnChange), e.events.push({ type: "onChange" }); } selectFocusedItem(n, e) { const { virtual: t } = this.props, o = x(this.props), { focusedIndex: s } = e || this.getFocusedState(), a = t ? t.skip : 0; o[s - a] !== void 0 && this.handleItemClick(s, n); } setItems(n, e) { e.length = 0, e.push(...n); } getFocusedState() { const { focusedIndex: n } = this.state, e = this.props.filter !== void 0 ? this.props.filter : this.state.text, { allowCustom: t, dataItemKey: o, virtual: s, textField: a, focusedItemIndex: i = ce, skipDisabledItems: p } = this.props, r = x(this.props), d = s && s.skip || 0; let l; if (n !== void 0) return { focusedIndex: n, focusedItem: r[n - d], focusedType: 1 /* ListItem */ }; const h = this.value; if (t && e) return { focusedItem: null, focusedIndex: -1, focusedType: 2 /* CustomItem */ }; if (e) return l = i(r, e, a), { focusedItem: r[l], focusedIndex: l + d, focusedType: 1 /* ListItem */ }; if (h.length) { const f = h[h.length - 1]; return l = r.findIndex((c) => P(c, f, o)), r[l] !== void 0 ? { focusedIndex: l + d, focusedItem: r[l], focusedType: 1 /* ListItem */ } : { focusedType: 0, focusedIndex: -1 }; } else if (p && a && !e && d === 0) { const f = r.findIndex((c) => !c.disabled && c[a]); return { focusedIndex: f, focusedItem: r[f - d], focusedType: 1 /* ListItem */ }; } return d === 0 ? { focusedItem: r[0], focusedIndex: 0, focusedType: 1 /* ListItem */ } : { focusedType: 0, focusedIndex: -1 }; } focusElement(n) { this._skipFocusEvent = !0, n.focus(), window.setTimeout(() => this._skipFocusEvent = !1, 0); } applyState(n) { this.base.applyState(n), this._valueItemsDuringOnChange = null; } calculateMedia(n) { for (const e of n) this.setState({ windowWidth: e.target.clientWidth }); } /** * Updates the state of the MultiSelect when the complex keyboard navigation that * includes key combinations with the Ctrl/Command, Shift, Home and End keys * * @param {Array<string | Object>} dataToSet Defines the array of new values that will be applied to the MultiSelect * @param {MultiSelectInternalState} state The current state of the MultiSelect */ updateStateOnKeyboardNavigation(n, e) { this.setState({ value: n }), this.triggerOnChange(n, e), this.applyState(e); } /** * Returns the last element that was selected or deselected. Needed for the keyboard navigation specifications * * @param {number} correction A correction is needed depending on if UP or DOWN key is pressed */ getLastSelectedOrDeselectedIndex(n, e) { return this._lastSelectedOrDeslectedItemIndex === null && (this._lastSelectedOrDeslectedItemIndex = e), this._lastSelectedOrDeslectedItemIndex !== null ? this._lastSelectedOrDeslectedItemIndex + n : null; } }; C.displayName = "MultiSelect", C.propTypes = { ...O.propTypes, autoClose: v.bool, value: v.arrayOf(v.any), defaultValue: v.arrayOf(v.any), dataItemKey: v.string, placeholder: v.string, tags: v.arrayOf( v.shape({ text: v.string, data: v.arrayOf(v.any) }) ), tagRender: v.func, id: v.string, ariaLabelledBy: v.string, ariaDescribedBy: v.string, groupField: v.string, list: v.any, adaptive: v.bool, adaptiveTitle: v.string, adaptiveSubtitle: v.string, onCancel: v.func, skipDisabledItems: v.bool, inputAttributes: v.object }, C.defaultProps = { ...O.defaultProps, autoClose: !0, required: !1, size: "medium", rounded: "medium", fillMode: "solid", groupMode: "modern", skipDisabledItems: !0, prefix: void 0, suffix: void 0 }; let N = C; const Ie = Z(), ye = ee( te( Ie, se(N) ) ); ye.displayName = "KendoReactMultiSelect"; export { ye as MultiSelect, Ie as MultiSelectPropsContext, N as MultiSelectWithoutContext };