{"version":3,"file":"roving-focus-group-impl.mjs","sources":["../../../../../../packages/components/roving-focus-group/src/roving-focus-group-impl.vue"],"sourcesContent":["<template>\n  <slot></slot>\n</template>\n\n<script lang=\"ts\">\nimport {\n  computed,\n  defineComponent,\n  provide,\n  ref,\n  unref,\n  inject,\n  watch,\n  readonly,\n  toRef,\n} from 'vue'\nimport { composeEventHandlers } from '@hongluan-ui/utils'\nimport { useEventListener } from '@vueuse/core'\nimport {\n  rovingFocusGroupProps,\n  ROVING_FOCUS_COLLECTION_INJECTION_KEY,\n} from './roving-focus-group'\nimport { ROVING_FOCUS_GROUP_INJECTION_KEY } from './tokens'\nimport { focusFirst } from './utils'\n\nimport type { StyleValue } from 'vue'\n\nconst CURRENT_TAB_ID_CHANGE_EVT = 'currentTabIdChange'\n\nconst ENTRY_FOCUS_EVT = 'rovingFocusGroup.entryFocus'\nconst EVT_OPTS: EventInit = { bubbles: false, cancelable: true }\nexport default defineComponent({\n  name: 'RovingFocusGroupImpl',\n  inheritAttrs: false,\n  props: rovingFocusGroupProps,\n  emits: [CURRENT_TAB_ID_CHANGE_EVT, 'entryFocus'],\n  setup(props, { emit }) {\n    const currentTabbedId = ref<string | null>(\n      (props.currentTabId || props.defaultCurrentTabId) ?? null,\n    )\n    const isBackingOut = ref(false)\n    const isClickFocus = ref(false)\n    const rovingFocusGroupRef = ref<HTMLElement | null>(null)\n    const { getItems } = inject(\n      ROVING_FOCUS_COLLECTION_INJECTION_KEY,\n      undefined,\n    )\n    const rovingFocusGroupRootStyle = computed(() => {\n      // casting to any for fix compiler error since HTMLElement.StyleValue does not\n      // support CSSProperties\n      return [\n        {\n          outline: 'none',\n        },\n        props.style as StyleValue,\n      ] as any\n    })\n\n    const onItemFocus = (tabbedId: string) => {\n      emit(CURRENT_TAB_ID_CHANGE_EVT, tabbedId)\n    }\n\n    const onItemShiftTab = () => {\n      isBackingOut.value = true\n    }\n\n    const onMousedown = composeEventHandlers(\n      (e: Event) => {\n        props.onMousedown?.(e)\n      },\n      () => {\n        isClickFocus.value = true\n      },\n    )\n\n    const onFocus = composeEventHandlers(\n      (e: FocusEvent) => {\n        props.onFocus?.(e)\n      },\n      e => {\n        const isKeyboardFocus = !unref(isClickFocus)\n        const { target, currentTarget } = e\n        if (\n          target === currentTarget &&\n          isKeyboardFocus &&\n          !unref(isBackingOut)\n        ) {\n          const entryFocusEvt = new Event(ENTRY_FOCUS_EVT, EVT_OPTS)\n          currentTarget?.dispatchEvent(entryFocusEvt)\n\n          if (!entryFocusEvt.defaultPrevented) {\n            const items = getItems<{\n              id: string\n              focusable: boolean\n              active: boolean\n            }>().filter(item => item.focusable)\n            const activeItem = items.find(item => item.active)\n            const currentItem = items.find(\n              item => item.id === unref(currentTabbedId),\n            )\n            const candidates = [activeItem, currentItem, ...items].filter(\n              Boolean,\n            )\n            const candidateNodes = candidates.map(item => item.ref)\n            focusFirst(candidateNodes)\n          }\n        }\n\n        isClickFocus.value = false\n      },\n    )\n\n    const onBlur = composeEventHandlers(\n      (e: Event) => {\n        props.onBlur?.(e)\n      },\n      () => {\n        isBackingOut.value = false\n      },\n    )\n\n    const handleEntryFocus = (...args: any[]) => {\n      emit('entryFocus', ...args)\n    }\n\n    provide(ROVING_FOCUS_GROUP_INJECTION_KEY, {\n      currentTabbedId: readonly(currentTabbedId),\n      loop: toRef(props, 'loop'),\n      tabIndex: computed(() => {\n        return unref(isBackingOut) ? -1 : 0\n      }),\n      rovingFocusGroupRef,\n      rovingFocusGroupRootStyle,\n      orientation: toRef(props, 'orientation'),\n      dir: toRef(props, 'dir'),\n      onItemFocus,\n      onItemShiftTab,\n      onBlur,\n      onFocus,\n      onMousedown,\n    })\n\n    watch(\n      () => props.currentTabId,\n      val => {\n        currentTabbedId.value = val ?? null\n      },\n    )\n\n    useEventListener(rovingFocusGroupRef, ENTRY_FOCUS_EVT, handleEntryFocus)\n  },\n})\n</script>\n"],"names":[],"mappings":";;;;;;;;;AA2BA,MAAM,4BAA4B;AAElC,MAAM,kBAAkB;AACxB,MAAM,WAAsB,EAAE,SAAS,OAAO,YAAY;AAC1D,MAAK,YAAa,gBAAa;AAAA,EAC7B,MAAM;AAAA,EACN,cAAc;AAAA,EACd,OAAO;AAAA,EACP,OAAO,CAAC,2BAA2B,YAAY;AAAA,EAC/C,MAAM,OAAO,EAAE,QAAQ;AACrB,UAAM;AAGN,UAAM,eAAe;AACrB,UAAM,eAAe,IAAI,KAAK;AAC9B,UAAM,0BAA8C;AACpD,UAAM,sBACJ;AAGF,UAAM;AAGJ;AAAO;AACL;AACW;AACX;AACM;AACR;AAGF;AACE,sCAAgC;AAAQ;AAG1C;AACE,2BAAqB;AAAA;AAGvB;AAEI;AAAqB,aAEjB;AACJ,mBAAa;AAAQ,KAEzB;AAEA;AAEI;AAAiB,IACnB;AAEE;AACA;AACA;AAKE,8BAAsB;AACtB,qCAA6B;AAE7B;AACE,yDAIyB,SAAS;AAClC,6BAAmB,0BAAwB;AAC3C;AAGA,gBAAM,0BAA0B;AAGhC,gBAAM,+CAA6C;AACnD,mCAAyB;AAAA;AAC3B;AAGF;AAAqB;AAIzB;AAEI;AAAgB,OAElB;AACE,mBAAa;AAAQ;AAIzB,UAAM,gCAAuC;AAC3C;AAA0B;AAG5B;AAA0C;AACC,MACzC,mBAAmB;AAAM,MACzB;AACE;AAAkC,MACpC;AAAC,MACD;AAAA,MACA;AAAA;AACuC;AAChB,MACvB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAGF;AAGI;AAA+B;AAInC;AAAuE;AAE3E;;;;;;;;;;;;"}