OptionList.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  2. import _extends from "@babel/runtime/helpers/esm/extends";
  3. import { resolveDirective as _resolveDirective, createVNode as _createVNode } from "vue";
  4. import { computed, defineComponent, nextTick, ref, shallowRef, toRaw, watch } from 'vue';
  5. import useMemo from '../_util/hooks/useMemo';
  6. import KeyCode from '../_util/KeyCode';
  7. import Tree from '../vc-tree/Tree';
  8. import { getAllKeys, isCheckDisabled } from './utils/valueUtil';
  9. import { useBaseProps } from '../vc-select';
  10. import useInjectLegacySelectContext from './LegacyContext';
  11. import useInjectSelectContext from './TreeSelectContext';
  12. const HIDDEN_STYLE = {
  13. width: 0,
  14. height: 0,
  15. display: 'flex',
  16. overflow: 'hidden',
  17. opacity: 0,
  18. border: 0,
  19. padding: 0,
  20. margin: 0
  21. };
  22. export default defineComponent({
  23. compatConfig: {
  24. MODE: 3
  25. },
  26. name: 'OptionList',
  27. inheritAttrs: false,
  28. setup(_, _ref) {
  29. let {
  30. slots,
  31. expose
  32. } = _ref;
  33. const baseProps = useBaseProps();
  34. const legacyContext = useInjectLegacySelectContext();
  35. const context = useInjectSelectContext();
  36. const treeRef = ref();
  37. const memoTreeData = useMemo(() => context.treeData, [() => baseProps.open, () => context.treeData], next => next[0]);
  38. const mergedCheckedKeys = computed(() => {
  39. const {
  40. checkable,
  41. halfCheckedKeys,
  42. checkedKeys
  43. } = legacyContext;
  44. if (!checkable) {
  45. return null;
  46. }
  47. return {
  48. checked: checkedKeys,
  49. halfChecked: halfCheckedKeys
  50. };
  51. });
  52. watch(() => baseProps.open, () => {
  53. nextTick(() => {
  54. var _a;
  55. if (baseProps.open && !baseProps.multiple && legacyContext.checkedKeys.length) {
  56. (_a = treeRef.value) === null || _a === void 0 ? void 0 : _a.scrollTo({
  57. key: legacyContext.checkedKeys[0]
  58. });
  59. }
  60. });
  61. }, {
  62. immediate: true,
  63. flush: 'post'
  64. });
  65. // ========================== Search ==========================
  66. const lowerSearchValue = computed(() => String(baseProps.searchValue).toLowerCase());
  67. const filterTreeNode = treeNode => {
  68. if (!lowerSearchValue.value) {
  69. return false;
  70. }
  71. return String(treeNode[legacyContext.treeNodeFilterProp]).toLowerCase().includes(lowerSearchValue.value);
  72. };
  73. // =========================== Keys ===========================
  74. const expandedKeys = shallowRef(legacyContext.treeDefaultExpandedKeys);
  75. const searchExpandedKeys = shallowRef(null);
  76. watch(() => baseProps.searchValue, () => {
  77. if (baseProps.searchValue) {
  78. searchExpandedKeys.value = getAllKeys(toRaw(context.treeData), toRaw(context.fieldNames));
  79. }
  80. }, {
  81. immediate: true
  82. });
  83. const mergedExpandedKeys = computed(() => {
  84. if (legacyContext.treeExpandedKeys) {
  85. return legacyContext.treeExpandedKeys.slice();
  86. }
  87. return baseProps.searchValue ? searchExpandedKeys.value : expandedKeys.value;
  88. });
  89. const onInternalExpand = keys => {
  90. var _a;
  91. expandedKeys.value = keys;
  92. searchExpandedKeys.value = keys;
  93. (_a = legacyContext.onTreeExpand) === null || _a === void 0 ? void 0 : _a.call(legacyContext, keys);
  94. };
  95. // ========================== Events ==========================
  96. const onListMouseDown = event => {
  97. event.preventDefault();
  98. };
  99. const onInternalSelect = (_, _ref2) => {
  100. let {
  101. node
  102. } = _ref2;
  103. var _a, _b;
  104. const {
  105. checkable,
  106. checkedKeys
  107. } = legacyContext;
  108. if (checkable && isCheckDisabled(node)) {
  109. return;
  110. }
  111. (_a = context.onSelect) === null || _a === void 0 ? void 0 : _a.call(context, node.key, {
  112. selected: !checkedKeys.includes(node.key)
  113. });
  114. if (!baseProps.multiple) {
  115. (_b = baseProps.toggleOpen) === null || _b === void 0 ? void 0 : _b.call(baseProps, false);
  116. }
  117. };
  118. // ========================= Keyboard =========================
  119. const activeKey = ref(null);
  120. const activeEntity = computed(() => legacyContext.keyEntities[activeKey.value]);
  121. const setActiveKey = key => {
  122. activeKey.value = key;
  123. };
  124. expose({
  125. scrollTo: function () {
  126. var _a, _b;
  127. for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
  128. args[_key] = arguments[_key];
  129. }
  130. return (_b = (_a = treeRef.value) === null || _a === void 0 ? void 0 : _a.scrollTo) === null || _b === void 0 ? void 0 : _b.call(_a, ...args);
  131. },
  132. onKeydown: event => {
  133. var _a;
  134. const {
  135. which
  136. } = event;
  137. switch (which) {
  138. // >>> Arrow keys
  139. case KeyCode.UP:
  140. case KeyCode.DOWN:
  141. case KeyCode.LEFT:
  142. case KeyCode.RIGHT:
  143. (_a = treeRef.value) === null || _a === void 0 ? void 0 : _a.onKeydown(event);
  144. break;
  145. // >>> Select item
  146. case KeyCode.ENTER:
  147. {
  148. if (activeEntity.value) {
  149. const {
  150. selectable,
  151. value
  152. } = activeEntity.value.node || {};
  153. if (selectable !== false) {
  154. onInternalSelect(null, {
  155. node: {
  156. key: activeKey.value
  157. },
  158. selected: !legacyContext.checkedKeys.includes(value)
  159. });
  160. }
  161. }
  162. break;
  163. }
  164. // >>> Close
  165. case KeyCode.ESC:
  166. {
  167. baseProps.toggleOpen(false);
  168. }
  169. }
  170. },
  171. onKeyup: () => {}
  172. });
  173. return () => {
  174. var _a;
  175. const {
  176. prefixCls,
  177. multiple,
  178. searchValue,
  179. open,
  180. notFoundContent = (_a = slots.notFoundContent) === null || _a === void 0 ? void 0 : _a.call(slots)
  181. } = baseProps;
  182. const {
  183. listHeight,
  184. listItemHeight,
  185. virtual,
  186. dropdownMatchSelectWidth,
  187. treeExpandAction
  188. } = context;
  189. const {
  190. checkable,
  191. treeDefaultExpandAll,
  192. treeIcon,
  193. showTreeIcon,
  194. switcherIcon,
  195. treeLine,
  196. loadData,
  197. treeLoadedKeys,
  198. treeMotion,
  199. onTreeLoad,
  200. checkedKeys
  201. } = legacyContext;
  202. // ========================== Render ==========================
  203. if (memoTreeData.value.length === 0) {
  204. return _createVNode("div", {
  205. "role": "listbox",
  206. "class": `${prefixCls}-empty`,
  207. "onMousedown": onListMouseDown
  208. }, [notFoundContent]);
  209. }
  210. const treeProps = {
  211. fieldNames: context.fieldNames
  212. };
  213. if (treeLoadedKeys) {
  214. treeProps.loadedKeys = treeLoadedKeys;
  215. }
  216. if (mergedExpandedKeys.value) {
  217. treeProps.expandedKeys = mergedExpandedKeys.value;
  218. }
  219. return _createVNode("div", {
  220. "onMousedown": onListMouseDown
  221. }, [activeEntity.value && open && _createVNode("span", {
  222. "style": HIDDEN_STYLE,
  223. "aria-live": "assertive"
  224. }, [activeEntity.value.node.value]), _createVNode(Tree, _objectSpread(_objectSpread({
  225. "ref": treeRef,
  226. "focusable": false,
  227. "prefixCls": `${prefixCls}-tree`,
  228. "treeData": memoTreeData.value,
  229. "height": listHeight,
  230. "itemHeight": listItemHeight,
  231. "virtual": virtual !== false && dropdownMatchSelectWidth !== false,
  232. "multiple": multiple,
  233. "icon": treeIcon,
  234. "showIcon": showTreeIcon,
  235. "switcherIcon": switcherIcon,
  236. "showLine": treeLine,
  237. "loadData": searchValue ? null : loadData,
  238. "motion": treeMotion,
  239. "activeKey": activeKey.value,
  240. "checkable": checkable,
  241. "checkStrictly": true,
  242. "checkedKeys": mergedCheckedKeys.value,
  243. "selectedKeys": !checkable ? checkedKeys : [],
  244. "defaultExpandAll": treeDefaultExpandAll
  245. }, treeProps), {}, {
  246. "onActiveChange": setActiveKey,
  247. "onSelect": onInternalSelect,
  248. "onCheck": onInternalSelect,
  249. "onExpand": onInternalExpand,
  250. "onLoad": onTreeLoad,
  251. "filterTreeNode": filterTreeNode,
  252. "expandAction": treeExpandAction
  253. }), _extends(_extends({}, slots), {
  254. checkable: legacyContext.customSlots.treeCheckable
  255. }))]);
  256. };
  257. }
  258. });