{"version":3,"file":"useKeydown.mjs","names":[],"sources":["../../../../../../../packages/components/tree/src/model/useKeydown.ts"],"sourcesContent":["import { onMounted, onUpdated } from 'vue'\nimport { useEventListener } from '@vueuse/core'\nimport { EVENT_CODE } from '@element-plus/constants'\nimport { useNamespace } from '@element-plus/hooks'\nimport { getEventCode } from '@element-plus/utils'\n\nimport type TreeStore from './tree-store'\nimport type { Ref } from 'vue'\nimport type { Nullable } from '@element-plus/utils'\n\ninterface UseKeydownOption {\n  el$: Ref<HTMLElement | null>\n}\nexport function useKeydown({ el$ }: UseKeydownOption, store: Ref<TreeStore>) {\n  const ns = useNamespace('tree')\n\n  onMounted(() => {\n    initTabIndex()\n  })\n\n  onUpdated(() => {\n    el$.value?.querySelectorAll('input[type=checkbox]').forEach((checkbox) => {\n      checkbox.setAttribute('tabindex', '-1')\n    })\n  })\n\n  function canNodeFocus(treeItems: HTMLElement[], nextIndex: number): boolean {\n    const currentNode = store.value.getNode(treeItems[nextIndex].dataset.key!)\n    return (\n      currentNode.canFocus &&\n      currentNode.visible &&\n      (currentNode.parent?.expanded || currentNode.parent?.level === 0)\n    )\n  }\n\n  const handleKeydown = (ev: KeyboardEvent): void => {\n    const currentItem = ev.target as HTMLDivElement\n    if (!currentItem.className.includes(ns.b('node'))) return\n    const code = getEventCode(ev)\n    const treeItems: HTMLElement[] = Array.from(\n      el$.value!.querySelectorAll(`.${ns.is('focusable')}[role=treeitem]`)\n    )\n    const currentIndex = treeItems.indexOf(currentItem)\n    let nextIndex\n    if ([EVENT_CODE.up, EVENT_CODE.down].includes(code)) {\n      ev.preventDefault()\n      if (code === EVENT_CODE.up) {\n        nextIndex =\n          currentIndex === -1\n            ? 0\n            : currentIndex !== 0\n              ? currentIndex - 1\n              : treeItems.length - 1\n        const startIndex = nextIndex\n        while (true) {\n          if (canNodeFocus(treeItems, nextIndex)) {\n            break\n          }\n\n          nextIndex--\n          if (nextIndex === startIndex) {\n            nextIndex = -1\n            break\n          }\n          if (nextIndex < 0) {\n            nextIndex = treeItems.length - 1\n          }\n        }\n      } else {\n        nextIndex =\n          currentIndex === -1\n            ? 0\n            : currentIndex < treeItems.length - 1\n              ? currentIndex + 1\n              : 0\n        const startIndex = nextIndex\n        while (true) {\n          if (canNodeFocus(treeItems, nextIndex)) {\n            break\n          }\n\n          nextIndex++\n          if (nextIndex === startIndex) {\n            nextIndex = -1\n            break\n          }\n          if (nextIndex >= treeItems.length) {\n            nextIndex = 0\n          }\n        }\n      }\n      nextIndex !== -1 && treeItems[nextIndex].focus()\n    }\n    if ([EVENT_CODE.left, EVENT_CODE.right].includes(code)) {\n      ev.preventDefault()\n      currentItem.click()\n    }\n    const hasInput = currentItem.querySelector(\n      '[type=\"checkbox\"]'\n    ) as Nullable<HTMLInputElement>\n    if (\n      [EVENT_CODE.enter, EVENT_CODE.numpadEnter, EVENT_CODE.space].includes(\n        code\n      ) &&\n      hasInput\n    ) {\n      ev.preventDefault()\n      hasInput.click()\n    }\n  }\n\n  useEventListener(el$, 'keydown', handleKeydown)\n\n  const initTabIndex = (): void => {\n    if (!el$.value) return\n    const treeItems = Array.from(\n      el$.value.querySelectorAll(`.${ns.is('focusable')}[role=treeitem]`)\n    )\n    const checkboxItems = Array.from(\n      el$.value.querySelectorAll('input[type=checkbox]')\n    )\n    checkboxItems.forEach((checkbox) => {\n      checkbox.setAttribute('tabindex', '-1')\n    })\n    const checkedItem = el$.value.querySelectorAll(\n      `.${ns.is('checked')}[role=treeitem]`\n    )\n    if (checkedItem.length) {\n      checkedItem[0].setAttribute('tabindex', '0')\n      return\n    }\n    treeItems[0]?.setAttribute('tabindex', '0')\n  }\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,WAAW,EAAE,OAAyB,OAAuB;CAC3E,MAAM,KAAK,aAAa,OAAO;AAE/B,iBAAgB;AACd,gBAAc;GACd;AAEF,iBAAgB;AACd,MAAI,OAAO,iBAAiB,uBAAuB,CAAC,SAAS,aAAa;AACxE,YAAS,aAAa,YAAY,KAAK;IACvC;GACF;CAEF,SAAS,aAAa,WAA0B,WAA4B;EAC1E,MAAM,cAAc,MAAM,MAAM,QAAQ,UAAU,WAAW,QAAQ,IAAK;AAC1E,SACE,YAAY,YACZ,YAAY,YACX,YAAY,QAAQ,YAAY,YAAY,QAAQ,UAAU;;CAInE,MAAM,iBAAiB,OAA4B;EACjD,MAAM,cAAc,GAAG;AACvB,MAAI,CAAC,YAAY,UAAU,SAAS,GAAG,EAAE,OAAO,CAAC,CAAE;EACnD,MAAM,OAAO,aAAa,GAAG;EAC7B,MAAM,YAA2B,MAAM,KACrC,IAAI,MAAO,iBAAiB,IAAI,GAAG,GAAG,YAAY,CAAC,iBAAiB,CACrE;EACD,MAAM,eAAe,UAAU,QAAQ,YAAY;EACnD,IAAI;AACJ,MAAI,CAAC,WAAW,IAAI,WAAW,KAAK,CAAC,SAAS,KAAK,EAAE;AACnD,MAAG,gBAAgB;AACnB,OAAI,SAAS,WAAW,IAAI;AAC1B,gBACE,iBAAiB,KACb,IACA,iBAAiB,IACf,eAAe,IACf,UAAU,SAAS;IAC3B,MAAM,aAAa;AACnB,WAAO,MAAM;AACX,SAAI,aAAa,WAAW,UAAU,CACpC;AAGF;AACA,SAAI,cAAc,YAAY;AAC5B,kBAAY;AACZ;;AAEF,SAAI,YAAY,EACd,aAAY,UAAU,SAAS;;UAG9B;AACL,gBACE,iBAAiB,KACb,IACA,eAAe,UAAU,SAAS,IAChC,eAAe,IACf;IACR,MAAM,aAAa;AACnB,WAAO,MAAM;AACX,SAAI,aAAa,WAAW,UAAU,CACpC;AAGF;AACA,SAAI,cAAc,YAAY;AAC5B,kBAAY;AACZ;;AAEF,SAAI,aAAa,UAAU,OACzB,aAAY;;;AAIlB,iBAAc,MAAM,UAAU,WAAW,OAAO;;AAElD,MAAI,CAAC,WAAW,MAAM,WAAW,MAAM,CAAC,SAAS,KAAK,EAAE;AACtD,MAAG,gBAAgB;AACnB,eAAY,OAAO;;EAErB,MAAM,WAAW,YAAY,cAC3B,sBACD;AACD,MACE;GAAC,WAAW;GAAO,WAAW;GAAa,WAAW;GAAM,CAAC,SAC3D,KACD,IACD,UACA;AACA,MAAG,gBAAgB;AACnB,YAAS,OAAO;;;AAIpB,kBAAiB,KAAK,WAAW,cAAc;CAE/C,MAAM,qBAA2B;AAC/B,MAAI,CAAC,IAAI,MAAO;EAChB,MAAM,YAAY,MAAM,KACtB,IAAI,MAAM,iBAAiB,IAAI,GAAG,GAAG,YAAY,CAAC,iBAAiB,CACpE;AAID,EAHsB,MAAM,KAC1B,IAAI,MAAM,iBAAiB,uBAAuB,CACnD,CACa,SAAS,aAAa;AAClC,YAAS,aAAa,YAAY,KAAK;IACvC;EACF,MAAM,cAAc,IAAI,MAAM,iBAC5B,IAAI,GAAG,GAAG,UAAU,CAAC,iBACtB;AACD,MAAI,YAAY,QAAQ;AACtB,eAAY,GAAG,aAAa,YAAY,IAAI;AAC5C;;AAEF,YAAU,IAAI,aAAa,YAAY,IAAI"}