{"version":3,"file":"index.mjs","sources":["../../../../../../packages/components/cascader-panel/src/index.vue"],"sourcesContent":["<template>\n  <div\n    :class=\"['el-cascader-panel', border && 'is-bordered']\"\n    @keydown=\"handleKeyDown\"\n  >\n    <el-cascader-menu\n      v-for=\"(menu, index) in menus\"\n      :key=\"index\"\n      :ref=\"(item) => (menuList[index] = item)\"\n      :index=\"index\"\n      :nodes=\"menu\"\n    />\n  </div>\n</template>\n\n<script lang=\"ts\">\nimport {\n  computed,\n  defineComponent,\n  nextTick,\n  onBeforeUpdate,\n  onMounted,\n  provide,\n  reactive,\n  ref,\n  watch,\n} from 'vue'\nimport { isEqual, flattenDeep } from 'lodash-unified'\nimport { isClient } from '@vueuse/core'\nimport {\n  focusNode,\n  getSibling,\n  isEmpty,\n  unique,\n  castArray,\n  scrollIntoView,\n} from '@element-plus/utils'\nimport {\n  EVENT_CODE,\n  UPDATE_MODEL_EVENT,\n  CHANGE_EVENT,\n} from '@element-plus/constants'\n\nimport ElCascaderMenu from './menu.vue'\nimport Store from './store'\nimport Node, { ExpandTrigger } from './node'\nimport { CommonProps, useCascaderConfig } from './config'\nimport { checkNode, getMenuIndex, sortByOriginalOrder } from './utils'\nimport { CASCADER_PANEL_INJECTION_KEY } from './types'\n\nimport type { PropType } from 'vue'\nimport type { Nullable } from '@element-plus/utils'\nimport type {\n  CascaderValue,\n  CascaderNodeValue,\n  CascaderOption,\n  RenderLabel,\n  default as CascaderNode,\n} from './node'\n\nimport type { ElCascaderPanelContext } from './types'\n\nexport default defineComponent({\n  name: 'ElCascaderPanel',\n\n  components: {\n    ElCascaderMenu,\n  },\n\n  props: {\n    ...CommonProps,\n    border: {\n      type: Boolean,\n      default: true,\n    },\n    renderLabel: Function as PropType<RenderLabel>,\n  },\n\n  emits: [UPDATE_MODEL_EVENT, CHANGE_EVENT, 'close', 'expand-change'],\n\n  setup(props, { emit, slots }) {\n    // for interrupt sync check status in lazy mode\n    let manualChecked = false\n\n    const config = useCascaderConfig(props)\n\n    let store: Nullable<Store> = null\n    const initialLoaded = ref(true)\n    const menuList = ref<any[]>([])\n    const checkedValue = ref<Nullable<CascaderValue>>(null)\n    const menus = ref<CascaderNode[][]>([])\n    const expandingNode = ref<Nullable<CascaderNode>>(null)\n    const checkedNodes = ref<CascaderNode[]>([])\n\n    const isHoverMenu = computed(\n      () => config.value.expandTrigger === ExpandTrigger.HOVER\n    )\n    const renderLabelFn = computed(() => props.renderLabel || slots.default)\n\n    const initStore = () => {\n      const { options } = props\n      const cfg = config.value\n\n      manualChecked = false\n      store = new Store(options, cfg)\n      menus.value = [store.getNodes()]\n\n      if (cfg.lazy && isEmpty(props.options)) {\n        initialLoaded.value = false\n        lazyLoad(undefined, (list) => {\n          if (list) {\n            store = new Store(list, cfg)\n            menus.value = [store.getNodes()]\n          }\n          initialLoaded.value = true\n          syncCheckedValue(false, true)\n        })\n      } else {\n        syncCheckedValue(false, true)\n      }\n    }\n\n    const lazyLoad: ElCascaderPanelContext['lazyLoad'] = (node, cb) => {\n      const cfg = config.value\n      node! = node || new Node({}, cfg, undefined, true)\n      node.loading = true\n\n      const resolve = (dataList: CascaderOption[]) => {\n        const _node = node as Node\n        const parent = _node.root ? null : _node\n        dataList && store?.appendNodes(dataList, parent as any)\n        _node.loading = false\n        _node.loaded = true\n        _node.childrenData = _node.childrenData || []\n        cb && cb(dataList)\n      }\n\n      cfg.lazyLoad(node, resolve as any)\n    }\n\n    const expandNode: ElCascaderPanelContext['expandNode'] = (node, silent) => {\n      const { level } = node\n      const newMenus = menus.value.slice(0, level)\n      let newExpandingNode: Nullable<CascaderNode>\n\n      if (node.isLeaf) {\n        newExpandingNode = node.pathNodes[level - 2]\n      } else {\n        newExpandingNode = node\n        newMenus.push(node.children)\n      }\n\n      if (expandingNode.value?.uid !== newExpandingNode?.uid) {\n        expandingNode.value = node\n        menus.value = newMenus\n        !silent && emit('expand-change', node?.pathValues || [])\n      }\n    }\n\n    const handleCheckChange: ElCascaderPanelContext['handleCheckChange'] = (\n      node,\n      checked,\n      emitClose = true\n    ) => {\n      const { checkStrictly, multiple } = config.value\n      const oldNode = checkedNodes.value[0]\n      manualChecked = true\n\n      !multiple && oldNode?.doCheck(false)\n      node.doCheck(checked)\n      calculateCheckedValue()\n      emitClose && !multiple && !checkStrictly && emit('close')\n      !emitClose && !multiple && !checkStrictly && expandParentNode(node)\n    }\n\n    const expandParentNode = (node) => {\n      if (!node) return\n      node = node.parent\n      expandParentNode(node)\n      node && expandNode(node)\n    }\n\n    const getFlattedNodes = (leafOnly: boolean) => {\n      return store?.getFlattedNodes(leafOnly)\n    }\n\n    const getCheckedNodes = (leafOnly: boolean) => {\n      return getFlattedNodes(leafOnly)?.filter((node) => node.checked !== false)\n    }\n\n    const clearCheckedNodes = () => {\n      checkedNodes.value.forEach((node) => node.doCheck(false))\n      calculateCheckedValue()\n    }\n\n    const calculateCheckedValue = () => {\n      const { checkStrictly, multiple } = config.value\n      const oldNodes = checkedNodes.value\n      const newNodes = getCheckedNodes(!checkStrictly)!\n      // ensure the original order\n      const nodes = sortByOriginalOrder(oldNodes, newNodes)\n      const values = nodes.map((node) => node.valueByOption)\n      checkedNodes.value = nodes\n      checkedValue.value = multiple ? values : values[0] ?? null\n    }\n\n    const syncCheckedValue = (loaded = false, forced = false) => {\n      const { modelValue } = props\n      const { lazy, multiple, checkStrictly } = config.value\n      const leafOnly = !checkStrictly\n\n      if (\n        !initialLoaded.value ||\n        manualChecked ||\n        (!forced && isEqual(modelValue, checkedValue.value))\n      )\n        return\n\n      if (lazy && !loaded) {\n        const values: CascaderNodeValue[] = unique(\n          flattenDeep(castArray(modelValue))\n        )\n        const nodes = values\n          .map((val) => store?.getNodeByValue(val))\n          .filter((node) => !!node && !node.loaded && !node.loading) as Node[]\n\n        if (nodes.length) {\n          nodes.forEach((node) => {\n            lazyLoad(node, () => syncCheckedValue(false, forced))\n          })\n        } else {\n          syncCheckedValue(true, forced)\n        }\n      } else {\n        const values = multiple ? castArray(modelValue) : [modelValue]\n        const nodes = unique(\n          values.map((val) => store?.getNodeByValue(val, leafOnly))\n        ) as Node[]\n        syncMenuState(nodes, false)\n        checkedValue.value = modelValue!\n      }\n    }\n\n    const syncMenuState = (\n      newCheckedNodes: CascaderNode[],\n      reserveExpandingState = true\n    ) => {\n      const { checkStrictly } = config.value\n      const oldNodes = checkedNodes.value\n      const newNodes = newCheckedNodes.filter(\n        (node) => !!node && (checkStrictly || node.isLeaf)\n      )\n      const oldExpandingNode = store?.getSameNode(expandingNode.value!)\n      const newExpandingNode =\n        (reserveExpandingState && oldExpandingNode) || newNodes[0]\n\n      if (newExpandingNode) {\n        newExpandingNode.pathNodes.forEach((node) => expandNode(node, true))\n      } else {\n        expandingNode.value = null\n      }\n\n      oldNodes.forEach((node) => node.doCheck(false))\n      newNodes.forEach((node) => node.doCheck(true))\n\n      checkedNodes.value = newNodes\n      nextTick(scrollToExpandingNode)\n    }\n\n    const scrollToExpandingNode = () => {\n      if (!isClient) return\n\n      menuList.value.forEach((menu) => {\n        const menuElement = menu?.$el\n        if (menuElement) {\n          const container = (menuElement as HTMLElement).querySelector(\n            '.el-scrollbar__wrap'\n          )\n          const activeNode =\n            menuElement.querySelector('.el-cascader-node.is-active') ||\n            menuElement.querySelector('.el-cascader-node.in-active-path')\n          scrollIntoView(container as HTMLElement, activeNode)\n        }\n      })\n    }\n\n    const handleKeyDown = (e: KeyboardEvent) => {\n      const target = e.target as HTMLElement\n      const { code } = e\n\n      switch (code) {\n        case EVENT_CODE.up:\n        case EVENT_CODE.down: {\n          e.preventDefault()\n          const distance = code === EVENT_CODE.up ? -1 : 1\n          focusNode(\n            getSibling(target, distance, '.el-cascader-node[tabindex=\"-1\"]')\n          )\n          break\n        }\n        case EVENT_CODE.left: {\n          e.preventDefault()\n          const preMenu = menuList.value[getMenuIndex(target) - 1]\n          const expandedNode = preMenu?.$el.querySelector(\n            '.el-cascader-node[aria-expanded=\"true\"]'\n          )\n          focusNode(expandedNode)\n          break\n        }\n        case EVENT_CODE.right: {\n          e.preventDefault()\n          const nextMenu = menuList.value[getMenuIndex(target) + 1]\n          const firstNode = nextMenu?.$el.querySelector(\n            '.el-cascader-node[tabindex=\"-1\"]'\n          )\n          focusNode(firstNode)\n          break\n        }\n        case EVENT_CODE.enter:\n          checkNode(target)\n          break\n        case EVENT_CODE.esc:\n        case EVENT_CODE.tab:\n          emit('close')\n          break\n      }\n    }\n\n    provide(\n      CASCADER_PANEL_INJECTION_KEY,\n      reactive({\n        config,\n        expandingNode,\n        checkedNodes,\n        isHoverMenu,\n        initialLoaded,\n        renderLabelFn,\n        lazyLoad,\n        expandNode,\n        handleCheckChange,\n      })\n    )\n\n    watch([config, () => props.options], initStore, {\n      deep: true,\n      immediate: true,\n    })\n\n    watch(\n      () => props.modelValue,\n      () => {\n        manualChecked = false\n        syncCheckedValue()\n      }\n    )\n\n    watch(checkedValue, (val) => {\n      if (!isEqual(val, props.modelValue)) {\n        emit(UPDATE_MODEL_EVENT, val)\n        emit(CHANGE_EVENT, val)\n      }\n    })\n\n    onBeforeUpdate(() => (menuList.value = []))\n\n    onMounted(() => !isEmpty(props.modelValue) && syncCheckedValue())\n\n    return {\n      menuList,\n      menus,\n      checkedNodes,\n      handleKeyDown,\n      handleCheckChange,\n      getFlattedNodes,\n      getCheckedNodes,\n      clearCheckedNodes,\n      calculateCheckedValue,\n      scrollToExpandingNode,\n    }\n  },\n})\n</script>\n"],"names":["_openBlock"],"mappings":"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"}