@progress/kendo-react-dropdowns
Version:
React DropDowns offer an interface for users to select different items from a list and more. KendoReact Dropdowns package
707 lines (706 loc) • 32.6 kB
JavaScript
/**
* @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 L, WatermarkOverlay as Y, canUseDOM as B, validatePackage as J, createPropsContext as Q, withIdHOC as X, withPropsContext as Z, withAdaptiveModeContext as tt, kendoThemeMaps as et } from "@progress/kendo-react-common";
import { plusIcon as st } from "@progress/kendo-svg-icons";
import { FloatingLabel as it } from "@progress/kendo-react-labels";
import ot from "../common/ListContainer.mjs";
import at from "../common/List.mjs";
import nt from "../common/GroupStickyHeader.mjs";
import lt from "./TagList.mjs";
import dt from "../common/SearchBar.mjs";
import E from "../common/DropDownBase.mjs";
import { ActiveDescendant as w } from "../common/settings.mjs";
import { getFilteredData as b, areSame as M, removeDataItems as T, isPresent as O, getItemValue as P, preventDefaultNonInputs as rt, matchTags as V, itemIndexStartsWith as ht } from "../common/utils.mjs";
import { packageMetadata as pt } from "../package-metadata.mjs";
import ct from "../common/ClearButton.mjs";
import { AdaptiveMode as ut } from "../common/AdaptiveMode.mjs";
import { ActionSheetContent as ft } from "@progress/kendo-react-layout";
import { provideLocalizationService as mt } from "@progress/kendo-react-intl";
import gt from "../common/ListFilter.mjs";
import z from "../common/withCustomComponent.mjs";
const { sizeMap: D, roundedMap: vt } = et, bt = "Please enter a valid value!", A = (F) => F.preventDefault(), H = (F) => F === 2, y = class y extends f.Component {
constructor(n) {
super(n), this.state = {
activedescendant: w.PopupList,
currentValue: []
}, this._element = null, this._valueItemsDuringOnChange = null, this.base = new E(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: a, virtual: s } = this.props, o = b(this.props), p = s ? s.skip : 0, c = o[t - p], r = this.value.findIndex((m) => M(m, c, a));
this._lastSelectedOrDeslectedItemIndex = o.findIndex((m) => M(m, c, a));
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 a = this.base.initState();
a.syntheticEvent = e, this.opened && this.base.togglePopup(a), !this.state.focused && !this.mobileMode && (a.data.focused = !0, this.focus());
const s = this.value;
T(s, t, this.props.dataItemKey), this.triggerOnChange(s, a), this.applyState(a);
}, this.itemFocus = (t, e) => {
const { allowCustom: a, virtual: s } = this.props, o = 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 = a && c, l = o[t - p];
l && r !== t ? this.state.focusedIndex !== t && (e.data.focusedIndex = t, e.data.activedescendant = w.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(), a = t.target.value;
e.syntheticEvent = t, this.props.filter === void 0 && (e.data.text = a), e.data.focusedIndex = void 0, this.opened || (this.base.togglePopup(e), this.setState({ currentValue: this.value })), this.base.filterChanged(a, 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 a = this.props.filter !== void 0 ? this.props.filter : this.state.text;
O(a) && a !== "" && this.base.filterChanged("", e), this.state.text && (e.data.text = ""), this._lastSelectedOrDeslectedItemIndex = null, this.applyState(e);
}, this.onInputKeyDown = (t) => {
const { textField: e, groupField: a } = this.props, s = b(this.props), o = 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 && (o === u.left || o === u.right || o === u.home || o === u.end || o === u.delete || o === u.backspace) && !t.shiftKey)
return this.onTagsNavigate(t, l);
const m = () => {
t.preventDefault(), this.base.togglePopup(l), this.applyState(l);
};
if (this.opened)
if (o === u.pageUp)
t.preventDefault(), this.base.scrollPopupByPageSize(-1);
else if (o === 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 && o === u.up)
m();
else if (o === u.up || o === u.down) {
if (a !== "" && e)
if (!this.props.skipDisabledItems && c)
this.onNavigate(l, o);
else {
let d = 0;
if (o === u.down || o === 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 (o === u.up || o === 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, o, h);
} else d !== void 0 && this.onNavigate(l, o);
}
else if (!this.props.skipDisabledItems && c)
this.onNavigate(l, o);
else {
let d = null;
if (o === u.down || o === u.right)
d = s.slice(i + 1).find((h) => !h.disabled);
else if (o === u.up || o === 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, o, h);
} else
this.onNavigate(l, o);
}
this.applyState(l), t.preventDefault();
} else o === u.enter ? (t.preventDefault(), this.props.allowCustom && p && r === null ? this.customItemSelect(t) : r && r.disabled ? m() : this.selectFocusedItem(t)) : o === u.esc && m();
else t.altKey && o === u.down ? m() : o === u.esc && this.clearButtonClick(t);
}, this.listContainerContent = () => {
const { header: t, footer: e, allowCustom: a, size: s, groupStickyHeaderItemRender: o, 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 = a && i && /* @__PURE__ */ f.createElement(
"div",
{
className: I("k-list", {
[`k-list-${D[s] || s}`]: s
}),
key: "customitem",
onClick: this.customItemSelect,
onMouseDown: A
},
/* @__PURE__ */ f.createElement(
"div",
{
className: I("k-list-item k-custom-item", { "k-focus": H(l) }),
style: { fontStyle: "italic" }
},
i,
/* @__PURE__ */ f.createElement(L, { name: "plus", icon: st, style: { position: "absolute", right: "0.5em" } })
)
);
let { group: d } = this.state;
return d === void 0 && p !== void 0 && (d = P(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" : D[s] || s}`]: s,
"k-virtual-list": this.base.vs.enabled
})
},
!c && d && r.length !== 0 && /* @__PURE__ */ f.createElement(nt, { group: d, groupMode: "modern", render: o }),
this.renderList()
), this.showLicenseWatermark && /* @__PURE__ */ f.createElement(Y, null), e && /* @__PURE__ */ f.createElement("div", { className: "k-list-footer" }, e));
}, this.renderListContainer = () => {
const t = this.base, { dir: e } = this.props, a = b(this.props), s = this.base.getPopupSettings(), o = s.width !== void 0 ? s.width : t.popupWidth, p = {
dir: e !== void 0 ? e : t.dirCalculated,
width: o,
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: [a.length, this.value.length]
};
return /* @__PURE__ */ f.createElement(ot, { ...p }, this.listContainerContent());
}, this.renderAdaptiveListContainer = () => {
const { adaptiveTitle: t, adaptiveSubtitle: e, filterable: a, filter: s } = this.props, { windowWidth: o = 0 } = this.state, p = s !== void 0 ? s : this.state.text;
this.localization = mt(this);
const c = a ? /* @__PURE__ */ f.createElement(
gt,
{
value: p,
ref: (i) => {
this._adaptiveInput = i && i.element;
},
onChange: this.onChangeHandler,
onKeyDown: this.onInputKeyDown,
size: "large",
rounded: this.props.rounded,
fillMode: this.props.fillMode,
placeholder: this.props.placeholder
}
) : null, r = {
title: t || this.props.label,
subTitle: e,
expand: this.opened,
onClose: (i) => this.closePopup(i),
windowWidth: o,
mobileFilter: c
};
return /* @__PURE__ */ f.createElement(ut, { ...r }, /* @__PURE__ */ f.createElement(ft, null, /* @__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 a = this.props.filter !== void 0 ? this.props.filter : this.state.text;
O(a) && a !== "" && 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 a = this.props.filter !== void 0 ? this.props.filter : this.state.text;
O(a) && a !== "" && this.base.filterChanged("", e), this.state.text && (e.data.text = ""), this.applyState(e);
}, this.renderList = () => {
const {
textField: t,
listNoDataRender: e,
itemRender: a,
groupHeaderItemRender: s,
dataItemKey: o,
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(
at,
{
id: this.base.listBoxId,
show: this.opened,
data: c.slice(),
focusedIndex: i - p.skip,
value: this.value,
textField: t,
valueField: o,
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: a,
groupHeaderItemRender: s,
noDataRender: e,
onMouseDown: A,
onBlur: this.handleBlur,
onScroll: this.onScroll,
wrapperRef: r.scrollerRef,
scroller: this.base.renderScrollElement(),
ariaSetSize: p.total
}
);
}, this.onScroll = (t) => {
const { vs: e, list: a } = this.base;
e.scrollHandler(t);
const { groupField: s } = this.props;
let o = b(this.props);
if (!(!s || !o.length) && s) {
const p = this.itemHeight = this.itemHeight || (e.enabled ? e.itemHeight : a ? a.children[0].offsetHeight : 0), r = t.target.scrollTop - e.skip * p;
o = this.base.getGroupedDataModernMode(o, s);
let i = o[0][s];
for (let l = 1; l < o.length && !(p * l > r); l++)
o[l] && o[l][s] && (i = o[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: a } = this.props;
if (!e)
return;
const s = this.base.initState();
s.syntheticEvent = t;
const o = a ? { [a]: e } : e;
this.state.text !== void 0 && (s.data.text = ""), s.data.focusedIndex = void 0, this.base.filterChanged("", s);
const p = [...this.value, o];
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 a = this.base.initState();
a.syntheticEvent = t, !this.state.focused && !this.mobileMode && (a.events.push({ type: "onFocus" }), a.data.focused = !0), this.mobileMode && (this.setState({ currentValue: this.tagsToRender }), this.mobileMode && window.setTimeout(() => this._adaptiveInput && this._adaptiveInput.focus(), 300)), this.base.togglePopup(a), this.applyState(a);
}, this.handleItemClick = (t, e) => {
const a = this.base.initState();
a.syntheticEvent = e, this.handleItemSelect(t, a), this.props.autoClose && this.base.togglePopup(a), e.stopPropagation(), this.applyState(a);
}, this.handleBlur = (t) => {
if (!this.state.focused || this._skipFocusEvent)
return;
const e = this.base.initState(), { allowCustom: a, 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" })), !a && !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 || bt
);
}, this.validate(n);
}
get _inputId() {
return this.props.id;
}
get document() {
if (B)
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 = !J(pt, {
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((a) => {
e.push({ text: P(a, t), data: [a] });
}) : 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: a = "" } = this.props, s = b(this.props), o = 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();
a !== "" && (h = (m = this.base.getGroupedDataModernMode(s, a)) == null ? void 0 : m.indexOf(d)), r && e ? this.base.scrollToVirtualItem(e, h - o) : r && !e ? (s && s.length !== 0 && this.base.resetGroupStickyHeader(s[0][a], this), this.base.scrollToItem(h)) : this.opened && c && d && this.scrollToFocused && this.base.scrollToItem(h - o);
}
this.scrollToFocused = !1, this.setValidity();
}
/** @hidden */
componentDidMount() {
var n;
this.observerResize = B && 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: a } = this.props, s = b(this.props), o = this.props.filter !== void 0 ? this.props.filter : this.state.text, { focusedType: p, focusedIndex: c } = this.getFocusedState(), r = a && o, i = H(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: a,
disabled: s,
textField: o,
dataItemKey: p,
virtual: c,
size: r,
rounded: i,
fillMode: l,
loading: m,
filter: d
} = this.props, { text: h, focused: v, focusedTag: x, currentValue: W } = this.state, C = this.base.vs, K = 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 ? W : this.tagsToRender;
this.setItems(this.tagsToRender, this._tags);
const N = !this.validityStyles || this.validity.valid, $ = !!(d !== void 0 ? d : h) || S && S.length > 0, [q, G] = z(this.props.prefix || f.Fragment), [U, j] = z(this.props.suffix || f.Fragment), R = /* @__PURE__ */ f.createElement(f.Fragment, null, /* @__PURE__ */ f.createElement(
"div",
{
ref: this.componentRef,
className: I("k-multiselect k-input", t, {
[`k-input-${D[r] || r}`]: r,
[`k-rounded-${vt[i] || i}`]: i,
[`k-input-${l}`]: l,
"k-focus": v && !s,
"k-invalid": !N,
"k-disabled": s,
"k-loading": m,
"k-required": this.required
}),
style: e ? { ...n, width: void 0 } : n,
dir: a,
onFocus: (k) => {
this.mobileMode ? this.handleWrapperClick(k) : this.handleFocus(k);
},
onBlur: this.handleBlur,
onClick: this.handleWrapperClick,
onMouseDown: rt
},
this.props.prefix && /* @__PURE__ */ f.createElement(q, { ...G }),
/* @__PURE__ */ f.createElement("div", { className: I("k-input-values") }, /* @__PURE__ */ f.createElement(
"div",
{
className: I("k-chip-list", { [`k-chip-list-${D[r] || r}`]: r }),
role: "listbox",
id: "tagslist-" + this.base.guid
},
S && S.length > 0 && /* @__PURE__ */ f.createElement(
lt,
{
tagRender: this.props.tagRender,
onTagDelete: this.onTagDelete,
data: S,
guid: this.base.guid,
focused: x ? S.find((k) => V(k, x, p)) : void 0,
size: r
}
)
), this.renderSearchBar(K)),
m && /* @__PURE__ */ f.createElement(L, { className: "k-input-loading-icon", name: "loading" }),
this.props.suffix && /* @__PURE__ */ f.createElement(U, { ...j }),
$ && /* @__PURE__ */ f.createElement(ct, { onClick: this.clearButtonClick }),
!this.mobileMode && this.renderListContainer()
), this.mobileMode && this.renderAdaptiveListContainer());
return e ? /* @__PURE__ */ f.createElement(
it,
{
label: e,
editorId: K,
editorValue: h || P(this.value[0], o),
editorValid: N,
editorDisabled: s,
style: { width: n ? n.width : void 0 },
children: R
}
) : R;
}
renderSearchBar(n) {
const { activedescendant: t, focusedTag: e, currentValue: a } = this.state, { disabled: s, placeholder: o, 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 ? o : void 0, h = a && a.length > 0 ? void 0 : o, v = t === w.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(
dt,
{
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: a } = this.state, s = this._tags, o = this.props.dataItemKey;
let p = a ? s.findIndex((i) => V(i, a, o)) : -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;
T(i, s[p].data, o), this.triggerOnChange(i, t);
}
} else if (e === u.backspace) {
const i = this.value;
if (r)
T(i, s[p].data, o), this.triggerOnChange(i, t);
else if (!r && s.length) {
const l = s.pop();
T(i, l.data, o), this.triggerOnChange(i, t);
}
}
c !== a && (t.data.focusedTag = c, t.data.activedescendant = w.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, a = b(this.props), { focusedIndex: s } = t || this.getFocusedState(), o = e ? e.skip : 0;
a[s - o] !== 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: a,
virtual: s,
textField: o,
focusedItemIndex: p = ht,
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, o), {
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, a)), r[l] !== void 0 ? {
focusedIndex: l + i,
focusedItem: r[l],
focusedType: 1
/* ListItem */
} : { focusedType: 0, focusedIndex: -1 };
} else if (c && o && !t && i === 0) {
const d = r.findIndex((h) => !h.disabled && h[o]);
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 = {
...E.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,
adaptiveSubtitle: g.string,
onCancel: g.func,
skipDisabledItems: g.bool,
inputAttributes: g.object
}, y.defaultProps = {
...E.defaultProps,
autoClose: !0,
required: !1,
size: "medium",
rounded: "medium",
fillMode: "solid",
groupMode: "modern",
skipDisabledItems: !0,
prefix: void 0,
suffix: void 0
};
let _ = y;
const It = Q(), yt = X(
Z(
It,
tt(_)
)
);
yt.displayName = "KendoReactMultiSelect";
export {
yt as MultiSelect,
It as MultiSelectPropsContext,
_ as MultiSelectWithoutContext
};