631d45b8f16d9105b1140b46734d774415c5441d130e04701ca896012422cebcb4ad3217ab2a0a27d45619a7dffe7ee2b9402c5ea6b4543309306c39269f82 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var lodashUnified = require('lodash-unified');
  5. var core = require('@vueuse/core');
  6. var useAllowCreate = require('./useAllowCreate.js');
  7. var useProps = require('./useProps.js');
  8. var index = require('../../../hooks/use-locale/index.js');
  9. var index$1 = require('../../../hooks/use-namespace/index.js');
  10. var useFormItem = require('../../form/src/hooks/use-form-item.js');
  11. var index$2 = require('../../../hooks/use-empty-values/index.js');
  12. var index$3 = require('../../../hooks/use-composition/index.js');
  13. var index$4 = require('../../../hooks/use-focus-controller/index.js');
  14. var error = require('../../../utils/error.js');
  15. var shared = require('@vue/shared');
  16. var icon = require('../../../utils/vue/icon.js');
  17. var strings = require('../../../utils/strings.js');
  18. var useFormCommonProps = require('../../form/src/hooks/use-form-common-props.js');
  19. var form = require('../../../constants/form.js');
  20. var aria = require('../../../constants/aria.js');
  21. var types = require('../../../utils/types.js');
  22. var event = require('../../../constants/event.js');
  23. const useSelect = (props, emit) => {
  24. const { t } = index.useLocale();
  25. const nsSelect = index$1.useNamespace("select");
  26. const nsInput = index$1.useNamespace("input");
  27. const { form: elForm, formItem: elFormItem } = useFormItem.useFormItem();
  28. const { inputId } = useFormItem.useFormItemInputId(props, {
  29. formItemContext: elFormItem
  30. });
  31. const { aliasProps, getLabel, getValue, getDisabled, getOptions } = useProps.useProps(props);
  32. const { valueOnClear, isEmptyValue } = index$2.useEmptyValues(props);
  33. const states = vue.reactive({
  34. inputValue: "",
  35. cachedOptions: [],
  36. createdOptions: [],
  37. hoveringIndex: -1,
  38. inputHovering: false,
  39. selectionWidth: 0,
  40. collapseItemWidth: 0,
  41. previousQuery: null,
  42. previousValue: void 0,
  43. selectedLabel: "",
  44. menuVisibleOnFocus: false,
  45. isBeforeHide: false
  46. });
  47. const popperSize = vue.ref(-1);
  48. const selectRef = vue.ref();
  49. const selectionRef = vue.ref();
  50. const tooltipRef = vue.ref();
  51. const tagTooltipRef = vue.ref();
  52. const inputRef = vue.ref();
  53. const prefixRef = vue.ref();
  54. const suffixRef = vue.ref();
  55. const menuRef = vue.ref();
  56. const tagMenuRef = vue.ref();
  57. const collapseItemRef = vue.ref();
  58. const {
  59. isComposing,
  60. handleCompositionStart,
  61. handleCompositionEnd,
  62. handleCompositionUpdate
  63. } = index$3.useComposition({
  64. afterComposition: (e) => onInput(e)
  65. });
  66. const selectDisabled = vue.computed(() => props.disabled || !!(elForm == null ? void 0 : elForm.disabled));
  67. const { wrapperRef, isFocused, handleBlur } = index$4.useFocusController(inputRef, {
  68. disabled: selectDisabled,
  69. afterFocus() {
  70. if (props.automaticDropdown && !expanded.value) {
  71. expanded.value = true;
  72. states.menuVisibleOnFocus = true;
  73. }
  74. },
  75. beforeBlur(event) {
  76. var _a, _b;
  77. return ((_a = tooltipRef.value) == null ? void 0 : _a.isFocusInsideContent(event)) || ((_b = tagTooltipRef.value) == null ? void 0 : _b.isFocusInsideContent(event));
  78. },
  79. afterBlur() {
  80. var _a;
  81. expanded.value = false;
  82. states.menuVisibleOnFocus = false;
  83. if (props.validateEvent) {
  84. (_a = elFormItem == null ? void 0 : elFormItem.validate) == null ? void 0 : _a.call(elFormItem, "blur").catch((err) => error.debugWarn());
  85. }
  86. }
  87. });
  88. const allOptions = vue.computed(() => filterOptions(""));
  89. const hasOptions = vue.computed(() => {
  90. if (props.loading)
  91. return false;
  92. return props.options.length > 0 || states.createdOptions.length > 0;
  93. });
  94. const filteredOptions = vue.ref([]);
  95. const expanded = vue.ref(false);
  96. const needStatusIcon = vue.computed(() => {
  97. var _a;
  98. return (_a = elForm == null ? void 0 : elForm.statusIcon) != null ? _a : false;
  99. });
  100. const popupHeight = vue.computed(() => {
  101. const totalHeight = filteredOptions.value.length * props.itemHeight;
  102. return totalHeight > props.height ? props.height : totalHeight;
  103. });
  104. const hasModelValue = vue.computed(() => {
  105. return props.multiple ? shared.isArray(props.modelValue) && props.modelValue.length > 0 : !isEmptyValue(props.modelValue);
  106. });
  107. const showClearBtn = vue.computed(() => {
  108. return props.clearable && !selectDisabled.value && hasModelValue.value && (isFocused.value || states.inputHovering);
  109. });
  110. const iconComponent = vue.computed(() => props.remote && props.filterable ? "" : props.suffixIcon);
  111. const iconReverse = vue.computed(() => iconComponent.value && nsSelect.is("reverse", expanded.value));
  112. const validateState = vue.computed(() => (elFormItem == null ? void 0 : elFormItem.validateState) || "");
  113. const validateIcon = vue.computed(() => {
  114. if (!validateState.value)
  115. return;
  116. return icon.ValidateComponentsMap[validateState.value];
  117. });
  118. const debounce = vue.computed(() => props.remote ? 300 : 0);
  119. const emptyText = vue.computed(() => {
  120. if (props.loading) {
  121. return props.loadingText || t("el.select.loading");
  122. } else {
  123. if (props.remote && !states.inputValue && !hasOptions.value)
  124. return false;
  125. if (props.filterable && states.inputValue && hasOptions.value && filteredOptions.value.length === 0) {
  126. return props.noMatchText || t("el.select.noMatch");
  127. }
  128. if (!hasOptions.value) {
  129. return props.noDataText || t("el.select.noData");
  130. }
  131. }
  132. return null;
  133. });
  134. const isFilterMethodValid = vue.computed(() => props.filterable && shared.isFunction(props.filterMethod));
  135. const isRemoteMethodValid = vue.computed(() => props.filterable && props.remote && shared.isFunction(props.remoteMethod));
  136. const filterOptions = (query) => {
  137. const regexp = new RegExp(strings.escapeStringRegexp(query), "i");
  138. const isValidOption = (o) => {
  139. if (isFilterMethodValid.value || isRemoteMethodValid.value)
  140. return true;
  141. return query ? regexp.test(getLabel(o) || "") : true;
  142. };
  143. if (props.loading) {
  144. return [];
  145. }
  146. return [...states.createdOptions, ...props.options].reduce((all, item) => {
  147. const options = getOptions(item);
  148. if (shared.isArray(options)) {
  149. const filtered = options.filter(isValidOption);
  150. if (filtered.length > 0) {
  151. all.push({
  152. label: getLabel(item),
  153. type: "Group"
  154. }, ...filtered);
  155. }
  156. } else if (props.remote || isValidOption(item)) {
  157. all.push(item);
  158. }
  159. return all;
  160. }, []);
  161. };
  162. const updateOptions = () => {
  163. filteredOptions.value = filterOptions(states.inputValue);
  164. };
  165. const allOptionsValueMap = vue.computed(() => {
  166. const valueMap = /* @__PURE__ */ new Map();
  167. allOptions.value.forEach((option, index) => {
  168. valueMap.set(getValueKey(getValue(option)), { option, index });
  169. });
  170. return valueMap;
  171. });
  172. const filteredOptionsValueMap = vue.computed(() => {
  173. const valueMap = /* @__PURE__ */ new Map();
  174. filteredOptions.value.forEach((option, index) => {
  175. valueMap.set(getValueKey(getValue(option)), { option, index });
  176. });
  177. return valueMap;
  178. });
  179. const optionsAllDisabled = vue.computed(() => filteredOptions.value.every((option) => getDisabled(option)));
  180. const selectSize = useFormCommonProps.useFormSize();
  181. const collapseTagSize = vue.computed(() => selectSize.value === "small" ? "small" : "default");
  182. const calculatePopperSize = () => {
  183. var _a;
  184. if (types.isNumber(props.fitInputWidth)) {
  185. popperSize.value = props.fitInputWidth;
  186. return;
  187. }
  188. const width = ((_a = selectRef.value) == null ? void 0 : _a.offsetWidth) || 200;
  189. if (!props.fitInputWidth && hasOptions.value) {
  190. vue.nextTick(() => {
  191. popperSize.value = Math.max(width, calculateLabelMaxWidth());
  192. });
  193. } else {
  194. popperSize.value = width;
  195. }
  196. };
  197. const calculateLabelMaxWidth = () => {
  198. var _a, _b;
  199. const canvas = document.createElement("canvas");
  200. const ctx = canvas.getContext("2d");
  201. const selector = nsSelect.be("dropdown", "item");
  202. const dom = ((_b = (_a = menuRef.value) == null ? void 0 : _a.listRef) == null ? void 0 : _b.innerRef) || document;
  203. const dropdownItemEl = dom.querySelector(`.${selector}`);
  204. if (dropdownItemEl === null || ctx === null)
  205. return 0;
  206. const style = getComputedStyle(dropdownItemEl);
  207. const padding = Number.parseFloat(style.paddingLeft) + Number.parseFloat(style.paddingRight);
  208. ctx.font = `bold ${style.font.replace(new RegExp(`\\b${style.fontWeight}\\b`), "")}`;
  209. const maxWidth = filteredOptions.value.reduce((max, option) => {
  210. const metrics = ctx.measureText(getLabel(option));
  211. return Math.max(metrics.width, max);
  212. }, 0);
  213. return maxWidth + padding;
  214. };
  215. const getGapWidth = () => {
  216. if (!selectionRef.value)
  217. return 0;
  218. const style = window.getComputedStyle(selectionRef.value);
  219. return Number.parseFloat(style.gap || "6px");
  220. };
  221. const tagStyle = vue.computed(() => {
  222. const gapWidth = getGapWidth();
  223. const inputSlotWidth = props.filterable ? gapWidth + form.MINIMUM_INPUT_WIDTH : 0;
  224. const maxWidth = collapseItemRef.value && props.maxCollapseTags === 1 ? states.selectionWidth - states.collapseItemWidth - gapWidth - inputSlotWidth : states.selectionWidth - inputSlotWidth;
  225. return { maxWidth: `${maxWidth}px` };
  226. });
  227. const collapseTagStyle = vue.computed(() => {
  228. return { maxWidth: `${states.selectionWidth}px` };
  229. });
  230. const shouldShowPlaceholder = vue.computed(() => {
  231. if (shared.isArray(props.modelValue)) {
  232. return props.modelValue.length === 0 && !states.inputValue;
  233. }
  234. return props.filterable ? !states.inputValue : true;
  235. });
  236. const currentPlaceholder = vue.computed(() => {
  237. var _a;
  238. const _placeholder = (_a = props.placeholder) != null ? _a : t("el.select.placeholder");
  239. return props.multiple || !hasModelValue.value ? _placeholder : states.selectedLabel;
  240. });
  241. const popperRef = vue.computed(() => {
  242. var _a, _b;
  243. return (_b = (_a = tooltipRef.value) == null ? void 0 : _a.popperRef) == null ? void 0 : _b.contentRef;
  244. });
  245. const indexRef = vue.computed(() => {
  246. if (props.multiple) {
  247. const len = props.modelValue.length;
  248. if (props.modelValue.length > 0 && filteredOptionsValueMap.value.has(props.modelValue[len - 1])) {
  249. const { index } = filteredOptionsValueMap.value.get(props.modelValue[len - 1]);
  250. return index;
  251. }
  252. } else {
  253. if (!isEmptyValue(props.modelValue) && filteredOptionsValueMap.value.has(props.modelValue)) {
  254. const { index } = filteredOptionsValueMap.value.get(props.modelValue);
  255. return index;
  256. }
  257. }
  258. return -1;
  259. });
  260. const dropdownMenuVisible = vue.computed({
  261. get() {
  262. return expanded.value && emptyText.value !== false;
  263. },
  264. set(val) {
  265. expanded.value = val;
  266. }
  267. });
  268. const showTagList = vue.computed(() => {
  269. if (!props.multiple) {
  270. return [];
  271. }
  272. return props.collapseTags ? states.cachedOptions.slice(0, props.maxCollapseTags) : states.cachedOptions;
  273. });
  274. const collapseTagList = vue.computed(() => {
  275. if (!props.multiple) {
  276. return [];
  277. }
  278. return props.collapseTags ? states.cachedOptions.slice(props.maxCollapseTags) : [];
  279. });
  280. const {
  281. createNewOption,
  282. removeNewOption,
  283. selectNewOption,
  284. clearAllNewOption
  285. } = useAllowCreate.useAllowCreate(props, states);
  286. const toggleMenu = () => {
  287. if (selectDisabled.value)
  288. return;
  289. if (states.menuVisibleOnFocus) {
  290. states.menuVisibleOnFocus = false;
  291. } else {
  292. expanded.value = !expanded.value;
  293. }
  294. };
  295. const onInputChange = () => {
  296. if (states.inputValue.length > 0 && !expanded.value) {
  297. expanded.value = true;
  298. }
  299. createNewOption(states.inputValue);
  300. vue.nextTick(() => {
  301. handleQueryChange(states.inputValue);
  302. });
  303. };
  304. const debouncedOnInputChange = lodashUnified.debounce(onInputChange, debounce.value);
  305. const handleQueryChange = (val) => {
  306. if (states.previousQuery === val || isComposing.value) {
  307. return;
  308. }
  309. states.previousQuery = val;
  310. if (props.filterable && shared.isFunction(props.filterMethod)) {
  311. props.filterMethod(val);
  312. } else if (props.filterable && props.remote && shared.isFunction(props.remoteMethod)) {
  313. props.remoteMethod(val);
  314. }
  315. if (props.defaultFirstOption && (props.filterable || props.remote) && filteredOptions.value.length) {
  316. vue.nextTick(checkDefaultFirstOption);
  317. } else {
  318. vue.nextTick(updateHoveringIndex);
  319. }
  320. };
  321. const checkDefaultFirstOption = () => {
  322. const optionsInDropdown = filteredOptions.value.filter((n) => !n.disabled && n.type !== "Group");
  323. const userCreatedOption = optionsInDropdown.find((n) => n.created);
  324. const firstOriginOption = optionsInDropdown[0];
  325. states.hoveringIndex = getValueIndex(filteredOptions.value, userCreatedOption || firstOriginOption);
  326. };
  327. const emitChange = (val) => {
  328. if (!lodashUnified.isEqual(props.modelValue, val)) {
  329. emit(event.CHANGE_EVENT, val);
  330. }
  331. };
  332. const update = (val) => {
  333. emit(event.UPDATE_MODEL_EVENT, val);
  334. emitChange(val);
  335. states.previousValue = props.multiple ? String(val) : val;
  336. vue.nextTick(() => {
  337. if (props.multiple && shared.isArray(props.modelValue)) {
  338. const cachedOptions = states.cachedOptions.slice();
  339. const selectedOptions = props.modelValue.map((value) => getOption(value, cachedOptions));
  340. if (!lodashUnified.isEqual(states.cachedOptions, selectedOptions)) {
  341. states.cachedOptions = selectedOptions;
  342. }
  343. } else {
  344. initStates(true);
  345. }
  346. });
  347. };
  348. const getValueIndex = (arr = [], value) => {
  349. if (!shared.isObject(value)) {
  350. return arr.indexOf(value);
  351. }
  352. const valueKey = props.valueKey;
  353. let index = -1;
  354. arr.some((item, i) => {
  355. if (lodashUnified.get(item, valueKey) === lodashUnified.get(value, valueKey)) {
  356. index = i;
  357. return true;
  358. }
  359. return false;
  360. });
  361. return index;
  362. };
  363. const getValueKey = (item) => {
  364. return shared.isObject(item) ? lodashUnified.get(item, props.valueKey) : item;
  365. };
  366. const handleResize = () => {
  367. calculatePopperSize();
  368. };
  369. const resetSelectionWidth = () => {
  370. states.selectionWidth = Number.parseFloat(window.getComputedStyle(selectionRef.value).width);
  371. };
  372. const resetCollapseItemWidth = () => {
  373. states.collapseItemWidth = collapseItemRef.value.getBoundingClientRect().width;
  374. };
  375. const updateTooltip = () => {
  376. var _a, _b;
  377. (_b = (_a = tooltipRef.value) == null ? void 0 : _a.updatePopper) == null ? void 0 : _b.call(_a);
  378. };
  379. const updateTagTooltip = () => {
  380. var _a, _b;
  381. (_b = (_a = tagTooltipRef.value) == null ? void 0 : _a.updatePopper) == null ? void 0 : _b.call(_a);
  382. };
  383. const onSelect = (option) => {
  384. const optionValue = getValue(option);
  385. if (props.multiple) {
  386. let selectedOptions = props.modelValue.slice();
  387. const index = getValueIndex(selectedOptions, optionValue);
  388. if (index > -1) {
  389. selectedOptions = [
  390. ...selectedOptions.slice(0, index),
  391. ...selectedOptions.slice(index + 1)
  392. ];
  393. states.cachedOptions.splice(index, 1);
  394. removeNewOption(option);
  395. } else if (props.multipleLimit <= 0 || selectedOptions.length < props.multipleLimit) {
  396. selectedOptions = [...selectedOptions, optionValue];
  397. states.cachedOptions.push(option);
  398. selectNewOption(option);
  399. }
  400. update(selectedOptions);
  401. if (option.created) {
  402. handleQueryChange("");
  403. }
  404. if (props.filterable && !props.reserveKeyword) {
  405. states.inputValue = "";
  406. }
  407. } else {
  408. states.selectedLabel = getLabel(option);
  409. !lodashUnified.isEqual(props.modelValue, optionValue) && update(optionValue);
  410. expanded.value = false;
  411. selectNewOption(option);
  412. if (!option.created) {
  413. clearAllNewOption();
  414. }
  415. }
  416. focus();
  417. };
  418. const deleteTag = (event, option) => {
  419. let selectedOptions = props.modelValue.slice();
  420. const index = getValueIndex(selectedOptions, getValue(option));
  421. if (index > -1 && !selectDisabled.value) {
  422. selectedOptions = [
  423. ...props.modelValue.slice(0, index),
  424. ...props.modelValue.slice(index + 1)
  425. ];
  426. states.cachedOptions.splice(index, 1);
  427. update(selectedOptions);
  428. emit("remove-tag", getValue(option));
  429. removeNewOption(option);
  430. }
  431. event.stopPropagation();
  432. focus();
  433. };
  434. const focus = () => {
  435. var _a;
  436. (_a = inputRef.value) == null ? void 0 : _a.focus();
  437. };
  438. const blur = () => {
  439. var _a;
  440. if (expanded.value) {
  441. expanded.value = false;
  442. vue.nextTick(() => {
  443. var _a2;
  444. return (_a2 = inputRef.value) == null ? void 0 : _a2.blur();
  445. });
  446. return;
  447. }
  448. (_a = inputRef.value) == null ? void 0 : _a.blur();
  449. };
  450. const handleEsc = () => {
  451. if (states.inputValue.length > 0) {
  452. states.inputValue = "";
  453. } else {
  454. expanded.value = false;
  455. }
  456. };
  457. const getLastNotDisabledIndex = (value) => lodashUnified.findLastIndex(value, (it) => !states.cachedOptions.some((option) => getValue(option) === it && getDisabled(option)));
  458. const handleDel = (e) => {
  459. if (!props.multiple)
  460. return;
  461. if (e.code === aria.EVENT_CODE.delete)
  462. return;
  463. if (states.inputValue.length === 0) {
  464. e.preventDefault();
  465. const selected = props.modelValue.slice();
  466. const lastNotDisabledIndex = getLastNotDisabledIndex(selected);
  467. if (lastNotDisabledIndex < 0)
  468. return;
  469. const removeTagValue = selected[lastNotDisabledIndex];
  470. selected.splice(lastNotDisabledIndex, 1);
  471. const option = states.cachedOptions[lastNotDisabledIndex];
  472. states.cachedOptions.splice(lastNotDisabledIndex, 1);
  473. removeNewOption(option);
  474. update(selected);
  475. emit("remove-tag", removeTagValue);
  476. }
  477. };
  478. const handleClear = () => {
  479. let emptyValue;
  480. if (shared.isArray(props.modelValue)) {
  481. emptyValue = [];
  482. } else {
  483. emptyValue = valueOnClear.value;
  484. }
  485. states.selectedLabel = "";
  486. expanded.value = false;
  487. update(emptyValue);
  488. emit("clear");
  489. clearAllNewOption();
  490. focus();
  491. };
  492. const onKeyboardNavigate = (direction, hoveringIndex = void 0) => {
  493. const options = filteredOptions.value;
  494. if (!["forward", "backward"].includes(direction) || selectDisabled.value || options.length <= 0 || optionsAllDisabled.value || isComposing.value) {
  495. return;
  496. }
  497. if (!expanded.value) {
  498. return toggleMenu();
  499. }
  500. if (types.isUndefined(hoveringIndex)) {
  501. hoveringIndex = states.hoveringIndex;
  502. }
  503. let newIndex = -1;
  504. if (direction === "forward") {
  505. newIndex = hoveringIndex + 1;
  506. if (newIndex >= options.length) {
  507. newIndex = 0;
  508. }
  509. } else if (direction === "backward") {
  510. newIndex = hoveringIndex - 1;
  511. if (newIndex < 0 || newIndex >= options.length) {
  512. newIndex = options.length - 1;
  513. }
  514. }
  515. const option = options[newIndex];
  516. if (getDisabled(option) || option.type === "Group") {
  517. return onKeyboardNavigate(direction, newIndex);
  518. } else {
  519. states.hoveringIndex = newIndex;
  520. scrollToItem(newIndex);
  521. }
  522. };
  523. const onKeyboardSelect = () => {
  524. if (!expanded.value) {
  525. return toggleMenu();
  526. } else if (~states.hoveringIndex && filteredOptions.value[states.hoveringIndex]) {
  527. onSelect(filteredOptions.value[states.hoveringIndex]);
  528. }
  529. };
  530. const onHoverOption = (idx) => {
  531. states.hoveringIndex = idx != null ? idx : -1;
  532. };
  533. const updateHoveringIndex = () => {
  534. if (!props.multiple) {
  535. states.hoveringIndex = filteredOptions.value.findIndex((item) => {
  536. return getValueKey(getValue(item)) === getValueKey(props.modelValue);
  537. });
  538. } else {
  539. states.hoveringIndex = filteredOptions.value.findIndex((item) => props.modelValue.some((modelValue) => getValueKey(modelValue) === getValueKey(getValue(item))));
  540. }
  541. };
  542. const onInput = (event) => {
  543. states.inputValue = event.target.value;
  544. if (props.remote) {
  545. debouncedOnInputChange();
  546. } else {
  547. return onInputChange();
  548. }
  549. };
  550. const handleClickOutside = (event) => {
  551. expanded.value = false;
  552. if (isFocused.value) {
  553. const _event = new FocusEvent("blur", event);
  554. handleBlur(_event);
  555. }
  556. };
  557. const handleMenuEnter = () => {
  558. states.isBeforeHide = false;
  559. return vue.nextTick(() => {
  560. if (~indexRef.value) {
  561. scrollToItem(states.hoveringIndex);
  562. }
  563. });
  564. };
  565. const scrollToItem = (index) => {
  566. menuRef.value.scrollToItem(index);
  567. };
  568. const getOption = (value, cachedOptions) => {
  569. const selectValue = getValueKey(value);
  570. if (allOptionsValueMap.value.has(selectValue)) {
  571. const { option } = allOptionsValueMap.value.get(selectValue);
  572. return option;
  573. }
  574. if (cachedOptions && cachedOptions.length) {
  575. const option = cachedOptions.find((option2) => getValueKey(getValue(option2)) === selectValue);
  576. if (option) {
  577. return option;
  578. }
  579. }
  580. return {
  581. [aliasProps.value.value]: value,
  582. [aliasProps.value.label]: value
  583. };
  584. };
  585. const getIndex = (option) => {
  586. var _a, _b;
  587. return (_b = (_a = allOptionsValueMap.value.get(getValue(option))) == null ? void 0 : _a.index) != null ? _b : -1;
  588. };
  589. const initStates = (needUpdateSelectedLabel = false) => {
  590. if (props.multiple) {
  591. if (props.modelValue.length > 0) {
  592. const cachedOptions = states.cachedOptions.slice();
  593. states.cachedOptions.length = 0;
  594. states.previousValue = props.modelValue.toString();
  595. for (const value of props.modelValue) {
  596. const option = getOption(value, cachedOptions);
  597. states.cachedOptions.push(option);
  598. }
  599. } else {
  600. states.cachedOptions = [];
  601. states.previousValue = void 0;
  602. }
  603. } else {
  604. if (hasModelValue.value) {
  605. states.previousValue = props.modelValue;
  606. const options = filteredOptions.value;
  607. const selectedItemIndex = options.findIndex((option) => getValueKey(getValue(option)) === getValueKey(props.modelValue));
  608. if (~selectedItemIndex) {
  609. states.selectedLabel = getLabel(options[selectedItemIndex]);
  610. } else {
  611. if (!states.selectedLabel || needUpdateSelectedLabel) {
  612. states.selectedLabel = getValueKey(props.modelValue);
  613. }
  614. }
  615. } else {
  616. states.selectedLabel = "";
  617. states.previousValue = void 0;
  618. }
  619. }
  620. clearAllNewOption();
  621. calculatePopperSize();
  622. };
  623. vue.watch(() => props.fitInputWidth, () => {
  624. calculatePopperSize();
  625. });
  626. vue.watch(expanded, (val) => {
  627. if (val) {
  628. if (!props.persistent) {
  629. calculatePopperSize();
  630. }
  631. handleQueryChange("");
  632. } else {
  633. states.inputValue = "";
  634. states.previousQuery = null;
  635. states.isBeforeHide = true;
  636. createNewOption("");
  637. }
  638. emit("visible-change", val);
  639. });
  640. vue.watch(() => props.modelValue, (val, oldVal) => {
  641. var _a;
  642. const isValEmpty = !val || shared.isArray(val) && val.length === 0;
  643. if (isValEmpty || props.multiple && !lodashUnified.isEqual(val.toString(), states.previousValue) || !props.multiple && getValueKey(val) !== getValueKey(states.previousValue)) {
  644. initStates(true);
  645. }
  646. if (!lodashUnified.isEqual(val, oldVal) && props.validateEvent) {
  647. (_a = elFormItem == null ? void 0 : elFormItem.validate) == null ? void 0 : _a.call(elFormItem, "change").catch((err) => error.debugWarn());
  648. }
  649. }, {
  650. deep: true
  651. });
  652. vue.watch(() => props.options, () => {
  653. const input = inputRef.value;
  654. if (!input || input && document.activeElement !== input) {
  655. initStates();
  656. }
  657. }, {
  658. deep: true,
  659. flush: "post"
  660. });
  661. vue.watch(() => filteredOptions.value, () => {
  662. calculatePopperSize();
  663. return menuRef.value && vue.nextTick(menuRef.value.resetScrollTop);
  664. });
  665. vue.watchEffect(() => {
  666. if (states.isBeforeHide)
  667. return;
  668. updateOptions();
  669. });
  670. vue.watchEffect(() => {
  671. const { valueKey, options } = props;
  672. const duplicateValue = /* @__PURE__ */ new Map();
  673. for (const item of options) {
  674. const optionValue = getValue(item);
  675. let v = optionValue;
  676. if (shared.isObject(v)) {
  677. v = lodashUnified.get(optionValue, valueKey);
  678. }
  679. if (duplicateValue.get(v)) {
  680. break;
  681. } else {
  682. duplicateValue.set(v, true);
  683. }
  684. }
  685. });
  686. vue.onMounted(() => {
  687. initStates();
  688. });
  689. core.useResizeObserver(selectRef, handleResize);
  690. core.useResizeObserver(selectionRef, resetSelectionWidth);
  691. core.useResizeObserver(menuRef, updateTooltip);
  692. core.useResizeObserver(wrapperRef, updateTooltip);
  693. core.useResizeObserver(tagMenuRef, updateTagTooltip);
  694. core.useResizeObserver(collapseItemRef, resetCollapseItemWidth);
  695. return {
  696. inputId,
  697. collapseTagSize,
  698. currentPlaceholder,
  699. expanded,
  700. emptyText,
  701. popupHeight,
  702. debounce,
  703. allOptions,
  704. allOptionsValueMap,
  705. filteredOptions,
  706. iconComponent,
  707. iconReverse,
  708. tagStyle,
  709. collapseTagStyle,
  710. popperSize,
  711. dropdownMenuVisible,
  712. hasModelValue,
  713. shouldShowPlaceholder,
  714. selectDisabled,
  715. selectSize,
  716. needStatusIcon,
  717. showClearBtn,
  718. states,
  719. isFocused,
  720. nsSelect,
  721. nsInput,
  722. inputRef,
  723. menuRef,
  724. tagMenuRef,
  725. tooltipRef,
  726. tagTooltipRef,
  727. selectRef,
  728. wrapperRef,
  729. selectionRef,
  730. prefixRef,
  731. suffixRef,
  732. collapseItemRef,
  733. popperRef,
  734. validateState,
  735. validateIcon,
  736. showTagList,
  737. collapseTagList,
  738. debouncedOnInputChange,
  739. deleteTag,
  740. getLabel,
  741. getValue,
  742. getDisabled,
  743. getValueKey,
  744. getIndex,
  745. handleClear,
  746. handleClickOutside,
  747. handleDel,
  748. handleEsc,
  749. focus,
  750. blur,
  751. handleMenuEnter,
  752. handleResize,
  753. resetSelectionWidth,
  754. updateTooltip,
  755. updateTagTooltip,
  756. updateOptions,
  757. toggleMenu,
  758. scrollTo: scrollToItem,
  759. onInput,
  760. onKeyboardNavigate,
  761. onKeyboardSelect,
  762. onSelect,
  763. onHover: onHoverOption,
  764. handleCompositionStart,
  765. handleCompositionEnd,
  766. handleCompositionUpdate
  767. };
  768. };
  769. exports["default"] = useSelect;
  770. //# sourceMappingURL=useSelect.js.map