{"version":3,"file":"index2.mjs","sources":["../../../../../src/components/ivue-tree/index.vue"],"sourcesContent":["<template>\r\n  <div :class=\"wrapperClasses\" ref=\"treeRef\">\r\n    <!-- 节点 -->\r\n    <tree-node\r\n      v-for=\"child in root.childNodes\"\r\n      :node=\"child\"\r\n      :accordion=\"accordion\"\r\n      :show-checkbox=\"showCheckbox\"\r\n      :render-after-expand=\"renderAfterExpand\"\r\n      :render-content=\"renderContent\"\r\n      :props=\"props\"\r\n      :key=\"getTreeNodeKey(child)\"\r\n      @on-node-expand=\"handleNodeExpand\"\r\n    ></tree-node>\r\n    <!-- 没有数据 -->\r\n    <div :class=\"`${prefixCls}-no-data`\" v-if=\"isEmpty\">{{ emptyText }}</div>\r\n    <!-- 拖动下划线 -->\r\n    <div\r\n      v-show=\"dragState.showDropIndicator\"\r\n      ref=\"dropIndicator\"\r\n      :class=\"`${prefixCls}-drop-indicator`\"\r\n    ></div>\r\n  </div>\r\n</template>\r\n\r\n<script lang=\"ts\">\r\nimport {\r\n  computed,\r\n  defineComponent,\r\n  ref,\r\n  provide,\r\n  ComponentInternalInstance,\r\n  PropType,\r\n  watch,\r\n} from 'vue';\r\nimport TreeStore from './store/tree-store';\r\nimport { getNodeKey, handleCurrentChange } from './utils';\r\nimport { useNodeExpandEventBroadcast } from './hooks/useNodeExpandEventBroadcast';\r\nimport { useKeydown } from './hooks/useKeydown';\r\nimport { useDragNodeHandler } from './hooks/useDragNode';\r\nimport { throwError } from '../../utils/error';\r\n\r\nimport TreeNode from './node.vue';\r\n\r\n// type\r\nimport type Node from './store/node';\r\nimport type { Props, TreeNodeData, TreeKey, TreeData } from './types/tree';\r\nimport { TreeContextKey, IconPropType } from './types/tree';\r\n\r\nconst prefixCls = 'ivue-tree';\r\n\r\nexport default defineComponent({\r\n  name: prefixCls,\r\n  emits: [\r\n    'on-current-change',\r\n    'on-node-collapse',\r\n    'on-node-expand',\r\n    'on-node-click',\r\n    'on-check',\r\n    'on-check-change',\r\n    'on-node-drag-start',\r\n    'on-node-drag-leave',\r\n    'on-node-drag-enter',\r\n    'on-node-drag-over',\r\n    'on-node-drag-end',\r\n    'on-node-drop',\r\n  ],\r\n  props: {\r\n    /**\r\n     * tree数据\r\n     *\r\n     * @type {Array}\r\n     */\r\n    data: {\r\n      type: Array,\r\n      default: () => [],\r\n    },\r\n    /**\r\n     * 是否懒加载子节点，需与 load 方法结合使用\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    lazy: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * tree 配置选项\r\n     *\r\n     * @type {Object}\r\n     */\r\n    props: {\r\n      type: Object as PropType<Props['props']>,\r\n      default: () => ({\r\n        children: 'children',\r\n        label: 'label',\r\n        disabled: 'disabled',\r\n      }),\r\n    },\r\n    /**\r\n     * 暂无数据文案\r\n     *\r\n     * @type {String}\r\n     */\r\n    emptyText: {\r\n      type: String,\r\n      default: '暂无数据',\r\n    },\r\n    /**\r\n     * 每个树节点用来作为唯一标识的属性，整棵树应该是唯一的\r\n     *\r\n     * @type {String}\r\n     */\r\n    nodeKey: {\r\n      type: String,\r\n    },\r\n    /**\r\n     * 相邻级节点间的水平缩进，单位为像素\r\n     *\r\n     * @type {Number}\r\n     */\r\n    indent: {\r\n      type: Number,\r\n      default: 18,\r\n    },\r\n    /**\r\n     * 自定义树节点扩展图标\r\n     *\r\n     * @type {IconPropType}\r\n     */\r\n    icon: {\r\n      type: IconPropType,\r\n      default: 'arrow_right',\r\n    },\r\n    /**\r\n     * 树节点的内容区的渲染方法\r\n     *\r\n     * @type {Function}\r\n     */\r\n    renderContent: {\r\n      type: Function as PropType<Props['renderContent']>,\r\n    },\r\n    /**\r\n     * 是否在点击节点的时候展开或者收缩节点\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    expandOnClickNode: {\r\n      type: Boolean,\r\n      default: true,\r\n    },\r\n    /**\r\n     * 是否每次只打开一个同级树节点展开\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    accordion: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 设置节点是否被选中\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    showCheckbox: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 在显示复选框的情况下，是否严格的遵循父子不互相关联的做法\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    checkBoxStrictly: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 加载子树数据的方法，仅当 lazy 属性为true 时生效\r\n     *\r\n     * @type {Function}\r\n     */\r\n    load: {\r\n      type: Function as PropType<Props['load']>,\r\n    },\r\n    /**\r\n     * 默认勾选的节点的 key 的数组\r\n     *\r\n     * @type {Array}\r\n     */\r\n    defaultCheckedKeys: {\r\n      type: Array as PropType<Props['defaultCheckedKeys']>,\r\n    },\r\n    /**\r\n     * 默认展开的节点的 key 的数组\r\n     *\r\n     * @type {Array}\r\n     */\r\n    defaultExpandedKeys: {\r\n      type: Array as PropType<Props['defaultExpandedKeys']>,\r\n    },\r\n    /**\r\n     * 展开子节点的时候是否自动展开父节点\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    autoExpandParent: {\r\n      type: Boolean,\r\n      default: true,\r\n    },\r\n    /**\r\n     * 是否默认展开所有节点\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    defaultExpandAll: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 是否在第一次展开某个树节点后才渲染其子节点\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    renderAfterExpand: {\r\n      type: Boolean,\r\n      default: true,\r\n    },\r\n    /**\r\n     * 是否高亮当前选中节点\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    highlightCurrent: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 当前选中的节点\r\n     *\r\n     * @type {String | Number}\r\n     */\r\n    currentNodeKey: {\r\n      type: [String, Number],\r\n    },\r\n    /**\r\n     * 对树节点进行筛选时执行的方法， 返回 false 则表示这个节点会被隐藏\r\n     *\r\n     * @type {Function}\r\n     */\r\n    filterNodeMethod: {\r\n      type: Function as PropType<Props['filterNodeMethod']>,\r\n    },\r\n    /**\r\n     * 是否在点击节点的时候选中节点\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    checkOnClickNode: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 是否开启拖拽节点功能\r\n     *\r\n     * @type {Boolean}\r\n     */\r\n    draggable: {\r\n      type: Boolean,\r\n      default: false,\r\n    },\r\n    /**\r\n     * 判断节点能否被拖拽 如果返回 false ，节点不能被拖动\r\n     *\r\n     * @type {Function}\r\n     */\r\n    allowDrag: {\r\n      type: Function as PropType<Props['allowDrag']>,\r\n    },\r\n    /**\r\n     * 拖拽时判定目标节点能否成为拖动目标位置\r\n     *\r\n     * @type {Function}\r\n     */\r\n    allowDrop: {\r\n      type: Function as PropType<Props['allowDrop']>,\r\n    },\r\n  },\r\n  setup(props: Props, ctx) {\r\n    // 派发事件到所有子节点是否关闭展开\r\n    const { broadcastExpanded } = useNodeExpandEventBroadcast(props);\r\n\r\n    // data\r\n\r\n    // tree 存储\r\n    const store = ref<TreeStore>(\r\n      new TreeStore({\r\n        key: props.nodeKey,\r\n        data: props.data,\r\n        lazy: props.lazy,\r\n        props: props.props,\r\n        checkBoxStrictly: props.checkBoxStrictly,\r\n        load: props.load,\r\n        defaultCheckedKeys: props.defaultCheckedKeys,\r\n        defaultExpandedKeys: props.defaultExpandedKeys,\r\n        autoExpandParent: props.autoExpandParent,\r\n        defaultExpandAll: props.defaultExpandAll,\r\n        filterNodeMethod: props.filterNodeMethod,\r\n      })\r\n    );\r\n\r\n    // 初始化\r\n    store.value.initialize();\r\n\r\n    // 根节点数据\r\n    const root = ref<Node>(store.value.root);\r\n    // 当前节点\r\n    const currentNode = ref<Node>(null);\r\n    // 跟节点\r\n    const treeRef = ref<HTMLElement>(null);\r\n\r\n    // 拖动时显示的线条\r\n    const dropIndicator = ref<HTMLElement>(null);\r\n\r\n    // 键盘事件\r\n    useKeydown(treeRef, store);\r\n\r\n    // 拖动事件\r\n    const { dragState } = useDragNodeHandler({\r\n      props,\r\n      ctx,\r\n      treeRef,\r\n      dropIndicator,\r\n      store,\r\n    });\r\n\r\n    // computed\r\n\r\n    // 外层样式\r\n    const wrapperClasses = computed(() => {\r\n      return [\r\n        prefixCls,\r\n        {\r\n          [`${prefixCls}-highlight-current`]: props.highlightCurrent,\r\n        },\r\n      ];\r\n    });\r\n\r\n    // 是否没有数据\r\n    const isEmpty = computed(() => {\r\n      const { childNodes } = root.value;\r\n\r\n      return (\r\n        !childNodes ||\r\n        childNodes.length === 0 ||\r\n        childNodes.every(({ visible }) => !visible)\r\n      );\r\n    });\r\n\r\n    // methods\r\n\r\n    // 获取节点key\r\n    const getTreeNodeKey = (node: Node) => {\r\n      return getNodeKey(props.nodeKey, node.data);\r\n    };\r\n\r\n    // 节点展开\r\n    const handleNodeExpand = (\r\n      nodeData: TreeNodeData,\r\n      node: Node,\r\n      instance: ComponentInternalInstance\r\n    ) => {\r\n      // 派发展开事件\r\n      broadcastExpanded(node);\r\n      // 节点被展开时触发的事件\r\n      ctx.emit(\r\n        'on-node-expand',\r\n        // 传递给 data 属性的数组中该节点所对应的对象\r\n        nodeData,\r\n        // 节点对应的 Node\r\n        node,\r\n        // 节点组件本身\r\n        instance\r\n      );\r\n    };\r\n\r\n    // 返回当前选中节点的数组\r\n    const getCheckedNodes = (\r\n      // 返回当前选中节点的子节点\r\n      leafOnly?: boolean,\r\n      // 返回值包含半选中节点数据\r\n      includeHalfChecked?: boolean\r\n    ): TreeNodeData[] => {\r\n      return store.value.getCheckedNodes(leafOnly, includeHalfChecked);\r\n    };\r\n\r\n    // 返回当前选中节点 key 的数组\r\n    const getCheckedKeys = (leafOnly?: boolean): TreeKey[] => {\r\n      return store.value.getCheckedKeys(leafOnly);\r\n    };\r\n\r\n    // 通过 Node 节点数据设置复选框勾选的节点，使用此方法必须提前设置 node-key 属性\r\n    const setCheckedNodes = (nodes: Node[], leafOnly?: boolean) => {\r\n      if (!props.nodeKey) {\r\n        throwError(prefixCls, 'nodeKey is required in setCheckedNodes');\r\n      }\r\n\r\n      store.value.setCheckedNodes(nodes, leafOnly);\r\n    };\r\n\r\n    // 通过 key 数组设置复选框勾选的节点，使用此方法必须设置 node-key 属性\r\n    const setCheckedKeys = (keys: TreeKey[], leafOnly?: boolean) => {\r\n      if (!props.nodeKey) {\r\n        throwError(prefixCls, 'nodeKey is required in setCheckedKeys');\r\n      }\r\n\r\n      store.value.setCheckedKeys(keys, leafOnly);\r\n    };\r\n\r\n    // 为节点设置新数据，只有当设置 node-key 属性的时候才可用\r\n    const updateKeyChildren = (key: TreeKey, data: TreeData) => {\r\n      if (!props.nodeKey) {\r\n        throwError(prefixCls, 'nodeKey is required in updateKeyChild');\r\n      }\r\n\r\n      store.value.updateChildren(key, data);\r\n    };\r\n\r\n    // 过滤所有树节点，过滤后的节点将被隐藏\r\n    const filter = (value) => {\r\n      if (!props.filterNodeMethod) {\r\n        throwError(prefixCls, 'filterNodeMethod is required when filter');\r\n      }\r\n\r\n      store.value.filter(value);\r\n    };\r\n\r\n    // 插入到节点前面\r\n    const insertBefore = (\r\n      // 要增加的节点的 data\r\n      data: TreeNodeData,\r\n      // 参考节点的 data, key\r\n      refNode: TreeKey | TreeNodeData\r\n    ) => {\r\n      store.value.insertBefore(data, refNode);\r\n    };\r\n\r\n    // 插入到节点后面\r\n    const insertAfter = (\r\n      // 要增加的节点的 data\r\n      data: TreeNodeData,\r\n      // 参考节点的 data, key\r\n      refNode: TreeKey | TreeNodeData\r\n    ) => {\r\n      store.value.insertAfter(data, refNode);\r\n    };\r\n\r\n    // 设置节点是否被选中, 使用此方法必须设置 node-key 属性\r\n    const setChecked = (\r\n      data: TreeKey | TreeNodeData,\r\n      checked: boolean,\r\n      deep: boolean\r\n    ) => {\r\n      store.value.setChecked(data, checked, deep);\r\n    };\r\n\r\n    // 如果节点可用被选中 (show-checkbox 为 true), 它将返回当前半选中的节点组成的数组\r\n    const getHalfCheckedNodes = (): TreeNodeData[] => {\r\n      return store.value.getHalfCheckedNodes();\r\n    };\r\n\r\n    // 若节点可被选中(show-checkbox 为 true)，则返回目前半选中的节点的 key 所组成的数组\r\n    const getHalfCheckedKeys = (): TreeKey[] => {\r\n      return store.value.getHalfCheckedKeys();\r\n    };\r\n\r\n    // 返回当前被选中节点的数据 (如果没有则返回 null)\r\n    const getCurrentNode = (): TreeNodeData => {\r\n      const currentNode = store.value.getCurrentNode();\r\n\r\n      return currentNode ? currentNode.data : null;\r\n    };\r\n\r\n    // 返回当前被选中节点的数据的key (如果没有则返回 null)\r\n    const getCurrentKey = (): any => {\r\n      if (!props.nodeKey) {\r\n        throwError(prefixCls, 'nodeKey is required in getCurrentKey');\r\n      }\r\n\r\n      const currentNode = getCurrentNode();\r\n\r\n      return currentNode ? currentNode[props.nodeKey] : null;\r\n    };\r\n\r\n    // 通过 key 设置某个节点的当前选中状态，使用此方法必须设置 node-key  属性\r\n    const setCurrentKey = (\r\n      // 需要选中节点的 key， 如果为 null, 取消当前选中的节点\r\n      key?: TreeKey,\r\n      // 是否自动展开父节点\r\n      shouldAutoExpandParent = true\r\n    ) => {\r\n      if (!props.nodeKey) {\r\n        throwError(prefixCls, 'nodeKey is required in setCurrentKey');\r\n      }\r\n\r\n      // 发送点击事件\r\n      handleCurrentChange(store, ctx.emit, () =>\r\n        store.value.setCurrentNodeKey(key, shouldAutoExpandParent)\r\n      );\r\n    };\r\n\r\n    // 设置节点为选中状态，使用此方法必须设置 node-key 属性\r\n    const setCurrentNode = (\r\n      // 待被选中的节点\r\n      node: Node,\r\n      // 是否自动展开父节点\r\n      shouldAutoExpandParent = true\r\n    ) => {\r\n      if (!props.nodeKey) {\r\n        throwError(prefixCls, 'nodeKey is required in setCurrentNode');\r\n      }\r\n\r\n      // 发送点击事件\r\n      handleCurrentChange(store, ctx.emit, () =>\r\n        store.value.setUserCurrentNode(node, shouldAutoExpandParent)\r\n      );\r\n    };\r\n\r\n    // 根据 data 或者 key 拿到 Tree 组件中的 node\r\n    const getNode = (\r\n      // 节点的 data 或 key\r\n      data: TreeKey | TreeNodeData\r\n    ): Node => {\r\n      return store.value.getNode(data);\r\n    };\r\n\r\n    // 删除 Tree 中的一个节点\r\n    const remove = (\r\n      // 要删除的节点的 data 或者 node 对象\r\n      data: TreeNodeData | Node\r\n    ) => {\r\n      store.value.remove(data);\r\n    };\r\n\r\n    // 为 Tree 中的一个节点追加一个子节点\r\n    const append = (\r\n      // 要追加的子节点的 data\r\n      data: TreeNodeData,\r\n      // 父节点的 data, key 或 node\r\n      parentNode: TreeNodeData | TreeKey | Node\r\n    ) => {\r\n      store.value.append(data, parentNode);\r\n    };\r\n\r\n    // watch\r\n\r\n    // 监听数据变化\r\n    watch(\r\n      () => props.data,\r\n      (value) => {\r\n        store.value.setData(value);\r\n      },\r\n      {\r\n        deep: true,\r\n      }\r\n    );\r\n\r\n    // 监听在显示复选框的情况下，是否严格的遵循父子不互相关联的做法\r\n    watch(\r\n      () => props.checkBoxStrictly,\r\n      (newVal) => {\r\n        store.value.checkBoxStrictly = newVal;\r\n      }\r\n    );\r\n\r\n    // 监听当前选中的节点\r\n    watch(\r\n      () => props.currentNodeKey,\r\n      (newVal) => {\r\n        store.value.setCurrentNodeKey(newVal);\r\n      }\r\n    );\r\n\r\n    // 监听默认勾选的节点的 key 的数组\r\n    watch(\r\n      () => props.defaultCheckedKeys,\r\n      (newVal) => {\r\n        store.value.setDefaultCheckedKey(newVal);\r\n      }\r\n    );\r\n\r\n    // 监听默认展开的节点的 key 的数组\r\n    watch(\r\n      () => props.defaultExpandedKeys,\r\n      (newVal) => {\r\n        store.value.setDefaultExpandedKeys(newVal);\r\n      }\r\n    );\r\n\r\n    // 监听在显示复选框的情况下，是否严格的遵循父子不互相关联的做法\r\n    watch(\r\n      () => props.checkBoxStrictly,\r\n      (newVal) => {\r\n        store.value.checkBoxStrictly = newVal;\r\n      }\r\n    );\r\n\r\n    // provide\r\n    provide(TreeContextKey, {\r\n      props,\r\n      ctx,\r\n      store,\r\n      currentNode,\r\n    });\r\n\r\n    return {\r\n      prefixCls,\r\n\r\n      // dom\r\n      treeRef,\r\n      dropIndicator,\r\n\r\n      // data\r\n      root,\r\n      dragState,\r\n\r\n      // computed\r\n      wrapperClasses,\r\n      isEmpty,\r\n\r\n      // methods\r\n      handleNodeExpand,\r\n      getTreeNodeKey,\r\n      getCheckedNodes,\r\n      getCheckedKeys,\r\n      getHalfCheckedNodes,\r\n      getHalfCheckedKeys,\r\n      getCurrentNode,\r\n      getCurrentKey,\r\n      getNode,\r\n\r\n      setCheckedNodes,\r\n      setCheckedKeys,\r\n      setChecked,\r\n      setCurrentKey,\r\n      setCurrentNode,\r\n\r\n      remove,\r\n      append,\r\n      updateKeyChildren,\r\n      insertBefore,\r\n      insertAfter,\r\n      filter,\r\n    };\r\n  },\r\n  components: {\r\n    TreeNode,\r\n  },\r\n});\r\n</script>\r\n"],"names":["_resolveComponent","_openBlock","_createElementBlock","_normalizeClass","_createCommentVNode","_Fragment","_renderList","_createBlock","_toDisplayString","_withDirectives","_createElementVNode"],"mappings":";;;;;+BACEA,iBAqBM,WAAA,CAAA,CAAA;EArB2B,OAAAC,SAAA,EAAS,EAAAC,kBAAA,CAAA,KAAA,EAAA;AAAA,IAAA,KAAA,EAAAC,cAAA,CAAA,IAAA,CAAA,cAAA,CAAA;AAAA,IACxC,GAAA,EAAA,SAAA;AAAA,GAAA,EAAA;AAAA,IACAC,mBAAA,gBAAA,CAAA;AAAA,KAAAH,SAAA,CAES,IAAK,CAAA,EAAAC,kBAAA,CAAAG,QAAA,EAAA,IAAA,EAAAC,UAAA,CAAA,IAAA,CAAA,IAAA,CAAA,UAAA,EAAA,CAAA,KAAA,KAAA;AACX,MAAA,OAAAL,SAAA,EAAoB,EAAAM,WAAA,CAAA,oBAAA,EAAA;AAAA,QACpB,IAAA,EAAA,KAAA;AAAA,QACA,WAAA,IAAA,CAAA,SAAA;AAAA,QACA,iBAAc,IAAE,CAAA,YAAA;AAAA,QAChB,uBAAY,IAAA,CAAA,iBAAA;AAAA,QACZ,kBAAK,IAAA,CAAA,aAAA;AAAA,QACL,OAAA,IAAA,CAAA,KAAA;AAAA,QAAA,GAAA,EAAA,IAAA,CAAA,cAAA,CAAA,KAAA,CAAA;AAAA;OAEH,EAAa,IAAA,EAAA,CAAA,EAAA,CAAA,MAAA,EAAA,WAAA,EAAA,eAAA,EAAA,qBAAA,EAAA,gBAAA,EAAA,OAAA,EAAA,gBAAA,CAAA,CAAA,CAAA;AAAA,KAC8B,GAAO,GAAA,CAAA;AAAA,IAAlDH,mBAAA,4BAAA,CAAA;AAAA,IAAA,IAAA,CAAA,OAAA,IAAAH,SAAW,EAAA,qBAAK,KAAS,EAAA;AAAA,MAAA,GAAA,EAAA,CAAA;AAAA;KACzB,EAAAO,gBAAA,IAAA,CAAA,SAAc,2BACd,CAAA,MAAA,EAIO,IAAA,CAAA;AAAA,IAAAJ,mBAFD,kCAAe,CAAA;AAAA,IAAAK,cAAA,CACbC,mBAAK,KAAS,EAAA;AAAA,MAAA,GAAA,EAAA,eAAA;AAAA,MAFH,KAAA,EAAAP,cAAA,CAAA,CAAC,EAAA,IAAA,CAAiB,SAAA,CAAA,eAAA,CAAA,CAAA;AAAA,KAAA,EAAA,IAAA,EAAA,CAAA,CAAA,EAAA;AAAA;;;;;;;;"}