e7e3fb691823447d8bf3b3ac7e6d84ae991871d33f09b987bff57adeb369a25aa53d772dab303d3141e8c552efbc03011afd33afe55cc1a792f55f25765bb3 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. 'use strict';
  2. Object.defineProperty(exports, '__esModule', { value: true });
  3. var vue = require('vue');
  4. var lodashUnified = require('lodash-unified');
  5. var menu = require('./menu.js');
  6. var store = require('./store.js');
  7. var node = require('./node.js');
  8. var config = require('./config.js');
  9. var utils = require('./utils.js');
  10. var types = require('./types.js');
  11. var pluginVue_exportHelper = require('../../../_virtual/plugin-vue_export-helper.js');
  12. var arrays = require('../../../utils/arrays.js');
  13. var scroll = require('../../../utils/dom/scroll.js');
  14. var aria$1 = require('../../../utils/dom/aria.js');
  15. var index = require('../../../hooks/use-namespace/index.js');
  16. var event = require('../../../constants/event.js');
  17. var types$1 = require('../../../utils/types.js');
  18. var core = require('@vueuse/core');
  19. var aria = require('../../../constants/aria.js');
  20. const __default__ = vue.defineComponent({
  21. name: "ElCascaderPanel",
  22. inheritAttrs: false
  23. });
  24. const _sfc_main = /* @__PURE__ */ vue.defineComponent({
  25. ...__default__,
  26. props: config.cascaderPanelProps,
  27. emits: config.cascaderPanelEmits,
  28. setup(__props, { expose, emit }) {
  29. const props = __props;
  30. let manualChecked = false;
  31. const ns = index.useNamespace("cascader");
  32. const config$1 = config.useCascaderConfig(props);
  33. const slots = vue.useSlots();
  34. let store$1;
  35. const initialLoaded = vue.ref(true);
  36. const menuList = vue.ref([]);
  37. const checkedValue = vue.ref();
  38. const menus = vue.ref([]);
  39. const expandingNode = vue.ref();
  40. const checkedNodes = vue.ref([]);
  41. const isHoverMenu = vue.computed(() => config$1.value.expandTrigger === "hover");
  42. const renderLabelFn = vue.computed(() => props.renderLabel || slots.default);
  43. const initStore = () => {
  44. const { options } = props;
  45. const cfg = config$1.value;
  46. manualChecked = false;
  47. store$1 = new store["default"](options, cfg);
  48. menus.value = [store$1.getNodes()];
  49. if (cfg.lazy && types$1.isEmpty(props.options)) {
  50. initialLoaded.value = false;
  51. lazyLoad(void 0, (list) => {
  52. if (list) {
  53. store$1 = new store["default"](list, cfg);
  54. menus.value = [store$1.getNodes()];
  55. }
  56. initialLoaded.value = true;
  57. syncCheckedValue(false, true);
  58. });
  59. } else {
  60. syncCheckedValue(false, true);
  61. }
  62. };
  63. const lazyLoad = (node$1, cb) => {
  64. const cfg = config$1.value;
  65. node$1 = node$1 || new node["default"]({}, cfg, void 0, true);
  66. node$1.loading = true;
  67. const resolve = (dataList) => {
  68. const _node = node$1;
  69. const parent = _node.root ? null : _node;
  70. _node.loading = false;
  71. _node.loaded = true;
  72. _node.childrenData = _node.childrenData || [];
  73. dataList && (store$1 == null ? void 0 : store$1.appendNodes(dataList, parent));
  74. dataList && (cb == null ? void 0 : cb(dataList));
  75. };
  76. cfg.lazyLoad(node$1, resolve);
  77. };
  78. const expandNode = (node, silent) => {
  79. var _a;
  80. const { level } = node;
  81. const newMenus = menus.value.slice(0, level);
  82. let newExpandingNode;
  83. if (node.isLeaf) {
  84. newExpandingNode = node.pathNodes[level - 2];
  85. } else {
  86. newExpandingNode = node;
  87. newMenus.push(node.children);
  88. }
  89. if (((_a = expandingNode.value) == null ? void 0 : _a.uid) !== (newExpandingNode == null ? void 0 : newExpandingNode.uid)) {
  90. expandingNode.value = node;
  91. menus.value = newMenus;
  92. !silent && emit("expand-change", (node == null ? void 0 : node.pathValues) || []);
  93. }
  94. };
  95. const handleCheckChange = (node, checked, emitClose = true) => {
  96. const { checkStrictly, multiple } = config$1.value;
  97. const oldNode = checkedNodes.value[0];
  98. manualChecked = true;
  99. !multiple && (oldNode == null ? void 0 : oldNode.doCheck(false));
  100. node.doCheck(checked);
  101. calculateCheckedValue();
  102. emitClose && !multiple && !checkStrictly && emit("close");
  103. !emitClose && !multiple && !checkStrictly && expandParentNode(node);
  104. };
  105. const expandParentNode = (node) => {
  106. if (!node)
  107. return;
  108. node = node.parent;
  109. expandParentNode(node);
  110. node && expandNode(node);
  111. };
  112. const getFlattedNodes = (leafOnly) => store$1 == null ? void 0 : store$1.getFlattedNodes(leafOnly);
  113. const getCheckedNodes = (leafOnly) => {
  114. var _a;
  115. return (_a = getFlattedNodes(leafOnly)) == null ? void 0 : _a.filter(({ checked }) => checked !== false);
  116. };
  117. const clearCheckedNodes = () => {
  118. checkedNodes.value.forEach((node) => node.doCheck(false));
  119. calculateCheckedValue();
  120. menus.value = menus.value.slice(0, 1);
  121. expandingNode.value = void 0;
  122. emit("expand-change", []);
  123. };
  124. const calculateCheckedValue = () => {
  125. var _a;
  126. const { checkStrictly, multiple } = config$1.value;
  127. const oldNodes = checkedNodes.value;
  128. const newNodes = getCheckedNodes(!checkStrictly);
  129. const nodes = utils.sortByOriginalOrder(oldNodes, newNodes);
  130. const values = nodes.map((node) => node.valueByOption);
  131. checkedNodes.value = nodes;
  132. checkedValue.value = multiple ? values : (_a = values[0]) != null ? _a : null;
  133. };
  134. const syncCheckedValue = (loaded = false, forced = false) => {
  135. const { modelValue } = props;
  136. const { lazy, multiple, checkStrictly } = config$1.value;
  137. const leafOnly = !checkStrictly;
  138. if (!initialLoaded.value || manualChecked || !forced && lodashUnified.isEqual(modelValue, checkedValue.value))
  139. return;
  140. if (lazy && !loaded) {
  141. const values = arrays.unique(lodashUnified.flattenDeep(arrays.castArray(modelValue)));
  142. const nodes = values.map((val) => store$1 == null ? void 0 : store$1.getNodeByValue(val)).filter((node) => !!node && !node.loaded && !node.loading);
  143. if (nodes.length) {
  144. nodes.forEach((node) => {
  145. lazyLoad(node, () => syncCheckedValue(false, forced));
  146. });
  147. } else {
  148. syncCheckedValue(true, forced);
  149. }
  150. } else {
  151. const values = multiple ? arrays.castArray(modelValue) : [modelValue];
  152. const nodes = arrays.unique(values.map((val) => store$1 == null ? void 0 : store$1.getNodeByValue(val, leafOnly)));
  153. syncMenuState(nodes, forced);
  154. checkedValue.value = lodashUnified.cloneDeep(modelValue != null ? modelValue : void 0);
  155. }
  156. };
  157. const syncMenuState = (newCheckedNodes, reserveExpandingState = true) => {
  158. const { checkStrictly } = config$1.value;
  159. const oldNodes = checkedNodes.value;
  160. const newNodes = newCheckedNodes.filter((node) => !!node && (checkStrictly || node.isLeaf));
  161. const oldExpandingNode = store$1 == null ? void 0 : store$1.getSameNode(expandingNode.value);
  162. const newExpandingNode = reserveExpandingState && oldExpandingNode || newNodes[0];
  163. if (newExpandingNode) {
  164. newExpandingNode.pathNodes.forEach((node) => expandNode(node, true));
  165. } else {
  166. expandingNode.value = void 0;
  167. }
  168. oldNodes.forEach((node) => node.doCheck(false));
  169. vue.reactive(newNodes).forEach((node) => node.doCheck(true));
  170. checkedNodes.value = newNodes;
  171. vue.nextTick(scrollToExpandingNode);
  172. };
  173. const scrollToExpandingNode = () => {
  174. if (!core.isClient)
  175. return;
  176. menuList.value.forEach((menu) => {
  177. const menuElement = menu == null ? void 0 : menu.$el;
  178. if (menuElement) {
  179. const container = menuElement.querySelector(`.${ns.namespace.value}-scrollbar__wrap`);
  180. const activeNode = menuElement.querySelector(`.${ns.b("node")}.${ns.is("active")}:last-child`) || menuElement.querySelector(`.${ns.b("node")}.in-active-path`);
  181. scroll.scrollIntoView(container, activeNode);
  182. }
  183. });
  184. };
  185. const handleKeyDown = (e) => {
  186. const target = e.target;
  187. const { code } = e;
  188. switch (code) {
  189. case aria.EVENT_CODE.up:
  190. case aria.EVENT_CODE.down: {
  191. e.preventDefault();
  192. const distance = code === aria.EVENT_CODE.up ? -1 : 1;
  193. aria$1.focusNode(aria$1.getSibling(target, distance, `.${ns.b("node")}[tabindex="-1"]`));
  194. break;
  195. }
  196. case aria.EVENT_CODE.left: {
  197. e.preventDefault();
  198. const preMenu = menuList.value[utils.getMenuIndex(target) - 1];
  199. const expandedNode = preMenu == null ? void 0 : preMenu.$el.querySelector(`.${ns.b("node")}[aria-expanded="true"]`);
  200. aria$1.focusNode(expandedNode);
  201. break;
  202. }
  203. case aria.EVENT_CODE.right: {
  204. e.preventDefault();
  205. const nextMenu = menuList.value[utils.getMenuIndex(target) + 1];
  206. const firstNode = nextMenu == null ? void 0 : nextMenu.$el.querySelector(`.${ns.b("node")}[tabindex="-1"]`);
  207. aria$1.focusNode(firstNode);
  208. break;
  209. }
  210. case aria.EVENT_CODE.enter:
  211. case aria.EVENT_CODE.numpadEnter:
  212. utils.checkNode(target);
  213. break;
  214. }
  215. };
  216. vue.provide(types.CASCADER_PANEL_INJECTION_KEY, vue.reactive({
  217. config: config$1,
  218. expandingNode,
  219. checkedNodes,
  220. isHoverMenu,
  221. initialLoaded,
  222. renderLabelFn,
  223. lazyLoad,
  224. expandNode,
  225. handleCheckChange
  226. }));
  227. vue.watch(config$1, (newVal, oldVal) => {
  228. if (lodashUnified.isEqual(newVal, oldVal))
  229. return;
  230. initStore();
  231. }, {
  232. immediate: true
  233. });
  234. vue.watch(() => props.options, initStore, {
  235. deep: true
  236. });
  237. vue.watch(() => props.modelValue, () => {
  238. manualChecked = false;
  239. syncCheckedValue();
  240. }, {
  241. deep: true
  242. });
  243. vue.watch(() => checkedValue.value, (val) => {
  244. if (!lodashUnified.isEqual(val, props.modelValue)) {
  245. emit(event.UPDATE_MODEL_EVENT, val);
  246. emit(event.CHANGE_EVENT, val);
  247. }
  248. });
  249. vue.onBeforeUpdate(() => menuList.value = []);
  250. vue.onMounted(() => !types$1.isEmpty(props.modelValue) && syncCheckedValue());
  251. expose({
  252. menuList,
  253. menus,
  254. checkedNodes,
  255. handleKeyDown,
  256. handleCheckChange,
  257. getFlattedNodes,
  258. getCheckedNodes,
  259. clearCheckedNodes,
  260. calculateCheckedValue,
  261. scrollToExpandingNode
  262. });
  263. return (_ctx, _cache) => {
  264. return vue.openBlock(), vue.createElementBlock("div", {
  265. class: vue.normalizeClass([vue.unref(ns).b("panel"), vue.unref(ns).is("bordered", _ctx.border)]),
  266. onKeydown: handleKeyDown
  267. }, [
  268. (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(menus.value, (menu$1, index) => {
  269. return vue.openBlock(), vue.createBlock(menu["default"], {
  270. key: index,
  271. ref_for: true,
  272. ref: (item) => menuList.value[index] = item,
  273. index,
  274. nodes: [...menu$1]
  275. }, {
  276. empty: vue.withCtx(() => [
  277. vue.renderSlot(_ctx.$slots, "empty")
  278. ]),
  279. _: 2
  280. }, 1032, ["index", "nodes"]);
  281. }), 128))
  282. ], 34);
  283. };
  284. }
  285. });
  286. var CascaderPanel = /* @__PURE__ */ pluginVue_exportHelper["default"](_sfc_main, [["__file", "index.vue"]]);
  287. exports["default"] = CascaderPanel;
  288. //# sourceMappingURL=index.js.map