{"version":3,"file":"index.cjs","names":["React"],"sources":["../../../src/components/EventExtender/index.tsx"],"sourcesContent":["import { isFunction } from '@modern-kit/utils';\nimport React from 'react';\n\n/**\n * @description HTML 요소들의 태그 이름 타입 (예: \"div\", \"span\", \"input\" 등)\n */\ntype HTMLElementType = keyof React.JSX.IntrinsicElements;\n\n/**\n * @description React.DOMAttributes<HTMLElement>에 정의된 이벤트\n * - \"on\"으로 시작하는 이벤트 핸들러 이름만 포함 (예: \"onClick\", \"onChange\", \"onSubmit\" 등)\n */\ntype EventNames = keyof React.DOMAttributes<HTMLElement> & `on${string}`;\n\n/**\n * @description 특정 HTML 요소의 특정 이벤트에 대한 이벤트 객체 타입을 추론하는 제네릭 타입\n * @template K - HTML 요소 타입 (예: \"button\", \"input\" 등)\n * @template E - 이벤트 핸들러 이름 (예: \"onClick\", \"onChange\" 등)\n * @returns 해당 이벤트의 이벤트 객체 타입 또는 never\n * @example\n * type InputChangeEvent = ElementEventType<\"input\", \"onChange\">; // React.ChangeEvent<HTMLInputElement>\n * type FormSubmitEvent = ElementEventType<\"form\", \"onSubmit\">; // React.FormEvent<HTMLFormElement>\n * type ButtonClickEvent = ElementEventType<\"button\", \"onClick\">; // React.MouseEvent<HTMLButtonElement, MouseEvent>\n */\ntype ElementEventType<\n  K extends HTMLElementType,\n  E extends EventNames\n> = React.JSX.IntrinsicElements[K][E] extends ((e: infer Event) => void) | undefined\n  ? Event\n  : never;\n\ninterface EventExtenderProps<K extends HTMLElementType, E extends EventNames> {\n  children: React.JSX.Element;\n  capture: E;\n  shouldAwait?: boolean;\n  beforeEvent?: (e: ElementEventType<K, E>) => void | Promise<void>;\n  afterEvent?: (e: ElementEventType<K, E>) => void | Promise<void>;\n}\n\n/**\n * @description 자식 컴포넌트의 이벤트 핸들러를 확장하여 `전후 처리`를 가능하게 하는 컴포넌트입니다.\n *\n * `shouldAwait` 옵션에 따라 다음과 같이 동작합니다:\n *\n * `shouldAwait: false` (기본값)\n * - 비동기 함수를 await 하지 않습니다.\n * - beforeEvent → 원본 이벤트 → afterEvent 순서로 실행되지만, 각 단계의 완료를 기다리지 않습니다.\n * - 일반적인 이벤트 호출 순서를 유지합니다.\n * - 예시: mouseDown -> mouseUp -> click 호출 순서가 유지됩니다.\n *\n * `shouldAwait: true`\n * - 비동기 함수를 await 합니다.\n * - beforeEvent → 원본 이벤트 → afterEvent 순서로 실행을 보장하며, 각 단계의 완료를 기다립니다.\n * - 주의: 일반적인 이벤트 호출 순서와 달라질 수 있습니다.\n * - 예시: `mouseUp` 이벤트는 `click` 이벤트 이전에 호출되는게 일반적이지만, `onMouseUp` 이벤트를 캡처하면 `mouseUp` 이벤트가 `click` 이벤트 이후에 호출됩니다.\n *\n * @template K - HTML 요소 타입 (예: \"button\", \"input\" 등)\n * @template E - 이벤트 핸들러 이름 (예: \"onClick\", \"onChange\" 등)\n * @param {EventExtenderProps<K, E>} props - 컴포넌트 속성\n * @param {JSX.Element} props.children - 단일 자식 컴포넌트 (React 엘리먼트)\n * @param {E} props.capture - 확장하고자 하는 이벤트 핸들러 이름\n * @param {boolean} [props.shouldAwait=false] - 이벤트 핸들러의 비동기 함수를 await 할지 여부. true일 경우 각 핸들러의 완료를 기다립니다.\n * @param {(e: ElementEventType<K, E>) => void | Promise<void>} [props.beforeEvent] - 이벤트 발생 전 실행할 함수, 비동기 함수 허용\n * @param {(e: ElementEventType<K, E>) => void | Promise<void>} [props.afterEvent] - 이벤트 발생 후 실행할 함수, 비동기 함수 허용\n * @returns {JSX.Element} 이벤트가 확장된 자식 컴포넌트\n *\n * @example\n * ```tsx\n * // 기본 사용법\n * <EventExtender\n *   capture=\"onClick\"\n *   beforeEvent={(e: React.MouseEvent<HTMLButtonElement>) => {\n *     console.log('클릭 전', e);\n *   }}\n *   afterEvent={(e: React.MouseEvent<HTMLButtonElement>) => {\n *     console.log('클릭 후', e);\n *   }}\n * >\n *   <button onClick={(e) => console.log('클릭', e)}>\n *     Button\n *   </button>\n * </EventExtender>\n * ```\n *\n * @example\n * ```tsx\n * // 비동기 함수의 완료를 기다립니다.\n * <EventExtender\n *   shouldAwait={true} // (*)\n *   capture=\"onClick\"\n *   beforeEvent={async (e: React.MouseEvent<HTMLButtonElement>) => {\n *     console.log('클릭 전', e);\n *     await asyncFunction();\n *   }}\n *   afterEvent={async (e: React.MouseEvent<HTMLButtonElement>) => {\n *     console.log('클릭 후', e);\n *     await asyncFunction();\n *   }}\n * >\n *   <button onClick={(e: React.MouseEvent<HTMLButtonElement>) => console.log('클릭', e)}>\n *     Button\n *   </button>\n * </EventExtender>\n * ```\n */\nexport const EventExtender = <K extends HTMLElementType, E extends EventNames>({\n  children,\n  capture,\n  shouldAwait = false,\n  beforeEvent,\n  afterEvent,\n}: EventExtenderProps<K, E>): React.JSX.Element => {\n  const child = React.Children.only(children);\n\n  const asyncEvent = async (eventType: ElementEventType<K, E>) => {\n    if (beforeEvent) {\n      await beforeEvent(eventType);\n    }\n\n    const originEvent = child.props[capture];\n    if (isFunction(originEvent)) {\n      await originEvent(eventType);\n    }\n\n    if (afterEvent) {\n      await afterEvent(eventType);\n    }\n  };\n\n  const syncEvent = (eventType: ElementEventType<K, E>) => {\n    if (beforeEvent) {\n      beforeEvent(eventType);\n    }\n\n    const originEvent = child.props[capture];\n    if (isFunction(originEvent)) {\n      originEvent(eventType);\n    }\n\n    if (afterEvent) {\n      afterEvent(eventType);\n    }\n  };\n\n  const enhancedProps = {\n    [capture]: shouldAwait ? asyncEvent : syncEvent,\n  };\n\n  return React.cloneElement(child, enhancedProps);\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyGA,MAAa,iBAAkE,EAC7E,UACA,SACA,cAAc,OACd,aACA,iBACiD;CACjD,MAAM,QAAQA,MAAAA,QAAM,SAAS,KAAK,SAAS;CAE3C,MAAM,aAAa,OAAO,cAAsC;EAC9D,IAAI,aACF,MAAM,YAAY,UAAU;EAG9B,MAAM,cAAc,MAAM,MAAM;EAChC,KAAA,GAAA,kBAAA,YAAe,YAAY,EACzB,MAAM,YAAY,UAAU;EAG9B,IAAI,YACF,MAAM,WAAW,UAAU;;CAI/B,MAAM,aAAa,cAAsC;EACvD,IAAI,aACF,YAAY,UAAU;EAGxB,MAAM,cAAc,MAAM,MAAM;EAChC,KAAA,GAAA,kBAAA,YAAe,YAAY,EACzB,YAAY,UAAU;EAGxB,IAAI,YACF,WAAW,UAAU;;CAIzB,MAAM,gBAAgB,GACnB,UAAU,cAAc,aAAa,WACvC;CAED,OAAOA,MAAAA,QAAM,aAAa,OAAO,cAAc"}