@ehfuse/overlay-scrollbar 1.6.0 → 1.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/OverlayScrollbar.d.ts +86 -0
- package/dist/OverlayScrollbar.d.ts.map +1 -0
- package/dist/components/ScrollbarArrows.d.ts +29 -0
- package/dist/components/ScrollbarArrows.d.ts.map +1 -0
- package/dist/components/ScrollbarThumb.d.ts +35 -0
- package/dist/components/ScrollbarThumb.d.ts.map +1 -0
- package/dist/components/ScrollbarTrack.d.ts +32 -0
- package/dist/components/ScrollbarTrack.d.ts.map +1 -0
- package/dist/hooks/useArrowNavigation.d.ts +27 -0
- package/dist/hooks/useArrowNavigation.d.ts.map +1 -0
- package/dist/hooks/useAutoHide.d.ts +19 -0
- package/dist/hooks/useAutoHide.d.ts.map +1 -0
- package/dist/hooks/useDragScroll.d.ts +23 -0
- package/dist/hooks/useDragScroll.d.ts.map +1 -0
- package/dist/hooks/useKeyboardNavigation.d.ts +18 -0
- package/dist/hooks/useKeyboardNavigation.d.ts.map +1 -0
- package/dist/hooks/useScrollEvents.d.ts +20 -0
- package/dist/hooks/useScrollEvents.d.ts.map +1 -0
- package/dist/hooks/useScrollbarConfig.d.ts +53 -0
- package/dist/hooks/useScrollbarConfig.d.ts.map +1 -0
- package/dist/hooks/useScrollbarInitialization.d.ts +21 -0
- package/dist/hooks/useScrollbarInitialization.d.ts.map +1 -0
- package/dist/hooks/useScrollbarUpdate.d.ts +27 -0
- package/dist/hooks/useScrollbarUpdate.d.ts.map +1 -0
- package/dist/hooks/useThumbDrag.d.ts +25 -0
- package/dist/hooks/useThumbDrag.d.ts.map +1 -0
- package/dist/hooks/useTrackClick.d.ts +20 -0
- package/dist/hooks/useTrackClick.d.ts.map +1 -0
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +43 -21
- package/dist/index.esm.js.map +4 -4
- package/dist/index.js +43 -21
- package/dist/index.js.map +4 -4
- package/dist/src/OverlayScrollbar.d.ts +61 -2
- package/dist/src/OverlayScrollbar.d.ts.map +1 -1
- package/dist/types.d.ts +70 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/dragScrollUtils.d.ts +40 -0
- package/dist/utils/dragScrollUtils.d.ts.map +1 -0
- package/package.json +4 -11
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../index.ts", "../src/OverlayScrollbar.tsx", "../src/
|
|
4
|
-
"sourcesContent": ["export { default } from \"./src/OverlayScrollbar\";\nexport { default as OverlayScrollbar } from \"./src/OverlayScrollbar\";\nexport type {\n OverlayScrollbarRef,\n OverlayScrollbarProps,\n ThumbConfig,\n TrackConfig,\n ArrowsConfig,\n DragScrollConfig,\n AutoHideConfig,\n} from \"./src/types\";\n", "/**\n * OverlayScrollbar.tsx\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport {\n useRef,\n useState,\n useCallback,\n forwardRef,\n useImperativeHandle,\n} from \"react\";\nimport {\n OverlayScrollbarProps,\n OverlayScrollbarRef,\n DEFAULT_THUMB_CONFIG,\n DEFAULT_TRACK_CONFIG,\n DEFAULT_ARROWS_CONFIG,\n DEFAULT_DRAG_SCROLL_CONFIG,\n DEFAULT_AUTO_HIDE_CONFIG,\n} from \"./types\";\nimport { useScrollbarConfig } from \"./hooks/useScrollbarConfig\";\nimport { useScrollbarUpdate } from \"./hooks/useScrollbarUpdate\";\nimport { useThumbDrag } from \"./hooks/useThumbDrag\";\nimport { useTrackClick } from \"./hooks/useTrackClick\";\nimport { useArrowNavigation } from \"./hooks/useArrowNavigation\";\nimport { useDragScroll } from \"./hooks/useDragScroll\";\nimport { useScrollEvents } from \"./hooks/useScrollEvents\";\nimport { useKeyboardNavigation } from \"./hooks/useKeyboardNavigation\";\nimport { useScrollbarInitialization } from \"./hooks/useScrollbarInitialization\";\nimport { ScrollbarTrack } from \"./components/ScrollbarTrack\";\nimport { ScrollbarThumb } from \"./components/ScrollbarThumb\";\nimport { ScrollbarArrows } from \"./components/ScrollbarArrows\";\n\nconst OverlayScrollbar = forwardRef<OverlayScrollbarRef, OverlayScrollbarProps>(\n (\n {\n className = \"\",\n style = {},\n containerStyle = {},\n contentStyle = {},\n children,\n onScroll,\n\n // \uADF8\uB8F9\uD654\uB41C \uC124\uC815 \uAC1D\uCCB4\uB4E4\n thumb = DEFAULT_THUMB_CONFIG,\n track = DEFAULT_TRACK_CONFIG,\n arrows = DEFAULT_ARROWS_CONFIG,\n dragScroll = DEFAULT_DRAG_SCROLL_CONFIG,\n autoHide = DEFAULT_AUTO_HIDE_CONFIG,\n\n // \uAE30\uD0C0 \uC124\uC815\uB4E4\n showScrollbar = true,\n detectInnerScroll = false,\n },\n ref\n ) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const scrollbarRef = useRef<HTMLDivElement>(null);\n const thumbRef = useRef<HTMLDivElement>(null);\n\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uCE90\uC2F1\uC6A9 ref (\uC131\uB2A5 \uCD5C\uC801\uD654)\n const cachedScrollContainerRef = useRef<HTMLElement | null>(null);\n\n // \uAE30\uBCF8 \uC0C1\uD0DC\uB4E4\n const [scrollbarVisible, setScrollbarVisible] = useState(false);\n\n // \uC228\uAE40 \uD0C0\uC774\uBA38\n const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // useScrollbarConfig \uD6C5 \uC0AC\uC6A9 - \uC124\uC815 \uACC4\uC0B0\n const {\n finalThumbConfig,\n finalTrackConfig,\n finalArrowsConfig,\n finalDragScrollConfig,\n finalAutoHideConfig,\n } = useScrollbarConfig({\n thumb,\n track,\n arrows,\n dragScroll,\n autoHide,\n });\n\n // \uC790\uC8FC \uC0AC\uC6A9\uB418\uB294 \uBCC0\uC218\uB4E4\n const finalThumbWidth = finalThumbConfig.width;\n const finalTrackWidth = finalTrackConfig.width;\n const thumbMinHeight = finalThumbConfig.minHeight;\n const showArrows = finalArrowsConfig.visible;\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 \uD568\uC218 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n const maintainFocus = useCallback(() => {\n if (!containerRef.current) return;\n\n // \uD604\uC7AC \uD3EC\uCEE4\uC2A4\uB41C \uC694\uC18C \uD655\uC778\n const activeElement = document.activeElement;\n\n // \uC624\uBC84\uB808\uC774 \uC2A4\uD06C\uB864\uBC14 \uB0B4\uBD80\uC5D0 \uC774\uBBF8 \uD3EC\uCEE4\uC2A4\uB41C \uC694\uC18C\uAC00 \uC788\uC73C\uBA74 \uC2A4\uD0B5\n if (\n activeElement &&\n containerRef.current.contains(activeElement) &&\n activeElement !== containerRef.current\n ) {\n return;\n }\n\n // \uD3EC\uCEE4\uC2A4\uB41C \uC694\uC18C\uAC00 \uC5C6\uAC70\uB098 \uC678\uBD80\uC5D0 \uC788\uC73C\uBA74 \uCEE8\uD14C\uC774\uB108\uC5D0 \uD3EC\uCEE4\uC2A4\n containerRef.current.focus();\n }, []);\n\n // \uCEE8\uD14C\uC774\uB108 \uD074\uB9AD \uC2DC \uD3EC\uCEE4\uC2A4 (\uD0A4\uBCF4\uB4DC \uC791\uB3D9\uC744 \uC704\uD574)\n const handleContainerClick = useCallback((e: React.MouseEvent) => {\n // \uD14D\uC2A4\uD2B8 \uC120\uD0DD\uC774\uB098 \uB2E4\uB978 \uC0C1\uD638\uC791\uC6A9\uC744 \uBC29\uD574\uD558\uC9C0 \uC54A\uB3C4\uB85D \uCCB4\uD06C\n const target = e.target as HTMLElement;\n\n // input, textarea, button \uB4F1\uC740 \uC81C\uC678\n if (\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.tagName === \"BUTTON\" ||\n target.tagName === \"SELECT\" ||\n target.isContentEditable\n ) {\n return;\n }\n\n // \uCEE8\uD14C\uC774\uB108\uC5D0 \uD3EC\uCEE4\uC2A4 (\uD0A4\uBCF4\uB4DC \uC774\uBCA4\uD2B8 \uD65C\uC131\uD654)\n if (\n containerRef.current &&\n containerRef.current !== document.activeElement\n ) {\n containerRef.current.focus();\n }\n }, []);\n\n // ref\uB97C \uD1B5\uD574 \uC678\uBD80\uC5D0\uC11C \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108\uC5D0 \uC811\uADFC\uD560 \uC218 \uC788\uB3C4\uB85D \uD568\n useImperativeHandle(\n ref,\n () => ({\n getScrollContainer: () => containerRef.current,\n scrollTo: (options: ScrollToOptions) => {\n if (containerRef.current) {\n containerRef.current.scrollTo(options);\n }\n },\n get scrollTop() {\n return containerRef.current?.scrollTop || 0;\n },\n get scrollHeight() {\n return containerRef.current?.scrollHeight || 0;\n },\n get clientHeight() {\n return containerRef.current?.clientHeight || 0;\n },\n }),\n []\n );\n\n // \uC2E4\uC81C \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C \uCC3E\uAE30 (\uCE90\uC2F1 \uCD5C\uC801\uD654)\n const findScrollableElement = useCallback((): HTMLElement | null => {\n // \uCE90\uC2DC\uB41C \uC694\uC18C\uAC00 \uC5EC\uC804\uD788 \uC720\uD6A8\uD55C\uC9C0 \uD655\uC778\n if (cachedScrollContainerRef.current) {\n const cached = cachedScrollContainerRef.current;\n // DOM\uC5D0 \uC5F0\uACB0\uB418\uC5B4 \uC788\uACE0 \uC5EC\uC804\uD788 \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C\uC9C0 \uD655\uC778\n if (\n document.contains(cached) &&\n cached.scrollHeight > cached.clientHeight + 2\n ) {\n return cached;\n }\n // \uCE90\uC2DC \uBB34\uD6A8\uD654\n cachedScrollContainerRef.current = null;\n }\n\n if (!containerRef.current) {\n return null;\n }\n\n // \uB0B4\uBD80 \uCEE8\uD14C\uC774\uB108\uC758 \uC2A4\uD06C\uB864 \uAC00\uB2A5 \uC5EC\uBD80 \uD655\uC778\n if (\n contentRef.current &&\n contentRef.current.scrollHeight >\n containerRef.current.clientHeight + 2\n ) {\n cachedScrollContainerRef.current = containerRef.current;\n return containerRef.current;\n }\n\n // detectInnerScroll \uC635\uC158\uC774 \uD65C\uC131\uD654\uB41C \uACBD\uC6B0\uC5D0\uB9CC children \uB0B4\uBD80\uC758 \uC2A4\uD06C\uB864 \uC694\uC18C \uCC3E\uAE30\n // (\uAC00\uC0C1 \uD14C\uC774\uBE14 \uB4F1 \uB0B4\uBD80\uC5D0\uC11C \uC2A4\uD06C\uB864\uC744 \uCC98\uB9AC\uD558\uB294 \uACBD\uC6B0\uC5D0 \uC0AC\uC6A9)\n if (!detectInnerScroll) {\n return null;\n }\n\n // children \uC694\uC18C\uC5D0\uC11C \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C \uCC3E\uAE30\n // \uC911\uCCA9\uB41C OverlayScrollbar\uC758 \uC601\uC5ED\uC740 \uC81C\uC678 (\uB2E4\uB978 OverlayScrollbar\uC758 container\uB294 \uC2A4\uD0B5)\n const childScrollableElements =\n containerRef.current.querySelectorAll(\n '[data-virtuoso-scroller], [style*=\"overflow\"], .virtuoso-scroller, [style*=\"overflow: auto\"], [style*=\"overflow:auto\"]'\n );\n\n for (const child of childScrollableElements) {\n const element = child as HTMLElement;\n\n // \uC774 \uC694\uC18C\uAC00 \uB2E4\uB978 OverlayScrollbar\uC758 container\uC778\uC9C0 \uD655\uC778\n // (\uC790\uC2E0\uC758 containerRef\uB294 \uC544\uB2C8\uC5B4\uC57C \uD558\uACE0, overlay-scrollbar-container \uD074\uB798\uC2A4\uB97C \uAC00\uC9C4 \uACBD\uC6B0)\n if (\n element !== containerRef.current &&\n element.classList.contains(\"overlay-scrollbar-container\")\n ) {\n // \uC911\uCCA9\uB41C OverlayScrollbar\uC758 container\uC774\uBBC0\uB85C \uC2A4\uD0B5\n continue;\n }\n\n // \uC774 \uC694\uC18C\uC758 \uBD80\uBAA8 \uC911\uC5D0 \uB2E4\uB978 OverlayScrollbar container\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\n let parent: HTMLElement | null = element.parentElement;\n let isNestedInAnotherScrollbar = false;\n\n while (parent && parent !== containerRef.current) {\n if (\n parent.classList.contains(\n \"overlay-scrollbar-container\"\n ) &&\n parent !== containerRef.current\n ) {\n // \uB2E4\uB978 OverlayScrollbar \uB0B4\uBD80\uC758 \uC694\uC18C\uC774\uBBC0\uB85C \uC2A4\uD0B5\n isNestedInAnotherScrollbar = true;\n break;\n }\n parent = parent.parentElement;\n }\n\n if (isNestedInAnotherScrollbar) {\n continue;\n }\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C\uC778\uC9C0 \uD655\uC778\n if (element.scrollHeight > element.clientHeight + 2) {\n cachedScrollContainerRef.current = element;\n return element;\n }\n }\n\n return null;\n }, []);\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5 \uC5EC\uBD80 \uCCB4\uD06C\n const isScrollable = useCallback(() => {\n return findScrollableElement() !== null;\n }, [findScrollableElement]);\n\n // \uD0C0\uC774\uBA38 \uC815\uB9AC\n const clearHideTimer = useCallback(() => {\n if (hideTimeoutRef.current) {\n clearTimeout(hideTimeoutRef.current);\n hideTimeoutRef.current = null;\n }\n }, []);\n\n // \uC2A4\uD06C\uB864\uBC14 \uC228\uAE30\uAE30 \uD0C0\uC774\uBA38\n const setHideTimer = useCallback(\n (delay: number) => {\n // \uC790\uB3D9 \uC228\uAE40\uC774 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uC73C\uBA74 \uD0C0\uC774\uBA38\uB97C \uC124\uC815\uD558\uC9C0 \uC54A\uC74C\n if (!finalAutoHideConfig.enabled) {\n return;\n }\n clearHideTimer();\n hideTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(false);\n hideTimeoutRef.current = null;\n }, delay);\n },\n [clearHideTimer, finalAutoHideConfig.enabled]\n );\n\n // useScrollbarUpdate \uD6C5 \uC0AC\uC6A9\n const { thumbHeight, thumbTop, hasScrollableContent, updateScrollbar } =\n useScrollbarUpdate({\n wrapperRef,\n scrollbarRef,\n contentRef,\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n thumb: finalThumbConfig,\n track: finalTrackConfig,\n arrows: finalArrowsConfig,\n autoHide: finalAutoHideConfig,\n });\n\n // useThumbDrag \uD6C5 \uC0AC\uC6A9\n const {\n isDragging,\n isThumbHovered,\n setIsThumbHovered,\n handleThumbMouseDown,\n } = useThumbDrag({\n findScrollableElement,\n thumbHeight,\n clearHideTimer,\n setScrollbarVisible,\n updateScrollbar,\n setHideTimer,\n hideDelay: finalAutoHideConfig.delay,\n isScrollable,\n maintainFocus,\n });\n\n // useDragScroll \uD6C5 \uC0AC\uC6A9\n const { isDragScrolling, handleDragScrollStart } = useDragScroll({\n dragScroll: finalDragScrollConfig,\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n updateScrollbar,\n setHideTimer,\n hideDelay: finalAutoHideConfig.delay,\n isScrollable,\n });\n\n // useTrackClick \uD6C5 \uC0AC\uC6A9\n const { handleTrackClick } = useTrackClick({\n scrollbarRef,\n findScrollableElement,\n updateScrollbar,\n setScrollbarVisible,\n setHideTimer,\n hideDelay: finalAutoHideConfig.delay,\n maintainFocus,\n });\n\n // useArrowNavigation \uD6C5 \uC0AC\uC6A9\n const {\n hoveredArrow,\n setHoveredArrow,\n handleUpArrowClick,\n handleDownArrowClick,\n } = useArrowNavigation({\n arrows: finalArrowsConfig,\n containerRef,\n contentRef,\n updateScrollbar,\n setScrollbarVisible,\n setHideTimer,\n hideDelay: finalAutoHideConfig.delay,\n maintainFocus,\n });\n\n // useScrollEvents \uD6C5 \uC0AC\uC6A9\n useScrollEvents({\n containerRef,\n findScrollableElement,\n updateScrollbar,\n clearHideTimer,\n setScrollbarVisible,\n setHideTimer,\n autoHide: finalAutoHideConfig,\n onScroll,\n });\n\n // useKeyboardNavigation \uD6C5 \uC0AC\uC6A9\n useKeyboardNavigation({\n containerRef,\n findScrollableElement,\n updateScrollbar,\n clearHideTimer,\n setScrollbarVisible,\n setHideTimer,\n hideDelay: finalAutoHideConfig.delay,\n });\n\n // useScrollbarInitialization \uD6C5 \uC0AC\uC6A9\n useScrollbarInitialization({\n containerRef,\n contentRef,\n cachedScrollContainerRef,\n updateScrollbar,\n setScrollbarVisible,\n isScrollable,\n autoHide: finalAutoHideConfig,\n });\n\n // trackWidth\uAC00 thumbWidth\uBCF4\uB2E4 \uC791\uC73C\uBA74 thumbWidth\uC640 \uAC19\uAC8C \uC124\uC815\n const adjustedTrackWidth = Math.max(finalTrackWidth, finalThumbWidth);\n\n return (\n <div\n ref={wrapperRef}\n className={`overlay-scrollbar-wrapper ${className}`}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n minHeight: 0, // shrink \uAC00\uB2A5\uD558\uB3C4\uB85D\n height: \"100%\", // \uBD80\uBAA8\uC758 \uC804\uCCB4 \uB192\uC774 \uC0AC\uC6A9\n flex: \"1 1 0%\", // \uAE30\uBCF8\uC801\uC73C\uB85C flex item\uC73C\uB85C \uB3D9\uC791\n ...style, // \uC0AC\uC6A9\uC790\uAC00 flex\uB97C override \uD560 \uC218 \uC788\uB3C4\uB85D style\uC744 \uB4A4\uC5D0 \uBC30\uCE58\n }}\n >\n {/* \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 */}\n <div\n ref={containerRef}\n className=\"overlay-scrollbar-container\"\n tabIndex={0} // \uD0A4\uBCF4\uB4DC \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5\uD558\uAC8C \uD568 (\uD074\uB9AD\uC73C\uB85C \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5)\n onClick={handleContainerClick}\n onMouseDown={handleDragScrollStart}\n style={{\n display: \"flex\",\n width: \"100%\", // \uBA85\uC2DC\uC801 \uB108\uBE44 \uC124\uC815\n flex: \"1 1 auto\", // flex item\uC73C\uB85C \uC124\uC815\uD558\uC5EC \uB192\uC774\uB97C \uC790\uB3D9\uC73C\uB85C \uACC4\uC0B0\n minHeight: 0, // \uCD5C\uC18C \uB192\uC774 \uBCF4\uC7A5\n overflow: \"auto\", // \uB124\uC774\uD2F0\uBE0C \uC2A4\uD06C\uB864 \uAE30\uB2A5 \uC720\uC9C0\n // \uBE0C\uB77C\uC6B0\uC800 \uAE30\uBCF8 \uC2A4\uD06C\uB864\uBC14\uB9CC \uC228\uAE30\uAE30\n scrollbarWidth: \"none\", // Firefox\n msOverflowStyle: \"none\", // IE/Edge\n // \uD0A4\uBCF4\uB4DC \uD3EC\uCEE4\uC2A4 \uC2A4\uD0C0\uC77C (\uC811\uADFC\uC131)\n outline: \"none\", // \uAE30\uBCF8 \uC544\uC6C3\uB77C\uC778 \uC81C\uAC70\n userSelect: isDragScrolling ? \"none\" : \"auto\", // \uB4DC\uB798\uADF8 \uC911 \uD14D\uC2A4\uD2B8 \uC120\uD0DD \uBC29\uC9C0\n ...containerStyle, // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC2A4\uD0C0\uC77C \uC801\uC6A9\n }}\n >\n <div\n ref={contentRef}\n className=\"overlay-scrollbar-content\"\n style={{\n flex: \"1 1 0%\", // grow\uD558\uC5EC \uACF5\uAC04 \uCC44\uC6B0\uAE30\n minHeight: 0, // flex shrink \uD5C8\uC6A9\n display: \"flex\", // flex \uCEE8\uD14C\uC774\uB108\uB85C \uC124\uC815\n flexDirection: \"column\", // \uC138\uB85C \uBC29\uD5A5 \uC815\uB82C\n ...contentStyle, // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC2A4\uD0C0\uC77C \uC801\uC6A9\n }}\n >\n {children}\n </div>\n </div>\n\n {/* \uCEE4\uC2A4\uD140 \uC2A4\uD06C\uB864\uBC14 */}\n {showScrollbar && hasScrollableContent && (\n <ScrollbarTrack\n scrollbarRef={scrollbarRef}\n adjustedTrackWidth={adjustedTrackWidth}\n scrollbarVisible={scrollbarVisible}\n isDragging={isDragging}\n showArrows={showArrows}\n finalThumbWidth={finalThumbWidth}\n finalTrackConfig={finalTrackConfig}\n clearHideTimer={clearHideTimer}\n setScrollbarVisible={setScrollbarVisible}\n setHideTimer={setHideTimer}\n autoHideDelay={finalAutoHideConfig.delay}\n handleTrackClick={handleTrackClick}\n >\n <ScrollbarThumb\n thumbRef={thumbRef}\n thumbTop={thumbTop}\n thumbHeight={thumbHeight}\n thumbMinHeight={thumbMinHeight}\n showArrows={showArrows}\n finalThumbWidth={finalThumbWidth}\n adjustedTrackWidth={adjustedTrackWidth}\n isDragging={isDragging}\n isThumbHovered={isThumbHovered}\n finalThumbConfig={finalThumbConfig}\n finalTrackConfig={finalTrackConfig}\n handleThumbMouseDown={handleThumbMouseDown}\n setIsThumbHovered={setIsThumbHovered}\n />\n </ScrollbarTrack>\n )}\n\n {/* \uD654\uC0B4\uD45C \uBC84\uD2BC\uB4E4 */}\n {showScrollbar && hasScrollableContent && showArrows && (\n <ScrollbarArrows\n adjustedTrackWidth={adjustedTrackWidth}\n finalThumbWidth={finalThumbWidth}\n scrollbarVisible={scrollbarVisible}\n hoveredArrow={hoveredArrow}\n finalArrowsConfig={finalArrowsConfig}\n finalTrackConfig={finalTrackConfig}\n setHoveredArrow={setHoveredArrow}\n handleUpArrowClick={handleUpArrowClick}\n handleDownArrowClick={handleDownArrowClick}\n />\n )}\n </div>\n );\n }\n);\n\nOverlayScrollbar.displayName = \"OverlayScrollbar\";\n\nexport default OverlayScrollbar;\n", "/**\n * types.ts\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { ReactNode } from \"react\";\n\n// thumb \uAD00\uB828 \uC124\uC815\nexport interface ThumbConfig {\n width?: number; // \uC378\uC758 \uB108\uBE44 (\uAE30\uBCF8\uAC12: 8px)\n minHeight?: number; // \uC378\uC758 \uCD5C\uC18C \uB192\uC774 (\uAE30\uBCF8\uAC12: 50px)\n radius?: number; // \uC378\uC758 border-radius (\uAE30\uBCF8\uAC12: width / 2)\n color?: string; // \uC378 \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: \"#606060\")\n opacity?: number; // \uAE30\uBCF8 \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC12: 0.6)\n hoverColor?: string; // \uD638\uBC84 \uC2DC \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: color \uB3D9\uC77C)\n hoverOpacity?: number; // \uD638\uBC84 \uC2DC \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC12: 1.0)\n}\n\n// track \uAD00\uB828 \uC124\uC815\nexport interface TrackConfig {\n width?: number; // \uD638\uBC84 \uC601\uC5ED\uC778 \uD2B8\uB799\uC758 \uB108\uBE44 (\uAE30\uBCF8\uAC12: 16px)\n color?: string; // \uD2B8\uB799 \uBC30\uACBD \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: \"rgba(128, 128, 128, 0.1)\")\n visible?: boolean; // \uD2B8\uB799 \uBC30\uACBD \uD45C\uC2DC \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n alignment?: \"center\" | \"right\"; // \uD2B8\uB799 \uB0B4\uBD80 \uC815\uB82C (\uAE30\uBCF8\uAC12: \"center\")\n radius?: number; // \uD2B8\uB799 \uBC30\uACBD\uC758 border-radius (\uAE30\uBCF8\uAC12: thumb.radius \uB610\uB294 4px)\n margin?: number; // \uD2B8\uB799 \uC0C1\uD558 \uB9C8\uC9C4 (\uAE30\uBCF8\uAC12: 4px)\n}\n\n// arrows \uAD00\uB828 \uC124\uC815\nexport interface ArrowsConfig {\n visible?: boolean; // \uD654\uC0B4\uD45C \uD45C\uC2DC \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: false)\n step?: number; // \uD654\uC0B4\uD45C \uD074\uB9AD\uC2DC \uC2A4\uD06C\uB864 \uC774\uB3D9 \uAC70\uB9AC (\uAE30\uBCF8\uAC12: 50px)\n color?: string; // \uD654\uC0B4\uD45C \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: \"#808080\")\n opacity?: number; // \uAE30\uBCF8 \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC12: 0.6)\n hoverColor?: string; // \uD638\uBC84 \uC2DC \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: color \uB3D9\uC77C)\n hoverOpacity?: number; // \uD638\uBC84 \uC2DC \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC12: 1.0)\n}\n\n// \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAD00\uB828 \uC124\uC815\nexport interface DragScrollConfig {\n enabled?: boolean; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uD65C\uC131\uD654 \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n excludeClasses?: string[]; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uCD94\uAC00 \uD074\uB798\uC2A4\uB4E4 (\uC790\uC2E0 \uB610\uB294 \uBD80\uBAA8 \uC694\uC18C \uD655\uC778, \uCD5C\uB300 5\uB2E8\uACC4)\n excludeSelectors?: string[]; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uCD94\uAC00 CSS \uC140\uB809\uD130\uB4E4 (element.matches() \uC0AC\uC6A9)\n}\n\n// \uC790\uB3D9 \uC228\uAE40 \uAD00\uB828 \uC124\uC815\nexport interface AutoHideConfig {\n enabled?: boolean; // \uC790\uB3D9 \uC228\uAE40 \uD65C\uC131\uD654 \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n delay?: number; // \uAE30\uBCF8 \uC790\uB3D9 \uC228\uAE40 \uC2DC\uAC04 (\uAE30\uBCF8\uAC12: 1500ms)\n delayOnWheel?: number; // \uD720 \uC2A4\uD06C\uB864 \uD6C4 \uC790\uB3D9 \uC228\uAE40 \uC2DC\uAC04 (\uAE30\uBCF8\uAC12: 700ms)\n}\n\nexport interface OverlayScrollbarProps {\n className?: string;\n style?: React.CSSProperties; // wrapper div\uC5D0 \uC801\uC6A9\uD560 \uC2A4\uD0C0\uC77C\n containerStyle?: React.CSSProperties; // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 div\uC5D0 \uC801\uC6A9\uD560 \uC2A4\uD0C0\uC77C\n contentStyle?: React.CSSProperties; // \uB0B4\uBD80 content div\uC5D0 \uC801\uC6A9\uD560 \uC2A4\uD0C0\uC77C\n children: ReactNode;\n onScroll?: (event: Event) => void;\n\n // \uADF8\uB8F9\uD654\uB41C \uC124\uC815 \uAC1D\uCCB4\uB4E4\n thumb?: ThumbConfig; // \uC378 \uAD00\uB828 \uC124\uC815\n track?: TrackConfig; // \uD2B8\uB799 \uAD00\uB828 \uC124\uC815\n arrows?: ArrowsConfig; // \uD654\uC0B4\uD45C\uB4E4 \uAD00\uB828 \uC124\uC815\n dragScroll?: DragScrollConfig; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAD00\uB828 \uC124\uC815\n autoHide?: AutoHideConfig; // \uC790\uB3D9 \uC228\uAE40 \uAD00\uB828 \uC124\uC815\n\n // \uAE30\uD0C0 \uC124\uC815\uB4E4\n showScrollbar?: boolean; // \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n detectInnerScroll?: boolean; // children \uB0B4\uBD80\uC758 \uC2A4\uD06C\uB864 \uC694\uC18C \uAC10\uC9C0 \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: false, \uAC00\uC0C1 \uD14C\uC774\uBE14 \uB4F1\uC5D0 \uC0AC\uC6A9)\n}\n\n// OverlayScrollbar\uAC00 \uB178\uCD9C\uD560 \uBA54\uC11C\uB4DC\uB4E4\nexport interface OverlayScrollbarRef {\n getScrollContainer: () => HTMLDivElement | null;\n scrollTo: (options: ScrollToOptions) => void;\n scrollTop: number;\n scrollHeight: number;\n clientHeight: number;\n}\n\n// \uAE30\uBCF8 \uC124\uC815 \uAC1D\uCCB4\uB4E4\uC744 \uC0C1\uC218\uB85C \uC120\uC5B8 (\uC7AC\uB80C\uB354\uB9C1 \uC2DC \uB3D9\uC77C\uD55C \uCC38\uC870 \uC720\uC9C0)\nexport const DEFAULT_THUMB_CONFIG: ThumbConfig = {};\nexport const DEFAULT_TRACK_CONFIG: TrackConfig = {};\nexport const DEFAULT_ARROWS_CONFIG: ArrowsConfig = {};\nexport const DEFAULT_DRAG_SCROLL_CONFIG: DragScrollConfig = {};\nexport const DEFAULT_AUTO_HIDE_CONFIG: AutoHideConfig = {};\n", "/**\n * useScrollbarConfig.ts\n * \uC2A4\uD06C\uB864\uBC14 \uC124\uC815 \uACC4\uC0B0 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useMemo } from \"react\";\nimport {\n ThumbConfig,\n TrackConfig,\n ArrowsConfig,\n DragScrollConfig,\n AutoHideConfig,\n} from \"../types\";\n\ninterface UseScrollbarConfigProps {\n thumb: ThumbConfig;\n track: TrackConfig;\n arrows: ArrowsConfig;\n dragScroll: DragScrollConfig;\n autoHide: AutoHideConfig;\n}\n\nexport const useScrollbarConfig = ({\n thumb,\n track,\n arrows,\n dragScroll,\n autoHide,\n}: UseScrollbarConfigProps) => {\n // Thumb \uC124\uC815\n const finalThumbConfig = useMemo(() => {\n const baseColor = thumb.color ?? \"#606060\";\n return {\n width: thumb.width ?? 8,\n minHeight: thumb.minHeight ?? 50,\n radius: thumb.radius ?? (thumb.width ?? 8) / 2,\n color: baseColor,\n opacity: thumb.opacity ?? 0.6,\n hoverColor: thumb.hoverColor ?? baseColor,\n hoverOpacity: thumb.hoverOpacity ?? 1.0,\n };\n }, [thumb]);\n\n // Track \uC124\uC815\n const finalTrackConfig = useMemo(\n () => ({\n width: track.width ?? 16,\n color: track.color ?? \"rgba(128, 128, 128, 0.1)\",\n visible: track.visible ?? true,\n alignment: track.alignment ?? \"center\",\n radius: track.radius ?? finalThumbConfig.radius ?? 4,\n margin: track.margin ?? 4,\n }),\n [track, finalThumbConfig.radius]\n );\n\n // Arrows \uC124\uC815\n const finalArrowsConfig = useMemo(() => {\n const baseColor = arrows.color ?? \"#808080\";\n return {\n visible: arrows.visible ?? false,\n step: arrows.step ?? 50,\n color: baseColor,\n opacity: arrows.opacity ?? 0.6,\n hoverColor: arrows.hoverColor ?? baseColor,\n hoverOpacity: arrows.hoverOpacity ?? 1.0,\n };\n }, [arrows]);\n\n // DragScroll \uC124\uC815\n const finalDragScrollConfig = useMemo(\n () => ({\n enabled: dragScroll.enabled ?? true,\n excludeClasses: dragScroll.excludeClasses ?? [],\n excludeSelectors: dragScroll.excludeSelectors ?? [],\n }),\n [dragScroll]\n );\n\n // AutoHide \uC124\uC815\n const finalAutoHideConfig = useMemo(\n () => ({\n enabled: autoHide.enabled ?? true,\n delay: autoHide.delay ?? 1500,\n delayOnWheel: autoHide.delayOnWheel ?? 700,\n }),\n [autoHide]\n );\n\n return {\n finalThumbConfig,\n finalTrackConfig,\n finalArrowsConfig,\n finalDragScrollConfig,\n finalAutoHideConfig,\n };\n};\n", "/**\n * useScrollbarUpdate.ts\n * \uC2A4\uD06C\uB864\uBC14 \uC5C5\uB370\uC774\uD2B8 \uAD00\uB828 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useState, useCallback, useEffect } from \"react\";\nimport {\n ThumbConfig,\n TrackConfig,\n ArrowsConfig,\n AutoHideConfig,\n} from \"../types\";\n\ninterface UseScrollbarUpdateProps {\n wrapperRef: React.RefObject<HTMLDivElement>;\n scrollbarRef: React.RefObject<HTMLDivElement>;\n contentRef: React.RefObject<HTMLDivElement>;\n findScrollableElement: () => HTMLElement | null;\n clearHideTimer: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n thumb: ThumbConfig;\n track: TrackConfig;\n arrows: ArrowsConfig;\n autoHide: AutoHideConfig;\n}\n\nexport const useScrollbarUpdate = ({\n wrapperRef,\n scrollbarRef,\n contentRef,\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n thumb,\n track,\n arrows,\n autoHide,\n}: UseScrollbarUpdateProps) => {\n const [thumbHeight, setThumbHeight] = useState(0);\n const [thumbTop, setThumbTop] = useState(0);\n const [hasScrollableContent, setHasScrollableContent] = useState(false);\n\n const thumbMinHeight = thumb.minHeight ?? 50;\n const finalThumbWidth = thumb.width ?? 8;\n const showArrows = arrows.visible ?? false;\n const finalTrackMargin = track.margin ?? 4;\n const autoHideEnabled = autoHide.enabled ?? true;\n\n // \uC2A4\uD06C\uB864\uBC14 \uC704\uCE58 \uBC0F \uD06C\uAE30 \uC5C5\uB370\uC774\uD2B8\n const updateScrollbar = useCallback(() => {\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) {\n // \uC2A4\uD06C\uB864 \uBD88\uAC00\uB2A5\uD558\uBA74 \uC228\uAE40\n setScrollbarVisible(false);\n setHasScrollableContent(false);\n clearHideTimer();\n return;\n }\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uCF58\uD150\uCE20\uAC00 \uC788\uC74C\uC744 \uD45C\uC2DC\n setHasScrollableContent(true);\n\n if (!scrollbarRef.current) return;\n\n // \uC790\uB3D9 \uC228\uAE40\uC774 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uC73C\uBA74 \uC2A4\uD06C\uB864\uBC14\uB97C \uD56D\uC0C1 \uD45C\uC2DC\n if (!autoHideEnabled) {\n setScrollbarVisible(true);\n clearHideTimer();\n }\n\n const containerHeight = scrollableElement.clientHeight;\n const contentHeight = scrollableElement.scrollHeight;\n const scrollTop = scrollableElement.scrollTop;\n\n // wrapper\uC758 \uD328\uB529 \uACC4\uC0B0 (\uC0C1\uD558 \uD328\uB529\uB9CC \uD544\uC694)\n let wrapperPaddingTopBottom = 0;\n if (wrapperRef.current) {\n const computedStyle = window.getComputedStyle(wrapperRef.current);\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\n const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;\n wrapperPaddingTopBottom = paddingTop + paddingBottom;\n }\n\n // \uD654\uC0B4\uD45C\uC640 \uAC04\uACA9 \uACF5\uAC04 \uACC4\uC0B0 (\uD654\uC0B4\uD45C + \uC704\uC544\uB798 \uB9C8\uC9C4, \uD654\uC0B4\uD45C \uC5C6\uC5B4\uB3C4 \uC704\uC544\uB798 \uB9C8\uC9C4)\n const arrowSpace = showArrows\n ? finalThumbWidth * 2 + finalTrackMargin * 4\n : finalTrackMargin * 2;\n\n // \uC378 \uB192\uC774 \uACC4\uC0B0 (\uC0AC\uC6A9\uC790 \uC124\uC815 \uCD5C\uC18C \uB192\uC774 \uC0AC\uC6A9, \uD654\uC0B4\uD45C \uACF5\uAC04 \uC81C\uC678, wrapper \uD328\uB529 \uCD94\uAC00)\n const availableHeight =\n containerHeight - arrowSpace + wrapperPaddingTopBottom;\n const scrollRatio = containerHeight / contentHeight;\n const calculatedThumbHeight = Math.max(\n availableHeight * scrollRatio,\n thumbMinHeight\n );\n\n // \uC378 \uC704\uCE58 \uACC4\uC0B0 (\uD654\uC0B4\uD45C\uC640 \uAC04\uACA9 \uACF5\uAC04 \uC81C\uC678)\n const scrollableHeight = contentHeight - containerHeight;\n const thumbScrollableHeight = availableHeight - calculatedThumbHeight;\n const calculatedThumbTop =\n scrollableHeight > 0\n ? (scrollTop / scrollableHeight) * thumbScrollableHeight\n : 0;\n\n setThumbHeight(calculatedThumbHeight);\n setThumbTop(calculatedThumbTop);\n }, [\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n wrapperRef,\n scrollbarRef,\n thumbMinHeight,\n finalThumbWidth,\n showArrows,\n finalTrackMargin,\n autoHideEnabled,\n ]);\n\n // \uCD08\uAE30 \uC2A4\uD06C\uB864\uBC14 \uC5C5\uB370\uC774\uD2B8\n useEffect(() => {\n updateScrollbar();\n }, [updateScrollbar]);\n\n // Resize observer\uB85C \uD06C\uAE30 \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n const resizeObserver = new ResizeObserver(() => {\n updateScrollbar();\n });\n\n resizeObserver.observe(scrollableElement);\n\n // content\uC758 \uD06C\uAE30 \uBCC0\uACBD\uB3C4 \uAC10\uC9C0\n if (contentRef.current) {\n resizeObserver.observe(contentRef.current);\n }\n\n return () => resizeObserver.disconnect();\n }, [findScrollableElement, contentRef, updateScrollbar]);\n\n return {\n thumbHeight,\n thumbTop,\n hasScrollableContent,\n updateScrollbar,\n };\n};\n", "/**\n * useThumbDrag.ts\n * \uC378 \uB4DC\uB798\uADF8 \uAD00\uB828 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useState, useCallback, useEffect, useRef } from \"react\";\n\ninterface UseThumbDragProps {\n findScrollableElement: () => HTMLElement | null;\n thumbHeight: number;\n clearHideTimer: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n updateScrollbar: () => void;\n setHideTimer: (delay: number) => void;\n hideDelay: number;\n isScrollable: () => boolean;\n maintainFocus: () => void;\n}\n\nexport const useThumbDrag = ({\n findScrollableElement,\n thumbHeight,\n clearHideTimer,\n setScrollbarVisible,\n updateScrollbar,\n setHideTimer,\n hideDelay,\n isScrollable,\n maintainFocus,\n}: UseThumbDragProps) => {\n const [isDragging, setIsDragging] = useState(false);\n const [isThumbHovered, setIsThumbHovered] = useState(false);\n const [dragStart, setDragStart] = useState({ y: 0, scrollTop: 0 });\n\n // \uC378 \uB4DC\uB798\uADF8 \uC2DC\uC791\n const handleThumbMouseDown = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n setIsDragging(true);\n setDragStart({\n y: event.clientY,\n scrollTop: actualScrollContainer.scrollTop,\n });\n\n clearHideTimer();\n setScrollbarVisible(true);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n maintainFocus,\n ]\n );\n\n // \uC378 \uB4DC\uB798\uADF8 \uC911\n const handleMouseMove = useCallback(\n (event: MouseEvent) => {\n if (!isDragging) return;\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n const containerHeight = actualScrollContainer.clientHeight;\n const contentHeight = actualScrollContainer.scrollHeight;\n const scrollableHeight = contentHeight - containerHeight;\n\n const deltaY = event.clientY - dragStart.y;\n const thumbScrollableHeight = containerHeight - thumbHeight;\n const scrollDelta =\n (deltaY / thumbScrollableHeight) * scrollableHeight;\n\n const newScrollTop = Math.max(\n 0,\n Math.min(scrollableHeight, dragStart.scrollTop + scrollDelta)\n );\n\n actualScrollContainer.scrollTop = newScrollTop;\n updateScrollbar();\n },\n [\n isDragging,\n dragStart,\n thumbHeight,\n findScrollableElement,\n updateScrollbar,\n ]\n );\n\n // \uC378 \uB4DC\uB798\uADF8 \uC885\uB8CC\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n if (isScrollable()) {\n setHideTimer(hideDelay);\n }\n }, [isScrollable, setHideTimer, hideDelay]);\n\n // \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\n useEffect(() => {\n if (isDragging) {\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }\n }, [isDragging, handleMouseMove, handleMouseUp]);\n\n return {\n isDragging,\n isThumbHovered,\n setIsThumbHovered,\n handleThumbMouseDown,\n };\n};\n", "/**\n * useTrackClick.ts\n * \uD2B8\uB799 \uD074\uB9AD \uAD00\uB828 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useCallback } from \"react\";\n\ninterface UseTrackClickProps {\n scrollbarRef: React.RefObject<HTMLDivElement>;\n findScrollableElement: () => HTMLElement | null;\n updateScrollbar: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n setHideTimer: (delay: number) => void;\n hideDelay: number;\n maintainFocus: () => void;\n}\n\nexport const useTrackClick = ({\n scrollbarRef,\n findScrollableElement,\n updateScrollbar,\n setScrollbarVisible,\n setHideTimer,\n hideDelay,\n maintainFocus,\n}: UseTrackClickProps) => {\n // \uD2B8\uB799 \uD074\uB9AD\uC73C\uB85C \uC2A4\uD06C\uB864 \uC810\uD504\n const handleTrackClick = useCallback(\n (event: React.MouseEvent) => {\n if (!scrollbarRef.current) {\n return;\n }\n\n const scrollbar = scrollbarRef.current;\n const rect = scrollbar.getBoundingClientRect();\n const clickY = event.clientY - rect.top;\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n const containerHeight = actualScrollContainer.clientHeight;\n const contentHeight = actualScrollContainer.scrollHeight;\n\n const scrollRatio = clickY / containerHeight;\n const newScrollTop =\n scrollRatio * (contentHeight - containerHeight);\n\n actualScrollContainer.scrollTop = Math.max(\n 0,\n Math.min(contentHeight - containerHeight, newScrollTop)\n );\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(hideDelay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n scrollbarRef,\n updateScrollbar,\n setHideTimer,\n hideDelay,\n findScrollableElement,\n maintainFocus,\n setScrollbarVisible,\n ]\n );\n\n return {\n handleTrackClick,\n };\n};\n", "/**\n * useArrowNavigation.ts\n * \uD654\uC0B4\uD45C \uB124\uBE44\uAC8C\uC774\uC158 \uAD00\uB828 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useState, useCallback } from \"react\";\nimport { ArrowsConfig } from \"../types\";\n\ninterface UseArrowNavigationProps {\n arrows: ArrowsConfig;\n containerRef: React.RefObject<HTMLDivElement>;\n contentRef: React.RefObject<HTMLDivElement>;\n updateScrollbar: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n setHideTimer: (delay: number) => void;\n hideDelay: number;\n maintainFocus: () => void;\n}\n\nexport const useArrowNavigation = ({\n arrows,\n containerRef,\n contentRef,\n updateScrollbar,\n setScrollbarVisible,\n setHideTimer,\n hideDelay,\n maintainFocus,\n}: UseArrowNavigationProps) => {\n const [activeArrow, setActiveArrow] = useState<\"up\" | \"down\" | null>(null);\n const [hoveredArrow, setHoveredArrow] = useState<\"up\" | \"down\" | null>(\n null\n );\n\n const arrowStep = arrows.step ?? 50;\n\n // \uC704\uCABD \uD654\uC0B4\uD45C \uD074\uB9AD \uD578\uB4E4\uB7EC\n const handleUpArrowClick = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (!containerRef.current) return;\n\n const newScrollTop = Math.max(\n 0,\n containerRef.current.scrollTop - arrowStep\n );\n\n containerRef.current.scrollTop = newScrollTop;\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(hideDelay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n containerRef,\n updateScrollbar,\n setHideTimer,\n arrowStep,\n hideDelay,\n maintainFocus,\n setScrollbarVisible,\n ]\n );\n\n // \uC544\uB798\uCABD \uD654\uC0B4\uD45C \uD074\uB9AD \uD578\uB4E4\uB7EC\n const handleDownArrowClick = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (!containerRef.current || !contentRef.current) return;\n\n const container = containerRef.current;\n const content = contentRef.current;\n const maxScrollTop = content.scrollHeight - container.clientHeight;\n const newScrollTop = Math.min(\n maxScrollTop,\n container.scrollTop + arrowStep\n );\n\n container.scrollTop = newScrollTop;\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(hideDelay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n containerRef,\n contentRef,\n updateScrollbar,\n setHideTimer,\n arrowStep,\n hideDelay,\n maintainFocus,\n setScrollbarVisible,\n ]\n );\n\n return {\n activeArrow,\n setActiveArrow,\n hoveredArrow,\n setHoveredArrow,\n handleUpArrowClick,\n handleDownArrowClick,\n };\n};\n", "/**\n * useDragScroll.ts\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAD00\uB828 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useState, useCallback, useEffect } from \"react\";\nimport { DragScrollConfig } from \"../types\";\nimport { isTextInputElement } from \"../utils/dragScrollUtils\";\n\ninterface UseDragScrollProps {\n dragScroll: DragScrollConfig;\n findScrollableElement: () => HTMLElement | null;\n clearHideTimer: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n updateScrollbar: () => void;\n setHideTimer: (delay: number) => void;\n hideDelay: number;\n isScrollable: () => boolean;\n}\n\nexport const useDragScroll = ({\n dragScroll,\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n updateScrollbar,\n setHideTimer,\n hideDelay,\n isScrollable,\n}: UseDragScrollProps) => {\n const [isDragScrolling, setIsDragScrolling] = useState(false);\n const [isDragStarted, setIsDragStarted] = useState(false); // \uB4DC\uB798\uADF8\uAC00 \uC2E4\uC81C\uB85C \uC2DC\uC791\uB418\uC5C8\uB294\uC9C0 \uCD94\uC801\n const [dragScrollStart, setDragScrollStart] = useState({\n x: 0,\n y: 0,\n scrollTop: 0,\n scrollLeft: 0,\n });\n\n const enabled = dragScroll.enabled ?? true;\n const dragThreshold = 5; // \uB4DC\uB798\uADF8\uB85C \uC778\uC2DD\uD558\uAE30 \uC704\uD55C \uCD5C\uC18C \uC774\uB3D9 \uAC70\uB9AC (\uD53D\uC140)\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC2DC\uC791\n const handleDragScrollStart = useCallback(\n (event: React.MouseEvent) => {\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0\n if (!enabled) return;\n\n // \uD14D\uC2A4\uD2B8 \uC785\uB825 \uC694\uC18C\uB098 \uC81C\uC678 \uB300\uC0C1\uC774\uBA74 \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uD558\uC9C0 \uC54A\uC74C\n const target = event.target as Element;\n if (isTextInputElement(target, dragScroll)) {\n return;\n }\n\n // \uC624\uB978\uCABD \uD074\uB9AD\uC774\uB098 \uD720 \uD074\uB9AD\uC740 \uC81C\uC678\n if (event.button !== 0) return;\n\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC601\uC5ED\uC774 \uC544\uB2C8\uBA74 \uC81C\uC678\n if (\n scrollableElement.scrollHeight <= scrollableElement.clientHeight\n )\n return;\n\n event.preventDefault();\n setIsDragScrolling(true);\n setIsDragStarted(false); // \uC544\uC9C1 \uB4DC\uB798\uADF8\uAC00 \uC2DC\uC791\uB418\uC9C0 \uC54A\uC74C\n setDragScrollStart({\n x: event.clientX,\n y: event.clientY,\n scrollTop: scrollableElement.scrollTop,\n scrollLeft: scrollableElement.scrollLeft || 0,\n });\n\n // \uC2A4\uD06C\uB864\uBC14\uB294 \uC2E4\uC81C\uB85C \uB4DC\uB798\uADF8\uAC00 \uC2DC\uC791\uB420 \uB54C \uD45C\uC2DC (handleDragScrollMove\uC5D0\uC11C)\n },\n [\n enabled,\n dragScroll,\n findScrollableElement,\n clearHideTimer,\n setScrollbarVisible,\n ]\n );\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC911\n const handleDragScrollMove = useCallback(\n (event: MouseEvent) => {\n if (!isDragScrolling) return;\n\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n const deltaX = dragScrollStart.x - event.clientX;\n const deltaY = dragScrollStart.y - event.clientY;\n\n // \uB4DC\uB798\uADF8 \uAC70\uB9AC \uCCB4\uD06C - \uC784\uACC4\uAC12 \uC774\uC0C1 \uC6C0\uC9C1\uC600\uC744 \uB54C\uB9CC \uB4DC\uB798\uADF8\uB85C \uC778\uC2DD\n if (!isDragStarted) {\n const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);\n if (distance >= dragThreshold) {\n setIsDragStarted(true);\n // \uC774\uC81C \uC9C4\uC9DC \uB4DC\uB798\uADF8\uAC00 \uC2DC\uC791\uB418\uC5C8\uC73C\uBBC0\uB85C \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\n clearHideTimer();\n setScrollbarVisible(true);\n } else {\n // \uC544\uC9C1 \uC784\uACC4\uAC12\uC5D0 \uB3C4\uB2EC\uD558\uC9C0 \uC54A\uC74C\n return;\n }\n }\n\n // \uC138\uB85C \uC2A4\uD06C\uB864\uB9CC \uCC98\uB9AC (\uAC00\uB85C \uC2A4\uD06C\uB864\uC740 \uD544\uC694\uC2DC \uB098\uC911\uC5D0 \uCD94\uAC00)\n const newScrollTop = Math.max(\n 0,\n Math.min(\n scrollableElement.scrollHeight -\n scrollableElement.clientHeight,\n dragScrollStart.scrollTop + deltaY\n )\n );\n\n scrollableElement.scrollTop = newScrollTop;\n updateScrollbar();\n },\n [\n isDragScrolling,\n isDragStarted,\n dragScrollStart,\n dragThreshold,\n findScrollableElement,\n updateScrollbar,\n clearHideTimer,\n setScrollbarVisible,\n ]\n );\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC885\uB8CC\n const handleDragScrollEnd = useCallback(() => {\n setIsDragScrolling(false);\n setIsDragStarted(false); // \uB4DC\uB798\uADF8 \uC0C1\uD0DC \uCD08\uAE30\uD654\n if (isScrollable()) {\n setHideTimer(hideDelay);\n }\n }, [isScrollable, setHideTimer, hideDelay]);\n\n // \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\n useEffect(() => {\n if (isDragScrolling) {\n document.addEventListener(\"mousemove\", handleDragScrollMove);\n document.addEventListener(\"mouseup\", handleDragScrollEnd);\n return () => {\n document.removeEventListener(\"mousemove\", handleDragScrollMove);\n document.removeEventListener(\"mouseup\", handleDragScrollEnd);\n };\n }\n }, [isDragScrolling, handleDragScrollMove, handleDragScrollEnd]);\n\n return {\n isDragScrolling,\n handleDragScrollStart,\n };\n};\n", "/**\n * MIT License\n *\n * Copyright (c) 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { DragScrollConfig } from \"../types\";\n\n// \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uD074\uB798\uC2A4\uB4E4 (\uC790\uC2E0 \uB610\uB294 \uBD80\uBAA8 \uC694\uC18C\uC5D0\uC11C \uD655\uC778)\nconst DEFAULT_EXCLUDE_CLASSES = [\n // \uAE30\uBCF8 \uC785\uB825 \uC694\uC18C\uB4E4\n \"editor\",\n \"textarea\",\n \"input\",\n \"select\",\n \"textfield\",\n \"form-control\",\n \"contenteditable\",\n\n // Material-UI \uCEF4\uD3EC\uB10C\uD2B8\uB4E4\n \"MuiInputBase-input\",\n \"MuiSelect-select\",\n \"MuiOutlinedInput-input\",\n \"MuiFilledInput-input\",\n \"MuiInput-input\",\n \"MuiFormControl-root\",\n \"MuiTextField-root\",\n \"MuiSelect-root\",\n \"MuiOutlinedInput-root\",\n \"MuiFilledInput-root\",\n \"MuiInput-root\",\n \"MuiAutocomplete-input\",\n \"MuiDatePicker-input\",\n \"MuiSlider-thumb\",\n \"MuiSlider-rail\",\n \"MuiSlider-track\",\n \"MuiSlider-mark\",\n \"MuiSlider-markLabel\",\n \"MuiSlider-root\",\n \"MuiSlider-colorPrimary\",\n \"MuiSlider-sizeMedium\",\n \"MuiIconButton-root\",\n \"MuiButton-root\",\n \"MuiButtonBase-root\",\n \"MuiTouchRipple-root\",\n \"MuiCheckbox-root\",\n \"MuiRadio-root\",\n \"MuiSwitch-root\",\n \"PrivateSwitchBase-root\",\n\n // Ant Design \uCEF4\uD3EC\uB10C\uD2B8\uB4E4\n \"ant-input\",\n \"ant-input-affix-wrapper\",\n \"ant-input-group-addon\",\n \"ant-input-number\",\n \"ant-input-number-handler\",\n \"ant-select\",\n \"ant-select-selector\",\n \"ant-select-selection-search\",\n \"ant-select-dropdown\",\n \"ant-cascader\",\n \"ant-cascader-input\",\n \"ant-picker\",\n \"ant-picker-input\",\n \"ant-time-picker\",\n \"ant-calendar-picker\",\n \"ant-slider\",\n \"ant-slider-track\",\n \"ant-slider-handle\",\n \"ant-switch\",\n \"ant-checkbox\",\n \"ant-checkbox-wrapper\",\n \"ant-radio\",\n \"ant-radio-wrapper\",\n \"ant-rate\",\n \"ant-upload\",\n \"ant-upload-drag\",\n \"ant-form-item\",\n \"ant-form-item-control\",\n \"ant-btn\",\n \"ant-dropdown\",\n \"ant-dropdown-trigger\",\n \"ant-menu\",\n \"ant-menu-item\",\n \"ant-tooltip\",\n \"ant-popover\",\n \"ant-modal\",\n \"ant-drawer\",\n \"ant-tree-select\",\n \"ant-auto-complete\",\n \"ant-mentions\",\n \"ant-transfer\",\n\n // Shadcn/ui \uCEF4\uD3EC\uB10C\uD2B8\uB4E4\n \"ui-input\",\n \"ui-textarea\",\n \"ui-select\",\n \"ui-select-trigger\",\n \"ui-select-content\",\n \"ui-select-item\",\n \"ui-button\",\n \"ui-checkbox\",\n \"ui-radio-group\",\n \"ui-switch\",\n \"ui-slider\",\n \"ui-range-slider\",\n \"ui-calendar\",\n \"ui-date-picker\",\n \"ui-combobox\",\n \"ui-command\",\n \"ui-command-input\",\n \"ui-popover\",\n \"ui-dialog\",\n \"ui-sheet\",\n \"ui-dropdown-menu\",\n \"ui-context-menu\",\n \"ui-menubar\",\n \"ui-navigation-menu\",\n \"ui-form\",\n \"ui-form-control\",\n \"ui-form-item\",\n \"ui-form-field\",\n \"ui-label\",\n // Radix UI \uAE30\uBCF8 \uD074\uB798\uC2A4\uB4E4 (Shadcn \uAE30\uBC18)\n \"radix-ui\",\n \"radix-select\",\n \"radix-dropdown\",\n \"radix-dialog\",\n \"radix-popover\",\n \"radix-accordion\",\n \"radix-tabs\",\n \"radix-slider\",\n \"radix-switch\",\n \"radix-checkbox\",\n \"radix-radio\",\n\n // Quill Editor\n \"ql-editor\",\n \"ql-container\",\n \"ql-toolbar\",\n \"ql-picker\",\n \"ql-picker-label\",\n \"ql-picker-options\",\n \"ql-formats\",\n \"ql-snow\",\n \"ql-bubble\",\n \"quill\",\n \"quilleditor\",\n\n // Monaco Editor\n \"monaco-editor\",\n \"monaco-editor-background\",\n \"view-lines\",\n \"decorationsOverviewRuler\",\n \"monaco-scrollable-element\",\n\n // CodeMirror\n \"CodeMirror\",\n \"CodeMirror-code\",\n \"CodeMirror-lines\",\n \"CodeMirror-scroll\",\n \"CodeMirror-sizer\",\n \"cm-editor\",\n \"cm-focused\",\n \"cm-content\",\n\n // TinyMCE\n \"tox-editor-container\",\n \"tox-editor-header\",\n \"tox-edit-area\",\n \"tox-tinymce\",\n \"mce-content-body\",\n\n // CKEditor\n \"ck-editor\",\n \"ck-content\",\n \"ck-toolbar\",\n \"ck-editor__editable\",\n \"ck-widget\",\n\n // Slate.js\n \"slate-editor\",\n \"slate-content\",\n\n // Draft.js\n \"DraftEditor-root\",\n \"DraftEditor-editorContainer\",\n \"public-DraftEditor-content\",\n\n // EhfuseEditor\n \"ehfuse-editor\",\n \"ehfuse-editor-wrapper\",\n \"ehfuse-editor-content\",\n \"ehfuse-toolbar\",\n \"ehfuse-toolbar-group\",\n \"ehfuse-cursor\",\n\n // \uAE30\uD0C0 \uC5D0\uB514\uD130\uB4E4\n \"text-editor\",\n \"rich-text-editor\",\n \"wysiwyg\",\n \"ace_editor\",\n \"ace_content\",\n];\n\n/**\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uC694\uC18C\uB4E4\uC778\uC9C0 \uD655\uC778\n */\n/**\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uC694\uC18C\uB4E4\uC778\uC9C0 \uD655\uC778\n */\nexport const isTextInputElement = (\n element: Element,\n config?: DragScrollConfig\n): boolean => {\n const tagName = element.tagName.toLowerCase();\n const inputTypes = [\n \"text\",\n \"password\",\n \"email\",\n \"number\",\n \"search\",\n \"tel\",\n \"url\",\n \"checkbox\",\n \"radio\",\n ];\n\n // input \uD0DC\uADF8\uC774\uBA74\uC11C \uD14D\uC2A4\uD2B8 \uC785\uB825 \uD0C0\uC785\uC774\uB098 \uCCB4\uD06C\uBC15\uC2A4/\uB77C\uB514\uC624\uC778 \uACBD\uC6B0\n if (tagName === \"input\") {\n const type = (element as HTMLInputElement).type;\n return inputTypes.includes(type);\n }\n\n // textarea, select, \uD3B8\uC9D1 \uAC00\uB2A5\uD55C \uC694\uC18C\uB4E4\n if ([\"textarea\", \"select\", \"button\"].includes(tagName)) {\n return true;\n }\n\n // SVG \uC694\uC18C\uB4E4 (\uC544\uC774\uCF58\uB4E4)\n if (\n [\n \"svg\",\n \"path\",\n \"circle\",\n \"rect\",\n \"line\",\n \"polygon\",\n \"polyline\",\n ].includes(tagName)\n ) {\n return true;\n }\n\n // contenteditable \uC18D\uC131\uC774 \uC788\uB294 \uC694\uC18C\n if (element.getAttribute(\"contenteditable\") === \"true\") {\n return true;\n }\n\n // \uCD94\uAC00 \uC140\uB809\uD130 \uCCB4\uD06C\n if (config?.excludeSelectors) {\n for (const selector of config.excludeSelectors) {\n if (element.matches(selector)) {\n return true;\n }\n }\n }\n\n return checkElementAndParents(element, config);\n};\n\n/**\n * \uC790\uC2E0 \uB610\uB294 \uBD80\uBAA8 \uC694\uC18C\uB4E4\uC744 \uD655\uC778\uD558\uC5EC \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uC694\uC18C\uC778\uC9C0 \uD310\uB2E8\n */\nconst checkElementAndParents = (\n element: Element,\n config?: DragScrollConfig\n): boolean => {\n // \uBAA8\uB4E0 \uC81C\uC678 \uD074\uB798\uC2A4\uB4E4 \uD569\uCE58\uAE30 (\uAE30\uBCF8 \uD074\uB798\uC2A4 + \uC0AC\uC6A9\uC790 \uCD94\uAC00 \uD074\uB798\uC2A4)\n const allExcludeClasses = [\n ...DEFAULT_EXCLUDE_CLASSES,\n ...(config?.excludeClasses || []),\n ];\n\n let currentElement: Element | null = element;\n let depth = 0;\n const maxDepth = 5; // \uCD5C\uB300 5\uB2E8\uACC4\uAE4C\uC9C0 \uBD80\uBAA8 \uC694\uC18C \uD655\uC778\n\n while (currentElement && depth <= maxDepth) {\n // \uD604\uC7AC \uC694\uC18C\uAC00 \uC81C\uC678 \uD074\uB798\uC2A4\uB97C \uAC00\uC9C0\uACE0 \uC788\uB294\uC9C0 \uD655\uC778\n if (\n allExcludeClasses.some((cls) =>\n currentElement!.classList.contains(cls)\n )\n ) {\n return true;\n }\n\n // \uB2E4\uC774\uC5BC\uB85C\uADF8 \uB8E8\uD2B8\uC5D0 \uB3C4\uB2EC\uD558\uBA74 \uC911\uB2E8\n if (currentElement.classList.contains(\"MuiDialogContent-root\")) {\n break;\n }\n\n currentElement = currentElement.parentElement;\n depth++;\n }\n\n return false;\n};\n\n/**\n * \uB2E4\uB978 \uB2E4\uC774\uC5BC\uB85C\uADF8\uB098 \uBAA8\uB2EC\uC774 \uC0C1\uC704\uC5D0 \uC788\uB294\uC9C0 \uD655\uC778\n */\nexport const hasUpperModal = (scrollContainer: Element): boolean => {\n const currentDialog = scrollContainer.closest(\n \".MuiDialog-root\"\n ) as HTMLElement;\n if (!currentDialog) return false;\n\n const allModals = document.querySelectorAll(\n \".MuiDialog-root, .MuiModal-root, .MuiPopover-root\"\n );\n const currentZIndex = parseInt(\n window.getComputedStyle(currentDialog).zIndex || \"0\"\n );\n\n for (const modal of allModals) {\n if (modal !== currentDialog) {\n const modalElement = modal as HTMLElement;\n const modalZIndex = parseInt(\n window.getComputedStyle(modalElement).zIndex || \"0\"\n );\n\n if (\n modalZIndex > currentZIndex &&\n modalElement.style.display !== \"none\"\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * \uD074\uB9AD\uD55C \uC694\uC18C\uAC00 \uB2E4\uB978 \uB2E4\uC774\uC5BC\uB85C\uADF8 \uB0B4\uBD80\uC778\uC9C0 \uD655\uC778\n */\nexport const isClickInOtherDialog = (\n clickedElement: Element,\n currentDialog: Element | null\n): boolean => {\n const parentDialog = clickedElement.closest(\n \".MuiDialog-root, .MuiPopover-root, .MuiModal-root\"\n );\n return parentDialog !== null && parentDialog !== currentDialog;\n};\n", "/**\n * useScrollEvents.ts\n * \uC2A4\uD06C\uB864 \uC774\uBCA4\uD2B8 \uAD00\uB828 \uB85C\uC9C1\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useRef, useEffect } from \"react\";\nimport { AutoHideConfig } from \"../types\";\n\ninterface UseScrollEventsProps {\n containerRef: React.RefObject<HTMLDivElement>;\n findScrollableElement: () => HTMLElement | null;\n updateScrollbar: () => void;\n clearHideTimer: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n setHideTimer: (delay: number) => void;\n autoHide: AutoHideConfig;\n onScroll?: (event: Event) => void;\n}\n\nexport const useScrollEvents = ({\n containerRef,\n findScrollableElement,\n updateScrollbar,\n clearHideTimer,\n setScrollbarVisible,\n setHideTimer,\n autoHide,\n onScroll,\n}: UseScrollEventsProps) => {\n const wheelTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const isWheelScrollingRef = useRef(false); // useState \uB300\uC2E0 useRef \uC0AC\uC6A9 (\uB9AC\uB80C\uB354\uB9C1 \uBC29\uC9C0)\n\n const hideDelay = autoHide.delay ?? 1500;\n const hideDelayOnWheel = autoHide.delayOnWheel ?? 700;\n\n useEffect(() => {\n const handleScroll = (event: Event) => {\n // \uC774\uBCA4\uD2B8 \uD0C0\uAC9F\uC774 \uC2E4\uC81C \uC2A4\uD06C\uB864\uB41C \uC694\uC18C\uC778\uC9C0 \uD655\uC778 (\uBC84\uBE14\uB9C1 \uBC29\uC9C0)\n const target = event.target as HTMLElement;\n const scrollableElement = findScrollableElement();\n\n // \uC2A4\uD06C\uB864 \uC774\uBCA4\uD2B8\uAC00 \uC790\uC2E0\uC758 \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108\uC5D0\uC11C \uBC1C\uC0DD\uD55C \uAC83\uC774 \uC544\uB2C8\uBA74 \uBB34\uC2DC\n if (!scrollableElement || target !== scrollableElement) {\n return;\n }\n\n updateScrollbar();\n\n // \uC2A4\uD06C\uB864 \uC911\uC5D0\uB294 \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\n clearHideTimer();\n setScrollbarVisible(true);\n\n // \uD720 \uC2A4\uD06C\uB864 \uC911\uC774\uBA74 \uBE60\uB978 \uC228\uAE40, \uC544\uB2C8\uBA74 \uAE30\uBCF8 \uC228\uAE40 \uC2DC\uAC04 \uC801\uC6A9\n const delay = isWheelScrollingRef.current\n ? hideDelayOnWheel\n : hideDelay;\n setHideTimer(delay);\n\n if (onScroll) {\n onScroll(event);\n }\n };\n\n const handleWheel = (event: Event) => {\n // \uC774\uBCA4\uD2B8 \uD0C0\uAC9F\uC774 \uC790\uC2E0\uC758 \uCEE8\uD14C\uC774\uB108 \uB0B4\uBD80\uC778\uC9C0 \uD655\uC778\n const target = event.target as HTMLElement;\n const container = containerRef.current;\n\n if (!container) return;\n\n // \uC774\uBCA4\uD2B8\uAC00 \uC790\uC2E0\uC758 \uCEE8\uD14C\uC774\uB108 \uB0B4\uBD80\uC5D0\uC11C \uBC1C\uC0DD\uD55C \uAC83\uC778\uC9C0 \uD655\uC778\n // \uC911\uCCA9\uB41C OverlayScrollbar\uC758 \uC774\uBCA4\uD2B8\uB294 \uBB34\uC2DC\n if (!container.contains(target)) {\n return;\n }\n\n // \uD0C0\uAC9F\uC774 \uB2E4\uB978 OverlayScrollbar\uC758 \uCEE8\uD14C\uC774\uB108\uC778\uC9C0 \uD655\uC778\n if (\n target.classList.contains(\"overlay-scrollbar-container\") &&\n target !== container\n ) {\n return;\n }\n\n // \uD0C0\uAC9F\uC758 \uBD80\uBAA8 \uC911\uC5D0 \uB2E4\uB978 OverlayScrollbar \uCEE8\uD14C\uC774\uB108\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\n let parent = target.parentElement;\n while (parent && parent !== container) {\n if (parent.classList.contains(\"overlay-scrollbar-container\")) {\n // \uC911\uCCA9\uB41C \uB0B4\uBD80 OverlayScrollbar\uC758 \uC774\uBCA4\uD2B8\uC774\uBBC0\uB85C \uBB34\uC2DC\n return;\n }\n parent = parent.parentElement;\n }\n\n // \uD720 \uC2A4\uD06C\uB864 \uC0C1\uD0DC \uD45C\uC2DC\n isWheelScrollingRef.current = true;\n\n // \uAE30\uC874 \uD720 \uD0C0\uC774\uBA38 \uC81C\uAC70\n if (wheelTimeoutRef.current) {\n clearTimeout(wheelTimeoutRef.current);\n }\n\n // 300ms \uD6C4 \uD720 \uC2A4\uD06C\uB864 \uC0C1\uD0DC \uD574\uC81C (\uD720 \uC2A4\uD06C\uB864\uC774 \uB05D\uB0AC\uB2E4\uACE0 \uAC04\uC8FC)\n wheelTimeoutRef.current = setTimeout(() => {\n isWheelScrollingRef.current = false;\n }, 300);\n\n clearHideTimer();\n setScrollbarVisible(true);\n };\n\n const elementsToWatch: HTMLElement[] = [];\n\n // \uC2E4\uC81C \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C \uCC3E\uAE30\n const scrollableElement = findScrollableElement();\n if (scrollableElement) {\n elementsToWatch.push(scrollableElement);\n }\n\n // fallback: \uB0B4\uBD80 \uCEE8\uD14C\uC774\uB108\uC640 children \uC694\uC18C\uB3C4 \uAC10\uC9C0\n const container = containerRef.current;\n if (container && !scrollableElement) {\n elementsToWatch.push(container);\n\n // children \uC694\uC18C\uB4E4\uC758 \uC2A4\uD06C\uB864\uB3C4 \uAC10\uC9C0 (\uC911\uCCA9\uB41C OverlayScrollbar \uC81C\uC678)\n const childScrollableElements = container.querySelectorAll(\n '[data-virtuoso-scroller], [style*=\"overflow\"], .virtuoso-scroller, [style*=\"overflow: auto\"], [style*=\"overflow:auto\"]'\n );\n childScrollableElements.forEach((child) => {\n const element = child as HTMLElement;\n\n // \uB2E4\uB978 OverlayScrollbar\uC758 container\uB294 \uC81C\uC678\n if (\n element !== container &&\n element.classList.contains(\"overlay-scrollbar-container\")\n ) {\n return;\n }\n\n // \uBD80\uBAA8 \uC911\uC5D0 \uB2E4\uB978 OverlayScrollbar container\uAC00 \uC788\uC73C\uBA74 \uC81C\uC678\n let parent: HTMLElement | null = element.parentElement;\n while (parent && parent !== container) {\n if (\n parent.classList.contains(\n \"overlay-scrollbar-container\"\n ) &&\n parent !== container\n ) {\n return; // \uC911\uCCA9\uB41C OverlayScrollbar \uB0B4\uBD80\uC774\uBBC0\uB85C \uC81C\uC678\n }\n parent = parent.parentElement;\n }\n\n elementsToWatch.push(element);\n });\n }\n\n // \uBAA8\uB4E0 \uC694\uC18C\uC5D0 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\n elementsToWatch.forEach((element) => {\n element.addEventListener(\"scroll\", handleScroll, {\n passive: true,\n });\n element.addEventListener(\"wheel\", handleWheel, {\n passive: true,\n });\n });\n\n return () => {\n elementsToWatch.forEach((element) => {\n element.removeEventListener(\"scroll\", handleScroll);\n element.removeEventListener(\"wheel\", handleWheel);\n });\n if (wheelTimeoutRef.current) {\n clearTimeout(wheelTimeoutRef.current);\n }\n };\n }, [\n containerRef,\n findScrollableElement,\n updateScrollbar,\n onScroll,\n clearHideTimer,\n setHideTimer,\n hideDelay,\n hideDelayOnWheel,\n setScrollbarVisible,\n ]);\n};\n", "/**\n * useKeyboardNavigation.ts\n * \uD0A4\uBCF4\uB4DC \uB124\uBE44\uAC8C\uC774\uC158 \uAD00\uB828 \uB85C\uC9C1 (\uBC29\uD5A5\uD0A4, PageUp/PageDown/Home/End)\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useEffect } from \"react\";\n\ninterface UseKeyboardNavigationProps {\n containerRef: React.RefObject<HTMLDivElement>;\n findScrollableElement: () => HTMLElement | null;\n updateScrollbar: () => void;\n clearHideTimer: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n setHideTimer: (delay: number) => void;\n hideDelay: number;\n}\n\nexport const useKeyboardNavigation = ({\n containerRef,\n findScrollableElement,\n updateScrollbar,\n clearHideTimer,\n setScrollbarVisible,\n setHideTimer,\n hideDelay,\n}: UseKeyboardNavigationProps) => {\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n // \uC785\uB825 \uAC00\uB2A5\uD55C \uC694\uC18C\uC5D0 \uD3EC\uCEE4\uC2A4\uAC00 \uC788\uC73C\uBA74 \uD0A4\uBCF4\uB4DC \uC2A4\uD06C\uB864 \uBE44\uD65C\uC131\uD654\n const target = event.target as HTMLElement;\n if (\n target.tagName === \"INPUT\" ||\n target.tagName === \"TEXTAREA\" ||\n target.tagName === \"SELECT\" ||\n target.isContentEditable ||\n target.getAttribute(\"role\") === \"textbox\" ||\n target.classList.contains(\"MuiInputBase-input\") || // Material-UI TextField\n target.closest(\".MuiTextField-root\") || // Material-UI TextField \uCEE8\uD14C\uC774\uB108\n target.closest('[contenteditable=\"true\"]') // contenteditable \uC694\uC18C\n ) {\n return; // \uC785\uB825 \uD544\uB4DC\uC5D0\uC11C\uB294 \uD0A4\uBCF4\uB4DC \uC2A4\uD06C\uB864\uC744 \uD558\uC9C0 \uC54A\uC74C\n }\n\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n const { key } = event;\n const { scrollTop, scrollHeight, clientHeight } = scrollableElement;\n const maxScrollTop = scrollHeight - clientHeight;\n\n // \uD55C \uC904 \uC2A4\uD06C\uB864 \uB2E8\uC704\n const lineScrollStep = 50;\n\n let newScrollTop: number | null = null;\n\n switch (key) {\n case \"ArrowUp\":\n event.preventDefault();\n newScrollTop = Math.max(0, scrollTop - lineScrollStep);\n break;\n case \"ArrowDown\":\n event.preventDefault();\n newScrollTop = Math.min(\n maxScrollTop,\n scrollTop + lineScrollStep\n );\n break;\n case \"PageUp\":\n event.preventDefault();\n newScrollTop = Math.max(0, scrollTop - clientHeight);\n break;\n case \"PageDown\":\n event.preventDefault();\n newScrollTop = Math.min(\n maxScrollTop,\n scrollTop + clientHeight\n );\n break;\n case \"Home\":\n event.preventDefault();\n newScrollTop = 0;\n break;\n case \"End\":\n event.preventDefault();\n newScrollTop = maxScrollTop;\n break;\n default:\n return;\n }\n\n if (newScrollTop !== null) {\n // \uC2A4\uD06C\uB864 \uC704\uCE58\uB97C \uC989\uC2DC \uBCC0\uACBD\n scrollableElement.scrollTop = newScrollTop;\n\n // updateScrollbar\uAC00 thumbTop\uC744 \uC790\uB3D9\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD568\n updateScrollbar();\n\n // \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\n clearHideTimer();\n setScrollbarVisible(true);\n setHideTimer(hideDelay);\n }\n };\n\n const container = containerRef.current;\n if (container) {\n container.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n container.removeEventListener(\"keydown\", handleKeyDown);\n };\n }\n }, [\n containerRef,\n findScrollableElement,\n updateScrollbar,\n clearHideTimer,\n setScrollbarVisible,\n setHideTimer,\n hideDelay,\n ]);\n};\n", "/**\n * useScrollbarInitialization.ts\n * \uC2A4\uD06C\uB864\uBC14 \uCD08\uAE30\uD654 \uAD00\uB828 \uB85C\uC9C1 (ResizeObserver, MutationObserver, CSS \uC8FC\uC785 \uB4F1)\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport { useEffect, useLayoutEffect, useState } from \"react\";\nimport { AutoHideConfig } from \"../types\";\n\ninterface UseScrollbarInitializationProps {\n containerRef: React.RefObject<HTMLDivElement>;\n contentRef: React.RefObject<HTMLDivElement>;\n cachedScrollContainerRef: React.MutableRefObject<HTMLElement | null>;\n updateScrollbar: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n isScrollable: () => boolean;\n autoHide: AutoHideConfig;\n}\n\nexport const useScrollbarInitialization = ({\n containerRef,\n contentRef,\n cachedScrollContainerRef,\n updateScrollbar,\n setScrollbarVisible,\n isScrollable,\n autoHide,\n}: UseScrollbarInitializationProps) => {\n const [isInitialized, setIsInitialized] = useState(false);\n\n // \uCD08\uAE30 \uC2A4\uD06C\uB864\uBC14 \uC5C5\uB370\uC774\uD2B8\n useEffect(() => {\n // \uC989\uC2DC \uC5C5\uB370\uC774\uD2B8\n updateScrollbar();\n // \uC57D\uAC04\uC758 \uC9C0\uC5F0 \uD6C4\uC5D0\uB3C4 \uC5C5\uB370\uC774\uD2B8 (DOM\uC774 \uC644\uC804\uD788 \uB80C\uB354\uB9C1\uB41C \uD6C4)\n const timer = setTimeout(() => {\n updateScrollbar();\n }, 100);\n return () => clearTimeout(timer);\n }, [updateScrollbar]);\n\n // \uCEF4\uD3EC\uB10C\uD2B8 \uCD08\uAE30\uD654 \uC644\uB8CC \uD45C\uC2DC (hover \uC774\uBCA4\uD2B8 \uD65C\uC131\uD654\uC6A9)\n useLayoutEffect(() => {\n setIsInitialized(true);\n // \uCD08\uAE30\uD654 \uC9C1\uD6C4 \uC2A4\uD06C\uB864\uBC14 \uC5C5\uB370\uC774\uD2B8 (\uC378 \uB192\uC774 \uC815\uD655\uD558\uAC8C \uACC4\uC0B0)\n updateScrollbar();\n // \uC790\uB3D9 \uC228\uAE40\uC774 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uC73C\uBA74 \uC2A4\uD06C\uB864\uBC14\uB97C \uD56D\uC0C1 \uD45C\uC2DC\n if (!autoHide.enabled && isScrollable()) {\n setScrollbarVisible(true);\n }\n }, [isScrollable, updateScrollbar, autoHide.enabled, setScrollbarVisible]);\n\n // ResizeObserver\uB85C \uD06C\uAE30 \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n const resizeObserver = new ResizeObserver(() => {\n updateScrollbar();\n });\n\n const elementsToObserve: HTMLElement[] = [];\n\n // \uB0B4\uBD80 \uCEE8\uD14C\uC774\uB108\uB4E4 \uAD00\uCC30\n if (containerRef.current) {\n elementsToObserve.push(containerRef.current);\n }\n if (contentRef.current) {\n elementsToObserve.push(contentRef.current);\n }\n\n // \uCE90\uC2DC\uB41C \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108\uB3C4 \uAD00\uCC30\n if (\n cachedScrollContainerRef.current &&\n document.contains(cachedScrollContainerRef.current)\n ) {\n elementsToObserve.push(cachedScrollContainerRef.current);\n }\n\n // \uBAA8\uB4E0 \uC694\uC18C\uB4E4 \uAD00\uCC30 \uC2DC\uC791\n elementsToObserve.forEach((element) => {\n resizeObserver.observe(element);\n });\n\n return () => resizeObserver.disconnect();\n }, [updateScrollbar, containerRef, contentRef, cachedScrollContainerRef]);\n\n // MutationObserver\uB85C DOM \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n const observer = new MutationObserver(() => {\n // \uCE90\uC2DC \uCD08\uAE30\uD654\uD558\uC5EC \uC0C8\uB85C\uC6B4 \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uAC10\uC9C0\n cachedScrollContainerRef.current = null;\n updateScrollbar();\n });\n\n observer.observe(containerRef.current, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\"],\n });\n\n return () => observer.disconnect();\n }, [updateScrollbar, containerRef, cachedScrollContainerRef]);\n\n // \uC6F9\uD0B7 \uC2A4\uD06C\uB864\uBC14 \uC228\uAE30\uAE30\uC6A9 CSS \uB3D9\uC801 \uC8FC\uC785\n useEffect(() => {\n const styleId = \"overlay-scrollbar-webkit-hide\";\n\n // \uC774\uBBF8 \uC2A4\uD0C0\uC77C\uC774 \uC788\uC73C\uBA74 \uC81C\uAC70\n const existingStyle = document.getElementById(styleId);\n if (existingStyle) {\n existingStyle.remove();\n }\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n .overlay-scrollbar-container::-webkit-scrollbar {\n display: none !important;\n width: 0 !important;\n height: 0 !important;\n }\n .overlay-scrollbar-container::-webkit-scrollbar-track {\n display: none !important;\n }\n .overlay-scrollbar-container::-webkit-scrollbar-thumb {\n display: none !important;\n }\n .overlay-scrollbar-container:focus {\n outline: 2px solid rgba(0, 123, 255, 0.3);\n outline-offset: -2px;\n }\n .overlay-scrollbar-container:focus-visible {\n outline: 2px solid rgba(0, 123, 255, 0.5);\n outline-offset: -2px;\n }\n `;\n document.head.appendChild(style);\n\n return () => {\n const styleToRemove = document.getElementById(styleId);\n if (styleToRemove) {\n styleToRemove.remove();\n }\n };\n }, []);\n\n return {\n isInitialized,\n };\n};\n", "/**\n * ScrollbarTrack.tsx\n * \uC2A4\uD06C\uB864\uBC14 \uD2B8\uB799 \uCEF4\uD3EC\uB10C\uD2B8\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport React from \"react\";\n\ninterface ScrollbarTrackProps {\n scrollbarRef: React.RefObject<HTMLDivElement>;\n adjustedTrackWidth: number;\n scrollbarVisible: boolean;\n isDragging: boolean;\n showArrows: boolean;\n finalThumbWidth: number;\n finalTrackConfig: {\n visible: boolean;\n alignment: string;\n margin: number;\n color: string;\n radius: number;\n width: number;\n };\n clearHideTimer: () => void;\n setScrollbarVisible: (visible: boolean) => void;\n setHideTimer: (delay: number) => void;\n autoHideDelay: number;\n handleTrackClick: (e: React.MouseEvent) => void;\n children: React.ReactNode;\n}\n\nexport const ScrollbarTrack: React.FC<ScrollbarTrackProps> = ({\n scrollbarRef,\n adjustedTrackWidth,\n scrollbarVisible,\n isDragging,\n showArrows,\n finalThumbWidth,\n finalTrackConfig,\n clearHideTimer,\n setScrollbarVisible,\n setHideTimer,\n autoHideDelay,\n handleTrackClick,\n children,\n}) => {\n return (\n <div\n ref={scrollbarRef}\n className=\"overlay-scrollbar-track\"\n onMouseEnter={() => {\n clearHideTimer();\n setScrollbarVisible(true);\n }}\n onMouseLeave={() => {\n if (!isDragging) {\n setHideTimer(autoHideDelay);\n }\n }}\n style={{\n position: \"absolute\",\n top: 0,\n right: 0,\n width: `${adjustedTrackWidth}px`,\n height: \"100%\",\n opacity: scrollbarVisible ? 1 : 0,\n transition: \"opacity 0.2s ease-in-out\",\n cursor: \"pointer\",\n zIndex: 1000,\n pointerEvents: \"auto\",\n }}\n >\n {/* \uC2A4\uD06C\uB864\uBC14 \uD2B8\uB799 \uBC30\uACBD */}\n {finalTrackConfig.visible && (\n <div\n className=\"overlay-scrollbar-track-background\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleTrackClick(e);\n }}\n style={{\n position: \"absolute\",\n top: showArrows\n ? `${\n finalThumbWidth + finalTrackConfig.margin * 2\n }px`\n : `${finalTrackConfig.margin}px`,\n right:\n finalTrackConfig.alignment === \"right\"\n ? \"0px\"\n : `${\n (adjustedTrackWidth - finalThumbWidth) / 2\n }px`,\n width: `${finalThumbWidth}px`,\n height: showArrows\n ? `calc(100% - ${\n finalThumbWidth * 2 +\n finalTrackConfig.margin * 4\n }px)`\n : `calc(100% - ${finalTrackConfig.margin * 2}px)`,\n backgroundColor: finalTrackConfig.color,\n borderRadius: `${finalTrackConfig.radius}px`,\n cursor: \"pointer\",\n }}\n />\n )}\n {children}\n </div>\n );\n};\n", "/**\n * ScrollbarThumb.tsx\n * \uC2A4\uD06C\uB864\uBC14 \uC378 \uCEF4\uD3EC\uB10C\uD2B8\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport React from \"react\";\n\ninterface ScrollbarThumbProps {\n thumbRef: React.RefObject<HTMLDivElement>;\n thumbTop: number;\n thumbHeight: number;\n thumbMinHeight: number;\n showArrows: boolean;\n finalThumbWidth: number;\n adjustedTrackWidth: number;\n isDragging: boolean;\n isThumbHovered: boolean;\n finalThumbConfig: {\n width: number;\n color: string;\n opacity: number;\n hoverColor: string;\n hoverOpacity: number;\n radius: number;\n };\n finalTrackConfig: {\n alignment: string;\n margin: number;\n };\n handleThumbMouseDown: (e: React.MouseEvent) => void;\n setIsThumbHovered: (hovered: boolean) => void;\n}\n\nexport const ScrollbarThumb: React.FC<ScrollbarThumbProps> = ({\n thumbRef,\n thumbTop,\n thumbHeight,\n thumbMinHeight,\n showArrows,\n finalThumbWidth,\n adjustedTrackWidth,\n isDragging,\n isThumbHovered,\n finalThumbConfig,\n finalTrackConfig,\n handleThumbMouseDown,\n setIsThumbHovered,\n}) => {\n return (\n <div\n ref={thumbRef}\n className=\"overlay-scrollbar-thumb\"\n onMouseDown={handleThumbMouseDown}\n onMouseEnter={() => setIsThumbHovered(true)}\n onMouseLeave={() => setIsThumbHovered(false)}\n style={{\n position: \"absolute\",\n top: `${\n (showArrows\n ? finalThumbWidth + finalTrackConfig.margin * 2\n : finalTrackConfig.margin) + thumbTop\n }px`,\n right:\n finalTrackConfig.alignment === \"right\"\n ? \"0px\"\n : `${(adjustedTrackWidth - finalThumbWidth) / 2}px`,\n width: `${finalThumbWidth}px`,\n height: `${Math.max(thumbHeight, thumbMinHeight)}px`,\n backgroundColor:\n isThumbHovered || isDragging\n ? finalThumbConfig.hoverColor\n : finalThumbConfig.color,\n opacity:\n isThumbHovered || isDragging\n ? finalThumbConfig.hoverOpacity\n : finalThumbConfig.opacity,\n borderRadius: `${finalThumbConfig.radius}px`,\n cursor: \"pointer\",\n transition:\n \"background-color 0.2s ease-in-out, opacity 0.2s ease-in-out\",\n }}\n />\n );\n};\n", "/**\n * ScrollbarArrows.tsx\n * \uC2A4\uD06C\uB864\uBC14 \uD654\uC0B4\uD45C \uBC84\uD2BC \uCEF4\uD3EC\uB10C\uD2B8\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nimport React from \"react\";\n\ninterface ScrollbarArrowsProps {\n adjustedTrackWidth: number;\n finalThumbWidth: number;\n scrollbarVisible: boolean;\n hoveredArrow: \"up\" | \"down\" | null;\n finalArrowsConfig: {\n color: string;\n opacity: number;\n hoverColor: string;\n hoverOpacity: number;\n };\n finalTrackConfig: {\n alignment: string;\n margin: number;\n };\n setHoveredArrow: (arrow: \"up\" | \"down\" | null) => void;\n handleUpArrowClick: (e: React.MouseEvent) => void;\n handleDownArrowClick: (e: React.MouseEvent) => void;\n}\n\nexport const ScrollbarArrows: React.FC<ScrollbarArrowsProps> = ({\n adjustedTrackWidth,\n finalThumbWidth,\n scrollbarVisible,\n hoveredArrow,\n finalArrowsConfig,\n finalTrackConfig,\n setHoveredArrow,\n handleUpArrowClick,\n handleDownArrowClick,\n}) => {\n const arrowStyle = {\n position: \"absolute\" as const,\n width: `${finalThumbWidth}px`,\n height: `${finalThumbWidth}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: `${Math.max(finalThumbWidth * 0.75, 8)}px`,\n userSelect: \"none\" as const,\n zIndex: 1001,\n transition: \"opacity 0.2s ease-in-out, color 0.15s ease-in-out\",\n right:\n finalTrackConfig.alignment === \"right\"\n ? \"0px\"\n : `${(adjustedTrackWidth - finalThumbWidth) / 2}px`,\n };\n\n return (\n <>\n {/* \uC704\uCABD \uD654\uC0B4\uD45C */}\n <div\n className=\"overlay-scrollbar-up-arrow\"\n onClick={handleUpArrowClick}\n onMouseEnter={() => setHoveredArrow(\"up\")}\n onMouseLeave={() => setHoveredArrow(null)}\n style={{\n ...arrowStyle,\n top: `${finalTrackConfig.margin}px`,\n color:\n hoveredArrow === \"up\"\n ? finalArrowsConfig.hoverColor\n : finalArrowsConfig.color,\n opacity: scrollbarVisible\n ? hoveredArrow === \"up\"\n ? finalArrowsConfig.hoverOpacity\n : finalArrowsConfig.opacity\n : 0,\n }}\n >\n \u25B2\n </div>\n\n {/* \uC544\uB798\uCABD \uD654\uC0B4\uD45C */}\n <div\n className=\"overlay-scrollbar-down-arrow\"\n onClick={handleDownArrowClick}\n onMouseEnter={() => setHoveredArrow(\"down\")}\n onMouseLeave={() => setHoveredArrow(null)}\n style={{\n ...arrowStyle,\n bottom: `${finalTrackConfig.margin}px`,\n color:\n hoveredArrow === \"down\"\n ? finalArrowsConfig.hoverColor\n : finalArrowsConfig.color,\n opacity: scrollbarVisible\n ? hoveredArrow === \"down\"\n ? finalArrowsConfig.hoverOpacity\n : finalArrowsConfig.opacity\n : 0,\n }}\n >\n \u25BC\n </div>\n </>\n );\n};\n"],
|
|
5
|
-
"mappings": "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aACA,sBACA,8BACA,sBACA,eACA,qBACA,aACA,mBACA,kBACA,sBACA,aACA,mBACA,oBACA,aACA,eACA,uBACA,YACA,oBACA,WACA,aACA,kBACA,gBACA,wBACA,UACA,eACA,uBACA,WACA,gBACA,cACA,cACA,YACA,aACA,kBACA,oBACA,eACA,eAGA,WACA,cACA,YACA,oBACA,oBACA,iBACA,YACA,cACA,iBACA,YACA,YACA,kBACA,cACA,iBACA,cACA,aACA,mBACA,aACA,YACA,WACA,mBACA,kBACA,aACA,qBACA,UACA,kBACA,eACA,gBACA,WAEA,WACA,eACA,iBACA,eACA,gBACA,kBACA,aACA,eACA,eACA,iBACA,cAGA,YACA,eACA,aACA,YACA,kBACA,oBACA,aACA,UACA,YACA,QACA,cAGA,gBACA,2BACA,aACA,2BACA,4BAGA,aACA,kBACA,mBACA,oBACA,mBACA,YACA,aACA,aAGA,uBACA,oBACA,gBACA,cACA,mBAGA,YACA,aACA,aACA,sBACA,YAGA,eACA,gBAGA,mBACA,8BACA,6BAGA,gBACA,wBACA,wBACA,iBACA,uBACA,gBAGA,cACA,mBACA,UACA,aACA,aACJ,EAQaC,GAAqB,CAC9BC,EACAC,IACU,CACV,IAAMC,EAAUF,EAAQ,QAAQ,YAAY,EACtCG,EAAa,CACf,OACA,WACA,QACA,SACA,SACA,MACA,MACA,WACA,OACJ,EAGA,GAAID,IAAY,QAAS,CACrB,IAAME,EAAQJ,EAA6B,KAC3C,OAAOG,EAAW,SAASC,CAAI,CACnC,CAuBA,GApBI,CAAC,WAAY,SAAU,QAAQ,EAAE,SAASF,CAAO,GAMjD,CACI,MACA,OACA,SACA,OACA,OACA,UACA,UACJ,EAAE,SAASA,CAAO,GAMlBF,EAAQ,aAAa,iBAAiB,IAAM,OAC5C,MAAO,GAIX,GAAIC,GAAQ,kBACR,QAAWI,KAAYJ,EAAO,iBAC1B,GAAID,EAAQ,QAAQK,CAAQ,EACxB,MAAO,GAKnB,OAAOC,GAAuBN,EAASC,CAAM,CACjD,EAKMK,GAAyB,CAC3BN,EACAC,IACU,CAEV,IAAMM,E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",
|
|
6
|
-
"names": ["index_exports", "__export", "OverlayScrollbar_default", "__toCommonJS", "import_react", "
|
|
3
|
+
"sources": ["../src/index.ts", "../src/OverlayScrollbar.tsx", "../src/utils/dragScrollUtils.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * src/index.ts\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n */\n\nexport { default } from \"./OverlayScrollbar\";\nexport { default as OverlayScrollbar } from \"./OverlayScrollbar\";\nexport type {\n OverlayScrollbarRef,\n OverlayScrollbarProps,\n ThumbConfig,\n TrackConfig,\n ArrowsConfig,\n DragScrollConfig,\n AutoHideConfig,\n} from \"./types\";\n", "/**\n * OverlayScrollbar.tsx\n *\n * @copyright 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport React, {\n useRef,\n useEffect,\n useState,\n useCallback,\n useMemo,\n ReactNode,\n forwardRef,\n useImperativeHandle,\n useLayoutEffect,\n} from \"react\";\nimport { isTextInputElement } from \"./utils/dragScrollUtils\";\n\n// thumb \uAD00\uB828 \uC124\uC815\nexport interface ThumbConfig {\n width?: number; // \uC378\uC758 \uB108\uBE44 (\uAE30\uBCF8\uAC00: 8px)\n minHeight?: number; // \uC378\uC758 \uCD5C\uC18C \uB192\uC774 (\uAE30\uBCF8\uAC00: 50px)\n radius?: number; // \uC378\uC758 border-radius (\uAE30\uBCF8\uAC00: width / 2)\n color?: string; // \uC378 \uC0C9\uC0C1 (\uAE30\uBCF8\uAC00: \"#606060\")\n opacity?: number; // \uAE30\uBCF8 \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC00: 0.6)\n hoverColor?: string; // \uD638\uBC84 \uC2DC \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: color \uB3D9\uC77C)\n hoverOpacity?: number; // \uD638\uBC84 \uC2DC \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC00: 1.0)\n}\n\n// track \uAD00\uB828 \uC124\uC815\nexport interface TrackConfig {\n width?: number; // \uD638\uBC84 \uC601\uC5ED\uC778 \uD2B8\uB799\uC758 \uB108\uBE44 (\uAE30\uBCF8\uAC12: 16px)\n color?: string; // \uD2B8\uB799 \uBC30\uACBD \uC0C9\uC0C1 (\uAE30\uBCF8\uAC12: \"rgba(128, 128, 128, 0.1)\")\n visible?: boolean; // \uD2B8\uB799 \uBC30\uACBD \uD45C\uC2DC \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n alignment?: \"center\" | \"outside\"; // \uD2B8\uB799 \uC815\uB82C (\uAE30\uBCF8\uAC12: \"center\", \"outside\"\uB294 \uC624\uB978\uCABD/\uC544\uB798 \uB05D\uC5D0 \uBD99\uC74C)\n radius?: number; // \uD2B8\uB799 \uBC30\uACBD\uC758 border-radius (\uAE30\uBCF8\uAC12: thumb.radius \uB610\uB294 4px)\n margin?: number; // \uD2B8\uB799 \uC0C1\uD558 \uB9C8\uC9C4 (\uAE30\uBCF8\uAC12: 4px)\n}\n\n// arrows \uAD00\uB828 \uC124\uC815\nexport interface ArrowsConfig {\n visible?: boolean; // \uD654\uC0B4\uD45C \uD45C\uC2DC \uC5EC\uBD80 (\uAE30\uBCF8\uAC00: false)\n step?: number; // \uD654\uC0B4\uD45C \uD074\uB9AD\uC2DC \uC2A4\uD06C\uB864 \uC774\uB3D9 \uAC70\uB9AC (\uAE30\uBCF8\uAC00: 50px)\n color?: string; // \uD654\uC0B4\uD45C \uC0C9\uC0C1 (\uAE30\uBCF8\uAC00: \"#808080\")\n opacity?: number; // \uAE30\uBCF8 \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC00: 0.6)\n hoverColor?: string; // \uD638\uBC84 \uC2DC \uC0C9\uC0C1 (\uAE30\uBCF8\uAC00: color \uB3D9\uC77C)\n hoverOpacity?: number; // \uD638\uBC84 \uC2DC \uD22C\uBA85\uB3C4 (\uAE30\uBCF8\uAC00: 1.0)\n}\n\n// \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAD00\uB828 \uC124\uC815\nexport interface DragScrollConfig {\n enabled?: boolean; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uD65C\uC131\uD654 \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n excludeClasses?: string[]; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uCD94\uAC00 \uD074\uB798\uC2A4\uB4E4 (\uC790\uC2E0 \uB610\uB294 \uBD80\uBAA8 \uC694\uC18C \uD655\uC778, \uCD5C\uB300 5\uB2E8\uACC4)\n excludeSelectors?: string[]; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uCD94\uAC00 CSS \uC140\uB809\uD130\uB4E4 (element.matches() \uC0AC\uC6A9)\n}\n\n// \uC790\uB3D9 \uC228\uAE40 \uAD00\uB828 \uC124\uC815\nexport interface AutoHideConfig {\n enabled?: boolean; // \uC790\uB3D9 \uC228\uAE40 \uD65C\uC131\uD654 \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n delay?: number; // \uAE30\uBCF8 \uC790\uB3D9 \uC228\uAE40 \uC2DC\uAC04 (\uAE30\uBCF8\uAC12: 1500ms)\n delayOnWheel?: number; // \uD720 \uC2A4\uD06C\uB864 \uD6C4 \uC790\uB3D9 \uC228\uAE40 \uC2DC\uAC04 (\uAE30\uBCF8\uAC00: 700ms)\n initialDelay?: number; // \uB9C8\uC6B4\uD2B8 \uD6C4 \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC \uC9C0\uC5F0 \uC2DC\uAC04 (\uAE30\uBCF8\uAC12: 200ms, 0\uBCF4\uB2E4 \uD06C\uBA74 \uCD08\uAE30 \uC2A4\uD06C\uB864 \uC2DC \uC2A4\uD06C\uB864\uBC14 \uC228\uAE40)\n}\n\nexport interface OverlayScrollbarProps {\n className?: string;\n style?: React.CSSProperties; // wrapper div\uC5D0 \uC801\uC6A9\uD560 \uC2A4\uD0C0\uC77C\n containerStyle?: React.CSSProperties; // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 div\uC5D0 \uC801\uC6A9\uD560 \uC2A4\uD0C0\uC77C\n contentStyle?: React.CSSProperties; // \uB0B4\uBD80 content div\uC5D0 \uC801\uC6A9\uD560 \uC2A4\uD0C0\uC77C\n children: ReactNode;\n onScroll?: (event: Event) => void;\n\n // \uADF8\uB8F9\uD654\uB41C \uC124\uC815 \uAC1D\uCCB4\uB4E4\n thumb?: ThumbConfig; // \uC378 \uAD00\uB828 \uC124\uC815\n track?: TrackConfig; // \uD2B8\uB799 \uAD00\uB828 \uC124\uC815\n arrows?: ArrowsConfig; // \uD654\uC0B4\uD45C\uB4E4 \uAD00\uB828 \uC124\uC815\n dragScroll?: DragScrollConfig; // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uAD00\uB828 \uC124\uC815\n autoHide?: AutoHideConfig; // \uC790\uB3D9 \uC228\uAE40 \uAD00\uB828 \uC124\uC815\n\n // \uAE30\uD0C0 \uC124\uC815\uB4E4\n showScrollbar?: boolean; // \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: true)\n detectInnerScroll?: boolean; // children \uB0B4\uBD80\uC758 \uC2A4\uD06C\uB864 \uC694\uC18C \uAC10\uC9C0 \uC5EC\uBD80 (\uAE30\uBCF8\uAC12: false, \uAC00\uC0C1 \uD14C\uC774\uBE14 \uB4F1\uC5D0 \uC0AC\uC6A9)\n}\n\n// OverlayScrollbar\uAC00 \uB178\uCD9C\uD560 \uBA54\uC11C\uB4DC\uB4E4\nexport interface OverlayScrollbarRef {\n getScrollContainer: () => HTMLDivElement | null;\n scrollTo: (options: ScrollToOptions) => void;\n scrollTop: number;\n scrollHeight: number;\n clientHeight: number;\n}\n\n// \uAE30\uBCF8 \uC124\uC815 \uAC1D\uCCB4\uB4E4\uC744 \uCEF4\uD3EC\uB10C\uD2B8 \uC678\uBD80\uC5D0 \uC0C1\uC218\uB85C \uC120\uC5B8 (\uC7AC\uB80C\uB354\uB9C1 \uC2DC \uB3D9\uC77C\uD55C \uCC38\uC870 \uC720\uC9C0)\nconst DEFAULT_THUMB_CONFIG: ThumbConfig = {};\nconst DEFAULT_TRACK_CONFIG: TrackConfig = {};\nconst DEFAULT_ARROWS_CONFIG: ArrowsConfig = {};\nconst DEFAULT_DRAG_SCROLL_CONFIG: DragScrollConfig = {};\nconst DEFAULT_AUTO_HIDE_CONFIG: AutoHideConfig = {};\n\nconst OverlayScrollbar = forwardRef<OverlayScrollbarRef, OverlayScrollbarProps>(\n (\n {\n className = \"\",\n style = {},\n containerStyle = {},\n contentStyle = {},\n children,\n onScroll,\n\n // \uADF8\uB8F9\uD654\uB41C \uC124\uC815 \uAC1D\uCCB4\uB4E4\n thumb = DEFAULT_THUMB_CONFIG,\n track = DEFAULT_TRACK_CONFIG,\n arrows = DEFAULT_ARROWS_CONFIG,\n dragScroll = DEFAULT_DRAG_SCROLL_CONFIG,\n autoHide = DEFAULT_AUTO_HIDE_CONFIG,\n\n // \uAE30\uD0C0 \uC124\uC815\uB4E4\n showScrollbar = true,\n detectInnerScroll = false,\n },\n ref\n ) => {\n // props \uBCC0\uACBD \uCD94\uC801\uC6A9 ref\n const prevPropsRef = useRef<{\n children?: ReactNode;\n onScroll?: (event: Event) => void;\n showScrollbar?: boolean;\n thumb?: ThumbConfig;\n track?: TrackConfig;\n arrows?: ArrowsConfig;\n dragScroll?: DragScrollConfig;\n autoHide?: AutoHideConfig;\n }>({});\n\n // \uB80C\uB354\uB9C1 \uC2DC \uC5B4\uB5A4 prop\uC774 \uBCC0\uACBD\uB418\uC5C8\uB294\uC9C0 \uCCB4\uD06C\n useEffect(() => {\n // \uD604\uC7AC props \uC800\uC7A5\n prevPropsRef.current = {\n children,\n onScroll,\n showScrollbar,\n thumb,\n track,\n arrows,\n dragScroll,\n autoHide,\n };\n });\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n const containerRef = useRef<HTMLDivElement>(null);\n const contentRef = useRef<HTMLDivElement>(null);\n const scrollbarRef = useRef<HTMLDivElement>(null);\n const thumbRef = useRef<HTMLDivElement>(null);\n\n // \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uCE90\uC2F1\uC6A9 ref (\uC131\uB2A5 \uCD5C\uC801\uD654)\n const cachedScrollContainerRef = useRef<HTMLElement | null>(null);\n\n // \uAE30\uBCF8 \uC0C1\uD0DC\uB4E4\n const [scrollbarVisible, setScrollbarVisible] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n const [isThumbHovered, setIsThumbHovered] = useState(false);\n const [dragStart, setDragStart] = useState({ y: 0, scrollTop: 0 });\n const [thumbHeight, setThumbHeight] = useState(0);\n const [thumbTop, setThumbTop] = useState(0);\n const [hasScrollableContent, setHasScrollableContent] = useState(false);\n\n // \uAC00\uB85C \uC2A4\uD06C\uB864\uBC14 \uC0C1\uD0DC\n const [isHorizontalThumbHovered, setIsHorizontalThumbHovered] =\n useState(false);\n const [isDraggingHorizontal, setIsDraggingHorizontal] = useState(false);\n const [dragStartHorizontal, setDragStartHorizontal] = useState({\n x: 0,\n scrollLeft: 0,\n });\n const [thumbWidth, setThumbWidth] = useState(0);\n const [thumbLeft, setThumbLeft] = useState(0);\n const [\n hasHorizontalScrollableContent,\n setHasHorizontalScrollableContent,\n ] = useState(false);\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC0C1\uD0DC\n const [isDragScrolling, setIsDragScrolling] = useState(false);\n const [dragScrollStart, setDragScrollStart] = useState({\n x: 0,\n y: 0,\n scrollTop: 0,\n scrollLeft: 0,\n });\n const [activeArrow, setActiveArrow] = useState<\"up\" | \"down\" | null>(\n null\n );\n const [hoveredArrow, setHoveredArrow] = useState<\"up\" | \"down\" | null>(\n null\n );\n\n // \uCD08\uAE30 \uB9C8\uC6B4\uD2B8 \uC2DC hover \uBC29\uC9C0\uC6A9\n const [isInitialized, setIsInitialized] = useState(false);\n\n // \uD720 \uC2A4\uD06C\uB864 \uAC10\uC9C0\uC6A9\n const wheelTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n const [isWheelScrolling, setIsWheelScrolling] = useState(false);\n\n // \uC228\uAE40 \uD0C0\uC774\uBA38\n const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // \uD638\uBC84 \uC9C4\uC785 \uD0C0\uC774\uBA38 (\uB514\uBC14\uC6B4\uC2A4\uC6A9)\n const hoverEnterTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // \uD720 \uC774\uBCA4\uD2B8 \uD45C\uC2DC \uD0C0\uC774\uBA38 (\uB514\uBC14\uC6B4\uC2A4\uC6A9)\n const wheelShowTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // \uADF8\uB8F9\uD654\uB41C \uC124\uC815 \uAC1D\uCCB4\uB4E4\uC5D0 \uAE30\uBCF8\uAC12 \uC124\uC815\n const finalThumbConfig = useMemo(() => {\n const baseColor = thumb.color ?? \"#606060\";\n return {\n width: thumb.width ?? 8,\n minHeight: thumb.minHeight ?? 50,\n radius: thumb.radius ?? (thumb.width ?? 8) / 2,\n color: baseColor,\n opacity: thumb.opacity ?? 0.6,\n hoverColor: thumb.hoverColor ?? baseColor,\n hoverOpacity: thumb.hoverOpacity ?? 1.0,\n };\n }, [thumb]);\n\n const finalTrackConfig = useMemo(\n () => ({\n width: track.width ?? 16,\n color: track.color ?? \"rgba(128, 128, 128, 0.1)\",\n visible: track.visible ?? true,\n alignment: track.alignment ?? \"center\",\n radius: track.radius ?? finalThumbConfig.radius ?? 4,\n margin: track.margin ?? 4,\n }),\n [track, finalThumbConfig.radius]\n );\n\n const finalArrowsConfig = useMemo(() => {\n const baseColor = arrows.color ?? \"#808080\";\n return {\n visible: arrows.visible ?? false,\n step: arrows.step ?? 50,\n color: baseColor,\n opacity: arrows.opacity ?? 0.6,\n hoverColor: arrows.hoverColor ?? baseColor,\n hoverOpacity: arrows.hoverOpacity ?? 1.0,\n };\n }, [arrows]);\n\n const finalDragScrollConfig = useMemo(\n () => ({\n enabled: dragScroll.enabled ?? true,\n excludeClasses: dragScroll.excludeClasses ?? [],\n excludeSelectors: dragScroll.excludeSelectors ?? [],\n }),\n [dragScroll]\n );\n\n const finalAutoHideConfig = useMemo(\n () => ({\n enabled: autoHide.enabled ?? true,\n delay: autoHide.delay ?? 1500,\n delayOnWheel: autoHide.delayOnWheel ?? 700,\n initialDelay: autoHide.initialDelay ?? 200,\n }),\n [autoHide]\n );\n\n // \uCD08\uAE30 \uB9C8\uC6B4\uD2B8 \uC2DC \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC \uC9C0\uC5F0 \uC0C1\uD0DC\n const [isInitialDelayActive, setIsInitialDelayActive] = useState(\n () => (autoHide.initialDelay ?? 200) > 0\n );\n\n // \uD638\uD658\uC131\uC744 \uC704\uD55C \uBCC0\uC218\uB4E4 (\uC790\uC8FC \uC0AC\uC6A9\uB418\uB294 \uBCC0\uC218\uB4E4\uB9CC \uC720\uC9C0)\n const finalThumbWidth = finalThumbConfig.width;\n const finalTrackWidth = finalTrackConfig.width;\n const thumbMinHeight = finalThumbConfig.minHeight;\n const showArrows = finalArrowsConfig.visible;\n const arrowStep = finalArrowsConfig.step;\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 \uD568\uC218 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n const maintainFocus = useCallback(() => {\n if (!containerRef.current) return;\n\n // \uD604\uC7AC \uD3EC\uCEE4\uC2A4\uB41C \uC694\uC18C \uD655\uC778\n const activeElement = document.activeElement;\n\n // \uC624\uBC84\uB808\uC774 \uC2A4\uD06C\uB864\uBC14 \uB0B4\uBD80\uC5D0 \uC774\uBBF8 \uD3EC\uCEE4\uC2A4\uB41C \uC694\uC18C\uAC00 \uC788\uC73C\uBA74 \uC2A4\uD0B5\n if (\n activeElement &&\n containerRef.current.contains(activeElement) &&\n activeElement !== containerRef.current\n ) {\n return;\n }\n\n // \uD3EC\uCEE4\uC2A4\uB41C \uC694\uC18C\uAC00 \uC5C6\uAC70\uB098 \uC678\uBD80\uC5D0 \uC788\uC73C\uBA74 \uCEE8\uD14C\uC774\uB108\uC5D0 \uD3EC\uCEE4\uC2A4\n containerRef.current.focus();\n }, []);\n\n // ref\uB97C \uD1B5\uD574 \uC678\uBD80\uC5D0\uC11C \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108\uC5D0 \uC811\uADFC\uD560 \uC218 \uC788\uB3C4\uB85D \uD568\n useImperativeHandle(\n ref,\n () => ({\n getScrollContainer: () => containerRef.current,\n scrollTo: (options: ScrollToOptions) => {\n if (containerRef.current) {\n containerRef.current.scrollTo(options);\n }\n },\n get scrollTop() {\n return containerRef.current?.scrollTop || 0;\n },\n get scrollHeight() {\n return containerRef.current?.scrollHeight || 0;\n },\n get clientHeight() {\n return containerRef.current?.clientHeight || 0;\n },\n }),\n []\n );\n\n // \uC2E4\uC81C \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C \uCC3E\uAE30 (\uCE90\uC2F1 \uCD5C\uC801\uD654)\n const findScrollableElement = useCallback((): HTMLElement | null => {\n // \uCE90\uC2DC\uB41C \uC694\uC18C\uAC00 \uC5EC\uC804\uD788 \uC720\uD6A8\uD55C\uC9C0 \uD655\uC778\n if (cachedScrollContainerRef.current) {\n const cached = cachedScrollContainerRef.current;\n // DOM\uC5D0 \uC5F0\uACB0\uB418\uC5B4 \uC788\uACE0 \uC5EC\uC804\uD788 \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C\uC9C0 \uD655\uC778\n if (\n document.contains(cached) &&\n cached.scrollHeight > cached.clientHeight + 2\n ) {\n return cached;\n }\n // \uCE90\uC2DC \uBB34\uD6A8\uD654\n cachedScrollContainerRef.current = null;\n }\n\n if (!containerRef.current) {\n return null;\n }\n\n // \uB0B4\uBD80 \uCEE8\uD14C\uC774\uB108\uC758 \uC2A4\uD06C\uB864 \uAC00\uB2A5 \uC5EC\uBD80 \uD655\uC778\n if (\n contentRef.current &&\n contentRef.current.scrollHeight >\n containerRef.current.clientHeight + 2\n ) {\n cachedScrollContainerRef.current = containerRef.current;\n return containerRef.current;\n }\n\n // detectInnerScroll \uC635\uC158\uC774 \uD65C\uC131\uD654\uB41C \uACBD\uC6B0\uC5D0\uB9CC children \uB0B4\uBD80\uC758 \uC2A4\uD06C\uB864 \uC694\uC18C \uCC3E\uAE30\n // (\uAC00\uC0C1 \uD14C\uC774\uBE14 \uB4F1 \uB0B4\uBD80\uC5D0\uC11C \uC2A4\uD06C\uB864\uC744 \uCC98\uB9AC\uD558\uB294 \uACBD\uC6B0\uC5D0 \uC0AC\uC6A9)\n if (!detectInnerScroll) {\n return null;\n }\n\n // children \uC694\uC18C\uC5D0\uC11C \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C \uCC3E\uAE30\n // \uC911\uCCA9\uB41C OverlayScrollbar\uC758 \uC601\uC5ED\uC740 \uC81C\uC678 (\uB2E4\uB978 OverlayScrollbar\uC758 container\uB294 \uC2A4\uD0B5)\n const childScrollableElements =\n containerRef.current.querySelectorAll(\n '[data-virtuoso-scroller], [style*=\"overflow\"], .virtuoso-scroller, [style*=\"overflow: auto\"], [style*=\"overflow:auto\"]'\n );\n\n for (const child of childScrollableElements) {\n const element = child as HTMLElement;\n\n // \uC774 \uC694\uC18C\uAC00 \uB2E4\uB978 OverlayScrollbar\uC758 container\uC778\uC9C0 \uD655\uC778\n // (\uC790\uC2E0\uC758 containerRef\uB294 \uC544\uB2C8\uC5B4\uC57C \uD558\uACE0, overlay-scrollbar-container \uD074\uB798\uC2A4\uB97C \uAC00\uC9C4 \uACBD\uC6B0)\n if (\n element !== containerRef.current &&\n element.classList.contains(\"overlay-scrollbar-container\")\n ) {\n // \uC911\uCCA9\uB41C OverlayScrollbar\uC758 container\uC774\uBBC0\uB85C \uC2A4\uD0B5\n continue;\n }\n\n // \uC774 \uC694\uC18C\uC758 \uBD80\uBAA8 \uC911\uC5D0 \uB2E4\uB978 OverlayScrollbar container\uAC00 \uC788\uB294\uC9C0 \uD655\uC778\n let parent: HTMLElement | null = element.parentElement;\n let isNestedInAnotherScrollbar = false;\n\n while (parent && parent !== containerRef.current) {\n if (\n parent.classList.contains(\n \"overlay-scrollbar-container\"\n ) &&\n parent !== containerRef.current\n ) {\n // \uB2E4\uB978 OverlayScrollbar \uB0B4\uBD80\uC758 \uC694\uC18C\uC774\uBBC0\uB85C \uC2A4\uD0B5\n isNestedInAnotherScrollbar = true;\n break;\n }\n parent = parent.parentElement;\n }\n\n if (isNestedInAnotherScrollbar) {\n continue;\n }\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C\uC778\uC9C0 \uD655\uC778\n if (element.scrollHeight > element.clientHeight + 2) {\n cachedScrollContainerRef.current = element;\n return element;\n }\n }\n\n return null;\n }, []);\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5 \uC5EC\uBD80 \uCCB4\uD06C\n const isScrollable = useCallback(() => {\n return findScrollableElement() !== null;\n }, [findScrollableElement]);\n\n // \uD0C0\uC774\uBA38 \uC815\uB9AC\n const clearHideTimer = useCallback(() => {\n if (hideTimeoutRef.current) {\n clearTimeout(hideTimeoutRef.current);\n hideTimeoutRef.current = null;\n }\n }, []);\n\n const clearHoverEnterTimer = useCallback(() => {\n if (hoverEnterTimeoutRef.current) {\n clearTimeout(hoverEnterTimeoutRef.current);\n hoverEnterTimeoutRef.current = null;\n }\n }, []);\n\n const clearWheelShowTimer = useCallback(() => {\n if (wheelShowTimeoutRef.current) {\n clearTimeout(wheelShowTimeoutRef.current);\n wheelShowTimeoutRef.current = null;\n }\n }, []);\n\n // \uC2A4\uD06C\uB864\uBC14 \uC228\uAE30\uAE30 \uD0C0\uC774\uBA38\n const setHideTimer = useCallback(\n (delay: number) => {\n // \uC790\uB3D9 \uC228\uAE40\uC774 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uC73C\uBA74 \uD0C0\uC774\uBA38\uB97C \uC124\uC815\uD558\uC9C0 \uC54A\uC74C\n if (!finalAutoHideConfig.enabled) {\n return;\n }\n clearHideTimer();\n hideTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(false);\n hideTimeoutRef.current = null;\n }, delay);\n },\n [clearHideTimer, finalAutoHideConfig.enabled]\n );\n\n // \uC2A4\uD06C\uB864\uBC14 \uC704\uCE58 \uBC0F \uD06C\uAE30 \uC5C5\uB370\uC774\uD2B8\n const updateScrollbar = useCallback(() => {\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) {\n // \uC2A4\uD06C\uB864 \uBD88\uAC00\uB2A5\uD558\uBA74 \uC228\uAE40\n setScrollbarVisible(false);\n setHasScrollableContent(false);\n setHasHorizontalScrollableContent(false);\n clearHideTimer();\n return;\n }\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uCF58\uD150\uCE20\uAC00 \uC788\uC74C\uC744 \uD45C\uC2DC\n setHasScrollableContent(true);\n\n if (!scrollbarRef.current) return;\n\n // \uC790\uB3D9 \uC228\uAE40\uC774 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uACE0 \uCD08\uAE30 \uC9C0\uC5F0\uC774 \uB05D\uB0AC\uC73C\uBA74 \uC2A4\uD06C\uB864\uBC14\uB97C \uD56D\uC0C1 \uD45C\uC2DC\n if (!finalAutoHideConfig.enabled && !isInitialDelayActive) {\n setScrollbarVisible(true);\n clearHideTimer();\n }\n\n const containerHeight = scrollableElement.clientHeight;\n const contentHeight = scrollableElement.scrollHeight;\n const scrollTop = scrollableElement.scrollTop;\n\n const containerWidth = scrollableElement.clientWidth;\n const contentWidth = scrollableElement.scrollWidth;\n const scrollLeft = scrollableElement.scrollLeft;\n\n // wrapper\uC758 \uD328\uB529 \uACC4\uC0B0 (\uC0C1\uD558 \uD328\uB529\uB9CC \uD544\uC694)\n let wrapperPaddingTopBottom = 0;\n if (wrapperRef.current) {\n const computedStyle = window.getComputedStyle(\n wrapperRef.current\n );\n const paddingTop = parseFloat(computedStyle.paddingTop) || 0;\n const paddingBottom =\n parseFloat(computedStyle.paddingBottom) || 0;\n wrapperPaddingTopBottom = paddingTop + paddingBottom;\n }\n\n // \uD654\uC0B4\uD45C\uC640 \uAC04\uACA9 \uACF5\uAC04 \uACC4\uC0B0 (\uD654\uC0B4\uD45C + \uC704\uC544\uB798 \uB9C8\uC9C4, \uD654\uC0B4\uD45C \uC5C6\uC5B4\uB3C4 \uC704\uC544\uB798 \uB9C8\uC9C4)\n const arrowSpace = showArrows\n ? finalThumbWidth * 2 + finalTrackConfig.margin * 4\n : finalTrackConfig.margin * 2;\n\n // \uC378 \uB192\uC774 \uACC4\uC0B0 (\uC0AC\uC6A9\uC790 \uC124\uC815 \uCD5C\uC18C \uB192\uC774 \uC0AC\uC6A9, \uD654\uC0B4\uD45C \uACF5\uAC04 \uC81C\uC678, wrapper \uD328\uB529 \uCD94\uAC00)\n const availableHeight =\n containerHeight - arrowSpace + wrapperPaddingTopBottom;\n const scrollRatio = containerHeight / contentHeight;\n const calculatedThumbHeight = Math.max(\n availableHeight * scrollRatio,\n thumbMinHeight\n );\n\n // \uC378 \uC704\uCE58 \uACC4\uC0B0 (\uD654\uC0B4\uD45C\uC640 \uAC04\uACA9 \uACF5\uAC04 \uC81C\uC678)\n const scrollableHeight = contentHeight - containerHeight;\n const thumbScrollableHeight =\n availableHeight - calculatedThumbHeight;\n const calculatedThumbTop =\n scrollableHeight > 0\n ? (scrollTop / scrollableHeight) * thumbScrollableHeight\n : 0;\n\n setThumbHeight(calculatedThumbHeight);\n setThumbTop(calculatedThumbTop);\n\n // \uAC00\uB85C \uC2A4\uD06C\uB864\uBC14 \uACC4\uC0B0\n const horizontalScrollableWidth = contentWidth - containerWidth;\n if (horizontalScrollableWidth > 0) {\n setHasHorizontalScrollableContent(true);\n\n const scrollRatioHorizontal = containerWidth / contentWidth;\n const calculatedThumbWidth = Math.max(\n containerWidth * scrollRatioHorizontal,\n 50 // \uCD5C\uC18C \uB108\uBE44\n );\n\n const thumbScrollableWidth =\n containerWidth - calculatedThumbWidth;\n const calculatedThumbLeft =\n horizontalScrollableWidth > 0\n ? (scrollLeft / horizontalScrollableWidth) *\n thumbScrollableWidth\n : 0;\n\n setThumbWidth(calculatedThumbWidth);\n setThumbLeft(calculatedThumbLeft);\n } else {\n setHasHorizontalScrollableContent(false);\n }\n }, [\n findScrollableElement,\n clearHideTimer,\n showArrows,\n finalThumbWidth,\n thumbMinHeight,\n finalAutoHideConfig.enabled,\n isInitialDelayActive,\n ]);\n\n // \uC378 \uB4DC\uB798\uADF8 \uC2DC\uC791\n const handleThumbMouseDown = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n setIsDragging(true);\n setDragStart({\n y: event.clientY,\n scrollTop: actualScrollContainer.scrollTop,\n });\n\n clearHideTimer();\n setScrollbarVisible(true);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [findScrollableElement, clearHideTimer, maintainFocus]\n );\n\n // \uC378 \uB4DC\uB798\uADF8 \uC911\n const handleMouseMove = useCallback(\n (event: MouseEvent) => {\n if (!isDragging) return;\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n const containerHeight = actualScrollContainer.clientHeight;\n const contentHeight = actualScrollContainer.scrollHeight;\n const scrollableHeight = contentHeight - containerHeight;\n\n const deltaY = event.clientY - dragStart.y;\n const thumbScrollableHeight = containerHeight - thumbHeight;\n const scrollDelta =\n (deltaY / thumbScrollableHeight) * scrollableHeight;\n\n const newScrollTop = Math.max(\n 0,\n Math.min(\n scrollableHeight,\n dragStart.scrollTop + scrollDelta\n )\n );\n\n actualScrollContainer.scrollTop = newScrollTop;\n updateScrollbar();\n },\n [\n isDragging,\n dragStart,\n thumbHeight,\n updateScrollbar,\n findScrollableElement,\n ]\n );\n\n // \uC378 \uB4DC\uB798\uADF8 \uC885\uB8CC\n const handleMouseUp = useCallback(() => {\n setIsDragging(false);\n if (isScrollable()) {\n setHideTimer(finalAutoHideConfig.delay); // \uAE30\uBCF8 \uC228\uAE40 \uC2DC\uAC04 \uC801\uC6A9\n }\n }, [isScrollable, setHideTimer, finalAutoHideConfig.delay]);\n\n // \uD2B8\uB799 \uD074\uB9AD\uC73C\uB85C \uC2A4\uD06C\uB864 \uC810\uD504\n const handleTrackClick = useCallback(\n (event: React.MouseEvent) => {\n if (!scrollbarRef.current) {\n return;\n }\n\n const scrollbar = scrollbarRef.current;\n const rect = scrollbar.getBoundingClientRect();\n const clickY = event.clientY - rect.top;\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n const containerHeight = actualScrollContainer.clientHeight;\n const contentHeight = actualScrollContainer.scrollHeight;\n\n const scrollRatio = clickY / containerHeight;\n const newScrollTop =\n scrollRatio * (contentHeight - containerHeight);\n\n actualScrollContainer.scrollTop = Math.max(\n 0,\n Math.min(contentHeight - containerHeight, newScrollTop)\n );\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(finalAutoHideConfig.delay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n updateScrollbar,\n setHideTimer,\n finalAutoHideConfig.delay,\n findScrollableElement,\n maintainFocus,\n ]\n );\n\n // \uC704\uCABD \uD654\uC0B4\uD45C \uD074\uB9AD \uD578\uB4E4\uB7EC\n const handleUpArrowClick = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (!containerRef.current) return;\n\n const newScrollTop = Math.max(\n 0,\n containerRef.current.scrollTop - arrowStep\n );\n\n containerRef.current.scrollTop = newScrollTop;\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(finalAutoHideConfig.delay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n updateScrollbar,\n setHideTimer,\n arrowStep,\n finalAutoHideConfig.delay,\n maintainFocus,\n ]\n );\n\n // \uC544\uB798\uCABD \uD654\uC0B4\uD45C \uD074\uB9AD \uD578\uB4E4\uB7EC\n const handleDownArrowClick = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n if (!containerRef.current || !contentRef.current) return;\n\n const container = containerRef.current;\n const content = contentRef.current;\n const maxScrollTop =\n content.scrollHeight - container.clientHeight;\n const newScrollTop = Math.min(\n maxScrollTop,\n container.scrollTop + arrowStep\n );\n\n container.scrollTop = newScrollTop;\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(finalAutoHideConfig.delay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n updateScrollbar,\n setHideTimer,\n arrowStep,\n finalAutoHideConfig.delay,\n maintainFocus,\n ]\n );\n\n // \uAC00\uB85C \uC378 \uB4DC\uB798\uADF8 \uC2DC\uC791\n const handleHorizontalThumbMouseDown = useCallback(\n (event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n setIsDraggingHorizontal(true);\n setDragStartHorizontal({\n x: event.clientX,\n scrollLeft: actualScrollContainer.scrollLeft,\n });\n\n clearHideTimer();\n setScrollbarVisible(true);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [findScrollableElement, clearHideTimer, maintainFocus]\n );\n\n // \uAC00\uB85C \uC378 \uB4DC\uB798\uADF8 \uC911\n const handleHorizontalMouseMove = useCallback(\n (event: MouseEvent) => {\n if (!isDraggingHorizontal) return;\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n const containerWidth = actualScrollContainer.clientWidth;\n const contentWidth = actualScrollContainer.scrollWidth;\n const scrollableWidth = contentWidth - containerWidth;\n\n const deltaX = event.clientX - dragStartHorizontal.x;\n const thumbScrollableWidth = containerWidth - thumbWidth;\n const scrollDelta =\n (deltaX / thumbScrollableWidth) * scrollableWidth;\n\n const newScrollLeft = Math.max(\n 0,\n Math.min(\n scrollableWidth,\n dragStartHorizontal.scrollLeft + scrollDelta\n )\n );\n\n actualScrollContainer.scrollLeft = newScrollLeft;\n updateScrollbar();\n },\n [\n isDraggingHorizontal,\n dragStartHorizontal,\n thumbWidth,\n updateScrollbar,\n findScrollableElement,\n ]\n );\n\n // \uAC00\uB85C \uC378 \uB4DC\uB798\uADF8 \uC885\uB8CC\n const handleHorizontalMouseUp = useCallback(() => {\n setIsDraggingHorizontal(false);\n if (isScrollable()) {\n setHideTimer(finalAutoHideConfig.delay); // \uAE30\uBCF8 \uC228\uAE40 \uC2DC\uAC04 \uC801\uC6A9\n }\n }, [isScrollable, setHideTimer, finalAutoHideConfig.delay]);\n\n // \uAC00\uB85C \uD2B8\uB799 \uD074\uB9AD\uC73C\uB85C \uC2A4\uD06C\uB864 \uC810\uD504\n const handleHorizontalTrackClick = useCallback(\n (event: React.MouseEvent) => {\n if (!scrollbarRef.current) {\n return;\n }\n\n const scrollbar = scrollbarRef.current;\n const rect = scrollbar.getBoundingClientRect();\n const clickX = event.clientX - rect.left;\n\n const actualScrollContainer = findScrollableElement();\n if (!actualScrollContainer) {\n return;\n }\n\n const containerWidth = actualScrollContainer.clientWidth;\n const contentWidth = actualScrollContainer.scrollWidth;\n\n const scrollRatio = clickX / containerWidth;\n const newScrollLeft =\n scrollRatio * (contentWidth - containerWidth);\n\n actualScrollContainer.scrollLeft = Math.max(\n 0,\n Math.min(contentWidth - containerWidth, newScrollLeft)\n );\n updateScrollbar();\n\n setScrollbarVisible(true);\n setHideTimer(finalAutoHideConfig.delay);\n\n // \uD3EC\uCEE4\uC2A4 \uC720\uC9C0 (\uD0A4\uBCF4\uB4DC \uC785\uB825\uC774 \uACC4\uC18D \uC791\uB3D9\uD558\uB3C4\uB85D)\n maintainFocus();\n },\n [\n updateScrollbar,\n setHideTimer,\n finalAutoHideConfig.delay,\n findScrollableElement,\n maintainFocus,\n ]\n );\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC2DC\uC791\n const handleDragScrollStart = useCallback(\n (event: React.MouseEvent) => {\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uBE44\uD65C\uC131\uD654\uB41C \uACBD\uC6B0\n if (!finalDragScrollConfig.enabled) return;\n\n // \uD14D\uC2A4\uD2B8 \uC785\uB825 \uC694\uC18C\uB098 \uC81C\uC678 \uB300\uC0C1\uC774\uBA74 \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uD558\uC9C0 \uC54A\uC74C\n const target = event.target as Element;\n if (isTextInputElement(target, finalDragScrollConfig)) {\n return;\n }\n\n // \uC624\uB978\uCABD \uD074\uB9AD\uC774\uB098 \uD720 \uD074\uB9AD\uC740 \uC81C\uC678\n if (event.button !== 0) return;\n\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n // \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC601\uC5ED\uC774 \uC544\uB2C8\uBA74 \uC81C\uC678\n if (\n scrollableElement.scrollHeight <=\n scrollableElement.clientHeight &&\n scrollableElement.scrollWidth <=\n scrollableElement.clientWidth\n )\n return;\n\n event.preventDefault();\n setIsDragScrolling(true);\n setDragScrollStart({\n x: event.clientX,\n y: event.clientY,\n scrollTop: scrollableElement.scrollTop,\n scrollLeft: scrollableElement.scrollLeft || 0,\n });\n\n // \uC2A4\uD06C\uB864\uBC14\uB294 \uC2E4\uC81C \uB4DC\uB798\uADF8\uAC00 \uBC1C\uC0DD\uD560 \uB54C \uD45C\uC2DC (handleDragScrollMove\uC5D0\uC11C \uCC98\uB9AC)\n clearHideTimer();\n },\n [\n finalDragScrollConfig,\n isTextInputElement,\n findScrollableElement,\n clearHideTimer,\n ]\n );\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC911\n const handleDragScrollMove = useCallback(\n (event: MouseEvent) => {\n if (!isDragScrolling) return;\n\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n const deltaX = dragScrollStart.x - event.clientX;\n const deltaY = dragScrollStart.y - event.clientY;\n\n // \uBBF8\uC138\uD55C \uC6C0\uC9C1\uC784 \uBB34\uC2DC (3px \uC774\uD558)\n if (Math.abs(deltaY) < 3 && Math.abs(deltaX) < 3) {\n return;\n }\n\n // \uC2E4\uC81C \uB4DC\uB798\uADF8\uAC00 \uBC1C\uC0DD\uD588\uC73C\uBBC0\uB85C \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\n setScrollbarVisible(true);\n\n // \uC138\uB85C \uC2A4\uD06C\uB864 \uCC98\uB9AC\n const newScrollTop = Math.max(\n 0,\n Math.min(\n scrollableElement.scrollHeight -\n scrollableElement.clientHeight,\n dragScrollStart.scrollTop + deltaY\n )\n );\n\n // \uAC00\uB85C \uC2A4\uD06C\uB864 \uCC98\uB9AC\n const newScrollLeft = Math.max(\n 0,\n Math.min(\n scrollableElement.scrollWidth -\n scrollableElement.clientWidth,\n dragScrollStart.scrollLeft + deltaX\n )\n );\n\n scrollableElement.scrollTop = newScrollTop;\n scrollableElement.scrollLeft = newScrollLeft;\n updateScrollbar();\n },\n [\n isDragScrolling,\n dragScrollStart,\n findScrollableElement,\n updateScrollbar,\n ]\n );\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC885\uB8CC\n const handleDragScrollEnd = useCallback(() => {\n setIsDragScrolling(false);\n if (isScrollable()) {\n setHideTimer(finalAutoHideConfig.delay);\n }\n }, [isScrollable, setHideTimer, finalAutoHideConfig.delay]);\n\n // \uC2A4\uD06C\uB864 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 (externalScrollContainer \uC6B0\uC120 \uC0AC\uC6A9)\n useEffect(() => {\n const handleScroll = (event: Event) => {\n updateScrollbar();\n\n // \uCD08\uAE30 \uC9C0\uC5F0 \uC911\uC5D0\uB294 \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\uD558\uC9C0 \uC54A\uC74C\n if (isInitialDelayActive) {\n if (onScroll) {\n onScroll(event);\n }\n return;\n }\n\n // \uC2A4\uD06C\uB864 \uC911\uC5D0\uB294 \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\n clearHideTimer();\n setScrollbarVisible(true);\n\n // \uD720 \uC774\uBCA4\uD2B8 \uB514\uBC14\uC6B4\uC2A4 \uD0C0\uC774\uBA38 \uCDE8\uC18C (\uC2E4\uC81C \uC2A4\uD06C\uB864 \uBC1C\uC0DD \uC2DC)\n clearWheelShowTimer();\n\n // \uD720 \uC2A4\uD06C\uB864 \uC911\uC774\uBA74 \uBE60\uB978 \uC228\uAE40, \uC544\uB2C8\uBA74 \uAE30\uBCF8 \uC228\uAE40 \uC2DC\uAC04 \uC801\uC6A9\n const delay = isWheelScrolling\n ? finalAutoHideConfig.delayOnWheel\n : finalAutoHideConfig.delay;\n setHideTimer(delay);\n\n if (onScroll) {\n onScroll(event);\n }\n };\n\n const handleWheel = () => {\n // \uD720 \uC2A4\uD06C\uB864 \uC0C1\uD0DC \uD45C\uC2DC\n setIsWheelScrolling(true);\n\n // \uAE30\uC874 \uD720 \uD0C0\uC774\uBA38 \uC81C\uAC70\n if (wheelTimeoutRef.current) {\n clearTimeout(wheelTimeoutRef.current);\n }\n\n // 300ms \uD6C4 \uD720 \uC2A4\uD06C\uB864 \uC0C1\uD0DC \uD574\uC81C (\uD720 \uC2A4\uD06C\uB864\uC774 \uB05D\uB0AC\uB2E4\uACE0 \uAC04\uC8FC)\n wheelTimeoutRef.current = setTimeout(() => {\n setIsWheelScrolling(false);\n }, 300);\n\n // \uD720 \uC774\uBCA4\uD2B8 \uC2DC 50ms \uB514\uBC14\uC6B4\uC2A4 \uC801\uC6A9 (\uC2E4\uC81C \uC2A4\uD06C\uB864 \uBC1C\uC0DD \uC2DC handleScroll\uC5D0\uC11C \uCDE8\uC18C\uB428)\n clearWheelShowTimer();\n wheelShowTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(true);\n wheelShowTimeoutRef.current = null;\n // \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC \uD6C4 \uC790\uB3D9 \uC228\uAE40 \uD0C0\uC774\uBA38 \uC124\uC815\n setHideTimer(finalAutoHideConfig.delayOnWheel);\n }, 50);\n };\n\n const elementsToWatch: HTMLElement[] = [];\n\n // \uC2E4\uC81C \uC2A4\uD06C\uB864 \uAC00\uB2A5\uD55C \uC694\uC18C \uCC3E\uAE30\n const scrollableElement = findScrollableElement();\n if (scrollableElement) {\n elementsToWatch.push(scrollableElement);\n }\n\n // fallback: \uB0B4\uBD80 \uCEE8\uD14C\uC774\uB108\uC640 children \uC694\uC18C\uB3C4 \uAC10\uC9C0\n const container = containerRef.current;\n if (container && !scrollableElement) {\n elementsToWatch.push(container);\n\n // children \uC694\uC18C\uB4E4\uC758 \uC2A4\uD06C\uB864\uB3C4 \uAC10\uC9C0 (\uC911\uCCA9\uB41C OverlayScrollbar \uC81C\uC678)\n const childScrollableElements = container.querySelectorAll(\n '[data-virtuoso-scroller], [style*=\"overflow\"], .virtuoso-scroller, [style*=\"overflow: auto\"], [style*=\"overflow:auto\"]'\n );\n childScrollableElements.forEach((child) => {\n const element = child as HTMLElement;\n\n // \uB2E4\uB978 OverlayScrollbar\uC758 container\uB294 \uC81C\uC678\n if (\n element !== container &&\n element.classList.contains(\n \"overlay-scrollbar-container\"\n )\n ) {\n return;\n }\n\n // \uBD80\uBAA8 \uC911\uC5D0 \uB2E4\uB978 OverlayScrollbar container\uAC00 \uC788\uC73C\uBA74 \uC81C\uC678\n let parent: HTMLElement | null = element.parentElement;\n while (parent && parent !== container) {\n if (\n parent.classList.contains(\n \"overlay-scrollbar-container\"\n ) &&\n parent !== container\n ) {\n return; // \uC911\uCCA9\uB41C OverlayScrollbar \uB0B4\uBD80\uC774\uBBC0\uB85C \uC81C\uC678\n }\n parent = parent.parentElement;\n }\n\n elementsToWatch.push(element);\n });\n }\n\n // \uBAA8\uB4E0 \uC694\uC18C\uC5D0 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uB4F1\uB85D\n elementsToWatch.forEach((element) => {\n element.addEventListener(\"scroll\", handleScroll, {\n passive: true,\n });\n element.addEventListener(\"wheel\", handleWheel, {\n passive: true,\n });\n });\n\n return () => {\n // \uBAA8\uB4E0 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108 \uC81C\uAC70\n elementsToWatch.forEach((element) => {\n element.removeEventListener(\"scroll\", handleScroll);\n element.removeEventListener(\"wheel\", handleWheel);\n });\n\n if (wheelTimeoutRef.current) {\n clearTimeout(wheelTimeoutRef.current);\n }\n if (wheelShowTimeoutRef.current) {\n clearTimeout(wheelShowTimeoutRef.current);\n }\n };\n }, [\n findScrollableElement,\n updateScrollbar,\n onScroll,\n clearHideTimer,\n setHideTimer,\n finalAutoHideConfig,\n isWheelScrolling,\n isInitialDelayActive,\n ]);\n\n // \uD0A4\uBCF4\uB4DC \uB124\uBE44\uAC8C\uC774\uC158 \uD578\uB4E4\uB7EC (\uBC29\uD5A5\uD0A4, PageUp/PageDown/Home/End)\n useEffect(() => {\n const handleKeyDown = (event: KeyboardEvent) => {\n const scrollableElement = findScrollableElement();\n if (!scrollableElement) return;\n\n const { key } = event;\n const { scrollTop, scrollHeight, clientHeight } =\n scrollableElement;\n const maxScrollTop = scrollHeight - clientHeight;\n\n // \uD55C \uC904 \uC2A4\uD06C\uB864 \uB2E8\uC704 (rowHeight \uB610\uB294 \uAE30\uBCF8\uAC12)\n const lineScrollStep = 50;\n\n let newScrollTop: number | null = null;\n\n switch (key) {\n case \"ArrowUp\":\n event.preventDefault();\n newScrollTop = Math.max(0, scrollTop - lineScrollStep);\n break;\n case \"ArrowDown\":\n event.preventDefault();\n newScrollTop = Math.min(\n maxScrollTop,\n scrollTop + lineScrollStep\n );\n break;\n case \"PageUp\":\n event.preventDefault();\n newScrollTop = Math.max(0, scrollTop - clientHeight);\n break;\n case \"PageDown\":\n event.preventDefault();\n newScrollTop = Math.min(\n maxScrollTop,\n scrollTop + clientHeight\n );\n break;\n case \"Home\":\n event.preventDefault();\n newScrollTop = 0;\n break;\n case \"End\":\n event.preventDefault();\n newScrollTop = maxScrollTop;\n break;\n default:\n return;\n }\n\n if (newScrollTop !== null) {\n // \uC378 \uC704\uCE58\uB97C \uBA3C\uC800 \uC5C5\uB370\uC774\uD2B8\n const scrollRatio = newScrollTop / maxScrollTop;\n const arrowSpace = showArrows\n ? finalThumbWidth * 2 + finalTrackConfig.margin * 4\n : finalTrackConfig.margin * 2;\n const availableHeight = clientHeight - arrowSpace;\n const scrollableThumbHeight = availableHeight - thumbHeight;\n const newThumbTop = scrollableThumbHeight * scrollRatio;\n\n setThumbTop(newThumbTop);\n\n // \uC2A4\uD06C\uB864 \uC704\uCE58\uB97C \uC989\uC2DC \uBCC0\uACBD (\uC560\uB2C8\uBA54\uC774\uC158 \uC5C6\uC74C)\n scrollableElement.scrollTop = newScrollTop;\n\n // \uC2A4\uD06C\uB864\uBC14 \uD45C\uC2DC\n clearHideTimer();\n setScrollbarVisible(true);\n setHideTimer(finalAutoHideConfig.delay);\n }\n };\n\n const container = containerRef.current;\n if (container) {\n container.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n container.removeEventListener(\"keydown\", handleKeyDown);\n };\n }\n }, [\n findScrollableElement,\n showArrows,\n finalThumbWidth,\n finalTrackConfig.margin,\n thumbHeight,\n clearHideTimer,\n setHideTimer,\n finalAutoHideConfig.delay,\n ]);\n\n // \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864 \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\n useEffect(() => {\n if (isDragScrolling) {\n document.addEventListener(\"mousemove\", handleDragScrollMove);\n document.addEventListener(\"mouseup\", handleDragScrollEnd);\n return () => {\n document.removeEventListener(\n \"mousemove\",\n handleDragScrollMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleDragScrollEnd\n );\n };\n }\n }, [isDragScrolling, handleDragScrollMove, handleDragScrollEnd]);\n\n // \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\n useEffect(() => {\n if (isDragging) {\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n return () => {\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }\n }, [isDragging, handleMouseMove, handleMouseUp]);\n\n // \uAC00\uB85C \uC804\uC5ED \uB9C8\uC6B0\uC2A4 \uC774\uBCA4\uD2B8 \uB9AC\uC2A4\uB108\n useEffect(() => {\n if (isDraggingHorizontal) {\n document.addEventListener(\n \"mousemove\",\n handleHorizontalMouseMove\n );\n document.addEventListener(\"mouseup\", handleHorizontalMouseUp);\n return () => {\n document.removeEventListener(\n \"mousemove\",\n handleHorizontalMouseMove\n );\n document.removeEventListener(\n \"mouseup\",\n handleHorizontalMouseUp\n );\n };\n }\n }, [\n isDraggingHorizontal,\n handleHorizontalMouseMove,\n handleHorizontalMouseUp,\n ]);\n\n // \uCD08\uAE30 \uC2A4\uD06C\uB864\uBC14 \uC5C5\uB370\uC774\uD2B8\n useEffect(() => {\n // \uC989\uC2DC \uC5C5\uB370\uC774\uD2B8\n updateScrollbar();\n // \uC57D\uAC04\uC758 \uC9C0\uC5F0 \uD6C4\uC5D0\uB3C4 \uC5C5\uB370\uC774\uD2B8 (DOM\uC774 \uC644\uC804\uD788 \uB80C\uB354\uB9C1\uB41C \uD6C4)\n const timer = setTimeout(() => {\n updateScrollbar();\n }, 100);\n return () => clearTimeout(timer);\n }, [updateScrollbar]);\n\n // \uCEF4\uD3EC\uB10C\uD2B8 \uCD08\uAE30\uD654 \uC644\uB8CC \uD45C\uC2DC (hover \uC774\uBCA4\uD2B8 \uD65C\uC131\uD654\uC6A9)\n useLayoutEffect(() => {\n setIsInitialized(true);\n // \uCD08\uAE30\uD654 \uC9C1\uD6C4 \uC2A4\uD06C\uB864\uBC14 \uC5C5\uB370\uC774\uD2B8 (\uC378 \uB192\uC774 \uC815\uD655\uD558\uAC8C \uACC4\uC0B0)\n updateScrollbar();\n // \uC790\uB3D9 \uC228\uAE40\uC774 \uBE44\uD65C\uC131\uD654\uB418\uC5B4 \uC788\uACE0 \uCD08\uAE30 \uC9C0\uC5F0\uC774 \uB05D\uB0AC\uC73C\uBA74 \uC2A4\uD06C\uB864\uBC14\uB97C \uD56D\uC0C1 \uD45C\uC2DC\n if (\n !finalAutoHideConfig.enabled &&\n !isInitialDelayActive &&\n isScrollable()\n ) {\n setScrollbarVisible(true);\n }\n }, [\n isScrollable,\n updateScrollbar,\n finalAutoHideConfig.enabled,\n isInitialDelayActive,\n ]);\n\n // \uCD08\uAE30 \uB9C8\uC6B4\uD2B8 \uC9C0\uC5F0 \uD0C0\uC774\uBA38\n useEffect(() => {\n if (finalAutoHideConfig.initialDelay > 0) {\n const timer = setTimeout(() => {\n setIsInitialDelayActive(false);\n }, finalAutoHideConfig.initialDelay);\n return () => clearTimeout(timer);\n }\n }, [finalAutoHideConfig.initialDelay]);\n\n // Resize observer\uB85C \uD06C\uAE30 \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n const resizeObserver = new ResizeObserver(() => {\n updateScrollbar();\n });\n\n const elementsToObserve: HTMLElement[] = [];\n\n // \uB0B4\uBD80 \uCEE8\uD14C\uC774\uB108\uB4E4 \uAD00\uCC30\n if (containerRef.current) {\n elementsToObserve.push(containerRef.current);\n }\n if (contentRef.current) {\n elementsToObserve.push(contentRef.current);\n }\n\n // \uCE90\uC2DC\uB41C \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108\uB3C4 \uAD00\uCC30\n if (\n cachedScrollContainerRef.current &&\n document.contains(cachedScrollContainerRef.current)\n ) {\n elementsToObserve.push(cachedScrollContainerRef.current);\n }\n\n // \uBAA8\uB4E0 \uC694\uC18C\uB4E4 \uAD00\uCC30 \uC2DC\uC791\n elementsToObserve.forEach((element) => {\n resizeObserver.observe(element);\n });\n\n return () => resizeObserver.disconnect();\n }, [updateScrollbar]);\n\n // MutationObserver\uB85C DOM \uBCC0\uACBD \uAC10\uC9C0\n useEffect(() => {\n if (!containerRef.current) {\n return;\n }\n\n const observer = new MutationObserver(() => {\n // \uCE90\uC2DC \uCD08\uAE30\uD654\uD558\uC5EC \uC0C8\uB85C\uC6B4 \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 \uAC10\uC9C0\n cachedScrollContainerRef.current = null;\n updateScrollbar();\n });\n\n observer.observe(containerRef.current, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"style\"],\n });\n\n return () => observer.disconnect();\n }, [updateScrollbar]);\n\n // trackWidth\uAC00 thumbWidth\uBCF4\uB2E4 \uC791\uC73C\uBA74 thumbWidth\uC640 \uAC19\uAC8C \uC124\uC815\n const adjustedTrackWidth = Math.max(finalTrackWidth, finalThumbWidth);\n\n // \uC6F9\uD0B7 \uC2A4\uD06C\uB864\uBC14 \uC228\uAE30\uAE30\uC6A9 CSS \uB3D9\uC801 \uC8FC\uC785\n useEffect(() => {\n const styleId = \"overlay-scrollbar-webkit-hide\";\n\n // \uC774\uBBF8 \uC2A4\uD0C0\uC77C\uC774 \uC788\uC73C\uBA74 \uC81C\uAC70\n const existingStyle = document.getElementById(styleId);\n if (existingStyle) {\n existingStyle.remove();\n }\n\n const style = document.createElement(\"style\");\n style.id = styleId;\n style.textContent = `\n .overlay-scrollbar-container::-webkit-scrollbar {\n display: none !important;\n width: 0 !important;\n height: 0 !important;\n }\n .overlay-scrollbar-container::-webkit-scrollbar-track {\n display: none !important;\n }\n .overlay-scrollbar-container::-webkit-scrollbar-thumb {\n display: none !important;\n }\n /* ehfuse-editor-content\uB294 \uC2A4\uD06C\uB864\uBC14 \uC720\uC9C0 */\n .overlay-scrollbar-container .ehfuse-editor-content {\n scrollbar-width: thin !important;\n -ms-overflow-style: auto !important;\n }\n .overlay-scrollbar-container .ehfuse-editor-content::-webkit-scrollbar {\n display: block !important;\n width: 8px !important;\n height: 8px !important;\n }\n .overlay-scrollbar-container .ehfuse-editor-content::-webkit-scrollbar-track {\n display: block !important;\n background: #f1f1f1 !important;\n }\n .overlay-scrollbar-container .ehfuse-editor-content::-webkit-scrollbar-thumb {\n display: block !important;\n background: #c1c1c1 !important;\n border-radius: 4px !important;\n }\n .overlay-scrollbar-container .ehfuse-editor-content::-webkit-scrollbar-thumb:hover {\n background: #a1a1a1 !important;\n }\n .overlay-scrollbar-container:focus {\n outline: 2px solid rgba(0, 123, 255, 0.3);\n outline-offset: -2px;\n }\n .overlay-scrollbar-container:focus-visible {\n outline: 2px solid rgba(0, 123, 255, 0.5);\n outline-offset: -2px;\n }\n `;\n document.head.appendChild(style);\n\n return () => {\n const styleToRemove = document.getElementById(styleId);\n if (styleToRemove) {\n styleToRemove.remove();\n }\n };\n }, []);\n\n return (\n <div\n ref={wrapperRef}\n className={`overlay-scrollbar-wrapper ${className}`}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n position: \"relative\",\n minHeight: 0, // shrink \uAC00\uB2A5\uD558\uB3C4\uB85D\n height: \"100%\", // \uBD80\uBAA8\uC758 \uC804\uCCB4 \uB192\uC774 \uC0AC\uC6A9\n flex: \"1 1 0%\", // \uAE30\uBCF8\uC801\uC73C\uB85C flex item\uC73C\uB85C \uB3D9\uC791\n ...style, // \uC0AC\uC6A9\uC790\uAC00 flex\uB97C override \uD560 \uC218 \uC788\uB3C4\uB85D style\uC744 \uB4A4\uC5D0 \uBC30\uCE58\n }}\n >\n {/* \uC2A4\uD06C\uB864 \uCEE8\uD14C\uC774\uB108 */}\n <div\n ref={containerRef}\n className=\"overlay-scrollbar-container\"\n tabIndex={-1} // \uD0A4\uBCF4\uB4DC \uD3EC\uCEE4\uC2A4 \uAC00\uB2A5\uD558\uAC8C \uD568\n onMouseDown={handleDragScrollStart}\n style={{\n display: \"flex\",\n width: \"100%\", // \uBA85\uC2DC\uC801 \uB108\uBE44 \uC124\uC815\n flex: \"1 1 auto\", // flex item\uC73C\uB85C \uC124\uC815\uD558\uC5EC \uB192\uC774\uB97C \uC790\uB3D9\uC73C\uB85C \uACC4\uC0B0\n minHeight: 0, // \uCD5C\uC18C \uB192\uC774 \uBCF4\uC7A5\n overflow: \"auto\", // \uB124\uC774\uD2F0\uBE0C \uC2A4\uD06C\uB864 \uAE30\uB2A5 \uC720\uC9C0\n // \uBE0C\uB77C\uC6B0\uC800 \uAE30\uBCF8 \uC2A4\uD06C\uB864\uBC14\uB9CC \uC228\uAE30\uAE30\n scrollbarWidth: \"none\", // Firefox\n msOverflowStyle: \"none\", // IE/Edge\n // \uD0A4\uBCF4\uB4DC \uD3EC\uCEE4\uC2A4 \uC2A4\uD0C0\uC77C (\uC811\uADFC\uC131)\n outline: \"none\", // \uAE30\uBCF8 \uC544\uC6C3\uB77C\uC778 \uC81C\uAC70\n userSelect: isDragScrolling ? \"none\" : \"auto\", // \uB4DC\uB798\uADF8 \uC911 \uD14D\uC2A4\uD2B8 \uC120\uD0DD \uBC29\uC9C0\n ...containerStyle, // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC2A4\uD0C0\uC77C \uC801\uC6A9\n }}\n >\n <div\n ref={contentRef}\n className=\"overlay-scrollbar-content\"\n style={{\n flex: \"1 1 0%\", // grow\uD558\uC5EC \uACF5\uAC04 \uCC44\uC6B0\uAE30\n minHeight: 0, // flex shrink \uD5C8\uC6A9\n display: \"flex\", // flex \uCEE8\uD14C\uC774\uB108\uB85C \uC124\uC815\n flexDirection: \"column\", // \uC138\uB85C \uBC29\uD5A5 \uC815\uB82C\n ...contentStyle, // \uC0AC\uC6A9\uC790 \uC815\uC758 \uC2A4\uD0C0\uC77C \uC801\uC6A9\n }}\n >\n {children}\n </div>\n </div>\n\n {/* \uCEE4\uC2A4\uD140 \uC2A4\uD06C\uB864\uBC14 */}\n {showScrollbar && hasScrollableContent && (\n <div\n ref={scrollbarRef}\n className=\"overlay-scrollbar-track\"\n onMouseEnter={() => {\n // \uC228\uAE40 \uD0C0\uC774\uBA38\uB294 \uC989\uC2DC \uCDE8\uC18C\n clearHideTimer();\n\n // \uD638\uBC84 \uC9C4\uC785 \uD0C0\uC774\uBA38 \uC124\uC815 (100ms \uD6C4 \uD45C\uC2DC)\n hoverEnterTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(true);\n hoverEnterTimeoutRef.current = null;\n }, 100);\n }}\n onMouseLeave={() => {\n // \uD638\uBC84 \uC9C4\uC785 \uD0C0\uC774\uBA38 \uCDE8\uC18C (\uC9C0\uB098\uAC00\uAE30\uB9CC \uD55C \uACBD\uC6B0)\n clearHoverEnterTimer();\n\n if (!isDragging) {\n setHideTimer(finalAutoHideConfig.delay);\n }\n }}\n style={{\n position: \"absolute\",\n top: 0,\n right: 0,\n width: `${adjustedTrackWidth}px`,\n height: \"100%\",\n opacity: scrollbarVisible ? 1 : 0,\n transition: \"opacity 0.2s ease-in-out\",\n cursor: \"pointer\",\n zIndex: 1000,\n pointerEvents: \"auto\",\n }}\n >\n {/* \uC2A4\uD06C\uB864\uBC14 \uD2B8\uB799 \uBC30\uACBD */}\n {finalTrackConfig.visible && (\n <div\n className=\"overlay-scrollbar-track-background\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleTrackClick(e);\n }}\n style={{\n position: \"absolute\",\n top: showArrows\n ? `${\n finalThumbConfig.width +\n finalTrackConfig.margin * 2\n }px`\n : `${finalTrackConfig.margin}px`,\n right:\n finalTrackConfig.alignment === \"outside\"\n ? \"0px\"\n : `${\n (adjustedTrackWidth -\n finalThumbConfig.width) /\n 2\n }px`, // \uD2B8\uB799 \uC815\uB82C\n width: `${finalThumbConfig.width}px`,\n height: showArrows\n ? `calc(100% - ${\n finalThumbConfig.width * 2 +\n finalTrackConfig.margin * 4\n }px)`\n : `calc(100% - ${\n finalTrackConfig.margin * 2\n }px)`,\n backgroundColor: finalTrackConfig.color,\n borderRadius: `${finalTrackConfig.radius}px`,\n cursor: \"pointer\",\n }}\n />\n )}\n\n {/* \uC2A4\uD06C\uB864\uBC14 \uC378 */}\n <div\n ref={thumbRef}\n className=\"overlay-scrollbar-thumb\"\n onMouseDown={handleThumbMouseDown}\n onMouseEnter={() => setIsThumbHovered(true)}\n onMouseLeave={() => setIsThumbHovered(false)}\n style={{\n position: \"absolute\",\n top: `${\n (showArrows\n ? finalThumbWidth +\n finalTrackConfig.margin * 2\n : finalTrackConfig.margin) + thumbTop\n }px`,\n right:\n finalTrackConfig.alignment === \"outside\"\n ? \"0px\"\n : `${\n (adjustedTrackWidth -\n finalThumbWidth) /\n 2\n }px`, // \uD2B8\uB799 \uC815\uB82C\n width: `${finalThumbWidth}px`,\n height: `${Math.max(\n thumbHeight,\n thumbMinHeight\n )}px`,\n backgroundColor:\n isThumbHovered || isDragging\n ? finalThumbConfig.hoverColor\n : finalThumbConfig.color,\n opacity:\n isThumbHovered || isDragging\n ? finalThumbConfig.hoverOpacity\n : finalThumbConfig.opacity,\n borderRadius: `${finalThumbConfig.radius}px`,\n cursor: \"pointer\",\n transition:\n \"background-color 0.2s ease-in-out, opacity 0.2s ease-in-out\",\n }}\n />\n </div>\n )}\n\n {/* \uC704\uCABD \uD654\uC0B4\uD45C \uBC84\uD2BC */}\n {showScrollbar && hasScrollableContent && showArrows && (\n <div\n className=\"overlay-scrollbar-up-arrow\"\n onClick={handleUpArrowClick}\n onMouseEnter={() => setHoveredArrow(\"up\")}\n onMouseLeave={() => setHoveredArrow(null)}\n style={{\n position: \"absolute\",\n top: `${finalTrackConfig.margin}px`,\n right:\n finalTrackConfig.alignment === \"outside\"\n ? \"0px\"\n : `${\n (adjustedTrackWidth -\n finalThumbWidth) /\n 2\n }px`, // \uD2B8\uB799 \uC815\uB82C\n width: `${finalThumbWidth}px`,\n height: `${finalThumbWidth}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: `${Math.max(\n finalThumbWidth * 0.75,\n 8\n )}px`,\n color:\n hoveredArrow === \"up\"\n ? finalArrowsConfig.hoverColor\n : finalArrowsConfig.color,\n userSelect: \"none\",\n zIndex: 1001,\n opacity: scrollbarVisible\n ? hoveredArrow === \"up\"\n ? finalArrowsConfig.hoverOpacity\n : finalArrowsConfig.opacity\n : 0,\n transition:\n \"opacity 0.2s ease-in-out, color 0.15s ease-in-out\",\n }}\n >\n \u25B2\n </div>\n )}\n\n {/* \uC544\uB798\uCABD \uD654\uC0B4\uD45C \uBC84\uD2BC */}\n {showScrollbar && hasScrollableContent && showArrows && (\n <div\n className=\"overlay-scrollbar-down-arrow\"\n onClick={handleDownArrowClick}\n onMouseEnter={() => setHoveredArrow(\"down\")}\n onMouseLeave={() => setHoveredArrow(null)}\n style={{\n position: \"absolute\",\n bottom: `${finalTrackConfig.margin}px`,\n right:\n finalTrackConfig.alignment === \"outside\"\n ? \"0px\"\n : `${\n (adjustedTrackWidth -\n finalThumbWidth) /\n 2\n }px`, // \uD2B8\uB799 \uC815\uB82C\n width: `${finalThumbWidth}px`,\n height: `${finalThumbWidth}px`,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: `${Math.max(\n finalThumbWidth * 0.75,\n 8\n )}px`,\n color:\n hoveredArrow === \"down\"\n ? finalArrowsConfig.hoverColor\n : finalArrowsConfig.color,\n userSelect: \"none\",\n zIndex: 1001,\n opacity: scrollbarVisible\n ? hoveredArrow === \"down\"\n ? finalArrowsConfig.hoverOpacity\n : finalArrowsConfig.opacity\n : 0,\n transition:\n \"opacity 0.2s ease-in-out, color 0.15s ease-in-out\",\n }}\n >\n \u25BC\n </div>\n )}\n\n {/* \uAC00\uB85C \uCEE4\uC2A4\uD140 \uC2A4\uD06C\uB864\uBC14 */}\n {showScrollbar && hasHorizontalScrollableContent && (\n <div\n className=\"overlay-scrollbar-horizontal-track\"\n onMouseEnter={() => {\n // \uC228\uAE40 \uD0C0\uC774\uBA38\uB294 \uC989\uC2DC \uCDE8\uC18C\n clearHideTimer();\n\n // \uD638\uBC84 \uC9C4\uC785 \uD0C0\uC774\uBA38 \uC124\uC815 (100ms \uD6C4 \uD45C\uC2DC)\n hoverEnterTimeoutRef.current = setTimeout(() => {\n setScrollbarVisible(true);\n hoverEnterTimeoutRef.current = null;\n }, 100);\n }}\n onMouseLeave={() => {\n // \uD638\uBC84 \uC9C4\uC785 \uD0C0\uC774\uBA38 \uCDE8\uC18C (\uC9C0\uB098\uAC00\uAE30\uB9CC \uD55C \uACBD\uC6B0)\n clearHoverEnterTimer();\n\n if (!isDraggingHorizontal) {\n setHideTimer(finalAutoHideConfig.delay);\n }\n }}\n style={{\n position: \"absolute\",\n bottom: 0,\n left: 0,\n width: \"100%\",\n height: `${adjustedTrackWidth}px`,\n opacity: scrollbarVisible ? 1 : 0,\n transition: \"opacity 0.2s ease-in-out\",\n cursor: \"pointer\",\n zIndex: 1000,\n pointerEvents: \"auto\",\n }}\n >\n {/* \uAC00\uB85C \uC2A4\uD06C\uB864\uBC14 \uD2B8\uB799 \uBC30\uACBD */}\n {finalTrackConfig.visible && (\n <div\n className=\"overlay-scrollbar-horizontal-track-background\"\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n handleHorizontalTrackClick(e);\n }}\n style={{\n position: \"absolute\",\n bottom: `${finalTrackConfig.margin}px`,\n left: `${finalTrackConfig.margin}px`,\n width: `calc(100% - ${\n finalTrackConfig.margin * 2\n }px)`,\n height: `${finalThumbWidth}px`,\n backgroundColor: finalTrackConfig.color,\n borderRadius: `${finalTrackConfig.radius}px`,\n cursor: \"pointer\",\n }}\n />\n )}\n\n {/* \uAC00\uB85C \uC2A4\uD06C\uB864\uBC14 \uC378 */}\n <div\n className=\"overlay-scrollbar-horizontal-thumb\"\n onMouseDown={handleHorizontalThumbMouseDown}\n onMouseEnter={() =>\n setIsHorizontalThumbHovered(true)\n }\n onMouseLeave={() =>\n setIsHorizontalThumbHovered(false)\n }\n style={{\n position: \"absolute\",\n bottom: `${finalTrackConfig.margin}px`,\n left: `${\n finalTrackConfig.margin + thumbLeft\n }px`,\n width: `${Math.max(thumbWidth, 50)}px`,\n height: `${finalThumbWidth}px`,\n backgroundColor:\n isHorizontalThumbHovered ||\n isDraggingHorizontal\n ? finalThumbConfig.hoverColor\n : finalThumbConfig.color,\n opacity:\n isHorizontalThumbHovered ||\n isDraggingHorizontal\n ? finalThumbConfig.hoverOpacity\n : finalThumbConfig.opacity,\n borderRadius: `${finalThumbConfig.radius}px`,\n cursor: \"pointer\",\n transition:\n \"background-color 0.2s ease-in-out, opacity 0.2s ease-in-out\",\n }}\n />\n </div>\n )}\n </div>\n );\n }\n);\n\nexport default OverlayScrollbar;\nexport { OverlayScrollbar };\n", "/**\n * MIT License\n *\n * Copyright (c) 2025 KIM YOUNG JIN (ehfuse@gmail.com)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\nimport { DragScrollConfig } from \"../types\";\n\n// \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uD074\uB798\uC2A4\uB4E4 (\uC790\uC2E0 \uB610\uB294 \uBD80\uBAA8 \uC694\uC18C\uC5D0\uC11C \uD655\uC778)\nconst DEFAULT_EXCLUDE_CLASSES = [\n // \uAE30\uBCF8 \uC785\uB825 \uC694\uC18C\uB4E4\n \"editor\",\n \"textarea\",\n \"input\",\n \"select\",\n \"textfield\",\n \"form-control\",\n \"contenteditable\",\n\n // Material-UI \uCEF4\uD3EC\uB10C\uD2B8\uB4E4\n \"MuiInputBase-input\",\n \"MuiSelect-select\",\n \"MuiOutlinedInput-input\",\n \"MuiFilledInput-input\",\n \"MuiInput-input\",\n \"MuiFormControl-root\",\n \"MuiTextField-root\",\n \"MuiSelect-root\",\n \"MuiOutlinedInput-root\",\n \"MuiFilledInput-root\",\n \"MuiInput-root\",\n \"MuiAutocomplete-input\",\n \"MuiDatePicker-input\",\n \"MuiSlider-thumb\",\n \"MuiSlider-rail\",\n \"MuiSlider-track\",\n \"MuiSlider-mark\",\n \"MuiSlider-markLabel\",\n \"MuiSlider-root\",\n \"MuiSlider-colorPrimary\",\n \"MuiSlider-sizeMedium\",\n \"MuiIconButton-root\",\n \"MuiButton-root\",\n \"MuiButtonBase-root\",\n \"MuiTouchRipple-root\",\n \"MuiCheckbox-root\",\n \"MuiRadio-root\",\n \"MuiSwitch-root\",\n \"PrivateSwitchBase-root\",\n\n // Ant Design \uCEF4\uD3EC\uB10C\uD2B8\uB4E4\n \"ant-input\",\n \"ant-input-affix-wrapper\",\n \"ant-input-group-addon\",\n \"ant-input-number\",\n \"ant-input-number-handler\",\n \"ant-select\",\n \"ant-select-selector\",\n \"ant-select-selection-search\",\n \"ant-select-dropdown\",\n \"ant-cascader\",\n \"ant-cascader-input\",\n \"ant-picker\",\n \"ant-picker-input\",\n \"ant-time-picker\",\n \"ant-calendar-picker\",\n \"ant-slider\",\n \"ant-slider-track\",\n \"ant-slider-handle\",\n \"ant-switch\",\n \"ant-checkbox\",\n \"ant-checkbox-wrapper\",\n \"ant-radio\",\n \"ant-radio-wrapper\",\n \"ant-rate\",\n \"ant-upload\",\n \"ant-upload-drag\",\n \"ant-form-item\",\n \"ant-form-item-control\",\n \"ant-btn\",\n \"ant-dropdown\",\n \"ant-dropdown-trigger\",\n \"ant-menu\",\n \"ant-menu-item\",\n \"ant-tooltip\",\n \"ant-popover\",\n \"ant-modal\",\n \"ant-drawer\",\n \"ant-tree-select\",\n \"ant-auto-complete\",\n \"ant-mentions\",\n \"ant-transfer\",\n\n // Shadcn/ui \uCEF4\uD3EC\uB10C\uD2B8\uB4E4\n \"ui-input\",\n \"ui-textarea\",\n \"ui-select\",\n \"ui-select-trigger\",\n \"ui-select-content\",\n \"ui-select-item\",\n \"ui-button\",\n \"ui-checkbox\",\n \"ui-radio-group\",\n \"ui-switch\",\n \"ui-slider\",\n \"ui-range-slider\",\n \"ui-calendar\",\n \"ui-date-picker\",\n \"ui-combobox\",\n \"ui-command\",\n \"ui-command-input\",\n \"ui-popover\",\n \"ui-dialog\",\n \"ui-sheet\",\n \"ui-dropdown-menu\",\n \"ui-context-menu\",\n \"ui-menubar\",\n \"ui-navigation-menu\",\n \"ui-form\",\n \"ui-form-control\",\n \"ui-form-item\",\n \"ui-form-field\",\n \"ui-label\",\n // Radix UI \uAE30\uBCF8 \uD074\uB798\uC2A4\uB4E4 (Shadcn \uAE30\uBC18)\n \"radix-ui\",\n \"radix-select\",\n \"radix-dropdown\",\n \"radix-dialog\",\n \"radix-popover\",\n \"radix-accordion\",\n \"radix-tabs\",\n \"radix-slider\",\n \"radix-switch\",\n \"radix-checkbox\",\n \"radix-radio\",\n\n // Quill Editor\n \"ql-editor\",\n \"ql-container\",\n \"ql-toolbar\",\n \"ql-picker\",\n \"ql-picker-label\",\n \"ql-picker-options\",\n \"ql-formats\",\n \"ql-snow\",\n \"ql-bubble\",\n \"quill\",\n \"quilleditor\",\n\n // Monaco Editor\n \"monaco-editor\",\n \"monaco-editor-background\",\n \"view-lines\",\n \"decorationsOverviewRuler\",\n \"monaco-scrollable-element\",\n\n // CodeMirror\n \"CodeMirror\",\n \"CodeMirror-code\",\n \"CodeMirror-lines\",\n \"CodeMirror-scroll\",\n \"CodeMirror-sizer\",\n \"cm-editor\",\n \"cm-focused\",\n \"cm-content\",\n\n // TinyMCE\n \"tox-editor-container\",\n \"tox-editor-header\",\n \"tox-edit-area\",\n \"tox-tinymce\",\n \"mce-content-body\",\n\n // CKEditor\n \"ck-editor\",\n \"ck-content\",\n \"ck-toolbar\",\n \"ck-editor__editable\",\n \"ck-widget\",\n\n // Slate.js\n \"slate-editor\",\n \"slate-content\",\n\n // Draft.js\n \"DraftEditor-root\",\n \"DraftEditor-editorContainer\",\n \"public-DraftEditor-content\",\n\n // EhfuseEditor\n \"ehfuse-editor\",\n \"ehfuse-editor-wrapper\",\n \"ehfuse-editor-content\",\n \"ehfuse-toolbar\",\n \"ehfuse-toolbar-group\",\n \"ehfuse-cursor\",\n\n // \uAE30\uD0C0 \uC5D0\uB514\uD130\uB4E4\n \"text-editor\",\n \"rich-text-editor\",\n \"wysiwyg\",\n \"ace_editor\",\n \"ace_content\",\n];\n\n/**\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uC694\uC18C\uB4E4\uC778\uC9C0 \uD655\uC778\n */\n/**\n * \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC774 \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294 \uC694\uC18C\uB4E4\uC778\uC9C0 \uD655\uC778\n */\nexport const isTextInputElement = (\n element: Element,\n config?: DragScrollConfig\n): boolean => {\n const tagName = element.tagName.toLowerCase();\n const inputTypes = [\n \"text\",\n \"password\",\n \"email\",\n \"number\",\n \"search\",\n \"tel\",\n \"url\",\n \"checkbox\",\n \"radio\",\n ];\n\n // input \uD0DC\uADF8\uC774\uBA74\uC11C \uD14D\uC2A4\uD2B8 \uC785\uB825 \uD0C0\uC785\uC774\uB098 \uCCB4\uD06C\uBC15\uC2A4/\uB77C\uB514\uC624\uC778 \uACBD\uC6B0\n if (tagName === \"input\") {\n const type = (element as HTMLInputElement).type;\n return inputTypes.includes(type);\n }\n\n // textarea, select, \uD3B8\uC9D1 \uAC00\uB2A5\uD55C \uC694\uC18C\uB4E4\n if ([\"textarea\", \"select\", \"button\"].includes(tagName)) {\n return true;\n }\n\n // SVG \uC694\uC18C\uB4E4 (\uC544\uC774\uCF58\uB4E4)\n if (\n [\n \"svg\",\n \"path\",\n \"circle\",\n \"rect\",\n \"line\",\n \"polygon\",\n \"polyline\",\n ].includes(tagName)\n ) {\n return true;\n }\n\n // contenteditable \uC18D\uC131\uC774 \uC788\uB294 \uC694\uC18C\n if (element.getAttribute(\"contenteditable\") === \"true\") {\n return true;\n }\n\n // \uCD94\uAC00 \uC140\uB809\uD130 \uCCB4\uD06C\n if (config?.excludeSelectors) {\n for (const selector of config.excludeSelectors) {\n if (element.matches(selector)) {\n return true;\n }\n }\n }\n\n return checkElementAndParents(element, config);\n};\n\n/**\n * \uC790\uC2E0 \uB610\uB294 \uBD80\uBAA8 \uC694\uC18C\uB4E4\uC744 \uD655\uC778\uD558\uC5EC \uB4DC\uB798\uADF8 \uC2A4\uD06C\uB864\uC744 \uC81C\uC678\uD560 \uC694\uC18C\uC778\uC9C0 \uD310\uB2E8\n */\nconst checkElementAndParents = (\n element: Element,\n config?: DragScrollConfig\n): boolean => {\n // \uBAA8\uB4E0 \uC81C\uC678 \uD074\uB798\uC2A4\uB4E4 \uD569\uCE58\uAE30 (\uAE30\uBCF8 \uD074\uB798\uC2A4 + \uC0AC\uC6A9\uC790 \uCD94\uAC00 \uD074\uB798\uC2A4)\n const allExcludeClasses = [\n ...DEFAULT_EXCLUDE_CLASSES,\n ...(config?.excludeClasses || []),\n ];\n\n let currentElement: Element | null = element;\n let depth = 0;\n const maxDepth = 5; // \uCD5C\uB300 5\uB2E8\uACC4\uAE4C\uC9C0 \uBD80\uBAA8 \uC694\uC18C \uD655\uC778\n\n while (currentElement && depth <= maxDepth) {\n // \uD604\uC7AC \uC694\uC18C\uAC00 \uC81C\uC678 \uD074\uB798\uC2A4\uB97C \uAC00\uC9C0\uACE0 \uC788\uB294\uC9C0 \uD655\uC778\n if (\n allExcludeClasses.some((cls) =>\n currentElement!.classList.contains(cls)\n )\n ) {\n return true;\n }\n\n // \uB2E4\uC774\uC5BC\uB85C\uADF8 \uB8E8\uD2B8\uC5D0 \uB3C4\uB2EC\uD558\uBA74 \uC911\uB2E8\n if (currentElement.classList.contains(\"MuiDialogContent-root\")) {\n break;\n }\n\n currentElement = currentElement.parentElement;\n depth++;\n }\n\n return false;\n};\n\n/**\n * \uB2E4\uB978 \uB2E4\uC774\uC5BC\uB85C\uADF8\uB098 \uBAA8\uB2EC\uC774 \uC0C1\uC704\uC5D0 \uC788\uB294\uC9C0 \uD655\uC778\n */\nexport const hasUpperModal = (scrollContainer: Element): boolean => {\n const currentDialog = scrollContainer.closest(\n \".MuiDialog-root\"\n ) as HTMLElement;\n if (!currentDialog) return false;\n\n const allModals = document.querySelectorAll(\n \".MuiDialog-root, .MuiModal-root, .MuiPopover-root\"\n );\n const currentZIndex = parseInt(\n window.getComputedStyle(currentDialog).zIndex || \"0\"\n );\n\n for (const modal of allModals) {\n if (modal !== currentDialog) {\n const modalElement = modal as HTMLElement;\n const modalZIndex = parseInt(\n window.getComputedStyle(modalElement).zIndex || \"0\"\n );\n\n if (\n modalZIndex > currentZIndex &&\n modalElement.style.display !== \"none\"\n ) {\n return true;\n }\n }\n }\n\n return false;\n};\n\n/**\n * \uD074\uB9AD\uD55C \uC694\uC18C\uAC00 \uB2E4\uB978 \uB2E4\uC774\uC5BC\uB85C\uADF8 \uB0B4\uBD80\uC778\uC9C0 \uD655\uC778\n */\nexport const isClickInOtherDialog = (\n clickedElement: Element,\n currentDialog: Element | null\n): boolean => {\n const parentDialog = clickedElement.closest(\n \".MuiDialog-root, .MuiPopover-root, .MuiModal-root\"\n );\n return parentDialog !== null && parentDialog !== currentDialog;\n};\n"],
|
|
5
|
+
"mappings": "ubAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,sBAAAE,GAAA,YAAAA,KAAA,eAAAC,GAAAH,ICwBA,IAAAI,EAUO,iBCPP,IAAMC,GAA0B,CAE5B,SACA,WACA,QACA,SACA,YACA,eACA,kBAGA,qBACA,mBACA,yBACA,uBACA,iBACA,sBACA,oBACA,iBACA,wBACA,sBACA,gBACA,wBACA,sBACA,kBACA,iBACA,kBACA,iBACA,sBACA,iBACA,yBACA,uBACA,qBACA,iBACA,qBACA,sBACA,mBACA,gBACA,iBACA,yBAGA,YACA,0BACA,wBACA,mBACA,2BACA,aACA,sBACA,8BACA,sBACA,eACA,qBACA,aACA,mBACA,kBACA,sBACA,aACA,mBACA,oBACA,aACA,eACA,uBACA,YACA,oBACA,WACA,aACA,kBACA,gBACA,wBACA,UACA,eACA,uBACA,WACA,gBACA,cACA,cACA,YACA,aACA,kBACA,oBACA,eACA,eAGA,WACA,cACA,YACA,oBACA,oBACA,iBACA,YACA,cACA,iBACA,YACA,YACA,kBACA,cACA,iBACA,cACA,aACA,mBACA,aACA,YACA,WACA,mBACA,kBACA,aACA,qBACA,UACA,kBACA,eACA,gBACA,WAEA,WACA,eACA,iBACA,eACA,gBACA,kBACA,aACA,eACA,eACA,iBACA,cAGA,YACA,eACA,aACA,YACA,kBACA,oBACA,aACA,UACA,YACA,QACA,cAGA,gBACA,2BACA,aACA,2BACA,4BAGA,aACA,kBACA,mBACA,oBACA,mBACA,YACA,aACA,aAGA,uBACA,oBACA,gBACA,cACA,mBAGA,YACA,aACA,aACA,sBACA,YAGA,eACA,gBAGA,mBACA,8BACA,6BAGA,gBACA,wBACA,wBACA,iBACA,uBACA,gBAGA,cACA,mBACA,UACA,aACA,aACJ,EAQaC,GAAqB,CAC9BC,EACAC,IACU,CACV,IAAMC,EAAUF,EAAQ,QAAQ,YAAY,EACtCG,EAAa,CACf,OACA,WACA,QACA,SACA,SACA,MACA,MACA,WACA,OACJ,EAGA,GAAID,IAAY,QAAS,CACrB,IAAME,EAAQ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",
|
|
6
|
+
"names": ["index_exports", "__export", "OverlayScrollbar_default", "__toCommonJS", "import_react", "DEFAULT_EXCLUDE_CLASSES", "isTextInputElement", "element", "config", "tagName", "inputTypes", "type", "selector", "checkElementAndParents", "allExcludeClasses", "currentElement", "depth", "maxDepth", "cls", "import_jsx_runtime", "DEFAULT_THUMB_CONFIG", "DEFAULT_TRACK_CONFIG", "DEFAULT_ARROWS_CONFIG", "DEFAULT_DRAG_SCROLL_CONFIG", "DEFAULT_AUTO_HIDE_CONFIG", "OverlayScrollbar", "className", "style", "containerStyle", "contentStyle", "children", "onScroll", "thumb", "track", "arrows", "dragScroll", "autoHide", "showScrollbar", "detectInnerScroll", "ref", "prevPropsRef", "wrapperRef", "containerRef", "contentRef", "scrollbarRef", "thumbRef", "cachedScrollContainerRef", "scrollbarVisible", "setScrollbarVisible", "isDragging", "setIsDragging", "isThumbHovered", "setIsThumbHovered", "dragStart", "setDragStart", "thumbHeight", "setThumbHeight", "thumbTop", "setThumbTop", "hasScrollableContent", "setHasScrollableContent", "isHorizontalThumbHovered", "setIsHorizontalThumbHovered", "isDraggingHorizontal", "setIsDraggingHorizontal", "dragStartHorizontal", "setDragStartHorizontal", "thumbWidth", "setThumbWidth", "thumbLeft", "setThumbLeft", "hasHorizontalScrollableContent", "setHasHorizontalScrollableContent", "isDragScrolling", "setIsDragScrolling", "dragScrollStart", "setDragScrollStart", "activeArrow", "setActiveArrow", "hoveredArrow", "setHoveredArrow", "isInitialized", "setIsInitialized", "wheelTimeoutRef", "isWheelScrolling", "setIsWheelScrolling", "hideTimeoutRef", "hoverEnterTimeoutRef", "wheelShowTimeoutRef", "finalThumbConfig", "baseColor", "finalTrackConfig", "finalArrowsConfig", "finalDragScrollConfig", "finalAutoHideConfig", "isInitialDelayActive", "setIsInitialDelayActive", "finalThumbWidth", "finalTrackWidth", "thumbMinHeight", "showArrows", "arrowStep", "maintainFocus", "activeElement", "options", "findScrollableElement", "cached", "childScrollableElements", "child", "element", "parent", "isNestedInAnotherScrollbar", "isScrollable", "clearHideTimer", "clearHoverEnterTimer", "clearWheelShowTimer", "setHideTimer", "delay", "updateScrollbar", "scrollableElement", "containerHeight", "contentHeight", "scrollTop", "containerWidth", "contentWidth", "scrollLeft", "wrapperPaddingTopBottom", "computedStyle", "paddingTop", "paddingBottom", "arrowSpace", "availableHeight", "scrollRatio", "calculatedThumbHeight", "scrollableHeight", "thumbScrollableHeight", "calculatedThumbTop", "horizontalScrollableWidth", "scrollRatioHorizontal", "calculatedThumbWidth", "thumbScrollableWidth", "calculatedThumbLeft", "handleThumbMouseDown", "event", "actualScrollContainer", "handleMouseMove", "deltaY", "scrollDelta", "newScrollTop", "handleMouseUp", "handleTrackClick", "rect", "clickY", "handleUpArrowClick", "handleDownArrowClick", "container", "maxScrollTop", "handleHorizontalThumbMouseDown", "handleHorizontalMouseMove", "scrollableWidth", "deltaX", "newScrollLeft", "handleHorizontalMouseUp", "handleHorizontalTrackClick", "clickX", "handleDragScrollStart", "target", "isTextInputElement", "handleDragScrollMove", "handleDragScrollEnd", "handleScroll", "handleWheel", "elementsToWatch", "handleKeyDown", "key", "scrollHeight", "clientHeight", "lineScrollStep", "newThumbTop", "timer", "resizeObserver", "elementsToObserve", "observer", "adjustedTrackWidth", "styleId", "existingStyle", "styleToRemove", "OverlayScrollbar_default"]
|
|
7
7
|
}
|