select.mjs 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. import { defineComponent, computed, reactive, toRefs, provide, resolveComponent, resolveDirective, withDirectives, openBlock, createElementBlock, normalizeClass, createVNode, withCtx, createElementVNode, withModifiers, renderSlot, createCommentVNode, Fragment, renderList, normalizeStyle, createTextVNode, toDisplayString, createBlock, withKeys, vModelText, resolveDynamicComponent, vShow, createSlots, normalizeProps, guardReactiveProps } from 'vue';
  2. import { ElTooltip } from '../../tooltip/index.mjs';
  3. import { ElTag } from '../../tag/index.mjs';
  4. import { ElIcon } from '../../icon/index.mjs';
  5. import ElSelectMenu from './select-dropdown.mjs';
  6. import useSelect from './useSelect.mjs';
  7. import { SelectProps, selectEmits } from './defaults.mjs';
  8. import { selectV2InjectionKey } from './token.mjs';
  9. import _export_sfc from '../../../_virtual/plugin-vue_export-helper.mjs';
  10. import ClickOutside from '../../../directives/click-outside/index.mjs';
  11. import { isArray } from '@vue/shared';
  12. import { useCalcInputWidth } from '../../../hooks/use-calc-input-width/index.mjs';
  13. const _sfc_main = defineComponent({
  14. name: "ElSelectV2",
  15. components: {
  16. ElSelectMenu,
  17. ElTag,
  18. ElTooltip,
  19. ElIcon
  20. },
  21. directives: { ClickOutside },
  22. props: SelectProps,
  23. emits: selectEmits,
  24. setup(props, { emit }) {
  25. const modelValue = computed(() => {
  26. const { modelValue: rawModelValue, multiple } = props;
  27. const fallback = multiple ? [] : void 0;
  28. if (isArray(rawModelValue)) {
  29. return multiple ? rawModelValue : fallback;
  30. }
  31. return multiple ? fallback : rawModelValue;
  32. });
  33. const API = useSelect(reactive({
  34. ...toRefs(props),
  35. modelValue
  36. }), emit);
  37. const { calculatorRef, inputStyle } = useCalcInputWidth();
  38. provide(selectV2InjectionKey, {
  39. props: reactive({
  40. ...toRefs(props),
  41. height: API.popupHeight,
  42. modelValue
  43. }),
  44. expanded: API.expanded,
  45. tooltipRef: API.tooltipRef,
  46. onSelect: API.onSelect,
  47. onHover: API.onHover,
  48. onKeyboardNavigate: API.onKeyboardNavigate,
  49. onKeyboardSelect: API.onKeyboardSelect
  50. });
  51. const selectedLabel = computed(() => {
  52. if (!props.multiple) {
  53. return API.states.selectedLabel;
  54. }
  55. return API.states.cachedOptions.map((i) => i.label);
  56. });
  57. return {
  58. ...API,
  59. modelValue,
  60. selectedLabel,
  61. calculatorRef,
  62. inputStyle
  63. };
  64. }
  65. });
  66. function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  67. const _component_el_tag = resolveComponent("el-tag");
  68. const _component_el_tooltip = resolveComponent("el-tooltip");
  69. const _component_el_icon = resolveComponent("el-icon");
  70. const _component_el_select_menu = resolveComponent("el-select-menu");
  71. const _directive_click_outside = resolveDirective("click-outside");
  72. return withDirectives((openBlock(), createElementBlock("div", {
  73. ref: "selectRef",
  74. class: normalizeClass([_ctx.nsSelect.b(), _ctx.nsSelect.m(_ctx.selectSize)]),
  75. onMouseenter: ($event) => _ctx.states.inputHovering = true,
  76. onMouseleave: ($event) => _ctx.states.inputHovering = false
  77. }, [
  78. createVNode(_component_el_tooltip, {
  79. ref: "tooltipRef",
  80. visible: _ctx.dropdownMenuVisible,
  81. teleported: _ctx.teleported,
  82. "popper-class": [_ctx.nsSelect.e("popper"), _ctx.popperClass],
  83. "gpu-acceleration": false,
  84. "stop-popper-mouse-event": false,
  85. "popper-options": _ctx.popperOptions,
  86. "fallback-placements": _ctx.fallbackPlacements,
  87. effect: _ctx.effect,
  88. placement: _ctx.placement,
  89. pure: "",
  90. transition: `${_ctx.nsSelect.namespace.value}-zoom-in-top`,
  91. trigger: "click",
  92. persistent: _ctx.persistent,
  93. "append-to": _ctx.appendTo,
  94. "show-arrow": _ctx.showArrow,
  95. offset: _ctx.offset,
  96. onBeforeShow: _ctx.handleMenuEnter,
  97. onHide: ($event) => _ctx.states.isBeforeHide = false
  98. }, {
  99. default: withCtx(() => [
  100. createElementVNode("div", {
  101. ref: "wrapperRef",
  102. class: normalizeClass([
  103. _ctx.nsSelect.e("wrapper"),
  104. _ctx.nsSelect.is("focused", _ctx.isFocused),
  105. _ctx.nsSelect.is("hovering", _ctx.states.inputHovering),
  106. _ctx.nsSelect.is("filterable", _ctx.filterable),
  107. _ctx.nsSelect.is("disabled", _ctx.selectDisabled)
  108. ]),
  109. onClick: withModifiers(_ctx.toggleMenu, ["prevent"])
  110. }, [
  111. _ctx.$slots.prefix ? (openBlock(), createElementBlock("div", {
  112. key: 0,
  113. ref: "prefixRef",
  114. class: normalizeClass(_ctx.nsSelect.e("prefix"))
  115. }, [
  116. renderSlot(_ctx.$slots, "prefix")
  117. ], 2)) : createCommentVNode("v-if", true),
  118. createElementVNode("div", {
  119. ref: "selectionRef",
  120. class: normalizeClass([
  121. _ctx.nsSelect.e("selection"),
  122. _ctx.nsSelect.is("near", _ctx.multiple && !_ctx.$slots.prefix && !!_ctx.modelValue.length)
  123. ])
  124. }, [
  125. _ctx.multiple ? renderSlot(_ctx.$slots, "tag", { key: 0 }, () => [
  126. (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.showTagList, (item) => {
  127. return openBlock(), createElementBlock("div", {
  128. key: _ctx.getValueKey(_ctx.getValue(item)),
  129. class: normalizeClass(_ctx.nsSelect.e("selected-item"))
  130. }, [
  131. createVNode(_component_el_tag, {
  132. closable: !_ctx.selectDisabled && !_ctx.getDisabled(item),
  133. size: _ctx.collapseTagSize,
  134. type: _ctx.tagType,
  135. effect: _ctx.tagEffect,
  136. "disable-transitions": "",
  137. style: normalizeStyle(_ctx.tagStyle),
  138. onClose: ($event) => _ctx.deleteTag($event, item)
  139. }, {
  140. default: withCtx(() => [
  141. createElementVNode("span", {
  142. class: normalizeClass(_ctx.nsSelect.e("tags-text"))
  143. }, [
  144. renderSlot(_ctx.$slots, "label", {
  145. label: _ctx.getLabel(item),
  146. value: _ctx.getValue(item)
  147. }, () => [
  148. createTextVNode(toDisplayString(_ctx.getLabel(item)), 1)
  149. ])
  150. ], 2)
  151. ]),
  152. _: 2
  153. }, 1032, ["closable", "size", "type", "effect", "style", "onClose"])
  154. ], 2);
  155. }), 128)),
  156. _ctx.collapseTags && _ctx.modelValue.length > _ctx.maxCollapseTags ? (openBlock(), createBlock(_component_el_tooltip, {
  157. key: 0,
  158. ref: "tagTooltipRef",
  159. disabled: _ctx.dropdownMenuVisible || !_ctx.collapseTagsTooltip,
  160. "fallback-placements": ["bottom", "top", "right", "left"],
  161. effect: _ctx.effect,
  162. placement: "bottom",
  163. teleported: _ctx.teleported
  164. }, {
  165. default: withCtx(() => [
  166. createElementVNode("div", {
  167. ref: "collapseItemRef",
  168. class: normalizeClass(_ctx.nsSelect.e("selected-item"))
  169. }, [
  170. createVNode(_component_el_tag, {
  171. closable: false,
  172. size: _ctx.collapseTagSize,
  173. type: _ctx.tagType,
  174. effect: _ctx.tagEffect,
  175. style: normalizeStyle(_ctx.collapseTagStyle),
  176. "disable-transitions": ""
  177. }, {
  178. default: withCtx(() => [
  179. createElementVNode("span", {
  180. class: normalizeClass(_ctx.nsSelect.e("tags-text"))
  181. }, " + " + toDisplayString(_ctx.modelValue.length - _ctx.maxCollapseTags), 3)
  182. ]),
  183. _: 1
  184. }, 8, ["size", "type", "effect", "style"])
  185. ], 2)
  186. ]),
  187. content: withCtx(() => [
  188. createElementVNode("div", {
  189. ref: "tagMenuRef",
  190. class: normalizeClass(_ctx.nsSelect.e("selection"))
  191. }, [
  192. (openBlock(true), createElementBlock(Fragment, null, renderList(_ctx.collapseTagList, (selected) => {
  193. return openBlock(), createElementBlock("div", {
  194. key: _ctx.getValueKey(_ctx.getValue(selected)),
  195. class: normalizeClass(_ctx.nsSelect.e("selected-item"))
  196. }, [
  197. createVNode(_component_el_tag, {
  198. class: "in-tooltip",
  199. closable: !_ctx.selectDisabled && !_ctx.getDisabled(selected),
  200. size: _ctx.collapseTagSize,
  201. type: _ctx.tagType,
  202. effect: _ctx.tagEffect,
  203. "disable-transitions": "",
  204. onClose: ($event) => _ctx.deleteTag($event, selected)
  205. }, {
  206. default: withCtx(() => [
  207. createElementVNode("span", {
  208. class: normalizeClass(_ctx.nsSelect.e("tags-text"))
  209. }, [
  210. renderSlot(_ctx.$slots, "label", {
  211. label: _ctx.getLabel(selected),
  212. value: _ctx.getValue(selected)
  213. }, () => [
  214. createTextVNode(toDisplayString(_ctx.getLabel(selected)), 1)
  215. ])
  216. ], 2)
  217. ]),
  218. _: 2
  219. }, 1032, ["closable", "size", "type", "effect", "onClose"])
  220. ], 2);
  221. }), 128))
  222. ], 2)
  223. ]),
  224. _: 3
  225. }, 8, ["disabled", "effect", "teleported"])) : createCommentVNode("v-if", true)
  226. ]) : createCommentVNode("v-if", true),
  227. createElementVNode("div", {
  228. class: normalizeClass([
  229. _ctx.nsSelect.e("selected-item"),
  230. _ctx.nsSelect.e("input-wrapper"),
  231. _ctx.nsSelect.is("hidden", !_ctx.filterable)
  232. ])
  233. }, [
  234. withDirectives(createElementVNode("input", {
  235. id: _ctx.inputId,
  236. ref: "inputRef",
  237. "onUpdate:modelValue": ($event) => _ctx.states.inputValue = $event,
  238. style: normalizeStyle(_ctx.inputStyle),
  239. autocomplete: _ctx.autocomplete,
  240. tabindex: _ctx.tabindex,
  241. "aria-autocomplete": "list",
  242. "aria-haspopup": "listbox",
  243. autocapitalize: "off",
  244. "aria-expanded": _ctx.expanded,
  245. "aria-label": _ctx.ariaLabel,
  246. class: normalizeClass([_ctx.nsSelect.e("input"), _ctx.nsSelect.is(_ctx.selectSize)]),
  247. disabled: _ctx.selectDisabled,
  248. role: "combobox",
  249. readonly: !_ctx.filterable,
  250. spellcheck: "false",
  251. type: "text",
  252. name: _ctx.name,
  253. onInput: _ctx.onInput,
  254. onCompositionstart: _ctx.handleCompositionStart,
  255. onCompositionupdate: _ctx.handleCompositionUpdate,
  256. onCompositionend: _ctx.handleCompositionEnd,
  257. onKeydown: [
  258. withKeys(withModifiers(($event) => _ctx.onKeyboardNavigate("backward"), ["stop", "prevent"]), ["up"]),
  259. withKeys(withModifiers(($event) => _ctx.onKeyboardNavigate("forward"), ["stop", "prevent"]), ["down"]),
  260. withKeys(withModifiers(_ctx.onKeyboardSelect, ["stop", "prevent"]), ["enter"]),
  261. withKeys(withModifiers(_ctx.handleEsc, ["stop", "prevent"]), ["esc"]),
  262. withKeys(withModifiers(_ctx.handleDel, ["stop"]), ["delete"])
  263. ],
  264. onClick: withModifiers(_ctx.toggleMenu, ["stop"])
  265. }, null, 46, ["id", "onUpdate:modelValue", "autocomplete", "tabindex", "aria-expanded", "aria-label", "disabled", "readonly", "name", "onInput", "onCompositionstart", "onCompositionupdate", "onCompositionend", "onKeydown", "onClick"]), [
  266. [vModelText, _ctx.states.inputValue]
  267. ]),
  268. _ctx.filterable ? (openBlock(), createElementBlock("span", {
  269. key: 0,
  270. ref: "calculatorRef",
  271. "aria-hidden": "true",
  272. class: normalizeClass(_ctx.nsSelect.e("input-calculator")),
  273. textContent: toDisplayString(_ctx.states.inputValue)
  274. }, null, 10, ["textContent"])) : createCommentVNode("v-if", true)
  275. ], 2),
  276. _ctx.shouldShowPlaceholder ? (openBlock(), createElementBlock("div", {
  277. key: 1,
  278. class: normalizeClass([
  279. _ctx.nsSelect.e("selected-item"),
  280. _ctx.nsSelect.e("placeholder"),
  281. _ctx.nsSelect.is("transparent", !_ctx.hasModelValue || _ctx.expanded && !_ctx.states.inputValue)
  282. ])
  283. }, [
  284. _ctx.hasModelValue ? renderSlot(_ctx.$slots, "label", {
  285. key: 0,
  286. label: _ctx.currentPlaceholder,
  287. value: _ctx.modelValue
  288. }, () => [
  289. createElementVNode("span", null, toDisplayString(_ctx.currentPlaceholder), 1)
  290. ]) : (openBlock(), createElementBlock("span", { key: 1 }, toDisplayString(_ctx.currentPlaceholder), 1))
  291. ], 2)) : createCommentVNode("v-if", true)
  292. ], 2),
  293. createElementVNode("div", {
  294. ref: "suffixRef",
  295. class: normalizeClass(_ctx.nsSelect.e("suffix"))
  296. }, [
  297. _ctx.iconComponent ? withDirectives((openBlock(), createBlock(_component_el_icon, {
  298. key: 0,
  299. class: normalizeClass([_ctx.nsSelect.e("caret"), _ctx.nsInput.e("icon"), _ctx.iconReverse])
  300. }, {
  301. default: withCtx(() => [
  302. (openBlock(), createBlock(resolveDynamicComponent(_ctx.iconComponent)))
  303. ]),
  304. _: 1
  305. }, 8, ["class"])), [
  306. [vShow, !_ctx.showClearBtn]
  307. ]) : createCommentVNode("v-if", true),
  308. _ctx.showClearBtn && _ctx.clearIcon ? (openBlock(), createBlock(_component_el_icon, {
  309. key: 1,
  310. class: normalizeClass([
  311. _ctx.nsSelect.e("caret"),
  312. _ctx.nsInput.e("icon"),
  313. _ctx.nsSelect.e("clear")
  314. ]),
  315. onClick: withModifiers(_ctx.handleClear, ["prevent", "stop"])
  316. }, {
  317. default: withCtx(() => [
  318. (openBlock(), createBlock(resolveDynamicComponent(_ctx.clearIcon)))
  319. ]),
  320. _: 1
  321. }, 8, ["class", "onClick"])) : createCommentVNode("v-if", true),
  322. _ctx.validateState && _ctx.validateIcon && _ctx.needStatusIcon ? (openBlock(), createBlock(_component_el_icon, {
  323. key: 2,
  324. class: normalizeClass([
  325. _ctx.nsInput.e("icon"),
  326. _ctx.nsInput.e("validateIcon"),
  327. _ctx.nsInput.is("loading", _ctx.validateState === "validating")
  328. ])
  329. }, {
  330. default: withCtx(() => [
  331. (openBlock(), createBlock(resolveDynamicComponent(_ctx.validateIcon)))
  332. ]),
  333. _: 1
  334. }, 8, ["class"])) : createCommentVNode("v-if", true)
  335. ], 2)
  336. ], 10, ["onClick"])
  337. ]),
  338. content: withCtx(() => [
  339. createVNode(_component_el_select_menu, {
  340. ref: "menuRef",
  341. data: _ctx.filteredOptions,
  342. width: _ctx.popperSize,
  343. "hovering-index": _ctx.states.hoveringIndex,
  344. "scrollbar-always-on": _ctx.scrollbarAlwaysOn
  345. }, createSlots({
  346. default: withCtx((scope) => [
  347. renderSlot(_ctx.$slots, "default", normalizeProps(guardReactiveProps(scope)))
  348. ]),
  349. _: 2
  350. }, [
  351. _ctx.$slots.header ? {
  352. name: "header",
  353. fn: withCtx(() => [
  354. createElementVNode("div", {
  355. class: normalizeClass(_ctx.nsSelect.be("dropdown", "header"))
  356. }, [
  357. renderSlot(_ctx.$slots, "header")
  358. ], 2)
  359. ])
  360. } : void 0,
  361. _ctx.$slots.loading && _ctx.loading ? {
  362. name: "loading",
  363. fn: withCtx(() => [
  364. createElementVNode("div", {
  365. class: normalizeClass(_ctx.nsSelect.be("dropdown", "loading"))
  366. }, [
  367. renderSlot(_ctx.$slots, "loading")
  368. ], 2)
  369. ])
  370. } : _ctx.loading || _ctx.filteredOptions.length === 0 ? {
  371. name: "empty",
  372. fn: withCtx(() => [
  373. createElementVNode("div", {
  374. class: normalizeClass(_ctx.nsSelect.be("dropdown", "empty"))
  375. }, [
  376. renderSlot(_ctx.$slots, "empty", {}, () => [
  377. createElementVNode("span", null, toDisplayString(_ctx.emptyText), 1)
  378. ])
  379. ], 2)
  380. ])
  381. } : void 0,
  382. _ctx.$slots.footer ? {
  383. name: "footer",
  384. fn: withCtx(() => [
  385. createElementVNode("div", {
  386. class: normalizeClass(_ctx.nsSelect.be("dropdown", "footer"))
  387. }, [
  388. renderSlot(_ctx.$slots, "footer")
  389. ], 2)
  390. ])
  391. } : void 0
  392. ]), 1032, ["data", "width", "hovering-index", "scrollbar-always-on"])
  393. ]),
  394. _: 3
  395. }, 8, ["visible", "teleported", "popper-class", "popper-options", "fallback-placements", "effect", "placement", "transition", "persistent", "append-to", "show-arrow", "offset", "onBeforeShow", "onHide"])
  396. ], 42, ["onMouseenter", "onMouseleave"])), [
  397. [_directive_click_outside, _ctx.handleClickOutside, _ctx.popperRef]
  398. ]);
  399. }
  400. var Select = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render], ["__file", "select.vue"]]);
  401. export { Select as default };
  402. //# sourceMappingURL=select.mjs.map