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

713 lines (712 loc) • 32.8 kB
/** * @license *------------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the package root for more information *------------------------------------------------------------------------------------------- */ import * as f from "react"; import g from "prop-types"; import { Keys as u, classNames as I, IconWrap as R, WatermarkOverlay as X, canUseDOM as L, validatePackage as Z, createPropsContext as tt, withIdHOC as et, withPropsContext as st, withAdaptiveModeContext as it, kendoThemeMaps as ot } from "@progress/kendo-react-common"; import { plusIcon as at } from "@progress/kendo-svg-icons"; import { FloatingLabel as nt } from "@progress/kendo-react-labels"; import lt from "../common/ListContainer.mjs"; import dt from "../common/List.mjs"; import rt from "../common/GroupStickyHeader.mjs"; import ht from "./TagList.mjs"; import pt from "../common/SearchBar.mjs"; import D from "../common/DropDownBase.mjs"; import { ActiveDescendant as k } from "../common/settings.mjs"; import { getFilteredData as b, areSame as M, removeDataItems as w, isPresent as E, getItemValue as O, preventDefaultNonInputs as ct, matchTags as z, itemIndexStartsWith as ut } from "../common/utils.mjs"; import { packageMetadata as ft } from "../package-metadata.mjs"; import mt from "../common/ClearButton.mjs"; import { AdaptiveMode as gt } from "../common/AdaptiveMode.mjs"; import { ActionSheetContent as vt } from "@progress/kendo-react-layout"; import { provideLocalizationService as bt } from "@progress/kendo-react-intl"; import { adaptiveModeFooterCancel as B, messages as V, adaptiveModeFooterApply as A } from "../messages/index.mjs"; import It from "../common/ListFilter.mjs"; import H from "../common/withCustomComponent.mjs"; const { sizeMap: T, roundedMap: yt } = ot, xt = "Please enter a valid value!", $ = (F) => F.preventDefault(), W = (F) => F === 2, y = class y extends f.Component { constructor(n) { super(n), this.state = { activedescendant: k.PopupList, currentValue: [] }, this._element = null, this._valueItemsDuringOnChange = null, this.base = new D(this), this._tags = [], this._input = null, this._adaptiveInput = null, this._skipFocusEvent = !1, this._lastSelectedOrDeslectedItemIndex = null, this.itemHeight = 0, this.scrollToFocused = !1, this.localization = null, this.showLicenseWatermark = !1, this.focus = () => { this._input && this._input.focus(); }, this.handleItemSelect = (t, e) => { const { dataItemKey: o, virtual: s } = this.props, a = b(this.props), p = s ? s.skip : 0, c = a[t - p], r = this.value.findIndex((m) => M(m, c, o)); this._lastSelectedOrDeslectedItemIndex = a.findIndex((m) => M(m, c, o)); let i = []; r !== -1 ? (i = this.value, i.splice(r, 1)) : i = [...this.value, c], (this.props.filter !== void 0 ? this.props.filter : this.state.text) && !this.mobileMode && (this.state.text && (e.data.text = ""), this.base.filterChanged("", e)), this._adaptiveInput && this._adaptiveInput.blur(), this.state.focusedIndex !== void 0 && (e.data.focusedIndex = void 0), this.triggerOnChange(i, e), this.base.triggerPageChangeCornerItems(c, e); }, this.onTagDelete = (t, e) => { const o = this.base.initState(); o.syntheticEvent = e, this.opened && this.base.togglePopup(o), !this.state.focused && !this.mobileMode && (o.data.focused = !0, this.focus()); const s = this.value; w(s, t, this.props.dataItemKey), this.triggerOnChange(s, o), this.applyState(o); }, this.itemFocus = (t, e) => { const { allowCustom: o, virtual: s } = this.props, a = b(this.props), p = s ? s.skip : 0, c = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedIndex: r } = this.getFocusedState(), i = o && c, l = a[t - p]; l && r !== t ? this.state.focusedIndex !== t && (e.data.focusedIndex = t, e.data.activedescendant = k.PopupList) : i && t === -1 && this.state.focusedIndex !== void 0 && (e.data.focusedIndex = void 0), this.base.triggerPageChangeCornerItems(l, e); }, this.componentRef = (t) => { this._element = t, this.base.wrapper = t; }, this.searchbarRef = (t) => { const e = this._input = t && t.input; e && this.state.focused && window.setTimeout(() => e.focus(), 0); }, this.onChangeHandler = (t) => { const e = this.base.initState(), o = t.target.value; e.syntheticEvent = t, this.props.filter === void 0 && (e.data.text = o), e.data.focusedIndex = void 0, this.opened || (this.base.togglePopup(e), this.setState({ currentValue: this.value })), this.base.filterChanged(o, e), this.applyState(e), this.setState({ group: void 0 }); }, this.clearButtonClick = (t) => { const e = this.base.initState(); e.syntheticEvent = t, t.stopPropagation(), this.value.length > 0 && this.triggerOnChange([], e), this.state.focusedIndex !== void 0 && (e.data.focusedIndex = void 0), this.opened && this.base.togglePopup(e); const o = this.props.filter !== void 0 ? this.props.filter : this.state.text; E(o) && o !== "" && this.base.filterChanged("", e), this.state.text && (e.data.text = ""), this._lastSelectedOrDeslectedItemIndex = null, this.applyState(e); }, this.onInputKeyDown = (t) => { const { textField: e, groupField: o } = this.props, s = b(this.props), a = t.keyCode, p = this.props.filter !== void 0 ? this.props.filter : this.state.text, c = this.props.opened !== void 0 ? this.props.opened : this.state.opened, { focusedItem: r, focusedIndex: i } = this.getFocusedState(), l = this.base.initState(); if (l.syntheticEvent = t, !p && this.value.length > 0 && (a === u.left || a === u.right || a === u.home || a === u.end || a === u.delete || a === u.backspace) && !t.shiftKey) return this.onTagsNavigate(t, l); const m = () => { t.preventDefault(), this.base.togglePopup(l), this.applyState(l); }; if (this.opened) if (a === u.pageUp) t.preventDefault(), this.base.scrollPopupByPageSize(-1); else if (a === u.pageDown) t.preventDefault(), this.base.scrollPopupByPageSize(1); else if ((t.ctrlKey || t.metaKey) && t.code === "KeyA") { const h = (this.state.value && this.state.value.length) === s.length ? [] : s; this.updateStateOnKeyboardNavigation(h, l); } else if ((t.ctrlKey || t.metaKey) && t.shiftKey && t.keyCode === u.end) { const d = s.slice(this.getFocusedState().focusedIndex); this.itemFocus(s.length - 1, l), this.updateStateOnKeyboardNavigation(d, l); } else if ((t.ctrlKey || t.metaKey) && t.shiftKey && t.keyCode === u.home) { const d = s.slice(0, this.getFocusedState().focusedIndex + 1); this.itemFocus(0, l), this.updateStateOnKeyboardNavigation(d, l); } else if (t.shiftKey && t.keyCode === u.up) { let d; const h = this.getLastSelectedOrDeselectedIndex(1, i); h === null ? d = i !== 0 ? s.slice(i - 1, i) : [s[i]] : h === i ? d = [s[h - 1]] : i >= 0 && (d = h > i ? s.slice(i - 1, h) : s.slice(h - 1, i)), d && d.length > 0 && (i >= 1 && this.itemFocus(i - 1, l), this.updateStateOnKeyboardNavigation(d, l)); } else if (t.shiftKey && t.keyCode === u.down) { let d; const h = this.getLastSelectedOrDeselectedIndex(0, i); h === null ? d = i !== s.length - 1 ? s.slice(i, i + 1) : [s[i]] : h === i ? d = s.slice(i, i + 2) : i >= 0 && (d = h > i ? s.slice(i + 1, h + 1) : s.slice(h, i + 2)), d && d.length >= 1 && (this.itemFocus(i + 1, l), this.updateStateOnKeyboardNavigation(d, l)); } else if (t.altKey && a === u.up) m(); else if (a === u.up || a === u.down) { if (o !== "" && e) if (!this.props.skipDisabledItems && c) this.onNavigate(l, a); else { let d = 0; if (a === u.down || a === u.right) { const h = s.slice(i + 1).find((v) => !v.disabled && v[e]); d = h && s.findIndex((v) => v[e] === h[e]); } else if (a === u.up || a === u.left) { let h; if (i === -1) h = s, d = s.findIndex((v) => !v.disabled && v[e]); else { h = s.slice(0, i); let v = h.pop(); for (; v && v.disabled; ) v = h.pop(); d = v && s.findIndex((x) => x[e] === v[e]); } } if (d) { const h = d - i; this.onNavigate(l, a, h); } else d !== void 0 && this.onNavigate(l, a); } else if (!this.props.skipDisabledItems && c) this.onNavigate(l, a); else { let d = null; if (a === u.down || a === u.right) d = s.slice(i + 1).find((h) => !h.disabled); else if (a === u.up || a === u.left) { const h = s.slice(0, i); for (d = h.pop(); d && d.disabled; ) d = h.pop(); } if (d) { const h = d.id - i - 1; this.onNavigate(l, a, h); } else this.onNavigate(l, a); } this.applyState(l), t.preventDefault(); } else a === u.enter ? (t.preventDefault(), this.props.allowCustom && p && r === null ? this.customItemSelect(t) : r && r.disabled ? m() : this.selectFocusedItem(t)) : a === u.esc && m(); else t.altKey && a === u.down ? m() : a === u.esc && this.clearButtonClick(t); }, this.listContainerContent = () => { const { header: t, footer: e, allowCustom: o, size: s, groupStickyHeaderItemRender: a, groupField: p, list: c } = this.props, r = b(this.props), i = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedType: l } = this.getFocusedState(), m = o && i && /* @__PURE__ */ f.createElement( "div", { className: I("k-list", { [`k-list-${T[s] || s}`]: s }), key: "customitem", onClick: this.customItemSelect, onMouseDown: $ }, /* @__PURE__ */ f.createElement( "div", { className: I("k-list-item k-custom-item", { "k-focus": W(l) }), style: { fontStyle: "italic" } }, i, /* @__PURE__ */ f.createElement(R, { name: "plus", icon: at, style: { position: "absolute", right: "0.5em" } }) ) ); let { group: d } = this.state; return d === void 0 && p !== void 0 && (d = O(r[0], p)), /* @__PURE__ */ f.createElement(f.Fragment, null, t && /* @__PURE__ */ f.createElement("div", { className: "k-list-header" }, t), m, /* @__PURE__ */ f.createElement( "div", { className: I("k-list", { [`k-list-${this.mobileMode ? "lg" : T[s] || s}`]: s, "k-virtual-list": this.base.vs.enabled }) }, !c && d && r.length !== 0 && /* @__PURE__ */ f.createElement(rt, { group: d, groupMode: "modern", render: a }), this.renderList() ), this.showLicenseWatermark && /* @__PURE__ */ f.createElement(X, null), e && /* @__PURE__ */ f.createElement("div", { className: "k-list-footer" }, e)); }, this.renderListContainer = () => { const t = this.base, { dir: e } = this.props, o = b(this.props), s = this.base.getPopupSettings(), a = s.width !== void 0 ? s.width : t.popupWidth, p = { dir: e !== void 0 ? e : t.dirCalculated, width: a, popupSettings: { ...s, popupClass: I(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__ */ f.createElement(lt, { ...p }, this.listContainerContent()); }, this.renderAdaptiveListContainer = () => { const { adaptiveTitle: t, filterable: e, filter: o } = this.props, { windowWidth: s = 0 } = this.state, a = o !== void 0 ? o : this.state.text; this.localization = bt(this); const p = e ? /* @__PURE__ */ f.createElement( It, { value: a, ref: (r) => this._adaptiveInput = r && r.element, onChange: this.onChangeHandler, onKeyDown: this.onInputKeyDown, size: this.props.size, rounded: this.props.rounded, fillMode: this.props.fillMode } ) : null, c = { title: t, expand: this.opened, onClose: (r) => this.onCancel(r), windowWidth: s, mobileFilter: p, footer: { cancelText: this.localization.toLanguageString( B, V[B] ), onCancel: this.onCancel, applyText: this.localization.toLanguageString( A, V[A] ), onApply: this.closePopup } }; return /* @__PURE__ */ f.createElement(gt, { ...c }, /* @__PURE__ */ f.createElement(vt, { overflowHidden: !0 }, /* @__PURE__ */ f.createElement("div", { className: "k-list-container" }, this.listContainerContent()))); }, this.closePopup = (t) => { const e = this.base.initState(); e.syntheticEvent = t, t.stopPropagation(), this.state.focusedIndex !== void 0 && (e.data.focusedIndex = void 0), this.opened && this.base.togglePopup(e), e.events.push({ type: "onClose" }); const o = this.props.filter !== void 0 ? this.props.filter : this.state.text; E(o) && o !== "" && this.base.filterChanged("", e), this.state.text && (e.data.text = ""), this.applyState(e); }, this.onCancel = (t) => { const e = this.base.initState(); e.syntheticEvent = t, t.stopPropagation(), this.state.focusedIndex !== void 0 && (e.data.focusedIndex = void 0), this.opened && this.base.togglePopup(e), e.events.push({ type: "onCancel" }); const o = this.props.filter !== void 0 ? this.props.filter : this.state.text; E(o) && o !== "" && this.base.filterChanged("", e), this.state.text && (e.data.text = ""), this.applyState(e); }, this.renderList = () => { const { textField: t, listNoDataRender: e, itemRender: o, groupHeaderItemRender: s, dataItemKey: a, virtual: p = { skip: 0, total: void 0 } } = this.props, c = b(this.props), r = this.base.vs, { focusedIndex: i } = this.getFocusedState(), l = this.base.getPopupSettings(), m = `translateY(${r.translate}px)`; return /* @__PURE__ */ f.createElement( dt, { id: this.base.listBoxId, show: this.opened, data: c.slice(), focusedIndex: i - p.skip, value: this.value, textField: t, valueField: a, optionsGuid: this.base.guid, groupField: this.props.groupField, groupMode: "modern", listRef: (d) => { r.list = this.base.list = d; }, wrapperStyle: this.mobileMode ? {} : { maxHeight: l.height }, wrapperCssClass: "k-list-content", listStyle: r.enabled ? { transform: m } : void 0, key: "listKey", skip: p.skip, onClick: this.handleItemClick, itemRender: o, groupHeaderItemRender: s, noDataRender: e, onMouseDown: $, onBlur: this.handleBlur, onScroll: this.onScroll, wrapperRef: r.scrollerRef, scroller: this.base.renderScrollElement(), ariaSetSize: p.total } ); }, this.onScroll = (t) => { const { vs: e, list: o } = this.base; e.scrollHandler(t); const { groupField: s } = this.props; let a = b(this.props); if (!(!s || !a.length) && s) { const p = this.itemHeight = this.itemHeight || (e.enabled ? e.itemHeight : o ? o.children[0].offsetHeight : 0), r = t.target.scrollTop - e.skip * p; a = this.base.getGroupedDataModernMode(a, s); let i = a[0][s]; for (let l = 1; l < a.length && !(p * l > r); l++) a[l] && a[l][s] && (i = a[l][s]); i !== this.state.group && this.setState({ group: i }); } }, this.customItemSelect = (t) => { const e = this.props.filter !== void 0 ? this.props.filter : this.state.text, { textField: o } = this.props; if (!e) return; const s = this.base.initState(); s.syntheticEvent = t; const a = o ? { [o]: e } : e; this.state.text !== void 0 && (s.data.text = ""), s.data.focusedIndex = void 0, this.base.filterChanged("", s); const p = [...this.value, a]; this.triggerOnChange(p, s), this.base.togglePopup(s), this.applyState(s); }, this.handleWrapperClick = (t) => { const e = this._input; !this.opened && e && this.focusElement(e); const o = this.base.initState(); o.syntheticEvent = t, !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 = (t, e) => { const o = this.base.initState(); o.syntheticEvent = e, this.handleItemSelect(t, o), this.props.autoClose && !this.mobileMode && this.base.togglePopup(o), e.stopPropagation(), this.applyState(o); }, this.handleBlur = (t) => { if (!this.state.focused || this._skipFocusEvent) return; const e = this.base.initState(), { allowCustom: o, filterable: s } = this.props; e.syntheticEvent = t, e.data.focused = !1, e.events.push({ type: "onBlur" }), this.opened && !this.mobileMode && (this.state.opened && (e.data.opened = !1), e.events.push({ type: "onClose" })), !o && !s && this.state.text && (e.data.text = ""), this.applyState(e); }, this.handleFocus = (t) => { this._skipFocusEvent || this.base.handleFocus(t); }, 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 || xt ); }, this.validate(n); } get _inputId() { return this.props.id; } get document() { if (L) return this.element && this.element.ownerDocument || document; } validate(n) { if (n.filterable || n.virtual) { const t = []; n.filterable && t.push("filterable"), n.virtual && t.push("virtualization"), this.showLicenseWatermark = !Z(ft, { component: "MultiSelect", features: t }); } } /** @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: t } = this.props, e = []; return n === void 0 ? this.value.forEach((o) => { e.push({ text: O(o, t), data: [o] }); }) : e.push(...n), e; } /** * The mobile mode of the MultiSelect. */ get mobileMode() { var t; return !!(this.state.windowWidth && this.props._adaptiveMode && this.state.windowWidth <= ((t = this.props._adaptiveMode) == null ? void 0 : t.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, t = !this.required || this.value !== null && this.value.length > 0 && this.value !== void 0, e = this.props.valid !== void 0 ? this.props.valid : t; return { customError: n, valid: e, valueMissing: this.value === null }; } /** @hidden */ get required() { return this.props.required !== void 0 ? this.props.required : y.defaultProps.required; } get validityStyles() { return this.props.validityStyles !== void 0 ? this.props.validityStyles : y.defaultProps.validityStyles; } /** @hidden */ componentDidUpdate(n, t) { var m; const { virtual: e, groupField: o = "" } = this.props, s = b(this.props), a = e ? e.skip : 0, p = n.virtual ? n.virtual.total : 0, c = n.opened !== void 0 ? n.opened : t.opened, r = !c && this.opened, i = c && !this.opened, l = this.base.getPopupSettings(); if (this.validate(this.props), this.base.didUpdate(), !l.animate && i && this.onPopupClosed(), e && e.total !== p) this.base.vs.calcScrollElementHeight(), this.base.vs.reset(); else { let { focusedItem: d, focusedIndex: h } = this.getFocusedState(); o !== "" && (h = (m = this.base.getGroupedDataModernMode(s, o)) == null ? void 0 : m.indexOf(d)), r && e ? this.base.scrollToVirtualItem(e, h - a) : r && !e ? (s && s.length !== 0 && this.base.resetGroupStickyHeader(s[0][o], this), this.base.scrollToItem(h)) : this.opened && c && d && this.scrollToFocused && this.base.scrollToItem(h - a); } this.scrollToFocused = !1, this.setValidity(); } /** @hidden */ componentDidMount() { var n; this.observerResize = L && 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, t, e) { const { allowCustom: o } = this.props, s = b(this.props), a = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedType: p, focusedIndex: c } = this.getFocusedState(), r = o && a, i = W(p), l = this.base, m = l.vs; if (this.opened && t === u.up && i) this.state.focusedIndex !== void 0 && (n.data.focusedIndex = void 0); else { const d = l.navigation.navigate({ keyCode: t, current: c, max: (m.enabled ? m.total : s.length) - 1, min: r ? -1 : 0, skipItems: e || void 0 }); d !== void 0 && (this.itemFocus(d, n), this.scrollToFocused = !0); } this.applyState(n); } /** @hidden */ render() { const { style: n, className: t, label: e, dir: o, disabled: s, textField: a, dataItemKey: p, virtual: c, size: r, rounded: i, fillMode: l, loading: m, filter: d } = this.props, { text: h, focused: v, focusedTag: x, currentValue: q } = this.state, C = this.base.vs, _ = this.props.id || this._inputId; C.enabled = c !== void 0, c !== void 0 && (C.skip = c.skip, C.total = c.total, C.pageSize = c.pageSize); const S = this.mobileMode && this.opened ? q : this.tagsToRender; this.setItems(this.tagsToRender, this._tags); const K = !this.validityStyles || this.validity.valid, G = !!(d !== void 0 ? d : h) || S && S.length > 0, [U, j] = H(this.props.prefix || f.Fragment), [Y, J] = H(this.props.suffix || f.Fragment), N = /* @__PURE__ */ f.createElement(f.Fragment, null, /* @__PURE__ */ f.createElement( "div", { ref: this.componentRef, className: I("k-multiselect k-input", t, { [`k-input-${T[r] || r}`]: r, [`k-rounded-${yt[i] || i}`]: i, [`k-input-${l}`]: l, "k-focus": v && !s, "k-invalid": !K, "k-disabled": s, "k-loading": m, "k-required": this.required }), style: e ? { ...n, width: void 0 } : n, dir: o, onFocus: this.handleFocus, onBlur: this.handleBlur, onClick: this.handleWrapperClick, onMouseDown: ct }, this.props.prefix && /* @__PURE__ */ f.createElement(U, { ...j }), /* @__PURE__ */ f.createElement("div", { className: I("k-input-values") }, /* @__PURE__ */ f.createElement( "div", { className: I("k-chip-list", { [`k-chip-list-${T[r] || r}`]: r }), role: "listbox", id: "tagslist-" + this.base.guid }, S && S.length > 0 && /* @__PURE__ */ f.createElement( ht, { tagRender: this.props.tagRender, onTagDelete: this.onTagDelete, data: S, guid: this.base.guid, focused: x ? S.find((Q) => z(Q, x, p)) : void 0, size: r } ) ), this.renderSearchBar(_)), m && /* @__PURE__ */ f.createElement(R, { className: "k-input-loading-icon", name: "loading" }), this.props.suffix && /* @__PURE__ */ f.createElement(Y, { ...J }), G && /* @__PURE__ */ f.createElement(mt, { onClick: this.clearButtonClick }), !this.mobileMode && this.renderListContainer() ), this.mobileMode && this.renderAdaptiveListContainer()); return e ? /* @__PURE__ */ f.createElement( nt, { label: e, editorId: _, editorValue: h || O(this.value[0], a), editorValid: K, editorDisabled: s, style: { width: n ? n.width : void 0 }, children: N } ) : N; } renderSearchBar(n) { const { activedescendant: t, focusedTag: e, currentValue: o } = this.state, { disabled: s, placeholder: a, ariaDescribedBy: p, ariaLabelledBy: c, ariaLabel: r, inputAttributes: i } = this.props, l = !this.mobileMode && (this.props.filter !== void 0 ? this.props.filter : this.state.text) || "", { focusedIndex: m } = this.getFocusedState(), d = this.value.length === 0 && !l ? a : void 0, h = o && o.length > 0 ? void 0 : a, v = t === k.TagsList && e !== void 0 ? `tag-${this.base.guid}-${e.text.replace(/\s+/g, "-")}` : `option-${this.base.guid}-${m}`, x = { accessKey: this.props.accessKey, tabIndex: this.props.tabIndex }; return /* @__PURE__ */ f.createElement( pt, { id: n, size: Math.max((d || "").length, l.length, 1), placeholder: this.mobileMode && this.opened ? h : d, value: l, onChange: this.onChangeHandler, onKeyDown: this.onInputKeyDown, ref: this.searchbarRef, disabled: s, expanded: this.opened, owns: this.base.listBoxId, role: "combobox", activedescendant: v, ariaDescribedBy: `tagslist-${this.base.guid}${p ? " " + p : ""}`, ariaLabelledBy: c, ariaRequired: this.required, ariaLabel: r, inputAttributes: i, ...x } ); } onTagsNavigate(n, t) { const e = n.keyCode, { focusedTag: o } = this.state, s = this._tags, a = this.props.dataItemKey; let p = o ? s.findIndex((i) => z(i, o, a)) : -1, c; const r = p !== -1; if (e === u.left) r ? p = Math.max(0, p - 1) : p = s.length - 1, c = s[p]; else if (e === u.right) p === s.length - 1 ? c = void 0 : r && (p = Math.min(s.length - 1, p + 1), c = s[p]); else if (e === u.home && !n.shiftKey) c = s[0]; else if (e === u.end && !n.shiftKey) c = s[s.length - 1]; else if (e === u.delete) { if (r) { const i = this.value; w(i, s[p].data, a), this.triggerOnChange(i, t); } } else if (e === u.backspace) { const i = this.value; if (r) w(i, s[p].data, a), this.triggerOnChange(i, t); else if (!r && s.length) { const l = s.pop(); w(i, l.data, a), this.triggerOnChange(i, t); } } c !== o && (t.data.focusedTag = c, t.data.activedescendant = k.TagsList), this.applyState(t); } triggerOnChange(n, t) { this.props.value === void 0 && (t.data.value = [...n]), this._valueItemsDuringOnChange = [], this.setItems(n, this._valueItemsDuringOnChange), t.events.push({ type: "onChange" }); } selectFocusedItem(n, t) { const { virtual: e } = this.props, o = b(this.props), { focusedIndex: s } = t || this.getFocusedState(), a = e ? e.skip : 0; o[s - a] !== void 0 && this.handleItemClick(s, n); } setItems(n, t) { t.length = 0, t.push(...n); } getFocusedState() { const { focusedIndex: n } = this.state, t = this.props.filter !== void 0 ? this.props.filter : this.state.text, { allowCustom: e, dataItemKey: o, virtual: s, textField: a, focusedItemIndex: p = ut, skipDisabledItems: c } = this.props, r = b(this.props), i = s && s.skip || 0; let l; if (n !== void 0) return { focusedIndex: n, focusedItem: r[n - i], focusedType: 1 /* ListItem */ }; const m = this.value; if (e && t) return { focusedItem: null, focusedIndex: -1, focusedType: 2 /* CustomItem */ }; if (t) return l = p(r, t, a), { focusedItem: r[l], focusedIndex: l + i, focusedType: 1 /* ListItem */ }; if (m.length) { const d = m[m.length - 1]; return l = r.findIndex((h) => M(h, d, o)), r[l] !== void 0 ? { focusedIndex: l + i, focusedItem: r[l], focusedType: 1 /* ListItem */ } : { focusedType: 0, focusedIndex: -1 }; } else if (c && a && !t && i === 0) { const d = r.findIndex((h) => !h.disabled && h[a]); return { focusedIndex: d, focusedItem: r[d - i], focusedType: 1 /* ListItem */ }; } return i === 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 t of n) this.setState({ windowWidth: t.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, t) { this.setState({ value: n }), this.triggerOnChange(n, t), this.applyState(t); } /** * 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, t) { return this._lastSelectedOrDeslectedItemIndex === null && (this._lastSelectedOrDeslectedItemIndex = t), this._lastSelectedOrDeslectedItemIndex !== null ? this._lastSelectedOrDeslectedItemIndex + n : null; } }; y.displayName = "MultiSelect", y.propTypes = { ...D.propTypes, autoClose: g.bool, value: g.arrayOf(g.any), defaultValue: g.arrayOf(g.any), dataItemKey: g.string, placeholder: g.string, tags: g.arrayOf( g.shape({ text: g.string, data: g.arrayOf(g.any) }) ), tagRender: g.func, id: g.string, ariaLabelledBy: g.string, ariaDescribedBy: g.string, groupField: g.string, list: g.any, adaptive: g.bool, adaptiveTitle: g.string, onCancel: g.func, skipDisabledItems: g.bool, inputAttributes: g.object }, y.defaultProps = { ...D.defaultProps, autoClose: !0, required: !1, size: "medium", rounded: "medium", fillMode: "solid", groupMode: "modern", skipDisabledItems: !0, prefix: void 0, suffix: void 0 }; let P = y; const St = tt(), Ct = et( st( St, it(P) ) ); Ct.displayName = "KendoReactMultiSelect"; export { Ct as MultiSelect, St as MultiSelectPropsContext, P as MultiSelectWithoutContext };