select-dropdown.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var lodashUnified = require('lodash-unified');
  5. var groupItem = require('./group-item.js');
  6. var optionItem = require('./option-item.js');
  7. var useProps = require('./useProps.js');
  8. var token = require('./token.js');
  9. var fixedSizeList = require('../../virtual-list/src/components/fixed-size-list.js');
  10. var dynamicSizeList = require('../../virtual-list/src/components/dynamic-size-list.js');
  11. var index = require('../../../hooks/use-namespace/index.js');
  12. var types = require('../../../utils/types.js');
  13. var core = require('@vueuse/core');
  14. var event = require('../../../utils/dom/event.js');
  15. var aria = require('../../../constants/aria.js');
  16. var shared = require('@vue/shared');
  17. const props = {
  18. loading: Boolean,
  19. data: {
  20. type: Array,
  21. required: true
  22. },
  23. hoveringIndex: Number,
  24. width: Number,
  25. id: String,
  26. ariaLabel: String
  27. };
  28. var ElSelectMenu = vue.defineComponent({
  29. name: "ElSelectDropdown",
  30. props,
  31. setup(props2, {
  32. slots,
  33. expose
  34. }) {
  35. const select = vue.inject(token.selectV2InjectionKey);
  36. const ns = index.useNamespace("select");
  37. const {
  38. getLabel,
  39. getValue,
  40. getDisabled
  41. } = useProps.useProps(select.props);
  42. const cachedHeights = vue.ref([]);
  43. const listRef = vue.ref();
  44. const size = vue.computed(() => props2.data.length);
  45. vue.watch(() => size.value, () => {
  46. var _a, _b;
  47. (_b = (_a = select.tooltipRef.value) == null ? void 0 : _a.updatePopper) == null ? void 0 : _b.call(_a);
  48. });
  49. const isSized = vue.computed(() => types.isUndefined(select.props.estimatedOptionHeight));
  50. const listProps = vue.computed(() => {
  51. if (isSized.value) {
  52. return {
  53. itemSize: select.props.itemHeight
  54. };
  55. }
  56. return {
  57. estimatedSize: select.props.estimatedOptionHeight,
  58. itemSize: (idx) => cachedHeights.value[idx]
  59. };
  60. });
  61. const contains = (arr = [], target) => {
  62. const {
  63. props: {
  64. valueKey
  65. }
  66. } = select;
  67. if (!shared.isObject(target)) {
  68. return arr.includes(target);
  69. }
  70. return arr && arr.some((item) => {
  71. return vue.toRaw(lodashUnified.get(item, valueKey)) === lodashUnified.get(target, valueKey);
  72. });
  73. };
  74. const isEqual = (selected, target) => {
  75. if (!shared.isObject(target)) {
  76. return selected === target;
  77. } else {
  78. const {
  79. valueKey
  80. } = select.props;
  81. return lodashUnified.get(selected, valueKey) === lodashUnified.get(target, valueKey);
  82. }
  83. };
  84. const isItemSelected = (modelValue, target) => {
  85. if (select.props.multiple) {
  86. return contains(modelValue, getValue(target));
  87. }
  88. return isEqual(modelValue, getValue(target));
  89. };
  90. const isItemDisabled = (modelValue, selected) => {
  91. const {
  92. disabled,
  93. multiple,
  94. multipleLimit
  95. } = select.props;
  96. return disabled || !selected && (multiple ? multipleLimit > 0 && modelValue.length >= multipleLimit : false);
  97. };
  98. const isItemHovering = (target) => props2.hoveringIndex === target;
  99. const scrollToItem = (index) => {
  100. const list = listRef.value;
  101. if (list) {
  102. list.scrollToItem(index);
  103. }
  104. };
  105. const resetScrollTop = () => {
  106. const list = listRef.value;
  107. if (list) {
  108. list.resetScrollTop();
  109. }
  110. };
  111. const exposed = {
  112. listRef,
  113. isSized,
  114. isItemDisabled,
  115. isItemHovering,
  116. isItemSelected,
  117. scrollToItem,
  118. resetScrollTop
  119. };
  120. expose(exposed);
  121. const Item = (itemProps) => {
  122. const {
  123. index,
  124. data,
  125. style
  126. } = itemProps;
  127. const sized = vue.unref(isSized);
  128. const {
  129. itemSize,
  130. estimatedSize
  131. } = vue.unref(listProps);
  132. const {
  133. modelValue
  134. } = select.props;
  135. const {
  136. onSelect,
  137. onHover
  138. } = select;
  139. const item = data[index];
  140. if (item.type === "Group") {
  141. return vue.createVNode(groupItem["default"], {
  142. "item": item,
  143. "style": style,
  144. "height": sized ? itemSize : estimatedSize
  145. }, null);
  146. }
  147. const isSelected = isItemSelected(modelValue, item);
  148. const isDisabled = isItemDisabled(modelValue, isSelected);
  149. const isHovering = isItemHovering(index);
  150. return vue.createVNode(optionItem["default"], vue.mergeProps(itemProps, {
  151. "selected": isSelected,
  152. "disabled": getDisabled(item) || isDisabled,
  153. "created": !!item.created,
  154. "hovering": isHovering,
  155. "item": item,
  156. "onSelect": onSelect,
  157. "onHover": onHover
  158. }), {
  159. default: (props3) => {
  160. var _a;
  161. return ((_a = slots.default) == null ? void 0 : _a.call(slots, props3)) || vue.createVNode("span", null, [getLabel(item)]);
  162. }
  163. });
  164. };
  165. const {
  166. onKeyboardNavigate,
  167. onKeyboardSelect
  168. } = select;
  169. const onForward = () => {
  170. onKeyboardNavigate("forward");
  171. };
  172. const onBackward = () => {
  173. onKeyboardNavigate("backward");
  174. };
  175. const onKeydown = (e) => {
  176. const code = event.getEventCode(e);
  177. const {
  178. tab,
  179. esc,
  180. down,
  181. up,
  182. enter,
  183. numpadEnter
  184. } = aria.EVENT_CODE;
  185. if ([esc, down, up, enter, numpadEnter].includes(code)) {
  186. e.preventDefault();
  187. e.stopPropagation();
  188. }
  189. switch (code) {
  190. case tab:
  191. case esc:
  192. break;
  193. case down:
  194. onForward();
  195. break;
  196. case up:
  197. onBackward();
  198. break;
  199. case enter:
  200. case numpadEnter:
  201. onKeyboardSelect();
  202. break;
  203. }
  204. };
  205. return () => {
  206. var _a, _b, _c, _d;
  207. const {
  208. data,
  209. width
  210. } = props2;
  211. const {
  212. height,
  213. multiple,
  214. scrollbarAlwaysOn
  215. } = select.props;
  216. const isScrollbarAlwaysOn = vue.computed(() => {
  217. return core.isIOS ? true : scrollbarAlwaysOn;
  218. });
  219. const List = vue.unref(isSized) ? fixedSizeList["default"] : dynamicSizeList["default"];
  220. return vue.createVNode("div", {
  221. "class": [ns.b("dropdown"), ns.is("multiple", multiple)],
  222. "style": {
  223. width: `${width}px`
  224. }
  225. }, [(_a = slots.header) == null ? void 0 : _a.call(slots), ((_b = slots.loading) == null ? void 0 : _b.call(slots)) || ((_c = slots.empty) == null ? void 0 : _c.call(slots)) || vue.createVNode(List, vue.mergeProps({
  226. "ref": listRef
  227. }, vue.unref(listProps), {
  228. "className": ns.be("dropdown", "list"),
  229. "scrollbarAlwaysOn": isScrollbarAlwaysOn.value,
  230. "data": data,
  231. "height": height,
  232. "width": width,
  233. "total": data.length,
  234. "innerElement": "ul",
  235. "innerProps": {
  236. id: props2.id,
  237. role: "listbox",
  238. "aria-label": props2.ariaLabel,
  239. "aria-orientation": "vertical"
  240. },
  241. "onKeydown": onKeydown
  242. }), {
  243. default: (props3) => vue.createVNode(Item, props3, null)
  244. }), (_d = slots.footer) == null ? void 0 : _d.call(slots)]);
  245. };
  246. }
  247. });
  248. exports["default"] = ElSelectMenu;
  249. //# sourceMappingURL=select-dropdown.js.map